From 1c617bdbf32e212ee957f7ff8629475c92e603b7 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 15 Jun 2023 14:44:07 +0200 Subject: [PATCH 0001/1125] Syncthing: add Steam Deck to devices --- roles/server/syncthing.nix | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index f16a7ba..9795e87 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -20,14 +20,18 @@ id = "MGMYYA2-4PXGHHH-2LOVD5N-I7IYBBS-4Y4UQNK-H73S2JG-ZCK5GCN-NHTWMAR"; addresses = [ "tcp://archie.local:22000" "tcp://192.168.0.160:22000"]; }; + "steamdeck" = { + name = "Steam Deck"; + id = "DLQPL74-KEQTPM5-X4PDZHB-4HLQYHV-UCMJLOB-P6W3KWU-QLJADBY-V4KEMA5"; + }; }; folders = { "passwords" = { label = "KeePassXC Passwords"; id = "rdyaq-ex659"; path = "${config.services.syncthing.dataDir}/passwords"; - devices = [ "phone" "pc" ]; + devices = [ "phone" "pc" "steamdeck"]; }; }; }; -} \ No newline at end of file +} From 10404c18e346406ccccd57852286123ffebff9d2 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 16 Jun 2023 11:02:51 +0200 Subject: [PATCH 0002/1125] Set up /tmp --- roles/common/configuration.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 96b3b9e..c2b45d4 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -1,4 +1,4 @@ -{ config, pkgs, ... }: +{ config, lib, pkgs, ... }: { environment = { @@ -11,6 +11,13 @@ }; }; + # Set up /tmp + boot.tmp = { + useTmpfs = lib.mkDefault true; + # Cleaning out /tmp at boot if it's a tmpfs is quite stupid + cleanOnBoot = !config.boot.tmp.useTmpfs; + }; + # Set up secrets age = { identityPaths = [ From 79ea9fe230effba801bb5b575829d656aa3c9b2e Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 18 Jun 2023 13:12:34 +0200 Subject: [PATCH 0003/1125] I give up :( --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index eea2bc6..3357b94 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,3 @@ # Ignore build outputs from performing a nix-build or `nix build` command result result-* - -# I don't want to do a commit everytime that I want to update stuff -flake.lock From e2a406b5512e43e6f197d9600784b1bd484d2d5f Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 18 Jun 2023 13:12:51 +0200 Subject: [PATCH 0004/1125] Add lock file --- flake.lock | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 flake.lock diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..edfb100 --- /dev/null +++ b/flake.lock @@ -0,0 +1,124 @@ +{ + "nodes": { + "agenix": { + "inputs": { + "darwin": [], + "home-manager": "home-manager", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1684153753, + "narHash": "sha256-PVbWt3qrjYAK+T5KplFcO+h7aZWfEj1UtyoKlvcDxh0=", + "owner": "ryantm", + "repo": "agenix", + "rev": "db5637d10f797bb251b94ef9040b237f4702cde3", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1682203081, + "narHash": "sha256-kRL4ejWDhi0zph/FpebFYhzqlOBrk0Pl3dzGEKSAlEw=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "32d3e39c491e2f91152c84f8ad8b003420eab0a1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1687041925, + "narHash": "sha256-Zfn/SphInZ9PEIHWdQk+wGQ0XGlwAgRUp/Qso+8vDOY=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "a8d549351d4b87ab80665f35e57bee2a04201245", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-23.05", + "repo": "home-manager", + "type": "github" + } + }, + "nix-impermanence": { + "locked": { + "lastModified": 1684264534, + "narHash": "sha256-K0zr+ry3FwIo3rN2U/VWAkCJSgBslBisvfRIPwMbuCQ=", + "owner": "nix-community", + "repo": "impermanence", + "rev": "89253fb1518063556edd5e54509c30ac3089d5e6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "impermanence", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1686921029, + "narHash": "sha256-J1bX9plPCFhTSh6E3TWn9XSxggBh/zDD4xigyaIQBy8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c7ff1b9b95620ce8728c0d7bd501c458e6da9e04", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-23.05", + "type": "indirect" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1686960236, + "narHash": "sha256-AYCC9rXNLpUWzD9hm+askOfpliLEC9kwAo7ITJc4HIw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "04af42f3b31dba0ef742d254456dc4c14eedac86", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "root": { + "inputs": { + "agenix": "agenix", + "home-manager": "home-manager_2", + "nix-impermanence": "nix-impermanence", + "nixpkgs": "nixpkgs", + "nixpkgs-unstable": "nixpkgs-unstable" + } + } + }, + "root": "root", + "version": 7 +} From 879abfdf7df4b4fe41e567a64211888ae55cd4e7 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 20 Jun 2023 21:22:11 +0200 Subject: [PATCH 0005/1125] Archie: enable xone --- machines/Archie/hardware-configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index cd626b4..08c86b5 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -8,6 +8,9 @@ [ (modulesPath + "/installer/scan/not-detected.nix") ]; + # Enabke support for the Xbox One wireless dongle + hardware.xone.enable = true; + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-amd" ]; From 62bc8f9bee520866244d8c5e0185dea0d7ba164d Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 21 Jun 2023 13:55:22 +0200 Subject: [PATCH 0006/1125] Sddm: work around a bug --- roles/kde/default.nix | 1 + roles/kde/plasma.nix | 1 - roles/kde/sddm.nix | 15 +++++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 roles/kde/sddm.nix diff --git a/roles/kde/default.nix b/roles/kde/default.nix index fbcf748..ffcbb8f 100755 --- a/roles/kde/default.nix +++ b/roles/kde/default.nix @@ -3,5 +3,6 @@ { imports = [ ./plasma.nix + ./sddm.nix ]; } diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index d2e7ab0..48d7098 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -20,7 +20,6 @@ in { # Enable the Plasma 5 Desktop Environment. - services.xserver.displayManager.sddm.enable = true; services.xserver.desktopManager.plasma5.enable = true; # GTK apps need dconf to grab the correct theme on Wayland diff --git a/roles/kde/sddm.nix b/roles/kde/sddm.nix new file mode 100644 index 0000000..a2d34d3 --- /dev/null +++ b/roles/kde/sddm.nix @@ -0,0 +1,15 @@ +{ config, ... }: + +{ + # Enable SDDM. + services.xserver.displayManager.sddm.enable = true; + + /* + Sddm has a very annoying bug where it sometimes hangs at shutdown + if you use Plasma's wayland session. The bug is already fixed upstream, + but until it sddm gets updated on the repos this will do + */ + systemd.services.display-manager.serviceConfig = { + TimeoutStopSec = "5s"; + }; +} From d6705e5a975f0de2562646bc246dcbe1a35a4bb7 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 21 Jun 2023 17:08:22 +0200 Subject: [PATCH 0007/1125] Add plasma's sdk to the dev shell --- flake.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 8c8c19f..60407d9 100755 --- a/flake.nix +++ b/flake.nix @@ -24,9 +24,10 @@ outputs = {nixpkgs, agenix, home-manager, nixpkgs-unstable, nix-impermanence, .. name = "Environment for toast's nixos configurations"; # The agenix cli is not needed to activate a configuration, so instead of installing it # I'll just add it to de devShell, since that's the only real time I'm going to use it. - packages = [ + packages = with nixpkgs.legacyPackages.x86_64-linux; [ agenix.packages.x86_64-linux.default - nixpkgs.legacyPackages.x86_64-linux.git + git + plasma5Packages.plasma-sdk ]; shellHook ='' export PS1="$PS1(toast-configs)> " From fd0ef3be5b47c4276065ba835662a1816ee441f3 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 21 Jun 2023 17:31:43 +0200 Subject: [PATCH 0008/1125] Enable firefox and disable Pocket --- machines/Archie/configuration.nix | 1 - roles/desktop/default.nix | 1 + roles/desktop/firefox.nix | 11 +++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 roles/desktop/firefox.nix diff --git a/machines/Archie/configuration.nix b/machines/Archie/configuration.nix index f91582d..c01b561 100644 --- a/machines/Archie/configuration.nix +++ b/machines/Archie/configuration.nix @@ -65,7 +65,6 @@ isNormalUser = true; extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. packages = with pkgs; [ - firefox tree ]; }; diff --git a/roles/desktop/default.nix b/roles/desktop/default.nix index 52f5478..b13a242 100755 --- a/roles/desktop/default.nix +++ b/roles/desktop/default.nix @@ -3,5 +3,6 @@ { imports = [ ./discord.nix + ./firefox.nix ]; } diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix new file mode 100644 index 0000000..ffc50f5 --- /dev/null +++ b/roles/desktop/firefox.nix @@ -0,0 +1,11 @@ +{ config, pkgs, ... }: + +{ + # System wide firefox settings + programs.firefox = { + enable = true; + policies = { + "DisablePocket" = true; + }; + }; +} From b7c99f3fea8e0302a7ef2d691cae82a242bed217 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 21 Jun 2023 17:44:24 +0200 Subject: [PATCH 0009/1125] Firefox: enable video hardware acceleration by default --- roles/desktop/firefox.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix index ffc50f5..23aaab0 100644 --- a/roles/desktop/firefox.nix +++ b/roles/desktop/firefox.nix @@ -6,6 +6,13 @@ enable = true; policies = { "DisablePocket" = true; + "Preferences" = { + # Enable video hardware acceleration + "media.ffmpeg.vaapi.enabled" = { + "Value" = true; + "Status" = "default"; + }; + }; }; }; } From 06d11340a86746362d456fcdd965df3e004520fb Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 22 Jun 2023 20:17:06 +0200 Subject: [PATCH 0010/1125] Firefox: disable telemetry --- roles/desktop/firefox.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix index 23aaab0..e4165db 100644 --- a/roles/desktop/firefox.nix +++ b/roles/desktop/firefox.nix @@ -6,6 +6,7 @@ enable = true; policies = { "DisablePocket" = true; + "DisableTelemetry" = true; "Preferences" = { # Enable video hardware acceleration "media.ffmpeg.vaapi.enabled" = { From 6c64366a42d0baa7821bf851ae789d123c21734c Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 22 Jun 2023 20:17:49 +0200 Subject: [PATCH 0011/1125] Firefox: set default autoplay permissions --- roles/desktop/firefox.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix index e4165db..fa2e96f 100644 --- a/roles/desktop/firefox.nix +++ b/roles/desktop/firefox.nix @@ -14,6 +14,12 @@ "Status" = "default"; }; }; + "Permissions" = { + "Autoplay" = { + "Allow" = [ "https://www.youtube.com" ]; + "Default" = "block-audio-video"; + }; + }; }; }; } From a167ea6dd116ba97c73e914ecae7daa31ce74372 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 22 Jun 2023 20:18:31 +0200 Subject: [PATCH 0012/1125] Firefox: enable DRM --- roles/desktop/firefox.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix index fa2e96f..095d45f 100644 --- a/roles/desktop/firefox.nix +++ b/roles/desktop/firefox.nix @@ -7,6 +7,8 @@ policies = { "DisablePocket" = true; "DisableTelemetry" = true; + # You need these for Spotify + "EncryptedMediaExtensions" = { "Enabled" = true; }; "Preferences" = { # Enable video hardware acceleration "media.ffmpeg.vaapi.enabled" = { From c5937bf9b6f3a2b9cf64d5bf6c3b90d85604d47e Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 22 Jun 2023 20:26:22 +0200 Subject: [PATCH 0013/1125] Firefox: enable uBlock origin --- roles/desktop/firefox.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix index 095d45f..33830ff 100644 --- a/roles/desktop/firefox.nix +++ b/roles/desktop/firefox.nix @@ -9,6 +9,13 @@ "DisableTelemetry" = true; # You need these for Spotify "EncryptedMediaExtensions" = { "Enabled" = true; }; + "ExtensionSettings" = { + # TODO: Install extensions the NUR instead of from AMO + "uBlock0@raymondhill.net" = { + "installation_mode" = "force_installed"; + "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; + }; + }; "Preferences" = { # Enable video hardware acceleration "media.ffmpeg.vaapi.enabled" = { From 762d43bd91e5e74181dd30fd5f14e0c8ae79002c Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 22 Jun 2023 21:11:17 +0200 Subject: [PATCH 0014/1125] Firefox: add extensions --- roles/desktop/firefox.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix index 33830ff..aaed591 100644 --- a/roles/desktop/firefox.nix +++ b/roles/desktop/firefox.nix @@ -15,6 +15,15 @@ "installation_mode" = "force_installed"; "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; }; + # Decentraleyes + "jid1-BoFifL9Vbdl2zQ@jetpack" = { + "installation_mode" = "normal_installed"; + "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/decentraleyes/latest.xpi"; + }; + "jid1-MnnxcxisBPnSXQ@jetpack" = { + "installation_mode" = "normal_installed"; + "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/privacy-badger17/latest.xpi"; + }; }; "Preferences" = { # Enable video hardware acceleration From 26a6a74bc630e091b705c3bfda13ada93b0e50a6 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 22 Jun 2023 21:21:45 +0200 Subject: [PATCH 0015/1125] Firefox: disable sponsored links in home page --- roles/desktop/firefox.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix index aaed591..797fd9e 100644 --- a/roles/desktop/firefox.nix +++ b/roles/desktop/firefox.nix @@ -38,6 +38,7 @@ "Default" = "block-audio-video"; }; }; + "FirefoxHome" = { "SponsoredTopSites" = false; }; }; }; } From 0b0e52e0c5b1c74504d4de4f17d99194cdc4027a Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 22 Jun 2023 23:04:39 +0200 Subject: [PATCH 0016/1125] Update lock file --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index edfb100..da2aae1 100644 --- a/flake.lock +++ b/flake.lock @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1687041925, - "narHash": "sha256-Zfn/SphInZ9PEIHWdQk+wGQ0XGlwAgRUp/Qso+8vDOY=", + "lastModified": 1687163790, + "narHash": "sha256-CmG/ZdswJrWM0CMgJiVyWfO6LqaI4SKEAx9IrnYDrpI=", "owner": "nix-community", "repo": "home-manager", - "rev": "a8d549351d4b87ab80665f35e57bee2a04201245", + "rev": "ac53777f52929bc82efcd2830bfc5aa60bcb4337", "type": "github" }, "original": { @@ -81,11 +81,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1686921029, - "narHash": "sha256-J1bX9plPCFhTSh6E3TWn9XSxggBh/zDD4xigyaIQBy8=", + "lastModified": 1687379288, + "narHash": "sha256-cSuwfiqYfeVyqzCRkU9AvLTysmEuSal8nh6CYr+xWog=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c7ff1b9b95620ce8728c0d7bd501c458e6da9e04", + "rev": "ef0bc3976340dab9a4e087a0bcff661a8b2e87f3", "type": "github" }, "original": { From 5dec9fe288f788a45ea0e5d0541dfcfab4674f12 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 22 Jun 2023 23:12:45 +0200 Subject: [PATCH 0017/1125] Archie: use unstable home-manager --- flake.nix | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index 8c8c19f..5b5c277 100755 --- a/flake.nix +++ b/flake.nix @@ -13,13 +13,20 @@ agenix = { }; }; -home-manager.url = "github:nix-community/home-manager/release-23.05"; -home-manager.inputs.nixpkgs.follows = "nixpkgs"; +home-manager = { + url = "github:nix-community/home-manager/release-23.05"; + inputs.nixpkgs.follows = "nixpkgs"; +}; + +home-manager-unstable = { + url = "github:nix-community/home-manager/"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; +}; nix-impermanence.url = "github:nix-community/impermanence"; }; -outputs = {nixpkgs, agenix, home-manager, nixpkgs-unstable, nix-impermanence, ... }: { +outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nix-impermanence, ... }: { devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { name = "Environment for toast's nixos configurations"; # The agenix cli is not needed to activate a configuration, so instead of installing it @@ -54,7 +61,7 @@ outputs = {nixpkgs, agenix, home-manager, nixpkgs-unstable, nix-impermanence, .. # Needed for nix-index { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } agenix.nixosModules.default - home-manager.nixosModule + home-manager-unstable.nixosModule ./roles/common ./roles/desktop ./roles/kde From 0de81c94068c6ea2bf80b92147d2910efa47ddec Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 26 Jun 2023 18:17:22 +0200 Subject: [PATCH 0018/1125] Add unstable home-manager to flake.lock (oops) --- flake.lock | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/flake.lock b/flake.lock index da2aae1..a4098ff 100644 --- a/flake.lock +++ b/flake.lock @@ -43,6 +43,26 @@ "type": "github" } }, + "home-manager-unstable": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1687647343, + "narHash": "sha256-1/o/i9KEFOBdlF9Cs04kBcqDFbYMt6W4SMqGa+QnnaI=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "0ee5ab611dc1fbb5180bd7d88d2aeb7841a4d179", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, "home-manager_2": { "inputs": { "nixpkgs": [ @@ -113,6 +133,7 @@ "inputs": { "agenix": "agenix", "home-manager": "home-manager_2", + "home-manager-unstable": "home-manager-unstable", "nix-impermanence": "nix-impermanence", "nixpkgs": "nixpkgs", "nixpkgs-unstable": "nixpkgs-unstable" From 933b4fb9bb7459cffe704a91ec1a4075ce948e9c Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 26 Jun 2023 23:50:04 +0200 Subject: [PATCH 0019/1125] Sddm: enable numlock by default --- roles/kde/sddm.nix | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/roles/kde/sddm.nix b/roles/kde/sddm.nix index a2d34d3..b290390 100644 --- a/roles/kde/sddm.nix +++ b/roles/kde/sddm.nix @@ -2,7 +2,13 @@ { # Enable SDDM. - services.xserver.displayManager.sddm.enable = true; + services.xserver.displayManager.sddm = { + enable = true; + settings = { + General = { Numlock = "on"; }; + }; + }; + /* Sddm has a very annoying bug where it sometimes hangs at shutdown From 87f78bac52a496e36f0a60fb459cf9b22fd19cb7 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 27 Jun 2023 00:12:18 +0200 Subject: [PATCH 0020/1125] Archie: fix typo in archie's hardware-configuration.nix --- machines/Archie/hardware-configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index 08c86b5..3412764 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -9,6 +9,7 @@ ]; # Enabke support for the Xbox One wireless dongle + # Enable support for the Xbox One wireless dongle hardware.xone.enable = true; boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; From 6e6fa9c599b121fed77377a7ac422e2f725c50e0 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 27 Jun 2023 00:26:10 +0200 Subject: [PATCH 0021/1125] Archie: mount root subvolume of ssd --- machines/Archie/hardware-configuration.nix | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index 3412764..48133e7 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -40,6 +40,19 @@ fsType = "vfat"; }; + /* + Mount the root subvolume of the SSD + This is helpful for getting things from + my old Arch install, as well as for running btdu + */ + fileSystems = { + "/mnt/ssd" = { + device = config.fileSystems."/".device; + fsType = config.fileSystems."/".fsType; + options = [ "subvolid=5" "ro" ]; + }; + }; + swapDevices = [ ]; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; From 25ca3bb7cca4c79a28faa356b43581af98f2f73e Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 27 Jun 2023 00:40:33 +0200 Subject: [PATCH 0022/1125] Install KeePassXC using home-manager --- roles/desktop/default.nix | 1 + roles/desktop/keepassxc.nix | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 roles/desktop/keepassxc.nix diff --git a/roles/desktop/default.nix b/roles/desktop/default.nix index b13a242..ac8b5dc 100755 --- a/roles/desktop/default.nix +++ b/roles/desktop/default.nix @@ -4,5 +4,6 @@ imports = [ ./discord.nix ./firefox.nix + ./keepassxc.nix ]; } diff --git a/roles/desktop/keepassxc.nix b/roles/desktop/keepassxc.nix new file mode 100644 index 0000000..677c828 --- /dev/null +++ b/roles/desktop/keepassxc.nix @@ -0,0 +1,20 @@ +{ config, pkgs, ... }: + +{ + # I'm only using keepass on my user, so I'm installing it with home-manager + home-manager = { + /* + TODO: move home-manager settings into the common role + They are not keepass specific, so they really should + not be here. I'm too lazy to do it now tho :P + */ + backupFileExtension = "backup"; + useGlobalPkgs = true; + users.toast = { config, pkgs, ... }: { + home = { + stateVersion = "23.05"; + packages = [ pkgs.keepassxc ]; + }; + }; + }; +} From ded324e0f303b3ef1bce59fbfd2b724de128a271 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 28 Jun 2023 14:30:54 +0200 Subject: [PATCH 0023/1125] KeepassXC: configure keepass and set up autostart --- roles/desktop/keepassxc.nix | 52 +++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/roles/desktop/keepassxc.nix b/roles/desktop/keepassxc.nix index 677c828..8018453 100644 --- a/roles/desktop/keepassxc.nix +++ b/roles/desktop/keepassxc.nix @@ -1,4 +1,25 @@ -{ config, pkgs, ... }: +{ config, pkgs, lib, ... }: + +let + kpxcSettings = lib.generators.toINI {} { + # Not sure what changing this does, I'll leave it alone + General = { + ConfigVersion = 2; + MinimizeAfterUnlock = true; + }; + GUI = { + ApplicationTheme = "classic"; + MinimizeOnStartup = false; + MinimizeOnClose = true; + MinimizeToTray = true; + ShowTrayIcon = true; + # 0 is icons, 1 is text, 2 is text next to icons, 3 is text under icons, and 4 is follow style + ToolButtonStyle = 0; # Would choose 4 but it's too big for a small window + # monochrome-light, monochrome-dark or colorful + TrayIconAppearance = "monochrome-light"; + }; + }; +in { # I'm only using keepass on my user, so I'm installing it with home-manager @@ -10,11 +31,38 @@ */ backupFileExtension = "backup"; useGlobalPkgs = true; - users.toast = { config, pkgs, ... }: { + + extraSpecialArgs = { kpxcSettings = kpxcSettings; }; + users.toast = { config, pkgs, kpxcSettings, ... }: { home = { stateVersion = "23.05"; packages = [ pkgs.keepassxc ]; + # No module for KeePassXC config :( + file = { + ".config/keepassxc/keepassxc.ini".text = kpxcSettings; + # For some reason the autostart .desktop is not the same as the regular one + ".config/autostart/org.keepassxc.KeePassXC.desktop".text = '' + [Desktop Entry] + Name=KeePassXC + GenericName=Password Manager + Exec=keepassxc + TryExec=keepassxc + Icon=keepassxc + StartupWMClass=keepassxc + StartupNotify=true + Terminal=false + Type=Application + Version=1.0 + Categories=Utility;Security;Qt; + MimeType=application/x-keepass2; + X-GNOME-Autostart-enabled=true + X-GNOME-Autostart-Delay=2 + X-KDE-autostart-after=panel + X-LXQt-Need-Tray=true + ''; + }; }; + }; }; } From fa385918cdc7e4f1f7b8f4eebdd12d984cd22113 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 28 Jun 2023 14:49:18 +0200 Subject: [PATCH 0024/1125] Plasma: remove leftover testing package --- roles/kde/plasma.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 48d7098..1445083 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -57,5 +57,4 @@ in "xdg/gtkrc-2.0".text = gtk1and2settings; "xdg/gtkrc".text = gtk1and2settings; }; - environment.systemPackages = [pkgs.yaru-theme]; } From d6eff86646fe3b0105fd220e436f77dd67668dfd Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 28 Jun 2023 14:50:12 +0200 Subject: [PATCH 0025/1125] Plasma: set default session to plasma wayland --- roles/kde/plasma.nix | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 1445083..e2b8eb8 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -19,8 +19,12 @@ let in { - # Enable the Plasma 5 Desktop Environment. - services.xserver.desktopManager.plasma5.enable = true; + services.xserver = { + # Enable the Plasma 5 Desktop Environment + desktopManager.plasma5.enable = true; + displayManager.defaultSession = "plasmawayland"; + }; + # GTK apps need dconf to grab the correct theme on Wayland programs.dconf.enable = true; From 0dc2b2980b7daa03f10ba78fff9a1ec69bc1954d Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 29 Jun 2023 12:57:40 +0200 Subject: [PATCH 0026/1125] Sddm: create derivation containing custom theme --- roles/kde/sddm.nix | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/roles/kde/sddm.nix b/roles/kde/sddm.nix index b290390..1c6e689 100644 --- a/roles/kde/sddm.nix +++ b/roles/kde/sddm.nix @@ -1,15 +1,36 @@ -{ config, ... }: +{ config, pkgs, ... }: + +let + sddm-sugar-candy = pkgs.stdenv.mkDerivation { + pname = "sddm-sugar-candy"; + version = "master"; + src = pkgs.fetchgit { + url = "https://framagit.org/MarianArlt/sddm-sugar-candy.git"; + hash = "sha256-XggFVsEXLYklrfy1ElkIp9fkTw4wvXbyVkaVCZq4ZLU="; + }; + installPhase = '' + runHook preInstall + + mkdir -p $out/share/sddm/themes/sugar-candy + cp -r /build/sddm-sugar-candy/* $out/share/sddm/themes/sugar-candy + + runHook postInstall + ''; + }; + +in { # Enable SDDM. services.xserver.displayManager.sddm = { enable = true; + theme = "sugar-candy"; settings = { General = { Numlock = "on"; }; }; }; - + environment.systemPackages = [ sddm-sugar-candy ]; /* Sddm has a very annoying bug where it sometimes hangs at shutdown if you use Plasma's wayland session. The bug is already fixed upstream, From 69ad5319786c9c014463b655324ef5ba0c400f4d Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 29 Jun 2023 12:58:40 +0200 Subject: [PATCH 0027/1125] Sddm: customize the currently applied theme --- roles/kde/sddm.nix | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/roles/kde/sddm.nix b/roles/kde/sddm.nix index 1c6e689..10afa13 100644 --- a/roles/kde/sddm.nix +++ b/roles/kde/sddm.nix @@ -1,6 +1,8 @@ { config, pkgs, ... }: let + currentTheme = config.services.xserver.displayManager.sddm.theme; + sddm-sugar-candy = pkgs.stdenv.mkDerivation { pname = "sddm-sugar-candy"; version = "master"; @@ -18,6 +20,25 @@ let ''; }; + /* + Adds a theme.conf.user file to the current sddm theme's folder, + allowing you to change it's configuration without needing to + repackage it + */ + customcfg = pkgs.stdenv.mkDerivation { + name = "sddm-theme-customizer"; + dontUnpack = true; + # TODO: generate theme.conf.user outside of installPhase + installPhase = '' + runHook preInstall + + mkdir -p $out/share/sddm/themes/${currentTheme}/ + echo "[General] + background = ${pkgs.plasma-workspace-wallpapers}/share/wallpapers/MilkyWay/contents/images/5120x2880.png" >> $out/share/sddm/themes/${currentTheme}/theme.conf.user + + runHook postInstall + ''; + }; in { @@ -30,7 +51,7 @@ in }; }; - environment.systemPackages = [ sddm-sugar-candy ]; + environment.systemPackages = [ sddm-sugar-candy customcfg ]; /* Sddm has a very annoying bug where it sometimes hangs at shutdown if you use Plasma's wayland session. The bug is already fixed upstream, From 7974ca628c638e113ec40dc49bcf66cf34f0623c Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 29 Jun 2023 16:35:22 +0200 Subject: [PATCH 0028/1125] Firefox: enable HTTPS only mode --- roles/desktop/firefox.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix index 797fd9e..76c431a 100644 --- a/roles/desktop/firefox.nix +++ b/roles/desktop/firefox.nix @@ -31,6 +31,10 @@ "Value" = true; "Status" = "default"; }; + "dom.security.https_only_mode" = { + "Value" = true; + "Status" = "locked"; + }; }; "Permissions" = { "Autoplay" = { From f9e71005a428fc5ab29ab2c7893b9db249a57e70 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 29 Jun 2023 16:36:06 +0200 Subject: [PATCH 0029/1125] Firefox: integrate better with kde --- roles/desktop/firefox.nix | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix index 76c431a..238149b 100644 --- a/roles/desktop/firefox.nix +++ b/roles/desktop/firefox.nix @@ -35,6 +35,20 @@ "Value" = true; "Status" = "locked"; }; + # Make firefox use the kde file picker + "widget.use-xdg-desktop-portal.file-picker" = { + "Value" = 1; + "Status" = "default"; + }; + /* + Not sure what this does, + but https://wiki.archlinux.org/title/Firefox#KDE_integration + tells me to enable it + */ + "widget.use-xdg-desktop-portal.mime-handler" = { + "Value" = 1; + "Status" = "default"; + }; }; "Permissions" = { "Autoplay" = { From 52f70f88291bb694859e0489ed9c61dd458e4416 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 29 Jun 2023 16:47:17 +0200 Subject: [PATCH 0030/1125] Firefox: disable the password manager --- roles/desktop/firefox.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix index 238149b..3e31b0f 100644 --- a/roles/desktop/firefox.nix +++ b/roles/desktop/firefox.nix @@ -50,6 +50,8 @@ "Status" = "default"; }; }; + # I use an external password manager, so the built in one just bothers me + "PasswordManagerEnabled" = false; "Permissions" = { "Autoplay" = { "Allow" = [ "https://www.youtube.com" ]; From 1167b979d9a71fb40264b4eeb8ba490c9ca792d3 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 29 Jun 2023 16:48:13 +0200 Subject: [PATCH 0031/1125] Firefox: always ask where to download files --- roles/desktop/firefox.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix index 3e31b0f..5a44b3f 100644 --- a/roles/desktop/firefox.nix +++ b/roles/desktop/firefox.nix @@ -50,6 +50,7 @@ "Status" = "default"; }; }; + "PromptForDownloadLocation" = true; # I use an external password manager, so the built in one just bothers me "PasswordManagerEnabled" = false; "Permissions" = { From e1d352d0193c180d1077e1ad6faea5927d85c3a8 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 29 Jun 2023 17:35:20 +0200 Subject: [PATCH 0032/1125] Add gaming role --- roles/gaming/default.nix | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100755 roles/gaming/default.nix diff --git a/roles/gaming/default.nix b/roles/gaming/default.nix new file mode 100755 index 0000000..f3991a4 --- /dev/null +++ b/roles/gaming/default.nix @@ -0,0 +1,6 @@ +{ ... }: + +{ + imports = [ + ]; +} From 757f60070fc96bfebb18d0ec7af45c7b40d633e1 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 29 Jun 2023 18:42:24 +0200 Subject: [PATCH 0033/1125] Gaming: enable steam --- roles/gaming/default.nix | 1 + roles/gaming/steam.nix | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 roles/gaming/steam.nix diff --git a/roles/gaming/default.nix b/roles/gaming/default.nix index f3991a4..3a963cc 100755 --- a/roles/gaming/default.nix +++ b/roles/gaming/default.nix @@ -2,5 +2,6 @@ { imports = [ + ./steam.nix ]; } diff --git a/roles/gaming/steam.nix b/roles/gaming/steam.nix new file mode 100644 index 0000000..178dc44 --- /dev/null +++ b/roles/gaming/steam.nix @@ -0,0 +1,9 @@ +{ config, pkgs, ... }: + +{ + programs.steam = { + enable = true; + # Doubt that I'll use it, but I'll enable it anyways + remotePlay.openFirewall = true; + }; +} From 4ba470cf5d3e9f4178fd53b7d4af35259e2e2c6c Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 29 Jun 2023 18:42:41 +0200 Subject: [PATCH 0034/1125] Archie: add gaming role --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 5b5c277..6c02a6b 100755 --- a/flake.nix +++ b/flake.nix @@ -65,6 +65,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl ./roles/common ./roles/desktop ./roles/kde + ./roles/gaming ./machines/Archie ]; }; From 2d69565d91c39c8242c4c24a5e400da54056de0a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 30 Jun 2023 12:10:07 +0200 Subject: [PATCH 0035/1125] Firefox: disable widget.use-xdg-desktop-portal.mime-handler --- roles/desktop/firefox.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/roles/desktop/firefox.nix b/roles/desktop/firefox.nix index 5a44b3f..643f174 100644 --- a/roles/desktop/firefox.nix +++ b/roles/desktop/firefox.nix @@ -41,12 +41,12 @@ "Status" = "default"; }; /* - Not sure what this does, - but https://wiki.archlinux.org/title/Firefox#KDE_integration - tells me to enable it + https://wiki.archlinux.org/title/Firefox#KDE_integration tells me to enable this, + but strangely enough doing so makes firefox ask to be set as the default browser + every time you start it up, so I'll disable it */ "widget.use-xdg-desktop-portal.mime-handler" = { - "Value" = 1; + "Value" = 0; "Status" = "default"; }; }; From 8f7e8e3661a991e7bf044bac5c5a5670b293b555 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 30 Jun 2023 12:15:13 +0200 Subject: [PATCH 0036/1125] Steam: enable pipewire alsa compatibility --- roles/gaming/steam.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/gaming/steam.nix b/roles/gaming/steam.nix index 178dc44..1c71901 100644 --- a/roles/gaming/steam.nix +++ b/roles/gaming/steam.nix @@ -6,4 +6,6 @@ # Doubt that I'll use it, but I'll enable it anyways remotePlay.openFirewall = true; }; + # Some linux native games (rise of the tomb raider) use alsa for sound + services.pipewire.alsa.enable = true; } From e844d29eaec24bb12f799bcabb458bb658813273 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 30 Jun 2023 16:43:30 +0200 Subject: [PATCH 0037/1125] Gaming: enable mangohud --- roles/gaming/default.nix | 1 + roles/gaming/mangohud.nix | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 roles/gaming/mangohud.nix diff --git a/roles/gaming/default.nix b/roles/gaming/default.nix index 3a963cc..fb3cce4 100755 --- a/roles/gaming/default.nix +++ b/roles/gaming/default.nix @@ -3,5 +3,6 @@ { imports = [ ./steam.nix + ./mangohud.nix ]; } diff --git a/roles/gaming/mangohud.nix b/roles/gaming/mangohud.nix new file mode 100644 index 0000000..ff6f5df --- /dev/null +++ b/roles/gaming/mangohud.nix @@ -0,0 +1,19 @@ +{ config, ... }: + +{ + # This does the same as enableSessionWide does on the mangohud config + environment.sessionVariables = { MANGOHUD = "1"; MANGOHUD_DLSYM = "1"; }; + + home-manager.users.toast = { config, ... }: + { + programs.mangohud = { + enable = true; + # TODO: fix envvars set by home manager not applying for some reason + # This only works for Vulkan, openGL programs still need the mangohud wrapper + enableSessionWide = true; + settings = { + preset = 4; + }; + }; + }; +} From 6df7d43e731023e3dfa84a466ab2b3bcc61877be Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 2 Jul 2023 14:20:57 +0200 Subject: [PATCH 0038/1125] Mangohud: hide hud by default --- roles/gaming/mangohud.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/gaming/mangohud.nix b/roles/gaming/mangohud.nix index ff6f5df..47b37be 100644 --- a/roles/gaming/mangohud.nix +++ b/roles/gaming/mangohud.nix @@ -13,6 +13,7 @@ enableSessionWide = true; settings = { preset = 4; + no_display = true; }; }; }; From 8975afd18dc3a4b33367c56fc148c3ec01339317 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 3 Jul 2023 01:02:09 +0200 Subject: [PATCH 0039/1125] Flake: do not set up pkgs --- flake.nix | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/flake.nix b/flake.nix index 6c02a6b..8f48cb0 100755 --- a/flake.nix +++ b/flake.nix @@ -43,20 +43,12 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl nixosConfigurations = { Archie = nixpkgs-unstable.lib.nixosSystem { system = "x86_64-linux"; - pkgs = import nixpkgs-unstable { - system = "x86_64-linux"; - config = { allowUnfree = true; }; # TODO: Find why this doesn't work - overlays = - let - discordOverlay = self: super: { - discord = super.discord.override { - withOpenASAR = true; - withVencord = true; - }; - }; - in - [ discordOverlay ]; - }; + /* + I used to set up nixpkgs in the flake, but doing that made + defining overlays in modules impossible (or at least I could + not figure out how) + Also has nice side effect of making it easier to add new systems :3 + */ modules = [ # Needed for nix-index { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } @@ -72,10 +64,6 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl Everest = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; - pkgs = import nixpkgs { - system = "x86_64-linux"; - config = { allowUnfree = false; }; # TODO: Find why this doesn't work - }; modules = [ # Needed for nix-index { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } From 79006c509b57e8f1740dfd2b5b45986e77387b0f Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 3 Jul 2023 01:03:29 +0200 Subject: [PATCH 0040/1125] Discord: enable OpenASAR and vencord (again) --- roles/desktop/discord.nix | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/roles/desktop/discord.nix b/roles/desktop/discord.nix index bdabdc4..5f47f87 100644 --- a/roles/desktop/discord.nix +++ b/roles/desktop/discord.nix @@ -1,9 +1,5 @@ { config, pkgs, ... }: -{ - # TODO: Find out why this does not do anything. If I put this - # on flake.nix it does work, so it's not completely wrong. - /* nixpkgs.overlays = let discordOverlay = self: super: { discord = super.discord.override { @@ -12,7 +8,8 @@ }; }; in - [ discordOverlay ]; */ +{ + nixpkgs.overlays = [ discordOverlay ]; users.users.toast.packages = with pkgs; [ discord ]; From ad8081bba3f4df2256d5813bb88938f9a7cd49ac Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 3 Jul 2023 12:31:25 +0200 Subject: [PATCH 0041/1125] Common: configure micro --- roles/common/programs/default.nix | 2 +- roles/common/programs/micro.nix | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 roles/common/programs/micro.nix diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index d28c74d..6262b48 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -4,6 +4,7 @@ imports = [ ./htop.nix ./nix.nix + ./micro.nix ./nix-index.nix ./command-not-found.nix ]; @@ -11,7 +12,6 @@ environment.systemPackages = with pkgs; [ speedtest-cli bat - micro nvd ncdu tree diff --git a/roles/common/programs/micro.nix b/roles/common/programs/micro.nix new file mode 100644 index 0000000..a80a708 --- /dev/null +++ b/roles/common/programs/micro.nix @@ -0,0 +1,17 @@ +{ config, pkgs, ... }: + +{ + home-manager = { + users.toast = { config, pkgs, ... }: + { + programs.micro = { + enable = true; + settings = { + clipboard = "terminal"; + indentchar = "|"; + softwrap = true; + }; + }; + }; + }; +} From bb6c9ea5d1128663e2e8fede52db57265b7b283c Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 3 Jul 2023 13:20:11 +0200 Subject: [PATCH 0042/1125] Desktop: enable external clipboard on micro --- roles/desktop/default.nix | 1 + roles/desktop/micro.nix | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 roles/desktop/micro.nix diff --git a/roles/desktop/default.nix b/roles/desktop/default.nix index ac8b5dc..6aa4825 100755 --- a/roles/desktop/default.nix +++ b/roles/desktop/default.nix @@ -4,6 +4,7 @@ imports = [ ./discord.nix ./firefox.nix + ./micro.nix ./keepassxc.nix ]; } diff --git a/roles/desktop/micro.nix b/roles/desktop/micro.nix new file mode 100644 index 0000000..a09e819 --- /dev/null +++ b/roles/desktop/micro.nix @@ -0,0 +1,21 @@ +{ config, pkgs, lib, ... }: + +{ + home-manager = { + users.toast = { config, pkgs, ... }: + { + programs.micro = { + enable = true; + settings = { + # Use xclip/wl-clipboard for copying and pasting + clipboard = lib.mkForce "external"; + }; + }; + /* + On a kde wayland session micro uses xsel or xclip instead of wl-clipboard + which doesn't work, so I only install wl-clipboard here to make micro use it + */ + home.packages = with pkgs; [ wl-clipboard ]; + }; + }; +} From ade2927e8b2b2da817fb06c20d679bb1f2c293da Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Jul 2023 08:06:17 +0200 Subject: [PATCH 0043/1125] Desktop: restructure folder structure --- roles/desktop/default.nix | 6 ++---- roles/desktop/programs/default.nix | 10 ++++++++++ roles/desktop/{ => programs}/discord.nix | 0 roles/desktop/{ => programs}/firefox.nix | 0 roles/desktop/{ => programs}/keepassxc.nix | 0 roles/desktop/{ => programs}/micro.nix | 0 roles/desktop/services/default.nix | 7 +++++++ 7 files changed, 19 insertions(+), 4 deletions(-) mode change 100755 => 100644 roles/desktop/default.nix create mode 100755 roles/desktop/programs/default.nix rename roles/desktop/{ => programs}/discord.nix (100%) rename roles/desktop/{ => programs}/firefox.nix (100%) rename roles/desktop/{ => programs}/keepassxc.nix (100%) rename roles/desktop/{ => programs}/micro.nix (100%) create mode 100644 roles/desktop/services/default.nix diff --git a/roles/desktop/default.nix b/roles/desktop/default.nix old mode 100755 new mode 100644 index 6aa4825..cb3d38f --- a/roles/desktop/default.nix +++ b/roles/desktop/default.nix @@ -2,9 +2,7 @@ { imports = [ - ./discord.nix - ./firefox.nix - ./micro.nix - ./keepassxc.nix + ./services + ./programs ]; } diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix new file mode 100755 index 0000000..6aa4825 --- /dev/null +++ b/roles/desktop/programs/default.nix @@ -0,0 +1,10 @@ +{ ... }: + +{ + imports = [ + ./discord.nix + ./firefox.nix + ./micro.nix + ./keepassxc.nix + ]; +} diff --git a/roles/desktop/discord.nix b/roles/desktop/programs/discord.nix similarity index 100% rename from roles/desktop/discord.nix rename to roles/desktop/programs/discord.nix diff --git a/roles/desktop/firefox.nix b/roles/desktop/programs/firefox.nix similarity index 100% rename from roles/desktop/firefox.nix rename to roles/desktop/programs/firefox.nix diff --git a/roles/desktop/keepassxc.nix b/roles/desktop/programs/keepassxc.nix similarity index 100% rename from roles/desktop/keepassxc.nix rename to roles/desktop/programs/keepassxc.nix diff --git a/roles/desktop/micro.nix b/roles/desktop/programs/micro.nix similarity index 100% rename from roles/desktop/micro.nix rename to roles/desktop/programs/micro.nix diff --git a/roles/desktop/services/default.nix b/roles/desktop/services/default.nix new file mode 100644 index 0000000..c6786ec --- /dev/null +++ b/roles/desktop/services/default.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + imports = [ + + ]; +} From b202fe478dafe8e27c414da91f75137b2c33716f Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Jul 2023 08:46:05 +0200 Subject: [PATCH 0044/1125] Desktop: start ssh-agent on login --- roles/desktop/services/default.nix | 2 +- roles/desktop/services/ssh-agent.nix | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 roles/desktop/services/ssh-agent.nix diff --git a/roles/desktop/services/default.nix b/roles/desktop/services/default.nix index c6786ec..48f9952 100644 --- a/roles/desktop/services/default.nix +++ b/roles/desktop/services/default.nix @@ -2,6 +2,6 @@ { imports = [ - + ./ssh-agent.nix ]; } diff --git a/roles/desktop/services/ssh-agent.nix b/roles/desktop/services/ssh-agent.nix new file mode 100644 index 0000000..7081761 --- /dev/null +++ b/roles/desktop/services/ssh-agent.nix @@ -0,0 +1,10 @@ +{ config, pkgs, ... }: + +{ + programs.ssh.startAgent = true; + /* + Home assistant added an option that does this + https://github.com/nix-community/home-manager/commit/2d9210f25ed18d5d4e11e6b886de4027c0c51a94 + but since I still need to fix home-manager's envvars not applying I'll stick to the NixOS one + */ +} From 70baaaca0f01ca87bf21e93bfc80b172226de6b6 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Jul 2023 08:48:05 +0200 Subject: [PATCH 0045/1125] Gitignore: ignore swap files from kate --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 3357b94..1df9283 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ # Ignore build outputs from performing a nix-build or `nix build` command result result-* + +# ---> Kate +# Ignore kate's swap files +*.kate-swp From c690057adde405aaa9e5483b065d61a059087c3e Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Jul 2023 09:37:45 +0200 Subject: [PATCH 0046/1125] KeepassXC: enable ssh-agent integration --- roles/desktop/programs/keepassxc.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/programs/keepassxc.nix b/roles/desktop/programs/keepassxc.nix index 8018453..53f42da 100644 --- a/roles/desktop/programs/keepassxc.nix +++ b/roles/desktop/programs/keepassxc.nix @@ -18,6 +18,7 @@ let # monochrome-light, monochrome-dark or colorful TrayIconAppearance = "monochrome-light"; }; + SSHAgent.Enabled = true; }; in From 1c35c527a591eafc71b5919beb53ef9c2e69248f Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Jul 2023 09:38:30 +0200 Subject: [PATCH 0047/1125] Ssh-agent: add temporary workaround --- roles/desktop/services/ssh-agent.nix | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/roles/desktop/services/ssh-agent.nix b/roles/desktop/services/ssh-agent.nix index 7081761..31b9f73 100644 --- a/roles/desktop/services/ssh-agent.nix +++ b/roles/desktop/services/ssh-agent.nix @@ -7,4 +7,15 @@ https://github.com/nix-community/home-manager/commit/2d9210f25ed18d5d4e11e6b886de4027c0c51a94 but since I still need to fix home-manager's envvars not applying I'll stick to the NixOS one */ + /* + TODO: fix SSH_AUTH_SOCK not being set in Plasma + Turns out the NixOS module also has issues :3 + The env is set but only in bash, not in the DE, so + keepass can't pick it up. For now I'll just set it manually + */ + home-manager.users.toast.xdg.configFile."plasma-workspace/env/ssh-agent.sh".text = '' + if [[ -z "$SSH_AUTH_SOCK" ]]; then + export SSH_AUTH_SOCK=$XDG_RUNTIME_DIR/ssh-agent + fi + ''; } From 3dc9a6bb633311e3c8eeaa40b5a9d9162d406e92 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Jul 2023 16:23:49 +0200 Subject: [PATCH 0048/1125] Plasma: set up breeze-dark as the gtk2 theme --- roles/kde/plasma.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index e2b8eb8..4c09d33 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -13,8 +13,8 @@ let # which is weird cause applying the theme to gtk1 but not 2 is dumb. I'll write it to # both files just in case :3 gtk1and2settings = '' - include "/run/current-system/sw/share/themes/${themeName}/gtk-2.0/gtkrc" - gtk-theme-name="${themeName}" + include "/run/current-system/sw/share/themes/${themeName}-Dark/gtk-2.0/gtkrc" + gtk-theme-name="${themeName}-Dark" ''; in From ea6f1be0160f685e99621a61abe53af03848ec9e Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Jul 2023 16:26:21 +0200 Subject: [PATCH 0049/1125] Plasma: don't write gtk1 settings file --- roles/kde/plasma.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 4c09d33..e61a7e6 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -59,6 +59,5 @@ in "xdg/gtk-4.0/settings.ini".text = gtk3and4settings; "xdg/gtk-3.0/settings.ini".text = gtk3and4settings; "xdg/gtkrc-2.0".text = gtk1and2settings; - "xdg/gtkrc".text = gtk1and2settings; }; } From d016e5f21e841dc943c31504e575e05195fe3a5f Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Jul 2023 16:30:44 +0200 Subject: [PATCH 0050/1125] Plasma: write gtk2's gtkrc to right directory --- roles/kde/plasma.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index e61a7e6..de0d458 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -58,6 +58,6 @@ in environment.etc = { "xdg/gtk-4.0/settings.ini".text = gtk3and4settings; "xdg/gtk-3.0/settings.ini".text = gtk3and4settings; - "xdg/gtkrc-2.0".text = gtk1and2settings; + "gtk-2.0/gtkrc".text = gtk1and2settings; }; } From bec17eb0f36e6811adeb6af6ca144aa45ae304fb Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Jul 2023 16:54:22 +0200 Subject: [PATCH 0051/1125] Plasma: rename variable Old variable was used to set both the gtkrc for gtk 1 and 2, but since it's used by only gtk 2 now I wanted the name to reflect that --- roles/kde/plasma.nix | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index de0d458..d6a6a59 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -9,10 +9,7 @@ let }; }; - # The configuration files that Plasma made have set the theme in gtkrc, not gtkrc-2.0 - # which is weird cause applying the theme to gtk1 but not 2 is dumb. I'll write it to - # both files just in case :3 - gtk1and2settings = '' + gtk2settings = '' include "/run/current-system/sw/share/themes/${themeName}-Dark/gtk-2.0/gtkrc" gtk-theme-name="${themeName}-Dark" ''; @@ -58,6 +55,6 @@ in environment.etc = { "xdg/gtk-4.0/settings.ini".text = gtk3and4settings; "xdg/gtk-3.0/settings.ini".text = gtk3and4settings; - "gtk-2.0/gtkrc".text = gtk1and2settings; + "gtk-2.0/gtkrc".text = gtk2settings; }; } From 894e0c85ce288d3afc63502dae32264e3f15b46b Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 5 Jul 2023 21:29:33 +0200 Subject: [PATCH 0052/1125] Plasma: patch and install Breeze color schemes --- roles/kde/patches/BreezeTint.patch | 191 +++++++++++++++++++++++++++++ roles/kde/plasma.nix | 18 +++ 2 files changed, 209 insertions(+) create mode 100644 roles/kde/patches/BreezeTint.patch diff --git a/roles/kde/patches/BreezeTint.patch b/roles/kde/patches/BreezeTint.patch new file mode 100644 index 0000000..8f17370 --- /dev/null +++ b/roles/kde/patches/BreezeTint.patch @@ -0,0 +1,191 @@ +diff --git a/share/color-schemes/BreezeClassic.colors b/share/color-schemes/BreezeClassicTint.colors +similarity index 70% +rename from share/color-schemes/BreezeClassic.colors +rename to share/color-schemes/BreezeClassicTint.colors +index 8dbc299..d64e300 100644 +--- a/share/color-schemes/BreezeClassic.colors ++++ b/share/color-schemes/BreezeClassicTint.colors +@@ -103,48 +103,12 @@ ForegroundPositive=46,204,113 + ForegroundVisited=61,174,230 + + [General] +-ColorScheme=BreezeClassic +-Name=Breeze Classic +-Name[ar]=نسيم التقليدي +-Name[az]=Breeze klassik +-Name[bg]=Breeze Класически +-Name[ca]=Brisa clàssica +-Name[ca@valencia]=Brisa clàssica +-Name[cs]=Breeze Classic +-Name[da]=Breeze Classic +-Name[de]=Breeze Klassisch +-Name[el]=Breeze κλασικό +-Name[en_GB]=Breeze Classic +-Name[es]=Brisa clásico +-Name[eu]=Breeze klasikoa +-Name[fi]=Perinteinen Breeze +-Name[fr]=Breeze classique +-Name[gl]=Brisa clásica +-Name[hi]=ब्रीज़ क्लासिक +-Name[hu]=Breeze Classic +-Name[ia]=Brisa Classic +-Name[id]=Breeze Klasik +-Name[it]=Brezza classico +-Name[ja]=Breeze クラシック +-Name[ka]=Breeze კლასიკური +-Name[ko]=Breeze 고전 +-Name[nl]=Breeze Classic +-Name[nn]=Breeze klassisk +-Name[pl]=Klasyczna Bryza +-Name[pt]=Brisa Clássica +-Name[pt_BR]=Breeze Classic +-Name[ro]=Briză, clasic +-Name[ru]=Breeze, классический вариант +-Name[sk]=Klasický vánok +-Name[sl]=Sapica, klasična +-Name[sv]=Breeze klassisk +-Name[tr]=Esinti Klasik +-Name[uk]=Класична Breeze +-Name[x-test]=xxBreeze Classicxx +-Name[zh_CN]=Breeze 微风经典 +-Name[zh_TW]=Breeze Classic ++ColorScheme=BreezeClassicTint ++Name=Breeze Classic (Tint) + accentActiveTitlebar=true + accentInactiveTitlebar=false ++TintFactor=0.2 ++TitlebarIsAccentColored=true + shadeSortColumn=true + + [KDE] +diff --git a/share/color-schemes/BreezeDark.colors b/share/color-schemes/BreezeDarkTint.colors +similarity index 71% +rename from share/color-schemes/BreezeDark.colors +rename to share/color-schemes/BreezeDarkTint.colors +index fc1fcb0..a97a552 100644 +--- a/share/color-schemes/BreezeDark.colors ++++ b/share/color-schemes/BreezeDarkTint.colors +@@ -131,57 +131,10 @@ ForegroundPositive=39,174,96 + ForegroundVisited=155,89,182 + + [General] +-ColorScheme=BreezeDark +-Name=Breeze Dark +-Name[ar]=نسيم داكن +-Name[az]=Breeze - Tünd +-Name[bg]=Breeze Тъмен +-Name[bs]=Breeze tamna +-Name[ca]=Brisa fosca +-Name[ca@valencia]=Brisa fosca +-Name[cs]=Breeze Tmavé +-Name[da]=Breeze Dark +-Name[de]=Breeze Dunkel +-Name[el]=Breeze σκούρο +-Name[en_GB]=Breeze Dark +-Name[es]=Brisa oscuro +-Name[et]=Breeze tume +-Name[eu]=Breeze iluna +-Name[fi]=Tumma Breeze +-Name[fr]=Brise sombre +-Name[gl]=Brisa escura +-Name[he]=Breeze Dark +-Name[hi]=ब्रीज़ गहरा +-Name[hu]=Breeze Dark +-Name[ia]=Brisa obscure +-Name[id]=Breeze Gelap +-Name[it]=Brezza scuro +-Name[ja]=Breeze ダーク +-Name[ka]=Breeze მუქი +-Name[ko]=어두운 Breeze +-Name[lt]=Breeze tamsus +-Name[nb]=Breeze mørk +-Name[nl]=Breeze Dark +-Name[nn]=Breeze mørk +-Name[pa]=ਬਰੀਜ਼ ਗੂੜ੍ਹਾ +-Name[pl]=Ciemna Bryza +-Name[pt]=Brisa Escura +-Name[pt_BR]=Breeze Dark +-Name[ro]=Briză, întunecat +-Name[ru]=Breeze, тёмный вариант +-Name[sk]=Tmavý vánok +-Name[sl]=Sapica, temna +-Name[sr]=Поветарац тамни +-Name[sr@ijekavian]=Поветарац тамни +-Name[sr@ijekavianlatin]=Povetarac tamni +-Name[sr@latin]=Povetarac tamni +-Name[sv]=Breeze mörk +-Name[tg]=Насими торик +-Name[tr]=Esinti Koyu +-Name[uk]=Темна Breeze +-Name[x-test]=xxBreeze Darkxx +-Name[zh_CN]=Breeze 微风深色 +-Name[zh_TW]=Breeze Dark ++ColorScheme=BreezeDarkTint ++Name=Breeze Dark (Tint) ++TintFactor=0.2 ++TitlebarIsAccentColored=true + shadeSortColumn=true + + [KDE] +diff --git a/share/color-schemes/BreezeLight.colors b/share/color-schemes/BreezeLightTint.colors +similarity index 75% +rename from share/color-schemes/BreezeLight.colors +rename to share/color-schemes/BreezeLightTint.colors +index 5bfdc22..223509c 100644 +--- a/share/color-schemes/BreezeLight.colors ++++ b/share/color-schemes/BreezeLightTint.colors +@@ -131,50 +131,10 @@ ForegroundPositive=39,174,96 + ForegroundVisited=155,89,182 + + [General] +-ColorScheme=BreezeLight +-Name=Breeze Light +-Name[ar]=نسيم فاتح +-Name[az]=Breeze - İşıqlı +-Name[bg]=Breeze Светъл +-Name[ca]=Brisa clara +-Name[ca@valencia]=Brisa clara +-Name[cs]=Breeze Světlé +-Name[da]=Breeze Light +-Name[de]=Breeze Hell +-Name[el]=Breeze φωτεινό +-Name[en_GB]=Breeze Light +-Name[es]=Brisa claro +-Name[et]=Breeze hele +-Name[eu]=Breeze argia +-Name[fi]=Vaalea Breeze +-Name[fr]=Brise clair +-Name[gl]=Brisa clara +-Name[hi]=ब्रीज़ हलका +-Name[hu]=Breeze Light +-Name[ia]=Brisa Ligier +-Name[id]=Breeze Terang +-Name[it]=Brezza chiaro +-Name[ja]=Breeze ライト +-Name[ka]=Breeze ღია +-Name[ko]=밝은 Breeze +-Name[lt]=Breeze šviesus +-Name[nl]=Breeze Light +-Name[nn]=Breeze lys +-Name[pa]=ਬਰੀਜ਼ ਹਲਕਾ +-Name[pl]=Jasna Bryza +-Name[pt]=Brisa Clara +-Name[pt_BR]=Breeze Light +-Name[ro]=Briză, luminos +-Name[ru]=Breeze, светлый вариант +-Name[sk]=Svetlý vánok +-Name[sl]=Sapica, svetla +-Name[sv]=Breeze ljus +-Name[tg]=Насими сабук +-Name[tr]=Esinti Açık +-Name[uk]=Світла Breeze +-Name[x-test]=xxBreeze Lightxx +-Name[zh_CN]=Breeze 微风浅色 +-Name[zh_TW]=Breeze Light ++ColorScheme=BreezeLightTint ++Name=Breeze Light (Tint) ++TintFactor=0.2 ++TitlebarIsAccentColored=true + shadeSortColumn=true + + [KDE] diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index d6a6a59..dc08ec4 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -13,6 +13,20 @@ let include "/run/current-system/sw/share/themes/${themeName}-Dark/gtk-2.0/gtkrc" gtk-theme-name="${themeName}-Dark" ''; + + breezeTint = pkgs.stdenv.mkDerivation { + name = "breeze-tint"; + src = "${pkgs.breeze-qt5}"; + patches = [ ./patches/BreezeTint.patch ]; + installPhase = '' + runHook preInstall + + mkdir -p $out/share/color-schemes/ + cp -r share/color-schemes/* $out/share/color-schemes/ + + runHook postInstall + ''; + }; in { @@ -57,4 +71,8 @@ in "xdg/gtk-3.0/settings.ini".text = gtk3and4settings; "gtk-2.0/gtkrc".text = gtk2settings; }; + + # Install the patched Breeze color schemes + environment.systemPackages = [ breezeTint ]; + } From aa00c6eefb993263fc79c28a3c309ceba6d65174 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 6 Jul 2023 21:13:53 +0200 Subject: [PATCH 0053/1125] Plasma: install tinted look and feel packages --- roles/kde/patches/TintedLookAndFeel.patch | 838 ++++++++++++++++++++++ roles/kde/plasma.nix | 17 +- 2 files changed, 853 insertions(+), 2 deletions(-) create mode 100644 roles/kde/patches/TintedLookAndFeel.patch diff --git a/roles/kde/patches/TintedLookAndFeel.patch b/roles/kde/patches/TintedLookAndFeel.patch new file mode 100644 index 0000000..b955cc3 --- /dev/null +++ b/roles/kde/patches/TintedLookAndFeel.patch @@ -0,0 +1,838 @@ +diff --git a/share/plasma/look-and-feel/org.kde.breezedark.desktop/metadata.json b/share/plasma/look-and-feel/org.kde.breezedark.desktop/metadata.json +deleted file mode 100644 +index eb49faf..0000000 +--- a/share/plasma/look-and-feel/org.kde.breezedark.desktop/metadata.json ++++ /dev/null +@@ -1,147 +0,0 @@ +-{ +- "KPlugin": { +- "Authors": [ +- { +- "Email": "plasma-devel@kde.org", +- "Name": "KDE Visual Design Group", +- "Name[ar]": "مجموعة التصميم المرئي لكِيدِي", +- "Name[az]": "KDE Vizual Dizayn Qrupu", +- "Name[be]": "Суполка візуальнага дызайну KDE", +- "Name[bg]": "KDE Visual Design Group", +- "Name[ca@valencia]": "Grup de disseny visual de KDE", +- "Name[ca]": "Grup de disseny visual de KDE", +- "Name[cs]": "Skupina vizuálního návrhu KDE", +- "Name[da]": "KDE Visual Design Group", +- "Name[de]": "KDE Visual Design Group", +- "Name[en_GB]": "KDE Visual Design Group", +- "Name[es]": "El grupo de diseño visual de KDE", +- "Name[eu]": "KDE Diseinu bisualeko taldea", +- "Name[fi]": "KDE:n visuaalinen suunnitteluryhmä", +- "Name[fr]": "Groupe de conception visuelle de KDE", +- "Name[hi]": "केडीई विज़ुअल डिज़ाइन दल", +- "Name[hu]": "KDE Visual Design Group", +- "Name[ia]": "KDE Visual Design Group (Gruppo de Designo Visual de KDE)", +- "Name[id]": "Grup Desain Visual KDE", +- "Name[is]": "Myndrænn hönnunarhópur KDE", +- "Name[it]": "KDE Visual Design Group", +- "Name[ja]": "KDE Visual Design Group", +- "Name[ka]": "KDE-ის ვიზუალური დიზაინის ჯგუფი", +- "Name[ko]": "KDE 시각 디자인 그룹", +- "Name[lt]": "KDE vaizdinio dizaino grupė", +- "Name[nl]": "KDE Visuele ontwerpgroep", +- "Name[nn]": "KDE Visual Design Group", +- "Name[pl]": "Grupa oprawy graficznej KDE", +- "Name[pt]": "Grupo de Desenho Visual do KDE", +- "Name[pt_BR]": "Grupo de Design Visual do KDE", +- "Name[ro]": "KDE Visual Design Group", +- "Name[ru]": "Группа KDE Visual Design", +- "Name[sk]": "KDE Visual Design Group", +- "Name[sl]": "Skupina vizualnega designa KDE", +- "Name[sv]": "KDE:s visuella designgrupp", +- "Name[ta]": "கே.டீ.யீ. வரைகலை வடிவமைப்புக் குழு", +- "Name[tr]": "KDE Görsel Tasarım Grubu", +- "Name[uk]": "Група з візуального дизайну KDE", +- "Name[vi]": "Đội Thiết kế Trực quan KDE", +- "Name[x-test]": "xxKDE Visual Design Groupxx", +- "Name[zh_CN]": "KDE 视觉设计团队" +- } +- ], +- "Category": "", +- "Description": "Breeze Dark by the KDE VDG", +- "Description[ar]": "نسيم داكن من من مجموعة تصميم كِيدِي", +- "Description[az]": "KDE VDG tərəfindən Breeze Qara", +- "Description[be]": "Breeze Dark ад KDE VDG", +- "Description[bg]": "Breeze Тъмен от KDE VDG", +- "Description[ca@valencia]": "Brisa fosca, creat pel VDG de KDE", +- "Description[ca]": "Brisa fosca, creat pel VDG del KDE", +- "Description[cs]": "Breeze Dark od KDE VDG", +- "Description[da]": "Breeze Dark af KDE's visuelle designgruppe", +- "Description[de]": "Breeze Dunkel von der KDE VDG", +- "Description[en_GB]": "Breeze Dark by the KDE VDG", +- "Description[es]": "Brisa oscuro por KDE VDG", +- "Description[et]": "Breeze tume KDE VDG-lt", +- "Description[eu]": "Breeze iluna KDEren VDGk egina", +- "Description[fi]": "Tumma Breeze KDE VDG:ltä", +- "Description[fr]": "Breeze sombre par le groupe de conception visuelle de KDE « VDG »", +- "Description[hi]": "केडीई वीडीजी द्वारा ब्रीज़ गहरा", +- "Description[hu]": "Breeze Dark a KDE VDG-től", +- "Description[ia]": "Breeze Dark (Brisa Obscure) per le KDE VDG", +- "Description[id]": "Breeze oleh KDE VDG", +- "Description[is]": "Breeze Dark frá KDE VDG", +- "Description[it]": "Brezza scuro del KDE VDG", +- "Description[ja]": "Breeze Dark by the KDE VDG", +- "Description[ka]": "Breeze Dark \"KDE VDG\"-სგან", +- "Description[ko]": "KDE 시각 디자인 그룹에서 제작한 어두운 Breeze", +- "Description[lt]": "Breeze tamsus pagal KDE VDG", +- "Description[nl]": "Breeze Dark door de KDE VDG", +- "Description[nn]": "Breeze mørk frå KDE VDG", +- "Description[pa]": "ਕੇਡੀਈ ਵੀਡੀਜੀ ਵਲੋਂ ਬਰੀਜ਼ ਗੂੜ੍ਹਾ", +- "Description[pl]": "Ciemna Bryza autorstwa KDE VDG", +- "Description[pt]": "Brisa Escuro da VDG do KDE", +- "Description[pt_BR]": "Breeze Dark pelo KDE VDG", +- "Description[ro]": "Briză, întunecat, de KDE VDG", +- "Description[ru]": "Тёмный вариант Breeze от KDE VDG", +- "Description[sk]": "Vánok Tmavý od KDE VDG", +- "Description[sl]": "Sapica temna avtorjev KDE VDG", +- "Description[sv]": "Breeze mörk av KDE:s visuella designgrupp", +- "Description[tr]": "KDE VDG'den Esinti Koyu", +- "Description[uk]": "Темна Breeze, автори — KDE VDG", +- "Description[vi]": "Breeze Tối, do KDE VDG", +- "Description[x-test]": "xxBreeze Dark by the KDE VDGxx", +- "Description[zh_CN]": "Breeze 微风深色主题,由 KDE VDG (视觉设计团队) 设计制作", +- "Description[zh_TW]": "由 KDE VDG 設計的 Breeze Dark", +- "Id": "org.kde.breezedark.desktop", +- "License": "GPLv2+", +- "Name": "Breeze Dark", +- "Name[ar]": "نسيم داكن", +- "Name[az]": "Breeze Qara", +- "Name[be]": "Breeze Dark", +- "Name[bg]": "Breeze Тъмен", +- "Name[ca@valencia]": "Brisa fosca", +- "Name[ca]": "Brisa fosca", +- "Name[cs]": "Breeze Tmavé", +- "Name[da]": "Breeze Dark", +- "Name[de]": "Breeze Dunkel", +- "Name[en_GB]": "Breeze Dark", +- "Name[es]": "Brisa oscuro", +- "Name[et]": "Breeze tume", +- "Name[eu]": "Breeze iluna", +- "Name[fi]": "Tumma Breeze", +- "Name[fr]": "Breeze sombre", +- "Name[hi]": "ब्रीज़ गहरा", +- "Name[hu]": "Breeze Dark", +- "Name[ia]": "Brisa obscure", +- "Name[id]": "Breeze Gelap", +- "Name[is]": "Breeze Dark", +- "Name[it]": "Brezza scuro", +- "Name[ja]": "Breeze Dark", +- "Name[ka]": "ნავი მუქი", +- "Name[ko]": "어두운 Breeze", +- "Name[lt]": "Breeze tamsus", +- "Name[nl]": "Breeze Dark", +- "Name[nn]": "Breeze mørk", +- "Name[pa]": "ਬਰੀਜ਼ ਗੂੜ੍ਹਾ", +- "Name[pl]": "Ciemna Bryza", +- "Name[pt]": "Brisa Escura", +- "Name[pt_BR]": "Breeze Dark", +- "Name[ro]": "Briză, întunecat", +- "Name[ru]": "Breeze, тёмный вариант", +- "Name[sk]": "Vánok Tmavý", +- "Name[sl]": "Sapica temna", +- "Name[sv]": "Breeze mörk", +- "Name[ta]": "கருப்பு பிரீஸ்", +- "Name[tg]": "Насими торик", +- "Name[tr]": "Esinti Koyu", +- "Name[uk]": "Темна Breeze", +- "Name[vi]": "Breeze Tối", +- "Name[x-test]": "xxBreeze Darkxx", +- "Name[zh_CN]": "Breeze 微风深色", +- "Name[zh_TW]": "Breeze Dark", +- "ServiceTypes": [ +- "Plasma/LookAndFeel" +- ], +- "Version": "2.0", +- "Website": "https://www.kde.org" +- }, +- "X-Plasma-MainScript": "defaults" +-} +diff --git a/share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/defaults b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/defaults +similarity index 90% +rename from share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/defaults +rename to share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/defaults +index 3db126f..764fa66 100644 +--- a/share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/defaults ++++ b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/defaults +@@ -2,7 +2,7 @@ + widgetStyle=Breeze + + [kdeglobals][General] +-ColorScheme=BreezeDark ++ColorScheme=BreezeDarkTint + + [kdeglobals][Icons] + Theme=breeze-dark +@@ -11,7 +11,7 @@ Theme=breeze-dark + name=default + + [Wallpaper] +-Image=Next ++Image=MilkyWay + + [kcminputrc][Mouse] + cursorTheme=breeze_cursors +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/layouts/org.kde.plasma.desktop-layout.js b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/layouts/org.kde.plasma.desktop-layout.js +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/layouts/org.kde.plasma.desktop-layout.js +rename to share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/layouts/org.kde.plasma.desktop-layout.js +diff --git a/share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/previews/fullscreenpreview.jpg b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/previews/fullscreenpreview.jpg +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/previews/fullscreenpreview.jpg +rename to share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/previews/fullscreenpreview.jpg +diff --git a/share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/previews/preview.png b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/previews/preview.png +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/previews/preview.png +rename to share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/previews/preview.png +diff --git a/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/metadata.json b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/metadata.json +new file mode 100644 +index 0000000..4103034 +--- /dev/null ++++ b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/metadata.json +@@ -0,0 +1,61 @@ ++{ ++ "KPlugin": { ++ "Authors": [ ++ { ++ "Email": "plasma-devel@kde.org", ++ "Name": "KDE Visual Design Group", ++ "Name[ar]": "مجموعة التصميم المرئي لكِيدِي", ++ "Name[az]": "KDE Vizual Dizayn Qrupu", ++ "Name[be]": "Суполка візуальнага дызайну KDE", ++ "Name[bg]": "KDE Visual Design Group", ++ "Name[ca@valencia]": "Grup de disseny visual de KDE", ++ "Name[ca]": "Grup de disseny visual de KDE", ++ "Name[cs]": "Skupina vizuálního návrhu KDE", ++ "Name[da]": "KDE Visual Design Group", ++ "Name[de]": "KDE Visual Design Group", ++ "Name[en_GB]": "KDE Visual Design Group", ++ "Name[es]": "El grupo de diseño visual de KDE", ++ "Name[eu]": "KDE Diseinu bisualeko taldea", ++ "Name[fi]": "KDE:n visuaalinen suunnitteluryhmä", ++ "Name[fr]": "Groupe de conception visuelle de KDE", ++ "Name[hi]": "केडीई विज़ुअल डिज़ाइन दल", ++ "Name[hu]": "KDE Visual Design Group", ++ "Name[ia]": "KDE Visual Design Group (Gruppo de Designo Visual de KDE)", ++ "Name[id]": "Grup Desain Visual KDE", ++ "Name[is]": "Myndrænn hönnunarhópur KDE", ++ "Name[it]": "KDE Visual Design Group", ++ "Name[ja]": "KDE Visual Design Group", ++ "Name[ka]": "KDE-ის ვიზუალური დიზაინის ჯგუფი", ++ "Name[ko]": "KDE 시각 디자인 그룹", ++ "Name[lt]": "KDE vaizdinio dizaino grupė", ++ "Name[nl]": "KDE Visuele ontwerpgroep", ++ "Name[nn]": "KDE Visual Design Group", ++ "Name[pl]": "Grupa oprawy graficznej KDE", ++ "Name[pt]": "Grupo de Desenho Visual do KDE", ++ "Name[pt_BR]": "Grupo de Design Visual do KDE", ++ "Name[ro]": "KDE Visual Design Group", ++ "Name[ru]": "Группа KDE Visual Design", ++ "Name[sk]": "KDE Visual Design Group", ++ "Name[sl]": "Skupina vizualnega designa KDE", ++ "Name[sv]": "KDE:s visuella designgrupp", ++ "Name[ta]": "கே.டீ.யீ. வரைகலை வடிவமைப்புக் குழு", ++ "Name[tr]": "KDE Görsel Tasarım Grubu", ++ "Name[uk]": "Група з візуального дизайну KDE", ++ "Name[vi]": "Đội Thiết kế Trực quan KDE", ++ "Name[x-test]": "xxKDE Visual Design Groupxx", ++ "Name[zh_CN]": "KDE 视觉设计团队" ++ } ++ ], ++ "Category": "", ++ "Description": "Breeze Dark (Tint) by the KDE VDG", ++ "Id": "org.kde.breezedarktint.desktop", ++ "License": "GPLv2+", ++ "Name": "Breeze Dark (Tint)", ++ "ServiceTypes": [ ++ "Plasma/LookAndFeel" ++ ], ++ "Version": "2.0", ++ "Website": "https://www.kde.org" ++ }, ++ "X-Plasma-MainScript": "defaults" ++} +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/ActionButton.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/ActionButton.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/ActionButton.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/ActionButton.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/Battery.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/Battery.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/Battery.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/Battery.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/Clock.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/Clock.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/Clock.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/Clock.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/SessionManagementScreen.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/SessionManagementScreen.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/SessionManagementScreen.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/SessionManagementScreen.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/UserDelegate.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/UserDelegate.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/UserDelegate.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/UserDelegate.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/UserList.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/UserList.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/UserList.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/UserList.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/VirtualKeyboard.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/VirtualKeyboard.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/VirtualKeyboard.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/VirtualKeyboard.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/VirtualKeyboard_wayland.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/VirtualKeyboard_wayland.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/VirtualKeyboard_wayland.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/VirtualKeyboard_wayland.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/WallpaperFader.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/WallpaperFader.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/WallpaperFader.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/WallpaperFader.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/animation/RejectPasswordAnimation.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/animation/RejectPasswordAnimation.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/animation/RejectPasswordAnimation.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/animation/RejectPasswordAnimation.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/animation/RejectPasswordPathAnimation.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/animation/RejectPasswordPathAnimation.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/animation/RejectPasswordPathAnimation.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/animation/RejectPasswordPathAnimation.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/README.txt b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/README.txt +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/README.txt +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/README.txt +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/logout_primary.svgz b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/logout_primary.svgz +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/logout_primary.svgz +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/logout_primary.svgz +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/restart_primary.svgz b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/restart_primary.svgz +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/restart_primary.svgz +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/restart_primary.svgz +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/shutdown_primary.svgz b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/shutdown_primary.svgz +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/shutdown_primary.svgz +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/shutdown_primary.svgz +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/defaults b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/defaults +similarity index 90% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/defaults +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/defaults +index d8df939..852c691 100644 +--- a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/defaults ++++ b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/defaults +@@ -2,7 +2,7 @@ + widgetStyle=Breeze + + [kdeglobals][General] +-ColorScheme=BreezeLight ++ColorScheme=BreezeLightTint + + [kdeglobals][Icons] + Theme=breeze +@@ -11,7 +11,7 @@ Theme=breeze + name=default + + [Wallpaper] +-Image=Next ++Image=MilkyWay + + [kcminputrc][Mouse] + cursorTheme=breeze_cursors +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/desktopswitcher/DesktopSwitcher.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/desktopswitcher/DesktopSwitcher.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/desktopswitcher/DesktopSwitcher.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/desktopswitcher/DesktopSwitcher.qml +diff --git a/share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/layouts/org.kde.plasma.desktop-layout.js b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/layouts/org.kde.plasma.desktop-layout.js +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/layouts/org.kde.plasma.desktop-layout.js +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/layouts/org.kde.plasma.desktop-layout.js +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/LockOsd.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/LockOsd.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/LockOsd.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/LockOsd.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/LockScreen.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/LockScreen.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/LockScreen.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/LockScreen.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/LockScreenUi.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/LockScreenUi.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/LockScreenUi.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/LockScreenUi.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/MainBlock.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/MainBlock.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/MainBlock.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/MainBlock.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/MediaControls.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/MediaControls.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/MediaControls.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/MediaControls.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/NoPasswordUnlock.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/NoPasswordUnlock.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/NoPasswordUnlock.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/NoPasswordUnlock.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/config.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/config.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/config.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/config.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/config.xml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/config.xml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/config.xml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/config.xml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/logout/Logout.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/logout/Logout.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/logout/Logout.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/logout/Logout.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/logout/LogoutButton.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/logout/LogoutButton.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/logout/LogoutButton.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/logout/LogoutButton.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/logout/timer.js b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/logout/timer.js +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/logout/timer.js +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/logout/timer.js +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/osd/Osd.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/osd/Osd.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/osd/Osd.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/osd/Osd.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/osd/OsdItem.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/osd/OsdItem.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/osd/OsdItem.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/osd/OsdItem.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/desktopswitcher.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/desktopswitcher.png +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/desktopswitcher.png +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/desktopswitcher.png +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/fullscreenpreview.jpg b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/fullscreenpreview.jpg +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/fullscreenpreview.jpg +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/fullscreenpreview.jpg +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/lockscreen.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/lockscreen.png +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/lockscreen.png +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/lockscreen.png +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/loginmanager.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/loginmanager.png +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/loginmanager.png +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/loginmanager.png +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/preview.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/preview.png +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/preview.png +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/preview.png +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/runcommand.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/runcommand.png +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/runcommand.png +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/runcommand.png +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/splash.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/splash.png +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/splash.png +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/splash.png +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/userswitcher.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/userswitcher.png +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/userswitcher.png +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/userswitcher.png +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/windowdecoration.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/windowdecoration.png +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/windowdecoration.png +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/windowdecoration.png +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/windowswitcher.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/windowswitcher.png +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/windowswitcher.png +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/windowswitcher.png +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/Splash.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/Splash.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/Splash.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/Splash.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/images/busywidget.svgz b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/images/busywidget.svgz +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/images/busywidget.svgz +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/images/busywidget.svgz +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/images/kde.svgz b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/images/kde.svgz +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/images/kde.svgz +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/images/kde.svgz +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/images/plasma.svgz b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/images/plasma.svgz +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/images/plasma.svgz +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/images/plasma.svgz +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/systemdialog/SystemDialog.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/systemdialog/SystemDialog.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/systemdialog/SystemDialog.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/systemdialog/SystemDialog.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/windowswitcher/WindowSwitcher.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/windowswitcher/WindowSwitcher.qml +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/windowswitcher/WindowSwitcher.qml +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/windowswitcher/WindowSwitcher.qml +diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/metadata.json b/share/plasma/look-and-feel/org.kde.breezetint.desktop/metadata.json +similarity index 72% +rename from share/plasma/look-and-feel/org.kde.breeze.desktop/metadata.json +rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/metadata.json +index a6899c0..108c44e 100644 +--- a/share/plasma/look-and-feel/org.kde.breeze.desktop/metadata.json ++++ b/share/plasma/look-and-feel/org.kde.breezetint.desktop/metadata.json +@@ -47,106 +47,10 @@ + } + ], + "Category": "", +- "Description": "Breeze by the KDE VDG", +- "Description[ar]": "نسيم من مجموعة تصميم كِيدِي", +- "Description[az]": "KDE VDG tərəfindən Breeze İş mühiti görünüşü", +- "Description[be]": "Breeze ад KDE VDG", +- "Description[bg]": "Breeze от KDE VDG", +- "Description[ca@valencia]": "Brisa, creat pel VDG de KDE", +- "Description[ca]": "Brisa, creat pel VDG del KDE", +- "Description[cs]": "Breeze od KDE VDG", +- "Description[da]": "Breeze af KDE's visuelle designgruppe", +- "Description[de]": "Breeze von der KDE VDG", +- "Description[en_GB]": "Breeze by the KDE VDG", +- "Description[es]": "Brisa por KDE VDG", +- "Description[et]": "Breeze KDE VDG-lt", +- "Description[eu]": "Breeze KDEren VDGk egina", +- "Description[fi]": "Breeze KDE VDG:ltä", +- "Description[fr]": "Breeze, par KDE VDG", +- "Description[hi]": "केडीई वीडीजी द्वारा ब्रीज़", +- "Description[hu]": "Breeze a KDE VDG-től", +- "Description[ia]": "Breeze (Brisa) per le KDE VDG", +- "Description[id]": "Breeze oleh KDE VDG", +- "Description[is]": "Breeze frá KDE VDG", +- "Description[it]": "Brezza del KDE VDG", +- "Description[ja]": "Breeze by the KDE VDG", +- "Description[ka]": "Breeze KDE VDG-სგან", +- "Description[ko]": "KDE 시각 디자인 그룹에서 제작한 Breeze", +- "Description[lt]": "Breeze pagal KDE VDG", +- "Description[nl]": "Breeze door de KDE VDG", +- "Description[nn]": "Breeze frå KDE VDG", +- "Description[pa]": "KDE VDG ਵਲੋਂ ਬਰੀਜ਼", +- "Description[pl]": "Bryza autorstwa KDE VDG", +- "Description[pt]": "Brisa da VDG do KDE", +- "Description[pt_BR]": "Breeze pelo KDE VDG", +- "Description[ro]": "Briză, de KDE VDG", +- "Description[ru]": "Оформление рабочей среды Breeze от KDE VDG", +- "Description[sk]": "Vánok od KDE VDG", +- "Description[sl]": "Sapica avtorjev KDE VDG", +- "Description[sv]": "Breeze av KDE:s visuella designgrupp", +- "Description[tr]": "KDE VDG'den Esinti", +- "Description[uk]": "Breeze, автори — KDE VDG", +- "Description[vi]": "Breeze, do KDE VDG", +- "Description[x-test]": "xxBreeze by the KDE VDGxx", +- "Description[zh_CN]": "Breeze 微风主题,由 KDE VDG (视觉设计团队) 设计制作", +- "Description[zh_TW]": "由 KDE VDG 設計的 Breeze", +- "Id": "org.kde.breeze.desktop", ++ "Description": "Breeze (Tint) by the KDE VDG", ++ "Id": "org.kde.breezetint.desktop", + "License": "GPLv2+", +- "Name": "Breeze", +- "Name[ar]": "نسيم", +- "Name[az]": "Breeze", +- "Name[be]": "Breeze", +- "Name[bg]": "Breeze", +- "Name[bs]": "Breeze", +- "Name[ca@valencia]": "Brisa", +- "Name[ca]": "Brisa", +- "Name[cs]": "Breeze", +- "Name[da]": "Breeze", +- "Name[de]": "Breeze", +- "Name[el]": "Breeze", +- "Name[en_GB]": "Breeze", +- "Name[es]": "Brisa", +- "Name[et]": "Breeze", +- "Name[eu]": "Breeze", +- "Name[fi]": "Breeze", +- "Name[fr]": "Breeze", +- "Name[gl]": "Breeze", +- "Name[hi]": "ब्रीज़", +- "Name[hu]": "Breeze", +- "Name[ia]": "Brisa", +- "Name[id]": "Breeze", +- "Name[is]": "Breeze", +- "Name[it]": "Brezza", +- "Name[ja]": "Breeze", +- "Name[ka]": "ნიავი", +- "Name[ko]": "Breeze", +- "Name[lt]": "Breeze", +- "Name[ml]": "ബ്രീസ്", +- "Name[nb]": "Breeze", +- "Name[nds]": "Breeze", +- "Name[nl]": "Breeze", +- "Name[nn]": "Breeze", +- "Name[pa]": "ਬਰੀਜ਼", +- "Name[pl]": "Bryza", +- "Name[pt]": "Brisa", +- "Name[pt_BR]": "Breeze", +- "Name[ro]": "Briză", +- "Name[ru]": "Breeze", +- "Name[sk]": "Vánok", +- "Name[sl]": "Sapica", +- "Name[sr@ijekavian]": "Поветарац", +- "Name[sr@ijekavianlatin]": "Povetarac", +- "Name[sr@latin]": "Povetarac", +- "Name[sr]": "Поветарац", +- "Name[sv]": "Breeze", +- "Name[ta]": "பிரீஸ்", +- "Name[tg]": "Насим", +- "Name[tr]": "Esinti", +- "Name[uk]": "Breeze", +- "Name[vi]": "Breeze", +- "Name[x-test]": "xxBreezexx", +- "Name[zh_CN]": "Breeze 微风", +- "Name[zh_TW]": "微風", ++ "Name": "Breeze (Tint)", + "ServiceTypes": [ + "Plasma/LookAndFeel" + ], +diff --git a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/metadata.json b/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/metadata.json +deleted file mode 100644 +index 16dec51..0000000 +--- a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/metadata.json ++++ /dev/null +@@ -1,145 +0,0 @@ +-{ +- "KPlugin": { +- "Authors": [ +- { +- "Email": "plasma-devel@kde.org", +- "Name": "KDE Visual Design Group", +- "Name[ar]": "مجموعة التصميم المرئي لكِيدِي", +- "Name[az]": "KDE Vizual Dizayn Qrupu", +- "Name[be]": "Суполка візуальнага дызайну KDE", +- "Name[bg]": "KDE Visual Design Group", +- "Name[ca@valencia]": "Grup de disseny visual de KDE", +- "Name[ca]": "Grup de disseny visual de KDE", +- "Name[cs]": "Skupina vizuálního návrhu KDE", +- "Name[da]": "KDE Visual Design Group", +- "Name[de]": "KDE Visual Design Group", +- "Name[en_GB]": "KDE Visual Design Group", +- "Name[es]": "El grupo de diseño visual de KDE", +- "Name[eu]": "KDE Diseinu bisualeko taldea", +- "Name[fi]": "KDE:n visuaalinen suunnitteluryhmä", +- "Name[fr]": "Groupe de conception visuelle de KDE", +- "Name[hi]": "केडीई विज़ुअल डिज़ाइन दल", +- "Name[hu]": "KDE Visual Design Group", +- "Name[ia]": "KDE Visual Design Group (Gruppo de Designo Visual de KDE)", +- "Name[id]": "Grup Desain Visual KDE", +- "Name[is]": "Myndrænn hönnunarhópur KDE", +- "Name[it]": "KDE Visual Design Group", +- "Name[ja]": "KDE Visual Design Group", +- "Name[ka]": "KDE-ის ვიზუალური დიზაინის ჯგუფი", +- "Name[ko]": "KDE 시각 디자인 그룹", +- "Name[lt]": "KDE vaizdinio dizaino grupė", +- "Name[nl]": "KDE Visuele ontwerpgroep", +- "Name[nn]": "KDE Visual Design Group", +- "Name[pl]": "Grupa oprawy graficznej KDE", +- "Name[pt]": "Grupo de Desenho Visual do KDE", +- "Name[pt_BR]": "Grupo de Design Visual do KDE", +- "Name[ro]": "KDE Visual Design Group", +- "Name[ru]": "Группа KDE Visual Design", +- "Name[sk]": "KDE Visual Design Group", +- "Name[sl]": "Skupina vizualnega designa KDE", +- "Name[sv]": "KDE:s visuella designgrupp", +- "Name[ta]": "கே.டீ.யீ. வரைகலை வடிவமைப்புக் குழு", +- "Name[tr]": "KDE Görsel Tasarım Grubu", +- "Name[uk]": "Група з візуального дизайну KDE", +- "Name[vi]": "Đội Thiết kế Trực quan KDE", +- "Name[x-test]": "xxKDE Visual Design Groupxx", +- "Name[zh_CN]": "KDE 视觉设计团队" +- } +- ], +- "Category": "", +- "Description": "Breeze Twilight by the KDE VDG", +- "Description[ar]": "نسيم الفجر من مجموعة تصميم كِيدِي", +- "Description[az]": "KDE VDG tərəfindən Breeze Toranlıq", +- "Description[be]": "Breeze Twilight ад KDE VDG", +- "Description[bg]": "Breeze Здрач от KDE VDG", +- "Description[ca@valencia]": "Brisa crepuscular, creat pel VDG de KDE", +- "Description[ca]": "Brisa crepuscular, creat pel VDG del KDE", +- "Description[cs]": "Breeze Twilight od KDE VDG", +- "Description[da]": "Breeze Twilight af KDE VDG", +- "Description[de]": "Breeze Dämmerung von der KDE VG", +- "Description[en_GB]": "Breeze Twilight by the KDE VDG", +- "Description[es]": "Brisa crepúsculo por KDE VDG", +- "Description[et]": "Breeze videvik KDE VDG-lt", +- "Description[eu]": "Breeze ilunabarra KDEren VDGk egina", +- "Description[fi]": "Hämärä Breeze KDE VDG:ltä", +- "Description[fr]": "Breeze clair-obscur par l'équipe de conception visuelle de KDE « VDG »", +- "Description[hi]": "केडीई वीडीजी द्वारा ब्रीज़ गोधूली", +- "Description[hu]": "Breeze Twilight a KDE VDG-től", +- "Description[ia]": "Brisa Crepusculo (Breeze Twilight) per KDE VDG", +- "Description[id]": "Breeze Twilight oleh KDE VDG", +- "Description[is]": "Breeze Twilight frá KDE VDG", +- "Description[it]": "Brezza crepuscolo del VDG di KDE", +- "Description[ja]": "Breeze Twilight by the KDE VDG", +- "Description[ka]": "Breeze Twilight-ი KDE VDG-ის მიერ", +- "Description[ko]": "KDE 시각 디자인 그룹에서 제작한 새벽의 Breeze", +- "Description[lt]": "Breeze prieblanda pagal KDE VDG", +- "Description[nl]": "Breeze Twilight door de KDE VDG", +- "Description[nn]": "Breeze skumring frå KDE VDG", +- "Description[pl]": "Półmroczna bryza autorstwa KDE VDG", +- "Description[pt]": "Brisa ao Anoitecer da VDG do KDE", +- "Description[pt_BR]": "Breeze Twilight pelo KDE VDG", +- "Description[ro]": "Briză, amurg, de KDE VDG", +- "Description[ru]": "Оформление рабочей среды Breeze Twilight от KDE VDG", +- "Description[sk]": "Vánok Súmrak od KDE VDG", +- "Description[sl]": "Sapica ob mraku avtorjev KDE VDG", +- "Description[sv]": "Breeze skymning av KDE:s visuella designgrupp", +- "Description[tr]": "KDE VDG'den Esinti Gündoğumu", +- "Description[uk]": "Сутінкова Breeze, автори — KDE VDG", +- "Description[vi]": "Breeze Chạng vạng, do KDE VDG", +- "Description[x-test]": "xxBreeze Twilight by the KDE VDGxx", +- "Description[zh_CN]": "Breeze 微风阴阳主题,由 KDE VDG (视觉设计团队) 设计制作", +- "Description[zh_TW]": "由 KDE VDG 設計的 Breeze Twilight", +- "Id": "org.kde.breezetwilight.desktop", +- "License": "GPLv2+", +- "Name": "Breeze Twilight", +- "Name[ar]": "نسيم الفجر", +- "Name[az]": "Breeze Toranlıq", +- "Name[be]": "Breeze Twilight", +- "Name[bg]": "Breeze Здрач", +- "Name[ca@valencia]": "Brisa crepuscular", +- "Name[ca]": "Brisa crepuscular", +- "Name[cs]": "Breeze Twilight", +- "Name[da]": "Breeze Twilight", +- "Name[de]": "Breeze Dämmerung", +- "Name[en_GB]": "Breeze Twilight", +- "Name[es]": "Brisa crepúsculo", +- "Name[et]": "Breeze videvik", +- "Name[eu]": "Breeze ilunabarra", +- "Name[fi]": "Hämärä Breeze", +- "Name[fr]": "Breeze clair-obscur ", +- "Name[hi]": "ब्रीज़ गोधूली", +- "Name[hu]": "Breeze Twilight", +- "Name[ia]": "Brisa Crepusculo (Breeze Twilight)", +- "Name[id]": "Breeze Twilight", +- "Name[is]": "Breeze Twilight", +- "Name[it]": "Brezza crepuscolo", +- "Name[ja]": "Breeze Twilight", +- "Name[ka]": "ნიავი ღია", +- "Name[ko]": "새벽의 Breeze", +- "Name[lt]": "Breeze prieblanda", +- "Name[nl]": "Breeze Twilight", +- "Name[nn]": "Breeze skumring", +- "Name[pa]": "ਬਰੀਜ਼ ਆਥਣ", +- "Name[pl]": "Półmroczna bryza", +- "Name[pt]": "Brisa ao Anoitecer", +- "Name[pt_BR]": "Breeze Twilight", +- "Name[ro]": "Briză, amurg", +- "Name[ru]": "Breeze Twilight", +- "Name[sk]": "Vánok Súmrak", +- "Name[sl]": "Sapica ob mraku", +- "Name[sv]": "Breeze skymning", +- "Name[ta]": "கலந்த பிரீஸ்", +- "Name[tg]": "Насими нимторикӣ", +- "Name[tr]": "Esinti Gündoğumu", +- "Name[uk]": "Сутінкова Breeze", +- "Name[vi]": "Breeze Chạng vạng", +- "Name[x-test]": "xxBreeze Twilightxx", +- "Name[zh_CN]": "Breeze 微风阴阳", +- "ServiceTypes": [ +- "Plasma/LookAndFeel" +- ], +- "Version": "2.0", +- "Website": "https://www.kde.org" +- }, +- "X-Plasma-MainScript": "defaults" +-} +diff --git a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/defaults b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/defaults +similarity index 90% +rename from share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/defaults +rename to share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/defaults +index 02bc445..8537d4b 100644 +--- a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/defaults ++++ b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/defaults +@@ -2,7 +2,7 @@ + widgetStyle=Breeze + + [kdeglobals][General] +-ColorScheme=BreezeLight ++ColorScheme=BreezeLightTint + + [kdeglobals][Icons] + Theme=breeze +@@ -11,7 +11,7 @@ Theme=breeze + name=breeze-dark + + [Wallpaper] +-Image=Next ++Image=MilkyWay + + [kcminputrc][Mouse] + cursorTheme=breeze_cursors +diff --git a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/layouts/org.kde.plasma.desktop-layout.js b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/layouts/org.kde.plasma.desktop-layout.js +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/layouts/org.kde.plasma.desktop-layout.js +rename to share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/layouts/org.kde.plasma.desktop-layout.js +diff --git a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/previews/fullscreenpreview.jpg b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/previews/fullscreenpreview.jpg +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/previews/fullscreenpreview.jpg +rename to share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/previews/fullscreenpreview.jpg +diff --git a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/previews/preview.png b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/previews/preview.png +similarity index 100% +rename from share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/previews/preview.png +rename to share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/previews/preview.png +diff --git a/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/metadata.json b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/metadata.json +new file mode 100644 +index 0000000..405d0fd +--- /dev/null ++++ b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/metadata.json +@@ -0,0 +1,61 @@ ++{ ++ "KPlugin": { ++ "Authors": [ ++ { ++ "Email": "plasma-devel@kde.org", ++ "Name": "KDE Visual Design Group", ++ "Name[ar]": "مجموعة التصميم المرئي لكِيدِي", ++ "Name[az]": "KDE Vizual Dizayn Qrupu", ++ "Name[be]": "Суполка візуальнага дызайну KDE", ++ "Name[bg]": "KDE Visual Design Group", ++ "Name[ca@valencia]": "Grup de disseny visual de KDE", ++ "Name[ca]": "Grup de disseny visual de KDE", ++ "Name[cs]": "Skupina vizuálního návrhu KDE", ++ "Name[da]": "KDE Visual Design Group", ++ "Name[de]": "KDE Visual Design Group", ++ "Name[en_GB]": "KDE Visual Design Group", ++ "Name[es]": "El grupo de diseño visual de KDE", ++ "Name[eu]": "KDE Diseinu bisualeko taldea", ++ "Name[fi]": "KDE:n visuaalinen suunnitteluryhmä", ++ "Name[fr]": "Groupe de conception visuelle de KDE", ++ "Name[hi]": "केडीई विज़ुअल डिज़ाइन दल", ++ "Name[hu]": "KDE Visual Design Group", ++ "Name[ia]": "KDE Visual Design Group (Gruppo de Designo Visual de KDE)", ++ "Name[id]": "Grup Desain Visual KDE", ++ "Name[is]": "Myndrænn hönnunarhópur KDE", ++ "Name[it]": "KDE Visual Design Group", ++ "Name[ja]": "KDE Visual Design Group", ++ "Name[ka]": "KDE-ის ვიზუალური დიზაინის ჯგუფი", ++ "Name[ko]": "KDE 시각 디자인 그룹", ++ "Name[lt]": "KDE vaizdinio dizaino grupė", ++ "Name[nl]": "KDE Visuele ontwerpgroep", ++ "Name[nn]": "KDE Visual Design Group", ++ "Name[pl]": "Grupa oprawy graficznej KDE", ++ "Name[pt]": "Grupo de Desenho Visual do KDE", ++ "Name[pt_BR]": "Grupo de Design Visual do KDE", ++ "Name[ro]": "KDE Visual Design Group", ++ "Name[ru]": "Группа KDE Visual Design", ++ "Name[sk]": "KDE Visual Design Group", ++ "Name[sl]": "Skupina vizualnega designa KDE", ++ "Name[sv]": "KDE:s visuella designgrupp", ++ "Name[ta]": "கே.டீ.யீ. வரைகலை வடிவமைப்புக் குழு", ++ "Name[tr]": "KDE Görsel Tasarım Grubu", ++ "Name[uk]": "Група з візуального дизайну KDE", ++ "Name[vi]": "Đội Thiết kế Trực quan KDE", ++ "Name[x-test]": "xxKDE Visual Design Groupxx", ++ "Name[zh_CN]": "KDE 视觉设计团队" ++ } ++ ], ++ "Category": "", ++ "Description": "Breeze Twilight (Tint) by the KDE VDG", ++ "Id": "org.kde.breezetwilighttint.desktop", ++ "License": "GPLv2+", ++ "Name": "Breeze Twilight (Tint)", ++ "ServiceTypes": [ ++ "Plasma/LookAndFeel" ++ ], ++ "Version": "2.0", ++ "Website": "https://www.kde.org" ++ }, ++ "X-Plasma-MainScript": "defaults" ++} diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index dc08ec4..1acc523 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -24,6 +24,19 @@ let mkdir -p $out/share/color-schemes/ cp -r share/color-schemes/* $out/share/color-schemes/ + runHook postInstall + ''; + }; + lookAndFeel = pkgs.stdenv.mkDerivation { + name = "toast-look-and-feel"; + src = "${pkgs.plasma-workspace}"; + patches = [ ./patches/TintedLookAndFeel.patch ]; + installPhase = '' + runHook preInstall + + mkdir -p $out/share/plasma/look-and-feel/ + cp -r share/plasma/look-and-feel/* $out/share/plasma/look-and-feel/ + runHook postInstall ''; }; @@ -72,7 +85,7 @@ in "gtk-2.0/gtkrc".text = gtk2settings; }; - # Install the patched Breeze color schemes - environment.systemPackages = [ breezeTint ]; + # Install the patched Breeze color schemes and look and feel packages + environment.systemPackages = [ breezeTint lookAndFeel ]; } From ac567396db4db4367a19d26894f54a50da6c05e1 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 7 Jul 2023 23:32:29 +0200 Subject: [PATCH 0054/1125] Plasma: change default settings --- roles/kde/plasma.nix | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 1acc523..f3586a3 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -14,6 +14,15 @@ let gtk-theme-name="${themeName}-Dark" ''; + # Set up the default kde options + kdeglobals = lib.generators.toINI {} { + KDE.LookAndFeelPackage = "org.kde.breezedarktint.desktop"; + KDE.SingleClick = false; + General = { + accentColorFromWallpaper = true; + AccentColor = "172,53,164" ; }; + }; + breezeTint = pkgs.stdenv.mkDerivation { name = "breeze-tint"; src = "${pkgs.breeze-qt5}"; @@ -40,6 +49,22 @@ let runHook postInstall ''; }; + + # /etc/xdg is not read by plasma, so to change the default settings you need to put them in a package + plasmaDefaults = pkgs.stdenv.mkDerivation { + name = "toast-plasma-defaults"; + dontUnpack = true; + installPhase = '' + runHook preInstall + + set -x + mkdir -p $out/etc/xdg + echo "${kdeglobals}" > $out/etc/xdg/kdeglobals + + runHook postInstall + ''; + }; + in { @@ -85,7 +110,10 @@ in "gtk-2.0/gtkrc".text = gtk2settings; }; - # Install the patched Breeze color schemes and look and feel packages - environment.systemPackages = [ breezeTint lookAndFeel ]; + /* + Install the patched Breeze color schemes and look and feel packages, + as well as the plasma default configs + */ + environment.systemPackages = [ breezeTint lookAndFeel plasmaDefaults ]; } From 76630bb781a2d317dd15733db47d84c276de9495 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 7 Jul 2023 23:37:18 +0200 Subject: [PATCH 0055/1125] Plasma: remove leftover command from testing --- roles/kde/plasma.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index f3586a3..baec988 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -96,7 +96,6 @@ in text= '' echo "updating system dconf database..." ${pkgs.dconf}/bin/dconf update - touch /testfile ''; deps = [ "etc" ]; }; From b7cbebdd058c475d38a6fe636818c93faf8398a6 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 7 Jul 2023 23:41:35 +0200 Subject: [PATCH 0056/1125] Common: install file --- roles/common/programs/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index 6262b48..e3aaa87 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -12,6 +12,7 @@ environment.systemPackages = with pkgs; [ speedtest-cli bat + file nvd ncdu tree From c7206aa602d63ec051a19c8fc94039b9b483df53 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 12 Jul 2023 19:39:38 +0200 Subject: [PATCH 0057/1125] Update lock file --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index a4098ff..4a32b35 100644 --- a/flake.lock +++ b/flake.lock @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1687647343, - "narHash": "sha256-1/o/i9KEFOBdlF9Cs04kBcqDFbYMt6W4SMqGa+QnnaI=", + "lastModified": 1689134369, + "narHash": "sha256-0G9dutIvhS/WUr3Awcnqw71g8EVVvvkOhVDnDDbY4Fw=", "owner": "nix-community", "repo": "home-manager", - "rev": "0ee5ab611dc1fbb5180bd7d88d2aeb7841a4d179", + "rev": "e42fb59768f0305085abde0dd27ab5e0cc15420c", "type": "github" }, "original": { @@ -70,11 +70,11 @@ ] }, "locked": { - "lastModified": 1687163790, - "narHash": "sha256-CmG/ZdswJrWM0CMgJiVyWfO6LqaI4SKEAx9IrnYDrpI=", + "lastModified": 1687871164, + "narHash": "sha256-bBFlPthuYX322xOlpJvkjUBz0C+MOBjZdDOOJJ+G2jU=", "owner": "nix-community", "repo": "home-manager", - "rev": "ac53777f52929bc82efcd2830bfc5aa60bcb4337", + "rev": "07c347bb50994691d7b0095f45ebd8838cf6bc38", "type": "github" }, "original": { @@ -101,11 +101,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1687379288, - "narHash": "sha256-cSuwfiqYfeVyqzCRkU9AvLTysmEuSal8nh6CYr+xWog=", + "lastModified": 1689137672, + "narHash": "sha256-QZoHxr0a73x6rQcAo5CiwYpysHbSnk7lAR8/16um7mM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ef0bc3976340dab9a4e087a0bcff661a8b2e87f3", + "rev": "98da3dd0de6660d4abed7bb74e748694bd803413", "type": "github" }, "original": { @@ -116,11 +116,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1686960236, - "narHash": "sha256-AYCC9rXNLpUWzD9hm+askOfpliLEC9kwAo7ITJc4HIw=", + "lastModified": 1689098530, + "narHash": "sha256-fxc/9f20wRyo/5ydkmZkX/Sh/ULa7RcT8h+cUv8p/44=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "04af42f3b31dba0ef742d254456dc4c14eedac86", + "rev": "f2406198ea0e4e37d4380d0e20336c575b8f8ef9", "type": "github" }, "original": { From 7c41dfd9b30ffff79fce501a896b752c20ed11a3 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 12 Jul 2023 21:03:06 +0200 Subject: [PATCH 0058/1125] Archie: switch kernel to xanmod --- machines/Archie/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/machines/Archie/configuration.nix b/machines/Archie/configuration.nix index c01b561..4b56c96 100644 --- a/machines/Archie/configuration.nix +++ b/machines/Archie/configuration.nix @@ -18,6 +18,8 @@ }; boot.loader.efi.canTouchEfiVariables = true; + boot.kernelPackages = pkgs.linuxKernel.packages.linux_xanmod_latest; + networking.hostName = "Archie"; # Define your hostname. networking.networkmanager.enable = true; # Enable networking From 31d1018267c7b49a5a851901e6064f66388d3469 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 12 Jul 2023 21:24:10 +0200 Subject: [PATCH 0059/1125] Kde: enable kate --- roles/kde/default.nix | 1 + roles/kde/kate.nix | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 roles/kde/kate.nix diff --git a/roles/kde/default.nix b/roles/kde/default.nix index ffcbb8f..76968a3 100755 --- a/roles/kde/default.nix +++ b/roles/kde/default.nix @@ -4,5 +4,6 @@ imports = [ ./plasma.nix ./sddm.nix + ./kate.nix ]; } diff --git a/roles/kde/kate.nix b/roles/kde/kate.nix new file mode 100644 index 0000000..ff84a90 --- /dev/null +++ b/roles/kde/kate.nix @@ -0,0 +1,8 @@ +{ config, pkgs, ... }: + +{ + home-manager.users.toast = { config, pkgs, ... }: + { + home.packages = [ pkgs.kate ]; + }; +} From 92f599675973f7f9cbe4244e2e414a34536b0ca8 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 13 Jul 2023 21:51:35 +0200 Subject: [PATCH 0060/1125] Micro: change clipboard to internal --- roles/common/programs/micro.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/common/programs/micro.nix b/roles/common/programs/micro.nix index a80a708..e92646b 100644 --- a/roles/common/programs/micro.nix +++ b/roles/common/programs/micro.nix @@ -7,7 +7,7 @@ programs.micro = { enable = true; settings = { - clipboard = "terminal"; + clipboard = "internal"; indentchar = "|"; softwrap = true; }; From 46f3c709570544f8b82df550323826419327400a Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 13 Jul 2023 18:25:27 +0200 Subject: [PATCH 0061/1125] Common: don't keep host keys as secrets --- roles/common/configuration.nix | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index c2b45d4..ba301c4 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -27,32 +27,15 @@ # enter the password A LOT of times. Only on the first setup tho "/tmp/id_ed25519_bootstrap" ]; - # Copy (NOT SYMLINK) host ssh keys into place - secrets = { - "ed25519" = { - symlink = false; - file = ../../secrets/${config.networking.hostName}/host-key-ed25519; - path = "/etc/ssh/ssh_host_ed25519_key"; - }; - "rsa" = { - symlink = false; - file = ../../secrets/${config.networking.hostName}/host-key-rsa; - path= "/etc/ssh/ssh_host_rsa_key"; - }; - "ed25519-public" = { - symlink = false; - file = ../../secrets/${config.networking.hostName}/host-key-ed25519-public; - path = "/etc/ssh/ssh_host_ed25519_key.pub"; - mode = "0644"; - }; - "rsa-public" = { - symlink = false; - file = ../../secrets/${config.networking.hostName}/host-key-rsa-public; - path = "/etc/ssh/ssh_host_rsa_key.pub"; - mode = "0644"; - }; - }; }; + /* + I used to keep the host keys in the repo as a secret, but since I use the + host keys for decrypting too I'm not sure encrypting a key with itself + is a good idea. Now the host keys will need to be placed manually where they are needed + For first time installs they are generated by services.openssh.hostKeys on servers, and + manually on everything else + */ + system.stateVersion = "23.05"; } From e91cb56c09ce16be03ad787c50cf9e932a273f1b Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 13 Jul 2023 19:32:19 +0200 Subject: [PATCH 0062/1125] Secrets: remove uneeded secrets --- secrets/Archie/host-key-ed25519 | 14 -------------- secrets/Archie/host-key-ed25519-public | 10 ---------- secrets/Archie/host-key-rsa | Bin 3757 -> 0 bytes secrets/Archie/host-key-rsa-public | Bin 1202 -> 0 bytes secrets/Everest/host-key-ed25519 | Bin 879 -> 0 bytes secrets/Everest/host-key-ed25519-public | 9 --------- secrets/Everest/host-key-rsa | Bin 3736 -> 0 bytes secrets/Everest/host-key-rsa-public | Bin 1110 -> 0 bytes secrets/secrets.nix | 8 -------- 9 files changed, 41 deletions(-) delete mode 100644 secrets/Archie/host-key-ed25519 delete mode 100644 secrets/Archie/host-key-ed25519-public delete mode 100644 secrets/Archie/host-key-rsa delete mode 100644 secrets/Archie/host-key-rsa-public delete mode 100644 secrets/Everest/host-key-ed25519 delete mode 100644 secrets/Everest/host-key-ed25519-public delete mode 100644 secrets/Everest/host-key-rsa delete mode 100644 secrets/Everest/host-key-rsa-public diff --git a/secrets/Archie/host-key-ed25519 b/secrets/Archie/host-key-ed25519 deleted file mode 100644 index ddd8e91..0000000 --- a/secrets/Archie/host-key-ed25519 +++ /dev/null @@ -1,14 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 zhSyTg v0zMwf3PyU8i5Z8cKQAM8G/egqkmPONA7twvIsTtFUU -4BlqeR6PpQrYwf7BT1UXqzaiiNwHAxsbbvX1Sk7YG7M --> ssh-ed25519 AuWU1Q m0nCQcYG0Jz8AeouayMRTPiQvZxWDbci88ouaaW1kBE -FMRP4tDLTQ8wo/9j6AaVhl4/amQAjgZDPKqmtzTwHbI --> tR-grease jXU -zPQZdJy9DQ9MUenFWBk ---- NY5Z2u04JmXtfy09gfYTziCNqdXfSXQLe3n/e7wburg - -KQoa|ɗ .hS -^aɹL)m. At}BR!7J%f#f_/=d:\[ TxȔUs(:I~-i -l!(̮SG^٢Vڗig~MDdnWqÕb7P\CαI}msU4="1.:aT-Ooy%v$iBN)s8OV(EDžtWi;nP7Q0·tR+W1BdTTOWf>6C>nT¾ -K)D81il3JPQw.w\&6j T:8E`,"a҂<dKrc2䴃<~ -h?Fc - ΣJtoD \ No newline at end of file diff --git a/secrets/Archie/host-key-ed25519-public b/secrets/Archie/host-key-ed25519-public deleted file mode 100644 index 91e279e..0000000 --- a/secrets/Archie/host-key-ed25519-public +++ /dev/null @@ -1,10 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 zhSyTg Xkk6wPQm3Sm3RuNyKhnKVz/evGJtr0UwhB7m2iuhrR4 -RMheqKeCD+Py22+xmvp3Se1z84t60+6y1Bbt7uYGxFs --> ssh-ed25519 AuWU1Q 5l5/vuIGxW+6ZzlDKjLzNCxyiW1+Kh651xpnwjfF3FQ -ZIx/zZZMPpO8zDW5JdkucIBVH1xK4KtoA7Kovw+bcOU --> 7%-grease [ wwEC MxP UF:U6Cy -Hp7t6AxdTAfm4r/LMWAt22vOYvhfHJLX4BIB7eEUfQnNAPIx43SrK8QIrAGHWbxN -hdO18C5g6xoE5HHz5uM5ASzUWC4Nws3OXwY ---- 2kwRA1NakiMhvMQgkaiEiJ93SkjTmOt77m0tO+e/p/w -^^I=*='V [$-ʲ} .=&ɭl@l5׏pIKVNCԎ I_<g.mf}O4( @ ; \ No newline at end of file diff --git a/secrets/Archie/host-key-rsa b/secrets/Archie/host-key-rsa deleted file mode 100644 index e323c7a1265ff3085212e80c09eed605c5a026e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3757 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 diff --git a/secrets/Archie/host-key-rsa-public b/secrets/Archie/host-key-rsa-public deleted file mode 100644 index 8bb561db243e632bdcd11af2bd6650d03abb2a55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1202 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCTy$_TCuNmnSVNOKA> zvq%Bvb}2LsPV?1Hu{3ru zax*A#Ht;bD@NzUt_s@3mFLCyYa*s4N_jk)MOGdZNu{1o?Fi=6;r660sys{$DGuNri zBhfje+&IfOJIX@etoICpYYhvelA0*4fuRRyeHe80)I`$xisQ`I*mqq!@--YWR{%>23)TgIi0N)wdW ztTzRB7;3uoM0rY8{(J5G@JGmxkA13lZ~Q$p%`L#bM& zAvK?=uSRyM&E93+9ZK8IF>+h%FDcB~k`pcO5M;X|>9WJK6OXqsO-%afw_?-k8g;R} z?dfd?Jc?I*+5O5kL-SGbmqqi#I{v4|^t8pE%P9SMzPVD>H?Q;Nro?51{W_61>V1BG zY4E#Uw{HG{Sx=4oN_Xe2e;jyWe!|Ve_fs>rE!(ngPA1Eh>l2E7LbT$7(j*gZMLo~) zwvw7>x3GytdvduiM`5pJlF_c{C;#$WwfA@nTI@85lsZ~029-+J7keA4FDi=y&p)|{CeOCMz2xI8J-^N!@zb^8q@I~c#U zO!!>NY&7R=shT{F?~;1Bk!4=Kg2a@`I;G*U3W#V6`Jv*?(!pdg|(k% zMSi(0aG}<4-P~8fcZ%wtRBrHLvb$Eg)alXFFYlL|2gPxAG+tPhYhPsM?{QE0_r$Xn z*0oO@zs=i}{KfFv{;GAarfKvo*SZn6J?kvX_4N!Zk8oxx)rV?me?K4oZz=o24~JX( zTkrpGJdk+Hv+ePg|^)3P;tq&hckTP{{~u6g;zvdpXJY~0LP!mr0% nP0W~IX}L;yvFnA1_6fUqC-#>q>s@|cG)Z!nq)X3}3ICG;l2H|N diff --git a/secrets/Everest/host-key-ed25519 b/secrets/Everest/host-key-ed25519 deleted file mode 100644 index 0fe034f228173cf253f5a6a62845a0749015a4b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 879 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCSPEi8(xa8xi)_0A40 zjx^3PH!9QjvGn&XFD>yja4yzP^DcA^4Du`vv@G#032})EH{hx)iz+hAjL1uL_D}Ol zGcwBy4T%a!^K-5!3e8CIcQ2~U$xSyjHVbws$Va!$u{1o?Fi^ob$|%p#%O||ZJ<2U2 zE6uRbIZ$8QFCyGHGsDcRyeuy<%OKq#DJsP*u$ar!H!G$hXii&@ZpT%-7%9Coj;*&=X`^TC#3>QEFmwszRKCqlS;SLR>Caa8y-fxIs~# zlVgUXdsRt5pm(Bva7M6swntQwnPpVAen3#9V{kyeQ;KPsNnvralWTB9YFL&1_OVI*B0Miu-(trdAE*(b>8iX?|z)rZ$Fp8 zblQpQltIDAy9Y|PWk@;jW$yQUX1-E0R%d6d#8l5sR~gr@FMYq!mfb+cO(S;wr}c_A zzJ9!+^JVA!DAqL*(OlYB?i+6MKm4JwblGv`a;}R+3>Msn~wBb{vmgd4M^VBxa znzZP>(D93RPFw7Kd@X42y*T|7>@HOTzf|`eQ(DAP;m*H0tE2G4(iMWIRBwfbztm8% z-Y3XmXa3QGrS-gZ&1>IT&D!&O=Xoi2oW6XoTt$;3dl%boj=i4!p|5*e9%eJod>!p4 zvgp*t9MN}<;-P=feqN)c8OEl%aBYU|*7$2ap7Wf_ckg)qf@89vKxg|Mc~10>3`zT@g?o(v+{pEW&sVvd|UCfuYl6z*@vtQ0y J)Xuo34gh2{Sw#Q< diff --git a/secrets/Everest/host-key-ed25519-public b/secrets/Everest/host-key-ed25519-public deleted file mode 100644 index 6b23715..0000000 --- a/secrets/Everest/host-key-ed25519-public +++ /dev/null @@ -1,9 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 5qrYxA OECuD3X/YhnhNDjXFBsoq+mOQmadIQch2DhcVM2es3g -Y9tNL/OXgxSrWtvrLDHBnaWGxDoSopQAVoFwx6WiHFE --> ssh-ed25519 AuWU1Q RawOBsHa1yGd0Nn3QPaZNlh3Qy5D5TNU0VVc6t7uwmU -M0OgClrDATN23KARdN8kee/tDSolbdVQwxclOwUlCY8 --> }|y:w-grease [|V >/-D+*J -zPzM ---- st6EavuBsvVd84P9CGhxLpgckxCsYjucYvpMiNS0YVY -wav\GU.<8\<ڂ>^=„0[f,!S0z%/eo48&J?@ZJ;1/ႄ*/t{ʹ-dna8.ES$˖: \ No newline at end of file diff --git a/secrets/Everest/host-key-rsa b/secrets/Everest/host-key-rsa deleted file mode 100644 index 18618b9940f30e9245dae45446724f57e4c9cbce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3736 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 K*ISUjY$gC6zy!Sj diff --git a/secrets/Everest/host-key-rsa-public b/secrets/Everest/host-key-rsa-public deleted file mode 100644 index cbfbf9f1bd8e2d3b4cb76dbaa0a1fc8c0431064c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1110 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCSPEi8(xa8xkY4ht*^ z($34s_Q)?NaZSk!3JUVi_BYATs>qHE%{9vQakb3PEH`y>4CL~4O48R3cPl9KGuKY{ z2o4ML(>6@=C^Pf%)=u)Q3Uta02@K8;4vtK(2t~Keu{1o?Fi^qWrNAY(tUTK}y~x7L zJkiN1$kZ_-H^ME|B|kjZ)X>K=*eSUnvMjYY%aJR+$lW_CFsLNOz{fDsCpaTCx!l9u z)4-z2ugX8r$1^G2(#hMfEZeLwq!?sdOqOnXQEFmws)DzIYL0?`0#|8)cad?hyL(Vr zMV_B=nrluSjlhy_kw|$)%=hCe`;n+j!FDkvT=*l%=NdgriU(>;yOvL zrghHR`287MEzJGa9u-vDZTWTnEUBs|dQTIXFDVB#23~A>U&8NZ_PsrG>2Bu6k{_ZP z_tUloXs;6%s=R;L-_4*fdXF*DL-m`Bnk7RsfyKSAcBE0ZpvSIDx z2_ZQZtwLrFUcJ|B)2vx8OtF90GV$Ft)65^&!WGZS)J5tp>*N&A>n#XCc7RlEPe z)C;vt?~oG!FGLV($}9wA7wBY4tT;J69&Pw~+3G26ao!825iCw|lcd?L{ z`P$n5YbNG(2>(3tS-(3(xLA6Bveg0ea=CyVr#L?!X3ph2<>$q1qUaD}e`}%9myfYN zG22(XaoN%L?QKV}i$#TfvFvBbgP*s5P`zFMC%AlS!p6DG*~cHLT3Jo1Y>Jt0>5k^iITv%W=&+J7%=l<(WMaQf{$F~*QA8Lo^}wn0B9NHzW@LL diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 5c1d5a7..1e2c31b 100755 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -7,12 +7,4 @@ in "ddclient-passwd".publicKeys = [ everest ]; "syncthing/key".publicKeys = [ everest ]; "syncthing/cert".publicKeys = [ everest ]; - "Everest/host-key-ed25519".publicKeys = [ everest bootsrtrap ]; - "Everest/host-key-ed25519-public".publicKeys = [ everest bootsrtrap ]; - "Everest/host-key-rsa".publicKeys = [ everest bootsrtrap ]; - "Everest/host-key-rsa-public".publicKeys = [ everest bootsrtrap ]; - "Archie/host-key-ed25519".publicKeys = [ archie bootsrtrap ]; - "Archie/host-key-ed25519-public".publicKeys = [ archie bootsrtrap ]; - "Archie/host-key-rsa".publicKeys = [ archie bootsrtrap ]; - "Archie/host-key-rsa-public".publicKeys = [ archie bootsrtrap ]; } From 5566b334e1c954352314bcd86f93dfbf35d2418b Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 13 Jul 2023 20:55:17 +0200 Subject: [PATCH 0063/1125] Secrets: add new Everest key and rekey secrets --- secrets/ddclient-passwd | Bin 372 -> 478 bytes secrets/secrets.nix | 11 ++++++----- secrets/syncthing/cert | Bin 1153 -> 1172 bytes secrets/syncthing/key | Bin 617 -> 749 bytes 4 files changed, 6 insertions(+), 5 deletions(-) mode change 100755 => 100644 secrets/ddclient-passwd mode change 100755 => 100644 secrets/syncthing/cert mode change 100755 => 100644 secrets/syncthing/key diff --git a/secrets/ddclient-passwd b/secrets/ddclient-passwd old mode 100755 new mode 100644 index fb143cb3254084e4aa66d4640fd59efa45a5a4e2..2c6105d21e97d717fad785dcaca0e034c4d8cea4 GIT binary patch delta 451 zcmeyubdPz0YQ2G3eo~gBLV&hYvUX0owpnIGSfERwk6~g}ly-iOzq?DBaehTsN`ZNn zYj{PHk3qI8SDIUerBiTlrEyMSNqAvWcto11fw76HnT2mvNMvf6zmb=3xcadC!jYKoDmsiCEUX<<=hg`8g*5!q!6D1UqAOGk9$l;-v6W zFZcRVSBuEJ{K~4R$mEio;>d8XLMNXr&+0ps4V${(w1`G-BVr>&t(hbB^2biY5Rb5|~y1 delta 344 zcmcb|{Doxo&z@Zltrbe|=DDrDH%vh;yljp}V7(p}V7z zcXD#5zDK3Lb8%IGqmy4)Xi`JxHv;MHO0u()X-AFw6G|$!cn2XASWWiHN7m&vA)bTKgqYKtRT-xzoH_`uq-$@ zwY0e0GASV4+uhsT+`xn@)XN|;(77VZ)WR?&Dm=&{JgqD>x6mj&OW!xo%eTbKGtoIb z&&e{>+c6ttU3p1JpngS?ZhBE_VsWZMo@uU8xq4C&SFUeKqL*h-S#qj{nRBYASy5G# zwxdVANtB6iD3`9Tu0n)QW<{i{TW*A-e^Eq9RYg^yqf=R`VNhadp-V-%k*7&ns99CH zU!``S1=pS}v7C>Xmn&{KH$!V(^26r~71n;ev`W%PK&r2=qv+v`^^Y|VnB6kF-MW7I z#_fWeFBW-}$~Cw7z7SoPfo%fqYhRa{hif@@P-#FxMwdw+0ESLq5_e>Uj!G$*M_fkxrUAFQ9U zvbr7F9OD|Wz-zVJ8sQf~!PPSVgKXTl`^%&}<5MYePcED->AEA}(D7{E&{HgnD?Fzr zthDy>oMsy6cB+26(?&;$xguv~i#Zp)x)XKks9>U!xRjMva#r85Q^AvOe)_UB>eHWo zl|$EeRT%zdX>#1BKPx?}_r5>t)v%o+k5VVxy8OIlno=2yg_R`Z)mu#Javg#FJ!uyv z=qy%@diYMD#HZBw^qXBOH~(EJxo~m1MsNPngJRldhx zZcjCrEMdL8-*PL{vi`i!KV+XM3Yf;t+I`l^=e*vRl*4i}`jTW5C%kWRZa;59V)Xf1&RoPNnAKQ&iu<0Zmeku58vgeKby)8Xy zzKR;ld1Y06dQY9wY;peRbZGsqZ0}=|mm8%l9}h%4aj0mNu3hu-pQm>2 z&R@6pu9flIm=bXPslWj?ne+EPFt#mP5wbq7zw7YCnMsEip51`pS2w*VHL*BVK`GeULBZWXAvv?EDBH`I%g89Xv_3i6EF{0QARxCqIH@Sj(mNtO zusA6w)Fd@8E8DEn!!6J}HQOb~#U;-)CEqj3JH^w?BGjbJtvtWf$(1X~yCB0oGAY7P zzu3gf#WlOsFVD9!r`XHc#M#8$KioOfEYsi8tk^v_+d0wEI4R3A*f)?%S65fT#XK}K z%Fn+btX@0OEYqkYvdBLpGRHmHIomTMIKtF8&?Vo|$ILLxKR+*!t4jZ^16Ok*hw|ct z7iUi#dol4`kZi&UfuOUmdrv0>UpnOeT&KXe_keWk&Gm)XJZopEJqln*iD&MAwpT;p zQ=EX-s~bM~Vpjs9cX@OjYxr>1k@J9tmr2H%3v_Wo^rM&d{ z;`8@ZuPotrUhwH$gaBW-!zRDS`|7Xs$7{Q^ zefr;1p2w%%-*aP%ThF9V)2zRQ-nHZpnEGqykN68V@@?`DoT9yp!#L|JR=wo8n5qAM z(hKo~HRk(oL_Ya?yuN4ZnFq1|?;PbRR;pd`BJtb4iK?7aA2=!*d|!TSp5a7x2fw*a zyScce_6XHC1YWql^tj;f7jJLAvy0?R^iyFl`Pmx0>%-sqoD=Pmx6gNVbr8)xe)hI% zSB+`dbDnFre?HVud0O%8@Ls2u4KnrD`57(?8r<>t@mqJ>zHj+@b{jq4Om{ecKut4g zboG)Txi42^yRhg_vb#g ze^sxT@iCk^;H~YyZx8=Vb=Tz{1wt0M!Y!}Rx`jmO#!^ZT>MK?v3*VjymUQy3*oAF=k zEt8}7Yac7UI8mhUxMSO+=Z#!;#+F|=jraNKoSwNYMM{YCl0ix9iCI^)4ft4!ER#j= zr0N>%UBAU@%NmBH-RCYZy?DuN)=}a2t2?~UY|Lzxd6~H`M)=9M;va`B4Ey(GhDa>S n_&eEHEB(Y4@x)b$;13P diff --git a/secrets/syncthing/key b/secrets/syncthing/key old mode 100755 new mode 100644 index e0dd47da7c8951fc85a12b2e55b1a47567369daa..01a905f9aaffb7342f3493c05139d8423a5d22a0 GIT binary patch delta 724 zcmaFK@|JaiYQ2G3eo~gBLS|6DbGT8si(|QINt%zBp+~NHdA3hwaY=!rYe`j_w|9V7 zVqmF$a9WTfS81uCkC#PiMM*|MfvZ!Jd0<$HPijhmhoP}!ptetlxp!(*h>5cadC!jYKoDmsiCEUX<<=hg`ddkrPj!W=fK=Pi1g@0O@^tScM;|{+vuv{@ z=faA5?J|FtB=dlDqb#E^{VYRmZ{IX0vw#v43qzlf+!EjHfB*wCE?r$+g`B7oj}-IJ z9OrP8vP}KN5=$e?-1J2AknE5|?J8sM%SALYGH@GaXue~#Bh z#qb%&ugxlvwR+7Nbo|dzhT>n2=Gp7_`GqWs&b)e4!P=#d=i@v{_II-n?qyVpjO}6S zD_f^He^LCM-lN)Q%8feyMr_kLw@P6C>9vnfsFm+xH#sGID7#_h`GVQPlQ_5Q@hd(L zP597pZf^ab3(G#(oX)wce{Lh=&W;<+!p>U->;+$ZJ<|052#fpc^!Q6RPtA{eqb%}< z%~@&fy0iZmAAD0jXl TOYA+Hu-K~)E;^=@g;SFNvoR!_ delta 591 zcmaFM`jTaWYQ1S;QDlXqLO`yeiMF?KP+4SASz?-#PiU^ChlPb{QJ_UZX+T*}c9oB| zuWL@0Yfff5SActtp=nlfP@0Epe!i1-nMbjKe@S?cm4;hokdLFTZhBE_VsWZMykVVfl|rpTxk0K|T)jdTmsy!#c445KNvT1JW0hNS zS*ArqnU8-!T3}dJWva2hWwEc5b8d-adO^8mNrYprd9YJba#)gSaaE*Qs)=QI1ea@O zfOcT6i*cBLs7YjcGMBEdu0mvPM6O{)xmQw@eo(q^p?k7RaZz}%Q&C`UdT@BDQ;>nV zW08S>V10R1X*$>B$gIM!{3lPnxZKvS%!&zIlQ3~NtNPR>3a-0NxYLadxgHd*P~FR~ z+ZH~T|LxA6JC}Aha%)wuvo>%2Rrt|XWHqznqU;?epMwI_5(}BzznGr)S8+U+LW_q#fV#S|9xisnkRa~ms`HPwu+SCIlUm8eL>mx z1>BxLDpHF7H939EI9H!Po9jR8+WD8QYwWT(YdCkTj;zsUyS+oG=s{(2#rX+ck~)W( ziryt!ZR9psa-nGPh2tKNCLdb)e}(8~oflW$@8W-#d1>;MCBMw??3t)Mm3>L`?3%J? szr4Bpc?`l&xQJV5aR)3C+;ON?l6U!!oJ8XnA{$Pw*4c1+%T(nZ02nLx>Hq)$ From 49966fb6da5f119c541f476fbd8f3390c567775d Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 13 Jul 2023 21:04:58 +0200 Subject: [PATCH 0064/1125] Secrets: delete deprecated keys --- secrets/secrets.nix | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 0e8fdbc..a6becb9 100755 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -1,11 +1,9 @@ let - everest_old = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID7GzKZIK/UAMfRjsaxWWKOBqG7sa1ttJ+Gp0zTQSBXM root@Everest"; everest = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEY+nRHGyId1eYdC0tk4eKDG8UPpWjNekif+XPPHa0XD root@Everest"; - archie = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINuqKOfYb2lyhoQYBQbuIEyMomze872rnpxDnax8BsC5 root@Archie"; bootsrtrap = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMKloSXSeF4dNXebd93uMuiFuXRHfxo/he4+O9SFTz1s bootstrap key"; in { - "ddclient-passwd".publicKeys = [ everest everest_old ]; - "syncthing/key".publicKeys = [ everest everest_old ]; - "syncthing/cert".publicKeys = [ everest everest_old ]; + "ddclient-passwd".publicKeys = [ everest ]; + "syncthing/key".publicKeys = [ everest ]; + "syncthing/cert".publicKeys = [ everest ]; } From ec15de1f6c0f9341d61b16b934b423a8f2819468 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 13 Jul 2023 21:14:21 +0200 Subject: [PATCH 0065/1125] Secrets: change ddclient password --- secrets/ddclient-passwd | Bin 478 -> 331 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/secrets/ddclient-passwd b/secrets/ddclient-passwd index 2c6105d21e97d717fad785dcaca0e034c4d8cea4..e8dac5e0aa2b1ca9ce716c5ffb79060d2653e8ae 100644 GIT binary patch delta 296 zcmcb|e41&3PJN|GQkY?7NoaX?Zi!_;l7CTHx_gLeXjz84p^;HuQn+DgewImuiMwHT zK3Ar5UUGR>WNNvkXN9MqPf1FMle33mMOe9SMNX1yXqJI?pi5F=V7`%&0hg|wLXfGE zK}M;Xj&6EUYGQG!f>S70k%3WUkY!SlM}DYdNq9t5O1)uaRZ*U!p{HwQuB(}=d#1Lh zUuI-gVyM1ZX>z`AL7|Ibc1Tj5pQC<+XRcE@m#(g^LY_xaLB4)PZnBGUrF*bNNoBg9 zzK4%#zDa4Nn^TxqaZaRpMP;&2sh6cM*OPm@POJ-1w>IK7Rax!#ymn^Z+lx!qvuBBjRWFwXAdXE-nr delta 444 zcmX@jbdPz0PJMv3Q?hnWy0%$nL|C9pppRijZ@NLQPlUNaIhU@TLUD11 zZfc5=si~o*f@xtNzW$l|2%QZM&XSBuEJ z{L1>OsL14!oZ`rEuRlV`s-ouZUn%b6>8giX^wFlpu4*JlDv4 zGqaLxSGO=1!w~1(5EnP?KrUTfU4<-j?Z_Y}@1Usgu;k)^ByC?$^GK7NBDbI*iva(? z%0Qo^y`d@rot@S5lTM From 89140b9bfdc111fd69f3566e2e9557e3f4e8beb2 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 13 Jul 2023 21:57:22 +0200 Subject: [PATCH 0066/1125] Secrets: change syncthing key and cert --- secrets/syncthing/cert | Bin 1172 -> 1044 bytes secrets/syncthing/key | Bin 749 -> 608 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/secrets/syncthing/cert b/secrets/syncthing/cert index 8b94e84633ccdf7736717010207e051b477e0ec0..576dd37a780d765cd8b2c50a0093d27f67b2fa11 100644 GIT binary patch delta 1014 zcmbQjIfY|_PJL2jl5ws}QE^CRX_dcWQgTv3d0s|AaE^ISntyOfseWN;VRlJSq`tO? zE0<+RP>G*sVnC{4S&6fmhf#KwYm#}MNseD&s+VJ4YOrOJfnRc%d0~2TK9{bYLQ-_F zZhBE_VsWZMj9;}&oPwfqX|+OOh`p6BSEZ+Cno}T`ZoRIqf~lK(cCxE$aY;^5u}M{^ zvst01k#S_6e_Da3p}V(dL`raFc95@+PgYbQm)@TTfk!xkdxPVjZS#{`)FQrl{*ho+ z&x>2cy{yAj8QjbNH!it1_446sF*bK5AA3IGTh)?Nxf@^ct(Q~Sx%=g3?p%3;yn`*0 zQWdgR@qZS7-&g-U@ZQOS{8cYIcPmEFZ>ak9Ws6UG;Y|X zA680VUf6Qs<3z&*>-OC}s?!bnjW1>Y?>+eQ>WWuue4KYos!{r&G-39JnTmJ*$MQ8e z)Jr9;*s|@A|Kawn98#ZDu5WFa$$L(=J#@|O`!N9rryp7SY;{EN#Cmr@A?NLH_MUwG zhEGNQP3unGzH^gycNt9x%a3?`W&t;Fug(S8r8VvC8?`-?9XGS#No>N1j}oU&X~k)h;fdYB}T5 zQpefb=X}~T@glEu#;+3*J^x?dUVPyC_7}`e=7&G7>up@dJ$2U-&;0aqbrZH(YQfbD zy+xbZV~?wJs~54zN8WnGD!$ytdfxi)37d}k8Re^|9;?_;UM}Y3R%ij*KF=xdda0d zMfjUipX<5#kABYX``3N=WSr`9QE~0S@1+}sSGCtaa(*PAKc8V+)I?)zg=Kw_Y|~HRxK$uPLzpy@BzYBl409qGpNS zFqxOgap|&P?`-c2oF`9dZoJa=cGB9-dn=?;-zs#Z9-HK5_V)9VU$aiUenEG}3oJny@!j1RuSz8?wB5vGw@#A&7m!b~E z`lhe)x?i&uRGC~AT)%5xgS}?khWx#HFXyQ~4LOokvTRc9(Ijo-YQPqwZe057BCD*ylh delta 1143 zcmbQjF@MQVymaj1S+T8LY5SXG68WL8OeF_*5LLUD11 zZfc5=si~o*f@xtq4|MR;0SYHp!Xc$U6zo|kWlmuI4Lc%GAGsJCM_ z$hz{9kU;&4B;E9))WqUcg*?+-qjL46BCcHDl0+}hpt9st3p3|bPqU(`C~Zd%lPDA4 zP%hniU0sC;pUjF#SGU{j%dTEuUkAPHPUq{iy8S5Ww9x%IQcDr@`^o`pEH(xCB zD3xn&^L-(@j{8*Y%;Ou5PkwWvf6W7nxpLPgsxh8bN&_5|0awumo*JNEwIny%6nvi@w)>1j?&{zlRsELWo30cvN^^z zV1d_aw>82qf`Y4M{s-B(Z}*o;dB&$wmn}W2b^A-~9AtY1F4b{VIp9@2W8T z%hKeyPk&Z=R_}d()~jJVMINP2xOMq?%QU4j77Hs$#;doO)a5z?`+L$ZOwd`Z81?X- zK#5PO@##0aRBryeQgY$s1O^GKxM{WWB4=5C7TfBwU5bCzJl`eZUHwvFp|W7P@aRLg zOqgTdM{BAVdnheDp=)#~b-P^e*U2a9iA>~Tfi>aFflB%+$v_7^QonX^RIQ&xZ&t%UV`FmS>(tH&)mh;N0 z`1GDSrP<>A(dp3oUD@8pBri8gS;%kmJt2Ow{Z`|avZ?k@_ZUq}X?b1WKJDj@1GnlI zPP`JKXn!YrMnrK^mDA!0hsw9Gd#6TKuo=BOVff=xPHrye7Zb*s4>b&GlMeege2}j^ zE8*~JHhXX3OwaG(&-mjy|Cn~xoZEe*MvkLi(!_hqwW~S*qY7bATRTE4^C}Y)o=2m^EepJY`u8X w$?lC8PnO5_#N!E*O@d0EmEZ6A`6(0hg|wf}N*s zdQoa(ajJr`Qn^C9aiFtrgrb7FcesKkS6OPQL7JIvRSn4ep)pSedxn5UDA zho57rt6xr*vq_1uxqg~)re&FPp>t%4Ye`jcMYe^rfpL|ia|BmKuzzJqK%zyKi3OLg zuC79qe`Zu*VL?=gxuv#IN>EBbT1a_Lj-iXIWmaXGe?gRsNr;?g z!vn0V^M6cks=GVs+3Nk1Zc8WK+guQ=HvODT(BtH-Pd)}-tZzSmvn=75E0>(gk_Ey4 zT0~7!LnS+pA4{6JubWG1S9#Q4pR|uRel3(1<#{{PVA}jY&#$sA*}s`z!fVNMuEom& zxEIeBHoVstKlxe7qu9HCDw4jNa%X;yGm{XP<+pHoqVn)y*W_r9r#mF~Ox$?Jcw+u6 zvGt-Kd=s9^xSn~sn;~hfh1jkIIx81AUa;A?)#EAOq8XoRCbDhnS6acsGqG(+?^Jab cPMv%6lYIk^SSR(?&I$ba#G)a{JxT330Lm-t7ytkO delta 717 zcmaFB@|JaiPJL!jzH_)yxQk=CX-S%om!U_ld3m-^WpPP?qiac3nzwg=S7KnPesEfl zBUfpup^ukEYDGy#L4m7Nl6hcQiBD=ufrp{7W1zNAh`D!aREUYble2MFF_*5LLUD11 zZfc5=si~o*f@xtZJ*ld??x z#1cy*%iQ!t^N{S2MC~eL@8ooga9_)`@Q{G|WM8gBbsy!uPVg<;K7WqaMaA$L$FI#Q zk+piw8Fc*5QHJ7Qj^^3x_xXh^iq5=xQ^DG$kLTk&N%nWM5AJ1Dij3`H>ML8PIDb+6 zo!+C`XUdH_{zh!mIk!q+{^_-kPpFmeVmCP@d?>qN<@tiy!jm|+>+vf-4^8;cac=IP z3(G#(oX)AgtAB1I-6|bH&4xvd!sD!hRs=N?Ygu7 z7ax36K51RQQJuwom$euEeKD)tYW3~I;kbCSg^E)egm!OKWf!%-qnob5)nM%OWx@KX z+^#(=tdsu*AFutISH8vJh>OeV8=LxrS{*ZA#uO~R=b7preAVq%Zqh!j?y`{N!nv1T zK72gmVv_TogM700ZrCO!e^B8(Q)qWyGW&Y#w~2W^4}4cW$WW*%xKw*2J4@_6o3Plc M4=y^UlZ8{00Q(>!kN^Mx From 23c444cdd070709b61be2a56014f215bdf00542b Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 14 Jul 2023 00:13:58 +0200 Subject: [PATCH 0067/1125] Secrets: change Everest key and reencrypt secrets (whoops) Accidentally deleted the host keys, so I had to do this --- secrets/ddclient-passwd | Bin 331 -> 404 bytes secrets/secrets.nix | 2 +- secrets/syncthing/cert | Bin 1044 -> 1133 bytes secrets/syncthing/key | Bin 608 -> 547 bytes 4 files changed, 1 insertion(+), 1 deletion(-) diff --git a/secrets/ddclient-passwd b/secrets/ddclient-passwd index e8dac5e0aa2b1ca9ce716c5ffb79060d2653e8ae..90f0728d402fd083561164e35e4023deb60bc6a4 100644 GIT binary patch delta 376 zcmX@jG=+JBYJFI~U%rW>LUw3=j!A`CVN^+lSBR@oqOVtBaH6YuP?AfenQ^LiQE^2; zj(?I{Nl9QfS5AIGP>7MCc0^K8X}P1ZXIWmdUsQ&7j!~vdp=nZ;iKB6pr*~*ZX+?1$ zm#&?Hn?|B;dQoa(ajJrnqMEUfOO--!g=cPRjj=ITVtrnfxl>t?foG^!RZx{#gmX@o zNq9hbr9p^yiAh>+fU8HOrKLx3dTzR5Wki&_g+abyuBl^sUS)2&lTlc9E|;UPM~S~n zxS^4ksdi*qa&~D>fR~|puyJ}-j!U>SKg@tQmewdkGMP;CSM5U{_b5Tw~siSj{kE=(dyKkCLlz&EH zC|88z`R7Mw9Nob%`@^-{#-0DqEKfTd=Ck@^Z`!nlTTgEmh~;IC>q)&KbZW^Cj%p@l Xr9NAG^Iu8p9=C0MBl9iddCXG)WWk6% delta 303 zcmbQje41&3YQ2G3eo~gBLZwMkm|ckg1VDMyZ;PZhBE_VsWa1Qz%!Ffl*|TWm1txetoE8Nq9t5ieY6{QJ$lrr)y=d ztC_2NrnaYFW@J@jsJ>Zga=vdtp^IU5NK&4kqke>Eu2VUeuCA^^o<~tZzJ5h+vWs!0 zd$2`GWxAifhmUE#Nol2bO&c{l*gpS~`W=0v=SJg=1LARK4=2Unm=oO4yFbYDRK#z=jn}g>-d0>!Q2+o_ Cw{KVg diff --git a/secrets/secrets.nix b/secrets/secrets.nix index a6becb9..169c588 100755 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -1,5 +1,5 @@ let - everest = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEY+nRHGyId1eYdC0tk4eKDG8UPpWjNekif+XPPHa0XD root@Everest"; + everest = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBYENWORu3M32NIIip8gZO5VbCUBwsT2RgOU8ATsASpc root@Everest"; bootsrtrap = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMKloSXSeF4dNXebd93uMuiFuXRHfxo/he4+O9SFTz1s bootstrap key"; in { diff --git a/secrets/syncthing/cert b/secrets/syncthing/cert index 576dd37a780d765cd8b2c50a0093d27f67b2fa11..db1966e84947fb0e1d58b7698738efde18486f2b 100644 GIT binary patch delta 1111 zcmbQj@s?wPYJFI~U%rW>f__9nabj9Tc1l%fMrEEspiz`hfJdQcq-BN$ zm#&?HqCu3QexYu9QEFmwDpzo^Yk5F$QogZ)nRa4fMSY54NVs!ySiWnvr@OmzsEcKV zt7}S59_%c3x1PiKC;dM`D(L zSdwdUWPPZqaiwLRWw2|xV@jlXAlK?%uR|`8->cSLEKbcU_*=kM61wnhsO{ocw>HYUvXQx1JG*v!RO=s$0#hvM1V$Le)F6OMODmxmN@2$;Uk zUUa)&HNIe8zuO zVuIU=R$htwx^WL1n1jAZ{tMONe^meQwK3Nw@qFR)=YfA~t=V9HU|rF&|)zXpi!UU1|S*UI*L(`UCG z(7JinH>diG{Kq5n>vdlA{l5LKIh*ka@5z{UJG;+D%|Byji$3ul176}VhEMlt<$>P@!3$pEecy6_~N!67%jfGDf|Gl1T-?we5 z@7Lq?zOIS7PyDWUstB+!pDAWJC#JJAE^7Xv5~gFS_txgMX4lHdY}wCu^l;o_(MhXg zZoXCWYTWJi@v`+!kAlRdb0%|^PM(~*=3?23*hwn_cq41=@A^*?T>h`1+pE%G$?@Ep z6ZO)6OWv3?T zDVx{ZQW!5;+`d{sq{^@3#;T*>leBwcD!^2`}6vy=?uRue(9%1 RcQgpCxdQoa(ajHU$U$sk|f}(P1wL)Qty_GLlWxc0ono}T`uCA_vshfLtva4%x zNlsC*NmZz`S)r$qab%uv9egX5oV^OIZD zBEEV4kziHNi(ACKtix0p+{^zrF1a`L^5JVSHg_f;dp_Y?)sj=W8(;CQms8le`{ifu zTzP}MgDsL$74@=K@qZS7-}gN5-pPXeRWCc`S+0I+(iC@&U(fO)Qsz$T!N`~|{1KZS zGJX3rZrG(CR!U!9*mB|HM8gE@_T4?I(+&EKFJ=GlJ^1tLidSoVoOevBQTm`XVfKcZ zig*6U@-;ZrOC_z?vh9%n;r6W@QlC_=Z*7>#drr1Jbj|JiF#!js*B@E?Y;{ENM0Y_U z=k0Iyo_zg=PeuMs>rUOibCY&=8BG>`;p&)r-F>3&le^_R)!R2nKK!^sDy4kNmlaRa z7GHUF?PATU+qs(746j>~mU?mvNo5y5XNd@2d;M%t!&(#J?xs_JUuK=xFWUaj@cYDI zsb#xQZ*bK4RXgGL`{E<(iuUU7sBf#?;Fug(XH{6S%K6#fvIKcqZ+Wvvo?Mz=#l=I_ zE-s&HIpfk&$JyKGeA+YdBCmADuM-hH|6ku;eBk=_7tBrOhd-|CZCu7Zb=MNl{Pc2l z6Si4u!PN`BMVr}UkE?X67qQ4k-g?9;zTC!o-umwen~wS!<*TP2tJqLpF6QJ`YcE^B z_?=l{-_N;MF0y#E*F2fGZ9lub&wdx#ARoJMsjmknDPI2>ci?5*g!79^AGnzBS*Lg= zwfL4jYpuzGTd$OV-fiI0)Jwa3^>M?iEbZe*bb@5>TO8fGGK*{S$ySwq^~ZLvLR~Z0 zZ0=op$)!C-_?uFn>$&-le$MXu*M0b8oa%B>aqarR@1+}sSG7NKek9%^{%K+I>l4Q{ zSJ&7?-aS_MPfJ^MLhQY#XPJ&2C{Bs#y4E*i3yY`K)0cg>UN&7d=vv3GDX{*%f$^Io z@{$XpW{KV~nU~0M>9Sz&Z0`%4Cr@c^ywdh|(%Q{?E2L82Ds-eCo8)Hp_VbeEY*(j; z8!#4S{$1x39$%(+&vLcBsN%+MtF`Idmd82BcWHi@`gQr7NpVZUjrZ?aTOAW3ZrpeA z<8`~2q7KFSrmyn4U$YfdnOqfIziVEDy=L2n{JnZF=czsoIhpyPjp0M=v-8d0D!w;t jlt2AFlr=|T%e{gtIiGFoG>>gnXDTa=-@KYnwyqukb`a%- diff --git a/secrets/syncthing/key b/secrets/syncthing/key index 4ea8d32b9d3f4f6bfaef5644ef29f08ea78d6fe3..d1e1609c0e865cc1d1da5ec3b7a989ea015cb7e7 100644 GIT binary patch delta 521 zcmaFBvY2IpYJFI~U%rW>LTH3Vm7$?es$*6_g?qk_hgnp3c~XW?VM=6rZe*fmfJani zfp(-l{W^ksLcd&PUexbfA zm#&?Hw|%vKRkCf8ZhBE_VsWZMNwsB|mRhw!n!SNHSG`xNajIW#l4+oKfO(N4m#(g^ zLTH)4Z?22JZ(dlsTa`z+iK&ZaRb)g`fu~DUQc+M&hF^YCvTItDX|YE>m-C&8@%Q}& zgUUR&e$S5dnfZCH^|fys)D~ZPy;eOsc+&cg^Do4OH_yrAoI2%gh^3FfdLC9uT~X;* zecbKaY)&!XtG8BYzGh#tcikWJZ)~aTK@U84m$WCn@JP{ryoUJ)*9+^fAs-)4W<9uX z*&K(B$?U7&NFD0Bww3?6g;%s%hO+H@udC|4bJ$#3>Uuq+&-Y!|E!D7od!>!@^OK}& zlXo~RU0OL!rdK9$?(5iNVawO0yfw1!myl;ashJvF?W=rLT`RJF)tpb#o8_{!9`hY* za^SM}ys>S`EIz~HTY|4{JI_&{A9ObUKgaghDt#+Fe!rRDb!z2Zo&}QI9<61){8#gz z_qr19>U_uWwI_4xEWEt4PNq-kxNh3#UVhl=){_-6Cxo_ZnRq@tWA|$=-_7>rix29b Zw!US~kQnWdRGQAep>ua#J2O+88~{(O-0J`U delta 582 zcmZ3?@_=Q6YQ2G3eo~gBLaI+;YCwupqN8?UkXMDFXIiOiNKs~`QK@;cadAjVa6oxs zdU>*Em}Pb`SD3N4m$`?5fs;i}L7<_JOG;q6cR_%$vwwu4sZmf_X>NLWNsfhuL0NzS zm#&?Hou_VkQEFmws)Dgnxk9>eptEm;qJp}2xPm5ES$%4$L7JI zxkp8qr<03^pJS@4Urv^@Nr|z!ewuNnWtnrKb7YEZNmX%0wuQ5Sah0QU1Xo3{e`QHP zqD7X81(&X_u0oW5W>jEdK~#vjrM6K@P)a~rNO?|iv^$ODEmiTo9}_{hUlt{o~}VPd)}-Y(IaqEa8|d zmz>Iy1;PJXL`_mdB|DEFOPaW^n@eg}dDLE?w2wD_EtD4Jc{|f!+WbGyud*%KznNdc zYsqu2#mfS?7taozlD?aAXMT<|lMt8Xw{Ur)^6+5Sw8J}tDTEW6I jv2983RCN|koqO|>eFKkJC-v6O3H Date: Fri, 14 Jul 2023 15:24:33 +0200 Subject: [PATCH 0068/1125] Server: add wireguard --- roles/server/default.nix | 1 + roles/server/wireguard.nix | 73 +++++++++++++++++++++++++++++++++++ secrets/secrets.nix | 7 ++++ secrets/wg/silver/phonePriv | 8 ++++ secrets/wg/silver/phonePsk | 8 ++++ secrets/wg/silver/serverPriv | 8 ++++ secrets/wg/toast/phonePriv | Bin 0 -> 379 bytes secrets/wg/toast/phonePsk | 8 ++++ secrets/wg/toast/serverPriv | 8 ++++ 9 files changed, 121 insertions(+) create mode 100644 roles/server/wireguard.nix create mode 100644 secrets/wg/silver/phonePriv create mode 100644 secrets/wg/silver/phonePsk create mode 100644 secrets/wg/silver/serverPriv create mode 100644 secrets/wg/toast/phonePriv create mode 100644 secrets/wg/toast/phonePsk create mode 100644 secrets/wg/toast/serverPriv diff --git a/roles/server/default.nix b/roles/server/default.nix index 515d4bf..9b262ae 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -12,5 +12,6 @@ ./transmission.nix ./ddclient.nix ./beep.nix + ./wireguard.nix ]; } diff --git a/roles/server/wireguard.nix b/roles/server/wireguard.nix new file mode 100644 index 0000000..6ad8b0d --- /dev/null +++ b/roles/server/wireguard.nix @@ -0,0 +1,73 @@ +{ config, pkgs, ... }: + +{ + # Set up secrets + age.secrets = { + silverPrivate.file = ../../secrets/wg/silver/serverPriv; + silverPhonePsk.file = ../../secrets/wg/silver/phonePsk; + toastPrivate.file = ../../secrets/wg/toast/serverPriv; + toastPhonePsk.file = ../../secrets/wg/toast/phonePsk; + }; + + networking = { + # You need NAT if you want to use wireguard as a VPN + nat = { + enable = true; + externalInterface = "eno1"; + internalInterfaces = [ "wg-*" ]; + }; + + # Allow the wireguard port though the firewall + firewall.allowedUDPPorts = with config.networking.wireguard.interfaces; [ vpn-silver.listenPort vpn-toast.listenPort]; + + wireguard = { + enable = true; + interfaces = { + vpn-silver = { + /* + I see people normally use 10.0.X.X, but I already have the muscle memory of + typing 192.168.X.X so I went with this one. Plus I'm only going to have 2-3 + peers connected at once, so a type C IP is more than enough + */ + ips = [ "192.168.10.1/24" ]; + listenPort = 51820; + privateKeyFile = config.age.secrets.silverPrivate.path; + postSetup = '' + ${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eno1 -j MASQUERADE + ''; + postShutdown = '' + ${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 192.168.10.0/24 -o eno1 -j MASQUERADE + ''; + peers = [ + { + # Silver's phone + allowedIPs = [ "192.168.10.2" ]; + publicKey = "silvrNOD8j5aDm4PhY8zJBV3JZOeBX6VK5KPvT+3yic="; + presharedKeyFile = config.age.secrets.silverPhonePsk.path; + } + ]; + }; + vpn-toast = { + ips = [ "192.168.11.1/24" ]; + listenPort = 51821; + privateKeyFile = config.age.secrets.toastPrivate.path; + postSetup = '' + ${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 192.168.11.0/24 -o eno1 -j MASQUERADE + ''; + postShutdown = '' + ${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 192.168.11.0/24 -o eno1 -j MASQUERADE + ''; + peers = [ + { + # My phone + allowedIPs = [ "192.168.11.2" ]; + publicKey = "pHonE1YaBZcTU5sTMLg6Iy4FIyzInfHfH4x0NZ1lBRA="; + presharedKeyFile = config.age.secrets.toastPhonePsk.path; + } + ]; + }; + + }; + }; + }; +} diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 169c588..f43b96a 100755 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -4,6 +4,13 @@ let in { "ddclient-passwd".publicKeys = [ everest ]; + "cock".publicKeys = [ everest ]; "syncthing/key".publicKeys = [ everest ]; "syncthing/cert".publicKeys = [ everest ]; + "wg/silver/serverPriv".publicKeys = [ everest ]; + "wg/silver/phonePriv".publicKeys = [ everest ]; + "wg/silver/phonePsk".publicKeys = [ everest ]; + "wg/toast/serverPriv".publicKeys = [ everest ]; + "wg/toast/phonePriv".publicKeys = [ everest ]; + "wg/toast/phonePsk".publicKeys = [ everest ]; } diff --git a/secrets/wg/silver/phonePriv b/secrets/wg/silver/phonePriv new file mode 100644 index 0000000..e6d0722 --- /dev/null +++ b/secrets/wg/silver/phonePriv @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 VoNo4A vExPc7M17NblMkOjJCxVm6I4v6/6yYBzE6nfc9saOEc +muXFANq6dGV+ToPwlUTkZ84wVsGqnTcCLvncmOgcbrk +-> VN-grease (ijvp 99` (qc +f+ZaYegYdxUu4uj7uGtIl1Pm1ipMe4gQxs57vQxYCHOYO6tejSbwI8Y8sOAzkNV0 +pv0EFylBo9Y +--- SrPUCAPc2SmcpvPoPEK/gYJ9hn+vdplxJRMBfRSamAo +bϾr ?/⻏Q2Drr4;^|T {!] \ No newline at end of file diff --git a/secrets/wg/silver/phonePsk b/secrets/wg/silver/phonePsk new file mode 100644 index 0000000..796fddf --- /dev/null +++ b/secrets/wg/silver/phonePsk @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 VoNo4A 8YvcfWII3BKsM+V+ceoFC3XXldC0qvwnL/6ggK+Il0s +irwDqE2NcFHU/mVlhvIt787a4EW3kmEd11d0P393zXA +-> Wu;RC:#-grease EIrU+ a1!S.4 t Uq#Qab6^ +mpekj8nSA5jpzDm1l5VrrYxMxmcuG5Yh+ABWkv2Dn9dKuJG6E1CIcAnU+9rpP6n4 +waoAYhTnVZpcHd1qVVm1Mwlz1REymNYxYw7MVplfM3lm1jSU +--- Q+IuFa2gerHpADs2TR/ZkULZV0rIaUvqFpoiovmbcQs +A3zX"Ijlkx u7 UhGJ֏{+^qbL?RImS܈=PԽgqFtJx \ No newline at end of file diff --git a/secrets/wg/silver/serverPriv b/secrets/wg/silver/serverPriv new file mode 100644 index 0000000..0c42bd4 --- /dev/null +++ b/secrets/wg/silver/serverPriv @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 VoNo4A xu8kFORPIO3cpRKruN2H3Ab8kGHKooWF+a51uvo6AnQ +2LyysvbhXMTJ+CXZtqYksxNAH5E+fgpmtCkX0TVp1SI +-> T$7CzH-grease ZJA,Gm +fyYJztvSX5VrUustF3Y3XpgdmAhpMR/4 +--- S/lJcXIuerNOPN687eO9CgsLZE8/yTEGfs2GUD4H/+Y +ҵI + }v''9Fnג؏<W]t`k+xl7p9/5zCxFFHr \ No newline at end of file diff --git a/secrets/wg/toast/phonePriv b/secrets/wg/toast/phonePriv new file mode 100644 index 0000000000000000000000000000000000000000..76cc57306235177806cfc752643545a19d7bc9b3 GIT binary patch literal 379 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCR+%lFGSaa3?O4@eA4 z&owCu$}Wm@)(*_b(hmqo5395Y%<*?BPpxoFa?MNAE;38Xa^!MxF)cO-^-C}DG;;Ow zbal;ePb|wR(GPXaG0x11$jU3otS|_+@bJoZ2?g1vt(#tynpm8wpj@8j6&Ir5?_X?N z;+mz$Raog)R25R>n&Mwv=usM2o?;jj5gt|HW$NJ=S>_p$>Y<%gn(W~hn3&{OY+w=) z=8@-CQXZ*o;cQ%-9_p5u!Iff~mSS8LUYea^nv1oa~nFpPlWU9mJ)ptE=GS z7G~~i=4k31P?c(y6j|)(7aHp9R~nM-nwVAMZ|as98JH5_7wQ~h?8&8QuiBecu*)}i zibc-9#yzW)k}^upPB^h*VeFGXQ}>0+SZ6RKJiqWL%5|rKHvgA^Y1|pNxSURT_&rVe XTAO0IZ?V)h??0MS`C&gDSp~EJD9(j! literal 0 HcmV?d00001 diff --git a/secrets/wg/toast/phonePsk b/secrets/wg/toast/phonePsk new file mode 100644 index 0000000..853edab --- /dev/null +++ b/secrets/wg/toast/phonePsk @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 VoNo4A LJQA1BbMRZCiasZkqUIYdEF4U8AFfHv+tiDkIfp5xV0 +YVKxaYXmLMimAjQ5N0ALSkptDcSmUafX1JPaA+lXLiU +-> {m4@-grease o=oC?P u1g sMgp\s" +GwnTCGHOjeG1XzcjSD/nqqY5eJRAkCIikGEIhLCLfuKqryn69mRz0mxoy7949j4j +oSG2 +--- z6TjnxxvqB7M7IXuIEJIpQrSvtW6yUC+FJDC9e9o2rg +fYR"gg`AO;&; h;'(ujNw吨FDg \ No newline at end of file diff --git a/secrets/wg/toast/serverPriv b/secrets/wg/toast/serverPriv new file mode 100644 index 0000000..e7e3de5 --- /dev/null +++ b/secrets/wg/toast/serverPriv @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 VoNo4A Y2wquDHovRlD2P7tv+6Z+DV3uoOeqs219woSenjJGBg +ZvHSzvAxlK2hZt41I1q4lAV3g9dg+8onphpG8V3gPM8 +-> /-grease leqR +wT1Jyk7ceGKQlsQrNuTigKJbRLbk32r1ic/kHZnFikn1/Jx8W5t7VEVxV/qbbjM7 +2eV73hu3QR8uz/1/wwMuX9yyPX79o/BbmThqAwXR +--- v2H9k4DcOqjtAuw7fgX2AEOnJLC8BMH5l8KPvoLxxKc +'.|^_|svO'3@l6eQB.3/+I0-?Ihdm{h \ No newline at end of file From 31dcdf1d7cd38df227f86171c074f83d375feb82 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 17 Jul 2023 13:11:53 +0200 Subject: [PATCH 0069/1125] Machines: Add Surface Go --- flake.nix | 14 +++ machines/SurfaceGo/configuration.nix | 103 ++++++++++++++++++ machines/SurfaceGo/default.nix | 8 ++ machines/SurfaceGo/hardware-configuration.nix | 58 ++++++++++ 4 files changed, 183 insertions(+) create mode 100644 machines/SurfaceGo/configuration.nix create mode 100644 machines/SurfaceGo/default.nix create mode 100644 machines/SurfaceGo/hardware-configuration.nix diff --git a/flake.nix b/flake.nix index 8f48cb0..b2108d7 100755 --- a/flake.nix +++ b/flake.nix @@ -62,6 +62,20 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl ]; }; + SurfaceGo = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + # Needed for nix-index + { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } + agenix.nixosModules.default + home-manager.nixosModule + ./roles/common + ./roles/desktop + ./roles/kde + ./machines/SurfaceGo + ]; + }; + Everest = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix new file mode 100644 index 0000000..f0e31af --- /dev/null +++ b/machines/SurfaceGo/configuration.nix @@ -0,0 +1,103 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running `nixos-help`). + +{ config, pkgs, ... }: + +{ + # Use grub boot loader + boot.loader = { + systemd-boot.enable = false; + grub = { + enable = true; + device = "nodev"; + efiSupport = true; + enableCryptodisk = true; + }; + efi = { + efiSysMountPoint = "/boot/efi"; + canTouchEfiVariables = true; + }; + }; + + networking.hostName = "SurfaceGo"; # Define your hostname. + networking.networkmanager.enable = true; # Enable networking + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # Set your time zone. + time.timeZone = "Europe/Madrid"; + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + console = { + keyMap = "es"; + }; + + # Enable the X11 windowing system. + services.xserver.enable = true; + + # Enable the pipewire sound server + services.pipewire = { + enable = true; + pulse.enable = true; + }; + + # Configure keymap in X11 + # services.xserver.layout = "us"; + # services.xserver.xkbOptions = "eurosign:e,caps:escape"; + + # Enable CUPS to print documents. + # services.printing.enable = true; + + # Enable sound. + # sound.enable = true; + # hardware.pulseaudio.enable = true; + + # Enable touchpad support (enabled default in most desktopManager). + # services.xserver.libinput.enable = true; + + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.toast = { + isNormalUser = true; + extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + }; + + # List packages installed in system profile. To search, run: + # $ nix search wget + # environment.systemPackages = with pkgs; [ + # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + # wget + # ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + # services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + # system.copySystemConfiguration = true; + +} + diff --git a/machines/SurfaceGo/default.nix b/machines/SurfaceGo/default.nix new file mode 100644 index 0000000..5bf2485 --- /dev/null +++ b/machines/SurfaceGo/default.nix @@ -0,0 +1,8 @@ +{ ... }: + +{ + imports = [ + ./configuration.nix + ./hardware-configuration.nix + ]; +} diff --git a/machines/SurfaceGo/hardware-configuration.nix b/machines/SurfaceGo/hardware-configuration.nix new file mode 100644 index 0000000..e8f4999 --- /dev/null +++ b/machines/SurfaceGo/hardware-configuration.nix @@ -0,0 +1,58 @@ + # Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, /*modulesPath,*/ ... }: + +{ + /*imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ];*/ + + boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usbhid" "rtsx_pci_sdmmc" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + boot.initrd.luks.devices."SSD".device = "/dev/disk/by-uuid/1d8d7578-d3a1-4ea0-90ad-4257266a6caf"; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; + fsType = "btrfs"; + options = [ "subvol=@" "compress=zstd" ]; + }; + + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; + fsType = "btrfs"; + options = [ "subvol=@boot" "compress=zstd" ]; + }; + + fileSystems."/nix" ={ + device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; + fsType = "btrfs"; + options = [ "subvol=@nix" "compress=zstd" ]; + }; + + fileSystems."/home" = { + device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; + fsType = "btrfs"; + options = [ "subvol=@home" "compress=zstd" ]; + }; + + /*fileSystems."/swap" = { + device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; + fsType = "btrfs"; + options = [ "subvol=@swapfile" ]; + };*/ + + fileSystems."/boot/efi" = { + device = "/dev/disk/by-uuid/EC76-201F"; + fsType = "vfat"; + }; + + swapDevices = []; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} From 582fe1b01b1fdf17228d844140fa128bb83fcbdb Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 17 Jul 2023 13:15:52 +0200 Subject: [PATCH 0070/1125] Flake: fix formatting --- flake.nix | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/flake.nix b/flake.nix index b2108d7..b30b03b 100755 --- a/flake.nix +++ b/flake.nix @@ -2,29 +2,29 @@ description = "Configuration for Everest"; inputs = { -nixpkgs.url = "nixpkgs/nixos-23.05"; -nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; + nixpkgs.url = "nixpkgs/nixos-23.05"; + nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; -agenix = { - url = "github:ryantm/agenix"; - inputs = { - nixpkgs.follows = "nixpkgs"; - darwin.follows = ""; # Not using this on MacOS, so this doesn't pull it's dependencies + agenix = { + url = "github:ryantm/agenix"; + inputs = { + nixpkgs.follows = "nixpkgs"; + darwin.follows = ""; # Not using this on MacOS, so this doesn't pull it's dependencies + }; }; -}; -home-manager = { - url = "github:nix-community/home-manager/release-23.05"; - inputs.nixpkgs.follows = "nixpkgs"; -}; + home-manager = { + url = "github:nix-community/home-manager/release-23.05"; + inputs.nixpkgs.follows = "nixpkgs"; + }; -home-manager-unstable = { - url = "github:nix-community/home-manager/"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; -}; + home-manager-unstable = { + url = "github:nix-community/home-manager/"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; -nix-impermanence.url = "github:nix-community/impermanence"; -}; + nix-impermanence.url = "github:nix-community/impermanence"; + }; outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nix-impermanence, ... }: { devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { From f9830c2dfe9aa8345b8c755fb620294afe0d4294 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 19 Jul 2023 10:37:43 +0200 Subject: [PATCH 0071/1125] Flake: add nixos-hardware --- flake.lock | 17 +++++++++++++++++ flake.nix | 4 +++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index 4a32b35..d288db1 100644 --- a/flake.lock +++ b/flake.lock @@ -99,6 +99,22 @@ "type": "github" } }, + "nixos-hardware": { + "locked": { + "lastModified": 1689320556, + "narHash": "sha256-vODUkZLWFVCvo1KPK3dC2CbXjxa9antEn5ozwlcTr48=", + "owner": "NixOS", + "repo": "nixos-hardware", + "rev": "d4ea64f2063820120c05f6ba93ee02e6d4671d6b", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixos-hardware", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1689137672, @@ -135,6 +151,7 @@ "home-manager": "home-manager_2", "home-manager-unstable": "home-manager-unstable", "nix-impermanence": "nix-impermanence", + "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", "nixpkgs-unstable": "nixpkgs-unstable" } diff --git a/flake.nix b/flake.nix index b30b03b..6051319 100755 --- a/flake.nix +++ b/flake.nix @@ -23,10 +23,12 @@ inputs = { inputs.nixpkgs.follows = "nixpkgs-unstable"; }; + nixos-hardware.url = "github:NixOS/nixos-hardware/master"; + nix-impermanence.url = "github:nix-community/impermanence"; }; -outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nix-impermanence, ... }: { +outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, ... }: { devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { name = "Environment for toast's nixos configurations"; # The agenix cli is not needed to activate a configuration, so instead of installing it From 9220a6acb115bbe0e92c32de1bb6c70c36ba5e5d Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 19 Jul 2023 10:41:04 +0200 Subject: [PATCH 0072/1125] SurfaceGo: use nixos-hardware module --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 6051319..f2270f8 100755 --- a/flake.nix +++ b/flake.nix @@ -71,6 +71,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } agenix.nixosModules.default home-manager.nixosModule + nixos-hardware.nixosModules.microsoft-surface-go ./roles/common ./roles/desktop ./roles/kde From a213508f689494ac525eff16a621bb4e86c25749 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 19 Jul 2023 11:10:33 +0200 Subject: [PATCH 0073/1125] Flake: update lock file --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index d288db1..adfe329 100644 --- a/flake.lock +++ b/flake.lock @@ -9,11 +9,11 @@ ] }, "locked": { - "lastModified": 1684153753, - "narHash": "sha256-PVbWt3qrjYAK+T5KplFcO+h7aZWfEj1UtyoKlvcDxh0=", + "lastModified": 1689334118, + "narHash": "sha256-djk5AZv1yU84xlKFaVHqFWvH73U7kIRstXwUAnDJPsk=", "owner": "ryantm", "repo": "agenix", - "rev": "db5637d10f797bb251b94ef9040b237f4702cde3", + "rev": "0d8c5325fc81daf00532e3e26c6752f7bcde1143", "type": "github" }, "original": { @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1689134369, - "narHash": "sha256-0G9dutIvhS/WUr3Awcnqw71g8EVVvvkOhVDnDDbY4Fw=", + "lastModified": 1689495092, + "narHash": "sha256-yZu2j5FpLZEPhJQQutMCPTxa1VMigLPabLYvLTq6ASM=", "owner": "nix-community", "repo": "home-manager", - "rev": "e42fb59768f0305085abde0dd27ab5e0cc15420c", + "rev": "2f84579a70b8c74e5ebb37299a0c3ba279f09382", "type": "github" }, "original": { @@ -117,11 +117,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1689137672, - "narHash": "sha256-QZoHxr0a73x6rQcAo5CiwYpysHbSnk7lAR8/16um7mM=", + "lastModified": 1689605451, + "narHash": "sha256-u2qp2k9V1smCfk6rdUcgMKvBj3G9jVvaPHyeXinjN9E=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "98da3dd0de6660d4abed7bb74e748694bd803413", + "rev": "53657afe29748b3e462f1f892287b7e254c26d77", "type": "github" }, "original": { @@ -132,11 +132,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1689098530, - "narHash": "sha256-fxc/9f20wRyo/5ydkmZkX/Sh/ULa7RcT8h+cUv8p/44=", + "lastModified": 1689534811, + "narHash": "sha256-jnSUdzD/414d94plCyNlvTJJtiTogTep6t7ZgIKIHiE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f2406198ea0e4e37d4380d0e20336c575b8f8ef9", + "rev": "6cee3b5893090b0f5f0a06b4cf42ca4e60e5d222", "type": "github" }, "original": { From d15fa5d7faae655845f9244df6d69af1c95c3f7c Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 19 Jul 2023 11:14:53 +0200 Subject: [PATCH 0074/1125] Everest: do not use tmpfs as /tmp --- machines/Everest/configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index 5b6d2fe..2b6f110 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -71,6 +71,9 @@ ]; }; + # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs + boot.tmp.useTmpfs = false; + home-manager = { backupFileExtension = "backup"; useGlobalPkgs = true; From e3fe1566a41f84dbf2c4d819103fc3a3d9efd7ff Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 25 Jul 2023 00:42:54 +0200 Subject: [PATCH 0075/1125] Flake: update lock file --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index adfe329..f88c303 100644 --- a/flake.lock +++ b/flake.lock @@ -9,11 +9,11 @@ ] }, "locked": { - "lastModified": 1689334118, - "narHash": "sha256-djk5AZv1yU84xlKFaVHqFWvH73U7kIRstXwUAnDJPsk=", + "lastModified": 1690228878, + "narHash": "sha256-9Xe7JV0krp4RJC9W9W9WutZVlw6BlHTFMiUP/k48LQY=", "owner": "ryantm", "repo": "agenix", - "rev": "0d8c5325fc81daf00532e3e26c6752f7bcde1143", + "rev": "d8c973fd228949736dedf61b7f8cc1ece3236792", "type": "github" }, "original": { @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1689495092, - "narHash": "sha256-yZu2j5FpLZEPhJQQutMCPTxa1VMigLPabLYvLTq6ASM=", + "lastModified": 1690208251, + "narHash": "sha256-eb/KANeuQADVl5j4wVid4jyPCOMTorSI2+gqoXp3LME=", "owner": "nix-community", "repo": "home-manager", - "rev": "2f84579a70b8c74e5ebb37299a0c3ba279f09382", + "rev": "d309a62ee81faec56dd31a263a0184b0e3227e36", "type": "github" }, "original": { @@ -101,11 +101,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1689320556, - "narHash": "sha256-vODUkZLWFVCvo1KPK3dC2CbXjxa9antEn5ozwlcTr48=", + "lastModified": 1690200740, + "narHash": "sha256-aRkEXGmCbAGcvDcdh/HB3YN+EvoPoxmJMOaqRZmf6vM=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "d4ea64f2063820120c05f6ba93ee02e6d4671d6b", + "rev": "ba9650b14e83b365fb9e731f7d7c803f22d2aecf", "type": "github" }, "original": { @@ -117,11 +117,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1689605451, - "narHash": "sha256-u2qp2k9V1smCfk6rdUcgMKvBj3G9jVvaPHyeXinjN9E=", + "lastModified": 1690148897, + "narHash": "sha256-l/j/AX1d2K79EWslwgWR2+htkzCbtjKZsS5NbWXnhz4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "53657afe29748b3e462f1f892287b7e254c26d77", + "rev": "ac1acba43b2f9db073943ff5ed883ce7e8a40a2c", "type": "github" }, "original": { @@ -132,11 +132,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1689534811, - "narHash": "sha256-jnSUdzD/414d94plCyNlvTJJtiTogTep6t7ZgIKIHiE=", + "lastModified": 1690031011, + "narHash": "sha256-kzK0P4Smt7CL53YCdZCBbt9uBFFhE0iNvCki20etAf4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6cee3b5893090b0f5f0a06b4cf42ca4e60e5d222", + "rev": "12303c652b881435065a98729eb7278313041e49", "type": "github" }, "original": { From d3067f9547f7e9d23e4f537bc1a752bdac4ab336 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 21 Jul 2023 01:35:01 +0200 Subject: [PATCH 0076/1125] Common: move localisation settings to configuration.nix --- machines/Archie/configuration.nix | 2 -- machines/Everest/configuration.nix | 17 ----------------- machines/SurfaceGo/configuration.nix | 2 -- roles/common/configuration.nix | 18 +++++++++++++++++- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/machines/Archie/configuration.nix b/machines/Archie/configuration.nix index 4b56c96..cb196e3 100644 --- a/machines/Archie/configuration.nix +++ b/machines/Archie/configuration.nix @@ -33,8 +33,6 @@ # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - # Select internationalisation properties. - i18n.defaultLocale = "en_US.UTF-8"; console = { keyMap = "es"; }; diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index 2b6f110..85ff132 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -32,23 +32,6 @@ nameservers = [ "8.8.8.8" ]; }; - # Set your time zone. - time.timeZone = "Europe/Madrid"; - - # Select internationalisation properties. - i18n.defaultLocale = "en_US.UTF-8"; - - i18n.extraLocaleSettings = { - LC_ADDRESS = "es_ES.UTF-8"; - LC_IDENTIFICATION = "es_ES.UTF-8"; - LC_MEASUREMENT = "es_ES.UTF-8"; - LC_MONETARY = "es_ES.UTF-8"; - LC_NAME = "es_ES.UTF-8"; - LC_NUMERIC = "es_ES.UTF-8"; - LC_PAPER = "es_ES.UTF-8"; - LC_TELEPHONE = "es_ES.UTF-8"; - LC_TIME = "es_ES.UTF-8"; - }; # Configure keymap in X11 services.xserver = { diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix index f0e31af..ef12065 100644 --- a/machines/SurfaceGo/configuration.nix +++ b/machines/SurfaceGo/configuration.nix @@ -33,8 +33,6 @@ # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - # Select internationalisation properties. - i18n.defaultLocale = "en_US.UTF-8"; console = { keyMap = "es"; }; diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index ba301c4..8a02771 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -17,7 +17,23 @@ # Cleaning out /tmp at boot if it's a tmpfs is quite stupid cleanOnBoot = !config.boot.tmp.useTmpfs; }; - + + # Set up localisation + i18n = { + defaultLocale = "en_US.UTF-8"; + extraLocaleSettings = { + LC_NUMERIC = "es_ES.UTF-8"; + # am/pm is nice but mm/dd/yy is yucky + LC_TIME = "es_US.UTF-8"; + LC_MONETARY = "es_ES.UTF-8"; + LC_MEASUREMENT = "es_ES.UTF-8"; + LC_PAPER = "es_ES.UTF-8"; + LC_ADDRESS = "es_US.UTF-8"; + LC_NAME = "es_ES.UTF-8"; + LC_TELEPHONE = "es_ES.UTF-8"; + }; + }; + # Set up secrets age = { identityPaths = [ From 62a2fda28703eda1283ad6a0972e37d16caa1db3 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 21 Jul 2023 01:45:57 +0200 Subject: [PATCH 0077/1125] Common: set up timezone on configuration.nix --- machines/Archie/configuration.nix | 3 --- machines/Everest/configuration.nix | 1 - machines/SurfaceGo/configuration.nix | 3 --- roles/common/configuration.nix | 3 +++ 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/machines/Archie/configuration.nix b/machines/Archie/configuration.nix index cb196e3..020dc55 100644 --- a/machines/Archie/configuration.nix +++ b/machines/Archie/configuration.nix @@ -26,9 +26,6 @@ # Allow unfree packages nixpkgs.config.allowUnfree = true; - # Set your time zone. - time.timeZone = "Europe/Madrid"; - # Configure network proxy if necessary # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index 85ff132..b97449a 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -32,7 +32,6 @@ nameservers = [ "8.8.8.8" ]; }; - # Configure keymap in X11 services.xserver = { layout = "es"; diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix index ef12065..05f9686 100644 --- a/machines/SurfaceGo/configuration.nix +++ b/machines/SurfaceGo/configuration.nix @@ -26,9 +26,6 @@ # Allow unfree packages nixpkgs.config.allowUnfree = true; - # Set your time zone. - time.timeZone = "Europe/Madrid"; - # Configure network proxy if necessary # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 8a02771..9fc3089 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -34,6 +34,9 @@ }; }; + # Set up time zone. + time.timeZone = "Europe/Madrid"; + # Set up secrets age = { identityPaths = [ From 7e0a707db500a2a2f6d6ceee95b597c32d61ad70 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 21 Jul 2023 18:44:32 +0200 Subject: [PATCH 0078/1125] Common: set up default keyboard layout --- machines/Archie/configuration.nix | 4 ---- machines/Everest/configuration.nix | 9 --------- machines/SurfaceGo/configuration.nix | 4 ---- roles/common/configuration.nix | 5 +++++ 4 files changed, 5 insertions(+), 17 deletions(-) diff --git a/machines/Archie/configuration.nix b/machines/Archie/configuration.nix index 020dc55..dfd748a 100644 --- a/machines/Archie/configuration.nix +++ b/machines/Archie/configuration.nix @@ -30,10 +30,6 @@ # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - console = { - keyMap = "es"; - }; - # Enable the X11 windowing system. services.xserver.enable = true; diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index b97449a..8cd3198 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -32,15 +32,6 @@ nameservers = [ "8.8.8.8" ]; }; - # Configure keymap in X11 - services.xserver = { - layout = "es"; - xkbVariant = ""; - }; - - # Configure console keymap - console.keyMap = "es"; - # Define a user account. Don't forget to set a password with ‘passwd’. users.users.toast = { isNormalUser = true; diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix index 05f9686..3f91f65 100644 --- a/machines/SurfaceGo/configuration.nix +++ b/machines/SurfaceGo/configuration.nix @@ -30,10 +30,6 @@ # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - console = { - keyMap = "es"; - }; - # Enable the X11 windowing system. services.xserver.enable = true; diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 9fc3089..67ea919 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -18,6 +18,11 @@ cleanOnBoot = !config.boot.tmp.useTmpfs; }; + # Set up keyboard layout + services.xserver.layout = "es"; + # Make the console use X's keyboard configuration + console.useXkbConfig = true; + # Set up localisation i18n = { defaultLocale = "en_US.UTF-8"; From bc899d590186a344255223c85a9f3533ea3b8a8b Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 12 Aug 2023 14:04:45 +0200 Subject: [PATCH 0079/1125] Desktop:enable flatpak --- roles/desktop/services/default.nix | 1 + roles/desktop/services/flatpak.nix | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 roles/desktop/services/flatpak.nix diff --git a/roles/desktop/services/default.nix b/roles/desktop/services/default.nix index 48f9952..19921e3 100644 --- a/roles/desktop/services/default.nix +++ b/roles/desktop/services/default.nix @@ -3,5 +3,6 @@ { imports = [ ./ssh-agent.nix + ./flatpak.nix ]; } diff --git a/roles/desktop/services/flatpak.nix b/roles/desktop/services/flatpak.nix new file mode 100644 index 0000000..9a98896 --- /dev/null +++ b/roles/desktop/services/flatpak.nix @@ -0,0 +1,5 @@ +{ config, pkgs, ... }: + +{ + services.flatpak.enable = true; +} From 7d96e010edb8508075c5effb267ade47e3822d39 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 13 Aug 2023 11:43:14 +0200 Subject: [PATCH 0080/1125] Kde: move kate.nix into programs folder --- roles/kde/default.nix | 2 +- roles/kde/programs/default.nix | 7 +++++++ roles/kde/{ => programs}/kate.nix | 0 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 roles/kde/programs/default.nix rename roles/kde/{ => programs}/kate.nix (100%) diff --git a/roles/kde/default.nix b/roles/kde/default.nix index 76968a3..9aaf999 100755 --- a/roles/kde/default.nix +++ b/roles/kde/default.nix @@ -4,6 +4,6 @@ imports = [ ./plasma.nix ./sddm.nix - ./kate.nix + ./programs ]; } diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix new file mode 100644 index 0000000..9575dce --- /dev/null +++ b/roles/kde/programs/default.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + imports = [ + ./kate.nix + ]; +} diff --git a/roles/kde/kate.nix b/roles/kde/programs/kate.nix similarity index 100% rename from roles/kde/kate.nix rename to roles/kde/programs/kate.nix From 273bcd9ffdba86c9fcf59377b9992f1bad2fbf55 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 13 Aug 2023 13:55:47 +0200 Subject: [PATCH 0081/1125] Plasma: tell baloo to not index not useful folders --- roles/kde/plasma.nix | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index baec988..a9323d7 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -23,6 +23,20 @@ let AccentColor = "172,53,164" ; }; }; + balooExcludedDirs = lib.strings.intersperse "," [ + "$HOME/.cache/" + "$HOME/.config/" + "$HOME/.local/" + ]; + + baloofilerc = lib.generators.toINI {} { + General = { + # The [$e] part allows you to use environment variables + "exclude folders[$e]" = lib.strings.concatStrings balooExcludedDirs; + }; + }; + + # Make custom packages breezeTint = pkgs.stdenv.mkDerivation { name = "breeze-tint"; src = "${pkgs.breeze-qt5}"; @@ -60,6 +74,7 @@ let set -x mkdir -p $out/etc/xdg echo "${kdeglobals}" > $out/etc/xdg/kdeglobals + echo '${baloofilerc}' > $out/etc/xdg/baloofilerc runHook postInstall ''; From c7c780d86dec2a5029f304afae4f8b1c856edfca Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 14 Aug 2023 00:34:56 +0200 Subject: [PATCH 0082/1125] Flake: update lock file --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index f88c303..bb3fcea 100644 --- a/flake.lock +++ b/flake.lock @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1690208251, - "narHash": "sha256-eb/KANeuQADVl5j4wVid4jyPCOMTorSI2+gqoXp3LME=", + "lastModified": 1691882297, + "narHash": "sha256-e1/LAQSGLnBywfA1TfMl0Vj3tvYka73XOZ/D2/CJowE=", "owner": "nix-community", "repo": "home-manager", - "rev": "d309a62ee81faec56dd31a263a0184b0e3227e36", + "rev": "c3ab5ea047e6dc73df530948f7367455749d8906", "type": "github" }, "original": { @@ -86,11 +86,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1684264534, - "narHash": "sha256-K0zr+ry3FwIo3rN2U/VWAkCJSgBslBisvfRIPwMbuCQ=", + "lastModified": 1690797372, + "narHash": "sha256-GImz19e33SeVcIvBB7NnhbJSbTpFFmNtWLh7Z85Y188=", "owner": "nix-community", "repo": "impermanence", - "rev": "89253fb1518063556edd5e54509c30ac3089d5e6", + "rev": "e3a7acd113903269a1b5c8b527e84ce7ee859851", "type": "github" }, "original": { @@ -101,11 +101,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1690200740, - "narHash": "sha256-aRkEXGmCbAGcvDcdh/HB3YN+EvoPoxmJMOaqRZmf6vM=", + "lastModified": 1691871742, + "narHash": "sha256-6yDNjfbAMpwzWL4y75fxs6beXHRANfYX8BNSPjYehck=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "ba9650b14e83b365fb9e731f7d7c803f22d2aecf", + "rev": "430a56dd16fe583a812b2df44dca002acab2f4f6", "type": "github" }, "original": { @@ -117,11 +117,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1690148897, - "narHash": "sha256-l/j/AX1d2K79EWslwgWR2+htkzCbtjKZsS5NbWXnhz4=", + "lastModified": 1691831739, + "narHash": "sha256-6e12VCvA7jOjhzJ1adLiUV1GTPXGBcCfhggsDwiuNB4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ac1acba43b2f9db073943ff5ed883ce7e8a40a2c", + "rev": "3fe694c4156b84dac12627685c7ae592a71e2206", "type": "github" }, "original": { @@ -132,11 +132,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1690031011, - "narHash": "sha256-kzK0P4Smt7CL53YCdZCBbt9uBFFhE0iNvCki20etAf4=", + "lastModified": 1691654369, + "narHash": "sha256-gSILTEx1jRaJjwZxRlnu3ZwMn1FVNk80qlwiCX8kmpo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "12303c652b881435065a98729eb7278313041e49", + "rev": "ce5e4a6ef2e59d89a971bc434ca8ca222b9c7f5e", "type": "github" }, "original": { From 8e01e3b437a24170ce7dd1e0af7ae09aff5b632c Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 22 Aug 2023 00:13:48 +0200 Subject: [PATCH 0083/1125] Flake: update lock file --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index bb3fcea..e982d67 100644 --- a/flake.lock +++ b/flake.lock @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1691882297, - "narHash": "sha256-e1/LAQSGLnBywfA1TfMl0Vj3tvYka73XOZ/D2/CJowE=", + "lastModified": 1692503956, + "narHash": "sha256-MOA6FKc1YgfGP3ESnjSYfsyJ1BXlwV5pGlY/u5XdJfY=", "owner": "nix-community", "repo": "home-manager", - "rev": "c3ab5ea047e6dc73df530948f7367455749d8906", + "rev": "958c06303f43cf0625694326b7f7e5475b1a2d5c", "type": "github" }, "original": { @@ -70,11 +70,11 @@ ] }, "locked": { - "lastModified": 1687871164, - "narHash": "sha256-bBFlPthuYX322xOlpJvkjUBz0C+MOBjZdDOOJJ+G2jU=", + "lastModified": 1692099905, + "narHash": "sha256-/pSusGhmIdSdAaywQRFA5dVbfdIzlWQTecM+E46+cJ0=", "owner": "nix-community", "repo": "home-manager", - "rev": "07c347bb50994691d7b0095f45ebd8838cf6bc38", + "rev": "2a6679aa9cc3872c29ba2a57fe1b71b3e3c5649f", "type": "github" }, "original": { @@ -101,11 +101,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1691871742, - "narHash": "sha256-6yDNjfbAMpwzWL4y75fxs6beXHRANfYX8BNSPjYehck=", + "lastModified": 1692373088, + "narHash": "sha256-EPgCecdc9I8aTdmDNoO1l7R72r2WPhZRcesV4nzxBj8=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "430a56dd16fe583a812b2df44dca002acab2f4f6", + "rev": "7f1836531b126cfcf584e7d7d71bf8758bb58969", "type": "github" }, "original": { @@ -117,11 +117,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1691831739, - "narHash": "sha256-6e12VCvA7jOjhzJ1adLiUV1GTPXGBcCfhggsDwiuNB4=", + "lastModified": 1692525914, + "narHash": "sha256-MUgZ9/9mE/EbEQA6JPdcQHkjoR5fgvaKhpy6UO67uEc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3fe694c4156b84dac12627685c7ae592a71e2206", + "rev": "475d5ae2c4cb87b904545bdb547af05681198fcc", "type": "github" }, "original": { @@ -132,11 +132,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1691654369, - "narHash": "sha256-gSILTEx1jRaJjwZxRlnu3ZwMn1FVNk80qlwiCX8kmpo=", + "lastModified": 1692447944, + "narHash": "sha256-fkJGNjEmTPvqBs215EQU4r9ivecV5Qge5cF/QDLVn3U=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ce5e4a6ef2e59d89a971bc434ca8ca222b9c7f5e", + "rev": "d680ded26da5cf104dd2735a51e88d2d8f487b4d", "type": "github" }, "original": { From 62fdddc21e1f9f4c7bd22efc186d263098028dfc Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 25 Aug 2023 13:07:39 +0200 Subject: [PATCH 0084/1125] Common: set up console font --- roles/common/configuration.nix | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 67ea919..c8c6697 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -20,8 +20,15 @@ # Set up keyboard layout services.xserver.layout = "es"; - # Make the console use X's keyboard configuration - console.useXkbConfig = true; + + # Set up console + console = { + packages = [ pkgs.terminus_font ]; + earlySetup = true; + font = lib.mkDefault "ter-i16n"; + # Make the console use X's keyboard configuration + useXkbConfig = true; + }; # Set up localisation i18n = { From 9b1e8798c0fb33b06b48b18206f0b23730903214 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 25 Aug 2023 13:07:53 +0200 Subject: [PATCH 0085/1125] SurfaceGo: use a bigger console font --- machines/SurfaceGo/configuration.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix index 3f91f65..024bd92 100644 --- a/machines/SurfaceGo/configuration.nix +++ b/machines/SurfaceGo/configuration.nix @@ -43,6 +43,11 @@ # services.xserver.layout = "us"; # services.xserver.xkbOptions = "eurosign:e,caps:escape"; + console = { + # The kernel doesn't detect the scree as being HiDPI, so I need to use a bigger font + font = "ter-i32n"; + }; + # Enable CUPS to print documents. # services.printing.enable = true; From cb3ec0cb573e67d4eece46f9e23fd94ab4febba5 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 26 Aug 2023 13:05:54 +0200 Subject: [PATCH 0086/1125] Common: set up tailscale --- roles/common/default.nix | 2 +- roles/common/services/default.nix | 8 ++++++++ roles/common/services/tailscale.nix | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 roles/common/services/default.nix create mode 100644 roles/common/services/tailscale.nix diff --git a/roles/common/default.nix b/roles/common/default.nix index 91e9eb3..1e090a3 100755 --- a/roles/common/default.nix +++ b/roles/common/default.nix @@ -3,7 +3,7 @@ { imports = [ ./programs - ./services/avahi.nix + ./services ./configuration.nix ]; } diff --git a/roles/common/services/default.nix b/roles/common/services/default.nix new file mode 100644 index 0000000..38fca78 --- /dev/null +++ b/roles/common/services/default.nix @@ -0,0 +1,8 @@ +{ ... }: + +{ + imports = [ + ./avahi.nix + ./tailscale.nix + ]; +} diff --git a/roles/common/services/tailscale.nix b/roles/common/services/tailscale.nix new file mode 100644 index 0000000..aef79f6 --- /dev/null +++ b/roles/common/services/tailscale.nix @@ -0,0 +1,8 @@ +{ config, lib, ... }: + +{ + services.tailscale = { + enable = true; + useRoutingFeatures = lib.mkDefault "client"; + }; +} From 200ff430962e6c5325d4fef27b002a2fc3be3e71 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 26 Aug 2023 13:12:15 +0200 Subject: [PATCH 0087/1125] Server: enable routing features for tailscale --- roles/server/default.nix | 1 + roles/server/tailscale.nix | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 roles/server/tailscale.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index 9b262ae..d5a0970 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -13,5 +13,6 @@ ./ddclient.nix ./beep.nix ./wireguard.nix + ./tailscale.nix ]; } diff --git a/roles/server/tailscale.nix b/roles/server/tailscale.nix new file mode 100644 index 0000000..36ba593 --- /dev/null +++ b/roles/server/tailscale.nix @@ -0,0 +1,8 @@ +{ config, ... }: + +{ + services.tailscale = { + # This is needed for being an exit node + useRoutingFeatures = "server"; + }; +} From 0dbd1faaa637643939703fd566432cef0b52c17a Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 26 Aug 2023 21:19:28 +0200 Subject: [PATCH 0088/1125] Nix: write system nixpkgs into registry --- flake.nix | 6 +++++- roles/common/programs/nix.nix | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 652055f..747da57 100755 --- a/flake.nix +++ b/flake.nix @@ -28,7 +28,8 @@ inputs = { nix-impermanence.url = "github:nix-community/impermanence"; }; -outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, ... }: { +outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, ... } @inputs: { + devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { name = "Environment for toast's nixos configurations"; # The agenix cli is not needed to activate a configuration, so instead of installing it @@ -46,6 +47,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl nixosConfigurations = { Archie = nixpkgs-unstable.lib.nixosSystem { system = "x86_64-linux"; + specialArgs = { systemPkgs = inputs.nixpkgs-unstable; }; /* I used to set up nixpkgs in the flake, but doing that made defining overlays in modules impossible (or at least I could @@ -67,6 +69,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl SurfaceGo = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; + specialArgs = { systemPkgs = inputs.nixpkgs; }; modules = [ # Needed for nix-index { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } @@ -82,6 +85,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl Everest = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; + specialArgs = { systemPkgs = inputs.nixpkgs; }; modules = [ # Needed for nix-index { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index ea40ccd..baa1cc9 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -1,4 +1,4 @@ -{ config, ... }: +{ config, systemPkgs, ... }: { nix = { @@ -10,6 +10,9 @@ experimental-features = nix-command flakes from = { id = "agenix"; type = "indirect"; }; to = { owner = "ryantm"; repo = "agenix"; type = "github"; }; }; + # Write the system's nixpkgs into the registry to avoid mixing nixpkgs versions + # https://dataswamp.org/~solene/2022-07-20-nixos-flakes-command-sync-with-system.html + system.flake = systemPkgs; }; }; } From 94a87229f1751a64f032121dfe6f2e82e6e277ef Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 28 Aug 2023 13:13:51 +0200 Subject: [PATCH 0089/1125] Archie: remove duplicate comment in hardware-configuration.nix --- machines/Archie/hardware-configuration.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index 48133e7..7860798 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -8,7 +8,6 @@ [ (modulesPath + "/installer/scan/not-detected.nix") ]; - # Enabke support for the Xbox One wireless dongle # Enable support for the Xbox One wireless dongle hardware.xone.enable = true; From 60b28ea21869ebd6018c909a4cf914491ada5658 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 28 Aug 2023 14:01:48 +0200 Subject: [PATCH 0090/1125] Archie: mount home subvolume as /home --- machines/Archie/hardware-configuration.nix | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index 7860798..cc53c64 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -39,17 +39,22 @@ fsType = "vfat"; }; - /* - Mount the root subvolume of the SSD - This is helpful for getting things from - my old Arch install, as well as for running btdu - */ fileSystems = { + /* + Mount the root subvolume of the SSD + This is helpful for getting things from + my old Arch install, as well as for running btdu + */ "/mnt/ssd" = { device = config.fileSystems."/".device; fsType = config.fileSystems."/".fsType; options = [ "subvolid=5" "ro" ]; }; + "/home" = { + device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; + fsType = "btrfs"; + options = [ "subvol=@home" "compress=zstd" ]; + }; }; swapDevices = [ ]; From bd85f36dda9127cf1f77438bf70b9f4984fd680b Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 28 Aug 2023 16:34:19 +0200 Subject: [PATCH 0091/1125] Steam: only enable pipewire's alsa support if it's used as the sound server --- roles/gaming/steam.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/gaming/steam.nix b/roles/gaming/steam.nix index 1c71901..27a1a33 100644 --- a/roles/gaming/steam.nix +++ b/roles/gaming/steam.nix @@ -7,5 +7,5 @@ remotePlay.openFirewall = true; }; # Some linux native games (rise of the tomb raider) use alsa for sound - services.pipewire.alsa.enable = true; + services.pipewire.alsa.enable = if config.services.pipewire.pulse.enable == true then true else false; } From a0221784e77fb560b5f03ff60b0966e37c294110 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 28 Aug 2023 17:53:12 +0200 Subject: [PATCH 0092/1125] Archie: temporarely use pulseaudio as sound server --- machines/Archie/configuration.nix | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/machines/Archie/configuration.nix b/machines/Archie/configuration.nix index dfd748a..eb8bc43 100644 --- a/machines/Archie/configuration.nix +++ b/machines/Archie/configuration.nix @@ -33,11 +33,22 @@ # Enable the X11 windowing system. services.xserver.enable = true; - # Enable the pipewire sound server + /*# Enable the pipewire sound server services.pipewire = { enable = true; pulse.enable = true; + }; /* + + /* + Pipewire's audio server seems to be broken for now, so I'm going to + temporarely use pulse as my audio server + */ + services.pipewire = { + audio.enable = false; + pulse.enable = false; + alsa.enable = false; }; + hardware.pulseaudio.enable = true; # Configure keymap in X11 # services.xserver.layout = "us"; From a0e2825acd98945b111288115ed81b8c90090529 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 28 Aug 2023 18:30:04 +0200 Subject: [PATCH 0093/1125] Firefox: move kde specific settings to kde role --- roles/desktop/programs/firefox.nix | 14 -------------- roles/kde/programs/default.nix | 1 + roles/kde/programs/firefox.nix | 25 +++++++++++++++++++++++++ 3 files changed, 26 insertions(+), 14 deletions(-) create mode 100644 roles/kde/programs/firefox.nix diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index 643f174..7b601ea 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -35,20 +35,6 @@ "Value" = true; "Status" = "locked"; }; - # Make firefox use the kde file picker - "widget.use-xdg-desktop-portal.file-picker" = { - "Value" = 1; - "Status" = "default"; - }; - /* - https://wiki.archlinux.org/title/Firefox#KDE_integration tells me to enable this, - but strangely enough doing so makes firefox ask to be set as the default browser - every time you start it up, so I'll disable it - */ - "widget.use-xdg-desktop-portal.mime-handler" = { - "Value" = 0; - "Status" = "default"; - }; }; "PromptForDownloadLocation" = true; # I use an external password manager, so the built in one just bothers me diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index 9575dce..fe5c43b 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -3,5 +3,6 @@ { imports = [ ./kate.nix + ./firefox.nix ]; } diff --git a/roles/kde/programs/firefox.nix b/roles/kde/programs/firefox.nix new file mode 100644 index 0000000..284bb32 --- /dev/null +++ b/roles/kde/programs/firefox.nix @@ -0,0 +1,25 @@ +{ config, pkgs, ... }: + +{ + # KDE specific firefox settings + programs.firefox = { + policies = { + "Preferences" = { + # Make firefox use the kde file picker + "widget.use-xdg-desktop-portal.file-picker" = { + "Value" = 1; + "Status" = "default"; + }; + /* + https://wiki.archlinux.org/title/Firefox#KDE_integration tells me to enable this, + but strangely enough doing so makes firefox ask to be set as the default browser + every time you start it up, so I'll disable it + */ + "widget.use-xdg-desktop-portal.mime-handler" = { + "Value" = 0; + "Status" = "default"; + }; + }; + }; + }; +} From a0db9fdcdebb9a093470dc6be92c91ef7f4e2a94 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 28 Aug 2023 18:30:42 +0200 Subject: [PATCH 0094/1125] Kde: install firefox plasma integration extension --- roles/kde/programs/firefox.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/roles/kde/programs/firefox.nix b/roles/kde/programs/firefox.nix index 284bb32..9892650 100644 --- a/roles/kde/programs/firefox.nix +++ b/roles/kde/programs/firefox.nix @@ -4,6 +4,13 @@ # KDE specific firefox settings programs.firefox = { policies = { + "ExtensionSettings" = { + # TODO: Install extensions the NUR instead of from AMO + "plasma-browser-integration@kde.org" = { + "installation_mode" = "normal_installed"; + "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/plasma-integration/latest.xpi"; + }; + }; "Preferences" = { # Make firefox use the kde file picker "widget.use-xdg-desktop-portal.file-picker" = { From 8c35cda8e90f1e1629c117a4f00955a90a61ebf1 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 28 Aug 2023 18:31:42 +0200 Subject: [PATCH 0095/1125] Firefox: uninstall plasma integration extension by default --- roles/desktop/programs/firefox.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index 7b601ea..6871b6f 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -1,4 +1,4 @@ -{ config, pkgs, ... }: +{ config, lib, ... }: { # System wide firefox settings @@ -24,6 +24,8 @@ "installation_mode" = "normal_installed"; "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/privacy-badger17/latest.xpi"; }; + # Uninstall the kde plasma integration extension if KDE is not installed + "plasma-browser-integration@kde.org"."installation_mode" = lib.mkDefault "blocked"; }; "Preferences" = { # Enable video hardware acceleration From 6f59bd3d6d4ccb73e07df8ffae0f93689c1b4dbb Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 28 Aug 2023 23:44:25 +0200 Subject: [PATCH 0096/1125] Move home-manager settings to common role --- machines/Everest/configuration.nix | 11 ----------- roles/common/configuration.nix | 15 +++++++++++++++ roles/desktop/programs/keepassxc.nix | 10 ---------- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index 8cd3198..fd2f6de 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -48,24 +48,13 @@ boot.tmp.useTmpfs = false; home-manager = { - backupFileExtension = "backup"; - useGlobalPkgs = true; users.toast = { config, ... }: { home = { - stateVersion = "23.05"; file = { # This symlinks the Transmission downloads folder into my user's downloads folder for easy access "Downloads/Transmission".source = config.lib.file.mkOutOfStoreSymlink "/var/lib/transmission/Downloads"; }; }; - xdg = { - #enable = true; - userDirs = { - enable = true; - createDirectories = true; - publicShare = null; # Disable the public folder - }; - }; }; }; diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index c8c6697..2be5714 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -49,6 +49,21 @@ # Set up time zone. time.timeZone = "Europe/Madrid"; + home-manager = { + backupFileExtension = "hm-backup"; + useGlobalPkgs = true; + users.toast = { config, ... }: { + home.stateVersion = "23.05"; + xdg = { + userDirs = { + enable = true; + createDirectories = true; + publicShare = null; # Disable the public folder + }; + }; + }; + }; + # Set up secrets age = { identityPaths = [ diff --git a/roles/desktop/programs/keepassxc.nix b/roles/desktop/programs/keepassxc.nix index 53f42da..6ffb436 100644 --- a/roles/desktop/programs/keepassxc.nix +++ b/roles/desktop/programs/keepassxc.nix @@ -25,18 +25,9 @@ in { # I'm only using keepass on my user, so I'm installing it with home-manager home-manager = { - /* - TODO: move home-manager settings into the common role - They are not keepass specific, so they really should - not be here. I'm too lazy to do it now tho :P - */ - backupFileExtension = "backup"; - useGlobalPkgs = true; - extraSpecialArgs = { kpxcSettings = kpxcSettings; }; users.toast = { config, pkgs, kpxcSettings, ... }: { home = { - stateVersion = "23.05"; packages = [ pkgs.keepassxc ]; # No module for KeePassXC config :( file = { @@ -63,7 +54,6 @@ in ''; }; }; - }; }; } From 100a4df00655d4a29f91ba97501a1dfda927df5d Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 30 Aug 2023 00:16:37 +0200 Subject: [PATCH 0097/1125] Flake: add nix-diff to devShell --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 747da57..b6b1ad4 100755 --- a/flake.nix +++ b/flake.nix @@ -38,6 +38,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl agenix.packages.x86_64-linux.default git plasma5Packages.plasma-sdk + nix-diff ]; shellHook ='' export PS1="$PS1(toast-configs)> " From 638cf16a416257aed4ec3d6f766ec0a05e707a55 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 30 Aug 2023 00:30:11 +0200 Subject: [PATCH 0098/1125] Kate: install system-wide --- roles/kde/programs/kate.nix | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/roles/kde/programs/kate.nix b/roles/kde/programs/kate.nix index ff84a90..99b1e5d 100644 --- a/roles/kde/programs/kate.nix +++ b/roles/kde/programs/kate.nix @@ -1,8 +1,5 @@ { config, pkgs, ... }: { - home-manager.users.toast = { config, pkgs, ... }: - { - home.packages = [ pkgs.kate ]; - }; + environment.systemPackages = [ pkgs.kate ]; } From 0a358a8643ee520cfacb5b7af2949efadd78f3f6 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 30 Aug 2023 00:36:38 +0200 Subject: [PATCH 0099/1125] KeepassXC: install with users.users.<>-packages instead of home manager --- roles/desktop/programs/keepassxc.nix | 51 +++++++++++++--------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/roles/desktop/programs/keepassxc.nix b/roles/desktop/programs/keepassxc.nix index 6ffb436..2bff9ed 100644 --- a/roles/desktop/programs/keepassxc.nix +++ b/roles/desktop/programs/keepassxc.nix @@ -23,36 +23,33 @@ let in { - # I'm only using keepass on my user, so I'm installing it with home-manager + users.users.toast.packages = [ pkgs.keepassxc ]; home-manager = { extraSpecialArgs = { kpxcSettings = kpxcSettings; }; users.toast = { config, pkgs, kpxcSettings, ... }: { - home = { - packages = [ pkgs.keepassxc ]; - # No module for KeePassXC config :( - file = { - ".config/keepassxc/keepassxc.ini".text = kpxcSettings; - # For some reason the autostart .desktop is not the same as the regular one - ".config/autostart/org.keepassxc.KeePassXC.desktop".text = '' - [Desktop Entry] - Name=KeePassXC - GenericName=Password Manager - Exec=keepassxc - TryExec=keepassxc - Icon=keepassxc - StartupWMClass=keepassxc - StartupNotify=true - Terminal=false - Type=Application - Version=1.0 - Categories=Utility;Security;Qt; - MimeType=application/x-keepass2; - X-GNOME-Autostart-enabled=true - X-GNOME-Autostart-Delay=2 - X-KDE-autostart-after=panel - X-LXQt-Need-Tray=true - ''; - }; + # No module for KeePassXC config :( + home.file = { + ".config/keepassxc/keepassxc.ini".text = kpxcSettings; + # For some reason the autostart .desktop is not the same as the regular one + ".config/autostart/org.keepassxc.KeePassXC.desktop".text = '' + [Desktop Entry] + Name=KeePassXC + GenericName=Password Manager + Exec=keepassxc + TryExec=keepassxc + Icon=keepassxc + StartupWMClass=keepassxc + StartupNotify=true + Terminal=false + Type=Application + Version=1.0 + Categories=Utility;Security;Qt; + MimeType=application/x-keepass2; + X-GNOME-Autostart-enabled=true + X-GNOME-Autostart-Delay=2 + X-KDE-autostart-after=panel + X-LXQt-Need-Tray=true + ''; }; }; }; From a0d2ba5c70e22cefd6eafbd6a99b634079ff9c05 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 30 Aug 2023 00:54:54 +0200 Subject: [PATCH 0100/1125] Flake: update lock file --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index e982d67..0468085 100644 --- a/flake.lock +++ b/flake.lock @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1692503956, - "narHash": "sha256-MOA6FKc1YgfGP3ESnjSYfsyJ1BXlwV5pGlY/u5XdJfY=", + "lastModified": 1693187908, + "narHash": "sha256-cTcNpsqi1llmUFl9bmCdD0mTyfjhBrNFPhu2W12WXzA=", "owner": "nix-community", "repo": "home-manager", - "rev": "958c06303f43cf0625694326b7f7e5475b1a2d5c", + "rev": "8bde7a651b94ba30bd0baaa9c4a08aae88cc2e92", "type": "github" }, "original": { @@ -70,11 +70,11 @@ ] }, "locked": { - "lastModified": 1692099905, - "narHash": "sha256-/pSusGhmIdSdAaywQRFA5dVbfdIzlWQTecM+E46+cJ0=", + "lastModified": 1693208669, + "narHash": "sha256-hHFaaUsZ860wvppPeiu7nJn/nXZjJfnqAQEu9SPFE9I=", "owner": "nix-community", "repo": "home-manager", - "rev": "2a6679aa9cc3872c29ba2a57fe1b71b3e3c5649f", + "rev": "5bac4a1c06cd77cf8fc35a658ccb035a6c50cd2c", "type": "github" }, "original": { @@ -101,11 +101,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1692373088, - "narHash": "sha256-EPgCecdc9I8aTdmDNoO1l7R72r2WPhZRcesV4nzxBj8=", + "lastModified": 1692952286, + "narHash": "sha256-TsrtPv3+Q1KR0avZxpiJH+b6fX/R/hEQVHbjl1ebotY=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "7f1836531b126cfcf584e7d7d71bf8758bb58969", + "rev": "817e297fc3352fadc15f2c5306909aa9192d7d97", "type": "github" }, "original": { @@ -117,11 +117,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1692525914, - "narHash": "sha256-MUgZ9/9mE/EbEQA6JPdcQHkjoR5fgvaKhpy6UO67uEc=", + "lastModified": 1693231525, + "narHash": "sha256-Zmh8m0HHcgGBDth6jdJPmc4UAAP0L4jQmqIztywF1Iw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "475d5ae2c4cb87b904545bdb547af05681198fcc", + "rev": "c540061ac8d72d6e6d99345bd2d590c82b2f58c1", "type": "github" }, "original": { @@ -132,11 +132,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1692447944, - "narHash": "sha256-fkJGNjEmTPvqBs215EQU4r9ivecV5Qge5cF/QDLVn3U=", + "lastModified": 1693250523, + "narHash": "sha256-y3up5gXMTbnCsXrNEB5j+7TVantDLUYyQLu/ueiXuyg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d680ded26da5cf104dd2735a51e88d2d8f487b4d", + "rev": "3efb0f6f404ec8dae31bdb1a9b17705ce0d6986e", "type": "github" }, "original": { From 7765c2a55046fd7313e9280d4a7f2464866dc3ac Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 30 Aug 2023 00:56:29 +0200 Subject: [PATCH 0101/1125] Archie: use pipewire as the sound server again --- machines/Archie/configuration.nix | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/machines/Archie/configuration.nix b/machines/Archie/configuration.nix index eb8bc43..dfd748a 100644 --- a/machines/Archie/configuration.nix +++ b/machines/Archie/configuration.nix @@ -33,22 +33,11 @@ # Enable the X11 windowing system. services.xserver.enable = true; - /*# Enable the pipewire sound server + # Enable the pipewire sound server services.pipewire = { enable = true; pulse.enable = true; - }; /* - - /* - Pipewire's audio server seems to be broken for now, so I'm going to - temporarely use pulse as my audio server - */ - services.pipewire = { - audio.enable = false; - pulse.enable = false; - alsa.enable = false; }; - hardware.pulseaudio.enable = true; # Configure keymap in X11 # services.xserver.layout = "us"; From 455790a5b1aa4c287e7604a3026119ee97ced06b Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 30 Aug 2023 00:57:53 +0200 Subject: [PATCH 0102/1125] Desktop: install JamesDSP --- roles/desktop/programs/default.nix | 1 + roles/desktop/programs/jamesdsp.nix | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 roles/desktop/programs/jamesdsp.nix diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix index 6aa4825..b25ff4d 100755 --- a/roles/desktop/programs/default.nix +++ b/roles/desktop/programs/default.nix @@ -6,5 +6,6 @@ ./firefox.nix ./micro.nix ./keepassxc.nix + ./jamesdsp.nix ]; } diff --git a/roles/desktop/programs/jamesdsp.nix b/roles/desktop/programs/jamesdsp.nix new file mode 100644 index 0000000..4316cb5 --- /dev/null +++ b/roles/desktop/programs/jamesdsp.nix @@ -0,0 +1,5 @@ +{ config, pkgs, ... }: + +{ + users.users.toast.packages = [ pkgs.jamesdsp ]; +} From 124322df4c3e080c4587878636fa11c2167a31a8 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 30 Aug 2023 16:49:23 +0200 Subject: [PATCH 0103/1125] Flatpak: add flathub --- roles/desktop/services/flatpak.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/roles/desktop/services/flatpak.nix b/roles/desktop/services/flatpak.nix index 9a98896..fa658bf 100644 --- a/roles/desktop/services/flatpak.nix +++ b/roles/desktop/services/flatpak.nix @@ -2,4 +2,11 @@ { services.flatpak.enable = true; + system.activationScripts = { + flatpak.text = '' + echo "adding flatpak repos..." + repo=${pkgs.fetchurl { url = "https://dl.flathub.org/repo/flathub.flatpakrepo"; hash = "sha256-M3HdJQ5h2eFjNjAHP+/aFTzUQm9y9K+gwzc64uj+oDo="; } } + ${pkgs.flatpak}/bin/flatpak remote-add --if-not-exists flathub $repo + ''; + }; } From a67ce6f8ee97517dc89dc284df4ec8f0a2d0fa22 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 00:45:39 +0200 Subject: [PATCH 0104/1125] Kde: overhaul custom theme creation --- .../contents/defaults | 29 + .../layouts/org.kde.plasma.desktop-layout.js | 6 + .../org.kde.plasma.digitalclock.js | 3 + .../org.kde.plasma.kickoff.js | 3 + .../contents/previews/fullscreenpreview.jpg | Bin 0 -> 153563 bytes .../contents/previews/preview.png | Bin 0 -> 146651 bytes .../metadata.json | 19 + roles/kde/patches/TintedLookAndFeel.patch | 838 ------------------ roles/kde/plasma.nix | 7 +- 9 files changed, 64 insertions(+), 841 deletions(-) create mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/defaults create mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/layouts/org.kde.plasma.desktop-layout.js create mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.digitalclock.js create mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js create mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/previews/fullscreenpreview.jpg create mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/previews/preview.png create mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/metadata.json delete mode 100644 roles/kde/patches/TintedLookAndFeel.patch diff --git a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/defaults b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/defaults new file mode 100644 index 0000000..764fa66 --- /dev/null +++ b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/defaults @@ -0,0 +1,29 @@ +[kdeglobals][KDE] +widgetStyle=Breeze + +[kdeglobals][General] +ColorScheme=BreezeDarkTint + +[kdeglobals][Icons] +Theme=breeze-dark + +[plasmarc][Theme] +name=default + +[Wallpaper] +Image=MilkyWay + +[kcminputrc][Mouse] +cursorTheme=breeze_cursors + +[kwinrc][WindowSwitcher] +LayoutName=org.kde.breeze.desktop + +[kwinrc][DesktopSwitcher] +LayoutName=org.kde.breeze.desktop + +[kwinrc][org.kde.kdecoration2] +library=org.kde.breeze + +[KSplash] +Theme=org.kde.Breeze diff --git a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/layouts/org.kde.plasma.desktop-layout.js b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/layouts/org.kde.plasma.desktop-layout.js new file mode 100644 index 0000000..09fdfac --- /dev/null +++ b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/layouts/org.kde.plasma.desktop-layout.js @@ -0,0 +1,6 @@ +loadTemplate("org.kde.plasma.desktop.defaultPanel") + +var desktopsArray = desktopsForActivity(currentActivity()); +for( var j = 0; j < desktopsArray.length; j++) { + desktopsArray[j].wallpaperPlugin = 'org.kde.image'; +} diff --git a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.digitalclock.js b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.digitalclock.js new file mode 100644 index 0000000..f2d9552 --- /dev/null +++ b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.digitalclock.js @@ -0,0 +1,3 @@ +applet.currentConfigGroup = ["Appearance"] +applet.writeConfig("showSeconds", "true") +applet.reloadConfig() diff --git a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js new file mode 100644 index 0000000..5d17cfc --- /dev/null +++ b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js @@ -0,0 +1,3 @@ +applet.currentConfigGroup = ["General"] +applet.writeConfig("icon", "nix-snowflake-white") +applet.reloadConfig() diff --git a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/previews/fullscreenpreview.jpg b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/previews/fullscreenpreview.jpg new file mode 100644 index 0000000000000000000000000000000000000000..44aba5dd5d3c49eeef997ede7b199469302c8a8e GIT binary patch literal 153563 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 z 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 N2hYW8=yCD?CII}Y!Laka{`Bp4tNnM>wd5DR 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
  • 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

    nqokZPZ*dZ}W1;-wfvIu{`Te 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 literal 0 HcmV?d00001 diff --git a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/metadata.json b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/metadata.json new file mode 100644 index 0000000..820e77a --- /dev/null +++ b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/metadata.json @@ -0,0 +1,19 @@ +{ + "KPlugin": { + "Authors": [ + { + "Name": "Toast" + } + ], + "Category": "", + "Description": "Custom theme based on Breeze Dark", + "Id": "xyz.toast003.customtheme.desktop", + "License": "GPL", + "Name": "Toast's theme", + "ServiceTypes": [ + "Plasma/LookAndFeel" + ], + "Version": "1.0" + }, + "X-Plasma-MainScript": "defaults" +} diff --git a/roles/kde/patches/TintedLookAndFeel.patch b/roles/kde/patches/TintedLookAndFeel.patch deleted file mode 100644 index b955cc3..0000000 --- a/roles/kde/patches/TintedLookAndFeel.patch +++ /dev/null @@ -1,838 +0,0 @@ -diff --git a/share/plasma/look-and-feel/org.kde.breezedark.desktop/metadata.json b/share/plasma/look-and-feel/org.kde.breezedark.desktop/metadata.json -deleted file mode 100644 -index eb49faf..0000000 ---- a/share/plasma/look-and-feel/org.kde.breezedark.desktop/metadata.json -+++ /dev/null -@@ -1,147 +0,0 @@ --{ -- "KPlugin": { -- "Authors": [ -- { -- "Email": "plasma-devel@kde.org", -- "Name": "KDE Visual Design Group", -- "Name[ar]": "مجموعة التصميم المرئي لكِيدِي", -- "Name[az]": "KDE Vizual Dizayn Qrupu", -- "Name[be]": "Суполка візуальнага дызайну KDE", -- "Name[bg]": "KDE Visual Design Group", -- "Name[ca@valencia]": "Grup de disseny visual de KDE", -- "Name[ca]": "Grup de disseny visual de KDE", -- "Name[cs]": "Skupina vizuálního návrhu KDE", -- "Name[da]": "KDE Visual Design Group", -- "Name[de]": "KDE Visual Design Group", -- "Name[en_GB]": "KDE Visual Design Group", -- "Name[es]": "El grupo de diseño visual de KDE", -- "Name[eu]": "KDE Diseinu bisualeko taldea", -- "Name[fi]": "KDE:n visuaalinen suunnitteluryhmä", -- "Name[fr]": "Groupe de conception visuelle de KDE", -- "Name[hi]": "केडीई विज़ुअल डिज़ाइन दल", -- "Name[hu]": "KDE Visual Design Group", -- "Name[ia]": "KDE Visual Design Group (Gruppo de Designo Visual de KDE)", -- "Name[id]": "Grup Desain Visual KDE", -- "Name[is]": "Myndrænn hönnunarhópur KDE", -- "Name[it]": "KDE Visual Design Group", -- "Name[ja]": "KDE Visual Design Group", -- "Name[ka]": "KDE-ის ვიზუალური დიზაინის ჯგუფი", -- "Name[ko]": "KDE 시각 디자인 그룹", -- "Name[lt]": "KDE vaizdinio dizaino grupė", -- "Name[nl]": "KDE Visuele ontwerpgroep", -- "Name[nn]": "KDE Visual Design Group", -- "Name[pl]": "Grupa oprawy graficznej KDE", -- "Name[pt]": "Grupo de Desenho Visual do KDE", -- "Name[pt_BR]": "Grupo de Design Visual do KDE", -- "Name[ro]": "KDE Visual Design Group", -- "Name[ru]": "Группа KDE Visual Design", -- "Name[sk]": "KDE Visual Design Group", -- "Name[sl]": "Skupina vizualnega designa KDE", -- "Name[sv]": "KDE:s visuella designgrupp", -- "Name[ta]": "கே.டீ.யீ. வரைகலை வடிவமைப்புக் குழு", -- "Name[tr]": "KDE Görsel Tasarım Grubu", -- "Name[uk]": "Група з візуального дизайну KDE", -- "Name[vi]": "Đội Thiết kế Trực quan KDE", -- "Name[x-test]": "xxKDE Visual Design Groupxx", -- "Name[zh_CN]": "KDE 视觉设计团队" -- } -- ], -- "Category": "", -- "Description": "Breeze Dark by the KDE VDG", -- "Description[ar]": "نسيم داكن من من مجموعة تصميم كِيدِي", -- "Description[az]": "KDE VDG tərəfindən Breeze Qara", -- "Description[be]": "Breeze Dark ад KDE VDG", -- "Description[bg]": "Breeze Тъмен от KDE VDG", -- "Description[ca@valencia]": "Brisa fosca, creat pel VDG de KDE", -- "Description[ca]": "Brisa fosca, creat pel VDG del KDE", -- "Description[cs]": "Breeze Dark od KDE VDG", -- "Description[da]": "Breeze Dark af KDE's visuelle designgruppe", -- "Description[de]": "Breeze Dunkel von der KDE VDG", -- "Description[en_GB]": "Breeze Dark by the KDE VDG", -- "Description[es]": "Brisa oscuro por KDE VDG", -- "Description[et]": "Breeze tume KDE VDG-lt", -- "Description[eu]": "Breeze iluna KDEren VDGk egina", -- "Description[fi]": "Tumma Breeze KDE VDG:ltä", -- "Description[fr]": "Breeze sombre par le groupe de conception visuelle de KDE « VDG »", -- "Description[hi]": "केडीई वीडीजी द्वारा ब्रीज़ गहरा", -- "Description[hu]": "Breeze Dark a KDE VDG-től", -- "Description[ia]": "Breeze Dark (Brisa Obscure) per le KDE VDG", -- "Description[id]": "Breeze oleh KDE VDG", -- "Description[is]": "Breeze Dark frá KDE VDG", -- "Description[it]": "Brezza scuro del KDE VDG", -- "Description[ja]": "Breeze Dark by the KDE VDG", -- "Description[ka]": "Breeze Dark \"KDE VDG\"-სგან", -- "Description[ko]": "KDE 시각 디자인 그룹에서 제작한 어두운 Breeze", -- "Description[lt]": "Breeze tamsus pagal KDE VDG", -- "Description[nl]": "Breeze Dark door de KDE VDG", -- "Description[nn]": "Breeze mørk frå KDE VDG", -- "Description[pa]": "ਕੇਡੀਈ ਵੀਡੀਜੀ ਵਲੋਂ ਬਰੀਜ਼ ਗੂੜ੍ਹਾ", -- "Description[pl]": "Ciemna Bryza autorstwa KDE VDG", -- "Description[pt]": "Brisa Escuro da VDG do KDE", -- "Description[pt_BR]": "Breeze Dark pelo KDE VDG", -- "Description[ro]": "Briză, întunecat, de KDE VDG", -- "Description[ru]": "Тёмный вариант Breeze от KDE VDG", -- "Description[sk]": "Vánok Tmavý od KDE VDG", -- "Description[sl]": "Sapica temna avtorjev KDE VDG", -- "Description[sv]": "Breeze mörk av KDE:s visuella designgrupp", -- "Description[tr]": "KDE VDG'den Esinti Koyu", -- "Description[uk]": "Темна Breeze, автори — KDE VDG", -- "Description[vi]": "Breeze Tối, do KDE VDG", -- "Description[x-test]": "xxBreeze Dark by the KDE VDGxx", -- "Description[zh_CN]": "Breeze 微风深色主题,由 KDE VDG (视觉设计团队) 设计制作", -- "Description[zh_TW]": "由 KDE VDG 設計的 Breeze Dark", -- "Id": "org.kde.breezedark.desktop", -- "License": "GPLv2+", -- "Name": "Breeze Dark", -- "Name[ar]": "نسيم داكن", -- "Name[az]": "Breeze Qara", -- "Name[be]": "Breeze Dark", -- "Name[bg]": "Breeze Тъмен", -- "Name[ca@valencia]": "Brisa fosca", -- "Name[ca]": "Brisa fosca", -- "Name[cs]": "Breeze Tmavé", -- "Name[da]": "Breeze Dark", -- "Name[de]": "Breeze Dunkel", -- "Name[en_GB]": "Breeze Dark", -- "Name[es]": "Brisa oscuro", -- "Name[et]": "Breeze tume", -- "Name[eu]": "Breeze iluna", -- "Name[fi]": "Tumma Breeze", -- "Name[fr]": "Breeze sombre", -- "Name[hi]": "ब्रीज़ गहरा", -- "Name[hu]": "Breeze Dark", -- "Name[ia]": "Brisa obscure", -- "Name[id]": "Breeze Gelap", -- "Name[is]": "Breeze Dark", -- "Name[it]": "Brezza scuro", -- "Name[ja]": "Breeze Dark", -- "Name[ka]": "ნავი მუქი", -- "Name[ko]": "어두운 Breeze", -- "Name[lt]": "Breeze tamsus", -- "Name[nl]": "Breeze Dark", -- "Name[nn]": "Breeze mørk", -- "Name[pa]": "ਬਰੀਜ਼ ਗੂੜ੍ਹਾ", -- "Name[pl]": "Ciemna Bryza", -- "Name[pt]": "Brisa Escura", -- "Name[pt_BR]": "Breeze Dark", -- "Name[ro]": "Briză, întunecat", -- "Name[ru]": "Breeze, тёмный вариант", -- "Name[sk]": "Vánok Tmavý", -- "Name[sl]": "Sapica temna", -- "Name[sv]": "Breeze mörk", -- "Name[ta]": "கருப்பு பிரீஸ்", -- "Name[tg]": "Насими торик", -- "Name[tr]": "Esinti Koyu", -- "Name[uk]": "Темна Breeze", -- "Name[vi]": "Breeze Tối", -- "Name[x-test]": "xxBreeze Darkxx", -- "Name[zh_CN]": "Breeze 微风深色", -- "Name[zh_TW]": "Breeze Dark", -- "ServiceTypes": [ -- "Plasma/LookAndFeel" -- ], -- "Version": "2.0", -- "Website": "https://www.kde.org" -- }, -- "X-Plasma-MainScript": "defaults" --} -diff --git a/share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/defaults b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/defaults -similarity index 90% -rename from share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/defaults -rename to share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/defaults -index 3db126f..764fa66 100644 ---- a/share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/defaults -+++ b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/defaults -@@ -2,7 +2,7 @@ - widgetStyle=Breeze - - [kdeglobals][General] --ColorScheme=BreezeDark -+ColorScheme=BreezeDarkTint - - [kdeglobals][Icons] - Theme=breeze-dark -@@ -11,7 +11,7 @@ Theme=breeze-dark - name=default - - [Wallpaper] --Image=Next -+Image=MilkyWay - - [kcminputrc][Mouse] - cursorTheme=breeze_cursors -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/layouts/org.kde.plasma.desktop-layout.js b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/layouts/org.kde.plasma.desktop-layout.js -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/layouts/org.kde.plasma.desktop-layout.js -rename to share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/layouts/org.kde.plasma.desktop-layout.js -diff --git a/share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/previews/fullscreenpreview.jpg b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/previews/fullscreenpreview.jpg -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/previews/fullscreenpreview.jpg -rename to share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/previews/fullscreenpreview.jpg -diff --git a/share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/previews/preview.png b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/previews/preview.png -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/previews/preview.png -rename to share/plasma/look-and-feel/org.kde.breezedarktint.desktop/contents/previews/preview.png -diff --git a/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/metadata.json b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/metadata.json -new file mode 100644 -index 0000000..4103034 ---- /dev/null -+++ b/share/plasma/look-and-feel/org.kde.breezedarktint.desktop/metadata.json -@@ -0,0 +1,61 @@ -+{ -+ "KPlugin": { -+ "Authors": [ -+ { -+ "Email": "plasma-devel@kde.org", -+ "Name": "KDE Visual Design Group", -+ "Name[ar]": "مجموعة التصميم المرئي لكِيدِي", -+ "Name[az]": "KDE Vizual Dizayn Qrupu", -+ "Name[be]": "Суполка візуальнага дызайну KDE", -+ "Name[bg]": "KDE Visual Design Group", -+ "Name[ca@valencia]": "Grup de disseny visual de KDE", -+ "Name[ca]": "Grup de disseny visual de KDE", -+ "Name[cs]": "Skupina vizuálního návrhu KDE", -+ "Name[da]": "KDE Visual Design Group", -+ "Name[de]": "KDE Visual Design Group", -+ "Name[en_GB]": "KDE Visual Design Group", -+ "Name[es]": "El grupo de diseño visual de KDE", -+ "Name[eu]": "KDE Diseinu bisualeko taldea", -+ "Name[fi]": "KDE:n visuaalinen suunnitteluryhmä", -+ "Name[fr]": "Groupe de conception visuelle de KDE", -+ "Name[hi]": "केडीई विज़ुअल डिज़ाइन दल", -+ "Name[hu]": "KDE Visual Design Group", -+ "Name[ia]": "KDE Visual Design Group (Gruppo de Designo Visual de KDE)", -+ "Name[id]": "Grup Desain Visual KDE", -+ "Name[is]": "Myndrænn hönnunarhópur KDE", -+ "Name[it]": "KDE Visual Design Group", -+ "Name[ja]": "KDE Visual Design Group", -+ "Name[ka]": "KDE-ის ვიზუალური დიზაინის ჯგუფი", -+ "Name[ko]": "KDE 시각 디자인 그룹", -+ "Name[lt]": "KDE vaizdinio dizaino grupė", -+ "Name[nl]": "KDE Visuele ontwerpgroep", -+ "Name[nn]": "KDE Visual Design Group", -+ "Name[pl]": "Grupa oprawy graficznej KDE", -+ "Name[pt]": "Grupo de Desenho Visual do KDE", -+ "Name[pt_BR]": "Grupo de Design Visual do KDE", -+ "Name[ro]": "KDE Visual Design Group", -+ "Name[ru]": "Группа KDE Visual Design", -+ "Name[sk]": "KDE Visual Design Group", -+ "Name[sl]": "Skupina vizualnega designa KDE", -+ "Name[sv]": "KDE:s visuella designgrupp", -+ "Name[ta]": "கே.டீ.யீ. வரைகலை வடிவமைப்புக் குழு", -+ "Name[tr]": "KDE Görsel Tasarım Grubu", -+ "Name[uk]": "Група з візуального дизайну KDE", -+ "Name[vi]": "Đội Thiết kế Trực quan KDE", -+ "Name[x-test]": "xxKDE Visual Design Groupxx", -+ "Name[zh_CN]": "KDE 视觉设计团队" -+ } -+ ], -+ "Category": "", -+ "Description": "Breeze Dark (Tint) by the KDE VDG", -+ "Id": "org.kde.breezedarktint.desktop", -+ "License": "GPLv2+", -+ "Name": "Breeze Dark (Tint)", -+ "ServiceTypes": [ -+ "Plasma/LookAndFeel" -+ ], -+ "Version": "2.0", -+ "Website": "https://www.kde.org" -+ }, -+ "X-Plasma-MainScript": "defaults" -+} -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/ActionButton.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/ActionButton.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/ActionButton.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/ActionButton.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/Battery.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/Battery.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/Battery.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/Battery.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/Clock.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/Clock.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/Clock.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/Clock.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/SessionManagementScreen.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/SessionManagementScreen.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/SessionManagementScreen.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/SessionManagementScreen.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/UserDelegate.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/UserDelegate.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/UserDelegate.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/UserDelegate.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/UserList.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/UserList.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/UserList.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/UserList.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/VirtualKeyboard.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/VirtualKeyboard.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/VirtualKeyboard.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/VirtualKeyboard.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/VirtualKeyboard_wayland.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/VirtualKeyboard_wayland.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/VirtualKeyboard_wayland.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/VirtualKeyboard_wayland.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/WallpaperFader.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/WallpaperFader.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/WallpaperFader.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/WallpaperFader.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/animation/RejectPasswordAnimation.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/animation/RejectPasswordAnimation.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/animation/RejectPasswordAnimation.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/animation/RejectPasswordAnimation.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/animation/RejectPasswordPathAnimation.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/animation/RejectPasswordPathAnimation.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/animation/RejectPasswordPathAnimation.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/animation/RejectPasswordPathAnimation.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/README.txt b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/README.txt -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/README.txt -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/README.txt -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/logout_primary.svgz b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/logout_primary.svgz -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/logout_primary.svgz -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/logout_primary.svgz -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/restart_primary.svgz b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/restart_primary.svgz -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/restart_primary.svgz -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/restart_primary.svgz -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/shutdown_primary.svgz b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/shutdown_primary.svgz -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/components/artwork/shutdown_primary.svgz -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/components/artwork/shutdown_primary.svgz -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/defaults b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/defaults -similarity index 90% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/defaults -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/defaults -index d8df939..852c691 100644 ---- a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/defaults -+++ b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/defaults -@@ -2,7 +2,7 @@ - widgetStyle=Breeze - - [kdeglobals][General] --ColorScheme=BreezeLight -+ColorScheme=BreezeLightTint - - [kdeglobals][Icons] - Theme=breeze -@@ -11,7 +11,7 @@ Theme=breeze - name=default - - [Wallpaper] --Image=Next -+Image=MilkyWay - - [kcminputrc][Mouse] - cursorTheme=breeze_cursors -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/desktopswitcher/DesktopSwitcher.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/desktopswitcher/DesktopSwitcher.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/desktopswitcher/DesktopSwitcher.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/desktopswitcher/DesktopSwitcher.qml -diff --git a/share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/layouts/org.kde.plasma.desktop-layout.js b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/layouts/org.kde.plasma.desktop-layout.js -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breezedark.desktop/contents/layouts/org.kde.plasma.desktop-layout.js -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/layouts/org.kde.plasma.desktop-layout.js -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/LockOsd.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/LockOsd.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/LockOsd.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/LockOsd.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/LockScreen.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/LockScreen.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/LockScreen.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/LockScreen.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/LockScreenUi.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/LockScreenUi.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/LockScreenUi.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/LockScreenUi.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/MainBlock.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/MainBlock.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/MainBlock.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/MainBlock.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/MediaControls.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/MediaControls.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/MediaControls.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/MediaControls.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/NoPasswordUnlock.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/NoPasswordUnlock.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/NoPasswordUnlock.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/NoPasswordUnlock.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/config.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/config.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/config.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/config.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/config.xml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/config.xml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/lockscreen/config.xml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/lockscreen/config.xml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/logout/Logout.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/logout/Logout.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/logout/Logout.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/logout/Logout.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/logout/LogoutButton.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/logout/LogoutButton.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/logout/LogoutButton.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/logout/LogoutButton.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/logout/timer.js b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/logout/timer.js -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/logout/timer.js -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/logout/timer.js -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/osd/Osd.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/osd/Osd.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/osd/Osd.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/osd/Osd.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/osd/OsdItem.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/osd/OsdItem.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/osd/OsdItem.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/osd/OsdItem.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/desktopswitcher.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/desktopswitcher.png -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/desktopswitcher.png -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/desktopswitcher.png -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/fullscreenpreview.jpg b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/fullscreenpreview.jpg -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/fullscreenpreview.jpg -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/fullscreenpreview.jpg -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/lockscreen.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/lockscreen.png -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/lockscreen.png -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/lockscreen.png -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/loginmanager.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/loginmanager.png -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/loginmanager.png -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/loginmanager.png -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/preview.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/preview.png -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/preview.png -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/preview.png -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/runcommand.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/runcommand.png -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/runcommand.png -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/runcommand.png -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/splash.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/splash.png -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/splash.png -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/splash.png -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/userswitcher.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/userswitcher.png -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/userswitcher.png -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/userswitcher.png -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/windowdecoration.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/windowdecoration.png -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/windowdecoration.png -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/windowdecoration.png -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/windowswitcher.png b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/windowswitcher.png -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/previews/windowswitcher.png -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/previews/windowswitcher.png -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/Splash.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/Splash.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/Splash.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/Splash.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/images/busywidget.svgz b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/images/busywidget.svgz -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/images/busywidget.svgz -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/images/busywidget.svgz -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/images/kde.svgz b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/images/kde.svgz -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/images/kde.svgz -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/images/kde.svgz -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/images/plasma.svgz b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/images/plasma.svgz -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/splash/images/plasma.svgz -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/splash/images/plasma.svgz -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/systemdialog/SystemDialog.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/systemdialog/SystemDialog.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/systemdialog/SystemDialog.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/systemdialog/SystemDialog.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/contents/windowswitcher/WindowSwitcher.qml b/share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/windowswitcher/WindowSwitcher.qml -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/contents/windowswitcher/WindowSwitcher.qml -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/contents/windowswitcher/WindowSwitcher.qml -diff --git a/share/plasma/look-and-feel/org.kde.breeze.desktop/metadata.json b/share/plasma/look-and-feel/org.kde.breezetint.desktop/metadata.json -similarity index 72% -rename from share/plasma/look-and-feel/org.kde.breeze.desktop/metadata.json -rename to share/plasma/look-and-feel/org.kde.breezetint.desktop/metadata.json -index a6899c0..108c44e 100644 ---- a/share/plasma/look-and-feel/org.kde.breeze.desktop/metadata.json -+++ b/share/plasma/look-and-feel/org.kde.breezetint.desktop/metadata.json -@@ -47,106 +47,10 @@ - } - ], - "Category": "", -- "Description": "Breeze by the KDE VDG", -- "Description[ar]": "نسيم من مجموعة تصميم كِيدِي", -- "Description[az]": "KDE VDG tərəfindən Breeze İş mühiti görünüşü", -- "Description[be]": "Breeze ад KDE VDG", -- "Description[bg]": "Breeze от KDE VDG", -- "Description[ca@valencia]": "Brisa, creat pel VDG de KDE", -- "Description[ca]": "Brisa, creat pel VDG del KDE", -- "Description[cs]": "Breeze od KDE VDG", -- "Description[da]": "Breeze af KDE's visuelle designgruppe", -- "Description[de]": "Breeze von der KDE VDG", -- "Description[en_GB]": "Breeze by the KDE VDG", -- "Description[es]": "Brisa por KDE VDG", -- "Description[et]": "Breeze KDE VDG-lt", -- "Description[eu]": "Breeze KDEren VDGk egina", -- "Description[fi]": "Breeze KDE VDG:ltä", -- "Description[fr]": "Breeze, par KDE VDG", -- "Description[hi]": "केडीई वीडीजी द्वारा ब्रीज़", -- "Description[hu]": "Breeze a KDE VDG-től", -- "Description[ia]": "Breeze (Brisa) per le KDE VDG", -- "Description[id]": "Breeze oleh KDE VDG", -- "Description[is]": "Breeze frá KDE VDG", -- "Description[it]": "Brezza del KDE VDG", -- "Description[ja]": "Breeze by the KDE VDG", -- "Description[ka]": "Breeze KDE VDG-სგან", -- "Description[ko]": "KDE 시각 디자인 그룹에서 제작한 Breeze", -- "Description[lt]": "Breeze pagal KDE VDG", -- "Description[nl]": "Breeze door de KDE VDG", -- "Description[nn]": "Breeze frå KDE VDG", -- "Description[pa]": "KDE VDG ਵਲੋਂ ਬਰੀਜ਼", -- "Description[pl]": "Bryza autorstwa KDE VDG", -- "Description[pt]": "Brisa da VDG do KDE", -- "Description[pt_BR]": "Breeze pelo KDE VDG", -- "Description[ro]": "Briză, de KDE VDG", -- "Description[ru]": "Оформление рабочей среды Breeze от KDE VDG", -- "Description[sk]": "Vánok od KDE VDG", -- "Description[sl]": "Sapica avtorjev KDE VDG", -- "Description[sv]": "Breeze av KDE:s visuella designgrupp", -- "Description[tr]": "KDE VDG'den Esinti", -- "Description[uk]": "Breeze, автори — KDE VDG", -- "Description[vi]": "Breeze, do KDE VDG", -- "Description[x-test]": "xxBreeze by the KDE VDGxx", -- "Description[zh_CN]": "Breeze 微风主题,由 KDE VDG (视觉设计团队) 设计制作", -- "Description[zh_TW]": "由 KDE VDG 設計的 Breeze", -- "Id": "org.kde.breeze.desktop", -+ "Description": "Breeze (Tint) by the KDE VDG", -+ "Id": "org.kde.breezetint.desktop", - "License": "GPLv2+", -- "Name": "Breeze", -- "Name[ar]": "نسيم", -- "Name[az]": "Breeze", -- "Name[be]": "Breeze", -- "Name[bg]": "Breeze", -- "Name[bs]": "Breeze", -- "Name[ca@valencia]": "Brisa", -- "Name[ca]": "Brisa", -- "Name[cs]": "Breeze", -- "Name[da]": "Breeze", -- "Name[de]": "Breeze", -- "Name[el]": "Breeze", -- "Name[en_GB]": "Breeze", -- "Name[es]": "Brisa", -- "Name[et]": "Breeze", -- "Name[eu]": "Breeze", -- "Name[fi]": "Breeze", -- "Name[fr]": "Breeze", -- "Name[gl]": "Breeze", -- "Name[hi]": "ब्रीज़", -- "Name[hu]": "Breeze", -- "Name[ia]": "Brisa", -- "Name[id]": "Breeze", -- "Name[is]": "Breeze", -- "Name[it]": "Brezza", -- "Name[ja]": "Breeze", -- "Name[ka]": "ნიავი", -- "Name[ko]": "Breeze", -- "Name[lt]": "Breeze", -- "Name[ml]": "ബ്രീസ്", -- "Name[nb]": "Breeze", -- "Name[nds]": "Breeze", -- "Name[nl]": "Breeze", -- "Name[nn]": "Breeze", -- "Name[pa]": "ਬਰੀਜ਼", -- "Name[pl]": "Bryza", -- "Name[pt]": "Brisa", -- "Name[pt_BR]": "Breeze", -- "Name[ro]": "Briză", -- "Name[ru]": "Breeze", -- "Name[sk]": "Vánok", -- "Name[sl]": "Sapica", -- "Name[sr@ijekavian]": "Поветарац", -- "Name[sr@ijekavianlatin]": "Povetarac", -- "Name[sr@latin]": "Povetarac", -- "Name[sr]": "Поветарац", -- "Name[sv]": "Breeze", -- "Name[ta]": "பிரீஸ்", -- "Name[tg]": "Насим", -- "Name[tr]": "Esinti", -- "Name[uk]": "Breeze", -- "Name[vi]": "Breeze", -- "Name[x-test]": "xxBreezexx", -- "Name[zh_CN]": "Breeze 微风", -- "Name[zh_TW]": "微風", -+ "Name": "Breeze (Tint)", - "ServiceTypes": [ - "Plasma/LookAndFeel" - ], -diff --git a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/metadata.json b/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/metadata.json -deleted file mode 100644 -index 16dec51..0000000 ---- a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/metadata.json -+++ /dev/null -@@ -1,145 +0,0 @@ --{ -- "KPlugin": { -- "Authors": [ -- { -- "Email": "plasma-devel@kde.org", -- "Name": "KDE Visual Design Group", -- "Name[ar]": "مجموعة التصميم المرئي لكِيدِي", -- "Name[az]": "KDE Vizual Dizayn Qrupu", -- "Name[be]": "Суполка візуальнага дызайну KDE", -- "Name[bg]": "KDE Visual Design Group", -- "Name[ca@valencia]": "Grup de disseny visual de KDE", -- "Name[ca]": "Grup de disseny visual de KDE", -- "Name[cs]": "Skupina vizuálního návrhu KDE", -- "Name[da]": "KDE Visual Design Group", -- "Name[de]": "KDE Visual Design Group", -- "Name[en_GB]": "KDE Visual Design Group", -- "Name[es]": "El grupo de diseño visual de KDE", -- "Name[eu]": "KDE Diseinu bisualeko taldea", -- "Name[fi]": "KDE:n visuaalinen suunnitteluryhmä", -- "Name[fr]": "Groupe de conception visuelle de KDE", -- "Name[hi]": "केडीई विज़ुअल डिज़ाइन दल", -- "Name[hu]": "KDE Visual Design Group", -- "Name[ia]": "KDE Visual Design Group (Gruppo de Designo Visual de KDE)", -- "Name[id]": "Grup Desain Visual KDE", -- "Name[is]": "Myndrænn hönnunarhópur KDE", -- "Name[it]": "KDE Visual Design Group", -- "Name[ja]": "KDE Visual Design Group", -- "Name[ka]": "KDE-ის ვიზუალური დიზაინის ჯგუფი", -- "Name[ko]": "KDE 시각 디자인 그룹", -- "Name[lt]": "KDE vaizdinio dizaino grupė", -- "Name[nl]": "KDE Visuele ontwerpgroep", -- "Name[nn]": "KDE Visual Design Group", -- "Name[pl]": "Grupa oprawy graficznej KDE", -- "Name[pt]": "Grupo de Desenho Visual do KDE", -- "Name[pt_BR]": "Grupo de Design Visual do KDE", -- "Name[ro]": "KDE Visual Design Group", -- "Name[ru]": "Группа KDE Visual Design", -- "Name[sk]": "KDE Visual Design Group", -- "Name[sl]": "Skupina vizualnega designa KDE", -- "Name[sv]": "KDE:s visuella designgrupp", -- "Name[ta]": "கே.டீ.யீ. வரைகலை வடிவமைப்புக் குழு", -- "Name[tr]": "KDE Görsel Tasarım Grubu", -- "Name[uk]": "Група з візуального дизайну KDE", -- "Name[vi]": "Đội Thiết kế Trực quan KDE", -- "Name[x-test]": "xxKDE Visual Design Groupxx", -- "Name[zh_CN]": "KDE 视觉设计团队" -- } -- ], -- "Category": "", -- "Description": "Breeze Twilight by the KDE VDG", -- "Description[ar]": "نسيم الفجر من مجموعة تصميم كِيدِي", -- "Description[az]": "KDE VDG tərəfindən Breeze Toranlıq", -- "Description[be]": "Breeze Twilight ад KDE VDG", -- "Description[bg]": "Breeze Здрач от KDE VDG", -- "Description[ca@valencia]": "Brisa crepuscular, creat pel VDG de KDE", -- "Description[ca]": "Brisa crepuscular, creat pel VDG del KDE", -- "Description[cs]": "Breeze Twilight od KDE VDG", -- "Description[da]": "Breeze Twilight af KDE VDG", -- "Description[de]": "Breeze Dämmerung von der KDE VG", -- "Description[en_GB]": "Breeze Twilight by the KDE VDG", -- "Description[es]": "Brisa crepúsculo por KDE VDG", -- "Description[et]": "Breeze videvik KDE VDG-lt", -- "Description[eu]": "Breeze ilunabarra KDEren VDGk egina", -- "Description[fi]": "Hämärä Breeze KDE VDG:ltä", -- "Description[fr]": "Breeze clair-obscur par l'équipe de conception visuelle de KDE « VDG »", -- "Description[hi]": "केडीई वीडीजी द्वारा ब्रीज़ गोधूली", -- "Description[hu]": "Breeze Twilight a KDE VDG-től", -- "Description[ia]": "Brisa Crepusculo (Breeze Twilight) per KDE VDG", -- "Description[id]": "Breeze Twilight oleh KDE VDG", -- "Description[is]": "Breeze Twilight frá KDE VDG", -- "Description[it]": "Brezza crepuscolo del VDG di KDE", -- "Description[ja]": "Breeze Twilight by the KDE VDG", -- "Description[ka]": "Breeze Twilight-ი KDE VDG-ის მიერ", -- "Description[ko]": "KDE 시각 디자인 그룹에서 제작한 새벽의 Breeze", -- "Description[lt]": "Breeze prieblanda pagal KDE VDG", -- "Description[nl]": "Breeze Twilight door de KDE VDG", -- "Description[nn]": "Breeze skumring frå KDE VDG", -- "Description[pl]": "Półmroczna bryza autorstwa KDE VDG", -- "Description[pt]": "Brisa ao Anoitecer da VDG do KDE", -- "Description[pt_BR]": "Breeze Twilight pelo KDE VDG", -- "Description[ro]": "Briză, amurg, de KDE VDG", -- "Description[ru]": "Оформление рабочей среды Breeze Twilight от KDE VDG", -- "Description[sk]": "Vánok Súmrak od KDE VDG", -- "Description[sl]": "Sapica ob mraku avtorjev KDE VDG", -- "Description[sv]": "Breeze skymning av KDE:s visuella designgrupp", -- "Description[tr]": "KDE VDG'den Esinti Gündoğumu", -- "Description[uk]": "Сутінкова Breeze, автори — KDE VDG", -- "Description[vi]": "Breeze Chạng vạng, do KDE VDG", -- "Description[x-test]": "xxBreeze Twilight by the KDE VDGxx", -- "Description[zh_CN]": "Breeze 微风阴阳主题,由 KDE VDG (视觉设计团队) 设计制作", -- "Description[zh_TW]": "由 KDE VDG 設計的 Breeze Twilight", -- "Id": "org.kde.breezetwilight.desktop", -- "License": "GPLv2+", -- "Name": "Breeze Twilight", -- "Name[ar]": "نسيم الفجر", -- "Name[az]": "Breeze Toranlıq", -- "Name[be]": "Breeze Twilight", -- "Name[bg]": "Breeze Здрач", -- "Name[ca@valencia]": "Brisa crepuscular", -- "Name[ca]": "Brisa crepuscular", -- "Name[cs]": "Breeze Twilight", -- "Name[da]": "Breeze Twilight", -- "Name[de]": "Breeze Dämmerung", -- "Name[en_GB]": "Breeze Twilight", -- "Name[es]": "Brisa crepúsculo", -- "Name[et]": "Breeze videvik", -- "Name[eu]": "Breeze ilunabarra", -- "Name[fi]": "Hämärä Breeze", -- "Name[fr]": "Breeze clair-obscur ", -- "Name[hi]": "ब्रीज़ गोधूली", -- "Name[hu]": "Breeze Twilight", -- "Name[ia]": "Brisa Crepusculo (Breeze Twilight)", -- "Name[id]": "Breeze Twilight", -- "Name[is]": "Breeze Twilight", -- "Name[it]": "Brezza crepuscolo", -- "Name[ja]": "Breeze Twilight", -- "Name[ka]": "ნიავი ღია", -- "Name[ko]": "새벽의 Breeze", -- "Name[lt]": "Breeze prieblanda", -- "Name[nl]": "Breeze Twilight", -- "Name[nn]": "Breeze skumring", -- "Name[pa]": "ਬਰੀਜ਼ ਆਥਣ", -- "Name[pl]": "Półmroczna bryza", -- "Name[pt]": "Brisa ao Anoitecer", -- "Name[pt_BR]": "Breeze Twilight", -- "Name[ro]": "Briză, amurg", -- "Name[ru]": "Breeze Twilight", -- "Name[sk]": "Vánok Súmrak", -- "Name[sl]": "Sapica ob mraku", -- "Name[sv]": "Breeze skymning", -- "Name[ta]": "கலந்த பிரீஸ்", -- "Name[tg]": "Насими нимторикӣ", -- "Name[tr]": "Esinti Gündoğumu", -- "Name[uk]": "Сутінкова Breeze", -- "Name[vi]": "Breeze Chạng vạng", -- "Name[x-test]": "xxBreeze Twilightxx", -- "Name[zh_CN]": "Breeze 微风阴阳", -- "ServiceTypes": [ -- "Plasma/LookAndFeel" -- ], -- "Version": "2.0", -- "Website": "https://www.kde.org" -- }, -- "X-Plasma-MainScript": "defaults" --} -diff --git a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/defaults b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/defaults -similarity index 90% -rename from share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/defaults -rename to share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/defaults -index 02bc445..8537d4b 100644 ---- a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/defaults -+++ b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/defaults -@@ -2,7 +2,7 @@ - widgetStyle=Breeze - - [kdeglobals][General] --ColorScheme=BreezeLight -+ColorScheme=BreezeLightTint - - [kdeglobals][Icons] - Theme=breeze -@@ -11,7 +11,7 @@ Theme=breeze - name=breeze-dark - - [Wallpaper] --Image=Next -+Image=MilkyWay - - [kcminputrc][Mouse] - cursorTheme=breeze_cursors -diff --git a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/layouts/org.kde.plasma.desktop-layout.js b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/layouts/org.kde.plasma.desktop-layout.js -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/layouts/org.kde.plasma.desktop-layout.js -rename to share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/layouts/org.kde.plasma.desktop-layout.js -diff --git a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/previews/fullscreenpreview.jpg b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/previews/fullscreenpreview.jpg -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/previews/fullscreenpreview.jpg -rename to share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/previews/fullscreenpreview.jpg -diff --git a/share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/previews/preview.png b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/previews/preview.png -similarity index 100% -rename from share/plasma/look-and-feel/org.kde.breezetwilight.desktop/contents/previews/preview.png -rename to share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/contents/previews/preview.png -diff --git a/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/metadata.json b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/metadata.json -new file mode 100644 -index 0000000..405d0fd ---- /dev/null -+++ b/share/plasma/look-and-feel/org.kde.breezetwilighttint.desktop/metadata.json -@@ -0,0 +1,61 @@ -+{ -+ "KPlugin": { -+ "Authors": [ -+ { -+ "Email": "plasma-devel@kde.org", -+ "Name": "KDE Visual Design Group", -+ "Name[ar]": "مجموعة التصميم المرئي لكِيدِي", -+ "Name[az]": "KDE Vizual Dizayn Qrupu", -+ "Name[be]": "Суполка візуальнага дызайну KDE", -+ "Name[bg]": "KDE Visual Design Group", -+ "Name[ca@valencia]": "Grup de disseny visual de KDE", -+ "Name[ca]": "Grup de disseny visual de KDE", -+ "Name[cs]": "Skupina vizuálního návrhu KDE", -+ "Name[da]": "KDE Visual Design Group", -+ "Name[de]": "KDE Visual Design Group", -+ "Name[en_GB]": "KDE Visual Design Group", -+ "Name[es]": "El grupo de diseño visual de KDE", -+ "Name[eu]": "KDE Diseinu bisualeko taldea", -+ "Name[fi]": "KDE:n visuaalinen suunnitteluryhmä", -+ "Name[fr]": "Groupe de conception visuelle de KDE", -+ "Name[hi]": "केडीई विज़ुअल डिज़ाइन दल", -+ "Name[hu]": "KDE Visual Design Group", -+ "Name[ia]": "KDE Visual Design Group (Gruppo de Designo Visual de KDE)", -+ "Name[id]": "Grup Desain Visual KDE", -+ "Name[is]": "Myndrænn hönnunarhópur KDE", -+ "Name[it]": "KDE Visual Design Group", -+ "Name[ja]": "KDE Visual Design Group", -+ "Name[ka]": "KDE-ის ვიზუალური დიზაინის ჯგუფი", -+ "Name[ko]": "KDE 시각 디자인 그룹", -+ "Name[lt]": "KDE vaizdinio dizaino grupė", -+ "Name[nl]": "KDE Visuele ontwerpgroep", -+ "Name[nn]": "KDE Visual Design Group", -+ "Name[pl]": "Grupa oprawy graficznej KDE", -+ "Name[pt]": "Grupo de Desenho Visual do KDE", -+ "Name[pt_BR]": "Grupo de Design Visual do KDE", -+ "Name[ro]": "KDE Visual Design Group", -+ "Name[ru]": "Группа KDE Visual Design", -+ "Name[sk]": "KDE Visual Design Group", -+ "Name[sl]": "Skupina vizualnega designa KDE", -+ "Name[sv]": "KDE:s visuella designgrupp", -+ "Name[ta]": "கே.டீ.யீ. வரைகலை வடிவமைப்புக் குழு", -+ "Name[tr]": "KDE Görsel Tasarım Grubu", -+ "Name[uk]": "Група з візуального дизайну KDE", -+ "Name[vi]": "Đội Thiết kế Trực quan KDE", -+ "Name[x-test]": "xxKDE Visual Design Groupxx", -+ "Name[zh_CN]": "KDE 视觉设计团队" -+ } -+ ], -+ "Category": "", -+ "Description": "Breeze Twilight (Tint) by the KDE VDG", -+ "Id": "org.kde.breezetwilighttint.desktop", -+ "License": "GPLv2+", -+ "Name": "Breeze Twilight (Tint)", -+ "ServiceTypes": [ -+ "Plasma/LookAndFeel" -+ ], -+ "Version": "2.0", -+ "Website": "https://www.kde.org" -+ }, -+ "X-Plasma-MainScript": "defaults" -+} diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index a9323d7..e02d760 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -52,13 +52,14 @@ let }; lookAndFeel = pkgs.stdenv.mkDerivation { name = "toast-look-and-feel"; - src = "${pkgs.plasma-workspace}"; - patches = [ ./patches/TintedLookAndFeel.patch ]; + src = ./look-and-feel; + #postUnpack = "ls -la && uiagysduiags"; + #patches = [ ./patches/TintedLookAndFeel.patch ]; installPhase = '' runHook preInstall mkdir -p $out/share/plasma/look-and-feel/ - cp -r share/plasma/look-and-feel/* $out/share/plasma/look-and-feel/ + cp -r xyz.toast003.customtheme.desktop $out/share/plasma/look-and-feel/ runHook postInstall ''; From ed1d2f3830efc7c2cb346fb4ce9c9b1e053c64ca Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 00:45:39 +0200 Subject: [PATCH 0105/1125] Kde: remove leftover comments --- roles/kde/plasma.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index e02d760..4cf16ee 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -53,8 +53,6 @@ let lookAndFeel = pkgs.stdenv.mkDerivation { name = "toast-look-and-feel"; src = ./look-and-feel; - #postUnpack = "ls -la && uiagysduiags"; - #patches = [ ./patches/TintedLookAndFeel.patch ]; installPhase = '' runHook preInstall From 7d80cffd7f43f13d8e4ba841c8d190d2ce6e1d09 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 12:40:47 +0200 Subject: [PATCH 0106/1125] Nix-index: install using NixOS module --- roles/common/programs/nix-index.nix | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/roles/common/programs/nix-index.nix b/roles/common/programs/nix-index.nix index 93e88d4..492f770 100755 --- a/roles/common/programs/nix-index.nix +++ b/roles/common/programs/nix-index.nix @@ -1,8 +1,15 @@ -{ config, pkgs, ... }: +{ config, ... }: { - environment.systemPackages = [ pkgs.nix-index ]; + /* environment.systemPackages = [ pkgs.nix-index ]; programs.bash.interactiveShellInit = '' source ${pkgs.nix-index}/etc/profile.d/command-not-found.sh - ''; + ''; */ + programs.nix-index = { + enable = true; + enableBashIntegration = true; + # I don't use zsh or fish (yet) + enableZshIntegration = false; + enableFishIntegration = false; + }; } From c85c03a55e6deeea20ee8cf19498acda2503e5e7 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 12:48:32 +0200 Subject: [PATCH 0107/1125] Nix-index: add prebuild database --- flake.lock | 42 ++++++++++++++++++++++++++++++++++++++++++ flake.nix | 19 ++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index 0468085..4f07cef 100644 --- a/flake.lock +++ b/flake.lock @@ -99,6 +99,46 @@ "type": "github" } }, + "nix-index-db": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1693107069, + "narHash": "sha256-5dVXPchyvzmytanlwXHcmeQP9AfO/98Q6V+QtsMl5vQ=", + "owner": "Mic92", + "repo": "nix-index-database", + "rev": "53d40cf1bea235658ef8f6e8b8a1d033e2ecbfff", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "nix-index-database", + "type": "github" + } + }, + "nix-index-db-unstable": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1693107069, + "narHash": "sha256-5dVXPchyvzmytanlwXHcmeQP9AfO/98Q6V+QtsMl5vQ=", + "owner": "Mic92", + "repo": "nix-index-database", + "rev": "53d40cf1bea235658ef8f6e8b8a1d033e2ecbfff", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "nix-index-database", + "type": "github" + } + }, "nixos-hardware": { "locked": { "lastModified": 1692952286, @@ -151,6 +191,8 @@ "home-manager": "home-manager_2", "home-manager-unstable": "home-manager-unstable", "nix-impermanence": "nix-impermanence", + "nix-index-db": "nix-index-db", + "nix-index-db-unstable": "nix-index-db-unstable", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", "nixpkgs-unstable": "nixpkgs-unstable" diff --git a/flake.nix b/flake.nix index b6b1ad4..ae8edc7 100755 --- a/flake.nix +++ b/flake.nix @@ -26,9 +26,23 @@ inputs = { nixos-hardware.url = "github:NixOS/nixos-hardware/master"; nix-impermanence.url = "github:nix-community/impermanence"; + + /* + These are the same input, just following different nixpkgs versions + This avoids some wierdness when using one that follows unstable on a stable nixpkgs + */ + nix-index-db = { + url = "github:Mic92/nix-index-database"; + inputs.nixpkgs.follows = "nixpkgs"; }; -outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, ... } @inputs: { + nix-index-db-unstable = { + url = "github:Mic92/nix-index-database"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; +}; + +outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, nix-index-db, nix-index-db-unstable, ... } @inputs: { devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { name = "Environment for toast's nixos configurations"; @@ -60,6 +74,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } agenix.nixosModules.default home-manager-unstable.nixosModule + nix-index-db-unstable.nixosModules.nix-index ./roles/common ./roles/desktop ./roles/kde @@ -77,6 +92,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl agenix.nixosModules.default home-manager.nixosModule nixos-hardware.nixosModules.microsoft-surface-go + nix-index-db.nixosModules.nix-index ./roles/common ./roles/desktop ./roles/kde @@ -92,6 +108,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } agenix.nixosModules.default home-manager.nixosModule + nix-index-db.nixosModules.nix-index ./roles/common ./roles/server ./machines/Everest From efafd187d940ef99443125ebb78434d086a570cd Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 13:09:52 +0200 Subject: [PATCH 0108/1125] Common: enable and configure comma --- roles/common/programs/comma.nix | 8 ++++++++ roles/common/programs/default.nix | 1 + 2 files changed, 9 insertions(+) create mode 100644 roles/common/programs/comma.nix diff --git a/roles/common/programs/comma.nix b/roles/common/programs/comma.nix new file mode 100644 index 0000000..3c3f07b --- /dev/null +++ b/roles/common/programs/comma.nix @@ -0,0 +1,8 @@ +{ config, pkgs, ... }: + +{ + # Use nix-index-database's comma wrapper + programs.nix-index-database.comma.enable = true; + # Run programs from the system's nixpkgs + environment.variables = { COMMA_NIXPKGS_FLAKE="system"; }; +} diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index e3aaa87..83991eb 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -7,6 +7,7 @@ ./micro.nix ./nix-index.nix ./command-not-found.nix + ./comma.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ From 329ac39050c06937509acf213dcb47aed8086728 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 17:18:47 +0200 Subject: [PATCH 0109/1125] Server: add traefik --- roles/server/default.nix | 1 + roles/server/traefik.nix | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 roles/server/traefik.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index d5a0970..e75390f 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -14,5 +14,6 @@ ./beep.nix ./wireguard.nix ./tailscale.nix + ./traefik.nix ]; } diff --git a/roles/server/traefik.nix b/roles/server/traefik.nix new file mode 100644 index 0000000..c2b9442 --- /dev/null +++ b/roles/server/traefik.nix @@ -0,0 +1,16 @@ +{ config, ... }: + +{ + services.traefik = { + enable = true; + staticConfigOptions = { + # Enable the web ui + api.insecure = true; + api.dashboard = true; + entryPoints = { + http = { address = ":80"; }; + }; + }; + }; + networking.firewall.allowedTCPPorts = [ 80 8080 ]; +} From 6f7941aa74aee177e23ffa1bd295e493441cfdf4 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 17:19:40 +0200 Subject: [PATCH 0110/1125] Gitea: use traefik as reverse proxy --- roles/server/gitea.nix | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/roles/server/gitea.nix b/roles/server/gitea.nix index 40c8cb9..6cbac30 100644 --- a/roles/server/gitea.nix +++ b/roles/server/gitea.nix @@ -9,11 +9,32 @@ server = { #server.SSH_PORT = 69; DISABLE_REGISTRATION = lib.mkDefault true; - ROOT_URL = "http://everest.local:3000"; + ROOT_URL = "http://everest/gitea/"; }; }; }; - networking.firewall = { - allowedTCPPorts = [ 3000 ]; + # Set up traefik as the reverse proxy for Gitea + services.traefik = { + dynamicConfigOptions = { + http = { + routers = { + /* + Gitea works best as a subdomain, but I do not have a dns server (yet), + and since tailscale doesn't support adding subdomains with MagicDNS I'll + just put it in a subpath for now + */ + gitea-subpath = { + middlewares = [ "gitea-strip-prefix" ]; + rule = "PathPrefix(`/gitea`)"; + service = "gitea"; + }; + }; + services.gitea.loadBalancer.servers = [ + { url = "http://localhost:${toString config.services.gitea.settings.server.HTTP_PORT}"; } + ]; + # Gitea freaks out if you don't remove the subpath it's being proxied from + middlewares.gitea-strip-prefix.stripprefix.prefixes = "/gitea"; + }; + }; }; } From aeb1b8c376431bba47683f760ffdf9af28715b99 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 18:42:39 +0200 Subject: [PATCH 0111/1125] Transmission: use traefik as reverse proxy --- roles/server/transmission.nix | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/roles/server/transmission.nix b/roles/server/transmission.nix index 4f60c0d..767981e 100755 --- a/roles/server/transmission.nix +++ b/roles/server/transmission.nix @@ -4,11 +4,28 @@ services.transmission = { enable = true; openFirewall = true; - openRPCPort = true; settings = { incomplete-dir-enabled = false; rpc-bind-address = "0.0.0.0"; - rpc-whitelist = "127.0.0.1,192.168.0.16*"; + rpc-host-whitelist = "everest"; + rpc-whitelist = "127.0.0.1"; }; }; -} \ No newline at end of file + + # Set up traefik as the reverse proxy for transmission + services.traefik = { + dynamicConfigOptions = { + http = { + routers = { + transmission-subpath = { + rule = "PathPrefix(`/transmission`)"; + service = "transmission"; + }; + }; + services.transmission.loadBalancer.servers = [ + { url = "http://localhost:${toString config.services.transmission.settings.rpc-port}"; } + ]; + }; + }; + }; +} From a0b5740029096d81fbc1a7ee0195cd8e9bd42fb5 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 20:47:39 +0200 Subject: [PATCH 0112/1125] Server: chage archie's syncthing key --- roles/server/syncthing.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 9795e87..5bde1f7 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -17,8 +17,8 @@ }; "pc" = { name = "Archie"; - id = "MGMYYA2-4PXGHHH-2LOVD5N-I7IYBBS-4Y4UQNK-H73S2JG-ZCK5GCN-NHTWMAR"; - addresses = [ "tcp://archie.local:22000" "tcp://192.168.0.160:22000"]; + id = "NJPX754-64AQNP3-7GZFIRZ-W2EDRJQ-27ORWYM-X5YXEXQ-ERRTRTQ-BSYD4AY"; + addresses = [ "tcp://archie.local:22000" "tcp://192.168.0.161:22000"]; }; "steamdeck" = { name = "Steam Deck"; From b02aef6546218ca3ccae53fcd2a3566f98f99709 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 21:25:15 +0200 Subject: [PATCH 0113/1125] Syncthing: move common devices and folders into common role --- roles/common/services/default.nix | 1 + roles/common/services/syncthing.nix | 28 ++++++++++++++++++++++++++++ roles/server/syncthing.nix | 18 ------------------ 3 files changed, 29 insertions(+), 18 deletions(-) create mode 100755 roles/common/services/syncthing.nix diff --git a/roles/common/services/default.nix b/roles/common/services/default.nix index 38fca78..a045e1c 100644 --- a/roles/common/services/default.nix +++ b/roles/common/services/default.nix @@ -4,5 +4,6 @@ imports = [ ./avahi.nix ./tailscale.nix + ./syncthing.nix ]; } diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix new file mode 100755 index 0000000..551063a --- /dev/null +++ b/roles/common/services/syncthing.nix @@ -0,0 +1,28 @@ +{ config, ... }: + +{ + # Set up devices and folders common to every device + services.syncthing = { + devices = { + "phone" = { + name = "Xiaomi Redmi Note 10 Pro"; + id = "K7KNZ5V-XREUADL-CROQXPV-6AA4H65-2VUD34Z-VQWKJ6S-LWWW4EE-XPNEZQ6"; + }; + "pc" = { + name = "Archie"; + id = "NJPX754-64AQNP3-7GZFIRZ-W2EDRJQ-27ORWYM-X5YXEXQ-ERRTRTQ-BSYD4AY"; + }; + "steamdeck" = { + name = "Steam Deck"; + id = "DLQPL74-KEQTPM5-X4PDZHB-4HLQYHV-UCMJLOB-P6W3KWU-QLJADBY-V4KEMA5"; + }; + }; + folders = { + "passwords" = { + label = "KeePassXC Passwords"; + id = "rdyaq-ex659"; + devices = [ "phone" "pc" "steamdeck"]; + }; + }; + }; +} diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 5bde1f7..c8c5049 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -10,27 +10,9 @@ key = config.age.secrets.syncthingKey.path; cert = config.age.secrets.syncthingCert.path; guiAddress = "0.0.0.0:8384"; - devices = { - "phone" = { - id = "K7KNZ5V-XREUADL-CROQXPV-6AA4H65-2VUD34Z-VQWKJ6S-LWWW4EE-XPNEZQ6"; - name = "Xiaomi Redmi Note 10 Pro"; - }; - "pc" = { - name = "Archie"; - id = "NJPX754-64AQNP3-7GZFIRZ-W2EDRJQ-27ORWYM-X5YXEXQ-ERRTRTQ-BSYD4AY"; - addresses = [ "tcp://archie.local:22000" "tcp://192.168.0.161:22000"]; - }; - "steamdeck" = { - name = "Steam Deck"; - id = "DLQPL74-KEQTPM5-X4PDZHB-4HLQYHV-UCMJLOB-P6W3KWU-QLJADBY-V4KEMA5"; - }; - }; folders = { "passwords" = { - label = "KeePassXC Passwords"; - id = "rdyaq-ex659"; path = "${config.services.syncthing.dataDir}/passwords"; - devices = [ "phone" "pc" "steamdeck"]; }; }; }; From 3fc4d0bf809ced79313d462937c5c4a86229d46d Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 21:42:52 +0200 Subject: [PATCH 0114/1125] Everest: remove redundant firewall config --- machines/Everest/configuration.nix | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index fd2f6de..1d88a68 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -59,10 +59,9 @@ }; # Open ports in the firewall. - # 8384 is syncthing's webui, and 22000 is syncthing related too - # No idea what 5201 and 21027 do tho - networking.firewall.allowedTCPPorts = [ 5201 8384 22000 ]; - networking.firewall.allowedUDPPorts = [ 5201 22000 21027]; + # No idea what ports 5201 and 21027 do tho + networking.firewall.allowedTCPPorts = [ 5201 ]; + networking.firewall.allowedUDPPorts = [ 5201 21027]; # Or disable the firewall altogether. # networking.firewall.enable = false; } From 559121da211f004e1451b234db2f2f589d458618 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 22:13:44 +0200 Subject: [PATCH 0115/1125] Desktop: configure syncthing --- roles/desktop/services/default.nix | 1 + roles/desktop/services/syncthing.nix | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 roles/desktop/services/syncthing.nix diff --git a/roles/desktop/services/default.nix b/roles/desktop/services/default.nix index 19921e3..6393486 100644 --- a/roles/desktop/services/default.nix +++ b/roles/desktop/services/default.nix @@ -4,5 +4,6 @@ imports = [ ./ssh-agent.nix ./flatpak.nix + ./syncthing.nix ]; } diff --git a/roles/desktop/services/syncthing.nix b/roles/desktop/services/syncthing.nix new file mode 100644 index 0000000..b6b09bf --- /dev/null +++ b/roles/desktop/services/syncthing.nix @@ -0,0 +1,10 @@ +{ config, ... }: + +{ + services.syncthing = { + enable = true; + user = "toast"; + group = "users"; + dataDir = config.users.users.toast.home; + }; +} From 052d072ea55d7bf21d5cf9d46c0f3d29b39f99a0 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 22:15:01 +0200 Subject: [PATCH 0116/1125] Syncthing: change path of passwords folder on desktop role --- roles/desktop/services/syncthing.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/services/syncthing.nix b/roles/desktop/services/syncthing.nix index b6b09bf..728dd0e 100644 --- a/roles/desktop/services/syncthing.nix +++ b/roles/desktop/services/syncthing.nix @@ -6,5 +6,6 @@ user = "toast"; group = "users"; dataDir = config.users.users.toast.home; + folders."passwords".path = "~/Documents/Passwords"; }; } From e6b6416bc3f272a0c95b2285699e0d4546050ee5 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 22:16:02 +0200 Subject: [PATCH 0117/1125] Common: add everest to syncthing --- roles/common/services/syncthing.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index 551063a..a647089 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -16,12 +16,16 @@ name = "Steam Deck"; id = "DLQPL74-KEQTPM5-X4PDZHB-4HLQYHV-UCMJLOB-P6W3KWU-QLJADBY-V4KEMA5"; }; + "server" = { + name = "Everest"; + id = "BVJBCAZ-WDIWBFR-CK3WB3N-TWH3UXX-EPZXVWE-BLQ3IDU-U7MHVVB-WO4BKAJ"; + }; }; folders = { "passwords" = { label = "KeePassXC Passwords"; id = "rdyaq-ex659"; - devices = [ "phone" "pc" "steamdeck"]; + devices = [ "phone" "pc" "steamdeck" "server"]; }; }; }; From 47c8ca29a03a2357c7078698065c926045777436 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 22:19:12 +0200 Subject: [PATCH 0118/1125] Common: set syncthing options --- roles/common/services/syncthing.nix | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index a647089..da9174f 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -1,8 +1,16 @@ { config, ... }: { - # Set up devices and folders common to every device services.syncthing = { + overrideDevices = true; + overrideFolders = true; + openDefaultPorts = true; + extraOptions = { + options = { + urAccepted = 3; + }; + }; + # Set up devices and folders common to every device devices = { "phone" = { name = "Xiaomi Redmi Note 10 Pro"; From 88a712eac95dfc0326a95df31b5077c15bc2efc0 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Aug 2023 23:27:35 +0200 Subject: [PATCH 0119/1125] Syncthing: use traefik as reverse proxy --- roles/server/syncthing.nix | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index c8c5049..3378689 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -16,4 +16,23 @@ }; }; }; + + # Set up traefik as the reverse proxy for syncthing + services.traefik = { + dynamicConfigOptions = { + http = { + routers = { + syncthing-subpath = { + middlewares = [ "syncthing-strip-prefix" ]; + rule = "PathPrefix(`/syncthing/`)"; + service = "syncthing"; + }; + }; + services.syncthing.loadBalancer.servers = [ + { url = "http://localhost:8384"; } + ]; + middlewares.syncthing-strip-prefix.stripprefix.prefixes = "/syncthing"; + }; + }; + }; } From 1b2eadecf495292b880f783933593102350ec375 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 2 Sep 2023 00:49:03 +0200 Subject: [PATCH 0120/1125] Syncthing: add surface go to devices list --- roles/common/services/syncthing.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index da9174f..be8d5ac 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -28,12 +28,16 @@ name = "Everest"; id = "BVJBCAZ-WDIWBFR-CK3WB3N-TWH3UXX-EPZXVWE-BLQ3IDU-U7MHVVB-WO4BKAJ"; }; + "surface" = { + name = "Surface Go"; + id = "HTVSF3O-AHY3TNH-BLVSEGK-HRRSMHC-H5LJWVF-NDKGM6O-ATWZALC-YXNV2Q4"; + }; }; folders = { "passwords" = { label = "KeePassXC Passwords"; id = "rdyaq-ex659"; - devices = [ "phone" "pc" "steamdeck" "server"]; + devices = [ "phone" "pc" "steamdeck" "server" "surface"]; }; }; }; From 008f1bc36f0a3f38a75d937800b403b0c88097d0 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 2 Sep 2023 01:33:36 +0200 Subject: [PATCH 0121/1125] Syncthing: tell traefik to redirect /syncthing to /syncthing/ --- roles/server/syncthing.nix | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 3378689..baddf06 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -23,8 +23,8 @@ http = { routers = { syncthing-subpath = { - middlewares = [ "syncthing-strip-prefix" ]; - rule = "PathPrefix(`/syncthing/`)"; + middlewares = [ "syncthing-add-trailing-slash" "syncthing-strip-prefix" ]; + rule = "PathPrefix(`/syncthing`)"; service = "syncthing"; }; }; @@ -32,6 +32,11 @@ { url = "http://localhost:8384"; } ]; middlewares.syncthing-strip-prefix.stripprefix.prefixes = "/syncthing"; + middlewares.syncthing-add-trailing-slash.redirectRegex = { + # Going to everest/syncthing without a slash at the end breaks things + regex = "http:\/\/everest\/syncthing+$"; + replacement = "http://everest/syncthing/"; + }; }; }; }; From 5f983678dcd2b8677ed9ccf2a696637e90a801c4 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 2 Sep 2023 23:12:37 +0200 Subject: [PATCH 0122/1125] Syncthing: allow the syncthing user to stop syncthing service --- roles/desktop/services/syncthing.nix | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/roles/desktop/services/syncthing.nix b/roles/desktop/services/syncthing.nix index 728dd0e..c650ba9 100644 --- a/roles/desktop/services/syncthing.nix +++ b/roles/desktop/services/syncthing.nix @@ -8,4 +8,18 @@ dataDir = config.users.users.toast.home; folders."passwords".path = "~/Documents/Passwords"; }; + # Allow regular users to stop syncthing + # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if ( + action.id == "org.freedesktop.systemd1.manage-units" && + action.lookup("unit") == "syncthing.service" && + subject.user == "${config.services.syncthing.user}" + ) + { + return polkit.Result.YES; + } + }) + ''; } From 35189a4e19929cecd64b72ba51e3eb568befe268 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 4 Sep 2023 18:34:15 +0200 Subject: [PATCH 0123/1125] Discord: add specialication to use stock discord package --- roles/desktop/programs/discord.nix | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 5f47f87..5142192 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -1,4 +1,4 @@ -{ config, pkgs, ... }: +{ config, pkgs, lib, ... }: let discordOverlay = self: super: { @@ -7,8 +7,19 @@ withVencord = true; }; }; + stock-discord = self: super: { + discord = super.discord.override { + withOpenASAR = false; + withVencord = false; + }; + }; in { + # Sometimes discord breaks after updates, and launching it stock once fixes it + specialisation.stockDiscord.configuration = { + nixpkgs.overlays = lib.mkAfter [ stock-discord ]; + }; + nixpkgs.overlays = [ discordOverlay ]; users.users.toast.packages = with pkgs; [ discord From 9cb596d6c5ce513730f9cde92866260a4befa37f Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 4 Sep 2023 19:31:03 +0200 Subject: [PATCH 0124/1125] Flake: update lock file --- flake.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/flake.lock b/flake.lock index 4f07cef..b4b385f 100644 --- a/flake.lock +++ b/flake.lock @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1693187908, - "narHash": "sha256-cTcNpsqi1llmUFl9bmCdD0mTyfjhBrNFPhu2W12WXzA=", + "lastModified": 1693713564, + "narHash": "sha256-00w2uwb4O6Y1e2W5LG5UFyl1ZN3KFG7aoRdYEvT/BqA=", "owner": "nix-community", "repo": "home-manager", - "rev": "8bde7a651b94ba30bd0baaa9c4a08aae88cc2e92", + "rev": "8e49b883890ccb52c059abb152b00a416342ec1c", "type": "github" }, "original": { @@ -106,11 +106,11 @@ ] }, "locked": { - "lastModified": 1693107069, - "narHash": "sha256-5dVXPchyvzmytanlwXHcmeQP9AfO/98Q6V+QtsMl5vQ=", + "lastModified": 1693711723, + "narHash": "sha256-5QmlVzskLciJ0QzYmZ6ULvKA7bP6pgV9wwrLBB0V3j0=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "53d40cf1bea235658ef8f6e8b8a1d033e2ecbfff", + "rev": "aca56a79afb82208af2b39d8459dd29c10989135", "type": "github" }, "original": { @@ -126,11 +126,11 @@ ] }, "locked": { - "lastModified": 1693107069, - "narHash": "sha256-5dVXPchyvzmytanlwXHcmeQP9AfO/98Q6V+QtsMl5vQ=", + "lastModified": 1693711723, + "narHash": "sha256-5QmlVzskLciJ0QzYmZ6ULvKA7bP6pgV9wwrLBB0V3j0=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "53d40cf1bea235658ef8f6e8b8a1d033e2ecbfff", + "rev": "aca56a79afb82208af2b39d8459dd29c10989135", "type": "github" }, "original": { @@ -141,11 +141,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1692952286, - "narHash": "sha256-TsrtPv3+Q1KR0avZxpiJH+b6fX/R/hEQVHbjl1ebotY=", + "lastModified": 1693718952, + "narHash": "sha256-+nGdJlgTk0MPN7NygopipmyylVuAVi7OItIwTlwtGnw=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "817e297fc3352fadc15f2c5306909aa9192d7d97", + "rev": "793de77d9f83418b428e8ba70d1e42c6507d0d35", "type": "github" }, "original": { @@ -157,11 +157,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1693231525, - "narHash": "sha256-Zmh8m0HHcgGBDth6jdJPmc4UAAP0L4jQmqIztywF1Iw=", + "lastModified": 1693771906, + "narHash": "sha256-32EnPCaVjOiEERZ+o/2Ir7JH9pkfwJZJ27SKHNvt4yk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c540061ac8d72d6e6d99345bd2d590c82b2f58c1", + "rev": "da5adce0ffaff10f6d0fee72a02a5ed9d01b52fc", "type": "github" }, "original": { @@ -172,11 +172,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1693250523, - "narHash": "sha256-y3up5gXMTbnCsXrNEB5j+7TVantDLUYyQLu/ueiXuyg=", + "lastModified": 1693663421, + "narHash": "sha256-ImMIlWE/idjcZAfxKK8sQA7A1Gi/O58u5/CJA+mxvl8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3efb0f6f404ec8dae31bdb1a9b17705ce0d6986e", + "rev": "e56990880811a451abd32515698c712788be5720", "type": "github" }, "original": { From 7e6a0c9ad27792ce61ac53bf70916ed8d30da3ce Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 4 Sep 2023 19:31:17 +0200 Subject: [PATCH 0125/1125] SurfaceGo: update kernel version --- machines/SurfaceGo/configuration.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix index 024bd92..dbf1759 100644 --- a/machines/SurfaceGo/configuration.nix +++ b/machines/SurfaceGo/configuration.nix @@ -2,7 +2,7 @@ # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running `nixos-help`). -{ config, pkgs, ... }: +{ config, pkgs, lib, ... }: { # Use grub boot loader @@ -26,6 +26,13 @@ # Allow unfree packages nixpkgs.config.allowUnfree = true; + /* + As of commit 793de77d9f83418b428e8ba70d1e42c6507d0d35 of nixos-hardware, the + default kerrnel version for the Surface Go is 6.1.18, which fails to build. + Setting it to 6.4.12 works around this + */ + microsoft-surface.kernelVersion = lib.mkForce "6.4.12"; + # Configure network proxy if necessary # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; From 5af49c32e2ce516ecbad007fb56e2e80742a9b3f Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 6 Sep 2023 19:32:32 +0200 Subject: [PATCH 0126/1125] Syncthing: give additional capabilities --- roles/server/syncthing.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index baddf06..1f25424 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -5,6 +5,7 @@ syncthingKey.file = ../../secrets/syncthing/key; syncthingCert.file = ../../secrets/syncthing/cert; }; + services.syncthing = { enable = true; key = config.age.secrets.syncthingKey.path; @@ -16,6 +17,10 @@ }; }; }; + systemd.services.syncthing.serviceConfig = { + # Allow syncthing to change ownership of files + AmbientCapabilities = "CAP_CHOWN CAP_FOWNER"; + }; # Set up traefik as the reverse proxy for syncthing services.traefik = { From e3577910d159c66486e7d1bb2374a75ab35e4687 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 9 Sep 2023 20:59:33 +0200 Subject: [PATCH 0127/1125] Common: enable nfs support --- roles/common/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 2be5714..495b4f3 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -30,6 +30,8 @@ useXkbConfig = true; }; + boot.supportedFilesystems = [ "nfs" ]; + # Set up localisation i18n = { defaultLocale = "en_US.UTF-8"; From 3bdb7539b5453a0e102c87006315c860a703a7a1 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 9 Sep 2023 21:31:28 +0200 Subject: [PATCH 0128/1125] Archie: add mountpoint for windows partition --- machines/Archie/hardware-configuration.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index cc53c64..2966d88 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -50,6 +50,12 @@ fsType = config.fileSystems."/".fsType; options = [ "subvolid=5" "ro" ]; }; + "/mnt/windows" = { + device = "/dev/disk/by-uuid/B61AFDAC1AFD6A2F"; + fsType = "ntfs3"; + neededForBoot = false; + options = [ "noauto" "windows_names" ]; + }; "/home" = { device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; fsType = "btrfs"; From e98119358d33d15a34cda527037a5f474b18147d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 12 Sep 2023 18:23:22 +0200 Subject: [PATCH 0129/1125] Machines: Add Steam Deck --- flake.nix | 17 +++ machines/SteamDeck/configuration.nix | 100 ++++++++++++++++++ machines/SteamDeck/default.nix | 8 ++ machines/SteamDeck/hardware-configuration.nix | 71 +++++++++++++ 4 files changed, 196 insertions(+) create mode 100755 machines/SteamDeck/configuration.nix create mode 100755 machines/SteamDeck/default.nix create mode 100755 machines/SteamDeck/hardware-configuration.nix diff --git a/flake.nix b/flake.nix index ae8edc7..27630c6 100755 --- a/flake.nix +++ b/flake.nix @@ -100,6 +100,23 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl ]; }; + SteamDeck = nixpkgs-unstable.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { systemPkgs = inputs.nixpkgs-unstable; }; + modules = [ + # Needed for nix-index + { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } + agenix.nixosModules.default + home-manager-unstable.nixosModule + nix-index-db-unstable.nixosModules.nix-index + ./roles/common + ./roles/desktop + ./roles/kde + ./roles/gaming + ./machines/SteamDeck + ]; + }; + Everest = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; specialArgs = { systemPkgs = inputs.nixpkgs; }; diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix new file mode 100755 index 0000000..6c922ec --- /dev/null +++ b/machines/SteamDeck/configuration.nix @@ -0,0 +1,100 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running `nixos-help`). + +{ config, pkgs, ... }: + +{ + # Use grub boot loader + boot.loader = { + systemd-boot.enable = false; + grub = { + enable = true; + device = "nodev"; + efiSupport = true; + # No other OS on here :P + useOSProber = false; + }; + efi.efiSysMountPoint = config.fileSystems."efi_boot_partition".mountPoint; + }; + boot.loader.efi.canTouchEfiVariables = true; + + boot.kernelPackages = pkgs.linuxKernel.packages.linux_xanmod_latest; + + networking.hostName = "SteamDeck"; # Define your hostname. + networking.networkmanager.enable = true; # Enable networking + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + nix.settings.auto-optimise-store = true; + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Enable the X11 windowing system. + services.xserver.enable = true; + + # Enable the pipewire sound server + services.pipewire = { + enable = true; + pulse.enable = true; + }; + + # Configure keymap in X11 + # services.xserver.layout = "us"; + # services.xserver.xkbOptions = "eurosign:e,caps:escape"; + + # Enable CUPS to print documents. + # services.printing.enable = true; + + # Enable sound. + # sound.enable = true; + # hardware.pulseaudio.enable = true; + + # Enable touchpad support (enabled default in most desktopManager). + # services.xserver.libinput.enable = true; + + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.toast = { + isNormalUser = true; + extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + packages = with pkgs; [ + tree + ]; + }; + + # List packages installed in system profile. To search, run: + # $ nix search wget + # environment.systemPackages = with pkgs; [ + # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + # wget + # ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + # services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + # system.copySystemConfiguration = true; + +} + diff --git a/machines/SteamDeck/default.nix b/machines/SteamDeck/default.nix new file mode 100755 index 0000000..5bf2485 --- /dev/null +++ b/machines/SteamDeck/default.nix @@ -0,0 +1,8 @@ +{ ... }: + +{ + imports = [ + ./configuration.nix + ./hardware-configuration.nix + ]; +} diff --git a/machines/SteamDeck/hardware-configuration.nix b/machines/SteamDeck/hardware-configuration.nix new file mode 100755 index 0000000..1f4cd77 --- /dev/null +++ b/machines/SteamDeck/hardware-configuration.nix @@ -0,0 +1,71 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +let + # \x20 is the escape code for a space + ssdLabel = ''Deck\\x20SSD''; +in + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + # Enable support for the Xbox One wireless dongle + hardware.xone.enable = true; + + boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "usb_storage" "usbhid" "sd_mod" "sdhci_pci" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems = { + "efi_boot_partition" = { + mountPoint = "/boot/efi"; + label = "deckboot"; + fsType = "vfat"; + }; + /* + Mount the root subvolume of the SSD + This is helpful for getting things from + my old Arch install, as well as for running btdu + */ + "btrfs_root_subvolume" = { + mountPoint = "/mnt/ssd"; + label = ssdLabel; + fsType = "btrfs"; + options = [ "subvolid=5" "ro" ]; + }; + "btrfs_root" = { + mountPoint = "/"; + label = ssdLabel; + fsType = "btrfs"; + options = [ "subvol=@" "compress=zstd" ]; + }; + "btrfs_boot" = { + mountPoint = "/boot"; + label = ssdLabel; + fsType = "btrfs"; + options = [ "subvol=@boot" "compress=zstd" ]; + }; + "btrfs_home" = { + mountPoint = "/home"; + label = ssdLabel; + fsType = "btrfs"; + options = [ "subvol=@home" "compress=zstd" ]; + }; + "btrfs_nix" = { + mountPoint = "/nix"; + label = ssdLabel; + fsType = "btrfs"; + options = [ "subvol=@nix" "compress=zstd" ]; + }; + }; + + swapDevices = [ ]; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} From 4ff3dda4d02cc0504ea23eae83a0b910d3c0aec7 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 12 Sep 2023 18:58:24 +0200 Subject: [PATCH 0130/1125] Flake: update lock file --- flake.lock | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index b4b385f..2f16a62 100644 --- a/flake.lock +++ b/flake.lock @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1693713564, - "narHash": "sha256-00w2uwb4O6Y1e2W5LG5UFyl1ZN3KFG7aoRdYEvT/BqA=", + "lastModified": 1694469544, + "narHash": "sha256-eqZng5dZnAUyb7xXyFk5z871GY/++KVv3Gyld5mVh20=", "owner": "nix-community", "repo": "home-manager", - "rev": "8e49b883890ccb52c059abb152b00a416342ec1c", + "rev": "5171f5ef654425e09d9c2100f856d887da595437", "type": "github" }, "original": { @@ -70,11 +70,11 @@ ] }, "locked": { - "lastModified": 1693208669, - "narHash": "sha256-hHFaaUsZ860wvppPeiu7nJn/nXZjJfnqAQEu9SPFE9I=", + "lastModified": 1694465129, + "narHash": "sha256-8BQiuobMrCfCbGM7w6Snx+OBYdtTIm0+cGVaKwQ5BFg=", "owner": "nix-community", "repo": "home-manager", - "rev": "5bac4a1c06cd77cf8fc35a658ccb035a6c50cd2c", + "rev": "9787dffff5d315c9593d3f9fb0f9bf2097e1b57b", "type": "github" }, "original": { @@ -106,11 +106,11 @@ ] }, "locked": { - "lastModified": 1693711723, - "narHash": "sha256-5QmlVzskLciJ0QzYmZ6ULvKA7bP6pgV9wwrLBB0V3j0=", + "lastModified": 1694430658, + "narHash": "sha256-8+OZ98kD63e/GaOiJimXHR/VYiTYwr25jTYGEHHOfq4=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "aca56a79afb82208af2b39d8459dd29c10989135", + "rev": "9a5c4996d0918a151269600dfdf6ad3b3748f6a4", "type": "github" }, "original": { @@ -126,11 +126,11 @@ ] }, "locked": { - "lastModified": 1693711723, - "narHash": "sha256-5QmlVzskLciJ0QzYmZ6ULvKA7bP6pgV9wwrLBB0V3j0=", + "lastModified": 1694430658, + "narHash": "sha256-8+OZ98kD63e/GaOiJimXHR/VYiTYwr25jTYGEHHOfq4=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "aca56a79afb82208af2b39d8459dd29c10989135", + "rev": "9a5c4996d0918a151269600dfdf6ad3b3748f6a4", "type": "github" }, "original": { @@ -141,11 +141,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1693718952, - "narHash": "sha256-+nGdJlgTk0MPN7NygopipmyylVuAVi7OItIwTlwtGnw=", + "lastModified": 1694432324, + "narHash": "sha256-bo3Gv6Cp40vAXDBPi2XiDejzp/kyz65wZg4AnEWxAcY=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "793de77d9f83418b428e8ba70d1e42c6507d0d35", + "rev": "ca41b8a227dd235b1b308217f116c7e6e84ad779", "type": "github" }, "original": { @@ -157,11 +157,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1693771906, - "narHash": "sha256-32EnPCaVjOiEERZ+o/2Ir7JH9pkfwJZJ27SKHNvt4yk=", + "lastModified": 1694426803, + "narHash": "sha256-osusXQo0zkEqs502SNMffsKp1O9evpDM54A37MuyT2Q=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "da5adce0ffaff10f6d0fee72a02a5ed9d01b52fc", + "rev": "9a74ffb2ca1fc91c6ccc48bd3f8cbc1501bf7b8a", "type": "github" }, "original": { @@ -172,11 +172,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1693663421, - "narHash": "sha256-ImMIlWE/idjcZAfxKK8sQA7A1Gi/O58u5/CJA+mxvl8=", + "lastModified": 1694422566, + "narHash": "sha256-lHJ+A9esOz9vln/3CJG23FV6Wd2OoOFbDeEs4cMGMqc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e56990880811a451abd32515698c712788be5720", + "rev": "3a2786eea085f040a66ecde1bc3ddc7099f6dbeb", "type": "github" }, "original": { From b3297f130e8cc8b44c5a659af910ae6e3449f570 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 12 Sep 2023 18:58:52 +0200 Subject: [PATCH 0131/1125] SurfaceGo: use default kernel version --- machines/SurfaceGo/configuration.nix | 7 ------- 1 file changed, 7 deletions(-) diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix index dbf1759..1c30fd3 100644 --- a/machines/SurfaceGo/configuration.nix +++ b/machines/SurfaceGo/configuration.nix @@ -26,13 +26,6 @@ # Allow unfree packages nixpkgs.config.allowUnfree = true; - /* - As of commit 793de77d9f83418b428e8ba70d1e42c6507d0d35 of nixos-hardware, the - default kerrnel version for the Surface Go is 6.1.18, which fails to build. - Setting it to 6.4.12 works around this - */ - microsoft-surface.kernelVersion = lib.mkForce "6.4.12"; - # Configure network proxy if necessary # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; From 73f9f12489a75f8eda0593477df437ec3981978b Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 12 Sep 2023 20:48:09 +0200 Subject: [PATCH 0132/1125] Flake: add Jovian-Experiments modules --- flake.lock | 44 ++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 8 +++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index 2f16a62..4fede23 100644 --- a/flake.lock +++ b/flake.lock @@ -84,6 +84,49 @@ "type": "github" } }, + "jovian": { + "inputs": { + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1693592878, + "narHash": "sha256-pPTf8gjZwivBicb/DPY3YwbkCROVt2qftqQONb1xC2M=", + "owner": "Jovian-Experiments", + "repo": "Jovian-NixOS", + "rev": "d31a25e74b1bb7df342c0a53eeac4d4f91ea22b1", + "type": "github" + }, + "original": { + "owner": "Jovian-Experiments", + "repo": "Jovian-NixOS", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "jovian", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1690328911, + "narHash": "sha256-fxtExYk+aGf2YbjeWQ8JY9/n9dwuEt+ma1eUFzF8Jeo=", + "owner": "zhaofengli", + "repo": "nix-github-actions", + "rev": "96df4a39c52f53cb7098b923224d8ce941b64747", + "type": "github" + }, + "original": { + "owner": "zhaofengli", + "ref": "matrix-name", + "repo": "nix-github-actions", + "type": "github" + } + }, "nix-impermanence": { "locked": { "lastModified": 1690797372, @@ -190,6 +233,7 @@ "agenix": "agenix", "home-manager": "home-manager_2", "home-manager-unstable": "home-manager-unstable", + "jovian": "jovian", "nix-impermanence": "nix-impermanence", "nix-index-db": "nix-index-db", "nix-index-db-unstable": "nix-index-db-unstable", diff --git a/flake.nix b/flake.nix index 27630c6..523799f 100755 --- a/flake.nix +++ b/flake.nix @@ -24,6 +24,11 @@ inputs = { }; nixos-hardware.url = "github:NixOS/nixos-hardware/master"; + + jovian = { + url = "github:Jovian-Experiments/Jovian-NixOS"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; nix-impermanence.url = "github:nix-community/impermanence"; @@ -42,7 +47,7 @@ inputs = { }; }; -outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, nix-index-db, nix-index-db-unstable, ... } @inputs: { +outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, nix-index-db, nix-index-db-unstable, jovian, ... } @inputs: { devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { name = "Environment for toast's nixos configurations"; @@ -107,6 +112,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl # Needed for nix-index { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } agenix.nixosModules.default + jovian.nixosModules.default home-manager-unstable.nixosModule nix-index-db-unstable.nixosModules.nix-index ./roles/common From d92b95c90f7342157cf7b72c3dfc893136ff7c48 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 13 Sep 2023 01:15:30 +0200 Subject: [PATCH 0133/1125] SteamDeck: enable steam deck ui and hardware support --- machines/SteamDeck/configuration.nix | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index 6c922ec..bfb1605 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -2,7 +2,7 @@ # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running `nixos-help`). -{ config, pkgs, ... }: +{ config, pkgs, lib, ... }: { # Use grub boot loader @@ -42,6 +42,20 @@ pulse.enable = true; }; + jovian = { + devices.steamdeck = { + enable = true; + }; + # Steam Deck UI settings + steam = { + enable = true; + autoStart = true; + user = "toast"; + desktopSession = "plasmawayland"; + }; + }; + services.xserver.displayManager.sddm.enable = lib.mkForce false; + # Configure keymap in X11 # services.xserver.layout = "us"; # services.xserver.xkbOptions = "eurosign:e,caps:escape"; From 884590e97233194f8f17928bbc27fca410ccd4ee Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 14 Sep 2023 18:22:41 +0200 Subject: [PATCH 0134/1125] Flake: remove leftover nixPath setting --- flake.nix | 8 -------- 1 file changed, 8 deletions(-) diff --git a/flake.nix b/flake.nix index 523799f..377040a 100755 --- a/flake.nix +++ b/flake.nix @@ -75,8 +75,6 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl Also has nice side effect of making it easier to add new systems :3 */ modules = [ - # Needed for nix-index - { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } agenix.nixosModules.default home-manager-unstable.nixosModule nix-index-db-unstable.nixosModules.nix-index @@ -92,8 +90,6 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl system = "x86_64-linux"; specialArgs = { systemPkgs = inputs.nixpkgs; }; modules = [ - # Needed for nix-index - { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } agenix.nixosModules.default home-manager.nixosModule nixos-hardware.nixosModules.microsoft-surface-go @@ -109,8 +105,6 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl system = "x86_64-linux"; specialArgs = { systemPkgs = inputs.nixpkgs-unstable; }; modules = [ - # Needed for nix-index - { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } agenix.nixosModules.default jovian.nixosModules.default home-manager-unstable.nixosModule @@ -127,8 +121,6 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl system = "x86_64-linux"; specialArgs = { systemPkgs = inputs.nixpkgs; }; modules = [ - # Needed for nix-index - { nix.nixPath = [ "nixpkgs=${nixpkgs}" ]; } agenix.nixosModules.default home-manager.nixosModule nix-index-db.nixosModules.nix-index From da0bd779303547fb7031c27eed1cb011599d4fc7 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 14 Sep 2023 23:19:26 +0200 Subject: [PATCH 0135/1125] Common: set system.configurationRevision --- flake.nix | 10 +++++----- roles/common/configuration.nix | 7 +++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/flake.nix b/flake.nix index 377040a..ef3b7fc 100755 --- a/flake.nix +++ b/flake.nix @@ -47,7 +47,7 @@ inputs = { }; }; -outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, nix-index-db, nix-index-db-unstable, jovian, ... } @inputs: { +outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, nix-index-db, nix-index-db-unstable, jovian, ... } @inputs: { devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { name = "Environment for toast's nixos configurations"; @@ -67,7 +67,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl nixosConfigurations = { Archie = nixpkgs-unstable.lib.nixosSystem { system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-unstable; }; + specialArgs = { systemPkgs = inputs.nixpkgs-unstable; flakeSelf = self; }; /* I used to set up nixpkgs in the flake, but doing that made defining overlays in modules impossible (or at least I could @@ -88,7 +88,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl SurfaceGo = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs; }; + specialArgs = { systemPkgs = inputs.nixpkgs; flakeSelf = self; }; modules = [ agenix.nixosModules.default home-manager.nixosModule @@ -103,7 +103,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl SteamDeck = nixpkgs-unstable.lib.nixosSystem { system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-unstable; }; + specialArgs = { systemPkgs = inputs.nixpkgs-unstable; flakeSelf = self; }; modules = [ agenix.nixosModules.default jovian.nixosModules.default @@ -119,7 +119,7 @@ outputs = {nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstabl Everest = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs; }; + specialArgs = { systemPkgs = inputs.nixpkgs; flakeSelf = self; }; modules = [ agenix.nixosModules.default home-manager.nixosModule diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 495b4f3..9bf3d40 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, flakeSelf, ... }: { environment = { @@ -85,5 +85,8 @@ manually on everything else */ - system.stateVersion = "23.05"; + system = { + stateVersion = "23.05"; + configurationRevision = flakeSelf.sourceInfo.rev or flakeSelf.sourceInfo.dirtyRev; + }; } From b623acef48191fa13e3a71b5739c7fbd40c03e2f Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Sep 2023 13:27:14 +0200 Subject: [PATCH 0136/1125] Common: set hostname as variant id --- roles/common/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 9bf3d40..ed0fe30 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -88,5 +88,6 @@ system = { stateVersion = "23.05"; configurationRevision = flakeSelf.sourceInfo.rev or flakeSelf.sourceInfo.dirtyRev; + nixos.variant_id = lib.strings.toLower config.networking.hostName; }; } From ebee0cb26bab3884a7003229113aae811c313a9a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Sep 2023 19:15:13 +0200 Subject: [PATCH 0137/1125] Syncthing: update steam deck id --- roles/common/services/syncthing.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index be8d5ac..966b866 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -22,7 +22,7 @@ }; "steamdeck" = { name = "Steam Deck"; - id = "DLQPL74-KEQTPM5-X4PDZHB-4HLQYHV-UCMJLOB-P6W3KWU-QLJADBY-V4KEMA5"; + id = "DNFEGEA-PDEVW5A-O5VBVQK-IUXI7J5-MAHCQAG-2JLEFFM-DSXB6AS-TX6ZHAN"; }; "server" = { name = "Everest"; From b9663da3a3ed043db20eff55fcb0cab0029c47fb Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Sep 2023 20:33:09 +0200 Subject: [PATCH 0138/1125] SteamDeck: use the valve kernel --- machines/SteamDeck/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index bfb1605..295996a 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -19,7 +19,7 @@ }; boot.loader.efi.canTouchEfiVariables = true; - boot.kernelPackages = pkgs.linuxKernel.packages.linux_xanmod_latest; + #boot.kernelPackages = pkgs.linuxKernel.packages.linux_xanmod_latest; networking.hostName = "SteamDeck"; # Define your hostname. networking.networkmanager.enable = true; # Enable networking From 4b3a5a47783600a8e968e15a42de5cfaf944a2d8 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Sep 2023 19:36:23 +0200 Subject: [PATCH 0139/1125] KeepassXC: move comment to right place --- roles/desktop/programs/keepassxc.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/desktop/programs/keepassxc.nix b/roles/desktop/programs/keepassxc.nix index 2bff9ed..00b90e6 100644 --- a/roles/desktop/programs/keepassxc.nix +++ b/roles/desktop/programs/keepassxc.nix @@ -2,10 +2,10 @@ let kpxcSettings = lib.generators.toINI {} { - # Not sure what changing this does, I'll leave it alone General = { + # Not sure what changing this does, I'll leave it alone ConfigVersion = 2; - MinimizeAfterUnlock = true; + MinimizeAfterUnlock = true; }; GUI = { ApplicationTheme = "classic"; From 3e6ab74cb40aef84aa9f43e06bb0f08752c47d56 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Sep 2023 19:36:47 +0200 Subject: [PATCH 0140/1125] KeepassXC: change settings --- roles/desktop/programs/keepassxc.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/desktop/programs/keepassxc.nix b/roles/desktop/programs/keepassxc.nix index 00b90e6..22858fc 100644 --- a/roles/desktop/programs/keepassxc.nix +++ b/roles/desktop/programs/keepassxc.nix @@ -6,6 +6,7 @@ let # Not sure what changing this does, I'll leave it alone ConfigVersion = 2; MinimizeAfterUnlock = true; + AutoSaveAfterEveryChange = false; }; GUI = { ApplicationTheme = "classic"; @@ -18,6 +19,7 @@ let # monochrome-light, monochrome-dark or colorful TrayIconAppearance = "monochrome-light"; }; + Security.HideNotes = true; SSHAgent.Enabled = true; }; in From a4b51545e61c72902f46a4a8b5df88d40c3fda57 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 16 Sep 2023 11:31:11 +0200 Subject: [PATCH 0141/1125] Common: enable home-manager's verbose activation --- roles/common/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index ed0fe30..0436a56 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -54,6 +54,7 @@ home-manager = { backupFileExtension = "hm-backup"; useGlobalPkgs = true; + verbose = true; users.toast = { config, ... }: { home.stateVersion = "23.05"; xdg = { From f3c39dd7b4b6e8f2472b76ff2acdfec31db599b3 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Sep 2023 21:06:13 +0200 Subject: [PATCH 0142/1125] Common: manage bash using home-manager --- roles/common/programs/bash.nix | 7 +++++++ roles/common/programs/default.nix | 1 + 2 files changed, 8 insertions(+) create mode 100644 roles/common/programs/bash.nix diff --git a/roles/common/programs/bash.nix b/roles/common/programs/bash.nix new file mode 100644 index 0000000..c1684bf --- /dev/null +++ b/roles/common/programs/bash.nix @@ -0,0 +1,7 @@ +{ config, ... }: + +{ + home-manager.users.toast = { config, ... }: { + programs.bash.enable = true; + }; +} diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index 83991eb..1aa9c89 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -8,6 +8,7 @@ ./nix-index.nix ./command-not-found.nix ./comma.nix + ./bash.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ From 81ded02e1948ee88fdb70faab8696e22cc5ec6ed Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 18 Sep 2023 00:03:58 +0200 Subject: [PATCH 0143/1125] Flake: update lock file --- flake.lock | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/flake.lock b/flake.lock index 4fede23..2eb5956 100644 --- a/flake.lock +++ b/flake.lock @@ -9,11 +9,11 @@ ] }, "locked": { - "lastModified": 1690228878, - "narHash": "sha256-9Xe7JV0krp4RJC9W9W9WutZVlw6BlHTFMiUP/k48LQY=", + "lastModified": 1694793763, + "narHash": "sha256-y6gTE1C9mIoSkymRYyzCmv62PFgy+hbZ5j8fuiQK5KI=", "owner": "ryantm", "repo": "agenix", - "rev": "d8c973fd228949736dedf61b7f8cc1ece3236792", + "rev": "572baca9b0c592f71982fca0790db4ce311e3c75", "type": "github" }, "original": { @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1694469544, - "narHash": "sha256-eqZng5dZnAUyb7xXyFk5z871GY/++KVv3Gyld5mVh20=", + "lastModified": 1694643239, + "narHash": "sha256-pv2k/5FvyirDE8g4TNehzwZ0T4UOMMmqWSQnM/luRtE=", "owner": "nix-community", "repo": "home-manager", - "rev": "5171f5ef654425e09d9c2100f856d887da595437", + "rev": "d9b88b43524db1591fb3d9410a21428198d75d49", "type": "github" }, "original": { @@ -92,11 +92,11 @@ ] }, "locked": { - "lastModified": 1693592878, - "narHash": "sha256-pPTf8gjZwivBicb/DPY3YwbkCROVt2qftqQONb1xC2M=", + "lastModified": 1694968424, + "narHash": "sha256-GM6B3u9IRzd6t3OZF7q27SqwHcTLPXFO7HIgm5hTksY=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "d31a25e74b1bb7df342c0a53eeac4d4f91ea22b1", + "rev": "5eaab6bff94742a7066c0c62468dac644ce665dc", "type": "github" }, "original": { @@ -129,11 +129,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1690797372, - "narHash": "sha256-GImz19e33SeVcIvBB7NnhbJSbTpFFmNtWLh7Z85Y188=", + "lastModified": 1694622745, + "narHash": "sha256-z397+eDhKx9c2qNafL1xv75lC0Q4nOaFlhaU1TINqb8=", "owner": "nix-community", "repo": "impermanence", - "rev": "e3a7acd113903269a1b5c8b527e84ce7ee859851", + "rev": "e9643d08d0d193a2e074a19d4d90c67a874d932e", "type": "github" }, "original": { @@ -149,11 +149,11 @@ ] }, "locked": { - "lastModified": 1694430658, - "narHash": "sha256-8+OZ98kD63e/GaOiJimXHR/VYiTYwr25jTYGEHHOfq4=", + "lastModified": 1694921880, + "narHash": "sha256-yU36cs5UdzhTwsM9bUWUz43N//ELzQ1ro69C07pU/8E=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "9a5c4996d0918a151269600dfdf6ad3b3748f6a4", + "rev": "9d2bcc47110b3b6217dfebd6761ba20bc78aedf2", "type": "github" }, "original": { @@ -169,11 +169,11 @@ ] }, "locked": { - "lastModified": 1694430658, - "narHash": "sha256-8+OZ98kD63e/GaOiJimXHR/VYiTYwr25jTYGEHHOfq4=", + "lastModified": 1694921880, + "narHash": "sha256-yU36cs5UdzhTwsM9bUWUz43N//ELzQ1ro69C07pU/8E=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "9a5c4996d0918a151269600dfdf6ad3b3748f6a4", + "rev": "9d2bcc47110b3b6217dfebd6761ba20bc78aedf2", "type": "github" }, "original": { @@ -184,11 +184,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1694432324, - "narHash": "sha256-bo3Gv6Cp40vAXDBPi2XiDejzp/kyz65wZg4AnEWxAcY=", + "lastModified": 1694710316, + "narHash": "sha256-uRh46iIC86D8BD1wCDA5gRrt+hslUXiD0kx/UjnjBcs=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "ca41b8a227dd235b1b308217f116c7e6e84ad779", + "rev": "570256327eb6ca6f7bebe8d93af49459092a0c43", "type": "github" }, "original": { @@ -200,11 +200,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1694426803, - "narHash": "sha256-osusXQo0zkEqs502SNMffsKp1O9evpDM54A37MuyT2Q=", + "lastModified": 1694937365, + "narHash": "sha256-iHZSGrb9gVpZRR4B2ishUN/1LRKWtSHZNO37C8z1SmA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9a74ffb2ca1fc91c6ccc48bd3f8cbc1501bf7b8a", + "rev": "5d017a8822e0907fb96f7700a319f9fe2434de02", "type": "github" }, "original": { @@ -215,11 +215,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1694422566, - "narHash": "sha256-lHJ+A9esOz9vln/3CJG23FV6Wd2OoOFbDeEs4cMGMqc=", + "lastModified": 1694767346, + "narHash": "sha256-5uH27SiVFUwsTsqC5rs3kS7pBoNhtoy9QfTP9BmknGk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3a2786eea085f040a66ecde1bc3ddc7099f6dbeb", + "rev": "ace5093e36ab1e95cb9463863491bee90d5a4183", "type": "github" }, "original": { From 1328e16181744b5314b899d42527702284c9df5d Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 18 Sep 2023 22:28:45 +0200 Subject: [PATCH 0144/1125] Flake: add school role --- flake.nix | 1 + roles/school/default.nix | 7 +++++++ roles/school/services/default.nix | 7 +++++++ roles/school/services/syncthing.nix | 12 ++++++++++++ 4 files changed, 27 insertions(+) create mode 100644 roles/school/default.nix create mode 100644 roles/school/services/default.nix create mode 100644 roles/school/services/syncthing.nix diff --git a/flake.nix b/flake.nix index ef3b7fc..0e80695 100755 --- a/flake.nix +++ b/flake.nix @@ -113,6 +113,7 @@ outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager- ./roles/desktop ./roles/kde ./roles/gaming + ./roles/school ./machines/SteamDeck ]; }; diff --git a/roles/school/default.nix b/roles/school/default.nix new file mode 100644 index 0000000..f79f41d --- /dev/null +++ b/roles/school/default.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + imports = [ + ./services + ]; +} diff --git a/roles/school/services/default.nix b/roles/school/services/default.nix new file mode 100644 index 0000000..69a706a --- /dev/null +++ b/roles/school/services/default.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + imports = [ + ./syncthing.nix + ]; +} diff --git a/roles/school/services/syncthing.nix b/roles/school/services/syncthing.nix new file mode 100644 index 0000000..30ea20a --- /dev/null +++ b/roles/school/services/syncthing.nix @@ -0,0 +1,12 @@ +{ config, ... }: + +{ + services.syncthing.folders = { + "school-things" = { + label = "School things"; + id = "z6alc-nfoqr"; + devices = [ "steamdeck" "server" ]; + path = "~/Documents/School things"; + }; + }; +} From a641d8bb4cc86c6b76c883f28b5836ac8ce2f5a8 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 18 Sep 2023 22:29:23 +0200 Subject: [PATCH 0145/1125] Syncthing: add school things folder to server --- roles/server/syncthing.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 1f25424..8e0cc71 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -15,6 +15,12 @@ "passwords" = { path = "${config.services.syncthing.dataDir}/passwords"; }; + "school-things" = { + label = "School things"; + id = "z6alc-nfoqr"; + devices = [ "steamdeck" "server" ]; + path = "${config.services.syncthing.dataDir}/school-things"; + }; }; }; systemd.services.syncthing.serviceConfig = { From 74682751233202187b299e6990cf93018099d2b3 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 19 Sep 2023 08:24:39 +0200 Subject: [PATCH 0146/1125] Common: set nixpath to the system flake (again) --- roles/common/programs/nix.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index baa1cc9..07e90d7 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -14,5 +14,7 @@ experimental-features = nix-command flakes # https://dataswamp.org/~solene/2022-07-20-nixos-flakes-command-sync-with-system.html system.flake = systemPkgs; }; + # I removed this in the past since I thought that I didn't need it, but turns out comma does :) + nixPath = [ "nixpkgs=${systemPkgs}" ]; }; } From 71e088d8ca49225fd867c561a0abaffa4cd41ae2 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 19 Sep 2023 10:16:16 +0200 Subject: [PATCH 0147/1125] SteamDeck: enable decky loader --- machines/SteamDeck/configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index 295996a..e3d28e1 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -53,6 +53,9 @@ user = "toast"; desktopSession = "plasmawayland"; }; + decky-loader = { + enable = true; + }; }; services.xserver.displayManager.sddm.enable = lib.mkForce false; From 63ed34e5680a217cf9b6b26f15023aef93c75439 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 20 Sep 2023 11:09:28 +0200 Subject: [PATCH 0148/1125] School: enable virtualbox --- roles/school/programs/default.nix | 7 +++++++ roles/school/programs/virtualbox.nix | 9 +++++++++ 2 files changed, 16 insertions(+) create mode 100644 roles/school/programs/default.nix create mode 100644 roles/school/programs/virtualbox.nix diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix new file mode 100644 index 0000000..59bb34a --- /dev/null +++ b/roles/school/programs/default.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + imports = [ + ./virtualbox.nix + ]; +} diff --git a/roles/school/programs/virtualbox.nix b/roles/school/programs/virtualbox.nix new file mode 100644 index 0000000..275079d --- /dev/null +++ b/roles/school/programs/virtualbox.nix @@ -0,0 +1,9 @@ +{ config, ... }: + +{ + # Need to use visual studio 2019 :( + virtualisation.virtualbox.host = { + enable = true; + }; + users.users.toast.extraGroups = [ "vboxusers" ]; +} From 31501f509c5fdb838162807bf302e7942c949aa3 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 21 Sep 2023 11:38:51 +0200 Subject: [PATCH 0149/1125] Common: use zram as swap --- roles/common/configuration.nix | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 0436a56..d198309 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -18,6 +18,17 @@ cleanOnBoot = !config.boot.tmp.useTmpfs; }; + # Set up zram + zramSwap = { + enable = true; + priority = 100; + memoryPercent = 60; + # zstd my beloved <3 + algorithm = "zstd"; + }; + # zswap with zram is not a good idea + boot.kernelParams = [ "zswap.enabled=0" ]; + # Set up keyboard layout services.xserver.layout = "es"; From 2426e966e54d857bb7f6ecd82b58a06ee36dba56 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 23 Sep 2023 11:49:36 +0200 Subject: [PATCH 0150/1125] Flake: update lock file --- flake.lock | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index 2eb5956..81e6757 100644 --- a/flake.lock +++ b/flake.lock @@ -9,11 +9,11 @@ ] }, "locked": { - "lastModified": 1694793763, - "narHash": "sha256-y6gTE1C9mIoSkymRYyzCmv62PFgy+hbZ5j8fuiQK5KI=", + "lastModified": 1695384796, + "narHash": "sha256-TYlE4B0ktPtlJJF9IFxTWrEeq+XKG8Ny0gc2FGEAdj0=", "owner": "ryantm", "repo": "agenix", - "rev": "572baca9b0c592f71982fca0790db4ce311e3c75", + "rev": "1f677b3e161d3bdbfd08a939e8f25de2568e0ef4", "type": "github" }, "original": { @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1694643239, - "narHash": "sha256-pv2k/5FvyirDE8g4TNehzwZ0T4UOMMmqWSQnM/luRtE=", + "lastModified": 1695224363, + "narHash": "sha256-+hfjJLUMck5G92RVFDZA7LWkR3kOxs5zQ7RPW9t3eM8=", "owner": "nix-community", "repo": "home-manager", - "rev": "d9b88b43524db1591fb3d9410a21428198d75d49", + "rev": "408ba13188ff9ce309fa2bdd2f81287d79773b00", "type": "github" }, "original": { @@ -70,11 +70,11 @@ ] }, "locked": { - "lastModified": 1694465129, - "narHash": "sha256-8BQiuobMrCfCbGM7w6Snx+OBYdtTIm0+cGVaKwQ5BFg=", + "lastModified": 1695108154, + "narHash": "sha256-gSg7UTVtls2yO9lKtP0yb66XBHT1Fx5qZSZbGMpSn2c=", "owner": "nix-community", "repo": "home-manager", - "rev": "9787dffff5d315c9593d3f9fb0f9bf2097e1b57b", + "rev": "07682fff75d41f18327a871088d20af2710d4744", "type": "github" }, "original": { @@ -92,11 +92,11 @@ ] }, "locked": { - "lastModified": 1694968424, - "narHash": "sha256-GM6B3u9IRzd6t3OZF7q27SqwHcTLPXFO7HIgm5hTksY=", + "lastModified": 1695152592, + "narHash": "sha256-AW4gs1IiQUOgnYs6N+v+6wWSQDKlwCBUJJ6aB0n9JPs=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "5eaab6bff94742a7066c0c62468dac644ce665dc", + "rev": "e4e321a36922ee02682348b3e0eaa3c4a01deb31", "type": "github" }, "original": { @@ -184,11 +184,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1694710316, - "narHash": "sha256-uRh46iIC86D8BD1wCDA5gRrt+hslUXiD0kx/UjnjBcs=", + "lastModified": 1695109627, + "narHash": "sha256-4rpyoVzmunIG6xWA/EonnSSqC69bDBzciFi6SjBze/0=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "570256327eb6ca6f7bebe8d93af49459092a0c43", + "rev": "cb4dc98f776ddb6af165e6f06b2902efe31ca67a", "type": "github" }, "original": { @@ -200,11 +200,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1694937365, - "narHash": "sha256-iHZSGrb9gVpZRR4B2ishUN/1LRKWtSHZNO37C8z1SmA=", + "lastModified": 1695272228, + "narHash": "sha256-4uw2OdJPVyjdB+xcDst9SecrNIpxKXJ2usN3M5HVa7o=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5d017a8822e0907fb96f7700a319f9fe2434de02", + "rev": "55ac2a9d2024f15c56adf20da505b29659911da8", "type": "github" }, "original": { @@ -215,11 +215,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1694767346, - "narHash": "sha256-5uH27SiVFUwsTsqC5rs3kS7pBoNhtoy9QfTP9BmknGk=", + "lastModified": 1695145219, + "narHash": "sha256-Eoe9IHbvmo5wEDeJXKFOpKUwxYJIOxKUesounVccNYk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ace5093e36ab1e95cb9463863491bee90d5a4183", + "rev": "5ba549eafcf3e33405e5f66decd1a72356632b96", "type": "github" }, "original": { From 3f74fb61e45bfd15c5b8cf9fec7166f9f22c41d8 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 23 Sep 2023 12:01:48 +0200 Subject: [PATCH 0151/1125] SteamDeck: remove leftover comment --- machines/SteamDeck/configuration.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index e3d28e1..f0f61b8 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -19,8 +19,6 @@ }; boot.loader.efi.canTouchEfiVariables = true; - #boot.kernelPackages = pkgs.linuxKernel.packages.linux_xanmod_latest; - networking.hostName = "SteamDeck"; # Define your hostname. networking.networkmanager.enable = true; # Enable networking From bd5cba2c725ffaa937eecf9e333ae5e55895c9e1 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 23 Sep 2023 12:10:21 +0200 Subject: [PATCH 0152/1125] SteamDeck: install firmware upgraders --- machines/SteamDeck/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index f0f61b8..74f5487 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -80,6 +80,7 @@ ]; }; + environment.systemPackages = [ pkgs.steamdeck-firmware ]; # List packages installed in system profile. To search, run: # $ nix search wget # environment.systemPackages = with pkgs; [ From 2e666b18ee15de180c0bbbb91b22ae06b9ce3734 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 23 Sep 2023 12:12:36 +0200 Subject: [PATCH 0153/1125] Steamdeck: disable mangohud in game mode --- machines/SteamDeck/configuration.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index 74f5487..db30aa7 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -50,6 +50,14 @@ autoStart = true; user = "toast"; desktopSession = "plasmawayland"; + environment = { + /* + Steam already has a mangohud overlay, so this + avoids having two overlays at once + */ + MANGOHUD = "0"; + MANHOGUD_DLSYM = "0"; + }; }; decky-loader = { enable = true; From 49268397de1319ca04fde9157b6531de115871b7 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 25 Sep 2023 23:29:40 +0200 Subject: [PATCH 0154/1125] Gaming: install rpcs3 --- roles/gaming/default.nix | 1 + roles/gaming/rpcs3.nix | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 roles/gaming/rpcs3.nix diff --git a/roles/gaming/default.nix b/roles/gaming/default.nix index fb3cce4..dc70b10 100755 --- a/roles/gaming/default.nix +++ b/roles/gaming/default.nix @@ -4,5 +4,6 @@ imports = [ ./steam.nix ./mangohud.nix + ./rpcs3.nix ]; } diff --git a/roles/gaming/rpcs3.nix b/roles/gaming/rpcs3.nix new file mode 100644 index 0000000..43b80d0 --- /dev/null +++ b/roles/gaming/rpcs3.nix @@ -0,0 +1,5 @@ +{ config, pkgs, ... }: + +{ + environment.systemPackages = with pkgs; [ rpcs3 ]; +} From 061aee27ad9aa6eef4e45e1ceb2e841edfe999aa Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 25 Sep 2023 12:26:16 +0200 Subject: [PATCH 0155/1125] School: install dia --- roles/school/programs/default.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 59bb34a..816fade 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -1,7 +1,11 @@ -{ ... }: + { config, pkgs, ... }: { imports = [ ./virtualbox.nix ]; + + environment.systemPackages = with pkgs; [ + dia + ]; } From 1de7abfc58b811960a41fed6c7e79bb4c0f35245 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 25 Sep 2023 12:32:52 +0200 Subject: [PATCH 0156/1125] School: import programs --- roles/school/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/school/default.nix b/roles/school/default.nix index f79f41d..cb3d38f 100644 --- a/roles/school/default.nix +++ b/roles/school/default.nix @@ -3,5 +3,6 @@ { imports = [ ./services + ./programs ]; } From 84cbb13782ce2d2612652549a2515551dae29b99 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Sep 2023 00:02:00 +0200 Subject: [PATCH 0157/1125] Rpcs3: increase memlock limit --- roles/gaming/rpcs3.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/roles/gaming/rpcs3.nix b/roles/gaming/rpcs3.nix index 43b80d0..931b7ba 100644 --- a/roles/gaming/rpcs3.nix +++ b/roles/gaming/rpcs3.nix @@ -2,4 +2,12 @@ { environment.systemPackages = with pkgs; [ rpcs3 ]; + + # Increase the memory lock limit + security.pam.loginLimits = [{ + domain = "*"; + item = "memlock"; + type = "-"; # Applies to both hard and soft limits + value = "unlimited"; + }]; } From 8b6b7e54d68ec68e112323bea7e7137a6b18c13e Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Sep 2023 00:09:09 +0200 Subject: [PATCH 0158/1125] Do not enable pipewire in machine specific configs --- machines/Archie/configuration.nix | 6 ------ machines/SteamDeck/configuration.nix | 6 ------ machines/SurfaceGo/configuration.nix | 6 ------ 3 files changed, 18 deletions(-) diff --git a/machines/Archie/configuration.nix b/machines/Archie/configuration.nix index dfd748a..c610816 100644 --- a/machines/Archie/configuration.nix +++ b/machines/Archie/configuration.nix @@ -33,12 +33,6 @@ # Enable the X11 windowing system. services.xserver.enable = true; - # Enable the pipewire sound server - services.pipewire = { - enable = true; - pulse.enable = true; - }; - # Configure keymap in X11 # services.xserver.layout = "us"; # services.xserver.xkbOptions = "eurosign:e,caps:escape"; diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index db30aa7..ea49bd9 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -34,12 +34,6 @@ # Enable the X11 windowing system. services.xserver.enable = true; - # Enable the pipewire sound server - services.pipewire = { - enable = true; - pulse.enable = true; - }; - jovian = { devices.steamdeck = { enable = true; diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix index 1c30fd3..990d7a5 100644 --- a/machines/SurfaceGo/configuration.nix +++ b/machines/SurfaceGo/configuration.nix @@ -32,12 +32,6 @@ # Enable the X11 windowing system. services.xserver.enable = true; - - # Enable the pipewire sound server - services.pipewire = { - enable = true; - pulse.enable = true; - }; # Configure keymap in X11 # services.xserver.layout = "us"; From f40adefed8dfbe84fb326ea20fab3377cc0a491c Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Sep 2023 00:09:50 +0200 Subject: [PATCH 0159/1125] Desktop: configure pipewire --- roles/desktop/services/default.nix | 1 + roles/desktop/services/pipewire.nix | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 roles/desktop/services/pipewire.nix diff --git a/roles/desktop/services/default.nix b/roles/desktop/services/default.nix index 6393486..690505c 100644 --- a/roles/desktop/services/default.nix +++ b/roles/desktop/services/default.nix @@ -5,5 +5,6 @@ ./ssh-agent.nix ./flatpak.nix ./syncthing.nix + ./pipewire.nix ]; } diff --git a/roles/desktop/services/pipewire.nix b/roles/desktop/services/pipewire.nix new file mode 100644 index 0000000..447e307 --- /dev/null +++ b/roles/desktop/services/pipewire.nix @@ -0,0 +1,8 @@ +{ config, ... }: + +{ + services.pipewire = { + enable = true; + pulse.enable = true; + }; +} From 3480ab8216635317525cd221c31017ea91d8562a Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Sep 2023 00:11:34 +0200 Subject: [PATCH 0160/1125] Pipewire: enable rtkit --- roles/desktop/services/pipewire.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/desktop/services/pipewire.nix b/roles/desktop/services/pipewire.nix index 447e307..d064adb 100644 --- a/roles/desktop/services/pipewire.nix +++ b/roles/desktop/services/pipewire.nix @@ -5,4 +5,7 @@ enable = true; pulse.enable = true; }; + + # This allows pipewire to get realtime priority, which (hopefully) gets rid of stutters + security.rtkit.enable = true; } From 29e7ab4516b1cc9a1f192de5489c22918bb0823b Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 28 Sep 2023 00:20:24 +0200 Subject: [PATCH 0161/1125] Flake: add PSeInt package --- flake.nix | 6 +++++- pkgs/pseint.nix | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 pkgs/pseint.nix diff --git a/flake.nix b/flake.nix index 0e80695..451b953 100755 --- a/flake.nix +++ b/flake.nix @@ -63,7 +63,11 @@ outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager- export PS1="$PS1(toast-configs)> " ''; }; - + packages = { + x86_64-linux = with import nixpkgs-unstable { system = "x86_64-linux"; }; { + pseint = callPackage ./pkgs/pseint.nix {}; + }; + }; nixosConfigurations = { Archie = nixpkgs-unstable.lib.nixosSystem { system = "x86_64-linux"; diff --git a/pkgs/pseint.nix b/pkgs/pseint.nix new file mode 100644 index 0000000..bb33842 --- /dev/null +++ b/pkgs/pseint.nix @@ -0,0 +1,50 @@ +{ stdenv +, lib +, fetchurl +, wxGTK32 +, libX11 +, libglvnd +, libGLU +, gsettings-desktop-schemas +, makeBinaryWrapper +, wrapGAppsHook +}: +# Based on https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=pseint +stdenv.mkDerivation rec { + pname = "pseint"; + version = "20230517"; + + src = fetchurl { + url = "https://netactuate.dl.sourceforge.net/project/${pname}/${version}/${pname}-src-${version}.tgz"; + hash = "sha256-8zc7CtDQ9RjXLAVQTigstPqdDJsR8ffBopxBFzVP+eI="; + }; + + enableParallelBuilding = true; + + buildInputs = [ wxGTK32 libglvnd libGLU libX11 gsettings-desktop-schemas ]; + + nativeBuildInputs = [ makeBinaryWrapper wrapGAppsHook ]; + + # Build for linux + makeFlags = [ "ARCH=lnx" ]; + + installPhase = '' + runHook preInstall + + mkdir -p $out/opt/${pname}/ $out/bin/ + cp -rv bin/* $out/opt/${pname}/ + makeBinaryWrapper $out/opt/${pname}/pseint $out/bin/pseint + + runHook postInstall + ''; + + meta = with lib; { + description = "A tool for learning programming basis with a simple spanish pseudocode"; + homepage = "https://pseint.sourceforge.net/"; + downloadPage = "https://pseint.sourceforge.net/index.php?page=descargas.php"; + changelog = "https://pseint.sourceforge.net/index.php?page=cambios.php"; + # Website says GPLv2, so I'm assuming I need to use gpl2Only + license = lib.licenses.gpl2Only; + platforms = platforms.linux; + }; +} From 3746b5356ec07f5a77b9c522a102bcd01e9cd39b Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 28 Sep 2023 00:33:22 +0200 Subject: [PATCH 0162/1125] School: install PSeInt --- roles/school/programs/default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 816fade..77b1415 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -1,4 +1,4 @@ - { config, pkgs, ... }: + { config, pkgs, flakeSelf, ... }: { imports = [ @@ -7,5 +7,6 @@ environment.systemPackages = with pkgs; [ dia + flakeSelf.packages.x86_64-linux.pseint ]; } From 0dd4f4c956a0e0fe61606b9a5e2b41c5d4629d1b Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 28 Sep 2023 00:34:42 +0200 Subject: [PATCH 0163/1125] Flake: add school role to Archie --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 451b953..dfa59fa 100755 --- a/flake.nix +++ b/flake.nix @@ -86,6 +86,7 @@ outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager- ./roles/desktop ./roles/kde ./roles/gaming + ./roles/school ./machines/Archie ]; }; From 6cf28e30a728afa26642b0faa30b47c83b8d035b Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 28 Sep 2023 13:42:23 +0200 Subject: [PATCH 0164/1125] Flatpak: install flathub using systemd service --- roles/desktop/services/flatpak.nix | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/roles/desktop/services/flatpak.nix b/roles/desktop/services/flatpak.nix index fa658bf..3ff7152 100644 --- a/roles/desktop/services/flatpak.nix +++ b/roles/desktop/services/flatpak.nix @@ -2,11 +2,18 @@ { services.flatpak.enable = true; - system.activationScripts = { - flatpak.text = '' - echo "adding flatpak repos..." - repo=${pkgs.fetchurl { url = "https://dl.flathub.org/repo/flathub.flatpakrepo"; hash = "sha256-M3HdJQ5h2eFjNjAHP+/aFTzUQm9y9K+gwzc64uj+oDo="; } } - ${pkgs.flatpak}/bin/flatpak remote-add --if-not-exists flathub $repo - ''; + + /* + Create systemd service that adds flathub after getting network + This adds it automatically, which avoids the whack ass way I was + doing that before + */ + systemd.services.flathub-add = { + description = "Add flathub repo to system flatpak install"; + script = "${pkgs.flatpak}/bin/flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo"; + serviceConfig.Type = "oneshot"; + wantedBy = [ "network-online.target" ]; + # Run after networking is working + after = [ "NetworkManager-wait-online.service" ]; }; } From 50766db8c99583269850de3dcead5b189b065c36 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 28 Sep 2023 18:24:07 +0200 Subject: [PATCH 0165/1125] Desktop: enable printing --- roles/desktop/services/default.nix | 1 + roles/desktop/services/printing.nix | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 roles/desktop/services/printing.nix diff --git a/roles/desktop/services/default.nix b/roles/desktop/services/default.nix index 690505c..d2031da 100644 --- a/roles/desktop/services/default.nix +++ b/roles/desktop/services/default.nix @@ -6,5 +6,6 @@ ./flatpak.nix ./syncthing.nix ./pipewire.nix + ./printing.nix ]; } diff --git a/roles/desktop/services/printing.nix b/roles/desktop/services/printing.nix new file mode 100644 index 0000000..f32c58f --- /dev/null +++ b/roles/desktop/services/printing.nix @@ -0,0 +1,9 @@ +{ config, ... }: + +{ + services.printing = { + enable = true; + startWhenNeeded = true; + stateless = true; + }; +} From 747c01370a5f8ac6fda89393d5dafada7dab3ae7 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 28 Sep 2023 18:24:25 +0200 Subject: [PATCH 0166/1125] Desktop: enable scanning --- roles/desktop/configuration.nix | 9 +++++++++ roles/desktop/default.nix | 1 + 2 files changed, 10 insertions(+) create mode 100644 roles/desktop/configuration.nix diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix new file mode 100644 index 0000000..dbff60d --- /dev/null +++ b/roles/desktop/configuration.nix @@ -0,0 +1,9 @@ +{ config, pkgs, ... }: + +{ + hardware.sane = { + enable = true; + extraBackends = [ pkgs.sane-airscan ]; + }; + users.users.toast.extraGroups = [ "scanner" ]; +} diff --git a/roles/desktop/default.nix b/roles/desktop/default.nix index cb3d38f..7933104 100644 --- a/roles/desktop/default.nix +++ b/roles/desktop/default.nix @@ -4,5 +4,6 @@ imports = [ ./services ./programs + ./configuration.nix ]; } From 8b6c91980fc97410a910d64e401d664e20996e08 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 1 Oct 2023 13:48:40 +0200 Subject: [PATCH 0167/1125] Flake: update lock file --- flake.lock | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index 81e6757..bb99cd7 100644 --- a/flake.lock +++ b/flake.lock @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1695224363, - "narHash": "sha256-+hfjJLUMck5G92RVFDZA7LWkR3kOxs5zQ7RPW9t3eM8=", + "lastModified": 1696145345, + "narHash": "sha256-3dM7I/d4751SLPJah0to1WBlWiyzIiuCEUwJqwBdmr4=", "owner": "nix-community", "repo": "home-manager", - "rev": "408ba13188ff9ce309fa2bdd2f81287d79773b00", + "rev": "6f9b5b83ad1f470b3d11b8a9fe1d5ef68c7d0e30", "type": "github" }, "original": { @@ -92,11 +92,11 @@ ] }, "locked": { - "lastModified": 1695152592, - "narHash": "sha256-AW4gs1IiQUOgnYs6N+v+6wWSQDKlwCBUJJ6aB0n9JPs=", + "lastModified": 1696061591, + "narHash": "sha256-fqbuMDAmLW9d2flWy14+3bvLW/QzLRs++BksXvlDDsE=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "e4e321a36922ee02682348b3e0eaa3c4a01deb31", + "rev": "399187a234cfc9c312f830fc44017beb0106f0d5", "type": "github" }, "original": { @@ -149,11 +149,11 @@ ] }, "locked": { - "lastModified": 1694921880, - "narHash": "sha256-yU36cs5UdzhTwsM9bUWUz43N//ELzQ1ro69C07pU/8E=", + "lastModified": 1696131323, + "narHash": "sha256-Y47r8Jo+9rs+XUWHcDPZtkQs6wFeZ24L4CQTfVwE+vY=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "9d2bcc47110b3b6217dfebd6761ba20bc78aedf2", + "rev": "031d4b22505fdea47bd53bfafad517cd03c26a4f", "type": "github" }, "original": { @@ -169,11 +169,11 @@ ] }, "locked": { - "lastModified": 1694921880, - "narHash": "sha256-yU36cs5UdzhTwsM9bUWUz43N//ELzQ1ro69C07pU/8E=", + "lastModified": 1696131323, + "narHash": "sha256-Y47r8Jo+9rs+XUWHcDPZtkQs6wFeZ24L4CQTfVwE+vY=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "9d2bcc47110b3b6217dfebd6761ba20bc78aedf2", + "rev": "031d4b22505fdea47bd53bfafad517cd03c26a4f", "type": "github" }, "original": { @@ -184,11 +184,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1695109627, - "narHash": "sha256-4rpyoVzmunIG6xWA/EonnSSqC69bDBzciFi6SjBze/0=", + "lastModified": 1695887975, + "narHash": "sha256-u3+5FR12dI305jCMb0fJNQx2qwoQ54lv1tPoEWp0hmg=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "cb4dc98f776ddb6af165e6f06b2902efe31ca67a", + "rev": "adcfd6aa860d1d129055039696bc457af7d50d0e", "type": "github" }, "original": { @@ -200,11 +200,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1695272228, - "narHash": "sha256-4uw2OdJPVyjdB+xcDst9SecrNIpxKXJ2usN3M5HVa7o=", + "lastModified": 1695825837, + "narHash": "sha256-4Ne11kNRnQsmSJCRSSNkFRSnHC4Y5gPDBIQGjjPfJiU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "55ac2a9d2024f15c56adf20da505b29659911da8", + "rev": "5cfafa12d57374f48bcc36fda3274ada276cf69e", "type": "github" }, "original": { @@ -215,11 +215,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1695145219, - "narHash": "sha256-Eoe9IHbvmo5wEDeJXKFOpKUwxYJIOxKUesounVccNYk=", + "lastModified": 1696019113, + "narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5ba549eafcf3e33405e5f66decd1a72356632b96", + "rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", "type": "github" }, "original": { From 43fb0b11695a22b31a6f0bf748eecef3bbaa0a9f Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 2 Oct 2023 11:11:23 +0200 Subject: [PATCH 0168/1125] SteamDeck: remove obsolete option --- machines/SteamDeck/configuration.nix | 8 -------- 1 file changed, 8 deletions(-) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index ea49bd9..bbf55b4 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -44,14 +44,6 @@ autoStart = true; user = "toast"; desktopSession = "plasmawayland"; - environment = { - /* - Steam already has a mangohud overlay, so this - avoids having two overlays at once - */ - MANGOHUD = "0"; - MANHOGUD_DLSYM = "0"; - }; }; decky-loader = { enable = true; From 1c9dced21cdac007582e785de61f08ff4aa9649e Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 2 Oct 2023 11:12:31 +0200 Subject: [PATCH 0169/1125] Mangohud: remove session variable workaround --- roles/gaming/mangohud.nix | 4 ---- 1 file changed, 4 deletions(-) diff --git a/roles/gaming/mangohud.nix b/roles/gaming/mangohud.nix index 47b37be..fe418d4 100644 --- a/roles/gaming/mangohud.nix +++ b/roles/gaming/mangohud.nix @@ -1,14 +1,10 @@ { config, ... }: { - # This does the same as enableSessionWide does on the mangohud config - environment.sessionVariables = { MANGOHUD = "1"; MANGOHUD_DLSYM = "1"; }; - home-manager.users.toast = { config, ... }: { programs.mangohud = { enable = true; - # TODO: fix envvars set by home manager not applying for some reason # This only works for Vulkan, openGL programs still need the mangohud wrapper enableSessionWide = true; settings = { From efbba16fea3646f534a2b40e3e0b7c03ef14d4a0 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 2 Oct 2023 12:06:59 +0200 Subject: [PATCH 0170/1125] School: enable mysql --- roles/school/services/default.nix | 1 + roles/school/services/mysql.nix | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 roles/school/services/mysql.nix diff --git a/roles/school/services/default.nix b/roles/school/services/default.nix index 69a706a..1e5b9bb 100644 --- a/roles/school/services/default.nix +++ b/roles/school/services/default.nix @@ -3,5 +3,6 @@ { imports = [ ./syncthing.nix + ./mysql.nix ]; } diff --git a/roles/school/services/mysql.nix b/roles/school/services/mysql.nix new file mode 100644 index 0000000..6387afa --- /dev/null +++ b/roles/school/services/mysql.nix @@ -0,0 +1,12 @@ +{ config, pkgs, ... }: + +{ + services.mysql = { + enable = true; + package = pkgs.mysql80; + user = "toast"; + group = "users"; + }; + + environment.systemPackages = [ pkgs.mysql-workbench ]; +} From caff869c81c343a4a76ce03345b9c1c011720ffc Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 2 Oct 2023 12:49:19 +0200 Subject: [PATCH 0171/1125] Pseint: make wrapper run wxPSeInt --- pkgs/pseint.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pseint.nix b/pkgs/pseint.nix index bb33842..037dcaa 100644 --- a/pkgs/pseint.nix +++ b/pkgs/pseint.nix @@ -33,7 +33,7 @@ stdenv.mkDerivation rec { mkdir -p $out/opt/${pname}/ $out/bin/ cp -rv bin/* $out/opt/${pname}/ - makeBinaryWrapper $out/opt/${pname}/pseint $out/bin/pseint + makeBinaryWrapper $out/opt/${pname}/wxPSeInt $out/bin/pseint runHook postInstall ''; From 2040a00a022052b2a971e5aa0c41175aa63fe6fd Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 2 Oct 2023 12:49:40 +0200 Subject: [PATCH 0172/1125] Pseint: make desktop file with icons --- pkgs/pseint.nix | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/pkgs/pseint.nix b/pkgs/pseint.nix index 037dcaa..2351d94 100644 --- a/pkgs/pseint.nix +++ b/pkgs/pseint.nix @@ -7,6 +7,7 @@ , libGLU , gsettings-desktop-schemas , makeBinaryWrapper +, makeDesktopItem , wrapGAppsHook }: # Based on https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=pseint @@ -18,7 +19,6 @@ stdenv.mkDerivation rec { url = "https://netactuate.dl.sourceforge.net/project/${pname}/${version}/${pname}-src-${version}.tgz"; hash = "sha256-8zc7CtDQ9RjXLAVQTigstPqdDJsR8ffBopxBFzVP+eI="; }; - enableParallelBuilding = true; buildInputs = [ wxGTK32 libglvnd libGLU libX11 gsettings-desktop-schemas ]; @@ -31,13 +31,29 @@ stdenv.mkDerivation rec { installPhase = '' runHook preInstall - mkdir -p $out/opt/${pname}/ $out/bin/ + mkdir -p $out/opt/${pname}/ $out/bin/ $out/share/icons/hicolor/{16x16,32x32,48x48,64x64,128x128} cp -rv bin/* $out/opt/${pname}/ makeBinaryWrapper $out/opt/${pname}/wxPSeInt $out/bin/pseint + cp -rv bin/imgs/icon16.png $out/share/icons/hicolor/16x16/pseint.png + cp -rv bin/imgs/icon32.png $out/share/icons/hicolor/32x32/pseint.png + cp -rv bin/imgs/icon48.png $out/share/icons/hicolor/48x48/pseint.png + cp -rv bin/imgs/icon64.png $out/share/icons/hicolor/64x64/pseint.png + cp -rv bin/imgs/icon128.png $out/share/icons/hicolor/128x128/pseint.png + cp -rv "${desktopItem}/share/applications" "$out/share" runHook postInstall ''; + desktopItem = makeDesktopItem { + name = pname; + desktopName = "PSeInt"; + exec = "pseint"; + icon = "pseint"; + genericName = meta.description; + categories = [ "Development" ]; + }; + + meta = with lib; { description = "A tool for learning programming basis with a simple spanish pseudocode"; homepage = "https://pseint.sourceforge.net/"; From 190044ee8fdd5619929f861882afdbbf00f6395e Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 3 Oct 2023 00:20:19 +0200 Subject: [PATCH 0173/1125] School: share school things folder with Archie --- roles/school/services/syncthing.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/school/services/syncthing.nix b/roles/school/services/syncthing.nix index 30ea20a..aac049a 100644 --- a/roles/school/services/syncthing.nix +++ b/roles/school/services/syncthing.nix @@ -5,7 +5,7 @@ "school-things" = { label = "School things"; id = "z6alc-nfoqr"; - devices = [ "steamdeck" "server" ]; + devices = [ "steamdeck" "server" "pc" ]; path = "~/Documents/School things"; }; }; From ca7dd48db3b25b911b77317ea95c3f0a71a26093 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 3 Oct 2023 00:36:14 +0200 Subject: [PATCH 0174/1125] Gaming: restructure role --- roles/gaming/default.nix | 5 ++--- roles/gaming/programs/default.nix | 9 +++++++++ roles/gaming/{ => programs}/mangohud.nix | 0 roles/gaming/{ => programs}/rpcs3.nix | 0 roles/gaming/{ => programs}/steam.nix | 0 roles/gaming/services/default.nix | 5 +++++ 6 files changed, 16 insertions(+), 3 deletions(-) mode change 100755 => 100644 roles/gaming/default.nix create mode 100755 roles/gaming/programs/default.nix rename roles/gaming/{ => programs}/mangohud.nix (100%) rename roles/gaming/{ => programs}/rpcs3.nix (100%) rename roles/gaming/{ => programs}/steam.nix (100%) create mode 100644 roles/gaming/services/default.nix diff --git a/roles/gaming/default.nix b/roles/gaming/default.nix old mode 100755 new mode 100644 index dc70b10..cccac83 --- a/roles/gaming/default.nix +++ b/roles/gaming/default.nix @@ -2,8 +2,7 @@ { imports = [ - ./steam.nix - ./mangohud.nix - ./rpcs3.nix + ./programs + ./services ]; } diff --git a/roles/gaming/programs/default.nix b/roles/gaming/programs/default.nix new file mode 100755 index 0000000..dc70b10 --- /dev/null +++ b/roles/gaming/programs/default.nix @@ -0,0 +1,9 @@ +{ ... }: + +{ + imports = [ + ./steam.nix + ./mangohud.nix + ./rpcs3.nix + ]; +} diff --git a/roles/gaming/mangohud.nix b/roles/gaming/programs/mangohud.nix similarity index 100% rename from roles/gaming/mangohud.nix rename to roles/gaming/programs/mangohud.nix diff --git a/roles/gaming/rpcs3.nix b/roles/gaming/programs/rpcs3.nix similarity index 100% rename from roles/gaming/rpcs3.nix rename to roles/gaming/programs/rpcs3.nix diff --git a/roles/gaming/steam.nix b/roles/gaming/programs/steam.nix similarity index 100% rename from roles/gaming/steam.nix rename to roles/gaming/programs/steam.nix diff --git a/roles/gaming/services/default.nix b/roles/gaming/services/default.nix new file mode 100644 index 0000000..d8147ea --- /dev/null +++ b/roles/gaming/services/default.nix @@ -0,0 +1,5 @@ +{ ... }: + +{ + +} From 5fc18d212f5307cf8a056ff91de3c9d7a5bd541d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 3 Oct 2023 01:39:13 +0200 Subject: [PATCH 0175/1125] Gaming: configure syncthiing --- roles/gaming/services/default.nix | 4 +++- roles/gaming/services/syncthing.nix | 21 +++++++++++++++++++++ roles/server/syncthing.nix | 6 ++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 roles/gaming/services/syncthing.nix diff --git a/roles/gaming/services/default.nix b/roles/gaming/services/default.nix index d8147ea..69a706a 100644 --- a/roles/gaming/services/default.nix +++ b/roles/gaming/services/default.nix @@ -1,5 +1,7 @@ { ... }: { - + imports = [ + ./syncthing.nix + ]; } diff --git a/roles/gaming/services/syncthing.nix b/roles/gaming/services/syncthing.nix new file mode 100644 index 0000000..d275d88 --- /dev/null +++ b/roles/gaming/services/syncthing.nix @@ -0,0 +1,21 @@ +{ config, ... }: + +{ + /* + This file will sync saves for games that don't have cloud saves + TODO: turn this into a module eventually + */ + + services.syncthing.folders = { + "steam-201810" = { + label = "Wolfenstein The New Order Saves"; + id = "laxxf-t2wmy"; + devices = [ "steamdeck" "server" "pc" ]; + path = "~/.local/share/Steam/steamapps/compatdata/201810/pfx/drive_c/users/steamuser/Saved Games/MachineGames/Wolfenstein The New Order/"; + }; + }; + home-manager.users.toast.home.file."steam-201810-ignore" = { + target = ".local/share/Steam/steamapps/compatdata/201810/pfx/drive_c/users/steamuser/Saved Games/MachineGames/Wolfenstein The New Order/.stignore"; + text = "base/qconsole.log\nbase/wolfConfig.cfg"; + }; +} diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 8e0cc71..2f3ca48 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -21,6 +21,12 @@ devices = [ "steamdeck" "server" ]; path = "${config.services.syncthing.dataDir}/school-things"; }; + "steam-201810" = { + label = "Wolfenstein The New Order Saves"; + id = "laxxf-t2wmy"; + devices = [ "steamdeck" "server" "pc" ]; + path = "${config.services.syncthing.dataDir}/steam-201810"; + }; }; }; systemd.services.syncthing.serviceConfig = { From 3ecf51580d0c30fcda93c809b445ba43944293d6 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 3 Oct 2023 01:40:07 +0200 Subject: [PATCH 0176/1125] Server: make Everest share school-things folder with Archie --- roles/server/syncthing.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 2f3ca48..9c84f89 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -18,7 +18,7 @@ "school-things" = { label = "School things"; id = "z6alc-nfoqr"; - devices = [ "steamdeck" "server" ]; + devices = [ "steamdeck" "server" "pc"]; path = "${config.services.syncthing.dataDir}/school-things"; }; "steam-201810" = { From a595d97675934c7497f1b3fc97e0e47b3572e225 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 3 Oct 2023 09:42:45 +0200 Subject: [PATCH 0177/1125] Mysql: fix indentation --- roles/school/services/mysql.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/school/services/mysql.nix b/roles/school/services/mysql.nix index 6387afa..f9b43d0 100644 --- a/roles/school/services/mysql.nix +++ b/roles/school/services/mysql.nix @@ -3,9 +3,9 @@ { services.mysql = { enable = true; - package = pkgs.mysql80; - user = "toast"; - group = "users"; + package = pkgs.mysql80; + user = "toast"; + group = "users"; }; environment.systemPackages = [ pkgs.mysql-workbench ]; From e6b7c624af488bb67cb560b2b8b75f036c68ff1b Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 3 Oct 2023 09:56:29 +0200 Subject: [PATCH 0178/1125] Mysql: don't autostart service --- roles/school/services/mysql.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/school/services/mysql.nix b/roles/school/services/mysql.nix index f9b43d0..ad930fe 100644 --- a/roles/school/services/mysql.nix +++ b/roles/school/services/mysql.nix @@ -1,4 +1,4 @@ -{ config, pkgs, ... }: +{ config, pkgs, lib, ... }: { services.mysql = { @@ -8,5 +8,8 @@ group = "users"; }; + # Don't autostart MySQL + systemd.services.mysql.wantedBy = lib.mkForce []; + environment.systemPackages = [ pkgs.mysql-workbench ]; } From 2d22bdf0131a0df478bc7e30f02d73646d3c33eb Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 4 Oct 2023 12:04:44 +0200 Subject: [PATCH 0179/1125] School: install intellij ultimate --- roles/school/programs/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 77b1415..9783006 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -7,6 +7,7 @@ environment.systemPackages = with pkgs; [ dia + jetbrains.idea-ultimate flakeSelf.packages.x86_64-linux.pseint ]; } From f753d6787429dcd7468c7eaab4a8d577b3a4eb20 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 5 Oct 2023 10:13:06 +0200 Subject: [PATCH 0180/1125] Gaming: install Heroic games launcher --- roles/gaming/programs/default.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/gaming/programs/default.nix b/roles/gaming/programs/default.nix index dc70b10..ad5e946 100755 --- a/roles/gaming/programs/default.nix +++ b/roles/gaming/programs/default.nix @@ -1,4 +1,4 @@ -{ ... }: +{ config, pkgs, ... }: { imports = [ @@ -6,4 +6,7 @@ ./mangohud.nix ./rpcs3.nix ]; + environment.systemPackages = with pkgs; [ + heroic + ]; } From f2a3cbdbf656dca2927e2592fdd4f5293c543fd1 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 5 Oct 2023 12:47:23 +0200 Subject: [PATCH 0181/1125] Common: enable and configure Git --- roles/common/programs/default.nix | 1 + roles/common/programs/git.nix | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 roles/common/programs/git.nix diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index 1aa9c89..4d89ef0 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -9,6 +9,7 @@ ./command-not-found.nix ./comma.nix ./bash.nix + ./git.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix new file mode 100644 index 0000000..7a3e2bd --- /dev/null +++ b/roles/common/programs/git.nix @@ -0,0 +1,15 @@ +{ config, pkgs, ... }: + +{ + home-manager.users.toast = { + programs.git = { + enable = true; + delta.enable = true; + extraConfig = { + init.defaultBranch = "main"; + pull.rebase = "interactive"; + }; + }; + }; +} + From e67ace042de3a832410b7e8a60dcd9cf2ded58a9 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 5 Oct 2023 12:53:54 +0200 Subject: [PATCH 0182/1125] Kate: set kwrite as the default program for text files --- roles/kde/programs/kate.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/kde/programs/kate.nix b/roles/kde/programs/kate.nix index 99b1e5d..9379ba5 100644 --- a/roles/kde/programs/kate.nix +++ b/roles/kde/programs/kate.nix @@ -2,4 +2,9 @@ { environment.systemPackages = [ pkgs.kate ]; + + # Use kwrite to open text files, and kate if I'm developing stuff + xdg.mime.defaultApplications = { + "text/plain" = "org.kde.kwrite.desktop"; + }; } From c47e8216d5d70743f41a890ec90d98b576a067ae Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 6 Oct 2023 10:26:03 +0200 Subject: [PATCH 0183/1125] Mysql: allow user to start/stop service --- roles/school/services/mysql.nix | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/roles/school/services/mysql.nix b/roles/school/services/mysql.nix index ad930fe..49d686d 100644 --- a/roles/school/services/mysql.nix +++ b/roles/school/services/mysql.nix @@ -11,5 +11,20 @@ # Don't autostart MySQL systemd.services.mysql.wantedBy = lib.mkForce []; + # Allow regular users to start/stop mysql + # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if ( + action.id == "org.freedesktop.systemd1.manage-units" && + action.lookup("unit") == "mysql.service" && + subject.user == "${config.services.mysql.user}" + ) + { + return polkit.Result.YES; + } + }) + ''; + environment.systemPackages = [ pkgs.mysql-workbench ]; } From 1138343be820def711f3a370fe353fd4f7622f17 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 9 Oct 2023 19:51:53 +0200 Subject: [PATCH 0184/1125] Common: set configurationRevision to dirty if dirtyRev doesn't exist --- roles/common/configuration.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index d198309..e9ca5f1 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -99,7 +99,8 @@ system = { stateVersion = "23.05"; - configurationRevision = flakeSelf.sourceInfo.rev or flakeSelf.sourceInfo.dirtyRev; + # Nix on nixos 23.05 does not have dirtyRev + configurationRevision = flakeSelf.sourceInfo.rev or flakeSelf.sourceInfo.dirtyRev or "dirty"; nixos.variant_id = lib.strings.toLower config.networking.hostName; }; } From feec9e898e3e0bebe8772ac375628039716bb3f5 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 9 Oct 2023 20:22:50 +0200 Subject: [PATCH 0185/1125] Flake: update lock file --- flake.lock | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/flake.lock b/flake.lock index bb99cd7..b7af7c7 100644 --- a/flake.lock +++ b/flake.lock @@ -9,11 +9,11 @@ ] }, "locked": { - "lastModified": 1695384796, + "lastModified": 1696775529, "narHash": "sha256-TYlE4B0ktPtlJJF9IFxTWrEeq+XKG8Ny0gc2FGEAdj0=", "owner": "ryantm", "repo": "agenix", - "rev": "1f677b3e161d3bdbfd08a939e8f25de2568e0ef4", + "rev": "daf42cb35b2dc614d1551e37f96406e4c4a2d3e4", "type": "github" }, "original": { @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1696145345, - "narHash": "sha256-3dM7I/d4751SLPJah0to1WBlWiyzIiuCEUwJqwBdmr4=", + "lastModified": 1696737557, + "narHash": "sha256-YD/pjDjj/BNmisEvRdM/vspkCU3xyyeGVAUWhvVSi5Y=", "owner": "nix-community", "repo": "home-manager", - "rev": "6f9b5b83ad1f470b3d11b8a9fe1d5ef68c7d0e30", + "rev": "3c1d8758ac3f55ab96dcaf4d271c39da4b6e836d", "type": "github" }, "original": { @@ -92,11 +92,11 @@ ] }, "locked": { - "lastModified": 1696061591, - "narHash": "sha256-fqbuMDAmLW9d2flWy14+3bvLW/QzLRs++BksXvlDDsE=", + "lastModified": 1696680633, + "narHash": "sha256-773+wE1zvOePToAuR0dbQ/xyyev8Qh7TDp4DY9TzQ+4=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "399187a234cfc9c312f830fc44017beb0106f0d5", + "rev": "73ce8be67aee67fceef3e959a8922475cdcb7ba5", "type": "github" }, "original": { @@ -149,11 +149,11 @@ ] }, "locked": { - "lastModified": 1696131323, - "narHash": "sha256-Y47r8Jo+9rs+XUWHcDPZtkQs6wFeZ24L4CQTfVwE+vY=", + "lastModified": 1696736548, + "narHash": "sha256-Dg0gJ9xVXud55sAbXspMapFYZOpVAldQQo7MFp91Vb0=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "031d4b22505fdea47bd53bfafad517cd03c26a4f", + "rev": "2902dc66f64f733bfb45754e984e958e9fe7faf9", "type": "github" }, "original": { @@ -169,11 +169,11 @@ ] }, "locked": { - "lastModified": 1696131323, - "narHash": "sha256-Y47r8Jo+9rs+XUWHcDPZtkQs6wFeZ24L4CQTfVwE+vY=", + "lastModified": 1696736548, + "narHash": "sha256-Dg0gJ9xVXud55sAbXspMapFYZOpVAldQQo7MFp91Vb0=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "031d4b22505fdea47bd53bfafad517cd03c26a4f", + "rev": "2902dc66f64f733bfb45754e984e958e9fe7faf9", "type": "github" }, "original": { @@ -184,11 +184,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1695887975, - "narHash": "sha256-u3+5FR12dI305jCMb0fJNQx2qwoQ54lv1tPoEWp0hmg=", + "lastModified": 1696614066, + "narHash": "sha256-nAyYhO7TCr1tikacP37O9FnGr2USOsVBD3IgvndUYjM=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "adcfd6aa860d1d129055039696bc457af7d50d0e", + "rev": "bb2db418b616fea536b1be7f6ee72fb45c11afe0", "type": "github" }, "original": { @@ -200,11 +200,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1695825837, - "narHash": "sha256-4Ne11kNRnQsmSJCRSSNkFRSnHC4Y5gPDBIQGjjPfJiU=", + "lastModified": 1696697597, + "narHash": "sha256-q26Qv4DQ+h6IeozF2o1secyQG0jt2VUT3V0K58jr3pg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5cfafa12d57374f48bcc36fda3274ada276cf69e", + "rev": "5a237aecb57296f67276ac9ab296a41c23981f56", "type": "github" }, "original": { @@ -215,11 +215,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1696019113, - "narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", + "lastModified": 1696604326, + "narHash": "sha256-YXUNI0kLEcI5g8lqGMb0nh67fY9f2YoJsILafh6zlMo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", + "rev": "87828a0e03d1418e848d3dd3f3014a632e4a4f64", "type": "github" }, "original": { From fd1efa3aec15742f003254b427102b1e3cf12f6a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 6 Oct 2023 11:16:12 +0200 Subject: [PATCH 0186/1125] MySQL: install mycli --- roles/school/services/mysql.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/school/services/mysql.nix b/roles/school/services/mysql.nix index 49d686d..c4e08e9 100644 --- a/roles/school/services/mysql.nix +++ b/roles/school/services/mysql.nix @@ -26,5 +26,8 @@ }) ''; - environment.systemPackages = [ pkgs.mysql-workbench ]; + environment.systemPackages = with pkgs; [ + mysql-workbench + mycli + ]; } From 95c929bdf73f5730e8cc65dc3c412be05ceebcb8 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 6 Oct 2023 12:13:34 +0200 Subject: [PATCH 0187/1125] School: move intellij idea config to it's own file --- roles/school/programs/default.nix | 2 +- roles/school/programs/idea.nix | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 roles/school/programs/idea.nix diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 9783006..2c5fd21 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -3,11 +3,11 @@ { imports = [ ./virtualbox.nix + ./idea.nix ]; environment.systemPackages = with pkgs; [ dia - jetbrains.idea-ultimate flakeSelf.packages.x86_64-linux.pseint ]; } diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix new file mode 100644 index 0000000..4903bff --- /dev/null +++ b/roles/school/programs/idea.nix @@ -0,0 +1,7 @@ + { config, pkgs, flakeSelf, ... }: + +{ + environment.systemPackages = with pkgs; with jetbrains; [ + idea-ultimate + ]; +} From 46e73a0765263efc306af780a39aabda5ddafb77 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 6 Oct 2023 13:24:46 +0200 Subject: [PATCH 0188/1125] Intellij: remove unused parameter --- roles/school/programs/idea.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index 4903bff..3f363e2 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -1,4 +1,4 @@ - { config, pkgs, flakeSelf, ... }: + { config, pkgs, ... }: { environment.systemPackages = with pkgs; with jetbrains; [ From 69ae27e713f89577130bb2007a48f3a6fb31835e Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 6 Oct 2023 13:25:41 +0200 Subject: [PATCH 0189/1125] Intellij: configure jdk8 as default java version --- roles/school/programs/idea.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index 3f363e2..65b355c 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -1,6 +1,11 @@ { config, pkgs, ... }: { + programs.java = { + enable = true; + package = pkgs.jdk8; + }; + environment.systemPackages = with pkgs; with jetbrains; [ idea-ultimate ]; From 006ff76290d20c61b782aba20cf9a9826adeeae9 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Oct 2023 10:10:36 +0200 Subject: [PATCH 0190/1125] Intellij: install catppuccin plugin --- roles/school/programs/idea.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index 65b355c..68da13b 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -9,4 +9,12 @@ environment.systemPackages = with pkgs; with jetbrains; [ idea-ultimate ]; + + home-manager.users.toast = { + # Install plugins + home.file.".local/share/JetBrains/IntelliJIdea2023.2/catppuccin.jar".source = builtins.fetchurl { + url = "https://github.com/catppuccin/jetbrains/releases/download/v2.2.0/Catppuccin.Theme-2.2.0.jar"; + sha256 = "143jrhdfg7q24mnnzgqwgxq4glsxznxc6awcifpghr9q6nw1hfi0"; + }; + }; } From d3706f28ee95c8cf044f3238548af86a7b7c8877 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Oct 2023 10:15:43 +0200 Subject: [PATCH 0191/1125] Git: enable verbose commits --- roles/common/programs/git.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index 7a3e2bd..f5bce60 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -8,6 +8,7 @@ extraConfig = { init.defaultBranch = "main"; pull.rebase = "interactive"; + commit.verbose = "true"; }; }; }; From 0c053bde9c7032b7394951c68aac1116fbdd457a Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Oct 2023 20:17:06 +0200 Subject: [PATCH 0192/1125] Kde: install skanpage if scanning is enabled --- roles/kde/programs/default.nix | 1 + roles/kde/programs/skanpage.nix | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 roles/kde/programs/skanpage.nix diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index fe5c43b..198af46 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -4,5 +4,6 @@ imports = [ ./kate.nix ./firefox.nix + ./skanpage.nix ]; } diff --git a/roles/kde/programs/skanpage.nix b/roles/kde/programs/skanpage.nix new file mode 100644 index 0000000..508a7da --- /dev/null +++ b/roles/kde/programs/skanpage.nix @@ -0,0 +1,9 @@ +{ config, lib, pkgs, ... }: + +{ + # Only install skanpage if scanning is set up + config = lib.mkIf config.hardware.sane.enable { + environment.systemPackages = [ pkgs.skanpage ]; + }; +# environment.systemPackages = if config.hardware.sane.enable == true then [ pkgs.skanpage ] else []; +} From 3527a25625fd7b5fcbb75f4c8a24ed13e9aed026 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Oct 2023 21:40:51 +0200 Subject: [PATCH 0193/1125] Desktop: add commment and fix formatting in configuration.nix --- roles/desktop/configuration.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index dbff60d..1e59015 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -1,9 +1,10 @@ { config, pkgs, ... }: { + # Enable scanning hardware.sane = { - enable = true; - extraBackends = [ pkgs.sane-airscan ]; + enable = true; + extraBackends = [ pkgs.sane-airscan ]; }; users.users.toast.extraGroups = [ "scanner" ]; } From 330b2033960320406e7758dd486a524b33076952 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Oct 2023 22:53:10 +0200 Subject: [PATCH 0194/1125] Desktop: set up fonts --- roles/desktop/configuration.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index 1e59015..b44d58b 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -7,4 +7,10 @@ extraBackends = [ pkgs.sane-airscan ]; }; users.users.toast.extraGroups = [ "scanner" ]; + + # Set up fonts + fonts.fonts = [ + ( pkgs.nerdfonts.override { fonts = [ "Hack" "JetBrainsMono" ]; } ) + ]; + } From 5e8f1f823214c1cd341dc05547bf29ffcdf3a5ec Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Oct 2023 23:11:01 +0200 Subject: [PATCH 0195/1125] Common: enable starship --- roles/common/programs/default.nix | 1 + roles/common/programs/starship.nix | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 roles/common/programs/starship.nix diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index 4d89ef0..53af6f3 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -10,6 +10,7 @@ ./comma.nix ./bash.nix ./git.nix + ./starship.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix new file mode 100644 index 0000000..81340bf --- /dev/null +++ b/roles/common/programs/starship.nix @@ -0,0 +1,7 @@ +{ config, ... }: + +{ + programs.starship = { + enable = true; + }; +} From 5ec3c1c0689f847e72988a5cc0a95fb0f2408ff6 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 11 Oct 2023 00:49:37 +0200 Subject: [PATCH 0196/1125] Starship: enable and configure nix_shell module --- roles/common/programs/starship.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index 81340bf..7b33a20 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -3,5 +3,12 @@ { programs.starship = { enable = true; + settings = { + nix_shell = { + disabled = false; + heuristic = true; + symbol = ""; + }; + }; }; } From c5642afeb0b13625a3cf0c0350b4121eabb9c2d7 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 11 Oct 2023 01:03:39 +0200 Subject: [PATCH 0197/1125] Starship: add space after nix symbol --- roles/common/programs/starship.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index 7b33a20..c99d5c8 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -7,7 +7,7 @@ nix_shell = { disabled = false; heuristic = true; - symbol = ""; + symbol = " "; }; }; }; From 46433b513db78fd90d4685ddd100d2154ce25e79 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 11 Oct 2023 01:06:04 +0200 Subject: [PATCH 0198/1125] Starship: enable and configure os module --- roles/common/programs/starship.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index c99d5c8..897f159 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -9,6 +9,10 @@ heuristic = true; symbol = " "; }; + os = { + disabled = false; + symbols.NixOS = " "; + }; }; }; } From 4aeb6d4d537b7e73cf03cfbdbd12fea620e2ba5e Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 11 Oct 2023 01:15:35 +0200 Subject: [PATCH 0199/1125] Starship: enable and configure directory module --- roles/common/programs/starship.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index 897f159..9c9cd3b 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -13,6 +13,10 @@ disabled = false; symbols.NixOS = " "; }; + directory = { + disabled = false; + read_only = " 󰌾"; + }; }; }; } From a74a58ecfdf52e2f4eaf5c4fe7c3fce7f1a40691 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 11 Oct 2023 12:24:17 +0200 Subject: [PATCH 0200/1125] Flatpak: don't restart flathub-add service on configuration changes --- roles/desktop/services/flatpak.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/services/flatpak.nix b/roles/desktop/services/flatpak.nix index 3ff7152..daea0f7 100644 --- a/roles/desktop/services/flatpak.nix +++ b/roles/desktop/services/flatpak.nix @@ -15,5 +15,6 @@ wantedBy = [ "network-online.target" ]; # Run after networking is working after = [ "NetworkManager-wait-online.service" ]; + restartIfChanged = false; }; } From a11a7598fcfd725537ba0e805be5a4d25032b075 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 11 Oct 2023 17:23:08 +0200 Subject: [PATCH 0201/1125] Intellij: don't use system wide java --- roles/school/programs/idea.nix | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index 68da13b..2ee7f0c 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -1,11 +1,6 @@ { config, pkgs, ... }: { - programs.java = { - enable = true; - package = pkgs.jdk8; - }; - environment.systemPackages = with pkgs; with jetbrains; [ idea-ultimate ]; @@ -16,5 +11,12 @@ url = "https://github.com/catppuccin/jetbrains/releases/download/v2.2.0/Catppuccin.Theme-2.2.0.jar"; sha256 = "143jrhdfg7q24mnnzgqwgxq4glsxznxc6awcifpghr9q6nw1hfi0"; }; + + /* + If you use programs.java.enable intellij picks up the jdk package directly, which is not ideal + This adds the jdks I want to use to a directory intellij expects jdks to be + */ + home.file.".jdks/jdk8".source = "${pkgs.jdk8}/lib/openjdk"; + home.file.".jdks/jdk17".source = "${pkgs.jdk17}/lib/openjdk"; }; } From 6f7f8c5521063df204db3f8aaa37e61efb231d6a Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Oct 2023 12:13:21 +0200 Subject: [PATCH 0202/1125] Gaming: install prism launcher --- roles/gaming/programs/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/gaming/programs/default.nix b/roles/gaming/programs/default.nix index ad5e946..4bba376 100755 --- a/roles/gaming/programs/default.nix +++ b/roles/gaming/programs/default.nix @@ -8,5 +8,6 @@ ]; environment.systemPackages = with pkgs; [ heroic + prismlauncher-qt5 ]; } From 6249738563d941aeaed3ad496f5c2261c8d269f9 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Oct 2023 21:05:48 +0200 Subject: [PATCH 0203/1125] Flake: add anything-sync-daemon package --- flake.nix | 1 + pkgs/anything-sync-daemon/default.nix | 56 +++++++++++++++++++ .../disableDaemonStopTargets.patch | 23 ++++++++ 3 files changed, 80 insertions(+) create mode 100644 pkgs/anything-sync-daemon/default.nix create mode 100644 pkgs/anything-sync-daemon/disableDaemonStopTargets.patch diff --git a/flake.nix b/flake.nix index dfa59fa..7621b38 100755 --- a/flake.nix +++ b/flake.nix @@ -66,6 +66,7 @@ outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager- packages = { x86_64-linux = with import nixpkgs-unstable { system = "x86_64-linux"; }; { pseint = callPackage ./pkgs/pseint.nix {}; + anything-sync-daemon = callPackage ./pkgs/anything-sync-daemon {}; }; }; nixosConfigurations = { diff --git a/pkgs/anything-sync-daemon/default.nix b/pkgs/anything-sync-daemon/default.nix new file mode 100644 index 0000000..974bf9a --- /dev/null +++ b/pkgs/anything-sync-daemon/default.nix @@ -0,0 +1,56 @@ +{ stdenv +, lib +, fetchFromGitHub +, makeWrapper +, rsync +, gawk +, pv +, gnutar +, zstd +, util-linux +, coreutils +, gnugrep +, findutils +}: +stdenv.mkDerivation rec { + pname = "anything-sync-daemon"; + version = "6.0.0"; + + src = fetchFromGitHub { + owner = "graysky2"; + repo = pname; + rev = "v${version}"; + hash = "sha256-6nfaAMH5YgK6gimuZ8j1zWLTDOi11KIwW7Bf0Iwh7+I="; + }; + + patches = [ ./disableDaemonStopTargets.patch ]; + + nativeBuildInputs = [ makeWrapper ]; + + postPatch = '' + substituteInPlace init/asd* \ + --replace /usr/bin/anything-sync-daemon $out/bin/anything-sync-daemon + ''; + + enableParallelBuilding = true; + + makeFlags = [ + "DESTDIR=${placeholder "out"}" + "PREFIX=" + "INITDIR_SYSTEMD=/lib/systemd/system" + ]; + + installTargets = [ "install-systemd-all" ]; + + postInstall = '' + wrapProgram $out/bin/anything-sync-daemon \ + --suffix PATH : ${lib.makeBinPath [ rsync gawk pv gnutar zstd util-linux coreutils gnugrep findutils]} + ''; + + meta = with lib; { + description = "Symlinks and syncs user specified dirs to RAM"; + homepage = "https://github.com/graysky2/anything-sync-daemon/"; + license = lib.licenses.mit; + platforms = platforms.linux; + }; +} diff --git a/pkgs/anything-sync-daemon/disableDaemonStopTargets.patch b/pkgs/anything-sync-daemon/disableDaemonStopTargets.patch new file mode 100644 index 0000000..6dd71bd --- /dev/null +++ b/pkgs/anything-sync-daemon/disableDaemonStopTargets.patch @@ -0,0 +1,23 @@ +diff --git a/Makefile b/Makefile +index ddf2d73..827ea8f 100644 +--- a/Makefile ++++ b/Makefile +@@ -31,17 +31,7 @@ common/$(PN): Makefile common/$(PN).in + + help: install + +-stop-asd: +-ifneq ($(PREFIX), /usr) +- sudo -E asd unsync +-endif +- +-disable-systemd: +-ifeq ($(PREFIX), /usr) +- systemctl stop asd asd-resync || /bin/true +-endif +- +-install-bin: stop-asd disable-systemd common/$(PN) ++install-bin: common/$(PN) + $(Q)echo -e '\033[1;32mInstalling main script...\033[0m' + $(INSTALL_DIR) "$(DESTDIR)$(BINDIR)" + $(INSTALL_PROGRAM) common/$(PN) "$(DESTDIR)$(BINDIR)/$(PN)" From df662f7307429cc5aa31e1ef139d0173178419c2 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Oct 2023 22:52:41 +0200 Subject: [PATCH 0204/1125] Server: add minecraft server with anything-sync-daemon --- roles/server/default.nix | 1 + roles/server/minecraft.nix | 111 +++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 roles/server/minecraft.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index e75390f..075c012 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -15,5 +15,6 @@ ./wireguard.nix ./tailscale.nix ./traefik.nix + ./minecraft.nix ]; } diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix new file mode 100644 index 0000000..9adea0e --- /dev/null +++ b/roles/server/minecraft.nix @@ -0,0 +1,111 @@ +{ config, pkgs, flakeSelf, ... }: +let + atfc = builtins.fetchurl { + url = "https://www.curseforge.com/api/v1/mods/813246/files/4732590/download"; + sha256 = "0yl6ixmhfgqvcj3kfshpf8fy42vkkmjbn7d7yg86jx0ykiiq5f9x"; + }; + puffish_skills = builtins.fetchurl { + url = "https://www.curseforge.com/api/v1/mods/835091/files/4747353/download"; + sha256 = "0yl6ixmhfgqvcj3kfshpf8fy32vkkmjbn7d7yg86jx0ykiiq5f9x"; + }; + spark = builtins.fetchurl { + url = "https://www.curseforge.com/api/v1/mods/361579/files/4505375/download"; + sha256 = "1708lrx1nif0mvf7ambw8504j12wbn0vm69wsh21p8ylqpql1s4x"; + }; + + port = 25565; + users = config.users; +in +{ + users = { + groups.minecraft = { + members = [ "toast" ]; + gid = 987; + }; + users.atfc = { + isSystemUser = true; + uid = 988; + group = "minecraft"; + home = "/var/lib/minecraft/atfc"; + homeMode = "750"; + createHome = true; + }; + }; + + virtualisation.oci-containers = { + containers."minecraft-atfc" = { + autoStart = true; + image = "itzg/minecraft-server"; + #user = "${toString users.users.atfc.uid}:${toString users.groups.minecraft.gid}"; + environment = { + TZ = "Europe/Madrid"; + EULA = "true"; + TYPE = "forge"; + MEMORY = "2G"; + UID = toString users.users.atfc.uid; + GID = toString users.groups.minecraft.gid; + VERSION = "1.18.2"; + FORGE_VERSION = "40.2.10"; + GENERIC_PACK = "/modpack.zip"; + #USE_AIKAR_FLAGS = "true"; + + #STOP_DURATION = "70"; + STOP_SERVER_ANNOUNCE_DELAY = "20"; + + # server.properties + MOTD = "Toast's modded minecraft server"; + DIFFICULTY = "hard"; + SNOOPER_ENABLED = "false"; + SPAWN_PROTECTION = "0"; + LEVEL_TYPE = "tfc:tng"; + BROADCAST_CONSOLE_TO_OPS = "true"; + BROADCAST_RCON_TO_OPS = "true"; + + OPS = "b3ca4afb-a3da-4a78-85c3-2292fd0787e2,0cb3d02a-1d1f-4d7f-b70c-bd53dc155cff"; + EXISTING_OPS_FILE = "synchronize"; + + WHITELIST = "b3ca4afb-a3da-4a78-85c3-2292fd0787e2,0cb3d02a-1d1f-4d7f-b70c-bd53dc155cff,03f080e8-ce8e-4b90-a312-734747ce7db0,ea88f690-cf46-4416-bfd5-6f6b165885f7"; + EXISTING_WHITELIST_FILE = "synchronize"; + + # Auto pause needs this + MAX_TICK_TIME = "-1"; + AUTOPAUSE_KNOCK_INTERFACE = "tap0"; + ENABLE_AUTOPAUSE = "true"; + }; + extraOptions = [ + "--network=slirp4netns:port_handler=slirp4netns" + "--cap-add=CAP_NET_RAW" + ]; + + volumes = [ + "${atfc}:/modpack.zip" + "${puffish_skills}:/mods/puffish_skills.jar" + "${spark}:/mods/spark.jar" + "${users.users.atfc.home}:/data" + #"/tmp/minecraft:/data" + ]; + ports = [ "25565:${toString port}" ]; + }; + }; + + networking.firewall.allowedTCPPorts = [ port ]; + + # anything-sync-daemon config + systemd.packages = with pkgs; [ flakeSelf.packages.x86_64-linux.anything-sync-daemon ]; + environment.systemPackages = with pkgs; [ flakeSelf.packages.x86_64-linux.anything-sync-daemon ]; + fileSystems.minecraftTmpfs = { + device = "none"; + fsType = "tmpfs"; + mountPoint = "/mnt/minecraftTmpfs"; + options = [ "size=4G "]; + }; + environment.etc."asd.conf".text = +''WHATTOSYNC=('/var/lib/minecraft') +VOLATILE="${config.fileSystems.minecraftTmpfs.mountPoint}" +USE_OVERLAYFS="yes" ''; + systemd.services.asd = { + wantedBy = [ "podman-minecraft-atfc.service" ]; + before = [ "podman-minecraft-atfc.service" ]; + }; + +} From b856056d24b1e88f261a3e1a8499f5d45c987ab8 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Oct 2023 22:56:24 +0200 Subject: [PATCH 0205/1125] Minecraft: fix hash for puffish_skills --- roles/server/minecraft.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix index 9adea0e..14d46e0 100644 --- a/roles/server/minecraft.nix +++ b/roles/server/minecraft.nix @@ -6,7 +6,7 @@ let }; puffish_skills = builtins.fetchurl { url = "https://www.curseforge.com/api/v1/mods/835091/files/4747353/download"; - sha256 = "0yl6ixmhfgqvcj3kfshpf8fy32vkkmjbn7d7yg86jx0ykiiq5f9x"; + sha256 = "1pwx8zqih019l12lrmllrjv2al0mjzwj4p5qmc4ps1g555jy8qil"; }; spark = builtins.fetchurl { url = "https://www.curseforge.com/api/v1/mods/361579/files/4505375/download"; From a126250c44aff7759aeded8d5b704705ab2f0e40 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 19 Oct 2023 11:02:22 +0200 Subject: [PATCH 0206/1125] Firefox: enable physics based scrolling --- roles/desktop/programs/firefox.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index 6871b6f..89e1e27 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -37,6 +37,10 @@ "Value" = true; "Status" = "locked"; }; + "general.smoothScroll.msdPhysics.enabled" = { + "Value" = true; + "Status" = "default"; + }; }; "PromptForDownloadLocation" = true; # I use an external password manager, so the built in one just bothers me From 1deb7cf3c0ba5cfbc49134f620d71a24ede16869 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 20 Oct 2023 21:09:20 +0200 Subject: [PATCH 0207/1125] Everest: remove leftover configs --- flake.nix | 1 - openbox.nix | 24 ------------------------ 2 files changed, 25 deletions(-) delete mode 100755 openbox.nix diff --git a/flake.nix b/flake.nix index 7621b38..f6d05d8 100755 --- a/flake.nix +++ b/flake.nix @@ -134,7 +134,6 @@ outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager- ./roles/common ./roles/server ./machines/Everest - ./openbox.nix ]; }; }; diff --git a/openbox.nix b/openbox.nix deleted file mode 100755 index 505b90f..0000000 --- a/openbox.nix +++ /dev/null @@ -1,24 +0,0 @@ -{ config, pkgs, ... }: - -{ - services = { - xserver = { - enable = true; - autorun = false; - windowManager.openbox.enable = true; - }; - xrdp = { - enable = true; - openFirewall = true; - defaultWindowManager = "${pkgs.openbox}/bin/openbox-session"; - #confDir = "/etc/xrdp"; - }; - }; - environment.systemPackages = with pkgs; [ - pcmanfm - obconf - firefox - gnome.gnome-calculator - alacritty - ]; -} From 6683a3a161d2b51a0a3f263a0c2c8b20d5ccac03 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 20 Oct 2023 21:47:02 +0200 Subject: [PATCH 0208/1125] Flake: update lock file --- flake.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/flake.lock b/flake.lock index b7af7c7..8cb46e2 100644 --- a/flake.lock +++ b/flake.lock @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1696737557, - "narHash": "sha256-YD/pjDjj/BNmisEvRdM/vspkCU3xyyeGVAUWhvVSi5Y=", + "lastModified": 1697688028, + "narHash": "sha256-d9CAOd9W2iTrgB31a8Dvyp6Vgn/gxASCNrD4Z9yzUOY=", "owner": "nix-community", "repo": "home-manager", - "rev": "3c1d8758ac3f55ab96dcaf4d271c39da4b6e836d", + "rev": "c5c1ea85181d2bb44e46e8a944a8a3f56ad88f19", "type": "github" }, "original": { @@ -92,11 +92,11 @@ ] }, "locked": { - "lastModified": 1696680633, - "narHash": "sha256-773+wE1zvOePToAuR0dbQ/xyyev8Qh7TDp4DY9TzQ+4=", + "lastModified": 1697700248, + "narHash": "sha256-z45M6Fna2mR9zEK9fe9ng1XN+T7CvpmKBn/SaK9zwO4=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "73ce8be67aee67fceef3e959a8922475cdcb7ba5", + "rev": "2965d86926177af95af615a09138e0aaaaec56fa", "type": "github" }, "original": { @@ -129,11 +129,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1694622745, - "narHash": "sha256-z397+eDhKx9c2qNafL1xv75lC0Q4nOaFlhaU1TINqb8=", + "lastModified": 1697303681, + "narHash": "sha256-caJ0rXeagaih+xTgRduYtYKL1rZ9ylh06CIrt1w5B4g=", "owner": "nix-community", "repo": "impermanence", - "rev": "e9643d08d0d193a2e074a19d4d90c67a874d932e", + "rev": "0f317c2e9e56550ce12323eb39302d251618f5b5", "type": "github" }, "original": { @@ -149,11 +149,11 @@ ] }, "locked": { - "lastModified": 1696736548, - "narHash": "sha256-Dg0gJ9xVXud55sAbXspMapFYZOpVAldQQo7MFp91Vb0=", + "lastModified": 1697340827, + "narHash": "sha256-XlrR68N7jyaZ0bs8TPrhqcWG0IPG3pbjrKzJMpYOsos=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "2902dc66f64f733bfb45754e984e958e9fe7faf9", + "rev": "29977d0796c058bbcfb2df5b18eb5badf1711007", "type": "github" }, "original": { @@ -169,11 +169,11 @@ ] }, "locked": { - "lastModified": 1696736548, - "narHash": "sha256-Dg0gJ9xVXud55sAbXspMapFYZOpVAldQQo7MFp91Vb0=", + "lastModified": 1697340827, + "narHash": "sha256-XlrR68N7jyaZ0bs8TPrhqcWG0IPG3pbjrKzJMpYOsos=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "2902dc66f64f733bfb45754e984e958e9fe7faf9", + "rev": "29977d0796c058bbcfb2df5b18eb5badf1711007", "type": "github" }, "original": { @@ -184,11 +184,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1696614066, - "narHash": "sha256-nAyYhO7TCr1tikacP37O9FnGr2USOsVBD3IgvndUYjM=", + "lastModified": 1697748412, + "narHash": "sha256-5VSB63UE/O191cuZiGHbCJ9ipc7cGKB8cHp0cfusuyo=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "bb2db418b616fea536b1be7f6ee72fb45c11afe0", + "rev": "72d53d51704295f1645d20384cd13aecc182f624", "type": "github" }, "original": { @@ -200,11 +200,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1696697597, - "narHash": "sha256-q26Qv4DQ+h6IeozF2o1secyQG0jt2VUT3V0K58jr3pg=", + "lastModified": 1697655685, + "narHash": "sha256-79Kuv+QdgsVc+rkibuAgWHnh8IXrLBTOKg5nM0Qvux0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5a237aecb57296f67276ac9ab296a41c23981f56", + "rev": "80c1aab725151632ddc2a20caeb914e76dd0673c", "type": "github" }, "original": { @@ -215,11 +215,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1696604326, - "narHash": "sha256-YXUNI0kLEcI5g8lqGMb0nh67fY9f2YoJsILafh6zlMo=", + "lastModified": 1697456312, + "narHash": "sha256-roiSnrqb5r+ehnKCauPLugoU8S36KgmWraHgRqVYndo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "87828a0e03d1418e848d3dd3f3014a632e4a4f64", + "rev": "ca012a02bf8327be9e488546faecae5e05d7d749", "type": "github" }, "original": { From 605e3bd6304e90a4aafda3f5c98b32b17e680717 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 22 Oct 2023 03:00:45 +0200 Subject: [PATCH 0209/1125] Minecraft: change server settings --- roles/server/minecraft.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix index 14d46e0..50a01cc 100644 --- a/roles/server/minecraft.nix +++ b/roles/server/minecraft.nix @@ -50,7 +50,7 @@ in #USE_AIKAR_FLAGS = "true"; #STOP_DURATION = "70"; - STOP_SERVER_ANNOUNCE_DELAY = "20"; + STOP_SERVER_ANNOUNCE_DELAY = "25"; # server.properties MOTD = "Toast's modded minecraft server"; @@ -60,6 +60,10 @@ in LEVEL_TYPE = "tfc:tng"; BROADCAST_CONSOLE_TO_OPS = "true"; BROADCAST_RCON_TO_OPS = "true"; + VIEW_DISTANCE = "16"; + MAX_PLAYERS = "4"; + + RCON_CMDS_LAST_DISCONNECT = "save-all"; OPS = "b3ca4afb-a3da-4a78-85c3-2292fd0787e2,0cb3d02a-1d1f-4d7f-b70c-bd53dc155cff"; EXISTING_OPS_FILE = "synchronize"; From 33d16b58f175d6f04d2969160aff6de49dd7f483 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 22 Oct 2023 03:55:18 +0200 Subject: [PATCH 0210/1125] Kde: configure plasma with plasma-manager --- flake.lock | 26 +++++++++++++++++++++++++- flake.nix | 8 +++++++- roles/kde/plasma.nix | 9 ++++++++- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 8cb46e2..d23fa4a 100644 --- a/flake.lock +++ b/flake.lock @@ -228,6 +228,29 @@ "type": "indirect" } }, + "plasma-manager": { + "inputs": { + "home-manager": [ + "home-manager-unstable" + ], + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1690827734, + "narHash": "sha256-zcNLTSKGZ5zcx0RQkDKH4dN2MBx+KTfrYN7HfmD0N7c=", + "owner": "pjones", + "repo": "plasma-manager", + "rev": "b6241a2f7c625d0b0bee8e203d78232d0a6535e9", + "type": "github" + }, + "original": { + "owner": "pjones", + "repo": "plasma-manager", + "type": "github" + } + }, "root": { "inputs": { "agenix": "agenix", @@ -239,7 +262,8 @@ "nix-index-db-unstable": "nix-index-db-unstable", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", - "nixpkgs-unstable": "nixpkgs-unstable" + "nixpkgs-unstable": "nixpkgs-unstable", + "plasma-manager": "plasma-manager" } } }, diff --git a/flake.nix b/flake.nix index f6d05d8..4150c13 100755 --- a/flake.nix +++ b/flake.nix @@ -45,9 +45,15 @@ inputs = { url = "github:Mic92/nix-index-database"; inputs.nixpkgs.follows = "nixpkgs-unstable"; }; + + plasma-manager = { + url = "github:pjones/plasma-manager"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + inputs.home-manager.follows = "home-manager-unstable"; + }; }; -outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, nix-index-db, nix-index-db-unstable, jovian, ... } @inputs: { +outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, nix-index-db, nix-index-db-unstable, jovian, plasma-manager, ... } @inputs: { devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { name = "Environment for toast's nixos configurations"; diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 4cf16ee..0a04912 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -1,4 +1,4 @@ -{ config, pkgs, lib, ... }: +{ config, pkgs, lib, flakeSelf, ... }: let themeName = "Breeze"; @@ -129,4 +129,11 @@ in */ environment.systemPackages = [ breezeTint lookAndFeel plasmaDefaults ]; + # Plasma configs should be on all users + home-manager.sharedModules = [{ + imports = [ flakeSelf.inputs.plasma-manager.homeManagerModules.plasma-manager ]; + programs.plasma = { + enable = true; + }; + }]; } From 62ef357aff1c0a9338e75c4a2500b26321edeb56 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 22 Oct 2023 03:59:48 +0200 Subject: [PATCH 0211/1125] Kde: click item to select --- roles/kde/plasma.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 0a04912..db546fd 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -134,6 +134,7 @@ in imports = [ flakeSelf.inputs.plasma-manager.homeManagerModules.plasma-manager ]; programs.plasma = { enable = true; + workspace.clickItemTo = "select"; }; }]; } From 2e73463ebc2839b228647866434a1a57a8c98642 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 22 Oct 2023 04:08:20 +0200 Subject: [PATCH 0212/1125] Kde: add desktop switching shortcuts --- roles/kde/plasma.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index db546fd..c988aff 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -135,6 +135,12 @@ in programs.plasma = { enable = true; workspace.clickItemTo = "select"; + shortcuts = { + "kwin" = { + "Switch One Desktop to the Left" = [ "Meta+Ctrl+Left" ]; + "Switch One Desktop to the Right" = [ "Meta+Ctrl+Right" ]; + }; + }; }; }]; } From d0f8eab6c9631c2be3693c4d9a00bf403e11f6ec Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 22 Oct 2023 12:43:52 +0200 Subject: [PATCH 0213/1125] Kde: set up virtual desktops --- roles/kde/plasma.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index c988aff..f0ba955 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -141,6 +141,12 @@ in "Switch One Desktop to the Right" = [ "Meta+Ctrl+Right" ]; }; }; + configFile = { + "kwinrc"."Desktops" = { + "Number" = 2; + "Rows" = 1; + }; + }; }; }]; } From 6c14f4d0aa42cc59961afa1e0173706ec0c457c1 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 20 Oct 2023 10:58:03 +0200 Subject: [PATCH 0214/1125] Common: remove leftover space --- roles/common/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index e9ca5f1..52cb60e 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, flakeSelf, ... }: +{ config, lib, pkgs, flakeSelf, ... }: { environment = { From 4dd3b646f2df1db080df65d2e6d55ae40ccfc321 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 23 Oct 2023 10:49:17 +0200 Subject: [PATCH 0215/1125] Kde: change task switcher to thumbnail grid --- roles/kde/plasma.nix | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index f0ba955..d2e86dd 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -142,9 +142,12 @@ in }; }; configFile = { - "kwinrc"."Desktops" = { - "Number" = 2; - "Rows" = 1; + "kwinrc" = { + "Desktops" = { + "Number" = 2; + "Rows" = 1; + }; + "TabBox"."LayoutName" = "thumbnail_grid"; }; }; }; From 7e3dc3cb9755d18233adb08582ea0de58071903e Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 23 Oct 2023 11:50:10 +0200 Subject: [PATCH 0216/1125] Intellij: use fetchurl from pkgs instead of builtins --- roles/school/programs/idea.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index 2ee7f0c..6e06d17 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -1,13 +1,14 @@ { config, pkgs, ... }: +with pkgs; { - environment.systemPackages = with pkgs; with jetbrains; [ + environment.systemPackages = with jetbrains; [ idea-ultimate ]; home-manager.users.toast = { # Install plugins - home.file.".local/share/JetBrains/IntelliJIdea2023.2/catppuccin.jar".source = builtins.fetchurl { + home.file.".local/share/JetBrains/IntelliJIdea2023.2/catppuccin.jar".source = fetchurl { url = "https://github.com/catppuccin/jetbrains/releases/download/v2.2.0/Catppuccin.Theme-2.2.0.jar"; sha256 = "143jrhdfg7q24mnnzgqwgxq4glsxznxc6awcifpghr9q6nw1hfi0"; }; From 36928939d517e324036c0390eb1edb45d9ff9eb8 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 23 Oct 2023 12:22:27 +0200 Subject: [PATCH 0217/1125] Intellij: add rainbox-plugins plugin --- roles/school/programs/idea.nix | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index 6e06d17..d46c236 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -8,9 +8,15 @@ with pkgs; home-manager.users.toast = { # Install plugins - home.file.".local/share/JetBrains/IntelliJIdea2023.2/catppuccin.jar".source = fetchurl { - url = "https://github.com/catppuccin/jetbrains/releases/download/v2.2.0/Catppuccin.Theme-2.2.0.jar"; - sha256 = "143jrhdfg7q24mnnzgqwgxq4glsxznxc6awcifpghr9q6nw1hfi0"; + home.file = { + ".local/share/JetBrains/IntelliJIdea2023.2/catppuccin.jar".source = fetchurl { + url = "https://github.com/catppuccin/jetbrains/releases/download/v2.2.0/Catppuccin.Theme-2.2.0.jar"; + hash = "sha256:143jrhdfg7q24mnnzgqwgxq4glsxznxc6awcifpghr9q6nw1hfi0"; + }; + ".local/share/JetBrains/IntelliJIdea2023.2/rainbow-brackets".source = fetchzip { + url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/2023.3.6/intellij-rainbow-brackets-2023.3.6.zip"; + hash = "sha256-ZoBVRPZZn8QjXSLtskRtSpGoadc8KNKxsKvdcyNXT74"; + }; }; /* From a4ecb63da6917a41986a8a50958f963f9c30a4ad Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 23 Oct 2023 12:22:47 +0200 Subject: [PATCH 0218/1125] Intellij: remove leftover space --- roles/school/programs/idea.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index d46c236..bc13645 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -1,4 +1,4 @@ - { config, pkgs, ... }: +{ config, pkgs, ... }: with pkgs; { From 10fc83b906347e1ebf0447ab34cd3e6211294938 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 23 Oct 2023 12:42:58 +0200 Subject: [PATCH 0219/1125] Intellij: update catppuccin plugin --- roles/school/programs/idea.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index bc13645..8537e27 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -10,8 +10,8 @@ with pkgs; # Install plugins home.file = { ".local/share/JetBrains/IntelliJIdea2023.2/catppuccin.jar".source = fetchurl { - url = "https://github.com/catppuccin/jetbrains/releases/download/v2.2.0/Catppuccin.Theme-2.2.0.jar"; - hash = "sha256:143jrhdfg7q24mnnzgqwgxq4glsxznxc6awcifpghr9q6nw1hfi0"; + url = "https://github.com/catppuccin/jetbrains/releases/download/v3.0.0/Catppuccin.Theme-3.0.0.jar"; + hash = "sha256-tbcUtqA8wo9ZLjfkziRZiDTN748qWQ26A80pIJrTYuM"; }; ".local/share/JetBrains/IntelliJIdea2023.2/rainbow-brackets".source = fetchzip { url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/2023.3.6/intellij-rainbow-brackets-2023.3.6.zip"; From 4f5a944834fe42a1c03cecc2fd216431a17c951f Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 23 Oct 2023 13:27:57 +0200 Subject: [PATCH 0220/1125] Bat: configure using home-manager --- roles/common/programs/bat.nix | 9 +++++++++ roles/common/programs/default.nix | 2 ++ 2 files changed, 11 insertions(+) create mode 100644 roles/common/programs/bat.nix diff --git a/roles/common/programs/bat.nix b/roles/common/programs/bat.nix new file mode 100644 index 0000000..dd8020b --- /dev/null +++ b/roles/common/programs/bat.nix @@ -0,0 +1,9 @@ +{ config, ... }: + +{ + home-manager = { + users.toast.programs.bat = { + enable = true; + }; + }; +} diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index 53af6f3..0cf10fd 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -11,10 +11,12 @@ ./bash.nix ./git.nix ./starship.nix + ,/bat.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ speedtest-cli + # Bat has a home manager module, but I want it to be available system wide bat file nvd From 7505ddccb346951565698e88605801902754206f Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 23 Oct 2023 20:00:24 +0200 Subject: [PATCH 0221/1125] Bat: set catppuccin-mocha as the theme --- roles/common/programs/bat.nix | 16 +++++++++++++++- roles/common/programs/default.nix | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/roles/common/programs/bat.nix b/roles/common/programs/bat.nix index dd8020b..2075753 100644 --- a/roles/common/programs/bat.nix +++ b/roles/common/programs/bat.nix @@ -1,9 +1,23 @@ -{ config, ... }: +{ config, pkgs, ... }: { home-manager = { users.toast.programs.bat = { enable = true; + config = { + theme = "catppuccin-mocha"; + }; + themes = { + catppuccin-mocha = { + src = pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "bat"; + rev = "master"; + hash = "sha256-6WVKQErGdaqb++oaXnY3i6/GuH2FhTgK0v4TN4Y0Wbw="; + }; + file = "Catppuccin-mocha.tmTheme"; + }; + }; }; }; } diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index 0cf10fd..c6ab698 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -11,7 +11,7 @@ ./bash.nix ./git.nix ./starship.nix - ,/bat.nix + ./bat.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ From 5f5c16503a7a63065dd7eb74e270c5f0d81a1e75 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 24 Oct 2023 10:37:37 +0200 Subject: [PATCH 0222/1125] Intellij: update catppuccin plugin --- roles/school/programs/idea.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index 8537e27..a14d86b 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -10,8 +10,8 @@ with pkgs; # Install plugins home.file = { ".local/share/JetBrains/IntelliJIdea2023.2/catppuccin.jar".source = fetchurl { - url = "https://github.com/catppuccin/jetbrains/releases/download/v3.0.0/Catppuccin.Theme-3.0.0.jar"; - hash = "sha256-tbcUtqA8wo9ZLjfkziRZiDTN748qWQ26A80pIJrTYuM"; + url = "https://github.com/catppuccin/jetbrains/releases/download/v3.1.0/Catppuccin.Theme-3.1.0.jar"; + hash = "sha256-63fn3j57QBuwZLOKIEJVlQXYx+0C5mW/mVVDx1RdSMU="; }; ".local/share/JetBrains/IntelliJIdea2023.2/rainbow-brackets".source = fetchzip { url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/2023.3.6/intellij-rainbow-brackets-2023.3.6.zip"; From 0d6bdf7d94a79070d3fe03d89bbbe4d092f159d5 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 24 Oct 2023 20:15:14 +0200 Subject: [PATCH 0223/1125] Bat: use old theme syntax --- roles/common/programs/bat.nix | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/roles/common/programs/bat.nix b/roles/common/programs/bat.nix index 2075753..207887e 100644 --- a/roles/common/programs/bat.nix +++ b/roles/common/programs/bat.nix @@ -1,5 +1,17 @@ { config, pkgs, ... }: - +let + # Home manager on 23.05 doesn't understand the new format, so I'll use the old one until 23.11 becomes stable + newformat = { + src = pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "bat"; + rev = "master"; + hash = "sha256-6WVKQErGdaqb++oaXnY3i6/GuH2FhTgK0v4TN4Y0Wbw="; + }; + file = "Catppuccin-mocha.tmTheme"; + }; + oldformat = builtins.readFile (newformat.src + "/${newformat.file}"); +in { home-manager = { users.toast.programs.bat = { @@ -8,15 +20,7 @@ theme = "catppuccin-mocha"; }; themes = { - catppuccin-mocha = { - src = pkgs.fetchFromGitHub { - owner = "catppuccin"; - repo = "bat"; - rev = "master"; - hash = "sha256-6WVKQErGdaqb++oaXnY3i6/GuH2FhTgK0v4TN4Y0Wbw="; - }; - file = "Catppuccin-mocha.tmTheme"; - }; + catppuccin-mocha = oldformat; }; }; }; From fcc6fdfadecf992192ebe5290ab572efc3a53921 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 24 Oct 2023 20:30:59 +0200 Subject: [PATCH 0224/1125] Flake: update lock file --- flake.lock | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index d23fa4a..3fa4f42 100644 --- a/flake.lock +++ b/flake.lock @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1697688028, - "narHash": "sha256-d9CAOd9W2iTrgB31a8Dvyp6Vgn/gxASCNrD4Z9yzUOY=", + "lastModified": 1698128422, + "narHash": "sha256-Qf39ATHrj6wfeC+K6uwD/FnI7RKrdEiN3uWaciUi0rM=", "owner": "nix-community", "repo": "home-manager", - "rev": "c5c1ea85181d2bb44e46e8a944a8a3f56ad88f19", + "rev": "6045b68ee725167ed0487f0fb88123202ba61923", "type": "github" }, "original": { @@ -92,11 +92,11 @@ ] }, "locked": { - "lastModified": 1697700248, - "narHash": "sha256-z45M6Fna2mR9zEK9fe9ng1XN+T7CvpmKBn/SaK9zwO4=", + "lastModified": 1698155445, + "narHash": "sha256-/xG4EAt0eZgPInsPPBd04VKkvGsKw0x+/5F8dVqRi7s=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "2965d86926177af95af615a09138e0aaaaec56fa", + "rev": "da9c7f0237cbc029f722df08499da04934ae50e5", "type": "github" }, "original": { @@ -149,11 +149,11 @@ ] }, "locked": { - "lastModified": 1697340827, - "narHash": "sha256-XlrR68N7jyaZ0bs8TPrhqcWG0IPG3pbjrKzJMpYOsos=", + "lastModified": 1697946153, + "narHash": "sha256-7k7qIwWLaYPgQ4fxmEdew3yCffhK6rM4I4Jo3X/79DA=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "29977d0796c058bbcfb2df5b18eb5badf1711007", + "rev": "5a2006282caaf32663cdcd582c5b18809c7d7d8d", "type": "github" }, "original": { @@ -169,11 +169,11 @@ ] }, "locked": { - "lastModified": 1697340827, - "narHash": "sha256-XlrR68N7jyaZ0bs8TPrhqcWG0IPG3pbjrKzJMpYOsos=", + "lastModified": 1697946153, + "narHash": "sha256-7k7qIwWLaYPgQ4fxmEdew3yCffhK6rM4I4Jo3X/79DA=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "29977d0796c058bbcfb2df5b18eb5badf1711007", + "rev": "5a2006282caaf32663cdcd582c5b18809c7d7d8d", "type": "github" }, "original": { @@ -184,11 +184,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1697748412, - "narHash": "sha256-5VSB63UE/O191cuZiGHbCJ9ipc7cGKB8cHp0cfusuyo=", + "lastModified": 1698053470, + "narHash": "sha256-sP8D/41UiwC2qn0X40oi+DfuVzNHMROqIWdSdCI/AYA=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "72d53d51704295f1645d20384cd13aecc182f624", + "rev": "80d98a7d55c6e27954a166cb583a41325e9512d7", "type": "github" }, "original": { @@ -200,11 +200,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1697655685, - "narHash": "sha256-79Kuv+QdgsVc+rkibuAgWHnh8IXrLBTOKg5nM0Qvux0=", + "lastModified": 1697851979, + "narHash": "sha256-lJ8k4qkkwdvi+t/Xc6Fn74kUuobpu9ynPGxNZR6OwoA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "80c1aab725151632ddc2a20caeb914e76dd0673c", + "rev": "5550a85a087c04ddcace7f892b0bdc9d8bb080c8", "type": "github" }, "original": { @@ -215,11 +215,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1697456312, - "narHash": "sha256-roiSnrqb5r+ehnKCauPLugoU8S36KgmWraHgRqVYndo=", + "lastModified": 1697723726, + "narHash": "sha256-SaTWPkI8a5xSHX/rrKzUe+/uVNy6zCGMXgoeMb7T9rg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ca012a02bf8327be9e488546faecae5e05d7d749", + "rev": "7c9cc5a6e5d38010801741ac830a3f8fd667a7a0", "type": "github" }, "original": { From 6114bddb9171dc6fffa7b6f66c94913518f97c42 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 24 Oct 2023 23:25:21 +0200 Subject: [PATCH 0225/1125] Archie: load amdgpu module in initrd --- machines/Archie/hardware-configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index 2966d88..f123be5 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -12,7 +12,7 @@ hardware.xone.enable = true; boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; - boot.initrd.kernelModules = [ ]; + boot.initrd.kernelModules = [ "amdgpu" ]; boot.kernelModules = [ "kvm-amd" ]; boot.extraModulePackages = [ ]; From 5141f0bcf3bd9551e7f0c248bb777e8aea246b7d Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 25 Oct 2023 00:16:27 +0200 Subject: [PATCH 0226/1125] Default: enable plymouth --- roles/desktop/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index b44d58b..2ad993a 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -13,4 +13,5 @@ ( pkgs.nerdfonts.override { fonts = [ "Hack" "JetBrainsMono" ]; } ) ]; + boot.plymouth.enable = true; } From 15d667763c44f1ec28ca60c2ad38e01707264f69 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 27 Oct 2023 00:04:18 +0200 Subject: [PATCH 0227/1125] Gaming: temporarely disable heroic --- roles/gaming/programs/default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/gaming/programs/default.nix b/roles/gaming/programs/default.nix index 4bba376..1e26114 100755 --- a/roles/gaming/programs/default.nix +++ b/roles/gaming/programs/default.nix @@ -7,7 +7,8 @@ ./rpcs3.nix ]; environment.systemPackages = with pkgs; [ - heroic + # Heroic is using an electron version that's considered unsafe, so until that changes I'm not installing it + #heroic prismlauncher-qt5 ]; } From 2ad0a865d5722d901a5d6c75178568e64e8e725d Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 27 Oct 2023 11:23:19 +0200 Subject: [PATCH 0228/1125] SteamDeck: revert back to on disk /tmp --- machines/SteamDeck/configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index bbf55b4..3d4ba77 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -74,6 +74,9 @@ ]; }; + # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs + boot.tmp.useTmpfs = false; + environment.systemPackages = [ pkgs.steamdeck-firmware ]; # List packages installed in system profile. To search, run: # $ nix search wget From ac9f1aa71c440e8291aa054a56293e6a4fe26a95 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 28 Oct 2023 15:53:15 +0200 Subject: [PATCH 0229/1125] Flake: update lock file --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index 3fa4f42..e7ab3e1 100644 --- a/flake.lock +++ b/flake.lock @@ -50,11 +50,11 @@ ] }, "locked": { - "lastModified": 1698128422, - "narHash": "sha256-Qf39ATHrj6wfeC+K6uwD/FnI7RKrdEiN3uWaciUi0rM=", + "lastModified": 1698479159, + "narHash": "sha256-rJHBDwW4LbADEfhkgGHjKGfL2dF44NrlyXdXeZrQahs=", "owner": "nix-community", "repo": "home-manager", - "rev": "6045b68ee725167ed0487f0fb88123202ba61923", + "rev": "f92a54fef4eacdbe86b0a2054054dd58b0e2a2a4", "type": "github" }, "original": { @@ -92,11 +92,11 @@ ] }, "locked": { - "lastModified": 1698155445, - "narHash": "sha256-/xG4EAt0eZgPInsPPBd04VKkvGsKw0x+/5F8dVqRi7s=", + "lastModified": 1698485410, + "narHash": "sha256-+O5Acu2n4XQnT4M25W/oH5MLqXy4pFBFhBzKBFOF7Ik=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "da9c7f0237cbc029f722df08499da04934ae50e5", + "rev": "fd7753956149d4e8b19a810eed445d1a52aecd30", "type": "github" }, "original": { @@ -200,11 +200,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1697851979, - "narHash": "sha256-lJ8k4qkkwdvi+t/Xc6Fn74kUuobpu9ynPGxNZR6OwoA=", + "lastModified": 1698288402, + "narHash": "sha256-jIIjApPdm+4yt8PglX8pUOexAdEiAax/DXW3S/Mb21E=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5550a85a087c04ddcace7f892b0bdc9d8bb080c8", + "rev": "60b9db998f71ea49e1a9c41824d09aa274be1344", "type": "github" }, "original": { @@ -215,11 +215,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1697723726, - "narHash": "sha256-SaTWPkI8a5xSHX/rrKzUe+/uVNy6zCGMXgoeMb7T9rg=", + "lastModified": 1698318101, + "narHash": "sha256-gUihHt3yPD7bVqg+k/UVHgngyaJ3DMEBchbymBMvK1E=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7c9cc5a6e5d38010801741ac830a3f8fd667a7a0", + "rev": "63678e9f3d3afecfeafa0acead6239cdb447574c", "type": "github" }, "original": { From 27e3886afc38f1bdbdd044f4931d534d213f5be2 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 28 Oct 2023 15:54:10 +0200 Subject: [PATCH 0230/1125] Discord: override vencord version --- roles/desktop/programs/discord.nix | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 5142192..a5297a7 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -6,6 +6,16 @@ withOpenASAR = true; withVencord = true; }; + # Update some stuff while I wait for nixpkgs + vencord = super.vencord.overrideAttrs rec { + version = "1.6.1"; + src = pkgs.fetchFromGitHub { + owner = "Vendicated"; + repo = "Vencord"; + rev = "v${version}"; + hash = "sha256-t4+8ybPzqcCtTSukBBgvbD7HiKG4K51WPVnJg0RQbs8="; + }; + }; }; stock-discord = self: super: { discord = super.discord.override { @@ -23,5 +33,6 @@ nixpkgs.overlays = [ discordOverlay ]; users.users.toast.packages = with pkgs; [ discord + vesktop ]; } From 59d5da34192bc9cd99bb7612bf1694c105b43c13 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 29 Oct 2023 21:19:34 +0100 Subject: [PATCH 0231/1125] Kde: enable partition manager --- roles/kde/programs/default.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index 198af46..21e5545 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -1,4 +1,4 @@ -{ ... }: +{ config, ... }: { imports = [ @@ -6,4 +6,7 @@ ./firefox.nix ./skanpage.nix ]; + + # Enable the kde partition manager + programs.partition-manager.enable = true; } From 734b043bc77cefa5eda3ca14e00b73cf48625bf2 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 30 Oct 2023 11:25:26 +0100 Subject: [PATCH 0232/1125] SteamDeck: enable bluetooth --- machines/SteamDeck/configuration.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index 3d4ba77..5ff2b4a 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -51,6 +51,11 @@ }; services.xserver.displayManager.sddm.enable = lib.mkForce false; + # Enable bluetooth + hardware.bluetooth = { + enable = true; + }; + # Configure keymap in X11 # services.xserver.layout = "us"; # services.xserver.xkbOptions = "eurosign:e,caps:escape"; From 3dfdbe92c67066423d7d164660397471ffc60724 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 30 Oct 2023 12:03:20 +0100 Subject: [PATCH 0233/1125] Desktop: enable vscode --- roles/desktop/programs/default.nix | 1 + roles/desktop/programs/vscode.nix | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 roles/desktop/programs/vscode.nix diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix index b25ff4d..2cbcac7 100755 --- a/roles/desktop/programs/default.nix +++ b/roles/desktop/programs/default.nix @@ -7,5 +7,6 @@ ./micro.nix ./keepassxc.nix ./jamesdsp.nix + ./vscode.nix ]; } diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix new file mode 100644 index 0000000..739ba1b --- /dev/null +++ b/roles/desktop/programs/vscode.nix @@ -0,0 +1,8 @@ +{ config, pkgs, ... }: + +{ + home-manager.users.toast.programs.vscode = { + enable = true; + package = pkgs.vscodium; + }; +} From 25afdc2a3a55632cdb1af374f4b22e914b64d933 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 30 Oct 2023 13:52:24 +0100 Subject: [PATCH 0234/1125] Vscode: use catppuccin theme --- flake.lock | 21 +++++++++++++++++++++ flake.nix | 7 ++++++- roles/desktop/programs/vscode.nix | 11 +++++++++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index e7ab3e1..b24d853 100644 --- a/flake.lock +++ b/flake.lock @@ -22,6 +22,26 @@ "type": "github" } }, + "catppuccin-vsc": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1698626248, + "narHash": "sha256-oLkdb+041m26qU7SOy9vR8Hf6FejS1sjLnHghOya/5o=", + "owner": "catppuccin", + "repo": "vscode", + "rev": "e8dfc6d92dd33ffdd1db00b9b6cd1e78844dada4", + "type": "github" + }, + "original": { + "owner": "catppuccin", + "repo": "vscode", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -254,6 +274,7 @@ "root": { "inputs": { "agenix": "agenix", + "catppuccin-vsc": "catppuccin-vsc", "home-manager": "home-manager_2", "home-manager-unstable": "home-manager-unstable", "jovian": "jovian", diff --git a/flake.nix b/flake.nix index 4150c13..3547e7a 100755 --- a/flake.nix +++ b/flake.nix @@ -51,9 +51,14 @@ inputs = { inputs.nixpkgs.follows = "nixpkgs-unstable"; inputs.home-manager.follows = "home-manager-unstable"; }; + + catppuccin-vsc = { + url = "github:catppuccin/vscode"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; }; -outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, nix-index-db, nix-index-db-unstable, jovian, plasma-manager, ... } @inputs: { +outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, nix-index-db, nix-index-db-unstable, jovian, plasma-manager, catppuccin-vsc, ... } @inputs: { devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { name = "Environment for toast's nixos configurations"; diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index 739ba1b..59e4135 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -1,8 +1,15 @@ -{ config, pkgs, ... }: - +{ config, pkgs, flakeSelf, ... }: +let inputs = flakeSelf.inputs; in { + nixpkgs.overlays = [ inputs.catppuccin-vsc.overlays.default ]; home-manager.users.toast.programs.vscode = { enable = true; package = pkgs.vscodium; + extensions = [ + pkgs.catppuccin-vsc + ]; + userSettings = { + "workbench.colorTheme" = "Catppuccin Mocha"; + }; }; } From 4b1c7e7bd1270d17ead48592e9b2d87134c8fd8c Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 30 Oct 2023 14:10:28 +0100 Subject: [PATCH 0235/1125] Vscode: enable catppuccin recommended settings --- roles/desktop/programs/vscode.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index 59e4135..082b528 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -10,6 +10,12 @@ let inputs = flakeSelf.inputs; in ]; userSettings = { "workbench.colorTheme" = "Catppuccin Mocha"; + "editor" = { + "fontFamily" = "JetBrainsMono Nerd Font"; + "semanticHighlighting.enabled" = true; + }; + terminal.integrated.minimumContrastRatio = 1; + window.titleBarStyle = "custom"; }; }; } From e43b6dc8829c8dc844e91f83f12834269fe1ee1b Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 30 Oct 2023 20:35:14 +0100 Subject: [PATCH 0236/1125] Common: don't mount tmpfs to /tmp --- roles/common/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 52cb60e..5f8b13c 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -13,7 +13,7 @@ # Set up /tmp boot.tmp = { - useTmpfs = lib.mkDefault true; + useTmpfs = false; # Cleaning out /tmp at boot if it's a tmpfs is quite stupid cleanOnBoot = !config.boot.tmp.useTmpfs; }; From ff7cffe2561fc33097711555e81b02692c183abf Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 31 Oct 2023 00:22:55 +0100 Subject: [PATCH 0237/1125] Discord: update vencord --- roles/desktop/programs/discord.nix | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index a5297a7..d7d4a41 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -8,12 +8,13 @@ }; # Update some stuff while I wait for nixpkgs vencord = super.vencord.overrideAttrs rec { - version = "1.6.1"; + version = "522fdcd"; src = pkgs.fetchFromGitHub { owner = "Vendicated"; repo = "Vencord"; - rev = "v${version}"; - hash = "sha256-t4+8ybPzqcCtTSukBBgvbD7HiKG4K51WPVnJg0RQbs8="; + rev = "522fdcd"; + #rev = "v${version}"; + hash = "sha256-9G7FNL4pHaaLachzJmeAol0WpNUj533K2FNa7DH0eBM="; }; }; }; From c1756aff12fb6108fbcf930ebaa69e0129a03e1d Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 2 Nov 2023 08:04:44 +0100 Subject: [PATCH 0238/1125] Vscode: add the nix-ide extension from nix-vscode-extensions --- flake.lock | 74 ++++++++++++++++++++++++++++++- flake.nix | 5 +++ roles/desktop/programs/vscode.nix | 3 +- 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/flake.lock b/flake.lock index b24d853..9da0bdf 100644 --- a/flake.lock +++ b/flake.lock @@ -42,6 +42,40 @@ "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -284,7 +318,45 @@ "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", "nixpkgs-unstable": "nixpkgs-unstable", - "plasma-manager": "plasma-manager" + "plasma-manager": "plasma-manager", + "vscode-extensions": "vscode-extensions" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "vscode-extensions": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1698802076, + "narHash": "sha256-9JjcuX4Vf9Gvj6Gr3bu91Q/Twr3NeTMdU8T6+sDGaSQ=", + "owner": "nix-community", + "repo": "nix-vscode-extensions", + "rev": "bc5ea072fb52bacc3a48bc6e716c373b44d76088", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-vscode-extensions", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index 3547e7a..4f6fb0a 100755 --- a/flake.nix +++ b/flake.nix @@ -56,6 +56,11 @@ inputs = { url = "github:catppuccin/vscode"; inputs.nixpkgs.follows = "nixpkgs-unstable"; }; + + vscode-extensions = { + url = "github:nix-community/nix-vscode-extensions"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; }; outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, nix-index-db, nix-index-db-unstable, jovian, plasma-manager, catppuccin-vsc, ... } @inputs: { diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index 082b528..38f1b31 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -5,7 +5,8 @@ let inputs = flakeSelf.inputs; in home-manager.users.toast.programs.vscode = { enable = true; package = pkgs.vscodium; - extensions = [ + extensions = with inputs.vscode-extensions.extensions.x86_64-linux.open-vsx; [ + jnoortheen.nix-ide pkgs.catppuccin-vsc ]; userSettings = { From 7108758182f2f28d02a1c9ce1d8bfe210ce840f6 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 2 Nov 2023 08:05:11 +0100 Subject: [PATCH 0239/1125] School: add xml extension to vscode --- roles/school/programs/default.nix | 1 + roles/school/programs/vscode.nix | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 roles/school/programs/vscode.nix diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 2c5fd21..24dba3a 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -4,6 +4,7 @@ imports = [ ./virtualbox.nix ./idea.nix + ./vscode.nix ]; environment.systemPackages = with pkgs; [ diff --git a/roles/school/programs/vscode.nix b/roles/school/programs/vscode.nix new file mode 100644 index 0000000..2f2c7ba --- /dev/null +++ b/roles/school/programs/vscode.nix @@ -0,0 +1,12 @@ +{ config, pkgs, lib, flakeSelf, ... }: +let inputs = flakeSelf.inputs; in +{ + home-manager.users.toast.programs.vscode = { + # The redhat xml extension needs an fhs environment + package = lib.mkForce pkgs.vscodium-fhs; + extensions = [ inputs.vscode-extensions.extensions.x86_64-linux.open-vsx.redhat.vscode-xml ]; + userSettings = { + redhat.telemetry.enabled = false; + }; + }; +} From 778c084bd2691e7a579ed3e851bb36a4fcb6e54b Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 31 Oct 2023 11:11:34 +0100 Subject: [PATCH 0240/1125] .vscode: disable stupid settings --- .vscode/settings.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 6321126..bebb1a3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,5 @@ { "editor.detectIndentation": true, "editor.insertSpaces": false, - "editor.tabSize": 2, - "editor.renderWhitespace": "all", "editor.defaultFormatter": "jnoortheen.nix-ide" } From e0394bc056278a6cde52057d882011843213b1b4 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 2 Nov 2023 10:40:24 +0100 Subject: [PATCH 0241/1125] Vencord: don't override sources --- roles/desktop/programs/discord.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index d7d4a41..8f81f98 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -7,7 +7,7 @@ withVencord = true; }; # Update some stuff while I wait for nixpkgs - vencord = super.vencord.overrideAttrs rec { + /*vencord = super.vencord.overrideAttrs rec { version = "522fdcd"; src = pkgs.fetchFromGitHub { owner = "Vendicated"; @@ -16,7 +16,7 @@ #rev = "v${version}"; hash = "sha256-9G7FNL4pHaaLachzJmeAol0WpNUj533K2FNa7DH0eBM="; }; - }; + };*/ }; stock-discord = self: super: { discord = super.discord.override { From 1372eff3d8e3eb316944208cecc95367f0184a38 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 2 Nov 2023 10:50:00 +0100 Subject: [PATCH 0242/1125] Flake: update lock file --- flake.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/flake.lock b/flake.lock index 9da0bdf..fae2f9f 100644 --- a/flake.lock +++ b/flake.lock @@ -29,11 +29,11 @@ ] }, "locked": { - "lastModified": 1698626248, - "narHash": "sha256-oLkdb+041m26qU7SOy9vR8Hf6FejS1sjLnHghOya/5o=", + "lastModified": 1698700357, + "narHash": "sha256-YLD+DTMGPqEfHocfT3JVapHfFFLe2X3iqoV5Br7CIlM=", "owner": "catppuccin", "repo": "vscode", - "rev": "e8dfc6d92dd33ffdd1db00b9b6cd1e78844dada4", + "rev": "daad900d73f7060a413d454769de94258ccdd41d", "type": "github" }, "original": { @@ -104,11 +104,11 @@ ] }, "locked": { - "lastModified": 1698479159, - "narHash": "sha256-rJHBDwW4LbADEfhkgGHjKGfL2dF44NrlyXdXeZrQahs=", + "lastModified": 1698873617, + "narHash": "sha256-FfGFcfbULwbK1vD+H0rslIOfmy4g8f2hXiPkQG3ZCTk=", "owner": "nix-community", "repo": "home-manager", - "rev": "f92a54fef4eacdbe86b0a2054054dd58b0e2a2a4", + "rev": "48b0a30202516e25d9885525fbb200a045f23f26", "type": "github" }, "original": { @@ -203,11 +203,11 @@ ] }, "locked": { - "lastModified": 1697946153, - "narHash": "sha256-7k7qIwWLaYPgQ4fxmEdew3yCffhK6rM4I4Jo3X/79DA=", + "lastModified": 1698550809, + "narHash": "sha256-Um8+Wi6EAH5dCgfgl7OqaVd4wFJn6FKLafcP5QPr/98=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "5a2006282caaf32663cdcd582c5b18809c7d7d8d", + "rev": "1f0981f5baeb78e3c89a8980ff1a39f06876fa8c", "type": "github" }, "original": { @@ -223,11 +223,11 @@ ] }, "locked": { - "lastModified": 1697946153, - "narHash": "sha256-7k7qIwWLaYPgQ4fxmEdew3yCffhK6rM4I4Jo3X/79DA=", + "lastModified": 1698550809, + "narHash": "sha256-Um8+Wi6EAH5dCgfgl7OqaVd4wFJn6FKLafcP5QPr/98=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "5a2006282caaf32663cdcd582c5b18809c7d7d8d", + "rev": "1f0981f5baeb78e3c89a8980ff1a39f06876fa8c", "type": "github" }, "original": { @@ -238,11 +238,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1698053470, - "narHash": "sha256-sP8D/41UiwC2qn0X40oi+DfuVzNHMROqIWdSdCI/AYA=", + "lastModified": 1698853384, + "narHash": "sha256-/FQ2WeCjdjdNo9eGTO7JruGAjO2Ccime8y1OU4/Aesk=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "80d98a7d55c6e27954a166cb583a41325e9512d7", + "rev": "11d50c5d52472ed40d3cb109daad03c836d2b328", "type": "github" }, "original": { @@ -254,11 +254,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1698288402, - "narHash": "sha256-jIIjApPdm+4yt8PglX8pUOexAdEiAax/DXW3S/Mb21E=", + "lastModified": 1698846319, + "narHash": "sha256-4jyW/dqFBVpWFnhl0nvP6EN4lP7/ZqPxYRjl6var0Oc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "60b9db998f71ea49e1a9c41824d09aa274be1344", + "rev": "34bdaaf1f0b7fb6d9091472edc968ff10a8c2857", "type": "github" }, "original": { @@ -269,11 +269,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1698318101, - "narHash": "sha256-gUihHt3yPD7bVqg+k/UVHgngyaJ3DMEBchbymBMvK1E=", + "lastModified": 1698611440, + "narHash": "sha256-jPjHjrerhYDy3q9+s5EAsuhyhuknNfowY6yt6pjn9pc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "63678e9f3d3afecfeafa0acead6239cdb447574c", + "rev": "0cbe9f69c234a7700596e943bfae7ef27a31b735", "type": "github" }, "original": { @@ -346,11 +346,11 @@ ] }, "locked": { - "lastModified": 1698802076, - "narHash": "sha256-9JjcuX4Vf9Gvj6Gr3bu91Q/Twr3NeTMdU8T6+sDGaSQ=", + "lastModified": 1698887753, + "narHash": "sha256-6sIAOzMKkXEYnOpNIfoWO+QYCCz5uR/EzDwE+pEVFEc=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "bc5ea072fb52bacc3a48bc6e716c373b44d76088", + "rev": "c6080604ecf7c35da91d96ee0fb2601b20c1f5a1", "type": "github" }, "original": { From 3992f3e6b03e24a02543faf856e613cafd8b8ce1 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 3 Nov 2023 00:01:55 +0100 Subject: [PATCH 0243/1125] Kde: show notifications over fullscreen windows --- roles/kde/plasma.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index d2e86dd..eeabba9 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -149,6 +149,7 @@ in }; "TabBox"."LayoutName" = "thumbnail_grid"; }; + "plasmanotifyrc"."Notifications"."NormalAlwaysOnTop" = true; }; }; }]; From 998ea1fa4399107237b76dea68fcd4e36d9a16cb Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 3 Nov 2023 00:32:46 +0100 Subject: [PATCH 0244/1125] SurfaceGo: upgrade to nispkgs-unstable --- flake.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index 4f6fb0a..fc72423 100755 --- a/flake.nix +++ b/flake.nix @@ -108,14 +108,14 @@ outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager- ]; }; - SurfaceGo = nixpkgs.lib.nixosSystem { + SurfaceGo = nixpkgs-unstable.lib.nixosSystem { system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs; flakeSelf = self; }; + specialArgs = { systemPkgs = inputs.nixpkgs-unstable; flakeSelf = self; }; modules = [ agenix.nixosModules.default - home-manager.nixosModule + home-manager-unstable.nixosModule nixos-hardware.nixosModules.microsoft-surface-go - nix-index-db.nixosModules.nix-index + nix-index-db-unstable.nixosModules.nix-index ./roles/common ./roles/desktop ./roles/kde From 85b6f2f09cace6a288ff28b6d230e01f48028ef0 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 3 Nov 2023 12:37:44 +0100 Subject: [PATCH 0245/1125] Flake: update lock file --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index fae2f9f..d930bf3 100644 --- a/flake.lock +++ b/flake.lock @@ -29,11 +29,11 @@ ] }, "locked": { - "lastModified": 1698700357, - "narHash": "sha256-YLD+DTMGPqEfHocfT3JVapHfFFLe2X3iqoV5Br7CIlM=", + "lastModified": 1698928896, + "narHash": "sha256-u1zn+ra0veELWC7IRcAed/Cl91Tic0AkaLhvpGk54Xw=", "owner": "catppuccin", "repo": "vscode", - "rev": "daad900d73f7060a413d454769de94258ccdd41d", + "rev": "f6ac9ebb84464cd37d045561b9919f3ae3684edb", "type": "github" }, "original": { @@ -104,11 +104,11 @@ ] }, "locked": { - "lastModified": 1698873617, - "narHash": "sha256-FfGFcfbULwbK1vD+H0rslIOfmy4g8f2hXiPkQG3ZCTk=", + "lastModified": 1698896213, + "narHash": "sha256-u42NZt52F3o7pM5V7sYlLOp5tSN8z9+fO2wFcOs0EOQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "48b0a30202516e25d9885525fbb200a045f23f26", + "rev": "831b4fa31749208e576050c563e9773aafd04941", "type": "github" }, "original": { @@ -269,11 +269,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1698611440, - "narHash": "sha256-jPjHjrerhYDy3q9+s5EAsuhyhuknNfowY6yt6pjn9pc=", + "lastModified": 1698924604, + "narHash": "sha256-GCFbkl2tj8fEZBZCw3Tc0AkGo0v+YrQlohhEGJ/X4s0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0cbe9f69c234a7700596e943bfae7ef27a31b735", + "rev": "fa804edfb7869c9fb230e174182a8a1a7e512c40", "type": "github" }, "original": { @@ -346,11 +346,11 @@ ] }, "locked": { - "lastModified": 1698887753, - "narHash": "sha256-6sIAOzMKkXEYnOpNIfoWO+QYCCz5uR/EzDwE+pEVFEc=", + "lastModified": 1698974253, + "narHash": "sha256-W35N4WjGHOguAd8pDMoxHPiACwoBiVo9WVs9iEYzPcg=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "c6080604ecf7c35da91d96ee0fb2601b20c1f5a1", + "rev": "2a6f98f0521813a35cc7c40674629b0a9f9add86", "type": "github" }, "original": { From 3348f8457a456263cc67fffdbbaecc9541524e39 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 3 Nov 2023 13:28:30 +0100 Subject: [PATCH 0246/1125] Intellij: update plugins --- roles/school/programs/idea.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index a14d86b..c948bfa 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -10,12 +10,12 @@ with pkgs; # Install plugins home.file = { ".local/share/JetBrains/IntelliJIdea2023.2/catppuccin.jar".source = fetchurl { - url = "https://github.com/catppuccin/jetbrains/releases/download/v3.1.0/Catppuccin.Theme-3.1.0.jar"; - hash = "sha256-63fn3j57QBuwZLOKIEJVlQXYx+0C5mW/mVVDx1RdSMU="; + url = "https://github.com/catppuccin/jetbrains/releases/download/v3.2.1/Catppuccin.Theme-3.2.1.jar"; + hash = "sha256-vE3Tv/dNfWyRuBJXLDPmtY1GnLShqM+dJR5rltXYdOY="; }; ".local/share/JetBrains/IntelliJIdea2023.2/rainbow-brackets".source = fetchzip { - url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/2023.3.6/intellij-rainbow-brackets-2023.3.6.zip"; - hash = "sha256-ZoBVRPZZn8QjXSLtskRtSpGoadc8KNKxsKvdcyNXT74"; + url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/2023.3.7/intellij-rainbow-brackets-2023.3.7.zip"; + hash = "sha256-szgyQs3iCge9rI274PA29i+tprPE11xpyJqiccedp6A="; }; }; From a9df91829114a7247ac3f3d2f51a63101af4318b Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 4 Nov 2023 00:32:03 +0100 Subject: [PATCH 0247/1125] Flake: add discord-krisp-fixer package --- flake.nix | 1 + pkgs/discord-krisp-fixer | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 pkgs/discord-krisp-fixer diff --git a/flake.nix b/flake.nix index fc72423..d00bb06 100755 --- a/flake.nix +++ b/flake.nix @@ -83,6 +83,7 @@ outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager- x86_64-linux = with import nixpkgs-unstable { system = "x86_64-linux"; }; { pseint = callPackage ./pkgs/pseint.nix {}; anything-sync-daemon = callPackage ./pkgs/anything-sync-daemon {}; + discord-krisp-fixer = callPackage ./pkgs/discord-krisp-fixer {}; }; }; nixosConfigurations = { diff --git a/pkgs/discord-krisp-fixer b/pkgs/discord-krisp-fixer new file mode 100644 index 0000000..baa22d2 --- /dev/null +++ b/pkgs/discord-krisp-fixer @@ -0,0 +1,17 @@ +{ writeShellApplication +, rizin +, discord +}: + +writeShellApplication rec { + name = "discord-krisp-fixer"; + + runtimeInputs = [ rizin ]; + + text = '' + discord_version="${discord.version}" + file="$HOME/.config/discord/$discord_version/modules/discord_krisp/discord_krisp.node" + addr=$(rz-find -x '4881ec00010000' "$file" | head -n1) + rizin -q -w -c "s $addr + 0x30 ; wao nop" "$file" + ''; +} From 2ec7a30da16e37d9b21d52cd0264506c1b38f318 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 4 Nov 2023 02:03:24 +0100 Subject: [PATCH 0248/1125] Kde: deprecate system wide gtk settings --- roles/kde/plasma.nix | 45 -------------------------------------------- 1 file changed, 45 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index eeabba9..6fa1a6b 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -1,19 +1,6 @@ { config, pkgs, lib, flakeSelf, ... }: let - themeName = "Breeze"; - gtk3and4settings = lib.generators.toINI {} { - Settings = { - gtk-theme-name = themeName; - gtk-cursor-theme-name = "breeze_cursors"; - }; - }; - - gtk2settings = '' - include "/run/current-system/sw/share/themes/${themeName}-Dark/gtk-2.0/gtkrc" - gtk-theme-name="${themeName}-Dark" - ''; - # Set up the default kde options kdeglobals = lib.generators.toINI {} { KDE.LookAndFeelPackage = "org.kde.breezedarktint.desktop"; @@ -88,41 +75,9 @@ in displayManager.defaultSession = "plasmawayland"; }; - # GTK apps need dconf to grab the correct theme on Wayland programs.dconf.enable = true; - # The NixOS dconf module doesn't support creating databases - # (https://github.com/NixOS/nixpkgs/issues/54150), so I'm - # doing it manualy - - # https://help.gnome.org/admin/system-admin-guide/stable/dconf-custom-defaults.html.en - environment.etc = { - "dconf/profile/user".text = "user-db:user\nsystem-db:local"; - "dconf/db/local.d/00-defaultTheme".text = '' - [org/gnome/desktop/interface] - gtk-theme='${themeName}' - ''; - }; - - system.activationScripts = { - dconf = { - text= '' - echo "updating system dconf database..." - ${pkgs.dconf}/bin/dconf update - ''; - deps = [ "etc" ]; - }; - }; - - # Set up GTK to use Breeze instead of adwaita by default - # Theese only seem to work on X11, not wayland - environment.etc = { - "xdg/gtk-4.0/settings.ini".text = gtk3and4settings; - "xdg/gtk-3.0/settings.ini".text = gtk3and4settings; - "gtk-2.0/gtkrc".text = gtk2settings; - }; - /* Install the patched Breeze color schemes and look and feel packages, as well as the plasma default configs From bb7b08a6300bcd6fe4394db4682d2d7048d5569c Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 4 Nov 2023 02:03:47 +0100 Subject: [PATCH 0249/1125] Kde: set up gtk with home-manager --- roles/kde/plasma.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 6fa1a6b..88e334b 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -87,6 +87,15 @@ in # Plasma configs should be on all users home-manager.sharedModules = [{ imports = [ flakeSelf.inputs.plasma-manager.homeManagerModules.plasma-manager ]; + gtk = { + enable = true; + cursorTheme = { package = pkgs.breeze-icons; name = "breeze-cursors"; }; + iconTheme = { package = pkgs.breeze-icons; name = "breeze-dark"; }; + theme = { package = pkgs.breeze-gtk; name = "Breeze"; }; + # Gtk2 doesn't have a dark mode, so I just tell gtk 3 and 4 to use the dark variant + gtk3.extraConfig.gtk-application-prefer-dark-theme = true; + gtk4.extraConfig.gtk-application-prefer-dark-theme = true; + }; programs.plasma = { enable = true; workspace.clickItemTo = "select"; From 7df7f68291a53d767ef5d9f9a93bbbee1877911d Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 6 Nov 2023 11:14:13 +0100 Subject: [PATCH 0250/1125] Flake: update lock file --- flake.lock | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index d930bf3..a98fc39 100644 --- a/flake.lock +++ b/flake.lock @@ -104,11 +104,11 @@ ] }, "locked": { - "lastModified": 1698896213, - "narHash": "sha256-u42NZt52F3o7pM5V7sYlLOp5tSN8z9+fO2wFcOs0EOQ=", + "lastModified": 1699025595, + "narHash": "sha256-e+o4PoSu2Z6Ww8y/AVUmMU200rNZoRK+p2opQ7Db8Rg=", "owner": "nix-community", "repo": "home-manager", - "rev": "831b4fa31749208e576050c563e9773aafd04941", + "rev": "8765d4e38aa0be53cdeee26f7386173e6c65618d", "type": "github" }, "original": { @@ -203,11 +203,11 @@ ] }, "locked": { - "lastModified": 1698550809, - "narHash": "sha256-Um8+Wi6EAH5dCgfgl7OqaVd4wFJn6FKLafcP5QPr/98=", + "lastModified": 1699156599, + "narHash": "sha256-Qk9ZE/pG9lNIGUVNArJxL0Hc0Soa92eQPPIhcDwWinU=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "1f0981f5baeb78e3c89a8980ff1a39f06876fa8c", + "rev": "5388a4002179d6778d212dc2fdcc7ac3fdbd5b65", "type": "github" }, "original": { @@ -223,11 +223,11 @@ ] }, "locked": { - "lastModified": 1698550809, - "narHash": "sha256-Um8+Wi6EAH5dCgfgl7OqaVd4wFJn6FKLafcP5QPr/98=", + "lastModified": 1699156599, + "narHash": "sha256-Qk9ZE/pG9lNIGUVNArJxL0Hc0Soa92eQPPIhcDwWinU=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "1f0981f5baeb78e3c89a8980ff1a39f06876fa8c", + "rev": "5388a4002179d6778d212dc2fdcc7ac3fdbd5b65", "type": "github" }, "original": { @@ -238,11 +238,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1698853384, - "narHash": "sha256-/FQ2WeCjdjdNo9eGTO7JruGAjO2Ccime8y1OU4/Aesk=", + "lastModified": 1699159446, + "narHash": "sha256-cL63IjsbPl2otS7R4kdXbVOJOXYMpGw5KGZoWgdCuCM=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "11d50c5d52472ed40d3cb109daad03c836d2b328", + "rev": "627bc9b88256379578885a7028c9e791c29fb581", "type": "github" }, "original": { @@ -254,11 +254,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1698846319, - "narHash": "sha256-4jyW/dqFBVpWFnhl0nvP6EN4lP7/ZqPxYRjl6var0Oc=", + "lastModified": 1699169573, + "narHash": "sha256-cvUb1xZkvOp3W2SzylStrTirhVd9zCeo5utJl9nSIhw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "34bdaaf1f0b7fb6d9091472edc968ff10a8c2857", + "rev": "aeefe2054617cae501809b82b44a8e8f7be7cc4b", "type": "github" }, "original": { @@ -269,11 +269,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1698924604, - "narHash": "sha256-GCFbkl2tj8fEZBZCw3Tc0AkGo0v+YrQlohhEGJ/X4s0=", + "lastModified": 1699099776, + "narHash": "sha256-X09iKJ27mGsGambGfkKzqvw5esP1L/Rf8H3u3fCqIiU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "fa804edfb7869c9fb230e174182a8a1a7e512c40", + "rev": "85f1ba3e51676fa8cc604a3d863d729026a6b8eb", "type": "github" }, "original": { @@ -346,11 +346,11 @@ ] }, "locked": { - "lastModified": 1698974253, - "narHash": "sha256-W35N4WjGHOguAd8pDMoxHPiACwoBiVo9WVs9iEYzPcg=", + "lastModified": 1699233727, + "narHash": "sha256-n8IWvCI1UqmmvgezREirShQ3R7sLUW9ylqRDJNzHOgo=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "2a6f98f0521813a35cc7c40674629b0a9f9add86", + "rev": "8221a460d187e267fdb48368532ec83d2cadc24b", "type": "github" }, "original": { From e598012ab8136867c05e087dbfab31e384bd4327 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 5 Nov 2023 13:11:58 +0100 Subject: [PATCH 0251/1125] Archie: enable bluetooth --- machines/Archie/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/machines/Archie/configuration.nix b/machines/Archie/configuration.nix index c610816..7784db6 100644 --- a/machines/Archie/configuration.nix +++ b/machines/Archie/configuration.nix @@ -56,6 +56,8 @@ ]; }; + hardware.bluetooth.enable = true; + # List packages installed in system profile. To search, run: # $ nix search wget # environment.systemPackages = with pkgs; [ From a13dc7802442b74b85597d18573bb7dbad324e08 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 7 Nov 2023 11:36:53 +0100 Subject: [PATCH 0252/1125] Flake: update lock file --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index a98fc39..a46976a 100644 --- a/flake.lock +++ b/flake.lock @@ -146,11 +146,11 @@ ] }, "locked": { - "lastModified": 1698485410, - "narHash": "sha256-+O5Acu2n4XQnT4M25W/oH5MLqXy4pFBFhBzKBFOF7Ik=", + "lastModified": 1699302981, + "narHash": "sha256-BxhYqJZV6FHp4YnJt49ggi8Ghdi93K1MjQ2hISz+0J8=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "fd7753956149d4e8b19a810eed445d1a52aecd30", + "rev": "b2aabc16388edfe538d136dee4bc7861d5f40b39", "type": "github" }, "original": { From d4337b29b9c8939fefebbfe48cf52a94a64d6ef9 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 9 Nov 2023 10:57:30 +0100 Subject: [PATCH 0253/1125] School: add vscode extensions --- roles/school/programs/vscode.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/roles/school/programs/vscode.nix b/roles/school/programs/vscode.nix index 2f2c7ba..c5329bf 100644 --- a/roles/school/programs/vscode.nix +++ b/roles/school/programs/vscode.nix @@ -4,7 +4,12 @@ let inputs = flakeSelf.inputs; in home-manager.users.toast.programs.vscode = { # The redhat xml extension needs an fhs environment package = lib.mkForce pkgs.vscodium-fhs; - extensions = [ inputs.vscode-extensions.extensions.x86_64-linux.open-vsx.redhat.vscode-xml ]; + extensions = with inputs.vscode-extensions.extensions.x86_64-linux; [ + open-vsx.redhat.vscode-xml + open-vsx.tomoki1207.pdf + open-vsx.ms-vscode.live-server + open-vsx.ecmel.vscode-html-css + ]; userSettings = { redhat.telemetry.enabled = false; }; From 9b75124f16c0dc60ef3c3a94ccc0564e629d0161 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 9 Nov 2023 11:09:21 +0100 Subject: [PATCH 0254/1125] Kde: set correct cursor theme for gtk --- roles/kde/plasma.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 88e334b..329e2fa 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -89,7 +89,7 @@ in imports = [ flakeSelf.inputs.plasma-manager.homeManagerModules.plasma-manager ]; gtk = { enable = true; - cursorTheme = { package = pkgs.breeze-icons; name = "breeze-cursors"; }; + cursorTheme = { package = pkgs.breeze-qt5; name = "breeze_cursors"; }; iconTheme = { package = pkgs.breeze-icons; name = "breeze-dark"; }; theme = { package = pkgs.breeze-gtk; name = "Breeze"; }; # Gtk2 doesn't have a dark mode, so I just tell gtk 3 and 4 to use the dark variant From cafa6e4097de7090b192a13e0beddfd65a51f8ce Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 10 Nov 2023 10:56:48 +0100 Subject: [PATCH 0255/1125] School: add xampp --- roles/school/services/default.nix | 1 + roles/school/services/xampp.nix | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 roles/school/services/xampp.nix diff --git a/roles/school/services/default.nix b/roles/school/services/default.nix index 1e5b9bb..703919f 100644 --- a/roles/school/services/default.nix +++ b/roles/school/services/default.nix @@ -4,5 +4,6 @@ imports = [ ./syncthing.nix ./mysql.nix + ./xampp.nix ]; } diff --git a/roles/school/services/xampp.nix b/roles/school/services/xampp.nix new file mode 100644 index 0000000..1ec12a2 --- /dev/null +++ b/roles/school/services/xampp.nix @@ -0,0 +1,29 @@ +{ config, ... }: + +{ + # I tried setting up httpd + php in class but I just gave up + virtualisation.oci-containers = { + containers."xampp" = { + autoStart = false; + image = "tomsik68/xampp"; + #user = "${toString users.users.atfc.uid}:${toString users.groups.minecraft.gid}"; + volumes = [ + "xampp-mysql:/opt/lampp/var/mysql" + ]; + ports = [ "41061:22" "41062:80" ]; + }; + }; + + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if ( + action.id == "org.freedesktop.systemd1.manage-units" && + action.lookup("unit") == "podman-xampp.service" && + subject.user == "toast" + ) + { + return polkit.Result.YES; + } + }) + ''; +} \ No newline at end of file From 9cccf7b4b0cecdf2be1678b7345226484e025aa7 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 10 Nov 2023 13:19:17 +0100 Subject: [PATCH 0256/1125] SteamDeck: install the steamdeck themes --- machines/SteamDeck/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index 5ff2b4a..dc54043 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -82,7 +82,7 @@ # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs boot.tmp.useTmpfs = false; - environment.systemPackages = [ pkgs.steamdeck-firmware ]; + environment.systemPackages = [ pkgs.steamdeck-firmware pkgs.steamdeck-hw-theme ]; # List packages installed in system profile. To search, run: # $ nix search wget # environment.systemPackages = with pkgs; [ From 0353945decb106cc309023665bc918fbba3f1eb6 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 12 Nov 2023 02:41:58 +0100 Subject: [PATCH 0257/1125] Flake: update lock file --- flake.lock | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index a46976a..5e893a8 100644 --- a/flake.lock +++ b/flake.lock @@ -104,11 +104,11 @@ ] }, "locked": { - "lastModified": 1699025595, - "narHash": "sha256-e+o4PoSu2Z6Ww8y/AVUmMU200rNZoRK+p2opQ7Db8Rg=", + "lastModified": 1699748018, + "narHash": "sha256-28rwXnxgscLkeII6wj44cuP6RuiynhzZSa424ZwGt/s=", "owner": "nix-community", "repo": "home-manager", - "rev": "8765d4e38aa0be53cdeee26f7386173e6c65618d", + "rev": "50e582b9f91e409ffd2e134017445d376659b32e", "type": "github" }, "original": { @@ -124,11 +124,11 @@ ] }, "locked": { - "lastModified": 1695108154, - "narHash": "sha256-gSg7UTVtls2yO9lKtP0yb66XBHT1Fx5qZSZbGMpSn2c=", + "lastModified": 1699748081, + "narHash": "sha256-MOmMapBydd7MTjhX4eeQZzKlCABWw8W6iSHSG4OeFKE=", "owner": "nix-community", "repo": "home-manager", - "rev": "07682fff75d41f18327a871088d20af2710d4744", + "rev": "04bac349d585c9df38d78e0285b780a140dc74a4", "type": "github" }, "original": { @@ -146,11 +146,11 @@ ] }, "locked": { - "lastModified": 1699302981, - "narHash": "sha256-BxhYqJZV6FHp4YnJt49ggi8Ghdi93K1MjQ2hISz+0J8=", + "lastModified": 1699679038, + "narHash": "sha256-rT2p5nyLUEZYzuctstoFvjKWVqTyTfJhgrVNkFp5g/0=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "b2aabc16388edfe538d136dee4bc7861d5f40b39", + "rev": "42d4937d4b08aef56b04279518c5d50e97532e8b", "type": "github" }, "original": { @@ -238,11 +238,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1699159446, - "narHash": "sha256-cL63IjsbPl2otS7R4kdXbVOJOXYMpGw5KGZoWgdCuCM=", + "lastModified": 1699701045, + "narHash": "sha256-mDzUXK7jNO/utInWpSWEX1NgEEunVIpJg+LyPsDTfy0=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "627bc9b88256379578885a7028c9e791c29fb581", + "rev": "b689465d0c5d88e158e7d76094fca08cc0223aad", "type": "github" }, "original": { @@ -254,11 +254,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1699169573, - "narHash": "sha256-cvUb1xZkvOp3W2SzylStrTirhVd9zCeo5utJl9nSIhw=", + "lastModified": 1699291058, + "narHash": "sha256-5ggduoaAMPHUy4riL+OrlAZE14Kh7JWX4oLEs22ZqfU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "aeefe2054617cae501809b82b44a8e8f7be7cc4b", + "rev": "41de143fda10e33be0f47eab2bfe08a50f234267", "type": "github" }, "original": { @@ -292,11 +292,11 @@ ] }, "locked": { - "lastModified": 1690827734, - "narHash": "sha256-zcNLTSKGZ5zcx0RQkDKH4dN2MBx+KTfrYN7HfmD0N7c=", + "lastModified": 1699638264, + "narHash": "sha256-EGT10Ig8OFUY5T0nwnNuLa4z++yjaqfSQT/5Tyo1Z60=", "owner": "pjones", "repo": "plasma-manager", - "rev": "b6241a2f7c625d0b0bee8e203d78232d0a6535e9", + "rev": "56c325e68d69b9682bcb1be99650b6c28bedb93d", "type": "github" }, "original": { @@ -346,11 +346,11 @@ ] }, "locked": { - "lastModified": 1699233727, - "narHash": "sha256-n8IWvCI1UqmmvgezREirShQ3R7sLUW9ylqRDJNzHOgo=", + "lastModified": 1699669360, + "narHash": "sha256-EHcoK/LUo3wI/IFTRWkXWKow58zy6x25MXvz48izSLs=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "8221a460d187e267fdb48368532ec83d2cadc24b", + "rev": "80bfa86f4b3f38b41991d92124bebeee7f30839f", "type": "github" }, "original": { From 37dcf27b050965465c9719451da8e1af9ddb0fe9 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 12 Nov 2023 21:13:21 +0100 Subject: [PATCH 0258/1125] Flake: formatting and code cleanup --- flake.nix | 292 +++++++++++++++++++++++++++--------------------------- 1 file changed, 146 insertions(+), 146 deletions(-) diff --git a/flake.nix b/flake.nix index d00bb06..0db6b75 100755 --- a/flake.nix +++ b/flake.nix @@ -1,158 +1,158 @@ { -description = "Configuration for Everest"; + description = "Configuration for Everest"; -inputs = { - nixpkgs.url = "nixpkgs/nixos-23.05"; - nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; + inputs = { + nixpkgs.url = "nixpkgs/nixos-23.05"; + nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; - agenix = { - url = "github:ryantm/agenix"; - inputs = { - nixpkgs.follows = "nixpkgs"; - darwin.follows = ""; # Not using this on MacOS, so this doesn't pull it's dependencies - }; - }; - - home-manager = { - url = "github:nix-community/home-manager/release-23.05"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - - home-manager-unstable = { - url = "github:nix-community/home-manager/"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; - }; - - nixos-hardware.url = "github:NixOS/nixos-hardware/master"; - - jovian = { - url = "github:Jovian-Experiments/Jovian-NixOS"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; - }; - - nix-impermanence.url = "github:nix-community/impermanence"; - - /* - These are the same input, just following different nixpkgs versions - This avoids some wierdness when using one that follows unstable on a stable nixpkgs - */ - nix-index-db = { - url = "github:Mic92/nix-index-database"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - - nix-index-db-unstable = { - url = "github:Mic92/nix-index-database"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; - }; - - plasma-manager = { - url = "github:pjones/plasma-manager"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; - inputs.home-manager.follows = "home-manager-unstable"; - }; - - catppuccin-vsc = { - url = "github:catppuccin/vscode"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; - }; - - vscode-extensions = { - url = "github:nix-community/nix-vscode-extensions"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; - }; -}; - -outputs = { self, nixpkgs, nixpkgs-unstable, agenix, home-manager, home-manager-unstable, nixos-hardware, nix-impermanence, nix-index-db, nix-index-db-unstable, jovian, plasma-manager, catppuccin-vsc, ... } @inputs: { - - devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { - name = "Environment for toast's nixos configurations"; - # The agenix cli is not needed to activate a configuration, so instead of installing it - # I'll just add it to de devShell, since that's the only real time I'm going to use it. - packages = with nixpkgs.legacyPackages.x86_64-linux; [ - agenix.packages.x86_64-linux.default - git - plasma5Packages.plasma-sdk - nix-diff - ]; - shellHook ='' - export PS1="$PS1(toast-configs)> " - ''; - }; - packages = { - x86_64-linux = with import nixpkgs-unstable { system = "x86_64-linux"; }; { - pseint = callPackage ./pkgs/pseint.nix {}; - anything-sync-daemon = callPackage ./pkgs/anything-sync-daemon {}; - discord-krisp-fixer = callPackage ./pkgs/discord-krisp-fixer {}; - }; - }; - nixosConfigurations = { - Archie = nixpkgs-unstable.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-unstable; flakeSelf = self; }; - /* - I used to set up nixpkgs in the flake, but doing that made - defining overlays in modules impossible (or at least I could - not figure out how) - Also has nice side effect of making it easier to add new systems :3 - */ - modules = [ - agenix.nixosModules.default - home-manager-unstable.nixosModule - nix-index-db-unstable.nixosModules.nix-index - ./roles/common - ./roles/desktop - ./roles/kde - ./roles/gaming - ./roles/school - ./machines/Archie - ]; + agenix = { + url = "github:ryantm/agenix"; + inputs = { + nixpkgs.follows = "nixpkgs"; + darwin.follows = ""; # Not using this on MacOS, so this doesn't pull it's dependencies + }; }; - SurfaceGo = nixpkgs-unstable.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-unstable; flakeSelf = self; }; - modules = [ - agenix.nixosModules.default - home-manager-unstable.nixosModule - nixos-hardware.nixosModules.microsoft-surface-go - nix-index-db-unstable.nixosModules.nix-index - ./roles/common - ./roles/desktop - ./roles/kde - ./machines/SurfaceGo - ]; + home-manager = { + url = "github:nix-community/home-manager/release-23.05"; + inputs.nixpkgs.follows = "nixpkgs"; }; - SteamDeck = nixpkgs-unstable.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-unstable; flakeSelf = self; }; - modules = [ - agenix.nixosModules.default - jovian.nixosModules.default - home-manager-unstable.nixosModule - nix-index-db-unstable.nixosModules.nix-index - ./roles/common - ./roles/desktop - ./roles/kde - ./roles/gaming - ./roles/school - ./machines/SteamDeck - ]; + home-manager-unstable = { + url = "github:nix-community/home-manager/"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; + + nixos-hardware.url = "github:NixOS/nixos-hardware/master"; + + jovian = { + url = "github:Jovian-Experiments/Jovian-NixOS"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; }; - Everest = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs; flakeSelf = self; }; - modules = [ - agenix.nixosModules.default - home-manager.nixosModule - nix-index-db.nixosModules.nix-index - ./roles/common - ./roles/server - ./machines/Everest - ]; + nix-impermanence.url = "github:nix-community/impermanence"; + + /* + These are the same input, just following different nixpkgs versions + This avoids some wierdness when using one that follows unstable on a stable nixpkgs + */ + nix-index-db = { + url = "github:Mic92/nix-index-database"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + nix-index-db-unstable = { + url = "github:Mic92/nix-index-database"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; + + plasma-manager = { + url = "github:pjones/plasma-manager"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + inputs.home-manager.follows = "home-manager-unstable"; + }; + + catppuccin-vsc = { + url = "github:catppuccin/vscode"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; + + vscode-extensions = { + url = "github:nix-community/nix-vscode-extensions"; + inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; + }; + + outputs = { ... } @inputs: with inputs; { + + devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { + name = "Environment for toast's nixos configurations"; + # The agenix cli is not needed to activate a configuration, so instead of installing it + # I'll just add it to de devShell, since that's the only real time I'm going to use it. + packages = with nixpkgs.legacyPackages.x86_64-linux; [ + agenix.packages.x86_64-linux.default + git + plasma5Packages.plasma-sdk + nix-diff + ]; + shellHook ='' + export PS1="$PS1(toast-configs)> " + ''; + }; + packages = { + x86_64-linux = with import nixpkgs-unstable { system = "x86_64-linux"; }; { + pseint = callPackage ./pkgs/pseint.nix {}; + anything-sync-daemon = callPackage ./pkgs/anything-sync-daemon {}; + discord-krisp-fixer = callPackage ./pkgs/discord-krisp-fixer {}; + }; + }; + nixosConfigurations = { + Archie = nixpkgs-unstable.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { systemPkgs = inputs.nixpkgs-unstable; flakeSelf = self; }; + /* + I used to set up nixpkgs in the flake, but doing that made + defining overlays in modules impossible (or at least I could + not figure out how) + Also has nice side effect of making it easier to add new systems :3 + */ + modules = [ + agenix.nixosModules.default + home-manager-unstable.nixosModule + nix-index-db-unstable.nixosModules.nix-index + ./roles/common + ./roles/desktop + ./roles/kde + ./roles/gaming + ./roles/school + ./machines/Archie + ]; + }; + + SurfaceGo = nixpkgs-unstable.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { systemPkgs = inputs.nixpkgs-unstable; flakeSelf = self; }; + modules = [ + agenix.nixosModules.default + home-manager-unstable.nixosModule + nixos-hardware.nixosModules.microsoft-surface-go + nix-index-db-unstable.nixosModules.nix-index + ./roles/common + ./roles/desktop + ./roles/kde + ./machines/SurfaceGo + ]; + }; + + SteamDeck = nixpkgs-unstable.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { systemPkgs = inputs.nixpkgs-unstable; flakeSelf = self; }; + modules = [ + agenix.nixosModules.default + jovian.nixosModules.default + home-manager-unstable.nixosModule + nix-index-db-unstable.nixosModules.nix-index + ./roles/common + ./roles/desktop + ./roles/kde + ./roles/gaming + ./roles/school + ./machines/SteamDeck + ]; + }; + + Everest = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { systemPkgs = inputs.nixpkgs; flakeSelf = self; }; + modules = [ + agenix.nixosModules.default + home-manager.nixosModule + nix-index-db.nixosModules.nix-index + ./roles/common + ./roles/server + ./machines/Everest + ]; + }; }; }; -}; } From 749476efccf736c5f5a3a0f92565f0e51f399c99 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 12 Nov 2023 23:25:23 +0100 Subject: [PATCH 0259/1125] Kde: change gtk2 config location --- roles/kde/plasma.nix | 67 ++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 329e2fa..cbcaa8c 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -85,36 +85,47 @@ in environment.systemPackages = [ breezeTint lookAndFeel plasmaDefaults ]; # Plasma configs should be on all users - home-manager.sharedModules = [{ - imports = [ flakeSelf.inputs.plasma-manager.homeManagerModules.plasma-manager ]; - gtk = { - enable = true; - cursorTheme = { package = pkgs.breeze-qt5; name = "breeze_cursors"; }; - iconTheme = { package = pkgs.breeze-icons; name = "breeze-dark"; }; - theme = { package = pkgs.breeze-gtk; name = "Breeze"; }; - # Gtk2 doesn't have a dark mode, so I just tell gtk 3 and 4 to use the dark variant - gtk3.extraConfig.gtk-application-prefer-dark-theme = true; - gtk4.extraConfig.gtk-application-prefer-dark-theme = true; - }; - programs.plasma = { - enable = true; - workspace.clickItemTo = "select"; - shortcuts = { - "kwin" = { - "Switch One Desktop to the Left" = [ "Meta+Ctrl+Left" ]; - "Switch One Desktop to the Right" = [ "Meta+Ctrl+Right" ]; - }; + home-manager.sharedModules = [ + ( + { config, ... }: + let gtk2rc = "${config.xdg.configHome}/gtk-2.0/gtkrc"; in + { + gtk.gtk2.configLocation = gtk2rc; + # Kde has an annoying habit of overwriting the gtk2 config file + home.file."${gtk2rc}".force = true; + } + ) + { + imports = [ flakeSelf.inputs.plasma-manager.homeManagerModules.plasma-manager ]; + gtk = { + enable = true; + cursorTheme = { package = pkgs.breeze-qt5; name = "breeze_cursors"; }; + iconTheme = { package = pkgs.breeze-icons; name = "breeze-dark"; }; + theme = { package = pkgs.breeze-gtk; name = "Breeze"; }; + # Gtk2 doesn't have a dark mode, so I just tell gtk 3 and 4 to use the dark variant + gtk3.extraConfig.gtk-application-prefer-dark-theme = true; + gtk4.extraConfig.gtk-application-prefer-dark-theme = true; }; - configFile = { - "kwinrc" = { - "Desktops" = { - "Number" = 2; - "Rows" = 1; + programs.plasma = { + enable = true; + workspace.clickItemTo = "select"; + shortcuts = { + "kwin" = { + "Switch One Desktop to the Left" = [ "Meta+Ctrl+Left" ]; + "Switch One Desktop to the Right" = [ "Meta+Ctrl+Right" ]; }; - "TabBox"."LayoutName" = "thumbnail_grid"; }; - "plasmanotifyrc"."Notifications"."NormalAlwaysOnTop" = true; + configFile = { + "kwinrc" = { + "Desktops" = { + "Number" = 2; + "Rows" = 1; + }; + "TabBox"."LayoutName" = "thumbnail_grid"; + }; + "plasmanotifyrc"."Notifications"."NormalAlwaysOnTop" = true; + }; }; - }; - }]; + } + ]; } From 6ca883ca0a85e6427705ae831b8e71a2d157720b Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 12 Nov 2023 23:32:06 +0100 Subject: [PATCH 0260/1125] Flake: add nix-flatpak --- flake.lock | 17 +++++++++++++++++ flake.nix | 2 ++ 2 files changed, 19 insertions(+) diff --git a/flake.lock b/flake.lock index 5e893a8..7a5829e 100644 --- a/flake.lock +++ b/flake.lock @@ -159,6 +159,22 @@ "type": "github" } }, + "nix-flatpak": { + "locked": { + "lastModified": 1699822045, + "narHash": "sha256-ZKKbXcf7UXirQokVYNF0gN5AulWPDPsXXce6KolGr+g=", + "owner": "gmodena", + "repo": "nix-flatpak", + "rev": "bb4a08e975c5a64a909cc42de31cb02408c9bda8", + "type": "github" + }, + "original": { + "owner": "gmodena", + "ref": "main", + "repo": "nix-flatpak", + "type": "github" + } + }, "nix-github-actions": { "inputs": { "nixpkgs": [ @@ -312,6 +328,7 @@ "home-manager": "home-manager_2", "home-manager-unstable": "home-manager-unstable", "jovian": "jovian", + "nix-flatpak": "nix-flatpak", "nix-impermanence": "nix-impermanence", "nix-index-db": "nix-index-db", "nix-index-db-unstable": "nix-index-db-unstable", diff --git a/flake.nix b/flake.nix index 0db6b75..9119495 100755 --- a/flake.nix +++ b/flake.nix @@ -60,7 +60,9 @@ vscode-extensions = { url = "github:nix-community/nix-vscode-extensions"; inputs.nixpkgs.follows = "nixpkgs-unstable"; + }; + nix-flatpak.url = github:gmodena/nix-flatpak/main; }; outputs = { ... } @inputs: with inputs; { From 1510694a4acd43405734411a3713dc525b5417b1 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 12 Nov 2023 23:48:20 +0100 Subject: [PATCH 0261/1125] Flatpak: manage flatpak with nix-flatpak --- roles/desktop/services/flatpak.nix | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/roles/desktop/services/flatpak.nix b/roles/desktop/services/flatpak.nix index daea0f7..8d92e91 100644 --- a/roles/desktop/services/flatpak.nix +++ b/roles/desktop/services/flatpak.nix @@ -1,20 +1,12 @@ -{ config, pkgs, ... }: +{ config, pkgs, flakeSelf, ... }: { services.flatpak.enable = true; - /* - Create systemd service that adds flathub after getting network - This adds it automatically, which avoids the whack ass way I was - doing that before - */ - systemd.services.flathub-add = { - description = "Add flathub repo to system flatpak install"; - script = "${pkgs.flatpak}/bin/flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo"; - serviceConfig.Type = "oneshot"; - wantedBy = [ "network-online.target" ]; - # Run after networking is working - after = [ "NetworkManager-wait-online.service" ]; - restartIfChanged = false; + home-manager = { + sharedModules = [{ imports = [ flakeSelf.inputs.nix-flatpak.homeManagerModules.nix-flatpak ]; }]; + users.toast = { + services.flatpak.packages = [ "tv.plex.PlexDesktop" ]; + }; }; } From fe9038c6857e5a3254d558131626dbdb1e6f7317 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 13 Nov 2023 12:11:21 +0100 Subject: [PATCH 0262/1125] Common: enable fwupd --- roles/common/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 5f8b13c..922ce06 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -59,6 +59,8 @@ }; }; + services.fwupd.enable = true; + # Set up time zone. time.timeZone = "Europe/Madrid"; From 61ff38685455242941aa94e16817385a00898fb7 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 15 Nov 2023 00:06:52 +0100 Subject: [PATCH 0263/1125] flake: update lock file --- flake.lock | 60 +++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/flake.lock b/flake.lock index 7a5829e..575c464 100644 --- a/flake.lock +++ b/flake.lock @@ -104,11 +104,11 @@ ] }, "locked": { - "lastModified": 1699748018, - "narHash": "sha256-28rwXnxgscLkeII6wj44cuP6RuiynhzZSa424ZwGt/s=", + "lastModified": 1699783872, + "narHash": "sha256-4zTwLT2LL45Nmo6iwKB3ls3hWodVP9DiSWxki/oewWE=", "owner": "nix-community", "repo": "home-manager", - "rev": "50e582b9f91e409ffd2e134017445d376659b32e", + "rev": "280721186ab75a76537713ec310306f0eba3e407", "type": "github" }, "original": { @@ -146,11 +146,11 @@ ] }, "locked": { - "lastModified": 1699679038, - "narHash": "sha256-rT2p5nyLUEZYzuctstoFvjKWVqTyTfJhgrVNkFp5g/0=", + "lastModified": 1699775106, + "narHash": "sha256-NzzQqHpCn5zg58hUF0W3V3sqJuuKGc31hTMBNfEXpr4=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "42d4937d4b08aef56b04279518c5d50e97532e8b", + "rev": "97dfcb8aa32a0ff07426b01c4d27c674c717ff76", "type": "github" }, "original": { @@ -161,11 +161,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1699822045, - "narHash": "sha256-ZKKbXcf7UXirQokVYNF0gN5AulWPDPsXXce6KolGr+g=", + "lastModified": 1699990197, + "narHash": "sha256-zsmELy+imDzoMTxAKhPRT2I7zJ3YGMP+yT0slgZZSxI=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "bb4a08e975c5a64a909cc42de31cb02408c9bda8", + "rev": "9b7e536b6e6ca41dd53d93a697470636f9d3ae56", "type": "github" }, "original": { @@ -219,11 +219,11 @@ ] }, "locked": { - "lastModified": 1699156599, - "narHash": "sha256-Qk9ZE/pG9lNIGUVNArJxL0Hc0Soa92eQPPIhcDwWinU=", + "lastModified": 1699760693, + "narHash": "sha256-u/gkNUHQR/q23voqE5J4xmEWQIAqR+g3lUnCtzn0k7Y=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "5388a4002179d6778d212dc2fdcc7ac3fdbd5b65", + "rev": "8aff4ca3dee60d1422489fe8d52c2f837b3ad113", "type": "github" }, "original": { @@ -239,11 +239,11 @@ ] }, "locked": { - "lastModified": 1699156599, - "narHash": "sha256-Qk9ZE/pG9lNIGUVNArJxL0Hc0Soa92eQPPIhcDwWinU=", + "lastModified": 1699760693, + "narHash": "sha256-u/gkNUHQR/q23voqE5J4xmEWQIAqR+g3lUnCtzn0k7Y=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "5388a4002179d6778d212dc2fdcc7ac3fdbd5b65", + "rev": "8aff4ca3dee60d1422489fe8d52c2f837b3ad113", "type": "github" }, "original": { @@ -254,11 +254,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1699701045, - "narHash": "sha256-mDzUXK7jNO/utInWpSWEX1NgEEunVIpJg+LyPsDTfy0=", + "lastModified": 1699997707, + "narHash": "sha256-ugb+1TGoOqqiy3axyEZpfF6T4DQUGjfWZ3Htry1EfvI=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "b689465d0c5d88e158e7d76094fca08cc0223aad", + "rev": "5689f3ebf899f644a1aabe8774d4f37eb2f6c2f9", "type": "github" }, "original": { @@ -270,11 +270,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1699291058, - "narHash": "sha256-5ggduoaAMPHUy4riL+OrlAZE14Kh7JWX4oLEs22ZqfU=", + "lastModified": 1699596684, + "narHash": "sha256-XSXP8zjBZJBVvpNb2WmY0eW8O2ce+sVyj1T0/iBRIvg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "41de143fda10e33be0f47eab2bfe08a50f234267", + "rev": "da4024d0ead5d7820f6bd15147d3fe2a0c0cec73", "type": "github" }, "original": { @@ -285,11 +285,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1699099776, - "narHash": "sha256-X09iKJ27mGsGambGfkKzqvw5esP1L/Rf8H3u3fCqIiU=", + "lastModified": 1699781429, + "narHash": "sha256-UYefjidASiLORAjIvVsUHG6WBtRhM67kTjEY4XfZOFs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "85f1ba3e51676fa8cc604a3d863d729026a6b8eb", + "rev": "e44462d6021bfe23dfb24b775cc7c390844f773d", "type": "github" }, "original": { @@ -308,11 +308,11 @@ ] }, "locked": { - "lastModified": 1699638264, - "narHash": "sha256-EGT10Ig8OFUY5T0nwnNuLa4z++yjaqfSQT/5Tyo1Z60=", + "lastModified": 1699974118, + "narHash": "sha256-gnJAGIQb8c+DRYBh1BB04VuaR3LeA2MDt1HoOPu2CYc=", "owner": "pjones", "repo": "plasma-manager", - "rev": "56c325e68d69b9682bcb1be99650b6c28bedb93d", + "rev": "709f01ba922d3b81890ab76aeb916e051f88ea49", "type": "github" }, "original": { @@ -363,11 +363,11 @@ ] }, "locked": { - "lastModified": 1699669360, - "narHash": "sha256-EHcoK/LUo3wI/IFTRWkXWKow58zy6x25MXvz48izSLs=", + "lastModified": 1699924757, + "narHash": "sha256-kPEAAJE7bW1d63bh9WM8GJAWc9MkU2TuD052R9HULiU=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "80bfa86f4b3f38b41991d92124bebeee7f30839f", + "rev": "962359139e8f7dd3106c0235b1137c972242bc93", "type": "github" }, "original": { From 79012f45de35361f44f593d71869e13fc5112360 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 16 Nov 2023 00:10:22 +0100 Subject: [PATCH 0264/1125] Vscode: don't write nested settings --- roles/desktop/programs/vscode.nix | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index 38f1b31..dd2ef5f 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -10,13 +10,16 @@ let inputs = flakeSelf.inputs; in pkgs.catppuccin-vsc ]; userSettings = { + # VSCode doesn't like nested settings + # https://stackoverflow.com/questions/74134436/is-it-possible-to-express-settings-in-vs-codes-settings-json-where-each-dot-sep + # TODO: write a function that unnests settings "workbench.colorTheme" = "Catppuccin Mocha"; - "editor" = { - "fontFamily" = "JetBrainsMono Nerd Font"; + "editor.fontFamily" = "JetBrainsMono Nerd Font"; + "editor.semanticHighlighting.enabled" = true; "semanticHighlighting.enabled" = true; }; - terminal.integrated.minimumContrastRatio = 1; - window.titleBarStyle = "custom"; + "terminal.integrated.minimumContrastRatio" = 1; + "window.titleBarStyle" = "custom"; }; }; } From 5b99e3cc569aacaa2dcc89eda9e7502e6f1c5fea Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 16 Nov 2023 00:12:55 +0100 Subject: [PATCH 0265/1125] Vscode: add catppuccin icon theme --- roles/desktop/programs/vscode.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index dd2ef5f..a1eb40c 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -8,12 +8,14 @@ let inputs = flakeSelf.inputs; in extensions = with inputs.vscode-extensions.extensions.x86_64-linux.open-vsx; [ jnoortheen.nix-ide pkgs.catppuccin-vsc + catppuccin.catppuccin-vsc-icons ]; userSettings = { # VSCode doesn't like nested settings # https://stackoverflow.com/questions/74134436/is-it-possible-to-express-settings-in-vs-codes-settings-json-where-each-dot-sep # TODO: write a function that unnests settings "workbench.colorTheme" = "Catppuccin Mocha"; + "workbench.iconTheme": "catppuccin-mocha" "editor.fontFamily" = "JetBrainsMono Nerd Font"; "editor.semanticHighlighting.enabled" = true; "semanticHighlighting.enabled" = true; From 8a1d1bd41d1d51a4ea1b24fae9e63123de37de74 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 16 Nov 2023 00:13:39 +0100 Subject: [PATCH 0266/1125] Vscode: use nil as language server --- roles/desktop/programs/vscode.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index a1eb40c..2b468cc 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -18,8 +18,8 @@ let inputs = flakeSelf.inputs; in "workbench.iconTheme": "catppuccin-mocha" "editor.fontFamily" = "JetBrainsMono Nerd Font"; "editor.semanticHighlighting.enabled" = true; - "semanticHighlighting.enabled" = true; - }; + "nix.enableLanguageServer = true;" + "nix.serverPath = "${pkgs.nil}/bin/nil";" "terminal.integrated.minimumContrastRatio" = 1; "window.titleBarStyle" = "custom"; }; From f461c9e8f3402824c1dd249457fdacdcd27ad0a3 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 16 Nov 2023 00:16:49 +0100 Subject: [PATCH 0267/1125] Vscode: fix mistakes (whoops) --- roles/desktop/programs/vscode.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index 2b468cc..4750c54 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -15,11 +15,11 @@ let inputs = flakeSelf.inputs; in # https://stackoverflow.com/questions/74134436/is-it-possible-to-express-settings-in-vs-codes-settings-json-where-each-dot-sep # TODO: write a function that unnests settings "workbench.colorTheme" = "Catppuccin Mocha"; - "workbench.iconTheme": "catppuccin-mocha" + "workbench.iconTheme" = "catppuccin-mocha"; "editor.fontFamily" = "JetBrainsMono Nerd Font"; "editor.semanticHighlighting.enabled" = true; - "nix.enableLanguageServer = true;" - "nix.serverPath = "${pkgs.nil}/bin/nil";" + "nix.enableLanguageServer" = true; + "nix.serverPath" = "${pkgs.nil}/bin/nil"; "terminal.integrated.minimumContrastRatio" = 1; "window.titleBarStyle" = "custom"; }; From e351761651ef0335dfa4b6bf973432ecc57b32b0 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 16 Nov 2023 16:49:59 +0100 Subject: [PATCH 0268/1125] Flake: update jovian input --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 575c464..2f26d02 100644 --- a/flake.lock +++ b/flake.lock @@ -146,11 +146,11 @@ ] }, "locked": { - "lastModified": 1699775106, - "narHash": "sha256-NzzQqHpCn5zg58hUF0W3V3sqJuuKGc31hTMBNfEXpr4=", + "lastModified": 1700118950, + "narHash": "sha256-sDJWgkVM9rCpB7mzROBR7ihEdrEYQmkGvPnPnr9Qj2I=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "97dfcb8aa32a0ff07426b01c4d27c674c717ff76", + "rev": "4e1f56008f6f88593c77c0cce12b3c67c82e0b3c", "type": "github" }, "original": { From 921f4d4dce04a0b0011e786924f3839a1ca9adc6 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 17 Nov 2023 11:18:57 +0100 Subject: [PATCH 0269/1125] Vscode: disable mutable extension dir --- roles/desktop/programs/vscode.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index 4750c54..436f52d 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -5,6 +5,7 @@ let inputs = flakeSelf.inputs; in home-manager.users.toast.programs.vscode = { enable = true; package = pkgs.vscodium; + mutableExtensionsDir = false; extensions = with inputs.vscode-extensions.extensions.x86_64-linux.open-vsx; [ jnoortheen.nix-ide pkgs.catppuccin-vsc From 65ed299e183f20c10bd9c31a5e82800418aaef19 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 19 Nov 2023 19:15:30 +0100 Subject: [PATCH 0270/1125] Revert "Gaming: temporarely disable heroic" This reverts commit 15d667763c44f1ec28ca60c2ad38e01707264f69. --- roles/gaming/programs/default.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/roles/gaming/programs/default.nix b/roles/gaming/programs/default.nix index 1e26114..4bba376 100755 --- a/roles/gaming/programs/default.nix +++ b/roles/gaming/programs/default.nix @@ -7,8 +7,7 @@ ./rpcs3.nix ]; environment.systemPackages = with pkgs; [ - # Heroic is using an electron version that's considered unsafe, so until that changes I'm not installing it - #heroic + heroic prismlauncher-qt5 ]; } From 9d1e799dd32a25791fcb2441217ec359af7e0fe3 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 19 Nov 2023 19:19:37 +0100 Subject: [PATCH 0271/1125] Desktop: temporarely disable vesktop --- roles/desktop/programs/discord.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 8f81f98..1c436c7 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -34,6 +34,8 @@ nixpkgs.overlays = [ discordOverlay ]; users.users.toast.packages = with pkgs; [ discord - vesktop + # Vesktop's npm deps don't build as of 19/11/2023 + # https://github.com/NixOS/nixpkgs/issues/268517 + #vesktop ]; } From e4c6910d41c0f123641680d313e330cae08d6c57 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 19 Nov 2023 19:19:02 +0100 Subject: [PATCH 0272/1125] Flake: update lock file --- flake.lock | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/flake.lock b/flake.lock index 2f26d02..aba73c9 100644 --- a/flake.lock +++ b/flake.lock @@ -104,11 +104,11 @@ ] }, "locked": { - "lastModified": 1699783872, - "narHash": "sha256-4zTwLT2LL45Nmo6iwKB3ls3hWodVP9DiSWxki/oewWE=", + "lastModified": 1700386809, + "narHash": "sha256-2IPxWo0Yplv+70EueZVLTwRAijax0tirYp5Jh0QV1A4=", "owner": "nix-community", "repo": "home-manager", - "rev": "280721186ab75a76537713ec310306f0eba3e407", + "rev": "9a4725afa67db35cdf7be89f30527d745194cafa", "type": "github" }, "original": { @@ -124,11 +124,11 @@ ] }, "locked": { - "lastModified": 1699748081, - "narHash": "sha256-MOmMapBydd7MTjhX4eeQZzKlCABWw8W6iSHSG4OeFKE=", + "lastModified": 1700392168, + "narHash": "sha256-v5LprEFx3u4+1vmds9K0/i7sHjT0IYGs7u9v54iz/OA=", "owner": "nix-community", "repo": "home-manager", - "rev": "04bac349d585c9df38d78e0285b780a140dc74a4", + "rev": "28535c3a34d79071f2ccb68671971ce0c0984d7e", "type": "github" }, "original": { @@ -146,11 +146,11 @@ ] }, "locked": { - "lastModified": 1700118950, - "narHash": "sha256-sDJWgkVM9rCpB7mzROBR7ihEdrEYQmkGvPnPnr9Qj2I=", + "lastModified": 1700377627, + "narHash": "sha256-MrYHE/oWqVVwyV9n2MbtAHWplCkLvCcvLj3TOkyHD5k=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "4e1f56008f6f88593c77c0cce12b3c67c82e0b3c", + "rev": "1ccd4c94521ef7e6678f9d918dbee703d116dd76", "type": "github" }, "original": { @@ -161,11 +161,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1699990197, - "narHash": "sha256-zsmELy+imDzoMTxAKhPRT2I7zJ3YGMP+yT0slgZZSxI=", + "lastModified": 1700311469, + "narHash": "sha256-89ulQo4Jqt1OP06DGDErkj1Dpa0i1GZzWpR6Cs5PbE8=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "9b7e536b6e6ca41dd53d93a697470636f9d3ae56", + "rev": "d8f54c27de6617c44a67c36b361d4ad2512a51ce", "type": "github" }, "original": { @@ -219,11 +219,11 @@ ] }, "locked": { - "lastModified": 1699760693, - "narHash": "sha256-u/gkNUHQR/q23voqE5J4xmEWQIAqR+g3lUnCtzn0k7Y=", + "lastModified": 1700363379, + "narHash": "sha256-fBEVPFwSZ6AmBE1s1oT7E9WVuqRghruxTnSQ8UUlMkw=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "8aff4ca3dee60d1422489fe8d52c2f837b3ad113", + "rev": "27920146e671a0d565aaa7452907383be14d8d82", "type": "github" }, "original": { @@ -239,11 +239,11 @@ ] }, "locked": { - "lastModified": 1699760693, - "narHash": "sha256-u/gkNUHQR/q23voqE5J4xmEWQIAqR+g3lUnCtzn0k7Y=", + "lastModified": 1700363379, + "narHash": "sha256-fBEVPFwSZ6AmBE1s1oT7E9WVuqRghruxTnSQ8UUlMkw=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "8aff4ca3dee60d1422489fe8d52c2f837b3ad113", + "rev": "27920146e671a0d565aaa7452907383be14d8d82", "type": "github" }, "original": { @@ -254,11 +254,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1699997707, - "narHash": "sha256-ugb+1TGoOqqiy3axyEZpfF6T4DQUGjfWZ3Htry1EfvI=", + "lastModified": 1700392353, + "narHash": "sha256-KARn8aVJu5fdW0jdJYoOQ1SPqWlNdz4l7r90NbArWSY=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "5689f3ebf899f644a1aabe8774d4f37eb2f6c2f9", + "rev": "2b00bc76dc893cd996a3d76a2f059d657a5ef37a", "type": "github" }, "original": { @@ -270,11 +270,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1699596684, - "narHash": "sha256-XSXP8zjBZJBVvpNb2WmY0eW8O2ce+sVyj1T0/iBRIvg=", + "lastModified": 1700272409, + "narHash": "sha256-Mge6iOvomplBsvQ47sIeVAwAUGSVXH4qCW4pLUt/qMI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "da4024d0ead5d7820f6bd15147d3fe2a0c0cec73", + "rev": "8e5e424b1c059e9ccf5db6a652458e30de05fa3a", "type": "github" }, "original": { @@ -285,11 +285,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1699781429, - "narHash": "sha256-UYefjidASiLORAjIvVsUHG6WBtRhM67kTjEY4XfZOFs=", + "lastModified": 1700204040, + "narHash": "sha256-xSVcS5HBYnD3LTer7Y2K8ZQCDCXMa3QUD1MzRjHzuhI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e44462d6021bfe23dfb24b775cc7c390844f773d", + "rev": "c757e9bd77b16ca2e03c89bf8bc9ecb28e0c06ad", "type": "github" }, "original": { @@ -308,11 +308,11 @@ ] }, "locked": { - "lastModified": 1699974118, - "narHash": "sha256-gnJAGIQb8c+DRYBh1BB04VuaR3LeA2MDt1HoOPu2CYc=", + "lastModified": 1700267030, + "narHash": "sha256-1ke+7xrkCVOI13RJ1w6EjCGcJywkN3bbTKbLWAt4jaE=", "owner": "pjones", "repo": "plasma-manager", - "rev": "709f01ba922d3b81890ab76aeb916e051f88ea49", + "rev": "019a8fd22a26c8d59f63aa9cc8a9c1729d6ffbda", "type": "github" }, "original": { @@ -363,11 +363,11 @@ ] }, "locked": { - "lastModified": 1699924757, - "narHash": "sha256-kPEAAJE7bW1d63bh9WM8GJAWc9MkU2TuD052R9HULiU=", + "lastModified": 1700357039, + "narHash": "sha256-fFUDvmtehDsPi3qlYe6/3c9566eSqm5P46Cq1+cnE5s=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "962359139e8f7dd3106c0235b1137c972242bc93", + "rev": "6ea6023195707236feb71e28948f9343cf3be882", "type": "github" }, "original": { From 9f4501f9099c431ecd61b17f18449412b25bb187 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 23 Nov 2023 20:54:49 +0100 Subject: [PATCH 0273/1125] Revert "Desktop: temporarely disable vesktop" This reverts commit 9d1e799dd32a25791fcb2441217ec359af7e0fe3. --- roles/desktop/programs/discord.nix | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 1c436c7..8f81f98 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -34,8 +34,6 @@ nixpkgs.overlays = [ discordOverlay ]; users.users.toast.packages = with pkgs; [ discord - # Vesktop's npm deps don't build as of 19/11/2023 - # https://github.com/NixOS/nixpkgs/issues/268517 - #vesktop + vesktop ]; } From 7de933ebf80caf020b2493019c9640521dd1f485 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 23 Nov 2023 22:13:45 +0100 Subject: [PATCH 0274/1125] Flake: update lock file --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index aba73c9..f118136 100644 --- a/flake.lock +++ b/flake.lock @@ -104,11 +104,11 @@ ] }, "locked": { - "lastModified": 1700386809, - "narHash": "sha256-2IPxWo0Yplv+70EueZVLTwRAijax0tirYp5Jh0QV1A4=", + "lastModified": 1700695018, + "narHash": "sha256-MAiPLgBF4GLzSOlhnPCDWkWW5CDx4i7ApIYaR+TwTVg=", "owner": "nix-community", "repo": "home-manager", - "rev": "9a4725afa67db35cdf7be89f30527d745194cafa", + "rev": "134deb46abd5d0889d913b8509413f6f38b0811e", "type": "github" }, "original": { @@ -254,11 +254,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1700392353, - "narHash": "sha256-KARn8aVJu5fdW0jdJYoOQ1SPqWlNdz4l7r90NbArWSY=", + "lastModified": 1700559156, + "narHash": "sha256-gL4epO/qf+wo30JjC3g+b5Bs8UrpxzkhNBBsUYxpw2g=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "2b00bc76dc893cd996a3d76a2f059d657a5ef37a", + "rev": "c3abafb01cd7045dba522af29b625bd1e170c2fb", "type": "github" }, "original": { @@ -270,11 +270,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1700272409, - "narHash": "sha256-Mge6iOvomplBsvQ47sIeVAwAUGSVXH4qCW4pLUt/qMI=", + "lastModified": 1700678569, + "narHash": "sha256-2Ki+2UvOidxEb3xB4ADqlbPQ2BZOF4uZMR094O8or2I=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8e5e424b1c059e9ccf5db6a652458e30de05fa3a", + "rev": "8f1180704ac35baded1a74164365ac7cdfba6f38", "type": "github" }, "original": { @@ -285,11 +285,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1700204040, - "narHash": "sha256-xSVcS5HBYnD3LTer7Y2K8ZQCDCXMa3QUD1MzRjHzuhI=", + "lastModified": 1700612854, + "narHash": "sha256-yrQ8osMD+vDLGFX7pcwsY/Qr5PUd6OmDMYJZzZi0+zc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c757e9bd77b16ca2e03c89bf8bc9ecb28e0c06ad", + "rev": "19cbff58383a4ae384dea4d1d0c823d72b49d614", "type": "github" }, "original": { @@ -363,11 +363,11 @@ ] }, "locked": { - "lastModified": 1700357039, - "narHash": "sha256-fFUDvmtehDsPi3qlYe6/3c9566eSqm5P46Cq1+cnE5s=", + "lastModified": 1700702385, + "narHash": "sha256-AZRCPWn01Rl6XvC4kLVjCxmSLEWAAYnHykwxs+hJt3s=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "6ea6023195707236feb71e28948f9343cf3be882", + "rev": "652649d593baaa40927ce3408dda4b4f27907220", "type": "github" }, "original": { From 3b0764c4787f3839951bca5e9288952d2a0cacf6 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 24 Nov 2023 23:27:02 +0100 Subject: [PATCH 0275/1125] .vscode: use spaces for indenting --- .vscode/settings.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index bebb1a3..fdf6a9a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "editor.detectIndentation": true, - "editor.insertSpaces": false, - "editor.defaultFormatter": "jnoortheen.nix-ide" + "editor.detectIndentation": true, + "editor.insertSpaces": true, + "editor.defaultFormatter": "jnoortheen.nix-ide" } From 834d512ba283ce5788870f6159f62e830ca85891 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 25 Nov 2023 00:37:09 +0100 Subject: [PATCH 0276/1125] Flatpak: enable weekly auto updates --- roles/desktop/services/flatpak.nix | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/roles/desktop/services/flatpak.nix b/roles/desktop/services/flatpak.nix index 8d92e91..5a6834c 100644 --- a/roles/desktop/services/flatpak.nix +++ b/roles/desktop/services/flatpak.nix @@ -6,7 +6,13 @@ home-manager = { sharedModules = [{ imports = [ flakeSelf.inputs.nix-flatpak.homeManagerModules.nix-flatpak ]; }]; users.toast = { - services.flatpak.packages = [ "tv.plex.PlexDesktop" ]; + services.flatpak = { + packages = [ "tv.plex.PlexDesktop" ]; + update.auto = { + enable = true; + onCalendar = "weekly"; + }; + }; }; }; } From 2e47069bd16eef0724ecc6c93b82ae0d9fe728a7 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 27 Nov 2023 10:51:06 +0100 Subject: [PATCH 0277/1125] Flake: update lock file --- flake.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/flake.lock b/flake.lock index f118136..5e311aa 100644 --- a/flake.lock +++ b/flake.lock @@ -104,11 +104,11 @@ ] }, "locked": { - "lastModified": 1700695018, - "narHash": "sha256-MAiPLgBF4GLzSOlhnPCDWkWW5CDx4i7ApIYaR+TwTVg=", + "lastModified": 1701071203, + "narHash": "sha256-lQywA7QU/vzTdZ1apI0PfgCWNyQobXUYghVrR5zuIeM=", "owner": "nix-community", "repo": "home-manager", - "rev": "134deb46abd5d0889d913b8509413f6f38b0811e", + "rev": "db1878f013b52ba5e4034db7c1b63e8d04173a86", "type": "github" }, "original": { @@ -146,11 +146,11 @@ ] }, "locked": { - "lastModified": 1700377627, - "narHash": "sha256-MrYHE/oWqVVwyV9n2MbtAHWplCkLvCcvLj3TOkyHD5k=", + "lastModified": 1700979728, + "narHash": "sha256-Myh4f+pXVDPrxw96K1czQZJv6fqZVdaXkzyyyR+H9ro=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "1ccd4c94521ef7e6678f9d918dbee703d116dd76", + "rev": "4599d9edef37dec460cc08e85da6c699ac0d78fd", "type": "github" }, "original": { @@ -219,11 +219,11 @@ ] }, "locked": { - "lastModified": 1700363379, - "narHash": "sha256-fBEVPFwSZ6AmBE1s1oT7E9WVuqRghruxTnSQ8UUlMkw=", + "lastModified": 1700968077, + "narHash": "sha256-Lax+2g7G3Fe+ckMrHLYTl+97unbmNDmN1qS9MLBkxr4=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "27920146e671a0d565aaa7452907383be14d8d82", + "rev": "bd3aec0ecb0fdde863a7ed2c6caa220c47e22c07", "type": "github" }, "original": { @@ -239,11 +239,11 @@ ] }, "locked": { - "lastModified": 1700363379, - "narHash": "sha256-fBEVPFwSZ6AmBE1s1oT7E9WVuqRghruxTnSQ8UUlMkw=", + "lastModified": 1700968077, + "narHash": "sha256-Lax+2g7G3Fe+ckMrHLYTl+97unbmNDmN1qS9MLBkxr4=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "27920146e671a0d565aaa7452907383be14d8d82", + "rev": "bd3aec0ecb0fdde863a7ed2c6caa220c47e22c07", "type": "github" }, "original": { @@ -254,11 +254,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1700559156, - "narHash": "sha256-gL4epO/qf+wo30JjC3g+b5Bs8UrpxzkhNBBsUYxpw2g=", + "lastModified": 1701020860, + "narHash": "sha256-NwnRn04C8s+hH+KdVtGmVB1FFNIG7DtPJmQSCBDaET4=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "c3abafb01cd7045dba522af29b625bd1e170c2fb", + "rev": "b006ec52fce23b1d57f6ab4a42d7400732e9a0a2", "type": "github" }, "original": { @@ -270,11 +270,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1700678569, - "narHash": "sha256-2Ki+2UvOidxEb3xB4ADqlbPQ2BZOF4uZMR094O8or2I=", + "lastModified": 1700989516, + "narHash": "sha256-oKbmPa2wpTHh9XB3+zIx97uMZGNnp97GPliKKG2/plo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8f1180704ac35baded1a74164365ac7cdfba6f38", + "rev": "d2e4de209881b38392933fabf303cde3454b0b4c", "type": "github" }, "original": { @@ -285,11 +285,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1700612854, - "narHash": "sha256-yrQ8osMD+vDLGFX7pcwsY/Qr5PUd6OmDMYJZzZi0+zc=", + "lastModified": 1700794826, + "narHash": "sha256-RyJTnTNKhO0yqRpDISk03I/4A67/dp96YRxc86YOPgU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "19cbff58383a4ae384dea4d1d0c823d72b49d614", + "rev": "5a09cb4b393d58f9ed0d9ca1555016a8543c2ac8", "type": "github" }, "original": { @@ -363,11 +363,11 @@ ] }, "locked": { - "lastModified": 1700702385, - "narHash": "sha256-AZRCPWn01Rl6XvC4kLVjCxmSLEWAAYnHykwxs+hJt3s=", + "lastModified": 1701048169, + "narHash": "sha256-gsYFAIDMyXztMl39/EQzIVjQx/7z+0XPuCDhkrF2tbw=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "652649d593baaa40927ce3408dda4b4f27907220", + "rev": "23dfda3e3df1901d38f1efc98d3e90cefd73ff5d", "type": "github" }, "original": { From 9592300a09e3761058257bcaa868823c0013f2ff Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 27 Nov 2023 13:32:17 +0100 Subject: [PATCH 0278/1125] School/xampp: add booDark phpmyadmin theme --- roles/school/services/xampp.nix | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/roles/school/services/xampp.nix b/roles/school/services/xampp.nix index 1ec12a2..99f65bf 100644 --- a/roles/school/services/xampp.nix +++ b/roles/school/services/xampp.nix @@ -1,5 +1,10 @@ -{ config, ... }: - +{ config, pkgs, ... }: +let + booDark = pkgs.fetchzip { + url = "https://github.com/adorade/boodark/releases/download/v1.1.1/boodark-v1.1.1.zip"; + hash = "sha256-GE/FtFlU6A4I9sRyjMhQIidGpDLD99Wzzngz3QI/rSo="; + }; +in { # I tried setting up httpd + php in class but I just gave up virtualisation.oci-containers = { @@ -9,6 +14,8 @@ #user = "${toString users.users.atfc.uid}:${toString users.groups.minecraft.gid}"; volumes = [ "xampp-mysql:/opt/lampp/var/mysql" + # No dark mode installed by default :( + "${booDark}:/opt/lampp/phpmyadmin/themes/booDark" ]; ports = [ "41061:22" "41062:80" ]; }; From 51f3854609df4448704db83d79dc26372ce02596 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 30 Nov 2023 10:17:11 +0100 Subject: [PATCH 0279/1125] Kde: install neochat --- roles/kde/programs/default.nix | 1 + roles/kde/programs/neochat.nix | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 roles/kde/programs/neochat.nix diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index 21e5545..796a605 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -5,6 +5,7 @@ ./kate.nix ./firefox.nix ./skanpage.nix + ./neochat.nix ]; # Enable the kde partition manager diff --git a/roles/kde/programs/neochat.nix b/roles/kde/programs/neochat.nix new file mode 100644 index 0000000..f2009b3 --- /dev/null +++ b/roles/kde/programs/neochat.nix @@ -0,0 +1,7 @@ +{ pkgs, ... }: + +{ + home-manager.users.toast = { + home.packages = [ pkgs.neochat ]; + }; +} \ No newline at end of file From 2542722888ba883ff7ceaf7204176608a71e33e7 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 30 Nov 2023 10:19:00 +0100 Subject: [PATCH 0280/1125] School: install webstorm with plugins --- roles/school/programs/default.nix | 1 + roles/school/programs/webstorm.nix | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 roles/school/programs/webstorm.nix diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 24dba3a..f1fad93 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -4,6 +4,7 @@ imports = [ ./virtualbox.nix ./idea.nix + ./webstorm.nix ./vscode.nix ]; diff --git a/roles/school/programs/webstorm.nix b/roles/school/programs/webstorm.nix new file mode 100644 index 0000000..66a2265 --- /dev/null +++ b/roles/school/programs/webstorm.nix @@ -0,0 +1,22 @@ +{ pkgs, ... }: + +with pkgs; +{ + + home-manager.users.toast = { + home = { + packages = [ jetbrains.webstorm ]; + # Install plugins + file = { + ".local/share/JetBrains/WebStorm2023.2/catppuccin.jar".source = fetchurl { + url = "https://github.com/catppuccin/jetbrains/releases/download/v3.2.1/Catppuccin.Theme-3.2.1.jar"; + hash = "sha256-vE3Tv/dNfWyRuBJXLDPmtY1GnLShqM+dJR5rltXYdOY="; + }; + ".local/share/JetBrains/WebStorm2023.2/rainbow-brackets".source = fetchzip { + url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/2023.3.7/intellij-rainbow-brackets-2023.3.7.zip"; + hash = "sha256-szgyQs3iCge9rI274PA29i+tprPE11xpyJqiccedp6A="; + }; + }; + }; + }; +} From 6871f8f301fa1a72c01b83f0955b35987737b0aa Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 1 Dec 2023 00:27:01 +0100 Subject: [PATCH 0281/1125] Kde: set gtk cursor to breeze light --- roles/kde/plasma.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index cbcaa8c..47924d6 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -99,7 +99,8 @@ in imports = [ flakeSelf.inputs.plasma-manager.homeManagerModules.plasma-manager ]; gtk = { enable = true; - cursorTheme = { package = pkgs.breeze-qt5; name = "breeze_cursors"; }; + # Most apps are dark, so a white cursor is easier to spot + cursorTheme = { package = pkgs.breeze-qt5; name = "Breeze_Snow"; }; iconTheme = { package = pkgs.breeze-icons; name = "breeze-dark"; }; theme = { package = pkgs.breeze-gtk; name = "Breeze"; }; # Gtk2 doesn't have a dark mode, so I just tell gtk 3 and 4 to use the dark variant From 015ad6a1c685985eb2c90a8c0e8bb197f216decc Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 27 Nov 2023 11:05:12 +0100 Subject: [PATCH 0282/1125] Revert "Bat: use old theme syntax" This reverts commit 0d6bdf7d94a79070d3fe03d89bbbe4d092f159d5. --- roles/common/programs/bat.nix | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/roles/common/programs/bat.nix b/roles/common/programs/bat.nix index 207887e..2075753 100644 --- a/roles/common/programs/bat.nix +++ b/roles/common/programs/bat.nix @@ -1,17 +1,5 @@ { config, pkgs, ... }: -let - # Home manager on 23.05 doesn't understand the new format, so I'll use the old one until 23.11 becomes stable - newformat = { - src = pkgs.fetchFromGitHub { - owner = "catppuccin"; - repo = "bat"; - rev = "master"; - hash = "sha256-6WVKQErGdaqb++oaXnY3i6/GuH2FhTgK0v4TN4Y0Wbw="; - }; - file = "Catppuccin-mocha.tmTheme"; - }; - oldformat = builtins.readFile (newformat.src + "/${newformat.file}"); -in + { home-manager = { users.toast.programs.bat = { @@ -20,7 +8,15 @@ in theme = "catppuccin-mocha"; }; themes = { - catppuccin-mocha = oldformat; + catppuccin-mocha = { + src = pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "bat"; + rev = "master"; + hash = "sha256-6WVKQErGdaqb++oaXnY3i6/GuH2FhTgK0v4TN4Y0Wbw="; + }; + file = "Catppuccin-mocha.tmTheme"; + }; }; }; }; From d9aab2cdc8ed6b6f6bd6d55d7fcbd088427ffe36 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 27 Nov 2023 11:21:22 +0100 Subject: [PATCH 0283/1125] Desktop: use new fonts format --- roles/desktop/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index 2ad993a..7a07df6 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -9,7 +9,7 @@ users.users.toast.extraGroups = [ "scanner" ]; # Set up fonts - fonts.fonts = [ + fonts.packages = [ ( pkgs.nerdfonts.override { fonts = [ "Hack" "JetBrainsMono" ]; } ) ]; From 63d6a617c1aa97d24ea6f52868b82b75208bdbf1 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 30 Nov 2023 23:30:56 +0100 Subject: [PATCH 0284/1125] Flake: update stable nixpkgs to 23.11 --- flake.lock | 16 ++++++++-------- flake.nix | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index 5e311aa..4a17911 100644 --- a/flake.lock +++ b/flake.lock @@ -124,16 +124,16 @@ ] }, "locked": { - "lastModified": 1700392168, - "narHash": "sha256-v5LprEFx3u4+1vmds9K0/i7sHjT0IYGs7u9v54iz/OA=", + "lastModified": 1700814205, + "narHash": "sha256-lWqDPKHRbQfi+zNIivf031BUeyciVOtwCwTjyrhDB5g=", "owner": "nix-community", "repo": "home-manager", - "rev": "28535c3a34d79071f2ccb68671971ce0c0984d7e", + "rev": "aeb2232d7a32530d3448318790534d196bf9427a", "type": "github" }, "original": { "owner": "nix-community", - "ref": "release-23.05", + "ref": "release-23.11", "repo": "home-manager", "type": "github" } @@ -270,16 +270,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1700989516, - "narHash": "sha256-oKbmPa2wpTHh9XB3+zIx97uMZGNnp97GPliKKG2/plo=", + "lastModified": 1701263465, + "narHash": "sha256-lNXUIlkfyDyp9Ox21hr+wsEf/IBklLvb6bYcyeXbdRc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d2e4de209881b38392933fabf303cde3454b0b4c", + "rev": "50aa30a13c4ab5e7ba282da460a3e3d44e9d0eb3", "type": "github" }, "original": { "id": "nixpkgs", - "ref": "nixos-23.05", + "ref": "nixos-23.11", "type": "indirect" } }, diff --git a/flake.nix b/flake.nix index 9119495..75ab5e1 100755 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "Configuration for Everest"; inputs = { - nixpkgs.url = "nixpkgs/nixos-23.05"; + nixpkgs.url = "nixpkgs/nixos-23.11"; nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; agenix = { @@ -14,7 +14,7 @@ }; home-manager = { - url = "github:nix-community/home-manager/release-23.05"; + url = "github:nix-community/home-manager/release-23.11"; inputs.nixpkgs.follows = "nixpkgs"; }; From d5098eb264178469deb6decc450cd83ad5c75e11 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 1 Dec 2023 00:00:42 +0100 Subject: [PATCH 0285/1125] Move syncthing options to new format --- roles/common/services/syncthing.nix | 58 ++++++++++++++-------------- roles/desktop/services/syncthing.nix | 2 +- roles/gaming/services/syncthing.nix | 2 +- roles/school/services/syncthing.nix | 2 +- roles/server/syncthing.nix | 2 +- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index 966b866..9a090ab 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -5,39 +5,39 @@ overrideDevices = true; overrideFolders = true; openDefaultPorts = true; - extraOptions = { + settings = { options = { urAccepted = 3; }; - }; - # Set up devices and folders common to every device - devices = { - "phone" = { - name = "Xiaomi Redmi Note 10 Pro"; - id = "K7KNZ5V-XREUADL-CROQXPV-6AA4H65-2VUD34Z-VQWKJ6S-LWWW4EE-XPNEZQ6"; + # Set up devices and folders common to every device + devices = { + "phone" = { + name = "Xiaomi Redmi Note 10 Pro"; + id = "K7KNZ5V-XREUADL-CROQXPV-6AA4H65-2VUD34Z-VQWKJ6S-LWWW4EE-XPNEZQ6"; + }; + "pc" = { + name = "Archie"; + id = "NJPX754-64AQNP3-7GZFIRZ-W2EDRJQ-27ORWYM-X5YXEXQ-ERRTRTQ-BSYD4AY"; + }; + "steamdeck" = { + name = "Steam Deck"; + id = "DNFEGEA-PDEVW5A-O5VBVQK-IUXI7J5-MAHCQAG-2JLEFFM-DSXB6AS-TX6ZHAN"; + }; + "server" = { + name = "Everest"; + id = "BVJBCAZ-WDIWBFR-CK3WB3N-TWH3UXX-EPZXVWE-BLQ3IDU-U7MHVVB-WO4BKAJ"; + }; + "surface" = { + name = "Surface Go"; + id = "HTVSF3O-AHY3TNH-BLVSEGK-HRRSMHC-H5LJWVF-NDKGM6O-ATWZALC-YXNV2Q4"; + }; }; - "pc" = { - name = "Archie"; - id = "NJPX754-64AQNP3-7GZFIRZ-W2EDRJQ-27ORWYM-X5YXEXQ-ERRTRTQ-BSYD4AY"; - }; - "steamdeck" = { - name = "Steam Deck"; - id = "DNFEGEA-PDEVW5A-O5VBVQK-IUXI7J5-MAHCQAG-2JLEFFM-DSXB6AS-TX6ZHAN"; - }; - "server" = { - name = "Everest"; - id = "BVJBCAZ-WDIWBFR-CK3WB3N-TWH3UXX-EPZXVWE-BLQ3IDU-U7MHVVB-WO4BKAJ"; - }; - "surface" = { - name = "Surface Go"; - id = "HTVSF3O-AHY3TNH-BLVSEGK-HRRSMHC-H5LJWVF-NDKGM6O-ATWZALC-YXNV2Q4"; - }; - }; - folders = { - "passwords" = { - label = "KeePassXC Passwords"; - id = "rdyaq-ex659"; - devices = [ "phone" "pc" "steamdeck" "server" "surface"]; + folders = { + "passwords" = { + label = "KeePassXC Passwords"; + id = "rdyaq-ex659"; + devices = [ "phone" "pc" "steamdeck" "server" "surface"]; + }; }; }; }; diff --git a/roles/desktop/services/syncthing.nix b/roles/desktop/services/syncthing.nix index c650ba9..84dc962 100644 --- a/roles/desktop/services/syncthing.nix +++ b/roles/desktop/services/syncthing.nix @@ -6,7 +6,7 @@ user = "toast"; group = "users"; dataDir = config.users.users.toast.home; - folders."passwords".path = "~/Documents/Passwords"; + settings.folders."passwords".path = "~/Documents/Passwords"; }; # Allow regular users to stop syncthing # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service diff --git a/roles/gaming/services/syncthing.nix b/roles/gaming/services/syncthing.nix index d275d88..ed786b6 100644 --- a/roles/gaming/services/syncthing.nix +++ b/roles/gaming/services/syncthing.nix @@ -6,7 +6,7 @@ TODO: turn this into a module eventually */ - services.syncthing.folders = { + services.syncthing.settings.folders = { "steam-201810" = { label = "Wolfenstein The New Order Saves"; id = "laxxf-t2wmy"; diff --git a/roles/school/services/syncthing.nix b/roles/school/services/syncthing.nix index aac049a..9663c57 100644 --- a/roles/school/services/syncthing.nix +++ b/roles/school/services/syncthing.nix @@ -1,7 +1,7 @@ { config, ... }: { - services.syncthing.folders = { + services.syncthing.settings.folders = { "school-things" = { label = "School things"; id = "z6alc-nfoqr"; diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 9c84f89..489324d 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -11,7 +11,7 @@ key = config.age.secrets.syncthingKey.path; cert = config.age.secrets.syncthingCert.path; guiAddress = "0.0.0.0:8384"; - folders = { + settings.folders = { "passwords" = { path = "${config.services.syncthing.dataDir}/passwords"; }; From d54cf1741b5bd1c60e48a5b733002c060e6d443f Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 1 Dec 2023 00:03:37 +0100 Subject: [PATCH 0286/1125] Everest: declare interface for default gateway --- machines/Everest/configuration.nix | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index 1d88a68..5db99e7 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -28,10 +28,14 @@ prefixLength = 24; } ]; }; - defaultGateway = "192.168.0.1"; + # I use networkd, so I need to declare the interface for the default gateway + defaultGateway = { + address = "192.168.0.1"; + interface = "eno1"; + }; nameservers = [ "8.8.8.8" ]; }; - + # Define a user account. Don't forget to set a password with ‘passwd’. users.users.toast = { isNormalUser = true; From 0281e6cfeb6dd94f6e80215f1decc43c1326459a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 1 Dec 2023 00:12:33 +0100 Subject: [PATCH 0287/1125] Update home manager and system stateVersion to 23.11 --- roles/common/configuration.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 922ce06..42a9518 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -69,7 +69,7 @@ useGlobalPkgs = true; verbose = true; users.toast = { config, ... }: { - home.stateVersion = "23.05"; + home.stateVersion = "23.11"; xdg = { userDirs = { enable = true; @@ -100,7 +100,7 @@ */ system = { - stateVersion = "23.05"; + stateVersion = "23.11"; # Nix on nixos 23.05 does not have dirtyRev configurationRevision = flakeSelf.sourceInfo.rev or flakeSelf.sourceInfo.dirtyRev or "dirty"; nixos.variant_id = lib.strings.toLower config.networking.hostName; From d1787ecb247f72a9215299d9668d93919bef8380 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 4 Dec 2023 01:28:07 +0100 Subject: [PATCH 0288/1125] Everest: mount subvolumes --- machines/Everest/hardware-configuration.nix | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/machines/Everest/hardware-configuration.nix b/machines/Everest/hardware-configuration.nix index 528f3ba..ba3f567 100755 --- a/machines/Everest/hardware-configuration.nix +++ b/machines/Everest/hardware-configuration.nix @@ -13,10 +13,23 @@ boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; - fileSystems."/" = - { device = "/dev/disk/by-label/Everest"; + fileSystems = { + "/" = { + device = "/dev/disk/by-label/Everest"; fsType = "btrfs"; + options = [ "compress=zstd" "subvol=@"]; + }; + "/nix" = { + device = "/dev/disk/by-label/Everest"; + fsType = "btrfs"; + options = [ "compress=zstd" "subvol=@nix" ]; }; + "/home" = { + device = "/dev/disk/by-label/Everest"; + fsType = "btrfs"; + options = [ "compress=zstd" "subvol=@home" ]; + }; + }; fileSystems."/boot/efi" = { device = "/dev/disk/by-label/Boot"; From e8f709aa45063c562a602225121b4241f19e602e Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 5 Dec 2023 20:46:03 +0100 Subject: [PATCH 0289/1125] Everest: replace google dns with quad9 --- machines/Everest/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index 5db99e7..3a860e1 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -33,7 +33,7 @@ address = "192.168.0.1"; interface = "eno1"; }; - nameservers = [ "8.8.8.8" ]; + nameservers = [ "9.9.9.9" ]; }; # Define a user account. Don't forget to set a password with ‘passwd’. From dc3a37fd98639628cfcc13fb79013620fbe6263c Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 6 Dec 2023 15:13:08 +0100 Subject: [PATCH 0290/1125] Server: remove unused wireguard configs and secrets --- roles/server/default.nix | 1 - roles/server/wireguard.nix | 73 ----------------------------------- secrets/secrets.nix | 6 --- secrets/wg/silver/phonePriv | 8 ---- secrets/wg/silver/phonePsk | 8 ---- secrets/wg/silver/serverPriv | 8 ---- secrets/wg/toast/phonePriv | Bin 379 -> 0 bytes secrets/wg/toast/phonePsk | 8 ---- secrets/wg/toast/serverPriv | 8 ---- 9 files changed, 120 deletions(-) delete mode 100644 roles/server/wireguard.nix delete mode 100644 secrets/wg/silver/phonePriv delete mode 100644 secrets/wg/silver/phonePsk delete mode 100644 secrets/wg/silver/serverPriv delete mode 100644 secrets/wg/toast/phonePriv delete mode 100644 secrets/wg/toast/phonePsk delete mode 100644 secrets/wg/toast/serverPriv diff --git a/roles/server/default.nix b/roles/server/default.nix index 075c012..af9c11a 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -12,7 +12,6 @@ ./transmission.nix ./ddclient.nix ./beep.nix - ./wireguard.nix ./tailscale.nix ./traefik.nix ./minecraft.nix diff --git a/roles/server/wireguard.nix b/roles/server/wireguard.nix deleted file mode 100644 index 6ad8b0d..0000000 --- a/roles/server/wireguard.nix +++ /dev/null @@ -1,73 +0,0 @@ -{ config, pkgs, ... }: - -{ - # Set up secrets - age.secrets = { - silverPrivate.file = ../../secrets/wg/silver/serverPriv; - silverPhonePsk.file = ../../secrets/wg/silver/phonePsk; - toastPrivate.file = ../../secrets/wg/toast/serverPriv; - toastPhonePsk.file = ../../secrets/wg/toast/phonePsk; - }; - - networking = { - # You need NAT if you want to use wireguard as a VPN - nat = { - enable = true; - externalInterface = "eno1"; - internalInterfaces = [ "wg-*" ]; - }; - - # Allow the wireguard port though the firewall - firewall.allowedUDPPorts = with config.networking.wireguard.interfaces; [ vpn-silver.listenPort vpn-toast.listenPort]; - - wireguard = { - enable = true; - interfaces = { - vpn-silver = { - /* - I see people normally use 10.0.X.X, but I already have the muscle memory of - typing 192.168.X.X so I went with this one. Plus I'm only going to have 2-3 - peers connected at once, so a type C IP is more than enough - */ - ips = [ "192.168.10.1/24" ]; - listenPort = 51820; - privateKeyFile = config.age.secrets.silverPrivate.path; - postSetup = '' - ${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eno1 -j MASQUERADE - ''; - postShutdown = '' - ${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 192.168.10.0/24 -o eno1 -j MASQUERADE - ''; - peers = [ - { - # Silver's phone - allowedIPs = [ "192.168.10.2" ]; - publicKey = "silvrNOD8j5aDm4PhY8zJBV3JZOeBX6VK5KPvT+3yic="; - presharedKeyFile = config.age.secrets.silverPhonePsk.path; - } - ]; - }; - vpn-toast = { - ips = [ "192.168.11.1/24" ]; - listenPort = 51821; - privateKeyFile = config.age.secrets.toastPrivate.path; - postSetup = '' - ${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 192.168.11.0/24 -o eno1 -j MASQUERADE - ''; - postShutdown = '' - ${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 192.168.11.0/24 -o eno1 -j MASQUERADE - ''; - peers = [ - { - # My phone - allowedIPs = [ "192.168.11.2" ]; - publicKey = "pHonE1YaBZcTU5sTMLg6Iy4FIyzInfHfH4x0NZ1lBRA="; - presharedKeyFile = config.age.secrets.toastPhonePsk.path; - } - ]; - }; - - }; - }; - }; -} diff --git a/secrets/secrets.nix b/secrets/secrets.nix index f43b96a..fbb968e 100755 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -7,10 +7,4 @@ in "cock".publicKeys = [ everest ]; "syncthing/key".publicKeys = [ everest ]; "syncthing/cert".publicKeys = [ everest ]; - "wg/silver/serverPriv".publicKeys = [ everest ]; - "wg/silver/phonePriv".publicKeys = [ everest ]; - "wg/silver/phonePsk".publicKeys = [ everest ]; - "wg/toast/serverPriv".publicKeys = [ everest ]; - "wg/toast/phonePriv".publicKeys = [ everest ]; - "wg/toast/phonePsk".publicKeys = [ everest ]; } diff --git a/secrets/wg/silver/phonePriv b/secrets/wg/silver/phonePriv deleted file mode 100644 index e6d0722..0000000 --- a/secrets/wg/silver/phonePriv +++ /dev/null @@ -1,8 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 VoNo4A vExPc7M17NblMkOjJCxVm6I4v6/6yYBzE6nfc9saOEc -muXFANq6dGV+ToPwlUTkZ84wVsGqnTcCLvncmOgcbrk --> VN-grease (ijvp 99` (qc -f+ZaYegYdxUu4uj7uGtIl1Pm1ipMe4gQxs57vQxYCHOYO6tejSbwI8Y8sOAzkNV0 -pv0EFylBo9Y ---- SrPUCAPc2SmcpvPoPEK/gYJ9hn+vdplxJRMBfRSamAo -bϾr ?/⻏Q2Drr4;^|T {!] \ No newline at end of file diff --git a/secrets/wg/silver/phonePsk b/secrets/wg/silver/phonePsk deleted file mode 100644 index 796fddf..0000000 --- a/secrets/wg/silver/phonePsk +++ /dev/null @@ -1,8 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 VoNo4A 8YvcfWII3BKsM+V+ceoFC3XXldC0qvwnL/6ggK+Il0s -irwDqE2NcFHU/mVlhvIt787a4EW3kmEd11d0P393zXA --> Wu;RC:#-grease EIrU+ a1!S.4 t Uq#Qab6^ -mpekj8nSA5jpzDm1l5VrrYxMxmcuG5Yh+ABWkv2Dn9dKuJG6E1CIcAnU+9rpP6n4 -waoAYhTnVZpcHd1qVVm1Mwlz1REymNYxYw7MVplfM3lm1jSU ---- Q+IuFa2gerHpADs2TR/ZkULZV0rIaUvqFpoiovmbcQs -A3zX"Ijlkx u7 UhGJ֏{+^qbL?RImS܈=PԽgqFtJx \ No newline at end of file diff --git a/secrets/wg/silver/serverPriv b/secrets/wg/silver/serverPriv deleted file mode 100644 index 0c42bd4..0000000 --- a/secrets/wg/silver/serverPriv +++ /dev/null @@ -1,8 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 VoNo4A xu8kFORPIO3cpRKruN2H3Ab8kGHKooWF+a51uvo6AnQ -2LyysvbhXMTJ+CXZtqYksxNAH5E+fgpmtCkX0TVp1SI --> T$7CzH-grease ZJA,Gm -fyYJztvSX5VrUustF3Y3XpgdmAhpMR/4 ---- S/lJcXIuerNOPN687eO9CgsLZE8/yTEGfs2GUD4H/+Y -ҵI - }v''9Fnג؏<W]t`k+xl7p9/5zCxFFHr \ No newline at end of file diff --git a/secrets/wg/toast/phonePriv b/secrets/wg/toast/phonePriv deleted file mode 100644 index 76cc57306235177806cfc752643545a19d7bc9b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 379 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCR+%lFGSaa3?O4@eA4 z&owCu$}Wm@)(*_b(hmqo5395Y%<*?BPpxoFa?MNAE;38Xa^!MxF)cO-^-C}DG;;Ow zbal;ePb|wR(GPXaG0x11$jU3otS|_+@bJoZ2?g1vt(#tynpm8wpj@8j6&Ir5?_X?N z;+mz$Raog)R25R>n&Mwv=usM2o?;jj5gt|HW$NJ=S>_p$>Y<%gn(W~hn3&{OY+w=) z=8@-CQXZ*o;cQ%-9_p5u!Iff~mSS8LUYea^nv1oa~nFpPlWU9mJ)ptE=GS z7G~~i=4k31P?c(y6j|)(7aHp9R~nM-nwVAMZ|as98JH5_7wQ~h?8&8QuiBecu*)}i zibc-9#yzW)k}^upPB^h*VeFGXQ}>0+SZ6RKJiqWL%5|rKHvgA^Y1|pNxSURT_&rVe XTAO0IZ?V)h??0MS`C&gDSp~EJD9(j! diff --git a/secrets/wg/toast/phonePsk b/secrets/wg/toast/phonePsk deleted file mode 100644 index 853edab..0000000 --- a/secrets/wg/toast/phonePsk +++ /dev/null @@ -1,8 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 VoNo4A LJQA1BbMRZCiasZkqUIYdEF4U8AFfHv+tiDkIfp5xV0 -YVKxaYXmLMimAjQ5N0ALSkptDcSmUafX1JPaA+lXLiU --> {m4@-grease o=oC?P u1g sMgp\s" -GwnTCGHOjeG1XzcjSD/nqqY5eJRAkCIikGEIhLCLfuKqryn69mRz0mxoy7949j4j -oSG2 ---- z6TjnxxvqB7M7IXuIEJIpQrSvtW6yUC+FJDC9e9o2rg -fYR"gg`AO;&; h;'(ujNw吨FDg \ No newline at end of file diff --git a/secrets/wg/toast/serverPriv b/secrets/wg/toast/serverPriv deleted file mode 100644 index e7e3de5..0000000 --- a/secrets/wg/toast/serverPriv +++ /dev/null @@ -1,8 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 VoNo4A Y2wquDHovRlD2P7tv+6Z+DV3uoOeqs219woSenjJGBg -ZvHSzvAxlK2hZt41I1q4lAV3g9dg+8onphpG8V3gPM8 --> /-grease leqR -wT1Jyk7ceGKQlsQrNuTigKJbRLbk32r1ic/kHZnFikn1/Jx8W5t7VEVxV/qbbjM7 -2eV73hu3QR8uz/1/wwMuX9yyPX79o/BbmThqAwXR ---- v2H9k4DcOqjtAuw7fgX2AEOnJLC8BMH5l8KPvoLxxKc -'.|^_|svO'3@l6eQB.3/+I0-?Ihdm{h \ No newline at end of file From 486d719d52f15b0df4bda500fe4799baf4b2d406 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 9 Dec 2023 17:59:44 +0100 Subject: [PATCH 0291/1125] Server/dns: enable and configure dnsmasq --- roles/server/default.nix | 1 + roles/server/dns.nix | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 roles/server/dns.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index af9c11a..5d6a6b8 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -15,5 +15,6 @@ ./tailscale.nix ./traefik.nix ./minecraft.nix + ./dns.nix ]; } diff --git a/roles/server/dns.nix b/roles/server/dns.nix new file mode 100644 index 0000000..c5915d2 --- /dev/null +++ b/roles/server/dns.nix @@ -0,0 +1,40 @@ +{ ... }: + +{ + services.dnsmasq = { + enable = true; + + # Only using this for tailscale IPs, so better to let tailscale itself deal with it + resolveLocalQueries = false; + + settings = { + listen-address = [ "100.73.96.48" ]; + + /* + Dnsmasq tries to use the tailscale dns server, which is bad cause that points to dnsmasq + From the little testing I have done it seems to not cause any issues, but better to be safe + than sorry :P + */ + dns-loop-detect = true; + ## IPv6 is not a thing in Spain so I'm guaranteed to not use it + filter-AAAA = true; + expand-hosts = true; + domain = "sable-pancake.ts.net"; + domain-needed = true; + }; + }; + + # Add tailscale hosts + networking.hosts = { + "100.73.96.48" = [ "everest" ]; + "100.113.139.93" = [ "archie" ]; + "100.85.48.85" = [ "steamdeck" ]; + "100.96.92.13" = [ "surfecego" ]; + }; + + # Dnsmasq conflicts with the resolved dns stub listener + services.resolved.extraConfig = '' + [Resolve] + DNSStubListener=no + ''; +} From 3e4b9056f427c9580342659fbad941bbae6c8433 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 9 Dec 2023 18:31:08 +0100 Subject: [PATCH 0292/1125] Server/traefik: only enable web ui in specialisation --- roles/server/traefik.nix | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/roles/server/traefik.nix b/roles/server/traefik.nix index c2b9442..380d4b2 100644 --- a/roles/server/traefik.nix +++ b/roles/server/traefik.nix @@ -1,12 +1,19 @@ { config, ... }: { + specialisation.traefikEnableWebUI.configuration.services.traefik = { + staticConfigOptions = { + api = { + # Enable the web ui + insecure = true; + dashboard = true; + }; + }; + }; + services.traefik = { enable = true; staticConfigOptions = { - # Enable the web ui - api.insecure = true; - api.dashboard = true; entryPoints = { http = { address = ":80"; }; }; From 78d3ac4d4ebc516d7829b28e6119884fc49804d7 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 9 Dec 2023 18:39:45 +0100 Subject: [PATCH 0293/1125] Server/traefik: set http entrypoint address to the tailscale IP --- roles/server/traefik.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/traefik.nix b/roles/server/traefik.nix index 380d4b2..214827a 100644 --- a/roles/server/traefik.nix +++ b/roles/server/traefik.nix @@ -15,7 +15,7 @@ enable = true; staticConfigOptions = { entryPoints = { - http = { address = ":80"; }; + http = { address = "100.73.96.48:80"; }; }; }; }; From 5a52fd9f3a50a6a7c73b7fa8b2df7b440f2aea4a Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 9 Dec 2023 19:38:21 +0100 Subject: [PATCH 0294/1125] Server/dns: localise queries --- roles/server/dns.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/server/dns.nix b/roles/server/dns.nix index c5915d2..d50e8ea 100644 --- a/roles/server/dns.nix +++ b/roles/server/dns.nix @@ -16,6 +16,9 @@ than sorry :P */ dns-loop-detect = true; + + # If this isn't set a cname that targets a host might return the wrong ip + localise-queries = true; ## IPv6 is not a thing in Spain so I'm guaranteed to not use it filter-AAAA = true; expand-hosts = true; From 1a84aa229061c74661efc6d50955c0ab7dd41ba3 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 10 Dec 2023 18:12:27 +0100 Subject: [PATCH 0295/1125] Server: move services to subdomains --- roles/server/gitea.nix | 16 ++++++---------- roles/server/syncthing.nix | 14 +++++--------- roles/server/transmission.nix | 9 ++++++--- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/roles/server/gitea.nix b/roles/server/gitea.nix index 6cbac30..662da91 100644 --- a/roles/server/gitea.nix +++ b/roles/server/gitea.nix @@ -9,31 +9,27 @@ server = { #server.SSH_PORT = 69; DISABLE_REGISTRATION = lib.mkDefault true; - ROOT_URL = "http://everest/gitea/"; + ROOT_URL = "http://git.everest.sable-pancake.ts.net"; }; }; }; + + # Add a cname for gitea + services.dnsmasq.settings.cname = [ "git.everest.sable-pancake.ts.net,everest" ]; + # Set up traefik as the reverse proxy for Gitea services.traefik = { dynamicConfigOptions = { http = { routers = { - /* - Gitea works best as a subdomain, but I do not have a dns server (yet), - and since tailscale doesn't support adding subdomains with MagicDNS I'll - just put it in a subpath for now - */ gitea-subpath = { - middlewares = [ "gitea-strip-prefix" ]; - rule = "PathPrefix(`/gitea`)"; + rule = "Host(`git.everest.sable-pancake.ts.net`)"; service = "gitea"; }; }; services.gitea.loadBalancer.servers = [ { url = "http://localhost:${toString config.services.gitea.settings.server.HTTP_PORT}"; } ]; - # Gitea freaks out if you don't remove the subpath it's being proxied from - middlewares.gitea-strip-prefix.stripprefix.prefixes = "/gitea"; }; }; }; diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 489324d..c533cf4 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -34,26 +34,22 @@ AmbientCapabilities = "CAP_CHOWN CAP_FOWNER"; }; + # Add a cname for syncthing + services.dnsmasq.settings.cname = [ "sync.everest.sable-pancake.ts.net,everest" ]; + # Set up traefik as the reverse proxy for syncthing services.traefik = { dynamicConfigOptions = { http = { routers = { - syncthing-subpath = { - middlewares = [ "syncthing-add-trailing-slash" "syncthing-strip-prefix" ]; - rule = "PathPrefix(`/syncthing`)"; + syncthing-subdomain = { + rule = "Host(`sync.everest.sable-pancake.ts.net`)"; service = "syncthing"; }; }; services.syncthing.loadBalancer.servers = [ { url = "http://localhost:8384"; } ]; - middlewares.syncthing-strip-prefix.stripprefix.prefixes = "/syncthing"; - middlewares.syncthing-add-trailing-slash.redirectRegex = { - # Going to everest/syncthing without a slash at the end breaks things - regex = "http:\/\/everest\/syncthing+$"; - replacement = "http://everest/syncthing/"; - }; }; }; }; diff --git a/roles/server/transmission.nix b/roles/server/transmission.nix index 767981e..ed17095 100755 --- a/roles/server/transmission.nix +++ b/roles/server/transmission.nix @@ -7,18 +7,21 @@ settings = { incomplete-dir-enabled = false; rpc-bind-address = "0.0.0.0"; - rpc-host-whitelist = "everest"; + rpc-host-whitelist = "transmission.everest.sable-pancake.ts.net"; rpc-whitelist = "127.0.0.1"; }; }; + # Add a cname for transmission + services.dnsmasq.settings.cname = [ "transmission.everest.sable-pancake.ts.net,everest" ]; + # Set up traefik as the reverse proxy for transmission services.traefik = { dynamicConfigOptions = { http = { routers = { - transmission-subpath = { - rule = "PathPrefix(`/transmission`)"; + transmission-subdomain = { + rule = "Host(`transmission.everest.sable-pancake.ts.net`)"; service = "transmission"; }; }; From b841a4fda9eae413cbd669fcef75ba5a11b2a701 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 11 Dec 2023 10:39:43 +0100 Subject: [PATCH 0296/1125] Sever/gitea: migrate to forgejo --- roles/server/default.nix | 2 +- roles/server/forgejo.nix | 34 ++++++++++++++++++++++++++++++++++ roles/server/gitea.nix | 36 ------------------------------------ 3 files changed, 35 insertions(+), 37 deletions(-) create mode 100644 roles/server/forgejo.nix delete mode 100644 roles/server/gitea.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index 5d6a6b8..a52b02b 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -6,7 +6,7 @@ ./nfs.nix ./samba.nix ./ssh.nix - ./gitea.nix + ./forgejo.nix ./syncthing.nix ./endlessh.nix ./transmission.nix diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix new file mode 100644 index 0000000..fb4756e --- /dev/null +++ b/roles/server/forgejo.nix @@ -0,0 +1,34 @@ +{ config, lib, ... }: + +{ + specialisation.forgejoEnableRegistration.configuration.services.forgejo.settings.service.DISABLE_REGISTRATION = false; + services.forgejo = { + enable = true; + settings = { + server = { + DISABLE_REGISTRATION = lib.mkDefault true; + ROOT_URL = "http://git.everest.sable-pancake.ts.net"; + }; + }; + }; + + # Add a cname for forgejo + services.dnsmasq.settings.cname = [ "git.everest.sable-pancake.ts.net,everest" ]; + + # Set up traefik as the reverse proxy for Forgejo + services.traefik = { + dynamicConfigOptions = { + http = { + routers = { + forgejo-subpath = { + rule = "Host(`git.everest.sable-pancake.ts.net`)"; + service = "forgejo"; + }; + }; + services.forgejo.loadBalancer.servers = [ + { url = "http://localhost:${toString config.services.forgejo.settings.server.HTTP_PORT}"; } + ]; + }; + }; + }; +} diff --git a/roles/server/gitea.nix b/roles/server/gitea.nix deleted file mode 100644 index 662da91..0000000 --- a/roles/server/gitea.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ config, lib, ... }: - -{ - specialisation.giteaEnableRegistration.configuration.services.gitea.settings.service.DISABLE_REGISTRATION = false; - services.gitea = { - enable = true; - # TODO: Make this not be hardcoded - settings = { - server = { - #server.SSH_PORT = 69; - DISABLE_REGISTRATION = lib.mkDefault true; - ROOT_URL = "http://git.everest.sable-pancake.ts.net"; - }; - }; - }; - - # Add a cname for gitea - services.dnsmasq.settings.cname = [ "git.everest.sable-pancake.ts.net,everest" ]; - - # Set up traefik as the reverse proxy for Gitea - services.traefik = { - dynamicConfigOptions = { - http = { - routers = { - gitea-subpath = { - rule = "Host(`git.everest.sable-pancake.ts.net`)"; - service = "gitea"; - }; - }; - services.gitea.loadBalancer.servers = [ - { url = "http://localhost:${toString config.services.gitea.settings.server.HTTP_PORT}"; } - ]; - }; - }; - }; -} From ddca18122273872ddb6c24259d162c6dcd6631f2 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 11 Dec 2023 12:57:53 +0100 Subject: [PATCH 0297/1125] Flake: update lock file --- flake.lock | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/flake.lock b/flake.lock index 4a17911..4932888 100644 --- a/flake.lock +++ b/flake.lock @@ -9,11 +9,11 @@ ] }, "locked": { - "lastModified": 1696775529, - "narHash": "sha256-TYlE4B0ktPtlJJF9IFxTWrEeq+XKG8Ny0gc2FGEAdj0=", + "lastModified": 1701216516, + "narHash": "sha256-jKSeJn+7hZ1dZdiH1L+NWUGT2i/BGomKAJ54B9kT06Q=", "owner": "ryantm", "repo": "agenix", - "rev": "daf42cb35b2dc614d1551e37f96406e4c4a2d3e4", + "rev": "13ac9ac6d68b9a0896e3d43a082947233189e247", "type": "github" }, "original": { @@ -29,11 +29,11 @@ ] }, "locked": { - "lastModified": 1698928896, - "narHash": "sha256-u1zn+ra0veELWC7IRcAed/Cl91Tic0AkaLhvpGk54Xw=", + "lastModified": 1701997368, + "narHash": "sha256-JZ4K9muQHYqArTCZu4QsX+A08oQ7fH4omGaOgT2DOA0=", "owner": "catppuccin", "repo": "vscode", - "rev": "f6ac9ebb84464cd37d045561b9919f3ae3684edb", + "rev": "6d7abef0949faa6ddd7d2c87312f647742c48e04", "type": "github" }, "original": { @@ -104,11 +104,11 @@ ] }, "locked": { - "lastModified": 1701071203, - "narHash": "sha256-lQywA7QU/vzTdZ1apI0PfgCWNyQobXUYghVrR5zuIeM=", + "lastModified": 1702203126, + "narHash": "sha256-4BhN2Vji19MzRC7SUfPZGmtZ2WZydQeUk/ogfRBIZMs=", "owner": "nix-community", "repo": "home-manager", - "rev": "db1878f013b52ba5e4034db7c1b63e8d04173a86", + "rev": "defbb9c5857e157703e8fc7cf3c2ceb01cb95883", "type": "github" }, "original": { @@ -124,11 +124,11 @@ ] }, "locked": { - "lastModified": 1700814205, - "narHash": "sha256-lWqDPKHRbQfi+zNIivf031BUeyciVOtwCwTjyrhDB5g=", + "lastModified": 1702195709, + "narHash": "sha256-+zRjWkm5rKqQ57PuLZ3JF3xi3vPMiOJzItb1m/43Cq4=", "owner": "nix-community", "repo": "home-manager", - "rev": "aeb2232d7a32530d3448318790534d196bf9427a", + "rev": "6761b8188b860f374b457eddfdb05c82eef9752f", "type": "github" }, "original": { @@ -146,11 +146,11 @@ ] }, "locked": { - "lastModified": 1700979728, - "narHash": "sha256-Myh4f+pXVDPrxw96K1czQZJv6fqZVdaXkzyyyR+H9ro=", + "lastModified": 1702214253, + "narHash": "sha256-2ltPtWUNNHnYaCK4E+py5+nXqNVccUTusidTdbT28Vw=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "4599d9edef37dec460cc08e85da6c699ac0d78fd", + "rev": "ad708a479968eac4ed0aef9bc6dd7380cc6c15da", "type": "github" }, "original": { @@ -219,11 +219,11 @@ ] }, "locked": { - "lastModified": 1700968077, - "narHash": "sha256-Lax+2g7G3Fe+ckMrHLYTl+97unbmNDmN1qS9MLBkxr4=", + "lastModified": 1702291765, + "narHash": "sha256-kfxavgLKPIZdYVPUPcoDZyr5lleymrqbr5G9PVfQ2NY=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "bd3aec0ecb0fdde863a7ed2c6caa220c47e22c07", + "rev": "45d82e0a8b9dd6c5dd9da835ac0c072239af7785", "type": "github" }, "original": { @@ -239,11 +239,11 @@ ] }, "locked": { - "lastModified": 1700968077, - "narHash": "sha256-Lax+2g7G3Fe+ckMrHLYTl+97unbmNDmN1qS9MLBkxr4=", + "lastModified": 1702291765, + "narHash": "sha256-kfxavgLKPIZdYVPUPcoDZyr5lleymrqbr5G9PVfQ2NY=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "bd3aec0ecb0fdde863a7ed2c6caa220c47e22c07", + "rev": "45d82e0a8b9dd6c5dd9da835ac0c072239af7785", "type": "github" }, "original": { @@ -254,11 +254,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1701020860, - "narHash": "sha256-NwnRn04C8s+hH+KdVtGmVB1FFNIG7DtPJmQSCBDaET4=", + "lastModified": 1702245580, + "narHash": "sha256-tTVRB42Ljo2uWGP7ei5h5/qQjOsdXoz0GHRy9hrVrdw=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "b006ec52fce23b1d57f6ab4a42d7400732e9a0a2", + "rev": "030edbb68e69f2b97231479f98a9597024650df2", "type": "github" }, "original": { @@ -270,11 +270,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1701263465, - "narHash": "sha256-lNXUIlkfyDyp9Ox21hr+wsEf/IBklLvb6bYcyeXbdRc=", + "lastModified": 1701952659, + "narHash": "sha256-TJv2srXt6fYPUjxgLAL0cy4nuf1OZD4KuA1TrCiQqg0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "50aa30a13c4ab5e7ba282da460a3e3d44e9d0eb3", + "rev": "b4372c4924d9182034066c823df76d6eaf1f4ec4", "type": "github" }, "original": { @@ -285,11 +285,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1700794826, - "narHash": "sha256-RyJTnTNKhO0yqRpDISk03I/4A67/dp96YRxc86YOPgU=", + "lastModified": 1702151865, + "narHash": "sha256-9VAt19t6yQa7pHZLDbil/QctAgVsA66DLnzdRGqDisg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5a09cb4b393d58f9ed0d9ca1555016a8543c2ac8", + "rev": "666fc80e7b2afb570462423cb0e1cf1a3a34fedd", "type": "github" }, "original": { @@ -363,11 +363,11 @@ ] }, "locked": { - "lastModified": 1701048169, - "narHash": "sha256-gsYFAIDMyXztMl39/EQzIVjQx/7z+0XPuCDhkrF2tbw=", + "lastModified": 1702257609, + "narHash": "sha256-T8KfGBwuVVd3Yc1PYjjAFlj2W9Bmz3CIN5KmBWH0KkY=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "23dfda3e3df1901d38f1efc98d3e90cefd73ff5d", + "rev": "8a06aeb711a34ec1dad6ee1e2a3db90e473945a6", "type": "github" }, "original": { From e6fd986fc542fa304d1107b8a25f43df78538c53 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 14 Dec 2023 09:56:00 +0100 Subject: [PATCH 0298/1125] Flake: update lock file There are more things that can be updated, but jovian is going to get bumped soon but I want to get new packages now --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 4932888..8693cd5 100644 --- a/flake.lock +++ b/flake.lock @@ -104,11 +104,11 @@ ] }, "locked": { - "lastModified": 1702203126, - "narHash": "sha256-4BhN2Vji19MzRC7SUfPZGmtZ2WZydQeUk/ogfRBIZMs=", + "lastModified": 1702538064, + "narHash": "sha256-At5GwJPu2tzvS9dllhBoZmqK6lkkh/sOp2YefWRlaL8=", "owner": "nix-community", "repo": "home-manager", - "rev": "defbb9c5857e157703e8fc7cf3c2ceb01cb95883", + "rev": "0e2e443ff24f9d75925e91b89d1da44b863734af", "type": "github" }, "original": { @@ -270,11 +270,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1701952659, - "narHash": "sha256-TJv2srXt6fYPUjxgLAL0cy4nuf1OZD4KuA1TrCiQqg0=", + "lastModified": 1702346276, + "narHash": "sha256-eAQgwIWApFQ40ipeOjVSoK4TEHVd6nbSd9fApiHIw5A=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b4372c4924d9182034066c823df76d6eaf1f4ec4", + "rev": "cf28ee258fd5f9a52de6b9865cdb93a1f96d09b7", "type": "github" }, "original": { @@ -285,11 +285,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1702151865, - "narHash": "sha256-9VAt19t6yQa7pHZLDbil/QctAgVsA66DLnzdRGqDisg=", + "lastModified": 1702312524, + "narHash": "sha256-gkZJRDBUCpTPBvQk25G0B7vfbpEYM5s5OZqghkjZsnE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "666fc80e7b2afb570462423cb0e1cf1a3a34fedd", + "rev": "a9bf124c46ef298113270b1f84a164865987a91c", "type": "github" }, "original": { From cf34e7c222b64f7913eaf8b6015e72684d722df2 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 14 Dec 2023 10:04:12 +0100 Subject: [PATCH 0299/1125] Services/avahi: rename moved option --- roles/common/services/avahi.nix | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/roles/common/services/avahi.nix b/roles/common/services/avahi.nix index 2891e8d..ef9d747 100755 --- a/roles/common/services/avahi.nix +++ b/roles/common/services/avahi.nix @@ -1,8 +1,19 @@ { config, ... }: - -{ - services.avahi = { - enable = true; +let + old = { nssmdns = true; }; + new = { + nssmdns4 = true; + }; +in +{ + /* + NixOS 24.05 changed the option for mnds to be able to turn on/off IPv6 + 23.11 doesn't support this, so I need to use the conditional to be able to + use the same config for both + */ + services.avahi = { + enable = true; + } // (if config.system.nixos.release == "23.11" then old else new); } From 1443e62ccdf7e02da6474a7aec44d84572daa109 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Dec 2023 11:25:31 +0100 Subject: [PATCH 0300/1125] Desktop/programs/vscode: override catppuccin theme --- roles/desktop/programs/vscode.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index 436f52d..b0b1d51 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -8,7 +8,10 @@ let inputs = flakeSelf.inputs; in mutableExtensionsDir = false; extensions = with inputs.vscode-extensions.extensions.x86_64-linux.open-vsx; [ jnoortheen.nix-ide - pkgs.catppuccin-vsc + (pkgs.catppuccin-vsc.override { + workbenchMode = "flat"; + extraBordersEnabled = true; + }) catppuccin.catppuccin-vsc-icons ]; userSettings = { From 08df06dc263cd6e579e1b050453a153f8fc974ea Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Dec 2023 12:52:31 +0100 Subject: [PATCH 0301/1125] Common/programs/btop: enable using home manager --- roles/common/programs/btop.nix | 11 +++++++++++ roles/common/programs/default.nix | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 roles/common/programs/btop.nix diff --git a/roles/common/programs/btop.nix b/roles/common/programs/btop.nix new file mode 100644 index 0000000..feb3a9a --- /dev/null +++ b/roles/common/programs/btop.nix @@ -0,0 +1,11 @@ +{ ... }: + +{ + home-manager = { + users.toast = { + programs.btop = { + enable = true; + }; + }; + }; +} \ No newline at end of file diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index c6ab698..e6d2127 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -12,6 +12,7 @@ ./git.nix ./starship.nix ./bat.nix + ./btop.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ @@ -23,7 +24,6 @@ ncdu tree btdu - btop iperf3 restic ]; From f3189018bf1f07d58ffe8fd425bfdc1ea81a9bf3 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Dec 2023 12:53:11 +0100 Subject: [PATCH 0302/1125] Common/programs/btop: add catppuccin theme --- roles/common/programs/btop.nix | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/btop.nix b/roles/common/programs/btop.nix index feb3a9a..291d05e 100644 --- a/roles/common/programs/btop.nix +++ b/roles/common/programs/btop.nix @@ -1,10 +1,26 @@ -{ ... }: +{ pkgs, ... }: +let + catppuccinBtop = pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "btop"; + # I know fetiching from master is not best practice but idc this is not going to change often + # Latest commit rn is c6469190f2ecf25f017d6120bf4e050e6b1d17af + rev = "master"; + hash = "sha256-jodJl4f2T9ViNqsY9fk8IV62CrpC5hy7WK3aRpu70Cs="; +}; +in { home-manager = { users.toast = { programs.btop = { enable = true; + settings = { + color_theme = "catppuccin_mocha"; + }; + }; + xdg.configFile = { + "btop/themes".source = "${catppuccinBtop}/themes"; }; }; }; From b56b90651a611436aef9ed1867848e84fd8f6e4b Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Dec 2023 12:57:06 +0100 Subject: [PATCH 0303/1125] Common/programs/git: disable pull.rebase --- roles/common/programs/git.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index f5bce60..3002894 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -7,7 +7,6 @@ delta.enable = true; extraConfig = { init.defaultBranch = "main"; - pull.rebase = "interactive"; commit.verbose = "true"; }; }; From 437d3022eb43408e7acbed21f57d864ca931cdb8 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Dec 2023 14:02:13 +0100 Subject: [PATCH 0304/1125] kde/programs/konsole: add catppuccin colorscheme --- roles/kde/programs/default.nix | 1 + roles/kde/programs/konsole.nix | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 roles/kde/programs/konsole.nix diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index 796a605..7c22bb0 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -6,6 +6,7 @@ ./firefox.nix ./skanpage.nix ./neochat.nix + ./konsole.nix ]; # Enable the kde partition manager diff --git a/roles/kde/programs/konsole.nix b/roles/kde/programs/konsole.nix new file mode 100644 index 0000000..0dfdf57 --- /dev/null +++ b/roles/kde/programs/konsole.nix @@ -0,0 +1,17 @@ +{ pkgs, ... }: +let + catppuccinKonsole = pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "konsole"; + # Latest commit is 7d86b8a1e56e58f6b5649cdaac543a573ac194ca + rev = "main"; + hash = "sha256-EwSJMTxnaj2UlNJm1t6znnatfzgm1awIQQUF3VPfCTM="; + } + /Catppuccin-Mocha.colorscheme; +in +{ + home-manager.users.toast = { + xdg.dataFile = { + "konsole/Catppuccin-Mocha.colorscheme".source = catppuccinKonsole; + }; + }; +} \ No newline at end of file From 9a8309def9c60408b814d3b8f546dbd7f03e0a40 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Dec 2023 14:02:57 +0100 Subject: [PATCH 0305/1125] Common/programs/starship: add catpuccin color palette --- roles/common/programs/starship.nix | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index 9c9cd3b..5b168b7 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -1,7 +1,16 @@ -{ config, ... }: - +{ pkgs, ... }: +let + catppuccinFlavour = "mocha"; + catppuccinStarship = pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "starship"; + # Latest commit is 5629d2356f62a9f2f8efad3ff37476c19969bd4f + rev = "main"; + hash = "sha256-nsRuxQFKbQkyEI4TXgvAjcroVdG+heKX5Pauq/4Ota0="; + } + /palettes/${catppuccinFlavour}.toml; +in { - programs.starship = { + programs.starship = with builtins; { enable = true; settings = { nix_shell = { @@ -17,6 +26,9 @@ disabled = false; read_only = " 󰌾"; }; - }; + palette = "catppuccin_${catppuccinFlavour}"; + } // + # Add the catppuccin palette to the settings file + (fromTOML (readFile catppuccinStarship)); }; } From a80920a663b64f08b4ccbb9f6b64835eb407735b Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 18 Dec 2023 09:33:09 +0100 Subject: [PATCH 0306/1125] Programs/common/starship: add upstream nerd font preset --- roles/common/programs/starship.nix | 63 ++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index 5b168b7..f2380d3 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -1,4 +1,8 @@ -{ pkgs, ... }: +{ pkgs, lib, ... }: + +with lib; +with builtins; + let catppuccinFlavour = "mocha"; catppuccinStarship = pkgs.fetchFromGitHub { @@ -8,27 +12,46 @@ let rev = "main"; hash = "sha256-nsRuxQFKbQkyEI4TXgvAjcroVdG+heKX5Pauq/4Ota0="; } + /palettes/${catppuccinFlavour}.toml; + + presets = { + nerdFontSymbols = pkgs.fetchurl { + url = "https://starship.rs/presets/toml/nerd-font-symbols.toml"; + hash = "sha256-fPmZrfhwM9NakdlJ7Y4rZ5n6JjsqXNEQ9XuFa8en9n0="; + }; + }; + # -------------------------------- F U N C T I O N S -------------------------------- + + /* + Gonna be honest, I have no idea how this works, although it seems to work + Stolen from https://gist.github.com/pdalpra/daf339f59288201a6c8ba7dc84e9060e + */ + # Takes a list of attrSets and merges them + mergeAllAttrSets = attrsSets: + foldl' (recursiveUpdate) {} attrsSets; + + # Reads a TOML file and parses it + readTomlPreset = file: (fromTOML (readFile file)); + in { - programs.starship = with builtins; { + programs.starship = { enable = true; - settings = { - nix_shell = { - disabled = false; - heuristic = true; - symbol = " "; - }; - os = { - disabled = false; - symbols.NixOS = " "; - }; - directory = { - disabled = false; - read_only = " 󰌾"; - }; - palette = "catppuccin_${catppuccinFlavour}"; - } // - # Add the catppuccin palette to the settings file - (fromTOML (readFile catppuccinStarship)); + settings = mergeAllAttrSets [ + (readTomlPreset presets.nerdFontSymbols) + (readTomlPreset catppuccinStarship) + { + nix_shell = { + disabled = false; + heuristic = true; + }; + os = { + disabled = false; + }; + directory = { + disabled = false; + }; + palette = "catppuccin_${catppuccinFlavour}"; + } + ]; }; } From 04feb2a4fe53a8165f7c6902ee9683f2164d35ba Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 18 Dec 2023 11:00:28 +0100 Subject: [PATCH 0307/1125] Flake: update lock file --- flake.lock | 60 +++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/flake.lock b/flake.lock index 8693cd5..6279589 100644 --- a/flake.lock +++ b/flake.lock @@ -29,11 +29,11 @@ ] }, "locked": { - "lastModified": 1701997368, - "narHash": "sha256-JZ4K9muQHYqArTCZu4QsX+A08oQ7fH4omGaOgT2DOA0=", + "lastModified": 1702361774, + "narHash": "sha256-7hvwhbOQ+2LMt1HH7JJfyejYtdY4wqOvm3yrzCMb4eY=", "owner": "catppuccin", "repo": "vscode", - "rev": "6d7abef0949faa6ddd7d2c87312f647742c48e04", + "rev": "3cb3529c5c22ea47203f5e0e6e357b6b2623cfce", "type": "github" }, "original": { @@ -104,11 +104,11 @@ ] }, "locked": { - "lastModified": 1702538064, - "narHash": "sha256-At5GwJPu2tzvS9dllhBoZmqK6lkkh/sOp2YefWRlaL8=", + "lastModified": 1702814335, + "narHash": "sha256-Qck7BAMi3eydzT1WFOzp/SgECetyPpOn1dLgmxH2ebQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "0e2e443ff24f9d75925e91b89d1da44b863734af", + "rev": "e4dba0bd01956170667458be7b45f68170a63651", "type": "github" }, "original": { @@ -124,11 +124,11 @@ ] }, "locked": { - "lastModified": 1702195709, - "narHash": "sha256-+zRjWkm5rKqQ57PuLZ3JF3xi3vPMiOJzItb1m/43Cq4=", + "lastModified": 1702814678, + "narHash": "sha256-zDtO0jV2QLoddUJinLlTQrQqCUW3dPiIWOSYgg98T7E=", "owner": "nix-community", "repo": "home-manager", - "rev": "6761b8188b860f374b457eddfdb05c82eef9752f", + "rev": "1488651d02c1a7a15e284210f0d380a62d8d8cef", "type": "github" }, "original": { @@ -146,11 +146,11 @@ ] }, "locked": { - "lastModified": 1702214253, - "narHash": "sha256-2ltPtWUNNHnYaCK4E+py5+nXqNVccUTusidTdbT28Vw=", + "lastModified": 1702725654, + "narHash": "sha256-jcYYMEkHArk1K8IpL8X1+AzipmGlkRimKBpQ9kmDD4w=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "ad708a479968eac4ed0aef9bc6dd7380cc6c15da", + "rev": "e7ffb0cd75f38ac65d99614acfea576e1b23c100", "type": "github" }, "original": { @@ -161,11 +161,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1700311469, - "narHash": "sha256-89ulQo4Jqt1OP06DGDErkj1Dpa0i1GZzWpR6Cs5PbE8=", + "lastModified": 1702756026, + "narHash": "sha256-KEYa3S0JZCR2WpbEnVn9EXmN5/oCgWGlGg9yHoz5MLc=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "d8f54c27de6617c44a67c36b361d4ad2512a51ce", + "rev": "4f39230e34e8d5056e5b58ed9e4bb264438090bd", "type": "github" }, "original": { @@ -219,11 +219,11 @@ ] }, "locked": { - "lastModified": 1702291765, - "narHash": "sha256-kfxavgLKPIZdYVPUPcoDZyr5lleymrqbr5G9PVfQ2NY=", + "lastModified": 1702864432, + "narHash": "sha256-xR5Igg2hnm979W3YgMDrSjErHFhHo4rbMboF6DC0mbc=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "45d82e0a8b9dd6c5dd9da835ac0c072239af7785", + "rev": "4605ccd764fac78b9e4b5b058698cb9f04430b91", "type": "github" }, "original": { @@ -239,11 +239,11 @@ ] }, "locked": { - "lastModified": 1702291765, - "narHash": "sha256-kfxavgLKPIZdYVPUPcoDZyr5lleymrqbr5G9PVfQ2NY=", + "lastModified": 1702864432, + "narHash": "sha256-xR5Igg2hnm979W3YgMDrSjErHFhHo4rbMboF6DC0mbc=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "45d82e0a8b9dd6c5dd9da835ac0c072239af7785", + "rev": "4605ccd764fac78b9e4b5b058698cb9f04430b91", "type": "github" }, "original": { @@ -254,11 +254,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1702245580, - "narHash": "sha256-tTVRB42Ljo2uWGP7ei5h5/qQjOsdXoz0GHRy9hrVrdw=", + "lastModified": 1702453208, + "narHash": "sha256-0wRi9SposfE2wHqjuKt8WO2izKB/ASDOV91URunIqgo=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "030edbb68e69f2b97231479f98a9597024650df2", + "rev": "7763c6fd1f299cb9361ff2abf755ed9619ef01d6", "type": "github" }, "original": { @@ -270,11 +270,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1702346276, - "narHash": "sha256-eAQgwIWApFQ40ipeOjVSoK4TEHVd6nbSd9fApiHIw5A=", + "lastModified": 1702780907, + "narHash": "sha256-blbrBBXjjZt6OKTcYX1jpe9SRof2P9ZYWPzq22tzXAA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "cf28ee258fd5f9a52de6b9865cdb93a1f96d09b7", + "rev": "1e2e384c5b7c50dbf8e9c441a9e58d85f408b01f", "type": "github" }, "original": { @@ -363,11 +363,11 @@ ] }, "locked": { - "lastModified": 1702257609, - "narHash": "sha256-T8KfGBwuVVd3Yc1PYjjAFlj2W9Bmz3CIN5KmBWH0KkY=", + "lastModified": 1702862423, + "narHash": "sha256-8n/4gWiYqude+xItP2xyj/+DSjiysIYVWMDPAgsGhoQ=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "8a06aeb711a34ec1dad6ee1e2a3db90e473945a6", + "rev": "cdec9e2354f012a79cd1d8fe0a683d32f073f1a3", "type": "github" }, "original": { From e33be49adb4d76b919bda4d710ac8a34f8a6a6e8 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 18 Dec 2023 14:02:36 +0100 Subject: [PATCH 0308/1125] Flake: update plasma-manager --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 6279589..d393d49 100644 --- a/flake.lock +++ b/flake.lock @@ -308,11 +308,11 @@ ] }, "locked": { - "lastModified": 1700267030, - "narHash": "sha256-1ke+7xrkCVOI13RJ1w6EjCGcJywkN3bbTKbLWAt4jaE=", + "lastModified": 1702902485, + "narHash": "sha256-DNgZskTiQyiIRJPzCOZBPg4Td58Edezd+iyYqd6C9ag=", "owner": "pjones", "repo": "plasma-manager", - "rev": "019a8fd22a26c8d59f63aa9cc8a9c1729d6ffbda", + "rev": "13ffd5399eeec490e1269dae7971ab4fb4122b2c", "type": "github" }, "original": { From 175765ba57545663d31af4f23f0f4954663fff37 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 18 Dec 2023 14:10:18 +0100 Subject: [PATCH 0309/1125] Kde/plasma: set kwin window decorations --- roles/kde/plasma.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 47924d6..0140e0f 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -123,6 +123,7 @@ in "Rows" = 1; }; "TabBox"."LayoutName" = "thumbnail_grid"; + "org\\.kde\\.kdecoration2"."ButtonsOnLeft" = "SF"; }; "plasmanotifyrc"."Notifications"."NormalAlwaysOnTop" = true; }; From 73adf771c6fcf7c57ec1851b815a17778d630ab6 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 22 Dec 2023 21:01:20 +0100 Subject: [PATCH 0310/1125] Flake: update lock file --- flake.lock | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/flake.lock b/flake.lock index d393d49..689dcc3 100644 --- a/flake.lock +++ b/flake.lock @@ -9,11 +9,11 @@ ] }, "locked": { - "lastModified": 1701216516, - "narHash": "sha256-jKSeJn+7hZ1dZdiH1L+NWUGT2i/BGomKAJ54B9kT06Q=", + "lastModified": 1703260116, + "narHash": "sha256-ipqShkBmHKC9ft1ZAsA6aeKps32k7+XZSPwfxeHLsAU=", "owner": "ryantm", "repo": "agenix", - "rev": "13ac9ac6d68b9a0896e3d43a082947233189e247", + "rev": "d0d4ad5be611da43da04321f49684ad72d705c7e", "type": "github" }, "original": { @@ -104,11 +104,11 @@ ] }, "locked": { - "lastModified": 1702814335, - "narHash": "sha256-Qck7BAMi3eydzT1WFOzp/SgECetyPpOn1dLgmxH2ebQ=", + "lastModified": 1703265279, + "narHash": "sha256-5jVtOwyMH1FzclxHrsFWzBdB+VyjUUSu1wyZhZlR6WU=", "owner": "nix-community", "repo": "home-manager", - "rev": "e4dba0bd01956170667458be7b45f68170a63651", + "rev": "07c322a7cff03267fd881adae1afe63367c5d608", "type": "github" }, "original": { @@ -124,11 +124,11 @@ ] }, "locked": { - "lastModified": 1702814678, - "narHash": "sha256-zDtO0jV2QLoddUJinLlTQrQqCUW3dPiIWOSYgg98T7E=", + "lastModified": 1703113038, + "narHash": "sha256-oxkyzjpD+mNT7arzU/zHrkNHLuY9tKwmnD2MNaZiSDw=", "owner": "nix-community", "repo": "home-manager", - "rev": "1488651d02c1a7a15e284210f0d380a62d8d8cef", + "rev": "0c2353d5d930c3d93724df6858aef064a31b3c00", "type": "github" }, "original": { @@ -146,11 +146,11 @@ ] }, "locked": { - "lastModified": 1702725654, - "narHash": "sha256-jcYYMEkHArk1K8IpL8X1+AzipmGlkRimKBpQ9kmDD4w=", + "lastModified": 1703229133, + "narHash": "sha256-9Mj57V3FgZpQjSNv9b02GIx6GZWNRT8P1ZRKMk7dQK4=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "e7ffb0cd75f38ac65d99614acfea576e1b23c100", + "rev": "4d24d2ff927a8b8a698bbacdb1966045bcadf872", "type": "github" }, "original": { @@ -199,11 +199,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1697303681, - "narHash": "sha256-caJ0rXeagaih+xTgRduYtYKL1rZ9ylh06CIrt1w5B4g=", + "lastModified": 1702984171, + "narHash": "sha256-reIUBrUXibohXmvXRsgpvtlCE0QQSvWSA+qQCKohgR0=", "owner": "nix-community", "repo": "impermanence", - "rev": "0f317c2e9e56550ce12323eb39302d251618f5b5", + "rev": "123e94200f63952639492796b8878e588a4a2851", "type": "github" }, "original": { @@ -270,11 +270,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1702780907, - "narHash": "sha256-blbrBBXjjZt6OKTcYX1jpe9SRof2P9ZYWPzq22tzXAA=", + "lastModified": 1703068421, + "narHash": "sha256-WSw5Faqlw75McIflnl5v7qVD/B3S2sLh+968bpOGrWA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1e2e384c5b7c50dbf8e9c441a9e58d85f408b01f", + "rev": "d65bceaee0fb1e64363f7871bc43dc1c6ecad99f", "type": "github" }, "original": { @@ -285,11 +285,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1702312524, - "narHash": "sha256-gkZJRDBUCpTPBvQk25G0B7vfbpEYM5s5OZqghkjZsnE=", + "lastModified": 1703013332, + "narHash": "sha256-+tFNwMvlXLbJZXiMHqYq77z/RfmpfpiI3yjL6o/Zo9M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a9bf124c46ef298113270b1f84a164865987a91c", + "rev": "54aac082a4d9bb5bbc5c4e899603abfb76a3f6d6", "type": "github" }, "original": { @@ -308,11 +308,11 @@ ] }, "locked": { - "lastModified": 1702902485, - "narHash": "sha256-DNgZskTiQyiIRJPzCOZBPg4Td58Edezd+iyYqd6C9ag=", + "lastModified": 1703264118, + "narHash": "sha256-YzwzOqSDNLFcG2HulMw0k5reDhBPysq9AT1D8Y0Rky8=", "owner": "pjones", "repo": "plasma-manager", - "rev": "13ffd5399eeec490e1269dae7971ab4fb4122b2c", + "rev": "8e8f0852a49f9f776cbaf2156ebe8b4a8d4bf720", "type": "github" }, "original": { @@ -363,11 +363,11 @@ ] }, "locked": { - "lastModified": 1702862423, - "narHash": "sha256-8n/4gWiYqude+xItP2xyj/+DSjiysIYVWMDPAgsGhoQ=", + "lastModified": 1703208018, + "narHash": "sha256-Onaxa2D7fSunlDQQ1//QVPA0F5IXYl7jF154p3lvxNo=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "cdec9e2354f012a79cd1d8fe0a683d32f073f1a3", + "rev": "049ae6414ecfdac9bae325e658c878603b10e199", "type": "github" }, "original": { From f374274550dfa7a1403e2ed15b1114c0d3ae5ae3 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 26 Dec 2023 15:42:33 +0100 Subject: [PATCH 0311/1125] Flake: update lock file --- flake.lock | 86 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/flake.lock b/flake.lock index 689dcc3..f334b23 100644 --- a/flake.lock +++ b/flake.lock @@ -6,14 +6,15 @@ "home-manager": "home-manager", "nixpkgs": [ "nixpkgs" - ] + ], + "systems": "systems" }, "locked": { - "lastModified": 1703260116, - "narHash": "sha256-ipqShkBmHKC9ft1ZAsA6aeKps32k7+XZSPwfxeHLsAU=", + "lastModified": 1703433843, + "narHash": "sha256-nmtA4KqFboWxxoOAA6Y1okHbZh+HsXaMPFkYHsoDRDw=", "owner": "ryantm", "repo": "agenix", - "rev": "d0d4ad5be611da43da04321f49684ad72d705c7e", + "rev": "417caa847f9383e111d1397039c9d4337d024bf0", "type": "github" }, "original": { @@ -60,7 +61,7 @@ }, "flake-utils": { "inputs": { - "systems": "systems" + "systems": "systems_2" }, "locked": { "lastModified": 1681202837, @@ -84,11 +85,11 @@ ] }, "locked": { - "lastModified": 1682203081, - "narHash": "sha256-kRL4ejWDhi0zph/FpebFYhzqlOBrk0Pl3dzGEKSAlEw=", + "lastModified": 1703113217, + "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", "owner": "nix-community", "repo": "home-manager", - "rev": "32d3e39c491e2f91152c84f8ad8b003420eab0a1", + "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", "type": "github" }, "original": { @@ -104,11 +105,11 @@ ] }, "locked": { - "lastModified": 1703265279, - "narHash": "sha256-5jVtOwyMH1FzclxHrsFWzBdB+VyjUUSu1wyZhZlR6WU=", + "lastModified": 1703527373, + "narHash": "sha256-AjypRssRtS6F3xkf7rE3/bXkIF2WJOZLbTIspjcE1zM=", "owner": "nix-community", "repo": "home-manager", - "rev": "07c322a7cff03267fd881adae1afe63367c5d608", + "rev": "80679ea5074ab7190c4cce478c600057cfb5edae", "type": "github" }, "original": { @@ -124,11 +125,11 @@ ] }, "locked": { - "lastModified": 1703113038, - "narHash": "sha256-oxkyzjpD+mNT7arzU/zHrkNHLuY9tKwmnD2MNaZiSDw=", + "lastModified": 1703367386, + "narHash": "sha256-FMbm48UGrBfOWGt8+opuS+uLBLQlRfhiYXhHNcYMS5k=", "owner": "nix-community", "repo": "home-manager", - "rev": "0c2353d5d930c3d93724df6858aef064a31b3c00", + "rev": "d5824a76bc6bb93d1dce9ebbbcb09a9b6abcc224", "type": "github" }, "original": { @@ -199,11 +200,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1702984171, - "narHash": "sha256-reIUBrUXibohXmvXRsgpvtlCE0QQSvWSA+qQCKohgR0=", + "lastModified": 1703562375, + "narHash": "sha256-T46GgRVnSUo0DrCVAHreLNMgeCYmFvo469qj1Z6dYDQ=", "owner": "nix-community", "repo": "impermanence", - "rev": "123e94200f63952639492796b8878e588a4a2851", + "rev": "8d16ac97980b3641078dd7c11337bfaa77b45789", "type": "github" }, "original": { @@ -219,11 +220,11 @@ ] }, "locked": { - "lastModified": 1702864432, - "narHash": "sha256-xR5Igg2hnm979W3YgMDrSjErHFhHo4rbMboF6DC0mbc=", + "lastModified": 1703387252, + "narHash": "sha256-XKJqGj0BaEn/zyctEnkgVIh6Ba1rgTRc+UBi9EU8Y54=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "4605ccd764fac78b9e4b5b058698cb9f04430b91", + "rev": "f4340c1a42c38d79293ba69bfd839fbd6268a538", "type": "github" }, "original": { @@ -239,11 +240,11 @@ ] }, "locked": { - "lastModified": 1702864432, - "narHash": "sha256-xR5Igg2hnm979W3YgMDrSjErHFhHo4rbMboF6DC0mbc=", + "lastModified": 1703387252, + "narHash": "sha256-XKJqGj0BaEn/zyctEnkgVIh6Ba1rgTRc+UBi9EU8Y54=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "4605ccd764fac78b9e4b5b058698cb9f04430b91", + "rev": "f4340c1a42c38d79293ba69bfd839fbd6268a538", "type": "github" }, "original": { @@ -254,11 +255,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1702453208, - "narHash": "sha256-0wRi9SposfE2wHqjuKt8WO2izKB/ASDOV91URunIqgo=", + "lastModified": 1703545041, + "narHash": "sha256-nvQA+k1rSszrf4kA4eK2i/SGbzoXyoKHzzyzq/Jca1w=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "7763c6fd1f299cb9361ff2abf755ed9619ef01d6", + "rev": "a15b6e525f5737a47b4ce28445c836996fb2ea8c", "type": "github" }, "original": { @@ -270,11 +271,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1703068421, - "narHash": "sha256-WSw5Faqlw75McIflnl5v7qVD/B3S2sLh+968bpOGrWA=", + "lastModified": 1703200384, + "narHash": "sha256-q5j06XOsy0qHOarsYPfZYJPWbTbc8sryRxianlEPJN0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d65bceaee0fb1e64363f7871bc43dc1c6ecad99f", + "rev": "0b3d618173114c64ab666f557504d6982665d328", "type": "github" }, "original": { @@ -285,11 +286,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1703013332, - "narHash": "sha256-+tFNwMvlXLbJZXiMHqYq77z/RfmpfpiI3yjL6o/Zo9M=", + "lastModified": 1703255338, + "narHash": "sha256-Z6wfYJQKmDN9xciTwU3cOiOk+NElxdZwy/FiHctCzjU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "54aac082a4d9bb5bbc5c4e899603abfb76a3f6d6", + "rev": "6df37dc6a77654682fe9f071c62b4242b5342e04", "type": "github" }, "original": { @@ -354,6 +355,21 @@ "type": "github" } }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "vscode-extensions": { "inputs": { "flake-compat": "flake-compat", @@ -363,11 +379,11 @@ ] }, "locked": { - "lastModified": 1703208018, - "narHash": "sha256-Onaxa2D7fSunlDQQ1//QVPA0F5IXYl7jF154p3lvxNo=", + "lastModified": 1703553395, + "narHash": "sha256-lbioI+/sipflPD0XmJOjYfCioPIg/3cRo87l4hp6i7s=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "049ae6414ecfdac9bae325e658c878603b10e199", + "rev": "904561c550a38470b6093e431b961666838bc07e", "type": "github" }, "original": { From e0a28e73d2f328947a9fbba4d45fb4351ad65774 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Dec 2023 10:38:09 +0100 Subject: [PATCH 0312/1125] Revert "Sddm: work around a bug" This reverts commit 62bc8f9bee520866244d8c5e0185dea0d7ba164d since the bug no longer occurs --- roles/kde/sddm.nix | 8 -------- 1 file changed, 8 deletions(-) diff --git a/roles/kde/sddm.nix b/roles/kde/sddm.nix index 10afa13..1183ee4 100644 --- a/roles/kde/sddm.nix +++ b/roles/kde/sddm.nix @@ -52,12 +52,4 @@ in }; environment.systemPackages = [ sddm-sugar-candy customcfg ]; - /* - Sddm has a very annoying bug where it sometimes hangs at shutdown - if you use Plasma's wayland session. The bug is already fixed upstream, - but until it sddm gets updated on the repos this will do - */ - systemd.services.display-manager.serviceConfig = { - TimeoutStopSec = "5s"; - }; } From a4494f566b51fda6b98e116cce372dd35ab3ad09 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 29 Dec 2023 19:06:47 +0100 Subject: [PATCH 0313/1125] Machines/SurfaceGo: use default NixOS kernel --- machines/SurfaceGo/configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix index 990d7a5..1fd9518 100644 --- a/machines/SurfaceGo/configuration.nix +++ b/machines/SurfaceGo/configuration.nix @@ -65,6 +65,9 @@ # wget # ]; + # The surface kernel sometimes fails to suspend/shutdown and I got tired of fighting it + boot.kernelPackages = lib.mkForce pkgs.linuxPackages; + # Some programs need SUID wrappers, can be configured further or are # started in user sessions. # programs.mtr.enable = true; From 78d717bfeff7c7a62834cec3a7854aa1033a59d6 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 29 Dec 2023 19:17:07 +0100 Subject: [PATCH 0314/1125] Machines/SurfaceGo: remove unused stuff --- machines/SurfaceGo/hardware-configuration.nix | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/machines/SurfaceGo/hardware-configuration.nix b/machines/SurfaceGo/hardware-configuration.nix index e8f4999..75c5c1a 100644 --- a/machines/SurfaceGo/hardware-configuration.nix +++ b/machines/SurfaceGo/hardware-configuration.nix @@ -1,12 +1,9 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, /*modulesPath,*/ ... }: +{ config, lib, pkgs, ... }: { - /*imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ];*/ boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usbhid" "rtsx_pci_sdmmc" ]; boot.initrd.kernelModules = [ ]; @@ -39,12 +36,6 @@ options = [ "subvol=@home" "compress=zstd" ]; }; - /*fileSystems."/swap" = { - device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; - fsType = "btrfs"; - options = [ "subvol=@swapfile" ]; - };*/ - fileSystems."/boot/efi" = { device = "/dev/disk/by-uuid/EC76-201F"; fsType = "vfat"; From af5251bf42a1ad45a0cb21c32267efe34871356c Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 29 Dec 2023 19:22:56 +0100 Subject: [PATCH 0315/1125] Machines/SurfaceGo: enable tpm2 --- machines/SurfaceGo/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix index 1fd9518..98a7ed3 100644 --- a/machines/SurfaceGo/configuration.nix +++ b/machines/SurfaceGo/configuration.nix @@ -20,6 +20,8 @@ }; }; + security.tpm2.enable = true; + networking.hostName = "SurfaceGo"; # Define your hostname. networking.networkmanager.enable = true; # Enable networking From 44e2429b4c9ce5d8d050b2da0de8d3e28fd145b7 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 29 Dec 2023 19:23:40 +0100 Subject: [PATCH 0316/1125] Machines/SurfaceGo: use systemd initrd --- machines/SurfaceGo/configuration.nix | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix index 98a7ed3..1dd588b 100644 --- a/machines/SurfaceGo/configuration.nix +++ b/machines/SurfaceGo/configuration.nix @@ -5,19 +5,23 @@ { config, pkgs, lib, ... }: { - # Use grub boot loader - boot.loader = { - systemd-boot.enable = false; - grub = { - enable = true; - device = "nodev"; - efiSupport = true; - enableCryptodisk = true; - }; - efi = { - efiSysMountPoint = "/boot/efi"; - canTouchEfiVariables = true; + boot = { + loader = { + # Use grub boot loader + systemd-boot.enable = false; + grub = { + enable = true; + device = "nodev"; + efiSupport = true; + enableCryptodisk = true; + }; + efi = { + efiSysMountPoint = "/boot/efi"; + canTouchEfiVariables = true; + }; }; + # I need systemd for tpm luks unlocking + initrd.systemd.enable = true; }; security.tpm2.enable = true; From afb61709274516a9f2e00ce75e569540034a4255 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 30 Dec 2023 14:02:56 +0100 Subject: [PATCH 0317/1125] Server/traefik: depend on tailscale --- roles/server/traefik.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/server/traefik.nix b/roles/server/traefik.nix index 214827a..9550bb2 100644 --- a/roles/server/traefik.nix +++ b/roles/server/traefik.nix @@ -19,5 +19,8 @@ }; }; }; + + systemd.units.tailscaled.requiredBy = [ "traefik.service" ]; + networking.firewall.allowedTCPPorts = [ 80 8080 ]; } From dcd6b194cb76bb02eb1a355f3f83716235899025 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 30 Dec 2023 14:57:05 +0100 Subject: [PATCH 0318/1125] Desktop/keepassxc: enable favicon downloader --- roles/desktop/programs/keepassxc.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/desktop/programs/keepassxc.nix b/roles/desktop/programs/keepassxc.nix index 22858fc..637818c 100644 --- a/roles/desktop/programs/keepassxc.nix +++ b/roles/desktop/programs/keepassxc.nix @@ -19,7 +19,10 @@ let # monochrome-light, monochrome-dark or colorful TrayIconAppearance = "monochrome-light"; }; - Security.HideNotes = true; + Security = { + HideNotes = true; + IconDownloadFallback = true; + }; SSHAgent.Enabled = true; }; in From 63062475e2d2690228d865e0c5daa8b23fab3ca1 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 30 Dec 2023 14:57:20 +0100 Subject: [PATCH 0319/1125] Desktop/keepassxc: install using home-manager --- roles/desktop/programs/keepassxc.nix | 48 +++++++++++++++------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/roles/desktop/programs/keepassxc.nix b/roles/desktop/programs/keepassxc.nix index 637818c..7b42daf 100644 --- a/roles/desktop/programs/keepassxc.nix +++ b/roles/desktop/programs/keepassxc.nix @@ -28,33 +28,35 @@ let in { - users.users.toast.packages = [ pkgs.keepassxc ]; home-manager = { extraSpecialArgs = { kpxcSettings = kpxcSettings; }; users.toast = { config, pkgs, kpxcSettings, ... }: { # No module for KeePassXC config :( - home.file = { - ".config/keepassxc/keepassxc.ini".text = kpxcSettings; - # For some reason the autostart .desktop is not the same as the regular one - ".config/autostart/org.keepassxc.KeePassXC.desktop".text = '' - [Desktop Entry] - Name=KeePassXC - GenericName=Password Manager - Exec=keepassxc - TryExec=keepassxc - Icon=keepassxc - StartupWMClass=keepassxc - StartupNotify=true - Terminal=false - Type=Application - Version=1.0 - Categories=Utility;Security;Qt; - MimeType=application/x-keepass2; - X-GNOME-Autostart-enabled=true - X-GNOME-Autostart-Delay=2 - X-KDE-autostart-after=panel - X-LXQt-Need-Tray=true - ''; + home = { + packages = [ pkgs.keepassxc ]; + file = { + ".config/keepassxc/keepassxc.ini".text = kpxcSettings; + # For some reason the autostart .desktop is not the same as the regular one + ".config/autostart/org.keepassxc.KeePassXC.desktop".text = '' + [Desktop Entry] + Name=KeePassXC + GenericName=Password Manager + Exec=keepassxc + TryExec=keepassxc + Icon=keepassxc + StartupWMClass=keepassxc + StartupNotify=true + Terminal=false + Type=Application + Version=1.0 + Categories=Utility;Security;Qt; + MimeType=application/x-keepass2; + X-GNOME-Autostart-enabled=true + X-GNOME-Autostart-Delay=2 + X-KDE-autostart-after=panel + X-LXQt-Need-Tray=true + ''; + }; }; }; }; From b20181aec5304622bd910bf81dd8f17ac1fa33b1 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 30 Dec 2023 20:39:21 +0100 Subject: [PATCH 0320/1125] Gaming/retroarch: init --- roles/gaming/programs/default.nix | 1 + roles/gaming/programs/retroarch.nix | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 roles/gaming/programs/retroarch.nix diff --git a/roles/gaming/programs/default.nix b/roles/gaming/programs/default.nix index 4bba376..8e5776f 100755 --- a/roles/gaming/programs/default.nix +++ b/roles/gaming/programs/default.nix @@ -5,6 +5,7 @@ ./steam.nix ./mangohud.nix ./rpcs3.nix + ./retroarch.nix ]; environment.systemPackages = with pkgs; [ heroic diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix new file mode 100644 index 0000000..106659a --- /dev/null +++ b/roles/gaming/programs/retroarch.nix @@ -0,0 +1,18 @@ +{ pkgs, ... }: +{ + home-manager.users.toast = { + home = { + packages = [( + pkgs.retroarch.override { + cores = with pkgs.libretro; [ + snes9x + ]; + settings = { + video_driver = "vulkan"; + video_fullscreen = "true"; + }; + } + )]; + }; + }; +} From 1f281357aa6a5c75a057874e1a883fdcc0493442 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 30 Dec 2023 20:40:59 +0100 Subject: [PATCH 0321/1125] Gaming/retroarch: add snes roms --- roles/gaming/programs/retroarch.nix | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index 106659a..1a02b90 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -1,4 +1,14 @@ { pkgs, ... }: +let + actraiser = pkgs.fetchzip { + url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/ActRaiser%20%28USA%29.zip"; + hash = "sha256-yxIL5Pqlp8xsx7wvNO1MlB8ffDjS0xpE+yrEfMj61As="; + }; + kirby-super-star = pkgs.fetchzip { + url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/Kirby%20Super%20Star%20%28USA%29.zip"; + hash = "sha256-NX5OjCthf4ZiAhamclRBRk8GiMjZX3JLeShm8sQdDfc="; + }; +in { home-manager.users.toast = { home = { @@ -13,6 +23,10 @@ }; } )]; + file."Games/Roms/SNES/".source = pkgs.symlinkJoin { + name = "snes-roms"; + paths = [ actraiser kirby-super-star ]; + }; }; }; } From 3ee043ab137b7440656e3323bdfcb0cb1580a0bb Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 31 Dec 2023 01:09:45 +0100 Subject: [PATCH 0322/1125] Gaming/retroarch: store roms in list --- roles/gaming/programs/retroarch.nix | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index 1a02b90..b50c00b 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -1,13 +1,16 @@ { pkgs, ... }: let - actraiser = pkgs.fetchzip { + snes-roms = [ + # ActRaiser + ( pkgs.fetchzip { url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/ActRaiser%20%28USA%29.zip"; hash = "sha256-yxIL5Pqlp8xsx7wvNO1MlB8ffDjS0xpE+yrEfMj61As="; - }; - kirby-super-star = pkgs.fetchzip { + } ) + # Kirby Super Star + ( pkgs.fetchzip { url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/Kirby%20Super%20Star%20%28USA%29.zip"; hash = "sha256-NX5OjCthf4ZiAhamclRBRk8GiMjZX3JLeShm8sQdDfc="; - }; + } ) in { home-manager.users.toast = { @@ -23,9 +26,14 @@ in }; } )]; - file."Games/Roms/SNES/".source = pkgs.symlinkJoin { + file."Games/Roms/SNES/" = { + onChange = '' + ${pkgs.retroarch}/bin/retroarch --scan "/home/toast/Games/Roms/SNES" + ''; + source = pkgs.symlinkJoin { name = "snes-roms"; - paths = [ actraiser kirby-super-star ]; + paths = [ snes-roms ]; + }; }; }; }; From 30a39ec7b08e868ad54d0762738d792efb055513 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 31 Dec 2023 01:10:07 +0100 Subject: [PATCH 0323/1125] Gaming/retroarch: add super mario kart --- roles/gaming/programs/retroarch.nix | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index b50c00b..83ab80a 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -3,14 +3,20 @@ let snes-roms = [ # ActRaiser ( pkgs.fetchzip { - url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/ActRaiser%20%28USA%29.zip"; - hash = "sha256-yxIL5Pqlp8xsx7wvNO1MlB8ffDjS0xpE+yrEfMj61As="; + url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/ActRaiser%20%28USA%29.zip"; + hash = "sha256-yxIL5Pqlp8xsx7wvNO1MlB8ffDjS0xpE+yrEfMj61As="; } ) # Kirby Super Star ( pkgs.fetchzip { - url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/Kirby%20Super%20Star%20%28USA%29.zip"; - hash = "sha256-NX5OjCthf4ZiAhamclRBRk8GiMjZX3JLeShm8sQdDfc="; + url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/Kirby%20Super%20Star%20%28USA%29.zip"; + hash = "sha256-NX5OjCthf4ZiAhamclRBRk8GiMjZX3JLeShm8sQdDfc="; } ) + # Super Mario Kart + ( pkgs.fetchzip { + url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/Super%20Mario%20Kart%20%28USA%29.zip"; + hash = "sha256-RLBxPBmBrXCuPdnWE07KamBNgGJ5IntQVUPeij+2HUI="; + } ) + ]; in { home-manager.users.toast = { @@ -31,7 +37,7 @@ in ${pkgs.retroarch}/bin/retroarch --scan "/home/toast/Games/Roms/SNES" ''; source = pkgs.symlinkJoin { - name = "snes-roms"; + name = "snes-roms"; paths = [ snes-roms ]; }; }; From b924128f7c4445abca1b28bacb4a5ec0c72e5c93 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 31 Dec 2023 01:46:40 +0100 Subject: [PATCH 0324/1125] Gaming/retroarch: sync retroarch folder with syncthing --- roles/gaming/programs/retroarch.nix | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index 83ab80a..e247954 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -42,5 +42,28 @@ in }; }; }; + # Add a syncthing ignore file to the retroarch folder + xdg.configFile."retroarch-stignore" = { + target = "retroarch/.stignore"; + text = '' + !saves + !states + !database + !playlists + + // Ignore everything except stuff above + * + ''; + }; + }; + + # Sync saves and some other stuff + services.syncthing.settings.folders = { + "retroarch" = { + label = "RetroArch"; + id = "jxuou-2yjnu"; + devices = [ "steamdeck" "pc" ]; + path = "~/.config/retroarch"; + }; }; } From 7c463d4852b8b9aaf5f0898ed19993a6965fb533 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 31 Dec 2023 03:04:47 +0100 Subject: [PATCH 0325/1125] Gaming/retroarch: add default settings --- roles/gaming/programs/retroarch.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index e247954..012727d 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -29,6 +29,11 @@ in settings = { video_driver = "vulkan"; video_fullscreen = "true"; + + # By default settings has some things that this overrides, so I need to set them myself + libretro_info_path = "${pkgs.libretro-core-info}/share/retroarch/cores"; + joypad_autoconfig_dir = "${pkgs.retroarch-joypad-autoconfig}/share/libretro/autoconfig"; + assets_directory = "${pkgs.retroarch-assets}/share/retroarch/assets"; }; } )]; From 813993250a88748e29afe98ed909acfe7efd31bd Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 3 Jan 2024 15:02:32 +0100 Subject: [PATCH 0326/1125] Gaming/retroarch: temporarely disable syncthing folder --- roles/gaming/programs/retroarch.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index 012727d..1edb530 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -49,6 +49,7 @@ in }; # Add a syncthing ignore file to the retroarch folder xdg.configFile."retroarch-stignore" = { + enable = false; target = "retroarch/.stignore"; text = '' !saves @@ -65,6 +66,7 @@ in # Sync saves and some other stuff services.syncthing.settings.folders = { "retroarch" = { + enable = false; label = "RetroArch"; id = "jxuou-2yjnu"; devices = [ "steamdeck" "pc" ]; From 49e2e715b130d5c5b9a8923f212fa0d24b54ffdc Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 3 Jan 2024 16:10:52 +0100 Subject: [PATCH 0327/1125] Gaming/retroarch: swap ok and cancel buttons --- roles/gaming/programs/retroarch.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index 1edb530..794f570 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -29,6 +29,7 @@ in settings = { video_driver = "vulkan"; video_fullscreen = "true"; + menu_swap_ok_cancel_buttons = "true"; # By default settings has some things that this overrides, so I need to set them myself libretro_info_path = "${pkgs.libretro-core-info}/share/retroarch/cores"; From 1dbfc7ecc346f691017f872f74ed5c96aad41b3b Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 3 Jan 2024 18:28:07 +0100 Subject: [PATCH 0328/1125] Gaming/retroarch: change files location --- roles/gaming/programs/retroarch.nix | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index 794f570..8a55501 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -31,6 +31,27 @@ in video_fullscreen = "true"; menu_swap_ok_cancel_buttons = "true"; + # Folder stuffs + + # System/BIOS files + system_directory = "~/.local/share/retroarch/system"; + # Downloads + core_assets_directory = "~/.local/share/retroarch/downloads"; + thumbnails_directory = "~/.local/share/retroarch/thumbnails"; + content_database_path = "~/.local/share/retroarch/database/rdb"; + cheat_database_path = "~/.local/share/retroarch/cheats"; + video_filter_dir = "~/.local/share/retroarch/filters/video"; + audio_filter_dir = "~/.local/share/retroarch/filters/audio"; + video_shader_dir = "~/.local/share/retroarch/shaders"; + recording_output_directory = "~/.local/share/retroarch/records"; + overlay_directory = "~/.local/share/retroarch/overlays"; + osk_overlay_directory = "~/.local/share/retroarch/overlays/keyboards"; + screenshot_directory = "~/.local/share/retroarch/screenshots"; + playlist_directory = "~/.local/share/retroarch/playlists"; + savefile_directory = "~/.local/share/retroarch/saves"; + savestate_directory = "~/.local/share/retroarch/states"; + log_dir = "~/.local/share/retroarch/logs"; + # By default settings has some things that this overrides, so I need to set them myself libretro_info_path = "${pkgs.libretro-core-info}/share/retroarch/cores"; joypad_autoconfig_dir = "${pkgs.retroarch-joypad-autoconfig}/share/libretro/autoconfig"; @@ -48,6 +69,8 @@ in }; }; }; + # Retroarch is dumb since it doesn't generate this folder (but it does for others) + systemd.user.tmpfiles.rules = [ "d /%h/.local/share/retroarch/playlists" ]; # Add a syncthing ignore file to the retroarch folder xdg.configFile."retroarch-stignore" = { enable = false; From bafe0953a19c8bd328d3a8b47621657b38ac4dbd Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 3 Jan 2024 19:35:54 +0100 Subject: [PATCH 0329/1125] Gaming/retroarch: add settings for steam deck --- roles/gaming/programs/retroarch.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index 8a55501..d9ef702 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -30,6 +30,9 @@ in video_driver = "vulkan"; video_fullscreen = "true"; menu_swap_ok_cancel_buttons = "true"; + input_joypad_driver = "sdl2"; + # Enable touchscreen support + menu_pointer_enable = "true"; # Folder stuffs From 69afd4bdab235de3b0692e5437231265d1e0221a Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 3 Jan 2024 19:54:12 +0100 Subject: [PATCH 0330/1125] Gaming/retroarch: bring back syncthing --- roles/gaming/programs/retroarch.nix | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index d9ef702..3f957f8 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -74,30 +74,15 @@ in }; # Retroarch is dumb since it doesn't generate this folder (but it does for others) systemd.user.tmpfiles.rules = [ "d /%h/.local/share/retroarch/playlists" ]; - # Add a syncthing ignore file to the retroarch folder - xdg.configFile."retroarch-stignore" = { - enable = false; - target = "retroarch/.stignore"; - text = '' - !saves - !states - !database - !playlists - - // Ignore everything except stuff above - * - ''; - }; }; # Sync saves and some other stuff services.syncthing.settings.folders = { "retroarch" = { - enable = false; label = "RetroArch"; id = "jxuou-2yjnu"; devices = [ "steamdeck" "pc" ]; - path = "~/.config/retroarch"; + path = "~/.local/share/retroarch"; }; }; } From faad6bbe42eaff6f0b8e54d5d8ada242d7a107de Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 3 Jan 2024 20:11:23 +0100 Subject: [PATCH 0331/1125] Server/syncthing: add retroarch folder --- roles/gaming/programs/retroarch.nix | 2 +- roles/server/syncthing.nix | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index 3f957f8..7338caf 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -81,7 +81,7 @@ in "retroarch" = { label = "RetroArch"; id = "jxuou-2yjnu"; - devices = [ "steamdeck" "pc" ]; + devices = [ "steamdeck" "server" "pc" ]; path = "~/.local/share/retroarch"; }; }; diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index c533cf4..dd7768c 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -27,6 +27,12 @@ devices = [ "steamdeck" "server" "pc" ]; path = "${config.services.syncthing.dataDir}/steam-201810"; }; + "retroarch"= { + label = "RetroArch"; + id = "jxuou-2yjnu"; + devices = [ "steamdeck" "server" "pc" ]; + path = "${config.services.syncthing.dataDir}/retroarch"; + }; }; }; systemd.services.syncthing.serviceConfig = { From 8b7546a7fb4c84e98ae128ea69d2d34408f617d0 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 4 Jan 2024 22:55:06 +0100 Subject: [PATCH 0332/1125] Flake: update lock file --- flake.lock | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/flake.lock b/flake.lock index f334b23..09f6030 100644 --- a/flake.lock +++ b/flake.lock @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1703527373, - "narHash": "sha256-AjypRssRtS6F3xkf7rE3/bXkIF2WJOZLbTIspjcE1zM=", + "lastModified": 1704383912, + "narHash": "sha256-Be7O73qoOj/z+4ZCgizdLlu+5BkVvO2KO299goZ9cW8=", "owner": "nix-community", "repo": "home-manager", - "rev": "80679ea5074ab7190c4cce478c600057cfb5edae", + "rev": "26b8adb300e50efceb51fff6859a1a6ba1ade4f7", "type": "github" }, "original": { @@ -125,11 +125,11 @@ ] }, "locked": { - "lastModified": 1703367386, - "narHash": "sha256-FMbm48UGrBfOWGt8+opuS+uLBLQlRfhiYXhHNcYMS5k=", + "lastModified": 1704099619, + "narHash": "sha256-QRVMkdxLmv+aKGjcgeEg31xtJEIsYq4i1Kbyw5EPS6g=", "owner": "nix-community", "repo": "home-manager", - "rev": "d5824a76bc6bb93d1dce9ebbbcb09a9b6abcc224", + "rev": "7e398b3d76bc1503171b1364c9d4a07ac06f3851", "type": "github" }, "original": { @@ -147,11 +147,11 @@ ] }, "locked": { - "lastModified": 1703229133, - "narHash": "sha256-9Mj57V3FgZpQjSNv9b02GIx6GZWNRT8P1ZRKMk7dQK4=", + "lastModified": 1704344449, + "narHash": "sha256-rK0M8OUAcuYkGg92knYr87Al0FraZ9UaIGQS3wRZLMY=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "4d24d2ff927a8b8a698bbacdb1966045bcadf872", + "rev": "1962ff3135b1468ae473a196da01d0ebf38c144e", "type": "github" }, "original": { @@ -200,11 +200,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1703562375, - "narHash": "sha256-T46GgRVnSUo0DrCVAHreLNMgeCYmFvo469qj1Z6dYDQ=", + "lastModified": 1703656108, + "narHash": "sha256-hCSUqdFJKHHbER8Cenf5JRzjMlBjIdwdftGQsO0xoJs=", "owner": "nix-community", "repo": "impermanence", - "rev": "8d16ac97980b3641078dd7c11337bfaa77b45789", + "rev": "033643a45a4a920660ef91caa391fbffb14da466", "type": "github" }, "original": { @@ -220,11 +220,11 @@ ] }, "locked": { - "lastModified": 1703387252, - "narHash": "sha256-XKJqGj0BaEn/zyctEnkgVIh6Ba1rgTRc+UBi9EU8Y54=", + "lastModified": 1703992163, + "narHash": "sha256-709CGmwU34dxv8DjSpRBZ+HibVJIVaFcA4JH+GFnhyM=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f4340c1a42c38d79293ba69bfd839fbd6268a538", + "rev": "d6510ce144f5da7dd9bac667ba3d5a4946c00d11", "type": "github" }, "original": { @@ -240,11 +240,11 @@ ] }, "locked": { - "lastModified": 1703387252, - "narHash": "sha256-XKJqGj0BaEn/zyctEnkgVIh6Ba1rgTRc+UBi9EU8Y54=", + "lastModified": 1703992163, + "narHash": "sha256-709CGmwU34dxv8DjSpRBZ+HibVJIVaFcA4JH+GFnhyM=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f4340c1a42c38d79293ba69bfd839fbd6268a538", + "rev": "d6510ce144f5da7dd9bac667ba3d5a4946c00d11", "type": "github" }, "original": { @@ -255,11 +255,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1703545041, - "narHash": "sha256-nvQA+k1rSszrf4kA4eK2i/SGbzoXyoKHzzyzq/Jca1w=", + "lastModified": 1704266875, + "narHash": "sha256-luA5SGmeIRZlgLfSLUuR3eacS63q2bJ0Yywqak5lj3E=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "a15b6e525f5737a47b4ce28445c836996fb2ea8c", + "rev": "8e34f33464d77bea2d5cf7dc1066647b1ad2b324", "type": "github" }, "original": { @@ -271,11 +271,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1703200384, - "narHash": "sha256-q5j06XOsy0qHOarsYPfZYJPWbTbc8sryRxianlEPJN0=", + "lastModified": 1704145853, + "narHash": "sha256-G/1AMt9ibpeMlcxvD1vNaC8imGaK+g7zZ99e29BLgWw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0b3d618173114c64ab666f557504d6982665d328", + "rev": "2d2ea8eab9e400618748ab1a6a108255233b602c", "type": "github" }, "original": { @@ -286,11 +286,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1703255338, - "narHash": "sha256-Z6wfYJQKmDN9xciTwU3cOiOk+NElxdZwy/FiHctCzjU=", + "lastModified": 1704194953, + "narHash": "sha256-RtDKd8Mynhe5CFnVT8s0/0yqtWFMM9LmCzXv/YKxnq4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6df37dc6a77654682fe9f071c62b4242b5342e04", + "rev": "bd645e8668ec6612439a9ee7e71f7eac4099d4f6", "type": "github" }, "original": { @@ -309,11 +309,11 @@ ] }, "locked": { - "lastModified": 1703264118, - "narHash": "sha256-YzwzOqSDNLFcG2HulMw0k5reDhBPysq9AT1D8Y0Rky8=", + "lastModified": 1704383901, + "narHash": "sha256-i2+yzhc13omN+z9K8W3/+23g7D6yWfLb5Qn5f8VVvZI=", "owner": "pjones", "repo": "plasma-manager", - "rev": "8e8f0852a49f9f776cbaf2156ebe8b4a8d4bf720", + "rev": "f11fd526015b5e6b3622c660eda4c4a13d7592bc", "type": "github" }, "original": { @@ -379,11 +379,11 @@ ] }, "locked": { - "lastModified": 1703553395, - "narHash": "sha256-lbioI+/sipflPD0XmJOjYfCioPIg/3cRo87l4hp6i7s=", + "lastModified": 1704331201, + "narHash": "sha256-/TiuoPk5ZAdi+ieTzHdgtdGLsLMsbLdRze9PdxmnkA4=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "904561c550a38470b6093e431b961666838bc07e", + "rev": "cc9b4bc44e8518285a6499959dcf60dfb63dd807", "type": "github" }, "original": { From 8e49b25e4df8f2229ef2ecf65d2017ee874b4b01 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 8 Jan 2024 09:35:09 +0100 Subject: [PATCH 0333/1125] Gaming/retroarch: create saves and states folders --- roles/gaming/programs/retroarch.nix | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index 7338caf..72bd0e8 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -72,8 +72,12 @@ in }; }; }; - # Retroarch is dumb since it doesn't generate this folder (but it does for others) - systemd.user.tmpfiles.rules = [ "d /%h/.local/share/retroarch/playlists" ]; + # Retroarch is dumb since it doesn't generate some folders (but it does for others) + systemd.user.tmpfiles.rules = [ + "d /%h/.local/share/retroarch/playlists" + "d /%h/.local/share/retroarch/saves" + "d /%h/.local/share/retroarch/states" + ]; }; # Sync saves and some other stuff From 81893750722877983f512ec6bc8401603be33a22 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 9 Jan 2024 19:38:04 +0100 Subject: [PATCH 0334/1125] Flake: update lock file --- flake.lock | 60 +++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/flake.lock b/flake.lock index 09f6030..c71172a 100644 --- a/flake.lock +++ b/flake.lock @@ -30,11 +30,11 @@ ] }, "locked": { - "lastModified": 1702361774, - "narHash": "sha256-7hvwhbOQ+2LMt1HH7JJfyejYtdY4wqOvm3yrzCMb4eY=", + "lastModified": 1704479967, + "narHash": "sha256-YcbqMvphGDiAXX+zvEPci4LmBr1zQhGlwT/or9g7gHs=", "owner": "catppuccin", "repo": "vscode", - "rev": "3cb3529c5c22ea47203f5e0e6e357b6b2623cfce", + "rev": "80122d60e2d3a169d0f640cfa347d91b78f814d5", "type": "github" }, "original": { @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1704383912, - "narHash": "sha256-Be7O73qoOj/z+4ZCgizdLlu+5BkVvO2KO299goZ9cW8=", + "lastModified": 1704498488, + "narHash": "sha256-yINKdShHrtjdiJhov+q0s3Y3B830ujRoSbHduUNyKag=", "owner": "nix-community", "repo": "home-manager", - "rev": "26b8adb300e50efceb51fff6859a1a6ba1ade4f7", + "rev": "51e44a13acea71b36245e8bd8c7db53e0a3e61ee", "type": "github" }, "original": { @@ -147,11 +147,11 @@ ] }, "locked": { - "lastModified": 1704344449, - "narHash": "sha256-rK0M8OUAcuYkGg92knYr87Al0FraZ9UaIGQS3wRZLMY=", + "lastModified": 1704665257, + "narHash": "sha256-Cycz00I26e8QZ9sZtCz0uIz6Cad5ld3zM7N2I+5beqI=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "1962ff3135b1468ae473a196da01d0ebf38c144e", + "rev": "8951673c6c216ddd6bac3db3e88e3f2281b3511a", "type": "github" }, "original": { @@ -162,11 +162,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1702756026, - "narHash": "sha256-KEYa3S0JZCR2WpbEnVn9EXmN5/oCgWGlGg9yHoz5MLc=", + "lastModified": 1704403850, + "narHash": "sha256-VYa/EvYY0xjuK/oei2hOgE2fJIv+yZgFw0WgoBuzwBc=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "4f39230e34e8d5056e5b58ed9e4bb264438090bd", + "rev": "f43640ecb03e9e008076932a87987cf5c16d8cf9", "type": "github" }, "original": { @@ -220,11 +220,11 @@ ] }, "locked": { - "lastModified": 1703992163, - "narHash": "sha256-709CGmwU34dxv8DjSpRBZ+HibVJIVaFcA4JH+GFnhyM=", + "lastModified": 1704596958, + "narHash": "sha256-BK3Ohsz7m8X6qVKFxDtr8KVcHipfr5hYE9PDIJevHbQ=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "d6510ce144f5da7dd9bac667ba3d5a4946c00d11", + "rev": "f46800ac5a6e9f892fe36e50821c5d85794ecc62", "type": "github" }, "original": { @@ -240,11 +240,11 @@ ] }, "locked": { - "lastModified": 1703992163, - "narHash": "sha256-709CGmwU34dxv8DjSpRBZ+HibVJIVaFcA4JH+GFnhyM=", + "lastModified": 1704596958, + "narHash": "sha256-BK3Ohsz7m8X6qVKFxDtr8KVcHipfr5hYE9PDIJevHbQ=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "d6510ce144f5da7dd9bac667ba3d5a4946c00d11", + "rev": "f46800ac5a6e9f892fe36e50821c5d85794ecc62", "type": "github" }, "original": { @@ -255,11 +255,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1704266875, - "narHash": "sha256-luA5SGmeIRZlgLfSLUuR3eacS63q2bJ0Yywqak5lj3E=", + "lastModified": 1704786394, + "narHash": "sha256-aJM0ln9fMGWw1+tjyl5JZWZ3ahxAA2gw2ZpZY/hkEMs=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "8e34f33464d77bea2d5cf7dc1066647b1ad2b324", + "rev": "b34a6075e9e298c4124e35c3ccaf2210c1f3a43b", "type": "github" }, "original": { @@ -271,11 +271,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1704145853, - "narHash": "sha256-G/1AMt9ibpeMlcxvD1vNaC8imGaK+g7zZ99e29BLgWw=", + "lastModified": 1704420045, + "narHash": "sha256-C36QmoJd5tdQ5R9MC1jM7fBkZW9zBUqbUCsgwS6j4QU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2d2ea8eab9e400618748ab1a6a108255233b602c", + "rev": "c1be43e8e837b8dbee2b3665a007e761680f0c3d", "type": "github" }, "original": { @@ -286,11 +286,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1704194953, - "narHash": "sha256-RtDKd8Mynhe5CFnVT8s0/0yqtWFMM9LmCzXv/YKxnq4=", + "lastModified": 1704538339, + "narHash": "sha256-1734d3mQuux9ySvwf6axRWZRBhtcZA9Q8eftD6EZg6U=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bd645e8668ec6612439a9ee7e71f7eac4099d4f6", + "rev": "46ae0210ce163b3cba6c7da08840c1d63de9c701", "type": "github" }, "original": { @@ -379,11 +379,11 @@ ] }, "locked": { - "lastModified": 1704331201, - "narHash": "sha256-/TiuoPk5ZAdi+ieTzHdgtdGLsLMsbLdRze9PdxmnkA4=", + "lastModified": 1704763209, + "narHash": "sha256-n++yFjIO8ZxAYCRgfY+82H/2Ng5GQ9vK8N+iq9wqVCs=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "cc9b4bc44e8518285a6499959dcf60dfb63dd807", + "rev": "c4177ec6600af2f26fe5a8fd14605240130f8e56", "type": "github" }, "original": { From 83ba3625b03a9c8e15b7226b5b396d2dd442a21f Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 10 Jan 2024 12:17:56 +0100 Subject: [PATCH 0335/1125] School/idea: update catppuccin theme and change plugin folder location --- roles/school/programs/idea.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index c948bfa..f6c7140 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -9,11 +9,11 @@ with pkgs; home-manager.users.toast = { # Install plugins home.file = { - ".local/share/JetBrains/IntelliJIdea2023.2/catppuccin.jar".source = fetchurl { - url = "https://github.com/catppuccin/jetbrains/releases/download/v3.2.1/Catppuccin.Theme-3.2.1.jar"; - hash = "sha256-vE3Tv/dNfWyRuBJXLDPmtY1GnLShqM+dJR5rltXYdOY="; + ".local/share/JetBrains/IntelliJIdea2023.3/catppuccin.jar".source = fetchurl { + url = "https://github.com/catppuccin/jetbrains/releases/download/v3.2.2/Catppuccin.Theme-3.2.2.jar"; + hash = "sha256-1Zio3ZDhhZvpo6w9ULNhhDQnyT1W25CLcVSm/LcP648="; }; - ".local/share/JetBrains/IntelliJIdea2023.2/rainbow-brackets".source = fetchzip { + ".local/share/JetBrains/IntelliJIdea2023.3/rainbow-brackets".source = fetchzip { url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/2023.3.7/intellij-rainbow-brackets-2023.3.7.zip"; hash = "sha256-szgyQs3iCge9rI274PA29i+tprPE11xpyJqiccedp6A="; }; From 508b0326658b8dfb1cb2a961a89342a8528ed707 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 10 Jan 2024 13:59:13 +0100 Subject: [PATCH 0336/1125] School/idea: update rainbow brackets plugin --- roles/school/programs/idea.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index f6c7140..5741b14 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -14,8 +14,8 @@ with pkgs; hash = "sha256-1Zio3ZDhhZvpo6w9ULNhhDQnyT1W25CLcVSm/LcP648="; }; ".local/share/JetBrains/IntelliJIdea2023.3/rainbow-brackets".source = fetchzip { - url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/2023.3.7/intellij-rainbow-brackets-2023.3.7.zip"; - hash = "sha256-szgyQs3iCge9rI274PA29i+tprPE11xpyJqiccedp6A="; + url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/latest/intellij-rainbow-brackets-2023.3.9-233.zip"; + hash = "sha256-faMDP6kU21WOHVjY5Aj4/Glqymo1iUCTuUJdHsq1N/s="; }; }; From 4653a6cf94a9fe0bd810afefdf6cded22beb915c Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 10 Jan 2024 13:59:33 +0100 Subject: [PATCH 0337/1125] School/idea: add catppuccin icons --- roles/school/programs/idea.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index 5741b14..68fcdde 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -17,6 +17,10 @@ with pkgs; url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/latest/intellij-rainbow-brackets-2023.3.9-233.zip"; hash = "sha256-faMDP6kU21WOHVjY5Aj4/Glqymo1iUCTuUJdHsq1N/s="; }; + ".local/share/JetBrains/IntelliJIdea2023.3/catppuccin-icons.jar".source = fetchurl { + url = "https://github.com/catppuccin/jetbrains-icons/releases/download/v1.1.0/Catppuccin.Icons-1.1.0.jar"; + hash = "sha256-aM+IfIwvj1A14ELyW+KI9SaBrX8ZcnqkS59VbAWq9s4="; + }; }; /* From b3d71fc28c00a402de34f449b870d6524459029e Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Jan 2024 11:03:06 +0100 Subject: [PATCH 0338/1125] Flake: update lock file --- flake.lock | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index c71172a..beb39b3 100644 --- a/flake.lock +++ b/flake.lock @@ -30,11 +30,11 @@ ] }, "locked": { - "lastModified": 1704479967, - "narHash": "sha256-YcbqMvphGDiAXX+zvEPci4LmBr1zQhGlwT/or9g7gHs=", + "lastModified": 1704923501, + "narHash": "sha256-Kz3pymvpNHTlKruepOZ3lbiWxfGhtlK5JiqF0Hk+h6I=", "owner": "catppuccin", "repo": "vscode", - "rev": "80122d60e2d3a169d0f640cfa347d91b78f814d5", + "rev": "cf7019fdeba269650940fb0bd2c4e50c7bf498d8", "type": "github" }, "original": { @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1704498488, - "narHash": "sha256-yINKdShHrtjdiJhov+q0s3Y3B830ujRoSbHduUNyKag=", + "lastModified": 1704980804, + "narHash": "sha256-lPNNKdPqIYcjhhYIVwlajNt/HqVWbMOoSdNnwCvOP04=", "owner": "nix-community", "repo": "home-manager", - "rev": "51e44a13acea71b36245e8bd8c7db53e0a3e61ee", + "rev": "93e804e7f8a1eb88bde6117cd5046501e66aa4bd", "type": "github" }, "original": { @@ -125,11 +125,11 @@ ] }, "locked": { - "lastModified": 1704099619, - "narHash": "sha256-QRVMkdxLmv+aKGjcgeEg31xtJEIsYq4i1Kbyw5EPS6g=", + "lastModified": 1704980875, + "narHash": "sha256-IPZmMjk5f4TBbEpzUFBc3OC1W6OwDNEXk2w/0uVXX1o=", "owner": "nix-community", "repo": "home-manager", - "rev": "7e398b3d76bc1503171b1364c9d4a07ac06f3851", + "rev": "5f0ab0eedc6ede69beb8f45561ffefa54edc6e65", "type": "github" }, "original": { @@ -271,11 +271,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1704420045, - "narHash": "sha256-C36QmoJd5tdQ5R9MC1jM7fBkZW9zBUqbUCsgwS6j4QU=", + "lastModified": 1704874635, + "narHash": "sha256-YWuCrtsty5vVZvu+7BchAxmcYzTMfolSPP5io8+WYCg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c1be43e8e837b8dbee2b3665a007e761680f0c3d", + "rev": "3dc440faeee9e889fe2d1b4d25ad0f430d449356", "type": "github" }, "original": { @@ -286,11 +286,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1704538339, - "narHash": "sha256-1734d3mQuux9ySvwf6axRWZRBhtcZA9Q8eftD6EZg6U=", + "lastModified": 1704722960, + "narHash": "sha256-mKGJ3sPsT6//s+Knglai5YflJUF2DGj7Ai6Ynopz0kI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "46ae0210ce163b3cba6c7da08840c1d63de9c701", + "rev": "317484b1ead87b9c1b8ac5261a8d2dd748a0492d", "type": "github" }, "original": { @@ -309,11 +309,11 @@ ] }, "locked": { - "lastModified": 1704383901, - "narHash": "sha256-i2+yzhc13omN+z9K8W3/+23g7D6yWfLb5Qn5f8VVvZI=", + "lastModified": 1704927112, + "narHash": "sha256-AKTE0TczctkgAj3FGnslPrDZP0A9FDlRITv+aV2Agsg=", "owner": "pjones", "repo": "plasma-manager", - "rev": "f11fd526015b5e6b3622c660eda4c4a13d7592bc", + "rev": "06ad8e693009a64b58156b8b55e347defe759970", "type": "github" }, "original": { @@ -379,11 +379,11 @@ ] }, "locked": { - "lastModified": 1704763209, - "narHash": "sha256-n++yFjIO8ZxAYCRgfY+82H/2Ng5GQ9vK8N+iq9wqVCs=", + "lastModified": 1705022460, + "narHash": "sha256-SOLOCrCLxp7W4tDDgmDTDPNw7lcf18ZIcniXwNORkT4=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "c4177ec6600af2f26fe5a8fd14605240130f8e56", + "rev": "cc030ff88be6c4d8d2933b5682c9c8d966f74429", "type": "github" }, "original": { From 9d53cc611a0d8335239326de4d38a8feb5190493 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Jan 2024 12:18:55 +0100 Subject: [PATCH 0339/1125] Common/starship: update nerdfont preset --- roles/common/programs/starship.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index f2380d3..d7a3518 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -16,7 +16,7 @@ let presets = { nerdFontSymbols = pkgs.fetchurl { url = "https://starship.rs/presets/toml/nerd-font-symbols.toml"; - hash = "sha256-fPmZrfhwM9NakdlJ7Y4rZ5n6JjsqXNEQ9XuFa8en9n0="; + hash = "sha256-BVe5JMSIa3CoY2Wf9pvcF1EUtDVCWCLhW3IyKuwfHug="; }; }; # -------------------------------- F U N C T I O N S -------------------------------- From d8b8c8e37c8f1c514315e57ab62771b9a3bc8424 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 15 Jan 2024 12:08:31 +0100 Subject: [PATCH 0340/1125] School/idea: update catppuccin icons plugin --- roles/school/programs/idea.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index 68fcdde..bc231dd 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -18,8 +18,8 @@ with pkgs; hash = "sha256-faMDP6kU21WOHVjY5Aj4/Glqymo1iUCTuUJdHsq1N/s="; }; ".local/share/JetBrains/IntelliJIdea2023.3/catppuccin-icons.jar".source = fetchurl { - url = "https://github.com/catppuccin/jetbrains-icons/releases/download/v1.1.0/Catppuccin.Icons-1.1.0.jar"; - hash = "sha256-aM+IfIwvj1A14ELyW+KI9SaBrX8ZcnqkS59VbAWq9s4="; + url = "https://github.com/catppuccin/jetbrains-icons/releases/download/v1.1.1/Catppuccin.Icons-1.1.1.jar"; + hash = "sha256-Bn0Yn0RlNmJQCSC0MJQrKjeERzfHhupWnyYm0YjXFwY="; }; }; From dda60e84d800503dfc3c69ac09e880dbc817e3b3 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 15 Jan 2024 13:37:32 +0100 Subject: [PATCH 0341/1125] Flake: update lock file Mysql workbench doesn't build rn so I haven't updated nixpkgs and inputs that depend on it --- flake.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/flake.lock b/flake.lock index beb39b3..d3c6b94 100644 --- a/flake.lock +++ b/flake.lock @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1704980804, - "narHash": "sha256-lPNNKdPqIYcjhhYIVwlajNt/HqVWbMOoSdNnwCvOP04=", + "lastModified": 1705169127, + "narHash": "sha256-j9OEtNxOIPWZWjbECVMkI1TO17SzlpHMm0LnVWKOR/g=", "owner": "nix-community", "repo": "home-manager", - "rev": "93e804e7f8a1eb88bde6117cd5046501e66aa4bd", + "rev": "f2942f3385f1b35cc8a1abb03a45e29c9cb4d3c8", "type": "github" }, "original": { @@ -255,11 +255,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1704786394, - "narHash": "sha256-aJM0ln9fMGWw1+tjyl5JZWZ3ahxAA2gw2ZpZY/hkEMs=", + "lastModified": 1705312285, + "narHash": "sha256-rd+dY+v61Y8w3u9bukO/hB55Xl4wXv4/yC8rCGVnK5U=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "b34a6075e9e298c4124e35c3ccaf2210c1f3a43b", + "rev": "bee2202bec57e521e3bd8acd526884b9767d7fa0", "type": "github" }, "original": { @@ -309,11 +309,11 @@ ] }, "locked": { - "lastModified": 1704927112, - "narHash": "sha256-AKTE0TczctkgAj3FGnslPrDZP0A9FDlRITv+aV2Agsg=", + "lastModified": 1705257805, + "narHash": "sha256-hx88TjxRWR9hEYrePm2aR/rKAu4VFx4irgN7AofE0Wg=", "owner": "pjones", "repo": "plasma-manager", - "rev": "06ad8e693009a64b58156b8b55e347defe759970", + "rev": "87ca0e29c6fccfb7f09be6ff137716db5a7c8d8f", "type": "github" }, "original": { @@ -379,11 +379,11 @@ ] }, "locked": { - "lastModified": 1705022460, - "narHash": "sha256-SOLOCrCLxp7W4tDDgmDTDPNw7lcf18ZIcniXwNORkT4=", + "lastModified": 1705281787, + "narHash": "sha256-q1peRaGxQb05mzfSyB7D9PhVL8dK3YoVSGUKfKvXxoU=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "cc030ff88be6c4d8d2933b5682c9c8d966f74429", + "rev": "2357e0e02e954ad5b3a85bae108fc4c8804e0d26", "type": "github" }, "original": { From ea3870aa6e5cc3182a80f0a54df11ef5dd2968d5 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 13 Jan 2024 14:11:25 +0100 Subject: [PATCH 0342/1125] Use catppuccin from nixpkgs --- roles/common/configuration.nix | 15 +++++++++++++++ roles/common/programs/bat.nix | 9 ++------- roles/common/programs/btop.nix | 12 +----------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 42a9518..6a0d009 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -64,6 +64,21 @@ # Set up time zone. time.timeZone = "Europe/Madrid"; + nixpkgs.overlays = [ + ( + final: prev: { + catppuccin = prev.catppuccin.override { + accent = "mauve"; + variant = "mocha"; + themeList = [ + "bat" + "btop" + ]; + }; + } + ) + ]; + home-manager = { backupFileExtension = "hm-backup"; useGlobalPkgs = true; diff --git a/roles/common/programs/bat.nix b/roles/common/programs/bat.nix index 2075753..2a8224d 100644 --- a/roles/common/programs/bat.nix +++ b/roles/common/programs/bat.nix @@ -9,13 +9,8 @@ }; themes = { catppuccin-mocha = { - src = pkgs.fetchFromGitHub { - owner = "catppuccin"; - repo = "bat"; - rev = "master"; - hash = "sha256-6WVKQErGdaqb++oaXnY3i6/GuH2FhTgK0v4TN4Y0Wbw="; - }; - file = "Catppuccin-mocha.tmTheme"; + src = pkgs.catppuccin; + file = "bat/Catppuccin-mocha.tmTheme"; }; }; }; diff --git a/roles/common/programs/btop.nix b/roles/common/programs/btop.nix index 291d05e..5150cbf 100644 --- a/roles/common/programs/btop.nix +++ b/roles/common/programs/btop.nix @@ -1,15 +1,5 @@ { pkgs, ... }: -let - catppuccinBtop = pkgs.fetchFromGitHub { - owner = "catppuccin"; - repo = "btop"; - # I know fetiching from master is not best practice but idc this is not going to change often - # Latest commit rn is c6469190f2ecf25f017d6120bf4e050e6b1d17af - rev = "master"; - hash = "sha256-jodJl4f2T9ViNqsY9fk8IV62CrpC5hy7WK3aRpu70Cs="; -}; -in { home-manager = { users.toast = { @@ -20,7 +10,7 @@ in }; }; xdg.configFile = { - "btop/themes".source = "${catppuccinBtop}/themes"; + "btop/themes".source = "${pkgs.catppuccin}/btop"; }; }; }; From b4020d43160155661edceeb7099bdbb6909f5649 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 14 Jan 2024 01:11:19 +0100 Subject: [PATCH 0343/1125] Flake: apply patch to nixpkgs-unstable This feels really dirty, but it works and it's less effort that switching to something like flake-utils that can do this for you --- flake.lock | 29 +++++++++++++++++++++-------- flake.nix | 42 +++++++++++++++++++++++++++++------------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index d3c6b94..40c3bb1 100644 --- a/flake.lock +++ b/flake.lock @@ -26,7 +26,7 @@ "catppuccin-vsc": { "inputs": { "nixpkgs": [ - "nixpkgs-unstable" + "nixpkgs-unstable-raw" ] }, "locked": { @@ -101,7 +101,7 @@ "home-manager-unstable": { "inputs": { "nixpkgs": [ - "nixpkgs-unstable" + "nixpkgs-unstable-raw" ] }, "locked": { @@ -143,7 +143,7 @@ "inputs": { "nix-github-actions": "nix-github-actions", "nixpkgs": [ - "nixpkgs-unstable" + "nixpkgs-unstable-raw" ] }, "locked": { @@ -236,7 +236,7 @@ "nix-index-db-unstable": { "inputs": { "nixpkgs": [ - "nixpkgs-unstable" + "nixpkgs-unstable-raw" ] }, "locked": { @@ -284,7 +284,19 @@ "type": "indirect" } }, - "nixpkgs-unstable": { + "nixpkgs-pr280779": { + "flake": false, + "locked": { + "narHash": "sha256-eP6JaUafbs7ulve2jOsidJKM28bKzcLgoQ4WKXN1k4I=", + "type": "file", + "url": "https://github.com/NixOS/nixpkgs/pull/280779.patch" + }, + "original": { + "type": "file", + "url": "https://github.com/NixOS/nixpkgs/pull/280779.patch" + } + }, + "nixpkgs-unstable-raw": { "locked": { "lastModified": 1704722960, "narHash": "sha256-mKGJ3sPsT6//s+Knglai5YflJUF2DGj7Ai6Ynopz0kI=", @@ -305,7 +317,7 @@ "home-manager-unstable" ], "nixpkgs": [ - "nixpkgs-unstable" + "nixpkgs-unstable-raw" ] }, "locked": { @@ -335,7 +347,8 @@ "nix-index-db-unstable": "nix-index-db-unstable", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", - "nixpkgs-unstable": "nixpkgs-unstable", + "nixpkgs-pr280779": "nixpkgs-pr280779", + "nixpkgs-unstable-raw": "nixpkgs-unstable-raw", "plasma-manager": "plasma-manager", "vscode-extensions": "vscode-extensions" } @@ -375,7 +388,7 @@ "flake-compat": "flake-compat", "flake-utils": "flake-utils", "nixpkgs": [ - "nixpkgs-unstable" + "nixpkgs-unstable-raw" ] }, "locked": { diff --git a/flake.nix b/flake.nix index 75ab5e1..a7cdc98 100755 --- a/flake.nix +++ b/flake.nix @@ -3,7 +3,12 @@ inputs = { nixpkgs.url = "nixpkgs/nixos-23.11"; - nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; + nixpkgs-unstable-raw.url = "nixpkgs/nixos-unstable"; + + nixpkgs-pr280779 = { + url = "file+https://github.com/NixOS/nixpkgs/pull/280779.patch"; + flake = false; + }; agenix = { url = "github:ryantm/agenix"; @@ -20,14 +25,14 @@ home-manager-unstable = { url = "github:nix-community/home-manager/"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; }; nixos-hardware.url = "github:NixOS/nixos-hardware/master"; jovian = { url = "github:Jovian-Experiments/Jovian-NixOS"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; }; nix-impermanence.url = "github:nix-community/impermanence"; @@ -43,30 +48,41 @@ nix-index-db-unstable = { url = "github:Mic92/nix-index-database"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; }; plasma-manager = { url = "github:pjones/plasma-manager"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; inputs.home-manager.follows = "home-manager-unstable"; }; catppuccin-vsc = { url = "github:catppuccin/vscode"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; }; vscode-extensions = { url = "github:nix-community/nix-vscode-extensions"; - inputs.nixpkgs.follows = "nixpkgs-unstable"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; }; nix-flatpak.url = github:gmodena/nix-flatpak/main; }; - outputs = { ... } @inputs: with inputs; { - + outputs = { ... } @inputs: with inputs; + # Patch nixpkgs + # https://ertt.ca/nix/patch-nixpkgs/ + let + nixpkgs-unstable-patched = nixpkgs.legacyPackages.x86_64-linux.applyPatches { + name = "patched-nixpkgs-unstable"; + src = nixpkgs-unstable-raw; + patches = [ nixpkgs-pr280779 ]; + }; + # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 + nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs { self = inputs.self; }; + in + { devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { name = "Environment for toast's nixos configurations"; # The agenix cli is not needed to activate a configuration, so instead of installing it @@ -82,7 +98,7 @@ ''; }; packages = { - x86_64-linux = with import nixpkgs-unstable { system = "x86_64-linux"; }; { + x86_64-linux = with import nixpkgs-unstable-raw { system = "x86_64-linux"; }; { pseint = callPackage ./pkgs/pseint.nix {}; anything-sync-daemon = callPackage ./pkgs/anything-sync-daemon {}; discord-krisp-fixer = callPackage ./pkgs/discord-krisp-fixer {}; @@ -91,7 +107,7 @@ nixosConfigurations = { Archie = nixpkgs-unstable.lib.nixosSystem { system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-unstable; flakeSelf = self; }; + specialArgs = { systemPkgs = inputs.nixpkgs-unstable-raw; flakeSelf = self; }; /* I used to set up nixpkgs in the flake, but doing that made defining overlays in modules impossible (or at least I could @@ -113,7 +129,7 @@ SurfaceGo = nixpkgs-unstable.lib.nixosSystem { system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-unstable; flakeSelf = self; }; + specialArgs = { systemPkgs = inputs.nixpkgs-unstable-raw; flakeSelf = self; }; modules = [ agenix.nixosModules.default home-manager-unstable.nixosModule @@ -128,7 +144,7 @@ SteamDeck = nixpkgs-unstable.lib.nixosSystem { system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-unstable; flakeSelf = self; }; + specialArgs = { systemPkgs = inputs.nixpkgs-unstable-raw; flakeSelf = self; }; modules = [ agenix.nixosModules.default jovian.nixosModules.default From 90cbeed3f2f06b364d04dff90ed98bf6441dd175 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 14 Jan 2024 01:13:08 +0100 Subject: [PATCH 0344/1125] Common/starship: use catppuccin theme from nixpkgs --- roles/common/configuration.nix | 1 + roles/common/programs/starship.nix | 8 +------- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 6a0d009..29bf21d 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -73,6 +73,7 @@ themeList = [ "bat" "btop" + "starship" ]; }; } diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index d7a3518..0718478 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -5,13 +5,7 @@ with builtins; let catppuccinFlavour = "mocha"; - catppuccinStarship = pkgs.fetchFromGitHub { - owner = "catppuccin"; - repo = "starship"; - # Latest commit is 5629d2356f62a9f2f8efad3ff37476c19969bd4f - rev = "main"; - hash = "sha256-nsRuxQFKbQkyEI4TXgvAjcroVdG+heKX5Pauq/4Ota0="; - } + /palettes/${catppuccinFlavour}.toml; + catppuccinStarship = pkgs.catppuccin + /starship/${catppuccinFlavour}.toml; presets = { nerdFontSymbols = pkgs.fetchurl { From 4320ecc26a4df07d80f3a750c1a73c789fe821a2 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 00:56:59 +0100 Subject: [PATCH 0345/1125] Flake: update nixpkgs patch --- flake.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index 40c3bb1..ef21bd8 100644 --- a/flake.lock +++ b/flake.lock @@ -287,7 +287,7 @@ "nixpkgs-pr280779": { "flake": false, "locked": { - "narHash": "sha256-eP6JaUafbs7ulve2jOsidJKM28bKzcLgoQ4WKXN1k4I=", + "narHash": "sha256-MnUPeXecesXaBF4x9/+LCiANjzX9KVtl0JalyWAucYk=", "type": "file", "url": "https://github.com/NixOS/nixpkgs/pull/280779.patch" }, From 983b76f82ae1068120f635050b3e7b17a1becb34 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 01:16:24 +0100 Subject: [PATCH 0346/1125] School: remove WebStorm I didn't end up using it and it's being problematic so yeet --- roles/school/programs/default.nix | 1 - roles/school/programs/webstorm.nix | 22 ---------------------- 2 files changed, 23 deletions(-) delete mode 100644 roles/school/programs/webstorm.nix diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index f1fad93..24dba3a 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -4,7 +4,6 @@ imports = [ ./virtualbox.nix ./idea.nix - ./webstorm.nix ./vscode.nix ]; diff --git a/roles/school/programs/webstorm.nix b/roles/school/programs/webstorm.nix deleted file mode 100644 index 66a2265..0000000 --- a/roles/school/programs/webstorm.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ pkgs, ... }: - -with pkgs; -{ - - home-manager.users.toast = { - home = { - packages = [ jetbrains.webstorm ]; - # Install plugins - file = { - ".local/share/JetBrains/WebStorm2023.2/catppuccin.jar".source = fetchurl { - url = "https://github.com/catppuccin/jetbrains/releases/download/v3.2.1/Catppuccin.Theme-3.2.1.jar"; - hash = "sha256-vE3Tv/dNfWyRuBJXLDPmtY1GnLShqM+dJR5rltXYdOY="; - }; - ".local/share/JetBrains/WebStorm2023.2/rainbow-brackets".source = fetchzip { - url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/2023.3.7/intellij-rainbow-brackets-2023.3.7.zip"; - hash = "sha256-szgyQs3iCge9rI274PA29i+tprPE11xpyJqiccedp6A="; - }; - }; - }; - }; -} From 98e393fd92c41b8e0bcbe88a7dd37f1c460b1f09 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 01:44:40 +0100 Subject: [PATCH 0347/1125] Machines: add Win Max 2 --- flake.nix | 20 +++- machines/WinMax2/configuration.nix | 112 ++++++++++++++++++++ machines/WinMax2/default.nix | 8 ++ machines/WinMax2/hardware-configuration.nix | 70 ++++++++++++ roles/common/configuration.nix | 3 +- 5 files changed, 211 insertions(+), 2 deletions(-) create mode 100755 machines/WinMax2/configuration.nix create mode 100755 machines/WinMax2/default.nix create mode 100755 machines/WinMax2/hardware-configuration.nix diff --git a/flake.nix b/flake.nix index a7cdc98..31a166b 100755 --- a/flake.nix +++ b/flake.nix @@ -158,7 +158,25 @@ ./machines/SteamDeck ]; }; - + + WinMax2 = nixpkgs-unstable.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { systemPkgs = inputs.nixpkgs-unstable-raw; flakeSelf = self; }; + modules = [ + agenix.nixosModules.default + jovian.nixosModules.default + home-manager-unstable.nixosModule + nix-index-db-unstable.nixosModules.nix-index + nixos-hardware.nixosModules.gpd-win-max-2-2023 + ./roles/common + ./roles/desktop + ./roles/kde + ./roles/gaming + ./roles/school + ./machines/WinMax2 + ]; + }; + Everest = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; specialArgs = { systemPkgs = inputs.nixpkgs; flakeSelf = self; }; diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix new file mode 100755 index 0000000..fc39a34 --- /dev/null +++ b/machines/WinMax2/configuration.nix @@ -0,0 +1,112 @@ + # Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running `nixos-help`). + +{ config, pkgs, lib, ... }: + +{ + # Use grub boot loader + boot.loader = { + systemd-boot.enable = false; + grub = { + enable = true; + device = "nodev"; + efiSupport = true; + # No other OS on here :P + useOSProber = false; + }; + efi.efiSysMountPoint = config.fileSystems."efi_boot_partition".mountPoint; + }; + boot.loader.efi.canTouchEfiVariables = true; + + networking.hostName = "WinMax2"; # Define your hostname. + networking.networkmanager.enable = true; # Enable networking + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + nix.settings.auto-optimise-store = true; + + services.xserver.layout = lib.mkForce "us"; + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Enable the X11 windowing system. + services.xserver.enable = true; + + jovian = { + # Steam Deck UI settings + steam = { + enable = true; + autoStart = false; + user = "toast"; + desktopSession = "plasmawayland"; + }; + decky-loader = { + enable = true; + }; + }; + + # Enable bluetooth + hardware.bluetooth = { + enable = true; + }; + + # Configure keymap in X11 + # services.xserver.layout = "us"; + # services.xserver.xkbOptions = "eurosign:e,caps:escape"; + + # Enable CUPS to print documents. + # services.printing.enable = true; + + # Enable sound. + # sound.enable = true; + # hardware.pulseaudio.enable = true; + + # Enable touchpad support (enabled default in most desktopManager). + # services.xserver.libinput.enable = true; + + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.toast = { + isNormalUser = true; + extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + }; + + # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs + boot.tmp.useTmpfs = false; + + # List packages installed in system profile. To search, run: + # $ nix search wget + # environment.systemPackages = with pkgs; [ + # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + # wget + # ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + # services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + # system.copySystemConfiguration = true; + +} + diff --git a/machines/WinMax2/default.nix b/machines/WinMax2/default.nix new file mode 100755 index 0000000..5bf2485 --- /dev/null +++ b/machines/WinMax2/default.nix @@ -0,0 +1,8 @@ +{ ... }: + +{ + imports = [ + ./configuration.nix + ./hardware-configuration.nix + ]; +} diff --git a/machines/WinMax2/hardware-configuration.nix b/machines/WinMax2/hardware-configuration.nix new file mode 100755 index 0000000..43949ee --- /dev/null +++ b/machines/WinMax2/hardware-configuration.nix @@ -0,0 +1,70 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +let + # \x20 is the escape code for a space + ssdLabel = ''Win\\x20Max\\x202\\x20SSD''; +in + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usbhid" "sdhci_pci" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + boot.initrd.luks.devices."SSD".device = "/dev/disk/by-label/wm2-enc"; + + fileSystems = { + "efi_boot_partition" = { + mountPoint = "/boot/efi"; + label = "winmax2boot"; + fsType = "vfat"; + }; + /* + Mount the root subvolume of the SSD + This is helpful for getting things from + my old Arch install, as well as for running btdu + */ + "btrfs_root_subvolume" = { + mountPoint = "/mnt/ssd"; + label = ssdLabel; + fsType = "btrfs"; + options = [ "subvolid=5" "ro" ]; + }; + "btrfs_root" = { + mountPoint = "/"; + label = ssdLabel; + fsType = "btrfs"; + options = [ "subvol=@" ]; + }; + "btrfs_boot" = { + mountPoint = "/boot"; + label = ssdLabel; + fsType = "btrfs"; + options = [ "subvol=@boot" ]; + }; + "btrfs_home" = { + mountPoint = "/home"; + label = ssdLabel; + fsType = "btrfs"; + options = [ "subvol=@home" ]; + }; + "btrfs_nix" = { + mountPoint = "/nix"; + label = ssdLabel; + fsType = "btrfs"; + options = [ "subvol=@nix" ]; + }; + }; + + swapDevices = [ ]; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 29bf21d..8871d76 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -36,7 +36,8 @@ console = { packages = [ pkgs.terminus_font ]; earlySetup = true; - font = lib.mkDefault "ter-i16n"; + # mkDefault has 1000 priority, so that way I don't conflict with nixos-hardware + font = lib.mkOverride 999 "ter-i16n"; # Make the console use X's keyboard configuration useXkbConfig = true; }; From 89e548cb41c76ed200912575e5e50e9d2733cc11 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 02:27:06 +0100 Subject: [PATCH 0348/1125] Machines/WinMax2: mount efi partition in /boot --- machines/WinMax2/hardware-configuration.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/machines/WinMax2/hardware-configuration.nix b/machines/WinMax2/hardware-configuration.nix index 43949ee..de48c2d 100755 --- a/machines/WinMax2/hardware-configuration.nix +++ b/machines/WinMax2/hardware-configuration.nix @@ -22,7 +22,7 @@ in fileSystems = { "efi_boot_partition" = { - mountPoint = "/boot/efi"; + mountPoint = "/boot"; label = "winmax2boot"; fsType = "vfat"; }; @@ -43,12 +43,12 @@ in fsType = "btrfs"; options = [ "subvol=@" ]; }; - "btrfs_boot" = { + /*"btrfs_boot" = { mountPoint = "/boot"; label = ssdLabel; fsType = "btrfs"; options = [ "subvol=@boot" ]; - }; + };*/ "btrfs_home" = { mountPoint = "/home"; label = ssdLabel; From 6ce1dba91eeceb8c838f7e68cc4029d3e8962042 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 09:28:30 +0100 Subject: [PATCH 0349/1125] Common/syncthing: add Win Max 2 ID --- roles/common/services/syncthing.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index 9a090ab..5691ef3 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -31,12 +31,16 @@ name = "Surface Go"; id = "HTVSF3O-AHY3TNH-BLVSEGK-HRRSMHC-H5LJWVF-NDKGM6O-ATWZALC-YXNV2Q4"; }; + "winmax2" = { + name = "Win Max 2"; + id = "X2NILRM-ADRBQ23-AFREAZA-62GVFDF-UVMPR4L-KGHMUNY-BJ2C3CQ-RBT43QS"; + }; }; folders = { "passwords" = { label = "KeePassXC Passwords"; id = "rdyaq-ex659"; - devices = [ "phone" "pc" "steamdeck" "server" "surface"]; + devices = [ "phone" "pc" "steamdeck" "server" "surface" "winmax2"]; }; }; }; From cf4ab5001e01eec2f31aa53403798efa8775ad2a Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 09:40:34 +0100 Subject: [PATCH 0350/1125] Common/git: add user name and email --- roles/common/programs/git.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index 3002894..ed5cc08 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -4,6 +4,8 @@ home-manager.users.toast = { programs.git = { enable = true; + userName = "Toast"; + userEmail = "toast003@tutamail.com"; delta.enable = true; extraConfig = { init.defaultBranch = "main"; From c114dc56add1ce80b63489469234245475c30326 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 09:44:38 +0100 Subject: [PATCH 0351/1125] School/syncthing: add Win Max 2 --- roles/school/services/syncthing.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/school/services/syncthing.nix b/roles/school/services/syncthing.nix index 9663c57..a649b75 100644 --- a/roles/school/services/syncthing.nix +++ b/roles/school/services/syncthing.nix @@ -5,7 +5,7 @@ "school-things" = { label = "School things"; id = "z6alc-nfoqr"; - devices = [ "steamdeck" "server" "pc" ]; + devices = [ "steamdeck" "server" "pc" "winmax2" ]; path = "~/Documents/School things"; }; }; From e0f5fffea4534c7eeb9e4826f4ea02e873e4f61d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 20:40:21 +0100 Subject: [PATCH 0352/1125] Flake: store nixpkgs patches in repo --- flake.lock | 13 ---------- flake.nix | 7 +----- nixpkgs-patches/pr280779.patch | 46 ++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 nixpkgs-patches/pr280779.patch diff --git a/flake.lock b/flake.lock index ef21bd8..a69d702 100644 --- a/flake.lock +++ b/flake.lock @@ -284,18 +284,6 @@ "type": "indirect" } }, - "nixpkgs-pr280779": { - "flake": false, - "locked": { - "narHash": "sha256-MnUPeXecesXaBF4x9/+LCiANjzX9KVtl0JalyWAucYk=", - "type": "file", - "url": "https://github.com/NixOS/nixpkgs/pull/280779.patch" - }, - "original": { - "type": "file", - "url": "https://github.com/NixOS/nixpkgs/pull/280779.patch" - } - }, "nixpkgs-unstable-raw": { "locked": { "lastModified": 1704722960, @@ -347,7 +335,6 @@ "nix-index-db-unstable": "nix-index-db-unstable", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", - "nixpkgs-pr280779": "nixpkgs-pr280779", "nixpkgs-unstable-raw": "nixpkgs-unstable-raw", "plasma-manager": "plasma-manager", "vscode-extensions": "vscode-extensions" diff --git a/flake.nix b/flake.nix index 31a166b..308289c 100755 --- a/flake.nix +++ b/flake.nix @@ -5,11 +5,6 @@ nixpkgs.url = "nixpkgs/nixos-23.11"; nixpkgs-unstable-raw.url = "nixpkgs/nixos-unstable"; - nixpkgs-pr280779 = { - url = "file+https://github.com/NixOS/nixpkgs/pull/280779.patch"; - flake = false; - }; - agenix = { url = "github:ryantm/agenix"; inputs = { @@ -77,7 +72,7 @@ nixpkgs-unstable-patched = nixpkgs.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; - patches = [ nixpkgs-pr280779 ]; + patches = [ ./nixpkgs-patches/pr280779.patch ]; }; # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs { self = inputs.self; }; diff --git a/nixpkgs-patches/pr280779.patch b/nixpkgs-patches/pr280779.patch new file mode 100644 index 0000000..f404304 --- /dev/null +++ b/nixpkgs-patches/pr280779.patch @@ -0,0 +1,46 @@ +From cf1dfaa32a0201cc14801ebb93b5ef865d42522a Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Sat, 13 Jan 2024 18:41:51 +0100 +Subject: [PATCH] catppuccin: add starship theme + +--- + pkgs/data/themes/catppuccin/default.nix | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/pkgs/data/themes/catppuccin/default.nix b/pkgs/data/themes/catppuccin/default.nix +index c9a51ba241d482..25794c9e67d7cd 100644 +--- a/pkgs/data/themes/catppuccin/default.nix ++++ b/pkgs/data/themes/catppuccin/default.nix +@@ -1,5 +1,5 @@ + let +- validThemes = [ "bat" "bottom" "btop" "grub" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "qt5ct" "refind" "rofi" "waybar" ]; ++ validThemes = [ "bat" "bottom" "btop" "grub" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "qt5ct" "refind" "rofi" "starship" "waybar" ]; + in + { fetchFromGitHub + , lib +@@ -112,6 +112,14 @@ let + hash = "sha256-DNorfyl3C4RBclF2KDgwvQQwixpTwSRu7fIvihPN8JY="; + }; + ++ starship = fetchFromGitHub { ++ name = "starship"; ++ owner = "catppuccin"; ++ repo = "starship"; ++ rev = "5629d2356f62a9f2f8efad3ff37476c19969bd4f"; ++ hash = "sha256-nsRuxQFKbQkyEI4TXgvAjcroVdG+heKX5Pauq/4Ota0="; ++ }; ++ + waybar = fetchFromGitHub { + name = "waybar"; + owner = "catppuccin"; +@@ -195,6 +203,10 @@ stdenvNoCC.mkDerivation { + cp ${sources.refind}/${variant}.conf $out/refind/ + cp -r ${sources.refind}/assets/${variant} $out/refind/assets/ + ++ '' + lib.optionalString (lib.elem "starship" themeList) '' ++ mkdir -p $out/starship ++ cp ${sources.starship}/palettes/${variant}.toml $out/starship/ ++ + '' + lib.optionalString (lib.elem "waybar" themeList) '' + mkdir -p $out/waybar + cp ${sources.waybar}/${variant}.css $out/waybar/ From 3a15f90405685c1847b25385a67636f09c4dd542 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 10:47:36 +0100 Subject: [PATCH 0353/1125] Machines/WinMax2: use systemd initrd --- machines/WinMax2/configuration.nix | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index fc39a34..5a350a4 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -6,18 +6,27 @@ { # Use grub boot loader - boot.loader = { - systemd-boot.enable = false; - grub = { - enable = true; - device = "nodev"; - efiSupport = true; - # No other OS on here :P - useOSProber = false; + boot = { + loader = { + systemd-boot.enable = false; + grub = { + enable = true; + device = "nodev"; + efiSupport = true; + # No other OS on here :P + useOSProber = false; + }; + efi = { + efiSysMountPoint = config.fileSystems."efi_boot_partition".mountPoint; + canTouchEfiVariables = true; + }; }; - efi.efiSysMountPoint = config.fileSystems."efi_boot_partition".mountPoint; + /* + I use luks, and the systemd initrd works better for this + Both for tpm unlocking (soon) and for plymouth + */ + initrd.systemd.enable = true; }; - boot.loader.efi.canTouchEfiVariables = true; networking.hostName = "WinMax2"; # Define your hostname. networking.networkmanager.enable = true; # Enable networking From 92b2b131baf2925a7416e4bfef66599c09c919f4 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 20:53:40 +0100 Subject: [PATCH 0354/1125] Machines/WinMax2: force enable steam's scaling --- machines/WinMax2/configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 5a350a4..f5e869b 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -69,6 +69,9 @@ # Enable CUPS to print documents. # services.printing.enable = true; + environment.sessionVariables = { + STEAM_FORCE_DESKTOPUI_SCALING = "1.75"; + }; # Enable sound. # sound.enable = true; From 9b5dfb9c20798ad02d7949fe53c446b9a4883453 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 20:56:56 +0100 Subject: [PATCH 0355/1125] Machines/WinMax2: set up scaling for plymouth --- machines/WinMax2/configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index f5e869b..65980d5 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -26,6 +26,9 @@ Both for tpm unlocking (soon) and for plymouth */ initrd.systemd.enable = true; + # Plymouth doesn't support fractional scaling :( + plymouth.extraConfig = "DeviceScale=2"; + }; networking.hostName = "WinMax2"; # Define your hostname. From 7f202c503d54473405ae1a0e60c4b834985e1194 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 22:28:36 +0100 Subject: [PATCH 0356/1125] Flake: update lock file --- flake.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/flake.lock b/flake.lock index a69d702..91d52f0 100644 --- a/flake.lock +++ b/flake.lock @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1705169127, - "narHash": "sha256-j9OEtNxOIPWZWjbECVMkI1TO17SzlpHMm0LnVWKOR/g=", + "lastModified": 1705408632, + "narHash": "sha256-/AhkReVocTli5BLWA5WXxUlGYXn3Agi/uzX76TNrsbo=", "owner": "nix-community", "repo": "home-manager", - "rev": "f2942f3385f1b35cc8a1abb03a45e29c9cb4d3c8", + "rev": "37d6eeceee464adc03585404eebd68765b3c8615", "type": "github" }, "original": { @@ -125,11 +125,11 @@ ] }, "locked": { - "lastModified": 1704980875, - "narHash": "sha256-IPZmMjk5f4TBbEpzUFBc3OC1W6OwDNEXk2w/0uVXX1o=", + "lastModified": 1705273357, + "narHash": "sha256-JAlkxgJbWh7+auiT0rJL3IUXXtkULRqygfxQA6mvLgc=", "owner": "nix-community", "repo": "home-manager", - "rev": "5f0ab0eedc6ede69beb8f45561ffefa54edc6e65", + "rev": "924d91e1e4c802fd8e60279a022dbae5acb36f2d", "type": "github" }, "original": { @@ -147,11 +147,11 @@ ] }, "locked": { - "lastModified": 1704665257, - "narHash": "sha256-Cycz00I26e8QZ9sZtCz0uIz6Cad5ld3zM7N2I+5beqI=", + "lastModified": 1705231543, + "narHash": "sha256-W8j0A5n2WOpCgdFRqMqwd9adNORcN1r/DpjRVxiFkAw=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "8951673c6c216ddd6bac3db3e88e3f2281b3511a", + "rev": "ab807f9740c533070e8b68b0d86034d4a293b5f1", "type": "github" }, "original": { @@ -220,11 +220,11 @@ ] }, "locked": { - "lastModified": 1704596958, - "narHash": "sha256-BK3Ohsz7m8X6qVKFxDtr8KVcHipfr5hYE9PDIJevHbQ=", + "lastModified": 1705282324, + "narHash": "sha256-LnURMA7yCM5t7et9O2+2YfGQh0FKAfE5GyahNDDzJVM=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f46800ac5a6e9f892fe36e50821c5d85794ecc62", + "rev": "49aaeecf41ae0a0944e2c627cb515bcde428a1d1", "type": "github" }, "original": { @@ -240,11 +240,11 @@ ] }, "locked": { - "lastModified": 1704596958, - "narHash": "sha256-BK3Ohsz7m8X6qVKFxDtr8KVcHipfr5hYE9PDIJevHbQ=", + "lastModified": 1705282324, + "narHash": "sha256-LnURMA7yCM5t7et9O2+2YfGQh0FKAfE5GyahNDDzJVM=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f46800ac5a6e9f892fe36e50821c5d85794ecc62", + "rev": "49aaeecf41ae0a0944e2c627cb515bcde428a1d1", "type": "github" }, "original": { @@ -271,11 +271,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1704874635, - "narHash": "sha256-YWuCrtsty5vVZvu+7BchAxmcYzTMfolSPP5io8+WYCg=", + "lastModified": 1705331948, + "narHash": "sha256-qjQXfvrAT1/RKDFAMdl8Hw3m4tLVvMCc8fMqzJv0pP4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3dc440faeee9e889fe2d1b4d25ad0f430d449356", + "rev": "b8dd8be3c790215716e7c12b247f45ca525867e2", "type": "github" }, "original": { @@ -286,11 +286,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1704722960, - "narHash": "sha256-mKGJ3sPsT6//s+Knglai5YflJUF2DGj7Ai6Ynopz0kI=", + "lastModified": 1705316053, + "narHash": "sha256-J2Ey5mPFT8gdfL2XC0JTZvKaBw/b2pnyudEXFvl+dQM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "317484b1ead87b9c1b8ac5261a8d2dd748a0492d", + "rev": "c3e128f3c0ecc1fb04aef9f72b3dcc2f6cecf370", "type": "github" }, "original": { @@ -379,11 +379,11 @@ ] }, "locked": { - "lastModified": 1705281787, - "narHash": "sha256-q1peRaGxQb05mzfSyB7D9PhVL8dK3YoVSGUKfKvXxoU=", + "lastModified": 1705368072, + "narHash": "sha256-e7Gn7daakWvEj/hQTw628zMGhAMH88thrmhmoB6RV6o=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "2357e0e02e954ad5b3a85bae108fc4c8804e0d26", + "rev": "37b8bbc1717211338c446b7b926276bf8db234ac", "type": "github" }, "original": { From 9fc86390b8d2c3227960d7642e4f4877bb481ae1 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Jan 2024 22:28:54 +0100 Subject: [PATCH 0357/1125] Flake: add https://github.com/NixOS/nixpkgs/pull/281207 to nixpkgs unstable --- flake.nix | 5 +- nixpkgs-patches/pr281207.patch | 117 +++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 nixpkgs-patches/pr281207.patch diff --git a/flake.nix b/flake.nix index 308289c..427a665 100755 --- a/flake.nix +++ b/flake.nix @@ -72,7 +72,10 @@ nixpkgs-unstable-patched = nixpkgs.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; - patches = [ ./nixpkgs-patches/pr280779.patch ]; + patches = [ + ./nixpkgs-patches/pr280779.patch + ./nixpkgs-patches/pr281207.patch + ]; }; # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs { self = inputs.self; }; diff --git a/nixpkgs-patches/pr281207.patch b/nixpkgs-patches/pr281207.patch new file mode 100644 index 0000000..c9bea43 --- /dev/null +++ b/nixpkgs-patches/pr281207.patch @@ -0,0 +1,117 @@ +From 1f3bcdf27686e9d2c43a53cf3ba7cd0ee7978ff5 Mon Sep 17 00:00:00 2001 +From: TomaSajt <62384384+TomaSajt@users.noreply.github.com> +Date: Tue, 16 Jan 2024 00:58:48 +0100 +Subject: [PATCH] mysql-workbench: fix build, small refactor + +--- + .../misc/mysql-workbench/default.nix | 28 ++++++++++++------- + .../misc/mysql-workbench/fix-xml2.patch | 25 +++++++++++++++++ + 2 files changed, 43 insertions(+), 10 deletions(-) + create mode 100644 pkgs/applications/misc/mysql-workbench/fix-xml2.patch + +diff --git a/pkgs/applications/misc/mysql-workbench/default.nix b/pkgs/applications/misc/mysql-workbench/default.nix +index ff9fb7c6b2cbe2..6b5933b3ebd0fd 100644 +--- a/pkgs/applications/misc/mysql-workbench/default.nix ++++ b/pkgs/applications/misc/mysql-workbench/default.nix +@@ -1,4 +1,5 @@ +-{ lib, stdenv ++{ lib ++, stdenv + , fetchurl + , substituteAll + , cmake +@@ -44,13 +45,14 @@ + + let + inherit (python3.pkgs) paramiko pycairo pyodbc; +-in stdenv.mkDerivation rec { ++in ++stdenv.mkDerivation (finalAttrs: { + pname = "mysql-workbench"; + version = "8.0.34"; + + src = fetchurl { +- url = "https://cdn.mysql.com//Downloads/MySQLGUITools/mysql-workbench-community-${version}-src.tar.gz"; +- sha256 = "sha256-ub/D6HRtXOvX+lai71t1UjMmMzBsz5ljCrJCuf9aq7U="; ++ url = "https://cdn.mysql.com/Downloads/MySQLGUITools/mysql-workbench-community-${finalAttrs.version}-src.tar.gz"; ++ hash = "sha256-ub/D6HRtXOvX+lai71t1UjMmMzBsz5ljCrJCuf9aq7U="; + }; + + patches = [ +@@ -75,6 +77,9 @@ in stdenv.mkDerivation rec { + src = ./fix-swig-build.patch; + cairoDev = "${cairo.dev}"; + }) ++ ++ # a newer libxml2 version has changed some interfaces ++ ./fix-xml2.patch + ]; + + # 1. have it look for 4.12.0 instead of 4.11.1 +@@ -138,6 +143,10 @@ in stdenv.mkDerivation rec { + patchShebangs tools/get_wb_version.sh + ''; + ++ # GCC 13: error: 'int64_t' in namespace 'std' does not name a type ++ # when updating the version make sure this is still needed ++ env.CXXFLAGS = "-include cstdint"; ++ + env.NIX_CFLAGS_COMPILE = toString ([ + # error: 'OGRErr OGRSpatialReference::importFromWkt(char**)' is deprecated + "-Wno-error=deprecated-declarations" +@@ -183,7 +192,7 @@ in stdenv.mkDerivation rec { + done + ''; + +- meta = with lib; { ++ meta = { + description = "Visual MySQL database modeling, administration and querying tool"; + longDescription = '' + MySQL Workbench is a modeling tool that allows you to design +@@ -191,11 +200,10 @@ in stdenv.mkDerivation rec { + and query development modules where you can manage MySQL server instances + and execute SQL queries. + ''; +- + homepage = "http://wb.mysql.com/"; +- license = licenses.gpl2; +- maintainers = [ ]; +- platforms = platforms.linux; ++ license = lib.licenses.gpl2Only; + mainProgram = "mysql-workbench"; ++ maintainers = with lib.maintainers; [ tomasajt ]; ++ platforms = lib.platforms.linux; + }; +-} ++}) +diff --git a/pkgs/applications/misc/mysql-workbench/fix-xml2.patch b/pkgs/applications/misc/mysql-workbench/fix-xml2.patch +new file mode 100644 +index 00000000000000..857c3f9add4cae +--- /dev/null ++++ b/pkgs/applications/misc/mysql-workbench/fix-xml2.patch +@@ -0,0 +1,25 @@ ++diff --git a/library/grt/src/grt.h b/library/grt/src/grt.h ++index 47bfd63..59e664b 100644 ++--- a/library/grt/src/grt.h +++++ b/library/grt/src/grt.h ++@@ -35,6 +35,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include "base/threading.h" ++ #include ++ #include ++diff --git a/library/grt/src/unserializer.cpp b/library/grt/src/unserializer.cpp ++index 6dda76d..a6f6a3c 100644 ++--- a/library/grt/src/unserializer.cpp +++++ b/library/grt/src/unserializer.cpp ++@@ -401,7 +401,7 @@ ValueRef internal::Unserializer::unserialize_xmldata(const char *data, size_t si ++ xmlDocPtr doc = xmlReadMemory(data, (int)size, NULL, NULL, XML_PARSE_NOENT); ++ ++ if (!doc) { ++- xmlErrorPtr error = xmlGetLastError(); +++ const xmlError* error = xmlGetLastError(); ++ ++ if (error) ++ throw std::runtime_error(base::strfmt("Could not parse XML data. Line %d, %s", error->line, error->message)); From 42776e63962664f21a9726b7e6972dcf4a92c591 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Jan 2024 11:20:12 +0100 Subject: [PATCH 0358/1125] School/virtualbox: create folder and disable CoW --- roles/school/programs/virtualbox.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/school/programs/virtualbox.nix b/roles/school/programs/virtualbox.nix index 275079d..08f95b1 100644 --- a/roles/school/programs/virtualbox.nix +++ b/roles/school/programs/virtualbox.nix @@ -5,5 +5,11 @@ virtualisation.virtualbox.host = { enable = true; }; + home-manager.sharedModules = [{ + systemd.user.tmpfiles.rules = [ + "d '/%h/VirtualBox VMs'" + "h '/%h/VirtualBox VMs' - - - - C " + ]; + }]; users.users.toast.extraGroups = [ "vboxusers" ]; } From 7f86264983480cefcfb047381e7d87852b706f83 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Jan 2024 13:23:33 +0100 Subject: [PATCH 0359/1125] Kde/plasma: get rid of custom look and feel --- .../contents/defaults | 29 ------------------ .../layouts/org.kde.plasma.desktop-layout.js | 6 ---- .../org.kde.plasma.digitalclock.js | 3 -- .../org.kde.plasma.kickoff.js | 3 -- .../contents/previews/fullscreenpreview.jpg | Bin 153563 -> 0 bytes .../contents/previews/preview.png | Bin 146651 -> 0 bytes .../metadata.json | 19 ------------ roles/kde/plasma.nix | 15 +-------- 8 files changed, 1 insertion(+), 74 deletions(-) delete mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/defaults delete mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/layouts/org.kde.plasma.desktop-layout.js delete mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.digitalclock.js delete mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js delete mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/previews/fullscreenpreview.jpg delete mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/previews/preview.png delete mode 100644 roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/metadata.json diff --git a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/defaults b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/defaults deleted file mode 100644 index 764fa66..0000000 --- a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/defaults +++ /dev/null @@ -1,29 +0,0 @@ -[kdeglobals][KDE] -widgetStyle=Breeze - -[kdeglobals][General] -ColorScheme=BreezeDarkTint - -[kdeglobals][Icons] -Theme=breeze-dark - -[plasmarc][Theme] -name=default - -[Wallpaper] -Image=MilkyWay - -[kcminputrc][Mouse] -cursorTheme=breeze_cursors - -[kwinrc][WindowSwitcher] -LayoutName=org.kde.breeze.desktop - -[kwinrc][DesktopSwitcher] -LayoutName=org.kde.breeze.desktop - -[kwinrc][org.kde.kdecoration2] -library=org.kde.breeze - -[KSplash] -Theme=org.kde.Breeze diff --git a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/layouts/org.kde.plasma.desktop-layout.js b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/layouts/org.kde.plasma.desktop-layout.js deleted file mode 100644 index 09fdfac..0000000 --- a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/layouts/org.kde.plasma.desktop-layout.js +++ /dev/null @@ -1,6 +0,0 @@ -loadTemplate("org.kde.plasma.desktop.defaultPanel") - -var desktopsArray = desktopsForActivity(currentActivity()); -for( var j = 0; j < desktopsArray.length; j++) { - desktopsArray[j].wallpaperPlugin = 'org.kde.image'; -} diff --git a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.digitalclock.js b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.digitalclock.js deleted file mode 100644 index f2d9552..0000000 --- a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.digitalclock.js +++ /dev/null @@ -1,3 +0,0 @@ -applet.currentConfigGroup = ["Appearance"] -applet.writeConfig("showSeconds", "true") -applet.reloadConfig() diff --git a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js deleted file mode 100644 index 5d17cfc..0000000 --- a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/plasmoidsetupscripts/org.kde.plasma.kickoff.js +++ /dev/null @@ -1,3 +0,0 @@ -applet.currentConfigGroup = ["General"] -applet.writeConfig("icon", "nix-snowflake-white") -applet.reloadConfig() diff --git a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/previews/fullscreenpreview.jpg b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/contents/previews/fullscreenpreview.jpg deleted file mode 100644 index 44aba5dd5d3c49eeef997ede7b199469302c8a8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153563 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 z 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 N2hYW8=yCD?CII}Y!Laka{`Bp4tNnM>wd5DR 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

  • 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

    nqokZPZ*dZ}W1;-wfvIu{`Te zo#GCD&BL|LVn$p2q@zp4qhq6gZ&)34(tl5i<<$u)7O1#}Xwzac;IJY47$JtFH z$4*8aSi$pqvFN0ZXZMcZklxRj_Mquj`?p7>CeQwdd(3T!dR=y@-@o1yFp^*_&>gT?@zKTj~^4BDnmTu*;h&suvs#tn9D&6KmLtetf-s_XR zuHDN@pFH&%&m^^5R@oI39$9WOIzD~hqcg6xJZ*{MK6A5)9meej$WO9yPGFYO!V>bd2r_^cgJIi z$&)9~m^<5flEw-Z$3;SC&Yn$tKhM@w>+aP~ib+5HVw%y`2YD)6ZhD>l$-dfMb!x~a>zT7|<@>b16P)a-utMeFqf1Ez zXZ|Mb-`Vl@+xlSPUG<0mJE+Mm*pza?p`*2PK}nNs^|uF;_4l=Ki+_9k>`&13by5ap z(%s$Ol8;Nbt<;gxnlp3mS=Q%9M%LEP%iXT8zyIOb^O~y?d+xuLX+3vu^{w8}PYX`m zHJV}OIloxzy zv(AWN{gO%6f{H9zTRFPDPv7+``1XG8xv6J*Y9~)V#(m+exQJ1N-ptLxqRTXk|GdA+ zq}Z9W?y6(YowXc_7qiMge6RcZewNQS+dUp#dp@PizyJC8`|v~0xne>;DR@52xYMe6 zDDPP5bBO{@2`By@k?A5akn3antx#hey_-}DdOus-=9 zW-`k?Oa8a#mRYfeIG%G{FIA#&x>f4womRC^J}MltTMvg=My>Qw26ddO^{vlZN4%=q z!!5XI_nf=aZB9(Rw#DYdlb7OKZAH#zZu$9Jwa$Dl+eyb)4UuOjPYu}=eRBUvuAaq8 zhwAN2+7y-kL}fFJhwvQidH66Ou}AN`t(^VhZky;uwV(weKhKEXeI|Oy z>PO4A@W{R+TTfD9A!n}}^W@2sE525*SL}P7r1SXjiHP$K6K^H$yexZoYM>(9 zSL5dfZLha#i6`oxR4HDwWYTX9GyYBC<-Du(xIZVnjatFJv;yzwD70FFdwa2Jc7|5{uaR^}b=8N>6Myn=s36Eu+s< zrm!fg>c#He*BsO0`9^!;O2$cQ?C1Sg2?$!fHJf!-%*@=}e$vHR+B>&DI^-eQKKbAK zOAC@e_#Ioh*>cD0)bA{{N6$wH$%t-R?>{3f61AK5>)Px8{* zS)BMMs#>-_D}(2<%18fMuU|AY`mx(rJ&*nKMclqWdUJ8b-?Qe0Zx$}zQT5h};n;@{ z9C3f|Wv{rJb>qg3GdI#pStAr5PQF>aTRTzMR=DTu)PvCq2L+ZWdN^=7cr@N@E#33! z+U_5p^8a09VDQfVaKr9}@q8zfQwpNVyZ-ua$urqlm&~HV9wA{g`APrr7Uh-$zmBo} zn_vIM|3Z%0Uh%8`dP~+ksq+qGdU{WM!Skxx-x!A1tn!gqHn=UCStv^rs+7r&3`z?!FeZD|WXR_FZ^ zICNyQP?G}7ng2)r8FM-`D0bNH)?>ZUmt6Dx>i3VoqQeXRHOnV_JN49&VH%Uay!&ha zfBp-k8n0b9_-Xyzpz4RztZpgK<<;K|IFou;Zxvv2c6PQ?Ph5TV(@xgA@8y?$Ipuod z%#PaMW*!{*I^mwG<^B>p!c+1tSUk|ikTL!*TMi!tl-Rs#D*@>~h}5v1DG0Q09Zj1+wSQH%lJVn%uYM_g;}E z1y#jKESjyXQP)1)Wzzi~$Ia-Wc_F9#!|naw)$Z*t5ngRvJY#PKpH?S(PxDj*De2rf zGdmg{vZc-Y5#8~T|HFyk{~XWj-zIMGN|#z|`pw_>;bZw~#_ZRxBVu9>-Q1k6(0XL* z>hO=>tluY)YOGjU_Q@XlxVwHG}771_QmjE8|qfmgiqp6#Y2{l#8dD^mg@qoSPl z#vR^!WplaJT%Vs#QVmZ{!kxMfytsSDI8bHd&78+yuiroZI)6{EeC_{Io%45_!nm9` zPIx$}H@9V8aHyVZXm`j$z))|!!8d=SsJBhUog21oYYSfPmjF6zYyJHLe-1HSyRPow zGGm6s@ul9=3m+XR%*oANd^P9p+_+n<0)lzx&nKsqeRB>E4f`Z0nl?Xa;e?eZB^s9N z9X_ga?Ocj`qQpC`jGMKIJuyevUYYrF|9xO&lrL?uR<+XPFd~nB7UU%ChuXp=*T$NUk=2;(e<8ySM zn&#<+C*SC_GF3N!Sa&F;dizC|s^-ns1qy@IP?+w;<49gd4uZ_PqyGr0d zDo^4`?fkv%i;AV+>}qgiIu@c75)~xXdh54s*kvEpa&NBVk80N+wVf`z_Uuegy+3jP z9;NFgKKS$Xb;XY}i*MK)y>T{k3375_lD?gLXIF{z|99T^5AC+EVm^CTRAcIlJ!i^_ z7BzUi=ikuMkg;yTw|~B%G$l5e#TF;4f5xw)Ze()xhPv^hjE$9&1dg!e&rVZw{3Bd zx1P_&^M22pYwDLA-yC;AgilL;>fBnvC&_GHnhw*JI_Vxd8@>JG*YJJa=WAa*wy1rh z;=y%BZ+$}P;!gQ}wSxEm{|(=0P|X{qJwd>Xvn0w?Xj|0v|llvE?+}PxJ zG;`MZ#3&QPqENY`OR)X1sixRk!ONm~<$2!HFh4&TVb4wyt24^qeqZ#q}(Sxe`Z@9MrV= zeI#>+|ej3L@HmfK4`0QJaL zZ)o&!^2k{0<>$4SQ+UG1rqY=YLL+Nd$SzWm51m)C?9acWEyk7qPhMHgXlebGYZAw@ zz$KTnx82bb)8;p5VpWf+F!|D#l$k2Fwkh6oL+Z4q&Y0-+PHPz#9yE|^PgCR<%h|r_ zNmvH+28~?%>AL<84>`Av;3&irYUy-$i5sNZT*Vz{8iedyH7IbUkMocRPgmUQl)@$&V7)z_MI z9Ff-e1xj?dC(l~)I01OCoh_CNk#LlZ$zASW6Acp&(0NPbv$xdW}UjQNlUUi zuY1QGrckzRT@C?JVW(WDHnXy`eOk(H=G(V#lW@!~cK%lrlxH~!vb?aHpjn-L>in92 zc6~<`lpHn%id(e>a%`R}mU4m9c!rGm#MDJbJrNt6%euGhbk9rt_*il8u_N!enHz3o zT=}*;`u|dPcFlkfe@{rI%{<4nag*Vc<7Rtz@NDPU^}6evkv;#Rl9rwn&M#k*%{r#5 z+_`_D*@jhn;VjKRGhGdL>oCrba`k8n+Z&m|_0MSLfoboisTJ-tla`uzw)c6Evmx`w zpb3{M)=7qQU%$8IP~X)eoh@b;v@O~luE_SE{}LIu>9be(9lvddm!(Yj@%!71jysn7 z>Nnk;FDcY?>2b=%{oE@bxNW}HqjIrep{SDLnLAnB>fCEYjBiEz=H%uj7AA7eEn}K` zgdyR~%$TP!OO2d+jlW*;1kH~=IVie2STD$b^4*iWSm(C9nYG@_{OoSmh=P0Fc{fw` zM}O@u-{HXCy_h|yM|Opb!33?zCnSDnpKIJ|XD(PaQBc8PNoeca2Fs5O{SN2&xcOcM zdi~jP{8^a4*@4!G8?Cb(!%Sy3sU1&Rnrm`=*TEc%m$UV@KbVtKkn(8FTn=di(E~h} z`KLV9mtdHD;!c0UI@kVmiL`*nhm3bS7VnrL=Ec9@>H5oJEMkm0W`8H9nl!gYKY4v* z+kB@6!EZfpZOeL;jQE|rHvf1fb7B$0l;`iJB`&$Sm}B*VtGBMi?#||Pa$`92%v+Ub z>D0O0civxW;%O^bGcEbejV+C*0*Fy~}`4@g! z`24u@w=Fs61ylPi%lfAJJ#TK{4PLX*qVY=4ia6tWO=1&DqhxdPb7t*`=!;ZY!hH0< z@9IZp@;~<+ty*9aG1INMD`Vwv)s>)@^rjmpn_3t=Gea5~vxFMYI!+fT4QBp##V-0p zTxim(Bu71a2#BBS@+Bq*5hn0tiQteeQp|s9x^QaH?ehoalc-?WI#dR&U&}s?vcy5=Y;-A z{j_eU+(w4G`hQqYY<+PuXoJPGPM+;$Pf`VXgWh$$JN{Zq?N@Fi&Mr z@61iv)*|qvk)tCeYt7r&4q|T4m4kV@V^!FrXRB)W>S=-Bdq|ip-#IEUy0;>eLr`CwHJhb9us0%;y?eja8)u&GWn-XOG)3~GORJUY+?H2(hb^*?7dR#B~w-{Yn@HVmE z?NV~wL!~!GOAgO(K051c($rg9HXTotY`OB-^VxAHv4|y4EheaHZhcxPp>(HlxAt43 z$&Bnjmn5G1r?N&qHUG8!^xm61eK#9ttn;}!{f)k4obrnKwdX89s|jt&-eF)NEIeKI zMbXmImG4e&KfZE>ONv;9UZ8keciq0+z4r>zzF8KrSDtrXc68+|*~`we7PK}@C^Jr% zEG+vLn-h9s-b}B9JQI(%CHRGwtt%8UInuD2VU4)Srk=BB_+{s6oPU$G{NGnU#&3JM z4r~jToFuE8=AhIm`pBS=H#bk`}!(gthVC5b^Eu&H+9F%Ir>}&9NO-DsMln5Z)s38QL_Vfi0c~`~RL{dZ%}S z$(n5suc-Gnh1C^0JFQaQ%&W3>-(NO$-ld}~mc`6Xk;^sjXbMUmu6g~?>(UL)o!_`v z-bZs7Y4S#`DgEB?b^V&H^3L}bs!V>rYLD(Rj$rY*Dg}{qtFLa@x2^4CXJN)!&~VVf zX7&wRw)A}5Xn00nXF=Th$Nm4_oPY3YYxa+O+4cuMCi6eMtiQjd{`c+pL-PNZ#vcgZ z_scrtiu4NeS2O0!IRcV*&)?fSbLUQ>{PrS6r8yRLGMkHwGsGE=dTCWYIC7>w;o|(A zXLEMEW9wY=Cp>Hdb&DsdN$9VSUZuw^=^=D!RgdJH6vt`b-Yz}l9%py%rfI6e$8E)VYd9w| zr62#rk`S-XwMKH0SYwKa#QEjyq6YtnQzbk-_nP@Bg}~ z-5Vyc`>gn|Ij~-Gad_jSx#i2I*oZaE?Rj^qPO1A|N0&H@)2eA&+%^wg0`k10Io7eQ z-?za`Y1Y|w`>&TSTxIaTJKUD#^v?X+Ws~22{IHYd3^!-P-mVK0&u7P$G6byAOTA#0 zcFf^qg~#t6n`X6^r!SoXg!#nOvWt@$7H)hkWY_F4%k7BHI=efpJJm#H?nvLillAOT z1@4>k?bdGVaeXBjUZwW>i`2G;i>(d{m+KS5SP~mWHb**pN=yyOntpk4nCpJ_hs+U1 z7J>Wb2kV9zPI<+;;a49&zt*P3w>B>2v#_4++5TF#A&o(+Ptml&&9=jQdS880;s&0B z!5?@oDJK5YEpqz6aJICYdCSZAG&Y%pPqXC?O!np3a4kTq%}XSq_utHx>nC<^YnI(C z^`i6Sf9C&blbORDxlgQ6@;*3q@9~DX7M7+%5laf6J)XS7G5+Yh%f}0UJt>UYTf_S^ zcbWiGcel4i=_!Wkv(57>Zxv@(OBZj?U%V}*`I?kFpZqp6)dQa{afwZzX0W&3UN3G} zi+EfGpLyQBBcD!jor~Yma9pllM1IchhRx~c7lf@&&a7nhob%w@9~&|8=@&A1zUF)R zwFvAe`zw`}_Iy=L%hZ|-At|BvEMFxy9J;5xLL;}2zhTC2P5FN>{EjrTF8}sk)kV+D zcVq3e&PvuPjN0+%__F;CCfBde`0&nVib3SdTHorKJacC-MlybOk!jFLn~?0mp}=?U zYnq_rOKX<{e;LBERx(#KWH1U(K5?V{cOE|*C-a3RYlB-Ymu(H4=hnxWI71>~-McW> zsB2v&ae+~~yl+3o{=b&~_6wJIx%$re9w$T+e$Ebj#>91ilVieG4yVoh!9mB4m)#DU zsOqw2Qm;ga@U_#v)zJ&)>AwASx8d`>>5|pHdK~*7H1cd@KfCg9tF=9=Sd@0aBnc+v z%g-|#_r4O^6p_k5ZQ)tH6IP#69&W2OXGuNv!MR;h>zzc{sYQC}-mFG_>bDlVR}@US zW~p;wFN@OJ4GEL;rzD)#&0blZpKJfE`^h><3HgZ?->z7E^Lx`OV9Lz`KeP} zlT;4=`y1TxSmJFNd*K~N6=e?1HM!xuy>7CzXV1Q|Ih}vjS+Pkfj0rO~&poxkEFx6p zyVtvII>))9Jfu(7wimcF{0u#O=5ph8o=Y#D)ZP7lY(@EP?i)MOrayJl*{8JHOy!0` zU87+2M2QVsKJQx1kkK|T&vnu1JF|6-V_hgygCaN2o-MpR8cSP(ZoSW$JF)8DoeK?fJB+UX zkgd3p;QjuoEyw$%yrHZcw07PuN@wV1n9}dc9Cn7!W^=)hqeTG?M^)z+e;0n*xtx7x zbK15tt-s>e-gU(Pb-gW{leX^#<0c8$Ybs9ZJEdB2Hmiuqo@q6CZrpt~; z{)}Q>u>1m_&RTivXKTadcdup=t(qQMQ;=6?BfO-?A@Isqp~92Xb+&C}2zc4^(EfMh z{n(5jQ)aB0San=trFiI#qc4T0ozYy`5gu55d-axy|N4W)g}-jE74^B`*|T)DIJPvGv}DS|1?zTRtnte2uev@zNFY%_KZ4n*?fT9Q&vS0B zxv={}nOgRGuCK4eb{xGp=XuYgYF^R&g18+E&#q$oykE35=oVLFjgC$}zqp++`#PI~ z*80BI^3n(1v$BP!KDlQaZxCbeaA1=WTkoW8i`y>6y{>xE>a+CwXO~}o-|OGK{9#lo zv~O?U6_3QYTSdW^nk^f52b~h&cgR{3RxsJ1xq*{o&B1fk{Y}NCH;xtD<^RjM4xJ7cCC{P?Bh_VP9CJeMcztz^y8TKU9r zLQ`#AW64FfvUy(OJFF`gcb>>!aq3~*c_y3YMN^}%obtZeyL5?OsI272*V)(iN>r)u zb-vah#Zy+kRqJ*RYgbPCC9fyfpHBGs@wMD@xs{tu3l|(`-h1%X`GRu{hx9-3IAnAG zu+b=LR@?oUzu$VcoVnBHA4*$qUs7E;XAZ}VKfPA&PbCkhG%mWBR%OqADrm{;o7(Z_ z2g9^ed8hL}@;WVi=-7hd>)$0B*DZ8v*z#^2`-6iW@2&gqpQ(NlsnfDQ{r5?R7Lf;S zAJ`Q#xa)p<*3Geu4p`2WTK28rq1)MS2DdkeyR_|1y-_zwVB#Al+jm>9Mcuv zuXbp)?Paft@~`dAiDau3vTOO-?D%xpzl}GnAs}-z2evN$at8>Hd8+W}dX8!)QG16hDL+du_-P+E_3aa+c zIoW96-*t1%rVG4FABh$537!76;?lo{`<>!3F*{b4wSQ9aUJ+=>pvj_S{Zc=Bx4W3h zZPxR`JX7=z{NpmJn9Y2%O_owvg4+d@H&74CTr#+P=~Yk3N6zdi4(lC=8e!#^&mi5rHf?*F-c z?%(Zq?p=}54!O8&k#5HthA`Ese`7Oe?wac{8{EBKe)|H4 zz?4+ambnJqIkQgPiczud?S0-b?ey~P$qlKkIY~FJXs>>;4r;pfz6 z{>zko->9=cY6+ISb-6b->|Dkyp3MhteU|>vy;8TmIXW|1A+lj*?U!>~Jox^dy%HgD zmB;w&TXX(9Mr%#qgofLHG08E1UNBufC-L&^GrB%?!0-fvwW75mZawjpQ7&t zJKIxpx)yFeCs8=PTVA#G`Rxb08t+E737vW)a>=Y9%!c^A_5h??&^Bd7OzB<7G2FIU^Hb;4JkuGzHtwfChzEWU|;lG%?BmWeo$HvtO zQ&PPy?Ppm%ZL6YA$Um8)to?Sf6O*@`V4IL~e9yOzofB)dIn*pXzW$`&2 zKfST8;Lj#@=q+5%>n)%FKphh5wE$4*4R*9CBi`TW~ zjjCJDYW04axBcS_^?UPHzG%Cfb2s69#~)+!Mp0dZ)OUNmShjz7tue8)u7Apd0vWD@ zf86fHsrfFNebJh;>4M+iIjM8bOn9TU(dd|Zd2TuyHbHe>}I;$6!lgHNAb424-Ro$ z2R6o98oaW%Oc1`IAQ-@P?~<%vfc&dhO&iP(8gJS?=|RVWH?t4F2`*mtH|c7}y7e=C zXE2K%pT~K6yY8EAy#rGZi~qA@J-O%fy|oA9=E|*d%1$=hAg(Cr*nGiL0@x_Gg2hFP?k;+79v64r(tzVN}|+V$&a6-1b#Rw{%v?@`{}ch}?SxzJCE9Si2o z{t)ZA>-RfL?O(xVOq-6#8ir5d42rDc=Xz6e!|l14UMc6-BkBuh+*I3dG}GQ_!`8y* zOD1RfRVIr!T{&ydYP9#QUDwj*FPHMZt`%OCGwIP32Zj6Vg2GNWYwuRz+HP=b-|`UY z$A^F}XV30luRXIAcWVp#LL z#Y6MQ+WXo5dUaFy60-CIrfuga|0L-MFUN+GNeRgr@@C8U7T)dr_~fFd%)NcB>;JsFzAJ8l zisy%$=WC>@zrQ=Gy?#&E%D=%cN|NT(JrN06v|-aOP}f(+u7qRmj^?RTLqQ9{#Kgo5 z?eabeu3Mjf$Na$OAIbfXo~@P4$;%5i%~8JH#3^alAY-ITnO zJ=kaB#?AkAH*C~mij-Vj!7k;y(C${vJ&oDSB9jra~m_5HPEIrcLFkzalXe7U1JL8S5_bUT$)s?p0 zICfh9M3=#XYOg8B{7POuy0GIebE8~Vji;K~5_>h5XXVWeK@W@q_FlMczO0N1#Am|*;?^nY&ZrfHDe}K>U@r8xX32gWNKWNqx zPgIqk^`rFYKiQDo$?G>+KbyP9STp#dx%mTGgK!t?&n8O}t_nU0;koq0llkzDNJ+E1 z5A`N;zn;*~@@~%~melDD2mWhBv;WRt_0x!_vtV~sneg`mXLq#+rG1)X-93k0^}&HK zxtP+83L<*0uB#+|cNgscZ7Q;%XDJ6m?@86^({j5wB9vzb%xv0c?(g9s(A*mPL)jsd zS2$}`^+nU`n?lpQPh=SU4?bt2z#3lZ@bY)s0Y(S2Njv0y`PS^J{87JqQPvH37(`}~T_t3}tT9mV@+MK2$g%g#{yEbq~IkQ(vI8hrHezxr8?4ncx+_J*PE0cpIm4hmch$cf z9nEJ=RbP#lZ9ae1^+DQ!BW{}&ytsrPdrojrVaal4St_|P=-3Cl;BxD-8Z&XNNXyTU z@AtJeh<;pEvgk_mImWOL4mo0+rz&n4E|npCugtXY!&UvF zD<1k6#ZqQ|I=w)SIlxP@Ahmy`%EyIf91I(IH%{n3B)1`)FXLz6;{(?llr+B9s7i=! zxgWCaw{P$^V_RcOk5w{?ELoE_?A+MslIgOQ!^wl$t4PZ!?bwG828%Qf-MS_9?cLpO zzvYi@m6bFvcKY5^SZm5BZ`b0#|BukUs@J)9c2o-Iia&p3=Nb5Go>HN8pH`@!YPolq zFsm-R|J3A@?3;f~n62ZL@!L-5*1;V$S+38YY}R`7fN$r{gZ`EpW<`Fg7hfdJJ``m0 z;o+O9Zc9^c^!>T|lFhPQhOa>KV!=wkOIEwHmuTE?`I@|y=YZ6i<^pvkjZX*o9UdBJ zwTT`rEnLtzAvQmeklbC7)?K zx+qWoPEdQBoP+mk84I0TK80qp_HkRj+8?RrpUs-Or^Nu`HY%&eN; zu%|@o2G%IGv2x&wcKd( z#|4j`_32ogUN0<{ar1GIRG9MaKezq){v0@3UR2nz$-pPG*X6aIXvbz_sV(+C^+oR_ zX0Lcy9?CIs#oI%Hhti^S=43lRkiGG@C4ocjZ9jLTBGY-p$B`NiMy%`d)?N2f7Uqn# zU~^y25-fM+piO$Z_49e#Kf8TZRBlPs-g@bt#+(x>YGpjjJcD%hob4ADF6U~SDzxw8 zHlEdLJiAxTug==g&|a3!ce~X!^^nsSA#SlLsWmNA?kcRlek+7wi^cJMT}rxsdtq(vy8FShQC@IUZHCyDpKp;r*14Z;kfe zTo|>%=i}zhA;xVFH@fr(x>rnaja6uRld`JSbGOp&XEPf%Ex+=s>Ez6o;AcJz$7bBf z?d5j3w!n$SW2W8gx>+0FRf%s9kKNk3-Bc*7*6N3BP~E!Ud~dE+^BveVuSAhe;*Bl0 zZYP(x)_gDvzi{f zVw=&!vrV7NKkc*bn>-jB)$K1XoXxpdu2w;5r~QgGp{i4D1cDAlZ2W!lz0mt7VtOC$zk3`by8rm!X#(e( zB-7Pd*&-HeSFW)?tCM7!D1Q9VHg*N>my2Rq*4=r3Phd_gOa5kycV`+EqUCIwr(Hb$ zq$)N2srBQ$vs?|Fssgm8u05r@S#Gy$&zkUgyuAk!Hf;Ku$kcLrqIf~4&oj#| z6Zd)Sxtc8Al5P=Og9F0Ps@-Wk(Q?CK`mUZtPX;dK^X&VzbNB39Voeej7QS6 zhGEL4xe+$^IA;E;yeiSEdv@FP?aJ|C?^4SewS5Ki1jE}(xfp!jpA9?tY~g_wd*^Qm zV~dHjUOn$Q+bXN`GSeA!U)~Bka4hxU%Ea?QrFC3;WLI!EMpw*bKR4%Z_4bzBT?!8v z86&2K1bH?-kyt%%dDPVSN``}V*Jn$=V~Yula+p44bHp9fi{+Ud33qmMJ4{mu-lp*K zoKCAor8SRR<)sYAhN9ik=XPCP9$akbp&@F&_`d9Crm}5v-~QcFdn)Sm%pvCc)L4y0 z4zZJaugnv5WYJ)*^)a}VbKXi+Ot8@;vW$~q=O>9EuJ!kl#WQ&NCKjLZE4SYAtmpWm z%{wPCe&Z0FsPM^;L$Y+jwF@bc(rbeQWWO}NmghTl+Ji4;BFBy0PE*4(u20w3w+P#G zEB(sW0*1p)YcwK`Rd0;=SC;vd-SqUuu+SB{)yt+x-H18XSSoMT`o{V(;~H-L$xTY> zo9FgVej2gv-ea57^HOERK0SYW<>(v#TdFUek7)*!S}~NdY^D$?qQRS`-9i_Z41lpA6{Nk=o)>@DN~ryTIX=3{xXMSjZGIEW`8a&`1wTs z#-}N(rm=~H*GZl{k)SbGB253f{?Z4h^k${0EU@rbX>V{ZzkQhVTUKa&PlA)Mg&DgC zbC{8GSC(AJL>1}yGm>k(=vEqLPHng}=Equ)F?>~9xp()fP8`ta_3FPWRR_&I0) zxDj$|%JLANrBf5Nx(*z!;I72{B17R z)6dO48MS!prbmJGB9|5h6qdi#YOMO$?IBmsqhtMGSJOJ}f+ZhL78{1`|0;VYM_=R} zTe+?ilhUhI|C$xP8@ITq$_sLe_008PY@Dh+jZ3`r)EWIe{tjmk;RBLxEh=|@^dFo93UBe0Q9R4^h zEcQ8dj;m}bPmuiCQ%~+K77-}3b>v=U^k5Um&cY3id^xoZZ2*!%mBmi?WT{->u86KJ^L|OFjM1=X$$g?aQ9@H@f9-`fjtHG6`AEd^PXzUm;#z zUdDtAA0&P}DZbmP!TR;f>44>ajj8Ng*&GfZI2bMcqvgee@AK|AyKS0t@_nhhlTgGC zrdj)iDgzW+s&%vt1AJrzxG;6r;i+qo-58Wxm1F*(c9z z6whPi*7)IcHDQ$-SGRYkQ1ao$%-0%B*W~&J`1K!ko3P=VH_uV7LsCB8tBcM&z84hg zY`?JJ97ozyM)i{Y)9*9#U7xdRzfJYgl^5+2a<+AFwAph;`miLoZStAGs+hNrf2N49 znn+{#@{+_|7u1g3Dtu`ZVQelQlwxzrhi6U6l?=1W>|AewV_z>t-JZa)Zehy&jUQd6 z)Wtl_3}(}2Q<-|q<}?F`+p<1a1#SJr8*S?Xma+NiV*Dj<8HKed&!~?s36e4jR{bGP12OzqY9enYcYF>Rlf zI|FmELYH{-aixQA)wg`x`FD%o=a4oAS1-n?E2bPgQ`(cPG>3P3@?0gwi5ohP#xHrN z!=*R3$x!09a@for0q6E!Li~ok_PalqZMe3hI(kB?(402=<=?M( zDdw3iOj^9rD>*XgL;kiGpKkNzO=kU}^)BZYw|PVDj5YISD>T3OyL-XH*lj-9+s!q) zkIvlxGVaJ(SIxyzmh1WB_H_P;|5sZ6jKO?o_#ro2jg)eUzx;t(4WTFRPP0~O-%!2l zZs&$~v96ydmf!m<9knUp^hJ-Osm~fiqZV);U>Ccvq?U0KhtZ^OQ@+e<(Tx2v;gN{a z>%b|e7l((`FMs;-s{37^hDd``L4SD8C4FTIPh>sRX&aq)Z`tbWxp)1U_$;I@_8EF+ zr#fbz;v`)C+^%9&63*?5ak~%{w;Z; z!@tOx*(M^(&&ka+n%I=LEk`W-?%neS4}5PMW?%ZS#3!`CSit4kuS*{j{Vy^qoUG7h zyUwLqvww;gqvO+c>1pp}U-oG)^_eZydZcQ{)T@;OyWJSJy)V<+Yg_lbOSz%!uuA*4 zrDX;g5x<>Qo9X2T{A>U7JwSH;HQl8h9t~N}*6Y96PC9jMGPb#*RWag@F^xo_V}~f&i78-p7W}K?@y;oo7W}P!g(bZ${oXJ zW?Rf}JJICLed*B0se;vhj}~p^_C6d`z9~yfLOD_RfK(K-SLOdG1Vnh@IIODz3JU1VhYJ5W} z<_4S66sPq|zHCkp^V-5}$H&jqaJBpBE#4icV$O$&ik{2dRbZ=Tao&pIVAI6@D{-&F z7w{IlthBp2CtjF=WlLCsMO*uuLt;l1Hf2Sw4;68Hm=u!JcCfpt{qc=0Q=Yc?TQ5$W zWbu5yY9yQI%>X8=GwvCTLMCfu1)DW}XSx_XR(a}OT+tEy{Xc_S`oXk=i(VbGWDl3% zc{)RLs+~Sl2lKb>E_eL(WSY_!Ni^`vD4j?%*>K<*zel`2udK9!Xj@3Z>m}>s{n<4C zE`QjJxcBgJt>yEkx>l~Lb8^w-RZ{3uI#QS;w)VHdz0TlAN#EyG&aeKG>2Be+ zdEJ?^#*JH?XYTKeJfhQma86+3le{Zmr!I6TIOw$dwC?St={@H&%kMrH3tPMOqlxf2 zgByQl{mf>Jl-jhg<7g58=W{KVIla;{kqbZcTv%np5cY0;e^4Bg+|A<^uYO%+nrCu{ zy?O7)J*zntHSR4C6IhxjqXP-0$sV5tX(rgQo|O)ut@Z-L7UZ?O55D(J>< zOJ?ppz9x-#>6XmxU)#POI2G&oZvETlGk=?o%e`5&VnP1h@4MHA?z)_rpK$(AT$-(y z;>{ZkeZmS%5vmz_`ce~2ZSFju%6H#Ic};28tBK4Jo|7KD3HE>Zr1LRDL)zxf6=IHD zo$LR-yKYm^F_~qn#;3`QfmVUV3%2uJTw<(KGXJpWUWrmMZsWyas~;{Ew{NXl+je%X zu1)PX%{?EF@o(I+hewe`$h-ZNf?`@mzQfK>?~Wy{nsR93;r4}F4!yaPYxDok=89h{ zjen&7e-uB<>ZYd?Ti%wR`x9-uPsz*49a?Vp)6+z%^vrqvNA3B0r`k=nFw>f@vB@OW zEUc^3c(Po1-dop2TaQilw`o+DtLK^P$Nv1>{NqQxrzUTU~m&MXc-AwNzr`^5!ewkV7 zXZ72q`%ah~meku_{X0Z_C#U6+iL(y3x;Ps~^Y438VX{zU(^Mq}%i_5XUoYohN|TN@ zV2?TRUs#UAtK{zly||m{bzR69< zc#78oVPVg^cjJo#vt^-&1GK8gmzu)`itIiw7j)kU^*80BillGCi zAQfd8vZ?pnH8r>8{0lag+Y~UJxU+M^w>7=VoRKc`cTSpVXtqr}fA3#DGc$8TOUusd z`~EXOzLg~|smNmY?+`b`nLhijCG57!hYweL44!}B-%3pm#emgU1J+-6bg?K%kovuR znZdSl{Y4s|_;<+Dr=&4p7A z-84@Ba8$pB@4Ve-6TkU&N0^xvSzc|`_*`W6>g&GmZ`99#w%Pu9r2ogz=l%R+^M79c zugd51{`j4@mHZm>YoBHA`Ecm-k0ZzJ+b&KNj1OnGTQcQeaom<`79}4PmVNVmXkGsy zw&t(&{X-u<2+XtktTIW(QN*+6BlrB{%k6%0a&TvCxwhhJmV~tQ;VW0B=-&V0y!hgQ zi;LU2e_MMB*?c_mIK$+X#9d>qwWiCKFE4!bqfo`O>EXk~ns=M$AAHzfZM}_v)(%Q8KTnD3=&ygYRNVfhZLOSb?X7E}6W~ z0uotRW=46nH2t4@wVsQQy~?6ih5v`ooRYaatM|X&Ez!<+u6$ddm!<}rkXc!N*IAp_ z|H@~pE}b+ldC%{a&u&{BFcq7_%yGc2QhH8>PuhRew!592hZ7sS7#LO7oHAgYoB4ls z`pTP2nhhtuV15ue=~c%~qlIE$3>G^C%UoLb@L|bhtrmxn)i*2K1j?;mY?+;ro1au% z%RGCwbjJ25wvuON`nE^sUN~CxbhT2=#&>gfUN8Q9S7R>MrRJYiuZxVEuU!(_7CudI z^|sD1dG&xo=_u_LD#xC^wan2yr~GnD(fNJHqfg!ndh;y1?Vu3&SkjtDkM$F>v$?OY zi$5-I_dRmWnsqb9dnMKT<&KKm{g2Ga%X@HUruxRcTYFtJ-$=?Hz4goL*td6#oQ==t zRf~!1#T_~FgN0Als$=C!&zKzroKc!SK7I@CzDsyN&sM=PA};FKm&VMR$I|x?J-Zg> zZ>G?tBx7OFd%f<1)xXLAU)Uef|NH3tR=8o0T;7yh`Q zIA?zar~dvgN*x?ut7MBe7gzjv7#t9#*eSeb-P*_1>-Uzq^RxtUx%bN)-1_>upsP^$ z`nbd2>pxhDiBC^>)Wg_sS0yDs$GZPyCuhy8$@33<`C_6Mv!|ooe=cazBIr!z9m0>T z@7J=ve*OAp?6RPWPiKTBWF-&2|MSj#L21*>n~^qUzf9`BoU_g_k*av}B{L^4cj3Ji zk8fOT->_jv!@`A$pvjPm3W?|E<{rMe**~$km^;YJrskE%zn|;>TbY@e6}RnaY44Le zxV`@U_ltSkH*Ve9`}J!n_z5 zi^@k9aX;^6S3LT7Tw&>vr>DaUJ{)lL@##_a6RLT6I{syl@O|HxQODn|yJ5`6xO>{B z?q^5-tTR!*CT!iJo6J9_DpQ~!MJ{<;y3fv)zfSF#^gUsdPQs0=HqRo2(l0-` z{UoCP8+T6_SBDDMT}he0!Xh*CwI^Iv6X|0&Gh8hr93PeI$Lv;eeCwvCDxI9$4}4(z zF1KU%i>)cI7xvz|{?+kET#BUI_aixWuGtQ`8@2^T8n2&JoxYW8clqv#y9pa>9Al4j9T1gNn7Jh?W9`~o zXMI=%ek-hQs1Ca|XR(M>a<$@X-U&Sp0{46xYn1YXg|4c&tYs73&hSJ+XRYb6`$(h~<-;aqOkLoa5q)2R^;h>XWr^^HV=| z=k4u^7cVASrv-L!6bdC*RJb6dWPc1h$x56(c1lRNZy_bFe_~rEZhn_rP@tb48 zmv-#SmpUIGp9WLqNrFO44eac$U1fJ^IeS)j&+m7?Gq%p^cr4-GFJ~w`-;969&8(#A zYU$&Ba;_qtYu2q(>{5|(=GD>Hf4K3u+|kCDnLfU65A)am5KBu-zmT<+`)XOC`mrZR zSnmD0czZ{|MFx`R`}t9ql|qWkFc=tjG1#? zci&}Wl#rEm3|SrNu(c^_ZQJvCwQRrD)C#_wNL;gSUDC5_Jm22Vmbu~ZE00TX;mw@H zq9Ug4dFL8t`p#X<;hDq}D*aUobVQ%KzkQRR`mx2!{gbQy*D)M8t-qgz?eT|&%`ZxB zSyVh=;FFngtdaRL^UdRLkDat!vs>U$wf|Ssqf4&b_O>WHS(OoJ(3q}zylX@1CKI2a z7mVp{iSG|DQ?fmux}kJp`O2V6OYM#pvs#BOS<{yGmbv5Gq$ZK7r(aL4Xlt^+v-rK! zvK0^NBLqU(tR;`_iQH}c>H72e{u~h$JB5c zD%?1h*=5}^S)x!#*;7cxGbzGEdZ+!H!%1N#p`UmC42cZ8RXj;dK$43q%r(|0Qz|rh zTOo^CqiylaM<)WJ>UhL%=1TtFRAQT*mzR`XE4%h>uF71$tl(?>7E_u2Jec#T+qh?; zvFuLyN#UXQ3M<#~MmZlh3|XGL=xz0~X>ap6t)ioEM9p9?NoojGcM~e-IdJNzM)KMV zH*dLQr-~M??zG5TeEF73bv5(cx4v7pn_awl%i+$QHm{@xj;#wrwB6F@RW>pja~><~ z@!$VPDD3*Rj~6Z;mXMb|o^AibZeH~_OHiT1DERQg!R8%hf34yXf zbjgUAm>B33j+HAldwSm<{q%{;&8=;s%BlXyr6O)^?S&5?E!{VHqw$qDqU^6f&;QM{ zZTsvQb7mY6_P6QNum4*9;UN2S0aroLY6OM@uWm_A@hW)nKrv=#mFV$4+m^J=o&Nj3 z2;Hmr>^o-oozj(Wc+v6?Y|zWe5@pH>~{{8+fUD?6d6h>4rK z+oIwFL)!Da`g9hoO#+USe*puJMhn*FgI)rpMO^zTf+wF>5Qw za)0}#{Mz65lZ%VFtH1X=`gmOa@Si_Sx8|B{xi-P+(T9i55m9k&i|-w{^Y-?Nt63JG zp9t?L&1UQN?ymT=@p!?*N3K5p{>jC~!dq9g`Q6!A=5J_bX1@Ety}tr!50>xyVX33P zKB2Z&w%_iThF<)>rsC)4n>#){5%y0gDPb`--aKQ*oCCLBNiAFU?cudEJZkD{1=(qA z?)@^2L0oUk*j0RPP5s%*T4FVKUT#z%myYs!Aqkg`gdC<7vjq$8`8?d{cx(L@!#7)( zSu_McJ?K(u-cv5sApC;sU2KJYvdG*fcE=DNt+%$EQ=&V3;-#e5=H-NaJD2t4eE+Oa z-k^mGYuEptz$+|ZmNY@{`I*>ieZ8N*r%86EzYdktVm|oyQgwR&li+!h6E4_3mn_ix zJC*H!Vd9^aXa3%G%8=Y#lPkP-!k2*8DX$(xI(-gzcrxQLgOBIqjZu?@@@jrp-SD4v zQtI#WQlm4wPkTzVOlbI;biUL#zjPv6)aJ9gZ_et!cqJ0B>*Hg@xPJI=lehQe^KcH@~jJ2i%-rb?OrK#-FvSCClsY0aeuX4}No{pU4=NljlL z+Hj85hcAH91^>r6DU#-?(C&zDJ!?k$v;u&-29({ZJ z^UUYRdVJ=Z8ZQyJ7kFU#{13_EOZiw9uF+uCRZR(T&cB>EV|wV0r%G$f_uc-~$Nu!K z*_+L`H*gtMKJ5Cn?2M&iOvfE{=2aJto^JUT#cW)zs4Yn%J$XB%uKs@#ws?4^D5g~5AbP(ofn;Vvv%*tSHiK6k9D4S`seiRqp9aaFG(|O zmJBF3_V`%>R{~e=kr|3>6|E8uIIZb=?8mFLB=+{4D#@GsRE4Kp*|_beUBIk`Av4Y$ zUn9Qt#L`D6o7~slYzw~>wm2hXrB>jvi>Ed>He6r(T-d4l+X@wtcJ`cS`63JnZWDx7 zrnnefFt^xwzo%krV!`8T4ari?sy&yPeZ>2gX63JIoZQF%|6oqiOx3sB5?2`M%R2{D z#a+@oarDir^y53{^Pe=Br=rp_WkT8AG^5w~)ybDjQaLs-r0m)6WDvsQbcpp&p8ll0 z3}O>_l@IW^T-?j6Y{1dXdZ5bS){)KD8xCuF-Jc+yyd(3LY}3VR#qXcv_?zB*+j+Nh zjSAPDkKe2xE+$=IRAGkKPr3vaULOF7-J-JHx5fVRAWBnmnZ)EiEtc z_ieq+d4el3Hf#RX=sSD2eBGgRz^-5ESW8Zt{bZ9}^H)t=Vqz(~)hIJJhiBEF(7ned zP7#uF*yLSsbVI@|CKmQ-vcDgn`{>#CwtwZWISz+5xWu_WJ2o@5+;djZOw&hxZx}@c zN+wGGpJ|xxXdZd~kWmAx$U0rc14id{=gy94$|~6C%yD7<-lD+2bGfXFA6uXOZQj6h zB6#59CM$Eg%opN;JNxzA#?k}$xGUoD>~nhK2rFmF*2^BXL|a*>N_j1%{5&h z9eqaaN3M8Q(KkuIs-yNr&ub+JmjY_-bD^pi*xNac3yt1b7GOg zyGipq-kh7gv*4cLWv0u*P zzEQAR@IvwZIa6nGZ;L;*b>~^FiGi669y4m49{YU1weLdh4Q>5djVBBqMQP4X-cYUg z+O#i5XH#rSX{x9BjNna$4`UX6-o&Hd^U3hxI_5LK52#s}eQUG38`2Q+epAXZMlUn& z+P1dq7Yr0qTFQ1er&QmrXkrr6_;y2Qqw+hiNAFr^=WY9({x9;@U47-<8~?sovtVk- zr-sg%0nF0k&k`oRjLV&C+i=@r>h#y=ws)((dAH{{OP*14%8Etrihgg9bX7QQU~*Ka z=kp%Uya(dkypMaQu6JEnsFQwkjm>M;B|c$=5p1Ud`oef z=dlinbNBdn#~tb1e4b~CLyC>;+*uLdD>7x64;h?u<6AfBE&I}~rjxc^uRcC0# z`sRZ#C3KD#l-|AnHQG^D_C*ys&bqhS1c|ktD;b>ant*t4O z)`SL~{42hVGvelIy*nbYYf^4rz2kPpc)~_;$GEuypW+s3>16L`coJ58;Mr;J(}sy+ zyDBBamoe7P(e!WMrjQuiRA0<)tl%xqsKaoCCDx%*ki{fs%Lh5@*wdUpLbO(SEKSZ^ z6XD!=D%5=25vAMK?-sdLUDe8QzvXvM_nB*!$0oC2rNw$FPee;+zM3IwxnkC5o8;dT zXKhb!QcT%vnA^{0R%<vxBqdR59C zc05Jvnwjgxgs)rrPhD?abKUs4(X1(@{$W=&Z6o@+{3Kl5+}ym>`{RY@8y{4BjI%G-Iqx;~tyT9f&GNqB{5R-T4W&(x+_rZP;}{aoSD^_B6bgAQriFK8BKax>pACu+B8 zlXTnRTZT!yBk#YHI`QiAG^2*liXOwl4+dL!X9h&2Mf$!wWcB{>T){H-4ILa4r_@b< z^eFwytNipiQdPXuymlG*2+@_chQtu}xRx1FR1P z?VR57{;t;Uc+0&!<-4EF7TT6`q57`x&iL=QUe>-#m%r2bXUCPzldMIUvKS2Z{C@pD zBFN${>-o9QBUDs{)-IgH@>T9-iqDUR#GW3WU*_Jx4LuIG zUmq>e5!`Xtgl9_F1%ZH&X5(X%T_&6~i&*_;tK+tBv4-(eLyE+gHoXQdGEyxM-jsFD zqHnMG9&W>_{0~LijCNJ`#j=`#M)fDp|6#%KVCwt5ZSDT^j)2u8D%$$4l`@Zjg z_sRWLGfO&WVSnPfjMuWME-gQQvNEWB{&C#yo6Wyt>;D)n`+u$O&*l1W`T^Q6M3ffX z%}cH=Wu1G??9mN|RTh04?|LrS(soTsS$Xl(xu>KgZnFQqU>qQ6drY=l7_QHd={;B^z!JdAz0}3t^8zxLFysFwXh3Wmhhy&~YJ=WIXdmIV% z+SEJRfnJFf6%wG9+3&9S3G;U`No|)hjtc=f4FS_m37bWd(}U#ZU1lk?}z?Bn|n2%b>|nY z_tMD*F*IU?ykbqt%MAj`>%@T6*0fvd0OIEd%c*3hx!4Y9votv9m!G{BkH6IRI z)_i&_f7pEg*XkMZ5eJg{=dlSUR`2e-+;7vf{eC6?+OXB@XMK1$S^eX!@AVI^_WWM< z?ctS`lXsN;tuj1ND{KZ<^=duK=GWw*BXp{Z?IJ<5`E4;@u;3o(zg7Z-ItEtOFr zo0?^t#A|5N8UOQ|mDO4?AvK*GwTxp9hYtN;Kh?>07315tyI&=NZeR%s@>HEF;;r8I z@z3V-5BmRK(tjjg|F8ey^?yItKYkdzyx{k@+??E8MuUbGci$;Y5=>E9IK`~eW9qSE z$HHFCWM6Rk<%3Rjx#RkO51oJf{@>pH{k^@tPB}tq+xFLd)dCFcqR*);t9y?jIZ zdAXeY{KrTAYlY=UTmF5+r%Ni*_F_8i-L2l8vmr5iSuXKkDHhl~#JpX)H zD=)f=Yo_E^H(B}Whn4GBuD<$u=?6$(NO8>n4zrL+(ck&(ir6+UrIt*-#F8$UlVK8aT&OY$bw&nYCiPySrA46V2VJm=qto(j$rAwef&MU|YEUp_chJN)DQKimJy z&a3&uxn}+P#g|`-WNnSHU`^|N%G+xH!@=2D;pCL9TekGHwz}5u<57|^$hP_TBY8*B zQ>}UR?;_vaHs@rJkd-~UaD%)Y)(xogq9c~$25_m~)Tj;V?5 z=h@PEZrv&$Gc)tTH#Y(W7&jMhH?*{5Ogpyo^Yf1%RtE1V{LJ>q;^4koVF_vJ!&g^d z|4?lI+x^4a`@d^*@^X`Y9r$-?)6ywFj+yU|y|GW}Sob-b&rWRlKYAXUF@#SP5Ipwn z-Pirc3w!)_zx|r;r8&R;Wa*<1A2^ouIHZ)UmA+Pe;Es>7WW7k$6NLk8Yq<`vOD;{3 z-nvx&ptJH?h2{OqR-Ysm2rbyhUiH2(BUkB^cJ8B$jM>>TaU`C6;@AD zv5Q!db}w|^QzcEF9~-2flpX)(E5bYL$F2uaOd7dfOPN5InP`D744BvQYL|xm^iy)@ mZ%=Lat10J>VLb4kKW@G4%Byzs3K$p|7(8A5T-G@yGywoYHY;`j diff --git a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/metadata.json b/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/metadata.json deleted file mode 100644 index 820e77a..0000000 --- a/roles/kde/look-and-feel/xyz.toast003.customtheme.desktop/metadata.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "KPlugin": { - "Authors": [ - { - "Name": "Toast" - } - ], - "Category": "", - "Description": "Custom theme based on Breeze Dark", - "Id": "xyz.toast003.customtheme.desktop", - "License": "GPL", - "Name": "Toast's theme", - "ServiceTypes": [ - "Plasma/LookAndFeel" - ], - "Version": "1.0" - }, - "X-Plasma-MainScript": "defaults" -} diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 0140e0f..3c28e99 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -3,7 +3,6 @@ let # Set up the default kde options kdeglobals = lib.generators.toINI {} { - KDE.LookAndFeelPackage = "org.kde.breezedarktint.desktop"; KDE.SingleClick = false; General = { accentColorFromWallpaper = true; @@ -37,18 +36,6 @@ let runHook postInstall ''; }; - lookAndFeel = pkgs.stdenv.mkDerivation { - name = "toast-look-and-feel"; - src = ./look-and-feel; - installPhase = '' - runHook preInstall - - mkdir -p $out/share/plasma/look-and-feel/ - cp -r xyz.toast003.customtheme.desktop $out/share/plasma/look-and-feel/ - - runHook postInstall - ''; - }; # /etc/xdg is not read by plasma, so to change the default settings you need to put them in a package plasmaDefaults = pkgs.stdenv.mkDerivation { @@ -82,7 +69,7 @@ in Install the patched Breeze color schemes and look and feel packages, as well as the plasma default configs */ - environment.systemPackages = [ breezeTint lookAndFeel plasmaDefaults ]; + environment.systemPackages = [ breezeTint plasmaDefaults ]; # Plasma configs should be on all users home-manager.sharedModules = [ From 394ec6e78896d81b68862f7ca0df7ca8f408b70e Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Jan 2024 14:14:45 +0100 Subject: [PATCH 0360/1125] Kde/plasma: remove unused settings --- roles/kde/plasma.nix | 8 -------- 1 file changed, 8 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 3c28e99..8a5d8fb 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -2,13 +2,6 @@ let # Set up the default kde options - kdeglobals = lib.generators.toINI {} { - KDE.SingleClick = false; - General = { - accentColorFromWallpaper = true; - AccentColor = "172,53,164" ; }; - }; - balooExcludedDirs = lib.strings.intersperse "," [ "$HOME/.cache/" "$HOME/.config/" @@ -46,7 +39,6 @@ let set -x mkdir -p $out/etc/xdg - echo "${kdeglobals}" > $out/etc/xdg/kdeglobals echo '${baloofilerc}' > $out/etc/xdg/baloofilerc runHook postInstall From cbdd6192fe2878b8852cbb2787ea9ee8ab53aeb4 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Jan 2024 14:15:10 +0100 Subject: [PATCH 0361/1125] Kde/plasma: set up cursor theme --- roles/kde/plasma.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 8a5d8fb..1b35760 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -88,7 +88,10 @@ in }; programs.plasma = { enable = true; - workspace.clickItemTo = "select"; + workspace = { + clickItemTo = "select"; + cursorTheme = "Breeze_Snow"; + }; shortcuts = { "kwin" = { "Switch One Desktop to the Left" = [ "Meta+Ctrl+Left" ]; From f9986b0d8d9b0bd638c6672fd624b76b2bd8bf6f Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 18 Jan 2024 10:27:03 +0100 Subject: [PATCH 0362/1125] Flake: apply catppuccin patch to stable nixpkgs --- flake.nix | 20 +++++--- .../0001-catppuccin-add-starship-theme.patch | 50 +++++++++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) mode change 100755 => 100644 flake.nix create mode 100644 nixpkgs-patches/0001-catppuccin-add-starship-theme.patch diff --git a/flake.nix b/flake.nix old mode 100755 new mode 100644 index 427a665..a627754 --- a/flake.nix +++ b/flake.nix @@ -2,20 +2,20 @@ description = "Configuration for Everest"; inputs = { - nixpkgs.url = "nixpkgs/nixos-23.11"; + nixpkgs-raw.url = "nixpkgs/nixos-23.11"; nixpkgs-unstable-raw.url = "nixpkgs/nixos-unstable"; agenix = { url = "github:ryantm/agenix"; inputs = { - nixpkgs.follows = "nixpkgs"; + nixpkgs.follows = "nixpkgs-raw"; darwin.follows = ""; # Not using this on MacOS, so this doesn't pull it's dependencies }; }; home-manager = { url = "github:nix-community/home-manager/release-23.11"; - inputs.nixpkgs.follows = "nixpkgs"; + inputs.nixpkgs.follows = "nixpkgs-raw"; }; home-manager-unstable = { @@ -38,7 +38,7 @@ */ nix-index-db = { url = "github:Mic92/nix-index-database"; - inputs.nixpkgs.follows = "nixpkgs"; + inputs.nixpkgs.follows = "nixpkgs-raw"; }; nix-index-db-unstable = { @@ -69,7 +69,7 @@ # Patch nixpkgs # https://ertt.ca/nix/patch-nixpkgs/ let - nixpkgs-unstable-patched = nixpkgs.legacyPackages.x86_64-linux.applyPatches { + nixpkgs-unstable-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ @@ -77,8 +77,16 @@ ./nixpkgs-patches/pr281207.patch ]; }; + nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { + name = "patched-nixpkgs"; + src = nixpkgs-raw; + patches = [ + ./nixpkgs-patches/0001-catppuccin-add-starship-theme.patch + ]; + }; # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs { self = inputs.self; }; + nixpkgs = (import "${nixpkgs-patched}/flake.nix").outputs { self = inputs.self; }; in { devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { @@ -177,7 +185,7 @@ Everest = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs; flakeSelf = self; }; + specialArgs = { systemPkgs = inputs.nixpkgs-raw; flakeSelf = self; }; modules = [ agenix.nixosModules.default home-manager.nixosModule diff --git a/nixpkgs-patches/0001-catppuccin-add-starship-theme.patch b/nixpkgs-patches/0001-catppuccin-add-starship-theme.patch new file mode 100644 index 0000000..217f681 --- /dev/null +++ b/nixpkgs-patches/0001-catppuccin-add-starship-theme.patch @@ -0,0 +1,50 @@ +From 8a73b27f67158e8161fc33a61cae2ebd3aa6c625 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Sat, 13 Jan 2024 18:41:51 +0100 +Subject: [PATCH] catppuccin: add starship theme + +(cherry picked from commit cf1dfaa32a0201cc14801ebb93b5ef865d42522a) +--- + pkgs/data/themes/catppuccin/default.nix | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/pkgs/data/themes/catppuccin/default.nix b/pkgs/data/themes/catppuccin/default.nix +index 59e030eb9e0e..6db2679a9d72 100644 +--- a/pkgs/data/themes/catppuccin/default.nix ++++ b/pkgs/data/themes/catppuccin/default.nix +@@ -1,5 +1,5 @@ + let +- validThemes = [ "bat" "bottom" "btop" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "refind" "rofi" "waybar" ]; ++ validThemes = [ "bat" "bottom" "btop" "grub" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "qt5ct" "refind" "rofi" "starship" "waybar" ]; + in + { fetchFromGitHub + , lib +@@ -96,6 +96,14 @@ let + hash = "sha256-DNorfyl3C4RBclF2KDgwvQQwixpTwSRu7fIvihPN8JY="; + }; + ++ starship = fetchFromGitHub { ++ name = "starship"; ++ owner = "catppuccin"; ++ repo = "starship"; ++ rev = "5629d2356f62a9f2f8efad3ff37476c19969bd4f"; ++ hash = "sha256-nsRuxQFKbQkyEI4TXgvAjcroVdG+heKX5Pauq/4Ota0="; ++ }; ++ + waybar = fetchFromGitHub { + name = "waybar"; + owner = "catppuccin"; +@@ -171,6 +179,10 @@ stdenvNoCC.mkDerivation { + cp ${sources.refind}/${variant}.conf $out/refind/ + cp -r ${sources.refind}/assets/${variant} $out/refind/assets/ + ++ '' + lib.optionalString (lib.elem "starship" themeList) '' ++ mkdir -p $out/starship ++ cp ${sources.starship}/palettes/${variant}.toml $out/starship/ ++ + '' + lib.optionalString (lib.elem "waybar" themeList) '' + mkdir -p $out/waybar + cp ${sources.waybar}/${variant}.css $out/waybar/ +-- +2.42.0 + From e9bd1e24c3e423d8f1bd979d020c9dce091ffd04 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 18 Jan 2024 09:24:34 +0100 Subject: [PATCH 0363/1125] Machines/WinMax2: add SteamOS radv and patched mesa --- machines/WinMax2/configuration.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 65980d5..7b0f3d5 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -56,6 +56,11 @@ user = "toast"; desktopSession = "plasmawayland"; }; + # Need patched mesa + devices.steamdeck = { + enableMesaPatches = true; + enableVendorRadv = true; + }; decky-loader = { enable = true; }; From 621de00ad3e6baeb6a4556579d60c1bfc0008742 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 18 Jan 2024 09:35:04 +0100 Subject: [PATCH 0364/1125] Machines/WinMax2: add sleep fixes --- machines/WinMax2/configuration.nix | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 7b0f3d5..90d5d43 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -28,12 +28,18 @@ initrd.systemd.enable = true; # Plymouth doesn't support fractional scaling :( plymouth.extraConfig = "DeviceScale=2"; - }; networking.hostName = "WinMax2"; # Define your hostname. networking.networkmanager.enable = true; # Enable networking + # Sleep fixes + boot.kernelParams = [ "rtc_cmos.use_acpi_alarm=1" ]; + services.udev.extraRules = '' +ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="GXTP7385:00", ATTR{power/wakeup}="disabled" +ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="disabled" + ''; + # Allow unfree packages nixpkgs.config.allowUnfree = true; From 0162c94d93e0504d5ba9911f27866adb5476e781 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 18 Jan 2024 10:44:34 +0100 Subject: [PATCH 0365/1125] Flake: update lock file --- flake.lock | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/flake.lock b/flake.lock index 91d52f0..502fc74 100644 --- a/flake.lock +++ b/flake.lock @@ -5,7 +5,7 @@ "darwin": [], "home-manager": "home-manager", "nixpkgs": [ - "nixpkgs" + "nixpkgs-raw" ], "systems": "systems" }, @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1705408632, - "narHash": "sha256-/AhkReVocTli5BLWA5WXxUlGYXn3Agi/uzX76TNrsbo=", + "lastModified": 1705535278, + "narHash": "sha256-V5+XKfNbiY0bLKLQlH+AXyhHttEL7XcZBH9iSbxxexA=", "owner": "nix-community", "repo": "home-manager", - "rev": "37d6eeceee464adc03585404eebd68765b3c8615", + "rev": "b84191db127c16a92cbdf7f7b9969d58bb456699", "type": "github" }, "original": { @@ -121,15 +121,15 @@ "home-manager_2": { "inputs": { "nixpkgs": [ - "nixpkgs" + "nixpkgs-raw" ] }, "locked": { - "lastModified": 1705273357, - "narHash": "sha256-JAlkxgJbWh7+auiT0rJL3IUXXtkULRqygfxQA6mvLgc=", + "lastModified": 1705476964, + "narHash": "sha256-W5OK1fnj4qdn1HWOlxV2S3YiUvfaVjQM5ldWVpGV1fs=", "owner": "nix-community", "repo": "home-manager", - "rev": "924d91e1e4c802fd8e60279a022dbae5acb36f2d", + "rev": "85c3b600f660abd86e94cbcd1c46733943197a07", "type": "github" }, "original": { @@ -147,11 +147,11 @@ ] }, "locked": { - "lastModified": 1705231543, - "narHash": "sha256-W8j0A5n2WOpCgdFRqMqwd9adNORcN1r/DpjRVxiFkAw=", + "lastModified": 1705487282, + "narHash": "sha256-eX/0O2ybmFKD/MzYO8gDlr4tAurekDbJQa7olAFFbRo=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "ab807f9740c533070e8b68b0d86034d4a293b5f1", + "rev": "a00331e522b9a732f876cf707174ce37ae702762", "type": "github" }, "original": { @@ -216,7 +216,7 @@ "nix-index-db": { "inputs": { "nixpkgs": [ - "nixpkgs" + "nixpkgs-raw" ] }, "locked": { @@ -269,7 +269,7 @@ "type": "github" } }, - "nixpkgs": { + "nixpkgs-raw": { "locked": { "lastModified": 1705331948, "narHash": "sha256-qjQXfvrAT1/RKDFAMdl8Hw3m4tLVvMCc8fMqzJv0pP4=", @@ -334,7 +334,7 @@ "nix-index-db": "nix-index-db", "nix-index-db-unstable": "nix-index-db-unstable", "nixos-hardware": "nixos-hardware", - "nixpkgs": "nixpkgs", + "nixpkgs-raw": "nixpkgs-raw", "nixpkgs-unstable-raw": "nixpkgs-unstable-raw", "plasma-manager": "plasma-manager", "vscode-extensions": "vscode-extensions" @@ -379,11 +379,11 @@ ] }, "locked": { - "lastModified": 1705368072, - "narHash": "sha256-e7Gn7daakWvEj/hQTw628zMGhAMH88thrmhmoB6RV6o=", + "lastModified": 1705540888, + "narHash": "sha256-lDuq8dgVV6+FOO9rvl62+yOXPycf9XqHhqgDgTLd/mE=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "37b8bbc1717211338c446b7b926276bf8db234ac", + "rev": "e792da69b3af0431a2c33907866648198d59515f", "type": "github" }, "original": { From 1f00befb3e871e320035ddf552aceb3fc7cc3dbd Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Jan 2024 12:06:50 +0100 Subject: [PATCH 0366/1125] Plasma/kde: move titlebar button settings to new module --- roles/kde/plasma.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 1b35760..1ac1be8 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -92,6 +92,12 @@ in clickItemTo = "select"; cursorTheme = "Breeze_Snow"; }; + kwin = { + titlebarButtons = { + left = [ "on-all-desktops" "keep-above-windows" ]; + right = [ "minimize" "maximize" "close" ]; + }; + }; shortcuts = { "kwin" = { "Switch One Desktop to the Left" = [ "Meta+Ctrl+Left" ]; @@ -105,7 +111,6 @@ in "Rows" = 1; }; "TabBox"."LayoutName" = "thumbnail_grid"; - "org\\.kde\\.kdecoration2"."ButtonsOnLeft" = "SF"; }; "plasmanotifyrc"."Notifications"."NormalAlwaysOnTop" = true; }; From b5a58ea23f44b5f1eea6ebb80f77eff19f5645dd Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Jan 2024 12:10:00 +0100 Subject: [PATCH 0367/1125] Remove unused program from flake and school role --- flake.nix | 1 - pkgs/pseint.nix | 66 ------------------------------- roles/school/programs/default.nix | 3 +- 3 files changed, 1 insertion(+), 69 deletions(-) delete mode 100644 pkgs/pseint.nix diff --git a/flake.nix b/flake.nix index a627754..5a0c8f1 100644 --- a/flake.nix +++ b/flake.nix @@ -105,7 +105,6 @@ }; packages = { x86_64-linux = with import nixpkgs-unstable-raw { system = "x86_64-linux"; }; { - pseint = callPackage ./pkgs/pseint.nix {}; anything-sync-daemon = callPackage ./pkgs/anything-sync-daemon {}; discord-krisp-fixer = callPackage ./pkgs/discord-krisp-fixer {}; }; diff --git a/pkgs/pseint.nix b/pkgs/pseint.nix deleted file mode 100644 index 2351d94..0000000 --- a/pkgs/pseint.nix +++ /dev/null @@ -1,66 +0,0 @@ -{ stdenv -, lib -, fetchurl -, wxGTK32 -, libX11 -, libglvnd -, libGLU -, gsettings-desktop-schemas -, makeBinaryWrapper -, makeDesktopItem -, wrapGAppsHook -}: -# Based on https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=pseint -stdenv.mkDerivation rec { - pname = "pseint"; - version = "20230517"; - - src = fetchurl { - url = "https://netactuate.dl.sourceforge.net/project/${pname}/${version}/${pname}-src-${version}.tgz"; - hash = "sha256-8zc7CtDQ9RjXLAVQTigstPqdDJsR8ffBopxBFzVP+eI="; - }; - enableParallelBuilding = true; - - buildInputs = [ wxGTK32 libglvnd libGLU libX11 gsettings-desktop-schemas ]; - - nativeBuildInputs = [ makeBinaryWrapper wrapGAppsHook ]; - - # Build for linux - makeFlags = [ "ARCH=lnx" ]; - - installPhase = '' - runHook preInstall - - mkdir -p $out/opt/${pname}/ $out/bin/ $out/share/icons/hicolor/{16x16,32x32,48x48,64x64,128x128} - cp -rv bin/* $out/opt/${pname}/ - makeBinaryWrapper $out/opt/${pname}/wxPSeInt $out/bin/pseint - cp -rv bin/imgs/icon16.png $out/share/icons/hicolor/16x16/pseint.png - cp -rv bin/imgs/icon32.png $out/share/icons/hicolor/32x32/pseint.png - cp -rv bin/imgs/icon48.png $out/share/icons/hicolor/48x48/pseint.png - cp -rv bin/imgs/icon64.png $out/share/icons/hicolor/64x64/pseint.png - cp -rv bin/imgs/icon128.png $out/share/icons/hicolor/128x128/pseint.png - cp -rv "${desktopItem}/share/applications" "$out/share" - - runHook postInstall - ''; - - desktopItem = makeDesktopItem { - name = pname; - desktopName = "PSeInt"; - exec = "pseint"; - icon = "pseint"; - genericName = meta.description; - categories = [ "Development" ]; - }; - - - meta = with lib; { - description = "A tool for learning programming basis with a simple spanish pseudocode"; - homepage = "https://pseint.sourceforge.net/"; - downloadPage = "https://pseint.sourceforge.net/index.php?page=descargas.php"; - changelog = "https://pseint.sourceforge.net/index.php?page=cambios.php"; - # Website says GPLv2, so I'm assuming I need to use gpl2Only - license = lib.licenses.gpl2Only; - platforms = platforms.linux; - }; -} diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 24dba3a..6579783 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -1,4 +1,4 @@ - { config, pkgs, flakeSelf, ... }: + { config, pkgs, ... }: { imports = [ @@ -9,6 +9,5 @@ environment.systemPackages = with pkgs; [ dia - flakeSelf.packages.x86_64-linux.pseint ]; } From 100b4169b1c1a0bf28eaefcf134cdf9f85b10cf0 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Jan 2024 13:14:51 +0100 Subject: [PATCH 0368/1125] Plasma/kde: modify outdated comment --- roles/kde/plasma.nix | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 1ac1be8..b237ebf 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -57,10 +57,7 @@ in # GTK apps need dconf to grab the correct theme on Wayland programs.dconf.enable = true; - /* - Install the patched Breeze color schemes and look and feel packages, - as well as the plasma default configs - */ + # Install the patched Breeze color schemes as well as the plasma default configs environment.systemPackages = [ breezeTint plasmaDefaults ]; # Plasma configs should be on all users From 9ebfc2e1aeb571c3c99f83e068d6008493947b08 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Jan 2024 23:20:47 +0100 Subject: [PATCH 0369/1125] Machines/WinMax2: use latest linux kernel --- machines/WinMax2/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 90d5d43..b78af8b 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -28,6 +28,8 @@ initrd.systemd.enable = true; # Plymouth doesn't support fractional scaling :( plymouth.extraConfig = "DeviceScale=2"; + + kernelPackages = pkgs.linuxPackages_latest; }; networking.hostName = "WinMax2"; # Define your hostname. From c4e846e91e876bc6301488b1bb04348928744903 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 20 Jan 2024 00:50:36 +0100 Subject: [PATCH 0370/1125] Common/grub: set catppuccin theme --- roles/common/configuration.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 8871d76..99e8e1c 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -75,6 +75,7 @@ "bat" "btop" "starship" + "grub" ]; }; } @@ -108,6 +109,12 @@ ]; }; + boot.loader.grub = { + theme = "${pkgs.catppuccin}/grub"; + backgroundColor = "#1E1E2E"; + splashImage = "${pkgs.catppuccin}/grub/background.png"; + }; + /* I used to keep the host keys in the repo as a secret, but since I use the host keys for decrypting too I'm not sure encrypting a key with itself From 604d4b253acf089f8bd06be496bdb99737767679 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 20 Jan 2024 02:15:16 +0100 Subject: [PATCH 0371/1125] Kde/plasma: set up icon theme --- roles/kde/plasma.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index b237ebf..244b866 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -88,6 +88,7 @@ in workspace = { clickItemTo = "select"; cursorTheme = "Breeze_Snow"; + iconTheme = "breeze-dark"; }; kwin = { titlebarButtons = { From 07b2ee00ebb90387bee0db2c064faea13de72354 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 20 Jan 2024 02:19:08 +0100 Subject: [PATCH 0372/1125] Kde/plasma: add catppuccin theme --- roles/kde/plasma.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 244b866..21012c2 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -83,12 +83,20 @@ in gtk3.extraConfig.gtk-application-prefer-dark-theme = true; gtk4.extraConfig.gtk-application-prefer-dark-theme = true; }; + home.packages = [( + pkgs.catppuccin-kde.override { + flavour = [ "mocha" ]; + accents = [ "mauve" ]; + winDecStyles = [ "classic" ]; + } + )]; programs.plasma = { enable = true; workspace = { clickItemTo = "select"; cursorTheme = "Breeze_Snow"; iconTheme = "breeze-dark"; + lookAndFeel = "Catppuccin-Mocha-Mauve"; }; kwin = { titlebarButtons = { @@ -110,6 +118,7 @@ in }; "TabBox"."LayoutName" = "thumbnail_grid"; }; + "auroraerc"."CatppuccinMocha-Classic"."ButtonSize" = 0; "plasmanotifyrc"."Notifications"."NormalAlwaysOnTop" = true; }; }; From 77df840e1f21829b95f27c44656a98f31e182c4a Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 20 Jan 2024 02:46:42 +0100 Subject: [PATCH 0373/1125] Kde/plasma: configure panels --- roles/kde/plasma.nix | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 21012c2..b47b5a4 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -104,6 +104,24 @@ in right = [ "minimize" "maximize" "close" ]; }; }; + panels = [{ + location = "bottom"; + height = 44; + widgets = [ + "org.kde.plasma.kickoff" + "org.kde.plasma.pager" + "org.kde.plasma.icontasks" + "org.kde.plasma.marginsseparator" + "org.kde.plasma.systemtray" + "org.kde.plasma.digitalclock" + "org.kde.plasma.showdesktop" + ]; + extraSettings = '' + currentWidget = panelWidgets["org.kde.plasma.kickoff"] + currentWidget.currentConfigGroup = ["General"] + currentWidget.writeConfig("icon", "nix-snowflake-white") + ''; + }]; shortcuts = { "kwin" = { "Switch One Desktop to the Left" = [ "Meta+Ctrl+Left" ]; From 386d2ae024459003285e7802732d472cdad856cb Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 21 Jan 2024 17:48:38 +0100 Subject: [PATCH 0374/1125] Flake: update lock file --- flake.lock | 54 +++++++++++++++++----------------- flake.nix | 1 - nixpkgs-patches/pr280779.patch | 46 ----------------------------- 3 files changed, 27 insertions(+), 74 deletions(-) delete mode 100644 nixpkgs-patches/pr280779.patch diff --git a/flake.lock b/flake.lock index 502fc74..a8f5b4f 100644 --- a/flake.lock +++ b/flake.lock @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1705535278, - "narHash": "sha256-V5+XKfNbiY0bLKLQlH+AXyhHttEL7XcZBH9iSbxxexA=", + "lastModified": 1705823474, + "narHash": "sha256-2C4uRe9/U3QwSPC4dYKM1/njgCQk0Mltezy4VcjAqa4=", "owner": "nix-community", "repo": "home-manager", - "rev": "b84191db127c16a92cbdf7f7b9969d58bb456699", + "rev": "928f2528f9ee952ba0a47bbb1ece8d93ed66e784", "type": "github" }, "original": { @@ -125,11 +125,11 @@ ] }, "locked": { - "lastModified": 1705476964, - "narHash": "sha256-W5OK1fnj4qdn1HWOlxV2S3YiUvfaVjQM5ldWVpGV1fs=", + "lastModified": 1705659542, + "narHash": "sha256-WA3xVfAk1AYmFdwghT7mt/erYpsU6JPu9mdTEP/e9HQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "85c3b600f660abd86e94cbcd1c46733943197a07", + "rev": "10cd9c53115061aa6a0a90aad0b0dde6a999cdb9", "type": "github" }, "original": { @@ -147,11 +147,11 @@ ] }, "locked": { - "lastModified": 1705487282, - "narHash": "sha256-eX/0O2ybmFKD/MzYO8gDlr4tAurekDbJQa7olAFFbRo=", + "lastModified": 1705667791, + "narHash": "sha256-J0JYfA6eFdHluLnROVDkrqbYacWcJXYKXeJAFayDiAE=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "a00331e522b9a732f876cf707174ce37ae702762", + "rev": "330b7a78fcba967f2273ae71fb3c4bfb03b5dd21", "type": "github" }, "original": { @@ -162,11 +162,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1704403850, - "narHash": "sha256-VYa/EvYY0xjuK/oei2hOgE2fJIv+yZgFw0WgoBuzwBc=", + "lastModified": 1705758212, + "narHash": "sha256-96kbUcT7hvFPhs5vHqSLAQOCwsRojlmWa0+VpR6lrrE=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "f43640ecb03e9e008076932a87987cf5c16d8cf9", + "rev": "09d2dd72de3b9a7ef71f3013a15d34c649b83277", "type": "github" }, "original": { @@ -220,11 +220,11 @@ ] }, "locked": { - "lastModified": 1705282324, - "narHash": "sha256-LnURMA7yCM5t7et9O2+2YfGQh0FKAfE5GyahNDDzJVM=", + "lastModified": 1705806513, + "narHash": "sha256-FcOmNjhHFfPz2udZbRpZ1sfyhVMr+C2O8kOxPj+HDDk=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "49aaeecf41ae0a0944e2c627cb515bcde428a1d1", + "rev": "f8e04fbcebcc24cebc91989981bd45f69b963ed7", "type": "github" }, "original": { @@ -240,11 +240,11 @@ ] }, "locked": { - "lastModified": 1705282324, - "narHash": "sha256-LnURMA7yCM5t7et9O2+2YfGQh0FKAfE5GyahNDDzJVM=", + "lastModified": 1705806513, + "narHash": "sha256-FcOmNjhHFfPz2udZbRpZ1sfyhVMr+C2O8kOxPj+HDDk=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "49aaeecf41ae0a0944e2c627cb515bcde428a1d1", + "rev": "f8e04fbcebcc24cebc91989981bd45f69b963ed7", "type": "github" }, "original": { @@ -271,11 +271,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1705331948, - "narHash": "sha256-qjQXfvrAT1/RKDFAMdl8Hw3m4tLVvMCc8fMqzJv0pP4=", + "lastModified": 1705641746, + "narHash": "sha256-D6c2aH8HQbWc7ZWSV0BUpFpd94ImFyCP8jFIsKQ4Slg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b8dd8be3c790215716e7c12b247f45ca525867e2", + "rev": "d2003f2223cbb8cd95134e4a0541beea215c1073", "type": "github" }, "original": { @@ -286,11 +286,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1705316053, - "narHash": "sha256-J2Ey5mPFT8gdfL2XC0JTZvKaBw/b2pnyudEXFvl+dQM=", + "lastModified": 1705677747, + "narHash": "sha256-eyM3okYtMgYDgmYukoUzrmuoY4xl4FUujnsv/P6I/zI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c3e128f3c0ecc1fb04aef9f72b3dcc2f6cecf370", + "rev": "bbe7d8f876fbbe7c959c90ba2ae2852220573261", "type": "github" }, "original": { @@ -379,11 +379,11 @@ ] }, "locked": { - "lastModified": 1705540888, - "narHash": "sha256-lDuq8dgVV6+FOO9rvl62+yOXPycf9XqHhqgDgTLd/mE=", + "lastModified": 1705800393, + "narHash": "sha256-/aO8yu7r4fw+YFq/PWa0VErBDVVK9iDt1cqmLd/c7Lo=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "e792da69b3af0431a2c33907866648198d59515f", + "rev": "1823c666b159fec04d9c2bafc37b8f190e885e01", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 5a0c8f1..064a49d 100644 --- a/flake.nix +++ b/flake.nix @@ -73,7 +73,6 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/pr280779.patch ./nixpkgs-patches/pr281207.patch ]; }; diff --git a/nixpkgs-patches/pr280779.patch b/nixpkgs-patches/pr280779.patch deleted file mode 100644 index f404304..0000000 --- a/nixpkgs-patches/pr280779.patch +++ /dev/null @@ -1,46 +0,0 @@ -From cf1dfaa32a0201cc14801ebb93b5ef865d42522a Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Sat, 13 Jan 2024 18:41:51 +0100 -Subject: [PATCH] catppuccin: add starship theme - ---- - pkgs/data/themes/catppuccin/default.nix | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -diff --git a/pkgs/data/themes/catppuccin/default.nix b/pkgs/data/themes/catppuccin/default.nix -index c9a51ba241d482..25794c9e67d7cd 100644 ---- a/pkgs/data/themes/catppuccin/default.nix -+++ b/pkgs/data/themes/catppuccin/default.nix -@@ -1,5 +1,5 @@ - let -- validThemes = [ "bat" "bottom" "btop" "grub" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "qt5ct" "refind" "rofi" "waybar" ]; -+ validThemes = [ "bat" "bottom" "btop" "grub" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "qt5ct" "refind" "rofi" "starship" "waybar" ]; - in - { fetchFromGitHub - , lib -@@ -112,6 +112,14 @@ let - hash = "sha256-DNorfyl3C4RBclF2KDgwvQQwixpTwSRu7fIvihPN8JY="; - }; - -+ starship = fetchFromGitHub { -+ name = "starship"; -+ owner = "catppuccin"; -+ repo = "starship"; -+ rev = "5629d2356f62a9f2f8efad3ff37476c19969bd4f"; -+ hash = "sha256-nsRuxQFKbQkyEI4TXgvAjcroVdG+heKX5Pauq/4Ota0="; -+ }; -+ - waybar = fetchFromGitHub { - name = "waybar"; - owner = "catppuccin"; -@@ -195,6 +203,10 @@ stdenvNoCC.mkDerivation { - cp ${sources.refind}/${variant}.conf $out/refind/ - cp -r ${sources.refind}/assets/${variant} $out/refind/assets/ - -+ '' + lib.optionalString (lib.elem "starship" themeList) '' -+ mkdir -p $out/starship -+ cp ${sources.starship}/palettes/${variant}.toml $out/starship/ -+ - '' + lib.optionalString (lib.elem "waybar" themeList) '' - mkdir -p $out/waybar - cp ${sources.waybar}/${variant}.css $out/waybar/ From d78c2e3f67d37b2731abd2413edb2599bc1cb554 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 21 Jan 2024 17:50:28 +0100 Subject: [PATCH 0375/1125] Kde/plasma: add some additional settings --- roles/kde/plasma.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index b47b5a4..8586528 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -97,6 +97,8 @@ in cursorTheme = "Breeze_Snow"; iconTheme = "breeze-dark"; lookAndFeel = "Catppuccin-Mocha-Mauve"; + theme = "default"; + colorScheme = "CatppuccinMochaMauve"; }; kwin = { titlebarButtons = { @@ -136,6 +138,7 @@ in }; "TabBox"."LayoutName" = "thumbnail_grid"; }; + "kdeglobals"."General"."AccentColor" = null; "auroraerc"."CatppuccinMocha-Classic"."ButtonSize" = 0; "plasmanotifyrc"."Notifications"."NormalAlwaysOnTop" = true; }; From 17f58cfeba4d7ee63aa905afbeb2ec72718e8c74 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 21 Jan 2024 21:05:09 +0100 Subject: [PATCH 0376/1125] Flake: add nur --- flake.lock | 16 ++++++++++++++++ flake.nix | 2 ++ 2 files changed, 18 insertions(+) diff --git a/flake.lock b/flake.lock index a8f5b4f..2ab26b5 100644 --- a/flake.lock +++ b/flake.lock @@ -299,6 +299,21 @@ "type": "indirect" } }, + "nur": { + "locked": { + "lastModified": 1705847594, + "narHash": "sha256-YtoT6OoTIkYcwm+VPeqn+cJhyacd/WIMtBoBEvRDYVY=", + "owner": "nix-community", + "repo": "NUR", + "rev": "2b4a30cde35eb5b7813c731aa26fc475a27c723e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "NUR", + "type": "github" + } + }, "plasma-manager": { "inputs": { "home-manager": [ @@ -336,6 +351,7 @@ "nixos-hardware": "nixos-hardware", "nixpkgs-raw": "nixpkgs-raw", "nixpkgs-unstable-raw": "nixpkgs-unstable-raw", + "nur": "nur", "plasma-manager": "plasma-manager", "vscode-extensions": "vscode-extensions" } diff --git a/flake.nix b/flake.nix index 064a49d..b9d2c7e 100644 --- a/flake.nix +++ b/flake.nix @@ -63,6 +63,8 @@ }; nix-flatpak.url = github:gmodena/nix-flatpak/main; + + nur.url = "github:nix-community/NUR"; }; outputs = { ... } @inputs: with inputs; From 3c3b192f35d87aebb5ef79fa9bccdc4d176a835f Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 21 Jan 2024 21:06:22 +0100 Subject: [PATCH 0377/1125] Machines/WinMax2: add bmi260 module from nur --- machines/WinMax2/hardware-configuration.nix | 20 ++++++++++++++++---- roles/common/configuration.nix | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/machines/WinMax2/hardware-configuration.nix b/machines/WinMax2/hardware-configuration.nix index de48c2d..9f4145d 100755 --- a/machines/WinMax2/hardware-configuration.nix +++ b/machines/WinMax2/hardware-configuration.nix @@ -1,16 +1,25 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: +{ config, lib, flakeSelf, modulesPath, ... }: let # \x20 is the escape code for a space ssdLabel = ''Win\\x20Max\\x202\\x20SSD''; + + # You need to do fucky shit to import modules from the NUR + # https://github.com/nix-community/NUR#using-the-flake-in-nixos + nur = import flakeSelf.inputs.nur { + nurpkgs = import flakeSelf.inputs.nixpkgs-unstable-raw { + system = "x86_64-linux"; + }; + }; in { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + nur.repos.cryolitia.modules.bmi260 ]; boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usbhid" "sdhci_pci" ]; @@ -66,5 +75,8 @@ in swapDevices = [ ]; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + hardware = { + cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + sensor.iio.bmi260.enable = true; + }; } diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 99e8e1c..8809576 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -1,6 +1,7 @@ { config, lib, pkgs, flakeSelf, ... }: { + imports = [ flakeSelf.inputs.nur.nixosModules.nur ]; environment = { # As of the 1st of May 2023, the default packages are nano, perl, rsync and strace # I don't need any of them, so I just empty the list From 70202144a539a37442df8916493c5eb8d7f5d7bf Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 22 Jan 2024 13:40:27 +0100 Subject: [PATCH 0378/1125] Machines/WinMax2: use linux 6.6 --- machines/WinMax2/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index b78af8b..7190515 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -29,7 +29,7 @@ # Plymouth doesn't support fractional scaling :( plymouth.extraConfig = "DeviceScale=2"; - kernelPackages = pkgs.linuxPackages_latest; + kernelPackages = pkgs.linuxPackages_6_6; }; networking.hostName = "WinMax2"; # Define your hostname. From c7bcbaed03ac590536e6a0993c4ed213014fc97b Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 23 Jan 2024 00:14:37 +0100 Subject: [PATCH 0379/1125] Kde/sddm: set cursor theme --- roles/kde/sddm.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/kde/sddm.nix b/roles/kde/sddm.nix index 1183ee4..3fedc02 100644 --- a/roles/kde/sddm.nix +++ b/roles/kde/sddm.nix @@ -48,6 +48,7 @@ in theme = "sugar-candy"; settings = { General = { Numlock = "on"; }; + Theme = { CursorTheme = "Breeze_Snow"; }; }; }; From 14fa5aff15282507c15383af81fb9dc0e71f4a3c Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 23 Jan 2024 00:20:37 +0100 Subject: [PATCH 0380/1125] Machines/WinMax2: change sddm scale --- machines/WinMax2/configuration.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 7190515..2657f7d 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -54,7 +54,12 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="d # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; # Enable the X11 windowing system. - services.xserver.enable = true; + services.xserver = { + enable = true; + displayManager.sddm.settings = { + General.GreeterEnvironment="QT_SCREEN_SCALE_FACTORS=1.75"; + }; + }; jovian = { # Steam Deck UI settings From 7056d6f597da7ee6945a5d9ef7888332c9ca33af Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 23 Jan 2024 10:37:01 +0100 Subject: [PATCH 0381/1125] Flake: backport catppuccin grub theme to nixos 23.11 --- flake.nix | 3 +- .../0001-catppuccin-add-grub-theme.patch | 49 +++++++++++++++++++ ... 0002-catppuccin-add-starship-theme.patch} | 15 +++--- 3 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 nixpkgs-patches/0001-catppuccin-add-grub-theme.patch rename nixpkgs-patches/{0001-catppuccin-add-starship-theme.patch => 0002-catppuccin-add-starship-theme.patch} (73%) diff --git a/flake.nix b/flake.nix index b9d2c7e..d7c2400 100644 --- a/flake.nix +++ b/flake.nix @@ -82,7 +82,8 @@ name = "patched-nixpkgs"; src = nixpkgs-raw; patches = [ - ./nixpkgs-patches/0001-catppuccin-add-starship-theme.patch + ./nixpkgs-patches/0001-catppuccin-add-grub-theme.patch + ./nixpkgs-patches/0002-catppuccin-add-starship-theme.patch ]; }; # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 diff --git a/nixpkgs-patches/0001-catppuccin-add-grub-theme.patch b/nixpkgs-patches/0001-catppuccin-add-grub-theme.patch new file mode 100644 index 0000000..3455c15 --- /dev/null +++ b/nixpkgs-patches/0001-catppuccin-add-grub-theme.patch @@ -0,0 +1,49 @@ +From 316d5e8f356d6817626bca5a37dd587418afc856 Mon Sep 17 00:00:00 2001 +From: BlankParticle +Date: Tue, 21 Nov 2023 18:14:15 +0530 +Subject: [PATCH 1/2] catppuccin: add grub theme + +--- + pkgs/data/themes/catppuccin/default.nix | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/pkgs/data/themes/catppuccin/default.nix b/pkgs/data/themes/catppuccin/default.nix +index 59e030eb9e0e..e8cdb0456d17 100644 +--- a/pkgs/data/themes/catppuccin/default.nix ++++ b/pkgs/data/themes/catppuccin/default.nix +@@ -1,5 +1,5 @@ + let +- validThemes = [ "bat" "bottom" "btop" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "refind" "rofi" "waybar" ]; ++ validThemes = [ "bat" "bottom" "btop" "grub" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "refind" "rofi" "waybar" ]; + in + { fetchFromGitHub + , lib +@@ -40,6 +40,14 @@ let + hash = "sha256-J3UezOQMDdxpflGax0rGBF/XMiKqdqZXuX4KMVGTxFk="; + }; + ++ grub = fetchFromGitHub { ++ name = "grub"; ++ owner = "catppuccin"; ++ repo = "grub"; ++ rev = "v1.0.0"; ++ hash = "sha256-/bSolCta8GCZ4lP0u5NVqYQ9Y3ZooYCNdTwORNvR7M0="; ++ }; ++ + hyprland = fetchFromGitHub { + name = "hyprland"; + owner = "catppuccin"; +@@ -140,6 +148,10 @@ stdenvNoCC.mkDerivation { + mkdir -p $out/bottom + cp "${sources.bottom}/themes/${variant}.toml" "$out/bottom/" + ++ '' + lib.optionalString (lib.elem "grub" themeList) '' ++ mkdir -p $out/grub ++ cp -r ${sources.grub}/src/catppuccin-${variant}-grub-theme/* "$out/grub/" ++ + '' + lib.optionalString (lib.elem "hyprland" themeList) '' + mkdir -p $out/hyprland + cp "${sources.hyprland}/themes/${variant}.conf" "$out/hyprland/" +-- +2.42.0 + diff --git a/nixpkgs-patches/0001-catppuccin-add-starship-theme.patch b/nixpkgs-patches/0002-catppuccin-add-starship-theme.patch similarity index 73% rename from nixpkgs-patches/0001-catppuccin-add-starship-theme.patch rename to nixpkgs-patches/0002-catppuccin-add-starship-theme.patch index 217f681..18bcd0a 100644 --- a/nixpkgs-patches/0001-catppuccin-add-starship-theme.patch +++ b/nixpkgs-patches/0002-catppuccin-add-starship-theme.patch @@ -1,25 +1,24 @@ -From 8a73b27f67158e8161fc33a61cae2ebd3aa6c625 Mon Sep 17 00:00:00 2001 +From 93af02433861cd32221164ddb4fc03b19cbf776b Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Sat, 13 Jan 2024 18:41:51 +0100 -Subject: [PATCH] catppuccin: add starship theme +Subject: [PATCH 2/2] catppuccin: add starship theme -(cherry picked from commit cf1dfaa32a0201cc14801ebb93b5ef865d42522a) --- pkgs/data/themes/catppuccin/default.nix | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pkgs/data/themes/catppuccin/default.nix b/pkgs/data/themes/catppuccin/default.nix -index 59e030eb9e0e..6db2679a9d72 100644 +index e8cdb0456d17..6ac8cc541ad3 100644 --- a/pkgs/data/themes/catppuccin/default.nix +++ b/pkgs/data/themes/catppuccin/default.nix @@ -1,5 +1,5 @@ let -- validThemes = [ "bat" "bottom" "btop" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "refind" "rofi" "waybar" ]; -+ validThemes = [ "bat" "bottom" "btop" "grub" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "qt5ct" "refind" "rofi" "starship" "waybar" ]; +- validThemes = [ "bat" "bottom" "btop" "grub" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "refind" "rofi" "waybar" ]; ++ validThemes = [ "bat" "bottom" "btop" "grub" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "refind" "rofi" "starship" "waybar" ]; in { fetchFromGitHub , lib -@@ -96,6 +96,14 @@ let +@@ -104,6 +104,14 @@ let hash = "sha256-DNorfyl3C4RBclF2KDgwvQQwixpTwSRu7fIvihPN8JY="; }; @@ -34,7 +33,7 @@ index 59e030eb9e0e..6db2679a9d72 100644 waybar = fetchFromGitHub { name = "waybar"; owner = "catppuccin"; -@@ -171,6 +179,10 @@ stdenvNoCC.mkDerivation { +@@ -183,6 +191,10 @@ stdenvNoCC.mkDerivation { cp ${sources.refind}/${variant}.conf $out/refind/ cp -r ${sources.refind}/assets/${variant} $out/refind/assets/ From 58ce37c65f2e83af27e75188ad8e340cc6700535 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 23 Jan 2024 09:27:16 +0100 Subject: [PATCH 0382/1125] Flake: update plasma-manager --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 2ab26b5..af1c12c 100644 --- a/flake.lock +++ b/flake.lock @@ -324,11 +324,11 @@ ] }, "locked": { - "lastModified": 1705257805, - "narHash": "sha256-hx88TjxRWR9hEYrePm2aR/rKAu4VFx4irgN7AofE0Wg=", + "lastModified": 1705946102, + "narHash": "sha256-0hy28d7qC7Hv6/KV7xefa03b2xFJIGHPYAPcsVwzTeM=", "owner": "pjones", "repo": "plasma-manager", - "rev": "87ca0e29c6fccfb7f09be6ff137716db5a7c8d8f", + "rev": "4d209a083aeefa7d4f8060de14896399bbc8f30b", "type": "github" }, "original": { From 5c0fe687389df4d0cbc2b46db16b57e8a3169390 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 23 Jan 2024 09:27:30 +0100 Subject: [PATCH 0383/1125] Kde/plasma: set up widget settings --- roles/kde/plasma.nix | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 8586528..9915ba9 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -110,19 +110,20 @@ in location = "bottom"; height = 44; widgets = [ - "org.kde.plasma.kickoff" + { + name = "org.kde.plasma.kickoff"; + config.General.icon = "nix-snowflake-white"; + } "org.kde.plasma.pager" "org.kde.plasma.icontasks" "org.kde.plasma.marginsseparator" "org.kde.plasma.systemtray" - "org.kde.plasma.digitalclock" + { + name = "org.kde.plasma.digitalclock"; + config.Appearance.showSeconds = "true"; + } "org.kde.plasma.showdesktop" ]; - extraSettings = '' - currentWidget = panelWidgets["org.kde.plasma.kickoff"] - currentWidget.currentConfigGroup = ["General"] - currentWidget.writeConfig("icon", "nix-snowflake-white") - ''; }]; shortcuts = { "kwin" = { From a40268476cd2122021fe55a2524f830194f006c9 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 24 Jan 2024 09:27:56 +0100 Subject: [PATCH 0384/1125] Desktop/flatpak: uninstall unmanaged packages --- roles/desktop/services/flatpak.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/services/flatpak.nix b/roles/desktop/services/flatpak.nix index 5a6834c..20903f8 100644 --- a/roles/desktop/services/flatpak.nix +++ b/roles/desktop/services/flatpak.nix @@ -8,6 +8,7 @@ users.toast = { services.flatpak = { packages = [ "tv.plex.PlexDesktop" ]; + uninstallUnmanagedPackages = true; update.auto = { enable = true; onCalendar = "weekly"; From 1311ab275a5d6ef2d5826980e81c281b4bfbf84d Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 24 Jan 2024 09:31:38 +0100 Subject: [PATCH 0385/1125] Gaming/steam: install olympus --- roles/gaming/programs/steam.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/gaming/programs/steam.nix b/roles/gaming/programs/steam.nix index 27a1a33..372a707 100644 --- a/roles/gaming/programs/steam.nix +++ b/roles/gaming/programs/steam.nix @@ -8,4 +8,9 @@ }; # Some linux native games (rise of the tomb raider) use alsa for sound services.pipewire.alsa.enable = if config.services.pipewire.pulse.enable == true then true else false; + + # Celeste mod manager + home-manager.users.toast.services.flatpak.packages = [ + "io.github.everestapi.Olympus" + ]; } From 8d0aab3e22eb4968c014f161644d1c22a64b886d Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 24 Jan 2024 09:43:40 +0100 Subject: [PATCH 0386/1125] Flake: add nix-gaming --- flake.lock | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 5 +++++ 2 files changed, 63 insertions(+) diff --git a/flake.lock b/flake.lock index af1c12c..abd9cdd 100644 --- a/flake.lock +++ b/flake.lock @@ -59,6 +59,24 @@ "type": "github" } }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1704982712, + "narHash": "sha256-2Ptt+9h8dczgle2Oo6z5ni5rt/uLMG47UFTR1ry/wgg=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "07f6395285469419cf9d078f59b5b49993198c00", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems_2" @@ -176,6 +194,27 @@ "type": "github" } }, + "nix-gaming": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": [ + "nixpkgs-unstable-raw" + ] + }, + "locked": { + "lastModified": 1705972904, + "narHash": "sha256-tFTnkEf204Qd+EncVneGBZi/vqzU97Ody9JtWuOrYNE=", + "owner": "fufexan", + "repo": "nix-gaming", + "rev": "ec1ddf5032735e68b2bbde3cee9b536ea89c6fec", + "type": "github" + }, + "original": { + "owner": "fufexan", + "repo": "nix-gaming", + "type": "github" + } + }, "nix-github-actions": { "inputs": { "nixpkgs": [ @@ -269,6 +308,24 @@ "type": "github" } }, + "nixpkgs-lib": { + "locked": { + "dir": "lib", + "lastModified": 1703961334, + "narHash": "sha256-M1mV/Cq+pgjk0rt6VxoyyD+O8cOUiai8t9Q6Yyq4noY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b0d36bd0a420ecee3bc916c91886caca87c894e9", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs-raw": { "locked": { "lastModified": 1705641746, @@ -345,6 +402,7 @@ "home-manager-unstable": "home-manager-unstable", "jovian": "jovian", "nix-flatpak": "nix-flatpak", + "nix-gaming": "nix-gaming", "nix-impermanence": "nix-impermanence", "nix-index-db": "nix-index-db", "nix-index-db-unstable": "nix-index-db-unstable", diff --git a/flake.nix b/flake.nix index d7c2400..3a37f46 100644 --- a/flake.nix +++ b/flake.nix @@ -65,6 +65,11 @@ nix-flatpak.url = github:gmodena/nix-flatpak/main; nur.url = "github:nix-community/NUR"; + + nix-gaming = { + url = "github:fufexan/nix-gaming"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; + }; }; outputs = { ... } @inputs: with inputs; From 232963fffd22a11a8ef5a1d578e3defe812de749 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 24 Jan 2024 09:43:56 +0100 Subject: [PATCH 0387/1125] Gaming/steam: add proton-ge --- roles/gaming/programs/steam.nix | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/roles/gaming/programs/steam.nix b/roles/gaming/programs/steam.nix index 372a707..a0bb791 100644 --- a/roles/gaming/programs/steam.nix +++ b/roles/gaming/programs/steam.nix @@ -1,11 +1,31 @@ -{ config, pkgs, ... }: +{ config, flakeSelf, ... }: + +let + nix-gaming = flakeSelf.inputs.nix-gaming; +in { + # Get the nix-gaming module + imports = [ + nix-gaming.nixosModules.steamCompat + ]; + programs.steam = { enable = true; # Doubt that I'll use it, but I'll enable it anyways remotePlay.openFirewall = true; + + extraCompatPackages = with nix-gaming.packages.x86_64-linux; [ + proton-ge + ]; }; + + # Use nix-gaming's cachix + nix.settings = { + substituters = ["https://nix-gaming.cachix.org"]; + trusted-public-keys = ["nix-gaming.cachix.org-1:nbjlureqMbRAxR1gJ/f3hxemL9svXaZF/Ees8vCUUs4="]; + }; + # Some linux native games (rise of the tomb raider) use alsa for sound services.pipewire.alsa.enable = if config.services.pipewire.pulse.enable == true then true else false; From 50097d8c510e9570a09eeecc486961e1800709c0 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 24 Jan 2024 09:45:49 +0100 Subject: [PATCH 0388/1125] Gaming/retroarch: share saves with WinMax2 --- roles/gaming/programs/retroarch.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index 72bd0e8..5f47ca2 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -85,7 +85,7 @@ in "retroarch" = { label = "RetroArch"; id = "jxuou-2yjnu"; - devices = [ "steamdeck" "server" "pc" ]; + devices = [ "steamdeck" "server" "pc" "winmax2" ]; path = "~/.local/share/retroarch"; }; }; From 6769536ec7eebdfae4620c9c2197f9bcb499f06b Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 25 Jan 2024 09:23:07 +0100 Subject: [PATCH 0389/1125] Flake: add nixpkgs pr 277661 --- flake.nix | 1 + nixpkgs-patches/pr277661.patch | 336 +++++++++++++++++++++++++++++++++ 2 files changed, 337 insertions(+) create mode 100644 nixpkgs-patches/pr277661.patch diff --git a/flake.nix b/flake.nix index 3a37f46..57d78bc 100644 --- a/flake.nix +++ b/flake.nix @@ -81,6 +81,7 @@ src = nixpkgs-unstable-raw; patches = [ ./nixpkgs-patches/pr281207.patch + ./nixpkgs-patches/pr277661.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr277661.patch b/nixpkgs-patches/pr277661.patch new file mode 100644 index 0000000..17ec03c --- /dev/null +++ b/nixpkgs-patches/pr277661.patch @@ -0,0 +1,336 @@ +From bcf9a24332a04ddcef154b792697320d40829820 Mon Sep 17 00:00:00 2001 +From: Brenton Simpson +Date: Mon, 1 Jan 2024 16:18:45 -0800 +Subject: [PATCH 1/5] handheld-daemon: init at 0.2.7 + +--- + .../manual/release-notes/rl-2405.section.md | 2 + + nixos/modules/module-list.nix | 1 + + .../services/hardware/handheld-daemon.nix | 43 +++++++++++++++ + pkgs/by-name/ha/handheld-daemon/package.nix | 54 +++++++++++++++++++ + 4 files changed, 100 insertions(+) + create mode 100644 nixos/modules/services/hardware/handheld-daemon.nix + create mode 100644 pkgs/by-name/ha/handheld-daemon/package.nix + +diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md +index f4434fd6b94cac..3ddc2f781bd968 100644 +--- a/nixos/doc/manual/release-notes/rl-2405.section.md ++++ b/nixos/doc/manual/release-notes/rl-2405.section.md +@@ -22,6 +22,8 @@ In addition to numerous new and upgraded packages, this release has the followin + + + ++- [Handheld Daemon](https://github.com/hhd-dev/hhd), support for gaming handhelds like the Legion Go, ROG Ally, and GPD Win. Available as [services.handheldDaemon](#opt-services.handheldDaemon.enable). ++ + - [Guix](https://guix.gnu.org), a functional package manager inspired by Nix. Available as [services.guix](#opt-services.guix.enable). + + - [maubot](https://github.com/maubot/maubot), a plugin-based Matrix bot framework. Available as [services.maubot](#opt-services.maubot.enable). +diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix +index 00e6240f531d52..154fd8df2ce08d 100644 +--- a/nixos/modules/module-list.nix ++++ b/nixos/modules/module-list.nix +@@ -532,6 +532,7 @@ + ./services/hardware/fancontrol.nix + ./services/hardware/freefall.nix + ./services/hardware/fwupd.nix ++ ./services/hardware/handheld-daemon.nix + ./services/hardware/hddfancontrol.nix + ./services/hardware/illum.nix + ./services/hardware/interception-tools.nix +diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix +new file mode 100644 +index 00000000000000..a513ed7ddf8efe +--- /dev/null ++++ b/nixos/modules/services/hardware/handheld-daemon.nix +@@ -0,0 +1,43 @@ ++{ config ++, lib ++, pkgs ++, ... ++}: ++with lib; let ++ cfg = config.services.handheldDaemon; ++in ++{ ++ options.services.handheldDaemon = { ++ enable = mkEnableOption "Enable Handheld Daemon"; ++ ++ user = mkOption { ++ type = types.str; ++ description = lib.mdDoc '' ++ The user to run Handheld Daemon with. ++ ''; ++ }; ++ }; ++ ++ config = mkIf cfg.enable { ++ environment.systemPackages = [ pkgs.handheld-daemon ]; ++ services.udev.packages = [ pkgs.handheld-daemon ]; ++ systemd.packages = [ pkgs.handheld-daemon ]; ++ ++ systemd.services.handheldDaemon = { ++ description = "Handheld Daemon"; ++ ++ wantedBy = [ "multi-user.target" ]; ++ ++ restartIfChanged = true; ++ ++ serviceConfig = { ++ ExecStart = "${ pkgs.handheld-daemon }/bin/hhd --user ${ cfg.user }"; ++ Nice = "-12"; ++ Restart = "on-failure"; ++ RestartSec = "10"; ++ }; ++ }; ++ }; ++ ++ meta.maintainers = [ maintainers.appsforartists ]; ++} +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +new file mode 100644 +index 00000000000000..b8b14d85f45bf7 +--- /dev/null ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -0,0 +1,54 @@ ++{ config ++, fetchFromGitHub ++, hidapi ++, lib ++, python3 ++, ++}: ++python3.pkgs.buildPythonApplication rec { ++ pname = "handheld-daemon"; ++ version = "0.2.7"; ++ format = "pyproject"; ++ ++ src = fetchFromGitHub { ++ owner = "hhd-dev"; ++ repo = "hhd"; ++ rev = "ccae6b207cadfbdaef292270c4fc6c855f71ba03"; ++ hash = "sha256-+tyiXOvZXLbomhgFRKUNKGbkkkOxQKdk/kjeWZ4pvO0="; ++ }; ++ ++ pythonPath = with python3.pkgs; [ ++ evdev ++ pyyaml ++ rich ++ ]; ++ ++ nativeBuildInputs = with python3.pkgs; [ ++ setuptools ++ ]; ++ ++ propagatedBuildInputs = [ ++ hidapi ++ ]; ++ ++ # handheld-daemon contains a fork of the python module `hid`, so this hook ++ # is borrowed from the `hid` derivation. ++ postPatch = '' ++ hidapi=${ hidapi }/lib/ ++ test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } ++ sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py ++ ''; ++ ++ postInstall = '' ++ install -Dm644 $src/usr/lib/udev/rules.d/83-hhd.rules -t $out/lib/udev/rules.d/ ++ ''; ++ ++ meta = with lib; { ++ homepage = "https://github.com/hhd-dev/hhd/"; ++ description = "Linux support for gaming handhelds"; ++ platforms = platforms.linux; ++ license = licenses.mit; ++ maintainers = with maintainers; [ appsforartists ]; ++ mainProgram = "hhd"; ++ }; ++} + +From 52f22bfc57dff00a93343e30a42e434b68062196 Mon Sep 17 00:00:00 2001 +From: Brenton Simpson +Date: Wed, 17 Jan 2024 09:52:06 -0800 +Subject: [PATCH 2/5] handheld-daemon: 0.27 -> 1.0.8 + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index b8b14d85f45bf7..f590665a8292fa 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -3,18 +3,17 @@ + , hidapi + , lib + , python3 +-, + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "0.2.7"; ++ version = "1.0.8"; + format = "pyproject"; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; +- rev = "ccae6b207cadfbdaef292270c4fc6c855f71ba03"; +- hash = "sha256-+tyiXOvZXLbomhgFRKUNKGbkkkOxQKdk/kjeWZ4pvO0="; ++ rev = "6cb83a9833eebc81bd27bed57eb68ece15cdd7a6"; ++ hash = "sha256-YfBi5UKaB+v+eDI8rcvqkogAYRU2kTc0NqvakhKxBOE="; + }; + + pythonPath = with python3.pkgs; [ + +From f571033ce013a416c744bd3d3ffc0fe525dbe3a9 Mon Sep 17 00:00:00 2001 +From: Brenton Simpson +Date: Sat, 20 Jan 2024 17:56:44 -0800 +Subject: [PATCH 3/5] handheld-daemon: use kebab-case instead of camelCase for + service name + +--- + nixos/doc/manual/release-notes/rl-2405.section.md | 2 +- + nixos/modules/services/hardware/handheld-daemon.nix | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md +index 3ddc2f781bd968..994f642154619c 100644 +--- a/nixos/doc/manual/release-notes/rl-2405.section.md ++++ b/nixos/doc/manual/release-notes/rl-2405.section.md +@@ -22,7 +22,7 @@ In addition to numerous new and upgraded packages, this release has the followin + + + +-- [Handheld Daemon](https://github.com/hhd-dev/hhd), support for gaming handhelds like the Legion Go, ROG Ally, and GPD Win. Available as [services.handheldDaemon](#opt-services.handheldDaemon.enable). ++- [Handheld Daemon](https://github.com/hhd-dev/hhd), support for gaming handhelds like the Legion Go, ROG Ally, and GPD Win. Available as [services.handheld-daemon](#opt-services.handheld-daemon.enable). + + - [Guix](https://guix.gnu.org), a functional package manager inspired by Nix. Available as [services.guix](#opt-services.guix.enable). + +diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix +index a513ed7ddf8efe..81859bf5b122fe 100644 +--- a/nixos/modules/services/hardware/handheld-daemon.nix ++++ b/nixos/modules/services/hardware/handheld-daemon.nix +@@ -4,10 +4,10 @@ + , ... + }: + with lib; let +- cfg = config.services.handheldDaemon; ++ cfg = config.services.handheld-daemon; + in + { +- options.services.handheldDaemon = { ++ options.services.handheld-daemon = { + enable = mkEnableOption "Enable Handheld Daemon"; + + user = mkOption { +@@ -23,7 +23,7 @@ in + services.udev.packages = [ pkgs.handheld-daemon ]; + systemd.packages = [ pkgs.handheld-daemon ]; + +- systemd.services.handheldDaemon = { ++ systemd.services.handheld-daemon = { + description = "Handheld Daemon"; + + wantedBy = [ "multi-user.target" ]; + +From 75516996fe8b29d970e2eae003c67c07ef3ae206 Mon Sep 17 00:00:00 2001 +From: Brenton Simpson +Date: Mon, 22 Jan 2024 11:12:04 -0800 +Subject: [PATCH 4/5] handheld-daemon: make package overrideable + +Co-authored-by: h7x4 +--- + nixos/modules/services/hardware/handheld-daemon.nix | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix +index 81859bf5b122fe..154380985bf05d 100644 +--- a/nixos/modules/services/hardware/handheld-daemon.nix ++++ b/nixos/modules/services/hardware/handheld-daemon.nix +@@ -9,6 +9,7 @@ in + { + options.services.handheld-daemon = { + enable = mkEnableOption "Enable Handheld Daemon"; ++ package = mkPackageOption pkgs "handheld-daemon" { }; + + user = mkOption { + type = types.str; +@@ -19,9 +20,9 @@ in + }; + + config = mkIf cfg.enable { +- environment.systemPackages = [ pkgs.handheld-daemon ]; +- services.udev.packages = [ pkgs.handheld-daemon ]; +- systemd.packages = [ pkgs.handheld-daemon ]; ++ environment.systemPackages = [ cfg.package ]; ++ services.udev.packages = [ cfg.package ]; ++ systemd.packages = [ cfg.package ]; + + systemd.services.handheld-daemon = { + description = "Handheld Daemon"; +@@ -31,7 +32,7 @@ in + restartIfChanged = true; + + serviceConfig = { +- ExecStart = "${ pkgs.handheld-daemon }/bin/hhd --user ${ cfg.user }"; ++ ExecStart = "${ cfg.package }/bin/hhd --user ${ cfg.user }"; + Nice = "-12"; + Restart = "on-failure"; + RestartSec = "10"; + +From 3bc83885805347e099ab0e6469875b23edb5698e Mon Sep 17 00:00:00 2001 +From: Brenton Simpson +Date: Mon, 22 Jan 2024 11:13:15 -0800 +Subject: [PATCH 5/5] handheld-daemon: 1.0.8 -> 1.1.0 + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index f590665a8292fa..e037c4da70868b 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -1,19 +1,21 @@ + { config + , fetchFromGitHub + , hidapi ++, kmod + , lib + , python3 ++, toybox + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "1.0.8"; ++ version = "1.1.0"; + format = "pyproject"; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; +- rev = "6cb83a9833eebc81bd27bed57eb68ece15cdd7a6"; +- hash = "sha256-YfBi5UKaB+v+eDI8rcvqkogAYRU2kTc0NqvakhKxBOE="; ++ rev = "abe34c6841476f5b41afe30ee18ff3e510402d68"; ++ hash = "sha256-ovLC1BQ98jUaDEMPBzWma4TYSzTF+yE/cMemFdJmqlE="; + }; + + pythonPath = with python3.pkgs; [ +@@ -22,12 +24,11 @@ python3.pkgs.buildPythonApplication rec { + rich + ]; + +- nativeBuildInputs = with python3.pkgs; [ +- setuptools +- ]; +- +- propagatedBuildInputs = [ ++ propagatedBuildInputs = with python3.pkgs; [ + hidapi ++ kmod ++ setuptools ++ toybox + ]; + + # handheld-daemon contains a fork of the python module `hid`, so this hook From 8fad5e1f92624008b434e54f8d4e170741b89623 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 25 Jan 2024 09:24:34 +0100 Subject: [PATCH 0390/1125] Machines/WinMax2: enable handheld daemon --- machines/WinMax2/configuration.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 2657f7d..9631173 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -42,6 +42,11 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="GXTP7385:00", ATTR{power/wakeup}=" ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="disabled" ''; + services.handheld-daemon = { + enable = true; + user = "root"; + }; + # Allow unfree packages nixpkgs.config.allowUnfree = true; From 9f79cc18902d55845ac4dea3c0a9275ad2aa44a0 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 25 Jan 2024 09:25:19 +0100 Subject: [PATCH 0391/1125] Common: override handheld-daemon source --- roles/common/configuration.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 8809576..722824f 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -79,6 +79,14 @@ "grub" ]; }; + handheld-daemon = prev.handheld-daemon.overridePythonAttrs { + src = pkgs.fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + rev = "d50e59afb0180a70cb9ff4204fe589032e6b082f"; + hash = "sha256-DczxvbHvTle84sDIJgYfVTMHQqTAXmiEiFa5/L1A++o="; + }; + }; } ) ]; From 41e7112fce036f5c6b6949b6542bcddb187a63e1 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 25 Jan 2024 10:49:58 +0100 Subject: [PATCH 0392/1125] Desktop/discord: install using home manager --- roles/desktop/programs/discord.nix | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 8f81f98..db431ab 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -32,8 +32,10 @@ }; nixpkgs.overlays = [ discordOverlay ]; - users.users.toast.packages = with pkgs; [ - discord - vesktop - ]; + home-manager.users.toast = { + home.packages = with pkgs; [ + discord + vesktop + ]; + }; } From 1bb7eeb88e1cea8c07604f225ce615d6fa28fc7f Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Jan 2024 09:46:21 +0100 Subject: [PATCH 0393/1125] Revert "Machines/WinMax2: use linux 6.6" This reverts commit 70202144a539a37442df8916493c5eb8d7f5d7bf. --- machines/WinMax2/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 9631173..ed0fd93 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -29,7 +29,7 @@ # Plymouth doesn't support fractional scaling :( plymouth.extraConfig = "DeviceScale=2"; - kernelPackages = pkgs.linuxPackages_6_6; + kernelPackages = pkgs.linuxPackages_latest; }; networking.hostName = "WinMax2"; # Define your hostname. From 2448bc421a86477639373a73e44301ae02bbf107 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Jan 2024 09:46:55 +0100 Subject: [PATCH 0394/1125] Common: update hhd overlay --- roles/common/configuration.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 722824f..3b30960 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -83,9 +83,10 @@ src = pkgs.fetchFromGitHub { owner = "hhd-dev"; repo = "hhd"; - rev = "d50e59afb0180a70cb9ff4204fe589032e6b082f"; - hash = "sha256-DczxvbHvTle84sDIJgYfVTMHQqTAXmiEiFa5/L1A++o="; + rev = "8cc8c7143a5f35c6dd0c6036c6058f05220c2834"; + hash = "sha256-Jrk7LFCL0kdqFasPRuuEXNtQ5AY34/kJjw8Cqeg8bXc="; }; + version = "1.1.2"; }; } ) From cfaf6ddd9d413b3b3850fffcc39feca7a7277bef Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Jan 2024 10:02:53 +0100 Subject: [PATCH 0395/1125] Flake: update lock file --- flake.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/flake.lock b/flake.lock index abd9cdd..5dfdea4 100644 --- a/flake.lock +++ b/flake.lock @@ -123,11 +123,11 @@ ] }, "locked": { - "lastModified": 1705823474, - "narHash": "sha256-2C4uRe9/U3QwSPC4dYKM1/njgCQk0Mltezy4VcjAqa4=", + "lastModified": 1706221476, + "narHash": "sha256-T4b8YafVjHXvtDY8ARec1WrXO8uyyNZOpNgv9yoQy2M=", "owner": "nix-community", "repo": "home-manager", - "rev": "928f2528f9ee952ba0a47bbb1ece8d93ed66e784", + "rev": "c7ce343d9bf1a329056a4dd5b32ea8cc43b55e15", "type": "github" }, "original": { @@ -180,11 +180,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1705758212, - "narHash": "sha256-96kbUcT7hvFPhs5vHqSLAQOCwsRojlmWa0+VpR6lrrE=", + "lastModified": 1706131725, + "narHash": "sha256-HK/maOUUo+4tKL06VSV5szJXTtc7QqcO9F5c0FGi2F8=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "09d2dd72de3b9a7ef71f3013a15d34c649b83277", + "rev": "dfa162fab581ba293f5faa866e91c553b78a01aa", "type": "github" }, "original": { @@ -202,11 +202,11 @@ ] }, "locked": { - "lastModified": 1705972904, - "narHash": "sha256-tFTnkEf204Qd+EncVneGBZi/vqzU97Ody9JtWuOrYNE=", + "lastModified": 1706145483, + "narHash": "sha256-omDJXQPBNCFGjSSP4X3mlITdmgfkJ3wrlLN1RhR6ld0=", "owner": "fufexan", "repo": "nix-gaming", - "rev": "ec1ddf5032735e68b2bbde3cee9b536ea89c6fec", + "rev": "b9f77409aad6976efdae3b05523a07b328920c97", "type": "github" }, "original": { @@ -294,11 +294,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1705312285, - "narHash": "sha256-rd+dY+v61Y8w3u9bukO/hB55Xl4wXv4/yC8rCGVnK5U=", + "lastModified": 1706182238, + "narHash": "sha256-Ti7CerGydU7xyrP/ow85lHsOpf+XMx98kQnPoQCSi1g=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "bee2202bec57e521e3bd8acd526884b9767d7fa0", + "rev": "f84eaffc35d1a655e84749228cde19922fcf55f1", "type": "github" }, "original": { @@ -328,11 +328,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1705641746, - "narHash": "sha256-D6c2aH8HQbWc7ZWSV0BUpFpd94ImFyCP8jFIsKQ4Slg=", + "lastModified": 1706098335, + "narHash": "sha256-r3dWjT8P9/Ah5m5ul4WqIWD8muj5F+/gbCdjiNVBKmU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d2003f2223cbb8cd95134e4a0541beea215c1073", + "rev": "a77ab169a83a4175169d78684ddd2e54486ac651", "type": "github" }, "original": { @@ -343,11 +343,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1705677747, - "narHash": "sha256-eyM3okYtMgYDgmYukoUzrmuoY4xl4FUujnsv/P6I/zI=", + "lastModified": 1705856552, + "narHash": "sha256-JXfnuEf5Yd6bhMs/uvM67/joxYKoysyE3M2k6T3eWbg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bbe7d8f876fbbe7c959c90ba2ae2852220573261", + "rev": "612f97239e2cc474c13c9dafa0df378058c5ad8d", "type": "github" }, "original": { @@ -358,11 +358,11 @@ }, "nur": { "locked": { - "lastModified": 1705847594, - "narHash": "sha256-YtoT6OoTIkYcwm+VPeqn+cJhyacd/WIMtBoBEvRDYVY=", + "lastModified": 1706251467, + "narHash": "sha256-uR6TEvf0PNFgIKLTImc4mt00qS7H5op9r7B++vdj2Io=", "owner": "nix-community", "repo": "NUR", - "rev": "2b4a30cde35eb5b7813c731aa26fc475a27c723e", + "rev": "1e00872abadba03e57c74975b05527e418620986", "type": "github" }, "original": { @@ -453,11 +453,11 @@ ] }, "locked": { - "lastModified": 1705800393, - "narHash": "sha256-/aO8yu7r4fw+YFq/PWa0VErBDVVK9iDt1cqmLd/c7Lo=", + "lastModified": 1706232054, + "narHash": "sha256-AjwmVarytm50C6CNvybuabXhu0zewLOXuxcmuiGyz8U=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "1823c666b159fec04d9c2bafc37b8f190e885e01", + "rev": "e7db4235e6fcdff0d55925b4309bf8fe900501f0", "type": "github" }, "original": { From 49809407d5924eacf92ba20213f18ed3c2a77e7f Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 27 Jan 2024 22:57:48 +0100 Subject: [PATCH 0396/1125] Machines/WinMax2: add the finals fix --- machines/WinMax2/configuration.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index ed0fd93..c536ace 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -36,7 +36,11 @@ networking.networkmanager.enable = true; # Enable networking # Sleep fixes - boot.kernelParams = [ "rtc_cmos.use_acpi_alarm=1" ]; + boot.kernelParams = [ + # This doesn't fix sleeping, but it (should) fix The Finals + "clearcpuid=304" + "rtc_cmos.use_acpi_alarm=1" + ]; services.udev.extraRules = '' ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="GXTP7385:00", ATTR{power/wakeup}="disabled" ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="disabled" From 0156f17eea61aa786b142ea2fa1d2e272d3cb233 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Jan 2024 09:27:04 +0100 Subject: [PATCH 0397/1125] Machines/WinMax2: move the finals fix to specialistion --- machines/WinMax2/configuration.nix | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index c536ace..d622c7b 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -35,12 +35,13 @@ networking.hostName = "WinMax2"; # Define your hostname. networking.networkmanager.enable = true; # Enable networking + specialisation.noAVX512.configuration = { + # For some reason The Finals crashes on CPUs that support AVX512 + boot.kernelParams = [ "clearcpuid=304" ]; + }; + # Sleep fixes - boot.kernelParams = [ - # This doesn't fix sleeping, but it (should) fix The Finals - "clearcpuid=304" - "rtc_cmos.use_acpi_alarm=1" - ]; + boot.kernelParams = [ "rtc_cmos.use_acpi_alarm=1" ]; services.udev.extraRules = '' ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="GXTP7385:00", ATTR{power/wakeup}="disabled" ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="disabled" From 92eabd4b92458454fef085e651e2b06181bb6338 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Jan 2024 09:51:27 +0100 Subject: [PATCH 0398/1125] Flake: remove unused nixpkgs patch --- flake.nix | 1 - nixpkgs-patches/pr281207.patch | 117 --------------------------------- 2 files changed, 118 deletions(-) delete mode 100644 nixpkgs-patches/pr281207.patch diff --git a/flake.nix b/flake.nix index 57d78bc..0e0e713 100644 --- a/flake.nix +++ b/flake.nix @@ -80,7 +80,6 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/pr281207.patch ./nixpkgs-patches/pr277661.patch ]; }; diff --git a/nixpkgs-patches/pr281207.patch b/nixpkgs-patches/pr281207.patch deleted file mode 100644 index c9bea43..0000000 --- a/nixpkgs-patches/pr281207.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 1f3bcdf27686e9d2c43a53cf3ba7cd0ee7978ff5 Mon Sep 17 00:00:00 2001 -From: TomaSajt <62384384+TomaSajt@users.noreply.github.com> -Date: Tue, 16 Jan 2024 00:58:48 +0100 -Subject: [PATCH] mysql-workbench: fix build, small refactor - ---- - .../misc/mysql-workbench/default.nix | 28 ++++++++++++------- - .../misc/mysql-workbench/fix-xml2.patch | 25 +++++++++++++++++ - 2 files changed, 43 insertions(+), 10 deletions(-) - create mode 100644 pkgs/applications/misc/mysql-workbench/fix-xml2.patch - -diff --git a/pkgs/applications/misc/mysql-workbench/default.nix b/pkgs/applications/misc/mysql-workbench/default.nix -index ff9fb7c6b2cbe2..6b5933b3ebd0fd 100644 ---- a/pkgs/applications/misc/mysql-workbench/default.nix -+++ b/pkgs/applications/misc/mysql-workbench/default.nix -@@ -1,4 +1,5 @@ --{ lib, stdenv -+{ lib -+, stdenv - , fetchurl - , substituteAll - , cmake -@@ -44,13 +45,14 @@ - - let - inherit (python3.pkgs) paramiko pycairo pyodbc; --in stdenv.mkDerivation rec { -+in -+stdenv.mkDerivation (finalAttrs: { - pname = "mysql-workbench"; - version = "8.0.34"; - - src = fetchurl { -- url = "https://cdn.mysql.com//Downloads/MySQLGUITools/mysql-workbench-community-${version}-src.tar.gz"; -- sha256 = "sha256-ub/D6HRtXOvX+lai71t1UjMmMzBsz5ljCrJCuf9aq7U="; -+ url = "https://cdn.mysql.com/Downloads/MySQLGUITools/mysql-workbench-community-${finalAttrs.version}-src.tar.gz"; -+ hash = "sha256-ub/D6HRtXOvX+lai71t1UjMmMzBsz5ljCrJCuf9aq7U="; - }; - - patches = [ -@@ -75,6 +77,9 @@ in stdenv.mkDerivation rec { - src = ./fix-swig-build.patch; - cairoDev = "${cairo.dev}"; - }) -+ -+ # a newer libxml2 version has changed some interfaces -+ ./fix-xml2.patch - ]; - - # 1. have it look for 4.12.0 instead of 4.11.1 -@@ -138,6 +143,10 @@ in stdenv.mkDerivation rec { - patchShebangs tools/get_wb_version.sh - ''; - -+ # GCC 13: error: 'int64_t' in namespace 'std' does not name a type -+ # when updating the version make sure this is still needed -+ env.CXXFLAGS = "-include cstdint"; -+ - env.NIX_CFLAGS_COMPILE = toString ([ - # error: 'OGRErr OGRSpatialReference::importFromWkt(char**)' is deprecated - "-Wno-error=deprecated-declarations" -@@ -183,7 +192,7 @@ in stdenv.mkDerivation rec { - done - ''; - -- meta = with lib; { -+ meta = { - description = "Visual MySQL database modeling, administration and querying tool"; - longDescription = '' - MySQL Workbench is a modeling tool that allows you to design -@@ -191,11 +200,10 @@ in stdenv.mkDerivation rec { - and query development modules where you can manage MySQL server instances - and execute SQL queries. - ''; -- - homepage = "http://wb.mysql.com/"; -- license = licenses.gpl2; -- maintainers = [ ]; -- platforms = platforms.linux; -+ license = lib.licenses.gpl2Only; - mainProgram = "mysql-workbench"; -+ maintainers = with lib.maintainers; [ tomasajt ]; -+ platforms = lib.platforms.linux; - }; --} -+}) -diff --git a/pkgs/applications/misc/mysql-workbench/fix-xml2.patch b/pkgs/applications/misc/mysql-workbench/fix-xml2.patch -new file mode 100644 -index 00000000000000..857c3f9add4cae ---- /dev/null -+++ b/pkgs/applications/misc/mysql-workbench/fix-xml2.patch -@@ -0,0 +1,25 @@ -+diff --git a/library/grt/src/grt.h b/library/grt/src/grt.h -+index 47bfd63..59e664b 100644 -+--- a/library/grt/src/grt.h -++++ b/library/grt/src/grt.h -+@@ -35,6 +35,7 @@ -+ #include -+ #include -+ #include -++#include -+ #include "base/threading.h" -+ #include -+ #include -+diff --git a/library/grt/src/unserializer.cpp b/library/grt/src/unserializer.cpp -+index 6dda76d..a6f6a3c 100644 -+--- a/library/grt/src/unserializer.cpp -++++ b/library/grt/src/unserializer.cpp -+@@ -401,7 +401,7 @@ ValueRef internal::Unserializer::unserialize_xmldata(const char *data, size_t si -+ xmlDocPtr doc = xmlReadMemory(data, (int)size, NULL, NULL, XML_PARSE_NOENT); -+ -+ if (!doc) { -+- xmlErrorPtr error = xmlGetLastError(); -++ const xmlError* error = xmlGetLastError(); -+ -+ if (error) -+ throw std::runtime_error(base::strfmt("Could not parse XML data. Line %d, %s", error->line, error->message)); From f308ecaa72f5c99c914cefcb4089c9f2ffa5fb74 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Jan 2024 09:53:53 +0100 Subject: [PATCH 0399/1125] Flake: get rid of url literal --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 0e0e713..6f78a57 100644 --- a/flake.nix +++ b/flake.nix @@ -62,7 +62,7 @@ inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; }; - nix-flatpak.url = github:gmodena/nix-flatpak/main; + nix-flatpak.url = "github:gmodena/nix-flatpak/main"; nur.url = "github:nix-community/NUR"; From 25d981a1a0567e3cdbf64210d259499a6405a105 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Jan 2024 10:06:55 +0100 Subject: [PATCH 0400/1125] Flake: update lock file --- flake.lock | 60 +++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/flake.lock b/flake.lock index 5dfdea4..79e8ee6 100644 --- a/flake.lock +++ b/flake.lock @@ -123,11 +123,11 @@ ] }, "locked": { - "lastModified": 1706221476, - "narHash": "sha256-T4b8YafVjHXvtDY8ARec1WrXO8uyyNZOpNgv9yoQy2M=", + "lastModified": 1706435589, + "narHash": "sha256-yhEYJxMv5BkfmUuNe4QELKo+V5eq1pwhtVs6kEziHfE=", "owner": "nix-community", "repo": "home-manager", - "rev": "c7ce343d9bf1a329056a4dd5b32ea8cc43b55e15", + "rev": "4d54c29bce71f8c261513e0662cc573d30f3e33e", "type": "github" }, "original": { @@ -165,11 +165,11 @@ ] }, "locked": { - "lastModified": 1705667791, - "narHash": "sha256-J0JYfA6eFdHluLnROVDkrqbYacWcJXYKXeJAFayDiAE=", + "lastModified": 1706509827, + "narHash": "sha256-fnZ8BXDgfvXGwStQvmpUXe+I+Fjd2JCLm8xo0kVwVKc=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "330b7a78fcba967f2273ae71fb3c4bfb03b5dd21", + "rev": "e2c026d8efea340d2a2dcc56775212979dd51ef2", "type": "github" }, "original": { @@ -202,11 +202,11 @@ ] }, "locked": { - "lastModified": 1706145483, - "narHash": "sha256-omDJXQPBNCFGjSSP4X3mlITdmgfkJ3wrlLN1RhR6ld0=", + "lastModified": 1706482802, + "narHash": "sha256-KXwKTfqFkoPpV8QqaVlpmO8w8rD/jHZL2315RL5QQ8w=", "owner": "fufexan", "repo": "nix-gaming", - "rev": "b9f77409aad6976efdae3b05523a07b328920c97", + "rev": "8f354ef64cd18898b8980ecf7fe90118808b514b", "type": "github" }, "original": { @@ -259,11 +259,11 @@ ] }, "locked": { - "lastModified": 1705806513, - "narHash": "sha256-FcOmNjhHFfPz2udZbRpZ1sfyhVMr+C2O8kOxPj+HDDk=", + "lastModified": 1706411424, + "narHash": "sha256-BzziJYucEZvdCE985vjPoo3ztWcmUiSQ1wJ2CoT6jCc=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f8e04fbcebcc24cebc91989981bd45f69b963ed7", + "rev": "c782f2a4f6fc94311ab5ef31df2f1149a1856181", "type": "github" }, "original": { @@ -279,11 +279,11 @@ ] }, "locked": { - "lastModified": 1705806513, - "narHash": "sha256-FcOmNjhHFfPz2udZbRpZ1sfyhVMr+C2O8kOxPj+HDDk=", + "lastModified": 1706411424, + "narHash": "sha256-BzziJYucEZvdCE985vjPoo3ztWcmUiSQ1wJ2CoT6jCc=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f8e04fbcebcc24cebc91989981bd45f69b963ed7", + "rev": "c782f2a4f6fc94311ab5ef31df2f1149a1856181", "type": "github" }, "original": { @@ -328,11 +328,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1706098335, - "narHash": "sha256-r3dWjT8P9/Ah5m5ul4WqIWD8muj5F+/gbCdjiNVBKmU=", + "lastModified": 1706373441, + "narHash": "sha256-S1hbgNbVYhuY2L05OANWqmRzj4cElcbLuIkXTb69xkk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a77ab169a83a4175169d78684ddd2e54486ac651", + "rev": "56911ef3403a9318b7621ce745f5452fb9ef6867", "type": "github" }, "original": { @@ -343,11 +343,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1705856552, - "narHash": "sha256-JXfnuEf5Yd6bhMs/uvM67/joxYKoysyE3M2k6T3eWbg=", + "lastModified": 1706191920, + "narHash": "sha256-eLihrZAPZX0R6RyM5fYAWeKVNuQPYjAkCUBr+JNvtdE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "612f97239e2cc474c13c9dafa0df378058c5ad8d", + "rev": "ae5c332cbb5827f6b1f02572496b141021de335f", "type": "github" }, "original": { @@ -358,11 +358,11 @@ }, "nur": { "locked": { - "lastModified": 1706251467, - "narHash": "sha256-uR6TEvf0PNFgIKLTImc4mt00qS7H5op9r7B++vdj2Io=", + "lastModified": 1706515086, + "narHash": "sha256-tjWRh6hv2kNGFRV8ESjg3TZDuA6B4Ls1fnru5z89SNA=", "owner": "nix-community", "repo": "NUR", - "rev": "1e00872abadba03e57c74975b05527e418620986", + "rev": "0416c8902949ad6fcfe91af8d9f9efa66bce8bef", "type": "github" }, "original": { @@ -381,11 +381,11 @@ ] }, "locked": { - "lastModified": 1705946102, - "narHash": "sha256-0hy28d7qC7Hv6/KV7xefa03b2xFJIGHPYAPcsVwzTeM=", + "lastModified": 1706365059, + "narHash": "sha256-2+M4vliRmSHQwGb1q1krg5lWKYiX7rF/B9GF4AlzXW4=", "owner": "pjones", "repo": "plasma-manager", - "rev": "4d209a083aeefa7d4f8060de14896399bbc8f30b", + "rev": "64f31bc95c22b04896111e4c9921d3e1122c0a92", "type": "github" }, "original": { @@ -453,11 +453,11 @@ ] }, "locked": { - "lastModified": 1706232054, - "narHash": "sha256-AjwmVarytm50C6CNvybuabXhu0zewLOXuxcmuiGyz8U=", + "lastModified": 1706491024, + "narHash": "sha256-oRjvADEBpKayeA/UVYGtdt1Idv5sMP9EBcqoQg4cOYo=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "e7db4235e6fcdff0d55925b4309bf8fe900501f0", + "rev": "0d4c78fbb27b522aa50b2783c20fcec7f88f48d0", "type": "github" }, "original": { From 502e7576ae3607f72a99ab04bcff38e1a9855eb6 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Jan 2024 10:37:07 +0100 Subject: [PATCH 0401/1125] Desktop/vscode: add git blame extension --- roles/desktop/programs/vscode.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index b0b1d51..bfd7c38 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -13,6 +13,7 @@ let inputs = flakeSelf.inputs; in extraBordersEnabled = true; }) catppuccin.catppuccin-vsc-icons + waderyan.gitblame ]; userSettings = { # VSCode doesn't like nested settings From e7bee1a15f25432e1a538ae1f67dd728e1638c29 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Jan 2024 10:41:45 +0100 Subject: [PATCH 0402/1125] Common: don't set micro as default editor --- roles/common/configuration.nix | 4 ---- 1 file changed, 4 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 3b30960..0e5699e 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -6,10 +6,6 @@ # As of the 1st of May 2023, the default packages are nano, perl, rsync and strace # I don't need any of them, so I just empty the list defaultPackages = []; - variables = { - # Environment variables go here - EDITOR = "micro"; - }; }; # Set up /tmp From 12c9b16a55484734239fd83b41b5c3be7c7a8ddb Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Jan 2024 10:52:15 +0100 Subject: [PATCH 0403/1125] Common: add neovim --- roles/common/programs/default.nix | 1 + roles/common/programs/neovim.nix | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 roles/common/programs/neovim.nix diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index e6d2127..7950344 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -13,6 +13,7 @@ ./starship.nix ./bat.nix ./btop.nix + ./neovim.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ diff --git a/roles/common/programs/neovim.nix b/roles/common/programs/neovim.nix new file mode 100644 index 0000000..ad2db07 --- /dev/null +++ b/roles/common/programs/neovim.nix @@ -0,0 +1,9 @@ +{ ... }: + +{ + home-manager.users.toast = { + programs.neovim = { + enable = true; + }; + }; +} From fd8053ed65c7314bf4511e78ccc12d0b822f4a30 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Jan 2024 11:06:52 +0100 Subject: [PATCH 0404/1125] Server/syncthing: add Win Max 2 to syncthing folders --- roles/server/syncthing.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index dd7768c..48742ac 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -18,19 +18,19 @@ "school-things" = { label = "School things"; id = "z6alc-nfoqr"; - devices = [ "steamdeck" "server" "pc"]; + devices = [ "steamdeck" "server" "pc" "winmax2" ]; path = "${config.services.syncthing.dataDir}/school-things"; }; "steam-201810" = { label = "Wolfenstein The New Order Saves"; id = "laxxf-t2wmy"; - devices = [ "steamdeck" "server" "pc" ]; + devices = [ "steamdeck" "server" "pc" "winmax2" ]; path = "${config.services.syncthing.dataDir}/steam-201810"; }; "retroarch"= { label = "RetroArch"; id = "jxuou-2yjnu"; - devices = [ "steamdeck" "server" "pc" ]; + devices = [ "steamdeck" "server" "pc" "winmax2" ]; path = "${config.services.syncthing.dataDir}/retroarch"; }; }; From 502074653c9ece516975e451bb4ee6c75c6521a3 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Jan 2024 11:08:31 +0100 Subject: [PATCH 0405/1125] Common/neovim: install catppuccin theme --- roles/common/programs/neovim.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/neovim.nix b/roles/common/programs/neovim.nix index ad2db07..6b82c4b 100644 --- a/roles/common/programs/neovim.nix +++ b/roles/common/programs/neovim.nix @@ -1,9 +1,12 @@ -{ ... }: +{ pkgs, ... }: { home-manager.users.toast = { programs.neovim = { enable = true; + plugins = with pkgs.vimPlugins; [ + catppuccin-nvim + ]; }; }; } From afec7ca0bc3a52cbb8385173d71270704c46fd3e Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 30 Jan 2024 10:52:41 +0100 Subject: [PATCH 0406/1125] Flake: add nixpkgs pr 277661 --- flake.nix | 1 + nixpkgs-patches/pr284962.patch | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 nixpkgs-patches/pr284962.patch diff --git a/flake.nix b/flake.nix index 6f78a57..3071d97 100644 --- a/flake.nix +++ b/flake.nix @@ -81,6 +81,7 @@ src = nixpkgs-unstable-raw; patches = [ ./nixpkgs-patches/pr277661.patch + ./nixpkgs-patches/pr284962.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr284962.patch b/nixpkgs-patches/pr284962.patch new file mode 100644 index 0000000..11e2c9b --- /dev/null +++ b/nixpkgs-patches/pr284962.patch @@ -0,0 +1,23 @@ +From 0f34032f5a31b46da08126c9ccec16ffaab964fe Mon Sep 17 00:00:00 2001 +From: K900 +Date: Tue, 30 Jan 2024 11:38:10 +0300 +Subject: [PATCH] nixos/plasma5: install missing style plugins + +--- + nixos/modules/services/x11/desktop-managers/plasma5.nix | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix +index 38c858aaef0533..1611d77d81cf15 100644 +--- a/nixos/modules/services/x11/desktop-managers/plasma5.nix ++++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix +@@ -253,6 +253,9 @@ in + plasma-integration + polkit-kde-agent + ++ qqc2-breeze-style ++ qqc2-desktop-style ++ + plasma-desktop + plasma-workspace + plasma-workspace-wallpapers From d706a86250804af414906ba2b0bcf3aa60a5b6ef Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 30 Jan 2024 23:11:14 +0100 Subject: [PATCH 0407/1125] Kde/plasma: enable qt --- roles/kde/plasma.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 9915ba9..21488f1 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -54,6 +54,8 @@ in displayManager.defaultSession = "plasmawayland"; }; + qt.enable = true; + # GTK apps need dconf to grab the correct theme on Wayland programs.dconf.enable = true; From de8bfae07a1f45d08e8e6e761a65db2adee046df Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 30 Jan 2024 23:29:52 +0100 Subject: [PATCH 0408/1125] Gaming/rpcs3: use rpcs3 from NUR --- roles/gaming/programs/rpcs3.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/roles/gaming/programs/rpcs3.nix b/roles/gaming/programs/rpcs3.nix index 931b7ba..97d3279 100644 --- a/roles/gaming/programs/rpcs3.nix +++ b/roles/gaming/programs/rpcs3.nix @@ -1,7 +1,14 @@ { config, pkgs, ... }: { - environment.systemPackages = with pkgs; [ rpcs3 ]; + environment.systemPackages = with config; [ + nur.repos.ataraxiasjel.rpcs3 + ]; + # Compiling RPCS3 takes quite a while + nix.settings = { + substituters = [ "https://ataraxiadev-foss.cachix.org" ]; + trusted-public-keys = [ "ataraxiadev-foss.cachix.org-1:ws/jmPRUF5R8TkirnV1b525lP9F/uTBsz2KraV61058=" ]; + }; # Increase the memory lock limit security.pam.loginLimits = [{ From c038df0ba8e341042e859989f2ec62bfeb4f3a4d Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 2 Feb 2024 09:33:55 +0100 Subject: [PATCH 0409/1125] Flake: update pr 277661 patch --- nixpkgs-patches/pr277661.patch | 168 +++++++++++++++++++++++---------- 1 file changed, 118 insertions(+), 50 deletions(-) diff --git a/nixpkgs-patches/pr277661.patch b/nixpkgs-patches/pr277661.patch index 17ec03c..0b08ad1 100644 --- a/nixpkgs-patches/pr277661.patch +++ b/nixpkgs-patches/pr277661.patch @@ -1,7 +1,7 @@ From bcf9a24332a04ddcef154b792697320d40829820 Mon Sep 17 00:00:00 2001 From: Brenton Simpson Date: Mon, 1 Jan 2024 16:18:45 -0800 -Subject: [PATCH 1/5] handheld-daemon: init at 0.2.7 +Subject: [PATCH 1/6] handheld-daemon: init at 0.2.7 --- .../manual/release-notes/rl-2405.section.md | 2 + @@ -150,7 +150,7 @@ index 00000000000000..b8b14d85f45bf7 From 52f22bfc57dff00a93343e30a42e434b68062196 Mon Sep 17 00:00:00 2001 From: Brenton Simpson Date: Wed, 17 Jan 2024 09:52:06 -0800 -Subject: [PATCH 2/5] handheld-daemon: 0.27 -> 1.0.8 +Subject: [PATCH 2/6] handheld-daemon: 0.27 -> 1.0.8 --- pkgs/by-name/ha/handheld-daemon/package.nix | 7 +++---- @@ -186,7 +186,7 @@ index b8b14d85f45bf7..f590665a8292fa 100644 From f571033ce013a416c744bd3d3ffc0fe525dbe3a9 Mon Sep 17 00:00:00 2001 From: Brenton Simpson Date: Sat, 20 Jan 2024 17:56:44 -0800 -Subject: [PATCH 3/5] handheld-daemon: use kebab-case instead of camelCase for +Subject: [PATCH 3/6] handheld-daemon: use kebab-case instead of camelCase for service name --- @@ -234,55 +234,10 @@ index a513ed7ddf8efe..81859bf5b122fe 100644 wantedBy = [ "multi-user.target" ]; -From 75516996fe8b29d970e2eae003c67c07ef3ae206 Mon Sep 17 00:00:00 2001 -From: Brenton Simpson -Date: Mon, 22 Jan 2024 11:12:04 -0800 -Subject: [PATCH 4/5] handheld-daemon: make package overrideable - -Co-authored-by: h7x4 ---- - nixos/modules/services/hardware/handheld-daemon.nix | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix -index 81859bf5b122fe..154380985bf05d 100644 ---- a/nixos/modules/services/hardware/handheld-daemon.nix -+++ b/nixos/modules/services/hardware/handheld-daemon.nix -@@ -9,6 +9,7 @@ in - { - options.services.handheld-daemon = { - enable = mkEnableOption "Enable Handheld Daemon"; -+ package = mkPackageOption pkgs "handheld-daemon" { }; - - user = mkOption { - type = types.str; -@@ -19,9 +20,9 @@ in - }; - - config = mkIf cfg.enable { -- environment.systemPackages = [ pkgs.handheld-daemon ]; -- services.udev.packages = [ pkgs.handheld-daemon ]; -- systemd.packages = [ pkgs.handheld-daemon ]; -+ environment.systemPackages = [ cfg.package ]; -+ services.udev.packages = [ cfg.package ]; -+ systemd.packages = [ cfg.package ]; - - systemd.services.handheld-daemon = { - description = "Handheld Daemon"; -@@ -31,7 +32,7 @@ in - restartIfChanged = true; - - serviceConfig = { -- ExecStart = "${ pkgs.handheld-daemon }/bin/hhd --user ${ cfg.user }"; -+ ExecStart = "${ cfg.package }/bin/hhd --user ${ cfg.user }"; - Nice = "-12"; - Restart = "on-failure"; - RestartSec = "10"; - -From 3bc83885805347e099ab0e6469875b23edb5698e Mon Sep 17 00:00:00 2001 +From f939675e04ac34d91b2d549a105de4b7b1446255 Mon Sep 17 00:00:00 2001 From: Brenton Simpson Date: Mon, 22 Jan 2024 11:13:15 -0800 -Subject: [PATCH 5/5] handheld-daemon: 1.0.8 -> 1.1.0 +Subject: [PATCH 4/6] handheld-daemon: 1.0.8 -> 1.1.0 --- pkgs/by-name/ha/handheld-daemon/package.nix | 17 +++++++++-------- @@ -334,3 +289,116 @@ index f590665a8292fa..e037c4da70868b 100644 ]; # handheld-daemon contains a fork of the python module `hid`, so this hook + +From 3bfa7c5710fd06ba32bf844ca2d414a87308ebea Mon Sep 17 00:00:00 2001 +From: Brenton Simpson +Date: Mon, 29 Jan 2024 17:11:48 -0800 +Subject: [PATCH 5/6] handheld-daemon: touchup package description + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index e037c4da70868b..7df459cc9adda8 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -45,7 +45,7 @@ python3.pkgs.buildPythonApplication rec { + + meta = with lib; { + homepage = "https://github.com/hhd-dev/hhd/"; +- description = "Linux support for gaming handhelds"; ++ description = "Linux support for handheld gaming devices like the Legion Go, ROG Ally, and GPD Win"; + platforms = platforms.linux; + license = licenses.mit; + maintainers = with maintainers; [ appsforartists ]; + +From b960a217bd351378b01a27f37df9d4b0028570b0 Mon Sep 17 00:00:00 2001 +From: Brenton Simpson +Date: Mon, 22 Jan 2024 11:12:04 -0800 +Subject: [PATCH 6/6] handheld-daemon: touchup code style to better match + nixpkgs + +Co-authored-by: h7x4 +Co-authored-by: Luke Granger-Brown +Co-authored-by: Bruno BELANYI +--- + .../services/hardware/handheld-daemon.nix | 9 +++++---- + pkgs/by-name/ha/handheld-daemon/package.nix | 16 ++++++++-------- + 2 files changed, 13 insertions(+), 12 deletions(-) + +diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix +index 81859bf5b122fe..e8a7a39f441d25 100644 +--- a/nixos/modules/services/hardware/handheld-daemon.nix ++++ b/nixos/modules/services/hardware/handheld-daemon.nix +@@ -9,6 +9,7 @@ in + { + options.services.handheld-daemon = { + enable = mkEnableOption "Enable Handheld Daemon"; ++ package = mkPackageOption pkgs "handheld-daemon" { }; + + user = mkOption { + type = types.str; +@@ -19,9 +20,9 @@ in + }; + + config = mkIf cfg.enable { +- environment.systemPackages = [ pkgs.handheld-daemon ]; +- services.udev.packages = [ pkgs.handheld-daemon ]; +- systemd.packages = [ pkgs.handheld-daemon ]; ++ environment.systemPackages = [ cfg.package ]; ++ services.udev.packages = [ cfg.package ]; ++ systemd.packages = [ cfg.package ]; + + systemd.services.handheld-daemon = { + description = "Handheld Daemon"; +@@ -31,7 +32,7 @@ in + restartIfChanged = true; + + serviceConfig = { +- ExecStart = "${ pkgs.handheld-daemon }/bin/hhd --user ${ cfg.user }"; ++ ExecStart = "${ lib.getExe cfg.package } --user ${ cfg.user }"; + Nice = "-12"; + Restart = "on-failure"; + RestartSec = "10"; +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 7df459cc9adda8..bb0c9d65bfe19d 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -9,28 +9,28 @@ + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; + version = "1.1.0"; +- format = "pyproject"; ++ pyproject = true; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; +- rev = "abe34c6841476f5b41afe30ee18ff3e510402d68"; ++ rev = "v${version}"; + hash = "sha256-ovLC1BQ98jUaDEMPBzWma4TYSzTF+yE/cMemFdJmqlE="; + }; + +- pythonPath = with python3.pkgs; [ +- evdev +- pyyaml +- rich +- ]; +- + propagatedBuildInputs = with python3.pkgs; [ ++ evdev + hidapi + kmod ++ pyyaml ++ rich + setuptools + toybox + ]; + ++ # This package doesn't have upstream tests. ++ doCheck = false; ++ + # handheld-daemon contains a fork of the python module `hid`, so this hook + # is borrowed from the `hid` derivation. + postPatch = '' From 19ae6db3b11c078780da9c13b0ab9d8e3e448326 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 2 Feb 2024 09:40:34 +0100 Subject: [PATCH 0410/1125] Common: update hhd --- roles/common/configuration.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 0e5699e..a8f4887 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -79,10 +79,10 @@ src = pkgs.fetchFromGitHub { owner = "hhd-dev"; repo = "hhd"; - rev = "8cc8c7143a5f35c6dd0c6036c6058f05220c2834"; - hash = "sha256-Jrk7LFCL0kdqFasPRuuEXNtQ5AY34/kJjw8Cqeg8bXc="; + rev = "c074cb0e3e13ab18fd150eb36df70044ede45038"; + hash = "sha256-Jzx72d1l7v6d/fgPvj3BwAF/hgXL4MWzhPjKvtdqwfw="; }; - version = "1.1.2"; + version = "1.1.4"; }; } ) From cbd81915379fbafb36fb081cc0ea7e3df9d3985a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 2 Feb 2024 12:03:15 +0100 Subject: [PATCH 0411/1125] Flake: update lock file --- flake.lock | 60 +++++++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/flake.lock b/flake.lock index 79e8ee6..05c3b06 100644 --- a/flake.lock +++ b/flake.lock @@ -123,11 +123,11 @@ ] }, "locked": { - "lastModified": 1706435589, - "narHash": "sha256-yhEYJxMv5BkfmUuNe4QELKo+V5eq1pwhtVs6kEziHfE=", + "lastModified": 1706798041, + "narHash": "sha256-BbvuF4CsVRBGRP8P+R+JUilojk0M60D7hzqE0bEvJBQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "4d54c29bce71f8c261513e0662cc573d30f3e33e", + "rev": "4d53427bce7bf3d17e699252fd84dc7468afc46e", "type": "github" }, "original": { @@ -180,11 +180,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1706131725, - "narHash": "sha256-HK/maOUUo+4tKL06VSV5szJXTtc7QqcO9F5c0FGi2F8=", + "lastModified": 1706716715, + "narHash": "sha256-aoUh0585v3mMkqGV+aggvs9uZQdZWSqMEGGVUT1jX38=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "dfa162fab581ba293f5faa866e91c553b78a01aa", + "rev": "30f6cb66a1be2a350b08b13e820122b0f3d4bd81", "type": "github" }, "original": { @@ -202,11 +202,11 @@ ] }, "locked": { - "lastModified": 1706482802, - "narHash": "sha256-KXwKTfqFkoPpV8QqaVlpmO8w8rD/jHZL2315RL5QQ8w=", + "lastModified": 1706750085, + "narHash": "sha256-y/+t2ctdeUD/b0DLWS96UgGUs/srj7vbWef709DPxW4=", "owner": "fufexan", "repo": "nix-gaming", - "rev": "8f354ef64cd18898b8980ecf7fe90118808b514b", + "rev": "63fa64659760172fef0e4d674c6661b7ad53b16b", "type": "github" }, "original": { @@ -239,11 +239,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1703656108, - "narHash": "sha256-hCSUqdFJKHHbER8Cenf5JRzjMlBjIdwdftGQsO0xoJs=", + "lastModified": 1706639736, + "narHash": "sha256-CaG4j9+UwBDfinxxvJMo6yOonSmSo0ZgnbD7aj2Put0=", "owner": "nix-community", "repo": "impermanence", - "rev": "033643a45a4a920660ef91caa391fbffb14da466", + "rev": "cd13c2917eaa68e4c49fea0ff9cada45440d7045", "type": "github" }, "original": { @@ -294,11 +294,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1706182238, - "narHash": "sha256-Ti7CerGydU7xyrP/ow85lHsOpf+XMx98kQnPoQCSi1g=", + "lastModified": 1706834982, + "narHash": "sha256-3CfxA7gZ+DVv/N9Pvw61bV5Oe/mWfxYPyVQGqp9TMJA=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "f84eaffc35d1a655e84749228cde19922fcf55f1", + "rev": "83e571bb291161682b9c3ccd48318f115143a550", "type": "github" }, "original": { @@ -328,11 +328,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1706373441, - "narHash": "sha256-S1hbgNbVYhuY2L05OANWqmRzj4cElcbLuIkXTb69xkk=", + "lastModified": 1706718339, + "narHash": "sha256-S+S97c/HzkO2A/YsU7ZmNF9w2s7Xk6P8dzmfDdckzLs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "56911ef3403a9318b7621ce745f5452fb9ef6867", + "rev": "53fbe41cf76b6a685004194e38e889bc8857e8c2", "type": "github" }, "original": { @@ -343,11 +343,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1706191920, - "narHash": "sha256-eLihrZAPZX0R6RyM5fYAWeKVNuQPYjAkCUBr+JNvtdE=", + "lastModified": 1706550542, + "narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ae5c332cbb5827f6b1f02572496b141021de335f", + "rev": "97b17f32362e475016f942bbdfda4a4a72a8a652", "type": "github" }, "original": { @@ -358,11 +358,11 @@ }, "nur": { "locked": { - "lastModified": 1706515086, - "narHash": "sha256-tjWRh6hv2kNGFRV8ESjg3TZDuA6B4Ls1fnru5z89SNA=", + "lastModified": 1706863127, + "narHash": "sha256-GYAHiJ6Q/aJKJt2UbPh5/l+Zpmj+ofjckmGcMl/6t2w=", "owner": "nix-community", "repo": "NUR", - "rev": "0416c8902949ad6fcfe91af8d9f9efa66bce8bef", + "rev": "bfb80b4b69abcdab9f09e83637fb88de3c5c890c", "type": "github" }, "original": { @@ -381,11 +381,11 @@ ] }, "locked": { - "lastModified": 1706365059, - "narHash": "sha256-2+M4vliRmSHQwGb1q1krg5lWKYiX7rF/B9GF4AlzXW4=", + "lastModified": 1706718414, + "narHash": "sha256-qOwU5X0nG4nJ3xBSKWfJ9ROf6T2r7jThO85AiBimwgc=", "owner": "pjones", "repo": "plasma-manager", - "rev": "64f31bc95c22b04896111e4c9921d3e1122c0a92", + "rev": "91b5335d4310e94527a8a778d5e8884c43340276", "type": "github" }, "original": { @@ -453,11 +453,11 @@ ] }, "locked": { - "lastModified": 1706491024, - "narHash": "sha256-oRjvADEBpKayeA/UVYGtdt1Idv5sMP9EBcqoQg4cOYo=", + "lastModified": 1706836587, + "narHash": "sha256-+NsqaijHVIaPepCwkbhXyocHR0N+1PsRjQfX6PRHkkA=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "0d4c78fbb27b522aa50b2783c20fcec7f88f48d0", + "rev": "67b1cc7b069da720c8c3af0ab1b19eae28c6bb07", "type": "github" }, "original": { From cbf8e99b7be45adc547f62b857e5c6e7acb1629e Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 2 Feb 2024 13:39:36 +0100 Subject: [PATCH 0412/1125] School/idea: update catppuccin plugin --- roles/school/programs/idea.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index bc231dd..ea3b5de 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -10,8 +10,8 @@ with pkgs; # Install plugins home.file = { ".local/share/JetBrains/IntelliJIdea2023.3/catppuccin.jar".source = fetchurl { - url = "https://github.com/catppuccin/jetbrains/releases/download/v3.2.2/Catppuccin.Theme-3.2.2.jar"; - hash = "sha256-1Zio3ZDhhZvpo6w9ULNhhDQnyT1W25CLcVSm/LcP648="; + url = "https://github.com/catppuccin/jetbrains/releases/download/v3.2.3/Catppuccin.Theme-3.2.3.jar"; + hash = "sha256-v5BZ2UKEBA/0DHKGwmprmuu0RcJCDsxzWmCdnX9aXpE="; }; ".local/share/JetBrains/IntelliJIdea2023.3/rainbow-brackets".source = fetchzip { url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/latest/intellij-rainbow-brackets-2023.3.9-233.zip"; From ddde5f5c569226ad43c9bcac5b24395c00d67813 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 00:43:26 +0100 Subject: [PATCH 0413/1125] Machines/WinMax2: update jovian option --- machines/WinMax2/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index d622c7b..1d80393 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -80,7 +80,7 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="d desktopSession = "plasmawayland"; }; # Need patched mesa - devices.steamdeck = { + steamos = { enableMesaPatches = true; enableVendorRadv = true; }; From 8e92447f83fac6829e4b2fa46e1aca5d4009cc44 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 00:44:01 +0100 Subject: [PATCH 0414/1125] Machines:WinMax2/ enable brightness control in game mode --- machines/WinMax2/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 1d80393..b41a681 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -79,6 +79,7 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="d user = "toast"; desktopSession = "plasmawayland"; }; + hardware.amd.gpu.enableBacklightControl = true; # Need patched mesa steamos = { enableMesaPatches = true; From 0976d52cab00297d4cfd9b5c3817507709a72443 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 01:35:38 +0100 Subject: [PATCH 0415/1125] Flake: remove nixpkgs-unstable patches --- flake.nix | 3 +- nixpkgs-patches/pr277661.patch | 404 --------------------------------- nixpkgs-patches/pr284962.patch | 23 -- 3 files changed, 1 insertion(+), 429 deletions(-) delete mode 100644 nixpkgs-patches/pr277661.patch delete mode 100644 nixpkgs-patches/pr284962.patch diff --git a/flake.nix b/flake.nix index 3071d97..4074c49 100644 --- a/flake.nix +++ b/flake.nix @@ -80,8 +80,7 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/pr277661.patch - ./nixpkgs-patches/pr284962.patch + ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr277661.patch b/nixpkgs-patches/pr277661.patch deleted file mode 100644 index 0b08ad1..0000000 --- a/nixpkgs-patches/pr277661.patch +++ /dev/null @@ -1,404 +0,0 @@ -From bcf9a24332a04ddcef154b792697320d40829820 Mon Sep 17 00:00:00 2001 -From: Brenton Simpson -Date: Mon, 1 Jan 2024 16:18:45 -0800 -Subject: [PATCH 1/6] handheld-daemon: init at 0.2.7 - ---- - .../manual/release-notes/rl-2405.section.md | 2 + - nixos/modules/module-list.nix | 1 + - .../services/hardware/handheld-daemon.nix | 43 +++++++++++++++ - pkgs/by-name/ha/handheld-daemon/package.nix | 54 +++++++++++++++++++ - 4 files changed, 100 insertions(+) - create mode 100644 nixos/modules/services/hardware/handheld-daemon.nix - create mode 100644 pkgs/by-name/ha/handheld-daemon/package.nix - -diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md -index f4434fd6b94cac..3ddc2f781bd968 100644 ---- a/nixos/doc/manual/release-notes/rl-2405.section.md -+++ b/nixos/doc/manual/release-notes/rl-2405.section.md -@@ -22,6 +22,8 @@ In addition to numerous new and upgraded packages, this release has the followin - - - -+- [Handheld Daemon](https://github.com/hhd-dev/hhd), support for gaming handhelds like the Legion Go, ROG Ally, and GPD Win. Available as [services.handheldDaemon](#opt-services.handheldDaemon.enable). -+ - - [Guix](https://guix.gnu.org), a functional package manager inspired by Nix. Available as [services.guix](#opt-services.guix.enable). - - - [maubot](https://github.com/maubot/maubot), a plugin-based Matrix bot framework. Available as [services.maubot](#opt-services.maubot.enable). -diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix -index 00e6240f531d52..154fd8df2ce08d 100644 ---- a/nixos/modules/module-list.nix -+++ b/nixos/modules/module-list.nix -@@ -532,6 +532,7 @@ - ./services/hardware/fancontrol.nix - ./services/hardware/freefall.nix - ./services/hardware/fwupd.nix -+ ./services/hardware/handheld-daemon.nix - ./services/hardware/hddfancontrol.nix - ./services/hardware/illum.nix - ./services/hardware/interception-tools.nix -diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix -new file mode 100644 -index 00000000000000..a513ed7ddf8efe ---- /dev/null -+++ b/nixos/modules/services/hardware/handheld-daemon.nix -@@ -0,0 +1,43 @@ -+{ config -+, lib -+, pkgs -+, ... -+}: -+with lib; let -+ cfg = config.services.handheldDaemon; -+in -+{ -+ options.services.handheldDaemon = { -+ enable = mkEnableOption "Enable Handheld Daemon"; -+ -+ user = mkOption { -+ type = types.str; -+ description = lib.mdDoc '' -+ The user to run Handheld Daemon with. -+ ''; -+ }; -+ }; -+ -+ config = mkIf cfg.enable { -+ environment.systemPackages = [ pkgs.handheld-daemon ]; -+ services.udev.packages = [ pkgs.handheld-daemon ]; -+ systemd.packages = [ pkgs.handheld-daemon ]; -+ -+ systemd.services.handheldDaemon = { -+ description = "Handheld Daemon"; -+ -+ wantedBy = [ "multi-user.target" ]; -+ -+ restartIfChanged = true; -+ -+ serviceConfig = { -+ ExecStart = "${ pkgs.handheld-daemon }/bin/hhd --user ${ cfg.user }"; -+ Nice = "-12"; -+ Restart = "on-failure"; -+ RestartSec = "10"; -+ }; -+ }; -+ }; -+ -+ meta.maintainers = [ maintainers.appsforartists ]; -+} -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -new file mode 100644 -index 00000000000000..b8b14d85f45bf7 ---- /dev/null -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -0,0 +1,54 @@ -+{ config -+, fetchFromGitHub -+, hidapi -+, lib -+, python3 -+, -+}: -+python3.pkgs.buildPythonApplication rec { -+ pname = "handheld-daemon"; -+ version = "0.2.7"; -+ format = "pyproject"; -+ -+ src = fetchFromGitHub { -+ owner = "hhd-dev"; -+ repo = "hhd"; -+ rev = "ccae6b207cadfbdaef292270c4fc6c855f71ba03"; -+ hash = "sha256-+tyiXOvZXLbomhgFRKUNKGbkkkOxQKdk/kjeWZ4pvO0="; -+ }; -+ -+ pythonPath = with python3.pkgs; [ -+ evdev -+ pyyaml -+ rich -+ ]; -+ -+ nativeBuildInputs = with python3.pkgs; [ -+ setuptools -+ ]; -+ -+ propagatedBuildInputs = [ -+ hidapi -+ ]; -+ -+ # handheld-daemon contains a fork of the python module `hid`, so this hook -+ # is borrowed from the `hid` derivation. -+ postPatch = '' -+ hidapi=${ hidapi }/lib/ -+ test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } -+ sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py -+ ''; -+ -+ postInstall = '' -+ install -Dm644 $src/usr/lib/udev/rules.d/83-hhd.rules -t $out/lib/udev/rules.d/ -+ ''; -+ -+ meta = with lib; { -+ homepage = "https://github.com/hhd-dev/hhd/"; -+ description = "Linux support for gaming handhelds"; -+ platforms = platforms.linux; -+ license = licenses.mit; -+ maintainers = with maintainers; [ appsforartists ]; -+ mainProgram = "hhd"; -+ }; -+} - -From 52f22bfc57dff00a93343e30a42e434b68062196 Mon Sep 17 00:00:00 2001 -From: Brenton Simpson -Date: Wed, 17 Jan 2024 09:52:06 -0800 -Subject: [PATCH 2/6] handheld-daemon: 0.27 -> 1.0.8 - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index b8b14d85f45bf7..f590665a8292fa 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -3,18 +3,17 @@ - , hidapi - , lib - , python3 --, - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "0.2.7"; -+ version = "1.0.8"; - format = "pyproject"; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; -- rev = "ccae6b207cadfbdaef292270c4fc6c855f71ba03"; -- hash = "sha256-+tyiXOvZXLbomhgFRKUNKGbkkkOxQKdk/kjeWZ4pvO0="; -+ rev = "6cb83a9833eebc81bd27bed57eb68ece15cdd7a6"; -+ hash = "sha256-YfBi5UKaB+v+eDI8rcvqkogAYRU2kTc0NqvakhKxBOE="; - }; - - pythonPath = with python3.pkgs; [ - -From f571033ce013a416c744bd3d3ffc0fe525dbe3a9 Mon Sep 17 00:00:00 2001 -From: Brenton Simpson -Date: Sat, 20 Jan 2024 17:56:44 -0800 -Subject: [PATCH 3/6] handheld-daemon: use kebab-case instead of camelCase for - service name - ---- - nixos/doc/manual/release-notes/rl-2405.section.md | 2 +- - nixos/modules/services/hardware/handheld-daemon.nix | 6 +++--- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md -index 3ddc2f781bd968..994f642154619c 100644 ---- a/nixos/doc/manual/release-notes/rl-2405.section.md -+++ b/nixos/doc/manual/release-notes/rl-2405.section.md -@@ -22,7 +22,7 @@ In addition to numerous new and upgraded packages, this release has the followin - - - --- [Handheld Daemon](https://github.com/hhd-dev/hhd), support for gaming handhelds like the Legion Go, ROG Ally, and GPD Win. Available as [services.handheldDaemon](#opt-services.handheldDaemon.enable). -+- [Handheld Daemon](https://github.com/hhd-dev/hhd), support for gaming handhelds like the Legion Go, ROG Ally, and GPD Win. Available as [services.handheld-daemon](#opt-services.handheld-daemon.enable). - - - [Guix](https://guix.gnu.org), a functional package manager inspired by Nix. Available as [services.guix](#opt-services.guix.enable). - -diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix -index a513ed7ddf8efe..81859bf5b122fe 100644 ---- a/nixos/modules/services/hardware/handheld-daemon.nix -+++ b/nixos/modules/services/hardware/handheld-daemon.nix -@@ -4,10 +4,10 @@ - , ... - }: - with lib; let -- cfg = config.services.handheldDaemon; -+ cfg = config.services.handheld-daemon; - in - { -- options.services.handheldDaemon = { -+ options.services.handheld-daemon = { - enable = mkEnableOption "Enable Handheld Daemon"; - - user = mkOption { -@@ -23,7 +23,7 @@ in - services.udev.packages = [ pkgs.handheld-daemon ]; - systemd.packages = [ pkgs.handheld-daemon ]; - -- systemd.services.handheldDaemon = { -+ systemd.services.handheld-daemon = { - description = "Handheld Daemon"; - - wantedBy = [ "multi-user.target" ]; - -From f939675e04ac34d91b2d549a105de4b7b1446255 Mon Sep 17 00:00:00 2001 -From: Brenton Simpson -Date: Mon, 22 Jan 2024 11:13:15 -0800 -Subject: [PATCH 4/6] handheld-daemon: 1.0.8 -> 1.1.0 - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 17 +++++++++-------- - 1 file changed, 9 insertions(+), 8 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index f590665a8292fa..e037c4da70868b 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -1,19 +1,21 @@ - { config - , fetchFromGitHub - , hidapi -+, kmod - , lib - , python3 -+, toybox - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "1.0.8"; -+ version = "1.1.0"; - format = "pyproject"; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; -- rev = "6cb83a9833eebc81bd27bed57eb68ece15cdd7a6"; -- hash = "sha256-YfBi5UKaB+v+eDI8rcvqkogAYRU2kTc0NqvakhKxBOE="; -+ rev = "abe34c6841476f5b41afe30ee18ff3e510402d68"; -+ hash = "sha256-ovLC1BQ98jUaDEMPBzWma4TYSzTF+yE/cMemFdJmqlE="; - }; - - pythonPath = with python3.pkgs; [ -@@ -22,12 +24,11 @@ python3.pkgs.buildPythonApplication rec { - rich - ]; - -- nativeBuildInputs = with python3.pkgs; [ -- setuptools -- ]; -- -- propagatedBuildInputs = [ -+ propagatedBuildInputs = with python3.pkgs; [ - hidapi -+ kmod -+ setuptools -+ toybox - ]; - - # handheld-daemon contains a fork of the python module `hid`, so this hook - -From 3bfa7c5710fd06ba32bf844ca2d414a87308ebea Mon Sep 17 00:00:00 2001 -From: Brenton Simpson -Date: Mon, 29 Jan 2024 17:11:48 -0800 -Subject: [PATCH 5/6] handheld-daemon: touchup package description - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index e037c4da70868b..7df459cc9adda8 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -45,7 +45,7 @@ python3.pkgs.buildPythonApplication rec { - - meta = with lib; { - homepage = "https://github.com/hhd-dev/hhd/"; -- description = "Linux support for gaming handhelds"; -+ description = "Linux support for handheld gaming devices like the Legion Go, ROG Ally, and GPD Win"; - platforms = platforms.linux; - license = licenses.mit; - maintainers = with maintainers; [ appsforartists ]; - -From b960a217bd351378b01a27f37df9d4b0028570b0 Mon Sep 17 00:00:00 2001 -From: Brenton Simpson -Date: Mon, 22 Jan 2024 11:12:04 -0800 -Subject: [PATCH 6/6] handheld-daemon: touchup code style to better match - nixpkgs - -Co-authored-by: h7x4 -Co-authored-by: Luke Granger-Brown -Co-authored-by: Bruno BELANYI ---- - .../services/hardware/handheld-daemon.nix | 9 +++++---- - pkgs/by-name/ha/handheld-daemon/package.nix | 16 ++++++++-------- - 2 files changed, 13 insertions(+), 12 deletions(-) - -diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix -index 81859bf5b122fe..e8a7a39f441d25 100644 ---- a/nixos/modules/services/hardware/handheld-daemon.nix -+++ b/nixos/modules/services/hardware/handheld-daemon.nix -@@ -9,6 +9,7 @@ in - { - options.services.handheld-daemon = { - enable = mkEnableOption "Enable Handheld Daemon"; -+ package = mkPackageOption pkgs "handheld-daemon" { }; - - user = mkOption { - type = types.str; -@@ -19,9 +20,9 @@ in - }; - - config = mkIf cfg.enable { -- environment.systemPackages = [ pkgs.handheld-daemon ]; -- services.udev.packages = [ pkgs.handheld-daemon ]; -- systemd.packages = [ pkgs.handheld-daemon ]; -+ environment.systemPackages = [ cfg.package ]; -+ services.udev.packages = [ cfg.package ]; -+ systemd.packages = [ cfg.package ]; - - systemd.services.handheld-daemon = { - description = "Handheld Daemon"; -@@ -31,7 +32,7 @@ in - restartIfChanged = true; - - serviceConfig = { -- ExecStart = "${ pkgs.handheld-daemon }/bin/hhd --user ${ cfg.user }"; -+ ExecStart = "${ lib.getExe cfg.package } --user ${ cfg.user }"; - Nice = "-12"; - Restart = "on-failure"; - RestartSec = "10"; -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 7df459cc9adda8..bb0c9d65bfe19d 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -9,28 +9,28 @@ - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; - version = "1.1.0"; -- format = "pyproject"; -+ pyproject = true; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; -- rev = "abe34c6841476f5b41afe30ee18ff3e510402d68"; -+ rev = "v${version}"; - hash = "sha256-ovLC1BQ98jUaDEMPBzWma4TYSzTF+yE/cMemFdJmqlE="; - }; - -- pythonPath = with python3.pkgs; [ -- evdev -- pyyaml -- rich -- ]; -- - propagatedBuildInputs = with python3.pkgs; [ -+ evdev - hidapi - kmod -+ pyyaml -+ rich - setuptools - toybox - ]; - -+ # This package doesn't have upstream tests. -+ doCheck = false; -+ - # handheld-daemon contains a fork of the python module `hid`, so this hook - # is borrowed from the `hid` derivation. - postPatch = '' diff --git a/nixpkgs-patches/pr284962.patch b/nixpkgs-patches/pr284962.patch deleted file mode 100644 index 11e2c9b..0000000 --- a/nixpkgs-patches/pr284962.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0f34032f5a31b46da08126c9ccec16ffaab964fe Mon Sep 17 00:00:00 2001 -From: K900 -Date: Tue, 30 Jan 2024 11:38:10 +0300 -Subject: [PATCH] nixos/plasma5: install missing style plugins - ---- - nixos/modules/services/x11/desktop-managers/plasma5.nix | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix -index 38c858aaef0533..1611d77d81cf15 100644 ---- a/nixos/modules/services/x11/desktop-managers/plasma5.nix -+++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix -@@ -253,6 +253,9 @@ in - plasma-integration - polkit-kde-agent - -+ qqc2-breeze-style -+ qqc2-desktop-style -+ - plasma-desktop - plasma-workspace - plasma-workspace-wallpapers From 8311fcc69114e366b00498509aee6a3617c9afe6 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 01:36:15 +0100 Subject: [PATCH 0416/1125] Flake: update lock file --- flake.lock | 84 +++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/flake.lock b/flake.lock index 05c3b06..a51b029 100644 --- a/flake.lock +++ b/flake.lock @@ -30,11 +30,11 @@ ] }, "locked": { - "lastModified": 1704923501, - "narHash": "sha256-Kz3pymvpNHTlKruepOZ3lbiWxfGhtlK5JiqF0Hk+h6I=", + "lastModified": 1707059042, + "narHash": "sha256-6tomg1cTo7cwd7U3hIyDMA5iBuHg82cTr9TrUGnfxMw=", "owner": "catppuccin", "repo": "vscode", - "rev": "cf7019fdeba269650940fb0bd2c4e50c7bf498d8", + "rev": "50aa91ba31192bef8563a96e246d469091502d10", "type": "github" }, "original": { @@ -64,11 +64,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1704982712, - "narHash": "sha256-2Ptt+9h8dczgle2Oo6z5ni5rt/uLMG47UFTR1ry/wgg=", + "lastModified": 1706830856, + "narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "07f6395285469419cf9d078f59b5b49993198c00", + "rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f", "type": "github" }, "original": { @@ -123,11 +123,11 @@ ] }, "locked": { - "lastModified": 1706798041, - "narHash": "sha256-BbvuF4CsVRBGRP8P+R+JUilojk0M60D7hzqE0bEvJBQ=", + "lastModified": 1707088232, + "narHash": "sha256-nxPBAZ//BwKkBcjwLE5g9zTq29g7gccTnH5+CeMTxpA=", "owner": "nix-community", "repo": "home-manager", - "rev": "4d53427bce7bf3d17e699252fd84dc7468afc46e", + "rev": "4740f2ccda184e9cc509d7a82b26d7271e0c79d9", "type": "github" }, "original": { @@ -143,11 +143,11 @@ ] }, "locked": { - "lastModified": 1705659542, - "narHash": "sha256-WA3xVfAk1AYmFdwghT7mt/erYpsU6JPu9mdTEP/e9HQ=", + "lastModified": 1706981411, + "narHash": "sha256-cLbLPTL1CDmETVh4p0nQtvoF+FSEjsnJTFpTxhXywhQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "10cd9c53115061aa6a0a90aad0b0dde6a999cdb9", + "rev": "652fda4ca6dafeb090943422c34ae9145787af37", "type": "github" }, "original": { @@ -165,11 +165,11 @@ ] }, "locked": { - "lastModified": 1706509827, - "narHash": "sha256-fnZ8BXDgfvXGwStQvmpUXe+I+Fjd2JCLm8xo0kVwVKc=", + "lastModified": 1707082092, + "narHash": "sha256-icyIxbBXl1iG8gvF/gjGI5N4Phpoo1vFcQxmUz2DsNA=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "e2c026d8efea340d2a2dcc56775212979dd51ef2", + "rev": "3a9a168c04218418a6321e157b0f7a31a9ca342c", "type": "github" }, "original": { @@ -202,11 +202,11 @@ ] }, "locked": { - "lastModified": 1706750085, - "narHash": "sha256-y/+t2ctdeUD/b0DLWS96UgGUs/srj7vbWef709DPxW4=", + "lastModified": 1707009330, + "narHash": "sha256-epbXYb2noN8otPuTzYpxORRQcHKgm1E4wWJgZghynZs=", "owner": "fufexan", "repo": "nix-gaming", - "rev": "63fa64659760172fef0e4d674c6661b7ad53b16b", + "rev": "9bef54c361ae6fb8318ffb5e5d6d28c370c3a3d5", "type": "github" }, "original": { @@ -259,11 +259,11 @@ ] }, "locked": { - "lastModified": 1706411424, - "narHash": "sha256-BzziJYucEZvdCE985vjPoo3ztWcmUiSQ1wJ2CoT6jCc=", + "lastModified": 1707016097, + "narHash": "sha256-V4lHr6hFQ3rK650dh64Xffxsf4kse9vUYWsM+ldjkco=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "c782f2a4f6fc94311ab5ef31df2f1149a1856181", + "rev": "3e3dad2808379c522138e2e8b0eb73500721a237", "type": "github" }, "original": { @@ -279,11 +279,11 @@ ] }, "locked": { - "lastModified": 1706411424, - "narHash": "sha256-BzziJYucEZvdCE985vjPoo3ztWcmUiSQ1wJ2CoT6jCc=", + "lastModified": 1707016097, + "narHash": "sha256-V4lHr6hFQ3rK650dh64Xffxsf4kse9vUYWsM+ldjkco=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "c782f2a4f6fc94311ab5ef31df2f1149a1856181", + "rev": "3e3dad2808379c522138e2e8b0eb73500721a237", "type": "github" }, "original": { @@ -311,11 +311,11 @@ "nixpkgs-lib": { "locked": { "dir": "lib", - "lastModified": 1703961334, - "narHash": "sha256-M1mV/Cq+pgjk0rt6VxoyyD+O8cOUiai8t9Q6Yyq4noY=", + "lastModified": 1706550542, + "narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b0d36bd0a420ecee3bc916c91886caca87c894e9", + "rev": "97b17f32362e475016f942bbdfda4a4a72a8a652", "type": "github" }, "original": { @@ -328,11 +328,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1706718339, - "narHash": "sha256-S+S97c/HzkO2A/YsU7ZmNF9w2s7Xk6P8dzmfDdckzLs=", + "lastModified": 1706826059, + "narHash": "sha256-N69Oab+cbt3flLvYv8fYnEHlBsWwdKciNZHUbynVEOA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "53fbe41cf76b6a685004194e38e889bc8857e8c2", + "rev": "25e3d4c0d3591c99929b1ec07883177f6ea70c9d", "type": "github" }, "original": { @@ -343,11 +343,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1706550542, - "narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=", + "lastModified": 1706913249, + "narHash": "sha256-x3M7iV++CsvRXI1fpyFPduGELUckZEhSv0XWnUopAG8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "97b17f32362e475016f942bbdfda4a4a72a8a652", + "rev": "e92b6015881907e698782c77641aa49298330223", "type": "github" }, "original": { @@ -358,11 +358,11 @@ }, "nur": { "locked": { - "lastModified": 1706863127, - "narHash": "sha256-GYAHiJ6Q/aJKJt2UbPh5/l+Zpmj+ofjckmGcMl/6t2w=", + "lastModified": 1707090259, + "narHash": "sha256-ZZEQCpPohb2KbaRK3ijp+fbuAISevFp9FpADjFjq5bc=", "owner": "nix-community", "repo": "NUR", - "rev": "bfb80b4b69abcdab9f09e83637fb88de3c5c890c", + "rev": "51437703b754e4be55f604c6cfb8eee8f8874ab8", "type": "github" }, "original": { @@ -381,11 +381,11 @@ ] }, "locked": { - "lastModified": 1706718414, - "narHash": "sha256-qOwU5X0nG4nJ3xBSKWfJ9ROf6T2r7jThO85AiBimwgc=", + "lastModified": 1707045317, + "narHash": "sha256-o2NZJcNu2/M3qycZ2Z9sgIESQEBFmihbbA7//sp7yVA=", "owner": "pjones", "repo": "plasma-manager", - "rev": "91b5335d4310e94527a8a778d5e8884c43340276", + "rev": "290cd65b65e2da11ca9fda69781ea9beb8a6f6ac", "type": "github" }, "original": { @@ -453,11 +453,11 @@ ] }, "locked": { - "lastModified": 1706836587, - "narHash": "sha256-+NsqaijHVIaPepCwkbhXyocHR0N+1PsRjQfX6PRHkkA=", + "lastModified": 1707009713, + "narHash": "sha256-oDr8YWRKFmwV2+B4H0ih7BbYjKAMi99yBpzVAXdWWo0=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "67b1cc7b069da720c8c3af0ab1b19eae28c6bb07", + "rev": "5a034e1b2dee0df8c8d8a6b25902fbc61c26a139", "type": "github" }, "original": { From de85ce8d81f2c81e4bc60c4ae81f6525768a5c5f Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 11:00:17 +0100 Subject: [PATCH 0417/1125] Update x server layout option --- machines/WinMax2/configuration.nix | 3 +-- roles/common/configuration.nix | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index b41a681..70b2c53 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -57,8 +57,6 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="d nix.settings.auto-optimise-store = true; - services.xserver.layout = lib.mkForce "us"; - # Configure network proxy if necessary # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; @@ -66,6 +64,7 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="d # Enable the X11 windowing system. services.xserver = { enable = true; + xkb.layout = lib.mkForce "us"; displayManager.sddm.settings = { General.GreeterEnvironment="QT_SCREEN_SCALE_FACTORS=1.75"; }; diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index a8f4887..a0d7fea 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -27,7 +27,7 @@ boot.kernelParams = [ "zswap.enabled=0" ]; # Set up keyboard layout - services.xserver.layout = "es"; + services.xserver.xkb.layout = "es"; # Set up console console = { From cb538d49fcb72ac3fd392792a9432eec2c7e07fd Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 11:11:28 +0100 Subject: [PATCH 0418/1125] Desktop: enable NetworkManager --- roles/desktop/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index 7a07df6..5b090c1 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -8,6 +8,8 @@ }; users.users.toast.extraGroups = [ "scanner" ]; + networking.networkmanager.enable = true; + # Set up fonts fonts.packages = [ ( pkgs.nerdfonts.override { fonts = [ "Hack" "JetBrainsMono" ]; } ) From d14a5e89c38368bb0914de1274c926f647856821 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 11:13:36 +0100 Subject: [PATCH 0419/1125] Desktop: enable x server --- roles/desktop/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index 5b090c1..3a10fee 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -10,6 +10,8 @@ networking.networkmanager.enable = true; + services.xserver.enable = true; + # Set up fonts fonts.packages = [ ( pkgs.nerdfonts.override { fonts = [ "Hack" "JetBrainsMono" ]; } ) From ad10e13501f08f7761750860eebad553e6bfe7b7 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 12:59:20 +0100 Subject: [PATCH 0420/1125] Common: set up user --- roles/common/configuration.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index a0d7fea..0666e24 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -59,6 +59,13 @@ services.fwupd.enable = true; + # Set up my user + users.users.toast = { + isNormalUser = true; + description = "Toast"; + extraGroupps = [ "wheel" ]; + }; + # Set up time zone. time.timeZone = "Europe/Madrid"; From 75cf2f674035f263d11141c9e7c8543faad9423a Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 11:11:52 +0100 Subject: [PATCH 0421/1125] Machines: remove redundant options --- machines/Archie/configuration.nix | 12 ------------ machines/Everest/configuration.nix | 5 +---- machines/SteamDeck/configuration.nix | 13 ------------- machines/SurfaceGo/configuration.nix | 10 ---------- machines/WinMax2/configuration.nix | 9 --------- 5 files changed, 1 insertion(+), 48 deletions(-) diff --git a/machines/Archie/configuration.nix b/machines/Archie/configuration.nix index 7784db6..9c1ae34 100644 --- a/machines/Archie/configuration.nix +++ b/machines/Archie/configuration.nix @@ -21,7 +21,6 @@ boot.kernelPackages = pkgs.linuxKernel.packages.linux_xanmod_latest; networking.hostName = "Archie"; # Define your hostname. - networking.networkmanager.enable = true; # Enable networking # Allow unfree packages nixpkgs.config.allowUnfree = true; @@ -30,9 +29,6 @@ # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - # Enable the X11 windowing system. - services.xserver.enable = true; - # Configure keymap in X11 # services.xserver.layout = "us"; # services.xserver.xkbOptions = "eurosign:e,caps:escape"; @@ -47,14 +43,6 @@ # Enable touchpad support (enabled default in most desktopManager). # services.xserver.libinput.enable = true; - # Define a user account. Don't forget to set a password with ‘passwd’. - users.users.toast = { - isNormalUser = true; - extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. - packages = with pkgs; [ - tree - ]; - }; hardware.bluetooth.enable = true; diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index 3a860e1..085260d 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -38,10 +38,7 @@ # Define a user account. Don't forget to set a password with ‘passwd’. users.users.toast = { - isNormalUser = true; - description = "Toast"; - extraGroups = [ "networkmanager" "wheel" "transmission"]; - packages = with pkgs; []; + extraGroups = [ "networkmanager" "transmission"]; openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2bOVmxUNvg9qFv9DlzMmTRlzcNsyNq1F1wBuAXySwsWAzHGaO+WGdSCINxW3k2ccXn7M/o1r89LeTzRzi8sWQYCpBaIqYVszM/r7SvTS4gASyKhM6lNlyUEPOnvCXH7rdtF+fjoA1TJPv7GBk78QRhGh+eVO3qhY1m++5C1CPFlyrc6sSfgIBQJ5GQZFl/7YEgsrPo+M+0Sd7LkaCOyNmJA0Wi0BA3bbf5sJhrZVMMg/p7w+eMphz2kd1VTVjW3yeMq9zLCiu4SOTBNGCMEvKIdUZbQ83lNrqO2z1/3T1bDwJgpz3xusfkNCeNJSmhfFw5ydHEUp/9jshq38WmulKAMw2Kl/Zed62AVU7Ux7YjUkZkWvo8i3eXuLUxoG891S7cWV1/ijs9QMajOLLT14FG7RbzUYYaYlx+/iNGji9d4sp9/oMYyO45TMe+vEezFSBygP7TY0QFOr4xTi49ZRQFsszbFnGRv+k3wVKoGoeNt0xWB8pBEPFtaeHJpQyJX8= id_rsa_moon" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOeu3crGqtxwaqgoQPt5mWlC8+PL/Icvcvo0MBAaK80L Key for work laptop" diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index dc54043..930782a 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -20,7 +20,6 @@ boot.loader.efi.canTouchEfiVariables = true; networking.hostName = "SteamDeck"; # Define your hostname. - networking.networkmanager.enable = true; # Enable networking # Allow unfree packages nixpkgs.config.allowUnfree = true; @@ -31,9 +30,6 @@ # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - # Enable the X11 windowing system. - services.xserver.enable = true; - jovian = { devices.steamdeck = { enable = true; @@ -70,15 +66,6 @@ # Enable touchpad support (enabled default in most desktopManager). # services.xserver.libinput.enable = true; - # Define a user account. Don't forget to set a password with ‘passwd’. - users.users.toast = { - isNormalUser = true; - extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. - packages = with pkgs; [ - tree - ]; - }; - # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs boot.tmp.useTmpfs = false; diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix index 1dd588b..7b63b8d 100644 --- a/machines/SurfaceGo/configuration.nix +++ b/machines/SurfaceGo/configuration.nix @@ -27,7 +27,6 @@ security.tpm2.enable = true; networking.hostName = "SurfaceGo"; # Define your hostname. - networking.networkmanager.enable = true; # Enable networking # Allow unfree packages nixpkgs.config.allowUnfree = true; @@ -36,9 +35,6 @@ # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - # Enable the X11 windowing system. - services.xserver.enable = true; - # Configure keymap in X11 # services.xserver.layout = "us"; # services.xserver.xkbOptions = "eurosign:e,caps:escape"; @@ -58,12 +54,6 @@ # Enable touchpad support (enabled default in most desktopManager). # services.xserver.libinput.enable = true; - # Define a user account. Don't forget to set a password with ‘passwd’. - users.users.toast = { - isNormalUser = true; - extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. - }; - # List packages installed in system profile. To search, run: # $ nix search wget # environment.systemPackages = with pkgs; [ diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 70b2c53..1b8ddc8 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -33,7 +33,6 @@ }; networking.hostName = "WinMax2"; # Define your hostname. - networking.networkmanager.enable = true; # Enable networking specialisation.noAVX512.configuration = { # For some reason The Finals crashes on CPUs that support AVX512 @@ -61,9 +60,7 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="d # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - # Enable the X11 windowing system. services.xserver = { - enable = true; xkb.layout = lib.mkForce "us"; displayManager.sddm.settings = { General.GreeterEnvironment="QT_SCREEN_SCALE_FACTORS=1.75"; @@ -111,12 +108,6 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="d # Enable touchpad support (enabled default in most desktopManager). # services.xserver.libinput.enable = true; - # Define a user account. Don't forget to set a password with ‘passwd’. - users.users.toast = { - isNormalUser = true; - extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. - }; - # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs boot.tmp.useTmpfs = false; From 054edff989190a70d1b3382f6c78c89a7c95beaf Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 11:11:52 +0100 Subject: [PATCH 0422/1125] Common: fix typo (whoops) --- roles/common/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 0666e24..f129e53 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -63,7 +63,7 @@ users.users.toast = { isNormalUser = true; description = "Toast"; - extraGroupps = [ "wheel" ]; + extraGroups = [ "wheel" ]; }; # Set up time zone. From 11cad9233f640ddd0a05fc60cb9b194fad95acc6 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 13:28:16 +0100 Subject: [PATCH 0423/1125] Don't override handheld-daemon package in common --- machines/WinMax2/configuration.nix | 9 +++++++++ roles/common/configuration.nix | 9 --------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 1b8ddc8..6d231c1 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -47,6 +47,15 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="d ''; services.handheld-daemon = { + package = pkgs.handheld-daemon.overridePythonAttrs { + src = pkgs.fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + rev = "c074cb0e3e13ab18fd150eb36df70044ede45038"; + hash = "sha256-Jzx72d1l7v6d/fgPvj3BwAF/hgXL4MWzhPjKvtdqwfw="; + }; + version = "1.1.4"; + }; enable = true; user = "root"; }; diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index f129e53..9caaeb9 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -82,15 +82,6 @@ "grub" ]; }; - handheld-daemon = prev.handheld-daemon.overridePythonAttrs { - src = pkgs.fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - rev = "c074cb0e3e13ab18fd150eb36df70044ede45038"; - hash = "sha256-Jzx72d1l7v6d/fgPvj3BwAF/hgXL4MWzhPjKvtdqwfw="; - }; - version = "1.1.4"; - }; } ) ]; From fcb0ecb3df23881308bf7c261db61a740e281c34 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 14:03:13 +0100 Subject: [PATCH 0424/1125] Machines/WinMax2: update handheld-daemon --- machines/WinMax2/configuration.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 6d231c1..9eb4f06 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -47,14 +47,14 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="d ''; services.handheld-daemon = { - package = pkgs.handheld-daemon.overridePythonAttrs { + package = pkgs.handheld-daemon.overridePythonAttrs rec{ src = pkgs.fetchFromGitHub { owner = "hhd-dev"; repo = "hhd"; - rev = "c074cb0e3e13ab18fd150eb36df70044ede45038"; - hash = "sha256-Jzx72d1l7v6d/fgPvj3BwAF/hgXL4MWzhPjKvtdqwfw="; + rev = "v${version}"; + hash = "sha256-avlQNo2Q2AAEefwZs14fzMDuWYrj9bn9zQ18IMlmxJU="; }; - version = "1.1.4"; + version = "1.3.3"; }; enable = true; user = "root"; From d2beeff9284b70b9a8718a297cc3bdf6cc98ba70 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 14:31:16 +0100 Subject: [PATCH 0425/1125] Common/neovim: autodetect indenting --- roles/common/programs/neovim.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/common/programs/neovim.nix b/roles/common/programs/neovim.nix index 6b82c4b..104862b 100644 --- a/roles/common/programs/neovim.nix +++ b/roles/common/programs/neovim.nix @@ -7,6 +7,9 @@ plugins = with pkgs.vimPlugins; [ catppuccin-nvim ]; + extraConfig = '' + filetype indent on + ''; }; }; } From efc0440d61a68e47381a3f1a3d1c13d48d7e2900 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Feb 2024 14:31:32 +0100 Subject: [PATCH 0426/1125] Common/neovim: set as default editor --- roles/common/programs/neovim.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/programs/neovim.nix b/roles/common/programs/neovim.nix index 104862b..d45d2ce 100644 --- a/roles/common/programs/neovim.nix +++ b/roles/common/programs/neovim.nix @@ -7,6 +7,7 @@ plugins = with pkgs.vimPlugins; [ catppuccin-nvim ]; + defaultEditor = true; extraConfig = '' filetype indent on ''; From 0adf440318b03ba68f5ccc2ae4d9b9aec0de2722 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 7 Feb 2024 12:18:19 +0100 Subject: [PATCH 0427/1125] Common: replace neovim with helix --- roles/common/programs/default.nix | 2 +- roles/common/programs/helix.nix | 22 ++++++++++++++++++++++ roles/common/programs/neovim.nix | 16 ---------------- 3 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 roles/common/programs/helix.nix delete mode 100644 roles/common/programs/neovim.nix diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index 7950344..8641b50 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -13,7 +13,7 @@ ./starship.nix ./bat.nix ./btop.nix - ./neovim.nix + ./helix.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix new file mode 100644 index 0000000..8e60ecc --- /dev/null +++ b/roles/common/programs/helix.nix @@ -0,0 +1,22 @@ +{ pkgs, ... }: + +{ + home-manager.users.toast = { + programs.helix = { + enable = true; + defaultEditor = true; + settings = { + theme = "catppuccin_mocha"; + editor = { + mouse = true; + cursorline = true; + statusline.mode = { + normal = "Normal"; + insert = "Insert"; + select = "Select"; + }; + }; + }; + }; + }; +} diff --git a/roles/common/programs/neovim.nix b/roles/common/programs/neovim.nix deleted file mode 100644 index d45d2ce..0000000 --- a/roles/common/programs/neovim.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ pkgs, ... }: - -{ - home-manager.users.toast = { - programs.neovim = { - enable = true; - plugins = with pkgs.vimPlugins; [ - catppuccin-nvim - ]; - defaultEditor = true; - extraConfig = '' - filetype indent on - ''; - }; - }; -} From 9166ecdede0bc9747eca137d4164ba1895726c65 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 7 Feb 2024 14:12:48 +0100 Subject: [PATCH 0428/1125] Common/helix: enable indent guides --- roles/common/programs/helix.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index 8e60ecc..a542a4a 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -15,6 +15,7 @@ insert = "Insert"; select = "Select"; }; + indent-guides.render = true; }; }; }; From b59d94321a7ebedb10fadde4f5d4f0fa9a936593 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 7 Feb 2024 19:24:04 +0100 Subject: [PATCH 0429/1125] Machines/WinMax2: update handeld-daemon --- machines/WinMax2/configuration.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 9eb4f06..c385e37 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -52,9 +52,9 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="d owner = "hhd-dev"; repo = "hhd"; rev = "v${version}"; - hash = "sha256-avlQNo2Q2AAEefwZs14fzMDuWYrj9bn9zQ18IMlmxJU="; + hash = "sha256-3xJs+IjyTPC3R9YthmutP+yUlNlBN2K/aDqbKAJ44PA="; }; - version = "1.3.3"; + version = "1.3.6"; }; enable = true; user = "root"; From ec8de77c541ee74cb1c94c6c92d30d05a213a19f Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 7 Feb 2024 20:24:58 +0100 Subject: [PATCH 0430/1125] Flake: update lock file --- flake.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/flake.lock b/flake.lock index a51b029..b3c29d7 100644 --- a/flake.lock +++ b/flake.lock @@ -123,11 +123,11 @@ ] }, "locked": { - "lastModified": 1707088232, - "narHash": "sha256-nxPBAZ//BwKkBcjwLE5g9zTq29g7gccTnH5+CeMTxpA=", + "lastModified": 1707175763, + "narHash": "sha256-0MKHC6tQ4KEuM5rui6DjKZ/VNiSANB4E+DJ/+wPS1PU=", "owner": "nix-community", "repo": "home-manager", - "rev": "4740f2ccda184e9cc509d7a82b26d7271e0c79d9", + "rev": "f99eace7c167b8a6a0871849493b1c613d0f1b80", "type": "github" }, "original": { @@ -165,11 +165,11 @@ ] }, "locked": { - "lastModified": 1707082092, - "narHash": "sha256-icyIxbBXl1iG8gvF/gjGI5N4Phpoo1vFcQxmUz2DsNA=", + "lastModified": 1707226874, + "narHash": "sha256-uo3oGHc/oLbcS6tDlm+Z130tQNRX2ufs9r+kGRTx0Ng=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "3a9a168c04218418a6321e157b0f7a31a9ca342c", + "rev": "8f355736d9449a6650418f8e70f8dacf652401a7", "type": "github" }, "original": { @@ -202,11 +202,11 @@ ] }, "locked": { - "lastModified": 1707009330, - "narHash": "sha256-epbXYb2noN8otPuTzYpxORRQcHKgm1E4wWJgZghynZs=", + "lastModified": 1707095568, + "narHash": "sha256-6zZifK7cs9eWiC+3MQvlMsq2JeyH7hPSP0qZ6sTny68=", "owner": "fufexan", "repo": "nix-gaming", - "rev": "9bef54c361ae6fb8318ffb5e5d6d28c370c3a3d5", + "rev": "9bde4efca9e4750ed691520d68c4c6eb308015e7", "type": "github" }, "original": { @@ -294,11 +294,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1706834982, - "narHash": "sha256-3CfxA7gZ+DVv/N9Pvw61bV5Oe/mWfxYPyVQGqp9TMJA=", + "lastModified": 1707211557, + "narHash": "sha256-LTKTzZ6fM5j8XWXf51IMBzDaOaJg9kYWLUZxoIhzRN8=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "83e571bb291161682b9c3ccd48318f115143a550", + "rev": "6e5cc385fc8cf5ca6495d70243074ccdea9f64c7", "type": "github" }, "original": { @@ -328,11 +328,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1706826059, - "narHash": "sha256-N69Oab+cbt3flLvYv8fYnEHlBsWwdKciNZHUbynVEOA=", + "lastModified": 1707091808, + "narHash": "sha256-LahKBAfGbY836gtpVNnWwBTIzN7yf/uYM/S0g393r0Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "25e3d4c0d3591c99929b1ec07883177f6ea70c9d", + "rev": "9f2ee8c91ac42da3ae6c6a1d21555f283458247e", "type": "github" }, "original": { @@ -343,11 +343,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1706913249, - "narHash": "sha256-x3M7iV++CsvRXI1fpyFPduGELUckZEhSv0XWnUopAG8=", + "lastModified": 1707092692, + "narHash": "sha256-ZbHsm+mGk/izkWtT4xwwqz38fdlwu7nUUKXTOmm4SyE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e92b6015881907e698782c77641aa49298330223", + "rev": "faf912b086576fd1a15fca610166c98d47bc667e", "type": "github" }, "original": { @@ -358,11 +358,11 @@ }, "nur": { "locked": { - "lastModified": 1707090259, - "narHash": "sha256-ZZEQCpPohb2KbaRK3ijp+fbuAISevFp9FpADjFjq5bc=", + "lastModified": 1707330307, + "narHash": "sha256-kR7DeIy4C0XwR36X4O+98cjWK8S3jpPAopNDz+eDSgI=", "owner": "nix-community", "repo": "NUR", - "rev": "51437703b754e4be55f604c6cfb8eee8f8874ab8", + "rev": "4d14dfd1ee00acc4e2e38982c4b104dce2e64b30", "type": "github" }, "original": { @@ -453,11 +453,11 @@ ] }, "locked": { - "lastModified": 1707009713, - "narHash": "sha256-oDr8YWRKFmwV2+B4H0ih7BbYjKAMi99yBpzVAXdWWo0=", + "lastModified": 1707268437, + "narHash": "sha256-V2R7OyXn5E5A9YuAmpLTDGjHmxuFBRHFTyf9RoloYXw=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "5a034e1b2dee0df8c8d8a6b25902fbc61c26a139", + "rev": "bdb6e70f3dd307fdd9a20698a861d8f298883ea1", "type": "github" }, "original": { From 93f60414ac133493f41f03ce889c0d901351c6c1 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 9 Feb 2024 01:04:09 +0100 Subject: [PATCH 0431/1125] Common/helix: add nil (nix lsp) --- roles/common/programs/helix.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index a542a4a..a10c323 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -5,6 +5,9 @@ programs.helix = { enable = true; defaultEditor = true; + extraPackages = with pkgs; [ + nil + ]; settings = { theme = "catppuccin_mocha"; editor = { From 80eaacd3a36d553767ec0eaceaf29db8bb8c445c Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 9 Feb 2024 01:06:06 +0100 Subject: [PATCH 0432/1125] Common/helix: add nixpkgs-fmt (nix formatter) --- roles/common/programs/helix.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index a10c323..5a535fb 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -6,9 +6,10 @@ enable = true; defaultEditor = true; extraPackages = with pkgs; [ + nixpkgs-fmt nil ]; - settings = { + settings = { theme = "catppuccin_mocha"; editor = { mouse = true; @@ -21,6 +22,12 @@ indent-guides.render = true; }; }; + languages = [ + { + name = "nix"; + formatter.command = "nixpkgs-fmt"; + } + ]; }; }; } From b27ddf6aadd22ea679d8cb88a12af8a1af0667cb Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 9 Feb 2024 14:12:43 +0100 Subject: [PATCH 0433/1125] Common/helix: manually write languages.toml and configure nil for formatting --- roles/common/programs/helix.nix | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index 5a535fb..00f0af2 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -22,12 +22,17 @@ indent-guides.render = true; }; }; - languages = [ - { - name = "nix"; - formatter.command = "nixpkgs-fmt"; - } - ]; + }; + # The builtin languages options have issues + # https://github.com/nix-community/home-manager/issues/3299 + xdg.configFile."helixLanguages" = { + target = "helix/languages.toml"; + text = '' + [language-server.nil] + config.nil.formatting.command = [ "nixpkgs-fmt" ] + [[language]] + name = "nix" + ''; }; }; } From fea701c7b85002d4899bee1a27ad54020cc026ae Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 9 Feb 2024 15:40:43 +0100 Subject: [PATCH 0434/1125] Desktop/vscode: configure nil to use nixpkgs-fmt to format --- roles/desktop/programs/vscode.nix | 56 ++++++++++++++++++------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index bfd7c38..d75c465 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -2,31 +2,39 @@ let inputs = flakeSelf.inputs; in { nixpkgs.overlays = [ inputs.catppuccin-vsc.overlays.default ]; - home-manager.users.toast.programs.vscode = { - enable = true; - package = pkgs.vscodium; - mutableExtensionsDir = false; - extensions = with inputs.vscode-extensions.extensions.x86_64-linux.open-vsx; [ - jnoortheen.nix-ide - (pkgs.catppuccin-vsc.override { - workbenchMode = "flat"; - extraBordersEnabled = true; - }) - catppuccin.catppuccin-vsc-icons - waderyan.gitblame + home-manager.users.toast = { + home.packages = with pkgs; [ + nixpkgs-fmt ]; - userSettings = { - # VSCode doesn't like nested settings - # https://stackoverflow.com/questions/74134436/is-it-possible-to-express-settings-in-vs-codes-settings-json-where-each-dot-sep - # TODO: write a function that unnests settings - "workbench.colorTheme" = "Catppuccin Mocha"; - "workbench.iconTheme" = "catppuccin-mocha"; - "editor.fontFamily" = "JetBrainsMono Nerd Font"; - "editor.semanticHighlighting.enabled" = true; - "nix.enableLanguageServer" = true; - "nix.serverPath" = "${pkgs.nil}/bin/nil"; - "terminal.integrated.minimumContrastRatio" = 1; - "window.titleBarStyle" = "custom"; + programs.vscode = { + enable = true; + package = pkgs.vscodium; + mutableExtensionsDir = false; + extensions = with inputs.vscode-extensions.extensions.x86_64-linux.open-vsx; [ + jnoortheen.nix-ide + (pkgs.catppuccin-vsc.override { + workbenchMode = "flat"; + extraBordersEnabled = true; + }) + catppuccin.catppuccin-vsc-icons + waderyan.gitblame + ]; + userSettings = { + # VSCode doesn't like nested settings + # https://stackoverflow.com/questions/74134436/is-it-possible-to-express-settings-in-vs-codes-settings-json-where-each-dot-sep + # TODO: write a function that unnests settings + "workbench.colorTheme" = "Catppuccin Mocha"; + "workbench.iconTheme" = "catppuccin-mocha"; + "editor.fontFamily" = "JetBrainsMono Nerd Font"; + "editor.semanticHighlighting.enabled" = true; + "nix.enableLanguageServer" = true; + "nix.serverPath" = "${pkgs.nil}/bin/nil"; + "nix.serverSettings" = { + "nil"."formatting"."command" = [ "nixpkgs-fmt" ]; + }; + "terminal.integrated.minimumContrastRatio" = 1; + "window.titleBarStyle" = "custom"; + }; }; }; } From 7af7bd2b4f931a0cf66ff95014f78a2ed5b8943f Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 14 Feb 2024 12:30:24 +0100 Subject: [PATCH 0435/1125] Common/helix: enable color modes --- roles/common/programs/helix.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index 00f0af2..2a0669d 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -14,6 +14,7 @@ editor = { mouse = true; cursorline = true; + color-modes = true; statusline.mode = { normal = "Normal"; insert = "Insert"; From cbe3645a3a9d84c8b572d003ea2e8cf534521799 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 14 Feb 2024 12:30:54 +0100 Subject: [PATCH 0436/1125] Common/helix: show buffer line if multiple buffers exist --- roles/common/programs/helix.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index 2a0669d..78f09da 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -15,6 +15,7 @@ mouse = true; cursorline = true; color-modes = true; + bufferline = "multiple"; statusline.mode = { normal = "Normal"; insert = "Insert"; From 8a0a0ff09e799b56bdf54c4ab6f27f29f67984b7 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 14 Feb 2024 13:13:13 +0100 Subject: [PATCH 0437/1125] Flake: update lock file --- flake.lock | 78 +++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/flake.lock b/flake.lock index b3c29d7..23f36a7 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1703433843, - "narHash": "sha256-nmtA4KqFboWxxoOAA6Y1okHbZh+HsXaMPFkYHsoDRDw=", + "lastModified": 1707830867, + "narHash": "sha256-PAdwm5QqdlwIqGrfzzvzZubM+FXtilekQ/FA0cI49/o=", "owner": "ryantm", "repo": "agenix", - "rev": "417caa847f9383e111d1397039c9d4337d024bf0", + "rev": "8cb01a0e717311680e0cbca06a76cbceba6f3ed6", "type": "github" }, "original": { @@ -30,11 +30,11 @@ ] }, "locked": { - "lastModified": 1707059042, - "narHash": "sha256-6tomg1cTo7cwd7U3hIyDMA5iBuHg82cTr9TrUGnfxMw=", + "lastModified": 1707530346, + "narHash": "sha256-LGvGeDwQtVQ4Pfa7JJKESAUg3n7Dy9d4kVCZf69kDRY=", "owner": "catppuccin", "repo": "vscode", - "rev": "50aa91ba31192bef8563a96e246d469091502d10", + "rev": "a5c28e9319556c696e184a2f2f49813288063ed6", "type": "github" }, "original": { @@ -123,11 +123,11 @@ ] }, "locked": { - "lastModified": 1707175763, - "narHash": "sha256-0MKHC6tQ4KEuM5rui6DjKZ/VNiSANB4E+DJ/+wPS1PU=", + "lastModified": 1707919853, + "narHash": "sha256-qxmBGDzutuJ/tsX4gp+Mr7fjxOZBbeT9ixhS5o4iFOw=", "owner": "nix-community", "repo": "home-manager", - "rev": "f99eace7c167b8a6a0871849493b1c613d0f1b80", + "rev": "043ba285c6dc20f36441d48525402bcb9743c498", "type": "github" }, "original": { @@ -165,11 +165,11 @@ ] }, "locked": { - "lastModified": 1707226874, - "narHash": "sha256-uo3oGHc/oLbcS6tDlm+Z130tQNRX2ufs9r+kGRTx0Ng=", + "lastModified": 1707845461, + "narHash": "sha256-aTAhJyNvMzYjncOAUWyKdFdjmaRbDx5xhYflf1S+oHc=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "8f355736d9449a6650418f8e70f8dacf652401a7", + "rev": "c87a9c5aa904e98a49c66ab82322b754598a4256", "type": "github" }, "original": { @@ -180,11 +180,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1706716715, - "narHash": "sha256-aoUh0585v3mMkqGV+aggvs9uZQdZWSqMEGGVUT1jX38=", + "lastModified": 1707731066, + "narHash": "sha256-8eK9mny6I3B1eMOYu9iDhKTY6jXfvrxJoH7jMqIm/hs=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "30f6cb66a1be2a350b08b13e820122b0f3d4bd81", + "rev": "8d8da0b127b6dbb4ce5256e5708eca2efe2409f6", "type": "github" }, "original": { @@ -202,11 +202,11 @@ ] }, "locked": { - "lastModified": 1707095568, - "narHash": "sha256-6zZifK7cs9eWiC+3MQvlMsq2JeyH7hPSP0qZ6sTny68=", + "lastModified": 1707614138, + "narHash": "sha256-xdmNhDnlDF5H/yT1wLGqwVyphjj03lmA/e3SGXyC3DU=", "owner": "fufexan", "repo": "nix-gaming", - "rev": "9bde4efca9e4750ed691520d68c4c6eb308015e7", + "rev": "a5de885438ecce695b4b7a110974c33f0eb507e3", "type": "github" }, "original": { @@ -259,11 +259,11 @@ ] }, "locked": { - "lastModified": 1707016097, - "narHash": "sha256-V4lHr6hFQ3rK650dh64Xffxsf4kse9vUYWsM+ldjkco=", + "lastModified": 1707620986, + "narHash": "sha256-XE0tCSkSVBeJDWhjFwusNInwAhrnp+TloUNUpvnTiLw=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "3e3dad2808379c522138e2e8b0eb73500721a237", + "rev": "0cb4345704123492e6d1f1068629069413c80de0", "type": "github" }, "original": { @@ -279,11 +279,11 @@ ] }, "locked": { - "lastModified": 1707016097, - "narHash": "sha256-V4lHr6hFQ3rK650dh64Xffxsf4kse9vUYWsM+ldjkco=", + "lastModified": 1707620986, + "narHash": "sha256-XE0tCSkSVBeJDWhjFwusNInwAhrnp+TloUNUpvnTiLw=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "3e3dad2808379c522138e2e8b0eb73500721a237", + "rev": "0cb4345704123492e6d1f1068629069413c80de0", "type": "github" }, "original": { @@ -294,11 +294,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1707211557, - "narHash": "sha256-LTKTzZ6fM5j8XWXf51IMBzDaOaJg9kYWLUZxoIhzRN8=", + "lastModified": 1707842204, + "narHash": "sha256-M+HAq1qWQBi/gywaMZwX0odU+Qb/XeqVeANGKRBDOwU=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "6e5cc385fc8cf5ca6495d70243074ccdea9f64c7", + "rev": "f1b2f71c86a5b1941d20608db0b1e88a07d31303", "type": "github" }, "original": { @@ -328,11 +328,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1707091808, - "narHash": "sha256-LahKBAfGbY836gtpVNnWwBTIzN7yf/uYM/S0g393r0Y=", + "lastModified": 1707786466, + "narHash": "sha256-yLPfrmW87M2qt+8bAmwopJawa+MJLh3M9rUbXtpUc1o=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9f2ee8c91ac42da3ae6c6a1d21555f283458247e", + "rev": "01885a071465e223f8f68971f864b15829988504", "type": "github" }, "original": { @@ -343,11 +343,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1707092692, - "narHash": "sha256-ZbHsm+mGk/izkWtT4xwwqz38fdlwu7nUUKXTOmm4SyE=", + "lastModified": 1707689078, + "narHash": "sha256-UUGmRa84ZJHpGZ1WZEBEUOzaPOWG8LZ0yPg1pdDF/yM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "faf912b086576fd1a15fca610166c98d47bc667e", + "rev": "f9d39fb9aff0efee4a3d5f4a6d7c17701d38a1d8", "type": "github" }, "original": { @@ -358,11 +358,11 @@ }, "nur": { "locked": { - "lastModified": 1707330307, - "narHash": "sha256-kR7DeIy4C0XwR36X4O+98cjWK8S3jpPAopNDz+eDSgI=", + "lastModified": 1707932646, + "narHash": "sha256-d41Jz73mc3uEmgLwrrZL2FywNXf2xYVyIMOh5A3zCUE=", "owner": "nix-community", "repo": "NUR", - "rev": "4d14dfd1ee00acc4e2e38982c4b104dce2e64b30", + "rev": "c9ce9d9d4df39c555e7c866cfcc84f28a9ebc6e4", "type": "github" }, "original": { @@ -381,11 +381,11 @@ ] }, "locked": { - "lastModified": 1707045317, - "narHash": "sha256-o2NZJcNu2/M3qycZ2Z9sgIESQEBFmihbbA7//sp7yVA=", + "lastModified": 1707590627, + "narHash": "sha256-LJ/lFEupLSi7xtUps234hhMk7ZdVLRoYeU7KiCFaoGw=", "owner": "pjones", "repo": "plasma-manager", - "rev": "290cd65b65e2da11ca9fda69781ea9beb8a6f6ac", + "rev": "4e56cfeb95081a43cb49487d0996dc936d6201e5", "type": "github" }, "original": { From b89652f269bae120bb7fb9d20974d2353664f7f8 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 14 Feb 2024 19:44:02 +0100 Subject: [PATCH 0438/1125] Machines/WinMax2: don't import cryolitia's nur repo --- machines/WinMax2/hardware-configuration.nix | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/machines/WinMax2/hardware-configuration.nix b/machines/WinMax2/hardware-configuration.nix index 9f4145d..de97fb0 100755 --- a/machines/WinMax2/hardware-configuration.nix +++ b/machines/WinMax2/hardware-configuration.nix @@ -1,25 +1,16 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, flakeSelf, modulesPath, ... }: +{ config, lib, modulesPath, ... }: let # \x20 is the escape code for a space ssdLabel = ''Win\\x20Max\\x202\\x20SSD''; - - # You need to do fucky shit to import modules from the NUR - # https://github.com/nix-community/NUR#using-the-flake-in-nixos - nur = import flakeSelf.inputs.nur { - nurpkgs = import flakeSelf.inputs.nixpkgs-unstable-raw { - system = "x86_64-linux"; - }; - }; in { imports = [ (modulesPath + "/installer/scan/not-detected.nix") - nur.repos.cryolitia.modules.bmi260 ]; boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usbhid" "sdhci_pci" ]; From 73a1fa2f84e340dabfe7cb6bd132908aa90e01e2 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 09:55:13 +0100 Subject: [PATCH 0439/1125] Flake: update lock file --- flake.lock | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/flake.lock b/flake.lock index 23f36a7..15b7eeb 100644 --- a/flake.lock +++ b/flake.lock @@ -123,11 +123,11 @@ ] }, "locked": { - "lastModified": 1707919853, - "narHash": "sha256-qxmBGDzutuJ/tsX4gp+Mr7fjxOZBbeT9ixhS5o4iFOw=", + "lastModified": 1708294481, + "narHash": "sha256-DZtxmeb4OR7iCaKUUuq05ADV2rX8WReZEF7Tq//W0+Y=", "owner": "nix-community", "repo": "home-manager", - "rev": "043ba285c6dc20f36441d48525402bcb9743c498", + "rev": "a54e05bc12d88ff2df941d0dc1183cb5235fa438", "type": "github" }, "original": { @@ -165,11 +165,11 @@ ] }, "locked": { - "lastModified": 1707845461, - "narHash": "sha256-aTAhJyNvMzYjncOAUWyKdFdjmaRbDx5xhYflf1S+oHc=", + "lastModified": 1708148641, + "narHash": "sha256-UliMMpx84PPA+0mcyBj2yuKNawOX7L4u/wO8j9QGHVk=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "c87a9c5aa904e98a49c66ab82322b754598a4256", + "rev": "f318a856ff3177fdea6044d6c77dd49992330a31", "type": "github" }, "original": { @@ -180,11 +180,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1707731066, - "narHash": "sha256-8eK9mny6I3B1eMOYu9iDhKTY6jXfvrxJoH7jMqIm/hs=", + "lastModified": 1708268179, + "narHash": "sha256-NNVuhf84AeDTxadfSGnFqPHR0ED+QyM2gmu+Wyz6PrY=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "8d8da0b127b6dbb4ce5256e5708eca2efe2409f6", + "rev": "a243cb0522f6240c194b873dde68e25370b06034", "type": "github" }, "original": { @@ -202,11 +202,11 @@ ] }, "locked": { - "lastModified": 1707614138, - "narHash": "sha256-xdmNhDnlDF5H/yT1wLGqwVyphjj03lmA/e3SGXyC3DU=", + "lastModified": 1708267826, + "narHash": "sha256-sv5L5iFnXa5wFxMXAEdW7Fcd6dFtAcvDETbKaS7JWZw=", "owner": "fufexan", "repo": "nix-gaming", - "rev": "a5de885438ecce695b4b7a110974c33f0eb507e3", + "rev": "f961c5727fd812c2f0db1425d09ad55b35652587", "type": "github" }, "original": { @@ -259,11 +259,11 @@ ] }, "locked": { - "lastModified": 1707620986, - "narHash": "sha256-XE0tCSkSVBeJDWhjFwusNInwAhrnp+TloUNUpvnTiLw=", + "lastModified": 1708225687, + "narHash": "sha256-NJBDfvknI26beOFmjO2coeJMTTUCCtw2Iu+rvJ1Zb9k=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "0cb4345704123492e6d1f1068629069413c80de0", + "rev": "17352eb241a8d158c4ac523b19d8d2a6c8efe127", "type": "github" }, "original": { @@ -279,11 +279,11 @@ ] }, "locked": { - "lastModified": 1707620986, - "narHash": "sha256-XE0tCSkSVBeJDWhjFwusNInwAhrnp+TloUNUpvnTiLw=", + "lastModified": 1708225687, + "narHash": "sha256-NJBDfvknI26beOFmjO2coeJMTTUCCtw2Iu+rvJ1Zb9k=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "0cb4345704123492e6d1f1068629069413c80de0", + "rev": "17352eb241a8d158c4ac523b19d8d2a6c8efe127", "type": "github" }, "original": { @@ -294,11 +294,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1707842204, - "narHash": "sha256-M+HAq1qWQBi/gywaMZwX0odU+Qb/XeqVeANGKRBDOwU=", + "lastModified": 1708091350, + "narHash": "sha256-o28BJYi68qqvHipT7V2jkWxDiMS1LF9nxUsou+eFUPQ=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "f1b2f71c86a5b1941d20608db0b1e88a07d31303", + "rev": "106d3fec43bcea19cb2e061ca02531d54b542ce3", "type": "github" }, "original": { @@ -328,11 +328,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1707786466, - "narHash": "sha256-yLPfrmW87M2qt+8bAmwopJawa+MJLh3M9rUbXtpUc1o=", + "lastModified": 1708161998, + "narHash": "sha256-6KnemmUorCvlcAvGziFosAVkrlWZGIc6UNT9GUYr0jQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "01885a071465e223f8f68971f864b15829988504", + "rev": "84d981bae8b5e783b3b548de505b22880559515f", "type": "github" }, "original": { @@ -343,11 +343,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1707689078, - "narHash": "sha256-UUGmRa84ZJHpGZ1WZEBEUOzaPOWG8LZ0yPg1pdDF/yM=", + "lastModified": 1708118438, + "narHash": "sha256-kk9/0nuVgA220FcqH/D2xaN6uGyHp/zoxPNUmPCMmEE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f9d39fb9aff0efee4a3d5f4a6d7c17701d38a1d8", + "rev": "5863c27340ba4de8f83e7e3c023b9599c3cb3c80", "type": "github" }, "original": { @@ -358,11 +358,11 @@ }, "nur": { "locked": { - "lastModified": 1707932646, - "narHash": "sha256-d41Jz73mc3uEmgLwrrZL2FywNXf2xYVyIMOh5A3zCUE=", + "lastModified": 1708329376, + "narHash": "sha256-E5LJjNT6dMD2r6m93CdOccQmW3+YT7Pr2lHMMmr5pXs=", "owner": "nix-community", "repo": "NUR", - "rev": "c9ce9d9d4df39c555e7c866cfcc84f28a9ebc6e4", + "rev": "e17ac139d5903c021aff79b52d659bf90145cbb2", "type": "github" }, "original": { @@ -453,11 +453,11 @@ ] }, "locked": { - "lastModified": 1707268437, - "narHash": "sha256-V2R7OyXn5E5A9YuAmpLTDGjHmxuFBRHFTyf9RoloYXw=", + "lastModified": 1708305444, + "narHash": "sha256-hCDR72rsHC3z2YvDywRgXLiPK8emn+jtl5fdoH30aeY=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "bdb6e70f3dd307fdd9a20698a861d8f298883ea1", + "rev": "35e0cabb16c66709d6c91eda8067d740492172d5", "type": "github" }, "original": { From f4bb46fb286ed72a214fa7fd06b4b0b1b11bb744 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 11:18:32 +0100 Subject: [PATCH 0440/1125] Nix: auto optimise store --- machines/SteamDeck/configuration.nix | 2 -- machines/WinMax2/configuration.nix | 2 -- roles/common/programs/nix.nix | 3 +++ 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index 930782a..0319993 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -24,8 +24,6 @@ # Allow unfree packages nixpkgs.config.allowUnfree = true; - nix.settings.auto-optimise-store = true; - # Configure network proxy if necessary # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index c385e37..fe960af 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -63,8 +63,6 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="d # Allow unfree packages nixpkgs.config.allowUnfree = true; - nix.settings.auto-optimise-store = true; - # Configure network proxy if necessary # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index 07e90d7..deed94d 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -5,6 +5,9 @@ extraOptions = '' experimental-features = nix-command flakes ''; + settings = { + auto-optimise-store = true; + }; registry = { agenix = { from = { id = "agenix"; type = "indirect"; }; From 8d1b7584f3346be030f5654ecf81104317adcbfb Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 11:26:41 +0100 Subject: [PATCH 0441/1125] Nix: move experimantal options setting tot nix.settings --- roles/common/programs/nix.nix | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index deed94d..fd36171 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -2,11 +2,9 @@ { nix = { - extraOptions = '' -experimental-features = nix-command flakes - ''; settings = { auto-optimise-store = true; + experimental-features = "nix-command flakes"; }; registry = { agenix = { From 8a8b69b79bf4b005d5d50a8ae6791e1b303a7c81 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 13:22:25 +0100 Subject: [PATCH 0442/1125] Flake: add secrets repo --- flake.lock | 17 +++++++++++++++++ flake.nix | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/flake.lock b/flake.lock index 15b7eeb..76a0889 100644 --- a/flake.lock +++ b/flake.lock @@ -411,9 +411,26 @@ "nixpkgs-unstable-raw": "nixpkgs-unstable-raw", "nur": "nur", "plasma-manager": "plasma-manager", + "secrets": "secrets", "vscode-extensions": "vscode-extensions" } }, + "secrets": { + "flake": false, + "locked": { + "lastModified": 1708347322, + "narHash": "sha256-30rLLNMGvVz8xbklqRpA3uE6UDneAUGFz7dCmH9YbA8=", + "ref": "refs/heads/main", + "rev": "409536f1d2b8ffe741fe47b8701ba28137f9de38", + "revCount": 3, + "type": "git", + "url": "http://git.everest.sable-pancake.ts.net/Toast/nix-secrets" + }, + "original": { + "type": "git", + "url": "http://git.everest.sable-pancake.ts.net/Toast/nix-secrets" + } + }, "systems": { "locked": { "lastModified": 1681028828, diff --git a/flake.nix b/flake.nix index 4074c49..326a5f9 100644 --- a/flake.nix +++ b/flake.nix @@ -2,6 +2,10 @@ description = "Configuration for Everest"; inputs = { + secrets = { + url = "git+http://git.everest.sable-pancake.ts.net/Toast/nix-secrets"; + flake = false; + }; nixpkgs-raw.url = "nixpkgs/nixos-23.11"; nixpkgs-unstable-raw.url = "nixpkgs/nixos-unstable"; From a1f41b62954084027a5ee0914b5399f598d9cd78 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 14:00:39 +0100 Subject: [PATCH 0443/1125] WinMax2: mount persist subvolume --- machines/WinMax2/hardware-configuration.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/machines/WinMax2/hardware-configuration.nix b/machines/WinMax2/hardware-configuration.nix index de97fb0..39126af 100755 --- a/machines/WinMax2/hardware-configuration.nix +++ b/machines/WinMax2/hardware-configuration.nix @@ -43,12 +43,12 @@ in fsType = "btrfs"; options = [ "subvol=@" ]; }; - /*"btrfs_boot" = { - mountPoint = "/boot"; + "btrfs_persist" = { + mountPoint = "/persist"; label = ssdLabel; fsType = "btrfs"; - options = [ "subvol=@boot" ]; - };*/ + options = [ "subvol=@persist" ]; + }; "btrfs_home" = { mountPoint = "/home"; label = ssdLabel; From 2f0230c4010641bd4e08f99e8bb699a9b224d26c Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 14:01:17 +0100 Subject: [PATCH 0444/1125] Common: set up secrets --- roles/common/configuration.nix | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 9caaeb9..3e42588 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -105,11 +105,7 @@ # Set up secrets age = { identityPaths = [ - "/etc/ssh/ssh_host_rsa_key" - "/etc/ssh/ssh_host_ed25519_key" - # This key has a passcode, so if you need to use it you'll have to - # enter the password A LOT of times. Only on the first setup tho - "/tmp/id_ed25519_bootstrap" + "/persist/id_host" ]; }; From 436c1785a8a03316d19d7b2118b0fbf60d31330c Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 14:02:05 +0100 Subject: [PATCH 0445/1125] Common/syncthing: use key and cert from secrets --- roles/common/services/syncthing.nix | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index 5691ef3..9bcfb63 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -1,7 +1,19 @@ -{ config, ... }: +{ config, flakeSelf, ... }: + +let + hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName; +in { + # Get secrets + age.secrets = { + syncthingKey.file = hostSecrets + "/syncthingKey.age"; + syncthingCert.file = hostSecrets + "/syncthingCert.age"; + }; + services.syncthing = { + key = config.age.secrets.syncthingKey.path; + cert = config.age.secrets.syncthingCert.path; overrideDevices = true; overrideFolders = true; openDefaultPorts = true; From d081c06a1c6e04ba34553a9fd89afc304c0f6c7e Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 21:27:22 +0100 Subject: [PATCH 0446/1125] Server/syncthing: remove redundant secrets configuration --- roles/server/syncthing.nix | 5 ----- 1 file changed, 5 deletions(-) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 48742ac..1d2b61f 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -1,11 +1,6 @@ { config, ... }: { - age.secrets = { - syncthingKey.file = ../../secrets/syncthing/key; - syncthingCert.file = ../../secrets/syncthing/cert; - }; - services.syncthing = { enable = true; key = config.age.secrets.syncthingKey.path; From 50bb1a9ba0821fae9a4e7713956e78270713d87f Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 19:08:51 +0100 Subject: [PATCH 0447/1125] Machines/Archie: mount persist subvolume --- machines/Archie/hardware-configuration.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index f123be5..2e04763 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -61,6 +61,11 @@ fsType = "btrfs"; options = [ "subvol=@home" "compress=zstd" ]; }; + "/persist" = { + device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; + fsType = "btrfs"; + options = [ "subvol=@persist" "compress=zstd" ]; + }; }; swapDevices = [ ]; From 192b1362596256a19ba38a3873eb29bfc3b8f756 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 23:05:15 +0100 Subject: [PATCH 0448/1125] Machines/Everest: mount root subvolume --- machines/Everest/hardware-configuration.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/machines/Everest/hardware-configuration.nix b/machines/Everest/hardware-configuration.nix index ba3f567..0f6afe4 100755 --- a/machines/Everest/hardware-configuration.nix +++ b/machines/Everest/hardware-configuration.nix @@ -29,6 +29,11 @@ fsType = "btrfs"; options = [ "compress=zstd" "subvol=@home" ]; }; + "/mnt/hdd" = { + device = "/dev/disk/by-label/Everest"; + fsType = "btrfs"; + options = [ "compress=zstd" "subvol=/" "ro" ]; + }; }; fileSystems."/boot/efi" = From 26cc28ba41ac34394968ea8f987113ae445baa66 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 23:07:38 +0100 Subject: [PATCH 0449/1125] Machins/Everest: mount persist subvolume --- machines/Everest/hardware-configuration.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/machines/Everest/hardware-configuration.nix b/machines/Everest/hardware-configuration.nix index 0f6afe4..40fc930 100755 --- a/machines/Everest/hardware-configuration.nix +++ b/machines/Everest/hardware-configuration.nix @@ -34,6 +34,11 @@ fsType = "btrfs"; options = [ "compress=zstd" "subvol=/" "ro" ]; }; + "/persist" = { + device = "/dev/disk/by-label/Everest"; + fsType = "btrfs"; + options = [ "compress=zstd" "subvol=@persist" ]; + }; }; fileSystems."/boot/efi" = From c23dda00c0f298332aa53857db8527c669026e92 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 23:14:13 +0100 Subject: [PATCH 0450/1125] Flake: update secrets --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 76a0889..77f772b 100644 --- a/flake.lock +++ b/flake.lock @@ -418,11 +418,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1708347322, - "narHash": "sha256-30rLLNMGvVz8xbklqRpA3uE6UDneAUGFz7dCmH9YbA8=", + "lastModified": 1708379923, + "narHash": "sha256-3V7lwL+GQIi3os9jDetzl5Y1+Rgs2ES5kwjHzG9HteU=", "ref": "refs/heads/main", - "rev": "409536f1d2b8ffe741fe47b8701ba28137f9de38", - "revCount": 3, + "rev": "90dd2143e21ba1442b054c47a09d5a15229cf5f7", + "revCount": 6, "type": "git", "url": "http://git.everest.sable-pancake.ts.net/Toast/nix-secrets" }, From 8f3eefe140d960013b1de97e575f71f4f4205be6 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 23:14:27 +0100 Subject: [PATCH 0451/1125] Common/syncthing: update Everest's id --- roles/common/services/syncthing.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index 9bcfb63..501b4e3 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -37,7 +37,7 @@ in }; "server" = { name = "Everest"; - id = "BVJBCAZ-WDIWBFR-CK3WB3N-TWH3UXX-EPZXVWE-BLQ3IDU-U7MHVVB-WO4BKAJ"; + id = "2GXFZJZ-CF56ER2-SISBGOF-VNXJIG5-GQC6ECA-NHCHAPX-677RSJT-RI5POAZ"; }; "surface" = { name = "Surface Go"; From 1ecb8c32dc61757f5ec17ebb0c1b9bae291bfb87 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 19 Feb 2024 23:48:01 +0100 Subject: [PATCH 0452/1125] Remove redundant secrets --- secrets/syncthing/cert | Bin 1133 -> 0 bytes secrets/syncthing/key | Bin 547 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 secrets/syncthing/cert delete mode 100644 secrets/syncthing/key diff --git a/secrets/syncthing/cert b/secrets/syncthing/cert deleted file mode 100644 index db1966e84947fb0e1d58b7698738efde18486f2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1133 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCR+%lFGSaa7QcC@4-$ zi^xu?3i0<1GH~R(l2?q^|EW?ZH1rd?L( zZ*H7lS<2<^Wo(%l66~Irnc`!b<5U@0?qTeg>l{#AUJ#J$T$pR@ljG+YR+(PzZWzL) ztE;OJR1oIpm>l4hlbxQO7nEn>=;-Q^nB^aqd-J_|+}RW}iJZi{I^=Y;{KV<(=2n%BwFPW;dQ*&lBm@ z=U6q*bF%oCJDq1`4#!$d{pKpYI4Vp29b2=>XSw624@y~EOR%#~(qO9D@F+%V_Os{l zl6!jpecBnqr=`{U>FPBxAA7N4Ue$iyFF`J9M;~~_CB4#KqL8Ym-SA|~(Ue193^sG| z75dNH>7jVG_OW^$&xGS$(&Zt=8v>@UGx@e);p|NFir>6!lh#yUU$M<)4%^l01IfW} zzke5$dfsOdQU2!XiRlRy&EYOhmXiB#M96fuB}GbIz4v}zUc!|-Gai}vysG}%^UUqo z^fIeNfn(8Tmu@+k@xIFYkWn5S`G5M8s2kd+4hD1uaeWuzTI*b*@%HuQl4jw+oNYlX z9tJF2vAl%4pkB-Pi?g0p_5UX)pYdOnnBaDzl~>}vZrsBL=AbW<|3Y>6AJsp6ZOl2Z z@ovY2XCguj1z)5l-734tp5z=ID7WAzx8CQb<=XZ>avaPy;bNLPPI>hUY?#d-z7jW> za#VHco*M420phzC9Qnkxvi;ul*=+~3Zl3kcss1AW@yPsoofmz-Z@+8KW<0`sGN#?m z?z2(z&zYr;9W!>S2|C=ZV7*>om^IDk>C-1#F*CU}mM;78P~nC}!h#ix*g~@S^}~W} zJ0G4~?QK$ZEX-$$S+?2L<=f2f4% znCiW?d9B&CGBR8C^Bp}Lw^(%2>X@5vmAo2vyM4TDz0;#0ap|1NoTZZ|=dQU}wjy@Y ziU8ioTKl{HlLVLlE9myBG+1&xx8{WO-;($1PqZah=3G3rsN_!T;_I%9f5t6;eQy2x zyXW7VZ9MQ^?1-g#?7!AOKCOz3#)~^Gz5Xt|uNjbPkz=W8(66bc#=>39=f6U6|H&sW zZh2^a(Cm75HSLkEzE^7TM<$k7o%I5X96vj&yx3AXJABsD%mE{*pamv?eDt(jf!YVn{ l`i1U^9WPzM{=B|vI>T>^U;3#L`NEH$#9U8bm-!`OF#uwk`*{EW diff --git a/secrets/syncthing/key b/secrets/syncthing/key deleted file mode 100644 index d1e1609c0e865cc1d1da5ec3b7a989ea015cb7e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 547 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCR+%lFGSaa0J6u&6RL z^htHh3aD_;_wg``3NKH}@F`4*OwWx>v<&cwsw~is^r}knDCP<*$nXwvP06oJ4e-ni zHjVN&D+xDAs;nr?33CcEFvtwf^zsh&&d)E@cLmwzZC|Zlm28`&n_iTfSe&X*Qf(Qg zrBX(~j8t5HhUgXH7tE;OJTITPY>!RXT>S9?H8Ie@r z=@OMx6qJ+Um!FjEnigeR?2*sqd}m_(eSg8AGS98wvmxDtpia z&)p^MNiRH7^dGNb{=xOa`fJF?$CFtP?prp;VPi7;>Niq{x~^^Ie{SIwt(Ku|``+uS zdhZ-ImzKI-&*<}g*L6!ZtlwT~DuHSPD__oPLt`CNu2vS_E^~Rbt!L+totS8 z*-vVw23PwkA63_iTs7yD^k%s%t;c-FnjE<7J#TDVGK;=LemQ|Ie}g zwMyR#kKb?Rcb!^!muG?GwnuAOFaOp2=e@3kyE@-7eC^4cItwrFtdr?eI$?9GbBbkB$cM~Z|K}z*UsD~2LKIJ Date: Tue, 20 Feb 2024 00:10:00 +0100 Subject: [PATCH 0453/1125] Remove secrets folder --- secrets/ddclient-passwd | Bin 404 -> 0 bytes secrets/secrets.nix | 10 ---------- 2 files changed, 10 deletions(-) delete mode 100644 secrets/ddclient-passwd delete mode 100755 secrets/secrets.nix diff --git a/secrets/ddclient-passwd b/secrets/ddclient-passwd deleted file mode 100644 index 90f0728d402fd083561164e35e4023deb60bc6a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 404 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCR+%lFGSaa70-&CfBZ zFe{8IsqhMMHA?jLDhy6^H4jR1i8M1#)h;To2*~kIaw{nb%;w6;F9-@TGSrSp3Mwsk zH1;gZOZJP(@Xj&HbSX4Vsxomjj`H*l%_yxX4g}ferje+dUX+?xoT{LtsAlZrQl$`F z;hCFSV{FWom{(=)R2F358R}IPRAm<7oReh|9uQt>5aL~8l9n6b>Je#a=@Fcsn{HSc z5#?@SkZ+i4>X@EanVarp6qcRK<>>2C;_nh}Xyj$89hsJ#U78c%WoRC3oL-gV5^k6t z5@2ExVP;|Ml2}=so#&AjR-RMkRhgJtnGqCW=H|$ytE;O}9ORspRZ?N$8krwv=2uY} z=pIq&YVKT=Q&8&Y9OUEb5$W!m<`dt+AZwQ@QvV)_VNm;4S*53SA(z?fOTi?ihi+CRM6abJKkfi_s diff --git a/secrets/secrets.nix b/secrets/secrets.nix deleted file mode 100755 index fbb968e..0000000 --- a/secrets/secrets.nix +++ /dev/null @@ -1,10 +0,0 @@ -let - everest = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBYENWORu3M32NIIip8gZO5VbCUBwsT2RgOU8ATsASpc root@Everest"; - bootsrtrap = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMKloSXSeF4dNXebd93uMuiFuXRHfxo/he4+O9SFTz1s bootstrap key"; -in -{ - "ddclient-passwd".publicKeys = [ everest ]; - "cock".publicKeys = [ everest ]; - "syncthing/key".publicKeys = [ everest ]; - "syncthing/cert".publicKeys = [ everest ]; -} From 38ad6796a1d7d238102de5bfc56c637232af4cd8 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 20 Feb 2024 00:11:10 +0100 Subject: [PATCH 0454/1125] Server/ddclient: update password --- roles/server/ddclient.nix | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/roles/server/ddclient.nix b/roles/server/ddclient.nix index e4520d9..5a88f7f 100755 --- a/roles/server/ddclient.nix +++ b/roles/server/ddclient.nix @@ -1,8 +1,12 @@ -{ config, ... }: +{ config, flakeSelf, ... }: + +let + hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName; +in { # Set up secrets - age.secrets = { ddclient-passwd.file = ../../secrets/ddclient-passwd; }; + age.secrets = { ddclient-passwd.file = hostSecrets + "/ddclient-password.age"; }; services.ddclient = { enable = true; @@ -13,4 +17,4 @@ passwordFile = config.age.secrets.ddclient-passwd.path; domains = [ "@" ]; }; -} \ No newline at end of file +} From d02fae40add7ca435ed9b1293d6ba122cfc0716c Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 20 Feb 2024 00:11:30 +0100 Subject: [PATCH 0455/1125] Flake: update secrets --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 77f772b..df673ba 100644 --- a/flake.lock +++ b/flake.lock @@ -418,11 +418,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1708379923, - "narHash": "sha256-3V7lwL+GQIi3os9jDetzl5Y1+Rgs2ES5kwjHzG9HteU=", + "lastModified": 1708383844, + "narHash": "sha256-cl5HngHhGW6qkvjv9ZSaiQuZKXfxlDfM4IDVPyMRBcY=", "ref": "refs/heads/main", - "rev": "90dd2143e21ba1442b054c47a09d5a15229cf5f7", - "revCount": 6, + "rev": "31ef63532cf9907e8580741f1c9428b4176874cf", + "revCount": 8, "type": "git", "url": "http://git.everest.sable-pancake.ts.net/Toast/nix-secrets" }, From fb8aa242c3b117bd64ab6faf711602b5bbfc61c8 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 20 Feb 2024 09:15:26 +0100 Subject: [PATCH 0456/1125] Machines: mount /persist in early boot --- machines/Archie/hardware-configuration.nix | 1 + machines/Everest/hardware-configuration.nix | 1 + machines/WinMax2/hardware-configuration.nix | 1 + 3 files changed, 3 insertions(+) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index 2e04763..00a0702 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -65,6 +65,7 @@ device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; fsType = "btrfs"; options = [ "subvol=@persist" "compress=zstd" ]; + neededForBoot = true; }; }; diff --git a/machines/Everest/hardware-configuration.nix b/machines/Everest/hardware-configuration.nix index 40fc930..d165feb 100755 --- a/machines/Everest/hardware-configuration.nix +++ b/machines/Everest/hardware-configuration.nix @@ -38,6 +38,7 @@ device = "/dev/disk/by-label/Everest"; fsType = "btrfs"; options = [ "compress=zstd" "subvol=@persist" ]; + neededForBoot = true; }; }; diff --git a/machines/WinMax2/hardware-configuration.nix b/machines/WinMax2/hardware-configuration.nix index 39126af..2f8b16b 100755 --- a/machines/WinMax2/hardware-configuration.nix +++ b/machines/WinMax2/hardware-configuration.nix @@ -48,6 +48,7 @@ in label = ssdLabel; fsType = "btrfs"; options = [ "subvol=@persist" ]; + neededForBoot = true; }; "btrfs_home" = { mountPoint = "/home"; From 2abeee6dbeba779def0a2498cab432dbc7849f5a Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 20 Feb 2024 15:09:12 +0100 Subject: [PATCH 0457/1125] Kde/plasma: disable window borders --- roles/kde/plasma.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 21488f1..25c00a6 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -135,6 +135,7 @@ in }; configFile = { "kwinrc" = { + "org\\.kde\\.kdecoration2"."BorderSize" = "None"; "Desktops" = { "Number" = 2; "Rows" = 1; From ae8471345d6cface2dff497391dcc0c601dd17ee Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 21 Feb 2024 00:16:14 +0100 Subject: [PATCH 0458/1125] Common/tailscale: disable logging --- roles/common/services/tailscale.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/common/services/tailscale.nix b/roles/common/services/tailscale.nix index aef79f6..176bded 100644 --- a/roles/common/services/tailscale.nix +++ b/roles/common/services/tailscale.nix @@ -5,4 +5,8 @@ enable = true; useRoutingFeatures = lib.mkDefault "client"; }; + + systemd.services.tailscaled.environment = { + TS_NO_LOGS_NO_SUPPORT = "true"; + }; } From 90d45024dbd8a46dfd5a66491d0db2ef4cf81a88 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 21 Feb 2024 13:43:15 +0100 Subject: [PATCH 0459/1125] Desktop: configure NetworkManager in a separate file --- roles/desktop/configuration.nix | 2 -- roles/desktop/services/default.nix | 1 + roles/desktop/services/networkmanager.nix | 7 +++++++ 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 roles/desktop/services/networkmanager.nix diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index 3a10fee..ab3242a 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -8,8 +8,6 @@ }; users.users.toast.extraGroups = [ "scanner" ]; - networking.networkmanager.enable = true; - services.xserver.enable = true; # Set up fonts diff --git a/roles/desktop/services/default.nix b/roles/desktop/services/default.nix index d2031da..c746c38 100644 --- a/roles/desktop/services/default.nix +++ b/roles/desktop/services/default.nix @@ -7,5 +7,6 @@ ./syncthing.nix ./pipewire.nix ./printing.nix + ./networkmanager.nix ]; } diff --git a/roles/desktop/services/networkmanager.nix b/roles/desktop/services/networkmanager.nix new file mode 100644 index 0000000..fd91b03 --- /dev/null +++ b/roles/desktop/services/networkmanager.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + networking.networkmanager = { + enable = true; + }; +} From d90a2676185a927f8cd851b46607487ec237441c Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 21 Feb 2024 13:55:42 +0100 Subject: [PATCH 0460/1125] Desktop/NetworkManager: don't manage tailscale's interface --- roles/desktop/services/networkmanager.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/roles/desktop/services/networkmanager.nix b/roles/desktop/services/networkmanager.nix index fd91b03..54d4b08 100644 --- a/roles/desktop/services/networkmanager.nix +++ b/roles/desktop/services/networkmanager.nix @@ -1,7 +1,14 @@ -{ ... }: +{ config, ... }: + +let + tailscaleName = config.services.tailscale.interfaceName; +in { networking.networkmanager = { enable = true; + unmanaged = [ + "interface-name:${tailscaleName}" + ]; }; } From cb748fedaa19240543864430ec5329af2eabae57 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 21 Feb 2024 14:09:35 +0100 Subject: [PATCH 0461/1125] Desktop/NetworkManager: enable wifi mac address randomisation --- roles/desktop/services/networkmanager.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/services/networkmanager.nix b/roles/desktop/services/networkmanager.nix index 54d4b08..7a64922 100644 --- a/roles/desktop/services/networkmanager.nix +++ b/roles/desktop/services/networkmanager.nix @@ -10,5 +10,6 @@ in unmanaged = [ "interface-name:${tailscaleName}" ]; + wifi.macAddress = "random"; }; } From 27d0d1de30c193f86246967d54e27bfcd0161aba Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 21 Feb 2024 00:28:01 +0100 Subject: [PATCH 0462/1125] Common/starship: change directory truncation settings --- roles/common/programs/starship.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index 0718478..3a29736 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -43,6 +43,8 @@ in }; directory = { disabled = false; + truncation_length = 6; + truncation_symbol = ".../"; }; palette = "catppuccin_${catppuccinFlavour}"; } From 7ca46b27d152bd38a80d39bb85e2cc50a0cc74f9 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 21 Feb 2024 00:35:47 +0100 Subject: [PATCH 0463/1125] Flake: remove plasma sdk from devshell --- flake.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/flake.nix b/flake.nix index 326a5f9..c38ecab 100644 --- a/flake.nix +++ b/flake.nix @@ -107,7 +107,6 @@ packages = with nixpkgs.legacyPackages.x86_64-linux; [ agenix.packages.x86_64-linux.default git - plasma5Packages.plasma-sdk nix-diff ]; shellHook ='' From e724778fcf55203cf4e7aa29c194ec8134189dcf Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 22 Feb 2024 10:03:12 +0100 Subject: [PATCH 0464/1125] Common/git: set delta theme to catppuccin-mocha --- roles/common/programs/git.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index ed5cc08..4ac4731 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -6,7 +6,12 @@ enable = true; userName = "Toast"; userEmail = "toast003@tutamail.com"; - delta.enable = true; + delta = { + enable = true; + options = { + syntax-theme = "catppuccin-mocha"; + }; + }; extraConfig = { init.defaultBranch = "main"; commit.verbose = "true"; From 1132547d9161465120c3ac75ef71ad52b4c7a0d5 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 22 Feb 2024 23:58:08 +0100 Subject: [PATCH 0465/1125] Common/git: use catppuccin mocha theme --- roles/common/programs/git.nix | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index 4ac4731..01f0108 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -1,5 +1,14 @@ { config, pkgs, ... }: +let + catppuccinDelta = pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "delta"; + rev = "main"; + hash = "sha256-0QQLkfLBVuB2re6tjtPNuOQZNK0MDBAIFgNGHZM8afs="; + }; +in + { home-manager.users.toast = { programs.git = { @@ -10,8 +19,10 @@ enable = true; options = { syntax-theme = "catppuccin-mocha"; + features = "catppuccin-mocha"; }; }; + includes = [{ path = "${catppuccinDelta}/themes/mocha.gitconfig"; }]; extraConfig = { init.defaultBranch = "main"; commit.verbose = "true"; From dddd601fd262b0a8a1708c83761fabb396ef391d Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 22 Feb 2024 23:58:37 +0100 Subject: [PATCH 0466/1125] Git/common: enable diff colorMoved --- roles/common/programs/git.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index 01f0108..17fdf47 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -25,6 +25,7 @@ in includes = [{ path = "${catppuccinDelta}/themes/mocha.gitconfig"; }]; extraConfig = { init.defaultBranch = "main"; + diff.colorMoved = "default"; commit.verbose = "true"; }; }; From 7c7f1ca3398a3c14f02f009a1a7f760af76279c6 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Feb 2024 09:54:03 +0100 Subject: [PATCH 0467/1125] School: add mongodb and mongosh --- roles/school/services/default.nix | 1 + roles/school/services/mongodb.nix | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 roles/school/services/mongodb.nix diff --git a/roles/school/services/default.nix b/roles/school/services/default.nix index 703919f..0fa68eb 100644 --- a/roles/school/services/default.nix +++ b/roles/school/services/default.nix @@ -5,5 +5,6 @@ ./syncthing.nix ./mysql.nix ./xampp.nix + ./mongodb.nix ]; } diff --git a/roles/school/services/mongodb.nix b/roles/school/services/mongodb.nix new file mode 100644 index 0000000..cb8cee1 --- /dev/null +++ b/roles/school/services/mongodb.nix @@ -0,0 +1,31 @@ +{ config, pkgs, lib, ... }: + +{ + services.mongodb = { + enable = true; + package = pkgs.mongodb-4_4; + user = "toast"; + }; + + # Don't autostart MySQL + systemd.services.mongodb.wantedBy = lib.mkForce []; + + # Allow regular users to start/stop mongodb + # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if ( + action.id == "org.freedesktop.systemd1.manage-units" && + action.lookup("unit") == "mongodb.service" && + subject.user == "${config.services.mongodb.user}" + ) + { + return polkit.Result.YES; + } + }) + ''; + + environment.systemPackages = with pkgs; [ + mongosh + ]; +} From 7f8155840c3a00f6d67879bcdc55061ccda57aa5 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Feb 2024 10:42:44 +0100 Subject: [PATCH 0468/1125] Flake: change name of devshell --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index c38ecab..825c5dd 100644 --- a/flake.nix +++ b/flake.nix @@ -101,7 +101,7 @@ in { devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { - name = "Environment for toast's nixos configurations"; + name = "toast-devshell"; # The agenix cli is not needed to activate a configuration, so instead of installing it # I'll just add it to de devShell, since that's the only real time I'm going to use it. packages = with nixpkgs.legacyPackages.x86_64-linux; [ From 2018954c98d3488ed0326e42ce6c1dd9491b0073 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Feb 2024 11:03:35 +0100 Subject: [PATCH 0469/1125] Common/bash: enable VTE integration --- roles/common/programs/bash.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/bash.nix b/roles/common/programs/bash.nix index c1684bf..a87dea5 100644 --- a/roles/common/programs/bash.nix +++ b/roles/common/programs/bash.nix @@ -2,6 +2,9 @@ { home-manager.users.toast = { config, ... }: { - programs.bash.enable = true; + programs.bash = { + enable = true; + enableVteIntegration = true; }; + }; } From c0529d52257c7eb1c1b2e68be892895ab44050d8 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Feb 2024 12:07:22 +0100 Subject: [PATCH 0470/1125] Common: add direnv --- roles/common/programs/default.nix | 1 + roles/common/programs/direnv.nix | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 roles/common/programs/direnv.nix diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index 8641b50..bc89f3a 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -14,6 +14,7 @@ ./bat.nix ./btop.nix ./helix.nix + ./direnv.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ diff --git a/roles/common/programs/direnv.nix b/roles/common/programs/direnv.nix new file mode 100644 index 0000000..af02580 --- /dev/null +++ b/roles/common/programs/direnv.nix @@ -0,0 +1,7 @@ +{ ... }: + +{ + programs.direnv = { + enable = true; + }; +} From 61c2b3dcbbc1ef5b3c594ef292a92a2ade6d43b0 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Feb 2024 12:08:19 +0100 Subject: [PATCH 0471/1125] Common/direnv: enable nix-direnv --- roles/common/programs/direnv.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/direnv.nix b/roles/common/programs/direnv.nix index af02580..c0ab11a 100644 --- a/roles/common/programs/direnv.nix +++ b/roles/common/programs/direnv.nix @@ -1,7 +1,10 @@ -{ ... }: +{ ... }: { programs.direnv = { enable = true; + nix-direnv = { + enable = true; + }; }; } From 06ec5105999ac1e37fa865c00aed4d1f44afe25f Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Feb 2024 12:10:47 +0100 Subject: [PATCH 0472/1125] Add .envrc --- .envrc | 1 + .gitignore | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 .envrc diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index 1df9283..e81be07 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ result-* # ---> Kate # Ignore kate's swap files *.kate-swp + + +# ---> Direnv +.direnv From 975b402ff7030bc17c8481e26c381e89e9c0714a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Feb 2024 12:32:04 +0100 Subject: [PATCH 0473/1125] Flake: add just to devshell --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 825c5dd..4e99901 100644 --- a/flake.nix +++ b/flake.nix @@ -108,6 +108,7 @@ agenix.packages.x86_64-linux.default git nix-diff + just ]; shellHook ='' export PS1="$PS1(toast-configs)> " From e2d5273ed8bab0b0cc432da8eb4e2faa87d599df Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Feb 2024 12:32:17 +0100 Subject: [PATCH 0474/1125] Add justfile --- .justfile | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .justfile diff --git a/.justfile b/.justfile new file mode 100644 index 0000000..9c7c34e --- /dev/null +++ b/.justfile @@ -0,0 +1,8 @@ +# Hide the default option from the recipes list +_default: print-recipes + +find-results: + find . -name '*result*' + +print-recipes: + @just --list From 8b2709ae33a2760caec4bca860b348a081e1a628 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Feb 2024 12:50:00 +0100 Subject: [PATCH 0475/1125] Justfile: add build-nixos recipe --- .justfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.justfile b/.justfile index 9c7c34e..a9173e3 100644 --- a/.justfile +++ b/.justfile @@ -6,3 +6,8 @@ find-results: print-recipes: @just --list + +alias build := build-nixos +# Build a NixOS configuration +build-nixos host=`hostname`: + nixos-rebuild build --flake .#{{host}} From a9aa0dff0011b7fcc68b7b45c2a0bc604b0a8458 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Feb 2024 12:59:07 +0100 Subject: [PATCH 0476/1125] Flake: add nix-diff to devshell --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 4e99901..283a6e4 100644 --- a/flake.nix +++ b/flake.nix @@ -109,6 +109,7 @@ git nix-diff just + nix-diff ]; shellHook ='' export PS1="$PS1(toast-configs)> " From f012eb6d2bef1cd3881668b8a7c5984011f0cad4 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Feb 2024 13:43:25 +0100 Subject: [PATCH 0477/1125] Justfile: add nix-diff recipe --- .justfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.justfile b/.justfile index a9173e3..64c0604 100644 --- a/.justfile +++ b/.justfile @@ -11,3 +11,7 @@ alias build := build-nixos # Build a NixOS configuration build-nixos host=`hostname`: nixos-rebuild build --flake .#{{host}} + +# nix-diff with some parameters piped to less +nix-diff left right: + nix-diff --color=always --skip-already-compared {{left}} {{right}} | less -F From f0b0ca75dabb551f29854618e5299e0853519686 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Feb 2024 21:06:28 +0100 Subject: [PATCH 0478/1125] Justfile: add update recipe --- .justfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.justfile b/.justfile index 64c0604..74ba154 100644 --- a/.justfile +++ b/.justfile @@ -7,6 +7,9 @@ find-results: print-recipes: @just --list +update: + nix flake update + alias build := build-nixos # Build a NixOS configuration build-nixos host=`hostname`: From 6d7408bc5b550a90672c3f2e3a062948483ae51a Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 28 Feb 2024 09:40:34 +0100 Subject: [PATCH 0479/1125] Kde/plasma: override some config files --- roles/kde/plasma.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 25c00a6..45f154f 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -94,6 +94,12 @@ in )]; programs.plasma = { enable = true; + overrideConfig = true; + # Delete config files that I fully configure here + overrideConfigFiles = [ + "plasmashellrc" + "plasma-org.kde.plasma.desktop-appletsrc" + ]; workspace = { clickItemTo = "select"; cursorTheme = "Breeze_Snow"; From 020c4bc4b8346bec7e2317617b69bd253593659f Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 28 Feb 2024 11:51:18 +0100 Subject: [PATCH 0480/1125] Justfile: add update-input recipe --- .justfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.justfile b/.justfile index 74ba154..4927b8a 100644 --- a/.justfile +++ b/.justfile @@ -10,6 +10,10 @@ print-recipes: update: nix flake update +# Update a single input +update-input input: + nix flake lock --update-input {{input}} + alias build := build-nixos # Build a NixOS configuration build-nixos host=`hostname`: From 6b53ede822ab937bc03f7299db8691358952e8d1 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 28 Feb 2024 13:04:56 +0100 Subject: [PATCH 0481/1125] Justfile: Add edit-secrets recipe --- .justfile | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.justfile b/.justfile index 4927b8a..252a267 100644 --- a/.justfile +++ b/.justfile @@ -1,6 +1,10 @@ # Hide the default option from the recipes list _default: print-recipes +# Escape codes for text formatting +bold := `tput bold` +normal := `tput sgr0` + find-results: find . -name '*result*' @@ -14,6 +18,15 @@ update: update-input input: nix flake lock --update-input {{input}} +@edit-secrets: + git clone http://git.everest.sable-pancake.ts.net/Toast/nix-secrets.git /tmp/secrets + sed -i 's\git+http://git.everest.sable-pancake.ts.net/Toast/nix-secrets\/tmp/secrets\g' flake.nix + just -q update-input secrets + echo "{{bold}}All done!" + echo "{{normal}}Remember to restore flake.nix" + echo "" + echo "" + alias build := build-nixos # Build a NixOS configuration build-nixos host=`hostname`: From e4f4b8db98fb6177b4c1948370a33cc212c3ff30 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 29 Feb 2024 09:28:30 +0100 Subject: [PATCH 0482/1125] Flake: add nixpkgs pr 288913 --- flake.nix | 2 +- nixpkgs-patches/288913.patch | 309 +++++++++++++++++++++++++++++++++++ 2 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 nixpkgs-patches/288913.patch diff --git a/flake.nix b/flake.nix index 283a6e4..9fc8ba7 100644 --- a/flake.nix +++ b/flake.nix @@ -84,7 +84,7 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - + ./nixpkgs-patches/288913.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/288913.patch b/nixpkgs-patches/288913.patch new file mode 100644 index 0000000..6cbc106 --- /dev/null +++ b/nixpkgs-patches/288913.patch @@ -0,0 +1,309 @@ +From e62dac66f96a8b02b612d58438e1d11324083794 Mon Sep 17 00:00:00 2001 +From: annalee <150648636+a-n-n-a-l-e-e@users.noreply.github.com> +Date: Wed, 14 Feb 2024 03:31:15 +0000 +Subject: [PATCH 1/3] duckdb,python311Packages.duckdb: 0.9.2 -> 0.10.0 + +--- + pkgs/development/libraries/duckdb/default.nix | 42 +++++++++++----- + .../libraries/duckdb/version.patch | 2 +- + .../python-modules/duckdb/default.nix | 48 ++++++++++++------- + .../python-modules/duckdb/setup.patch | 30 ------------ + 4 files changed, 62 insertions(+), 60 deletions(-) + delete mode 100644 pkgs/development/python-modules/duckdb/setup.patch + +diff --git a/pkgs/development/libraries/duckdb/default.nix b/pkgs/development/libraries/duckdb/default.nix +index 801ad7979aee91..e6645480d2b24a 100644 +--- a/pkgs/development/libraries/duckdb/default.nix ++++ b/pkgs/development/libraries/duckdb/default.nix +@@ -1,10 +1,13 @@ + { lib + , stdenv + , fetchFromGitHub ++, fetchpatch ++, substituteAll + , cmake + , ninja + , openssl + , openjdk11 ++, python3 + , unixODBC + , withJdbc ? false + , withOdbc ? false +@@ -15,22 +18,31 @@ let + in + stdenv.mkDerivation rec { + pname = "duckdb"; +- version = "0.9.2"; ++ version = "0.10.0"; + + src = fetchFromGitHub { + owner = pname; + repo = pname; +- rev = "v${version}"; +- hash = "sha256-QFK8mEMcqQwALFNvAdD8yWixwMYHSbeo6xqx86PvejU="; ++ rev = "refs/tags/v${version}"; ++ hash = "sha256-qGUq0iYTaLNHKqbXNLRmvqHMqunvIlP991IKb4qdSt4="; + }; + +- patches = [ ./version.patch ]; +- +- postPatch = '' +- substituteInPlace CMakeLists.txt --subst-var-by DUCKDB_VERSION "v${version}" +- ''; ++ patches = [ ++ # remove calls to git and set DUCKDB_VERSION to version ++ (substituteAll { ++ src = ./version.patch; ++ version = "v${version}"; ++ }) ++ # add missing file needed for httpfs compile ++ # remove on next update ++ (fetchpatch { ++ name = "missing-httpfs-file.patch"; ++ url = "https://github.com/duckdb/duckdb/commit/3d7aa3ed46ecf5f18122559e385b75f1f5e9aba8.patch"; ++ hash = "sha256-Q4IHCpMpxn86OquUZdEF7P0nHEPOcWS0TQijTkvBYbQ="; ++ }) ++ ]; + +- nativeBuildInputs = [ cmake ninja ]; ++ nativeBuildInputs = [ cmake ninja python3 ]; + buildInputs = [ openssl ] + ++ lib.optionals withJdbc [ openjdk11 ] + ++ lib.optionals withOdbc [ unixODBC ]; +@@ -54,7 +66,7 @@ stdenv.mkDerivation rec { + + installCheckPhase = + let +- excludes = map (pattern: "exclude:'${pattern}'") [ ++ excludes = map (pattern: "exclude:'${pattern}'") ([ + "[s3]" + "Test closing database during long running query" + "Test using a remote optimizer pass in case thats important to someone" +@@ -91,16 +103,22 @@ stdenv.mkDerivation rec { + "[!hide]" + # this test apparently never terminates + "test/sql/copy/csv/auto/test_csv_auto.test" ++ # test expects installed file timestamp to be > 2024 ++ "test/sql/table_function/read_text_and_blob.test" ++ # can re-enable next update (broken for 0.10.0) ++ "test/sql/secrets/create_secret_non_writable_persistent_dir.test" ++ # https://github.com/duckdb/duckdb/issues/10722 ++ "test/sql/types/nested/list/list_aggregate_dict.test" + ] ++ lib.optionals stdenv.isAarch64 [ + "test/sql/aggregate/aggregates/test_kurtosis.test" + "test/sql/aggregate/aggregates/test_skewness.test" + "test/sql/function/list/aggregates/skewness.test" +- ]; ++ ]); + in + '' + runHook preInstallCheck + +- $PWD/test/unittest ${lib.concatStringsSep " " excludes} ++ ./test/unittest ${toString excludes} + + runHook postInstallCheck + ''; +diff --git a/pkgs/development/libraries/duckdb/version.patch b/pkgs/development/libraries/duckdb/version.patch +index f40785b430797b..122ad4295d41e9 100644 +--- a/pkgs/development/libraries/duckdb/version.patch ++++ b/pkgs/development/libraries/duckdb/version.patch +@@ -52,7 +52,7 @@ index 2b49e11288..0a4a69b9a0 100644 + - set(DUCKDB_DEV_ITERATION 0) + - set(DUCKDB_VERSION "v${DUCKDB_MAJOR_VERSION}.${DUCKDB_MINOR_VERSION}.${DUCKDB_PATCH_VERSION}-dev${DUCKDB_DEV_ITERATION}") + -endif() +-+set(DUCKDB_VERSION "@DUCKDB_VERSION@") +++set(DUCKDB_VERSION "@version@") + + message(STATUS "git hash ${GIT_COMMIT_HASH}, version ${DUCKDB_VERSION}") + +diff --git a/pkgs/development/python-modules/duckdb/default.nix b/pkgs/development/python-modules/duckdb/default.nix +index a7cd1aa36dd45f..fd197f9305d63d 100644 +--- a/pkgs/development/python-modules/duckdb/default.nix ++++ b/pkgs/development/python-modules/duckdb/default.nix +@@ -1,4 +1,5 @@ + { lib ++, stdenv + , buildPythonPackage + , duckdb + , fsspec +@@ -13,25 +14,24 @@ + }: + + buildPythonPackage rec { +- inherit (duckdb) pname version src; +- format = "setuptools"; +- +- # 1. let nix control build cores +- # 2. default to extension autoload & autoinstall disabled +- # 3. unconstrain setuptools_scm version +- patches = (duckdb.patches or []) ++ [ ./setup.patch ]; ++ inherit (duckdb) patches pname src version; ++ pyproject = true; + + postPatch = (duckdb.postPatch or "") + '' + # we can't use sourceRoot otherwise patches don't apply, because the patches apply to the C++ library + cd tools/pythonpkg + +- substituteInPlace setup.py --subst-var NIX_BUILD_CORES +- +- # avoid dependency on mypy +- rm tests/stubs/test_stubs.py ++ # 1. let nix control build cores ++ # 2. default to extension autoload & autoinstall disabled ++ substituteInPlace setup.py \ ++ --replace-fail "ParallelCompile()" 'ParallelCompile("NIX_BUILD_CORES")' \ ++ --replace-fail "define_macros.extend([('DUCKDB_EXTENSION_AUTOLOAD_DEFAULT', '1'), ('DUCKDB_EXTENSION_AUTOINSTALL_DEFAULT', '1')])" "" + ''; + +- BUILD_HTTPFS = 1; ++ env = { ++ BUILD_HTTPFS = 1; ++ DUCKDB_BUILD_UNITY = 1; ++ }; + + nativeBuildInputs = [ + pybind11 +@@ -52,21 +52,35 @@ buildPythonPackage rec { + pytestCheckHook + ]; + ++ # test flags from .github/workflows/Python.yml ++ pytestFlagsArray = [ ++ "--verbose" ++ ] ++ lib.optionals stdenv.isDarwin [ ++ "tests/fast" ++ ]; ++ ++ disabledTestPaths = [ ++ # avoid dependency on mypy ++ "tests/stubs/test_stubs.py" ++ ]; ++ + disabledTests = [ + # tries to make http request + "test_install_non_existent_extension" +- # test is racy and interrupt can be delivered before or after target point ++ ++ # https://github.com/duckdb/duckdb/issues/10702 ++ # tests are racy and interrupt can be delivered before or after target point ++ # causing a later test to fail with a spurious KeyboardInterrupt + "test_connection_interrupt" ++ "test_query_interruption" + ]; + ++ # remove duckdb dir to prevent import confusion by pytest + preCheck = '' + export HOME="$(mktemp -d)" ++ rm -rf duckdb + ''; + +- setupPyBuildFlags = [ +- "--inplace" +- ]; +- + pythonImportsCheck = [ + "duckdb" + ]; +diff --git a/pkgs/development/python-modules/duckdb/setup.patch b/pkgs/development/python-modules/duckdb/setup.patch +deleted file mode 100644 +index 8c8f790a66a1d1..00000000000000 +--- a/pkgs/development/python-modules/duckdb/setup.patch ++++ /dev/null +@@ -1,30 +0,0 @@ +-diff --git a/tools/pythonpkg/setup.py b/tools/pythonpkg/setup.py +-index 30f1e1ccdd..6784169fcb 100644 +---- a/tools/pythonpkg/setup.py +-+++ b/tools/pythonpkg/setup.py +-@@ -96,7 +96,7 @@ def parallel_cpp_compile( +- return +- self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) +- +-- list(multiprocessing.pool.ThreadPool(multiprocessing.cpu_count()).imap(_single_compile, objects)) +-+ list(multiprocessing.pool.ThreadPool(@NIX_BUILD_CORES@).imap(_single_compile, objects)) +- return objects +- +- +-@@ -163,7 +163,6 @@ if 'BUILD_HTTPFS' in os.environ: +- for ext in extensions: +- toolchain_args.extend(['-DDUCKDB_EXTENSION_{}_LINKED'.format(ext.upper())]) +- +--toolchain_args.extend(['-DDUCKDB_EXTENSION_AUTOLOAD_DEFAULT=1', '-DDUCKDB_EXTENSION_AUTOINSTALL_DEFAULT=1']) +- +- +- class get_pybind_include(object): +-@@ -348,7 +347,7 @@ setup( +- packages=packages, +- include_package_data=True, +- python_requires='>=3.7.0', +-- setup_requires=setup_requires + ["setuptools_scm<7.0.0", 'pybind11>=2.6.0'], +-+ setup_requires=setup_requires + ["setuptools_scm", 'pybind11>=2.6.0'], +- use_scm_version=setuptools_scm_conf, +- tests_require=['google-cloud-storage', 'mypy', 'pytest'], +- classifiers=[ + +From e72db5d1718ab74321efde3b05039e202677afae Mon Sep 17 00:00:00 2001 +From: annalee <150648636+a-n-n-a-l-e-e@users.noreply.github.com> +Date: Wed, 14 Feb 2024 23:04:47 +0000 +Subject: [PATCH 2/3] python311Packages.duckdb-engine: 0.9.2 -> 0.11.1 + +--- + pkgs/development/python-modules/duckdb-engine/default.nix | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/pkgs/development/python-modules/duckdb-engine/default.nix b/pkgs/development/python-modules/duckdb-engine/default.nix +index ab82edb0893b7b..efdc1d10ace37c 100644 +--- a/pkgs/development/python-modules/duckdb-engine/default.nix ++++ b/pkgs/development/python-modules/duckdb-engine/default.nix +@@ -14,8 +14,8 @@ + + buildPythonPackage rec { + pname = "duckdb-engine"; +- version = "0.9.2"; +- format = "pyproject"; ++ version = "0.11.1"; ++ pyproject = true; + + disabled = pythonOlder "3.7"; + +@@ -23,7 +23,7 @@ buildPythonPackage rec { + repo = "duckdb_engine"; + owner = "Mause"; + rev = "refs/tags/v${version}"; +- hash = "sha256-T02nGF+YlughRQPinb0I3NC6xsarh4+qRhG8YfhTvhI="; ++ hash = "sha256-GMtQtcKEn2mdryl1KMYnYYeGpdbowP3o4dStwuL8AcU="; + }; + + patches = [ ./remote_data.patch ]; + +From fc7168d8d918b9a8fd11f0c27685b31d9a571f26 Mon Sep 17 00:00:00 2001 +From: annalee <150648636+a-n-n-a-l-e-e@users.noreply.github.com> +Date: Wed, 14 Feb 2024 23:14:49 +0000 +Subject: [PATCH 3/3] python311Packages.sqlglot: 20.9.0 -> 21.1.1 + +--- + pkgs/development/python-modules/sqlglot/default.nix | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/pkgs/development/python-modules/sqlglot/default.nix b/pkgs/development/python-modules/sqlglot/default.nix +index f02a32d0f64f86..7eb9ee70eca91b 100644 +--- a/pkgs/development/python-modules/sqlglot/default.nix ++++ b/pkgs/development/python-modules/sqlglot/default.nix +@@ -11,7 +11,7 @@ + + buildPythonPackage rec { + pname = "sqlglot"; +- version = "20.9.0"; ++ version = "21.1.1"; + pyproject = true; + + disabled = pythonOlder "3.8"; +@@ -20,7 +20,7 @@ buildPythonPackage rec { + repo = "sqlglot"; + owner = "tobymao"; + rev = "refs/tags/v${version}"; +- hash = "sha256-4czhmAJUDRj0x8dCmIXg5BQ1Uvie5vx+UtWdSSY5mnM="; ++ hash = "sha256-xMKDkhotVBkLzn+f9RMGCPfWTF4Rz9a193nSJv5z+iA="; + }; + + nativeBuildInputs = [ From da19e35f83f7c3f5bc827d2e82fb2b232a695b62 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 29 Feb 2024 09:46:14 +0100 Subject: [PATCH 0483/1125] Flake: update lock file --- flake.lock | 84 +++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/flake.lock b/flake.lock index df673ba..a7870fc 100644 --- a/flake.lock +++ b/flake.lock @@ -30,11 +30,11 @@ ] }, "locked": { - "lastModified": 1707530346, - "narHash": "sha256-LGvGeDwQtVQ4Pfa7JJKESAUg3n7Dy9d4kVCZf69kDRY=", + "lastModified": 1708962818, + "narHash": "sha256-oN4D8YBbwxz/YHyV1i+y+ujUKAmhIeSqGBWFIWyQnGw=", "owner": "catppuccin", "repo": "vscode", - "rev": "a5c28e9319556c696e184a2f2f49813288063ed6", + "rev": "49632377cb02b45bc47c929bbc2874de54dbbda2", "type": "github" }, "original": { @@ -123,11 +123,11 @@ ] }, "locked": { - "lastModified": 1708294481, - "narHash": "sha256-DZtxmeb4OR7iCaKUUuq05ADV2rX8WReZEF7Tq//W0+Y=", + "lastModified": 1708988456, + "narHash": "sha256-RCz7Xe64tN2zgWk+MVHkzg224znwqknJ1RnB7rVqUWw=", "owner": "nix-community", "repo": "home-manager", - "rev": "a54e05bc12d88ff2df941d0dc1183cb5235fa438", + "rev": "1d085ea4444d26aa52297758b333b449b2aa6fca", "type": "github" }, "original": { @@ -165,11 +165,11 @@ ] }, "locked": { - "lastModified": 1708148641, - "narHash": "sha256-UliMMpx84PPA+0mcyBj2yuKNawOX7L4u/wO8j9QGHVk=", + "lastModified": 1709142038, + "narHash": "sha256-ZjP808isgLwuiqxSU1CYFyafm5GF80aYw1CXJbnVsgs=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "f318a856ff3177fdea6044d6c77dd49992330a31", + "rev": "b83751a057acbb5f989193773841217ddc93d1f8", "type": "github" }, "original": { @@ -180,11 +180,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1708268179, - "narHash": "sha256-NNVuhf84AeDTxadfSGnFqPHR0ED+QyM2gmu+Wyz6PrY=", + "lastModified": 1708781964, + "narHash": "sha256-qbEZgB1mNuMADLmM64EtcRjDHXR3UFL4xVmoanv9wZU=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "a243cb0522f6240c194b873dde68e25370b06034", + "rev": "09d07c73b4d9771f527a168e0b1b6d8a1f39de28", "type": "github" }, "original": { @@ -202,11 +202,11 @@ ] }, "locked": { - "lastModified": 1708267826, - "narHash": "sha256-sv5L5iFnXa5wFxMXAEdW7Fcd6dFtAcvDETbKaS7JWZw=", + "lastModified": 1709045095, + "narHash": "sha256-6PeSdkt9Ey2k6yrRBpTFgS3RxTjyhRHZlR8hhy38xfQ=", "owner": "fufexan", "repo": "nix-gaming", - "rev": "f961c5727fd812c2f0db1425d09ad55b35652587", + "rev": "75625623631c294604b48035db5d95fe8ff08ef3", "type": "github" }, "original": { @@ -239,11 +239,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1706639736, - "narHash": "sha256-CaG4j9+UwBDfinxxvJMo6yOonSmSo0ZgnbD7aj2Put0=", + "lastModified": 1708968331, + "narHash": "sha256-VUXLaPusCBvwM3zhGbRIJVeYluh2uWuqtj4WirQ1L9Y=", "owner": "nix-community", "repo": "impermanence", - "rev": "cd13c2917eaa68e4c49fea0ff9cada45440d7045", + "rev": "a33ef102a02ce77d3e39c25197664b7a636f9c30", "type": "github" }, "original": { @@ -259,11 +259,11 @@ ] }, "locked": { - "lastModified": 1708225687, - "narHash": "sha256-NJBDfvknI26beOFmjO2coeJMTTUCCtw2Iu+rvJ1Zb9k=", + "lastModified": 1708830466, + "narHash": "sha256-nGKe3Y1/jkLR2eh1aRSVBtKadMBNv8kOnB52UXqRy6A=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "17352eb241a8d158c4ac523b19d8d2a6c8efe127", + "rev": "f070c7eeec3bde8c8c8baa9c02b6d3d5e114d73b", "type": "github" }, "original": { @@ -279,11 +279,11 @@ ] }, "locked": { - "lastModified": 1708225687, - "narHash": "sha256-NJBDfvknI26beOFmjO2coeJMTTUCCtw2Iu+rvJ1Zb9k=", + "lastModified": 1708830466, + "narHash": "sha256-nGKe3Y1/jkLR2eh1aRSVBtKadMBNv8kOnB52UXqRy6A=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "17352eb241a8d158c4ac523b19d8d2a6c8efe127", + "rev": "f070c7eeec3bde8c8c8baa9c02b6d3d5e114d73b", "type": "github" }, "original": { @@ -294,11 +294,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1708091350, - "narHash": "sha256-o28BJYi68qqvHipT7V2jkWxDiMS1LF9nxUsou+eFUPQ=", + "lastModified": 1709110790, + "narHash": "sha256-qUk0G9vWX90beOKB1EtLFdeImXAujNi5SP5zTyIEATc=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "106d3fec43bcea19cb2e061ca02531d54b542ce3", + "rev": "01467901ec51dd92774040f2b3dff4f21f4e1c45", "type": "github" }, "original": { @@ -328,11 +328,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1708161998, - "narHash": "sha256-6KnemmUorCvlcAvGziFosAVkrlWZGIc6UNT9GUYr0jQ=", + "lastModified": 1708979614, + "narHash": "sha256-FWLWmYojIg6TeqxSnHkKpHu5SGnFP5um1uUjH+wRV6g=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "84d981bae8b5e783b3b548de505b22880559515f", + "rev": "b7ee09cf5614b02d289cd86fcfa6f24d4e078c2a", "type": "github" }, "original": { @@ -343,11 +343,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1708118438, - "narHash": "sha256-kk9/0nuVgA220FcqH/D2xaN6uGyHp/zoxPNUmPCMmEE=", + "lastModified": 1708984720, + "narHash": "sha256-gJctErLbXx4QZBBbGp78PxtOOzsDaQ+yw1ylNQBuSUY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5863c27340ba4de8f83e7e3c023b9599c3cb3c80", + "rev": "13aff9b34cc32e59d35c62ac9356e4a41198a538", "type": "github" }, "original": { @@ -358,11 +358,11 @@ }, "nur": { "locked": { - "lastModified": 1708329376, - "narHash": "sha256-E5LJjNT6dMD2r6m93CdOccQmW3+YT7Pr2lHMMmr5pXs=", + "lastModified": 1709144707, + "narHash": "sha256-RvJU+wWBs05ET56LSK8gXIC6vXZuKl9HewCezS1Ta2Q=", "owner": "nix-community", "repo": "NUR", - "rev": "e17ac139d5903c021aff79b52d659bf90145cbb2", + "rev": "a6e5afae495cf1dd3dcd1d89c672885fc5eb2688", "type": "github" }, "original": { @@ -381,11 +381,11 @@ ] }, "locked": { - "lastModified": 1707590627, - "narHash": "sha256-LJ/lFEupLSi7xtUps234hhMk7ZdVLRoYeU7KiCFaoGw=", + "lastModified": 1708970090, + "narHash": "sha256-z/8pJRiLfYqGQvIJj3xGqobygNkVSSGN6115pAEDNU4=", "owner": "pjones", "repo": "plasma-manager", - "rev": "4e56cfeb95081a43cb49487d0996dc936d6201e5", + "rev": "74fa336c22adf822c6ef13b21bfff18fbef66e9c", "type": "github" }, "original": { @@ -470,11 +470,11 @@ ] }, "locked": { - "lastModified": 1708305444, - "narHash": "sha256-hCDR72rsHC3z2YvDywRgXLiPK8emn+jtl5fdoH30aeY=", + "lastModified": 1709082883, + "narHash": "sha256-KIt4XTDspnUze/QUU8mqiHea3opOv9hXl91N2L8bAB0=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "35e0cabb16c66709d6c91eda8067d740492172d5", + "rev": "de410fd3d5915c9ac8ba5a3bd1464ba623933656", "type": "github" }, "original": { From 84d4918224f37bf0902b1d13c881cb5cb47b3d79 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 29 Feb 2024 16:28:37 +0100 Subject: [PATCH 0484/1125] Server/forgejo: fix disable resignation setting --- roles/server/forgejo.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index fb4756e..3dd1ff3 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -5,8 +5,10 @@ services.forgejo = { enable = true; settings = { - server = { + service = { DISABLE_REGISTRATION = lib.mkDefault true; + }; + server = { ROOT_URL = "http://git.everest.sable-pancake.ts.net"; }; }; From 620cb43697f9778b83a4d765b5864a018a6196d8 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 1 Mar 2024 10:55:49 +0100 Subject: [PATCH 0485/1125] Server/forgejo: use built in ssh server --- roles/server/forgejo.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index 3dd1ff3..3d15f08 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -10,6 +10,8 @@ }; server = { ROOT_URL = "http://git.everest.sable-pancake.ts.net"; + START_SSH_SERVER = true; + SSH_PORT = 4222; }; }; }; From e7b6ebb54e801326ca2d374ceed11bda1b6556bd Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 1 Mar 2024 12:24:57 +0100 Subject: [PATCH 0486/1125] Server/traefik: change systemd restart interval --- roles/server/traefik.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/roles/server/traefik.nix b/roles/server/traefik.nix index 9550bb2..d611211 100644 --- a/roles/server/traefik.nix +++ b/roles/server/traefik.nix @@ -20,7 +20,14 @@ }; }; - systemd.units.tailscaled.requiredBy = [ "traefik.service" ]; + systemd = { + units.tailscaled.requiredBy = [ "traefik.service" ]; + # We have somewhat frequent power outages, and our ISP router takes + # ages to boot up. If I don't add a delay, traefik tries to bind to + # the tailscale interface before it's ready, making it crash too much + # in too little time + services.traefik.serviceConfig.RestartSec = 120; + }; networking.firewall.allowedTCPPorts = [ 80 8080 ]; } From 721adfb3d6f9db2145a8d393cd41a6c6fec78f01 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 2 Mar 2024 00:16:24 +0100 Subject: [PATCH 0487/1125] Common/nix: optimise store every week --- roles/common/programs/nix.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index fd36171..41e4cc2 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -6,6 +6,10 @@ auto-optimise-store = true; experimental-features = "nix-command flakes"; }; + optimise = { + automatic = true; + dates = [ "weekly" ]; + }; registry = { agenix = { from = { id = "agenix"; type = "indirect"; }; From c3f7752d0978bc5513ef2292aaf257d34a587d74 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 3 Mar 2024 00:15:37 +0100 Subject: [PATCH 0488/1125] Server/dns: add entry for winmax2 --- roles/server/dns.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/dns.nix b/roles/server/dns.nix index d50e8ea..600dfc1 100644 --- a/roles/server/dns.nix +++ b/roles/server/dns.nix @@ -33,6 +33,7 @@ "100.113.139.93" = [ "archie" ]; "100.85.48.85" = [ "steamdeck" ]; "100.96.92.13" = [ "surfecego" ]; + "100.106.73.20" = [ "winmax2" ]; }; # Dnsmasq conflicts with the resolved dns stub listener From e89a25dfc219f17edeb89daf046d9063d0123bb9 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 3 Mar 2024 13:59:41 +0100 Subject: [PATCH 0489/1125] Machines/WinMax2: update hhd --- machines/WinMax2/configuration.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index fe960af..026000b 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -52,9 +52,9 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="d owner = "hhd-dev"; repo = "hhd"; rev = "v${version}"; - hash = "sha256-3xJs+IjyTPC3R9YthmutP+yUlNlBN2K/aDqbKAJ44PA="; + hash = "sha256-Ujbou+f/EvHyqpp3FCNqIyZiCEFxSeQfflR3JmRxWFc="; }; - version = "1.3.6"; + version = "1.3.13"; }; enable = true; user = "root"; From cca30dea32da16d664675a92d532f59ef569f265 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 4 Mar 2024 13:18:40 +0100 Subject: [PATCH 0490/1125] Server/nfs: use tailscale domain instead of .local --- roles/server/nfs.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/nfs.nix b/roles/server/nfs.nix index 2b83b68..d91dd87 100755 --- a/roles/server/nfs.nix +++ b/roles/server/nfs.nix @@ -5,7 +5,7 @@ nfs.server = { enable = true; exports = '' -${config.services.transmission.settings.download-dir} *.local(ro,all_squash,anonuid=${toString config.users.users.transmission.uid},anongid=${toString config.users.groups.transmission.gid}) + ${config.services.transmission.settings.download-dir} *.sable-pancake.ts.net(ro,all_squash,anonuid=${toString config.users.users.transmission.uid},anongid=${toString config.users.groups.transmission.gid}) ''; # NFSv3 uses random ports, so you need to make them static to be able to pass though the firewall statdPort = 4000; From 63c544b37ffd7bfe0255e933f27c3a17599552f5 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 5 Mar 2024 10:41:11 +0100 Subject: [PATCH 0491/1125] Flake: update lock file --- flake.lock | 78 +++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/flake.lock b/flake.lock index a7870fc..8dcb417 100644 --- a/flake.lock +++ b/flake.lock @@ -64,11 +64,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1706830856, - "narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=", + "lastModified": 1709336216, + "narHash": "sha256-Dt/wOWeW6Sqm11Yh+2+t0dfEWxoMxGBvv3JpIocFl9E=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f", + "rev": "f7b3c975cf067e56e7cda6cb098ebe3fb4d74ca2", "type": "github" }, "original": { @@ -123,11 +123,11 @@ ] }, "locked": { - "lastModified": 1708988456, - "narHash": "sha256-RCz7Xe64tN2zgWk+MVHkzg224znwqknJ1RnB7rVqUWw=", + "lastModified": 1709578243, + "narHash": "sha256-hF96D+c2PBmAFhymMw3z8hou++lqKtZ7IzpFbYeL1/Y=", "owner": "nix-community", "repo": "home-manager", - "rev": "1d085ea4444d26aa52297758b333b449b2aa6fca", + "rev": "23ff9821bcaec12981e32049e8687f25f11e5ef3", "type": "github" }, "original": { @@ -165,11 +165,11 @@ ] }, "locked": { - "lastModified": 1709142038, - "narHash": "sha256-ZjP808isgLwuiqxSU1CYFyafm5GF80aYw1CXJbnVsgs=", + "lastModified": 1709295149, + "narHash": "sha256-+blV8vKyvh3gYnUFYTOu2yuWxEEBqwS7hfLm6qdpoe4=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "b83751a057acbb5f989193773841217ddc93d1f8", + "rev": "0ef51034dcc8b65b8be72eedd0d5db7d426ea054", "type": "github" }, "original": { @@ -202,11 +202,11 @@ ] }, "locked": { - "lastModified": 1709045095, - "narHash": "sha256-6PeSdkt9Ey2k6yrRBpTFgS3RxTjyhRHZlR8hhy38xfQ=", + "lastModified": 1709428394, + "narHash": "sha256-WIDKofwDWFLHtk14MdBiRiM8Lxn+OByHYtybjSU/18Q=", "owner": "fufexan", "repo": "nix-gaming", - "rev": "75625623631c294604b48035db5d95fe8ff08ef3", + "rev": "1f3fa3b398051c815e8500d4c4fe794ecfdee328", "type": "github" }, "original": { @@ -259,11 +259,11 @@ ] }, "locked": { - "lastModified": 1708830466, - "narHash": "sha256-nGKe3Y1/jkLR2eh1aRSVBtKadMBNv8kOnB52UXqRy6A=", + "lastModified": 1709435391, + "narHash": "sha256-s4itTkIVxn5lYeTzwkbAgl99atnjdZv1idI1118vdzA=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f070c7eeec3bde8c8c8baa9c02b6d3d5e114d73b", + "rev": "93554c04c2f1c02f4a383538e8848d511c3129e9", "type": "github" }, "original": { @@ -279,11 +279,11 @@ ] }, "locked": { - "lastModified": 1708830466, - "narHash": "sha256-nGKe3Y1/jkLR2eh1aRSVBtKadMBNv8kOnB52UXqRy6A=", + "lastModified": 1709435391, + "narHash": "sha256-s4itTkIVxn5lYeTzwkbAgl99atnjdZv1idI1118vdzA=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f070c7eeec3bde8c8c8baa9c02b6d3d5e114d73b", + "rev": "93554c04c2f1c02f4a383538e8848d511c3129e9", "type": "github" }, "original": { @@ -294,11 +294,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1709110790, - "narHash": "sha256-qUk0G9vWX90beOKB1EtLFdeImXAujNi5SP5zTyIEATc=", + "lastModified": 1709410583, + "narHash": "sha256-esOSUoQ7mblwcsSea0K17McZuwAIjoS6dq/4b83+lvw=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "01467901ec51dd92774040f2b3dff4f21f4e1c45", + "rev": "59e37017b9ed31dee303dbbd4531c594df95cfbc", "type": "github" }, "original": { @@ -311,11 +311,11 @@ "nixpkgs-lib": { "locked": { "dir": "lib", - "lastModified": 1706550542, - "narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=", + "lastModified": 1709237383, + "narHash": "sha256-cy6ArO4k5qTx+l5o+0mL9f5fa86tYUX3ozE1S+Txlds=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "97b17f32362e475016f942bbdfda4a4a72a8a652", + "rev": "1536926ef5621b09bba54035ae2bb6d806d72ac8", "type": "github" }, "original": { @@ -328,11 +328,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1708979614, - "narHash": "sha256-FWLWmYojIg6TeqxSnHkKpHu5SGnFP5um1uUjH+wRV6g=", + "lastModified": 1709309926, + "narHash": "sha256-VZFBtXGVD9LWTecGi6eXrE0hJ/mVB3zGUlHImUs2Qak=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b7ee09cf5614b02d289cd86fcfa6f24d4e078c2a", + "rev": "79baff8812a0d68e24a836df0a364c678089e2c7", "type": "github" }, "original": { @@ -343,11 +343,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1708984720, - "narHash": "sha256-gJctErLbXx4QZBBbGp78PxtOOzsDaQ+yw1ylNQBuSUY=", + "lastModified": 1709479366, + "narHash": "sha256-n6F0n8UV6lnTZbYPl1A9q1BS0p4hduAv1mGAP17CVd0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "13aff9b34cc32e59d35c62ac9356e4a41198a538", + "rev": "b8697e57f10292a6165a20f03d2f42920dfaf973", "type": "github" }, "original": { @@ -358,11 +358,11 @@ }, "nur": { "locked": { - "lastModified": 1709144707, - "narHash": "sha256-RvJU+wWBs05ET56LSK8gXIC6vXZuKl9HewCezS1Ta2Q=", + "lastModified": 1709620574, + "narHash": "sha256-gnnPCl6xxqtrZewW0H2oSi5BHJeYFaKRFXOWn9nMLSk=", "owner": "nix-community", "repo": "NUR", - "rev": "a6e5afae495cf1dd3dcd1d89c672885fc5eb2688", + "rev": "3394dde2beb574b52a518806900da3fee4ad6010", "type": "github" }, "original": { @@ -381,11 +381,11 @@ ] }, "locked": { - "lastModified": 1708970090, - "narHash": "sha256-z/8pJRiLfYqGQvIJj3xGqobygNkVSSGN6115pAEDNU4=", + "lastModified": 1709474138, + "narHash": "sha256-OWwiBEw6bdCOdOTDSfLbGmWDV2JhrglfV76qlD61eAQ=", "owner": "pjones", "repo": "plasma-manager", - "rev": "74fa336c22adf822c6ef13b21bfff18fbef66e9c", + "rev": "8de2af1270b2a48f9f97880ae611c626379c860a", "type": "github" }, "original": { @@ -470,11 +470,11 @@ ] }, "locked": { - "lastModified": 1709082883, - "narHash": "sha256-KIt4XTDspnUze/QUU8mqiHea3opOv9hXl91N2L8bAB0=", + "lastModified": 1709601361, + "narHash": "sha256-mLK/kksj7yjF/N5tBWkK+/v0cRGgvt00fQYwLV4kGDs=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "de410fd3d5915c9ac8ba5a3bd1464ba623933656", + "rev": "568cdfed83f7bccf9189ac34991845f3fd469ddb", "type": "github" }, "original": { From 7c731dd5838a186dfd4eca7042ee76e98aa12890 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 5 Mar 2024 10:41:28 +0100 Subject: [PATCH 0492/1125] Flake: remove unused nixpkgs patch --- flake.nix | 1 - nixpkgs-patches/288913.patch | 309 ----------------------------------- 2 files changed, 310 deletions(-) delete mode 100644 nixpkgs-patches/288913.patch diff --git a/flake.nix b/flake.nix index 9fc8ba7..dd0146e 100644 --- a/flake.nix +++ b/flake.nix @@ -84,7 +84,6 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/288913.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/288913.patch b/nixpkgs-patches/288913.patch deleted file mode 100644 index 6cbc106..0000000 --- a/nixpkgs-patches/288913.patch +++ /dev/null @@ -1,309 +0,0 @@ -From e62dac66f96a8b02b612d58438e1d11324083794 Mon Sep 17 00:00:00 2001 -From: annalee <150648636+a-n-n-a-l-e-e@users.noreply.github.com> -Date: Wed, 14 Feb 2024 03:31:15 +0000 -Subject: [PATCH 1/3] duckdb,python311Packages.duckdb: 0.9.2 -> 0.10.0 - ---- - pkgs/development/libraries/duckdb/default.nix | 42 +++++++++++----- - .../libraries/duckdb/version.patch | 2 +- - .../python-modules/duckdb/default.nix | 48 ++++++++++++------- - .../python-modules/duckdb/setup.patch | 30 ------------ - 4 files changed, 62 insertions(+), 60 deletions(-) - delete mode 100644 pkgs/development/python-modules/duckdb/setup.patch - -diff --git a/pkgs/development/libraries/duckdb/default.nix b/pkgs/development/libraries/duckdb/default.nix -index 801ad7979aee91..e6645480d2b24a 100644 ---- a/pkgs/development/libraries/duckdb/default.nix -+++ b/pkgs/development/libraries/duckdb/default.nix -@@ -1,10 +1,13 @@ - { lib - , stdenv - , fetchFromGitHub -+, fetchpatch -+, substituteAll - , cmake - , ninja - , openssl - , openjdk11 -+, python3 - , unixODBC - , withJdbc ? false - , withOdbc ? false -@@ -15,22 +18,31 @@ let - in - stdenv.mkDerivation rec { - pname = "duckdb"; -- version = "0.9.2"; -+ version = "0.10.0"; - - src = fetchFromGitHub { - owner = pname; - repo = pname; -- rev = "v${version}"; -- hash = "sha256-QFK8mEMcqQwALFNvAdD8yWixwMYHSbeo6xqx86PvejU="; -+ rev = "refs/tags/v${version}"; -+ hash = "sha256-qGUq0iYTaLNHKqbXNLRmvqHMqunvIlP991IKb4qdSt4="; - }; - -- patches = [ ./version.patch ]; -- -- postPatch = '' -- substituteInPlace CMakeLists.txt --subst-var-by DUCKDB_VERSION "v${version}" -- ''; -+ patches = [ -+ # remove calls to git and set DUCKDB_VERSION to version -+ (substituteAll { -+ src = ./version.patch; -+ version = "v${version}"; -+ }) -+ # add missing file needed for httpfs compile -+ # remove on next update -+ (fetchpatch { -+ name = "missing-httpfs-file.patch"; -+ url = "https://github.com/duckdb/duckdb/commit/3d7aa3ed46ecf5f18122559e385b75f1f5e9aba8.patch"; -+ hash = "sha256-Q4IHCpMpxn86OquUZdEF7P0nHEPOcWS0TQijTkvBYbQ="; -+ }) -+ ]; - -- nativeBuildInputs = [ cmake ninja ]; -+ nativeBuildInputs = [ cmake ninja python3 ]; - buildInputs = [ openssl ] - ++ lib.optionals withJdbc [ openjdk11 ] - ++ lib.optionals withOdbc [ unixODBC ]; -@@ -54,7 +66,7 @@ stdenv.mkDerivation rec { - - installCheckPhase = - let -- excludes = map (pattern: "exclude:'${pattern}'") [ -+ excludes = map (pattern: "exclude:'${pattern}'") ([ - "[s3]" - "Test closing database during long running query" - "Test using a remote optimizer pass in case thats important to someone" -@@ -91,16 +103,22 @@ stdenv.mkDerivation rec { - "[!hide]" - # this test apparently never terminates - "test/sql/copy/csv/auto/test_csv_auto.test" -+ # test expects installed file timestamp to be > 2024 -+ "test/sql/table_function/read_text_and_blob.test" -+ # can re-enable next update (broken for 0.10.0) -+ "test/sql/secrets/create_secret_non_writable_persistent_dir.test" -+ # https://github.com/duckdb/duckdb/issues/10722 -+ "test/sql/types/nested/list/list_aggregate_dict.test" - ] ++ lib.optionals stdenv.isAarch64 [ - "test/sql/aggregate/aggregates/test_kurtosis.test" - "test/sql/aggregate/aggregates/test_skewness.test" - "test/sql/function/list/aggregates/skewness.test" -- ]; -+ ]); - in - '' - runHook preInstallCheck - -- $PWD/test/unittest ${lib.concatStringsSep " " excludes} -+ ./test/unittest ${toString excludes} - - runHook postInstallCheck - ''; -diff --git a/pkgs/development/libraries/duckdb/version.patch b/pkgs/development/libraries/duckdb/version.patch -index f40785b430797b..122ad4295d41e9 100644 ---- a/pkgs/development/libraries/duckdb/version.patch -+++ b/pkgs/development/libraries/duckdb/version.patch -@@ -52,7 +52,7 @@ index 2b49e11288..0a4a69b9a0 100644 - - set(DUCKDB_DEV_ITERATION 0) - - set(DUCKDB_VERSION "v${DUCKDB_MAJOR_VERSION}.${DUCKDB_MINOR_VERSION}.${DUCKDB_PATCH_VERSION}-dev${DUCKDB_DEV_ITERATION}") - -endif() --+set(DUCKDB_VERSION "@DUCKDB_VERSION@") -++set(DUCKDB_VERSION "@version@") - - message(STATUS "git hash ${GIT_COMMIT_HASH}, version ${DUCKDB_VERSION}") - -diff --git a/pkgs/development/python-modules/duckdb/default.nix b/pkgs/development/python-modules/duckdb/default.nix -index a7cd1aa36dd45f..fd197f9305d63d 100644 ---- a/pkgs/development/python-modules/duckdb/default.nix -+++ b/pkgs/development/python-modules/duckdb/default.nix -@@ -1,4 +1,5 @@ - { lib -+, stdenv - , buildPythonPackage - , duckdb - , fsspec -@@ -13,25 +14,24 @@ - }: - - buildPythonPackage rec { -- inherit (duckdb) pname version src; -- format = "setuptools"; -- -- # 1. let nix control build cores -- # 2. default to extension autoload & autoinstall disabled -- # 3. unconstrain setuptools_scm version -- patches = (duckdb.patches or []) ++ [ ./setup.patch ]; -+ inherit (duckdb) patches pname src version; -+ pyproject = true; - - postPatch = (duckdb.postPatch or "") + '' - # we can't use sourceRoot otherwise patches don't apply, because the patches apply to the C++ library - cd tools/pythonpkg - -- substituteInPlace setup.py --subst-var NIX_BUILD_CORES -- -- # avoid dependency on mypy -- rm tests/stubs/test_stubs.py -+ # 1. let nix control build cores -+ # 2. default to extension autoload & autoinstall disabled -+ substituteInPlace setup.py \ -+ --replace-fail "ParallelCompile()" 'ParallelCompile("NIX_BUILD_CORES")' \ -+ --replace-fail "define_macros.extend([('DUCKDB_EXTENSION_AUTOLOAD_DEFAULT', '1'), ('DUCKDB_EXTENSION_AUTOINSTALL_DEFAULT', '1')])" "" - ''; - -- BUILD_HTTPFS = 1; -+ env = { -+ BUILD_HTTPFS = 1; -+ DUCKDB_BUILD_UNITY = 1; -+ }; - - nativeBuildInputs = [ - pybind11 -@@ -52,21 +52,35 @@ buildPythonPackage rec { - pytestCheckHook - ]; - -+ # test flags from .github/workflows/Python.yml -+ pytestFlagsArray = [ -+ "--verbose" -+ ] ++ lib.optionals stdenv.isDarwin [ -+ "tests/fast" -+ ]; -+ -+ disabledTestPaths = [ -+ # avoid dependency on mypy -+ "tests/stubs/test_stubs.py" -+ ]; -+ - disabledTests = [ - # tries to make http request - "test_install_non_existent_extension" -- # test is racy and interrupt can be delivered before or after target point -+ -+ # https://github.com/duckdb/duckdb/issues/10702 -+ # tests are racy and interrupt can be delivered before or after target point -+ # causing a later test to fail with a spurious KeyboardInterrupt - "test_connection_interrupt" -+ "test_query_interruption" - ]; - -+ # remove duckdb dir to prevent import confusion by pytest - preCheck = '' - export HOME="$(mktemp -d)" -+ rm -rf duckdb - ''; - -- setupPyBuildFlags = [ -- "--inplace" -- ]; -- - pythonImportsCheck = [ - "duckdb" - ]; -diff --git a/pkgs/development/python-modules/duckdb/setup.patch b/pkgs/development/python-modules/duckdb/setup.patch -deleted file mode 100644 -index 8c8f790a66a1d1..00000000000000 ---- a/pkgs/development/python-modules/duckdb/setup.patch -+++ /dev/null -@@ -1,30 +0,0 @@ --diff --git a/tools/pythonpkg/setup.py b/tools/pythonpkg/setup.py --index 30f1e1ccdd..6784169fcb 100644 ----- a/tools/pythonpkg/setup.py --+++ b/tools/pythonpkg/setup.py --@@ -96,7 +96,7 @@ def parallel_cpp_compile( -- return -- self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) -- --- list(multiprocessing.pool.ThreadPool(multiprocessing.cpu_count()).imap(_single_compile, objects)) --+ list(multiprocessing.pool.ThreadPool(@NIX_BUILD_CORES@).imap(_single_compile, objects)) -- return objects -- -- --@@ -163,7 +163,6 @@ if 'BUILD_HTTPFS' in os.environ: -- for ext in extensions: -- toolchain_args.extend(['-DDUCKDB_EXTENSION_{}_LINKED'.format(ext.upper())]) -- ---toolchain_args.extend(['-DDUCKDB_EXTENSION_AUTOLOAD_DEFAULT=1', '-DDUCKDB_EXTENSION_AUTOINSTALL_DEFAULT=1']) -- -- -- class get_pybind_include(object): --@@ -348,7 +347,7 @@ setup( -- packages=packages, -- include_package_data=True, -- python_requires='>=3.7.0', --- setup_requires=setup_requires + ["setuptools_scm<7.0.0", 'pybind11>=2.6.0'], --+ setup_requires=setup_requires + ["setuptools_scm", 'pybind11>=2.6.0'], -- use_scm_version=setuptools_scm_conf, -- tests_require=['google-cloud-storage', 'mypy', 'pytest'], -- classifiers=[ - -From e72db5d1718ab74321efde3b05039e202677afae Mon Sep 17 00:00:00 2001 -From: annalee <150648636+a-n-n-a-l-e-e@users.noreply.github.com> -Date: Wed, 14 Feb 2024 23:04:47 +0000 -Subject: [PATCH 2/3] python311Packages.duckdb-engine: 0.9.2 -> 0.11.1 - ---- - pkgs/development/python-modules/duckdb-engine/default.nix | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/pkgs/development/python-modules/duckdb-engine/default.nix b/pkgs/development/python-modules/duckdb-engine/default.nix -index ab82edb0893b7b..efdc1d10ace37c 100644 ---- a/pkgs/development/python-modules/duckdb-engine/default.nix -+++ b/pkgs/development/python-modules/duckdb-engine/default.nix -@@ -14,8 +14,8 @@ - - buildPythonPackage rec { - pname = "duckdb-engine"; -- version = "0.9.2"; -- format = "pyproject"; -+ version = "0.11.1"; -+ pyproject = true; - - disabled = pythonOlder "3.7"; - -@@ -23,7 +23,7 @@ buildPythonPackage rec { - repo = "duckdb_engine"; - owner = "Mause"; - rev = "refs/tags/v${version}"; -- hash = "sha256-T02nGF+YlughRQPinb0I3NC6xsarh4+qRhG8YfhTvhI="; -+ hash = "sha256-GMtQtcKEn2mdryl1KMYnYYeGpdbowP3o4dStwuL8AcU="; - }; - - patches = [ ./remote_data.patch ]; - -From fc7168d8d918b9a8fd11f0c27685b31d9a571f26 Mon Sep 17 00:00:00 2001 -From: annalee <150648636+a-n-n-a-l-e-e@users.noreply.github.com> -Date: Wed, 14 Feb 2024 23:14:49 +0000 -Subject: [PATCH 3/3] python311Packages.sqlglot: 20.9.0 -> 21.1.1 - ---- - pkgs/development/python-modules/sqlglot/default.nix | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/pkgs/development/python-modules/sqlglot/default.nix b/pkgs/development/python-modules/sqlglot/default.nix -index f02a32d0f64f86..7eb9ee70eca91b 100644 ---- a/pkgs/development/python-modules/sqlglot/default.nix -+++ b/pkgs/development/python-modules/sqlglot/default.nix -@@ -11,7 +11,7 @@ - - buildPythonPackage rec { - pname = "sqlglot"; -- version = "20.9.0"; -+ version = "21.1.1"; - pyproject = true; - - disabled = pythonOlder "3.8"; -@@ -20,7 +20,7 @@ buildPythonPackage rec { - repo = "sqlglot"; - owner = "tobymao"; - rev = "refs/tags/v${version}"; -- hash = "sha256-4czhmAJUDRj0x8dCmIXg5BQ1Uvie5vx+UtWdSSY5mnM="; -+ hash = "sha256-xMKDkhotVBkLzn+f9RMGCPfWTF4Rz9a193nSJv5z+iA="; - }; - - nativeBuildInputs = [ From 9bbe570dfb7687b4da7d4a623ba94f27e284c2a8 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 5 Mar 2024 11:17:01 +0100 Subject: [PATCH 0493/1125] School: add typescript settings to helix --- roles/school/programs/default.nix | 1 + roles/school/programs/helix.nix | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 roles/school/programs/helix.nix diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 6579783..91d4471 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -5,6 +5,7 @@ ./virtualbox.nix ./idea.nix ./vscode.nix + ./helix.nix ]; environment.systemPackages = with pkgs; [ diff --git a/roles/school/programs/helix.nix b/roles/school/programs/helix.nix new file mode 100644 index 0000000..f28b348 --- /dev/null +++ b/roles/school/programs/helix.nix @@ -0,0 +1,12 @@ + +{ pkgs, ... }: + +{ + home-manager.users.toast = { + programs.helix = { + extraPackages = with pkgs; [ + nodePackages.typescript-language-server + ]; + }; + }; +} From eaac86bb1f525c6b8dae8558296241c5effe69e1 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 5 Mar 2024 11:17:34 +0100 Subject: [PATCH 0494/1125] School/vscode: add angular extension --- roles/school/programs/vscode.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/school/programs/vscode.nix b/roles/school/programs/vscode.nix index c5329bf..fa55360 100644 --- a/roles/school/programs/vscode.nix +++ b/roles/school/programs/vscode.nix @@ -9,6 +9,7 @@ let inputs = flakeSelf.inputs; in open-vsx.tomoki1207.pdf open-vsx.ms-vscode.live-server open-vsx.ecmel.vscode-html-css + open-vsx.angular.ng-template ]; userSettings = { redhat.telemetry.enabled = false; From 1ccb1ded826ba6e7f306f9aa73d274e29019717a Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 12 Mar 2024 10:17:33 +0100 Subject: [PATCH 0495/1125] Desktop: configure git --- roles/desktop/programs/default.nix | 1 + roles/desktop/programs/git.nix | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 roles/desktop/programs/git.nix diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix index 2cbcac7..32eedf6 100755 --- a/roles/desktop/programs/default.nix +++ b/roles/desktop/programs/default.nix @@ -8,5 +8,6 @@ ./keepassxc.nix ./jamesdsp.nix ./vscode.nix + ./git.nix ]; } diff --git a/roles/desktop/programs/git.nix b/roles/desktop/programs/git.nix new file mode 100644 index 0000000..ed2ba14 --- /dev/null +++ b/roles/desktop/programs/git.nix @@ -0,0 +1,9 @@ +{ pkgs, lib, ... }: + +{ + home-manager.users.toast = { + programs.git = { + package = pkgs.gitFull; + }; + }; +} From 34a9c49b174915eb49ce28bea8629c24cdcde257 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 12 Mar 2024 10:18:03 +0100 Subject: [PATCH 0496/1125] Desktop/git: install and configure git-cola --- roles/desktop/programs/git.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/roles/desktop/programs/git.nix b/roles/desktop/programs/git.nix index ed2ba14..d630bdd 100644 --- a/roles/desktop/programs/git.nix +++ b/roles/desktop/programs/git.nix @@ -4,6 +4,13 @@ home-manager.users.toast = { programs.git = { package = pkgs.gitFull; + extraConfig = { + cola = { + icontheme = lib.mkDefault "dark"; + }; + }; }; + + home.packages = [ pkgs.git-cola ]; }; } From 8c2041893960399162f7aac682e292dbf2677706 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 12 Mar 2024 10:43:19 +0100 Subject: [PATCH 0497/1125] Kde: configure git-cola --- roles/kde/programs/default.nix | 1 + roles/kde/programs/git.nix | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 roles/kde/programs/git.nix diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index 7c22bb0..b39dcfc 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -7,6 +7,7 @@ ./skanpage.nix ./neochat.nix ./konsole.nix + ./git.nix ]; # Enable the kde partition manager diff --git a/roles/kde/programs/git.nix b/roles/kde/programs/git.nix new file mode 100644 index 0000000..9d1c045 --- /dev/null +++ b/roles/kde/programs/git.nix @@ -0,0 +1,13 @@ +{ pkgs, lib, ... }: + +{ + home-manager.users.toast = { + programs.git = { + extraConfig = { + cola = { + terminal = "konsole"; + }; + }; + }; + }; +} From fff0a55aed3d8cb5ae6b84c37d22e780aef858c0 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 13 Mar 2024 10:27:52 +0100 Subject: [PATCH 0498/1125] Server/forgejo: enable push to create --- roles/server/forgejo.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index 3d15f08..e467a4e 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -13,6 +13,10 @@ START_SSH_SERVER = true; SSH_PORT = 4222; }; + repository = { + ENABLE_PUSH_CREATE_USER = true; + DEFAULT_PUSH_CREATE_PRIVATE = true; + }; }; }; From de26a1adc40e190e408b6fbb827203bfba0798d9 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 13 Mar 2024 10:38:08 +0100 Subject: [PATCH 0499/1125] Server/forgejo: set default branch name to main --- roles/server/forgejo.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index e467a4e..7075395 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -16,6 +16,7 @@ repository = { ENABLE_PUSH_CREATE_USER = true; DEFAULT_PUSH_CREATE_PRIVATE = true; + DEFAULT_BRANCH = "main"; }; }; }; From ff7ed8e9401d3f8b6c38b965e69ec288b328920f Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 13 Mar 2024 09:24:21 +0100 Subject: [PATCH 0500/1125] Flake: get secrets using ssh --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index dd0146e..a68172a 100644 --- a/flake.nix +++ b/flake.nix @@ -3,7 +3,7 @@ inputs = { secrets = { - url = "git+http://git.everest.sable-pancake.ts.net/Toast/nix-secrets"; + url = "git+ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets"; flake = false; }; nixpkgs-raw.url = "nixpkgs/nixos-23.11"; From 81bb301ee2f2fb1c9253efc8f840bd19ee585e90 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 13 Mar 2024 11:01:22 +0100 Subject: [PATCH 0501/1125] School: add unity hub --- roles/school/programs/default.nix | 1 + roles/school/programs/unity.nix | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 roles/school/programs/unity.nix diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 91d4471..6bc4de6 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -6,6 +6,7 @@ ./idea.nix ./vscode.nix ./helix.nix + ./unity.nix ]; environment.systemPackages = with pkgs; [ diff --git a/roles/school/programs/unity.nix b/roles/school/programs/unity.nix new file mode 100644 index 0000000..0a5d1a3 --- /dev/null +++ b/roles/school/programs/unity.nix @@ -0,0 +1,9 @@ +{ pkgs, ... }: + +{ + home-manager.users.toast = { + home.packages = [( + pkgs.unityhub + )]; + }; +} From 8f84c123064e974a68852e136cfe6f18607b395b Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 13 Mar 2024 11:42:12 +0100 Subject: [PATCH 0502/1125] Desktop: configure ssh client --- roles/desktop/programs/default.nix | 1 + roles/desktop/programs/ssh.nix | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 roles/desktop/programs/ssh.nix diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix index 32eedf6..fe5bf8e 100755 --- a/roles/desktop/programs/default.nix +++ b/roles/desktop/programs/default.nix @@ -9,5 +9,6 @@ ./jamesdsp.nix ./vscode.nix ./git.nix + ./ssh.nix ]; } diff --git a/roles/desktop/programs/ssh.nix b/roles/desktop/programs/ssh.nix new file mode 100644 index 0000000..d82e171 --- /dev/null +++ b/roles/desktop/programs/ssh.nix @@ -0,0 +1,9 @@ +{ ... }: + +{ + home-manager.users.toast = { + programs.ssh = { + enable = true; + }; + }; +} From b9c51f922662b0583764f2ce37919ffb5c1b67a0 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 13 Mar 2024 11:42:34 +0100 Subject: [PATCH 0503/1125] Desktop/ssh: enable agent forwarding for everest --- roles/desktop/programs/ssh.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/roles/desktop/programs/ssh.nix b/roles/desktop/programs/ssh.nix index d82e171..b3f17f0 100644 --- a/roles/desktop/programs/ssh.nix +++ b/roles/desktop/programs/ssh.nix @@ -4,6 +4,13 @@ home-manager.users.toast = { programs.ssh = { enable = true; + matchBlocks = { + "everest" = { + host = "everest"; + hostname = "everest.sable-pancake.ts.net"; + forwardAgent = true; + }; + }; }; }; } From 2bf27fdf63d1f92b7181c86e8f699619ce980cac Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 13 Mar 2024 12:14:15 +0100 Subject: [PATCH 0504/1125] Flake: update lock file --- flake.lock | 84 ++++++++++++++++----------------- roles/gaming/programs/steam.nix | 3 +- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/flake.lock b/flake.lock index 8dcb417..438feb8 100644 --- a/flake.lock +++ b/flake.lock @@ -30,11 +30,11 @@ ] }, "locked": { - "lastModified": 1708962818, - "narHash": "sha256-oN4D8YBbwxz/YHyV1i+y+ujUKAmhIeSqGBWFIWyQnGw=", + "lastModified": 1710153923, + "narHash": "sha256-aCaHueh0QkFoAMnhfYwrG9LTx/fCCsicPzjgPMLjByc=", "owner": "catppuccin", "repo": "vscode", - "rev": "49632377cb02b45bc47c929bbc2874de54dbbda2", + "rev": "91851ec881a99541355ad4d665f775ee0e15dfcc", "type": "github" }, "original": { @@ -123,11 +123,11 @@ ] }, "locked": { - "lastModified": 1709578243, - "narHash": "sha256-hF96D+c2PBmAFhymMw3z8hou++lqKtZ7IzpFbYeL1/Y=", + "lastModified": 1710281778, + "narHash": "sha256-bvWr9vvBrAxb44kHM3H3cY/uQg+4pYP1BM/Nu3e/7V8=", "owner": "nix-community", "repo": "home-manager", - "rev": "23ff9821bcaec12981e32049e8687f25f11e5ef3", + "rev": "49a266d2ca59df8a03249550e73a54626181b65d", "type": "github" }, "original": { @@ -165,11 +165,11 @@ ] }, "locked": { - "lastModified": 1709295149, - "narHash": "sha256-+blV8vKyvh3gYnUFYTOu2yuWxEEBqwS7hfLm6qdpoe4=", + "lastModified": 1710025765, + "narHash": "sha256-CnNH3E1xB/xfif+KotTfvSGLLqOZ0OvUcUrDsFMwN6Q=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "0ef51034dcc8b65b8be72eedd0d5db7d426ea054", + "rev": "2e8c168044e86ee1344c18bde5caeffe205292f2", "type": "github" }, "original": { @@ -202,11 +202,11 @@ ] }, "locked": { - "lastModified": 1709428394, - "narHash": "sha256-WIDKofwDWFLHtk14MdBiRiM8Lxn+OByHYtybjSU/18Q=", + "lastModified": 1710310905, + "narHash": "sha256-D7f1CTKO8AZupjvymvrgCm3PY1x79IMrTqvppNyVjnY=", "owner": "fufexan", "repo": "nix-gaming", - "rev": "1f3fa3b398051c815e8500d4c4fe794ecfdee328", + "rev": "dcae53055d404ee74a8273276d4b8731718574a9", "type": "github" }, "original": { @@ -259,11 +259,11 @@ ] }, "locked": { - "lastModified": 1709435391, - "narHash": "sha256-s4itTkIVxn5lYeTzwkbAgl99atnjdZv1idI1118vdzA=", + "lastModified": 1710120787, + "narHash": "sha256-tlLuB73OCOKtU2j83bQzSYFyzjJo3rjpITZE5MoofG8=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "93554c04c2f1c02f4a383538e8848d511c3129e9", + "rev": "e76ff2df6bfd2abe06abd8e7b9f217df941c1b07", "type": "github" }, "original": { @@ -279,11 +279,11 @@ ] }, "locked": { - "lastModified": 1709435391, - "narHash": "sha256-s4itTkIVxn5lYeTzwkbAgl99atnjdZv1idI1118vdzA=", + "lastModified": 1710120787, + "narHash": "sha256-tlLuB73OCOKtU2j83bQzSYFyzjJo3rjpITZE5MoofG8=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "93554c04c2f1c02f4a383538e8848d511c3129e9", + "rev": "e76ff2df6bfd2abe06abd8e7b9f217df941c1b07", "type": "github" }, "original": { @@ -294,11 +294,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1709410583, - "narHash": "sha256-esOSUoQ7mblwcsSea0K17McZuwAIjoS6dq/4b83+lvw=", + "lastModified": 1710123225, + "narHash": "sha256-j3oWlxRZxB7cFsgEntpH3rosjFHRkAo/dhX9H3OfxtY=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "59e37017b9ed31dee303dbbd4531c594df95cfbc", + "rev": "ad2fd7b978d5e462048729a6c635c45d3d33c9ba", "type": "github" }, "original": { @@ -328,11 +328,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1709309926, - "narHash": "sha256-VZFBtXGVD9LWTecGi6eXrE0hJ/mVB3zGUlHImUs2Qak=", + "lastModified": 1710162809, + "narHash": "sha256-i2R2bcnQp+85de67yjgZVvJhd6rRnJbSYNpGmB6Leb8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "79baff8812a0d68e24a836df0a364c678089e2c7", + "rev": "ddcd7598b2184008c97e6c9c6a21c5f37590b8d2", "type": "github" }, "original": { @@ -343,11 +343,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1709479366, - "narHash": "sha256-n6F0n8UV6lnTZbYPl1A9q1BS0p4hduAv1mGAP17CVd0=", + "lastModified": 1710272261, + "narHash": "sha256-g0bDwXFmTE7uGDOs9HcJsfLFhH7fOsASbAuOzDC+fhQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b8697e57f10292a6165a20f03d2f42920dfaf973", + "rev": "0ad13a6833440b8e238947e47bea7f11071dc2b2", "type": "github" }, "original": { @@ -358,11 +358,11 @@ }, "nur": { "locked": { - "lastModified": 1709620574, - "narHash": "sha256-gnnPCl6xxqtrZewW0H2oSi5BHJeYFaKRFXOWn9nMLSk=", + "lastModified": 1710317965, + "narHash": "sha256-XsumRdRnryHdyzKMxXFhI7FXp0JCksDr19S96jG5fCI=", "owner": "nix-community", "repo": "NUR", - "rev": "3394dde2beb574b52a518806900da3fee4ad6010", + "rev": "e3ca1bd405762320da4c8808acc724b89dbe5edd", "type": "github" }, "original": { @@ -381,11 +381,11 @@ ] }, "locked": { - "lastModified": 1709474138, - "narHash": "sha256-OWwiBEw6bdCOdOTDSfLbGmWDV2JhrglfV76qlD61eAQ=", + "lastModified": 1709982472, + "narHash": "sha256-cMPHIV7yWbve+nwiQDhVt7BBkxrGTLzSTAslv7u6HZo=", "owner": "pjones", "repo": "plasma-manager", - "rev": "8de2af1270b2a48f9f97880ae611c626379c860a", + "rev": "26acf8f5880ae7d6e5de4ca953c8ad161b7903eb", "type": "github" }, "original": { @@ -418,17 +418,17 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1708383844, - "narHash": "sha256-cl5HngHhGW6qkvjv9ZSaiQuZKXfxlDfM4IDVPyMRBcY=", + "lastModified": 1710238597, + "narHash": "sha256-N0CVdpIyAkofXIHS9SUuDS27gS5HiYue+i4CBtk9IqE=", "ref": "refs/heads/main", - "rev": "31ef63532cf9907e8580741f1c9428b4176874cf", - "revCount": 8, + "rev": "e05ec0b3a77ea7c2aecf699894cdabac1b377bab", + "revCount": 9, "type": "git", - "url": "http://git.everest.sable-pancake.ts.net/Toast/nix-secrets" + "url": "ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets" }, "original": { "type": "git", - "url": "http://git.everest.sable-pancake.ts.net/Toast/nix-secrets" + "url": "ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets" } }, "systems": { @@ -470,11 +470,11 @@ ] }, "locked": { - "lastModified": 1709601361, - "narHash": "sha256-mLK/kksj7yjF/N5tBWkK+/v0cRGgvt00fQYwLV4kGDs=", + "lastModified": 1710292754, + "narHash": "sha256-xwX3HOa7cKEeN6jU/QpLyTDbzlYwuRAAhC1rzu04ndE=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "568cdfed83f7bccf9189ac34991845f3fd469ddb", + "rev": "46173e748ea7d66d285302c899e5016613be9199", "type": "github" }, "original": { diff --git a/roles/gaming/programs/steam.nix b/roles/gaming/programs/steam.nix index a0bb791..5499456 100644 --- a/roles/gaming/programs/steam.nix +++ b/roles/gaming/programs/steam.nix @@ -7,7 +7,8 @@ in { # Get the nix-gaming module imports = [ - nix-gaming.nixosModules.steamCompat + # This module is basically built in to nixpkgs now, so it;s not useful + # nix-gaming.nixosModules.steamCompat ]; programs.steam = { From 47e6ac288b6a8f4fefbe39c0b6175c58eb0aa6f7 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 20 Mar 2024 10:04:49 +0100 Subject: [PATCH 0505/1125] Flake: update lock file --- flake.lock | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/flake.lock b/flake.lock index 438feb8..27faf9e 100644 --- a/flake.lock +++ b/flake.lock @@ -30,11 +30,11 @@ ] }, "locked": { - "lastModified": 1710153923, - "narHash": "sha256-aCaHueh0QkFoAMnhfYwrG9LTx/fCCsicPzjgPMLjByc=", + "lastModified": 1710544781, + "narHash": "sha256-nkxihb3D85k1nZV1CzlB3seMKtTEeKb688sblIGp/Bs=", "owner": "catppuccin", "repo": "vscode", - "rev": "91851ec881a99541355ad4d665f775ee0e15dfcc", + "rev": "d7b96ccac36fd29929bd97bc9357413cc4e0240c", "type": "github" }, "original": { @@ -123,11 +123,11 @@ ] }, "locked": { - "lastModified": 1710281778, - "narHash": "sha256-bvWr9vvBrAxb44kHM3H3cY/uQg+4pYP1BM/Nu3e/7V8=", + "lastModified": 1710820906, + "narHash": "sha256-2bNMraoRB4pdw/HtxgYTFeMhEekBZeQ53/a8xkqpbZc=", "owner": "nix-community", "repo": "home-manager", - "rev": "49a266d2ca59df8a03249550e73a54626181b65d", + "rev": "022464438a85450abb23d93b91aa82e0addd71fb", "type": "github" }, "original": { @@ -165,11 +165,11 @@ ] }, "locked": { - "lastModified": 1710025765, - "narHash": "sha256-CnNH3E1xB/xfif+KotTfvSGLLqOZ0OvUcUrDsFMwN6Q=", + "lastModified": 1710915975, + "narHash": "sha256-yOc0AD6ba7mbialNciZGzuSQLMo4CopoZGEfcUugA4I=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "2e8c168044e86ee1344c18bde5caeffe205292f2", + "rev": "179d73fbe14c5bdb835d10bcc1c783466112bfa6", "type": "github" }, "original": { @@ -202,11 +202,11 @@ ] }, "locked": { - "lastModified": 1710310905, - "narHash": "sha256-D7f1CTKO8AZupjvymvrgCm3PY1x79IMrTqvppNyVjnY=", + "lastModified": 1710810847, + "narHash": "sha256-l1DacjuZny7i7YRbxIsa6DhXWoKJZEnM3Em8gt6Fsfk=", "owner": "fufexan", "repo": "nix-gaming", - "rev": "dcae53055d404ee74a8273276d4b8731718574a9", + "rev": "03d036f41beaa8c31b2b2261918d248f5c4d45c8", "type": "github" }, "original": { @@ -259,11 +259,11 @@ ] }, "locked": { - "lastModified": 1710120787, - "narHash": "sha256-tlLuB73OCOKtU2j83bQzSYFyzjJo3rjpITZE5MoofG8=", + "lastModified": 1710644923, + "narHash": "sha256-0fjbN5GYYDKPyPay0l8gYoH+tFfNqPPwP5sxxBreeA4=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "e76ff2df6bfd2abe06abd8e7b9f217df941c1b07", + "rev": "e25efda85e39fcdc845e371971ac4384989c4295", "type": "github" }, "original": { @@ -279,11 +279,11 @@ ] }, "locked": { - "lastModified": 1710120787, - "narHash": "sha256-tlLuB73OCOKtU2j83bQzSYFyzjJo3rjpITZE5MoofG8=", + "lastModified": 1710644923, + "narHash": "sha256-0fjbN5GYYDKPyPay0l8gYoH+tFfNqPPwP5sxxBreeA4=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "e76ff2df6bfd2abe06abd8e7b9f217df941c1b07", + "rev": "e25efda85e39fcdc845e371971ac4384989c4295", "type": "github" }, "original": { @@ -294,11 +294,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1710123225, - "narHash": "sha256-j3oWlxRZxB7cFsgEntpH3rosjFHRkAo/dhX9H3OfxtY=", + "lastModified": 1710783728, + "narHash": "sha256-eIsfu3c9JUBgm3cURSKTXLEI9Dlk1azo+MWKZVqrmkc=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "ad2fd7b978d5e462048729a6c635c45d3d33c9ba", + "rev": "1e679b9a9970780cd5d4dfe755a74a8f96d33388", "type": "github" }, "original": { @@ -328,11 +328,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1710162809, - "narHash": "sha256-i2R2bcnQp+85de67yjgZVvJhd6rRnJbSYNpGmB6Leb8=", + "lastModified": 1710838473, + "narHash": "sha256-RLvwdQSENKOaLdKhNie8XqHmTXzNm00/M/THj6zplQo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ddcd7598b2184008c97e6c9c6a21c5f37590b8d2", + "rev": "fa9f817df522ac294016af3d40ccff82f5fd3a63", "type": "github" }, "original": { @@ -343,11 +343,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1710272261, - "narHash": "sha256-g0bDwXFmTE7uGDOs9HcJsfLFhH7fOsASbAuOzDC+fhQ=", + "lastModified": 1710806803, + "narHash": "sha256-qrxvLS888pNJFwJdK+hf1wpRCSQcqA6W5+Ox202NDa0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0ad13a6833440b8e238947e47bea7f11071dc2b2", + "rev": "b06025f1533a1e07b6db3e75151caa155d1c7eb3", "type": "github" }, "original": { @@ -358,11 +358,11 @@ }, "nur": { "locked": { - "lastModified": 1710317965, - "narHash": "sha256-XsumRdRnryHdyzKMxXFhI7FXp0JCksDr19S96jG5fCI=", + "lastModified": 1710919093, + "narHash": "sha256-0A7NnR+kfsn9VSTkbZpkx5JAl7psNU5QKpEZk8wU/uU=", "owner": "nix-community", "repo": "NUR", - "rev": "e3ca1bd405762320da4c8808acc724b89dbe5edd", + "rev": "14ecc0dbbc7f572a29fb177168c991379d5e44b9", "type": "github" }, "original": { @@ -470,11 +470,11 @@ ] }, "locked": { - "lastModified": 1710292754, - "narHash": "sha256-xwX3HOa7cKEeN6jU/QpLyTDbzlYwuRAAhC1rzu04ndE=", + "lastModified": 1710897544, + "narHash": "sha256-3mPv91syU+Vqu4TPoOJR6dKBAjfOHZL44jPXdHZ0Les=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "46173e748ea7d66d285302c899e5016613be9199", + "rev": "f2f5adbda31543a80667500769f20c6369038897", "type": "github" }, "original": { From 26f91e4e19013d037857cc7c9eddfa152a7586c3 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 20 Mar 2024 10:05:14 +0100 Subject: [PATCH 0506/1125] Gaming/steam: use proton-ge from nixpkgs --- roles/gaming/programs/steam.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/gaming/programs/steam.nix b/roles/gaming/programs/steam.nix index 5499456..a2f48f6 100644 --- a/roles/gaming/programs/steam.nix +++ b/roles/gaming/programs/steam.nix @@ -1,4 +1,4 @@ -{ config, flakeSelf, ... }: + { config, flakeSelf, pkgs, ... }: let nix-gaming = flakeSelf.inputs.nix-gaming; @@ -16,8 +16,8 @@ in # Doubt that I'll use it, but I'll enable it anyways remotePlay.openFirewall = true; - extraCompatPackages = with nix-gaming.packages.x86_64-linux; [ - proton-ge + extraCompatPackages = with pkgs; [ + proton-ge-bin ]; }; From 5a1fd5175c63f60d953160367d59962e7db80de3 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 20 Mar 2024 10:07:28 +0100 Subject: [PATCH 0507/1125] Flake: remove nix-gaming --- flake.lock | 58 --------------------------------- flake.nix | 5 --- roles/gaming/programs/steam.nix | 18 +--------- 3 files changed, 1 insertion(+), 80 deletions(-) diff --git a/flake.lock b/flake.lock index 27faf9e..cc3d7ac 100644 --- a/flake.lock +++ b/flake.lock @@ -59,24 +59,6 @@ "type": "github" } }, - "flake-parts": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib" - }, - "locked": { - "lastModified": 1709336216, - "narHash": "sha256-Dt/wOWeW6Sqm11Yh+2+t0dfEWxoMxGBvv3JpIocFl9E=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "f7b3c975cf067e56e7cda6cb098ebe3fb4d74ca2", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, "flake-utils": { "inputs": { "systems": "systems_2" @@ -194,27 +176,6 @@ "type": "github" } }, - "nix-gaming": { - "inputs": { - "flake-parts": "flake-parts", - "nixpkgs": [ - "nixpkgs-unstable-raw" - ] - }, - "locked": { - "lastModified": 1710810847, - "narHash": "sha256-l1DacjuZny7i7YRbxIsa6DhXWoKJZEnM3Em8gt6Fsfk=", - "owner": "fufexan", - "repo": "nix-gaming", - "rev": "03d036f41beaa8c31b2b2261918d248f5c4d45c8", - "type": "github" - }, - "original": { - "owner": "fufexan", - "repo": "nix-gaming", - "type": "github" - } - }, "nix-github-actions": { "inputs": { "nixpkgs": [ @@ -308,24 +269,6 @@ "type": "github" } }, - "nixpkgs-lib": { - "locked": { - "dir": "lib", - "lastModified": 1709237383, - "narHash": "sha256-cy6ArO4k5qTx+l5o+0mL9f5fa86tYUX3ozE1S+Txlds=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "1536926ef5621b09bba54035ae2bb6d806d72ac8", - "type": "github" - }, - "original": { - "dir": "lib", - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, "nixpkgs-raw": { "locked": { "lastModified": 1710838473, @@ -402,7 +345,6 @@ "home-manager-unstable": "home-manager-unstable", "jovian": "jovian", "nix-flatpak": "nix-flatpak", - "nix-gaming": "nix-gaming", "nix-impermanence": "nix-impermanence", "nix-index-db": "nix-index-db", "nix-index-db-unstable": "nix-index-db-unstable", diff --git a/flake.nix b/flake.nix index a68172a..8dfa996 100644 --- a/flake.nix +++ b/flake.nix @@ -69,11 +69,6 @@ nix-flatpak.url = "github:gmodena/nix-flatpak/main"; nur.url = "github:nix-community/NUR"; - - nix-gaming = { - url = "github:fufexan/nix-gaming"; - inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; - }; }; outputs = { ... } @inputs: with inputs; diff --git a/roles/gaming/programs/steam.nix b/roles/gaming/programs/steam.nix index a2f48f6..321633c 100644 --- a/roles/gaming/programs/steam.nix +++ b/roles/gaming/programs/steam.nix @@ -1,16 +1,6 @@ - { config, flakeSelf, pkgs, ... }: - -let - nix-gaming = flakeSelf.inputs.nix-gaming; -in + { config, pkgs, ... }: { - # Get the nix-gaming module - imports = [ - # This module is basically built in to nixpkgs now, so it;s not useful - # nix-gaming.nixosModules.steamCompat - ]; - programs.steam = { enable = true; # Doubt that I'll use it, but I'll enable it anyways @@ -21,12 +11,6 @@ in ]; }; - # Use nix-gaming's cachix - nix.settings = { - substituters = ["https://nix-gaming.cachix.org"]; - trusted-public-keys = ["nix-gaming.cachix.org-1:nbjlureqMbRAxR1gJ/f3hxemL9svXaZF/Ees8vCUUs4="]; - }; - # Some linux native games (rise of the tomb raider) use alsa for sound services.pipewire.alsa.enable = if config.services.pipewire.pulse.enable == true then true else false; From 7474faefe526346ba49a6106b5898ea63d317d62 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 20 Mar 2024 11:00:05 +0100 Subject: [PATCH 0508/1125] Common/bat: fix theme name The name of the file changed in a nixpkgs update --- roles/common/programs/bat.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/common/programs/bat.nix b/roles/common/programs/bat.nix index 2a8224d..83ca905 100644 --- a/roles/common/programs/bat.nix +++ b/roles/common/programs/bat.nix @@ -10,7 +10,7 @@ themes = { catppuccin-mocha = { src = pkgs.catppuccin; - file = "bat/Catppuccin-mocha.tmTheme"; + file = "bat/Catppuccin Mocha.tmTheme"; }; }; }; From e88fb8a16e0eeb94dd27b10a76cba6347ae4235b Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 20 Mar 2024 11:16:22 +0100 Subject: [PATCH 0509/1125] Common/bat: use old theme name on nixos 23.11 --- roles/common/programs/bat.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/bat.nix b/roles/common/programs/bat.nix index 83ca905..43a53d1 100644 --- a/roles/common/programs/bat.nix +++ b/roles/common/programs/bat.nix @@ -1,5 +1,8 @@ { config, pkgs, ... }: +let + themeName = if config.system.nixos.release == "23.11" then "Catppuccin-mocha" else "Catppuccin Mocha"; +in { home-manager = { users.toast.programs.bat = { @@ -10,7 +13,7 @@ themes = { catppuccin-mocha = { src = pkgs.catppuccin; - file = "bat/Catppuccin Mocha.tmTheme"; + file = "bat/${themeName}.tmTheme"; }; }; }; From 9351f85534ffc2e81b895943a5d0aa57454bfd4e Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 20 Mar 2024 11:45:17 +0100 Subject: [PATCH 0510/1125] Flake: add alejandra to devshell --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 8dfa996..096bd6a 100644 --- a/flake.nix +++ b/flake.nix @@ -103,7 +103,7 @@ git nix-diff just - nix-diff + alejandra ]; shellHook ='' export PS1="$PS1(toast-configs)> " From 82bbd7ce873247aaaa02fd12a7566519d1d868f2 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 20 Mar 2024 12:44:55 +0100 Subject: [PATCH 0511/1125] Editors: format using alejandra --- .helix/languages.toml | 3 +++ .vscode/settings.json | 12 +++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 .helix/languages.toml diff --git a/.helix/languages.toml b/.helix/languages.toml new file mode 100644 index 0000000..3c8a111 --- /dev/null +++ b/.helix/languages.toml @@ -0,0 +1,3 @@ +[[language]] +name = "nix" +formatter = { command = "alejandra" } diff --git a/.vscode/settings.json b/.vscode/settings.json index fdf6a9a..4b907f6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,15 @@ { "editor.detectIndentation": true, "editor.insertSpaces": true, - "editor.defaultFormatter": "jnoortheen.nix-ide" + "editor.defaultFormatter": "jnoortheen.nix-ide", + "nix.formatterPath": "alejandra", + "nix.serverSettings": { + "nil": { + "formatting": { + "command": [ + "alejandra" + ] + } + } + } } From 7888103b1e33a775fc08fdd60aa7975b82341693 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 20 Mar 2024 12:54:25 +0100 Subject: [PATCH 0512/1125] Format everything with alejandra --- flake.nix | 384 +++++++++--------- machines/Archie/configuration.nix | 120 +++--- machines/Archie/default.nix | 12 +- machines/Archie/hardware-configuration.nix | 128 +++--- machines/Everest/configuration.nix | 120 +++--- machines/Everest/default.nix | 12 +- machines/Everest/hardware-configuration.nix | 104 ++--- machines/SteamDeck/configuration.nix | 164 ++++---- machines/SteamDeck/default.nix | 12 +- machines/SteamDeck/hardware-configuration.nix | 124 +++--- machines/SurfaceGo/configuration.nix | 142 +++---- machines/SurfaceGo/default.nix | 12 +- machines/SurfaceGo/hardware-configuration.nix | 76 ++-- machines/WinMax2/configuration.nix | 256 ++++++------ machines/WinMax2/default.nix | 12 +- machines/WinMax2/hardware-configuration.nix | 129 +++--- pkgs/anything-sync-daemon/default.nix | 91 +++-- roles/common/configuration.nix | 238 +++++------ roles/common/default.nix | 14 +- roles/common/programs/bash.nix | 16 +- roles/common/programs/bat.nix | 42 +- roles/common/programs/btop.nix | 6 +- roles/common/programs/comma.nix | 14 +- roles/common/programs/command-not-found.nix | 8 +- roles/common/programs/default.nix | 62 +-- roles/common/programs/direnv.nix | 4 +- roles/common/programs/git.nix | 63 ++- roles/common/programs/helix.nix | 6 +- roles/common/programs/htop.nix | 26 +- roles/common/programs/micro.nix | 35 +- roles/common/programs/nix-index.nix | 28 +- roles/common/programs/nix.nix | 55 +-- roles/common/programs/starship.nix | 101 +++-- roles/common/services/avahi.nix | 40 +- roles/common/services/default.nix | 14 +- roles/common/services/syncthing.nix | 114 +++--- roles/common/services/tailscale.nix | 20 +- roles/desktop/configuration.nix | 30 +- roles/desktop/default.nix | 14 +- roles/desktop/programs/default.nix | 24 +- roles/desktop/programs/discord.nix | 80 ++-- roles/desktop/programs/firefox.nix | 112 ++--- roles/desktop/programs/git.nix | 8 +- roles/desktop/programs/jamesdsp.nix | 8 +- roles/desktop/programs/keepassxc.nix | 128 +++--- roles/desktop/programs/micro.nix | 44 +- roles/desktop/programs/ssh.nix | 4 +- roles/desktop/programs/vscode.nix | 81 ++-- roles/desktop/services/default.nix | 20 +- roles/desktop/services/flatpak.nix | 35 +- roles/desktop/services/networkmanager.nix | 8 +- roles/desktop/services/pipewire.nix | 16 +- roles/desktop/services/printing.nix | 14 +- roles/desktop/services/ssh-agent.nix | 40 +- roles/desktop/services/syncthing.nix | 46 +-- roles/gaming/default.nix | 12 +- roles/gaming/programs/default.nix | 26 +- roles/gaming/programs/mangohud.nix | 27 +- roles/gaming/programs/retroarch.nix | 102 ++--- roles/gaming/programs/rpcs3.nix | 38 +- roles/gaming/programs/steam.nix | 37 +- roles/gaming/services/default.nix | 10 +- roles/gaming/services/syncthing.nix | 36 +- roles/kde/default.nix | 14 +- roles/kde/plasma.nix | 318 ++++++++------- roles/kde/programs/default.nix | 24 +- roles/kde/programs/firefox.nix | 62 +-- roles/kde/programs/git.nix | 6 +- roles/kde/programs/kate.nix | 16 +- roles/kde/programs/konsole.nix | 24 +- roles/kde/programs/neochat.nix | 8 +- roles/kde/programs/skanpage.nix | 17 +- roles/kde/sddm.nix | 106 ++--- roles/school/default.nix | 12 +- roles/school/programs/default.nix | 28 +- roles/school/programs/helix.nix | 5 +- roles/school/programs/idea.nix | 60 +-- roles/school/programs/unity.nix | 12 +- roles/school/programs/virtualbox.nix | 28 +- roles/school/programs/vscode.nix | 38 +- roles/school/services/default.nix | 16 +- roles/school/services/mongodb.nix | 55 +-- roles/school/services/mysql.nix | 59 +-- roles/school/services/syncthing.nix | 20 +- roles/school/services/xampp.nix | 70 ++-- roles/server/avahi.nix | 20 +- roles/server/beep.nix | 32 +- roles/server/ddclient.nix | 34 +- roles/server/default.nix | 36 +- roles/server/dns.nix | 24 +- roles/server/endlessh.nix | 18 +- roles/server/forgejo.nix | 10 +- roles/server/minecraft.nix | 217 +++++----- roles/server/nfs.nix | 66 +-- roles/server/samba.nix | 70 ++-- roles/server/ssh.nix | 20 +- roles/server/syncthing.nix | 106 +++-- roles/server/tailscale.nix | 12 +- roles/server/traefik.nix | 56 ++- roles/server/transmission.nix | 60 ++- 100 files changed, 2827 insertions(+), 2756 deletions(-) diff --git a/flake.nix b/flake.nix index 096bd6a..81171bf 100644 --- a/flake.nix +++ b/flake.nix @@ -1,205 +1,219 @@ { - description = "Configuration for Everest"; + description = "Configuration for Everest"; - inputs = { - secrets = { - url = "git+ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets"; - flake = false; - }; - nixpkgs-raw.url = "nixpkgs/nixos-23.11"; - nixpkgs-unstable-raw.url = "nixpkgs/nixos-unstable"; + inputs = { + secrets = { + url = "git+ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets"; + flake = false; + }; + nixpkgs-raw.url = "nixpkgs/nixos-23.11"; + nixpkgs-unstable-raw.url = "nixpkgs/nixos-unstable"; - agenix = { - url = "github:ryantm/agenix"; - inputs = { - nixpkgs.follows = "nixpkgs-raw"; - darwin.follows = ""; # Not using this on MacOS, so this doesn't pull it's dependencies - }; - }; + agenix = { + url = "github:ryantm/agenix"; + inputs = { + nixpkgs.follows = "nixpkgs-raw"; + darwin.follows = ""; # Not using this on MacOS, so this doesn't pull it's dependencies + }; + }; - home-manager = { - url = "github:nix-community/home-manager/release-23.11"; - inputs.nixpkgs.follows = "nixpkgs-raw"; - }; + home-manager = { + url = "github:nix-community/home-manager/release-23.11"; + inputs.nixpkgs.follows = "nixpkgs-raw"; + }; - home-manager-unstable = { - url = "github:nix-community/home-manager/"; - inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; - }; + home-manager-unstable = { + url = "github:nix-community/home-manager/"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; + }; - nixos-hardware.url = "github:NixOS/nixos-hardware/master"; + nixos-hardware.url = "github:NixOS/nixos-hardware/master"; - jovian = { - url = "github:Jovian-Experiments/Jovian-NixOS"; - inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; - }; - - nix-impermanence.url = "github:nix-community/impermanence"; + jovian = { + url = "github:Jovian-Experiments/Jovian-NixOS"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; + }; - /* - These are the same input, just following different nixpkgs versions - This avoids some wierdness when using one that follows unstable on a stable nixpkgs - */ - nix-index-db = { - url = "github:Mic92/nix-index-database"; - inputs.nixpkgs.follows = "nixpkgs-raw"; - }; + nix-impermanence.url = "github:nix-community/impermanence"; - nix-index-db-unstable = { - url = "github:Mic92/nix-index-database"; - inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; - }; + /* + These are the same input, just following different nixpkgs versions + This avoids some wierdness when using one that follows unstable on a stable nixpkgs + */ + nix-index-db = { + url = "github:Mic92/nix-index-database"; + inputs.nixpkgs.follows = "nixpkgs-raw"; + }; - plasma-manager = { - url = "github:pjones/plasma-manager"; - inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; - inputs.home-manager.follows = "home-manager-unstable"; - }; + nix-index-db-unstable = { + url = "github:Mic92/nix-index-database"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; + }; - catppuccin-vsc = { - url = "github:catppuccin/vscode"; - inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; - }; + plasma-manager = { + url = "github:pjones/plasma-manager"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; + inputs.home-manager.follows = "home-manager-unstable"; + }; - vscode-extensions = { - url = "github:nix-community/nix-vscode-extensions"; - inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; + catppuccin-vsc = { + url = "github:catppuccin/vscode"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; + }; - }; - nix-flatpak.url = "github:gmodena/nix-flatpak/main"; + vscode-extensions = { + url = "github:nix-community/nix-vscode-extensions"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; + }; + nix-flatpak.url = "github:gmodena/nix-flatpak/main"; - nur.url = "github:nix-community/NUR"; - }; + nur.url = "github:nix-community/NUR"; + }; - outputs = { ... } @inputs: with inputs; - # Patch nixpkgs - # https://ertt.ca/nix/patch-nixpkgs/ - let - nixpkgs-unstable-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { - name = "patched-nixpkgs-unstable"; - src = nixpkgs-unstable-raw; - patches = [ - ]; - }; - nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { - name = "patched-nixpkgs"; - src = nixpkgs-raw; - patches = [ - ./nixpkgs-patches/0001-catppuccin-add-grub-theme.patch - ./nixpkgs-patches/0002-catppuccin-add-starship-theme.patch - ]; - }; - # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 - nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs { self = inputs.self; }; - nixpkgs = (import "${nixpkgs-patched}/flake.nix").outputs { self = inputs.self; }; - in - { - devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { - name = "toast-devshell"; - # The agenix cli is not needed to activate a configuration, so instead of installing it - # I'll just add it to de devShell, since that's the only real time I'm going to use it. - packages = with nixpkgs.legacyPackages.x86_64-linux; [ - agenix.packages.x86_64-linux.default - git - nix-diff - just - alejandra - ]; - shellHook ='' - export PS1="$PS1(toast-configs)> " - ''; - }; - packages = { - x86_64-linux = with import nixpkgs-unstable-raw { system = "x86_64-linux"; }; { - anything-sync-daemon = callPackage ./pkgs/anything-sync-daemon {}; - discord-krisp-fixer = callPackage ./pkgs/discord-krisp-fixer {}; - }; - }; - nixosConfigurations = { - Archie = nixpkgs-unstable.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-unstable-raw; flakeSelf = self; }; - /* - I used to set up nixpkgs in the flake, but doing that made - defining overlays in modules impossible (or at least I could - not figure out how) - Also has nice side effect of making it easier to add new systems :3 - */ - modules = [ - agenix.nixosModules.default - home-manager-unstable.nixosModule - nix-index-db-unstable.nixosModules.nix-index - ./roles/common - ./roles/desktop - ./roles/kde - ./roles/gaming - ./roles/school - ./machines/Archie - ]; - }; + outputs = {...} @ inputs: + with inputs; + # Patch nixpkgs + # https://ertt.ca/nix/patch-nixpkgs/ + let + nixpkgs-unstable-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { + name = "patched-nixpkgs-unstable"; + src = nixpkgs-unstable-raw; + patches = [ + ]; + }; + nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { + name = "patched-nixpkgs"; + src = nixpkgs-raw; + patches = [ + ./nixpkgs-patches/0001-catppuccin-add-grub-theme.patch + ./nixpkgs-patches/0002-catppuccin-add-starship-theme.patch + ]; + }; + # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 + nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs {self = inputs.self;}; + nixpkgs = (import "${nixpkgs-patched}/flake.nix").outputs {self = inputs.self;}; + in { + devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { + name = "toast-devshell"; + # The agenix cli is not needed to activate a configuration, so instead of installing it + # I'll just add it to de devShell, since that's the only real time I'm going to use it. + packages = with nixpkgs.legacyPackages.x86_64-linux; [ + agenix.packages.x86_64-linux.default + git + nix-diff + just + alejandra + ]; + shellHook = '' + export PS1="$PS1(toast-configs)> " + ''; + }; + packages = { + x86_64-linux = with import nixpkgs-unstable-raw {system = "x86_64-linux";}; { + anything-sync-daemon = callPackage ./pkgs/anything-sync-daemon {}; + discord-krisp-fixer = callPackage ./pkgs/discord-krisp-fixer {}; + }; + }; + nixosConfigurations = { + Archie = nixpkgs-unstable.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { + systemPkgs = inputs.nixpkgs-unstable-raw; + flakeSelf = self; + }; + /* + I used to set up nixpkgs in the flake, but doing that made + defining overlays in modules impossible (or at least I could + not figure out how) + Also has nice side effect of making it easier to add new systems :3 + */ + modules = [ + agenix.nixosModules.default + home-manager-unstable.nixosModule + nix-index-db-unstable.nixosModules.nix-index + ./roles/common + ./roles/desktop + ./roles/kde + ./roles/gaming + ./roles/school + ./machines/Archie + ]; + }; - SurfaceGo = nixpkgs-unstable.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-unstable-raw; flakeSelf = self; }; - modules = [ - agenix.nixosModules.default - home-manager-unstable.nixosModule - nixos-hardware.nixosModules.microsoft-surface-go - nix-index-db-unstable.nixosModules.nix-index - ./roles/common - ./roles/desktop - ./roles/kde - ./machines/SurfaceGo - ]; - }; + SurfaceGo = nixpkgs-unstable.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { + systemPkgs = inputs.nixpkgs-unstable-raw; + flakeSelf = self; + }; + modules = [ + agenix.nixosModules.default + home-manager-unstable.nixosModule + nixos-hardware.nixosModules.microsoft-surface-go + nix-index-db-unstable.nixosModules.nix-index + ./roles/common + ./roles/desktop + ./roles/kde + ./machines/SurfaceGo + ]; + }; - SteamDeck = nixpkgs-unstable.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-unstable-raw; flakeSelf = self; }; - modules = [ - agenix.nixosModules.default - jovian.nixosModules.default - home-manager-unstable.nixosModule - nix-index-db-unstable.nixosModules.nix-index - ./roles/common - ./roles/desktop - ./roles/kde - ./roles/gaming - ./roles/school - ./machines/SteamDeck - ]; - }; + SteamDeck = nixpkgs-unstable.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { + systemPkgs = inputs.nixpkgs-unstable-raw; + flakeSelf = self; + }; + modules = [ + agenix.nixosModules.default + jovian.nixosModules.default + home-manager-unstable.nixosModule + nix-index-db-unstable.nixosModules.nix-index + ./roles/common + ./roles/desktop + ./roles/kde + ./roles/gaming + ./roles/school + ./machines/SteamDeck + ]; + }; - WinMax2 = nixpkgs-unstable.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-unstable-raw; flakeSelf = self; }; - modules = [ - agenix.nixosModules.default - jovian.nixosModules.default - home-manager-unstable.nixosModule - nix-index-db-unstable.nixosModules.nix-index - nixos-hardware.nixosModules.gpd-win-max-2-2023 - ./roles/common - ./roles/desktop - ./roles/kde - ./roles/gaming - ./roles/school - ./machines/WinMax2 - ]; - }; + WinMax2 = nixpkgs-unstable.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { + systemPkgs = inputs.nixpkgs-unstable-raw; + flakeSelf = self; + }; + modules = [ + agenix.nixosModules.default + jovian.nixosModules.default + home-manager-unstable.nixosModule + nix-index-db-unstable.nixosModules.nix-index + nixos-hardware.nixosModules.gpd-win-max-2-2023 + ./roles/common + ./roles/desktop + ./roles/kde + ./roles/gaming + ./roles/school + ./machines/WinMax2 + ]; + }; - Everest = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { systemPkgs = inputs.nixpkgs-raw; flakeSelf = self; }; - modules = [ - agenix.nixosModules.default - home-manager.nixosModule - nix-index-db.nixosModules.nix-index - ./roles/common - ./roles/server - ./machines/Everest - ]; - }; - }; - }; + Everest = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { + systemPkgs = inputs.nixpkgs-raw; + flakeSelf = self; + }; + modules = [ + agenix.nixosModules.default + home-manager.nixosModule + nix-index-db.nixosModules.nix-index + ./roles/common + ./roles/server + ./machines/Everest + ]; + }; + }; + }; } diff --git a/machines/Archie/configuration.nix b/machines/Archie/configuration.nix index 9c1ae34..e35d1fe 100644 --- a/machines/Archie/configuration.nix +++ b/machines/Archie/configuration.nix @@ -1,81 +1,79 @@ # Edit this configuration file to define what should be installed on # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running `nixos-help`). - -{ config, pkgs, ... }: - { - # Use grub boot loader - boot.loader = { - systemd-boot.enable = false; - grub = { - enable = true; - device = "nodev"; - efiSupport = true; - useOSProber = true; - }; - efi.efiSysMountPoint = "/boot/efi"; - }; - boot.loader.efi.canTouchEfiVariables = true; + config, + pkgs, + ... +}: { + # Use grub boot loader + boot.loader = { + systemd-boot.enable = false; + grub = { + enable = true; + device = "nodev"; + efiSupport = true; + useOSProber = true; + }; + efi.efiSysMountPoint = "/boot/efi"; + }; + boot.loader.efi.canTouchEfiVariables = true; - boot.kernelPackages = pkgs.linuxKernel.packages.linux_xanmod_latest; + boot.kernelPackages = pkgs.linuxKernel.packages.linux_xanmod_latest; - networking.hostName = "Archie"; # Define your hostname. + networking.hostName = "Archie"; # Define your hostname. - # Allow unfree packages - nixpkgs.config.allowUnfree = true; + # Allow unfree packages + nixpkgs.config.allowUnfree = true; - # Configure network proxy if necessary - # networking.proxy.default = "http://user:password@proxy:port/"; - # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - # Configure keymap in X11 - # services.xserver.layout = "us"; - # services.xserver.xkbOptions = "eurosign:e,caps:escape"; + # Configure keymap in X11 + # services.xserver.layout = "us"; + # services.xserver.xkbOptions = "eurosign:e,caps:escape"; - # Enable CUPS to print documents. - # services.printing.enable = true; + # Enable CUPS to print documents. + # services.printing.enable = true; - # Enable sound. - # sound.enable = true; - # hardware.pulseaudio.enable = true; + # Enable sound. + # sound.enable = true; + # hardware.pulseaudio.enable = true; - # Enable touchpad support (enabled default in most desktopManager). - # services.xserver.libinput.enable = true; + # Enable touchpad support (enabled default in most desktopManager). + # services.xserver.libinput.enable = true; + hardware.bluetooth.enable = true; - hardware.bluetooth.enable = true; + # List packages installed in system profile. To search, run: + # $ nix search wget + # environment.systemPackages = with pkgs; [ + # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + # wget + # ]; - # List packages installed in system profile. To search, run: - # $ nix search wget - # environment.systemPackages = with pkgs; [ - # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. - # wget - # ]; + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; - # Some programs need SUID wrappers, can be configured further or are - # started in user sessions. - # programs.mtr.enable = true; - # programs.gnupg.agent = { - # enable = true; - # enableSSHSupport = true; - # }; + # List services that you want to enable: - # List services that you want to enable: + # Enable the OpenSSH daemon. + # services.openssh.enable = true; - # Enable the OpenSSH daemon. - # services.openssh.enable = true; - - # Open ports in the firewall. - # networking.firewall.allowedTCPPorts = [ ... ]; - # networking.firewall.allowedUDPPorts = [ ... ]; - # Or disable the firewall altogether. - # networking.firewall.enable = false; - - # Copy the NixOS configuration file and link it from the resulting system - # (/run/current-system/configuration.nix). This is useful in case you - # accidentally delete configuration.nix. - # system.copySystemConfiguration = true; + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + # system.copySystemConfiguration = true; } - diff --git a/machines/Archie/default.nix b/machines/Archie/default.nix index 5bf2485..187a110 100755 --- a/machines/Archie/default.nix +++ b/machines/Archie/default.nix @@ -1,8 +1,6 @@ -{ ... }: - -{ - imports = [ - ./configuration.nix - ./hardware-configuration.nix - ]; +{...}: { + imports = [ + ./configuration.nix + ./hardware-configuration.nix + ]; } diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index 00a0702..ccd1840 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -1,76 +1,80 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: - { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; + config, + lib, + pkgs, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; - # Enable support for the Xbox One wireless dongle - hardware.xone.enable = true; + # Enable support for the Xbox One wireless dongle + hardware.xone.enable = true; - boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; - boot.initrd.kernelModules = [ "amdgpu" ]; - boot.kernelModules = [ "kvm-amd" ]; - boot.extraModulePackages = [ ]; + boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod"]; + boot.initrd.kernelModules = ["amdgpu"]; + boot.kernelModules = ["kvm-amd"]; + boot.extraModulePackages = []; - fileSystems."/" = - { device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; - fsType = "btrfs"; - options = [ "subvol=@root" "compress=zstd" ]; - }; + fileSystems."/" = { + device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; + fsType = "btrfs"; + options = ["subvol=@root" "compress=zstd"]; + }; - fileSystems."/nix" = - { device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; - fsType = "btrfs"; - options = [ "subvol=@nix" "compress=zstd" ]; - }; + fileSystems."/nix" = { + device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; + fsType = "btrfs"; + options = ["subvol=@nix" "compress=zstd"]; + }; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; - fsType = "btrfs"; - options = [ "subvol=@boot" "compress=zstd" ]; - }; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; + fsType = "btrfs"; + options = ["subvol=@boot" "compress=zstd"]; + }; - fileSystems."/boot/efi" = - { device = "/dev/disk/by-uuid/FB87-4CBC"; - fsType = "vfat"; - }; + fileSystems."/boot/efi" = { + device = "/dev/disk/by-uuid/FB87-4CBC"; + fsType = "vfat"; + }; - fileSystems = { - /* - Mount the root subvolume of the SSD - This is helpful for getting things from - my old Arch install, as well as for running btdu - */ - "/mnt/ssd" = { - device = config.fileSystems."/".device; - fsType = config.fileSystems."/".fsType; - options = [ "subvolid=5" "ro" ]; - }; - "/mnt/windows" = { - device = "/dev/disk/by-uuid/B61AFDAC1AFD6A2F"; - fsType = "ntfs3"; - neededForBoot = false; - options = [ "noauto" "windows_names" ]; - }; - "/home" = { - device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; - fsType = "btrfs"; - options = [ "subvol=@home" "compress=zstd" ]; - }; - "/persist" = { - device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; - fsType = "btrfs"; - options = [ "subvol=@persist" "compress=zstd" ]; - neededForBoot = true; - }; - }; + fileSystems = { + /* + Mount the root subvolume of the SSD + This is helpful for getting things from + my old Arch install, as well as for running btdu + */ + "/mnt/ssd" = { + device = config.fileSystems."/".device; + fsType = config.fileSystems."/".fsType; + options = ["subvolid=5" "ro"]; + }; + "/mnt/windows" = { + device = "/dev/disk/by-uuid/B61AFDAC1AFD6A2F"; + fsType = "ntfs3"; + neededForBoot = false; + options = ["noauto" "windows_names"]; + }; + "/home" = { + device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; + fsType = "btrfs"; + options = ["subvol=@home" "compress=zstd"]; + }; + "/persist" = { + device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; + fsType = "btrfs"; + options = ["subvol=@persist" "compress=zstd"]; + neededForBoot = true; + }; + }; - swapDevices = [ ]; + swapDevices = []; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index 085260d..d7f8a46 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -1,68 +1,72 @@ # Edit this configuration file to define what should be installed on # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running ‘nixos-help’). - -{ config, pkgs, lib, ... }: - { - # Bootloader. - boot.loader.systemd-boot.enable = true; - boot.loader.timeout = 5; - boot.loader.efi.canTouchEfiVariables = true; - boot.loader.efi.efiSysMountPoint = "/boot/efi"; + config, + pkgs, + lib, + ... +}: { + # Bootloader. + boot.loader.systemd-boot.enable = true; + boot.loader.timeout = 5; + boot.loader.efi.canTouchEfiVariables = true; + boot.loader.efi.efiSysMountPoint = "/boot/efi"; - # I'm using Nix OS, it's logo is a snowflake and the computer is - # a lot taller than the pi it's replacing, so Everest! :3 :3 - networking.hostName = "Everest"; # Define your hostname. + # I'm using Nix OS, it's logo is a snowflake and the computer is + # a lot taller than the pi it's replacing, so Everest! :3 :3 + networking.hostName = "Everest"; # Define your hostname. - # Set up networking - networking = { - wireless.enable = false; # Computer doesn't have wifi - enableIPv6 = false; - useNetworkd = true; - dhcpcd.enable = false; - interfaces.eno1 = { - wakeOnLan.enable = true; - ipv4.addresses = [ { - address = "192.168.0.160"; - prefixLength = 24; - } ]; - }; - # I use networkd, so I need to declare the interface for the default gateway - defaultGateway = { - address = "192.168.0.1"; - interface = "eno1"; - }; - nameservers = [ "9.9.9.9" ]; - }; - - # Define a user account. Don't forget to set a password with ‘passwd’. - users.users.toast = { - extraGroups = [ "networkmanager" "transmission"]; - openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2bOVmxUNvg9qFv9DlzMmTRlzcNsyNq1F1wBuAXySwsWAzHGaO+WGdSCINxW3k2ccXn7M/o1r89LeTzRzi8sWQYCpBaIqYVszM/r7SvTS4gASyKhM6lNlyUEPOnvCXH7rdtF+fjoA1TJPv7GBk78QRhGh+eVO3qhY1m++5C1CPFlyrc6sSfgIBQJ5GQZFl/7YEgsrPo+M+0Sd7LkaCOyNmJA0Wi0BA3bbf5sJhrZVMMg/p7w+eMphz2kd1VTVjW3yeMq9zLCiu4SOTBNGCMEvKIdUZbQ83lNrqO2z1/3T1bDwJgpz3xusfkNCeNJSmhfFw5ydHEUp/9jshq38WmulKAMw2Kl/Zed62AVU7Ux7YjUkZkWvo8i3eXuLUxoG891S7cWV1/ijs9QMajOLLT14FG7RbzUYYaYlx+/iNGji9d4sp9/oMYyO45TMe+vEezFSBygP7TY0QFOr4xTi49ZRQFsszbFnGRv+k3wVKoGoeNt0xWB8pBEPFtaeHJpQyJX8= id_rsa_moon" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOeu3crGqtxwaqgoQPt5mWlC8+PL/Icvcvo0MBAaK80L Key for work laptop" - ]; - }; + # Set up networking + networking = { + wireless.enable = false; # Computer doesn't have wifi + enableIPv6 = false; + useNetworkd = true; + dhcpcd.enable = false; + interfaces.eno1 = { + wakeOnLan.enable = true; + ipv4.addresses = [ + { + address = "192.168.0.160"; + prefixLength = 24; + } + ]; + }; + # I use networkd, so I need to declare the interface for the default gateway + defaultGateway = { + address = "192.168.0.1"; + interface = "eno1"; + }; + nameservers = ["9.9.9.9"]; + }; - # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs - boot.tmp.useTmpfs = false; + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.toast = { + extraGroups = ["networkmanager" "transmission"]; + openssh.authorizedKeys.keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2bOVmxUNvg9qFv9DlzMmTRlzcNsyNq1F1wBuAXySwsWAzHGaO+WGdSCINxW3k2ccXn7M/o1r89LeTzRzi8sWQYCpBaIqYVszM/r7SvTS4gASyKhM6lNlyUEPOnvCXH7rdtF+fjoA1TJPv7GBk78QRhGh+eVO3qhY1m++5C1CPFlyrc6sSfgIBQJ5GQZFl/7YEgsrPo+M+0Sd7LkaCOyNmJA0Wi0BA3bbf5sJhrZVMMg/p7w+eMphz2kd1VTVjW3yeMq9zLCiu4SOTBNGCMEvKIdUZbQ83lNrqO2z1/3T1bDwJgpz3xusfkNCeNJSmhfFw5ydHEUp/9jshq38WmulKAMw2Kl/Zed62AVU7Ux7YjUkZkWvo8i3eXuLUxoG891S7cWV1/ijs9QMajOLLT14FG7RbzUYYaYlx+/iNGji9d4sp9/oMYyO45TMe+vEezFSBygP7TY0QFOr4xTi49ZRQFsszbFnGRv+k3wVKoGoeNt0xWB8pBEPFtaeHJpQyJX8= id_rsa_moon" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOeu3crGqtxwaqgoQPt5mWlC8+PL/Icvcvo0MBAaK80L Key for work laptop" + ]; + }; - home-manager = { - users.toast = { config, ... }: { - home = { - file = { - # This symlinks the Transmission downloads folder into my user's downloads folder for easy access - "Downloads/Transmission".source = config.lib.file.mkOutOfStoreSymlink "/var/lib/transmission/Downloads"; - }; - }; - }; - }; + # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs + boot.tmp.useTmpfs = false; - # Open ports in the firewall. - # No idea what ports 5201 and 21027 do tho - networking.firewall.allowedTCPPorts = [ 5201 ]; - networking.firewall.allowedUDPPorts = [ 5201 21027]; - # Or disable the firewall altogether. - # networking.firewall.enable = false; + home-manager = { + users.toast = {config, ...}: { + home = { + file = { + # This symlinks the Transmission downloads folder into my user's downloads folder for easy access + "Downloads/Transmission".source = config.lib.file.mkOutOfStoreSymlink "/var/lib/transmission/Downloads"; + }; + }; + }; + }; + + # Open ports in the firewall. + # No idea what ports 5201 and 21027 do tho + networking.firewall.allowedTCPPorts = [5201]; + networking.firewall.allowedUDPPorts = [5201 21027]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; } diff --git a/machines/Everest/default.nix b/machines/Everest/default.nix index 5bf2485..187a110 100755 --- a/machines/Everest/default.nix +++ b/machines/Everest/default.nix @@ -1,8 +1,6 @@ -{ ... }: - -{ - imports = [ - ./configuration.nix - ./hardware-configuration.nix - ]; +{...}: { + imports = [ + ./configuration.nix + ./hardware-configuration.nix + ]; } diff --git a/machines/Everest/hardware-configuration.nix b/machines/Everest/hardware-configuration.nix index d165feb..007bc26 100755 --- a/machines/Everest/hardware-configuration.nix +++ b/machines/Everest/hardware-configuration.nix @@ -1,61 +1,65 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: - { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; + config, + lib, + pkgs, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; - boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; + boot.initrd.availableKernelModules = ["xhci_pci" "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod"]; + boot.initrd.kernelModules = []; + boot.kernelModules = ["kvm-intel"]; + boot.extraModulePackages = []; - fileSystems = { - "/" = { - device = "/dev/disk/by-label/Everest"; - fsType = "btrfs"; - options = [ "compress=zstd" "subvol=@"]; - }; - "/nix" = { - device = "/dev/disk/by-label/Everest"; - fsType = "btrfs"; - options = [ "compress=zstd" "subvol=@nix" ]; - }; - "/home" = { - device = "/dev/disk/by-label/Everest"; - fsType = "btrfs"; - options = [ "compress=zstd" "subvol=@home" ]; - }; - "/mnt/hdd" = { - device = "/dev/disk/by-label/Everest"; - fsType = "btrfs"; - options = [ "compress=zstd" "subvol=/" "ro" ]; - }; - "/persist" = { - device = "/dev/disk/by-label/Everest"; - fsType = "btrfs"; - options = [ "compress=zstd" "subvol=@persist" ]; - neededForBoot = true; - }; - }; + fileSystems = { + "/" = { + device = "/dev/disk/by-label/Everest"; + fsType = "btrfs"; + options = ["compress=zstd" "subvol=@"]; + }; + "/nix" = { + device = "/dev/disk/by-label/Everest"; + fsType = "btrfs"; + options = ["compress=zstd" "subvol=@nix"]; + }; + "/home" = { + device = "/dev/disk/by-label/Everest"; + fsType = "btrfs"; + options = ["compress=zstd" "subvol=@home"]; + }; + "/mnt/hdd" = { + device = "/dev/disk/by-label/Everest"; + fsType = "btrfs"; + options = ["compress=zstd" "subvol=/" "ro"]; + }; + "/persist" = { + device = "/dev/disk/by-label/Everest"; + fsType = "btrfs"; + options = ["compress=zstd" "subvol=@persist"]; + neededForBoot = true; + }; + }; - fileSystems."/boot/efi" = - { device = "/dev/disk/by-label/Boot"; - fsType = "vfat"; - }; + fileSystems."/boot/efi" = { + device = "/dev/disk/by-label/Boot"; + fsType = "vfat"; + }; - swapDevices = [ ]; + swapDevices = []; - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking - # (the default) this is the recommended approach. When using systemd-networkd it's - # still possible to use this option, but it's recommended to use it in conjunction - # with explicit per-interface declarations with `networking.interfaces..useDHCP`. - networking.useDHCP = lib.mkDefault true; - # networking.interfaces.eno1.useDHCP = lib.mkDefault true; + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.eno1.useDHCP = lib.mkDefault true; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index 0319993..6e0b86e 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -1,103 +1,103 @@ # Edit this configuration file to define what should be installed on # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running `nixos-help`). - -{ config, pkgs, lib, ... }: - { - # Use grub boot loader - boot.loader = { - systemd-boot.enable = false; - grub = { - enable = true; - device = "nodev"; - efiSupport = true; - # No other OS on here :P - useOSProber = false; - }; - efi.efiSysMountPoint = config.fileSystems."efi_boot_partition".mountPoint; - }; - boot.loader.efi.canTouchEfiVariables = true; + config, + pkgs, + lib, + ... +}: { + # Use grub boot loader + boot.loader = { + systemd-boot.enable = false; + grub = { + enable = true; + device = "nodev"; + efiSupport = true; + # No other OS on here :P + useOSProber = false; + }; + efi.efiSysMountPoint = config.fileSystems."efi_boot_partition".mountPoint; + }; + boot.loader.efi.canTouchEfiVariables = true; - networking.hostName = "SteamDeck"; # Define your hostname. + networking.hostName = "SteamDeck"; # Define your hostname. - # Allow unfree packages - nixpkgs.config.allowUnfree = true; + # Allow unfree packages + nixpkgs.config.allowUnfree = true; - # Configure network proxy if necessary - # networking.proxy.default = "http://user:password@proxy:port/"; - # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - jovian = { - devices.steamdeck = { - enable = true; - }; - # Steam Deck UI settings - steam = { - enable = true; - autoStart = true; - user = "toast"; - desktopSession = "plasmawayland"; - }; - decky-loader = { - enable = true; - }; - }; - services.xserver.displayManager.sddm.enable = lib.mkForce false; + jovian = { + devices.steamdeck = { + enable = true; + }; + # Steam Deck UI settings + steam = { + enable = true; + autoStart = true; + user = "toast"; + desktopSession = "plasmawayland"; + }; + decky-loader = { + enable = true; + }; + }; + services.xserver.displayManager.sddm.enable = lib.mkForce false; - # Enable bluetooth - hardware.bluetooth = { - enable = true; - }; + # Enable bluetooth + hardware.bluetooth = { + enable = true; + }; - # Configure keymap in X11 - # services.xserver.layout = "us"; - # services.xserver.xkbOptions = "eurosign:e,caps:escape"; + # Configure keymap in X11 + # services.xserver.layout = "us"; + # services.xserver.xkbOptions = "eurosign:e,caps:escape"; - # Enable CUPS to print documents. - # services.printing.enable = true; + # Enable CUPS to print documents. + # services.printing.enable = true; - # Enable sound. - # sound.enable = true; - # hardware.pulseaudio.enable = true; + # Enable sound. + # sound.enable = true; + # hardware.pulseaudio.enable = true; - # Enable touchpad support (enabled default in most desktopManager). - # services.xserver.libinput.enable = true; + # Enable touchpad support (enabled default in most desktopManager). + # services.xserver.libinput.enable = true; - # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs - boot.tmp.useTmpfs = false; + # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs + boot.tmp.useTmpfs = false; - environment.systemPackages = [ pkgs.steamdeck-firmware pkgs.steamdeck-hw-theme ]; - # List packages installed in system profile. To search, run: - # $ nix search wget - # environment.systemPackages = with pkgs; [ - # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. - # wget - # ]; + environment.systemPackages = [pkgs.steamdeck-firmware pkgs.steamdeck-hw-theme]; + # List packages installed in system profile. To search, run: + # $ nix search wget + # environment.systemPackages = with pkgs; [ + # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + # wget + # ]; - # Some programs need SUID wrappers, can be configured further or are - # started in user sessions. - # programs.mtr.enable = true; - # programs.gnupg.agent = { - # enable = true; - # enableSSHSupport = true; - # }; + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; - # List services that you want to enable: + # List services that you want to enable: - # Enable the OpenSSH daemon. - # services.openssh.enable = true; + # Enable the OpenSSH daemon. + # services.openssh.enable = true; - # Open ports in the firewall. - # networking.firewall.allowedTCPPorts = [ ... ]; - # networking.firewall.allowedUDPPorts = [ ... ]; - # Or disable the firewall altogether. - # networking.firewall.enable = false; - - # Copy the NixOS configuration file and link it from the resulting system - # (/run/current-system/configuration.nix). This is useful in case you - # accidentally delete configuration.nix. - # system.copySystemConfiguration = true; + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + # system.copySystemConfiguration = true; } - diff --git a/machines/SteamDeck/default.nix b/machines/SteamDeck/default.nix index 5bf2485..187a110 100755 --- a/machines/SteamDeck/default.nix +++ b/machines/SteamDeck/default.nix @@ -1,8 +1,6 @@ -{ ... }: - -{ - imports = [ - ./configuration.nix - ./hardware-configuration.nix - ]; +{...}: { + imports = [ + ./configuration.nix + ./hardware-configuration.nix + ]; } diff --git a/machines/SteamDeck/hardware-configuration.nix b/machines/SteamDeck/hardware-configuration.nix index 1f4cd77..dfb3835 100755 --- a/machines/SteamDeck/hardware-configuration.nix +++ b/machines/SteamDeck/hardware-configuration.nix @@ -1,71 +1,73 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: - -let - # \x20 is the escape code for a space - ssdLabel = ''Deck\\x20SSD''; -in - { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; + config, + lib, + pkgs, + modulesPath, + ... +}: let + # \x20 is the escape code for a space + ssdLabel = ''Deck\\x20SSD''; +in { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; - # Enable support for the Xbox One wireless dongle - hardware.xone.enable = true; + # Enable support for the Xbox One wireless dongle + hardware.xone.enable = true; - boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "usb_storage" "usbhid" "sd_mod" "sdhci_pci" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-amd" ]; - boot.extraModulePackages = [ ]; + boot.initrd.availableKernelModules = ["nvme" "xhci_pci" "usb_storage" "usbhid" "sd_mod" "sdhci_pci"]; + boot.initrd.kernelModules = []; + boot.kernelModules = ["kvm-amd"]; + boot.extraModulePackages = []; - fileSystems = { - "efi_boot_partition" = { - mountPoint = "/boot/efi"; - label = "deckboot"; - fsType = "vfat"; - }; - /* - Mount the root subvolume of the SSD - This is helpful for getting things from - my old Arch install, as well as for running btdu - */ - "btrfs_root_subvolume" = { - mountPoint = "/mnt/ssd"; - label = ssdLabel; - fsType = "btrfs"; - options = [ "subvolid=5" "ro" ]; - }; - "btrfs_root" = { - mountPoint = "/"; - label = ssdLabel; - fsType = "btrfs"; - options = [ "subvol=@" "compress=zstd" ]; - }; - "btrfs_boot" = { - mountPoint = "/boot"; - label = ssdLabel; - fsType = "btrfs"; - options = [ "subvol=@boot" "compress=zstd" ]; - }; - "btrfs_home" = { - mountPoint = "/home"; - label = ssdLabel; - fsType = "btrfs"; - options = [ "subvol=@home" "compress=zstd" ]; - }; - "btrfs_nix" = { - mountPoint = "/nix"; - label = ssdLabel; - fsType = "btrfs"; - options = [ "subvol=@nix" "compress=zstd" ]; - }; - }; + fileSystems = { + "efi_boot_partition" = { + mountPoint = "/boot/efi"; + label = "deckboot"; + fsType = "vfat"; + }; + /* + Mount the root subvolume of the SSD + This is helpful for getting things from + my old Arch install, as well as for running btdu + */ + "btrfs_root_subvolume" = { + mountPoint = "/mnt/ssd"; + label = ssdLabel; + fsType = "btrfs"; + options = ["subvolid=5" "ro"]; + }; + "btrfs_root" = { + mountPoint = "/"; + label = ssdLabel; + fsType = "btrfs"; + options = ["subvol=@" "compress=zstd"]; + }; + "btrfs_boot" = { + mountPoint = "/boot"; + label = ssdLabel; + fsType = "btrfs"; + options = ["subvol=@boot" "compress=zstd"]; + }; + "btrfs_home" = { + mountPoint = "/home"; + label = ssdLabel; + fsType = "btrfs"; + options = ["subvol=@home" "compress=zstd"]; + }; + "btrfs_nix" = { + mountPoint = "/nix"; + label = ssdLabel; + fsType = "btrfs"; + options = ["subvol=@nix" "compress=zstd"]; + }; + }; - swapDevices = [ ]; + swapDevices = []; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } diff --git a/machines/SurfaceGo/configuration.nix b/machines/SurfaceGo/configuration.nix index 7b63b8d..49c0620 100644 --- a/machines/SurfaceGo/configuration.nix +++ b/machines/SurfaceGo/configuration.nix @@ -1,92 +1,92 @@ # Edit this configuration file to define what should be installed on # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running `nixos-help`). - -{ config, pkgs, lib, ... }: - { - boot = { - loader = { - # Use grub boot loader - systemd-boot.enable = false; - grub = { - enable = true; - device = "nodev"; - efiSupport = true; - enableCryptodisk = true; - }; - efi = { - efiSysMountPoint = "/boot/efi"; - canTouchEfiVariables = true; - }; - }; - # I need systemd for tpm luks unlocking - initrd.systemd.enable = true; - }; + config, + pkgs, + lib, + ... +}: { + boot = { + loader = { + # Use grub boot loader + systemd-boot.enable = false; + grub = { + enable = true; + device = "nodev"; + efiSupport = true; + enableCryptodisk = true; + }; + efi = { + efiSysMountPoint = "/boot/efi"; + canTouchEfiVariables = true; + }; + }; + # I need systemd for tpm luks unlocking + initrd.systemd.enable = true; + }; - security.tpm2.enable = true; + security.tpm2.enable = true; - networking.hostName = "SurfaceGo"; # Define your hostname. + networking.hostName = "SurfaceGo"; # Define your hostname. - # Allow unfree packages - nixpkgs.config.allowUnfree = true; + # Allow unfree packages + nixpkgs.config.allowUnfree = true; - # Configure network proxy if necessary - # networking.proxy.default = "http://user:password@proxy:port/"; - # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - # Configure keymap in X11 - # services.xserver.layout = "us"; - # services.xserver.xkbOptions = "eurosign:e,caps:escape"; + # Configure keymap in X11 + # services.xserver.layout = "us"; + # services.xserver.xkbOptions = "eurosign:e,caps:escape"; - console = { - # The kernel doesn't detect the scree as being HiDPI, so I need to use a bigger font - font = "ter-i32n"; - }; - - # Enable CUPS to print documents. - # services.printing.enable = true; + console = { + # The kernel doesn't detect the scree as being HiDPI, so I need to use a bigger font + font = "ter-i32n"; + }; - # Enable sound. - # sound.enable = true; - # hardware.pulseaudio.enable = true; + # Enable CUPS to print documents. + # services.printing.enable = true; - # Enable touchpad support (enabled default in most desktopManager). - # services.xserver.libinput.enable = true; + # Enable sound. + # sound.enable = true; + # hardware.pulseaudio.enable = true; - # List packages installed in system profile. To search, run: - # $ nix search wget - # environment.systemPackages = with pkgs; [ - # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. - # wget - # ]; + # Enable touchpad support (enabled default in most desktopManager). + # services.xserver.libinput.enable = true; - # The surface kernel sometimes fails to suspend/shutdown and I got tired of fighting it - boot.kernelPackages = lib.mkForce pkgs.linuxPackages; + # List packages installed in system profile. To search, run: + # $ nix search wget + # environment.systemPackages = with pkgs; [ + # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + # wget + # ]; - # Some programs need SUID wrappers, can be configured further or are - # started in user sessions. - # programs.mtr.enable = true; - # programs.gnupg.agent = { - # enable = true; - # enableSSHSupport = true; - # }; + # The surface kernel sometimes fails to suspend/shutdown and I got tired of fighting it + boot.kernelPackages = lib.mkForce pkgs.linuxPackages; - # List services that you want to enable: + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; - # Enable the OpenSSH daemon. - # services.openssh.enable = true; + # List services that you want to enable: - # Open ports in the firewall. - # networking.firewall.allowedTCPPorts = [ ... ]; - # networking.firewall.allowedUDPPorts = [ ... ]; - # Or disable the firewall altogether. - # networking.firewall.enable = false; + # Enable the OpenSSH daemon. + # services.openssh.enable = true; - # Copy the NixOS configuration file and link it from the resulting system - # (/run/current-system/configuration.nix). This is useful in case you - # accidentally delete configuration.nix. - # system.copySystemConfiguration = true; + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + # system.copySystemConfiguration = true; } - diff --git a/machines/SurfaceGo/default.nix b/machines/SurfaceGo/default.nix index 5bf2485..187a110 100644 --- a/machines/SurfaceGo/default.nix +++ b/machines/SurfaceGo/default.nix @@ -1,8 +1,6 @@ -{ ... }: - -{ - imports = [ - ./configuration.nix - ./hardware-configuration.nix - ]; +{...}: { + imports = [ + ./configuration.nix + ./hardware-configuration.nix + ]; } diff --git a/machines/SurfaceGo/hardware-configuration.nix b/machines/SurfaceGo/hardware-configuration.nix index 75c5c1a..955cc05 100644 --- a/machines/SurfaceGo/hardware-configuration.nix +++ b/machines/SurfaceGo/hardware-configuration.nix @@ -1,49 +1,51 @@ - # Do not modify this file! It was generated by ‘nixos-generate-config’ +# Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, ... }: - { + config, + lib, + pkgs, + ... +}: { + boot.initrd.availableKernelModules = ["xhci_pci" "nvme" "usbhid" "rtsx_pci_sdmmc"]; + boot.initrd.kernelModules = []; + boot.kernelModules = ["kvm-intel"]; + boot.extraModulePackages = []; - boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usbhid" "rtsx_pci_sdmmc" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; + boot.initrd.luks.devices."SSD".device = "/dev/disk/by-uuid/1d8d7578-d3a1-4ea0-90ad-4257266a6caf"; - boot.initrd.luks.devices."SSD".device = "/dev/disk/by-uuid/1d8d7578-d3a1-4ea0-90ad-4257266a6caf"; + fileSystems."/" = { + device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; + fsType = "btrfs"; + options = ["subvol=@" "compress=zstd"]; + }; - fileSystems."/" = { - device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; - fsType = "btrfs"; - options = [ "subvol=@" "compress=zstd" ]; - }; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; + fsType = "btrfs"; + options = ["subvol=@boot" "compress=zstd"]; + }; - fileSystems."/boot" = { - device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; - fsType = "btrfs"; - options = [ "subvol=@boot" "compress=zstd" ]; - }; + fileSystems."/nix" = { + device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; + fsType = "btrfs"; + options = ["subvol=@nix" "compress=zstd"]; + }; - fileSystems."/nix" ={ - device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; - fsType = "btrfs"; - options = [ "subvol=@nix" "compress=zstd" ]; - }; + fileSystems."/home" = { + device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; + fsType = "btrfs"; + options = ["subvol=@home" "compress=zstd"]; + }; - fileSystems."/home" = { - device = "/dev/disk/by-uuid/19a52b40-3ff6-47ff-9402-18d8b289643e"; - fsType = "btrfs"; - options = [ "subvol=@home" "compress=zstd" ]; - }; + fileSystems."/boot/efi" = { + device = "/dev/disk/by-uuid/EC76-201F"; + fsType = "vfat"; + }; - fileSystems."/boot/efi" = { - device = "/dev/disk/by-uuid/EC76-201F"; - fsType = "vfat"; - }; + swapDevices = []; - swapDevices = []; - - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; - hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 026000b..a5d20c3 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -1,153 +1,153 @@ - # Edit this configuration file to define what should be installed on +# Edit this configuration file to define what should be installed on # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running `nixos-help`). - -{ config, pkgs, lib, ... }: - { - # Use grub boot loader - boot = { - loader = { - systemd-boot.enable = false; - grub = { - enable = true; - device = "nodev"; - efiSupport = true; - # No other OS on here :P - useOSProber = false; - }; - efi = { - efiSysMountPoint = config.fileSystems."efi_boot_partition".mountPoint; - canTouchEfiVariables = true; - }; - }; - /* - I use luks, and the systemd initrd works better for this - Both for tpm unlocking (soon) and for plymouth - */ - initrd.systemd.enable = true; - # Plymouth doesn't support fractional scaling :( - plymouth.extraConfig = "DeviceScale=2"; + config, + pkgs, + lib, + ... +}: { + # Use grub boot loader + boot = { + loader = { + systemd-boot.enable = false; + grub = { + enable = true; + device = "nodev"; + efiSupport = true; + # No other OS on here :P + useOSProber = false; + }; + efi = { + efiSysMountPoint = config.fileSystems."efi_boot_partition".mountPoint; + canTouchEfiVariables = true; + }; + }; + /* + I use luks, and the systemd initrd works better for this + Both for tpm unlocking (soon) and for plymouth + */ + initrd.systemd.enable = true; + # Plymouth doesn't support fractional scaling :( + plymouth.extraConfig = "DeviceScale=2"; - kernelPackages = pkgs.linuxPackages_latest; - }; + kernelPackages = pkgs.linuxPackages_latest; + }; - networking.hostName = "WinMax2"; # Define your hostname. + networking.hostName = "WinMax2"; # Define your hostname. - specialisation.noAVX512.configuration = { - # For some reason The Finals crashes on CPUs that support AVX512 - boot.kernelParams = [ "clearcpuid=304" ]; - }; + specialisation.noAVX512.configuration = { + # For some reason The Finals crashes on CPUs that support AVX512 + boot.kernelParams = ["clearcpuid=304"]; + }; - # Sleep fixes - boot.kernelParams = [ "rtc_cmos.use_acpi_alarm=1" ]; - services.udev.extraRules = '' -ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="GXTP7385:00", ATTR{power/wakeup}="disabled" -ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="disabled" - ''; + # Sleep fixes + boot.kernelParams = ["rtc_cmos.use_acpi_alarm=1"]; + services.udev.extraRules = '' + ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="GXTP7385:00", ATTR{power/wakeup}="disabled" + ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="disabled" + ''; - services.handheld-daemon = { - package = pkgs.handheld-daemon.overridePythonAttrs rec{ - src = pkgs.fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - rev = "v${version}"; - hash = "sha256-Ujbou+f/EvHyqpp3FCNqIyZiCEFxSeQfflR3JmRxWFc="; - }; - version = "1.3.13"; - }; - enable = true; - user = "root"; - }; + services.handheld-daemon = { + package = pkgs.handheld-daemon.overridePythonAttrs rec { + src = pkgs.fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + rev = "v${version}"; + hash = "sha256-Ujbou+f/EvHyqpp3FCNqIyZiCEFxSeQfflR3JmRxWFc="; + }; + version = "1.3.13"; + }; + enable = true; + user = "root"; + }; - # Allow unfree packages - nixpkgs.config.allowUnfree = true; + # Allow unfree packages + nixpkgs.config.allowUnfree = true; - # Configure network proxy if necessary - # networking.proxy.default = "http://user:password@proxy:port/"; - # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - services.xserver = { - xkb.layout = lib.mkForce "us"; - displayManager.sddm.settings = { - General.GreeterEnvironment="QT_SCREEN_SCALE_FACTORS=1.75"; - }; - }; + services.xserver = { + xkb.layout = lib.mkForce "us"; + displayManager.sddm.settings = { + General.GreeterEnvironment = "QT_SCREEN_SCALE_FACTORS=1.75"; + }; + }; - jovian = { - # Steam Deck UI settings - steam = { - enable = true; - autoStart = false; - user = "toast"; - desktopSession = "plasmawayland"; - }; - hardware.amd.gpu.enableBacklightControl = true; - # Need patched mesa - steamos = { - enableMesaPatches = true; - enableVendorRadv = true; - }; - decky-loader = { - enable = true; - }; - }; + jovian = { + # Steam Deck UI settings + steam = { + enable = true; + autoStart = false; + user = "toast"; + desktopSession = "plasmawayland"; + }; + hardware.amd.gpu.enableBacklightControl = true; + # Need patched mesa + steamos = { + enableMesaPatches = true; + enableVendorRadv = true; + }; + decky-loader = { + enable = true; + }; + }; - # Enable bluetooth - hardware.bluetooth = { - enable = true; - }; + # Enable bluetooth + hardware.bluetooth = { + enable = true; + }; - # Configure keymap in X11 - # services.xserver.layout = "us"; - # services.xserver.xkbOptions = "eurosign:e,caps:escape"; + # Configure keymap in X11 + # services.xserver.layout = "us"; + # services.xserver.xkbOptions = "eurosign:e,caps:escape"; - # Enable CUPS to print documents. - # services.printing.enable = true; - environment.sessionVariables = { - STEAM_FORCE_DESKTOPUI_SCALING = "1.75"; - }; + # Enable CUPS to print documents. + # services.printing.enable = true; + environment.sessionVariables = { + STEAM_FORCE_DESKTOPUI_SCALING = "1.75"; + }; - # Enable sound. - # sound.enable = true; - # hardware.pulseaudio.enable = true; + # Enable sound. + # sound.enable = true; + # hardware.pulseaudio.enable = true; - # Enable touchpad support (enabled default in most desktopManager). - # services.xserver.libinput.enable = true; + # Enable touchpad support (enabled default in most desktopManager). + # services.xserver.libinput.enable = true; - # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs - boot.tmp.useTmpfs = false; + # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs + boot.tmp.useTmpfs = false; - # List packages installed in system profile. To search, run: - # $ nix search wget - # environment.systemPackages = with pkgs; [ - # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. - # wget - # ]; + # List packages installed in system profile. To search, run: + # $ nix search wget + # environment.systemPackages = with pkgs; [ + # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + # wget + # ]; - # Some programs need SUID wrappers, can be configured further or are - # started in user sessions. - # programs.mtr.enable = true; - # programs.gnupg.agent = { - # enable = true; - # enableSSHSupport = true; - # }; + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; - # List services that you want to enable: + # List services that you want to enable: - # Enable the OpenSSH daemon. - # services.openssh.enable = true; + # Enable the OpenSSH daemon. + # services.openssh.enable = true; - # Open ports in the firewall. - # networking.firewall.allowedTCPPorts = [ ... ]; - # networking.firewall.allowedUDPPorts = [ ... ]; - # Or disable the firewall altogether. - # networking.firewall.enable = false; - - # Copy the NixOS configuration file and link it from the resulting system - # (/run/current-system/configuration.nix). This is useful in case you - # accidentally delete configuration.nix. - # system.copySystemConfiguration = true; + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + # system.copySystemConfiguration = true; } - diff --git a/machines/WinMax2/default.nix b/machines/WinMax2/default.nix index 5bf2485..187a110 100755 --- a/machines/WinMax2/default.nix +++ b/machines/WinMax2/default.nix @@ -1,8 +1,6 @@ -{ ... }: - -{ - imports = [ - ./configuration.nix - ./hardware-configuration.nix - ]; +{...}: { + imports = [ + ./configuration.nix + ./hardware-configuration.nix + ]; } diff --git a/machines/WinMax2/hardware-configuration.nix b/machines/WinMax2/hardware-configuration.nix index 2f8b16b..45745ac 100755 --- a/machines/WinMax2/hardware-configuration.nix +++ b/machines/WinMax2/hardware-configuration.nix @@ -1,74 +1,75 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, modulesPath, ... }: - -let - # \x20 is the escape code for a space - ssdLabel = ''Win\\x20Max\\x202\\x20SSD''; -in - { - imports = [ - (modulesPath + "/installer/scan/not-detected.nix") - ]; + config, + lib, + modulesPath, + ... +}: let + # \x20 is the escape code for a space + ssdLabel = ''Win\\x20Max\\x202\\x20SSD''; +in { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; - boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usbhid" "sdhci_pci" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-amd" ]; - boot.extraModulePackages = [ ]; + boot.initrd.availableKernelModules = ["nvme" "xhci_pci" "thunderbolt" "usbhid" "sdhci_pci"]; + boot.initrd.kernelModules = []; + boot.kernelModules = ["kvm-amd"]; + boot.extraModulePackages = []; - boot.initrd.luks.devices."SSD".device = "/dev/disk/by-label/wm2-enc"; + boot.initrd.luks.devices."SSD".device = "/dev/disk/by-label/wm2-enc"; - fileSystems = { - "efi_boot_partition" = { - mountPoint = "/boot"; - label = "winmax2boot"; - fsType = "vfat"; - }; - /* - Mount the root subvolume of the SSD - This is helpful for getting things from - my old Arch install, as well as for running btdu - */ - "btrfs_root_subvolume" = { - mountPoint = "/mnt/ssd"; - label = ssdLabel; - fsType = "btrfs"; - options = [ "subvolid=5" "ro" ]; - }; - "btrfs_root" = { - mountPoint = "/"; - label = ssdLabel; - fsType = "btrfs"; - options = [ "subvol=@" ]; - }; - "btrfs_persist" = { - mountPoint = "/persist"; - label = ssdLabel; - fsType = "btrfs"; - options = [ "subvol=@persist" ]; - neededForBoot = true; - }; - "btrfs_home" = { - mountPoint = "/home"; - label = ssdLabel; - fsType = "btrfs"; - options = [ "subvol=@home" ]; - }; - "btrfs_nix" = { - mountPoint = "/nix"; - label = ssdLabel; - fsType = "btrfs"; - options = [ "subvol=@nix" ]; - }; - }; + fileSystems = { + "efi_boot_partition" = { + mountPoint = "/boot"; + label = "winmax2boot"; + fsType = "vfat"; + }; + /* + Mount the root subvolume of the SSD + This is helpful for getting things from + my old Arch install, as well as for running btdu + */ + "btrfs_root_subvolume" = { + mountPoint = "/mnt/ssd"; + label = ssdLabel; + fsType = "btrfs"; + options = ["subvolid=5" "ro"]; + }; + "btrfs_root" = { + mountPoint = "/"; + label = ssdLabel; + fsType = "btrfs"; + options = ["subvol=@"]; + }; + "btrfs_persist" = { + mountPoint = "/persist"; + label = ssdLabel; + fsType = "btrfs"; + options = ["subvol=@persist"]; + neededForBoot = true; + }; + "btrfs_home" = { + mountPoint = "/home"; + label = ssdLabel; + fsType = "btrfs"; + options = ["subvol=@home"]; + }; + "btrfs_nix" = { + mountPoint = "/nix"; + label = ssdLabel; + fsType = "btrfs"; + options = ["subvol=@nix"]; + }; + }; - swapDevices = [ ]; + swapDevices = []; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware = { - cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; - sensor.iio.bmi260.enable = true; - }; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware = { + cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + sensor.iio.bmi260.enable = true; + }; } diff --git a/pkgs/anything-sync-daemon/default.nix b/pkgs/anything-sync-daemon/default.nix index 974bf9a..afa5417 100644 --- a/pkgs/anything-sync-daemon/default.nix +++ b/pkgs/anything-sync-daemon/default.nix @@ -1,56 +1,57 @@ -{ stdenv -, lib -, fetchFromGitHub -, makeWrapper -, rsync -, gawk -, pv -, gnutar -, zstd -, util-linux -, coreutils -, gnugrep -, findutils +{ + stdenv, + lib, + fetchFromGitHub, + makeWrapper, + rsync, + gawk, + pv, + gnutar, + zstd, + util-linux, + coreutils, + gnugrep, + findutils, }: stdenv.mkDerivation rec { - pname = "anything-sync-daemon"; - version = "6.0.0"; + pname = "anything-sync-daemon"; + version = "6.0.0"; - src = fetchFromGitHub { - owner = "graysky2"; - repo = pname; - rev = "v${version}"; - hash = "sha256-6nfaAMH5YgK6gimuZ8j1zWLTDOi11KIwW7Bf0Iwh7+I="; - }; + src = fetchFromGitHub { + owner = "graysky2"; + repo = pname; + rev = "v${version}"; + hash = "sha256-6nfaAMH5YgK6gimuZ8j1zWLTDOi11KIwW7Bf0Iwh7+I="; + }; - patches = [ ./disableDaemonStopTargets.patch ]; + patches = [./disableDaemonStopTargets.patch]; - nativeBuildInputs = [ makeWrapper ]; + nativeBuildInputs = [makeWrapper]; - postPatch = '' - substituteInPlace init/asd* \ - --replace /usr/bin/anything-sync-daemon $out/bin/anything-sync-daemon - ''; + postPatch = '' + substituteInPlace init/asd* \ + --replace /usr/bin/anything-sync-daemon $out/bin/anything-sync-daemon + ''; - enableParallelBuilding = true; + enableParallelBuilding = true; - makeFlags = [ - "DESTDIR=${placeholder "out"}" - "PREFIX=" - "INITDIR_SYSTEMD=/lib/systemd/system" - ]; + makeFlags = [ + "DESTDIR=${placeholder "out"}" + "PREFIX=" + "INITDIR_SYSTEMD=/lib/systemd/system" + ]; - installTargets = [ "install-systemd-all" ]; + installTargets = ["install-systemd-all"]; - postInstall = '' - wrapProgram $out/bin/anything-sync-daemon \ - --suffix PATH : ${lib.makeBinPath [ rsync gawk pv gnutar zstd util-linux coreutils gnugrep findutils]} - ''; - - meta = with lib; { - description = "Symlinks and syncs user specified dirs to RAM"; - homepage = "https://github.com/graysky2/anything-sync-daemon/"; - license = lib.licenses.mit; - platforms = platforms.linux; - }; + postInstall = '' + wrapProgram $out/bin/anything-sync-daemon \ + --suffix PATH : ${lib.makeBinPath [rsync gawk pv gnutar zstd util-linux coreutils gnugrep findutils]} + ''; + + meta = with lib; { + description = "Symlinks and syncs user specified dirs to RAM"; + homepage = "https://github.com/graysky2/anything-sync-daemon/"; + license = lib.licenses.mit; + platforms = platforms.linux; + }; } diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 3e42588..210eb6f 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -1,132 +1,136 @@ -{ config, lib, pkgs, flakeSelf, ... }: - { - imports = [ flakeSelf.inputs.nur.nixosModules.nur ]; - environment = { - # As of the 1st of May 2023, the default packages are nano, perl, rsync and strace - # I don't need any of them, so I just empty the list - defaultPackages = []; - }; + config, + lib, + pkgs, + flakeSelf, + ... +}: { + imports = [flakeSelf.inputs.nur.nixosModules.nur]; + environment = { + # As of the 1st of May 2023, the default packages are nano, perl, rsync and strace + # I don't need any of them, so I just empty the list + defaultPackages = []; + }; - # Set up /tmp - boot.tmp = { - useTmpfs = false; - # Cleaning out /tmp at boot if it's a tmpfs is quite stupid - cleanOnBoot = !config.boot.tmp.useTmpfs; - }; + # Set up /tmp + boot.tmp = { + useTmpfs = false; + # Cleaning out /tmp at boot if it's a tmpfs is quite stupid + cleanOnBoot = !config.boot.tmp.useTmpfs; + }; - # Set up zram - zramSwap = { - enable = true; - priority = 100; - memoryPercent = 60; - # zstd my beloved <3 - algorithm = "zstd"; - }; - # zswap with zram is not a good idea - boot.kernelParams = [ "zswap.enabled=0" ]; + # Set up zram + zramSwap = { + enable = true; + priority = 100; + memoryPercent = 60; + # zstd my beloved <3 + algorithm = "zstd"; + }; + # zswap with zram is not a good idea + boot.kernelParams = ["zswap.enabled=0"]; - # Set up keyboard layout - services.xserver.xkb.layout = "es"; + # Set up keyboard layout + services.xserver.xkb.layout = "es"; - # Set up console - console = { - packages = [ pkgs.terminus_font ]; - earlySetup = true; - # mkDefault has 1000 priority, so that way I don't conflict with nixos-hardware - font = lib.mkOverride 999 "ter-i16n"; - # Make the console use X's keyboard configuration - useXkbConfig = true; - }; + # Set up console + console = { + packages = [pkgs.terminus_font]; + earlySetup = true; + # mkDefault has 1000 priority, so that way I don't conflict with nixos-hardware + font = lib.mkOverride 999 "ter-i16n"; + # Make the console use X's keyboard configuration + useXkbConfig = true; + }; - boot.supportedFilesystems = [ "nfs" ]; - - # Set up localisation - i18n = { - defaultLocale = "en_US.UTF-8"; - extraLocaleSettings = { - LC_NUMERIC = "es_ES.UTF-8"; - # am/pm is nice but mm/dd/yy is yucky - LC_TIME = "es_US.UTF-8"; - LC_MONETARY = "es_ES.UTF-8"; - LC_MEASUREMENT = "es_ES.UTF-8"; - LC_PAPER = "es_ES.UTF-8"; - LC_ADDRESS = "es_US.UTF-8"; - LC_NAME = "es_ES.UTF-8"; - LC_TELEPHONE = "es_ES.UTF-8"; - }; - }; + boot.supportedFilesystems = ["nfs"]; - services.fwupd.enable = true; + # Set up localisation + i18n = { + defaultLocale = "en_US.UTF-8"; + extraLocaleSettings = { + LC_NUMERIC = "es_ES.UTF-8"; + # am/pm is nice but mm/dd/yy is yucky + LC_TIME = "es_US.UTF-8"; + LC_MONETARY = "es_ES.UTF-8"; + LC_MEASUREMENT = "es_ES.UTF-8"; + LC_PAPER = "es_ES.UTF-8"; + LC_ADDRESS = "es_US.UTF-8"; + LC_NAME = "es_ES.UTF-8"; + LC_TELEPHONE = "es_ES.UTF-8"; + }; + }; - # Set up my user - users.users.toast = { - isNormalUser = true; - description = "Toast"; - extraGroups = [ "wheel" ]; - }; + services.fwupd.enable = true; - # Set up time zone. - time.timeZone = "Europe/Madrid"; + # Set up my user + users.users.toast = { + isNormalUser = true; + description = "Toast"; + extraGroups = ["wheel"]; + }; - nixpkgs.overlays = [ - ( - final: prev: { - catppuccin = prev.catppuccin.override { - accent = "mauve"; - variant = "mocha"; - themeList = [ - "bat" - "btop" - "starship" - "grub" - ]; - }; - } - ) - ]; + # Set up time zone. + time.timeZone = "Europe/Madrid"; - home-manager = { - backupFileExtension = "hm-backup"; - useGlobalPkgs = true; - verbose = true; - users.toast = { config, ... }: { - home.stateVersion = "23.11"; - xdg = { - userDirs = { - enable = true; - createDirectories = true; - publicShare = null; # Disable the public folder - }; - }; - }; - }; + nixpkgs.overlays = [ + ( + final: prev: { + catppuccin = prev.catppuccin.override { + accent = "mauve"; + variant = "mocha"; + themeList = [ + "bat" + "btop" + "starship" + "grub" + ]; + }; + } + ) + ]; - # Set up secrets - age = { - identityPaths = [ - "/persist/id_host" - ]; - }; + home-manager = { + backupFileExtension = "hm-backup"; + useGlobalPkgs = true; + verbose = true; + users.toast = {config, ...}: { + home.stateVersion = "23.11"; + xdg = { + userDirs = { + enable = true; + createDirectories = true; + publicShare = null; # Disable the public folder + }; + }; + }; + }; - boot.loader.grub = { - theme = "${pkgs.catppuccin}/grub"; - backgroundColor = "#1E1E2E"; - splashImage = "${pkgs.catppuccin}/grub/background.png"; - }; + # Set up secrets + age = { + identityPaths = [ + "/persist/id_host" + ]; + }; - /* - I used to keep the host keys in the repo as a secret, but since I use the - host keys for decrypting too I'm not sure encrypting a key with itself - is a good idea. Now the host keys will need to be placed manually where they are needed - For first time installs they are generated by services.openssh.hostKeys on servers, and - manually on everything else - */ - - system = { - stateVersion = "23.11"; - # Nix on nixos 23.05 does not have dirtyRev - configurationRevision = flakeSelf.sourceInfo.rev or flakeSelf.sourceInfo.dirtyRev or "dirty"; - nixos.variant_id = lib.strings.toLower config.networking.hostName; - }; + boot.loader.grub = { + theme = "${pkgs.catppuccin}/grub"; + backgroundColor = "#1E1E2E"; + splashImage = "${pkgs.catppuccin}/grub/background.png"; + }; + + /* + I used to keep the host keys in the repo as a secret, but since I use the + host keys for decrypting too I'm not sure encrypting a key with itself + is a good idea. Now the host keys will need to be placed manually where they are needed + For first time installs they are generated by services.openssh.hostKeys on servers, and + manually on everything else + */ + + system = { + stateVersion = "23.11"; + # Nix on nixos 23.05 does not have dirtyRev + configurationRevision = flakeSelf.sourceInfo.rev or flakeSelf.sourceInfo.dirtyRev or "dirty"; + nixos.variant_id = lib.strings.toLower config.networking.hostName; + }; } diff --git a/roles/common/default.nix b/roles/common/default.nix index 1e090a3..c9bfd8b 100755 --- a/roles/common/default.nix +++ b/roles/common/default.nix @@ -1,9 +1,7 @@ -{ ... }: - -{ - imports = [ - ./programs - ./services - ./configuration.nix - ]; +{...}: { + imports = [ + ./programs + ./services + ./configuration.nix + ]; } diff --git a/roles/common/programs/bash.nix b/roles/common/programs/bash.nix index a87dea5..bfcc625 100644 --- a/roles/common/programs/bash.nix +++ b/roles/common/programs/bash.nix @@ -1,10 +1,8 @@ -{ config, ... }: - -{ - home-manager.users.toast = { config, ... }: { - programs.bash = { - enable = true; - enableVteIntegration = true; - }; - }; +{config, ...}: { + home-manager.users.toast = {config, ...}: { + programs.bash = { + enable = true; + enableVteIntegration = true; + }; + }; } diff --git a/roles/common/programs/bat.nix b/roles/common/programs/bat.nix index 43a53d1..021d531 100644 --- a/roles/common/programs/bat.nix +++ b/roles/common/programs/bat.nix @@ -1,21 +1,25 @@ -{ config, pkgs, ... }: - -let - themeName = if config.system.nixos.release == "23.11" then "Catppuccin-mocha" else "Catppuccin Mocha"; -in { - home-manager = { - users.toast.programs.bat = { - enable = true; - config = { - theme = "catppuccin-mocha"; - }; - themes = { - catppuccin-mocha = { - src = pkgs.catppuccin; - file = "bat/${themeName}.tmTheme"; - }; - }; - }; - }; + config, + pkgs, + ... +}: let + themeName = + if config.system.nixos.release == "23.11" + then "Catppuccin-mocha" + else "Catppuccin Mocha"; +in { + home-manager = { + users.toast.programs.bat = { + enable = true; + config = { + theme = "catppuccin-mocha"; + }; + themes = { + catppuccin-mocha = { + src = pkgs.catppuccin; + file = "bat/${themeName}.tmTheme"; + }; + }; + }; + }; } diff --git a/roles/common/programs/btop.nix b/roles/common/programs/btop.nix index 5150cbf..c0bf0de 100644 --- a/roles/common/programs/btop.nix +++ b/roles/common/programs/btop.nix @@ -1,6 +1,4 @@ -{ pkgs, ... }: - -{ +{pkgs, ...}: { home-manager = { users.toast = { programs.btop = { @@ -14,4 +12,4 @@ }; }; }; -} \ No newline at end of file +} diff --git a/roles/common/programs/comma.nix b/roles/common/programs/comma.nix index 3c3f07b..e276b89 100644 --- a/roles/common/programs/comma.nix +++ b/roles/common/programs/comma.nix @@ -1,8 +1,10 @@ -{ config, pkgs, ... }: - { - # Use nix-index-database's comma wrapper - programs.nix-index-database.comma.enable = true; - # Run programs from the system's nixpkgs - environment.variables = { COMMA_NIXPKGS_FLAKE="system"; }; + config, + pkgs, + ... +}: { + # Use nix-index-database's comma wrapper + programs.nix-index-database.comma.enable = true; + # Run programs from the system's nixpkgs + environment.variables = {COMMA_NIXPKGS_FLAKE = "system";}; } diff --git a/roles/common/programs/command-not-found.nix b/roles/common/programs/command-not-found.nix index 0816b39..8dfa3d1 100755 --- a/roles/common/programs/command-not-found.nix +++ b/roles/common/programs/command-not-found.nix @@ -1,6 +1,4 @@ -{ config, ... }: - -{ - # The nixpkgs command-not-found script does not work with flakes, so I disable it - programs.command-not-found.enable = false; +{config, ...}: { + # The nixpkgs command-not-found script does not work with flakes, so I disable it + programs.command-not-found.enable = false; } diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index bc89f3a..8a8df10 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -1,32 +1,34 @@ -{ config, pkgs, ... }: - { - imports = [ - ./htop.nix - ./nix.nix - ./micro.nix - ./nix-index.nix - ./command-not-found.nix - ./comma.nix - ./bash.nix - ./git.nix - ./starship.nix - ./bat.nix - ./btop.nix - ./helix.nix - ./direnv.nix - ]; - # Some programs dont have a programs.*.enable option, so I install their package here - environment.systemPackages = with pkgs; [ - speedtest-cli - # Bat has a home manager module, but I want it to be available system wide - bat - file - nvd - ncdu - tree - btdu - iperf3 - restic - ]; + config, + pkgs, + ... +}: { + imports = [ + ./htop.nix + ./nix.nix + ./micro.nix + ./nix-index.nix + ./command-not-found.nix + ./comma.nix + ./bash.nix + ./git.nix + ./starship.nix + ./bat.nix + ./btop.nix + ./helix.nix + ./direnv.nix + ]; + # Some programs dont have a programs.*.enable option, so I install their package here + environment.systemPackages = with pkgs; [ + speedtest-cli + # Bat has a home manager module, but I want it to be available system wide + bat + file + nvd + ncdu + tree + btdu + iperf3 + restic + ]; } diff --git a/roles/common/programs/direnv.nix b/roles/common/programs/direnv.nix index c0ab11a..856dcbb 100644 --- a/roles/common/programs/direnv.nix +++ b/roles/common/programs/direnv.nix @@ -1,6 +1,4 @@ -{ ... }: - -{ +{...}: { programs.direnv = { enable = true; nix-direnv = { diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index 17fdf47..c9b673a 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -1,34 +1,33 @@ -{ config, pkgs, ... }: - -let - catppuccinDelta = pkgs.fetchFromGitHub { - owner = "catppuccin"; - repo = "delta"; - rev = "main"; - hash = "sha256-0QQLkfLBVuB2re6tjtPNuOQZNK0MDBAIFgNGHZM8afs="; - }; -in - { - home-manager.users.toast = { - programs.git = { - enable = true; - userName = "Toast"; - userEmail = "toast003@tutamail.com"; - delta = { - enable = true; - options = { - syntax-theme = "catppuccin-mocha"; - features = "catppuccin-mocha"; - }; - }; - includes = [{ path = "${catppuccinDelta}/themes/mocha.gitconfig"; }]; - extraConfig = { - init.defaultBranch = "main"; - diff.colorMoved = "default"; - commit.verbose = "true"; - }; - }; - }; + config, + pkgs, + ... +}: let + catppuccinDelta = pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "delta"; + rev = "main"; + hash = "sha256-0QQLkfLBVuB2re6tjtPNuOQZNK0MDBAIFgNGHZM8afs="; + }; +in { + home-manager.users.toast = { + programs.git = { + enable = true; + userName = "Toast"; + userEmail = "toast003@tutamail.com"; + delta = { + enable = true; + options = { + syntax-theme = "catppuccin-mocha"; + features = "catppuccin-mocha"; + }; + }; + includes = [{path = "${catppuccinDelta}/themes/mocha.gitconfig";}]; + extraConfig = { + init.defaultBranch = "main"; + diff.colorMoved = "default"; + commit.verbose = "true"; + }; + }; + }; } - diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index 78f09da..70fa320 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -1,6 +1,4 @@ -{ pkgs, ... }: - -{ +{pkgs, ...}: { home-manager.users.toast = { programs.helix = { enable = true; @@ -9,7 +7,7 @@ nixpkgs-fmt nil ]; - settings = { + settings = { theme = "catppuccin_mocha"; editor = { mouse = true; diff --git a/roles/common/programs/htop.nix b/roles/common/programs/htop.nix index 4eb7fbe..27c0ea1 100755 --- a/roles/common/programs/htop.nix +++ b/roles/common/programs/htop.nix @@ -1,15 +1,13 @@ -{ config, ... }: - -{ - programs.htop = { - enable = true; - settings = { - tree_view = 1; - highlight_base_name = 1; - show_program_path = 0; - show_cpu_frequency = 1; - show_cpu_temperature = 1; - hide_userland_threads = 1; - }; - }; +{config, ...}: { + programs.htop = { + enable = true; + settings = { + tree_view = 1; + highlight_base_name = 1; + show_program_path = 0; + show_cpu_frequency = 1; + show_cpu_temperature = 1; + hide_userland_threads = 1; + }; + }; } diff --git a/roles/common/programs/micro.nix b/roles/common/programs/micro.nix index e92646b..ab14d1d 100644 --- a/roles/common/programs/micro.nix +++ b/roles/common/programs/micro.nix @@ -1,17 +1,22 @@ -{ config, pkgs, ... }: - { - home-manager = { - users.toast = { config, pkgs, ... }: - { - programs.micro = { - enable = true; - settings = { - clipboard = "internal"; - indentchar = "|"; - softwrap = true; - }; - }; - }; - }; + config, + pkgs, + ... +}: { + home-manager = { + users.toast = { + config, + pkgs, + ... + }: { + programs.micro = { + enable = true; + settings = { + clipboard = "internal"; + indentchar = "|"; + softwrap = true; + }; + }; + }; + }; } diff --git a/roles/common/programs/nix-index.nix b/roles/common/programs/nix-index.nix index 492f770..cce8c55 100755 --- a/roles/common/programs/nix-index.nix +++ b/roles/common/programs/nix-index.nix @@ -1,15 +1,15 @@ -{ config, ... }: - -{ - /* environment.systemPackages = [ pkgs.nix-index ]; - programs.bash.interactiveShellInit = '' -source ${pkgs.nix-index}/etc/profile.d/command-not-found.sh - ''; */ - programs.nix-index = { - enable = true; - enableBashIntegration = true; - # I don't use zsh or fish (yet) - enableZshIntegration = false; - enableFishIntegration = false; - }; +{config, ...}: { + /* + environment.systemPackages = [ pkgs.nix-index ]; + programs.bash.interactiveShellInit = '' + source ${pkgs.nix-index}/etc/profile.d/command-not-found.sh + ''; + */ + programs.nix-index = { + enable = true; + enableBashIntegration = true; + # I don't use zsh or fish (yet) + enableZshIntegration = false; + enableFishIntegration = false; + }; } diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index 41e4cc2..9444f9b 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -1,25 +1,34 @@ -{ config, systemPkgs, ... }: - { - nix = { - settings = { - auto-optimise-store = true; - experimental-features = "nix-command flakes"; - }; - optimise = { - automatic = true; - dates = [ "weekly" ]; - }; - registry = { - agenix = { - from = { id = "agenix"; type = "indirect"; }; - to = { owner = "ryantm"; repo = "agenix"; type = "github"; }; - }; - # Write the system's nixpkgs into the registry to avoid mixing nixpkgs versions - # https://dataswamp.org/~solene/2022-07-20-nixos-flakes-command-sync-with-system.html - system.flake = systemPkgs; - }; - # I removed this in the past since I thought that I didn't need it, but turns out comma does :) - nixPath = [ "nixpkgs=${systemPkgs}" ]; - }; + config, + systemPkgs, + ... +}: { + nix = { + settings = { + auto-optimise-store = true; + experimental-features = "nix-command flakes"; + }; + optimise = { + automatic = true; + dates = ["weekly"]; + }; + registry = { + agenix = { + from = { + id = "agenix"; + type = "indirect"; + }; + to = { + owner = "ryantm"; + repo = "agenix"; + type = "github"; + }; + }; + # Write the system's nixpkgs into the registry to avoid mixing nixpkgs versions + # https://dataswamp.org/~solene/2022-07-20-nixos-flakes-command-sync-with-system.html + system.flake = systemPkgs; + }; + # I removed this in the past since I thought that I didn't need it, but turns out comma does :) + nixPath = ["nixpkgs=${systemPkgs}"]; + }; } diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index 3a29736..8e60667 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -1,53 +1,52 @@ -{ pkgs, lib, ... }: - -with lib; -with builtins; - -let - catppuccinFlavour = "mocha"; - catppuccinStarship = pkgs.catppuccin + /starship/${catppuccinFlavour}.toml; - - presets = { - nerdFontSymbols = pkgs.fetchurl { - url = "https://starship.rs/presets/toml/nerd-font-symbols.toml"; - hash = "sha256-BVe5JMSIa3CoY2Wf9pvcF1EUtDVCWCLhW3IyKuwfHug="; - }; - }; - # -------------------------------- F U N C T I O N S -------------------------------- - - /* - Gonna be honest, I have no idea how this works, although it seems to work - Stolen from https://gist.github.com/pdalpra/daf339f59288201a6c8ba7dc84e9060e - */ - # Takes a list of attrSets and merges them - mergeAllAttrSets = attrsSets: - foldl' (recursiveUpdate) {} attrsSets; - - # Reads a TOML file and parses it - readTomlPreset = file: (fromTOML (readFile file)); - -in { - programs.starship = { - enable = true; - settings = mergeAllAttrSets [ - (readTomlPreset presets.nerdFontSymbols) - (readTomlPreset catppuccinStarship) - { - nix_shell = { - disabled = false; - heuristic = true; - }; - os = { - disabled = false; - }; - directory = { - disabled = false; - truncation_length = 6; - truncation_symbol = ".../"; - }; - palette = "catppuccin_${catppuccinFlavour}"; - } - ]; - }; + pkgs, + lib, + ... +}: +with lib; +with builtins; let + catppuccinFlavour = "mocha"; + catppuccinStarship = pkgs.catppuccin + /starship/${catppuccinFlavour}.toml; + + presets = { + nerdFontSymbols = pkgs.fetchurl { + url = "https://starship.rs/presets/toml/nerd-font-symbols.toml"; + hash = "sha256-BVe5JMSIa3CoY2Wf9pvcF1EUtDVCWCLhW3IyKuwfHug="; + }; + }; + # -------------------------------- F U N C T I O N S -------------------------------- + + /* + Gonna be honest, I have no idea how this works, although it seems to work + Stolen from https://gist.github.com/pdalpra/daf339f59288201a6c8ba7dc84e9060e + */ + # Takes a list of attrSets and merges them + mergeAllAttrSets = attrsSets: + foldl' recursiveUpdate {} attrsSets; + + # Reads a TOML file and parses it + readTomlPreset = file: (fromTOML (readFile file)); +in { + programs.starship = { + enable = true; + settings = mergeAllAttrSets [ + (readTomlPreset presets.nerdFontSymbols) + (readTomlPreset catppuccinStarship) + { + nix_shell = { + disabled = false; + heuristic = true; + }; + os = { + disabled = false; + }; + directory = { + disabled = false; + truncation_length = 6; + truncation_symbol = ".../"; + }; + palette = "catppuccin_${catppuccinFlavour}"; + } + ]; + }; } diff --git a/roles/common/services/avahi.nix b/roles/common/services/avahi.nix index ef9d747..5136f64 100755 --- a/roles/common/services/avahi.nix +++ b/roles/common/services/avahi.nix @@ -1,19 +1,23 @@ -{ config, ... }: -let - old = { - nssmdns = true; - }; - new = { - nssmdns4 = true; - }; -in -{ - /* - NixOS 24.05 changed the option for mnds to be able to turn on/off IPv6 - 23.11 doesn't support this, so I need to use the conditional to be able to - use the same config for both - */ - services.avahi = { - enable = true; - } // (if config.system.nixos.release == "23.11" then old else new); +{config, ...}: let + old = { + nssmdns = true; + }; + new = { + nssmdns4 = true; + }; +in { + /* + NixOS 24.05 changed the option for mnds to be able to turn on/off IPv6 + 23.11 doesn't support this, so I need to use the conditional to be able to + use the same config for both + */ + services.avahi = + { + enable = true; + } + // ( + if config.system.nixos.release == "23.11" + then old + else new + ); } diff --git a/roles/common/services/default.nix b/roles/common/services/default.nix index a045e1c..960410b 100644 --- a/roles/common/services/default.nix +++ b/roles/common/services/default.nix @@ -1,9 +1,7 @@ -{ ... }: - -{ - imports = [ - ./avahi.nix - ./tailscale.nix - ./syncthing.nix - ]; +{...}: { + imports = [ + ./avahi.nix + ./tailscale.nix + ./syncthing.nix + ]; } diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index 501b4e3..8d81a53 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -1,60 +1,60 @@ -{ config, flakeSelf, ... }: - -let - hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName; -in - { - # Get secrets - age.secrets = { - syncthingKey.file = hostSecrets + "/syncthingKey.age"; - syncthingCert.file = hostSecrets + "/syncthingCert.age"; - }; + config, + flakeSelf, + ... +}: let + hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName; +in { + # Get secrets + age.secrets = { + syncthingKey.file = hostSecrets + "/syncthingKey.age"; + syncthingCert.file = hostSecrets + "/syncthingCert.age"; + }; - services.syncthing = { - key = config.age.secrets.syncthingKey.path; - cert = config.age.secrets.syncthingCert.path; - overrideDevices = true; - overrideFolders = true; - openDefaultPorts = true; - settings = { - options = { - urAccepted = 3; - }; - # Set up devices and folders common to every device - devices = { - "phone" = { - name = "Xiaomi Redmi Note 10 Pro"; - id = "K7KNZ5V-XREUADL-CROQXPV-6AA4H65-2VUD34Z-VQWKJ6S-LWWW4EE-XPNEZQ6"; - }; - "pc" = { - name = "Archie"; - id = "NJPX754-64AQNP3-7GZFIRZ-W2EDRJQ-27ORWYM-X5YXEXQ-ERRTRTQ-BSYD4AY"; - }; - "steamdeck" = { - name = "Steam Deck"; - id = "DNFEGEA-PDEVW5A-O5VBVQK-IUXI7J5-MAHCQAG-2JLEFFM-DSXB6AS-TX6ZHAN"; - }; - "server" = { - name = "Everest"; - id = "2GXFZJZ-CF56ER2-SISBGOF-VNXJIG5-GQC6ECA-NHCHAPX-677RSJT-RI5POAZ"; - }; - "surface" = { - name = "Surface Go"; - id = "HTVSF3O-AHY3TNH-BLVSEGK-HRRSMHC-H5LJWVF-NDKGM6O-ATWZALC-YXNV2Q4"; - }; - "winmax2" = { - name = "Win Max 2"; - id = "X2NILRM-ADRBQ23-AFREAZA-62GVFDF-UVMPR4L-KGHMUNY-BJ2C3CQ-RBT43QS"; - }; - }; - folders = { - "passwords" = { - label = "KeePassXC Passwords"; - id = "rdyaq-ex659"; - devices = [ "phone" "pc" "steamdeck" "server" "surface" "winmax2"]; - }; - }; - }; - }; + services.syncthing = { + key = config.age.secrets.syncthingKey.path; + cert = config.age.secrets.syncthingCert.path; + overrideDevices = true; + overrideFolders = true; + openDefaultPorts = true; + settings = { + options = { + urAccepted = 3; + }; + # Set up devices and folders common to every device + devices = { + "phone" = { + name = "Xiaomi Redmi Note 10 Pro"; + id = "K7KNZ5V-XREUADL-CROQXPV-6AA4H65-2VUD34Z-VQWKJ6S-LWWW4EE-XPNEZQ6"; + }; + "pc" = { + name = "Archie"; + id = "NJPX754-64AQNP3-7GZFIRZ-W2EDRJQ-27ORWYM-X5YXEXQ-ERRTRTQ-BSYD4AY"; + }; + "steamdeck" = { + name = "Steam Deck"; + id = "DNFEGEA-PDEVW5A-O5VBVQK-IUXI7J5-MAHCQAG-2JLEFFM-DSXB6AS-TX6ZHAN"; + }; + "server" = { + name = "Everest"; + id = "2GXFZJZ-CF56ER2-SISBGOF-VNXJIG5-GQC6ECA-NHCHAPX-677RSJT-RI5POAZ"; + }; + "surface" = { + name = "Surface Go"; + id = "HTVSF3O-AHY3TNH-BLVSEGK-HRRSMHC-H5LJWVF-NDKGM6O-ATWZALC-YXNV2Q4"; + }; + "winmax2" = { + name = "Win Max 2"; + id = "X2NILRM-ADRBQ23-AFREAZA-62GVFDF-UVMPR4L-KGHMUNY-BJ2C3CQ-RBT43QS"; + }; + }; + folders = { + "passwords" = { + label = "KeePassXC Passwords"; + id = "rdyaq-ex659"; + devices = ["phone" "pc" "steamdeck" "server" "surface" "winmax2"]; + }; + }; + }; + }; } diff --git a/roles/common/services/tailscale.nix b/roles/common/services/tailscale.nix index 176bded..92080d1 100644 --- a/roles/common/services/tailscale.nix +++ b/roles/common/services/tailscale.nix @@ -1,12 +1,14 @@ -{ config, lib, ... }: - { - services.tailscale = { - enable = true; - useRoutingFeatures = lib.mkDefault "client"; - }; + config, + lib, + ... +}: { + services.tailscale = { + enable = true; + useRoutingFeatures = lib.mkDefault "client"; + }; - systemd.services.tailscaled.environment = { - TS_NO_LOGS_NO_SUPPORT = "true"; - }; + systemd.services.tailscaled.environment = { + TS_NO_LOGS_NO_SUPPORT = "true"; + }; } diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index ab3242a..c56559d 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -1,19 +1,21 @@ -{ config, pkgs, ... }: - { - # Enable scanning - hardware.sane = { - enable = true; - extraBackends = [ pkgs.sane-airscan ]; - }; - users.users.toast.extraGroups = [ "scanner" ]; + config, + pkgs, + ... +}: { + # Enable scanning + hardware.sane = { + enable = true; + extraBackends = [pkgs.sane-airscan]; + }; + users.users.toast.extraGroups = ["scanner"]; - services.xserver.enable = true; + services.xserver.enable = true; - # Set up fonts - fonts.packages = [ - ( pkgs.nerdfonts.override { fonts = [ "Hack" "JetBrainsMono" ]; } ) - ]; + # Set up fonts + fonts.packages = [ + (pkgs.nerdfonts.override {fonts = ["Hack" "JetBrainsMono"];}) + ]; - boot.plymouth.enable = true; + boot.plymouth.enable = true; } diff --git a/roles/desktop/default.nix b/roles/desktop/default.nix index 7933104..d8e1f2b 100644 --- a/roles/desktop/default.nix +++ b/roles/desktop/default.nix @@ -1,9 +1,7 @@ -{ ... }: - -{ - imports = [ - ./services - ./programs - ./configuration.nix - ]; +{...}: { + imports = [ + ./services + ./programs + ./configuration.nix + ]; } diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix index fe5bf8e..6a06ba2 100755 --- a/roles/desktop/programs/default.nix +++ b/roles/desktop/programs/default.nix @@ -1,14 +1,12 @@ -{ ... }: - -{ - imports = [ - ./discord.nix - ./firefox.nix - ./micro.nix - ./keepassxc.nix - ./jamesdsp.nix - ./vscode.nix - ./git.nix - ./ssh.nix - ]; +{...}: { + imports = [ + ./discord.nix + ./firefox.nix + ./micro.nix + ./keepassxc.nix + ./jamesdsp.nix + ./vscode.nix + ./git.nix + ./ssh.nix + ]; } diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index db431ab..71b3c07 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -1,41 +1,45 @@ -{ config, pkgs, lib, ... }: - - let - discordOverlay = self: super: { - discord = super.discord.override { - withOpenASAR = true; - withVencord = true; - }; - # Update some stuff while I wait for nixpkgs - /*vencord = super.vencord.overrideAttrs rec { - version = "522fdcd"; - src = pkgs.fetchFromGitHub { - owner = "Vendicated"; - repo = "Vencord"; - rev = "522fdcd"; - #rev = "v${version}"; - hash = "sha256-9G7FNL4pHaaLachzJmeAol0WpNUj533K2FNa7DH0eBM="; - }; - };*/ - }; - stock-discord = self: super: { - discord = super.discord.override { - withOpenASAR = false; - withVencord = false; - }; - }; - in { - # Sometimes discord breaks after updates, and launching it stock once fixes it - specialisation.stockDiscord.configuration = { - nixpkgs.overlays = lib.mkAfter [ stock-discord ]; - }; + config, + pkgs, + lib, + ... +}: let + discordOverlay = self: super: { + discord = super.discord.override { + withOpenASAR = true; + withVencord = true; + }; + # Update some stuff while I wait for nixpkgs + /* + vencord = super.vencord.overrideAttrs rec { + version = "522fdcd"; + src = pkgs.fetchFromGitHub { + owner = "Vendicated"; + repo = "Vencord"; + rev = "522fdcd"; + #rev = "v${version}"; + hash = "sha256-9G7FNL4pHaaLachzJmeAol0WpNUj533K2FNa7DH0eBM="; + }; + }; + */ + }; + stock-discord = self: super: { + discord = super.discord.override { + withOpenASAR = false; + withVencord = false; + }; + }; +in { + # Sometimes discord breaks after updates, and launching it stock once fixes it + specialisation.stockDiscord.configuration = { + nixpkgs.overlays = lib.mkAfter [stock-discord]; + }; - nixpkgs.overlays = [ discordOverlay ]; - home-manager.users.toast = { - home.packages = with pkgs; [ - discord - vesktop - ]; - }; + nixpkgs.overlays = [discordOverlay]; + home-manager.users.toast = { + home.packages = with pkgs; [ + discord + vesktop + ]; + }; } diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index 89e1e27..bb2e697 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -1,57 +1,59 @@ -{ config, lib, ... }: - { - # System wide firefox settings - programs.firefox = { - enable = true; - policies = { - "DisablePocket" = true; - "DisableTelemetry" = true; - # You need these for Spotify - "EncryptedMediaExtensions" = { "Enabled" = true; }; - "ExtensionSettings" = { - # TODO: Install extensions the NUR instead of from AMO - "uBlock0@raymondhill.net" = { - "installation_mode" = "force_installed"; - "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; - }; - # Decentraleyes - "jid1-BoFifL9Vbdl2zQ@jetpack" = { - "installation_mode" = "normal_installed"; - "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/decentraleyes/latest.xpi"; - }; - "jid1-MnnxcxisBPnSXQ@jetpack" = { - "installation_mode" = "normal_installed"; - "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/privacy-badger17/latest.xpi"; - }; - # Uninstall the kde plasma integration extension if KDE is not installed - "plasma-browser-integration@kde.org"."installation_mode" = lib.mkDefault "blocked"; - }; - "Preferences" = { - # Enable video hardware acceleration - "media.ffmpeg.vaapi.enabled" = { - "Value" = true; - "Status" = "default"; - }; - "dom.security.https_only_mode" = { - "Value" = true; - "Status" = "locked"; - }; - "general.smoothScroll.msdPhysics.enabled" = { - "Value" = true; - "Status" = "default"; - }; - }; - "PromptForDownloadLocation" = true; - # I use an external password manager, so the built in one just bothers me - "PasswordManagerEnabled" = false; - "Permissions" = { - "Autoplay" = { - "Allow" = [ "https://www.youtube.com" ]; - "Default" = "block-audio-video"; - }; - }; - "FirefoxHome" = { "SponsoredTopSites" = false; }; - }; - }; + config, + lib, + ... +}: { + # System wide firefox settings + programs.firefox = { + enable = true; + policies = { + "DisablePocket" = true; + "DisableTelemetry" = true; + # You need these for Spotify + "EncryptedMediaExtensions" = {"Enabled" = true;}; + "ExtensionSettings" = { + # TODO: Install extensions the NUR instead of from AMO + "uBlock0@raymondhill.net" = { + "installation_mode" = "force_installed"; + "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; + }; + # Decentraleyes + "jid1-BoFifL9Vbdl2zQ@jetpack" = { + "installation_mode" = "normal_installed"; + "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/decentraleyes/latest.xpi"; + }; + "jid1-MnnxcxisBPnSXQ@jetpack" = { + "installation_mode" = "normal_installed"; + "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/privacy-badger17/latest.xpi"; + }; + # Uninstall the kde plasma integration extension if KDE is not installed + "plasma-browser-integration@kde.org"."installation_mode" = lib.mkDefault "blocked"; + }; + "Preferences" = { + # Enable video hardware acceleration + "media.ffmpeg.vaapi.enabled" = { + "Value" = true; + "Status" = "default"; + }; + "dom.security.https_only_mode" = { + "Value" = true; + "Status" = "locked"; + }; + "general.smoothScroll.msdPhysics.enabled" = { + "Value" = true; + "Status" = "default"; + }; + }; + "PromptForDownloadLocation" = true; + # I use an external password manager, so the built in one just bothers me + "PasswordManagerEnabled" = false; + "Permissions" = { + "Autoplay" = { + "Allow" = ["https://www.youtube.com"]; + "Default" = "block-audio-video"; + }; + }; + "FirefoxHome" = {"SponsoredTopSites" = false;}; + }; + }; } diff --git a/roles/desktop/programs/git.nix b/roles/desktop/programs/git.nix index d630bdd..594c3e7 100644 --- a/roles/desktop/programs/git.nix +++ b/roles/desktop/programs/git.nix @@ -1,6 +1,8 @@ -{ pkgs, lib, ... }: - { + pkgs, + lib, + ... +}: { home-manager.users.toast = { programs.git = { package = pkgs.gitFull; @@ -11,6 +13,6 @@ }; }; - home.packages = [ pkgs.git-cola ]; + home.packages = [pkgs.git-cola]; }; } diff --git a/roles/desktop/programs/jamesdsp.nix b/roles/desktop/programs/jamesdsp.nix index 4316cb5..3f1aa35 100644 --- a/roles/desktop/programs/jamesdsp.nix +++ b/roles/desktop/programs/jamesdsp.nix @@ -1,5 +1,7 @@ -{ config, pkgs, ... }: - { - users.users.toast.packages = [ pkgs.jamesdsp ]; + config, + pkgs, + ... +}: { + users.users.toast.packages = [pkgs.jamesdsp]; } diff --git a/roles/desktop/programs/keepassxc.nix b/roles/desktop/programs/keepassxc.nix index 7b42daf..3eedb2b 100644 --- a/roles/desktop/programs/keepassxc.nix +++ b/roles/desktop/programs/keepassxc.nix @@ -1,63 +1,69 @@ -{ config, pkgs, lib, ... }: - -let - kpxcSettings = lib.generators.toINI {} { - General = { - # Not sure what changing this does, I'll leave it alone - ConfigVersion = 2; - MinimizeAfterUnlock = true; - AutoSaveAfterEveryChange = false; - }; - GUI = { - ApplicationTheme = "classic"; - MinimizeOnStartup = false; - MinimizeOnClose = true; - MinimizeToTray = true; - ShowTrayIcon = true; - # 0 is icons, 1 is text, 2 is text next to icons, 3 is text under icons, and 4 is follow style - ToolButtonStyle = 0; # Would choose 4 but it's too big for a small window - # monochrome-light, monochrome-dark or colorful - TrayIconAppearance = "monochrome-light"; - }; - Security = { - HideNotes = true; - IconDownloadFallback = true; - }; - SSHAgent.Enabled = true; - }; -in - { - home-manager = { - extraSpecialArgs = { kpxcSettings = kpxcSettings; }; - users.toast = { config, pkgs, kpxcSettings, ... }: { - # No module for KeePassXC config :( - home = { - packages = [ pkgs.keepassxc ]; - file = { - ".config/keepassxc/keepassxc.ini".text = kpxcSettings; - # For some reason the autostart .desktop is not the same as the regular one - ".config/autostart/org.keepassxc.KeePassXC.desktop".text = '' - [Desktop Entry] - Name=KeePassXC - GenericName=Password Manager - Exec=keepassxc - TryExec=keepassxc - Icon=keepassxc - StartupWMClass=keepassxc - StartupNotify=true - Terminal=false - Type=Application - Version=1.0 - Categories=Utility;Security;Qt; - MimeType=application/x-keepass2; - X-GNOME-Autostart-enabled=true - X-GNOME-Autostart-Delay=2 - X-KDE-autostart-after=panel - X-LXQt-Need-Tray=true - ''; - }; - }; - }; - }; + config, + pkgs, + lib, + ... +}: let + kpxcSettings = lib.generators.toINI {} { + General = { + # Not sure what changing this does, I'll leave it alone + ConfigVersion = 2; + MinimizeAfterUnlock = true; + AutoSaveAfterEveryChange = false; + }; + GUI = { + ApplicationTheme = "classic"; + MinimizeOnStartup = false; + MinimizeOnClose = true; + MinimizeToTray = true; + ShowTrayIcon = true; + # 0 is icons, 1 is text, 2 is text next to icons, 3 is text under icons, and 4 is follow style + ToolButtonStyle = 0; # Would choose 4 but it's too big for a small window + # monochrome-light, monochrome-dark or colorful + TrayIconAppearance = "monochrome-light"; + }; + Security = { + HideNotes = true; + IconDownloadFallback = true; + }; + SSHAgent.Enabled = true; + }; +in { + home-manager = { + extraSpecialArgs = {kpxcSettings = kpxcSettings;}; + users.toast = { + config, + pkgs, + kpxcSettings, + ... + }: { + # No module for KeePassXC config :( + home = { + packages = [pkgs.keepassxc]; + file = { + ".config/keepassxc/keepassxc.ini".text = kpxcSettings; + # For some reason the autostart .desktop is not the same as the regular one + ".config/autostart/org.keepassxc.KeePassXC.desktop".text = '' + [Desktop Entry] + Name=KeePassXC + GenericName=Password Manager + Exec=keepassxc + TryExec=keepassxc + Icon=keepassxc + StartupWMClass=keepassxc + StartupNotify=true + Terminal=false + Type=Application + Version=1.0 + Categories=Utility;Security;Qt; + MimeType=application/x-keepass2; + X-GNOME-Autostart-enabled=true + X-GNOME-Autostart-Delay=2 + X-KDE-autostart-after=panel + X-LXQt-Need-Tray=true + ''; + }; + }; + }; + }; } diff --git a/roles/desktop/programs/micro.nix b/roles/desktop/programs/micro.nix index a09e819..38fda68 100644 --- a/roles/desktop/programs/micro.nix +++ b/roles/desktop/programs/micro.nix @@ -1,21 +1,27 @@ -{ config, pkgs, lib, ... }: - { - home-manager = { - users.toast = { config, pkgs, ... }: - { - programs.micro = { - enable = true; - settings = { - # Use xclip/wl-clipboard for copying and pasting - clipboard = lib.mkForce "external"; - }; - }; - /* - On a kde wayland session micro uses xsel or xclip instead of wl-clipboard - which doesn't work, so I only install wl-clipboard here to make micro use it - */ - home.packages = with pkgs; [ wl-clipboard ]; - }; - }; + config, + pkgs, + lib, + ... +}: { + home-manager = { + users.toast = { + config, + pkgs, + ... + }: { + programs.micro = { + enable = true; + settings = { + # Use xclip/wl-clipboard for copying and pasting + clipboard = lib.mkForce "external"; + }; + }; + /* + On a kde wayland session micro uses xsel or xclip instead of wl-clipboard + which doesn't work, so I only install wl-clipboard here to make micro use it + */ + home.packages = with pkgs; [wl-clipboard]; + }; + }; } diff --git a/roles/desktop/programs/ssh.nix b/roles/desktop/programs/ssh.nix index b3f17f0..86f1b2d 100644 --- a/roles/desktop/programs/ssh.nix +++ b/roles/desktop/programs/ssh.nix @@ -1,6 +1,4 @@ -{ ... }: - -{ +{...}: { home-manager.users.toast = { programs.ssh = { enable = true; diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index d75c465..ba6fa43 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -1,40 +1,45 @@ -{ config, pkgs, flakeSelf, ... }: -let inputs = flakeSelf.inputs; in { - nixpkgs.overlays = [ inputs.catppuccin-vsc.overlays.default ]; - home-manager.users.toast = { - home.packages = with pkgs; [ - nixpkgs-fmt - ]; - programs.vscode = { - enable = true; - package = pkgs.vscodium; - mutableExtensionsDir = false; - extensions = with inputs.vscode-extensions.extensions.x86_64-linux.open-vsx; [ - jnoortheen.nix-ide - (pkgs.catppuccin-vsc.override { - workbenchMode = "flat"; - extraBordersEnabled = true; - }) - catppuccin.catppuccin-vsc-icons - waderyan.gitblame - ]; - userSettings = { - # VSCode doesn't like nested settings - # https://stackoverflow.com/questions/74134436/is-it-possible-to-express-settings-in-vs-codes-settings-json-where-each-dot-sep - # TODO: write a function that unnests settings - "workbench.colorTheme" = "Catppuccin Mocha"; - "workbench.iconTheme" = "catppuccin-mocha"; - "editor.fontFamily" = "JetBrainsMono Nerd Font"; - "editor.semanticHighlighting.enabled" = true; - "nix.enableLanguageServer" = true; - "nix.serverPath" = "${pkgs.nil}/bin/nil"; - "nix.serverSettings" = { - "nil"."formatting"."command" = [ "nixpkgs-fmt" ]; - }; - "terminal.integrated.minimumContrastRatio" = 1; - "window.titleBarStyle" = "custom"; - }; - }; - }; + config, + pkgs, + flakeSelf, + ... +}: let + inputs = flakeSelf.inputs; +in { + nixpkgs.overlays = [inputs.catppuccin-vsc.overlays.default]; + home-manager.users.toast = { + home.packages = with pkgs; [ + nixpkgs-fmt + ]; + programs.vscode = { + enable = true; + package = pkgs.vscodium; + mutableExtensionsDir = false; + extensions = with inputs.vscode-extensions.extensions.x86_64-linux.open-vsx; [ + jnoortheen.nix-ide + (pkgs.catppuccin-vsc.override { + workbenchMode = "flat"; + extraBordersEnabled = true; + }) + catppuccin.catppuccin-vsc-icons + waderyan.gitblame + ]; + userSettings = { + # VSCode doesn't like nested settings + # https://stackoverflow.com/questions/74134436/is-it-possible-to-express-settings-in-vs-codes-settings-json-where-each-dot-sep + # TODO: write a function that unnests settings + "workbench.colorTheme" = "Catppuccin Mocha"; + "workbench.iconTheme" = "catppuccin-mocha"; + "editor.fontFamily" = "JetBrainsMono Nerd Font"; + "editor.semanticHighlighting.enabled" = true; + "nix.enableLanguageServer" = true; + "nix.serverPath" = "${pkgs.nil}/bin/nil"; + "nix.serverSettings" = { + "nil"."formatting"."command" = ["nixpkgs-fmt"]; + }; + "terminal.integrated.minimumContrastRatio" = 1; + "window.titleBarStyle" = "custom"; + }; + }; + }; } diff --git a/roles/desktop/services/default.nix b/roles/desktop/services/default.nix index c746c38..f08cc3b 100644 --- a/roles/desktop/services/default.nix +++ b/roles/desktop/services/default.nix @@ -1,12 +1,10 @@ -{ ... }: - -{ - imports = [ - ./ssh-agent.nix - ./flatpak.nix - ./syncthing.nix - ./pipewire.nix - ./printing.nix - ./networkmanager.nix - ]; +{...}: { + imports = [ + ./ssh-agent.nix + ./flatpak.nix + ./syncthing.nix + ./pipewire.nix + ./printing.nix + ./networkmanager.nix + ]; } diff --git a/roles/desktop/services/flatpak.nix b/roles/desktop/services/flatpak.nix index 20903f8..775bf53 100644 --- a/roles/desktop/services/flatpak.nix +++ b/roles/desktop/services/flatpak.nix @@ -1,19 +1,22 @@ -{ config, pkgs, flakeSelf, ... }: - { - services.flatpak.enable = true; + config, + pkgs, + flakeSelf, + ... +}: { + services.flatpak.enable = true; - home-manager = { - sharedModules = [{ imports = [ flakeSelf.inputs.nix-flatpak.homeManagerModules.nix-flatpak ]; }]; - users.toast = { - services.flatpak = { - packages = [ "tv.plex.PlexDesktop" ]; - uninstallUnmanagedPackages = true; - update.auto = { - enable = true; - onCalendar = "weekly"; - }; - }; - }; - }; + home-manager = { + sharedModules = [{imports = [flakeSelf.inputs.nix-flatpak.homeManagerModules.nix-flatpak];}]; + users.toast = { + services.flatpak = { + packages = ["tv.plex.PlexDesktop"]; + uninstallUnmanagedPackages = true; + update.auto = { + enable = true; + onCalendar = "weekly"; + }; + }; + }; + }; } diff --git a/roles/desktop/services/networkmanager.nix b/roles/desktop/services/networkmanager.nix index 7a64922..d56c81b 100644 --- a/roles/desktop/services/networkmanager.nix +++ b/roles/desktop/services/networkmanager.nix @@ -1,10 +1,6 @@ -{ config, ... }: - -let +{config, ...}: let tailscaleName = config.services.tailscale.interfaceName; -in - -{ +in { networking.networkmanager = { enable = true; unmanaged = [ diff --git a/roles/desktop/services/pipewire.nix b/roles/desktop/services/pipewire.nix index d064adb..c25506f 100644 --- a/roles/desktop/services/pipewire.nix +++ b/roles/desktop/services/pipewire.nix @@ -1,11 +1,9 @@ -{ config, ... }: +{config, ...}: { + services.pipewire = { + enable = true; + pulse.enable = true; + }; -{ - services.pipewire = { - enable = true; - pulse.enable = true; - }; - - # This allows pipewire to get realtime priority, which (hopefully) gets rid of stutters - security.rtkit.enable = true; + # This allows pipewire to get realtime priority, which (hopefully) gets rid of stutters + security.rtkit.enable = true; } diff --git a/roles/desktop/services/printing.nix b/roles/desktop/services/printing.nix index f32c58f..faa6c14 100644 --- a/roles/desktop/services/printing.nix +++ b/roles/desktop/services/printing.nix @@ -1,9 +1,7 @@ -{ config, ... }: - -{ - services.printing = { - enable = true; - startWhenNeeded = true; - stateless = true; - }; +{config, ...}: { + services.printing = { + enable = true; + startWhenNeeded = true; + stateless = true; + }; } diff --git a/roles/desktop/services/ssh-agent.nix b/roles/desktop/services/ssh-agent.nix index 31b9f73..a2de598 100644 --- a/roles/desktop/services/ssh-agent.nix +++ b/roles/desktop/services/ssh-agent.nix @@ -1,21 +1,23 @@ -{ config, pkgs, ... }: - { - programs.ssh.startAgent = true; - /* - Home assistant added an option that does this - https://github.com/nix-community/home-manager/commit/2d9210f25ed18d5d4e11e6b886de4027c0c51a94 - but since I still need to fix home-manager's envvars not applying I'll stick to the NixOS one - */ - /* - TODO: fix SSH_AUTH_SOCK not being set in Plasma - Turns out the NixOS module also has issues :3 - The env is set but only in bash, not in the DE, so - keepass can't pick it up. For now I'll just set it manually - */ - home-manager.users.toast.xdg.configFile."plasma-workspace/env/ssh-agent.sh".text = '' - if [[ -z "$SSH_AUTH_SOCK" ]]; then - export SSH_AUTH_SOCK=$XDG_RUNTIME_DIR/ssh-agent - fi - ''; + config, + pkgs, + ... +}: { + programs.ssh.startAgent = true; + /* + Home assistant added an option that does this + https://github.com/nix-community/home-manager/commit/2d9210f25ed18d5d4e11e6b886de4027c0c51a94 + but since I still need to fix home-manager's envvars not applying I'll stick to the NixOS one + */ + /* + TODO: fix SSH_AUTH_SOCK not being set in Plasma + Turns out the NixOS module also has issues :3 + The env is set but only in bash, not in the DE, so + keepass can't pick it up. For now I'll just set it manually + */ + home-manager.users.toast.xdg.configFile."plasma-workspace/env/ssh-agent.sh".text = '' + if [[ -z "$SSH_AUTH_SOCK" ]]; then + export SSH_AUTH_SOCK=$XDG_RUNTIME_DIR/ssh-agent + fi + ''; } diff --git a/roles/desktop/services/syncthing.nix b/roles/desktop/services/syncthing.nix index 84dc962..ba2ca9f 100644 --- a/roles/desktop/services/syncthing.nix +++ b/roles/desktop/services/syncthing.nix @@ -1,25 +1,23 @@ -{ config, ... }: - -{ - services.syncthing = { - enable = true; - user = "toast"; - group = "users"; - dataDir = config.users.users.toast.home; - settings.folders."passwords".path = "~/Documents/Passwords"; - }; - # Allow regular users to stop syncthing - # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service - security.polkit.extraConfig = '' - polkit.addRule(function(action, subject) { - if ( - action.id == "org.freedesktop.systemd1.manage-units" && - action.lookup("unit") == "syncthing.service" && - subject.user == "${config.services.syncthing.user}" - ) - { - return polkit.Result.YES; - } - }) - ''; +{config, ...}: { + services.syncthing = { + enable = true; + user = "toast"; + group = "users"; + dataDir = config.users.users.toast.home; + settings.folders."passwords".path = "~/Documents/Passwords"; + }; + # Allow regular users to stop syncthing + # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if ( + action.id == "org.freedesktop.systemd1.manage-units" && + action.lookup("unit") == "syncthing.service" && + subject.user == "${config.services.syncthing.user}" + ) + { + return polkit.Result.YES; + } + }) + ''; } diff --git a/roles/gaming/default.nix b/roles/gaming/default.nix index cccac83..2d8f4ab 100644 --- a/roles/gaming/default.nix +++ b/roles/gaming/default.nix @@ -1,8 +1,6 @@ -{ ... }: - -{ - imports = [ - ./programs - ./services - ]; +{...}: { + imports = [ + ./programs + ./services + ]; } diff --git a/roles/gaming/programs/default.nix b/roles/gaming/programs/default.nix index 8e5776f..a81bba7 100755 --- a/roles/gaming/programs/default.nix +++ b/roles/gaming/programs/default.nix @@ -1,14 +1,16 @@ -{ config, pkgs, ... }: - { - imports = [ - ./steam.nix - ./mangohud.nix - ./rpcs3.nix - ./retroarch.nix - ]; - environment.systemPackages = with pkgs; [ - heroic - prismlauncher-qt5 - ]; + config, + pkgs, + ... +}: { + imports = [ + ./steam.nix + ./mangohud.nix + ./rpcs3.nix + ./retroarch.nix + ]; + environment.systemPackages = with pkgs; [ + heroic + prismlauncher-qt5 + ]; } diff --git a/roles/gaming/programs/mangohud.nix b/roles/gaming/programs/mangohud.nix index fe418d4..41db63d 100644 --- a/roles/gaming/programs/mangohud.nix +++ b/roles/gaming/programs/mangohud.nix @@ -1,16 +1,13 @@ -{ config, ... }: - -{ - home-manager.users.toast = { config, ... }: - { - programs.mangohud = { - enable = true; - # This only works for Vulkan, openGL programs still need the mangohud wrapper - enableSessionWide = true; - settings = { - preset = 4; - no_display = true; - }; - }; - }; +{config, ...}: { + home-manager.users.toast = {config, ...}: { + programs.mangohud = { + enable = true; + # This only works for Vulkan, openGL programs still need the mangohud wrapper + enableSessionWide = true; + settings = { + preset = 4; + no_display = true; + }; + }; + }; } diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index 5f47ca2..3088ab2 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -1,79 +1,79 @@ -{ pkgs, ... }: -let +{pkgs, ...}: let snes-roms = [ # ActRaiser - ( pkgs.fetchzip { + (pkgs.fetchzip { url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/ActRaiser%20%28USA%29.zip"; hash = "sha256-yxIL5Pqlp8xsx7wvNO1MlB8ffDjS0xpE+yrEfMj61As="; - } ) + }) # Kirby Super Star - ( pkgs.fetchzip { + (pkgs.fetchzip { url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/Kirby%20Super%20Star%20%28USA%29.zip"; hash = "sha256-NX5OjCthf4ZiAhamclRBRk8GiMjZX3JLeShm8sQdDfc="; - } ) + }) # Super Mario Kart - ( pkgs.fetchzip { + (pkgs.fetchzip { url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/Super%20Mario%20Kart%20%28USA%29.zip"; hash = "sha256-RLBxPBmBrXCuPdnWE07KamBNgGJ5IntQVUPeij+2HUI="; - } ) + }) ]; -in -{ +in { home-manager.users.toast = { home = { - packages = [( - pkgs.retroarch.override { - cores = with pkgs.libretro; [ - snes9x - ]; - settings = { - video_driver = "vulkan"; - video_fullscreen = "true"; - menu_swap_ok_cancel_buttons = "true"; - input_joypad_driver = "sdl2"; - # Enable touchscreen support - menu_pointer_enable = "true"; + packages = [ + ( + pkgs.retroarch.override { + cores = with pkgs.libretro; [ + snes9x + ]; + settings = { + video_driver = "vulkan"; + video_fullscreen = "true"; + menu_swap_ok_cancel_buttons = "true"; + input_joypad_driver = "sdl2"; + # Enable touchscreen support + menu_pointer_enable = "true"; - # Folder stuffs + # Folder stuffs - # System/BIOS files - system_directory = "~/.local/share/retroarch/system"; - # Downloads - core_assets_directory = "~/.local/share/retroarch/downloads"; - thumbnails_directory = "~/.local/share/retroarch/thumbnails"; - content_database_path = "~/.local/share/retroarch/database/rdb"; - cheat_database_path = "~/.local/share/retroarch/cheats"; - video_filter_dir = "~/.local/share/retroarch/filters/video"; - audio_filter_dir = "~/.local/share/retroarch/filters/audio"; - video_shader_dir = "~/.local/share/retroarch/shaders"; - recording_output_directory = "~/.local/share/retroarch/records"; - overlay_directory = "~/.local/share/retroarch/overlays"; - osk_overlay_directory = "~/.local/share/retroarch/overlays/keyboards"; - screenshot_directory = "~/.local/share/retroarch/screenshots"; - playlist_directory = "~/.local/share/retroarch/playlists"; - savefile_directory = "~/.local/share/retroarch/saves"; - savestate_directory = "~/.local/share/retroarch/states"; - log_dir = "~/.local/share/retroarch/logs"; + # System/BIOS files + system_directory = "~/.local/share/retroarch/system"; + # Downloads + core_assets_directory = "~/.local/share/retroarch/downloads"; + thumbnails_directory = "~/.local/share/retroarch/thumbnails"; + content_database_path = "~/.local/share/retroarch/database/rdb"; + cheat_database_path = "~/.local/share/retroarch/cheats"; + video_filter_dir = "~/.local/share/retroarch/filters/video"; + audio_filter_dir = "~/.local/share/retroarch/filters/audio"; + video_shader_dir = "~/.local/share/retroarch/shaders"; + recording_output_directory = "~/.local/share/retroarch/records"; + overlay_directory = "~/.local/share/retroarch/overlays"; + osk_overlay_directory = "~/.local/share/retroarch/overlays/keyboards"; + screenshot_directory = "~/.local/share/retroarch/screenshots"; + playlist_directory = "~/.local/share/retroarch/playlists"; + savefile_directory = "~/.local/share/retroarch/saves"; + savestate_directory = "~/.local/share/retroarch/states"; + log_dir = "~/.local/share/retroarch/logs"; - # By default settings has some things that this overrides, so I need to set them myself - libretro_info_path = "${pkgs.libretro-core-info}/share/retroarch/cores"; - joypad_autoconfig_dir = "${pkgs.retroarch-joypad-autoconfig}/share/libretro/autoconfig"; - assets_directory = "${pkgs.retroarch-assets}/share/retroarch/assets"; - }; - } - )]; + # By default settings has some things that this overrides, so I need to set them myself + libretro_info_path = "${pkgs.libretro-core-info}/share/retroarch/cores"; + joypad_autoconfig_dir = "${pkgs.retroarch-joypad-autoconfig}/share/libretro/autoconfig"; + assets_directory = "${pkgs.retroarch-assets}/share/retroarch/assets"; + }; + } + ) + ]; file."Games/Roms/SNES/" = { onChange = '' ${pkgs.retroarch}/bin/retroarch --scan "/home/toast/Games/Roms/SNES" ''; source = pkgs.symlinkJoin { name = "snes-roms"; - paths = [ snes-roms ]; + paths = [snes-roms]; }; }; }; # Retroarch is dumb since it doesn't generate some folders (but it does for others) - systemd.user.tmpfiles.rules = [ + systemd.user.tmpfiles.rules = [ "d /%h/.local/share/retroarch/playlists" "d /%h/.local/share/retroarch/saves" "d /%h/.local/share/retroarch/states" @@ -85,7 +85,7 @@ in "retroarch" = { label = "RetroArch"; id = "jxuou-2yjnu"; - devices = [ "steamdeck" "server" "pc" "winmax2" ]; + devices = ["steamdeck" "server" "pc" "winmax2"]; path = "~/.local/share/retroarch"; }; }; diff --git a/roles/gaming/programs/rpcs3.nix b/roles/gaming/programs/rpcs3.nix index 97d3279..bb7f908 100644 --- a/roles/gaming/programs/rpcs3.nix +++ b/roles/gaming/programs/rpcs3.nix @@ -1,20 +1,24 @@ -{ config, pkgs, ... }: - { - environment.systemPackages = with config; [ - nur.repos.ataraxiasjel.rpcs3 - ]; - # Compiling RPCS3 takes quite a while - nix.settings = { - substituters = [ "https://ataraxiadev-foss.cachix.org" ]; - trusted-public-keys = [ "ataraxiadev-foss.cachix.org-1:ws/jmPRUF5R8TkirnV1b525lP9F/uTBsz2KraV61058=" ]; - }; + config, + pkgs, + ... +}: { + environment.systemPackages = with config; [ + nur.repos.ataraxiasjel.rpcs3 + ]; + # Compiling RPCS3 takes quite a while + nix.settings = { + substituters = ["https://ataraxiadev-foss.cachix.org"]; + trusted-public-keys = ["ataraxiadev-foss.cachix.org-1:ws/jmPRUF5R8TkirnV1b525lP9F/uTBsz2KraV61058="]; + }; - # Increase the memory lock limit - security.pam.loginLimits = [{ - domain = "*"; - item = "memlock"; - type = "-"; # Applies to both hard and soft limits - value = "unlimited"; - }]; + # Increase the memory lock limit + security.pam.loginLimits = [ + { + domain = "*"; + item = "memlock"; + type = "-"; # Applies to both hard and soft limits + value = "unlimited"; + } + ]; } diff --git a/roles/gaming/programs/steam.nix b/roles/gaming/programs/steam.nix index 321633c..baf9b11 100644 --- a/roles/gaming/programs/steam.nix +++ b/roles/gaming/programs/steam.nix @@ -1,21 +1,26 @@ - { config, pkgs, ... }: - { - programs.steam = { - enable = true; - # Doubt that I'll use it, but I'll enable it anyways - remotePlay.openFirewall = true; + config, + pkgs, + ... +}: { + programs.steam = { + enable = true; + # Doubt that I'll use it, but I'll enable it anyways + remotePlay.openFirewall = true; - extraCompatPackages = with pkgs; [ - proton-ge-bin - ]; - }; + extraCompatPackages = with pkgs; [ + proton-ge-bin + ]; + }; - # Some linux native games (rise of the tomb raider) use alsa for sound - services.pipewire.alsa.enable = if config.services.pipewire.pulse.enable == true then true else false; + # Some linux native games (rise of the tomb raider) use alsa for sound + services.pipewire.alsa.enable = + if config.services.pipewire.pulse.enable == true + then true + else false; - # Celeste mod manager - home-manager.users.toast.services.flatpak.packages = [ - "io.github.everestapi.Olympus" - ]; + # Celeste mod manager + home-manager.users.toast.services.flatpak.packages = [ + "io.github.everestapi.Olympus" + ]; } diff --git a/roles/gaming/services/default.nix b/roles/gaming/services/default.nix index 69a706a..24b067d 100644 --- a/roles/gaming/services/default.nix +++ b/roles/gaming/services/default.nix @@ -1,7 +1,5 @@ -{ ... }: - -{ - imports = [ - ./syncthing.nix - ]; +{...}: { + imports = [ + ./syncthing.nix + ]; } diff --git a/roles/gaming/services/syncthing.nix b/roles/gaming/services/syncthing.nix index ed786b6..c9749c6 100644 --- a/roles/gaming/services/syncthing.nix +++ b/roles/gaming/services/syncthing.nix @@ -1,21 +1,19 @@ -{ config, ... }: +{config, ...}: { + /* + This file will sync saves for games that don't have cloud saves + TODO: turn this into a module eventually + */ -{ - /* - This file will sync saves for games that don't have cloud saves - TODO: turn this into a module eventually - */ - - services.syncthing.settings.folders = { - "steam-201810" = { - label = "Wolfenstein The New Order Saves"; - id = "laxxf-t2wmy"; - devices = [ "steamdeck" "server" "pc" ]; - path = "~/.local/share/Steam/steamapps/compatdata/201810/pfx/drive_c/users/steamuser/Saved Games/MachineGames/Wolfenstein The New Order/"; - }; - }; - home-manager.users.toast.home.file."steam-201810-ignore" = { - target = ".local/share/Steam/steamapps/compatdata/201810/pfx/drive_c/users/steamuser/Saved Games/MachineGames/Wolfenstein The New Order/.stignore"; - text = "base/qconsole.log\nbase/wolfConfig.cfg"; - }; + services.syncthing.settings.folders = { + "steam-201810" = { + label = "Wolfenstein The New Order Saves"; + id = "laxxf-t2wmy"; + devices = ["steamdeck" "server" "pc"]; + path = "~/.local/share/Steam/steamapps/compatdata/201810/pfx/drive_c/users/steamuser/Saved Games/MachineGames/Wolfenstein The New Order/"; + }; + }; + home-manager.users.toast.home.file."steam-201810-ignore" = { + target = ".local/share/Steam/steamapps/compatdata/201810/pfx/drive_c/users/steamuser/Saved Games/MachineGames/Wolfenstein The New Order/.stignore"; + text = "base/qconsole.log\nbase/wolfConfig.cfg"; + }; } diff --git a/roles/kde/default.nix b/roles/kde/default.nix index 9aaf999..363920a 100755 --- a/roles/kde/default.nix +++ b/roles/kde/default.nix @@ -1,9 +1,7 @@ -{ ... }: - -{ - imports = [ - ./plasma.nix - ./sddm.nix - ./programs - ]; +{...}: { + imports = [ + ./plasma.nix + ./sddm.nix + ./programs + ]; } diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 45f154f..6cd8e09 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -1,158 +1,172 @@ -{ config, pkgs, lib, flakeSelf, ... }: - -let - # Set up the default kde options - balooExcludedDirs = lib.strings.intersperse "," [ - "$HOME/.cache/" - "$HOME/.config/" - "$HOME/.local/" - ]; - - baloofilerc = lib.generators.toINI {} { - General = { - # The [$e] part allows you to use environment variables - "exclude folders[$e]" = lib.strings.concatStrings balooExcludedDirs; - }; - }; - - # Make custom packages - breezeTint = pkgs.stdenv.mkDerivation { - name = "breeze-tint"; - src = "${pkgs.breeze-qt5}"; - patches = [ ./patches/BreezeTint.patch ]; - installPhase = '' - runHook preInstall - - mkdir -p $out/share/color-schemes/ - cp -r share/color-schemes/* $out/share/color-schemes/ - - runHook postInstall - ''; - }; - - # /etc/xdg is not read by plasma, so to change the default settings you need to put them in a package - plasmaDefaults = pkgs.stdenv.mkDerivation { - name = "toast-plasma-defaults"; - dontUnpack = true; - installPhase = '' - runHook preInstall - - set -x - mkdir -p $out/etc/xdg - echo '${baloofilerc}' > $out/etc/xdg/baloofilerc - - runHook postInstall - ''; - }; - -in - { - services.xserver = { - # Enable the Plasma 5 Desktop Environment - desktopManager.plasma5.enable = true; - displayManager.defaultSession = "plasmawayland"; - }; + config, + pkgs, + lib, + flakeSelf, + ... +}: let + # Set up the default kde options + balooExcludedDirs = lib.strings.intersperse "," [ + "$HOME/.cache/" + "$HOME/.config/" + "$HOME/.local/" + ]; - qt.enable = true; + baloofilerc = lib.generators.toINI {} { + General = { + # The [$e] part allows you to use environment variables + "exclude folders[$e]" = lib.strings.concatStrings balooExcludedDirs; + }; + }; - # GTK apps need dconf to grab the correct theme on Wayland - programs.dconf.enable = true; + # Make custom packages + breezeTint = pkgs.stdenv.mkDerivation { + name = "breeze-tint"; + src = "${pkgs.breeze-qt5}"; + patches = [./patches/BreezeTint.patch]; + installPhase = '' + runHook preInstall - # Install the patched Breeze color schemes as well as the plasma default configs - environment.systemPackages = [ breezeTint plasmaDefaults ]; + mkdir -p $out/share/color-schemes/ + cp -r share/color-schemes/* $out/share/color-schemes/ - # Plasma configs should be on all users - home-manager.sharedModules = [ - ( - { config, ... }: - let gtk2rc = "${config.xdg.configHome}/gtk-2.0/gtkrc"; in - { - gtk.gtk2.configLocation = gtk2rc; - # Kde has an annoying habit of overwriting the gtk2 config file - home.file."${gtk2rc}".force = true; - } - ) - { - imports = [ flakeSelf.inputs.plasma-manager.homeManagerModules.plasma-manager ]; - gtk = { - enable = true; - # Most apps are dark, so a white cursor is easier to spot - cursorTheme = { package = pkgs.breeze-qt5; name = "Breeze_Snow"; }; - iconTheme = { package = pkgs.breeze-icons; name = "breeze-dark"; }; - theme = { package = pkgs.breeze-gtk; name = "Breeze"; }; - # Gtk2 doesn't have a dark mode, so I just tell gtk 3 and 4 to use the dark variant - gtk3.extraConfig.gtk-application-prefer-dark-theme = true; - gtk4.extraConfig.gtk-application-prefer-dark-theme = true; - }; - home.packages = [( - pkgs.catppuccin-kde.override { - flavour = [ "mocha" ]; - accents = [ "mauve" ]; - winDecStyles = [ "classic" ]; - } - )]; - programs.plasma = { - enable = true; - overrideConfig = true; - # Delete config files that I fully configure here - overrideConfigFiles = [ - "plasmashellrc" - "plasma-org.kde.plasma.desktop-appletsrc" - ]; - workspace = { - clickItemTo = "select"; - cursorTheme = "Breeze_Snow"; - iconTheme = "breeze-dark"; - lookAndFeel = "Catppuccin-Mocha-Mauve"; - theme = "default"; - colorScheme = "CatppuccinMochaMauve"; - }; - kwin = { - titlebarButtons = { - left = [ "on-all-desktops" "keep-above-windows" ]; - right = [ "minimize" "maximize" "close" ]; - }; - }; - panels = [{ - location = "bottom"; - height = 44; - widgets = [ - { - name = "org.kde.plasma.kickoff"; - config.General.icon = "nix-snowflake-white"; - } - "org.kde.plasma.pager" - "org.kde.plasma.icontasks" - "org.kde.plasma.marginsseparator" - "org.kde.plasma.systemtray" - { - name = "org.kde.plasma.digitalclock"; - config.Appearance.showSeconds = "true"; - } - "org.kde.plasma.showdesktop" - ]; - }]; - shortcuts = { - "kwin" = { - "Switch One Desktop to the Left" = [ "Meta+Ctrl+Left" ]; - "Switch One Desktop to the Right" = [ "Meta+Ctrl+Right" ]; - }; - }; - configFile = { - "kwinrc" = { - "org\\.kde\\.kdecoration2"."BorderSize" = "None"; - "Desktops" = { - "Number" = 2; - "Rows" = 1; - }; - "TabBox"."LayoutName" = "thumbnail_grid"; - }; - "kdeglobals"."General"."AccentColor" = null; - "auroraerc"."CatppuccinMocha-Classic"."ButtonSize" = 0; - "plasmanotifyrc"."Notifications"."NormalAlwaysOnTop" = true; - }; - }; - } - ]; + runHook postInstall + ''; + }; + + # /etc/xdg is not read by plasma, so to change the default settings you need to put them in a package + plasmaDefaults = pkgs.stdenv.mkDerivation { + name = "toast-plasma-defaults"; + dontUnpack = true; + installPhase = '' + runHook preInstall + + set -x + mkdir -p $out/etc/xdg + echo '${baloofilerc}' > $out/etc/xdg/baloofilerc + + runHook postInstall + ''; + }; +in { + services.xserver = { + # Enable the Plasma 5 Desktop Environment + desktopManager.plasma5.enable = true; + displayManager.defaultSession = "plasmawayland"; + }; + + qt.enable = true; + + # GTK apps need dconf to grab the correct theme on Wayland + programs.dconf.enable = true; + + # Install the patched Breeze color schemes as well as the plasma default configs + environment.systemPackages = [breezeTint plasmaDefaults]; + + # Plasma configs should be on all users + home-manager.sharedModules = [ + ( + {config, ...}: let + gtk2rc = "${config.xdg.configHome}/gtk-2.0/gtkrc"; + in { + gtk.gtk2.configLocation = gtk2rc; + # Kde has an annoying habit of overwriting the gtk2 config file + home.file."${gtk2rc}".force = true; + } + ) + { + imports = [flakeSelf.inputs.plasma-manager.homeManagerModules.plasma-manager]; + gtk = { + enable = true; + # Most apps are dark, so a white cursor is easier to spot + cursorTheme = { + package = pkgs.breeze-qt5; + name = "Breeze_Snow"; + }; + iconTheme = { + package = pkgs.breeze-icons; + name = "breeze-dark"; + }; + theme = { + package = pkgs.breeze-gtk; + name = "Breeze"; + }; + # Gtk2 doesn't have a dark mode, so I just tell gtk 3 and 4 to use the dark variant + gtk3.extraConfig.gtk-application-prefer-dark-theme = true; + gtk4.extraConfig.gtk-application-prefer-dark-theme = true; + }; + home.packages = [ + ( + pkgs.catppuccin-kde.override { + flavour = ["mocha"]; + accents = ["mauve"]; + winDecStyles = ["classic"]; + } + ) + ]; + programs.plasma = { + enable = true; + overrideConfig = true; + # Delete config files that I fully configure here + overrideConfigFiles = [ + "plasmashellrc" + "plasma-org.kde.plasma.desktop-appletsrc" + ]; + workspace = { + clickItemTo = "select"; + cursorTheme = "Breeze_Snow"; + iconTheme = "breeze-dark"; + lookAndFeel = "Catppuccin-Mocha-Mauve"; + theme = "default"; + colorScheme = "CatppuccinMochaMauve"; + }; + kwin = { + titlebarButtons = { + left = ["on-all-desktops" "keep-above-windows"]; + right = ["minimize" "maximize" "close"]; + }; + }; + panels = [ + { + location = "bottom"; + height = 44; + widgets = [ + { + name = "org.kde.plasma.kickoff"; + config.General.icon = "nix-snowflake-white"; + } + "org.kde.plasma.pager" + "org.kde.plasma.icontasks" + "org.kde.plasma.marginsseparator" + "org.kde.plasma.systemtray" + { + name = "org.kde.plasma.digitalclock"; + config.Appearance.showSeconds = "true"; + } + "org.kde.plasma.showdesktop" + ]; + } + ]; + shortcuts = { + "kwin" = { + "Switch One Desktop to the Left" = ["Meta+Ctrl+Left"]; + "Switch One Desktop to the Right" = ["Meta+Ctrl+Right"]; + }; + }; + configFile = { + "kwinrc" = { + "org\\.kde\\.kdecoration2"."BorderSize" = "None"; + "Desktops" = { + "Number" = 2; + "Rows" = 1; + }; + "TabBox"."LayoutName" = "thumbnail_grid"; + }; + "kdeglobals"."General"."AccentColor" = null; + "auroraerc"."CatppuccinMocha-Classic"."ButtonSize" = 0; + "plasmanotifyrc"."Notifications"."NormalAlwaysOnTop" = true; + }; + }; + } + ]; } diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index b39dcfc..21f09ba 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -1,15 +1,13 @@ -{ config, ... }: +{config, ...}: { + imports = [ + ./kate.nix + ./firefox.nix + ./skanpage.nix + ./neochat.nix + ./konsole.nix + ./git.nix + ]; -{ - imports = [ - ./kate.nix - ./firefox.nix - ./skanpage.nix - ./neochat.nix - ./konsole.nix - ./git.nix - ]; - - # Enable the kde partition manager - programs.partition-manager.enable = true; + # Enable the kde partition manager + programs.partition-manager.enable = true; } diff --git a/roles/kde/programs/firefox.nix b/roles/kde/programs/firefox.nix index 9892650..14eab1a 100644 --- a/roles/kde/programs/firefox.nix +++ b/roles/kde/programs/firefox.nix @@ -1,32 +1,34 @@ -{ config, pkgs, ... }: - { - # KDE specific firefox settings - programs.firefox = { - policies = { - "ExtensionSettings" = { - # TODO: Install extensions the NUR instead of from AMO - "plasma-browser-integration@kde.org" = { - "installation_mode" = "normal_installed"; - "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/plasma-integration/latest.xpi"; - }; - }; - "Preferences" = { - # Make firefox use the kde file picker - "widget.use-xdg-desktop-portal.file-picker" = { - "Value" = 1; - "Status" = "default"; - }; - /* - https://wiki.archlinux.org/title/Firefox#KDE_integration tells me to enable this, - but strangely enough doing so makes firefox ask to be set as the default browser - every time you start it up, so I'll disable it - */ - "widget.use-xdg-desktop-portal.mime-handler" = { - "Value" = 0; - "Status" = "default"; - }; - }; - }; - }; + config, + pkgs, + ... +}: { + # KDE specific firefox settings + programs.firefox = { + policies = { + "ExtensionSettings" = { + # TODO: Install extensions the NUR instead of from AMO + "plasma-browser-integration@kde.org" = { + "installation_mode" = "normal_installed"; + "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/plasma-integration/latest.xpi"; + }; + }; + "Preferences" = { + # Make firefox use the kde file picker + "widget.use-xdg-desktop-portal.file-picker" = { + "Value" = 1; + "Status" = "default"; + }; + /* + https://wiki.archlinux.org/title/Firefox#KDE_integration tells me to enable this, + but strangely enough doing so makes firefox ask to be set as the default browser + every time you start it up, so I'll disable it + */ + "widget.use-xdg-desktop-portal.mime-handler" = { + "Value" = 0; + "Status" = "default"; + }; + }; + }; + }; } diff --git a/roles/kde/programs/git.nix b/roles/kde/programs/git.nix index 9d1c045..59a3924 100644 --- a/roles/kde/programs/git.nix +++ b/roles/kde/programs/git.nix @@ -1,6 +1,8 @@ -{ pkgs, lib, ... }: - { + pkgs, + lib, + ... +}: { home-manager.users.toast = { programs.git = { extraConfig = { diff --git a/roles/kde/programs/kate.nix b/roles/kde/programs/kate.nix index 9379ba5..9151416 100644 --- a/roles/kde/programs/kate.nix +++ b/roles/kde/programs/kate.nix @@ -1,10 +1,12 @@ -{ config, pkgs, ... }: - { - environment.systemPackages = [ pkgs.kate ]; + config, + pkgs, + ... +}: { + environment.systemPackages = [pkgs.kate]; - # Use kwrite to open text files, and kate if I'm developing stuff - xdg.mime.defaultApplications = { - "text/plain" = "org.kde.kwrite.desktop"; - }; + # Use kwrite to open text files, and kate if I'm developing stuff + xdg.mime.defaultApplications = { + "text/plain" = "org.kde.kwrite.desktop"; + }; } diff --git a/roles/kde/programs/konsole.nix b/roles/kde/programs/konsole.nix index 0dfdf57..709903a 100644 --- a/roles/kde/programs/konsole.nix +++ b/roles/kde/programs/konsole.nix @@ -1,17 +1,17 @@ -{ pkgs, ... }: -let - catppuccinKonsole = pkgs.fetchFromGitHub { - owner = "catppuccin"; - repo = "konsole"; - # Latest commit is 7d86b8a1e56e58f6b5649cdaac543a573ac194ca - rev = "main"; - hash = "sha256-EwSJMTxnaj2UlNJm1t6znnatfzgm1awIQQUF3VPfCTM="; - } + /Catppuccin-Mocha.colorscheme; -in -{ +{pkgs, ...}: let + catppuccinKonsole = + pkgs.fetchFromGitHub { + owner = "catppuccin"; + repo = "konsole"; + # Latest commit is 7d86b8a1e56e58f6b5649cdaac543a573ac194ca + rev = "main"; + hash = "sha256-EwSJMTxnaj2UlNJm1t6znnatfzgm1awIQQUF3VPfCTM="; + } + + /Catppuccin-Mocha.colorscheme; +in { home-manager.users.toast = { xdg.dataFile = { "konsole/Catppuccin-Mocha.colorscheme".source = catppuccinKonsole; }; }; -} \ No newline at end of file +} diff --git a/roles/kde/programs/neochat.nix b/roles/kde/programs/neochat.nix index f2009b3..0e666d4 100644 --- a/roles/kde/programs/neochat.nix +++ b/roles/kde/programs/neochat.nix @@ -1,7 +1,5 @@ -{ pkgs, ... }: - -{ +{pkgs, ...}: { home-manager.users.toast = { - home.packages = [ pkgs.neochat ]; + home.packages = [pkgs.neochat]; }; -} \ No newline at end of file +} diff --git a/roles/kde/programs/skanpage.nix b/roles/kde/programs/skanpage.nix index 508a7da..08ed4e4 100644 --- a/roles/kde/programs/skanpage.nix +++ b/roles/kde/programs/skanpage.nix @@ -1,9 +1,12 @@ -{ config, lib, pkgs, ... }: - { - # Only install skanpage if scanning is set up - config = lib.mkIf config.hardware.sane.enable { - environment.systemPackages = [ pkgs.skanpage ]; - }; -# environment.systemPackages = if config.hardware.sane.enable == true then [ pkgs.skanpage ] else []; + config, + lib, + pkgs, + ... +}: { + # Only install skanpage if scanning is set up + config = lib.mkIf config.hardware.sane.enable { + environment.systemPackages = [pkgs.skanpage]; + }; + # environment.systemPackages = if config.hardware.sane.enable == true then [ pkgs.skanpage ] else []; } diff --git a/roles/kde/sddm.nix b/roles/kde/sddm.nix index 3fedc02..8fd3b6a 100644 --- a/roles/kde/sddm.nix +++ b/roles/kde/sddm.nix @@ -1,56 +1,56 @@ -{ config, pkgs, ... }: - -let - currentTheme = config.services.xserver.displayManager.sddm.theme; - - sddm-sugar-candy = pkgs.stdenv.mkDerivation { - pname = "sddm-sugar-candy"; - version = "master"; - src = pkgs.fetchgit { - url = "https://framagit.org/MarianArlt/sddm-sugar-candy.git"; - hash = "sha256-XggFVsEXLYklrfy1ElkIp9fkTw4wvXbyVkaVCZq4ZLU="; - }; - installPhase = '' - runHook preInstall - - mkdir -p $out/share/sddm/themes/sugar-candy - cp -r /build/sddm-sugar-candy/* $out/share/sddm/themes/sugar-candy - - runHook postInstall - ''; - }; - - /* - Adds a theme.conf.user file to the current sddm theme's folder, - allowing you to change it's configuration without needing to - repackage it - */ - customcfg = pkgs.stdenv.mkDerivation { - name = "sddm-theme-customizer"; - dontUnpack = true; - # TODO: generate theme.conf.user outside of installPhase - installPhase = '' - runHook preInstall - - mkdir -p $out/share/sddm/themes/${currentTheme}/ - echo "[General] - background = ${pkgs.plasma-workspace-wallpapers}/share/wallpapers/MilkyWay/contents/images/5120x2880.png" >> $out/share/sddm/themes/${currentTheme}/theme.conf.user - - runHook postInstall - ''; - }; -in - { - # Enable SDDM. - services.xserver.displayManager.sddm = { - enable = true; - theme = "sugar-candy"; - settings = { - General = { Numlock = "on"; }; - Theme = { CursorTheme = "Breeze_Snow"; }; - }; - }; + config, + pkgs, + ... +}: let + currentTheme = config.services.xserver.displayManager.sddm.theme; - environment.systemPackages = [ sddm-sugar-candy customcfg ]; + sddm-sugar-candy = pkgs.stdenv.mkDerivation { + pname = "sddm-sugar-candy"; + version = "master"; + src = pkgs.fetchgit { + url = "https://framagit.org/MarianArlt/sddm-sugar-candy.git"; + hash = "sha256-XggFVsEXLYklrfy1ElkIp9fkTw4wvXbyVkaVCZq4ZLU="; + }; + installPhase = '' + runHook preInstall + + mkdir -p $out/share/sddm/themes/sugar-candy + cp -r /build/sddm-sugar-candy/* $out/share/sddm/themes/sugar-candy + + runHook postInstall + ''; + }; + + /* + Adds a theme.conf.user file to the current sddm theme's folder, + allowing you to change it's configuration without needing to + repackage it + */ + customcfg = pkgs.stdenv.mkDerivation { + name = "sddm-theme-customizer"; + dontUnpack = true; + # TODO: generate theme.conf.user outside of installPhase + installPhase = '' + runHook preInstall + + mkdir -p $out/share/sddm/themes/${currentTheme}/ + echo "[General] + background = ${pkgs.plasma-workspace-wallpapers}/share/wallpapers/MilkyWay/contents/images/5120x2880.png" >> $out/share/sddm/themes/${currentTheme}/theme.conf.user + + runHook postInstall + ''; + }; +in { + # Enable SDDM. + services.xserver.displayManager.sddm = { + enable = true; + theme = "sugar-candy"; + settings = { + General = {Numlock = "on";}; + Theme = {CursorTheme = "Breeze_Snow";}; + }; + }; + + environment.systemPackages = [sddm-sugar-candy customcfg]; } diff --git a/roles/school/default.nix b/roles/school/default.nix index cb3d38f..515d2d6 100644 --- a/roles/school/default.nix +++ b/roles/school/default.nix @@ -1,8 +1,6 @@ -{ ... }: - -{ - imports = [ - ./services - ./programs - ]; +{...}: { + imports = [ + ./services + ./programs + ]; } diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 6bc4de6..cef6e88 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -1,15 +1,17 @@ - { config, pkgs, ... }: - { - imports = [ - ./virtualbox.nix - ./idea.nix - ./vscode.nix - ./helix.nix - ./unity.nix - ]; - - environment.systemPackages = with pkgs; [ - dia - ]; + config, + pkgs, + ... +}: { + imports = [ + ./virtualbox.nix + ./idea.nix + ./vscode.nix + ./helix.nix + ./unity.nix + ]; + + environment.systemPackages = with pkgs; [ + dia + ]; } diff --git a/roles/school/programs/helix.nix b/roles/school/programs/helix.nix index f28b348..f26c5d0 100644 --- a/roles/school/programs/helix.nix +++ b/roles/school/programs/helix.nix @@ -1,7 +1,4 @@ - -{ pkgs, ... }: - -{ +{pkgs, ...}: { home-manager.users.toast = { programs.helix = { extraPackages = with pkgs; [ diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index ea3b5de..a13dd63 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -1,33 +1,35 @@ -{ config, pkgs, ... }: - -with pkgs; { - environment.systemPackages = with jetbrains; [ - idea-ultimate - ]; + config, + pkgs, + ... +}: +with pkgs; { + environment.systemPackages = with jetbrains; [ + idea-ultimate + ]; - home-manager.users.toast = { - # Install plugins - home.file = { - ".local/share/JetBrains/IntelliJIdea2023.3/catppuccin.jar".source = fetchurl { - url = "https://github.com/catppuccin/jetbrains/releases/download/v3.2.3/Catppuccin.Theme-3.2.3.jar"; - hash = "sha256-v5BZ2UKEBA/0DHKGwmprmuu0RcJCDsxzWmCdnX9aXpE="; - }; - ".local/share/JetBrains/IntelliJIdea2023.3/rainbow-brackets".source = fetchzip { - url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/latest/intellij-rainbow-brackets-2023.3.9-233.zip"; - hash = "sha256-faMDP6kU21WOHVjY5Aj4/Glqymo1iUCTuUJdHsq1N/s="; - }; - ".local/share/JetBrains/IntelliJIdea2023.3/catppuccin-icons.jar".source = fetchurl { - url = "https://github.com/catppuccin/jetbrains-icons/releases/download/v1.1.1/Catppuccin.Icons-1.1.1.jar"; - hash = "sha256-Bn0Yn0RlNmJQCSC0MJQrKjeERzfHhupWnyYm0YjXFwY="; - }; - }; + home-manager.users.toast = { + # Install plugins + home.file = { + ".local/share/JetBrains/IntelliJIdea2023.3/catppuccin.jar".source = fetchurl { + url = "https://github.com/catppuccin/jetbrains/releases/download/v3.2.3/Catppuccin.Theme-3.2.3.jar"; + hash = "sha256-v5BZ2UKEBA/0DHKGwmprmuu0RcJCDsxzWmCdnX9aXpE="; + }; + ".local/share/JetBrains/IntelliJIdea2023.3/rainbow-brackets".source = fetchzip { + url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/latest/intellij-rainbow-brackets-2023.3.9-233.zip"; + hash = "sha256-faMDP6kU21WOHVjY5Aj4/Glqymo1iUCTuUJdHsq1N/s="; + }; + ".local/share/JetBrains/IntelliJIdea2023.3/catppuccin-icons.jar".source = fetchurl { + url = "https://github.com/catppuccin/jetbrains-icons/releases/download/v1.1.1/Catppuccin.Icons-1.1.1.jar"; + hash = "sha256-Bn0Yn0RlNmJQCSC0MJQrKjeERzfHhupWnyYm0YjXFwY="; + }; + }; - /* - If you use programs.java.enable intellij picks up the jdk package directly, which is not ideal - This adds the jdks I want to use to a directory intellij expects jdks to be - */ - home.file.".jdks/jdk8".source = "${pkgs.jdk8}/lib/openjdk"; - home.file.".jdks/jdk17".source = "${pkgs.jdk17}/lib/openjdk"; - }; + /* + If you use programs.java.enable intellij picks up the jdk package directly, which is not ideal + This adds the jdks I want to use to a directory intellij expects jdks to be + */ + home.file.".jdks/jdk8".source = "${pkgs.jdk8}/lib/openjdk"; + home.file.".jdks/jdk17".source = "${pkgs.jdk17}/lib/openjdk"; + }; } diff --git a/roles/school/programs/unity.nix b/roles/school/programs/unity.nix index 0a5d1a3..88943e1 100644 --- a/roles/school/programs/unity.nix +++ b/roles/school/programs/unity.nix @@ -1,9 +1,9 @@ -{ pkgs, ... }: - -{ +{pkgs, ...}: { home-manager.users.toast = { - home.packages = [( - pkgs.unityhub - )]; + home.packages = [ + ( + pkgs.unityhub + ) + ]; }; } diff --git a/roles/school/programs/virtualbox.nix b/roles/school/programs/virtualbox.nix index 08f95b1..0e88135 100644 --- a/roles/school/programs/virtualbox.nix +++ b/roles/school/programs/virtualbox.nix @@ -1,15 +1,15 @@ -{ config, ... }: - -{ - # Need to use visual studio 2019 :( - virtualisation.virtualbox.host = { - enable = true; - }; - home-manager.sharedModules = [{ - systemd.user.tmpfiles.rules = [ - "d '/%h/VirtualBox VMs'" - "h '/%h/VirtualBox VMs' - - - - C " - ]; - }]; - users.users.toast.extraGroups = [ "vboxusers" ]; +{config, ...}: { + # Need to use visual studio 2019 :( + virtualisation.virtualbox.host = { + enable = true; + }; + home-manager.sharedModules = [ + { + systemd.user.tmpfiles.rules = [ + "d '/%h/VirtualBox VMs'" + "h '/%h/VirtualBox VMs' - - - - C " + ]; + } + ]; + users.users.toast.extraGroups = ["vboxusers"]; } diff --git a/roles/school/programs/vscode.nix b/roles/school/programs/vscode.nix index fa55360..331f5f5 100644 --- a/roles/school/programs/vscode.nix +++ b/roles/school/programs/vscode.nix @@ -1,18 +1,24 @@ -{ config, pkgs, lib, flakeSelf, ... }: -let inputs = flakeSelf.inputs; in { - home-manager.users.toast.programs.vscode = { - # The redhat xml extension needs an fhs environment - package = lib.mkForce pkgs.vscodium-fhs; - extensions = with inputs.vscode-extensions.extensions.x86_64-linux; [ - open-vsx.redhat.vscode-xml - open-vsx.tomoki1207.pdf - open-vsx.ms-vscode.live-server - open-vsx.ecmel.vscode-html-css - open-vsx.angular.ng-template - ]; - userSettings = { - redhat.telemetry.enabled = false; - }; - }; + config, + pkgs, + lib, + flakeSelf, + ... +}: let + inputs = flakeSelf.inputs; +in { + home-manager.users.toast.programs.vscode = { + # The redhat xml extension needs an fhs environment + package = lib.mkForce pkgs.vscodium-fhs; + extensions = with inputs.vscode-extensions.extensions.x86_64-linux; [ + open-vsx.redhat.vscode-xml + open-vsx.tomoki1207.pdf + open-vsx.ms-vscode.live-server + open-vsx.ecmel.vscode-html-css + open-vsx.angular.ng-template + ]; + userSettings = { + redhat.telemetry.enabled = false; + }; + }; } diff --git a/roles/school/services/default.nix b/roles/school/services/default.nix index 0fa68eb..350d7bd 100644 --- a/roles/school/services/default.nix +++ b/roles/school/services/default.nix @@ -1,10 +1,8 @@ -{ ... }: - -{ - imports = [ - ./syncthing.nix - ./mysql.nix - ./xampp.nix - ./mongodb.nix - ]; +{...}: { + imports = [ + ./syncthing.nix + ./mysql.nix + ./xampp.nix + ./mongodb.nix + ]; } diff --git a/roles/school/services/mongodb.nix b/roles/school/services/mongodb.nix index cb8cee1..75f7c7a 100644 --- a/roles/school/services/mongodb.nix +++ b/roles/school/services/mongodb.nix @@ -1,31 +1,34 @@ -{ config, pkgs, lib, ... }: - { - services.mongodb = { - enable = true; - package = pkgs.mongodb-4_4; - user = "toast"; - }; + config, + pkgs, + lib, + ... +}: { + services.mongodb = { + enable = true; + package = pkgs.mongodb-4_4; + user = "toast"; + }; - # Don't autostart MySQL - systemd.services.mongodb.wantedBy = lib.mkForce []; + # Don't autostart MySQL + systemd.services.mongodb.wantedBy = lib.mkForce []; - # Allow regular users to start/stop mongodb - # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service - security.polkit.extraConfig = '' - polkit.addRule(function(action, subject) { - if ( - action.id == "org.freedesktop.systemd1.manage-units" && - action.lookup("unit") == "mongodb.service" && - subject.user == "${config.services.mongodb.user}" - ) - { - return polkit.Result.YES; - } - }) - ''; + # Allow regular users to start/stop mongodb + # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if ( + action.id == "org.freedesktop.systemd1.manage-units" && + action.lookup("unit") == "mongodb.service" && + subject.user == "${config.services.mongodb.user}" + ) + { + return polkit.Result.YES; + } + }) + ''; - environment.systemPackages = with pkgs; [ - mongosh - ]; + environment.systemPackages = with pkgs; [ + mongosh + ]; } diff --git a/roles/school/services/mysql.nix b/roles/school/services/mysql.nix index c4e08e9..fbbd3f9 100644 --- a/roles/school/services/mysql.nix +++ b/roles/school/services/mysql.nix @@ -1,33 +1,36 @@ -{ config, pkgs, lib, ... }: - { - services.mysql = { - enable = true; - package = pkgs.mysql80; - user = "toast"; - group = "users"; - }; + config, + pkgs, + lib, + ... +}: { + services.mysql = { + enable = true; + package = pkgs.mysql80; + user = "toast"; + group = "users"; + }; - # Don't autostart MySQL - systemd.services.mysql.wantedBy = lib.mkForce []; + # Don't autostart MySQL + systemd.services.mysql.wantedBy = lib.mkForce []; - # Allow regular users to start/stop mysql - # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service - security.polkit.extraConfig = '' - polkit.addRule(function(action, subject) { - if ( - action.id == "org.freedesktop.systemd1.manage-units" && - action.lookup("unit") == "mysql.service" && - subject.user == "${config.services.mysql.user}" - ) - { - return polkit.Result.YES; - } - }) - ''; + # Allow regular users to start/stop mysql + # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if ( + action.id == "org.freedesktop.systemd1.manage-units" && + action.lookup("unit") == "mysql.service" && + subject.user == "${config.services.mysql.user}" + ) + { + return polkit.Result.YES; + } + }) + ''; - environment.systemPackages = with pkgs; [ - mysql-workbench - mycli - ]; + environment.systemPackages = with pkgs; [ + mysql-workbench + mycli + ]; } diff --git a/roles/school/services/syncthing.nix b/roles/school/services/syncthing.nix index a649b75..bb23f47 100644 --- a/roles/school/services/syncthing.nix +++ b/roles/school/services/syncthing.nix @@ -1,12 +1,10 @@ -{ config, ... }: - -{ - services.syncthing.settings.folders = { - "school-things" = { - label = "School things"; - id = "z6alc-nfoqr"; - devices = [ "steamdeck" "server" "pc" "winmax2" ]; - path = "~/Documents/School things"; - }; - }; +{config, ...}: { + services.syncthing.settings.folders = { + "school-things" = { + label = "School things"; + id = "z6alc-nfoqr"; + devices = ["steamdeck" "server" "pc" "winmax2"]; + path = "~/Documents/School things"; + }; + }; } diff --git a/roles/school/services/xampp.nix b/roles/school/services/xampp.nix index 99f65bf..22eed0d 100644 --- a/roles/school/services/xampp.nix +++ b/roles/school/services/xampp.nix @@ -1,36 +1,38 @@ -{ config, pkgs, ... }: -let - booDark = pkgs.fetchzip { - url = "https://github.com/adorade/boodark/releases/download/v1.1.1/boodark-v1.1.1.zip"; - hash = "sha256-GE/FtFlU6A4I9sRyjMhQIidGpDLD99Wzzngz3QI/rSo="; - }; -in { - # I tried setting up httpd + php in class but I just gave up - virtualisation.oci-containers = { - containers."xampp" = { - autoStart = false; - image = "tomsik68/xampp"; - #user = "${toString users.users.atfc.uid}:${toString users.groups.minecraft.gid}"; - volumes = [ - "xampp-mysql:/opt/lampp/var/mysql" - # No dark mode installed by default :( - "${booDark}:/opt/lampp/phpmyadmin/themes/booDark" - ]; - ports = [ "41061:22" "41062:80" ]; - }; - }; + config, + pkgs, + ... +}: let + booDark = pkgs.fetchzip { + url = "https://github.com/adorade/boodark/releases/download/v1.1.1/boodark-v1.1.1.zip"; + hash = "sha256-GE/FtFlU6A4I9sRyjMhQIidGpDLD99Wzzngz3QI/rSo="; + }; +in { + # I tried setting up httpd + php in class but I just gave up + virtualisation.oci-containers = { + containers."xampp" = { + autoStart = false; + image = "tomsik68/xampp"; + #user = "${toString users.users.atfc.uid}:${toString users.groups.minecraft.gid}"; + volumes = [ + "xampp-mysql:/opt/lampp/var/mysql" + # No dark mode installed by default :( + "${booDark}:/opt/lampp/phpmyadmin/themes/booDark" + ]; + ports = ["41061:22" "41062:80"]; + }; + }; - security.polkit.extraConfig = '' - polkit.addRule(function(action, subject) { - if ( - action.id == "org.freedesktop.systemd1.manage-units" && - action.lookup("unit") == "podman-xampp.service" && - subject.user == "toast" - ) - { - return polkit.Result.YES; - } - }) - ''; -} \ No newline at end of file + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if ( + action.id == "org.freedesktop.systemd1.manage-units" && + action.lookup("unit") == "podman-xampp.service" && + subject.user == "toast" + ) + { + return polkit.Result.YES; + } + }) + ''; +} diff --git a/roles/server/avahi.nix b/roles/server/avahi.nix index 9302bb7..bfbb229 100755 --- a/roles/server/avahi.nix +++ b/roles/server/avahi.nix @@ -1,11 +1,9 @@ -{ config, ... }: - -{ - services.avahi = { - openFirewall = true; - publish = { - enable = true; - userServices = true; - }; - }; -} \ No newline at end of file +{config, ...}: { + services.avahi = { + openFirewall = true; + publish = { + enable = true; + userServices = true; + }; + }; +} diff --git a/roles/server/beep.nix b/roles/server/beep.nix index b454726..1758887 100755 --- a/roles/server/beep.nix +++ b/roles/server/beep.nix @@ -1,16 +1,20 @@ -{ config, pkgs, ... }: - { - # Beep as soon as possible in the initrd - boot.initrd = { - kernelModules = [ "pcspkr" ]; - extraFiles.beep.source = pkgs.beep; - postDeviceCommands = "/beep/bin/beep -f 3000 -l 50 -r 2"; - }; - /*systemd.services.startupBeep = { - description = "Beep when system started booting"; - wantedBy = [ "sysinit.target" ]; - script = "${pkgs.beep}/bin/beep -f 3000 -l 50 -r 2"; - serviceConfig = { Type = "oneshot"; }; - };*/ + config, + pkgs, + ... +}: { + # Beep as soon as possible in the initrd + boot.initrd = { + kernelModules = ["pcspkr"]; + extraFiles.beep.source = pkgs.beep; + postDeviceCommands = "/beep/bin/beep -f 3000 -l 50 -r 2"; + }; + /* + systemd.services.startupBeep = { + description = "Beep when system started booting"; + wantedBy = [ "sysinit.target" ]; + script = "${pkgs.beep}/bin/beep -f 3000 -l 50 -r 2"; + serviceConfig = { Type = "oneshot"; }; + }; + */ } diff --git a/roles/server/ddclient.nix b/roles/server/ddclient.nix index 5a88f7f..d747a30 100755 --- a/roles/server/ddclient.nix +++ b/roles/server/ddclient.nix @@ -1,20 +1,20 @@ -{ config, flakeSelf, ... }: - -let - hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName; -in - { - # Set up secrets - age.secrets = { ddclient-passwd.file = hostSecrets + "/ddclient-password.age"; }; + config, + flakeSelf, + ... +}: let + hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName; +in { + # Set up secrets + age.secrets = {ddclient-passwd.file = hostSecrets + "/ddclient-password.age";}; - services.ddclient = { - enable = true; - use = "web, web=dynamicdns.park-your-domain.com/getip"; - protocol = "namecheap"; - server = "dynamicdns.park-your-domain.com"; - username = "toast003.xyz"; - passwordFile = config.age.secrets.ddclient-passwd.path; - domains = [ "@" ]; - }; + services.ddclient = { + enable = true; + use = "web, web=dynamicdns.park-your-domain.com/getip"; + protocol = "namecheap"; + server = "dynamicdns.park-your-domain.com"; + username = "toast003.xyz"; + passwordFile = config.age.secrets.ddclient-passwd.path; + domains = ["@"]; + }; } diff --git a/roles/server/default.nix b/roles/server/default.nix index a52b02b..aa16bef 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -1,20 +1,18 @@ -{ ... }: - -{ - imports = [ - ./avahi.nix - ./nfs.nix - ./samba.nix - ./ssh.nix - ./forgejo.nix - ./syncthing.nix - ./endlessh.nix - ./transmission.nix - ./ddclient.nix - ./beep.nix - ./tailscale.nix - ./traefik.nix - ./minecraft.nix - ./dns.nix - ]; +{...}: { + imports = [ + ./avahi.nix + ./nfs.nix + ./samba.nix + ./ssh.nix + ./forgejo.nix + ./syncthing.nix + ./endlessh.nix + ./transmission.nix + ./ddclient.nix + ./beep.nix + ./tailscale.nix + ./traefik.nix + ./minecraft.nix + ./dns.nix + ]; } diff --git a/roles/server/dns.nix b/roles/server/dns.nix index 600dfc1..22c91de 100644 --- a/roles/server/dns.nix +++ b/roles/server/dns.nix @@ -1,22 +1,20 @@ -{ ... }: - -{ +{...}: { services.dnsmasq = { enable = true; - + # Only using this for tailscale IPs, so better to let tailscale itself deal with it resolveLocalQueries = false; - + settings = { - listen-address = [ "100.73.96.48" ]; - + listen-address = ["100.73.96.48"]; + /* Dnsmasq tries to use the tailscale dns server, which is bad cause that points to dnsmasq From the little testing I have done it seems to not cause any issues, but better to be safe than sorry :P */ dns-loop-detect = true; - + # If this isn't set a cname that targets a host might return the wrong ip localise-queries = true; ## IPv6 is not a thing in Spain so I'm guaranteed to not use it @@ -29,11 +27,11 @@ # Add tailscale hosts networking.hosts = { - "100.73.96.48" = [ "everest" ]; - "100.113.139.93" = [ "archie" ]; - "100.85.48.85" = [ "steamdeck" ]; - "100.96.92.13" = [ "surfecego" ]; - "100.106.73.20" = [ "winmax2" ]; + "100.73.96.48" = ["everest"]; + "100.113.139.93" = ["archie"]; + "100.85.48.85" = ["steamdeck"]; + "100.96.92.13" = ["surfecego"]; + "100.106.73.20" = ["winmax2"]; }; # Dnsmasq conflicts with the resolved dns stub listener diff --git a/roles/server/endlessh.nix b/roles/server/endlessh.nix index 6646d1e..6495f26 100755 --- a/roles/server/endlessh.nix +++ b/roles/server/endlessh.nix @@ -1,10 +1,8 @@ -{ config, ... }: - -{ - # I prefer using the go implementation - services.endlessh-go = { - enable = true; - openFirewall = true; - extraOptions = [ "-alsologtostderr" "-v=1"] ; - }; -} \ No newline at end of file +{config, ...}: { + # I prefer using the go implementation + services.endlessh-go = { + enable = true; + openFirewall = true; + extraOptions = ["-alsologtostderr" "-v=1"]; + }; +} diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index 7075395..b8f04c9 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -1,6 +1,8 @@ -{ config, lib, ... }: - { + config, + lib, + ... +}: { specialisation.forgejoEnableRegistration.configuration.services.forgejo.settings.service.DISABLE_REGISTRATION = false; services.forgejo = { enable = true; @@ -22,7 +24,7 @@ }; # Add a cname for forgejo - services.dnsmasq.settings.cname = [ "git.everest.sable-pancake.ts.net,everest" ]; + services.dnsmasq.settings.cname = ["git.everest.sable-pancake.ts.net,everest"]; # Set up traefik as the reverse proxy for Forgejo services.traefik = { @@ -35,7 +37,7 @@ }; }; services.forgejo.loadBalancer.servers = [ - { url = "http://localhost:${toString config.services.forgejo.settings.server.HTTP_PORT}"; } + {url = "http://localhost:${toString config.services.forgejo.settings.server.HTTP_PORT}";} ]; }; }; diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix index 50a01cc..5743b39 100644 --- a/roles/server/minecraft.nix +++ b/roles/server/minecraft.nix @@ -1,115 +1,116 @@ -{ config, pkgs, flakeSelf, ... }: -let - atfc = builtins.fetchurl { - url = "https://www.curseforge.com/api/v1/mods/813246/files/4732590/download"; - sha256 = "0yl6ixmhfgqvcj3kfshpf8fy42vkkmjbn7d7yg86jx0ykiiq5f9x"; - }; - puffish_skills = builtins.fetchurl { - url = "https://www.curseforge.com/api/v1/mods/835091/files/4747353/download"; - sha256 = "1pwx8zqih019l12lrmllrjv2al0mjzwj4p5qmc4ps1g555jy8qil"; - }; - spark = builtins.fetchurl { - url = "https://www.curseforge.com/api/v1/mods/361579/files/4505375/download"; - sha256 = "1708lrx1nif0mvf7ambw8504j12wbn0vm69wsh21p8ylqpql1s4x"; - }; - - port = 25565; - users = config.users; -in { - users = { - groups.minecraft = { - members = [ "toast" ]; - gid = 987; - }; - users.atfc = { - isSystemUser = true; - uid = 988; - group = "minecraft"; - home = "/var/lib/minecraft/atfc"; - homeMode = "750"; - createHome = true; - }; - }; - - virtualisation.oci-containers = { - containers."minecraft-atfc" = { - autoStart = true; - image = "itzg/minecraft-server"; - #user = "${toString users.users.atfc.uid}:${toString users.groups.minecraft.gid}"; - environment = { - TZ = "Europe/Madrid"; - EULA = "true"; - TYPE = "forge"; - MEMORY = "2G"; - UID = toString users.users.atfc.uid; - GID = toString users.groups.minecraft.gid; - VERSION = "1.18.2"; - FORGE_VERSION = "40.2.10"; - GENERIC_PACK = "/modpack.zip"; - #USE_AIKAR_FLAGS = "true"; - - #STOP_DURATION = "70"; - STOP_SERVER_ANNOUNCE_DELAY = "25"; + config, + pkgs, + flakeSelf, + ... +}: let + atfc = builtins.fetchurl { + url = "https://www.curseforge.com/api/v1/mods/813246/files/4732590/download"; + sha256 = "0yl6ixmhfgqvcj3kfshpf8fy42vkkmjbn7d7yg86jx0ykiiq5f9x"; + }; + puffish_skills = builtins.fetchurl { + url = "https://www.curseforge.com/api/v1/mods/835091/files/4747353/download"; + sha256 = "1pwx8zqih019l12lrmllrjv2al0mjzwj4p5qmc4ps1g555jy8qil"; + }; + spark = builtins.fetchurl { + url = "https://www.curseforge.com/api/v1/mods/361579/files/4505375/download"; + sha256 = "1708lrx1nif0mvf7ambw8504j12wbn0vm69wsh21p8ylqpql1s4x"; + }; - # server.properties - MOTD = "Toast's modded minecraft server"; - DIFFICULTY = "hard"; - SNOOPER_ENABLED = "false"; - SPAWN_PROTECTION = "0"; - LEVEL_TYPE = "tfc:tng"; - BROADCAST_CONSOLE_TO_OPS = "true"; - BROADCAST_RCON_TO_OPS = "true"; - VIEW_DISTANCE = "16"; - MAX_PLAYERS = "4"; + port = 25565; + users = config.users; +in { + users = { + groups.minecraft = { + members = ["toast"]; + gid = 987; + }; + users.atfc = { + isSystemUser = true; + uid = 988; + group = "minecraft"; + home = "/var/lib/minecraft/atfc"; + homeMode = "750"; + createHome = true; + }; + }; - RCON_CMDS_LAST_DISCONNECT = "save-all"; - - OPS = "b3ca4afb-a3da-4a78-85c3-2292fd0787e2,0cb3d02a-1d1f-4d7f-b70c-bd53dc155cff"; - EXISTING_OPS_FILE = "synchronize"; + virtualisation.oci-containers = { + containers."minecraft-atfc" = { + autoStart = true; + image = "itzg/minecraft-server"; + #user = "${toString users.users.atfc.uid}:${toString users.groups.minecraft.gid}"; + environment = { + TZ = "Europe/Madrid"; + EULA = "true"; + TYPE = "forge"; + MEMORY = "2G"; + UID = toString users.users.atfc.uid; + GID = toString users.groups.minecraft.gid; + VERSION = "1.18.2"; + FORGE_VERSION = "40.2.10"; + GENERIC_PACK = "/modpack.zip"; + #USE_AIKAR_FLAGS = "true"; - WHITELIST = "b3ca4afb-a3da-4a78-85c3-2292fd0787e2,0cb3d02a-1d1f-4d7f-b70c-bd53dc155cff,03f080e8-ce8e-4b90-a312-734747ce7db0,ea88f690-cf46-4416-bfd5-6f6b165885f7"; - EXISTING_WHITELIST_FILE = "synchronize"; + #STOP_DURATION = "70"; + STOP_SERVER_ANNOUNCE_DELAY = "25"; - # Auto pause needs this - MAX_TICK_TIME = "-1"; - AUTOPAUSE_KNOCK_INTERFACE = "tap0"; - ENABLE_AUTOPAUSE = "true"; - }; - extraOptions = [ - "--network=slirp4netns:port_handler=slirp4netns" - "--cap-add=CAP_NET_RAW" - ]; - - volumes = [ - "${atfc}:/modpack.zip" - "${puffish_skills}:/mods/puffish_skills.jar" - "${spark}:/mods/spark.jar" - "${users.users.atfc.home}:/data" - #"/tmp/minecraft:/data" - ]; - ports = [ "25565:${toString port}" ]; - }; - }; - - networking.firewall.allowedTCPPorts = [ port ]; + # server.properties + MOTD = "Toast's modded minecraft server"; + DIFFICULTY = "hard"; + SNOOPER_ENABLED = "false"; + SPAWN_PROTECTION = "0"; + LEVEL_TYPE = "tfc:tng"; + BROADCAST_CONSOLE_TO_OPS = "true"; + BROADCAST_RCON_TO_OPS = "true"; + VIEW_DISTANCE = "16"; + MAX_PLAYERS = "4"; - # anything-sync-daemon config - systemd.packages = with pkgs; [ flakeSelf.packages.x86_64-linux.anything-sync-daemon ]; - environment.systemPackages = with pkgs; [ flakeSelf.packages.x86_64-linux.anything-sync-daemon ]; - fileSystems.minecraftTmpfs = { - device = "none"; - fsType = "tmpfs"; - mountPoint = "/mnt/minecraftTmpfs"; - options = [ "size=4G "]; - }; - environment.etc."asd.conf".text = -''WHATTOSYNC=('/var/lib/minecraft') -VOLATILE="${config.fileSystems.minecraftTmpfs.mountPoint}" -USE_OVERLAYFS="yes" ''; - systemd.services.asd = { - wantedBy = [ "podman-minecraft-atfc.service" ]; - before = [ "podman-minecraft-atfc.service" ]; - }; - + RCON_CMDS_LAST_DISCONNECT = "save-all"; + + OPS = "b3ca4afb-a3da-4a78-85c3-2292fd0787e2,0cb3d02a-1d1f-4d7f-b70c-bd53dc155cff"; + EXISTING_OPS_FILE = "synchronize"; + + WHITELIST = "b3ca4afb-a3da-4a78-85c3-2292fd0787e2,0cb3d02a-1d1f-4d7f-b70c-bd53dc155cff,03f080e8-ce8e-4b90-a312-734747ce7db0,ea88f690-cf46-4416-bfd5-6f6b165885f7"; + EXISTING_WHITELIST_FILE = "synchronize"; + + # Auto pause needs this + MAX_TICK_TIME = "-1"; + AUTOPAUSE_KNOCK_INTERFACE = "tap0"; + ENABLE_AUTOPAUSE = "true"; + }; + extraOptions = [ + "--network=slirp4netns:port_handler=slirp4netns" + "--cap-add=CAP_NET_RAW" + ]; + + volumes = [ + "${atfc}:/modpack.zip" + "${puffish_skills}:/mods/puffish_skills.jar" + "${spark}:/mods/spark.jar" + "${users.users.atfc.home}:/data" + #"/tmp/minecraft:/data" + ]; + ports = ["25565:${toString port}"]; + }; + }; + + networking.firewall.allowedTCPPorts = [port]; + + # anything-sync-daemon config + systemd.packages = with pkgs; [flakeSelf.packages.x86_64-linux.anything-sync-daemon]; + environment.systemPackages = with pkgs; [flakeSelf.packages.x86_64-linux.anything-sync-daemon]; + fileSystems.minecraftTmpfs = { + device = "none"; + fsType = "tmpfs"; + mountPoint = "/mnt/minecraftTmpfs"; + options = ["size=4G "]; + }; + environment.etc."asd.conf".text = '' WHATTOSYNC=('/var/lib/minecraft') + VOLATILE="${config.fileSystems.minecraftTmpfs.mountPoint}" + USE_OVERLAYFS="yes" ''; + systemd.services.asd = { + wantedBy = ["podman-minecraft-atfc.service"]; + before = ["podman-minecraft-atfc.service"]; + }; } diff --git a/roles/server/nfs.nix b/roles/server/nfs.nix index d91dd87..f87c4a7 100755 --- a/roles/server/nfs.nix +++ b/roles/server/nfs.nix @@ -1,36 +1,38 @@ -{ config, lib, ... }: - { - services = { - nfs.server = { - enable = true; - exports = '' - ${config.services.transmission.settings.download-dir} *.sable-pancake.ts.net(ro,all_squash,anonuid=${toString config.users.users.transmission.uid},anongid=${toString config.users.groups.transmission.gid}) - ''; - # NFSv3 uses random ports, so you need to make them static to be able to pass though the firewall - statdPort = 4000; - lockdPort = 4001; - mountdPort = 4002; - }; + config, + lib, + ... +}: { + services = { + nfs.server = { + enable = true; + exports = '' + ${config.services.transmission.settings.download-dir} *.sable-pancake.ts.net(ro,all_squash,anonuid=${toString config.users.users.transmission.uid},anongid=${toString config.users.groups.transmission.gid}) + ''; + # NFSv3 uses random ports, so you need to make them static to be able to pass though the firewall + statdPort = 4000; + lockdPort = 4001; + mountdPort = 4002; + }; - avahi.extraServiceFiles = { - Transmission-downloads-nfs = '' - - - - Transmission Downloads on %h (NFS) - - _nfs._tcp - 2049 - path=${config.services.transmission.settings.download-dir} - - -''; - }; - }; + avahi.extraServiceFiles = { + Transmission-downloads-nfs = '' + + + + Transmission Downloads on %h (NFS) + + _nfs._tcp + 2049 + path=${config.services.transmission.settings.download-dir} + + + ''; + }; + }; - networking.firewall = { - allowedTCPPorts = [ 111 2049 4000 40001 4002 ]; - allowedUDPPorts = [ 111 2049 4000 40001 4002 ]; - }; + networking.firewall = { + allowedTCPPorts = [111 2049 4000 40001 4002]; + allowedUDPPorts = [111 2049 4000 40001 4002]; + }; } diff --git a/roles/server/samba.nix b/roles/server/samba.nix index dcd25aa..bb7def4 100755 --- a/roles/server/samba.nix +++ b/roles/server/samba.nix @@ -1,37 +1,39 @@ -{ config, lib, ... }: - { - services = { - samba = { - enable = true; - openFirewall = true; - extraConfig = '' -map to guest = bad user -guest account = transmission -''; - shares = { - "Transmission downloads" = { - path = "${config.services.transmission.settings.download-dir}"; - "read only" = true; - public = true; - "guest only" = true; - browseable = true; - }; - }; - }; + config, + lib, + ... +}: { + services = { + samba = { + enable = true; + openFirewall = true; + extraConfig = '' + map to guest = bad user + guest account = transmission + ''; + shares = { + "Transmission downloads" = { + path = "${config.services.transmission.settings.download-dir}"; + "read only" = true; + public = true; + "guest only" = true; + browseable = true; + }; + }; + }; - avahi.extraServiceFiles = { - Transmission-downloads-smb = '' - - - - SMB shares on %h - - _smb._tcp - 139 - - -''; - }; - }; + avahi.extraServiceFiles = { + Transmission-downloads-smb = '' + + + + SMB shares on %h + + _smb._tcp + 139 + + + ''; + }; + }; } diff --git a/roles/server/ssh.nix b/roles/server/ssh.nix index 576cd3b..0275ca1 100755 --- a/roles/server/ssh.nix +++ b/roles/server/ssh.nix @@ -1,12 +1,10 @@ -{ config, ... }: - -{ - services.openssh = { - enable = true; - settings = { - PermitRootLogin = "no"; - PasswordAuthentication = false; - }; - startWhenNeeded = true; - }; +{config, ...}: { + services.openssh = { + enable = true; + settings = { + PermitRootLogin = "no"; + PasswordAuthentication = false; + }; + startWhenNeeded = true; + }; } diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 1d2b61f..b0e8f8c 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -1,57 +1,55 @@ -{ config, ... }: +{config, ...}: { + services.syncthing = { + enable = true; + key = config.age.secrets.syncthingKey.path; + cert = config.age.secrets.syncthingCert.path; + guiAddress = "0.0.0.0:8384"; + settings.folders = { + "passwords" = { + path = "${config.services.syncthing.dataDir}/passwords"; + }; + "school-things" = { + label = "School things"; + id = "z6alc-nfoqr"; + devices = ["steamdeck" "server" "pc" "winmax2"]; + path = "${config.services.syncthing.dataDir}/school-things"; + }; + "steam-201810" = { + label = "Wolfenstein The New Order Saves"; + id = "laxxf-t2wmy"; + devices = ["steamdeck" "server" "pc" "winmax2"]; + path = "${config.services.syncthing.dataDir}/steam-201810"; + }; + "retroarch" = { + label = "RetroArch"; + id = "jxuou-2yjnu"; + devices = ["steamdeck" "server" "pc" "winmax2"]; + path = "${config.services.syncthing.dataDir}/retroarch"; + }; + }; + }; + systemd.services.syncthing.serviceConfig = { + # Allow syncthing to change ownership of files + AmbientCapabilities = "CAP_CHOWN CAP_FOWNER"; + }; -{ - services.syncthing = { - enable = true; - key = config.age.secrets.syncthingKey.path; - cert = config.age.secrets.syncthingCert.path; - guiAddress = "0.0.0.0:8384"; - settings.folders = { - "passwords" = { - path = "${config.services.syncthing.dataDir}/passwords"; - }; - "school-things" = { - label = "School things"; - id = "z6alc-nfoqr"; - devices = [ "steamdeck" "server" "pc" "winmax2" ]; - path = "${config.services.syncthing.dataDir}/school-things"; - }; - "steam-201810" = { - label = "Wolfenstein The New Order Saves"; - id = "laxxf-t2wmy"; - devices = [ "steamdeck" "server" "pc" "winmax2" ]; - path = "${config.services.syncthing.dataDir}/steam-201810"; - }; - "retroarch"= { - label = "RetroArch"; - id = "jxuou-2yjnu"; - devices = [ "steamdeck" "server" "pc" "winmax2" ]; - path = "${config.services.syncthing.dataDir}/retroarch"; - }; - }; - }; - systemd.services.syncthing.serviceConfig = { - # Allow syncthing to change ownership of files - AmbientCapabilities = "CAP_CHOWN CAP_FOWNER"; - }; + # Add a cname for syncthing + services.dnsmasq.settings.cname = ["sync.everest.sable-pancake.ts.net,everest"]; - # Add a cname for syncthing - services.dnsmasq.settings.cname = [ "sync.everest.sable-pancake.ts.net,everest" ]; - - # Set up traefik as the reverse proxy for syncthing - services.traefik = { - dynamicConfigOptions = { - http = { - routers = { - syncthing-subdomain = { - rule = "Host(`sync.everest.sable-pancake.ts.net`)"; - service = "syncthing"; - }; - }; - services.syncthing.loadBalancer.servers = [ - { url = "http://localhost:8384"; } - ]; - }; - }; - }; + # Set up traefik as the reverse proxy for syncthing + services.traefik = { + dynamicConfigOptions = { + http = { + routers = { + syncthing-subdomain = { + rule = "Host(`sync.everest.sable-pancake.ts.net`)"; + service = "syncthing"; + }; + }; + services.syncthing.loadBalancer.servers = [ + {url = "http://localhost:8384";} + ]; + }; + }; + }; } diff --git a/roles/server/tailscale.nix b/roles/server/tailscale.nix index 36ba593..0f0fba4 100644 --- a/roles/server/tailscale.nix +++ b/roles/server/tailscale.nix @@ -1,8 +1,6 @@ -{ config, ... }: - -{ - services.tailscale = { - # This is needed for being an exit node - useRoutingFeatures = "server"; - }; +{config, ...}: { + services.tailscale = { + # This is needed for being an exit node + useRoutingFeatures = "server"; + }; } diff --git a/roles/server/traefik.nix b/roles/server/traefik.nix index d611211..5e44607 100644 --- a/roles/server/traefik.nix +++ b/roles/server/traefik.nix @@ -1,33 +1,31 @@ -{ config, ... }: +{config, ...}: { + specialisation.traefikEnableWebUI.configuration.services.traefik = { + staticConfigOptions = { + api = { + # Enable the web ui + insecure = true; + dashboard = true; + }; + }; + }; -{ - specialisation.traefikEnableWebUI.configuration.services.traefik = { - staticConfigOptions = { - api = { - # Enable the web ui - insecure = true; - dashboard = true; - }; - }; - }; - - services.traefik = { - enable = true; - staticConfigOptions = { - entryPoints = { - http = { address = "100.73.96.48:80"; }; - }; - }; - }; + services.traefik = { + enable = true; + staticConfigOptions = { + entryPoints = { + http = {address = "100.73.96.48:80";}; + }; + }; + }; - systemd = { - units.tailscaled.requiredBy = [ "traefik.service" ]; - # We have somewhat frequent power outages, and our ISP router takes - # ages to boot up. If I don't add a delay, traefik tries to bind to - # the tailscale interface before it's ready, making it crash too much - # in too little time - services.traefik.serviceConfig.RestartSec = 120; - }; + systemd = { + units.tailscaled.requiredBy = ["traefik.service"]; + # We have somewhat frequent power outages, and our ISP router takes + # ages to boot up. If I don't add a delay, traefik tries to bind to + # the tailscale interface before it's ready, making it crash too much + # in too little time + services.traefik.serviceConfig.RestartSec = 120; + }; - networking.firewall.allowedTCPPorts = [ 80 8080 ]; + networking.firewall.allowedTCPPorts = [80 8080]; } diff --git a/roles/server/transmission.nix b/roles/server/transmission.nix index ed17095..3e64aec 100755 --- a/roles/server/transmission.nix +++ b/roles/server/transmission.nix @@ -1,34 +1,32 @@ -{ config , ... }: +{config, ...}: { + services.transmission = { + enable = true; + openFirewall = true; + settings = { + incomplete-dir-enabled = false; + rpc-bind-address = "0.0.0.0"; + rpc-host-whitelist = "transmission.everest.sable-pancake.ts.net"; + rpc-whitelist = "127.0.0.1"; + }; + }; -{ - services.transmission = { - enable = true; - openFirewall = true; - settings = { - incomplete-dir-enabled = false; - rpc-bind-address = "0.0.0.0"; - rpc-host-whitelist = "transmission.everest.sable-pancake.ts.net"; - rpc-whitelist = "127.0.0.1"; - }; - }; + # Add a cname for transmission + services.dnsmasq.settings.cname = ["transmission.everest.sable-pancake.ts.net,everest"]; - # Add a cname for transmission - services.dnsmasq.settings.cname = [ "transmission.everest.sable-pancake.ts.net,everest" ]; - - # Set up traefik as the reverse proxy for transmission - services.traefik = { - dynamicConfigOptions = { - http = { - routers = { - transmission-subdomain = { - rule = "Host(`transmission.everest.sable-pancake.ts.net`)"; - service = "transmission"; - }; - }; - services.transmission.loadBalancer.servers = [ - { url = "http://localhost:${toString config.services.transmission.settings.rpc-port}"; } - ]; - }; - }; - }; + # Set up traefik as the reverse proxy for transmission + services.traefik = { + dynamicConfigOptions = { + http = { + routers = { + transmission-subdomain = { + rule = "Host(`transmission.everest.sable-pancake.ts.net`)"; + service = "transmission"; + }; + }; + services.transmission.loadBalancer.servers = [ + {url = "http://localhost:${toString config.services.transmission.settings.rpc-port}";} + ]; + }; + }; + }; } From 430bafb0b278ae4719f8a0e724cfe49429a188c5 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 20 Mar 2024 13:03:05 +0100 Subject: [PATCH 0513/1125] Run deadnix --- machines/Archie/hardware-configuration.nix | 1 - machines/Everest/configuration.nix | 7 +------ machines/Everest/hardware-configuration.nix | 1 - machines/SteamDeck/hardware-configuration.nix | 1 - machines/SurfaceGo/hardware-configuration.nix | 1 - roles/common/configuration.nix | 2 +- roles/common/programs/bash.nix | 4 ++-- roles/common/programs/comma.nix | 6 +----- roles/common/programs/command-not-found.nix | 2 +- roles/common/programs/default.nix | 6 +----- roles/common/programs/git.nix | 6 +----- roles/common/programs/htop.nix | 2 +- roles/common/programs/micro.nix | 12 ++---------- roles/common/programs/nix-index.nix | 2 +- roles/common/programs/nix.nix | 6 +----- roles/common/services/tailscale.nix | 6 +----- roles/desktop/configuration.nix | 6 +----- roles/desktop/programs/discord.nix | 5 ++--- roles/desktop/programs/firefox.nix | 6 +----- roles/desktop/programs/jamesdsp.nix | 6 +----- roles/desktop/programs/keepassxc.nix | 8 +------- roles/desktop/programs/micro.nix | 13 ++----------- roles/desktop/programs/vscode.nix | 1 - roles/desktop/services/flatpak.nix | 7 +------ roles/desktop/services/pipewire.nix | 2 +- roles/desktop/services/printing.nix | 2 +- roles/desktop/services/ssh-agent.nix | 6 +----- roles/gaming/programs/default.nix | 6 +----- roles/gaming/programs/mangohud.nix | 4 ++-- roles/gaming/programs/rpcs3.nix | 6 +----- roles/gaming/services/syncthing.nix | 2 +- roles/kde/programs/default.nix | 2 +- roles/kde/programs/firefox.nix | 6 +----- roles/kde/programs/git.nix | 6 +----- roles/kde/programs/kate.nix | 6 +----- roles/school/programs/default.nix | 6 +----- roles/school/programs/idea.nix | 6 +----- roles/school/programs/virtualbox.nix | 2 +- roles/school/programs/vscode.nix | 1 - roles/school/services/syncthing.nix | 2 +- roles/school/services/xampp.nix | 6 +----- roles/server/avahi.nix | 2 +- roles/server/beep.nix | 6 +----- roles/server/endlessh.nix | 2 +- roles/server/nfs.nix | 6 +----- roles/server/samba.nix | 6 +----- roles/server/ssh.nix | 2 +- roles/server/tailscale.nix | 2 +- roles/server/traefik.nix | 2 +- 49 files changed, 48 insertions(+), 168 deletions(-) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index ccd1840..bd32dc6 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -4,7 +4,6 @@ { config, lib, - pkgs, modulesPath, ... }: { diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index d7f8a46..c85e788 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -1,12 +1,7 @@ # Edit this configuration file to define what should be installed on # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running ‘nixos-help’). -{ - config, - pkgs, - lib, - ... -}: { +{lib, ...}: { # Bootloader. boot.loader.systemd-boot.enable = true; boot.loader.timeout = 5; diff --git a/machines/Everest/hardware-configuration.nix b/machines/Everest/hardware-configuration.nix index 007bc26..7a97c97 100755 --- a/machines/Everest/hardware-configuration.nix +++ b/machines/Everest/hardware-configuration.nix @@ -4,7 +4,6 @@ { config, lib, - pkgs, modulesPath, ... }: { diff --git a/machines/SteamDeck/hardware-configuration.nix b/machines/SteamDeck/hardware-configuration.nix index dfb3835..74f2cd4 100755 --- a/machines/SteamDeck/hardware-configuration.nix +++ b/machines/SteamDeck/hardware-configuration.nix @@ -4,7 +4,6 @@ { config, lib, - pkgs, modulesPath, ... }: let diff --git a/machines/SurfaceGo/hardware-configuration.nix b/machines/SurfaceGo/hardware-configuration.nix index 955cc05..81a4c56 100644 --- a/machines/SurfaceGo/hardware-configuration.nix +++ b/machines/SurfaceGo/hardware-configuration.nix @@ -4,7 +4,6 @@ { config, lib, - pkgs, ... }: { boot.initrd.availableKernelModules = ["xhci_pci" "nvme" "usbhid" "rtsx_pci_sdmmc"]; diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 210eb6f..53fa7ba 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -94,7 +94,7 @@ backupFileExtension = "hm-backup"; useGlobalPkgs = true; verbose = true; - users.toast = {config, ...}: { + users.toast = {...}: { home.stateVersion = "23.11"; xdg = { userDirs = { diff --git a/roles/common/programs/bash.nix b/roles/common/programs/bash.nix index bfcc625..66bfbea 100644 --- a/roles/common/programs/bash.nix +++ b/roles/common/programs/bash.nix @@ -1,5 +1,5 @@ -{config, ...}: { - home-manager.users.toast = {config, ...}: { +{...}: { + home-manager.users.toast = {...}: { programs.bash = { enable = true; enableVteIntegration = true; diff --git a/roles/common/programs/comma.nix b/roles/common/programs/comma.nix index e276b89..c04afcb 100644 --- a/roles/common/programs/comma.nix +++ b/roles/common/programs/comma.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: { +{...}: { # Use nix-index-database's comma wrapper programs.nix-index-database.comma.enable = true; # Run programs from the system's nixpkgs diff --git a/roles/common/programs/command-not-found.nix b/roles/common/programs/command-not-found.nix index 8dfa3d1..e3dcd3a 100755 --- a/roles/common/programs/command-not-found.nix +++ b/roles/common/programs/command-not-found.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { # The nixpkgs command-not-found script does not work with flakes, so I disable it programs.command-not-found.enable = false; } diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index 8a8df10..feff14d 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: { +{pkgs, ...}: { imports = [ ./htop.nix ./nix.nix diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index c9b673a..3b125df 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: let +{pkgs, ...}: let catppuccinDelta = pkgs.fetchFromGitHub { owner = "catppuccin"; repo = "delta"; diff --git a/roles/common/programs/htop.nix b/roles/common/programs/htop.nix index 27c0ea1..4d8bd79 100755 --- a/roles/common/programs/htop.nix +++ b/roles/common/programs/htop.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { programs.htop = { enable = true; settings = { diff --git a/roles/common/programs/micro.nix b/roles/common/programs/micro.nix index ab14d1d..75df151 100644 --- a/roles/common/programs/micro.nix +++ b/roles/common/programs/micro.nix @@ -1,14 +1,6 @@ -{ - config, - pkgs, - ... -}: { +{...}: { home-manager = { - users.toast = { - config, - pkgs, - ... - }: { + users.toast = {...}: { programs.micro = { enable = true; settings = { diff --git a/roles/common/programs/nix-index.nix b/roles/common/programs/nix-index.nix index cce8c55..c3a8177 100755 --- a/roles/common/programs/nix-index.nix +++ b/roles/common/programs/nix-index.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { /* environment.systemPackages = [ pkgs.nix-index ]; programs.bash.interactiveShellInit = '' diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index 9444f9b..1663df2 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -1,8 +1,4 @@ -{ - config, - systemPkgs, - ... -}: { +{systemPkgs, ...}: { nix = { settings = { auto-optimise-store = true; diff --git a/roles/common/services/tailscale.nix b/roles/common/services/tailscale.nix index 92080d1..a7c0338 100644 --- a/roles/common/services/tailscale.nix +++ b/roles/common/services/tailscale.nix @@ -1,8 +1,4 @@ -{ - config, - lib, - ... -}: { +{lib, ...}: { services.tailscale = { enable = true; useRoutingFeatures = lib.mkDefault "client"; diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index c56559d..26030cf 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: { +{pkgs, ...}: { # Enable scanning hardware.sane = { enable = true; diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 71b3c07..722d013 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -1,10 +1,9 @@ { - config, pkgs, lib, ... }: let - discordOverlay = self: super: { + discordOverlay = _self: super: { discord = super.discord.override { withOpenASAR = true; withVencord = true; @@ -23,7 +22,7 @@ }; */ }; - stock-discord = self: super: { + stock-discord = _self: super: { discord = super.discord.override { withOpenASAR = false; withVencord = false; diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index bb2e697..96b50a9 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -1,8 +1,4 @@ -{ - config, - lib, - ... -}: { +{lib, ...}: { # System wide firefox settings programs.firefox = { enable = true; diff --git a/roles/desktop/programs/jamesdsp.nix b/roles/desktop/programs/jamesdsp.nix index 3f1aa35..a9933bc 100644 --- a/roles/desktop/programs/jamesdsp.nix +++ b/roles/desktop/programs/jamesdsp.nix @@ -1,7 +1,3 @@ -{ - config, - pkgs, - ... -}: { +{pkgs, ...}: { users.users.toast.packages = [pkgs.jamesdsp]; } diff --git a/roles/desktop/programs/keepassxc.nix b/roles/desktop/programs/keepassxc.nix index 3eedb2b..ad2dbb2 100644 --- a/roles/desktop/programs/keepassxc.nix +++ b/roles/desktop/programs/keepassxc.nix @@ -1,9 +1,4 @@ -{ - config, - pkgs, - lib, - ... -}: let +{lib, ...}: let kpxcSettings = lib.generators.toINI {} { General = { # Not sure what changing this does, I'll leave it alone @@ -32,7 +27,6 @@ in { home-manager = { extraSpecialArgs = {kpxcSettings = kpxcSettings;}; users.toast = { - config, pkgs, kpxcSettings, ... diff --git a/roles/desktop/programs/micro.nix b/roles/desktop/programs/micro.nix index 38fda68..d934774 100644 --- a/roles/desktop/programs/micro.nix +++ b/roles/desktop/programs/micro.nix @@ -1,15 +1,6 @@ -{ - config, - pkgs, - lib, - ... -}: { +{lib, ...}: { home-manager = { - users.toast = { - config, - pkgs, - ... - }: { + users.toast = {pkgs, ...}: { programs.micro = { enable = true; settings = { diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix index ba6fa43..0147762 100644 --- a/roles/desktop/programs/vscode.nix +++ b/roles/desktop/programs/vscode.nix @@ -1,5 +1,4 @@ { - config, pkgs, flakeSelf, ... diff --git a/roles/desktop/services/flatpak.nix b/roles/desktop/services/flatpak.nix index 775bf53..57d5456 100644 --- a/roles/desktop/services/flatpak.nix +++ b/roles/desktop/services/flatpak.nix @@ -1,9 +1,4 @@ -{ - config, - pkgs, - flakeSelf, - ... -}: { +{flakeSelf, ...}: { services.flatpak.enable = true; home-manager = { diff --git a/roles/desktop/services/pipewire.nix b/roles/desktop/services/pipewire.nix index c25506f..f32365b 100644 --- a/roles/desktop/services/pipewire.nix +++ b/roles/desktop/services/pipewire.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { services.pipewire = { enable = true; pulse.enable = true; diff --git a/roles/desktop/services/printing.nix b/roles/desktop/services/printing.nix index faa6c14..49a590d 100644 --- a/roles/desktop/services/printing.nix +++ b/roles/desktop/services/printing.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { services.printing = { enable = true; startWhenNeeded = true; diff --git a/roles/desktop/services/ssh-agent.nix b/roles/desktop/services/ssh-agent.nix index a2de598..6f734f8 100644 --- a/roles/desktop/services/ssh-agent.nix +++ b/roles/desktop/services/ssh-agent.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: { +{...}: { programs.ssh.startAgent = true; /* Home assistant added an option that does this diff --git a/roles/gaming/programs/default.nix b/roles/gaming/programs/default.nix index a81bba7..445b615 100755 --- a/roles/gaming/programs/default.nix +++ b/roles/gaming/programs/default.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: { +{pkgs, ...}: { imports = [ ./steam.nix ./mangohud.nix diff --git a/roles/gaming/programs/mangohud.nix b/roles/gaming/programs/mangohud.nix index 41db63d..91e4675 100644 --- a/roles/gaming/programs/mangohud.nix +++ b/roles/gaming/programs/mangohud.nix @@ -1,5 +1,5 @@ -{config, ...}: { - home-manager.users.toast = {config, ...}: { +{...}: { + home-manager.users.toast = {...}: { programs.mangohud = { enable = true; # This only works for Vulkan, openGL programs still need the mangohud wrapper diff --git a/roles/gaming/programs/rpcs3.nix b/roles/gaming/programs/rpcs3.nix index bb7f908..ef1be51 100644 --- a/roles/gaming/programs/rpcs3.nix +++ b/roles/gaming/programs/rpcs3.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: { +{config, ...}: { environment.systemPackages = with config; [ nur.repos.ataraxiasjel.rpcs3 ]; diff --git a/roles/gaming/services/syncthing.nix b/roles/gaming/services/syncthing.nix index c9749c6..5a1daa0 100644 --- a/roles/gaming/services/syncthing.nix +++ b/roles/gaming/services/syncthing.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { /* This file will sync saves for games that don't have cloud saves TODO: turn this into a module eventually diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index 21f09ba..bbfc028 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { imports = [ ./kate.nix ./firefox.nix diff --git a/roles/kde/programs/firefox.nix b/roles/kde/programs/firefox.nix index 14eab1a..bbe1638 100644 --- a/roles/kde/programs/firefox.nix +++ b/roles/kde/programs/firefox.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: { +{...}: { # KDE specific firefox settings programs.firefox = { policies = { diff --git a/roles/kde/programs/git.nix b/roles/kde/programs/git.nix index 59a3924..e4e40d4 100644 --- a/roles/kde/programs/git.nix +++ b/roles/kde/programs/git.nix @@ -1,8 +1,4 @@ -{ - pkgs, - lib, - ... -}: { +{...}: { home-manager.users.toast = { programs.git = { extraConfig = { diff --git a/roles/kde/programs/kate.nix b/roles/kde/programs/kate.nix index 9151416..7f034fc 100644 --- a/roles/kde/programs/kate.nix +++ b/roles/kde/programs/kate.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: { +{pkgs, ...}: { environment.systemPackages = [pkgs.kate]; # Use kwrite to open text files, and kate if I'm developing stuff diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index cef6e88..2bbc214 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: { +{pkgs, ...}: { imports = [ ./virtualbox.nix ./idea.nix diff --git a/roles/school/programs/idea.nix b/roles/school/programs/idea.nix index a13dd63..7f818a5 100644 --- a/roles/school/programs/idea.nix +++ b/roles/school/programs/idea.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: +{pkgs, ...}: with pkgs; { environment.systemPackages = with jetbrains; [ idea-ultimate diff --git a/roles/school/programs/virtualbox.nix b/roles/school/programs/virtualbox.nix index 0e88135..58e7ff1 100644 --- a/roles/school/programs/virtualbox.nix +++ b/roles/school/programs/virtualbox.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { # Need to use visual studio 2019 :( virtualisation.virtualbox.host = { enable = true; diff --git a/roles/school/programs/vscode.nix b/roles/school/programs/vscode.nix index 331f5f5..e39e633 100644 --- a/roles/school/programs/vscode.nix +++ b/roles/school/programs/vscode.nix @@ -1,5 +1,4 @@ { - config, pkgs, lib, flakeSelf, diff --git a/roles/school/services/syncthing.nix b/roles/school/services/syncthing.nix index bb23f47..84cd213 100644 --- a/roles/school/services/syncthing.nix +++ b/roles/school/services/syncthing.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { services.syncthing.settings.folders = { "school-things" = { label = "School things"; diff --git a/roles/school/services/xampp.nix b/roles/school/services/xampp.nix index 22eed0d..26ee73b 100644 --- a/roles/school/services/xampp.nix +++ b/roles/school/services/xampp.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: let +{pkgs, ...}: let booDark = pkgs.fetchzip { url = "https://github.com/adorade/boodark/releases/download/v1.1.1/boodark-v1.1.1.zip"; hash = "sha256-GE/FtFlU6A4I9sRyjMhQIidGpDLD99Wzzngz3QI/rSo="; diff --git a/roles/server/avahi.nix b/roles/server/avahi.nix index bfbb229..b0d3798 100755 --- a/roles/server/avahi.nix +++ b/roles/server/avahi.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { services.avahi = { openFirewall = true; publish = { diff --git a/roles/server/beep.nix b/roles/server/beep.nix index 1758887..f8be721 100755 --- a/roles/server/beep.nix +++ b/roles/server/beep.nix @@ -1,8 +1,4 @@ -{ - config, - pkgs, - ... -}: { +{pkgs, ...}: { # Beep as soon as possible in the initrd boot.initrd = { kernelModules = ["pcspkr"]; diff --git a/roles/server/endlessh.nix b/roles/server/endlessh.nix index 6495f26..9650d7c 100755 --- a/roles/server/endlessh.nix +++ b/roles/server/endlessh.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { # I prefer using the go implementation services.endlessh-go = { enable = true; diff --git a/roles/server/nfs.nix b/roles/server/nfs.nix index f87c4a7..5122cc7 100755 --- a/roles/server/nfs.nix +++ b/roles/server/nfs.nix @@ -1,8 +1,4 @@ -{ - config, - lib, - ... -}: { +{config, ...}: { services = { nfs.server = { enable = true; diff --git a/roles/server/samba.nix b/roles/server/samba.nix index bb7def4..f4fd086 100755 --- a/roles/server/samba.nix +++ b/roles/server/samba.nix @@ -1,8 +1,4 @@ -{ - config, - lib, - ... -}: { +{config, ...}: { services = { samba = { enable = true; diff --git a/roles/server/ssh.nix b/roles/server/ssh.nix index 0275ca1..ede04a3 100755 --- a/roles/server/ssh.nix +++ b/roles/server/ssh.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { services.openssh = { enable = true; settings = { diff --git a/roles/server/tailscale.nix b/roles/server/tailscale.nix index 0f0fba4..d0c6aed 100644 --- a/roles/server/tailscale.nix +++ b/roles/server/tailscale.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { services.tailscale = { # This is needed for being an exit node useRoutingFeatures = "server"; diff --git a/roles/server/traefik.nix b/roles/server/traefik.nix index 5e44607..171f64d 100644 --- a/roles/server/traefik.nix +++ b/roles/server/traefik.nix @@ -1,4 +1,4 @@ -{config, ...}: { +{...}: { specialisation.traefikEnableWebUI.configuration.services.traefik = { staticConfigOptions = { api = { From 693410597aab78188d3060c21edcc6952d2950e6 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 22 Mar 2024 09:36:42 +0100 Subject: [PATCH 0514/1125] Desktop/ssh-agent: use home-manager module --- roles/desktop/services/ssh-agent.nix | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/roles/desktop/services/ssh-agent.nix b/roles/desktop/services/ssh-agent.nix index 6f734f8..56fea6b 100644 --- a/roles/desktop/services/ssh-agent.nix +++ b/roles/desktop/services/ssh-agent.nix @@ -1,19 +1,3 @@ {...}: { - programs.ssh.startAgent = true; - /* - Home assistant added an option that does this - https://github.com/nix-community/home-manager/commit/2d9210f25ed18d5d4e11e6b886de4027c0c51a94 - but since I still need to fix home-manager's envvars not applying I'll stick to the NixOS one - */ - /* - TODO: fix SSH_AUTH_SOCK not being set in Plasma - Turns out the NixOS module also has issues :3 - The env is set but only in bash, not in the DE, so - keepass can't pick it up. For now I'll just set it manually - */ - home-manager.users.toast.xdg.configFile."plasma-workspace/env/ssh-agent.sh".text = '' - if [[ -z "$SSH_AUTH_SOCK" ]]; then - export SSH_AUTH_SOCK=$XDG_RUNTIME_DIR/ssh-agent - fi - ''; + home-manager.users.toast.services.ssh-agent.enable = true; } From 233581eccba465833ef898e879510e8fff68c038 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 22 Mar 2024 10:00:09 +0100 Subject: [PATCH 0515/1125] Gaming/steam: remove proton and steam linux runtime desktop files --- roles/gaming/programs/steam.nix | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/roles/gaming/programs/steam.nix b/roles/gaming/programs/steam.nix index baf9b11..afbfb67 100644 --- a/roles/gaming/programs/steam.nix +++ b/roles/gaming/programs/steam.nix @@ -20,7 +20,13 @@ else false; # Celeste mod manager - home-manager.users.toast.services.flatpak.packages = [ - "io.github.everestapi.Olympus" - ]; + home-manager.users.toast = { + systemd.user.tmpfiles.rules = [ + "r '/%h/.local/share/applications/Steam Linux Runtime *.desktop'" + "r '/%h/.local/share/applications/Proton *.desktop'" + ]; + services.flatpak.packages = [ + "io.github.everestapi.Olympus" + ]; + }; } From a07ddd315c890ecdd26c8c2caaa3b1a63a90ff04 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 22 Mar 2024 10:30:38 +0100 Subject: [PATCH 0516/1125] Common: add atuin --- roles/common/programs/atuin.nix | 15 +++++++++++++++ roles/common/programs/default.nix | 1 + 2 files changed, 16 insertions(+) create mode 100644 roles/common/programs/atuin.nix diff --git a/roles/common/programs/atuin.nix b/roles/common/programs/atuin.nix new file mode 100644 index 0000000..ecfe0b9 --- /dev/null +++ b/roles/common/programs/atuin.nix @@ -0,0 +1,15 @@ +{...}: { + home-manager.users.toast.programs.atuin = { + enable = true; + settings = { + enter_accept = false; + workspaces = true; + stats = { + common_prefix = [ + "sudo" + "," + ]; + }; + }; + }; +} diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index feff14d..2f0dd22 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -13,6 +13,7 @@ ./btop.nix ./helix.nix ./direnv.nix + ./atuin.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ From d93115b35cd3ff690dcc9379a7af629072518efa Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 25 Mar 2024 09:39:52 +0100 Subject: [PATCH 0517/1125] School: rename idea.nix to jetbrains.nix --- roles/school/programs/default.nix | 2 +- roles/school/programs/{idea.nix => jetbrains.nix} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename roles/school/programs/{idea.nix => jetbrains.nix} (100%) diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 2bbc214..24452c0 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -1,7 +1,7 @@ {pkgs, ...}: { imports = [ ./virtualbox.nix - ./idea.nix + ./jetbrains.nix ./vscode.nix ./helix.nix ./unity.nix diff --git a/roles/school/programs/idea.nix b/roles/school/programs/jetbrains.nix similarity index 100% rename from roles/school/programs/idea.nix rename to roles/school/programs/jetbrains.nix From bfbf57b1801c6cb19b5cc290a06c7f914924d631 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 25 Mar 2024 10:10:30 +0100 Subject: [PATCH 0518/1125] School: install datagrip --- roles/school/programs/jetbrains.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/school/programs/jetbrains.nix b/roles/school/programs/jetbrains.nix index 7f818a5..a7f5528 100644 --- a/roles/school/programs/jetbrains.nix +++ b/roles/school/programs/jetbrains.nix @@ -2,6 +2,7 @@ with pkgs; { environment.systemPackages = with jetbrains; [ idea-ultimate + datagrip ]; home-manager.users.toast = { From 27ebce4fc6fd9c8c8b46e705aafd26a887cb1026 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 25 Mar 2024 10:19:32 +0100 Subject: [PATCH 0519/1125] School/jetbrains: do not install plugins I sync plugins now with the settings sync feature, so I don't need this --- roles/school/programs/jetbrains.nix | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/roles/school/programs/jetbrains.nix b/roles/school/programs/jetbrains.nix index a7f5528..ecf5c90 100644 --- a/roles/school/programs/jetbrains.nix +++ b/roles/school/programs/jetbrains.nix @@ -6,22 +6,6 @@ with pkgs; { ]; home-manager.users.toast = { - # Install plugins - home.file = { - ".local/share/JetBrains/IntelliJIdea2023.3/catppuccin.jar".source = fetchurl { - url = "https://github.com/catppuccin/jetbrains/releases/download/v3.2.3/Catppuccin.Theme-3.2.3.jar"; - hash = "sha256-v5BZ2UKEBA/0DHKGwmprmuu0RcJCDsxzWmCdnX9aXpE="; - }; - ".local/share/JetBrains/IntelliJIdea2023.3/rainbow-brackets".source = fetchzip { - url = "https://github.com/izhangzhihao/intellij-rainbow-brackets/releases/download/latest/intellij-rainbow-brackets-2023.3.9-233.zip"; - hash = "sha256-faMDP6kU21WOHVjY5Aj4/Glqymo1iUCTuUJdHsq1N/s="; - }; - ".local/share/JetBrains/IntelliJIdea2023.3/catppuccin-icons.jar".source = fetchurl { - url = "https://github.com/catppuccin/jetbrains-icons/releases/download/v1.1.1/Catppuccin.Icons-1.1.1.jar"; - hash = "sha256-Bn0Yn0RlNmJQCSC0MJQrKjeERzfHhupWnyYm0YjXFwY="; - }; - }; - /* If you use programs.java.enable intellij picks up the jdk package directly, which is not ideal This adds the jdks I want to use to a directory intellij expects jdks to be From fe701b6eecc9684b6c2b48c0e0af1094baaf3097 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 26 Mar 2024 10:09:44 +0100 Subject: [PATCH 0520/1125] Flake: update lock file --- flake.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/flake.lock b/flake.lock index cc3d7ac..303540d 100644 --- a/flake.lock +++ b/flake.lock @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1710820906, - "narHash": "sha256-2bNMraoRB4pdw/HtxgYTFeMhEekBZeQ53/a8xkqpbZc=", + "lastModified": 1711133180, + "narHash": "sha256-WJOahf+6115+GMl3wUfURu8fszuNeJLv9qAWFQl3Vmo=", "owner": "nix-community", "repo": "home-manager", - "rev": "022464438a85450abb23d93b91aa82e0addd71fb", + "rev": "1c2c5e4cabba4c43504ef0f8cc3f3dfa284e2dbb", "type": "github" }, "original": { @@ -125,11 +125,11 @@ ] }, "locked": { - "lastModified": 1706981411, - "narHash": "sha256-cLbLPTL1CDmETVh4p0nQtvoF+FSEjsnJTFpTxhXywhQ=", + "lastModified": 1710888565, + "narHash": "sha256-s9Hi4RHhc6yut4EcYD50sZWRDKsugBJHSbON8KFwoTw=", "owner": "nix-community", "repo": "home-manager", - "rev": "652fda4ca6dafeb090943422c34ae9145787af37", + "rev": "f33900124c23c4eca5831b9b5eb32ea5894375ce", "type": "github" }, "original": { @@ -147,11 +147,11 @@ ] }, "locked": { - "lastModified": 1710915975, - "narHash": "sha256-yOc0AD6ba7mbialNciZGzuSQLMo4CopoZGEfcUugA4I=", + "lastModified": 1711231487, + "narHash": "sha256-dRdFjStMA7GeuD/V4vzKblzuHwxMPgzEboRleVdZlUM=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "179d73fbe14c5bdb835d10bcc1c783466112bfa6", + "rev": "1171169117f63f1de9ef2ea36efd8dcf377c6d5a", "type": "github" }, "original": { @@ -255,11 +255,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1710783728, - "narHash": "sha256-eIsfu3c9JUBgm3cURSKTXLEI9Dlk1azo+MWKZVqrmkc=", + "lastModified": 1711352745, + "narHash": "sha256-luvqik+i3HTvCbXQZgB6uggvEcxI9uae0nmrgtXJ17U=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "1e679b9a9970780cd5d4dfe755a74a8f96d33388", + "rev": "9a763a7acc4cfbb8603bb0231fec3eda864f81c0", "type": "github" }, "original": { @@ -324,11 +324,11 @@ ] }, "locked": { - "lastModified": 1709982472, - "narHash": "sha256-cMPHIV7yWbve+nwiQDhVt7BBkxrGTLzSTAslv7u6HZo=", + "lastModified": 1711295162, + "narHash": "sha256-gPTTYKvdnmaLcgOSpqtKHIf8J60J3Z4jAqXTwluxxUk=", "owner": "pjones", "repo": "plasma-manager", - "rev": "26acf8f5880ae7d6e5de4ca953c8ad161b7903eb", + "rev": "8a032af55ed686ab21e60530080462a1438812b9", "type": "github" }, "original": { @@ -412,11 +412,11 @@ ] }, "locked": { - "lastModified": 1710897544, - "narHash": "sha256-3mPv91syU+Vqu4TPoOJR6dKBAjfOHZL44jPXdHZ0Les=", + "lastModified": 1711415893, + "narHash": "sha256-f7KK83bGkLf7QxEpkOH3B4sqnzBvr6qf3jeGgfKNteA=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "f2f5adbda31543a80667500769f20c6369038897", + "rev": "da36b726fedf0ae85c3fc1f634fd38ebe2f0d070", "type": "github" }, "original": { From 2e159d1359a8a644c77a318900e24e947c2a64ab Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 26 Mar 2024 10:09:55 +0100 Subject: [PATCH 0521/1125] Kde/plasma: update kwinrc setting We don't need to escape dots anymore --- roles/kde/plasma.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 6cd8e09..75b664c 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -155,7 +155,7 @@ in { }; configFile = { "kwinrc" = { - "org\\.kde\\.kdecoration2"."BorderSize" = "None"; + "org.kde.kdecoration2"."BorderSize" = "None"; "Desktops" = { "Number" = 2; "Rows" = 1; From eb6be432d658a628abe297ff7008ea1fac8556df Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Mar 2024 00:37:32 +0100 Subject: [PATCH 0522/1125] Machines/winmax2: change hardcoded scale settings to 2 --- machines/WinMax2/configuration.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index a5d20c3..74f44c2 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -72,7 +72,7 @@ services.xserver = { xkb.layout = lib.mkForce "us"; displayManager.sddm.settings = { - General.GreeterEnvironment = "QT_SCREEN_SCALE_FACTORS=1.75"; + General.GreeterEnvironment = "QT_SCREEN_SCALE_FACTORS=2"; }; }; @@ -107,7 +107,7 @@ # Enable CUPS to print documents. # services.printing.enable = true; environment.sessionVariables = { - STEAM_FORCE_DESKTOPUI_SCALING = "1.75"; + STEAM_FORCE_DESKTOPUI_SCALING = "2"; }; # Enable sound. From 60ded6e15312c062953a71c704f06968b0710056 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Mar 2024 01:42:45 +0100 Subject: [PATCH 0523/1125] Machines/WinMax2: use prerelease decky-loader --- machines/WinMax2/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 74f44c2..79ce4d6 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -92,6 +92,7 @@ }; decky-loader = { enable = true; + package = pkgs.decky-loader-prerelease; }; }; From 72270366300eb15d72bae0fba2a70a84046ab735 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Mar 2024 09:49:06 +0100 Subject: [PATCH 0524/1125] Flake: update plasma-manager --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 303540d..8de9a02 100644 --- a/flake.lock +++ b/flake.lock @@ -324,11 +324,11 @@ ] }, "locked": { - "lastModified": 1711295162, - "narHash": "sha256-gPTTYKvdnmaLcgOSpqtKHIf8J60J3Z4jAqXTwluxxUk=", + "lastModified": 1711527622, + "narHash": "sha256-UCTdFTa4tQuXHzsJUhqDuTyvA2Xu6fvMe+mGXdQhPrg=", "owner": "pjones", "repo": "plasma-manager", - "rev": "8a032af55ed686ab21e60530080462a1438812b9", + "rev": "fd4426851e1a4b1fe88abba78171e142102ab065", "type": "github" }, "original": { From 640f1a1c41a90066c3c7ad4d7331ed40446eac0b Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Mar 2024 09:49:32 +0100 Subject: [PATCH 0525/1125] Kde/konsole: configure konsole profiles --- roles/kde/programs/konsole.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/roles/kde/programs/konsole.nix b/roles/kde/programs/konsole.nix index 709903a..109b200 100644 --- a/roles/kde/programs/konsole.nix +++ b/roles/kde/programs/konsole.nix @@ -13,5 +13,15 @@ in { xdg.dataFile = { "konsole/Catppuccin-Mocha.colorscheme".source = catppuccinKonsole; }; + programs.konsole = { + enable = true; + defaultProfile = "Toast.profile"; + profiles.toast = { + name = "Toast"; + colorScheme = "Catppuccin-Mocha"; + font.name = "JetBrainsMono Nerd Font"; + font.size = 10; + }; + }; }; } From b43657877c7f30b3d2d0ac4262aea9c3f916ccb8 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Mar 2024 12:06:57 +0100 Subject: [PATCH 0526/1125] Revert "Desktop/ssh-agent: use home-manager module" This reverts commit 693410597aab78188d3060c21edcc6952d2950e6. Neccesary cause the home-manager module has issues --- roles/desktop/services/ssh-agent.nix | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/roles/desktop/services/ssh-agent.nix b/roles/desktop/services/ssh-agent.nix index 56fea6b..6f734f8 100644 --- a/roles/desktop/services/ssh-agent.nix +++ b/roles/desktop/services/ssh-agent.nix @@ -1,3 +1,19 @@ {...}: { - home-manager.users.toast.services.ssh-agent.enable = true; + programs.ssh.startAgent = true; + /* + Home assistant added an option that does this + https://github.com/nix-community/home-manager/commit/2d9210f25ed18d5d4e11e6b886de4027c0c51a94 + but since I still need to fix home-manager's envvars not applying I'll stick to the NixOS one + */ + /* + TODO: fix SSH_AUTH_SOCK not being set in Plasma + Turns out the NixOS module also has issues :3 + The env is set but only in bash, not in the DE, so + keepass can't pick it up. For now I'll just set it manually + */ + home-manager.users.toast.xdg.configFile."plasma-workspace/env/ssh-agent.sh".text = '' + if [[ -z "$SSH_AUTH_SOCK" ]]; then + export SSH_AUTH_SOCK=$XDG_RUNTIME_DIR/ssh-agent + fi + ''; } From f8f05329a240653f88cdb9826487dc4771cafd68 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Mar 2024 12:59:06 +0100 Subject: [PATCH 0527/1125] Server/minecraft: remove server --- roles/server/default.nix | 1 - roles/server/minecraft.nix | 116 ------------------------------------- 2 files changed, 117 deletions(-) delete mode 100644 roles/server/minecraft.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index aa16bef..11c334a 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -12,7 +12,6 @@ ./beep.nix ./tailscale.nix ./traefik.nix - ./minecraft.nix ./dns.nix ]; } diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix deleted file mode 100644 index 5743b39..0000000 --- a/roles/server/minecraft.nix +++ /dev/null @@ -1,116 +0,0 @@ -{ - config, - pkgs, - flakeSelf, - ... -}: let - atfc = builtins.fetchurl { - url = "https://www.curseforge.com/api/v1/mods/813246/files/4732590/download"; - sha256 = "0yl6ixmhfgqvcj3kfshpf8fy42vkkmjbn7d7yg86jx0ykiiq5f9x"; - }; - puffish_skills = builtins.fetchurl { - url = "https://www.curseforge.com/api/v1/mods/835091/files/4747353/download"; - sha256 = "1pwx8zqih019l12lrmllrjv2al0mjzwj4p5qmc4ps1g555jy8qil"; - }; - spark = builtins.fetchurl { - url = "https://www.curseforge.com/api/v1/mods/361579/files/4505375/download"; - sha256 = "1708lrx1nif0mvf7ambw8504j12wbn0vm69wsh21p8ylqpql1s4x"; - }; - - port = 25565; - users = config.users; -in { - users = { - groups.minecraft = { - members = ["toast"]; - gid = 987; - }; - users.atfc = { - isSystemUser = true; - uid = 988; - group = "minecraft"; - home = "/var/lib/minecraft/atfc"; - homeMode = "750"; - createHome = true; - }; - }; - - virtualisation.oci-containers = { - containers."minecraft-atfc" = { - autoStart = true; - image = "itzg/minecraft-server"; - #user = "${toString users.users.atfc.uid}:${toString users.groups.minecraft.gid}"; - environment = { - TZ = "Europe/Madrid"; - EULA = "true"; - TYPE = "forge"; - MEMORY = "2G"; - UID = toString users.users.atfc.uid; - GID = toString users.groups.minecraft.gid; - VERSION = "1.18.2"; - FORGE_VERSION = "40.2.10"; - GENERIC_PACK = "/modpack.zip"; - #USE_AIKAR_FLAGS = "true"; - - #STOP_DURATION = "70"; - STOP_SERVER_ANNOUNCE_DELAY = "25"; - - # server.properties - MOTD = "Toast's modded minecraft server"; - DIFFICULTY = "hard"; - SNOOPER_ENABLED = "false"; - SPAWN_PROTECTION = "0"; - LEVEL_TYPE = "tfc:tng"; - BROADCAST_CONSOLE_TO_OPS = "true"; - BROADCAST_RCON_TO_OPS = "true"; - VIEW_DISTANCE = "16"; - MAX_PLAYERS = "4"; - - RCON_CMDS_LAST_DISCONNECT = "save-all"; - - OPS = "b3ca4afb-a3da-4a78-85c3-2292fd0787e2,0cb3d02a-1d1f-4d7f-b70c-bd53dc155cff"; - EXISTING_OPS_FILE = "synchronize"; - - WHITELIST = "b3ca4afb-a3da-4a78-85c3-2292fd0787e2,0cb3d02a-1d1f-4d7f-b70c-bd53dc155cff,03f080e8-ce8e-4b90-a312-734747ce7db0,ea88f690-cf46-4416-bfd5-6f6b165885f7"; - EXISTING_WHITELIST_FILE = "synchronize"; - - # Auto pause needs this - MAX_TICK_TIME = "-1"; - AUTOPAUSE_KNOCK_INTERFACE = "tap0"; - ENABLE_AUTOPAUSE = "true"; - }; - extraOptions = [ - "--network=slirp4netns:port_handler=slirp4netns" - "--cap-add=CAP_NET_RAW" - ]; - - volumes = [ - "${atfc}:/modpack.zip" - "${puffish_skills}:/mods/puffish_skills.jar" - "${spark}:/mods/spark.jar" - "${users.users.atfc.home}:/data" - #"/tmp/minecraft:/data" - ]; - ports = ["25565:${toString port}"]; - }; - }; - - networking.firewall.allowedTCPPorts = [port]; - - # anything-sync-daemon config - systemd.packages = with pkgs; [flakeSelf.packages.x86_64-linux.anything-sync-daemon]; - environment.systemPackages = with pkgs; [flakeSelf.packages.x86_64-linux.anything-sync-daemon]; - fileSystems.minecraftTmpfs = { - device = "none"; - fsType = "tmpfs"; - mountPoint = "/mnt/minecraftTmpfs"; - options = ["size=4G "]; - }; - environment.etc."asd.conf".text = '' WHATTOSYNC=('/var/lib/minecraft') - VOLATILE="${config.fileSystems.minecraftTmpfs.mountPoint}" - USE_OVERLAYFS="yes" ''; - systemd.services.asd = { - wantedBy = ["podman-minecraft-atfc.service"]; - before = ["podman-minecraft-atfc.service"]; - }; -} From 8aaa524fceb3803565a43683917388ffbbbbd2eb Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Mar 2024 13:35:32 +0100 Subject: [PATCH 0528/1125] Flake: update lock file --- flake.lock | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index 8de9a02..cb56d59 100644 --- a/flake.lock +++ b/flake.lock @@ -220,11 +220,11 @@ ] }, "locked": { - "lastModified": 1710644923, - "narHash": "sha256-0fjbN5GYYDKPyPay0l8gYoH+tFfNqPPwP5sxxBreeA4=", + "lastModified": 1711249705, + "narHash": "sha256-h/NQECj6mIzF4XR6AQoSpkCnwqAM+ol4+qOdYi2ykmQ=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "e25efda85e39fcdc845e371971ac4384989c4295", + "rev": "34519f3bb678a5abbddf7b200ac5347263ee781b", "type": "github" }, "original": { @@ -240,11 +240,11 @@ ] }, "locked": { - "lastModified": 1710644923, - "narHash": "sha256-0fjbN5GYYDKPyPay0l8gYoH+tFfNqPPwP5sxxBreeA4=", + "lastModified": 1711249705, + "narHash": "sha256-h/NQECj6mIzF4XR6AQoSpkCnwqAM+ol4+qOdYi2ykmQ=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "e25efda85e39fcdc845e371971ac4384989c4295", + "rev": "34519f3bb678a5abbddf7b200ac5347263ee781b", "type": "github" }, "original": { @@ -271,11 +271,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1710838473, - "narHash": "sha256-RLvwdQSENKOaLdKhNie8XqHmTXzNm00/M/THj6zplQo=", + "lastModified": 1711460390, + "narHash": "sha256-akSgjDZL6pVHEfSE6sz1DNSXuYX6hq+P/1Z5IoYWs7E=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "fa9f817df522ac294016af3d40ccff82f5fd3a63", + "rev": "44733514b72e732bd49f5511bd0203dea9b9a434", "type": "github" }, "original": { @@ -286,11 +286,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1710806803, - "narHash": "sha256-qrxvLS888pNJFwJdK+hf1wpRCSQcqA6W5+Ox202NDa0=", + "lastModified": 1711333969, + "narHash": "sha256-5PiWGn10DQjMZee5NXzeA6ccsv60iLu+Xtw+mfvkUAs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b06025f1533a1e07b6db3e75151caa155d1c7eb3", + "rev": "57e6b3a9e4ebec5aa121188301f04a6b8c354c9b", "type": "github" }, "original": { @@ -301,11 +301,11 @@ }, "nur": { "locked": { - "lastModified": 1710919093, - "narHash": "sha256-0A7NnR+kfsn9VSTkbZpkx5JAl7psNU5QKpEZk8wU/uU=", + "lastModified": 1711536331, + "narHash": "sha256-XM+v9UVX9MwdZ4IYEq0WdjaaJH+QL8LCInTZGttXKDY=", "owner": "nix-community", "repo": "NUR", - "rev": "14ecc0dbbc7f572a29fb177168c991379d5e44b9", + "rev": "592988f111a01b18a78d97fe71f174c1d5a9fced", "type": "github" }, "original": { @@ -324,11 +324,11 @@ ] }, "locked": { - "lastModified": 1711527622, - "narHash": "sha256-UCTdFTa4tQuXHzsJUhqDuTyvA2Xu6fvMe+mGXdQhPrg=", + "lastModified": 1711529011, + "narHash": "sha256-vx2ykxdVEPbr8aaNZlmXe6OLHnshHyBXhjH2BDJXcMw=", "owner": "pjones", "repo": "plasma-manager", - "rev": "fd4426851e1a4b1fe88abba78171e142102ab065", + "rev": "3fb7f033798f739b2f1e266c97be0087b826736b", "type": "github" }, "original": { @@ -412,11 +412,11 @@ ] }, "locked": { - "lastModified": 1711415893, - "narHash": "sha256-f7KK83bGkLf7QxEpkOH3B4sqnzBvr6qf3jeGgfKNteA=", + "lastModified": 1711502271, + "narHash": "sha256-Mj7RA/F5LplNsZqGN4/IXnDJzbyMZyjEVnoHbytoo+4=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "da36b726fedf0ae85c3fc1f634fd38ebe2f0d070", + "rev": "04bf2186f8e20f70c319034acc2c793dd07a712c", "type": "github" }, "original": { From 6b3003972df324c0ceed8c2b301d6fae661824eb Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 1 Apr 2024 14:41:55 +0200 Subject: [PATCH 0529/1125] Kde/plasma: update configFile config --- roles/kde/plasma.nix | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 75b664c..365dc9e 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -155,16 +155,16 @@ in { }; configFile = { "kwinrc" = { - "org.kde.kdecoration2"."BorderSize" = "None"; + "org.kde.kdecoration2"."BorderSize".value = "None"; "Desktops" = { - "Number" = 2; - "Rows" = 1; + "Number".value = 2; + "Rows".value = 1; }; - "TabBox"."LayoutName" = "thumbnail_grid"; + "TabBox"."LayoutName".value = "thumbnail_grid"; }; - "kdeglobals"."General"."AccentColor" = null; - "auroraerc"."CatppuccinMocha-Classic"."ButtonSize" = 0; - "plasmanotifyrc"."Notifications"."NormalAlwaysOnTop" = true; + "kdeglobals"."General"."AccentColor".value = null; + "auroraerc"."CatppuccinMocha-Classic"."ButtonSize".value = 0; + "plasmanotifyrc"."Notifications"."NormalAlwaysOnTop".value = true; }; }; } From fe52c9055b3944624cf0ae45a00ef06ddaae4c32 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 1 Apr 2024 14:44:45 +0200 Subject: [PATCH 0530/1125] Desktop/flatpak: update option --- roles/desktop/services/flatpak.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/desktop/services/flatpak.nix b/roles/desktop/services/flatpak.nix index 57d5456..a2f9723 100644 --- a/roles/desktop/services/flatpak.nix +++ b/roles/desktop/services/flatpak.nix @@ -6,7 +6,7 @@ users.toast = { services.flatpak = { packages = ["tv.plex.PlexDesktop"]; - uninstallUnmanagedPackages = true; + uninstallUnmanaged = true; update.auto = { enable = true; onCalendar = "weekly"; From 7048a5641341a849bd61c4684e1064b74eeae8f6 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 1 Apr 2024 14:45:18 +0200 Subject: [PATCH 0531/1125] Flake: update lock file --- flake.lock | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/flake.lock b/flake.lock index cb56d59..bbb1a1b 100644 --- a/flake.lock +++ b/flake.lock @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1711133180, - "narHash": "sha256-WJOahf+6115+GMl3wUfURu8fszuNeJLv9qAWFQl3Vmo=", + "lastModified": 1711915616, + "narHash": "sha256-co6LoFA+j6BZEeJNSR8nZ4oOort5qYPskjrDHBaJgmo=", "owner": "nix-community", "repo": "home-manager", - "rev": "1c2c5e4cabba4c43504ef0f8cc3f3dfa284e2dbb", + "rev": "820be197ccf3adaad9a8856ef255c13b6cc561a6", "type": "github" }, "original": { @@ -162,11 +162,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1708781964, - "narHash": "sha256-qbEZgB1mNuMADLmM64EtcRjDHXR3UFL4xVmoanv9wZU=", + "lastModified": 1711964948, + "narHash": "sha256-rU+ZyD2tRH6nif7RBklDahehFMjVcQf0HrK/oOS22ug=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "09d07c73b4d9771f527a168e0b1b6d8a1f39de28", + "rev": "248912b4003df87c7625d9c5f454606694c92fb1", "type": "github" }, "original": { @@ -220,11 +220,11 @@ ] }, "locked": { - "lastModified": 1711249705, - "narHash": "sha256-h/NQECj6mIzF4XR6AQoSpkCnwqAM+ol4+qOdYi2ykmQ=", + "lastModified": 1711854532, + "narHash": "sha256-JPStavwlT7TfxxiXHk6Q7sbNxtnXAIjXQJMLO0KB6M0=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "34519f3bb678a5abbddf7b200ac5347263ee781b", + "rev": "2844b5f3ad3b478468151bd101370b9d8ef8a3a7", "type": "github" }, "original": { @@ -240,11 +240,11 @@ ] }, "locked": { - "lastModified": 1711249705, - "narHash": "sha256-h/NQECj6mIzF4XR6AQoSpkCnwqAM+ol4+qOdYi2ykmQ=", + "lastModified": 1711854532, + "narHash": "sha256-JPStavwlT7TfxxiXHk6Q7sbNxtnXAIjXQJMLO0KB6M0=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "34519f3bb678a5abbddf7b200ac5347263ee781b", + "rev": "2844b5f3ad3b478468151bd101370b9d8ef8a3a7", "type": "github" }, "original": { @@ -271,11 +271,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1711460390, - "narHash": "sha256-akSgjDZL6pVHEfSE6sz1DNSXuYX6hq+P/1Z5IoYWs7E=", + "lastModified": 1711668574, + "narHash": "sha256-u1dfs0ASQIEr1icTVrsKwg2xToIpn7ZXxW3RHfHxshg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "44733514b72e732bd49f5511bd0203dea9b9a434", + "rev": "219951b495fc2eac67b1456824cc1ec1fd2ee659", "type": "github" }, "original": { @@ -286,11 +286,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1711333969, - "narHash": "sha256-5PiWGn10DQjMZee5NXzeA6ccsv60iLu+Xtw+mfvkUAs=", + "lastModified": 1711703276, + "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "57e6b3a9e4ebec5aa121188301f04a6b8c354c9b", + "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089", "type": "github" }, "original": { @@ -301,11 +301,11 @@ }, "nur": { "locked": { - "lastModified": 1711536331, - "narHash": "sha256-XM+v9UVX9MwdZ4IYEq0WdjaaJH+QL8LCInTZGttXKDY=", + "lastModified": 1711971896, + "narHash": "sha256-AISS9Z0YDKdhvep+ZEYVAfgoo7yMU1kGP1Zk/n2wiEc=", "owner": "nix-community", "repo": "NUR", - "rev": "592988f111a01b18a78d97fe71f174c1d5a9fced", + "rev": "3994218574cb3a1bd6f1effa838315f43eea6840", "type": "github" }, "original": { @@ -324,11 +324,11 @@ ] }, "locked": { - "lastModified": 1711529011, - "narHash": "sha256-vx2ykxdVEPbr8aaNZlmXe6OLHnshHyBXhjH2BDJXcMw=", + "lastModified": 1711920558, + "narHash": "sha256-F8ESttizNOXsLfv9PeTen3lvq3cnxG9RV2RiHgGzA2Q=", "owner": "pjones", "repo": "plasma-manager", - "rev": "3fb7f033798f739b2f1e266c97be0087b826736b", + "rev": "88cf932923835c05f26176a8a4df30a0dd1e7775", "type": "github" }, "original": { @@ -412,11 +412,11 @@ ] }, "locked": { - "lastModified": 1711502271, - "narHash": "sha256-Mj7RA/F5LplNsZqGN4/IXnDJzbyMZyjEVnoHbytoo+4=", + "lastModified": 1711934525, + "narHash": "sha256-nMRgXVApeacHoO+R6ap5Y1Did+qng0z/eBG8L7jFgJY=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "04bf2186f8e20f70c319034acc2c793dd07a712c", + "rev": "b2ca2718d4953bc2b41592d2a6b76e3d28236e69", "type": "github" }, "original": { From 762c0ff7dc21fb8cb3f4602c3f1883534b17d527 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 8 Apr 2024 23:26:18 +0200 Subject: [PATCH 0532/1125] Flake: update lock file --- flake.lock | 90 +++++++++++++++++++++++++++--------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/flake.lock b/flake.lock index bbb1a1b..cd441ac 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1707830867, - "narHash": "sha256-PAdwm5QqdlwIqGrfzzvzZubM+FXtilekQ/FA0cI49/o=", + "lastModified": 1712079060, + "narHash": "sha256-/JdiT9t+zzjChc5qQiF+jhrVhRt8figYH29rZO7pFe4=", "owner": "ryantm", "repo": "agenix", - "rev": "8cb01a0e717311680e0cbca06a76cbceba6f3ed6", + "rev": "1381a759b205dff7a6818733118d02253340fd5e", "type": "github" }, "original": { @@ -46,11 +46,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", "owner": "edolstra", "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "type": "github" }, "original": { @@ -64,11 +64,11 @@ "systems": "systems_2" }, "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1711915616, - "narHash": "sha256-co6LoFA+j6BZEeJNSR8nZ4oOort5qYPskjrDHBaJgmo=", + "lastModified": 1712462372, + "narHash": "sha256-WA3bbBWhd3o1wAgyHZNypjb/LG4oq+IWxFq8ey8yNPU=", "owner": "nix-community", "repo": "home-manager", - "rev": "820be197ccf3adaad9a8856ef255c13b6cc561a6", + "rev": "a561ad6ab38578c812cc9af3b04f2cc60ebf48c9", "type": "github" }, "original": { @@ -125,11 +125,11 @@ ] }, "locked": { - "lastModified": 1710888565, - "narHash": "sha256-s9Hi4RHhc6yut4EcYD50sZWRDKsugBJHSbON8KFwoTw=", + "lastModified": 1712386041, + "narHash": "sha256-dA82pOMQNnCJMAsPG7AXG35VmCSMZsJHTFlTHizpKWQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "f33900124c23c4eca5831b9b5eb32ea5894375ce", + "rev": "d6bb9f934f2870e5cbc5b94c79e9db22246141ff", "type": "github" }, "original": { @@ -147,11 +147,11 @@ ] }, "locked": { - "lastModified": 1711231487, - "narHash": "sha256-dRdFjStMA7GeuD/V4vzKblzuHwxMPgzEboRleVdZlUM=", + "lastModified": 1712521891, + "narHash": "sha256-qJRkB7QZo2mdR/nABeHQKi3xkQxUsSGjVVQXTSHQocI=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "1171169117f63f1de9ef2ea36efd8dcf377c6d5a", + "rev": "ec53086c76303dc8880fa7ba06c45abcae8b3398", "type": "github" }, "original": { @@ -162,11 +162,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1711964948, - "narHash": "sha256-rU+ZyD2tRH6nif7RBklDahehFMjVcQf0HrK/oOS22ug=", + "lastModified": 1711997375, + "narHash": "sha256-KvU4gOtuFMS9Il67glRGtdNfguAINT9pCaXtvCL8uI8=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "248912b4003df87c7625d9c5f454606694c92fb1", + "rev": "45bf66f7068db79b552da864c0e87452be624d6c", "type": "github" }, "original": { @@ -220,11 +220,11 @@ ] }, "locked": { - "lastModified": 1711854532, - "narHash": "sha256-JPStavwlT7TfxxiXHk6Q7sbNxtnXAIjXQJMLO0KB6M0=", + "lastModified": 1712459390, + "narHash": "sha256-e12bNDottaGoBgd0AdH/bQvk854xunlWAdZwr/oHO1c=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "2844b5f3ad3b478468151bd101370b9d8ef8a3a7", + "rev": "4676d72d872459e1e3a248d049609f110c570e9a", "type": "github" }, "original": { @@ -240,11 +240,11 @@ ] }, "locked": { - "lastModified": 1711854532, - "narHash": "sha256-JPStavwlT7TfxxiXHk6Q7sbNxtnXAIjXQJMLO0KB6M0=", + "lastModified": 1712459390, + "narHash": "sha256-e12bNDottaGoBgd0AdH/bQvk854xunlWAdZwr/oHO1c=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "2844b5f3ad3b478468151bd101370b9d8ef8a3a7", + "rev": "4676d72d872459e1e3a248d049609f110c570e9a", "type": "github" }, "original": { @@ -255,11 +255,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1711352745, - "narHash": "sha256-luvqik+i3HTvCbXQZgB6uggvEcxI9uae0nmrgtXJ17U=", + "lastModified": 1712566108, + "narHash": "sha256-c9nT2ZODGqobISP41kUwCQ84Srwg7a/1TmPFQuol2/8=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "9a763a7acc4cfbb8603bb0231fec3eda864f81c0", + "rev": "1e3b3a35b7083f4152f5a516798cf9b21e686465", "type": "github" }, "original": { @@ -271,11 +271,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1711668574, - "narHash": "sha256-u1dfs0ASQIEr1icTVrsKwg2xToIpn7ZXxW3RHfHxshg=", + "lastModified": 1712437997, + "narHash": "sha256-g0whLLwRvgO2FsyhY8fNk+TWenS3jg5UdlWL4uqgFeo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "219951b495fc2eac67b1456824cc1ec1fd2ee659", + "rev": "e38d7cb66ea4f7a0eb6681920615dfcc30fc2920", "type": "github" }, "original": { @@ -286,11 +286,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1711703276, - "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=", + "lastModified": 1712439257, + "narHash": "sha256-aSpiNepFOMk9932HOax0XwNxbA38GOUVOiXfUVPOrck=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089", + "rev": "ff0dbd94265ac470dda06a657d5fe49de93b4599", "type": "github" }, "original": { @@ -301,11 +301,11 @@ }, "nur": { "locked": { - "lastModified": 1711971896, - "narHash": "sha256-AISS9Z0YDKdhvep+ZEYVAfgoo7yMU1kGP1Zk/n2wiEc=", + "lastModified": 1712605683, + "narHash": "sha256-+ZnPwPchvPG+rOFfpxLjKm+5ZNRtYUBtn1KkEojgsSc=", "owner": "nix-community", "repo": "NUR", - "rev": "3994218574cb3a1bd6f1effa838315f43eea6840", + "rev": "1db8af43c9b75768461a01d84e17596e331df77f", "type": "github" }, "original": { @@ -324,11 +324,11 @@ ] }, "locked": { - "lastModified": 1711920558, - "narHash": "sha256-F8ESttizNOXsLfv9PeTen3lvq3cnxG9RV2RiHgGzA2Q=", + "lastModified": 1712484920, + "narHash": "sha256-wNwv12U/QYYgZanycZ32A41cEDa2zPwYuMKK6AJYNJk=", "owner": "pjones", "repo": "plasma-manager", - "rev": "88cf932923835c05f26176a8a4df30a0dd1e7775", + "rev": "4b127a5ede004f5c6d7c41938c2986b599dc0bf3", "type": "github" }, "original": { @@ -412,11 +412,11 @@ ] }, "locked": { - "lastModified": 1711934525, - "narHash": "sha256-nMRgXVApeacHoO+R6ap5Y1Did+qng0z/eBG8L7jFgJY=", + "lastModified": 1712580452, + "narHash": "sha256-X1LjMY8wpnflD2nq7GuYxTichyWR9qxw8eGmzyEW4h8=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "b2ca2718d4953bc2b41592d2a6b76e3d28236e69", + "rev": "5041ca76d6c80d057673e5202fa4167f81202391", "type": "github" }, "original": { From c29fbb1fd6b9c62f462ebc93cbaf8b7d70330607 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 3 Apr 2024 01:11:36 +0100 Subject: [PATCH 0533/1125] Machines/WinMax2: temporarely change timezone --- machines/WinMax2/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 79ce4d6..8e26c04 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -41,6 +41,8 @@ boot.kernelParams = ["clearcpuid=304"]; }; + time.timeZone = lib.mkForce "Europe/London"; + # Sleep fixes boot.kernelParams = ["rtc_cmos.use_acpi_alarm=1"]; services.udev.extraRules = '' From aad1faa05291e9fd0271ed6f72f8072cde6f53db Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 7 Apr 2024 20:51:06 +0100 Subject: [PATCH 0534/1125] Revert "Machines/WinMax2: temporarely change timezone" This reverts commit 124977bdadd5ca15356b214801902984384abf49. --- machines/WinMax2/configuration.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 8e26c04..79ce4d6 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -41,8 +41,6 @@ boot.kernelParams = ["clearcpuid=304"]; }; - time.timeZone = lib.mkForce "Europe/London"; - # Sleep fixes boot.kernelParams = ["rtc_cmos.use_acpi_alarm=1"]; services.udev.extraRules = '' From e28022921a872b5aef26baf562fd27e20715de08 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 9 Apr 2024 10:24:26 +0200 Subject: [PATCH 0535/1125] Kde/konsole: update default profile name Plasma-manager update made it so that you don't need to add .profile anymore --- roles/kde/programs/konsole.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/kde/programs/konsole.nix b/roles/kde/programs/konsole.nix index 109b200..407e2ad 100644 --- a/roles/kde/programs/konsole.nix +++ b/roles/kde/programs/konsole.nix @@ -15,7 +15,7 @@ in { }; programs.konsole = { enable = true; - defaultProfile = "Toast.profile"; + defaultProfile = "Toast"; profiles.toast = { name = "Toast"; colorScheme = "Catppuccin-Mocha"; From 57372c8d28dd2a01f7b0f8d4fa591e7d55565e76 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 9 Apr 2024 10:40:18 +0200 Subject: [PATCH 0536/1125] Common: add catpuccin modules --- flake.lock | 16 ++++++++++++++++ flake.nix | 7 +++++++ roles/common/configuration.nix | 1 + 3 files changed, 24 insertions(+) diff --git a/flake.lock b/flake.lock index cd441ac..02e25cf 100644 --- a/flake.lock +++ b/flake.lock @@ -23,6 +23,21 @@ "type": "github" } }, + "catppuccin": { + "locked": { + "lastModified": 1712482981, + "narHash": "sha256-LJOOpTey9Y29C/TK4h9KP7v4HvqDL3mLyT9hSWCfFlI=", + "owner": "catppuccin", + "repo": "nix", + "rev": "4043beb6c792a40e9c513aa261f4ba10601a4457", + "type": "github" + }, + "original": { + "owner": "catppuccin", + "repo": "nix", + "type": "github" + } + }, "catppuccin-vsc": { "inputs": { "nixpkgs": [ @@ -340,6 +355,7 @@ "root": { "inputs": { "agenix": "agenix", + "catppuccin": "catppuccin", "catppuccin-vsc": "catppuccin-vsc", "home-manager": "home-manager_2", "home-manager-unstable": "home-manager-unstable", diff --git a/flake.nix b/flake.nix index 81171bf..90defdb 100644 --- a/flake.nix +++ b/flake.nix @@ -68,6 +68,8 @@ nix-flatpak.url = "github:gmodena/nix-flatpak/main"; nur.url = "github:nix-community/NUR"; + + catppuccin.url = "github:catppuccin/nix"; }; outputs = {...} @ inputs: @@ -131,6 +133,7 @@ agenix.nixosModules.default home-manager-unstable.nixosModule nix-index-db-unstable.nixosModules.nix-index + catppuccin.nixosModules.catppuccin ./roles/common ./roles/desktop ./roles/kde @@ -151,6 +154,7 @@ home-manager-unstable.nixosModule nixos-hardware.nixosModules.microsoft-surface-go nix-index-db-unstable.nixosModules.nix-index + catppuccin.nixosModules.catppuccin ./roles/common ./roles/desktop ./roles/kde @@ -169,6 +173,7 @@ jovian.nixosModules.default home-manager-unstable.nixosModule nix-index-db-unstable.nixosModules.nix-index + catppuccin.nixosModules.catppuccin ./roles/common ./roles/desktop ./roles/kde @@ -190,6 +195,7 @@ home-manager-unstable.nixosModule nix-index-db-unstable.nixosModules.nix-index nixos-hardware.nixosModules.gpd-win-max-2-2023 + catppuccin.nixosModules.catppuccin ./roles/common ./roles/desktop ./roles/kde @@ -209,6 +215,7 @@ agenix.nixosModules.default home-manager.nixosModule nix-index-db.nixosModules.nix-index + catppuccin.nixosModules.catppuccin ./roles/common ./roles/server ./machines/Everest diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 53fa7ba..480d8ad 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -95,6 +95,7 @@ useGlobalPkgs = true; verbose = true; users.toast = {...}: { + sharedModules = [flakeSelf.inputs.catppuccin.homeManagerModules.catppuccin]; home.stateVersion = "23.11"; xdg = { userDirs = { From 317aa3800a8f9ae14bbc6eec1dc79e23b2d48018 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 9 Apr 2024 10:40:57 +0200 Subject: [PATCH 0537/1125] Common: set catppuccin flavour --- roles/common/configuration.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 480d8ad..35bd5fe 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -90,12 +90,15 @@ ) ]; + catppuccin.flavour = "mocha"; + home-manager = { backupFileExtension = "hm-backup"; useGlobalPkgs = true; verbose = true; - users.toast = {...}: { sharedModules = [flakeSelf.inputs.catppuccin.homeManagerModules.catppuccin]; + users.toast = {osConfig, ...}: { + catppuccin.flavour = osConfig.catppuccin.flavour; home.stateVersion = "23.11"; xdg = { userDirs = { From 72a94a71c1d77fad48cc85e7ba81c6dd767b108d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 9 Apr 2024 10:54:22 +0200 Subject: [PATCH 0538/1125] Common/bat: use catppuccin module --- roles/common/programs/bat.nix | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/roles/common/programs/bat.nix b/roles/common/programs/bat.nix index 021d531..cce65c9 100644 --- a/roles/common/programs/bat.nix +++ b/roles/common/programs/bat.nix @@ -1,25 +1,8 @@ -{ - config, - pkgs, - ... -}: let - themeName = - if config.system.nixos.release == "23.11" - then "Catppuccin-mocha" - else "Catppuccin Mocha"; -in { +{...}: { home-manager = { users.toast.programs.bat = { enable = true; - config = { - theme = "catppuccin-mocha"; - }; - themes = { - catppuccin-mocha = { - src = pkgs.catppuccin; - file = "bat/${themeName}.tmTheme"; - }; - }; + catppuccin.enable = true; }; }; } From cd48978f981104810747affd01e0802e7d22c458 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 9 Apr 2024 16:17:07 +0200 Subject: [PATCH 0539/1125] Common: use grub catppuccin module --- roles/common/configuration.nix | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 35bd5fe..84d20be 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -117,11 +117,7 @@ ]; }; - boot.loader.grub = { - theme = "${pkgs.catppuccin}/grub"; - backgroundColor = "#1E1E2E"; - splashImage = "${pkgs.catppuccin}/grub/background.png"; - }; + boot.loader.grub.catppuccin.enable = true; /* I used to keep the host keys in the repo as a secret, but since I use the From 8062c8ad5af9ddcb06c2bdeb0e8e39a87a7facff Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 9 Apr 2024 16:32:23 +0200 Subject: [PATCH 0540/1125] Common/git: use delta catppuccin module --- roles/common/programs/git.nix | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index 3b125df..f9f2b4e 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -1,11 +1,4 @@ -{pkgs, ...}: let - catppuccinDelta = pkgs.fetchFromGitHub { - owner = "catppuccin"; - repo = "delta"; - rev = "main"; - hash = "sha256-0QQLkfLBVuB2re6tjtPNuOQZNK0MDBAIFgNGHZM8afs="; - }; -in { +{...}: { home-manager.users.toast = { programs.git = { enable = true; @@ -13,12 +6,8 @@ in { userEmail = "toast003@tutamail.com"; delta = { enable = true; - options = { - syntax-theme = "catppuccin-mocha"; - features = "catppuccin-mocha"; - }; + catppuccin.enable = true; }; - includes = [{path = "${catppuccinDelta}/themes/mocha.gitconfig";}]; extraConfig = { init.defaultBranch = "main"; diff.colorMoved = "default"; From 89eb9e4b712f5f3e1cd075f6bf986831dc9bb2ee Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 10 Apr 2024 09:36:48 +0200 Subject: [PATCH 0541/1125] Common/btop: use catppuccin module --- roles/common/programs/btop.nix | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/roles/common/programs/btop.nix b/roles/common/programs/btop.nix index c0bf0de..1e25cbe 100644 --- a/roles/common/programs/btop.nix +++ b/roles/common/programs/btop.nix @@ -1,14 +1,9 @@ -{pkgs, ...}: { +{...}: { home-manager = { users.toast = { programs.btop = { enable = true; - settings = { - color_theme = "catppuccin_mocha"; - }; - }; - xdg.configFile = { - "btop/themes".source = "${pkgs.catppuccin}/btop"; + catppuccin.enable = true; }; }; }; From 13b2e5ef6fd3f02b81f6f2da446dbfa07407ff69 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 10 Apr 2024 09:45:50 +0200 Subject: [PATCH 0542/1125] Common/helix: use catppuccin module --- roles/common/programs/helix.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index 70fa320..c5ea603 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -7,8 +7,11 @@ nixpkgs-fmt nil ]; + catppuccin = { + enable = true; + useItalics = true; + }; settings = { - theme = "catppuccin_mocha"; editor = { mouse = true; cursorline = true; From 3ecc3456ecc5628611b56fb5007f498b0f52ea90 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 10 Apr 2024 10:43:44 +0200 Subject: [PATCH 0543/1125] Common: enable management of xdg directories --- roles/common/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 84d20be..8af3482 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -101,6 +101,7 @@ catppuccin.flavour = osConfig.catppuccin.flavour; home.stateVersion = "23.11"; xdg = { + enable = true; userDirs = { enable = true; createDirectories = true; From 16d47d521476a8380ea17a229b8fa938c64cbb25 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 10 Apr 2024 10:50:42 +0200 Subject: [PATCH 0544/1125] Common/starship: setup using home manager and use catppuccin modue --- roles/common/programs/starship.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index 8e60667..527034a 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -49,4 +49,13 @@ in { } ]; }; + # The catppuccin module only works for home-manager, so this + # sets up starship with home-manager using the system config + home-manager.users.toast = {osConfig, ...}: { + programs.starship = { + enable = true; + catppuccin.enable = true; + settings = osConfig.programs.starship.settings; + }; + }; } From ce6732acd8474d3c0e333f0616b4a4a5c6705968 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 9 Apr 2024 16:07:42 +0200 Subject: [PATCH 0545/1125] Machines/WinMax2: add encrypted swap partition --- machines/WinMax2/hardware-configuration.nix | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/machines/WinMax2/hardware-configuration.nix b/machines/WinMax2/hardware-configuration.nix index 45745ac..4778fbe 100755 --- a/machines/WinMax2/hardware-configuration.nix +++ b/machines/WinMax2/hardware-configuration.nix @@ -19,7 +19,10 @@ in { boot.kernelModules = ["kvm-amd"]; boot.extraModulePackages = []; - boot.initrd.luks.devices."SSD".device = "/dev/disk/by-label/wm2-enc"; + boot.initrd.luks.devices = { + "SSD".device = "/dev/disk/by-label/wm2-enc"; + "swap".device = "/dev/disk/by-label/wm2-swap"; + }; fileSystems = { "efi_boot_partition" = { @@ -65,7 +68,13 @@ in { }; }; - swapDevices = []; + swapDevices = [ + { + device = "/dev/mapper/swap"; + # only want to use the swap partition for hibernating + priority = 0; + } + ]; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware = { From 761dfedf1b61b86265f1fcda6150bb4800e070a1 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 10 Apr 2024 13:06:55 +0200 Subject: [PATCH 0546/1125] Machines/WinMax2: add desktop entry to launch steam without scaling --- machines/WinMax2/configuration.nix | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 79ce4d6..f5213b1 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -110,6 +110,17 @@ environment.sessionVariables = { STEAM_FORCE_DESKTOPUI_SCALING = "2"; }; + home-manager.users.toast = { + # Steam's hidpi support is bugged so it needds to be hardcoded + # This bypasses that + xdg.desktopEntries = { + steam-noScaling = { + name = "Steam (No Scaling)"; + exec = "env STEAM_FORCE_DESKTOPUI_SCALING=0 steam %U"; + icon = "steam"; + }; + }; + }; # Enable sound. # sound.enable = true; From 7019c43d85a38bffca6bcd72d55e565a2721ae68 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 11 Apr 2024 09:54:22 +0200 Subject: [PATCH 0547/1125] Machines/WinMax2: complete the steam desktop entry --- machines/WinMax2/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index f5213b1..664adc3 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -118,6 +118,8 @@ name = "Steam (No Scaling)"; exec = "env STEAM_FORCE_DESKTOPUI_SCALING=0 steam %U"; icon = "steam"; + categories = ["Network" "FileTransfer" "Game"]; + comment = "Application for managing and playing games on Steam"; }; }; }; From 0337f4f7a047f2278be2f8c7ce60c49c8b2a4320 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Apr 2024 00:11:25 +0200 Subject: [PATCH 0548/1125] Flake: temporarely change to my branch of plasma-manager --- flake.lock | 11 ++++++----- flake.nix | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 02e25cf..2046a49 100644 --- a/flake.lock +++ b/flake.lock @@ -339,15 +339,16 @@ ] }, "locked": { - "lastModified": 1712484920, - "narHash": "sha256-wNwv12U/QYYgZanycZ32A41cEDa2zPwYuMKK6AJYNJk=", - "owner": "pjones", + "lastModified": 1712872911, + "narHash": "sha256-gwYrKMXuUBf5acvTzH7+lXeBbBZYUUEgcLBugHXimuc=", + "owner": "toast003", "repo": "plasma-manager", - "rev": "4b127a5ede004f5c6d7c41938c2986b599dc0bf3", + "rev": "8a3ac8690d6f546ec9185e1f5ddbb1f76d63b6b1", "type": "github" }, "original": { - "owner": "pjones", + "owner": "toast003", + "ref": "libinput", "repo": "plasma-manager", "type": "github" } diff --git a/flake.nix b/flake.nix index 90defdb..a47a42f 100644 --- a/flake.nix +++ b/flake.nix @@ -51,7 +51,7 @@ }; plasma-manager = { - url = "github:pjones/plasma-manager"; + url = "github:toast003/plasma-manager/libinput"; inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; inputs.home-manager.follows = "home-manager-unstable"; }; From 819b9bd218f02d9691e06f0aea5083d4a9f4fdfd Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Apr 2024 00:40:19 +0200 Subject: [PATCH 0549/1125] Machines/WinMax2: apply home-manager tweaks to every user --- machines/WinMax2/configuration.nix | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 664adc3..b1bbbe5 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -110,19 +110,21 @@ environment.sessionVariables = { STEAM_FORCE_DESKTOPUI_SCALING = "2"; }; - home-manager.users.toast = { - # Steam's hidpi support is bugged so it needds to be hardcoded - # This bypasses that - xdg.desktopEntries = { - steam-noScaling = { - name = "Steam (No Scaling)"; - exec = "env STEAM_FORCE_DESKTOPUI_SCALING=0 steam %U"; - icon = "steam"; - categories = ["Network" "FileTransfer" "Game"]; - comment = "Application for managing and playing games on Steam"; + home-manager.sharedModules = [ + { + # Steam's hidpi support is bugged so it needds to be hardcoded + # This bypasses that + xdg.desktopEntries = { + steam-noScaling = { + name = "Steam (No Scaling)"; + exec = "env STEAM_FORCE_DESKTOPUI_SCALING=0 steam %U"; + icon = "steam"; + categories = ["Network" "FileTransfer" "Game"]; + comment = "Application for managing and playing games on Steam"; + }; }; - }; - }; + } + ]; # Enable sound. # sound.enable = true; From 26fde4688631ecd0406727ee62f9a03ae38fda64 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Apr 2024 00:58:09 +0200 Subject: [PATCH 0550/1125] Machines/WinMax2: set up keyboard layout for plasma --- machines/WinMax2/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index b1bbbe5..f3a64c1 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -123,6 +123,7 @@ comment = "Application for managing and playing games on Steam"; }; }; + programs.plasma.input.keyboard.layouts = lib.mkForce [ "us" ]; } ]; From 7202d3a57f5d6b5389d8f18b790c3a3a867ba09e Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Apr 2024 00:59:25 +0200 Subject: [PATCH 0551/1125] Kde/plasma: set up keyboard layout and numlock settings --- roles/kde/plasma.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 365dc9e..1a7ab52 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -126,6 +126,12 @@ in { right = ["minimize" "maximize" "close"]; }; }; + input = { + keyboard = { + layouts = ["es"]; + numlockOnStartup = "off"; + }; + }; panels = [ { location = "bottom"; From ea0d7caf4f16f2621a7c91333baafdf6d7189a0a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Apr 2024 01:16:31 +0200 Subject: [PATCH 0552/1125] Kde/plasma: configure virtual desktops with high level module --- roles/kde/plasma.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 1a7ab52..b88ff52 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -125,6 +125,10 @@ in { left = ["on-all-desktops" "keep-above-windows"]; right = ["minimize" "maximize" "close"]; }; + virtualDesktops = { + rows = 1; + number = 2; + }; }; input = { keyboard = { @@ -162,10 +166,6 @@ in { configFile = { "kwinrc" = { "org.kde.kdecoration2"."BorderSize".value = "None"; - "Desktops" = { - "Number".value = 2; - "Rows".value = 1; - }; "TabBox"."LayoutName".value = "thumbnail_grid"; }; "kdeglobals"."General"."AccentColor".value = null; From 09839004e1ff11cd45d8d3eddc434e0414e228fa Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Apr 2024 10:44:38 +0200 Subject: [PATCH 0553/1125] Flake: update lock file --- flake.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/flake.lock b/flake.lock index 2046a49..7691036 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1712482981, - "narHash": "sha256-LJOOpTey9Y29C/TK4h9KP7v4HvqDL3mLyT9hSWCfFlI=", + "lastModified": 1712890104, + "narHash": "sha256-56RS7wdJ2QDUNCQt/9lx8MFcwuTdVQnzBV+9QToLLmM=", "owner": "catppuccin", "repo": "nix", - "rev": "4043beb6c792a40e9c513aa261f4ba10601a4457", + "rev": "850c26a3a2474b0d068abc89c905f536cca415de", "type": "github" }, "original": { @@ -120,11 +120,11 @@ ] }, "locked": { - "lastModified": 1712462372, - "narHash": "sha256-WA3bbBWhd3o1wAgyHZNypjb/LG4oq+IWxFq8ey8yNPU=", + "lastModified": 1712759992, + "narHash": "sha256-2APpO3ZW4idlgtlb8hB04u/rmIcKA8O7pYqxF66xbNY=", "owner": "nix-community", "repo": "home-manager", - "rev": "a561ad6ab38578c812cc9af3b04f2cc60ebf48c9", + "rev": "31357486b0ef6f4e161e002b6893eeb4fafc3ca9", "type": "github" }, "original": { @@ -162,11 +162,11 @@ ] }, "locked": { - "lastModified": 1712521891, - "narHash": "sha256-qJRkB7QZo2mdR/nABeHQKi3xkQxUsSGjVVQXTSHQocI=", + "lastModified": 1712909442, + "narHash": "sha256-D+VrmsPLkEbxNcI7lp9rGFR33RumbQIyhhjJ4PooWBs=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "ec53086c76303dc8880fa7ba06c45abcae8b3398", + "rev": "8886e3da78fcefb11935ea85da3d1572bf444c55", "type": "github" }, "original": { @@ -270,11 +270,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1712566108, - "narHash": "sha256-c9nT2ZODGqobISP41kUwCQ84Srwg7a/1TmPFQuol2/8=", + "lastModified": 1712760404, + "narHash": "sha256-4zhaEW1nB+nGbCNMjOggWeY5nXs/H0Y71q0+h+jdxoU=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "1e3b3a35b7083f4152f5a516798cf9b21e686465", + "rev": "e1c4bac14beb8c409d0534382cf967171706b9d9", "type": "github" }, "original": { @@ -286,11 +286,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1712437997, - "narHash": "sha256-g0whLLwRvgO2FsyhY8fNk+TWenS3jg5UdlWL4uqgFeo=", + "lastModified": 1712741485, + "narHash": "sha256-bCs0+MSTra80oXAsnM6Oq62WsirOIaijQ/BbUY59tR4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e38d7cb66ea4f7a0eb6681920615dfcc30fc2920", + "rev": "b2cf36f43f9ef2ded5711b30b1f393ac423d8f72", "type": "github" }, "original": { @@ -301,11 +301,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1712439257, - "narHash": "sha256-aSpiNepFOMk9932HOax0XwNxbA38GOUVOiXfUVPOrck=", + "lastModified": 1712791164, + "narHash": "sha256-3sbWO1mbpWsLepZGbWaMovSO7ndZeFqDSdX0hZ9nVyw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ff0dbd94265ac470dda06a657d5fe49de93b4599", + "rev": "1042fd8b148a9105f3c0aca3a6177fd1d9360ba5", "type": "github" }, "original": { @@ -316,11 +316,11 @@ }, "nur": { "locked": { - "lastModified": 1712605683, - "narHash": "sha256-+ZnPwPchvPG+rOFfpxLjKm+5ZNRtYUBtn1KkEojgsSc=", + "lastModified": 1712906890, + "narHash": "sha256-MkhmSqGqQ5cDa1VzqkA76h6+9rYCY2IJzSRglNV+Vr4=", "owner": "nix-community", "repo": "NUR", - "rev": "1db8af43c9b75768461a01d84e17596e331df77f", + "rev": "0fb8bccadea16d13d87210c21fbae09b26c28e07", "type": "github" }, "original": { @@ -429,11 +429,11 @@ ] }, "locked": { - "lastModified": 1712580452, - "narHash": "sha256-X1LjMY8wpnflD2nq7GuYxTichyWR9qxw8eGmzyEW4h8=", + "lastModified": 1712884817, + "narHash": "sha256-zs8oMnWHg3g0P+3ZsEj69m9aZCrGa/bqZUHRV9sF0w0=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "5041ca76d6c80d057673e5202fa4167f81202391", + "rev": "882c461b61050a266fe9bc8d93d342f24b54250f", "type": "github" }, "original": { From bda9abff87c1c5333e5a38704c3d510618bd5290 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Apr 2024 11:01:23 +0200 Subject: [PATCH 0554/1125] Update old options to new formats --- machines/SteamDeck/configuration.nix | 2 +- machines/WinMax2/configuration.nix | 4 ++-- roles/kde/plasma.nix | 8 +++++--- roles/kde/sddm.nix | 6 +++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index 6e0b86e..7c2af0a 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -45,7 +45,7 @@ enable = true; }; }; - services.xserver.displayManager.sddm.enable = lib.mkForce false; + services.displayManager.sddm.enable = lib.mkForce false; # Enable bluetooth hardware.bluetooth = { diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index f3a64c1..f8e13d9 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -69,8 +69,8 @@ # networking.proxy.default = "http://user:password@proxy:port/"; # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - services.xserver = { - xkb.layout = lib.mkForce "us"; + services = { + xserver.xkb.layout = lib.mkForce "us"; displayManager.sddm.settings = { General.GreeterEnvironment = "QT_SCREEN_SCALE_FACTORS=2"; }; diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index b88ff52..e382060 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -49,10 +49,12 @@ ''; }; in { - services.xserver = { - # Enable the Plasma 5 Desktop Environment - desktopManager.plasma5.enable = true; + services = { displayManager.defaultSession = "plasmawayland"; + xserver = { + # Enable the Plasma 5 Desktop Environment + desktopManager.plasma5.enable = true; + }; }; qt.enable = true; diff --git a/roles/kde/sddm.nix b/roles/kde/sddm.nix index 8fd3b6a..bc331d7 100644 --- a/roles/kde/sddm.nix +++ b/roles/kde/sddm.nix @@ -3,7 +3,7 @@ pkgs, ... }: let - currentTheme = config.services.xserver.displayManager.sddm.theme; + currentTheme = config.services.displayManager.sddm.theme; sddm-sugar-candy = pkgs.stdenv.mkDerivation { pname = "sddm-sugar-candy"; @@ -43,11 +43,11 @@ }; in { # Enable SDDM. - services.xserver.displayManager.sddm = { + services.displayManager.sddm = { enable = true; theme = "sugar-candy"; settings = { - General = {Numlock = "on";}; + General = {Numlock = "off";}; Theme = {CursorTheme = "Breeze_Snow";}; }; }; From 789c84fc3f212eb75e24190d69ac5854172d8f32 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Apr 2024 13:49:02 +0200 Subject: [PATCH 0555/1125] Common: add missing locales --- roles/common/configuration.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 8af3482..b370073 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -48,6 +48,11 @@ # Set up localisation i18n = { defaultLocale = "en_US.UTF-8"; + supportedLocales = [ + "es_US.UTF-8/UTF-8" + "es_ES.UTF-8/UTF-8" + "en_US.UTF-8/UTF-8" + ]; extraLocaleSettings = { LC_NUMERIC = "es_ES.UTF-8"; # am/pm is nice but mm/dd/yy is yucky From cb04535cbf0cf3690eb5a55e6d75fc427f6d4c12 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 13 Apr 2024 16:32:27 +0200 Subject: [PATCH 0556/1125] Machines/WinMax2: run hhd as root --- machines/WinMax2/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index f8e13d9..b4b1ef2 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -60,6 +60,7 @@ }; enable = true; user = "root"; + user = "toast"; }; # Allow unfree packages From 3ccdbe36c9ce122266770d029be689ccb0833ba7 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 13 Apr 2024 16:33:10 +0200 Subject: [PATCH 0557/1125] Flake: add patch to update hhd --- flake.nix | 1 + .../0001-handheld-daemon-1.1.0-2.6.2.patch | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch diff --git a/flake.nix b/flake.nix index a47a42f..24f9efa 100644 --- a/flake.nix +++ b/flake.nix @@ -81,6 +81,7 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ + ./nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch b/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch new file mode 100644 index 0000000..278be1f --- /dev/null +++ b/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch @@ -0,0 +1,61 @@ +From d9e4af9ae8ed30a1ab860915c5c0ff9ae0c16dc1 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Fri, 12 Apr 2024 13:32:24 +0200 +Subject: [PATCH 1/2] handheld-daemon: 1.1.0 -> 2.6.2 + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index bb0c9d65bfe19d..b5f25f339ffb60 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -8,14 +8,14 @@ + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "1.1.0"; ++ version = "2.6.2"; + pyproject = true; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + rev = "v${version}"; +- hash = "sha256-ovLC1BQ98jUaDEMPBzWma4TYSzTF+yE/cMemFdJmqlE="; ++ hash = "sha256-fsH8H6ZhiguOWI2t79GnxqAmqL/1m06RQzs+k8bUWcU="; + }; + + propagatedBuildInputs = with python3.pkgs; [ +@@ -26,6 +26,7 @@ python3.pkgs.buildPythonApplication rec { + rich + setuptools + toybox ++ xlib + ]; + + # This package doesn't have upstream tests. + +From 2a8d54c511bda43bea18d35d2c08f224f3352a18 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Sat, 13 Apr 2024 15:42:25 +0200 +Subject: [PATCH 2/2] handheld-daemon: update license + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index b5f25f339ffb60..f0ce6e9648e3e8 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -48,7 +48,7 @@ python3.pkgs.buildPythonApplication rec { + homepage = "https://github.com/hhd-dev/hhd/"; + description = "Linux support for handheld gaming devices like the Legion Go, ROG Ally, and GPD Win"; + platforms = platforms.linux; +- license = licenses.mit; ++ license = licenses.gpl3Only; + maintainers = with maintainers; [ appsforartists ]; + mainProgram = "hhd"; + }; From 70f9fdecddeaeee06c137ab9a87e4a48d570846f Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 13 Apr 2024 16:33:37 +0200 Subject: [PATCH 0558/1125] Machines/WinMax2: remove unneeded hhd override --- machines/WinMax2/configuration.nix | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index b4b1ef2..13ad8f8 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -49,17 +49,7 @@ ''; services.handheld-daemon = { - package = pkgs.handheld-daemon.overridePythonAttrs rec { - src = pkgs.fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - rev = "v${version}"; - hash = "sha256-Ujbou+f/EvHyqpp3FCNqIyZiCEFxSeQfflR3JmRxWFc="; - }; - version = "1.3.13"; - }; enable = true; - user = "root"; user = "toast"; }; From d4c3fc64f7aacc9881576d9619a36e7fe138efdd Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 14 Apr 2024 02:44:45 +0200 Subject: [PATCH 0559/1125] Justfile: get secrets with ssh --- .justfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.justfile b/.justfile index 252a267..8d0afb9 100644 --- a/.justfile +++ b/.justfile @@ -19,8 +19,8 @@ update-input input: nix flake lock --update-input {{input}} @edit-secrets: - git clone http://git.everest.sable-pancake.ts.net/Toast/nix-secrets.git /tmp/secrets - sed -i 's\git+http://git.everest.sable-pancake.ts.net/Toast/nix-secrets\/tmp/secrets\g' flake.nix + git clone ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets.git /tmp/secrets + sed -i 's\git+ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets\/tmp/secrets\g' flake.nix just -q update-input secrets echo "{{bold}}All done!" echo "{{normal}}Remember to restore flake.nix" From 5f776ae552d801e23138ea78275198da9e77cf00 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 14 Apr 2024 17:24:29 +0200 Subject: [PATCH 0560/1125] Flake: update secrets --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 7691036..6482a8d 100644 --- a/flake.lock +++ b/flake.lock @@ -377,11 +377,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1710238597, - "narHash": "sha256-N0CVdpIyAkofXIHS9SUuDS27gS5HiYue+i4CBtk9IqE=", + "lastModified": 1713107869, + "narHash": "sha256-TniJoCQfJ3OXrcqhH/8xcV6o4Sa5C/4KSRtk0c0/RK4=", "ref": "refs/heads/main", - "rev": "e05ec0b3a77ea7c2aecf699894cdabac1b377bab", - "revCount": 9, + "rev": "a00a07cd931b6eab722727a0606837cb895997f0", + "revCount": 11, "type": "git", "url": "ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets" }, From 5926168b3f59a50e2759312cea643b92374e5b64 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 14 Apr 2024 17:24:39 +0200 Subject: [PATCH 0561/1125] Desktop/NetworkManager: add wifi networks --- roles/desktop/services/networkmanager.nix | 46 ++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/roles/desktop/services/networkmanager.nix b/roles/desktop/services/networkmanager.nix index d56c81b..acf5834 100644 --- a/roles/desktop/services/networkmanager.nix +++ b/roles/desktop/services/networkmanager.nix @@ -1,11 +1,55 @@ -{config, ...}: let +{ + config, + flakeSelf, + ... +}: let tailscaleName = config.services.tailscale.interfaceName; in { + age.secrets = { + wifiPasswords.file = "${flakeSelf.inputs.secrets}/wifi-passwords.age"; + }; networking.networkmanager = { enable = true; unmanaged = [ "interface-name:${tailscaleName}" ]; wifi.macAddress = "random"; + ensureProfiles = { + environmentFiles = [config.age.secrets.wifiPasswords.path]; + profiles = { + "4g-modem" = { + connection = { + id = "4G Modem"; + type = "wifi"; + }; + ipv4.method = "auto"; + wifi = { + mode = "infrastructure"; + ssid = "TP-Link_CCB4"; + }; + wifi-security = { + auth-alg = "open"; + key-mgmt = "wpa-psk"; + psk = "$MODEM"; + }; + }; + phone = { + connection = { + id = "Phone"; + type = "wifi"; + }; + ipv4.method = "auto"; + wifi = { + mode = "infrastructure"; + ssid = "Redmi Note 10 Pro_5197"; + }; + wifi-security = { + auth-alg = "open"; + key-mgmt = "sae"; + psk = "$PHONE"; + }; + }; + }; + }; }; } From b014af78911d4f4a627175b61498bf12b5784350 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 15 Apr 2024 00:37:09 +0200 Subject: [PATCH 0562/1125] Flake: update nixpkgs patch --- .../0001-handheld-daemon-1.1.0-2.6.2.patch | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch b/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch index 278be1f..d620cfb 100644 --- a/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch +++ b/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch @@ -1,7 +1,7 @@ From d9e4af9ae8ed30a1ab860915c5c0ff9ae0c16dc1 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Fri, 12 Apr 2024 13:32:24 +0200 -Subject: [PATCH 1/2] handheld-daemon: 1.1.0 -> 2.6.2 +Subject: [PATCH 1/3] handheld-daemon: 1.1.0 -> 2.6.2 --- pkgs/by-name/ha/handheld-daemon/package.nix | 5 +++-- @@ -40,7 +40,7 @@ index bb0c9d65bfe19d..b5f25f339ffb60 100644 From 2a8d54c511bda43bea18d35d2c08f224f3352a18 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Sat, 13 Apr 2024 15:42:25 +0200 -Subject: [PATCH 2/2] handheld-daemon: update license +Subject: [PATCH 2/3] handheld-daemon: update license --- pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- @@ -59,3 +59,37 @@ index b5f25f339ffb60..f0ce6e9648e3e8 100644 maintainers = with maintainers; [ appsforartists ]; mainProgram = "hhd"; }; + +From 3b96a3c082f6b0e9f7e2eabcc18cf599a0c7eb63 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 15 Apr 2024 00:31:56 +0200 +Subject: [PATCH 3/3] handheld-daemon: patch generated udev rules to use chmod + from nix store + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index f0ce6e9648e3e8..72981284e2e9c1 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -5,6 +5,7 @@ + , lib + , python3 + , toybox ++, coreutils + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +@@ -38,6 +39,10 @@ python3.pkgs.buildPythonApplication rec { + hidapi=${ hidapi }/lib/ + test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } + sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py ++ ++ # The generated udev rules point to /bin/chroot, which does not exist in NixOS ++ chmod=${ coreutils }/bin/chmod ++ sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py + ''; + + postInstall = '' From b322c242cebc338d22b6497e448925da5975462a Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Apr 2024 10:41:51 +0200 Subject: [PATCH 0563/1125] Flake: update nixpkgs patch --- .../0001-handheld-daemon-1.1.0-2.6.2.patch | 96 ++++++++++++++++++- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch b/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch index d620cfb..0c72686 100644 --- a/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch +++ b/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch @@ -1,7 +1,7 @@ From d9e4af9ae8ed30a1ab860915c5c0ff9ae0c16dc1 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Fri, 12 Apr 2024 13:32:24 +0200 -Subject: [PATCH 1/3] handheld-daemon: 1.1.0 -> 2.6.2 +Subject: [PATCH 1/6] handheld-daemon: 1.1.0 -> 2.6.2 --- pkgs/by-name/ha/handheld-daemon/package.nix | 5 +++-- @@ -40,7 +40,7 @@ index bb0c9d65bfe19d..b5f25f339ffb60 100644 From 2a8d54c511bda43bea18d35d2c08f224f3352a18 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Sat, 13 Apr 2024 15:42:25 +0200 -Subject: [PATCH 2/3] handheld-daemon: update license +Subject: [PATCH 2/6] handheld-daemon: update license --- pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- @@ -63,7 +63,7 @@ index b5f25f339ffb60..f0ce6e9648e3e8 100644 From 3b96a3c082f6b0e9f7e2eabcc18cf599a0c7eb63 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Mon, 15 Apr 2024 00:31:56 +0200 -Subject: [PATCH 3/3] handheld-daemon: patch generated udev rules to use chmod +Subject: [PATCH 3/6] handheld-daemon: patch generated udev rules to use chmod from nix store --- @@ -93,3 +93,93 @@ index f0ce6e9648e3e8..72981284e2e9c1 100644 ''; postInstall = '' + +From 6a2060842db04c81b354b49a9c53bfd2262a5af3 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 15 Apr 2024 19:57:10 +0200 +Subject: [PATCH 4/6] handheld-daemon: remove unneeded coreutils dependency + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 72981284e2e9c1..835c0774469354 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -5,7 +5,6 @@ + , lib + , python3 + , toybox +-, coreutils + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +@@ -41,7 +40,7 @@ python3.pkgs.buildPythonApplication rec { + sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py + + # The generated udev rules point to /bin/chroot, which does not exist in NixOS +- chmod=${ coreutils }/bin/chmod ++ chmod=${ toybox }/bin/chmod + sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py + ''; + + +From c9e8b7cf0260618682c15f7ba601ec9827396ceb Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 15 Apr 2024 20:07:46 +0200 +Subject: [PATCH 5/6] handheld-daemon: move udev rule comment + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 835c0774469354..d79457057e392c 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -34,12 +34,12 @@ python3.pkgs.buildPythonApplication rec { + + # handheld-daemon contains a fork of the python module `hid`, so this hook + # is borrowed from the `hid` derivation. ++ # The generated udev rules point to /bin/chroot, which does not exist in NixOS + postPatch = '' + hidapi=${ hidapi }/lib/ + test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } + sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py + +- # The generated udev rules point to /bin/chroot, which does not exist in NixOS + chmod=${ toybox }/bin/chmod + sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py + ''; + +From 7bea1eb24a9e84b343c3944318e74ce3442ce40c Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 15 Apr 2024 20:32:43 +0200 +Subject: [PATCH 6/6] handheld-daemon: 2.6.2 -> 2.6.4 + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index d79457057e392c..7801038ea36669 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -8,14 +8,14 @@ + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "2.6.2"; ++ version = "2.6.4"; + pyproject = true; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + rev = "v${version}"; +- hash = "sha256-fsH8H6ZhiguOWI2t79GnxqAmqL/1m06RQzs+k8bUWcU="; ++ hash = "sha256-S77APtE1GGfqnv1IkZdJOSlprPOBtrqVXV60yVMvopg="; + }; + + propagatedBuildInputs = with python3.pkgs; [ From 384ecd5712b12a1002c31f27f8679859038460ca Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Apr 2024 10:14:43 +0200 Subject: [PATCH 0564/1125] Common/starship: update nerd font symbols preset --- roles/common/programs/starship.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index 527034a..8c9cfaa 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -11,7 +11,7 @@ with builtins; let presets = { nerdFontSymbols = pkgs.fetchurl { url = "https://starship.rs/presets/toml/nerd-font-symbols.toml"; - hash = "sha256-BVe5JMSIa3CoY2Wf9pvcF1EUtDVCWCLhW3IyKuwfHug="; + hash = "sha256-JKX+DKY4IPQwNj3znkhMUReNqbKBxdJyBZW+WCdKwuU="; }; }; # -------------------------------- F U N C T I O N S -------------------------------- From 5d644f095917def5a21700eda2de7fa6249d6825 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Apr 2024 11:27:35 +0200 Subject: [PATCH 0565/1125] Common/helix: use home-manager languages option --- roles/common/programs/helix.nix | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index c5ea603..38e7d22 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -25,17 +25,14 @@ indent-guides.render = true; }; }; - }; - # The builtin languages options have issues - # https://github.com/nix-community/home-manager/issues/3299 - xdg.configFile."helixLanguages" = { - target = "helix/languages.toml"; - text = '' - [language-server.nil] - config.nil.formatting.command = [ "nixpkgs-fmt" ] - [[language]] - name = "nix" - ''; + languages = { + language = [ + { + name = "nix"; + formatter.command = "nixpkgs-fmt"; + } + ]; + }; }; }; } From 544d1f6a226a0e1a69971308f8c9230c3d9a84ee Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Apr 2024 11:57:05 +0200 Subject: [PATCH 0566/1125] Common/helix: change nil lsp settings --- roles/common/programs/helix.nix | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index 38e7d22..e30d49a 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -1,4 +1,4 @@ -{pkgs, ...}: { +{pkgs, config, ...}: { home-manager.users.toast = { programs.helix = { enable = true; @@ -32,6 +32,14 @@ formatter.command = "nixpkgs-fmt"; } ]; + language-server.nil = { + config = { + flake = { + autoArchive = false; + autoEvalInputs = true; + }; + }; + }; }; }; }; From 1ac5d06ab273494eb80a2716f2bea9e541fe2dab Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Apr 2024 11:58:03 +0200 Subject: [PATCH 0567/1125] School/helix: add omnisharp to helix --- roles/school/programs/helix.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/school/programs/helix.nix b/roles/school/programs/helix.nix index f26c5d0..e16ddf0 100644 --- a/roles/school/programs/helix.nix +++ b/roles/school/programs/helix.nix @@ -3,6 +3,7 @@ programs.helix = { extraPackages = with pkgs; [ nodePackages.typescript-language-server + omnisharp-roslyn ]; }; }; From ed6067d43eebc2ff253e17cf26acbcc4938959b0 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Apr 2024 12:28:35 +0200 Subject: [PATCH 0568/1125] Flake: update nixpkgs patch --- .../0001-handheld-daemon-1.1.0-2.6.2.patch | 185 -------- .../0001-handheld-daemon-1.1.0-2.6.4.patch | 417 ++++++++++++++++++ 2 files changed, 417 insertions(+), 185 deletions(-) delete mode 100644 nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch create mode 100644 nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.4.patch diff --git a/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch b/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch deleted file mode 100644 index 0c72686..0000000 --- a/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch +++ /dev/null @@ -1,185 +0,0 @@ -From d9e4af9ae8ed30a1ab860915c5c0ff9ae0c16dc1 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Fri, 12 Apr 2024 13:32:24 +0200 -Subject: [PATCH 1/6] handheld-daemon: 1.1.0 -> 2.6.2 - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index bb0c9d65bfe19d..b5f25f339ffb60 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -8,14 +8,14 @@ - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "1.1.0"; -+ version = "2.6.2"; - pyproject = true; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - rev = "v${version}"; -- hash = "sha256-ovLC1BQ98jUaDEMPBzWma4TYSzTF+yE/cMemFdJmqlE="; -+ hash = "sha256-fsH8H6ZhiguOWI2t79GnxqAmqL/1m06RQzs+k8bUWcU="; - }; - - propagatedBuildInputs = with python3.pkgs; [ -@@ -26,6 +26,7 @@ python3.pkgs.buildPythonApplication rec { - rich - setuptools - toybox -+ xlib - ]; - - # This package doesn't have upstream tests. - -From 2a8d54c511bda43bea18d35d2c08f224f3352a18 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Sat, 13 Apr 2024 15:42:25 +0200 -Subject: [PATCH 2/6] handheld-daemon: update license - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index b5f25f339ffb60..f0ce6e9648e3e8 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -48,7 +48,7 @@ python3.pkgs.buildPythonApplication rec { - homepage = "https://github.com/hhd-dev/hhd/"; - description = "Linux support for handheld gaming devices like the Legion Go, ROG Ally, and GPD Win"; - platforms = platforms.linux; -- license = licenses.mit; -+ license = licenses.gpl3Only; - maintainers = with maintainers; [ appsforartists ]; - mainProgram = "hhd"; - }; - -From 3b96a3c082f6b0e9f7e2eabcc18cf599a0c7eb63 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 15 Apr 2024 00:31:56 +0200 -Subject: [PATCH 3/6] handheld-daemon: patch generated udev rules to use chmod - from nix store - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index f0ce6e9648e3e8..72981284e2e9c1 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -5,6 +5,7 @@ - , lib - , python3 - , toybox -+, coreutils - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -@@ -38,6 +39,10 @@ python3.pkgs.buildPythonApplication rec { - hidapi=${ hidapi }/lib/ - test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } - sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py -+ -+ # The generated udev rules point to /bin/chroot, which does not exist in NixOS -+ chmod=${ coreutils }/bin/chmod -+ sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py - ''; - - postInstall = '' - -From 6a2060842db04c81b354b49a9c53bfd2262a5af3 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 15 Apr 2024 19:57:10 +0200 -Subject: [PATCH 4/6] handheld-daemon: remove unneeded coreutils dependency - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 72981284e2e9c1..835c0774469354 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -5,7 +5,6 @@ - , lib - , python3 - , toybox --, coreutils - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -@@ -41,7 +40,7 @@ python3.pkgs.buildPythonApplication rec { - sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py - - # The generated udev rules point to /bin/chroot, which does not exist in NixOS -- chmod=${ coreutils }/bin/chmod -+ chmod=${ toybox }/bin/chmod - sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py - ''; - - -From c9e8b7cf0260618682c15f7ba601ec9827396ceb Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 15 Apr 2024 20:07:46 +0200 -Subject: [PATCH 5/6] handheld-daemon: move udev rule comment - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 835c0774469354..d79457057e392c 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -34,12 +34,12 @@ python3.pkgs.buildPythonApplication rec { - - # handheld-daemon contains a fork of the python module `hid`, so this hook - # is borrowed from the `hid` derivation. -+ # The generated udev rules point to /bin/chroot, which does not exist in NixOS - postPatch = '' - hidapi=${ hidapi }/lib/ - test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } - sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py - -- # The generated udev rules point to /bin/chroot, which does not exist in NixOS - chmod=${ toybox }/bin/chmod - sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py - ''; - -From 7bea1eb24a9e84b343c3944318e74ce3442ce40c Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 15 Apr 2024 20:32:43 +0200 -Subject: [PATCH 6/6] handheld-daemon: 2.6.2 -> 2.6.4 - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index d79457057e392c..7801038ea36669 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -8,14 +8,14 @@ - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "2.6.2"; -+ version = "2.6.4"; - pyproject = true; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - rev = "v${version}"; -- hash = "sha256-fsH8H6ZhiguOWI2t79GnxqAmqL/1m06RQzs+k8bUWcU="; -+ hash = "sha256-S77APtE1GGfqnv1IkZdJOSlprPOBtrqVXV60yVMvopg="; - }; - - propagatedBuildInputs = with python3.pkgs; [ diff --git a/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.4.patch b/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.4.patch new file mode 100644 index 0000000..ed37f7a --- /dev/null +++ b/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.4.patch @@ -0,0 +1,417 @@ +From d9e4af9ae8ed30a1ab860915c5c0ff9ae0c16dc1 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Fri, 12 Apr 2024 13:32:24 +0200 +Subject: [PATCH 01/13] handheld-daemon: 1.1.0 -> 2.6.2 + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index bb0c9d65bfe19d..b5f25f339ffb60 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -8,14 +8,14 @@ + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "1.1.0"; ++ version = "2.6.2"; + pyproject = true; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + rev = "v${version}"; +- hash = "sha256-ovLC1BQ98jUaDEMPBzWma4TYSzTF+yE/cMemFdJmqlE="; ++ hash = "sha256-fsH8H6ZhiguOWI2t79GnxqAmqL/1m06RQzs+k8bUWcU="; + }; + + propagatedBuildInputs = with python3.pkgs; [ +@@ -26,6 +26,7 @@ python3.pkgs.buildPythonApplication rec { + rich + setuptools + toybox ++ xlib + ]; + + # This package doesn't have upstream tests. + +From 2a8d54c511bda43bea18d35d2c08f224f3352a18 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Sat, 13 Apr 2024 15:42:25 +0200 +Subject: [PATCH 02/13] handheld-daemon: update license + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index b5f25f339ffb60..f0ce6e9648e3e8 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -48,7 +48,7 @@ python3.pkgs.buildPythonApplication rec { + homepage = "https://github.com/hhd-dev/hhd/"; + description = "Linux support for handheld gaming devices like the Legion Go, ROG Ally, and GPD Win"; + platforms = platforms.linux; +- license = licenses.mit; ++ license = licenses.gpl3Only; + maintainers = with maintainers; [ appsforartists ]; + mainProgram = "hhd"; + }; + +From 3b96a3c082f6b0e9f7e2eabcc18cf599a0c7eb63 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 15 Apr 2024 00:31:56 +0200 +Subject: [PATCH 03/13] handheld-daemon: patch generated udev rules to use + chmod from nix store + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index f0ce6e9648e3e8..72981284e2e9c1 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -5,6 +5,7 @@ + , lib + , python3 + , toybox ++, coreutils + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +@@ -38,6 +39,10 @@ python3.pkgs.buildPythonApplication rec { + hidapi=${ hidapi }/lib/ + test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } + sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py ++ ++ # The generated udev rules point to /bin/chroot, which does not exist in NixOS ++ chmod=${ coreutils }/bin/chmod ++ sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py + ''; + + postInstall = '' + +From 6a2060842db04c81b354b49a9c53bfd2262a5af3 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 15 Apr 2024 19:57:10 +0200 +Subject: [PATCH 04/13] handheld-daemon: remove unneeded coreutils dependency + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 72981284e2e9c1..835c0774469354 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -5,7 +5,6 @@ + , lib + , python3 + , toybox +-, coreutils + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +@@ -41,7 +40,7 @@ python3.pkgs.buildPythonApplication rec { + sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py + + # The generated udev rules point to /bin/chroot, which does not exist in NixOS +- chmod=${ coreutils }/bin/chmod ++ chmod=${ toybox }/bin/chmod + sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py + ''; + + +From c9e8b7cf0260618682c15f7ba601ec9827396ceb Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 15 Apr 2024 20:07:46 +0200 +Subject: [PATCH 05/13] handheld-daemon: move udev rule comment + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 835c0774469354..d79457057e392c 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -34,12 +34,12 @@ python3.pkgs.buildPythonApplication rec { + + # handheld-daemon contains a fork of the python module `hid`, so this hook + # is borrowed from the `hid` derivation. ++ # The generated udev rules point to /bin/chroot, which does not exist in NixOS + postPatch = '' + hidapi=${ hidapi }/lib/ + test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } + sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py + +- # The generated udev rules point to /bin/chroot, which does not exist in NixOS + chmod=${ toybox }/bin/chmod + sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py + ''; + +From 7bea1eb24a9e84b343c3944318e74ce3442ce40c Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 15 Apr 2024 20:32:43 +0200 +Subject: [PATCH 06/13] handheld-daemon: 2.6.2 -> 2.6.4 + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index d79457057e392c..7801038ea36669 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -8,14 +8,14 @@ + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "2.6.2"; ++ version = "2.6.4"; + pyproject = true; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + rev = "v${version}"; +- hash = "sha256-fsH8H6ZhiguOWI2t79GnxqAmqL/1m06RQzs+k8bUWcU="; ++ hash = "sha256-S77APtE1GGfqnv1IkZdJOSlprPOBtrqVXV60yVMvopg="; + }; + + propagatedBuildInputs = with python3.pkgs; [ + +From b510c5a603c7f2193a4f1c10e03bac6f7f361584 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 15 Apr 2024 21:30:51 +0200 +Subject: [PATCH 07/13] handheld-daemon: move udev rule comment to the right + place this time + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 7801038ea36669..4189bf0483b973 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -32,14 +32,14 @@ python3.pkgs.buildPythonApplication rec { + # This package doesn't have upstream tests. + doCheck = false; + +- # handheld-daemon contains a fork of the python module `hid`, so this hook +- # is borrowed from the `hid` derivation. +- # The generated udev rules point to /bin/chroot, which does not exist in NixOS + postPatch = '' ++ # handheld-daemon contains a fork of the python module `hid`, so this hook ++ # is borrowed from the `hid` derivation. + hidapi=${ hidapi }/lib/ + test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } + sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py + ++ # The generated udev rules point to /bin/chroot, which does not exist in NixOS + chmod=${ toybox }/bin/chmod + sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py + ''; + +From f7b450a4d83aec36be9c1576cb69b92c7895b33d Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 15 Apr 2024 21:38:38 +0200 +Subject: [PATCH 08/13] handheld-daemon: fix typo in comment + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 4189bf0483b973..5087698c793430 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -39,7 +39,7 @@ python3.pkgs.buildPythonApplication rec { + test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } + sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py + +- # The generated udev rules point to /bin/chroot, which does not exist in NixOS ++ # The generated udev rules point to /bin/chmod, which does not exist in NixOS + chmod=${ toybox }/bin/chmod + sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py + ''; + +From a581a28a074a3a8bad48ba2883a320bfb02a5062 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Tue, 16 Apr 2024 19:50:25 +0200 +Subject: [PATCH 09/13] handheld-daemon: format with nixfmt-rfc-style + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 5087698c793430..52b5729bc6f300 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -1,10 +1,11 @@ +-{ config +-, fetchFromGitHub +-, hidapi +-, kmod +-, lib +-, python3 +-, toybox ++{ ++ config, ++ fetchFromGitHub, ++ hidapi, ++ kmod, ++ lib, ++ python3, ++ toybox, + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +@@ -35,12 +36,12 @@ python3.pkgs.buildPythonApplication rec { + postPatch = '' + # handheld-daemon contains a fork of the python module `hid`, so this hook + # is borrowed from the `hid` derivation. +- hidapi=${ hidapi }/lib/ ++ hidapi=${hidapi}/lib/ + test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } + sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py + + # The generated udev rules point to /bin/chmod, which does not exist in NixOS +- chmod=${ toybox }/bin/chmod ++ chmod=${toybox}/bin/chmod + sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py + ''; + + +From d9b7086a02c8b6a156438d88d86903218907aa9e Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Tue, 16 Apr 2024 20:15:21 +0200 +Subject: [PATCH 10/13] handheld-daemon: replace sed commands with + substituteInPlace + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 52b5729bc6f300..356130ec54e07e 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -34,15 +34,17 @@ python3.pkgs.buildPythonApplication rec { + doCheck = false; + + postPatch = '' ++ # The generated udev rules point to /bin/chmod, which does not exist in NixOS ++ substituteInPlace src/hhd/controller/lib/hide.py \ ++ --replace-fail /bin/chmod ${toybox}/bin/chmod ++ + # handheld-daemon contains a fork of the python module `hid`, so this hook + # is borrowed from the `hid` derivation. ++ substituteInPlace src/hhd/controller/lib/hid.py \ ++ --replace-fail libhidapi ${hidapi}/lib/libhidapi ++ + hidapi=${hidapi}/lib/ + test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } +- sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py +- +- # The generated udev rules point to /bin/chmod, which does not exist in NixOS +- chmod=${toybox}/bin/chmod +- sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py + ''; + + postInstall = '' + +From 20753a73d1a20cf5b67bc7cc51572807c0eda9fc Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Tue, 16 Apr 2024 20:29:56 +0200 +Subject: [PATCH 11/13] handheld-daemon: trim out trailing whitespace + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index b734034a439dab..db6c46a7e8055c 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -41,9 +41,9 @@ python3.pkgs.buildPythonApplication rec { + # handheld-daemon contains a fork of the python module `hid`, so this hook + # is borrowed from the `hid` derivation. + substituteInPlace src/hhd/controller/lib/hid.py \ +- --replace-fail libhidapi ${hidapi}/lib/libhidapi +- +- hidapi=${hidapi}/lib/ ++ --replace-fail libhidapi ${hidapi}/lib/libhidapi ++ ++ hidapi=${hidapi}/lib/ + test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } + ''; + + +From cb2fa9a66110a6deb4f66c2dfd146b2895f932bd Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Tue, 16 Apr 2024 21:04:48 +0200 +Subject: [PATCH 12/13] handheld-daemon: fix indenting + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index db6c46a7e8055c..ad0554bec36d52 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -41,9 +41,9 @@ python3.pkgs.buildPythonApplication rec { + # handheld-daemon contains a fork of the python module `hid`, so this hook + # is borrowed from the `hid` derivation. + substituteInPlace src/hhd/controller/lib/hid.py \ +- --replace-fail libhidapi ${hidapi}/lib/libhidapi ++ --replace-fail libhidapi ${hidapi}/lib/libhidapi + +- hidapi=${hidapi}/lib/ ++ hidapi=${hidapi}/lib/ + test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } + ''; + + +From d9b487ae609a368378c1a9d89a5441c5c44121df Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Wed, 17 Apr 2024 09:19:43 +0200 +Subject: [PATCH 13/13] handheld-daemon: undo refactor + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index ad0554bec36d52..246e3879bb5cfa 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -34,17 +34,15 @@ python3.pkgs.buildPythonApplication rec { + doCheck = false; + + postPatch = '' +- # The generated udev rules point to /bin/chmod, which does not exist in NixOS +- substituteInPlace src/hhd/controller/lib/hide.py \ +- --replace-fail /bin/chmod ${toybox}/bin/chmod +- + # handheld-daemon contains a fork of the python module `hid`, so this hook + # is borrowed from the `hid` derivation. +- substituteInPlace src/hhd/controller/lib/hid.py \ +- --replace-fail libhidapi ${hidapi}/lib/libhidapi +- + hidapi=${hidapi}/lib/ + test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } ++ sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py ++ ++ # The generated udev rules point to /bin/chmod, which does not exist in NixOS ++ chmod=${toybox}/bin/chmod ++ sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py + ''; + + postInstall = '' From 335c97864e2f30a226c0494357766b127093dca5 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Apr 2024 12:35:59 +0200 Subject: [PATCH 0569/1125] Flake: update lock file --- flake.lock | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/flake.lock b/flake.lock index 6482a8d..b11e227 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1712890104, - "narHash": "sha256-56RS7wdJ2QDUNCQt/9lx8MFcwuTdVQnzBV+9QToLLmM=", + "lastModified": 1713323853, + "narHash": "sha256-EfUm65RRsoch0tpfHZtEyqo+iWIYhuSX39U/fi0/4WU=", "owner": "catppuccin", "repo": "nix", - "rev": "850c26a3a2474b0d068abc89c905f536cca415de", + "rev": "372decb578f3187d7aad837885ed98e73e8abd60", "type": "github" }, "original": { @@ -45,11 +45,11 @@ ] }, "locked": { - "lastModified": 1710544781, - "narHash": "sha256-nkxihb3D85k1nZV1CzlB3seMKtTEeKb688sblIGp/Bs=", + "lastModified": 1713319998, + "narHash": "sha256-qigmP08byrOEAnvRC0aP+mxWGlXOlNgtvkDUnUblr8k=", "owner": "catppuccin", "repo": "vscode", - "rev": "d7b96ccac36fd29929bd97bc9357413cc4e0240c", + "rev": "15977cc2446fa661a228891a18125d0b6b9ed012", "type": "github" }, "original": { @@ -120,11 +120,11 @@ ] }, "locked": { - "lastModified": 1712759992, - "narHash": "sha256-2APpO3ZW4idlgtlb8hB04u/rmIcKA8O7pYqxF66xbNY=", + "lastModified": 1713294767, + "narHash": "sha256-LmaabaQZdx52MPGKPRt9Opoc9Gd9RbwvCdysUUYQoXI=", "owner": "nix-community", "repo": "home-manager", - "rev": "31357486b0ef6f4e161e002b6893eeb4fafc3ca9", + "rev": "fa8c16e2452bf092ac76f09ee1fb1e9f7d0796e7", "type": "github" }, "original": { @@ -162,11 +162,11 @@ ] }, "locked": { - "lastModified": 1712909442, - "narHash": "sha256-D+VrmsPLkEbxNcI7lp9rGFR33RumbQIyhhjJ4PooWBs=", + "lastModified": 1713333160, + "narHash": "sha256-iz4Uz3vykqsZwIY2hxEMfRrc1DvBgxHVCfSxppuj40s=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "8886e3da78fcefb11935ea85da3d1572bf444c55", + "rev": "d3ce25a385ec7ed899ffb282d1e54ccb4ac9ef0d", "type": "github" }, "original": { @@ -235,11 +235,11 @@ ] }, "locked": { - "lastModified": 1712459390, - "narHash": "sha256-e12bNDottaGoBgd0AdH/bQvk854xunlWAdZwr/oHO1c=", + "lastModified": 1713067146, + "narHash": "sha256-9D20xjblGKEVRVCnM3qWhiizEa9i6OpK6xQJajwcwOQ=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "4676d72d872459e1e3a248d049609f110c570e9a", + "rev": "93aed67288be60c9ef6133ba2f8de128f4ef265c", "type": "github" }, "original": { @@ -255,11 +255,11 @@ ] }, "locked": { - "lastModified": 1712459390, - "narHash": "sha256-e12bNDottaGoBgd0AdH/bQvk854xunlWAdZwr/oHO1c=", + "lastModified": 1713067146, + "narHash": "sha256-9D20xjblGKEVRVCnM3qWhiizEa9i6OpK6xQJajwcwOQ=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "4676d72d872459e1e3a248d049609f110c570e9a", + "rev": "93aed67288be60c9ef6133ba2f8de128f4ef265c", "type": "github" }, "original": { @@ -270,11 +270,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1712760404, - "narHash": "sha256-4zhaEW1nB+nGbCNMjOggWeY5nXs/H0Y71q0+h+jdxoU=", + "lastModified": 1712909959, + "narHash": "sha256-7/5ubuwdEbQ7Z+Vqd4u0mM5L2VMNDsBh54visp27CtQ=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "e1c4bac14beb8c409d0534382cf967171706b9d9", + "rev": "f58b25254be441cd2a9b4b444ed83f1e51244f1f", "type": "github" }, "original": { @@ -286,11 +286,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1712741485, - "narHash": "sha256-bCs0+MSTra80oXAsnM6Oq62WsirOIaijQ/BbUY59tR4=", + "lastModified": 1713145326, + "narHash": "sha256-m7+IWM6mkWOg22EC5kRUFCycXsXLSU7hWmHdmBfmC3s=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b2cf36f43f9ef2ded5711b30b1f393ac423d8f72", + "rev": "53a2c32bc66f5ae41a28d7a9a49d321172af621e", "type": "github" }, "original": { @@ -301,11 +301,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1712791164, - "narHash": "sha256-3sbWO1mbpWsLepZGbWaMovSO7ndZeFqDSdX0hZ9nVyw=", + "lastModified": 1713248628, + "narHash": "sha256-NLznXB5AOnniUtZsyy/aPWOk8ussTuePp2acb9U+ISA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1042fd8b148a9105f3c0aca3a6177fd1d9360ba5", + "rev": "5672bc9dbf9d88246ddab5ac454e82318d094bb8", "type": "github" }, "original": { @@ -316,11 +316,11 @@ }, "nur": { "locked": { - "lastModified": 1712906890, - "narHash": "sha256-MkhmSqGqQ5cDa1VzqkA76h6+9rYCY2IJzSRglNV+Vr4=", + "lastModified": 1713347163, + "narHash": "sha256-ElGPXN2CwsBn/f8yQuRx9Xtplnu/xX3gkuc84QhRTtg=", "owner": "nix-community", "repo": "NUR", - "rev": "0fb8bccadea16d13d87210c21fbae09b26c28e07", + "rev": "8848aa88dc8b9cfe4e9129b7fa06f47f9f2f5dbc", "type": "github" }, "original": { @@ -429,11 +429,11 @@ ] }, "locked": { - "lastModified": 1712884817, - "narHash": "sha256-zs8oMnWHg3g0P+3ZsEj69m9aZCrGa/bqZUHRV9sF0w0=", + "lastModified": 1713316726, + "narHash": "sha256-VIQkEgU1xUD4nEh7w3uL0xRsTYZdC7p5+v35G9wv8U0=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "882c461b61050a266fe9bc8d93d342f24b54250f", + "rev": "c1b75aedd50054ff43bb26ddb2702a2ac3475ea2", "type": "github" }, "original": { From 4964354f8cc03390851cd1134df25c4c90bb5884 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Apr 2024 12:36:08 +0200 Subject: [PATCH 0570/1125] School/mongodb: update to mongo 5.0 --- roles/school/services/mongodb.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/school/services/mongodb.nix b/roles/school/services/mongodb.nix index 75f7c7a..42c12fc 100644 --- a/roles/school/services/mongodb.nix +++ b/roles/school/services/mongodb.nix @@ -6,7 +6,7 @@ }: { services.mongodb = { enable = true; - package = pkgs.mongodb-4_4; + package = pkgs.mongodb-5_0; user = "toast"; }; From 35235b004baf828aa80373c6eddec3061d983bbb Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Apr 2024 12:39:44 +0200 Subject: [PATCH 0571/1125] Flake: update nixpkgs patch name --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 24f9efa..71fc945 100644 --- a/flake.nix +++ b/flake.nix @@ -81,7 +81,7 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.2.patch + ./nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.4.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { From e01b542bb549fc902cb9a5f4966e9a57e3c7c56a Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 18 Apr 2024 09:36:18 +0200 Subject: [PATCH 0572/1125] Desktop: add appimage support --- roles/desktop/programs/appimage.nix | 6 ++++++ roles/desktop/programs/default.nix | 1 + 2 files changed, 7 insertions(+) create mode 100644 roles/desktop/programs/appimage.nix diff --git a/roles/desktop/programs/appimage.nix b/roles/desktop/programs/appimage.nix new file mode 100644 index 0000000..7e90c2e --- /dev/null +++ b/roles/desktop/programs/appimage.nix @@ -0,0 +1,6 @@ +{...}: { + programs.appimage = { + enable = true; + binfmt = true; + }; +} diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix index 6a06ba2..7bceb47 100755 --- a/roles/desktop/programs/default.nix +++ b/roles/desktop/programs/default.nix @@ -8,5 +8,6 @@ ./vscode.nix ./git.nix ./ssh.nix + ./appimage.nix ]; } From 0a5226d6fdd1ca9451d8771f5ecd8d000d88ec28 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Apr 2024 09:31:56 +0200 Subject: [PATCH 0573/1125] School/jetbrains: enable javafx for jdk17 --- roles/school/programs/jetbrains.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/roles/school/programs/jetbrains.nix b/roles/school/programs/jetbrains.nix index ecf5c90..69be716 100644 --- a/roles/school/programs/jetbrains.nix +++ b/roles/school/programs/jetbrains.nix @@ -11,6 +11,8 @@ with pkgs; { This adds the jdks I want to use to a directory intellij expects jdks to be */ home.file.".jdks/jdk8".source = "${pkgs.jdk8}/lib/openjdk"; - home.file.".jdks/jdk17".source = "${pkgs.jdk17}/lib/openjdk"; + home.file.".jdks/jdk17".source = let + jdk17 = pkgs.jdk17.override { enableJavaFX = true; }; + in "${jdk17}/lib/openjdk"; }; } From 120583cea752ea19d2998939b1d04f77df0eef88 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Apr 2024 09:40:17 +0200 Subject: [PATCH 0574/1125] Flake: add formatter --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 71fc945..0b503c5 100644 --- a/flake.nix +++ b/flake.nix @@ -96,6 +96,7 @@ nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs {self = inputs.self;}; nixpkgs = (import "${nixpkgs-patched}/flake.nix").outputs {self = inputs.self;}; in { + formatter.x86_64-linux = nixpkgs-unstable.legacyPackages.x86_64-linux.alejandra; devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { name = "toast-devshell"; # The agenix cli is not needed to activate a configuration, so instead of installing it From 08824dddf310513e689d41c655dcf6d2280a87c3 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Apr 2024 09:48:12 +0200 Subject: [PATCH 0575/1125] Apply formatting --- machines/WinMax2/configuration.nix | 2 +- roles/common/programs/helix.nix | 6 +++++- roles/school/programs/jetbrains.nix | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 13ad8f8..65f51ff 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -114,7 +114,7 @@ comment = "Application for managing and playing games on Steam"; }; }; - programs.plasma.input.keyboard.layouts = lib.mkForce [ "us" ]; + programs.plasma.input.keyboard.layouts = lib.mkForce ["us"]; } ]; diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index e30d49a..553e7f8 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -1,4 +1,8 @@ -{pkgs, config, ...}: { +{ + pkgs, + config, + ... +}: { home-manager.users.toast = { programs.helix = { enable = true; diff --git a/roles/school/programs/jetbrains.nix b/roles/school/programs/jetbrains.nix index 69be716..fb67cf5 100644 --- a/roles/school/programs/jetbrains.nix +++ b/roles/school/programs/jetbrains.nix @@ -12,7 +12,7 @@ with pkgs; { */ home.file.".jdks/jdk8".source = "${pkgs.jdk8}/lib/openjdk"; home.file.".jdks/jdk17".source = let - jdk17 = pkgs.jdk17.override { enableJavaFX = true; }; + jdk17 = pkgs.jdk17.override {enableJavaFX = true;}; in "${jdk17}/lib/openjdk"; }; } From 2481e03a87b04e954682bf49a40e8b0fee303530 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Apr 2024 12:31:05 +0200 Subject: [PATCH 0576/1125] Justfile: build with nom --- .justfile | 2 +- flake.nix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.justfile b/.justfile index 8d0afb9..c03f8d8 100644 --- a/.justfile +++ b/.justfile @@ -30,7 +30,7 @@ update-input input: alias build := build-nixos # Build a NixOS configuration build-nixos host=`hostname`: - nixos-rebuild build --flake .#{{host}} + nom build .#nixosConfigurations.{{host}}.config.system.build.toplevel # nix-diff with some parameters piped to less nix-diff left right: diff --git a/flake.nix b/flake.nix index 0b503c5..a233781 100644 --- a/flake.nix +++ b/flake.nix @@ -104,6 +104,7 @@ packages = with nixpkgs.legacyPackages.x86_64-linux; [ agenix.packages.x86_64-linux.default git + nix-output-monitor nix-diff just alejandra From 228cbf373480b5c2d90823d43699952727a8fa3c Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Apr 2024 23:48:47 +0200 Subject: [PATCH 0577/1125] Flake: update lock file --- flake.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/flake.lock b/flake.lock index b11e227..f412779 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1713323853, - "narHash": "sha256-EfUm65RRsoch0tpfHZtEyqo+iWIYhuSX39U/fi0/4WU=", + "lastModified": 1713552048, + "narHash": "sha256-RcDJNnxjG9MTQHV/yG7JwPzffFub0JrwP2C1m6LxWFc=", "owner": "catppuccin", "repo": "nix", - "rev": "372decb578f3187d7aad837885ed98e73e8abd60", + "rev": "29bd8a3bda02434bf6ee3edf9ea6edd360a9ce17", "type": "github" }, "original": { @@ -45,11 +45,11 @@ ] }, "locked": { - "lastModified": 1713319998, - "narHash": "sha256-qigmP08byrOEAnvRC0aP+mxWGlXOlNgtvkDUnUblr8k=", + "lastModified": 1713403580, + "narHash": "sha256-VP3AiTLL40Zhr+99SwKjIE+ifRy/elhvGIF5W92J+fs=", "owner": "catppuccin", "repo": "vscode", - "rev": "15977cc2446fa661a228891a18125d0b6b9ed012", + "rev": "4dd5fa89173bc931e882f21da0de1609f1db9f39", "type": "github" }, "original": { @@ -120,11 +120,11 @@ ] }, "locked": { - "lastModified": 1713294767, - "narHash": "sha256-LmaabaQZdx52MPGKPRt9Opoc9Gd9RbwvCdysUUYQoXI=", + "lastModified": 1713547559, + "narHash": "sha256-zju60y4pyYQoRmqhbgkw+jwmKZReVsCNvb8mZxID2Do=", "owner": "nix-community", "repo": "home-manager", - "rev": "fa8c16e2452bf092ac76f09ee1fb1e9f7d0796e7", + "rev": "938357cb234e85da37109df2cdd9cc59ab9c1cc0", "type": "github" }, "original": { @@ -270,11 +270,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1712909959, - "narHash": "sha256-7/5ubuwdEbQ7Z+Vqd4u0mM5L2VMNDsBh54visp27CtQ=", + "lastModified": 1713521961, + "narHash": "sha256-EwR8wW9AqJhSIY+0oxWRybUZ32BVKuZ9bjlRh8SJvQ8=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "f58b25254be441cd2a9b4b444ed83f1e51244f1f", + "rev": "5d48925b815fd202781bfae8fb6f45c07112fdb2", "type": "github" }, "original": { @@ -316,11 +316,11 @@ }, "nur": { "locked": { - "lastModified": 1713347163, - "narHash": "sha256-ElGPXN2CwsBn/f8yQuRx9Xtplnu/xX3gkuc84QhRTtg=", + "lastModified": 1713555937, + "narHash": "sha256-ttraBb8XI/iTe0Q6hBTj/W8e+TvsPLACxdw693Gd3hQ=", "owner": "nix-community", "repo": "NUR", - "rev": "8848aa88dc8b9cfe4e9129b7fa06f47f9f2f5dbc", + "rev": "41c9fdae65031c6eaeab1c0a331c0eb9a32376c4", "type": "github" }, "original": { @@ -429,11 +429,11 @@ ] }, "locked": { - "lastModified": 1713316726, - "narHash": "sha256-VIQkEgU1xUD4nEh7w3uL0xRsTYZdC7p5+v35G9wv8U0=", + "lastModified": 1713549455, + "narHash": "sha256-wMHTvhl7Yl+nNVspchN7e337DBAM2LhHlcHnfAPhGEY=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "c1b75aedd50054ff43bb26ddb2702a2ac3475ea2", + "rev": "15529741a0f9c2b90a725ef5eb2262468a2f40a6", "type": "github" }, "original": { From 4ea69cf70d3d503c01d4608168d897c7eec9eca6 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 22 Apr 2024 09:26:41 +0200 Subject: [PATCH 0578/1125] Server/ssh: use dns for resolving hosts --- roles/server/ssh.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/ssh.nix b/roles/server/ssh.nix index ede04a3..db08e03 100755 --- a/roles/server/ssh.nix +++ b/roles/server/ssh.nix @@ -2,6 +2,7 @@ services.openssh = { enable = true; settings = { + UseDns = true; PermitRootLogin = "no"; PasswordAuthentication = false; }; From a3d1a8a744f9f96395b318f03dba21b99a61565a Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 22 Apr 2024 11:20:20 +0200 Subject: [PATCH 0579/1125] Flake: update secrets --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index f412779..47c2782 100644 --- a/flake.lock +++ b/flake.lock @@ -377,11 +377,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1713107869, - "narHash": "sha256-TniJoCQfJ3OXrcqhH/8xcV6o4Sa5C/4KSRtk0c0/RK4=", + "lastModified": 1713776544, + "narHash": "sha256-EQW8P1TfkYQV0EEK1n3Gh9wRp9KlC0EbidH2j+niCaE=", "ref": "refs/heads/main", - "rev": "a00a07cd931b6eab722727a0606837cb895997f0", - "revCount": 11, + "rev": "61410d68f15b3b970067a3fdd39667fdd9a89edd", + "revCount": 12, "type": "git", "url": "ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets" }, From befadf8ed215431ad7529a08e77eabf293328ab9 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 22 Apr 2024 11:25:43 +0200 Subject: [PATCH 0580/1125] Server/ssh: add ssh host key --- roles/server/ssh.nix | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/roles/server/ssh.nix b/roles/server/ssh.nix index db08e03..14ee0b6 100755 --- a/roles/server/ssh.nix +++ b/roles/server/ssh.nix @@ -1,4 +1,23 @@ -{...}: { +{ + flakeSelf, + config, + ... +}: let + hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName + "/"; + hostKeyPath = "/etc/ssh/everest_host_key"; +in { + age.secrets = { + everest-host-key = { + file = hostSecrets + "host-private-key.age"; + path = hostKeyPath; + mode = "0400"; + }; + "everest-host-key.pub" = { + file = hostSecrets + "host-public-key.age"; + path = hostKeyPath + ".pub"; + }; + }; + services.openssh = { enable = true; settings = { @@ -6,6 +25,13 @@ PermitRootLogin = "no"; PasswordAuthentication = false; }; + hostKeys = [ + { + path = hostKeyPath; + type = "ed25519"; + comment = "Everest host key"; + } + ]; startWhenNeeded = true; }; } From 2730ed6cdc94297b4bc7b97f04845e84659272d7 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 22 Apr 2024 09:42:19 +0200 Subject: [PATCH 0581/1125] School/jetbrains: install scenebuilder --- roles/school/programs/jetbrains.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/school/programs/jetbrains.nix b/roles/school/programs/jetbrains.nix index fb67cf5..57fe938 100644 --- a/roles/school/programs/jetbrains.nix +++ b/roles/school/programs/jetbrains.nix @@ -2,6 +2,7 @@ with pkgs; { environment.systemPackages = with jetbrains; [ idea-ultimate + scenebuilder datagrip ]; From 7cba5baa6397c5cb0c8c3d0bcb93e049d804a18b Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 22 Apr 2024 14:12:06 +0200 Subject: [PATCH 0582/1125] Desktop/ssh: add known hosts --- roles/desktop/programs/ssh.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/roles/desktop/programs/ssh.nix b/roles/desktop/programs/ssh.nix index 86f1b2d..b6e4dff 100644 --- a/roles/desktop/programs/ssh.nix +++ b/roles/desktop/programs/ssh.nix @@ -1,4 +1,14 @@ {...}: { + programs.ssh.knownHosts = { + everest = { + hostNames = [ + "everest.sable-pancake.ts.net" + "toast003.xyz" + ]; + publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAqfABZKnF5YYGZTOKuT7m+sOnUqBQSvLke9c3JDsF5s"; + }; + }; + home-manager.users.toast = { programs.ssh = { enable = true; From 56c81782bad693fee1096c8839a7e3515b6d0d16 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 22 Apr 2024 22:16:09 +0200 Subject: [PATCH 0583/1125] Machines/Everest: remove unused ssh public keys --- machines/Everest/configuration.nix | 4 ---- 1 file changed, 4 deletions(-) diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index c85e788..fdacf1b 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -38,10 +38,6 @@ # Define a user account. Don't forget to set a password with ‘passwd’. users.users.toast = { extraGroups = ["networkmanager" "transmission"]; - openssh.authorizedKeys.keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2bOVmxUNvg9qFv9DlzMmTRlzcNsyNq1F1wBuAXySwsWAzHGaO+WGdSCINxW3k2ccXn7M/o1r89LeTzRzi8sWQYCpBaIqYVszM/r7SvTS4gASyKhM6lNlyUEPOnvCXH7rdtF+fjoA1TJPv7GBk78QRhGh+eVO3qhY1m++5C1CPFlyrc6sSfgIBQJ5GQZFl/7YEgsrPo+M+0Sd7LkaCOyNmJA0Wi0BA3bbf5sJhrZVMMg/p7w+eMphz2kd1VTVjW3yeMq9zLCiu4SOTBNGCMEvKIdUZbQ83lNrqO2z1/3T1bDwJgpz3xusfkNCeNJSmhfFw5ydHEUp/9jshq38WmulKAMw2Kl/Zed62AVU7Ux7YjUkZkWvo8i3eXuLUxoG891S7cWV1/ijs9QMajOLLT14FG7RbzUYYaYlx+/iNGji9d4sp9/oMYyO45TMe+vEezFSBygP7TY0QFOr4xTi49ZRQFsszbFnGRv+k3wVKoGoeNt0xWB8pBEPFtaeHJpQyJX8= id_rsa_moon" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOeu3crGqtxwaqgoQPt5mWlC8+PL/Icvcvo0MBAaK80L Key for work laptop" - ]; }; # Large builds (the linux kernel) fail to build because /tmp is too small when using tmpfs From ea9715829600fe8902b90392c7702f79136d6c0a Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 22 Apr 2024 22:16:32 +0200 Subject: [PATCH 0584/1125] Server/ssh: add public key for toast --- roles/server/ssh.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/server/ssh.nix b/roles/server/ssh.nix index 14ee0b6..1fd1288 100755 --- a/roles/server/ssh.nix +++ b/roles/server/ssh.nix @@ -18,6 +18,10 @@ in { }; }; + users.users.toast.openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEas0RvecJpUA1rG87fHunxDb4O0Q7bQG7X8h3hZnrsE Everest access key" + ]; + services.openssh = { enable = true; settings = { From 2b9491c83782a2c9afc6096c355f69c33ac2bcbf Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 23 Apr 2024 10:07:00 +0200 Subject: [PATCH 0585/1125] Server/ssh: accept colorterm variable --- roles/server/ssh.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/server/ssh.nix b/roles/server/ssh.nix index 1fd1288..07d5edf 100755 --- a/roles/server/ssh.nix +++ b/roles/server/ssh.nix @@ -29,6 +29,11 @@ in { PermitRootLogin = "no"; PasswordAuthentication = false; }; + # The forgejo module is fucky so I can't set this with the nixos option + # https://github.com/NixOS/nixpkgs/issues/306205 + extraConfig = '' + AcceptEnv COLORTERM + ''; hostKeys = [ { path = hostKeyPath; From 319550e7181f875cd535f4c4a60b56ee70e875e7 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 23 Apr 2024 10:07:33 +0200 Subject: [PATCH 0586/1125] Desktop/ssh: send colorterm variable --- roles/desktop/programs/ssh.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/programs/ssh.nix b/roles/desktop/programs/ssh.nix index b6e4dff..4e1bd2f 100644 --- a/roles/desktop/programs/ssh.nix +++ b/roles/desktop/programs/ssh.nix @@ -17,6 +17,7 @@ host = "everest"; hostname = "everest.sable-pancake.ts.net"; forwardAgent = true; + sendEnv = ["COLORTERM"]; }; }; }; From 3d439c4893064fa7ee3fd08702cb076d7d87c43c Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 23 Apr 2024 13:47:27 +0200 Subject: [PATCH 0587/1125] Flake: update secrets --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 47c2782..c0cec35 100644 --- a/flake.lock +++ b/flake.lock @@ -377,11 +377,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1713776544, - "narHash": "sha256-EQW8P1TfkYQV0EEK1n3Gh9wRp9KlC0EbidH2j+niCaE=", + "lastModified": 1713863887, + "narHash": "sha256-TwlNZjJloyZ0/5KCPeSWrnyDfEFokayovRPQY7xqq1g=", "ref": "refs/heads/main", - "rev": "61410d68f15b3b970067a3fdd39667fdd9a89edd", - "revCount": 12, + "rev": "b8c66d7b0ca9fc21bc5332801b0203033cc3a772", + "revCount": 13, "type": "git", "url": "ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets" }, From c603df28bff289735be10f4967081db9773774ee Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 23 Apr 2024 13:47:41 +0200 Subject: [PATCH 0588/1125] Server/forgejo: use ssh host key from secrets --- roles/server/forgejo.nix | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index b8f04c9..e89fee9 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -1,8 +1,26 @@ { config, lib, + flakeSelf, ... -}: { +}: let + hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName + "/"; +in { + age.secrets = { + forgejo-host-key = { + file = hostSecrets + "forgejoPrivateKey.age"; + mode = "0400"; + owner = "forgejo"; + group = "forgejo"; + }; + "forgejo-host-key.pub" = { + file = hostSecrets + "forgejoPublicKey.age"; + mode = "0400"; + owner = "forgejo"; + group = "forgejo"; + }; + }; + specialisation.forgejoEnableRegistration.configuration.services.forgejo.settings.service.DISABLE_REGISTRATION = false; services.forgejo = { enable = true; @@ -14,6 +32,8 @@ ROOT_URL = "http://git.everest.sable-pancake.ts.net"; START_SSH_SERVER = true; SSH_PORT = 4222; + SSH_SERVER_HOST_KEYS = config.age.secrets.forgejo-host-key.path; + SSH_SERVER_HOST_KEY = "forgejo-host-key"; }; repository = { ENABLE_PUSH_CREATE_USER = true; From be5fb3bc2425902ec5e36f635e6e3d9b6ea6ef30 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 23 Apr 2024 13:48:15 +0200 Subject: [PATCH 0589/1125] Common/git: add forgejo's public key to known hosts --- roles/common/programs/git.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index f9f2b4e..02dc612 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -1,4 +1,9 @@ {...}: { + programs.ssh.knownHosts = { + "[git.everest.sable-pancake.ts.net]:4222".publicKey = '' + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKoUcWx56NZ3kqydN3d0gLNz6SlBm1ArkHhqR9Fwd8qs + ''; + }; home-manager.users.toast = { programs.git = { enable = true; From 0aee3539f0c219d558878bf2714f6c1b152ea9cd Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 24 Apr 2024 00:24:50 +0200 Subject: [PATCH 0590/1125] Flake: update secrets --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index c0cec35..79c1741 100644 --- a/flake.lock +++ b/flake.lock @@ -377,11 +377,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1713863887, - "narHash": "sha256-TwlNZjJloyZ0/5KCPeSWrnyDfEFokayovRPQY7xqq1g=", + "lastModified": 1713910881, + "narHash": "sha256-MZ1+GmZL3V3Kqe4YrxPA2W8vrF/c+f7sYOpf+jw6ESc=", "ref": "refs/heads/main", - "rev": "b8c66d7b0ca9fc21bc5332801b0203033cc3a772", - "revCount": 13, + "rev": "918b61f3ee194d7e67fa1d3200b64fe7741dd24a", + "revCount": 15, "type": "git", "url": "ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets" }, From 68628028bd611c721d628fb9d33c75eea8fedf96 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 24 Apr 2024 00:29:40 +0200 Subject: [PATCH 0591/1125] Machines/WinMax2: set up as a nix remote builder --- machines/WinMax2/default.nix | 1 + machines/WinMax2/remote-builder.nix | 55 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 machines/WinMax2/remote-builder.nix diff --git a/machines/WinMax2/default.nix b/machines/WinMax2/default.nix index 187a110..899f761 100755 --- a/machines/WinMax2/default.nix +++ b/machines/WinMax2/default.nix @@ -2,5 +2,6 @@ imports = [ ./configuration.nix ./hardware-configuration.nix + ./remote-builder.nix ]; } diff --git a/machines/WinMax2/remote-builder.nix b/machines/WinMax2/remote-builder.nix new file mode 100644 index 0000000..ad86042 --- /dev/null +++ b/machines/WinMax2/remote-builder.nix @@ -0,0 +1,55 @@ +{ + config, + flakeSelf, + ... +}: let + hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName + "/"; + hostKeyPath = "/etc/ssh/winmax2_host_key"; +in { + age.secrets = { + winmax2-host-key = { + file = hostSecrets + "host-private-key.age"; + path = hostKeyPath; + mode = "0400"; + }; + "winmax2-host-key.pub" = { + file = hostSecrets + "host-public-key.age"; + path = hostKeyPath + ".pub"; + }; + }; + + users = { + groups.nixrbld = {}; + users.nixrbld = { + isSystemUser = true; + group = "nixrbld"; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF8v+04ZwqHZRG8P8nxdQt+fGJfzlxHXF0F6jzENb+U6 Remote builder access key" + ]; + }; + }; + + nix.settings.trusted-users = ["nixrbld"]; + + services.openssh = { + enable = true; + startWhenNeeded = true; + # I only want it to be accesible though tailscale + openFirewall = false; + allowSFTP = false; + settings = { + UseDns = true; + PermitRootLogin = "no"; + PasswordAuthentication = false; + AllowUsers = ["nixrbld"]; + }; + hostKeys = [ + { + path = hostKeyPath; + type = "ed25519"; + comment = "Everest host key"; + } + ]; + }; + networking.firewall.interfaces.tailscale0.allowedTCPPorts = [22]; +} From 30f41d10db9c68587a8d560c4eee47b6b52fd76c Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 24 Apr 2024 01:09:08 +0200 Subject: [PATCH 0592/1125] Common/nix: add remote builder --- roles/common/programs/nix.nix | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index 1663df2..77fd14a 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -1,9 +1,38 @@ -{systemPkgs, ...}: { +{ + systemPkgs, + config, + flakeSelf, + ... +}: { + age.secrets = { + remoteBuilderKey.file = "${flakeSelf.inputs.secrets}/WinMax2/nixrbld-private-key.age"; + }; + + programs.ssh = { + knownHosts.winmax2.publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPE+ksvEq/I2LMLOztVXpLE9yuI6EkRh4EtXdlYkhl6C WinMax2 host key"; + extraConfig = '' + Host nixrbld + HostName winmax2 + IdentitiesOnly yes + IdentityFile ${config.age.secrets.remoteBuilderKey.path} + User nixrbld + ''; + }; + nix = { settings = { auto-optimise-store = true; experimental-features = "nix-command flakes"; }; + distributedBuilds = true; + buildMachines = [ + { + hostName = "nixrbld"; + system = "x86_64-linux"; + protocol = "ssh-ng"; + maxJobs = 4; + } + ]; optimise = { automatic = true; dates = ["weekly"]; From 7535e078fe790802ceef8041e91a0d4fe54350d0 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 24 Apr 2024 01:18:09 +0200 Subject: [PATCH 0593/1125] Common/nix: add supportedFeatures to remote builder --- roles/common/programs/nix.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index 77fd14a..6cdf8ae 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -31,6 +31,11 @@ system = "x86_64-linux"; protocol = "ssh-ng"; maxJobs = 4; + supportedFeatures = [ + "big-parallel" + "kvm" + "nixos-test" + ]; } ]; optimise = { From 19bddffde3c50ed62cca9685b616568ce920c907 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 24 Apr 2024 01:33:56 +0200 Subject: [PATCH 0594/1125] Machines/WinMax2: set up shell for nixrbld --- machines/WinMax2/remote-builder.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/WinMax2/remote-builder.nix b/machines/WinMax2/remote-builder.nix index ad86042..1a3f839 100644 --- a/machines/WinMax2/remote-builder.nix +++ b/machines/WinMax2/remote-builder.nix @@ -22,6 +22,7 @@ in { groups.nixrbld = {}; users.nixrbld = { isSystemUser = true; + useDefaultShell = true; group = "nixrbld"; openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF8v+04ZwqHZRG8P8nxdQt+fGJfzlxHXF0F6jzENb+U6 Remote builder access key" From d93320318627875d82898bac0f3da2fcb24de34f Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 24 Apr 2024 09:36:23 +0200 Subject: [PATCH 0595/1125] School/unity: install jetbrains rider --- roles/school/programs/unity.nix | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/roles/school/programs/unity.nix b/roles/school/programs/unity.nix index 88943e1..b30daf4 100644 --- a/roles/school/programs/unity.nix +++ b/roles/school/programs/unity.nix @@ -1,9 +1,8 @@ {pkgs, ...}: { home-manager.users.toast = { - home.packages = [ - ( - pkgs.unityhub - ) + home.packages = with pkgs; [ + unityhub + jetbrains.rider ]; }; } From f9d60b9c8b926e5c40cebd0930c9faacc3217048 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Apr 2024 09:37:33 +0200 Subject: [PATCH 0596/1125] Common/nix: don't use remote builder on WinMax2 --- roles/common/programs/nix.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index 6cdf8ae..de6a729 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -1,6 +1,7 @@ { systemPkgs, config, + lib, flakeSelf, ... }: { @@ -25,7 +26,8 @@ experimental-features = "nix-command flakes"; }; distributedBuilds = true; - buildMachines = [ + # Don't use remote builder on the remote builder + buildMachines = lib.mkIf (config.networking.hostName != "WinMax2") [ { hostName = "nixrbld"; system = "x86_64-linux"; From bad020c1d61fa62d76418c49d69241e4955ab4ad Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Apr 2024 12:07:39 +0200 Subject: [PATCH 0597/1125] Flake: remove hhd nixpkgs patch --- flake.nix | 4 +- .../0001-handheld-daemon-1.1.0-2.6.4.patch | 417 ------------------ 2 files changed, 1 insertion(+), 420 deletions(-) delete mode 100644 nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.4.patch diff --git a/flake.nix b/flake.nix index a233781..8ab876e 100644 --- a/flake.nix +++ b/flake.nix @@ -80,9 +80,7 @@ nixpkgs-unstable-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; - patches = [ - ./nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.4.patch - ]; + patches = []; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; diff --git a/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.4.patch b/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.4.patch deleted file mode 100644 index ed37f7a..0000000 --- a/nixpkgs-patches/0001-handheld-daemon-1.1.0-2.6.4.patch +++ /dev/null @@ -1,417 +0,0 @@ -From d9e4af9ae8ed30a1ab860915c5c0ff9ae0c16dc1 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Fri, 12 Apr 2024 13:32:24 +0200 -Subject: [PATCH 01/13] handheld-daemon: 1.1.0 -> 2.6.2 - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index bb0c9d65bfe19d..b5f25f339ffb60 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -8,14 +8,14 @@ - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "1.1.0"; -+ version = "2.6.2"; - pyproject = true; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - rev = "v${version}"; -- hash = "sha256-ovLC1BQ98jUaDEMPBzWma4TYSzTF+yE/cMemFdJmqlE="; -+ hash = "sha256-fsH8H6ZhiguOWI2t79GnxqAmqL/1m06RQzs+k8bUWcU="; - }; - - propagatedBuildInputs = with python3.pkgs; [ -@@ -26,6 +26,7 @@ python3.pkgs.buildPythonApplication rec { - rich - setuptools - toybox -+ xlib - ]; - - # This package doesn't have upstream tests. - -From 2a8d54c511bda43bea18d35d2c08f224f3352a18 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Sat, 13 Apr 2024 15:42:25 +0200 -Subject: [PATCH 02/13] handheld-daemon: update license - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index b5f25f339ffb60..f0ce6e9648e3e8 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -48,7 +48,7 @@ python3.pkgs.buildPythonApplication rec { - homepage = "https://github.com/hhd-dev/hhd/"; - description = "Linux support for handheld gaming devices like the Legion Go, ROG Ally, and GPD Win"; - platforms = platforms.linux; -- license = licenses.mit; -+ license = licenses.gpl3Only; - maintainers = with maintainers; [ appsforartists ]; - mainProgram = "hhd"; - }; - -From 3b96a3c082f6b0e9f7e2eabcc18cf599a0c7eb63 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 15 Apr 2024 00:31:56 +0200 -Subject: [PATCH 03/13] handheld-daemon: patch generated udev rules to use - chmod from nix store - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index f0ce6e9648e3e8..72981284e2e9c1 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -5,6 +5,7 @@ - , lib - , python3 - , toybox -+, coreutils - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -@@ -38,6 +39,10 @@ python3.pkgs.buildPythonApplication rec { - hidapi=${ hidapi }/lib/ - test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } - sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py -+ -+ # The generated udev rules point to /bin/chroot, which does not exist in NixOS -+ chmod=${ coreutils }/bin/chmod -+ sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py - ''; - - postInstall = '' - -From 6a2060842db04c81b354b49a9c53bfd2262a5af3 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 15 Apr 2024 19:57:10 +0200 -Subject: [PATCH 04/13] handheld-daemon: remove unneeded coreutils dependency - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 72981284e2e9c1..835c0774469354 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -5,7 +5,6 @@ - , lib - , python3 - , toybox --, coreutils - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -@@ -41,7 +40,7 @@ python3.pkgs.buildPythonApplication rec { - sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py - - # The generated udev rules point to /bin/chroot, which does not exist in NixOS -- chmod=${ coreutils }/bin/chmod -+ chmod=${ toybox }/bin/chmod - sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py - ''; - - -From c9e8b7cf0260618682c15f7ba601ec9827396ceb Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 15 Apr 2024 20:07:46 +0200 -Subject: [PATCH 05/13] handheld-daemon: move udev rule comment - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 835c0774469354..d79457057e392c 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -34,12 +34,12 @@ python3.pkgs.buildPythonApplication rec { - - # handheld-daemon contains a fork of the python module `hid`, so this hook - # is borrowed from the `hid` derivation. -+ # The generated udev rules point to /bin/chroot, which does not exist in NixOS - postPatch = '' - hidapi=${ hidapi }/lib/ - test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } - sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py - -- # The generated udev rules point to /bin/chroot, which does not exist in NixOS - chmod=${ toybox }/bin/chmod - sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py - ''; - -From 7bea1eb24a9e84b343c3944318e74ce3442ce40c Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 15 Apr 2024 20:32:43 +0200 -Subject: [PATCH 06/13] handheld-daemon: 2.6.2 -> 2.6.4 - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index d79457057e392c..7801038ea36669 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -8,14 +8,14 @@ - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "2.6.2"; -+ version = "2.6.4"; - pyproject = true; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - rev = "v${version}"; -- hash = "sha256-fsH8H6ZhiguOWI2t79GnxqAmqL/1m06RQzs+k8bUWcU="; -+ hash = "sha256-S77APtE1GGfqnv1IkZdJOSlprPOBtrqVXV60yVMvopg="; - }; - - propagatedBuildInputs = with python3.pkgs; [ - -From b510c5a603c7f2193a4f1c10e03bac6f7f361584 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 15 Apr 2024 21:30:51 +0200 -Subject: [PATCH 07/13] handheld-daemon: move udev rule comment to the right - place this time - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 7801038ea36669..4189bf0483b973 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -32,14 +32,14 @@ python3.pkgs.buildPythonApplication rec { - # This package doesn't have upstream tests. - doCheck = false; - -- # handheld-daemon contains a fork of the python module `hid`, so this hook -- # is borrowed from the `hid` derivation. -- # The generated udev rules point to /bin/chroot, which does not exist in NixOS - postPatch = '' -+ # handheld-daemon contains a fork of the python module `hid`, so this hook -+ # is borrowed from the `hid` derivation. - hidapi=${ hidapi }/lib/ - test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } - sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py - -+ # The generated udev rules point to /bin/chroot, which does not exist in NixOS - chmod=${ toybox }/bin/chmod - sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py - ''; - -From f7b450a4d83aec36be9c1576cb69b92c7895b33d Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 15 Apr 2024 21:38:38 +0200 -Subject: [PATCH 08/13] handheld-daemon: fix typo in comment - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 4189bf0483b973..5087698c793430 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -39,7 +39,7 @@ python3.pkgs.buildPythonApplication rec { - test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } - sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py - -- # The generated udev rules point to /bin/chroot, which does not exist in NixOS -+ # The generated udev rules point to /bin/chmod, which does not exist in NixOS - chmod=${ toybox }/bin/chmod - sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py - ''; - -From a581a28a074a3a8bad48ba2883a320bfb02a5062 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Tue, 16 Apr 2024 19:50:25 +0200 -Subject: [PATCH 09/13] handheld-daemon: format with nixfmt-rfc-style - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 19 ++++++++++--------- - 1 file changed, 10 insertions(+), 9 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 5087698c793430..52b5729bc6f300 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -1,10 +1,11 @@ --{ config --, fetchFromGitHub --, hidapi --, kmod --, lib --, python3 --, toybox -+{ -+ config, -+ fetchFromGitHub, -+ hidapi, -+ kmod, -+ lib, -+ python3, -+ toybox, - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -@@ -35,12 +36,12 @@ python3.pkgs.buildPythonApplication rec { - postPatch = '' - # handheld-daemon contains a fork of the python module `hid`, so this hook - # is borrowed from the `hid` derivation. -- hidapi=${ hidapi }/lib/ -+ hidapi=${hidapi}/lib/ - test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } - sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py - - # The generated udev rules point to /bin/chmod, which does not exist in NixOS -- chmod=${ toybox }/bin/chmod -+ chmod=${toybox}/bin/chmod - sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py - ''; - - -From d9b7086a02c8b6a156438d88d86903218907aa9e Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Tue, 16 Apr 2024 20:15:21 +0200 -Subject: [PATCH 10/13] handheld-daemon: replace sed commands with - substituteInPlace - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 52b5729bc6f300..356130ec54e07e 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -34,15 +34,17 @@ python3.pkgs.buildPythonApplication rec { - doCheck = false; - - postPatch = '' -+ # The generated udev rules point to /bin/chmod, which does not exist in NixOS -+ substituteInPlace src/hhd/controller/lib/hide.py \ -+ --replace-fail /bin/chmod ${toybox}/bin/chmod -+ - # handheld-daemon contains a fork of the python module `hid`, so this hook - # is borrowed from the `hid` derivation. -+ substituteInPlace src/hhd/controller/lib/hid.py \ -+ --replace-fail libhidapi ${hidapi}/lib/libhidapi -+ - hidapi=${hidapi}/lib/ - test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } -- sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py -- -- # The generated udev rules point to /bin/chmod, which does not exist in NixOS -- chmod=${toybox}/bin/chmod -- sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py - ''; - - postInstall = '' - -From 20753a73d1a20cf5b67bc7cc51572807c0eda9fc Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Tue, 16 Apr 2024 20:29:56 +0200 -Subject: [PATCH 11/13] handheld-daemon: trim out trailing whitespace - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index b734034a439dab..db6c46a7e8055c 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -41,9 +41,9 @@ python3.pkgs.buildPythonApplication rec { - # handheld-daemon contains a fork of the python module `hid`, so this hook - # is borrowed from the `hid` derivation. - substituteInPlace src/hhd/controller/lib/hid.py \ -- --replace-fail libhidapi ${hidapi}/lib/libhidapi -- -- hidapi=${hidapi}/lib/ -+ --replace-fail libhidapi ${hidapi}/lib/libhidapi -+ -+ hidapi=${hidapi}/lib/ - test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } - ''; - - -From cb2fa9a66110a6deb4f66c2dfd146b2895f932bd Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Tue, 16 Apr 2024 21:04:48 +0200 -Subject: [PATCH 12/13] handheld-daemon: fix indenting - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index db6c46a7e8055c..ad0554bec36d52 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -41,9 +41,9 @@ python3.pkgs.buildPythonApplication rec { - # handheld-daemon contains a fork of the python module `hid`, so this hook - # is borrowed from the `hid` derivation. - substituteInPlace src/hhd/controller/lib/hid.py \ -- --replace-fail libhidapi ${hidapi}/lib/libhidapi -+ --replace-fail libhidapi ${hidapi}/lib/libhidapi - -- hidapi=${hidapi}/lib/ -+ hidapi=${hidapi}/lib/ - test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } - ''; - - -From d9b487ae609a368378c1a9d89a5441c5c44121df Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Wed, 17 Apr 2024 09:19:43 +0200 -Subject: [PATCH 13/13] handheld-daemon: undo refactor - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 12 +++++------- - 1 file changed, 5 insertions(+), 7 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index ad0554bec36d52..246e3879bb5cfa 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -34,17 +34,15 @@ python3.pkgs.buildPythonApplication rec { - doCheck = false; - - postPatch = '' -- # The generated udev rules point to /bin/chmod, which does not exist in NixOS -- substituteInPlace src/hhd/controller/lib/hide.py \ -- --replace-fail /bin/chmod ${toybox}/bin/chmod -- - # handheld-daemon contains a fork of the python module `hid`, so this hook - # is borrowed from the `hid` derivation. -- substituteInPlace src/hhd/controller/lib/hid.py \ -- --replace-fail libhidapi ${hidapi}/lib/libhidapi -- - hidapi=${hidapi}/lib/ - test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } -+ sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py -+ -+ # The generated udev rules point to /bin/chmod, which does not exist in NixOS -+ chmod=${toybox}/bin/chmod -+ sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py - ''; - - postInstall = '' From 4244072f23a1897c77f53809ebe298e1bceafe1e Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Apr 2024 12:07:57 +0200 Subject: [PATCH 0598/1125] Flake: don't use system nixpkgs for catppuccin-vsc input --- flake.nix | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index 8ab876e..524a6a9 100644 --- a/flake.nix +++ b/flake.nix @@ -56,10 +56,7 @@ inputs.home-manager.follows = "home-manager-unstable"; }; - catppuccin-vsc = { - url = "github:catppuccin/vscode"; - inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; - }; + catppuccin-vsc.url = "github:catppuccin/vscode"; vscode-extensions = { url = "github:nix-community/nix-vscode-extensions"; From 921f1ad9123bbf394d6746b1c45f3f142c1febec Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Apr 2024 12:07:08 +0200 Subject: [PATCH 0599/1125] Flake: update lock file --- flake.lock | 100 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 43 deletions(-) diff --git a/flake.lock b/flake.lock index 79c1741..163f32b 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1713552048, - "narHash": "sha256-RcDJNnxjG9MTQHV/yG7JwPzffFub0JrwP2C1m6LxWFc=", + "lastModified": 1713895615, + "narHash": "sha256-SVkxhcL0/IN5fNI2dqr702wXOnzktsm0LCEVGRAJQcY=", "owner": "catppuccin", "repo": "nix", - "rev": "29bd8a3bda02434bf6ee3edf9ea6edd360a9ce17", + "rev": "a48e70a31616cb63e4794fd3465bff1835cc4246", "type": "github" }, "original": { @@ -40,16 +40,14 @@ }, "catppuccin-vsc": { "inputs": { - "nixpkgs": [ - "nixpkgs-unstable-raw" - ] + "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1713403580, - "narHash": "sha256-VP3AiTLL40Zhr+99SwKjIE+ifRy/elhvGIF5W92J+fs=", + "lastModified": 1713966850, + "narHash": "sha256-AHAkkTUjk86rED3pQh8i4OiSze+OHe697L0o3zhv89A=", "owner": "catppuccin", "repo": "vscode", - "rev": "4dd5fa89173bc931e882f21da0de1609f1db9f39", + "rev": "75d96f3ae48b249f77124688a026ca5d7eeb5fb2", "type": "github" }, "original": { @@ -120,11 +118,11 @@ ] }, "locked": { - "lastModified": 1713547559, - "narHash": "sha256-zju60y4pyYQoRmqhbgkw+jwmKZReVsCNvb8mZxID2Do=", + "lastModified": 1714042918, + "narHash": "sha256-4AItZA3EQIiSNAxliuYEJumw/LaVfrMv84gYyrs0r3U=", "owner": "nix-community", "repo": "home-manager", - "rev": "938357cb234e85da37109df2cdd9cc59ab9c1cc0", + "rev": "0c5704eceefcb7bb238a958f532a86e3b59d76db", "type": "github" }, "original": { @@ -140,11 +138,11 @@ ] }, "locked": { - "lastModified": 1712386041, - "narHash": "sha256-dA82pOMQNnCJMAsPG7AXG35VmCSMZsJHTFlTHizpKWQ=", + "lastModified": 1714043624, + "narHash": "sha256-Xn2r0Jv95TswvPlvamCC46wwNo8ALjRCMBJbGykdhcM=", "owner": "nix-community", "repo": "home-manager", - "rev": "d6bb9f934f2870e5cbc5b94c79e9db22246141ff", + "rev": "86853e31dc1b62c6eeed11c667e8cdd0285d4411", "type": "github" }, "original": { @@ -162,11 +160,11 @@ ] }, "locked": { - "lastModified": 1713333160, - "narHash": "sha256-iz4Uz3vykqsZwIY2hxEMfRrc1DvBgxHVCfSxppuj40s=", + "lastModified": 1714022840, + "narHash": "sha256-i6xZsf7Kvp1n/Sn3nqPY1MJQx0gf80OGQw32PA/aZd8=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "d3ce25a385ec7ed899ffb282d1e54ccb4ac9ef0d", + "rev": "94def3af1d45fe4b142beda3aa59a6a98e62ce9e", "type": "github" }, "original": { @@ -235,11 +233,11 @@ ] }, "locked": { - "lastModified": 1713067146, - "narHash": "sha256-9D20xjblGKEVRVCnM3qWhiizEa9i6OpK6xQJajwcwOQ=", + "lastModified": 1713869268, + "narHash": "sha256-o3CMQeu/S8/4zU0pMtYg51rd1FWdJsI2Xohzng1Ysdg=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "93aed67288be60c9ef6133ba2f8de128f4ef265c", + "rev": "dcb6ac44922858ce3a5b46f77a36d6030181460c", "type": "github" }, "original": { @@ -255,11 +253,11 @@ ] }, "locked": { - "lastModified": 1713067146, - "narHash": "sha256-9D20xjblGKEVRVCnM3qWhiizEa9i6OpK6xQJajwcwOQ=", + "lastModified": 1713869268, + "narHash": "sha256-o3CMQeu/S8/4zU0pMtYg51rd1FWdJsI2Xohzng1Ysdg=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "93aed67288be60c9ef6133ba2f8de128f4ef265c", + "rev": "dcb6ac44922858ce3a5b46f77a36d6030181460c", "type": "github" }, "original": { @@ -270,11 +268,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1713521961, - "narHash": "sha256-EwR8wW9AqJhSIY+0oxWRybUZ32BVKuZ9bjlRh8SJvQ8=", + "lastModified": 1713864415, + "narHash": "sha256-/BPDMJEkrsFAFOsQWhwm31wezlgshPFlLBn34KEUdVA=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "5d48925b815fd202781bfae8fb6f45c07112fdb2", + "rev": "797f8d8082c7cc3259cba7275c699d4991b09ecc", "type": "github" }, "original": { @@ -284,13 +282,29 @@ "type": "github" } }, - "nixpkgs-raw": { + "nixpkgs": { "locked": { - "lastModified": 1713145326, - "narHash": "sha256-m7+IWM6mkWOg22EC5kRUFCycXsXLSU7hWmHdmBfmC3s=", + "lastModified": 1712963716, + "narHash": "sha256-WKm9CvgCldeIVvRz87iOMi8CFVB1apJlkUT4GGvA0iM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "53a2c32bc66f5ae41a28d7a9a49d321172af621e", + "rev": "cfd6b5fc90b15709b780a5a1619695a88505a176", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-raw": { + "locked": { + "lastModified": 1713995372, + "narHash": "sha256-fFE3M0vCoiSwCX02z8VF58jXFRj9enYUSTqjyHAjrds=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "dd37924974b9202f8226ed5d74a252a9785aedf8", "type": "github" }, "original": { @@ -301,11 +315,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1713248628, - "narHash": "sha256-NLznXB5AOnniUtZsyy/aPWOk8ussTuePp2acb9U+ISA=", + "lastModified": 1713895582, + "narHash": "sha256-cfh1hi+6muQMbi9acOlju3V1gl8BEaZBXBR9jQfQi4U=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5672bc9dbf9d88246ddab5ac454e82318d094bb8", + "rev": "572af610f6151fd41c212f897c71f7056e3fb518", "type": "github" }, "original": { @@ -316,11 +330,11 @@ }, "nur": { "locked": { - "lastModified": 1713555937, - "narHash": "sha256-ttraBb8XI/iTe0Q6hBTj/W8e+TvsPLACxdw693Gd3hQ=", + "lastModified": 1714114197, + "narHash": "sha256-f1kMNBUgbY+2/N0YkeouGNYdL7HVsRgcQLf5zL/ayd0=", "owner": "nix-community", "repo": "NUR", - "rev": "41c9fdae65031c6eaeab1c0a331c0eb9a32376c4", + "rev": "10fc1b8b048fe797ada9302f700590afb457dde2", "type": "github" }, "original": { @@ -339,11 +353,11 @@ ] }, "locked": { - "lastModified": 1712872911, - "narHash": "sha256-gwYrKMXuUBf5acvTzH7+lXeBbBZYUUEgcLBugHXimuc=", + "lastModified": 1713952910, + "narHash": "sha256-7ICgAfFSQXZlWyhfSrGXAS0rg2YSMKqEO+4EF4lH25I=", "owner": "toast003", "repo": "plasma-manager", - "rev": "8a3ac8690d6f546ec9185e1f5ddbb1f76d63b6b1", + "rev": "13c65048f1f527c7d4ee1f921fa1847129139385", "type": "github" }, "original": { @@ -429,11 +443,11 @@ ] }, "locked": { - "lastModified": 1713549455, - "narHash": "sha256-wMHTvhl7Yl+nNVspchN7e337DBAM2LhHlcHnfAPhGEY=", + "lastModified": 1714094499, + "narHash": "sha256-SC6tm901h2tzRxd6hfzn5/bgLJ8R4ng39R7SIkg6wlo=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "15529741a0f9c2b90a725ef5eb2262468a2f40a6", + "rev": "e05ff96b9f710d57d7cd60641f0273176debf222", "type": "github" }, "original": { From 8699442aba3ceb11515afb571d7c9a04cf8b2c5f Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Apr 2024 13:56:16 +0200 Subject: [PATCH 0600/1125] Revert switching to my branch of plasma manager Revert "Kde/plasma: set up keyboard layout and numlock settings" This reverts commit 7202d3a57f5d6b5389d8f18b790c3a3a867ba09e. Revert "Machines/WinMax2: set up keyboard layout for plasma" This reverts commit 26fde4688631ecd0406727ee62f9a03ae38fda64. Revert "Flake: temporarely change to my branch of plasma-manager" This reverts commit 0337f4f7a047f2278be2f8c7ce60c49c8b2a4320. --- flake.lock | 13 ++++++------- flake.nix | 2 +- machines/WinMax2/configuration.nix | 1 - roles/kde/plasma.nix | 6 ------ 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index 163f32b..4cfe813 100644 --- a/flake.lock +++ b/flake.lock @@ -353,16 +353,15 @@ ] }, "locked": { - "lastModified": 1713952910, - "narHash": "sha256-7ICgAfFSQXZlWyhfSrGXAS0rg2YSMKqEO+4EF4lH25I=", - "owner": "toast003", + "lastModified": 1712484920, + "narHash": "sha256-wNwv12U/QYYgZanycZ32A41cEDa2zPwYuMKK6AJYNJk=", + "owner": "pjones", "repo": "plasma-manager", - "rev": "13c65048f1f527c7d4ee1f921fa1847129139385", + "rev": "4b127a5ede004f5c6d7c41938c2986b599dc0bf3", "type": "github" }, "original": { - "owner": "toast003", - "ref": "libinput", + "owner": "pjones", "repo": "plasma-manager", "type": "github" } @@ -459,4 +458,4 @@ }, "root": "root", "version": 7 -} +} \ No newline at end of file diff --git a/flake.nix b/flake.nix index 524a6a9..9f65afb 100644 --- a/flake.nix +++ b/flake.nix @@ -51,7 +51,7 @@ }; plasma-manager = { - url = "github:toast003/plasma-manager/libinput"; + url = "github:pjones/plasma-manager"; inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; inputs.home-manager.follows = "home-manager-unstable"; }; diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 65f51ff..fd5f9ea 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -114,7 +114,6 @@ comment = "Application for managing and playing games on Steam"; }; }; - programs.plasma.input.keyboard.layouts = lib.mkForce ["us"]; } ]; diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index e382060..2d135ad 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -132,12 +132,6 @@ in { number = 2; }; }; - input = { - keyboard = { - layouts = ["es"]; - numlockOnStartup = "off"; - }; - }; panels = [ { location = "bottom"; From 2eb19d7374c6a2f1a3df34c62d071a23cddacb7c Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 27 Apr 2024 20:34:11 +0200 Subject: [PATCH 0601/1125] Gaming: add pcsx2 --- roles/gaming/programs/default.nix | 1 + roles/gaming/programs/pcsx2.nix | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 roles/gaming/programs/pcsx2.nix diff --git a/roles/gaming/programs/default.nix b/roles/gaming/programs/default.nix index 445b615..4148b85 100755 --- a/roles/gaming/programs/default.nix +++ b/roles/gaming/programs/default.nix @@ -4,6 +4,7 @@ ./mangohud.nix ./rpcs3.nix ./retroarch.nix + ./pcsx2.nix ]; environment.systemPackages = with pkgs; [ heroic diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix new file mode 100644 index 0000000..c2bd45e --- /dev/null +++ b/roles/gaming/programs/pcsx2.nix @@ -0,0 +1,7 @@ +{pkgs, ...}: { + home-manager.users.toast = { + home.packages = with pkgs; [ + pcsx2 + ]; + }; +} From 944207fdd296568ed729ffc6232cd3735cd6ee29 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 28 Apr 2024 13:48:56 +0200 Subject: [PATCH 0602/1125] Gaming/pcsx2: add isos --- roles/gaming/programs/pcsx2.nix | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index c2bd45e..40a0497 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -1,7 +1,20 @@ -{pkgs, ...}: { +{pkgs, ...}: let + ps2-isos = [ + (pkgs.fetchzip { + url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202/007%20-%20Nightfire%20%28USA%29.zip"; + hash = "sha256-66Ey0SqC3Tk02Af+xR6rpxYSkO0n83NWYPCt4M3CUWo="; + }) + ]; +in { home-manager.users.toast = { - home.packages = with pkgs; [ - pcsx2 - ]; + home = { + packages = with pkgs; [ + pcsx2 + ]; + file."Games/Isos/PS2".source = pkgs.symlinkJoin { + name = "ps2-isos"; + paths = [ps2-isos]; + }; + }; }; } From bb9f35e9603db74f4b7be43f0b5ebd950d8b56b9 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 28 Apr 2024 16:48:32 +0200 Subject: [PATCH 0603/1125] Gaming/pcsx2: add ps2 bios --- roles/gaming/programs/pcsx2.nix | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index 40a0497..b3f0939 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -5,6 +5,10 @@ hash = "sha256-66Ey0SqC3Tk02Af+xR6rpxYSkO0n83NWYPCt4M3CUWo="; }) ]; + pcsx2-bios = pkgs.fetchzip { + url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202%20-%20BIOS%20Images/ps2-0200a-20040614.zip"; + hash = "sha256-wMvswgmsKl+cJl49VlVW84tvU5Jzd+2dl07SOiUDtwA="; + }; in { home-manager.users.toast = { home = { @@ -16,5 +20,12 @@ in { paths = [ps2-isos]; }; }; + xdg.dataFile = { + # I would prefer to use symlinkJoin like I do for the ISOs, but + # the bios folder needs to be writable to store the bios settings + "PCSX2/bios/ntsc.bin".source = pkgs.runCommandLocal "pcsx2-bios" {} '' + cp -v ${pcsx2-bios}/*.bin $out + ''; + }; }; } From 9bea86b4ff5890649dca738dbb2cac27806b4916 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 28 Apr 2024 22:24:45 +0200 Subject: [PATCH 0604/1125] Gaming/pcsx2: compress isos --- roles/gaming/programs/pcsx2.nix | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index b3f0939..cb288d6 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -1,10 +1,25 @@ {pkgs, ...}: let - ps2-isos = [ - (pkgs.fetchzip { - url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202/007%20-%20Nightfire%20%28USA%29.zip"; - hash = "sha256-66Ey0SqC3Tk02Af+xR6rpxYSkO0n83NWYPCt4M3CUWo="; - }) - ]; + ps2-isos = pkgs.symlinkJoin { + name = "ps2-isos"; + paths = [ + (pkgs.fetchzip { + url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202/007%20-%20Nightfire%20%28USA%29.zip"; + hash = "sha256-66Ey0SqC3Tk02Af+xR6rpxYSkO0n83NWYPCt4M3CUWo="; + }) + ]; + }; + + compressed-ps2-isos = pkgs.runCommand "compressed-ps2-isos" {} '' + mkdir $out + cd ${ps2-isos} + for file in ./* + do + echo $out + echo $file + ${pkgs.pigz}/bin/pigz -9 -c -v "$file" > "$out/$file.gz" + done + ''; + pcsx2-bios = pkgs.fetchzip { url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202%20-%20BIOS%20Images/ps2-0200a-20040614.zip"; hash = "sha256-wMvswgmsKl+cJl49VlVW84tvU5Jzd+2dl07SOiUDtwA="; @@ -15,10 +30,7 @@ in { packages = with pkgs; [ pcsx2 ]; - file."Games/Isos/PS2".source = pkgs.symlinkJoin { - name = "ps2-isos"; - paths = [ps2-isos]; - }; + file."Games/Isos/PS2".source = compressed-ps2-isos; }; xdg.dataFile = { # I would prefer to use symlinkJoin like I do for the ISOs, but From f13ac0b8ece284a836179a435f84c998a41b5c23 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 10:06:58 +0200 Subject: [PATCH 0605/1125] Gaming/pcsx2: compress roms to chd --- roles/gaming/programs/pcsx2.nix | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index cb288d6..70d8d18 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -14,9 +14,7 @@ cd ${ps2-isos} for file in ./* do - echo $out - echo $file - ${pkgs.pigz}/bin/pigz -9 -c -v "$file" > "$out/$file.gz" + ${pkgs.mame-tools}/bin/chdman createdvd -i "$file" -o "$out/''${file%.iso}.chd" done ''; From f6cb581dd2d1229f39df90e745af6846237f2d30 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 10:27:39 +0200 Subject: [PATCH 0606/1125] Gaming/pcsx2: configure declaratively --- roles/gaming/programs/pcsx2.nix | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index 70d8d18..089c56d 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -1,4 +1,4 @@ -{pkgs, ...}: let +{pkgs, lib, ...}: let ps2-isos = pkgs.symlinkJoin { name = "ps2-isos"; paths = [ @@ -30,6 +30,23 @@ in { ]; file."Games/Isos/PS2".source = compressed-ps2-isos; }; + xdg.configFile = { + #PCSX2 silently overwrites the symlink so I need to force it's creation + "PCSX2/inis/PCSX2.ini".force = true; + "PCSX2/inis/PCSX2.ini".text = lib.generators.toINI { + listsAsDuplicateKeys = true; + } { + UI = { + SettingsVersion = 1; + }; + Folders = { + Bios = "/home/toast/.local/share/PCSX2/bios"; + }; + GameList.RecursivePaths = [ + "/home/toast/Games/Isos/PS2/" + ]; + }; + }; xdg.dataFile = { # I would prefer to use symlinkJoin like I do for the ISOs, but # the bios folder needs to be writable to store the bios settings From 7bd66a216dd05b10f4a8740c897f8609bc662002 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 11:45:29 +0200 Subject: [PATCH 0607/1125] Gaming/pcsx2: add controller settings and enable discord presence --- roles/gaming/programs/pcsx2.nix | 65 ++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index 089c56d..8c3fd08 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -1,4 +1,8 @@ -{pkgs, lib, ...}: let +{ + pkgs, + lib, + ... +}: let ps2-isos = pkgs.symlinkJoin { name = "ps2-isos"; paths = [ @@ -33,19 +37,54 @@ in { xdg.configFile = { #PCSX2 silently overwrites the symlink so I need to force it's creation "PCSX2/inis/PCSX2.ini".force = true; - "PCSX2/inis/PCSX2.ini".text = lib.generators.toINI { - listsAsDuplicateKeys = true; - } { - UI = { - SettingsVersion = 1; + "PCSX2/inis/PCSX2.ini".text = + lib.generators.toINI { + listsAsDuplicateKeys = true; + } { + UI = { + SettingsVersion = 1; + # Use the system theme + Theme = ""; + }; + Folders = { + Bios = "/home/toast/.local/share/PCSX2/bios"; + }; + GameList.RecursivePaths = [ + "/home/toast/Games/Isos/PS2/" + ]; + EmuCore.EnableDiscordPresence = true; + + # Controller settings + Pad1 = { + Up = "SDL-0/DPadUp"; + Right = "SDL-0/DPadRight"; + Down = "SDL-0/DPadDown"; + Left = "SDL-0/DPadLeft"; + Triangle = "SDL-0/Y"; + Circle = "SDL-0/B"; + Cross = "SDL-0/A"; + Square = "SDL-0/X"; + Select = "SDL-0/Back"; + Start = "SDL-0/Start"; + L1 = "SDL-0/LeftShoulder"; + L2 = "SDL-0/+LeftTrigger"; + R1 = "SDL-0/RightShoulder"; + R2 = "SDL-0/+RightTrigger"; + L3 = "SDL-0/LeftStick"; + R3 = "SDL-0/RightStick"; + Analog = "SDL-0/Guide"; + LUp = "SDL-0/-LeftY"; + LRight = "SDL-0/+LeftX"; + LDown = "SDL-0/+LeftY"; + LLeft = "SDL-0/-LeftX"; + RUp = "SDL-0/-RightY"; + RRight = "SDL-0/+RightX"; + RDown = "SDL-0/+RightY"; + RLeft = "SDL-0/-RightX"; + LargeMotor = "SDL-0/LargeMotor"; + SmallMotor = "SDL-0/SmallMotor"; + }; }; - Folders = { - Bios = "/home/toast/.local/share/PCSX2/bios"; - }; - GameList.RecursivePaths = [ - "/home/toast/Games/Isos/PS2/" - ]; - }; }; xdg.dataFile = { # I would prefer to use symlinkJoin like I do for the ISOs, but From 4b1ea077d3223c7aa6324852a8f47ca8707f0f71 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 12:45:41 +0200 Subject: [PATCH 0608/1125] Gaming/pcsx2: add per-game settings and hide cursor on fullscreen --- roles/gaming/programs/pcsx2.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index 8c3fd08..7679c22 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -45,6 +45,7 @@ in { SettingsVersion = 1; # Use the system theme Theme = ""; + HideMouseCursor = true; }; Folders = { Bios = "/home/toast/.local/share/PCSX2/bios"; @@ -85,6 +86,10 @@ in { SmallMotor = "SDL-0/SmallMotor"; }; }; + # 007 nightfire + "PCSX2/gamesettings/SLUS-20579_5B86BB62.ini".text = lib.generators.toINI {} { + "EmuCore/GS".AspectRatio = "16:9"; + }; }; xdg.dataFile = { # I would prefer to use symlinkJoin like I do for the ISOs, but From 56442c00ddb35c9ba472ad110725d520d711b01e Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 13:09:17 +0200 Subject: [PATCH 0609/1125] Gaming/pcsx2: add more settings --- roles/gaming/programs/pcsx2.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index 7679c22..c475c07 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -53,7 +53,14 @@ in { GameList.RecursivePaths = [ "/home/toast/Games/Isos/PS2/" ]; - EmuCore.EnableDiscordPresence = true; + "EmuCore/GS".dithering_ps2 = 1; + EmuCore = { + EnableDiscordPresence = true; + EnableFastBoot = true; + McdFolderAutoManage = false; + }; + + MemoryCards.Slot1_Filename = "MemoryCard1.ps2"; # Controller settings Pad1 = { From 5e271ae4a560811373cc07dfda50812d048d5c4d Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 13:33:30 +0200 Subject: [PATCH 0610/1125] Revert "Revert switching to my branch of plasma manager" This reverts commit 8699442aba3ceb11515afb571d7c9a04cf8b2c5f. --- flake.lock | 13 +++++++------ flake.nix | 2 +- machines/WinMax2/configuration.nix | 1 + roles/kde/plasma.nix | 6 ++++++ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/flake.lock b/flake.lock index 4cfe813..163f32b 100644 --- a/flake.lock +++ b/flake.lock @@ -353,15 +353,16 @@ ] }, "locked": { - "lastModified": 1712484920, - "narHash": "sha256-wNwv12U/QYYgZanycZ32A41cEDa2zPwYuMKK6AJYNJk=", - "owner": "pjones", + "lastModified": 1713952910, + "narHash": "sha256-7ICgAfFSQXZlWyhfSrGXAS0rg2YSMKqEO+4EF4lH25I=", + "owner": "toast003", "repo": "plasma-manager", - "rev": "4b127a5ede004f5c6d7c41938c2986b599dc0bf3", + "rev": "13c65048f1f527c7d4ee1f921fa1847129139385", "type": "github" }, "original": { - "owner": "pjones", + "owner": "toast003", + "ref": "libinput", "repo": "plasma-manager", "type": "github" } @@ -458,4 +459,4 @@ }, "root": "root", "version": 7 -} \ No newline at end of file +} diff --git a/flake.nix b/flake.nix index 9f65afb..524a6a9 100644 --- a/flake.nix +++ b/flake.nix @@ -51,7 +51,7 @@ }; plasma-manager = { - url = "github:pjones/plasma-manager"; + url = "github:toast003/plasma-manager/libinput"; inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; inputs.home-manager.follows = "home-manager-unstable"; }; diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index fd5f9ea..65f51ff 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -114,6 +114,7 @@ comment = "Application for managing and playing games on Steam"; }; }; + programs.plasma.input.keyboard.layouts = lib.mkForce ["us"]; } ]; diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 2d135ad..e382060 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -132,6 +132,12 @@ in { number = 2; }; }; + input = { + keyboard = { + layouts = ["es"]; + numlockOnStartup = "off"; + }; + }; panels = [ { location = "bottom"; From f02f907932e93f0465db6178db9cc97d2e3fdf5a Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 13:45:20 +0200 Subject: [PATCH 0611/1125] Flake: update plasma-manager --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 163f32b..bc170ef 100644 --- a/flake.lock +++ b/flake.lock @@ -353,11 +353,11 @@ ] }, "locked": { - "lastModified": 1713952910, - "narHash": "sha256-7ICgAfFSQXZlWyhfSrGXAS0rg2YSMKqEO+4EF4lH25I=", + "lastModified": 1714390161, + "narHash": "sha256-hWPGLUGNr7IR2FT4xS0VlhTW3S6xpw0hU3LJJC3CaKo=", "owner": "toast003", "repo": "plasma-manager", - "rev": "13c65048f1f527c7d4ee1f921fa1847129139385", + "rev": "d9754f6f5dcf96969ad40496326213d5344846e5", "type": "github" }, "original": { From 760a3d3b2a9e8916c5f23cb17704cc4e223a0ad8 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 13:45:32 +0200 Subject: [PATCH 0612/1125] Kde/plasma: don't override config --- roles/kde/plasma.nix | 6 ------ 1 file changed, 6 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index e382060..f7052e8 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -108,12 +108,6 @@ in { ]; programs.plasma = { enable = true; - overrideConfig = true; - # Delete config files that I fully configure here - overrideConfigFiles = [ - "plasmashellrc" - "plasma-org.kde.plasma.desktop-appletsrc" - ]; workspace = { clickItemTo = "select"; cursorTheme = "Breeze_Snow"; From 012687565a98ca13bf21485b5938761c8020a026 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 13:56:33 +0200 Subject: [PATCH 0613/1125] Kde/plasma: update breeze packages --- roles/kde/plasma.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index f7052e8..13d1156 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -82,15 +82,15 @@ in { enable = true; # Most apps are dark, so a white cursor is easier to spot cursorTheme = { - package = pkgs.breeze-qt5; - name = "Breeze_Snow"; + package = pkgs.kdePackages.breeze; + name = "Breeze_Light"; }; iconTheme = { - package = pkgs.breeze-icons; + package = pkgs.kdePackages.breeze-icons; name = "breeze-dark"; }; theme = { - package = pkgs.breeze-gtk; + package = pkgs.kdePackages.breeze-gtk; name = "Breeze"; }; # Gtk2 doesn't have a dark mode, so I just tell gtk 3 and 4 to use the dark variant From 26798e0356d9b8c41b9e7a206ae9720fa259fd24 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 13:57:43 +0200 Subject: [PATCH 0614/1125] Kde/plasma: get rid of the custom breeze colorscheme --- roles/kde/plasma.nix | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 13d1156..7817573 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -19,21 +19,6 @@ }; }; - # Make custom packages - breezeTint = pkgs.stdenv.mkDerivation { - name = "breeze-tint"; - src = "${pkgs.breeze-qt5}"; - patches = [./patches/BreezeTint.patch]; - installPhase = '' - runHook preInstall - - mkdir -p $out/share/color-schemes/ - cp -r share/color-schemes/* $out/share/color-schemes/ - - runHook postInstall - ''; - }; - # /etc/xdg is not read by plasma, so to change the default settings you need to put them in a package plasmaDefaults = pkgs.stdenv.mkDerivation { name = "toast-plasma-defaults"; @@ -62,8 +47,8 @@ in { # GTK apps need dconf to grab the correct theme on Wayland programs.dconf.enable = true; - # Install the patched Breeze color schemes as well as the plasma default configs - environment.systemPackages = [breezeTint plasmaDefaults]; + # Install the plasma default configs + environment.systemPackages = [ plasmaDefaults]; # Plasma configs should be on all users home-manager.sharedModules = [ From 0be1aa7adc4f306f947cf0318f9092c000275dbf Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 18:55:29 +0200 Subject: [PATCH 0615/1125] Gaming: use qt6 version of prism launcher --- roles/gaming/programs/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/gaming/programs/default.nix b/roles/gaming/programs/default.nix index 4148b85..e43a6db 100755 --- a/roles/gaming/programs/default.nix +++ b/roles/gaming/programs/default.nix @@ -8,6 +8,6 @@ ]; environment.systemPackages = with pkgs; [ heroic - prismlauncher-qt5 + prismlauncher ]; } From 3425b0704018123069154dad71f907e19f118090 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 18:59:07 +0200 Subject: [PATCH 0616/1125] Kde/plasma: upgrade to plasma 6 --- roles/kde/plasma.nix | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 7817573..b9d835f 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -34,13 +34,8 @@ ''; }; in { - services = { - displayManager.defaultSession = "plasmawayland"; - xserver = { - # Enable the Plasma 5 Desktop Environment - desktopManager.plasma5.enable = true; - }; - }; + # Enable the Plasma 6 Desktop Environment + services.desktopManager.plasma6.enable = true; qt.enable = true; @@ -48,7 +43,7 @@ in { programs.dconf.enable = true; # Install the plasma default configs - environment.systemPackages = [ plasmaDefaults]; + environment.systemPackages = [plasmaDefaults]; # Plasma configs should be on all users home-manager.sharedModules = [ From b37b576eada65af3f26a674723f8157549c695a0 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 19:00:04 +0200 Subject: [PATCH 0617/1125] Kde/plasma: rename cursor name --- roles/kde/plasma.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index b9d835f..881694a 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -90,7 +90,7 @@ in { enable = true; workspace = { clickItemTo = "select"; - cursorTheme = "Breeze_Snow"; + cursorTheme = "Breeze_Light"; iconTheme = "breeze-dark"; lookAndFeel = "Catppuccin-Mocha-Mauve"; theme = "default"; From ca0c84006eedf7c86845128942d2e644462b9385 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Apr 2024 19:32:01 +0200 Subject: [PATCH 0618/1125] Kde/sddm: temporarely disable sdd theme --- roles/kde/sddm.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/kde/sddm.nix b/roles/kde/sddm.nix index bc331d7..9b7f8c9 100644 --- a/roles/kde/sddm.nix +++ b/roles/kde/sddm.nix @@ -45,12 +45,12 @@ in { # Enable SDDM. services.displayManager.sddm = { enable = true; - theme = "sugar-candy"; + # theme = "sugar-candy"; settings = { General = {Numlock = "off";}; Theme = {CursorTheme = "Breeze_Snow";}; }; }; - - environment.systemPackages = [sddm-sugar-candy customcfg]; + # Sugar candy doesn't seem to work on qt6 :( + # environment.systemPackages = [sddm-sugar-candy customcfg]; } From 6b8e8fc132aa1b86cc0da72f92e95f8e5e248637 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 1 May 2024 02:25:52 +0200 Subject: [PATCH 0619/1125] Gaming/pcsx2: set resolution multiplayer --- roles/gaming/programs/pcsx2.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index c475c07..22792a8 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -53,7 +53,10 @@ in { GameList.RecursivePaths = [ "/home/toast/Games/Isos/PS2/" ]; - "EmuCore/GS".dithering_ps2 = 1; + "EmuCore/GS" = { + dithering_ps2 = 1; + upscale_multiplier = 2; + }; EmuCore = { EnableDiscordPresence = true; EnableFastBoot = true; From 74116aa1109f76a5331ad8e3ce4291d53dcfe678 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 1 May 2024 02:40:41 +0200 Subject: [PATCH 0620/1125] Gaming/pcsx2: add default hotkeys --- roles/gaming/programs/pcsx2.nix | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index 22792a8..967fd22 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -95,6 +95,30 @@ in { LargeMotor = "SDL-0/LargeMotor"; SmallMotor = "SDL-0/SmallMotor"; }; + # Default hotkeys + Hotkeys = { + ToggleFullscreen = "Keyboard/Alt & Keyboard/Return"; + CycleAspectRatio = "Keyboard/F6"; + CycleInterlaceMode = "Keyboard/F5"; + CycleMipmapMode = "Keyboard/Insert"; + GSDumpMultiFrame = "Keyboard/Control & Keyboard/Shift & Keyboard/F8"; + Screenshot = "Keyboard/F8"; + GSDumpSingleFrame = "Keyboard/Shift & Keyboard/F8"; + ToggleSoftwareRendering = "Keyboard/F9"; + ZoomIn = "Keyboard/Control & Keyboard/Plus"; + ZoomOut = "Keyboard/Control & Keyboard/Minus"; + InputRecToggleMode = "Keyboard/Shift & Keyboard/R"; + LoadStateFromSlot = "Keyboard/F3"; + SaveStateToSlot = "Keyboard/F1"; + NextSaveStateSlot = "Keyboard/F2"; + PreviousSaveStateSlot = "Keyboard/Shift & Keyboard/F2"; + OpenPauseMenu = "Keyboard/Escape"; + ToggleFrameLimit = "Keyboard/F4"; + TogglePause = "Keyboard/Space"; + ToggleSlowMotion = "Keyboard/Shift & Keyboard/Backtab"; + ToggleTurbo = "Keyboard/Tab"; + HoldTurbo = "Keyboard/Period"; + }; }; # 007 nightfire "PCSX2/gamesettings/SLUS-20579_5B86BB62.ini".text = lib.generators.toINI {} { From 91ebf1acc9530bb06ac0b7c8b8982e7d5caa1462 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 1 May 2024 03:34:42 +0200 Subject: [PATCH 0621/1125] Gaming/pcsx2: set up syncthing --- roles/gaming/programs/pcsx2.nix | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index 967fd22..31b2fb9 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -133,4 +133,23 @@ in { ''; }; }; + + # Syncthing + services.syncthing.settings.folders."pcsx2" = { + label = "PCSX2"; + id = "qcdsp-qaaej"; + devices = ["steamdeck" "server" "pc" "winmax2"]; + path = "~/.config/PCSX2"; + }; + home-manager.users.toast.xdg.configFile = { + "PCSX2/.stignore".text = '' + cahe + bios + gamesettings + inis/PCSX2.int* + inis/debuggersettings + inputprofiles + logs + ''; + }; } From 2d49d6aece1cb9a8ffd38cda2806ff2c7f587a8b Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 1 May 2024 03:35:30 +0200 Subject: [PATCH 0622/1125] Server/syncthing: add pcsx2 folder --- roles/server/syncthing.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index b0e8f8c..b989171 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -26,6 +26,12 @@ devices = ["steamdeck" "server" "pc" "winmax2"]; path = "${config.services.syncthing.dataDir}/retroarch"; }; + "pcsx2" = { + label = "PCSX2"; + id = "qcdsp-qaaej"; + devices = ["steamdeck" "server" "pc" "winmax2"]; + path = "${config.services.syncthing.dataDir}/pcsx2"; + }; }; }; systemd.services.syncthing.serviceConfig = { From 8d8b118b36c47bdd10e7507f87caff43f81e16fd Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 3 May 2024 18:01:35 +0200 Subject: [PATCH 0623/1125] Flake: pin catppucin input The commit after this one breaks on nixos 23.11, and I can't be arsed to fix that rn --- flake.lock | 1 + flake.nix | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index bc170ef..816c04f 100644 --- a/flake.lock +++ b/flake.lock @@ -35,6 +35,7 @@ "original": { "owner": "catppuccin", "repo": "nix", + "rev": "a48e70a31616cb63e4794fd3465bff1835cc4246", "type": "github" } }, diff --git a/flake.nix b/flake.nix index 524a6a9..4c6d85f 100644 --- a/flake.nix +++ b/flake.nix @@ -66,7 +66,7 @@ nur.url = "github:nix-community/NUR"; - catppuccin.url = "github:catppuccin/nix"; + catppuccin.url = "github:catppuccin/nix/a48e70a31616cb63e4794fd3465bff1835cc4246"; }; outputs = {...} @ inputs: From c9646442f83c93b180ee49c7f623cebc5bac7601 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 3 May 2024 17:17:13 +0200 Subject: [PATCH 0624/1125] Gaming/syncthing: share wolfenstein the new order saves with winmax2 --- roles/gaming/services/syncthing.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/gaming/services/syncthing.nix b/roles/gaming/services/syncthing.nix index 5a1daa0..f511c87 100644 --- a/roles/gaming/services/syncthing.nix +++ b/roles/gaming/services/syncthing.nix @@ -8,7 +8,7 @@ "steam-201810" = { label = "Wolfenstein The New Order Saves"; id = "laxxf-t2wmy"; - devices = ["steamdeck" "server" "pc"]; + devices = ["steamdeck" "server" "pc" "winmax2"]; path = "~/.local/share/Steam/steamapps/compatdata/201810/pfx/drive_c/users/steamuser/Saved Games/MachineGames/Wolfenstein The New Order/"; }; }; From 008d792a4be2804839a48db80b8be8480666e3d4 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 3 May 2024 18:21:08 +0200 Subject: [PATCH 0625/1125] Flake: update lock file --- flake.lock | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/flake.lock b/flake.lock index 816c04f..75f984a 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1712079060, - "narHash": "sha256-/JdiT9t+zzjChc5qQiF+jhrVhRt8figYH29rZO7pFe4=", + "lastModified": 1714136352, + "narHash": "sha256-BtWQ2Th/jamO1SlD+2ASSW5Jaf7JhA/JLpQHk0Goqpg=", "owner": "ryantm", "repo": "agenix", - "rev": "1381a759b205dff7a6818733118d02253340fd5e", + "rev": "24a7ea390564ccd5b39b7884f597cfc8d7f6f44e", "type": "github" }, "original": { @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1713895615, - "narHash": "sha256-SVkxhcL0/IN5fNI2dqr702wXOnzktsm0LCEVGRAJQcY=", + "lastModified": 1714607657, + "narHash": "sha256-AnmN+JOzrpHv7Uw7JSPJ9JEjuqF7gjhx29UuuldNpas=", "owner": "catppuccin", "repo": "nix", - "rev": "a48e70a31616cb63e4794fd3465bff1835cc4246", + "rev": "b0dc7f3181063daa6532dc5f757ded1a605dfbd5", "type": "github" }, "original": { @@ -119,11 +119,11 @@ ] }, "locked": { - "lastModified": 1714042918, - "narHash": "sha256-4AItZA3EQIiSNAxliuYEJumw/LaVfrMv84gYyrs0r3U=", + "lastModified": 1714679908, + "narHash": "sha256-KzcXzDvDJjX34en8f3Zimm396x6idbt+cu4tWDVS2FI=", "owner": "nix-community", "repo": "home-manager", - "rev": "0c5704eceefcb7bb238a958f532a86e3b59d76db", + "rev": "9036fe9ef8e15a819fa76f47a8b1f287903fb848", "type": "github" }, "original": { @@ -161,11 +161,11 @@ ] }, "locked": { - "lastModified": 1714022840, - "narHash": "sha256-i6xZsf7Kvp1n/Sn3nqPY1MJQx0gf80OGQw32PA/aZd8=", + "lastModified": 1714720101, + "narHash": "sha256-Dxlj52coLzQZVV4a9IMMc/2xU5FIpj0iaHBigPwoNjM=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "94def3af1d45fe4b142beda3aa59a6a98e62ce9e", + "rev": "68b6bfacf67fcb1660c024b8dcd9376af38bbafe", "type": "github" }, "original": { @@ -234,11 +234,11 @@ ] }, "locked": { - "lastModified": 1713869268, - "narHash": "sha256-o3CMQeu/S8/4zU0pMtYg51rd1FWdJsI2Xohzng1Ysdg=", + "lastModified": 1714273701, + "narHash": "sha256-bmoeZ5zMSSO/e8P51yjrzaxA9uzA3SZAEFvih6S3LFo=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "dcb6ac44922858ce3a5b46f77a36d6030181460c", + "rev": "941c4973c824509e0356be455d89613611f76c8a", "type": "github" }, "original": { @@ -254,11 +254,11 @@ ] }, "locked": { - "lastModified": 1713869268, - "narHash": "sha256-o3CMQeu/S8/4zU0pMtYg51rd1FWdJsI2Xohzng1Ysdg=", + "lastModified": 1714273701, + "narHash": "sha256-bmoeZ5zMSSO/e8P51yjrzaxA9uzA3SZAEFvih6S3LFo=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "dcb6ac44922858ce3a5b46f77a36d6030181460c", + "rev": "941c4973c824509e0356be455d89613611f76c8a", "type": "github" }, "original": { @@ -269,11 +269,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1713864415, - "narHash": "sha256-/BPDMJEkrsFAFOsQWhwm31wezlgshPFlLBn34KEUdVA=", + "lastModified": 1714746424, + "narHash": "sha256-Jdyw7VcM+jQ0uSXgjFj8UdXZ229yOvPNlYkKyKyHA4s=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "797f8d8082c7cc3259cba7275c699d4991b09ecc", + "rev": "3f017311191fe6d501ca2496a835d012f656ee9c", "type": "github" }, "original": { @@ -301,11 +301,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1713995372, - "narHash": "sha256-fFE3M0vCoiSwCX02z8VF58jXFRj9enYUSTqjyHAjrds=", + "lastModified": 1714531828, + "narHash": "sha256-ILsf3bdY/hNNI/Hu5bSt2/KbmHaAVhBbNUOdGztTHEg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "dd37924974b9202f8226ed5d74a252a9785aedf8", + "rev": "0638fe2715d998fa81d173aad264eb671ce2ebc1", "type": "github" }, "original": { @@ -316,11 +316,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1713895582, - "narHash": "sha256-cfh1hi+6muQMbi9acOlju3V1gl8BEaZBXBR9jQfQi4U=", + "lastModified": 1714635257, + "narHash": "sha256-4cPymbty65RvF1DWQfc+Bc8B233A1BWxJnNULJKQ1EY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "572af610f6151fd41c212f897c71f7056e3fb518", + "rev": "63c3a29ca82437c87573e4c6919b09a24ea61b0f", "type": "github" }, "original": { @@ -331,11 +331,11 @@ }, "nur": { "locked": { - "lastModified": 1714114197, - "narHash": "sha256-f1kMNBUgbY+2/N0YkeouGNYdL7HVsRgcQLf5zL/ayd0=", + "lastModified": 1714746830, + "narHash": "sha256-c+I/pO6ZQjBGwykKpwuzzxc6Fsrn29iTdyenljxHn2I=", "owner": "nix-community", "repo": "NUR", - "rev": "10fc1b8b048fe797ada9302f700590afb457dde2", + "rev": "4d948474c1ba38a037fc52474fbbb3b79e8ac6e8", "type": "github" }, "original": { @@ -444,11 +444,11 @@ ] }, "locked": { - "lastModified": 1714094499, - "narHash": "sha256-SC6tm901h2tzRxd6hfzn5/bgLJ8R4ng39R7SIkg6wlo=", + "lastModified": 1714699387, + "narHash": "sha256-3PPA17RJvKjiaOnMSPYXnsg0Pux3GbQ4GXGAjJFOQZw=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "e05ff96b9f710d57d7cd60641f0273176debf222", + "rev": "e17d01c6d45bb73eda399c2f7f2dff6e2543c9a6", "type": "github" }, "original": { From aeed860735f1b705fd4fef9af9ef50c67f3260bc Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 6 May 2024 09:45:03 +0200 Subject: [PATCH 0626/1125] Flake: actually downgrade catppuccin input --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 75f984a..86e1dbd 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1714607657, - "narHash": "sha256-AnmN+JOzrpHv7Uw7JSPJ9JEjuqF7gjhx29UuuldNpas=", + "lastModified": 1713895615, + "narHash": "sha256-SVkxhcL0/IN5fNI2dqr702wXOnzktsm0LCEVGRAJQcY=", "owner": "catppuccin", "repo": "nix", - "rev": "b0dc7f3181063daa6532dc5f757ded1a605dfbd5", + "rev": "a48e70a31616cb63e4794fd3465bff1835cc4246", "type": "github" }, "original": { From 9e1ae553cf1a843e80630c233438cfb550acf39d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 7 May 2024 09:36:20 +0200 Subject: [PATCH 0627/1125] Flake: add nixpkgs patches --- flake.nix | 5 ++- ...Revert-handheld-daemon-undo-refactor.patch | 40 +++++++++++++++++++ .../0001-handheld-daemon-2.6.4-2.7.2.patch | 33 +++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 nixpkgs-patches/0001-Revert-handheld-daemon-undo-refactor.patch create mode 100644 nixpkgs-patches/0001-handheld-daemon-2.6.4-2.7.2.patch diff --git a/flake.nix b/flake.nix index 4c6d85f..44b41b8 100644 --- a/flake.nix +++ b/flake.nix @@ -77,7 +77,10 @@ nixpkgs-unstable-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; - patches = []; + patches = [ + ./nixpkgs-patches/0001-handheld-daemon-2.6.4-2.7.2.patch + ./nixpkgs-patches/0001-Revert-handheld-daemon-undo-refactor.patch + ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; diff --git a/nixpkgs-patches/0001-Revert-handheld-daemon-undo-refactor.patch b/nixpkgs-patches/0001-Revert-handheld-daemon-undo-refactor.patch new file mode 100644 index 0000000..a16b9e7 --- /dev/null +++ b/nixpkgs-patches/0001-Revert-handheld-daemon-undo-refactor.patch @@ -0,0 +1,40 @@ +From 904067bc281924e86e936c7d0162131e8af86d64 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 6 May 2024 12:26:54 +0200 +Subject: [PATCH 1/1] Revert "handheld-daemon: undo refactor" + +This reverts commit d9b487ae609a368378c1a9d89a5441c5c44121df. +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 246e3879bb5c..ad0554bec36d 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -34,15 +34,17 @@ python3.pkgs.buildPythonApplication rec { + doCheck = false; + + postPatch = '' ++ # The generated udev rules point to /bin/chmod, which does not exist in NixOS ++ substituteInPlace src/hhd/controller/lib/hide.py \ ++ --replace-fail /bin/chmod ${toybox}/bin/chmod ++ + # handheld-daemon contains a fork of the python module `hid`, so this hook + # is borrowed from the `hid` derivation. ++ substituteInPlace src/hhd/controller/lib/hid.py \ ++ --replace-fail libhidapi ${hidapi}/lib/libhidapi ++ + hidapi=${hidapi}/lib/ + test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } +- sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py +- +- # The generated udev rules point to /bin/chmod, which does not exist in NixOS +- chmod=${toybox}/bin/chmod +- sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py + ''; + + postInstall = '' +-- +2.44.0 + diff --git a/nixpkgs-patches/0001-handheld-daemon-2.6.4-2.7.2.patch b/nixpkgs-patches/0001-handheld-daemon-2.6.4-2.7.2.patch new file mode 100644 index 0000000..7921f80 --- /dev/null +++ b/nixpkgs-patches/0001-handheld-daemon-2.6.4-2.7.2.patch @@ -0,0 +1,33 @@ +From 742e26325f8d5b8bcc97afd11ae188c53c6f80f1 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 6 May 2024 11:52:09 +0200 +Subject: [PATCH 1/1] handheld-daemon: 2.6.4 -> 2.7.2 + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 246e3879bb5c..ec24637dde3f 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -9,14 +9,14 @@ + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "2.6.4"; ++ version = "2.7.2"; + pyproject = true; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + rev = "v${version}"; +- hash = "sha256-S77APtE1GGfqnv1IkZdJOSlprPOBtrqVXV60yVMvopg="; ++ hash = "sha256-jWLL1nmKam1iJ1R1l/OuIp+isgZ7toRhVamx1nOID/8="; + }; + + propagatedBuildInputs = with python3.pkgs; [ +-- +2.44.0 + From a66628290b11f12fa181b0d690b6b9faee62954a Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 7 May 2024 10:19:51 +0200 Subject: [PATCH 0628/1125] Desktop/discord: update vencord --- roles/desktop/programs/discord.nix | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 722d013..58051ae 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -9,18 +9,17 @@ withVencord = true; }; # Update some stuff while I wait for nixpkgs - /* vencord = super.vencord.overrideAttrs rec { - version = "522fdcd"; + version = "1.8.1"; src = pkgs.fetchFromGitHub { owner = "Vendicated"; repo = "Vencord"; - rev = "522fdcd"; - #rev = "v${version}"; - hash = "sha256-9G7FNL4pHaaLachzJmeAol0WpNUj533K2FNa7DH0eBM="; + rev = "a525cd0113b37fbe08512a6e68ecb62b8d74cd72"; + # rev = "v${version}"; + hash = "sha256-97KgELDNhP2aZU66tC+F/QfHuWnICGRzXQFQMbim4Sk="; }; + npmDepsHash = "sha256-97KgELDNhP2aZU66tC+F/QfHuWnICGRzXQFQMbim4Sk="; }; - */ }; stock-discord = _self: super: { discord = super.discord.override { From f704fd47d1d5e38a5805390d2a66cc3dccd4d2c9 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 11 May 2024 20:35:16 +0200 Subject: [PATCH 0629/1125] Machines/SteamDeck: mount persist subvolume --- machines/SteamDeck/hardware-configuration.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/machines/SteamDeck/hardware-configuration.nix b/machines/SteamDeck/hardware-configuration.nix index 74f2cd4..4ade12c 100755 --- a/machines/SteamDeck/hardware-configuration.nix +++ b/machines/SteamDeck/hardware-configuration.nix @@ -45,6 +45,13 @@ in { fsType = "btrfs"; options = ["subvol=@" "compress=zstd"]; }; + "btrfs_persist" = { + mountPoint = "/persist"; + label = ssdLabel; + fsType = "btrfs"; + options = ["subvol=@persist"]; + neededForBoot = true; + }; "btrfs_boot" = { mountPoint = "/boot"; label = ssdLabel; From 72557d36eaf61a644614ef2d7aff6aa17c38284e Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 11 May 2024 20:49:53 +0200 Subject: [PATCH 0630/1125] Flake: update secrets --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 86e1dbd..94b2859 100644 --- a/flake.lock +++ b/flake.lock @@ -392,11 +392,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1713910881, - "narHash": "sha256-MZ1+GmZL3V3Kqe4YrxPA2W8vrF/c+f7sYOpf+jw6ESc=", + "lastModified": 1715453060, + "narHash": "sha256-dhfjA0/x7V3Jug7a52wsELwb5jmNtJvPD0HC8jc2Ky8=", "ref": "refs/heads/main", - "rev": "918b61f3ee194d7e67fa1d3200b64fe7741dd24a", - "revCount": 15, + "rev": "08944755d22a7499b0b3fd39d48fdf1dabf4c83f", + "revCount": 19, "type": "git", "url": "ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets" }, From 94b0eb3d65c785515d60c64b46cd9d935f0c6592 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 11 May 2024 20:51:45 +0200 Subject: [PATCH 0631/1125] Machines: Update jovian desktop session name --- machines/SteamDeck/configuration.nix | 2 +- machines/WinMax2/configuration.nix | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/machines/SteamDeck/configuration.nix b/machines/SteamDeck/configuration.nix index 7c2af0a..c14385e 100755 --- a/machines/SteamDeck/configuration.nix +++ b/machines/SteamDeck/configuration.nix @@ -39,7 +39,7 @@ enable = true; autoStart = true; user = "toast"; - desktopSession = "plasmawayland"; + desktopSession = "plasma"; }; decky-loader = { enable = true; diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 65f51ff..707a949 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -73,7 +73,7 @@ enable = true; autoStart = false; user = "toast"; - desktopSession = "plasmawayland"; + desktopSession = "plasma"; }; hardware.amd.gpu.enableBacklightControl = true; # Need patched mesa From e2925ee06a15009e9d7d95fdd84dd8e217f2e7e3 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 14 May 2024 19:00:01 +0200 Subject: [PATCH 0632/1125] Machines/WinMax2: enable bolt --- machines/WinMax2/configuration.nix | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 707a949..e8bf59f 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -48,9 +48,12 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="disabled" ''; - services.handheld-daemon = { - enable = true; - user = "toast"; + services = { + hardware.bolt.enable = true; + handheld-daemon = { + enable = true; + user = "toast"; + }; }; # Allow unfree packages From 3931366eb957ee99e60971b5416132191b54ed28 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 14 May 2024 19:01:18 +0200 Subject: [PATCH 0633/1125] Kde/plasma: install plasma-thundetbolt --- roles/kde/plasma.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 881694a..b91dd3f 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -43,7 +43,7 @@ in { programs.dconf.enable = true; # Install the plasma default configs - environment.systemPackages = [plasmaDefaults]; + environment.systemPackages = [plasmaDefaults pkgs.kdePackages.plasma-thunderbolt]; # Plasma configs should be on all users home-manager.sharedModules = [ From 316a147c4a25caaae1441ecb0aab5392c153d498 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 14 May 2024 19:03:48 +0200 Subject: [PATCH 0634/1125] Machines/WinMax2: refactor steam scaling --- machines/WinMax2/configuration.nix | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index e8bf59f..69e10ea 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -101,20 +101,18 @@ # Enable CUPS to print documents. # services.printing.enable = true; - environment.sessionVariables = { - STEAM_FORCE_DESKTOPUI_SCALING = "2"; - }; home-manager.sharedModules = [ { # Steam's hidpi support is bugged so it needds to be hardcoded - # This bypasses that xdg.desktopEntries = { steam-noScaling = { - name = "Steam (No Scaling)"; - exec = "env STEAM_FORCE_DESKTOPUI_SCALING=0 steam %U"; + name = "Steam (2x scale)"; + exec = "env STEAM_FORCE_DESKTOPUI_SCALING=2 steam %U"; icon = "steam"; categories = ["Network" "FileTransfer" "Game"]; comment = "Application for managing and playing games on Steam"; + prefersNonDefaultGPU = true; + settings.X-KDE-RunOnDiscreteGpu = "true"; }; }; programs.plasma.input.keyboard.layouts = lib.mkForce ["us"]; From b740d56f03a20bd195989a175182b8e10999f21e Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 14 May 2024 19:04:18 +0200 Subject: [PATCH 0635/1125] Machines/WinMax2: add spanish keyboard layout to plasma --- machines/WinMax2/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 69e10ea..0eaceec 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -115,7 +115,7 @@ settings.X-KDE-RunOnDiscreteGpu = "true"; }; }; - programs.plasma.input.keyboard.layouts = lib.mkForce ["us"]; + programs.plasma.input.keyboard.layouts = lib.mkForce ["us" "es"]; } ]; From 19985c86da4b3cf838622197556d2eae6c60079b Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 14 May 2024 20:38:59 +0200 Subject: [PATCH 0636/1125] Kde/sddm: enable wayland --- roles/kde/sddm.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/kde/sddm.nix b/roles/kde/sddm.nix index 9b7f8c9..4a52489 100644 --- a/roles/kde/sddm.nix +++ b/roles/kde/sddm.nix @@ -45,6 +45,7 @@ in { # Enable SDDM. services.displayManager.sddm = { enable = true; + wayland.enable = true; # theme = "sugar-candy"; settings = { General = {Numlock = "off";}; From 28a3bf2509eda9df8f9e17e218d93972093f27ee Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 May 2024 01:31:40 +0200 Subject: [PATCH 0637/1125] School: remove most of the role --- roles/school/default.nix | 1 - roles/school/programs/default.nix | 13 ---------- roles/school/programs/helix.nix | 10 -------- roles/school/programs/jetbrains.nix | 19 --------------- roles/school/programs/unity.nix | 8 ------- roles/school/programs/virtualbox.nix | 15 ------------ roles/school/programs/vscode.nix | 23 ------------------ roles/school/services/default.nix | 3 --- roles/school/services/mongodb.nix | 34 -------------------------- roles/school/services/mysql.nix | 36 ---------------------------- roles/school/services/xampp.nix | 34 -------------------------- 11 files changed, 196 deletions(-) delete mode 100644 roles/school/programs/default.nix delete mode 100644 roles/school/programs/helix.nix delete mode 100644 roles/school/programs/jetbrains.nix delete mode 100644 roles/school/programs/unity.nix delete mode 100644 roles/school/programs/virtualbox.nix delete mode 100644 roles/school/programs/vscode.nix delete mode 100644 roles/school/services/mongodb.nix delete mode 100644 roles/school/services/mysql.nix delete mode 100644 roles/school/services/xampp.nix diff --git a/roles/school/default.nix b/roles/school/default.nix index 515d2d6..dc31263 100644 --- a/roles/school/default.nix +++ b/roles/school/default.nix @@ -1,6 +1,5 @@ {...}: { imports = [ ./services - ./programs ]; } diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix deleted file mode 100644 index 24452c0..0000000 --- a/roles/school/programs/default.nix +++ /dev/null @@ -1,13 +0,0 @@ -{pkgs, ...}: { - imports = [ - ./virtualbox.nix - ./jetbrains.nix - ./vscode.nix - ./helix.nix - ./unity.nix - ]; - - environment.systemPackages = with pkgs; [ - dia - ]; -} diff --git a/roles/school/programs/helix.nix b/roles/school/programs/helix.nix deleted file mode 100644 index e16ddf0..0000000 --- a/roles/school/programs/helix.nix +++ /dev/null @@ -1,10 +0,0 @@ -{pkgs, ...}: { - home-manager.users.toast = { - programs.helix = { - extraPackages = with pkgs; [ - nodePackages.typescript-language-server - omnisharp-roslyn - ]; - }; - }; -} diff --git a/roles/school/programs/jetbrains.nix b/roles/school/programs/jetbrains.nix deleted file mode 100644 index 57fe938..0000000 --- a/roles/school/programs/jetbrains.nix +++ /dev/null @@ -1,19 +0,0 @@ -{pkgs, ...}: -with pkgs; { - environment.systemPackages = with jetbrains; [ - idea-ultimate - scenebuilder - datagrip - ]; - - home-manager.users.toast = { - /* - If you use programs.java.enable intellij picks up the jdk package directly, which is not ideal - This adds the jdks I want to use to a directory intellij expects jdks to be - */ - home.file.".jdks/jdk8".source = "${pkgs.jdk8}/lib/openjdk"; - home.file.".jdks/jdk17".source = let - jdk17 = pkgs.jdk17.override {enableJavaFX = true;}; - in "${jdk17}/lib/openjdk"; - }; -} diff --git a/roles/school/programs/unity.nix b/roles/school/programs/unity.nix deleted file mode 100644 index b30daf4..0000000 --- a/roles/school/programs/unity.nix +++ /dev/null @@ -1,8 +0,0 @@ -{pkgs, ...}: { - home-manager.users.toast = { - home.packages = with pkgs; [ - unityhub - jetbrains.rider - ]; - }; -} diff --git a/roles/school/programs/virtualbox.nix b/roles/school/programs/virtualbox.nix deleted file mode 100644 index 58e7ff1..0000000 --- a/roles/school/programs/virtualbox.nix +++ /dev/null @@ -1,15 +0,0 @@ -{...}: { - # Need to use visual studio 2019 :( - virtualisation.virtualbox.host = { - enable = true; - }; - home-manager.sharedModules = [ - { - systemd.user.tmpfiles.rules = [ - "d '/%h/VirtualBox VMs'" - "h '/%h/VirtualBox VMs' - - - - C " - ]; - } - ]; - users.users.toast.extraGroups = ["vboxusers"]; -} diff --git a/roles/school/programs/vscode.nix b/roles/school/programs/vscode.nix deleted file mode 100644 index e39e633..0000000 --- a/roles/school/programs/vscode.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ - pkgs, - lib, - flakeSelf, - ... -}: let - inputs = flakeSelf.inputs; -in { - home-manager.users.toast.programs.vscode = { - # The redhat xml extension needs an fhs environment - package = lib.mkForce pkgs.vscodium-fhs; - extensions = with inputs.vscode-extensions.extensions.x86_64-linux; [ - open-vsx.redhat.vscode-xml - open-vsx.tomoki1207.pdf - open-vsx.ms-vscode.live-server - open-vsx.ecmel.vscode-html-css - open-vsx.angular.ng-template - ]; - userSettings = { - redhat.telemetry.enabled = false; - }; - }; -} diff --git a/roles/school/services/default.nix b/roles/school/services/default.nix index 350d7bd..24b067d 100644 --- a/roles/school/services/default.nix +++ b/roles/school/services/default.nix @@ -1,8 +1,5 @@ {...}: { imports = [ ./syncthing.nix - ./mysql.nix - ./xampp.nix - ./mongodb.nix ]; } diff --git a/roles/school/services/mongodb.nix b/roles/school/services/mongodb.nix deleted file mode 100644 index 42c12fc..0000000 --- a/roles/school/services/mongodb.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ - config, - pkgs, - lib, - ... -}: { - services.mongodb = { - enable = true; - package = pkgs.mongodb-5_0; - user = "toast"; - }; - - # Don't autostart MySQL - systemd.services.mongodb.wantedBy = lib.mkForce []; - - # Allow regular users to start/stop mongodb - # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service - security.polkit.extraConfig = '' - polkit.addRule(function(action, subject) { - if ( - action.id == "org.freedesktop.systemd1.manage-units" && - action.lookup("unit") == "mongodb.service" && - subject.user == "${config.services.mongodb.user}" - ) - { - return polkit.Result.YES; - } - }) - ''; - - environment.systemPackages = with pkgs; [ - mongosh - ]; -} diff --git a/roles/school/services/mysql.nix b/roles/school/services/mysql.nix deleted file mode 100644 index fbbd3f9..0000000 --- a/roles/school/services/mysql.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ - config, - pkgs, - lib, - ... -}: { - services.mysql = { - enable = true; - package = pkgs.mysql80; - user = "toast"; - group = "users"; - }; - - # Don't autostart MySQL - systemd.services.mysql.wantedBy = lib.mkForce []; - - # Allow regular users to start/stop mysql - # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service - security.polkit.extraConfig = '' - polkit.addRule(function(action, subject) { - if ( - action.id == "org.freedesktop.systemd1.manage-units" && - action.lookup("unit") == "mysql.service" && - subject.user == "${config.services.mysql.user}" - ) - { - return polkit.Result.YES; - } - }) - ''; - - environment.systemPackages = with pkgs; [ - mysql-workbench - mycli - ]; -} diff --git a/roles/school/services/xampp.nix b/roles/school/services/xampp.nix deleted file mode 100644 index 26ee73b..0000000 --- a/roles/school/services/xampp.nix +++ /dev/null @@ -1,34 +0,0 @@ -{pkgs, ...}: let - booDark = pkgs.fetchzip { - url = "https://github.com/adorade/boodark/releases/download/v1.1.1/boodark-v1.1.1.zip"; - hash = "sha256-GE/FtFlU6A4I9sRyjMhQIidGpDLD99Wzzngz3QI/rSo="; - }; -in { - # I tried setting up httpd + php in class but I just gave up - virtualisation.oci-containers = { - containers."xampp" = { - autoStart = false; - image = "tomsik68/xampp"; - #user = "${toString users.users.atfc.uid}:${toString users.groups.minecraft.gid}"; - volumes = [ - "xampp-mysql:/opt/lampp/var/mysql" - # No dark mode installed by default :( - "${booDark}:/opt/lampp/phpmyadmin/themes/booDark" - ]; - ports = ["41061:22" "41062:80"]; - }; - }; - - security.polkit.extraConfig = '' - polkit.addRule(function(action, subject) { - if ( - action.id == "org.freedesktop.systemd1.manage-units" && - action.lookup("unit") == "podman-xampp.service" && - subject.user == "toast" - ) - { - return polkit.Result.YES; - } - }) - ''; -} From cc11a5a38690b48d3da7d1732c0c69e1a37548e8 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 May 2024 12:14:41 +0200 Subject: [PATCH 0638/1125] Desktop: add mpv --- roles/desktop/programs/default.nix | 1 + roles/desktop/programs/mpv.nix | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 roles/desktop/programs/mpv.nix diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix index 7bceb47..30c6c6f 100755 --- a/roles/desktop/programs/default.nix +++ b/roles/desktop/programs/default.nix @@ -9,5 +9,6 @@ ./git.nix ./ssh.nix ./appimage.nix + ./mpv.nix ]; } diff --git a/roles/desktop/programs/mpv.nix b/roles/desktop/programs/mpv.nix new file mode 100644 index 0000000..81b8392 --- /dev/null +++ b/roles/desktop/programs/mpv.nix @@ -0,0 +1,14 @@ +{pkgs, ...}: { + home-manager.users.toast = { + programs.mpv = { + enable = true; + scripts = with pkgs.mpvScripts; [ + mpris + ]; + config = { + hwdec = "auto"; + cache = true; + }; + }; + }; +} From fbe01084d28f8d6a6c92b396500883a6ccb9fed6 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 May 2024 13:28:50 +0200 Subject: [PATCH 0639/1125] Desktop/discord: get rid of official discord app --- roles/desktop/programs/discord.nix | 34 ++++++++---------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 58051ae..dc5485d 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -1,42 +1,26 @@ -{ - pkgs, - lib, - ... -}: let +{pkgs, ...}: let discordOverlay = _self: super: { discord = super.discord.override { withOpenASAR = true; withVencord = true; }; # Update some stuff while I wait for nixpkgs - vencord = super.vencord.overrideAttrs rec { - version = "1.8.1"; - src = pkgs.fetchFromGitHub { - owner = "Vendicated"; - repo = "Vencord"; + vencord = super.vencord.overrideAttrs rec { + version = "1.8.1"; + src = pkgs.fetchFromGitHub { + owner = "Vendicated"; + repo = "Vencord"; rev = "a525cd0113b37fbe08512a6e68ecb62b8d74cd72"; - # rev = "v${version}"; - hash = "sha256-97KgELDNhP2aZU66tC+F/QfHuWnICGRzXQFQMbim4Sk="; - }; + # rev = "v${version}"; + hash = "sha256-97KgELDNhP2aZU66tC+F/QfHuWnICGRzXQFQMbim4Sk="; + }; npmDepsHash = "sha256-97KgELDNhP2aZU66tC+F/QfHuWnICGRzXQFQMbim4Sk="; }; }; - stock-discord = _self: super: { - discord = super.discord.override { - withOpenASAR = false; - withVencord = false; - }; - }; in { - # Sometimes discord breaks after updates, and launching it stock once fixes it - specialisation.stockDiscord.configuration = { - nixpkgs.overlays = lib.mkAfter [stock-discord]; - }; - nixpkgs.overlays = [discordOverlay]; home-manager.users.toast = { home.packages = with pkgs; [ - discord vesktop ]; }; From 89c600766a039dbcd88e61ae4ae679229fe5dd1a Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 May 2024 14:01:12 +0200 Subject: [PATCH 0640/1125] Desktop/discord: update vencord --- roles/desktop/programs/discord.nix | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index dc5485d..62aa940 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -6,15 +6,14 @@ }; # Update some stuff while I wait for nixpkgs vencord = super.vencord.overrideAttrs rec { - version = "1.8.1"; + version = "1.8.4"; src = pkgs.fetchFromGitHub { owner = "Vendicated"; repo = "Vencord"; - rev = "a525cd0113b37fbe08512a6e68ecb62b8d74cd72"; - # rev = "v${version}"; - hash = "sha256-97KgELDNhP2aZU66tC+F/QfHuWnICGRzXQFQMbim4Sk="; + rev = "v${version}"; + hash = "sha256-FbU1Zsz/84oSOCOSWunA5nn5qFGLQ4W3uqsbYytF/7c="; }; - npmDepsHash = "sha256-97KgELDNhP2aZU66tC+F/QfHuWnICGRzXQFQMbim4Sk="; + npmDepsHash = "sha256-97KgELDNhP2aZU66tC+F/QfHuWnICGRzX3FQMbim4Sk="; }; }; in { From 6628a2d1815ca757654c3a40c74abe7c456005e6 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 May 2024 18:55:03 +0200 Subject: [PATCH 0641/1125] Flake: update lock file and remove uneeded nixpkgs patch --- flake.lock | 72 +++++++++---------- flake.nix | 1 - .../0001-handheld-daemon-2.6.4-2.7.2.patch | 33 --------- 3 files changed, 36 insertions(+), 70 deletions(-) delete mode 100644 nixpkgs-patches/0001-handheld-daemon-2.6.4-2.7.2.patch diff --git a/flake.lock b/flake.lock index 94b2859..76651e1 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1714136352, - "narHash": "sha256-BtWQ2Th/jamO1SlD+2ASSW5Jaf7JhA/JLpQHk0Goqpg=", + "lastModified": 1715290355, + "narHash": "sha256-2T7CHTqBXJJ3ZC6R/4TXTcKoXWHcvubKNj9SfomURnw=", "owner": "ryantm", "repo": "agenix", - "rev": "24a7ea390564ccd5b39b7884f597cfc8d7f6f44e", + "rev": "8d37c5bdeade12b6479c85acd133063ab53187a0", "type": "github" }, "original": { @@ -44,11 +44,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1713966850, - "narHash": "sha256-AHAkkTUjk86rED3pQh8i4OiSze+OHe697L0o3zhv89A=", + "lastModified": 1715401925, + "narHash": "sha256-EGZGHCv4OFqzFc9oP82LCKMWfMGsmadOOZ0DZHYSdns=", "owner": "catppuccin", "repo": "vscode", - "rev": "75d96f3ae48b249f77124688a026ca5d7eeb5fb2", + "rev": "f0a6271f62ebb868f32c7ad4ecb31104c26f987a", "type": "github" }, "original": { @@ -119,11 +119,11 @@ ] }, "locked": { - "lastModified": 1714679908, - "narHash": "sha256-KzcXzDvDJjX34en8f3Zimm396x6idbt+cu4tWDVS2FI=", + "lastModified": 1715930644, + "narHash": "sha256-W9pyM3/vePxrffHtzlJI6lDS3seANQ+Nqp+i58O46LI=", "owner": "nix-community", "repo": "home-manager", - "rev": "9036fe9ef8e15a819fa76f47a8b1f287903fb848", + "rev": "e3ad5108f54177e6520535768ddbf1e6af54b59d", "type": "github" }, "original": { @@ -139,11 +139,11 @@ ] }, "locked": { - "lastModified": 1714043624, - "narHash": "sha256-Xn2r0Jv95TswvPlvamCC46wwNo8ALjRCMBJbGykdhcM=", + "lastModified": 1715381426, + "narHash": "sha256-wPuqrAQGdv3ISs74nJfGb+Yprm23U/rFpcHFFNWgM94=", "owner": "nix-community", "repo": "home-manager", - "rev": "86853e31dc1b62c6eeed11c667e8cdd0285d4411", + "rev": "ab5542e9dbd13d0100f8baae2bc2d68af901f4b4", "type": "github" }, "original": { @@ -161,11 +161,11 @@ ] }, "locked": { - "lastModified": 1714720101, - "narHash": "sha256-Dxlj52coLzQZVV4a9IMMc/2xU5FIpj0iaHBigPwoNjM=", + "lastModified": 1715922002, + "narHash": "sha256-FSUrne82MXFzZ7R88ZnJz21kv06GS2TS/Ctsd+RXbP4=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "68b6bfacf67fcb1660c024b8dcd9376af38bbafe", + "rev": "23a55d6bb80f6340d0acdb9feef754646b68f895", "type": "github" }, "original": { @@ -234,11 +234,11 @@ ] }, "locked": { - "lastModified": 1714273701, - "narHash": "sha256-bmoeZ5zMSSO/e8P51yjrzaxA9uzA3SZAEFvih6S3LFo=", + "lastModified": 1715483403, + "narHash": "sha256-WMDuQj7J5jbpXI/X/E6FZRKgBFGcaSTvYyVxPnKE6KU=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "941c4973c824509e0356be455d89613611f76c8a", + "rev": "f9027322f48b427da23746aa359a6510dfcd0228", "type": "github" }, "original": { @@ -254,11 +254,11 @@ ] }, "locked": { - "lastModified": 1714273701, - "narHash": "sha256-bmoeZ5zMSSO/e8P51yjrzaxA9uzA3SZAEFvih6S3LFo=", + "lastModified": 1715483403, + "narHash": "sha256-WMDuQj7J5jbpXI/X/E6FZRKgBFGcaSTvYyVxPnKE6KU=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "941c4973c824509e0356be455d89613611f76c8a", + "rev": "f9027322f48b427da23746aa359a6510dfcd0228", "type": "github" }, "original": { @@ -269,11 +269,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1714746424, - "narHash": "sha256-Jdyw7VcM+jQ0uSXgjFj8UdXZ229yOvPNlYkKyKyHA4s=", + "lastModified": 1715881912, + "narHash": "sha256-e4LJk5uV1wvrRkffGFZekPWvFUx29NnnOahBlLaq8Ek=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "3f017311191fe6d501ca2496a835d012f656ee9c", + "rev": "ff1be1e3cdf884df0935ab28745ab13c3c26d828", "type": "github" }, "original": { @@ -301,11 +301,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1714531828, - "narHash": "sha256-ILsf3bdY/hNNI/Hu5bSt2/KbmHaAVhBbNUOdGztTHEg=", + "lastModified": 1715668745, + "narHash": "sha256-xp62OkRkbUDNUc6VSqH02jB0FbOS+MsfMb7wL1RJOfA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0638fe2715d998fa81d173aad264eb671ce2ebc1", + "rev": "9ddcaffecdf098822d944d4147dd8da30b4e6843", "type": "github" }, "original": { @@ -316,11 +316,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1714635257, - "narHash": "sha256-4cPymbty65RvF1DWQfc+Bc8B233A1BWxJnNULJKQ1EY=", + "lastModified": 1715787315, + "narHash": "sha256-cYApT0NXJfqBkKcci7D9Kr4CBYZKOQKDYA23q8XNuWg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "63c3a29ca82437c87573e4c6919b09a24ea61b0f", + "rev": "33d1e753c82ffc557b4a585c77de43d4c922ebb5", "type": "github" }, "original": { @@ -331,11 +331,11 @@ }, "nur": { "locked": { - "lastModified": 1714746830, - "narHash": "sha256-c+I/pO6ZQjBGwykKpwuzzxc6Fsrn29iTdyenljxHn2I=", + "lastModified": 1716022947, + "narHash": "sha256-6MpQHyMEF0hSGFGeCJurXnRTFJ5D3BDynwaw4egCIME=", "owner": "nix-community", "repo": "NUR", - "rev": "4d948474c1ba38a037fc52474fbbb3b79e8ac6e8", + "rev": "76a11ee5e3b36f2a140a827fd266da5dd64f07b7", "type": "github" }, "original": { @@ -444,11 +444,11 @@ ] }, "locked": { - "lastModified": 1714699387, - "narHash": "sha256-3PPA17RJvKjiaOnMSPYXnsg0Pux3GbQ4GXGAjJFOQZw=", + "lastModified": 1715995317, + "narHash": "sha256-Pt6Lkr3qteSi4nF5x9RPrnOLoH1bZYnxLmhYVJHyZpY=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "e17d01c6d45bb73eda399c2f7f2dff6e2543c9a6", + "rev": "6c49c56d4365278f755a2a05ee8581706afed626", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 44b41b8..f9715fa 100644 --- a/flake.nix +++ b/flake.nix @@ -78,7 +78,6 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/0001-handheld-daemon-2.6.4-2.7.2.patch ./nixpkgs-patches/0001-Revert-handheld-daemon-undo-refactor.patch ]; }; diff --git a/nixpkgs-patches/0001-handheld-daemon-2.6.4-2.7.2.patch b/nixpkgs-patches/0001-handheld-daemon-2.6.4-2.7.2.patch deleted file mode 100644 index 7921f80..0000000 --- a/nixpkgs-patches/0001-handheld-daemon-2.6.4-2.7.2.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 742e26325f8d5b8bcc97afd11ae188c53c6f80f1 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 6 May 2024 11:52:09 +0200 -Subject: [PATCH 1/1] handheld-daemon: 2.6.4 -> 2.7.2 - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 246e3879bb5c..ec24637dde3f 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -9,14 +9,14 @@ - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "2.6.4"; -+ version = "2.7.2"; - pyproject = true; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - rev = "v${version}"; -- hash = "sha256-S77APtE1GGfqnv1IkZdJOSlprPOBtrqVXV60yVMvopg="; -+ hash = "sha256-jWLL1nmKam1iJ1R1l/OuIp+isgZ7toRhVamx1nOID/8="; - }; - - propagatedBuildInputs = with python3.pkgs; [ --- -2.44.0 - From 1fad8258684a330d0fb9627aade6587009351188 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 22 May 2024 00:43:32 +0200 Subject: [PATCH 0642/1125] Gaming/pcsx2: rework iso compression --- roles/gaming/programs/pcsx2.nix | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index 31b2fb9..0bdb17c 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -5,22 +5,25 @@ }: let ps2-isos = pkgs.symlinkJoin { name = "ps2-isos"; - paths = [ - (pkgs.fetchzip { - url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202/007%20-%20Nightfire%20%28USA%29.zip"; - hash = "sha256-66Ey0SqC3Tk02Af+xR6rpxYSkO0n83NWYPCt4M3CUWo="; - }) - ]; + paths = + lib.lists.forEach [ + (pkgs.fetchzip { + url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202/007%20-%20Nightfire%20%28USA%29.zip"; + hash = "sha256-66Ey0SqC3Tk02Af+xR6rpxYSkO0n83NWYPCt4M3CUWo="; + }) + ] + compress; }; - compressed-ps2-isos = pkgs.runCommand "compressed-ps2-isos" {} '' - mkdir $out - cd ${ps2-isos} - for file in ./* - do - ${pkgs.mame-tools}/bin/chdman createdvd -i "$file" -o "$out/''${file%.iso}.chd" - done - ''; + compress = iso: + pkgs.runCommand "compressed-ps2-isos" {} '' + mkdir $out + cd ${iso} + for file in ./* + do + ${pkgs.mame-tools}/bin/chdman createdvd -i "$file" -o "$out/''${file%.iso}.chd" + done + ''; pcsx2-bios = pkgs.fetchzip { url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202%20-%20BIOS%20Images/ps2-0200a-20040614.zip"; @@ -32,7 +35,7 @@ in { packages = with pkgs; [ pcsx2 ]; - file."Games/Isos/PS2".source = compressed-ps2-isos; + file."Games/Isos/PS2".source = ps2-isos; }; xdg.configFile = { #PCSX2 silently overwrites the symlink so I need to force it's creation From 07217c677747b46ff946f4ea14d2c42324c756da Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 24 May 2024 11:19:31 +0200 Subject: [PATCH 0643/1125] Gaming/pcsx2: add timesplitters 2 --- roles/gaming/programs/pcsx2.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index 0bdb17c..b378ca2 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -11,6 +11,10 @@ url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202/007%20-%20Nightfire%20%28USA%29.zip"; hash = "sha256-66Ey0SqC3Tk02Af+xR6rpxYSkO0n83NWYPCt4M3CUWo="; }) + (pkgs.fetchzip { + url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202/TimeSplitters%202%20%28USA%29.zip"; + hash = "sha256-UPED4/MF9fjTOgiIJy+CSbuO9cJr3CsR/gEquY6GfsU="; + }) ] compress; }; From e3f0c2666f12b7c1b728342652692a31d76a54fb Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 25 May 2024 00:56:36 +0200 Subject: [PATCH 0644/1125] Machines/WinMax2: disable fingerprint reader --- machines/WinMax2/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 0eaceec..58d49eb 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -46,6 +46,7 @@ services.udev.extraRules = '' ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="GXTP7385:00", ATTR{power/wakeup}="disabled" ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="disabled" + SUBSYSTEM=="usb", ATTR{idVendor}=="2541", ATTR{idProduct}=="9711", ATTR{authorized}="0" ''; services = { From 9fc7d0c26b9c731c3f4f562b5adf7575d34220fb Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 25 May 2024 02:17:22 +0200 Subject: [PATCH 0645/1125] Machines/WinMax2: remove fingerprint reader instead of disabling --- machines/WinMax2/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 58d49eb..9b8f4ae 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -46,7 +46,7 @@ services.udev.extraRules = '' ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="GXTP7385:00", ATTR{power/wakeup}="disabled" ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="disabled" - SUBSYSTEM=="usb", ATTR{idVendor}=="2541", ATTR{idProduct}=="9711", ATTR{authorized}="0" + SUBSYSTEM=="usb", ATTR{idVendor}=="2541", ATTR{idProduct}=="9711", ATTR{remove}="1" ''; services = { From b7d90ad5a549ea424f3179718d0597c27c48cca7 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 25 May 2024 16:03:52 +0200 Subject: [PATCH 0646/1125] Common/direnv: configure using home-manager --- roles/common/programs/direnv.nix | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/roles/common/programs/direnv.nix b/roles/common/programs/direnv.nix index 856dcbb..e4a4e29 100644 --- a/roles/common/programs/direnv.nix +++ b/roles/common/programs/direnv.nix @@ -1,8 +1,10 @@ {...}: { - programs.direnv = { - enable = true; - nix-direnv = { + home-manager.users.toast = { + programs.direnv = { enable = true; + nix-direnv = { + enable = true; + }; }; }; } From 57c9e8d66f103e37a8dd006a6f08b0e10bd73e6a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 31 May 2024 00:40:01 +0200 Subject: [PATCH 0647/1125] Flake: update lock file --- flake.lock | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/flake.lock b/flake.lock index 76651e1..8f269bf 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1715290355, - "narHash": "sha256-2T7CHTqBXJJ3ZC6R/4TXTcKoXWHcvubKNj9SfomURnw=", + "lastModified": 1716561646, + "narHash": "sha256-UIGtLO89RxKt7RF2iEgPikSdU53r6v/6WYB0RW3k89I=", "owner": "ryantm", "repo": "agenix", - "rev": "8d37c5bdeade12b6479c85acd133063ab53187a0", + "rev": "c2fc0762bbe8feb06a2e59a364fa81b3a57671c9", "type": "github" }, "original": { @@ -119,11 +119,11 @@ ] }, "locked": { - "lastModified": 1715930644, - "narHash": "sha256-W9pyM3/vePxrffHtzlJI6lDS3seANQ+Nqp+i58O46LI=", + "lastModified": 1717052710, + "narHash": "sha256-LRhOxzXmOza5SymhOgnEzA8EAQp+94kkeUYWKKpLJ/U=", "owner": "nix-community", "repo": "home-manager", - "rev": "e3ad5108f54177e6520535768ddbf1e6af54b59d", + "rev": "29c69d9a466e41d46fd3a7a9d0591ef9c113c2ae", "type": "github" }, "original": { @@ -139,11 +139,11 @@ ] }, "locked": { - "lastModified": 1715381426, - "narHash": "sha256-wPuqrAQGdv3ISs74nJfGb+Yprm23U/rFpcHFFNWgM94=", + "lastModified": 1716729592, + "narHash": "sha256-Y3bOjoh2cFBqZN0Jw1zUdyr7tjygyxl2bD/QY73GZP0=", "owner": "nix-community", "repo": "home-manager", - "rev": "ab5542e9dbd13d0100f8baae2bc2d68af901f4b4", + "rev": "2c78a57c544dd19b07442350727ced097e1aa6e6", "type": "github" }, "original": { @@ -161,11 +161,11 @@ ] }, "locked": { - "lastModified": 1715922002, - "narHash": "sha256-FSUrne82MXFzZ7R88ZnJz21kv06GS2TS/Ctsd+RXbP4=", + "lastModified": 1717012808, + "narHash": "sha256-Wn0fbjqmpIiuPUWnvxu85a9sPYtSd/2tcPDhAYW54RM=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "23a55d6bb80f6340d0acdb9feef754646b68f895", + "rev": "a8e6557f29fa0cbcc2c54d15f9664c14ae2a3e98", "type": "github" }, "original": { @@ -234,11 +234,11 @@ ] }, "locked": { - "lastModified": 1715483403, - "narHash": "sha256-WMDuQj7J5jbpXI/X/E6FZRKgBFGcaSTvYyVxPnKE6KU=", + "lastModified": 1716772633, + "narHash": "sha256-Idcye44UW+EgjbjCoklf2IDF+XrehV6CVYvxR1omst4=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f9027322f48b427da23746aa359a6510dfcd0228", + "rev": "ff80cb4a11bb87f3ce8459be6f16a25ac86eb2ac", "type": "github" }, "original": { @@ -254,11 +254,11 @@ ] }, "locked": { - "lastModified": 1715483403, - "narHash": "sha256-WMDuQj7J5jbpXI/X/E6FZRKgBFGcaSTvYyVxPnKE6KU=", + "lastModified": 1716772633, + "narHash": "sha256-Idcye44UW+EgjbjCoklf2IDF+XrehV6CVYvxR1omst4=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f9027322f48b427da23746aa359a6510dfcd0228", + "rev": "ff80cb4a11bb87f3ce8459be6f16a25ac86eb2ac", "type": "github" }, "original": { @@ -269,11 +269,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1715881912, - "narHash": "sha256-e4LJk5uV1wvrRkffGFZekPWvFUx29NnnOahBlLaq8Ek=", + "lastModified": 1716987116, + "narHash": "sha256-uuEkErFVsFdg2K0cKbNQ9JlFSAm/xYqPr4rbPLI91Y8=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "ff1be1e3cdf884df0935ab28745ab13c3c26d828", + "rev": "8251761f93d6f5b91cee45ac09edb6e382641009", "type": "github" }, "original": { @@ -301,11 +301,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1715668745, - "narHash": "sha256-xp62OkRkbUDNUc6VSqH02jB0FbOS+MsfMb7wL1RJOfA=", + "lastModified": 1716633019, + "narHash": "sha256-xim1b5/HZYbWaZKyI7cn9TJCM6ewNVZnesRr00mXeS4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9ddcaffecdf098822d944d4147dd8da30b4e6843", + "rev": "9d29cd266cebf80234c98dd0b87256b6be0af44e", "type": "github" }, "original": { @@ -316,11 +316,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1715787315, - "narHash": "sha256-cYApT0NXJfqBkKcci7D9Kr4CBYZKOQKDYA23q8XNuWg=", + "lastModified": 1716948383, + "narHash": "sha256-SzDKxseEcHR5KzPXLwsemyTR/kaM9whxeiJohbL04rs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "33d1e753c82ffc557b4a585c77de43d4c922ebb5", + "rev": "ad57eef4ef0659193044870c731987a6df5cf56b", "type": "github" }, "original": { @@ -331,11 +331,11 @@ }, "nur": { "locked": { - "lastModified": 1716022947, - "narHash": "sha256-6MpQHyMEF0hSGFGeCJurXnRTFJ5D3BDynwaw4egCIME=", + "lastModified": 1717079713, + "narHash": "sha256-mvTQgi86WwALm6NGi9tvCx92zrNjSr8Mz+nCqbG0ZhE=", "owner": "nix-community", "repo": "NUR", - "rev": "76a11ee5e3b36f2a140a827fd266da5dd64f07b7", + "rev": "1a7bbb238afcada295aabc758941ce82e6b1d292", "type": "github" }, "original": { @@ -444,11 +444,11 @@ ] }, "locked": { - "lastModified": 1715995317, - "narHash": "sha256-Pt6Lkr3qteSi4nF5x9RPrnOLoH1bZYnxLmhYVJHyZpY=", + "lastModified": 1717032429, + "narHash": "sha256-1+87CE8xOUsJChiq9aNQqWPKoWMuyurW+aXrGbMWH7I=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "6c49c56d4365278f755a2a05ee8581706afed626", + "rev": "0309d806a5431a46fb7fd81e20d7133ac8b1de55", "type": "github" }, "original": { From 617a0b235693d5a2c2065699e74e20bbf66d3979 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 31 May 2024 00:43:05 +0200 Subject: [PATCH 0648/1125] Machines/Archie: use amd zenpower nixos-hardware module --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index f9715fa..6b4b15c 100644 --- a/flake.nix +++ b/flake.nix @@ -134,6 +134,7 @@ home-manager-unstable.nixosModule nix-index-db-unstable.nixosModules.nix-index catppuccin.nixosModules.catppuccin + nixos-hardware.nixosModules.common-cpu-amd-zenpower ./roles/common ./roles/desktop ./roles/kde From 46678f11f1ecbc747efd351886214037ce65bc72 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 25 May 2024 17:01:38 +0200 Subject: [PATCH 0649/1125] Common/fish: enable fish --- roles/common/programs/default.nix | 1 + roles/common/programs/fish.nix | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 roles/common/programs/fish.nix diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index 2f0dd22..948cf95 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -14,6 +14,7 @@ ./helix.nix ./direnv.nix ./atuin.nix + ./fish.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ diff --git a/roles/common/programs/fish.nix b/roles/common/programs/fish.nix new file mode 100644 index 0000000..79a6648 --- /dev/null +++ b/roles/common/programs/fish.nix @@ -0,0 +1,11 @@ +{...}: { + programs.fish = { + enable = true; + }; + + home-manager.users.toast = { + programs.fish = { + enable = true; + }; + }; +} From 05c28f5ce56206a6843079a95c0cc72e96cc73c2 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 2 Jun 2024 00:29:22 +0200 Subject: [PATCH 0650/1125] Desktop/discord: remove vencord overlay I don't use the official discord app, and vesktop uses it's own vencord so I don't need it anymore --- roles/desktop/programs/discord.nix | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 62aa940..3df1659 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -4,17 +4,6 @@ withOpenASAR = true; withVencord = true; }; - # Update some stuff while I wait for nixpkgs - vencord = super.vencord.overrideAttrs rec { - version = "1.8.4"; - src = pkgs.fetchFromGitHub { - owner = "Vendicated"; - repo = "Vencord"; - rev = "v${version}"; - hash = "sha256-FbU1Zsz/84oSOCOSWunA5nn5qFGLQ4W3uqsbYytF/7c="; - }; - npmDepsHash = "sha256-97KgELDNhP2aZU66tC+F/QfHuWnICGRzX3FQMbim4Sk="; - }; }; in { nixpkgs.overlays = [discordOverlay]; From c0594967a7870d86dd3ca36fea446227044ac761 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 2 Jun 2024 20:27:03 +0200 Subject: [PATCH 0651/1125] Flake: pin catppuccin-vsc input --- flake.lock | 1 + flake.nix | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index 8f269bf..cd6704d 100644 --- a/flake.lock +++ b/flake.lock @@ -54,6 +54,7 @@ "original": { "owner": "catppuccin", "repo": "vscode", + "rev": "f0a6271f62ebb868f32c7ad4ecb31104c26f987a", "type": "github" } }, diff --git a/flake.nix b/flake.nix index 6b4b15c..798d6c9 100644 --- a/flake.nix +++ b/flake.nix @@ -56,7 +56,8 @@ inputs.home-manager.follows = "home-manager-unstable"; }; - catppuccin-vsc.url = "github:catppuccin/vscode"; + # The maintainer for this retired and the nix build is broken now :( + catppuccin-vsc.url = "github:catppuccin/vscode/f0a6271f62ebb868f32c7ad4ecb31104c26f987a"; vscode-extensions = { url = "github:nix-community/nix-vscode-extensions"; From fd871aed7ad4ac97080287d78c6c1b8c31dbcb0f Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 3 Jun 2024 00:48:56 +0200 Subject: [PATCH 0652/1125] Flake: upgrade nixos-stable and home-manager to 24.05, upgrade flake --- flake.lock | 52 ++++++++++++++++++++++++++-------------------------- flake.nix | 9 +++------ 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/flake.lock b/flake.lock index cd6704d..83f4976 100644 --- a/flake.lock +++ b/flake.lock @@ -120,11 +120,11 @@ ] }, "locked": { - "lastModified": 1717052710, - "narHash": "sha256-LRhOxzXmOza5SymhOgnEzA8EAQp+94kkeUYWKKpLJ/U=", + "lastModified": 1717316182, + "narHash": "sha256-Xi0EpZcu39N0eW7apLjFfUOR9y80toyjYizez7J1wMI=", "owner": "nix-community", "repo": "home-manager", - "rev": "29c69d9a466e41d46fd3a7a9d0591ef9c113c2ae", + "rev": "9b53a10f4c91892f5af87cf55d08fba59ca086af", "type": "github" }, "original": { @@ -140,16 +140,16 @@ ] }, "locked": { - "lastModified": 1716729592, - "narHash": "sha256-Y3bOjoh2cFBqZN0Jw1zUdyr7tjygyxl2bD/QY73GZP0=", + "lastModified": 1716736833, + "narHash": "sha256-rNObca6dm7Qs524O4st8VJH6pZ/Xe1gxl+Rx6mcWYo0=", "owner": "nix-community", "repo": "home-manager", - "rev": "2c78a57c544dd19b07442350727ced097e1aa6e6", + "rev": "a631666f5ec18271e86a5cde998cba68c33d9ac6", "type": "github" }, "original": { "owner": "nix-community", - "ref": "release-23.11", + "ref": "release-24.05", "repo": "home-manager", "type": "github" } @@ -235,11 +235,11 @@ ] }, "locked": { - "lastModified": 1716772633, - "narHash": "sha256-Idcye44UW+EgjbjCoklf2IDF+XrehV6CVYvxR1omst4=", + "lastModified": 1717297675, + "narHash": "sha256-43UmlS1Ifx17y93/Vc258U7bOlAAIZbu8dsGDHOIIr0=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "ff80cb4a11bb87f3ce8459be6f16a25ac86eb2ac", + "rev": "972a52bee3991ae1f1899e6452e0d7c01ee566d9", "type": "github" }, "original": { @@ -255,11 +255,11 @@ ] }, "locked": { - "lastModified": 1716772633, - "narHash": "sha256-Idcye44UW+EgjbjCoklf2IDF+XrehV6CVYvxR1omst4=", + "lastModified": 1717297675, + "narHash": "sha256-43UmlS1Ifx17y93/Vc258U7bOlAAIZbu8dsGDHOIIr0=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "ff80cb4a11bb87f3ce8459be6f16a25ac86eb2ac", + "rev": "972a52bee3991ae1f1899e6452e0d7c01ee566d9", "type": "github" }, "original": { @@ -270,11 +270,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1716987116, - "narHash": "sha256-uuEkErFVsFdg2K0cKbNQ9JlFSAm/xYqPr4rbPLI91Y8=", + "lastModified": 1717248095, + "narHash": "sha256-e8X2eWjAHJQT82AAN+mCI0B68cIDBJpqJ156+VRrFO0=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "8251761f93d6f5b91cee45ac09edb6e382641009", + "rev": "7b49d3967613d9aacac5b340ef158d493906ba79", "type": "github" }, "original": { @@ -302,16 +302,16 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1716633019, - "narHash": "sha256-xim1b5/HZYbWaZKyI7cn9TJCM6ewNVZnesRr00mXeS4=", + "lastModified": 1717144377, + "narHash": "sha256-F/TKWETwB5RaR8owkPPi+SPJh83AQsm6KrQAlJ8v/uA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9d29cd266cebf80234c98dd0b87256b6be0af44e", + "rev": "805a384895c696f802a9bf5bf4720f37385df547", "type": "github" }, "original": { "id": "nixpkgs", - "ref": "nixos-23.11", + "ref": "nixos-24.05", "type": "indirect" } }, @@ -332,11 +332,11 @@ }, "nur": { "locked": { - "lastModified": 1717079713, - "narHash": "sha256-mvTQgi86WwALm6NGi9tvCx92zrNjSr8Mz+nCqbG0ZhE=", + "lastModified": 1717346712, + "narHash": "sha256-QjFwg6M1dBj+2DhTvDOhvvybvSxXK0fJn1FuqbWhi1o=", "owner": "nix-community", "repo": "NUR", - "rev": "1a7bbb238afcada295aabc758941ce82e6b1d292", + "rev": "8587d6c2d6bef3775387336a8456702789cbfb0b", "type": "github" }, "original": { @@ -445,11 +445,11 @@ ] }, "locked": { - "lastModified": 1717032429, - "narHash": "sha256-1+87CE8xOUsJChiq9aNQqWPKoWMuyurW+aXrGbMWH7I=", + "lastModified": 1717291708, + "narHash": "sha256-9oqdLMnfzywk1B2Lx6jQP6mAL6or6clVtOp+vXBsn9E=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "0309d806a5431a46fb7fd81e20d7133ac8b1de55", + "rev": "4b46d344b7a9e2d026e7da71161826cc01b9eaa8", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 798d6c9..b323ae0 100644 --- a/flake.nix +++ b/flake.nix @@ -6,7 +6,7 @@ url = "git+ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets"; flake = false; }; - nixpkgs-raw.url = "nixpkgs/nixos-23.11"; + nixpkgs-raw.url = "nixpkgs/nixos-24.05"; nixpkgs-unstable-raw.url = "nixpkgs/nixos-unstable"; agenix = { @@ -18,7 +18,7 @@ }; home-manager = { - url = "github:nix-community/home-manager/release-23.11"; + url = "github:nix-community/home-manager/release-24.05"; inputs.nixpkgs.follows = "nixpkgs-raw"; }; @@ -85,10 +85,7 @@ nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; src = nixpkgs-raw; - patches = [ - ./nixpkgs-patches/0001-catppuccin-add-grub-theme.patch - ./nixpkgs-patches/0002-catppuccin-add-starship-theme.patch - ]; + patches = []; }; # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs {self = inputs.self;}; From 2f3eafb1ded49fb4fa6a58bf47dcce496b250405 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 3 Jun 2024 00:51:03 +0200 Subject: [PATCH 0653/1125] Common: update state version to 24.05 --- roles/common/configuration.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index b370073..f599cd2 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -104,7 +104,7 @@ sharedModules = [flakeSelf.inputs.catppuccin.homeManagerModules.catppuccin]; users.toast = {osConfig, ...}: { catppuccin.flavour = osConfig.catppuccin.flavour; - home.stateVersion = "23.11"; + home.stateVersion = "24.05"; xdg = { enable = true; userDirs = { @@ -134,7 +134,7 @@ */ system = { - stateVersion = "23.11"; + stateVersion = "24.05"; # Nix on nixos 23.05 does not have dirtyRev configurationRevision = flakeSelf.sourceInfo.rev or flakeSelf.sourceInfo.dirtyRev or "dirty"; nixos.variant_id = lib.strings.toLower config.networking.hostName; From 6ac0973357e3861fc88add159b86fd62523f6584 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 3 Jun 2024 00:52:22 +0200 Subject: [PATCH 0654/1125] Flake: remove unneeded nixpkgs patches --- .../0001-catppuccin-add-grub-theme.patch | 49 ------------------- .../0002-catppuccin-add-starship-theme.patch | 49 ------------------- 2 files changed, 98 deletions(-) delete mode 100644 nixpkgs-patches/0001-catppuccin-add-grub-theme.patch delete mode 100644 nixpkgs-patches/0002-catppuccin-add-starship-theme.patch diff --git a/nixpkgs-patches/0001-catppuccin-add-grub-theme.patch b/nixpkgs-patches/0001-catppuccin-add-grub-theme.patch deleted file mode 100644 index 3455c15..0000000 --- a/nixpkgs-patches/0001-catppuccin-add-grub-theme.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 316d5e8f356d6817626bca5a37dd587418afc856 Mon Sep 17 00:00:00 2001 -From: BlankParticle -Date: Tue, 21 Nov 2023 18:14:15 +0530 -Subject: [PATCH 1/2] catppuccin: add grub theme - ---- - pkgs/data/themes/catppuccin/default.nix | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -diff --git a/pkgs/data/themes/catppuccin/default.nix b/pkgs/data/themes/catppuccin/default.nix -index 59e030eb9e0e..e8cdb0456d17 100644 ---- a/pkgs/data/themes/catppuccin/default.nix -+++ b/pkgs/data/themes/catppuccin/default.nix -@@ -1,5 +1,5 @@ - let -- validThemes = [ "bat" "bottom" "btop" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "refind" "rofi" "waybar" ]; -+ validThemes = [ "bat" "bottom" "btop" "grub" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "refind" "rofi" "waybar" ]; - in - { fetchFromGitHub - , lib -@@ -40,6 +40,14 @@ let - hash = "sha256-J3UezOQMDdxpflGax0rGBF/XMiKqdqZXuX4KMVGTxFk="; - }; - -+ grub = fetchFromGitHub { -+ name = "grub"; -+ owner = "catppuccin"; -+ repo = "grub"; -+ rev = "v1.0.0"; -+ hash = "sha256-/bSolCta8GCZ4lP0u5NVqYQ9Y3ZooYCNdTwORNvR7M0="; -+ }; -+ - hyprland = fetchFromGitHub { - name = "hyprland"; - owner = "catppuccin"; -@@ -140,6 +148,10 @@ stdenvNoCC.mkDerivation { - mkdir -p $out/bottom - cp "${sources.bottom}/themes/${variant}.toml" "$out/bottom/" - -+ '' + lib.optionalString (lib.elem "grub" themeList) '' -+ mkdir -p $out/grub -+ cp -r ${sources.grub}/src/catppuccin-${variant}-grub-theme/* "$out/grub/" -+ - '' + lib.optionalString (lib.elem "hyprland" themeList) '' - mkdir -p $out/hyprland - cp "${sources.hyprland}/themes/${variant}.conf" "$out/hyprland/" --- -2.42.0 - diff --git a/nixpkgs-patches/0002-catppuccin-add-starship-theme.patch b/nixpkgs-patches/0002-catppuccin-add-starship-theme.patch deleted file mode 100644 index 18bcd0a..0000000 --- a/nixpkgs-patches/0002-catppuccin-add-starship-theme.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 93af02433861cd32221164ddb4fc03b19cbf776b Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Sat, 13 Jan 2024 18:41:51 +0100 -Subject: [PATCH 2/2] catppuccin: add starship theme - ---- - pkgs/data/themes/catppuccin/default.nix | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -diff --git a/pkgs/data/themes/catppuccin/default.nix b/pkgs/data/themes/catppuccin/default.nix -index e8cdb0456d17..6ac8cc541ad3 100644 ---- a/pkgs/data/themes/catppuccin/default.nix -+++ b/pkgs/data/themes/catppuccin/default.nix -@@ -1,5 +1,5 @@ - let -- validThemes = [ "bat" "bottom" "btop" "grub" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "refind" "rofi" "waybar" ]; -+ validThemes = [ "bat" "bottom" "btop" "grub" "hyprland" "k9s" "kvantum" "lazygit" "plymouth" "refind" "rofi" "starship" "waybar" ]; - in - { fetchFromGitHub - , lib -@@ -104,6 +104,14 @@ let - hash = "sha256-DNorfyl3C4RBclF2KDgwvQQwixpTwSRu7fIvihPN8JY="; - }; - -+ starship = fetchFromGitHub { -+ name = "starship"; -+ owner = "catppuccin"; -+ repo = "starship"; -+ rev = "5629d2356f62a9f2f8efad3ff37476c19969bd4f"; -+ hash = "sha256-nsRuxQFKbQkyEI4TXgvAjcroVdG+heKX5Pauq/4Ota0="; -+ }; -+ - waybar = fetchFromGitHub { - name = "waybar"; - owner = "catppuccin"; -@@ -183,6 +191,10 @@ stdenvNoCC.mkDerivation { - cp ${sources.refind}/${variant}.conf $out/refind/ - cp -r ${sources.refind}/assets/${variant} $out/refind/assets/ - -+ '' + lib.optionalString (lib.elem "starship" themeList) '' -+ mkdir -p $out/starship -+ cp ${sources.starship}/palettes/${variant}.toml $out/starship/ -+ - '' + lib.optionalString (lib.elem "waybar" themeList) '' - mkdir -p $out/waybar - cp ${sources.waybar}/${variant}.css $out/waybar/ --- -2.42.0 - From 7de1a1bad725bd9c0ecad970f2184b2e8c62c005 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 3 Jun 2024 01:02:39 +0200 Subject: [PATCH 0655/1125] Common/avahi: remove 23.11 compatibity on config --- roles/common/services/avahi.nix | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/roles/common/services/avahi.nix b/roles/common/services/avahi.nix index 5136f64..f7f33e6 100755 --- a/roles/common/services/avahi.nix +++ b/roles/common/services/avahi.nix @@ -1,23 +1,6 @@ -{config, ...}: let - old = { - nssmdns = true; - }; - new = { +{config, ...}: { + services.avahi = { + enable = true; nssmdns4 = true; }; -in { - /* - NixOS 24.05 changed the option for mnds to be able to turn on/off IPv6 - 23.11 doesn't support this, so I need to use the conditional to be able to - use the same config for both - */ - services.avahi = - { - enable = true; - } - // ( - if config.system.nixos.release == "23.11" - then old - else new - ); } From bec73e73adcf4f65b04bc1fef9334a7fa2dc7c96 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Jun 2024 09:35:54 +0200 Subject: [PATCH 0656/1125] Machines/WinMax2: enable ryzen smu --- machines/WinMax2/hardware-configuration.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/machines/WinMax2/hardware-configuration.nix b/machines/WinMax2/hardware-configuration.nix index 4778fbe..ac8d1cd 100755 --- a/machines/WinMax2/hardware-configuration.nix +++ b/machines/WinMax2/hardware-configuration.nix @@ -78,7 +78,10 @@ in { nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware = { - cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + cpu.amd = { + updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + ryzen-smu.enable = true; + }; sensor.iio.bmi260.enable = true; }; } From f4712fdf707f2d68e5210a6ba96a040631804fdd Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 5 Jun 2024 22:53:31 +0200 Subject: [PATCH 0657/1125] Kde/sddm: change cursor name The cursor name changed in Plasma 6 and I forgot to change it --- roles/kde/sddm.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/kde/sddm.nix b/roles/kde/sddm.nix index 4a52489..b435e72 100644 --- a/roles/kde/sddm.nix +++ b/roles/kde/sddm.nix @@ -49,9 +49,10 @@ in { # theme = "sugar-candy"; settings = { General = {Numlock = "off";}; - Theme = {CursorTheme = "Breeze_Snow";}; + Theme = {CursorTheme = "Breeze_Light";}; }; }; + # Sugar candy doesn't seem to work on qt6 :( # environment.systemPackages = [sddm-sugar-candy customcfg]; } From 84fa84350a298398021c1a80daf7e445134cb99d Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 5 Jun 2024 22:55:38 +0200 Subject: [PATCH 0658/1125] Kde/sddm: change background --- roles/kde/sddm.nix | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/roles/kde/sddm.nix b/roles/kde/sddm.nix index b435e72..1c296b9 100644 --- a/roles/kde/sddm.nix +++ b/roles/kde/sddm.nix @@ -1,10 +1,8 @@ { - config, + lib, pkgs, ... }: let - currentTheme = config.services.displayManager.sddm.theme; - sddm-sugar-candy = pkgs.stdenv.mkDerivation { pname = "sddm-sugar-candy"; version = "master"; @@ -30,13 +28,18 @@ customcfg = pkgs.stdenv.mkDerivation { name = "sddm-theme-customizer"; dontUnpack = true; - # TODO: generate theme.conf.user outside of installPhase - installPhase = '' + installPhase = let + config = lib.generators.toINI {} { + # Add the custom config here + General = { + background = "${pkgs.kdePackages.breeze}/share/wallpapers/Next/contents/images_dark/5120x2880.png"; + }; + }; + in '' runHook preInstall - mkdir -p $out/share/sddm/themes/${currentTheme}/ - echo "[General] - background = ${pkgs.plasma-workspace-wallpapers}/share/wallpapers/MilkyWay/contents/images/5120x2880.png" >> $out/share/sddm/themes/${currentTheme}/theme.conf.user + mkdir -p $out/share/sddm/themes/breeze/ + echo "${config}" >> $out/share/sddm/themes/breeze/theme.conf.user runHook postInstall ''; @@ -55,4 +58,5 @@ in { # Sugar candy doesn't seem to work on qt6 :( # environment.systemPackages = [sddm-sugar-candy customcfg]; + environment.systemPackages = [customcfg]; } From 45f86f522ac8ff1828c70e91969b47a0df51643a Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 5 Jun 2024 23:49:35 +0200 Subject: [PATCH 0659/1125] Server/forgejo: disable offline mode --- roles/server/forgejo.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index e89fee9..af99060 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -29,6 +29,7 @@ in { DISABLE_REGISTRATION = lib.mkDefault true; }; server = { + OFFLINE_MODE = false; ROOT_URL = "http://git.everest.sable-pancake.ts.net"; START_SSH_SERVER = true; SSH_PORT = 4222; From 5f99d8a0f4b843a7209087737ec22593fbdbb40d Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 6 Jun 2024 12:04:18 +0200 Subject: [PATCH 0660/1125] Revert "Flake: pin catppucin input" This reverts commit 8d8b118b36c47bdd10e7507f87caff43f81e16fd. Revert "Flake: actually downgrade catppuccin input" This reverts commit aeed860735f1b705fd4fef9af9ef50c67f3260bc. --- flake.lock | 7 +++---- flake.nix | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index 83f4976..e6d8efe 100644 --- a/flake.lock +++ b/flake.lock @@ -25,17 +25,16 @@ }, "catppuccin": { "locked": { - "lastModified": 1713895615, - "narHash": "sha256-SVkxhcL0/IN5fNI2dqr702wXOnzktsm0LCEVGRAJQcY=", + "lastModified": 1714607657, + "narHash": "sha256-AnmN+JOzrpHv7Uw7JSPJ9JEjuqF7gjhx29UuuldNpas=", "owner": "catppuccin", "repo": "nix", - "rev": "a48e70a31616cb63e4794fd3465bff1835cc4246", + "rev": "b0dc7f3181063daa6532dc5f757ded1a605dfbd5", "type": "github" }, "original": { "owner": "catppuccin", "repo": "nix", - "rev": "a48e70a31616cb63e4794fd3465bff1835cc4246", "type": "github" } }, diff --git a/flake.nix b/flake.nix index b323ae0..60128b1 100644 --- a/flake.nix +++ b/flake.nix @@ -67,7 +67,7 @@ nur.url = "github:nix-community/NUR"; - catppuccin.url = "github:catppuccin/nix/a48e70a31616cb63e4794fd3465bff1835cc4246"; + catppuccin.url = "github:catppuccin/nix"; }; outputs = {...} @ inputs: From 7e3da29f972121cf053f447dd8e0e7d34b4fcefb Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 6 Jun 2024 12:16:20 +0200 Subject: [PATCH 0661/1125] Flake: update catppuccin I had to change flavour into flavor in the configs --- flake.lock | 6 +++--- roles/common/configuration.nix | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index e6d8efe..d9abef9 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1714607657, - "narHash": "sha256-AnmN+JOzrpHv7Uw7JSPJ9JEjuqF7gjhx29UuuldNpas=", + "lastModified": 1717565621, + "narHash": "sha256-uU6GeSbzopVcPga+Fy5n3tKfzUhuw4FVMv7h61/13XY=", "owner": "catppuccin", "repo": "nix", - "rev": "b0dc7f3181063daa6532dc5f757ded1a605dfbd5", + "rev": "0cdfa29b902976fc2941468d326325d24e148437", "type": "github" }, "original": { diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index f599cd2..8fb05cf 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -95,7 +95,7 @@ ) ]; - catppuccin.flavour = "mocha"; + catppuccin.flavor = "mocha"; home-manager = { backupFileExtension = "hm-backup"; @@ -103,7 +103,7 @@ verbose = true; sharedModules = [flakeSelf.inputs.catppuccin.homeManagerModules.catppuccin]; users.toast = {osConfig, ...}: { - catppuccin.flavour = osConfig.catppuccin.flavour; + catppuccin.flavor = osConfig.catppuccin.flavor; home.stateVersion = "24.05"; xdg = { enable = true; From 4f61147f8d436da82989a43e25908dd4dbf9c04c Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 6 Jun 2024 12:33:16 +0200 Subject: [PATCH 0662/1125] Common: set catppuccin accent --- roles/common/configuration.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 8fb05cf..7092f16 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -95,7 +95,10 @@ ) ]; - catppuccin.flavor = "mocha"; + catppuccin = { + flavor = "mocha"; + accent = "mauve"; + }; home-manager = { backupFileExtension = "hm-backup"; @@ -104,6 +107,7 @@ sharedModules = [flakeSelf.inputs.catppuccin.homeManagerModules.catppuccin]; users.toast = {osConfig, ...}: { catppuccin.flavor = osConfig.catppuccin.flavor; + catppuccin.accent = osConfig.catppuccin.accent; home.stateVersion = "24.05"; xdg = { enable = true; From b7a9debd3b7435d42d97893d44ecedb05c7aef91 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 6 Jun 2024 12:37:03 +0200 Subject: [PATCH 0663/1125] Common/fish: enable catppuccin --- roles/common/programs/fish.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/programs/fish.nix b/roles/common/programs/fish.nix index 79a6648..25c43cd 100644 --- a/roles/common/programs/fish.nix +++ b/roles/common/programs/fish.nix @@ -6,6 +6,7 @@ home-manager.users.toast = { programs.fish = { enable = true; + catppuccin.enable = true; }; }; } From 421be2b14bd164f0a506eabe6d07a0497ba5d211 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 15 Jun 2024 18:31:48 +0200 Subject: [PATCH 0664/1125] Flake: update lock file --- flake.lock | 78 +++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/flake.lock b/flake.lock index d9abef9..7e964dd 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1716561646, - "narHash": "sha256-UIGtLO89RxKt7RF2iEgPikSdU53r6v/6WYB0RW3k89I=", + "lastModified": 1718371084, + "narHash": "sha256-abpBi61mg0g+lFFU0zY4C6oP6fBwPzbHPKBGw676xsA=", "owner": "ryantm", "repo": "agenix", - "rev": "c2fc0762bbe8feb06a2e59a364fa81b3a57671c9", + "rev": "3a56735779db467538fb2e577eda28a9daacaca6", "type": "github" }, "original": { @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1717565621, - "narHash": "sha256-uU6GeSbzopVcPga+Fy5n3tKfzUhuw4FVMv7h61/13XY=", + "lastModified": 1718339789, + "narHash": "sha256-Q3fgY7huFE+uaw7BNsAl1x+FvjDAi3EDWPnlALJt5pM=", "owner": "catppuccin", "repo": "nix", - "rev": "0cdfa29b902976fc2941468d326325d24e148437", + "rev": "73e06d5bd7ed34bdd0168030893ef8364fdc1d4a", "type": "github" }, "original": { @@ -119,11 +119,11 @@ ] }, "locked": { - "lastModified": 1717316182, - "narHash": "sha256-Xi0EpZcu39N0eW7apLjFfUOR9y80toyjYizez7J1wMI=", + "lastModified": 1718243258, + "narHash": "sha256-abBpj2VU8p6qlRzTU8o22q68MmOaZ4v8zZ4UlYl5YRU=", "owner": "nix-community", "repo": "home-manager", - "rev": "9b53a10f4c91892f5af87cf55d08fba59ca086af", + "rev": "8d5e27b4807d25308dfe369d5a923d87e7dbfda3", "type": "github" }, "original": { @@ -139,11 +139,11 @@ ] }, "locked": { - "lastModified": 1716736833, - "narHash": "sha256-rNObca6dm7Qs524O4st8VJH6pZ/Xe1gxl+Rx6mcWYo0=", + "lastModified": 1717527182, + "narHash": "sha256-vWSkg6AMok1UUQiSYVdGMOXKD2cDFnajITiSi0Zjd1A=", "owner": "nix-community", "repo": "home-manager", - "rev": "a631666f5ec18271e86a5cde998cba68c33d9ac6", + "rev": "845a5c4c073f74105022533907703441e0464bc3", "type": "github" }, "original": { @@ -161,11 +161,11 @@ ] }, "locked": { - "lastModified": 1717012808, - "narHash": "sha256-Wn0fbjqmpIiuPUWnvxu85a9sPYtSd/2tcPDhAYW54RM=", + "lastModified": 1718431241, + "narHash": "sha256-vOsklVeiGCvf9LBOz0sjHMNvohgUw8/Oe/8MpdFnF+Y=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "a8e6557f29fa0cbcc2c54d15f9664c14ae2a3e98", + "rev": "f02a01aab60c68b7898043c2e7f5bc97c93fb07b", "type": "github" }, "original": { @@ -214,11 +214,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1708968331, - "narHash": "sha256-VUXLaPusCBvwM3zhGbRIJVeYluh2uWuqtj4WirQ1L9Y=", + "lastModified": 1717932370, + "narHash": "sha256-7C5lCpiWiyPoIACOcu2mukn/1JRtz6HC/1aEMhUdcw0=", "owner": "nix-community", "repo": "impermanence", - "rev": "a33ef102a02ce77d3e39c25197664b7a636f9c30", + "rev": "27979f1c3a0d3b9617a3563e2839114ba7d48d3f", "type": "github" }, "original": { @@ -234,11 +234,11 @@ ] }, "locked": { - "lastModified": 1717297675, - "narHash": "sha256-43UmlS1Ifx17y93/Vc258U7bOlAAIZbu8dsGDHOIIr0=", + "lastModified": 1718458449, + "narHash": "sha256-FcX3/lTbb+WIW783b18SPudPYhdmmNLQADf4S3SsZos=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "972a52bee3991ae1f1899e6452e0d7c01ee566d9", + "rev": "963639a87fb7f746d45f14b8ab429d2c52dbb396", "type": "github" }, "original": { @@ -254,11 +254,11 @@ ] }, "locked": { - "lastModified": 1717297675, - "narHash": "sha256-43UmlS1Ifx17y93/Vc258U7bOlAAIZbu8dsGDHOIIr0=", + "lastModified": 1718458449, + "narHash": "sha256-FcX3/lTbb+WIW783b18SPudPYhdmmNLQADf4S3SsZos=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "972a52bee3991ae1f1899e6452e0d7c01ee566d9", + "rev": "963639a87fb7f746d45f14b8ab429d2c52dbb396", "type": "github" }, "original": { @@ -269,11 +269,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1717248095, - "narHash": "sha256-e8X2eWjAHJQT82AAN+mCI0B68cIDBJpqJ156+VRrFO0=", + "lastModified": 1718459188, + "narHash": "sha256-umwY+ivE98n/6EwEtobOlqf1t9VddhPIIZ6rVmFXlHg=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "7b49d3967613d9aacac5b340ef158d493906ba79", + "rev": "0cd562157274df3783840bdcb0ce6d9c4cf4aa29", "type": "github" }, "original": { @@ -301,11 +301,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1717144377, - "narHash": "sha256-F/TKWETwB5RaR8owkPPi+SPJh83AQsm6KrQAlJ8v/uA=", + "lastModified": 1718208800, + "narHash": "sha256-US1tAChvPxT52RV8GksWZS415tTS7PV42KTc2PNDBmc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "805a384895c696f802a9bf5bf4720f37385df547", + "rev": "cc54fb41d13736e92229c21627ea4f22199fee6b", "type": "github" }, "original": { @@ -316,11 +316,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1716948383, - "narHash": "sha256-SzDKxseEcHR5KzPXLwsemyTR/kaM9whxeiJohbL04rs=", + "lastModified": 1718318537, + "narHash": "sha256-4Zu0RYRcAY/VWuu6awwq4opuiD//ahpc2aFHg2CWqFY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ad57eef4ef0659193044870c731987a6df5cf56b", + "rev": "e9ee548d90ff586a6471b4ae80ae9cfcbceb3420", "type": "github" }, "original": { @@ -331,11 +331,11 @@ }, "nur": { "locked": { - "lastModified": 1717346712, - "narHash": "sha256-QjFwg6M1dBj+2DhTvDOhvvybvSxXK0fJn1FuqbWhi1o=", + "lastModified": 1718462028, + "narHash": "sha256-7a1I+bIgjQYfSuursGmSJeZc0+gUZLd3D9zEkrnWObs=", "owner": "nix-community", "repo": "NUR", - "rev": "8587d6c2d6bef3775387336a8456702789cbfb0b", + "rev": "d64b542f7f8f621ffcce3209184232024654bbac", "type": "github" }, "original": { @@ -444,11 +444,11 @@ ] }, "locked": { - "lastModified": 1717291708, - "narHash": "sha256-9oqdLMnfzywk1B2Lx6jQP6mAL6or6clVtOp+vXBsn9E=", + "lastModified": 1718414742, + "narHash": "sha256-JxLg5LNDoP2pWlkaItaNfGijH+FC6S3q4cLcisIP/a0=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "4b46d344b7a9e2d026e7da71161826cc01b9eaa8", + "rev": "070ac4ec68b9faff64ee94e975ccf61b6909afab", "type": "github" }, "original": { From 67f3cf3fadab37e91fa0206f54b4979cebfa185b Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 18 Jun 2024 15:54:33 +0200 Subject: [PATCH 0665/1125] Server/dns: change how host records are added --- roles/server/dns.nix | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/roles/server/dns.nix b/roles/server/dns.nix index 22c91de..e1c92c7 100644 --- a/roles/server/dns.nix +++ b/roles/server/dns.nix @@ -15,25 +15,23 @@ */ dns-loop-detect = true; + host-record = [ + "winmax2,winmax2.sable-pancake.ts.net,100.106.73.20" + "everest,everest.sable-pancake.ts.net,100.73.96.48" + "archie,archie.sable-pancake.ts.net,100.113.139.93" + "steamdeck,steamdeck.sable-pancake.ts.net,100.85.48.85" + "surfacego,surfacego.sable-pancake.ts.net,100.96.92.13" + ]; + # If this isn't set a cname that targets a host might return the wrong ip localise-queries = true; ## IPv6 is not a thing in Spain so I'm guaranteed to not use it filter-AAAA = true; - expand-hosts = true; domain = "sable-pancake.ts.net"; domain-needed = true; }; }; - # Add tailscale hosts - networking.hosts = { - "100.73.96.48" = ["everest"]; - "100.113.139.93" = ["archie"]; - "100.85.48.85" = ["steamdeck"]; - "100.96.92.13" = ["surfecego"]; - "100.106.73.20" = ["winmax2"]; - }; - # Dnsmasq conflicts with the resolved dns stub listener services.resolved.extraConfig = '' [Resolve] From e4ec92a8f0e26e0f8ccf565750deafe055c791ea Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 23 Jun 2024 13:22:51 +0200 Subject: [PATCH 0666/1125] Flake: update lock file and remove unneeded patch --- flake.lock | 72 +++++++++---------- flake.nix | 1 - ...Revert-handheld-daemon-undo-refactor.patch | 40 ----------- 3 files changed, 36 insertions(+), 77 deletions(-) delete mode 100644 nixpkgs-patches/0001-Revert-handheld-daemon-undo-refactor.patch diff --git a/flake.lock b/flake.lock index 7e964dd..a914b91 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1718339789, - "narHash": "sha256-Q3fgY7huFE+uaw7BNsAl1x+FvjDAi3EDWPnlALJt5pM=", + "lastModified": 1719059483, + "narHash": "sha256-JUGjp4P7Yi3ToxLW5iMSz7CI7mffprF8GsK1hkFdKzs=", "owner": "catppuccin", "repo": "nix", - "rev": "73e06d5bd7ed34bdd0168030893ef8364fdc1d4a", + "rev": "b6c854508d8c03f3ff06bf658d12b0ae8052d7a5", "type": "github" }, "original": { @@ -119,11 +119,11 @@ ] }, "locked": { - "lastModified": 1718243258, - "narHash": "sha256-abBpj2VU8p6qlRzTU8o22q68MmOaZ4v8zZ4UlYl5YRU=", + "lastModified": 1719037157, + "narHash": "sha256-aOKd8+mhBsLQChCu1mn/W5ww79ta5cXVE59aJFrifM8=", "owner": "nix-community", "repo": "home-manager", - "rev": "8d5e27b4807d25308dfe369d5a923d87e7dbfda3", + "rev": "cd886711998fe5d9ff7979fdd4b4cbd17b1f1511", "type": "github" }, "original": { @@ -139,11 +139,11 @@ ] }, "locked": { - "lastModified": 1717527182, - "narHash": "sha256-vWSkg6AMok1UUQiSYVdGMOXKD2cDFnajITiSi0Zjd1A=", + "lastModified": 1718530513, + "narHash": "sha256-BmO8d0r+BVlwWtMLQEYnwmngqdXIuyFzMwvmTcLMee8=", "owner": "nix-community", "repo": "home-manager", - "rev": "845a5c4c073f74105022533907703441e0464bc3", + "rev": "a1fddf0967c33754271761d91a3d921772b30d0e", "type": "github" }, "original": { @@ -161,11 +161,11 @@ ] }, "locked": { - "lastModified": 1718431241, - "narHash": "sha256-vOsklVeiGCvf9LBOz0sjHMNvohgUw8/Oe/8MpdFnF+Y=", + "lastModified": 1719032789, + "narHash": "sha256-MIPobSKR53T0Yrb8wu2fbjSVokhJeJy5AF6B1Hzckso=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "f02a01aab60c68b7898043c2e7f5bc97c93fb07b", + "rev": "495a672a2024bdc0e86af95f4e338827f9bfb865", "type": "github" }, "original": { @@ -214,11 +214,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1717932370, - "narHash": "sha256-7C5lCpiWiyPoIACOcu2mukn/1JRtz6HC/1aEMhUdcw0=", + "lastModified": 1719067779, + "narHash": "sha256-c8UPWKErzLtukeZ2xdyeZZTkEtg7cP8ApvMgYvjT1ss=", "owner": "nix-community", "repo": "impermanence", - "rev": "27979f1c3a0d3b9617a3563e2839114ba7d48d3f", + "rev": "363b3e8622e964a96db90ab6430ddcc338212e79", "type": "github" }, "original": { @@ -234,11 +234,11 @@ ] }, "locked": { - "lastModified": 1718458449, - "narHash": "sha256-FcX3/lTbb+WIW783b18SPudPYhdmmNLQADf4S3SsZos=", + "lastModified": 1718507237, + "narHash": "sha256-xBEWCxWeRpWQggFFp8ugJCDa63cOJsVvx71R9F0Eowg=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "963639a87fb7f746d45f14b8ab429d2c52dbb396", + "rev": "6af2c5e58c20311276f59d247341cafeebfcb6f4", "type": "github" }, "original": { @@ -254,11 +254,11 @@ ] }, "locked": { - "lastModified": 1718458449, - "narHash": "sha256-FcX3/lTbb+WIW783b18SPudPYhdmmNLQADf4S3SsZos=", + "lastModified": 1718507237, + "narHash": "sha256-xBEWCxWeRpWQggFFp8ugJCDa63cOJsVvx71R9F0Eowg=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "963639a87fb7f746d45f14b8ab429d2c52dbb396", + "rev": "6af2c5e58c20311276f59d247341cafeebfcb6f4", "type": "github" }, "original": { @@ -269,11 +269,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1718459188, - "narHash": "sha256-umwY+ivE98n/6EwEtobOlqf1t9VddhPIIZ6rVmFXlHg=", + "lastModified": 1719069430, + "narHash": "sha256-d9KzCJv3UG6nX9Aur5OSEf4Uj+ywuxojhiCiRKYVzXA=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "0cd562157274df3783840bdcb0ce6d9c4cf4aa29", + "rev": "e8232c132a95ddc62df9d404120ad4ff53862910", "type": "github" }, "original": { @@ -301,11 +301,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1718208800, - "narHash": "sha256-US1tAChvPxT52RV8GksWZS415tTS7PV42KTc2PNDBmc=", + "lastModified": 1718835956, + "narHash": "sha256-wM9v2yIxClRYsGHut5vHICZTK7xdrUGfrLkXvSuv6s4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "cc54fb41d13736e92229c21627ea4f22199fee6b", + "rev": "dd457de7e08c6d06789b1f5b88fc9327f4d96309", "type": "github" }, "original": { @@ -316,11 +316,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1718318537, - "narHash": "sha256-4Zu0RYRcAY/VWuu6awwq4opuiD//ahpc2aFHg2CWqFY=", + "lastModified": 1718895438, + "narHash": "sha256-k3JqJrkdoYwE3fHE6xGDY676AYmyh4U2Zw+0Bwe5DLU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e9ee548d90ff586a6471b4ae80ae9cfcbceb3420", + "rev": "d603719ec6e294f034936c0d0dc06f689d91b6c3", "type": "github" }, "original": { @@ -331,11 +331,11 @@ }, "nur": { "locked": { - "lastModified": 1718462028, - "narHash": "sha256-7a1I+bIgjQYfSuursGmSJeZc0+gUZLd3D9zEkrnWObs=", + "lastModified": 1719081887, + "narHash": "sha256-xAmq1hOGDF5t5+bKgU/zaSsuv5Nbo+KdzK2BFvLL56w=", "owner": "nix-community", "repo": "NUR", - "rev": "d64b542f7f8f621ffcce3209184232024654bbac", + "rev": "768bf25fd49b2b2d95dd477fccfacf7f8638212a", "type": "github" }, "original": { @@ -444,11 +444,11 @@ ] }, "locked": { - "lastModified": 1718414742, - "narHash": "sha256-JxLg5LNDoP2pWlkaItaNfGijH+FC6S3q4cLcisIP/a0=", + "lastModified": 1719019506, + "narHash": "sha256-2lpbK6W3QHxc7BFeEDPumcBoNBx7dO7UE+ypwFVEOOc=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "070ac4ec68b9faff64ee94e975ccf61b6909afab", + "rev": "935d522e2a0306083d15e09c7d17a9358c141f29", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 60128b1..76d9ce8 100644 --- a/flake.nix +++ b/flake.nix @@ -79,7 +79,6 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/0001-Revert-handheld-daemon-undo-refactor.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/0001-Revert-handheld-daemon-undo-refactor.patch b/nixpkgs-patches/0001-Revert-handheld-daemon-undo-refactor.patch deleted file mode 100644 index a16b9e7..0000000 --- a/nixpkgs-patches/0001-Revert-handheld-daemon-undo-refactor.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 904067bc281924e86e936c7d0162131e8af86d64 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 6 May 2024 12:26:54 +0200 -Subject: [PATCH 1/1] Revert "handheld-daemon: undo refactor" - -This reverts commit d9b487ae609a368378c1a9d89a5441c5c44121df. ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 246e3879bb5c..ad0554bec36d 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -34,15 +34,17 @@ python3.pkgs.buildPythonApplication rec { - doCheck = false; - - postPatch = '' -+ # The generated udev rules point to /bin/chmod, which does not exist in NixOS -+ substituteInPlace src/hhd/controller/lib/hide.py \ -+ --replace-fail /bin/chmod ${toybox}/bin/chmod -+ - # handheld-daemon contains a fork of the python module `hid`, so this hook - # is borrowed from the `hid` derivation. -+ substituteInPlace src/hhd/controller/lib/hid.py \ -+ --replace-fail libhidapi ${hidapi}/lib/libhidapi -+ - hidapi=${hidapi}/lib/ - test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } -- sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py -- -- # The generated udev rules point to /bin/chmod, which does not exist in NixOS -- chmod=${toybox}/bin/chmod -- sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py - ''; - - postInstall = '' --- -2.44.0 - From 5e310a8255ba6cb8c75c36a7567144b5f1da2d27 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 23 Jun 2024 13:41:57 +0200 Subject: [PATCH 0667/1125] Machines/WinMax2: remove scaling env variable --- machines/WinMax2/configuration.nix | 3 --- 1 file changed, 3 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 9b8f4ae..6dadf77 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -66,9 +66,6 @@ services = { xserver.xkb.layout = lib.mkForce "us"; - displayManager.sddm.settings = { - General.GreeterEnvironment = "QT_SCREEN_SCALE_FACTORS=2"; - }; }; jovian = { From 1318dbba6509e311412d3bfb8dd8f471d66a275f Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 26 Jun 2024 10:48:47 +0200 Subject: [PATCH 0668/1125] Machines/WinMax2: disable kwin direct scanout --- machines/WinMax2/configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 6dadf77..593fcb3 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -41,6 +41,9 @@ boot.kernelParams = ["clearcpuid=304"]; }; + # Direct scanout has some issues with my egpu so I just disable it + environment.sessionVariables."KWIN_DRM_NO_DIRECT_SCANOUT" = 1; + # Sleep fixes boot.kernelParams = ["rtc_cmos.use_acpi_alarm=1"]; services.udev.extraRules = '' From 8b43439238190d494f8d87a49af1df03163d1a0e Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 2 Jul 2024 14:34:28 +0200 Subject: [PATCH 0669/1125] Machines/WinMax2: remove unneeded workaround --- machines/WinMax2/configuration.nix | 5 ----- 1 file changed, 5 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 593fcb3..73b8a5a 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -36,11 +36,6 @@ networking.hostName = "WinMax2"; # Define your hostname. - specialisation.noAVX512.configuration = { - # For some reason The Finals crashes on CPUs that support AVX512 - boot.kernelParams = ["clearcpuid=304"]; - }; - # Direct scanout has some issues with my egpu so I just disable it environment.sessionVariables."KWIN_DRM_NO_DIRECT_SCANOUT" = 1; From b9b9f28e26b36570990f653364ec60e258d8e15b Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 2 Jul 2024 14:34:52 +0200 Subject: [PATCH 0670/1125] Common: enable iotop --- roles/common/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 7092f16..f891145 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -100,6 +100,8 @@ accent = "mauve"; }; + programs.iotop.enable = true; + home-manager = { backupFileExtension = "hm-backup"; useGlobalPkgs = true; From faab731506f6b74b8c311651a2996fc47a1be3a0 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 5 Jul 2024 13:22:52 +0200 Subject: [PATCH 0671/1125] Programs: delete micro --- roles/common/programs/default.nix | 1 - roles/common/programs/micro.nix | 14 -------------- roles/desktop/programs/default.nix | 1 - roles/desktop/programs/micro.nix | 18 ------------------ 4 files changed, 34 deletions(-) delete mode 100644 roles/common/programs/micro.nix delete mode 100644 roles/desktop/programs/micro.nix diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index 948cf95..d4428e5 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -2,7 +2,6 @@ imports = [ ./htop.nix ./nix.nix - ./micro.nix ./nix-index.nix ./command-not-found.nix ./comma.nix diff --git a/roles/common/programs/micro.nix b/roles/common/programs/micro.nix deleted file mode 100644 index 75df151..0000000 --- a/roles/common/programs/micro.nix +++ /dev/null @@ -1,14 +0,0 @@ -{...}: { - home-manager = { - users.toast = {...}: { - programs.micro = { - enable = true; - settings = { - clipboard = "internal"; - indentchar = "|"; - softwrap = true; - }; - }; - }; - }; -} diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix index 30c6c6f..7d6c257 100755 --- a/roles/desktop/programs/default.nix +++ b/roles/desktop/programs/default.nix @@ -2,7 +2,6 @@ imports = [ ./discord.nix ./firefox.nix - ./micro.nix ./keepassxc.nix ./jamesdsp.nix ./vscode.nix diff --git a/roles/desktop/programs/micro.nix b/roles/desktop/programs/micro.nix deleted file mode 100644 index d934774..0000000 --- a/roles/desktop/programs/micro.nix +++ /dev/null @@ -1,18 +0,0 @@ -{lib, ...}: { - home-manager = { - users.toast = {pkgs, ...}: { - programs.micro = { - enable = true; - settings = { - # Use xclip/wl-clipboard for copying and pasting - clipboard = lib.mkForce "external"; - }; - }; - /* - On a kde wayland session micro uses xsel or xclip instead of wl-clipboard - which doesn't work, so I only install wl-clipboard here to make micro use it - */ - home.packages = with pkgs; [wl-clipboard]; - }; - }; -} From c8863554a2fcc85751ef211a116915b2c69e98d7 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 5 Jul 2024 13:33:37 +0200 Subject: [PATCH 0672/1125] Flake: update lock file --- flake.lock | 78 +++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/flake.lock b/flake.lock index a914b91..75ecf6c 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1719059483, - "narHash": "sha256-JUGjp4P7Yi3ToxLW5iMSz7CI7mffprF8GsK1hkFdKzs=", + "lastModified": 1719915848, + "narHash": "sha256-zq+CMkdT8A9z74HonwspXp8HsX4OvP4uaVdD98AO6as=", "owner": "catppuccin", "repo": "nix", - "rev": "b6c854508d8c03f3ff06bf658d12b0ae8052d7a5", + "rev": "9345073d27d91ab66c1b6ab65df322906992aa59", "type": "github" }, "original": { @@ -119,11 +119,11 @@ ] }, "locked": { - "lastModified": 1719037157, - "narHash": "sha256-aOKd8+mhBsLQChCu1mn/W5ww79ta5cXVE59aJFrifM8=", + "lastModified": 1720167120, + "narHash": "sha256-K9JYdlPiyaXp33JRg7CT8rMwH56e4ncXSsXW/YKnNXc=", "owner": "nix-community", "repo": "home-manager", - "rev": "cd886711998fe5d9ff7979fdd4b4cbd17b1f1511", + "rev": "bbe6e94737289c8cb92d4d8f9199fbfe4f11c0ba", "type": "github" }, "original": { @@ -139,11 +139,11 @@ ] }, "locked": { - "lastModified": 1718530513, - "narHash": "sha256-BmO8d0r+BVlwWtMLQEYnwmngqdXIuyFzMwvmTcLMee8=", + "lastModified": 1720042825, + "narHash": "sha256-A0vrUB6x82/jvf17qPCpxaM+ulJnD8YZwH9Ci0BsAzE=", "owner": "nix-community", "repo": "home-manager", - "rev": "a1fddf0967c33754271761d91a3d921772b30d0e", + "rev": "e1391fb22e18a36f57e6999c7a9f966dc80ac073", "type": "github" }, "original": { @@ -161,11 +161,11 @@ ] }, "locked": { - "lastModified": 1719032789, - "narHash": "sha256-MIPobSKR53T0Yrb8wu2fbjSVokhJeJy5AF6B1Hzckso=", + "lastModified": 1720025282, + "narHash": "sha256-I70ARXPm1YjGJ0efykd5zsapUZtmVZ/sIgwJ0F0j17w=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "495a672a2024bdc0e86af95f4e338827f9bfb865", + "rev": "8dd0f8383bd60b8ed66cd27c1b49cdbf7be4ad9d", "type": "github" }, "original": { @@ -214,11 +214,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1719067779, - "narHash": "sha256-c8UPWKErzLtukeZ2xdyeZZTkEtg7cP8ApvMgYvjT1ss=", + "lastModified": 1719091691, + "narHash": "sha256-AxaLX5cBEcGtE02PeGsfscSb/fWMnyS7zMWBXQWDKbE=", "owner": "nix-community", "repo": "impermanence", - "rev": "363b3e8622e964a96db90ab6430ddcc338212e79", + "rev": "23c1f06316b67cb5dabdfe2973da3785cfe9c34a", "type": "github" }, "original": { @@ -234,11 +234,11 @@ ] }, "locked": { - "lastModified": 1718507237, - "narHash": "sha256-xBEWCxWeRpWQggFFp8ugJCDa63cOJsVvx71R9F0Eowg=", + "lastModified": 1719832725, + "narHash": "sha256-dr8DkeS74KVNTgi8BE0BiUKALb+EKlMIV86G2xPYO64=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "6af2c5e58c20311276f59d247341cafeebfcb6f4", + "rev": "2917972ed34ce292309b3a4976286f8b5c08db27", "type": "github" }, "original": { @@ -254,11 +254,11 @@ ] }, "locked": { - "lastModified": 1718507237, - "narHash": "sha256-xBEWCxWeRpWQggFFp8ugJCDa63cOJsVvx71R9F0Eowg=", + "lastModified": 1719832725, + "narHash": "sha256-dr8DkeS74KVNTgi8BE0BiUKALb+EKlMIV86G2xPYO64=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "6af2c5e58c20311276f59d247341cafeebfcb6f4", + "rev": "2917972ed34ce292309b3a4976286f8b5c08db27", "type": "github" }, "original": { @@ -269,11 +269,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1719069430, - "narHash": "sha256-d9KzCJv3UG6nX9Aur5OSEf4Uj+ywuxojhiCiRKYVzXA=", + "lastModified": 1719895800, + "narHash": "sha256-xNbjISJTFailxass4LmdWeV4jNhAlmJPwj46a/GxE6M=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "e8232c132a95ddc62df9d404120ad4ff53862910", + "rev": "6e253f12b1009053eff5344be5e835f604bb64cd", "type": "github" }, "original": { @@ -301,11 +301,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1718835956, - "narHash": "sha256-wM9v2yIxClRYsGHut5vHICZTK7xdrUGfrLkXvSuv6s4=", + "lastModified": 1719956923, + "narHash": "sha256-nNJHJ9kfPdzYsCOlHOnbiiyKjZUW5sWbwx3cakg3/C4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "dd457de7e08c6d06789b1f5b88fc9327f4d96309", + "rev": "706eef542dec88cc0ed25b9075d3037564b2d164", "type": "github" }, "original": { @@ -316,11 +316,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1718895438, - "narHash": "sha256-k3JqJrkdoYwE3fHE6xGDY676AYmyh4U2Zw+0Bwe5DLU=", + "lastModified": 1720031269, + "narHash": "sha256-rwz8NJZV+387rnWpTYcXaRNvzUSnnF9aHONoJIYmiUQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d603719ec6e294f034936c0d0dc06f689d91b6c3", + "rev": "9f4128e00b0ae8ec65918efeba59db998750ead6", "type": "github" }, "original": { @@ -331,11 +331,11 @@ }, "nur": { "locked": { - "lastModified": 1719081887, - "narHash": "sha256-xAmq1hOGDF5t5+bKgU/zaSsuv5Nbo+KdzK2BFvLL56w=", + "lastModified": 1720176372, + "narHash": "sha256-T1EOgGxdT0cRFahK2RoY3tQ1c9WklguVEvC+zGvd5zo=", "owner": "nix-community", "repo": "NUR", - "rev": "768bf25fd49b2b2d95dd477fccfacf7f8638212a", + "rev": "a7f3a4b394375acdd26a1a8c7aecacc71c824fbc", "type": "github" }, "original": { @@ -354,11 +354,11 @@ ] }, "locked": { - "lastModified": 1714390161, - "narHash": "sha256-hWPGLUGNr7IR2FT4xS0VlhTW3S6xpw0hU3LJJC3CaKo=", + "lastModified": 1719876998, + "narHash": "sha256-NPKL3Ri2dbOOtvsgezTiUYutEgZUjcIXpwKCgt4Eu4E=", "owner": "toast003", "repo": "plasma-manager", - "rev": "d9754f6f5dcf96969ad40496326213d5344846e5", + "rev": "d12cb0ed42a81ff84330b5cc94bff6abfeeb6da8", "type": "github" }, "original": { @@ -444,11 +444,11 @@ ] }, "locked": { - "lastModified": 1719019506, - "narHash": "sha256-2lpbK6W3QHxc7BFeEDPumcBoNBx7dO7UE+ypwFVEOOc=", + "lastModified": 1720142793, + "narHash": "sha256-KhKF1VEMT5vz0vv1HZy0IOTEp2ZU1UD4ZgJAkOFbhIg=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "935d522e2a0306083d15e09c7d17a9358c141f29", + "rev": "8d57c84024068180130f3c0a2103dda967a0ddc2", "type": "github" }, "original": { From a700fc64b748c075558c59f63c237209d6b38460 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 7 Jul 2024 17:56:27 +0200 Subject: [PATCH 0673/1125] Switch to lix --- flake.lock | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++- flake.nix | 20 +++++++ 2 files changed, 180 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index 75ecf6c..ff3b031 100644 --- a/flake.lock +++ b/flake.lock @@ -91,6 +91,72 @@ "type": "github" } }, + "flake-utils_2": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flakey-profile": { + "locked": { + "lastModified": 1712898590, + "narHash": "sha256-FhGIEU93VHAChKEXx905TSiPZKga69bWl1VB37FK//I=", + "owner": "lf-", + "repo": "flakey-profile", + "rev": "243c903fd8eadc0f63d205665a92d4df91d42d9d", + "type": "github" + }, + "original": { + "owner": "lf-", + "repo": "flakey-profile", + "type": "github" + } + }, + "flakey-profile_2": { + "locked": { + "lastModified": 1712898590, + "narHash": "sha256-FhGIEU93VHAChKEXx905TSiPZKga69bWl1VB37FK//I=", + "owner": "lf-", + "repo": "flakey-profile", + "rev": "243c903fd8eadc0f63d205665a92d4df91d42d9d", + "type": "github" + }, + "original": { + "owner": "lf-", + "repo": "flakey-profile", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -174,6 +240,66 @@ "type": "github" } }, + "lix": { + "flake": false, + "locked": { + "lastModified": 1720132382, + "narHash": "sha256-9+TCNMnynp+OzMhsUiVTZXJKGH3QkXWdmC3SNUOY2z4=", + "rev": "d00edfb28d0a52d9acd392c582a43f98e773cf4c", + "type": "tarball", + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/d00edfb28d0a52d9acd392c582a43f98e773cf4c.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://git.lix.systems/lix-project/lix/archive/main.tar.gz" + } + }, + "lix-module": { + "inputs": { + "flake-utils": "flake-utils", + "flakey-profile": "flakey-profile", + "lix": [ + "lix" + ], + "nixpkgs": [ + "nixpkgs-raw" + ] + }, + "locked": { + "lastModified": 1719353937, + "narHash": "sha256-86NBqDxAP20ET/UoKX0WvSItblNQ97czXb2q7lkMrwk=", + "rev": "5d9d94089fb1ca96222a34bfe245ef5c5ebefd37", + "type": "tarball", + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/5d9d94089fb1ca96222a34bfe245ef5c5ebefd37.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://git.lix.systems/lix-project/nixos-module/archive/main.tar.gz" + } + }, + "lix-module-unstable": { + "inputs": { + "flake-utils": "flake-utils_2", + "flakey-profile": "flakey-profile_2", + "lix": [ + "lix" + ], + "nixpkgs": [ + "nixpkgs-unstable-raw" + ] + }, + "locked": { + "lastModified": 1719353937, + "narHash": "sha256-86NBqDxAP20ET/UoKX0WvSItblNQ97czXb2q7lkMrwk=", + "rev": "5d9d94089fb1ca96222a34bfe245ef5c5ebefd37", + "type": "tarball", + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/5d9d94089fb1ca96222a34bfe245ef5c5ebefd37.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://git.lix.systems/lix-project/nixos-module/archive/main.tar.gz" + } + }, "nix-flatpak": { "locked": { "lastModified": 1711997375, @@ -376,6 +502,9 @@ "home-manager": "home-manager_2", "home-manager-unstable": "home-manager-unstable", "jovian": "jovian", + "lix": "lix", + "lix-module": "lix-module", + "lix-module-unstable": "lix-module-unstable", "nix-flatpak": "nix-flatpak", "nix-impermanence": "nix-impermanence", "nix-index-db": "nix-index-db", @@ -435,10 +564,40 @@ "type": "github" } }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "vscode-extensions": { "inputs": { "flake-compat": "flake-compat", - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_3", "nixpkgs": [ "nixpkgs-unstable-raw" ] diff --git a/flake.nix b/flake.nix index 76d9ce8..4193e23 100644 --- a/flake.nix +++ b/flake.nix @@ -68,6 +68,21 @@ nur.url = "github:nix-community/NUR"; catppuccin.url = "github:catppuccin/nix"; + + lix = { + url = "https://git.lix.systems/lix-project/lix/archive/main.tar.gz"; + flake = false; + }; + lix-module = { + url = "https://git.lix.systems/lix-project/nixos-module/archive/main.tar.gz"; + inputs.nixpkgs.follows = "nixpkgs-raw"; + inputs.lix.follows = "lix"; + }; + lix-module-unstable = { + url = "https://git.lix.systems/lix-project/nixos-module/archive/main.tar.gz"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; + inputs.lix.follows = "lix"; + }; }; outputs = {...} @ inputs: @@ -132,6 +147,7 @@ nix-index-db-unstable.nixosModules.nix-index catppuccin.nixosModules.catppuccin nixos-hardware.nixosModules.common-cpu-amd-zenpower + lix-module-unstable.nixosModules.default ./roles/common ./roles/desktop ./roles/kde @@ -153,6 +169,7 @@ nixos-hardware.nixosModules.microsoft-surface-go nix-index-db-unstable.nixosModules.nix-index catppuccin.nixosModules.catppuccin + lix-module-unstable.nixosModules.default ./roles/common ./roles/desktop ./roles/kde @@ -172,6 +189,7 @@ home-manager-unstable.nixosModule nix-index-db-unstable.nixosModules.nix-index catppuccin.nixosModules.catppuccin + lix-module-unstable.nixosModules.default ./roles/common ./roles/desktop ./roles/kde @@ -194,6 +212,7 @@ nix-index-db-unstable.nixosModules.nix-index nixos-hardware.nixosModules.gpd-win-max-2-2023 catppuccin.nixosModules.catppuccin + lix-module-unstable.nixosModules.default ./roles/common ./roles/desktop ./roles/kde @@ -214,6 +233,7 @@ home-manager.nixosModule nix-index-db.nixosModules.nix-index catppuccin.nixosModules.catppuccin + lix-module.nixosModules.default ./roles/common ./roles/server ./machines/Everest From cae5c4f0365ec84981a8220b3c1cef9350ac2853 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 11 Jul 2024 12:29:18 +0200 Subject: [PATCH 0674/1125] Flake: add nixpkgs patches --- flake.nix | 2 + nixpkgs-patches/handheld-daemon-ui-init.patch | 127 ++++++++++++++++++ nixpkgs-patches/update-hhd.patch | 30 +++++ 3 files changed, 159 insertions(+) create mode 100644 nixpkgs-patches/handheld-daemon-ui-init.patch create mode 100644 nixpkgs-patches/update-hhd.patch diff --git a/flake.nix b/flake.nix index 4193e23..bc4328e 100644 --- a/flake.nix +++ b/flake.nix @@ -94,6 +94,8 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ + ./nixpkgs-patches/handheld-daemon-ui-init.patch + ./nixpkgs-patches/update-hhd.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/handheld-daemon-ui-init.patch b/nixpkgs-patches/handheld-daemon-ui-init.patch new file mode 100644 index 0000000..16cd662 --- /dev/null +++ b/nixpkgs-patches/handheld-daemon-ui-init.patch @@ -0,0 +1,127 @@ +From 18cd88064d152491d5ba19602db5c5d65bc2d685 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Thu, 18 Apr 2024 11:22:24 +0200 +Subject: [PATCH 1/3] handheld-daemon-ui: init at 3.1.1 + +--- + .../by-name/ha/handheld-daemon-ui/package.nix | 39 +++++++++++++++++++ + 1 file changed, 39 insertions(+) + create mode 100644 pkgs/by-name/ha/handheld-daemon-ui/package.nix + +diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix +new file mode 100644 +index 00000000000000..81d318d88b5abd +--- /dev/null ++++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix +@@ -0,0 +1,39 @@ ++{ ++ lib, ++ appimageTools, ++ fetchurl, ++}: ++let ++ pname = "handheld-daemon-ui"; ++ version = "3.1.1"; ++ ++ src = fetchurl { ++ url = "https://github.com/hhd-dev/hhd-ui/releases/download/v${version}/hhd-ui.Appimage"; ++ hash = "sha256-KH01MvcCbvCqjp1UZHnwfh9G3Yh50CO9Ecjl1Y8VY9E="; ++ }; ++ extractedFiles = appimageTools.extractType2 { inherit pname version src; }; ++in ++appimageTools.wrapType2 { ++ inherit pname version src; ++ ++ extraInstallCommands = '' ++ # Handheld-daemon expects the UI binary to be called hhd-ui ++ mv $out/bin/${pname} $out/bin/hhd-ui ++ ++ mkdir -p $out/share/applications ++ substitute ${extractedFiles}/hhd-ui.desktop \ ++ $out/share/applications/hhd-ui.desktop \ ++ --replace-fail "Exec=AppRun" "Exec=hhd-ui" ++ cp ${extractedFiles}/usr/share/icons $out/share -r ++ ''; ++ ++ meta = with lib; { ++ description = "The main UI for the Handheld Daemon"; ++ homepage = "https://github.com/hhd-dev/hhd-ui"; ++ license = licenses.gpl3Only; ++ maintainers = with maintainers; [ toast ]; ++ mainProgram = "hhd-ui"; ++ platforms = [ "x86_64-linux" ]; ++ sourceProvenance = with sourceTypes; [ binaryNativeCode ]; ++ }; ++} + +From 8ebb1f0976c79c74eb0cea3975c348e36d86a7d1 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Wed, 10 Jul 2024 12:59:01 +0200 +Subject: [PATCH 2/3] handheld-daemon: add options for handheld-daemon-ui + +--- + .../modules/services/hardware/handheld-daemon.nix | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix +index 6c9d5aa3e22c86..e8e283bca89413 100644 +--- a/nixos/modules/services/hardware/handheld-daemon.nix ++++ b/nixos/modules/services/hardware/handheld-daemon.nix +@@ -11,6 +11,11 @@ in + enable = mkEnableOption "Enable Handheld Daemon"; + package = mkPackageOption pkgs "handheld-daemon" { }; + ++ ui = { ++ enable = mkEnableOption "Handheld Daemon UI"; ++ package = mkPackageOption pkgs "handheld-daemon-ui" { }; ++ }; ++ + user = mkOption { + type = types.str; + description = '' +@@ -20,7 +25,10 @@ in + }; + + config = mkIf cfg.enable { +- environment.systemPackages = [ cfg.package ]; ++ environment.systemPackages = [ ++ cfg.package ++ (mkIf cfg.ui.enable cfg.ui.package) ++ ]; + services.udev.packages = [ cfg.package ]; + systemd.packages = [ cfg.package ]; + +@@ -31,6 +39,11 @@ in + + restartIfChanged = true; + ++ path = mkIf cfg.ui.enable [ ++ pkgs.handheld-daemon-ui ++ pkgs.lsof ++ ]; ++ + serviceConfig = { + ExecStart = "${ lib.getExe cfg.package } --user ${ cfg.user }"; + Nice = "-12"; + +From 1b034ab22605b29195dabce893282b05077d0fe7 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Thu, 11 Jul 2024 12:11:00 +0200 +Subject: [PATCH 3/3] handheld-daemon: enable ui when enabling handheld-daemon + +--- + nixos/modules/services/hardware/handheld-daemon.nix | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix +index e8e283bca89413..d78bae5e9bc483 100644 +--- a/nixos/modules/services/hardware/handheld-daemon.nix ++++ b/nixos/modules/services/hardware/handheld-daemon.nix +@@ -25,6 +25,7 @@ in + }; + + config = mkIf cfg.enable { ++ services.handheld-daemon.ui.enable = mkDefault true; + environment.systemPackages = [ + cfg.package + (mkIf cfg.ui.enable cfg.ui.package) diff --git a/nixpkgs-patches/update-hhd.patch b/nixpkgs-patches/update-hhd.patch new file mode 100644 index 0000000..7c86f37 --- /dev/null +++ b/nixpkgs-patches/update-hhd.patch @@ -0,0 +1,30 @@ +From 77380945dd829e737533359e0eba9fc965c1bdb6 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Mon, 1 Jul 2024 16:41:48 +0200 +Subject: [PATCH] handheld-daemon: 2.7.2 -> 3.1.1 + +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index ec24637dde3f70..d670fdc8b11e72 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -9,14 +9,14 @@ + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "2.7.2"; ++ version = "3.1.1"; + pyproject = true; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + rev = "v${version}"; +- hash = "sha256-jWLL1nmKam1iJ1R1l/OuIp+isgZ7toRhVamx1nOID/8="; ++ hash = "sha256-XUnAgQWnBb8Xsu88UVpdVXbFPxG13TNJFX1xgY06HT8="; + }; + + propagatedBuildInputs = with python3.pkgs; [ From 675b8c7b85f4c55f0342ede5740d0fc6d9d5f09d Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 11 Jul 2024 12:29:33 +0200 Subject: [PATCH 0675/1125] Machines/WinMax2: enable hhd and hhd-ui --- machines/WinMax2/configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 73b8a5a..a10e624 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -51,6 +51,9 @@ hardware.bolt.enable = true; handheld-daemon = { enable = true; + ui = { + enable = true; + }; user = "toast"; }; }; From 85ccce45b9d76de3070125d443a99fe0d13767ba Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Jul 2024 01:52:26 +0200 Subject: [PATCH 0676/1125] Server: move transmission nfs share settings to transmission.nix --- roles/server/nfs.nix | 18 ------------------ roles/server/transmission.nix | 29 ++++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/roles/server/nfs.nix b/roles/server/nfs.nix index 5122cc7..e6aff84 100755 --- a/roles/server/nfs.nix +++ b/roles/server/nfs.nix @@ -2,29 +2,11 @@ services = { nfs.server = { enable = true; - exports = '' - ${config.services.transmission.settings.download-dir} *.sable-pancake.ts.net(ro,all_squash,anonuid=${toString config.users.users.transmission.uid},anongid=${toString config.users.groups.transmission.gid}) - ''; # NFSv3 uses random ports, so you need to make them static to be able to pass though the firewall statdPort = 4000; lockdPort = 4001; mountdPort = 4002; }; - - avahi.extraServiceFiles = { - Transmission-downloads-nfs = '' - - - - Transmission Downloads on %h (NFS) - - _nfs._tcp - 2049 - path=${config.services.transmission.settings.download-dir} - - - ''; - }; }; networking.firewall = { diff --git a/roles/server/transmission.nix b/roles/server/transmission.nix index 3e64aec..9b90f1b 100755 --- a/roles/server/transmission.nix +++ b/roles/server/transmission.nix @@ -1,4 +1,8 @@ -{config, ...}: { +{config, ...}: let + transmissionUid = toString config.users.users.transmission.uid; + transmissionGid = toString config.users.groups.transmission.gid; + mountPoint = config.fileSystems."nfs_transmission".mountPoint; +in { services.transmission = { enable = true; openFirewall = true; @@ -10,6 +14,29 @@ }; }; + # Allow my devices to access the downloads folder though NFS + fileSystems."nfs_transmission" = { + device = config.services.transmission.settings.download-dir; + mountPoint = "/srv/nfs/transmission"; + options = ["bind"]; + }; + services.nfs.server.exports = "${mountPoint} *.sable-pancake.ts.net(ro,all_squash,anonuid=${transmissionUid},anongid=${transmissionGid})"; + + services.avahi.extraServiceFiles = { + Transmission-downloads-nfs = '' + + + + Transmission Downloads on %h (NFS) + + _nfs._tcp + 2049 + path=${mountPoint} + + + ''; + }; + # Add a cname for transmission services.dnsmasq.settings.cname = ["transmission.everest.sable-pancake.ts.net,everest"]; From a826c532e558fbb7c19834fb56a39933e62e4b95 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Jul 2024 02:02:52 +0200 Subject: [PATCH 0677/1125] Server/nfs: add nfs root --- roles/server/nfs.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/nfs.nix b/roles/server/nfs.nix index e6aff84..22dbe91 100755 --- a/roles/server/nfs.nix +++ b/roles/server/nfs.nix @@ -2,6 +2,7 @@ services = { nfs.server = { enable = true; + exports = "/srv/nfs *.sable-pancake.ts.net(ro,fsid=root)"; # NFSv3 uses random ports, so you need to make them static to be able to pass though the firewall statdPort = 4000; lockdPort = 4001; From 99a17a7c79564bbebe13172771e6de8f39b4eca7 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Jul 2024 11:48:32 +0200 Subject: [PATCH 0678/1125] Server: add rust_motd --- roles/server/default.nix | 1 + roles/server/rust_motd.nix | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 roles/server/rust_motd.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index 11c334a..7468b3c 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -13,5 +13,6 @@ ./tailscale.nix ./traefik.nix ./dns.nix + ./rust_motd.nix ]; } diff --git a/roles/server/rust_motd.nix b/roles/server/rust_motd.nix new file mode 100644 index 0000000..d92dafd --- /dev/null +++ b/roles/server/rust_motd.nix @@ -0,0 +1,13 @@ +{...}: { + programs.rust-motd = { + enable = true; + enableMotdInSSHD = true; + settings = { + filesystems = { + Root = "/"; + Boot = "/boot/efi"; + }; + last_run.last_run = true; + }; + }; +} From 020cec94a17730f3e13d86c1d95d3ecf40c6697f Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 15 Jul 2024 16:32:08 +0200 Subject: [PATCH 0679/1125] Remove leftover school things --- flake.nix | 3 --- roles/school/default.nix | 5 ----- roles/school/services/default.nix | 5 ----- roles/school/services/syncthing.nix | 10 ---------- roles/server/syncthing.nix | 6 ------ 5 files changed, 29 deletions(-) delete mode 100644 roles/school/default.nix delete mode 100644 roles/school/services/default.nix delete mode 100644 roles/school/services/syncthing.nix diff --git a/flake.nix b/flake.nix index bc4328e..c7d95cc 100644 --- a/flake.nix +++ b/flake.nix @@ -154,7 +154,6 @@ ./roles/desktop ./roles/kde ./roles/gaming - ./roles/school ./machines/Archie ]; }; @@ -196,7 +195,6 @@ ./roles/desktop ./roles/kde ./roles/gaming - ./roles/school ./machines/SteamDeck ]; }; @@ -219,7 +217,6 @@ ./roles/desktop ./roles/kde ./roles/gaming - ./roles/school ./machines/WinMax2 ]; }; diff --git a/roles/school/default.nix b/roles/school/default.nix deleted file mode 100644 index dc31263..0000000 --- a/roles/school/default.nix +++ /dev/null @@ -1,5 +0,0 @@ -{...}: { - imports = [ - ./services - ]; -} diff --git a/roles/school/services/default.nix b/roles/school/services/default.nix deleted file mode 100644 index 24b067d..0000000 --- a/roles/school/services/default.nix +++ /dev/null @@ -1,5 +0,0 @@ -{...}: { - imports = [ - ./syncthing.nix - ]; -} diff --git a/roles/school/services/syncthing.nix b/roles/school/services/syncthing.nix deleted file mode 100644 index 84cd213..0000000 --- a/roles/school/services/syncthing.nix +++ /dev/null @@ -1,10 +0,0 @@ -{...}: { - services.syncthing.settings.folders = { - "school-things" = { - label = "School things"; - id = "z6alc-nfoqr"; - devices = ["steamdeck" "server" "pc" "winmax2"]; - path = "~/Documents/School things"; - }; - }; -} diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index b989171..137c32b 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -8,12 +8,6 @@ "passwords" = { path = "${config.services.syncthing.dataDir}/passwords"; }; - "school-things" = { - label = "School things"; - id = "z6alc-nfoqr"; - devices = ["steamdeck" "server" "pc" "winmax2"]; - path = "${config.services.syncthing.dataDir}/school-things"; - }; "steam-201810" = { label = "Wolfenstein The New Order Saves"; id = "laxxf-t2wmy"; From 5001e70c14ecbdfe64211eaf90a829ce73d1791c Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Jul 2024 19:06:24 +0200 Subject: [PATCH 0680/1125] Change my tailscale network name --- .justfile | 4 ++-- flake.lock | 4 ++-- flake.nix | 2 +- roles/common/programs/git.nix | 2 +- roles/desktop/programs/ssh.nix | 4 ++-- roles/server/dns.nix | 12 ++++++------ roles/server/forgejo.nix | 6 +++--- roles/server/nfs.nix | 2 +- roles/server/syncthing.nix | 4 ++-- roles/server/transmission.nix | 8 ++++---- 10 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.justfile b/.justfile index c03f8d8..09e5f48 100644 --- a/.justfile +++ b/.justfile @@ -19,8 +19,8 @@ update-input input: nix flake lock --update-input {{input}} @edit-secrets: - git clone ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets.git /tmp/secrets - sed -i 's\git+ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets\/tmp/secrets\g' flake.nix + git clone ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets.git /tmp/secrets + sed -i 's\git+ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets\/tmp/secrets\g' flake.nix just -q update-input secrets echo "{{bold}}All done!" echo "{{normal}}Remember to restore flake.nix" diff --git a/flake.lock b/flake.lock index ff3b031..bcc1ee7 100644 --- a/flake.lock +++ b/flake.lock @@ -527,11 +527,11 @@ "rev": "08944755d22a7499b0b3fd39d48fdf1dabf4c83f", "revCount": 19, "type": "git", - "url": "ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets" + "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets" }, "original": { "type": "git", - "url": "ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets" + "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets" } }, "systems": { diff --git a/flake.nix b/flake.nix index c7d95cc..c2385d3 100644 --- a/flake.nix +++ b/flake.nix @@ -3,7 +3,7 @@ inputs = { secrets = { - url = "git+ssh://forgejo@git.everest.sable-pancake.ts.net:4222/Toast/nix-secrets"; + url = "git+ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets"; flake = false; }; nixpkgs-raw.url = "nixpkgs/nixos-24.05"; diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index 02dc612..037bc6d 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -1,6 +1,6 @@ {...}: { programs.ssh.knownHosts = { - "[git.everest.sable-pancake.ts.net]:4222".publicKey = '' + "[git.everest.tailscale]:4222".publicKey = '' ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKoUcWx56NZ3kqydN3d0gLNz6SlBm1ArkHhqR9Fwd8qs ''; }; diff --git a/roles/desktop/programs/ssh.nix b/roles/desktop/programs/ssh.nix index 4e1bd2f..8449fe4 100644 --- a/roles/desktop/programs/ssh.nix +++ b/roles/desktop/programs/ssh.nix @@ -2,7 +2,7 @@ programs.ssh.knownHosts = { everest = { hostNames = [ - "everest.sable-pancake.ts.net" + "everest.tailscale" "toast003.xyz" ]; publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAqfABZKnF5YYGZTOKuT7m+sOnUqBQSvLke9c3JDsF5s"; @@ -15,7 +15,7 @@ matchBlocks = { "everest" = { host = "everest"; - hostname = "everest.sable-pancake.ts.net"; + hostname = "everest.tailscale"; forwardAgent = true; sendEnv = ["COLORTERM"]; }; diff --git a/roles/server/dns.nix b/roles/server/dns.nix index e1c92c7..88402e1 100644 --- a/roles/server/dns.nix +++ b/roles/server/dns.nix @@ -16,18 +16,18 @@ dns-loop-detect = true; host-record = [ - "winmax2,winmax2.sable-pancake.ts.net,100.106.73.20" - "everest,everest.sable-pancake.ts.net,100.73.96.48" - "archie,archie.sable-pancake.ts.net,100.113.139.93" - "steamdeck,steamdeck.sable-pancake.ts.net,100.85.48.85" - "surfacego,surfacego.sable-pancake.ts.net,100.96.92.13" + "winmax2,winmax2.tailscale,100.106.73.20" + "everest,everest.tailscale,100.73.96.48" + "archie,archie.tailscale,100.113.139.93" + "steamdeck,steamdeck.tailscale,100.85.48.85" + "surfacego,surfacego.tailscale,100.96.92.13" ]; # If this isn't set a cname that targets a host might return the wrong ip localise-queries = true; ## IPv6 is not a thing in Spain so I'm guaranteed to not use it filter-AAAA = true; - domain = "sable-pancake.ts.net"; + domain = "tailscale"; domain-needed = true; }; }; diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index af99060..cc16a44 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -30,7 +30,7 @@ in { }; server = { OFFLINE_MODE = false; - ROOT_URL = "http://git.everest.sable-pancake.ts.net"; + ROOT_URL = "http://git.everest.tailscale"; START_SSH_SERVER = true; SSH_PORT = 4222; SSH_SERVER_HOST_KEYS = config.age.secrets.forgejo-host-key.path; @@ -45,7 +45,7 @@ in { }; # Add a cname for forgejo - services.dnsmasq.settings.cname = ["git.everest.sable-pancake.ts.net,everest"]; + services.dnsmasq.settings.cname = ["git.everest.tailscale,everest"]; # Set up traefik as the reverse proxy for Forgejo services.traefik = { @@ -53,7 +53,7 @@ in { http = { routers = { forgejo-subpath = { - rule = "Host(`git.everest.sable-pancake.ts.net`)"; + rule = "Host(`git.everest.tailscale`)"; service = "forgejo"; }; }; diff --git a/roles/server/nfs.nix b/roles/server/nfs.nix index 22dbe91..37e472d 100755 --- a/roles/server/nfs.nix +++ b/roles/server/nfs.nix @@ -2,7 +2,7 @@ services = { nfs.server = { enable = true; - exports = "/srv/nfs *.sable-pancake.ts.net(ro,fsid=root)"; + exports = "/srv/nfs *.tailscale(ro,fsid=root)"; # NFSv3 uses random ports, so you need to make them static to be able to pass though the firewall statdPort = 4000; lockdPort = 4001; diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 137c32b..c581918 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -34,7 +34,7 @@ }; # Add a cname for syncthing - services.dnsmasq.settings.cname = ["sync.everest.sable-pancake.ts.net,everest"]; + services.dnsmasq.settings.cname = ["sync.everest.tailscale,everest"]; # Set up traefik as the reverse proxy for syncthing services.traefik = { @@ -42,7 +42,7 @@ http = { routers = { syncthing-subdomain = { - rule = "Host(`sync.everest.sable-pancake.ts.net`)"; + rule = "Host(`sync.everest.tailscale`)"; service = "syncthing"; }; }; diff --git a/roles/server/transmission.nix b/roles/server/transmission.nix index 9b90f1b..ec28ab8 100755 --- a/roles/server/transmission.nix +++ b/roles/server/transmission.nix @@ -9,7 +9,7 @@ in { settings = { incomplete-dir-enabled = false; rpc-bind-address = "0.0.0.0"; - rpc-host-whitelist = "transmission.everest.sable-pancake.ts.net"; + rpc-host-whitelist = "transmission.everest.tailscale"; rpc-whitelist = "127.0.0.1"; }; }; @@ -20,7 +20,7 @@ in { mountPoint = "/srv/nfs/transmission"; options = ["bind"]; }; - services.nfs.server.exports = "${mountPoint} *.sable-pancake.ts.net(ro,all_squash,anonuid=${transmissionUid},anongid=${transmissionGid})"; + services.nfs.server.exports = "${mountPoint} *.tailscale(ro,all_squash,anonuid=${transmissionUid},anongid=${transmissionGid})"; services.avahi.extraServiceFiles = { Transmission-downloads-nfs = '' @@ -38,7 +38,7 @@ in { }; # Add a cname for transmission - services.dnsmasq.settings.cname = ["transmission.everest.sable-pancake.ts.net,everest"]; + services.dnsmasq.settings.cname = ["transmission.everest.tailscale,everest"]; # Set up traefik as the reverse proxy for transmission services.traefik = { @@ -46,7 +46,7 @@ in { http = { routers = { transmission-subdomain = { - rule = "Host(`transmission.everest.sable-pancake.ts.net`)"; + rule = "Host(`transmission.everest.tailscale`)"; service = "transmission"; }; }; From 863840b2b19bcf47e8ba1ba061f2b0cbc1f4f5ed Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 18 Jul 2024 00:45:00 +0200 Subject: [PATCH 0681/1125] Server: replace traefik with caddy --- roles/server/caddy.nix | 11 +++++++++++ roles/server/default.nix | 2 +- roles/server/forgejo.nix | 22 +++++++--------------- roles/server/syncthing.nix | 22 +++++++--------------- roles/server/traefik.nix | 31 ------------------------------- roles/server/transmission.nix | 22 +++++++--------------- 6 files changed, 33 insertions(+), 77 deletions(-) create mode 100644 roles/server/caddy.nix delete mode 100644 roles/server/traefik.nix diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix new file mode 100644 index 0000000..d963527 --- /dev/null +++ b/roles/server/caddy.nix @@ -0,0 +1,11 @@ +{...}: { + services.caddy = { + enable = true; + extraConfig = '' + (tailscale) { + tls internal + bind 100.73.96.48 + } + ''; + }; +} diff --git a/roles/server/default.nix b/roles/server/default.nix index 7468b3c..5e32379 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -11,7 +11,7 @@ ./ddclient.nix ./beep.nix ./tailscale.nix - ./traefik.nix + ./caddy.nix ./dns.nix ./rust_motd.nix ]; diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index cc16a44..65fbf83 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -47,20 +47,12 @@ in { # Add a cname for forgejo services.dnsmasq.settings.cname = ["git.everest.tailscale,everest"]; - # Set up traefik as the reverse proxy for Forgejo - services.traefik = { - dynamicConfigOptions = { - http = { - routers = { - forgejo-subpath = { - rule = "Host(`git.everest.tailscale`)"; - service = "forgejo"; - }; - }; - services.forgejo.loadBalancer.servers = [ - {url = "http://localhost:${toString config.services.forgejo.settings.server.HTTP_PORT}";} - ]; - }; - }; + # Set up caddy as the reverse proxy for Forgejo + services.caddy.virtualHosts.forgejo = { + hostName = "git.everest.tailscale"; + extraConfig = '' + import tailscale + reverse_proxy localhost:${toString config.services.forgejo.settings.server.HTTP_PORT} + ''; }; } diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index c581918..f684129 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -36,20 +36,12 @@ # Add a cname for syncthing services.dnsmasq.settings.cname = ["sync.everest.tailscale,everest"]; - # Set up traefik as the reverse proxy for syncthing - services.traefik = { - dynamicConfigOptions = { - http = { - routers = { - syncthing-subdomain = { - rule = "Host(`sync.everest.tailscale`)"; - service = "syncthing"; - }; - }; - services.syncthing.loadBalancer.servers = [ - {url = "http://localhost:8384";} - ]; - }; - }; + # Set up caddy as the reverse proxy for syncthing + services.caddy.virtualHosts.syncthing = { + hostName = "sync.everest.tailscale"; + extraConfig = '' + import tailscale + reverse_proxy localhost:8384 + ''; }; } diff --git a/roles/server/traefik.nix b/roles/server/traefik.nix deleted file mode 100644 index 171f64d..0000000 --- a/roles/server/traefik.nix +++ /dev/null @@ -1,31 +0,0 @@ -{...}: { - specialisation.traefikEnableWebUI.configuration.services.traefik = { - staticConfigOptions = { - api = { - # Enable the web ui - insecure = true; - dashboard = true; - }; - }; - }; - - services.traefik = { - enable = true; - staticConfigOptions = { - entryPoints = { - http = {address = "100.73.96.48:80";}; - }; - }; - }; - - systemd = { - units.tailscaled.requiredBy = ["traefik.service"]; - # We have somewhat frequent power outages, and our ISP router takes - # ages to boot up. If I don't add a delay, traefik tries to bind to - # the tailscale interface before it's ready, making it crash too much - # in too little time - services.traefik.serviceConfig.RestartSec = 120; - }; - - networking.firewall.allowedTCPPorts = [80 8080]; -} diff --git a/roles/server/transmission.nix b/roles/server/transmission.nix index ec28ab8..e52f286 100755 --- a/roles/server/transmission.nix +++ b/roles/server/transmission.nix @@ -40,20 +40,12 @@ in { # Add a cname for transmission services.dnsmasq.settings.cname = ["transmission.everest.tailscale,everest"]; - # Set up traefik as the reverse proxy for transmission - services.traefik = { - dynamicConfigOptions = { - http = { - routers = { - transmission-subdomain = { - rule = "Host(`transmission.everest.tailscale`)"; - service = "transmission"; - }; - }; - services.transmission.loadBalancer.servers = [ - {url = "http://localhost:${toString config.services.transmission.settings.rpc-port}";} - ]; - }; - }; + # Set up caddy as the reverse proxy for transmission + services.caddy.virtualHosts.transmission = { + hostName = "transmission.everest.tailscale"; + extraConfig = '' + import tailscale + reverse_proxy localhost:${toString config.services.transmission.settings.rpc-port} + ''; }; } From e1f4b528c6aee4564cfc0973e7f184cd2f66b258 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 18 Jul 2024 00:55:00 +0200 Subject: [PATCH 0682/1125] Server/caddy: serve the NixOS manual --- roles/server/caddy.nix | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index d963527..f643527 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -1,4 +1,6 @@ -{...}: { +{config, ...}: let + manualHostname = "manual.everest.tailscale"; +in { services.caddy = { enable = true; extraConfig = '' @@ -7,5 +9,14 @@ bind 100.73.96.48 } ''; + virtualHosts.nixos-manual = { + hostName = manualHostname; + extraConfig = '' + import tailscale + file_server + root * ${config.system.build.manual.manualHTML}/share/doc/nixos + ''; + }; }; + services.dnsmasq.settings.cname = ["${manualHostname},everest"]; } From 114fcad32ee38702e64be9301b94117c23830e1b Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 18 Jul 2024 02:01:41 +0200 Subject: [PATCH 0683/1125] Server/caddy: change name of the root ca cert --- roles/server/caddy.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index f643527..bddf3b3 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -3,6 +3,13 @@ in { services.caddy = { enable = true; + globalConfig = '' + pki { + ca local { + name "Caddy (Everest) local CA" + } + } + ''; extraConfig = '' (tailscale) { tls internal From 1b96024e4a3c568979a3a8c095e68e441d4439fc Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 18 Jul 2024 02:04:41 +0200 Subject: [PATCH 0684/1125] Common: add Caddy root ca --- roles/common/configuration.nix | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index f891145..4cbf013 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -45,6 +45,23 @@ boot.supportedFilesystems = ["nfs"]; + security.pki.certificates = [ + # Caddy + '' + -----BEGIN CERTIFICATE----- + MIIBqTCCAU+gAwIBAgIQceh0ZUBNrOmqLVsDr+2HBjAKBggqhkjOPQQDAjAzMTEw + LwYDVQQDEyhDYWRkeSAoRXZlcmVzdCkgbG9jYWwgQ0EgLSAyMDI0IEVDQyBSb290 + MB4XDTI0MDcxODAwMDEwM1oXDTM0MDUyNzAwMDEwM1owMzExMC8GA1UEAxMoQ2Fk + ZHkgKEV2ZXJlc3QpIGxvY2FsIENBIC0gMjAyNCBFQ0MgUm9vdDBZMBMGByqGSM49 + AgEGCCqGSM49AwEHA0IABJjrY8x6iDXncxG8exwLyaEq8N0XnCIbga8PVYiz3VLS + 07++i0Dey9k68ag6KUZICfc8dX1uZ6/ozUZb4YO3xCSjRTBDMA4GA1UdDwEB/wQE + AwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBTQAqZS9KeiAr9mSPV9 + RIJbSvRsTzAKBggqhkjOPQQDAgNIADBFAiBIgHrD2cUfNEctVx0WzHb0cLAsrK4Q + 3QbyxPLyenR+dAIhAMOIAyxlKKKvAJMOzAg0r+csSVRdP1YHsHiE7U1GeHWx + -----END CERTIFICATE----- + '' + ]; + # Set up localisation i18n = { defaultLocale = "en_US.UTF-8"; From c322de57578d72f93b4cdd7d26b8e8eded78bbfb Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 18 Jul 2024 11:36:26 +0200 Subject: [PATCH 0685/1125] Flake: update stable nixpkgs --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index bcc1ee7..58dcf40 100644 --- a/flake.lock +++ b/flake.lock @@ -427,11 +427,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1719956923, - "narHash": "sha256-nNJHJ9kfPdzYsCOlHOnbiiyKjZUW5sWbwx3cakg3/C4=", + "lastModified": 1720954236, + "narHash": "sha256-1mEKHp4m9brvfQ0rjCca8P1WHpymK3TOr3v34ydv9bs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "706eef542dec88cc0ed25b9075d3037564b2d164", + "rev": "53e81e790209e41f0c1efa9ff26ff2fd7ab35e27", "type": "github" }, "original": { From 79a247d9e6cb2ed12a08678479a2e801891787cb Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 18 Jul 2024 23:26:47 +0200 Subject: [PATCH 0686/1125] Caddy: bring back tailscale depenency and restart interval --- roles/server/caddy.nix | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index bddf3b3..b4e5fd0 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -1,4 +1,4 @@ -{config, ...}: let +{config, lib, ...}: let manualHostname = "manual.everest.tailscale"; in { services.caddy = { @@ -26,4 +26,12 @@ in { }; }; services.dnsmasq.settings.cname = ["${manualHostname},everest"]; + systemd = { + units.tailscaled.requiredBy = ["caddy.service"]; + # We have somewhat frequent power outages, and our ISP router takes + # ages to boot up. If I don't add a delay, traefik tries to bind to + # the tailscale interface before it's ready, making it crash too much + # in too little time + services.caddy.serviceConfig.RestartSec = lib.mkForce "120s"; + }; } From 6e885dfbb6b797974e7053924ed4b9fab26aa43a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Jul 2024 12:42:37 +0200 Subject: [PATCH 0687/1125] Server/caddy: add status to rust-motd --- roles/server/caddy.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index b4e5fd0..8c9e1ee 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -1,4 +1,8 @@ -{config, lib, ...}: let +{ + config, + lib, + ... +}: let manualHostname = "manual.everest.tailscale"; in { services.caddy = { @@ -34,4 +38,5 @@ in { # in too little time services.caddy.serviceConfig.RestartSec = lib.mkForce "120s"; }; + programs.rust-motd.settings.service_status.Caddy = "caddy"; } From 301a1bfa9b6131efa64d35f2b4bc405a818f7eae Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Jul 2024 12:53:43 +0200 Subject: [PATCH 0688/1125] Server/dnsmasq: add status to rust-motd --- roles/server/dns.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/server/dns.nix b/roles/server/dns.nix index 88402e1..1e446e5 100644 --- a/roles/server/dns.nix +++ b/roles/server/dns.nix @@ -32,6 +32,8 @@ }; }; + programs.rust-motd.settings.service_status.dnsmasq = "dnsmasq"; + # Dnsmasq conflicts with the resolved dns stub listener services.resolved.extraConfig = '' [Resolve] From 7006a7ff9322330063fb2280f5d1b96add2a4fec Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Jul 2024 02:16:12 +0200 Subject: [PATCH 0689/1125] Server/caddy: add downloads page --- roles/server/caddy.nix | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index 8c9e1ee..42f5baf 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -4,6 +4,7 @@ ... }: let manualHostname = "manual.everest.tailscale"; + downloadsHostname = "dl.everest.tailscale"; in { services.caddy = { enable = true; @@ -20,16 +21,29 @@ in { bind 100.73.96.48 } ''; - virtualHosts.nixos-manual = { - hostName = manualHostname; - extraConfig = '' - import tailscale - file_server - root * ${config.system.build.manual.manualHTML}/share/doc/nixos - ''; + virtualHosts = { + nixos-manual = { + hostName = manualHostname; + extraConfig = '' + import tailscale + file_server + root * ${config.system.build.manual.manualHTML}/share/doc/nixos + ''; + }; + downloads = { + hostName = downloadsHostname; + extraConfig = '' + import tailscale + file_server browse + root * /srv/dl/ + ''; + }; }; }; - services.dnsmasq.settings.cname = ["${manualHostname},everest"]; + services.dnsmasq.settings.cname = [ + "${manualHostname},everest" + "${downloadsHostname},everest" + ]; systemd = { units.tailscaled.requiredBy = ["caddy.service"]; # We have somewhat frequent power outages, and our ISP router takes From 777ab3a99b689803201e8b66b14bdb53bef1d317 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Jul 2024 03:20:17 +0200 Subject: [PATCH 0690/1125] Server/caddy: also serve downloads over http --- roles/server/caddy.nix | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index 42f5baf..484a716 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -5,6 +5,11 @@ }: let manualHostname = "manual.everest.tailscale"; downloadsHostname = "dl.everest.tailscale"; + downloadsConfig = '' + import tailscale + file_server browse + root * /srv/dl/ + ''; in { services.caddy = { enable = true; @@ -32,11 +37,11 @@ in { }; downloads = { hostName = downloadsHostname; - extraConfig = '' - import tailscale - file_server browse - root * /srv/dl/ - ''; + extraConfig = downloadsConfig; + }; + downloads-http = { + hostName = "http://${downloadsHostname}"; + extraConfig = downloadsConfig; }; }; }; From 48f97c5aae4957f0e8837249d777020a3ee237a8 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 24 Jul 2024 19:48:53 +0200 Subject: [PATCH 0691/1125] Desktop: add sysdvr-qt --- roles/desktop/programs/default.nix | 1 + roles/desktop/programs/sysdvr-qt.nix | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 roles/desktop/programs/sysdvr-qt.nix diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix index 7d6c257..6b6c94a 100755 --- a/roles/desktop/programs/default.nix +++ b/roles/desktop/programs/default.nix @@ -9,5 +9,6 @@ ./ssh.nix ./appimage.nix ./mpv.nix + ./sysdvr-qt.nix ]; } diff --git a/roles/desktop/programs/sysdvr-qt.nix b/roles/desktop/programs/sysdvr-qt.nix new file mode 100644 index 0000000..342830f --- /dev/null +++ b/roles/desktop/programs/sysdvr-qt.nix @@ -0,0 +1,8 @@ +{...}: { + services.udev.extraRules = '' + SUBSYSTEM=="usb", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="4ee0", MODE="0666" + ''; + home-manager.users.toast.services.flatpak = { + packages = ["io.github.parnassius.SysDVR-Qt"]; + }; +} From bf3c360a0d8d6b7354ccbea77819a9372870abd8 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Jul 2024 02:20:13 +0200 Subject: [PATCH 0692/1125] Gaming: add cemu --- roles/gaming/programs/cemu.nix | 7 +++++++ roles/gaming/programs/default.nix | 1 + 2 files changed, 8 insertions(+) create mode 100644 roles/gaming/programs/cemu.nix diff --git a/roles/gaming/programs/cemu.nix b/roles/gaming/programs/cemu.nix new file mode 100644 index 0000000..588fd39 --- /dev/null +++ b/roles/gaming/programs/cemu.nix @@ -0,0 +1,7 @@ +{pkgs, ...}: { + home-manager.users.toast = { + home = { + packages = [pkgs.cemu]; + }; + }; +} diff --git a/roles/gaming/programs/default.nix b/roles/gaming/programs/default.nix index e43a6db..6686119 100755 --- a/roles/gaming/programs/default.nix +++ b/roles/gaming/programs/default.nix @@ -5,6 +5,7 @@ ./rpcs3.nix ./retroarch.nix ./pcsx2.nix + ./cemu.nix ]; environment.systemPackages = with pkgs; [ heroic From 7eae2ded13488a116a4fa13255ea65c41cc357a8 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Jul 2024 11:21:08 +0200 Subject: [PATCH 0693/1125] Gaming/cemu: add wii u discs --- roles/gaming/programs/cemu.nix | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/roles/gaming/programs/cemu.nix b/roles/gaming/programs/cemu.nix index 588fd39..80178f8 100644 --- a/roles/gaming/programs/cemu.nix +++ b/roles/gaming/programs/cemu.nix @@ -2,6 +2,20 @@ home-manager.users.toast = { home = { packages = [pkgs.cemu]; + file = { + "Games/Isos/Wii U/Kirby and the Rainbow Paintbrush.wux".source = ( + pkgs.fetchurl { + url = "http://dl.everest.tailscale/Wii%20U/Kirby%20and%20the%20Rainbow%20Paintbrush.wux"; + hash = "sha256-taPGf709N2p3GlqqT92+SbOeD7QNKFUfB9X5urWVQps="; + } + ); + "Games/Isos/Wii U/Mario Kary 8.wux".source = ( + pkgs.fetchurl { + url = "http://dl.everest.tailscale/Wii%20U/Mario%20Kart%208.wux"; + hash = "sha256-O6lOkLUKPZi+FiEWJQQEeiEXOo+GTUecoSpGjE811k0="; + } + ); + }; }; }; } From a65936845fdc37ae59d972510977ade939b0c4ee Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 1 Aug 2024 21:46:14 +0200 Subject: [PATCH 0694/1125] Desktop: change nix io and cpu schedulers --- roles/desktop/configuration.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index 26030cf..2f87103 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -8,6 +8,11 @@ services.xserver.enable = true; + nix = { + daemonIOSchedClass = "idle"; + daemonCPUSchedPolicy = "idle"; + }; + # Set up fonts fonts.packages = [ (pkgs.nerdfonts.override {fonts = ["Hack" "JetBrainsMono"];}) From 6f82fb26bd7995758c1f684a3ef34a5b0f53665d Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Aug 2024 12:53:29 +0200 Subject: [PATCH 0695/1125] Common/starship: remove catppuccin preset The catpuccin nix module already does this --- roles/common/programs/starship.nix | 5 ----- 1 file changed, 5 deletions(-) diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index 8c9cfaa..59406e3 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -5,9 +5,6 @@ }: with lib; with builtins; let - catppuccinFlavour = "mocha"; - catppuccinStarship = pkgs.catppuccin + /starship/${catppuccinFlavour}.toml; - presets = { nerdFontSymbols = pkgs.fetchurl { url = "https://starship.rs/presets/toml/nerd-font-symbols.toml"; @@ -31,7 +28,6 @@ in { enable = true; settings = mergeAllAttrSets [ (readTomlPreset presets.nerdFontSymbols) - (readTomlPreset catppuccinStarship) { nix_shell = { disabled = false; @@ -45,7 +41,6 @@ in { truncation_length = 6; truncation_symbol = ".../"; }; - palette = "catppuccin_${catppuccinFlavour}"; } ]; }; From 7a5219af7ca5de1ec369211e89658ac6dd9bb4de Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Aug 2024 17:34:18 +0200 Subject: [PATCH 0696/1125] Common/starship: configure only with nixos, remove old profile workaround --- roles/common/programs/starship.nix | 73 ++++++++++-------------------- 1 file changed, 24 insertions(+), 49 deletions(-) diff --git a/roles/common/programs/starship.nix b/roles/common/programs/starship.nix index 59406e3..f270a27 100644 --- a/roles/common/programs/starship.nix +++ b/roles/common/programs/starship.nix @@ -1,56 +1,31 @@ -{ - pkgs, - lib, - ... -}: -with lib; -with builtins; let - presets = { - nerdFontSymbols = pkgs.fetchurl { - url = "https://starship.rs/presets/toml/nerd-font-symbols.toml"; - hash = "sha256-JKX+DKY4IPQwNj3znkhMUReNqbKBxdJyBZW+WCdKwuU="; - }; - }; - # -------------------------------- F U N C T I O N S -------------------------------- - - /* - Gonna be honest, I have no idea how this works, although it seems to work - Stolen from https://gist.github.com/pdalpra/daf339f59288201a6c8ba7dc84e9060e - */ - # Takes a list of attrSets and merges them - mergeAllAttrSets = attrsSets: - foldl' recursiveUpdate {} attrsSets; - - # Reads a TOML file and parses it - readTomlPreset = file: (fromTOML (readFile file)); -in { +{...}: { programs.starship = { enable = true; - settings = mergeAllAttrSets [ - (readTomlPreset presets.nerdFontSymbols) - { - nix_shell = { - disabled = false; - heuristic = true; - }; - os = { - disabled = false; - }; - directory = { - disabled = false; - truncation_length = 6; - truncation_symbol = ".../"; - }; - } + presets = [ + "nerd-font-symbols" ]; + settings = { + nix_shell = { + disabled = false; + heuristic = true; + }; + os = { + disabled = false; + }; + directory = { + disabled = false; + truncation_length = 6; + truncation_symbol = ".../"; + }; + }; }; # The catppuccin module only works for home-manager, so this # sets up starship with home-manager using the system config - home-manager.users.toast = {osConfig, ...}: { - programs.starship = { - enable = true; - catppuccin.enable = true; - settings = osConfig.programs.starship.settings; - }; - }; + # home-manager.users.toast = {osConfig, ...}: { + # programs.starship = { + # enable = false; + # catppuccin.enable = true; + # settings = osConfig.programs.starship.settings; + # }; + # }; } From b8d1c3985b767ee13d1e4e04bec94b61e80bc318 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Aug 2024 18:48:57 +0200 Subject: [PATCH 0697/1125] Flake: remove unneeded patch --- flake.nix | 1 - nixpkgs-patches/update-hhd.patch | 30 ------------------------------ 2 files changed, 31 deletions(-) delete mode 100644 nixpkgs-patches/update-hhd.patch diff --git a/flake.nix b/flake.nix index c2385d3..7eff150 100644 --- a/flake.nix +++ b/flake.nix @@ -95,7 +95,6 @@ src = nixpkgs-unstable-raw; patches = [ ./nixpkgs-patches/handheld-daemon-ui-init.patch - ./nixpkgs-patches/update-hhd.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/update-hhd.patch b/nixpkgs-patches/update-hhd.patch deleted file mode 100644 index 7c86f37..0000000 --- a/nixpkgs-patches/update-hhd.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 77380945dd829e737533359e0eba9fc965c1bdb6 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Mon, 1 Jul 2024 16:41:48 +0200 -Subject: [PATCH] handheld-daemon: 2.7.2 -> 3.1.1 - ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index ec24637dde3f70..d670fdc8b11e72 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -9,14 +9,14 @@ - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "2.7.2"; -+ version = "3.1.1"; - pyproject = true; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - rev = "v${version}"; -- hash = "sha256-jWLL1nmKam1iJ1R1l/OuIp+isgZ7toRhVamx1nOID/8="; -+ hash = "sha256-XUnAgQWnBb8Xsu88UVpdVXbFPxG13TNJFX1xgY06HT8="; - }; - - propagatedBuildInputs = with python3.pkgs; [ From 95dd730b7d175338c2b885be2e90ef7b793cd422 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 5 Aug 2024 18:49:11 +0200 Subject: [PATCH 0698/1125] Flake: update lock file --- flake.lock | 102 ++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/flake.lock b/flake.lock index 58dcf40..f04ae27 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1718371084, - "narHash": "sha256-abpBi61mg0g+lFFU0zY4C6oP6fBwPzbHPKBGw676xsA=", + "lastModified": 1722339003, + "narHash": "sha256-ZeS51uJI30ehNkcZ4uKqT4ZDARPyqrHADSKAwv5vVCU=", "owner": "ryantm", "repo": "agenix", - "rev": "3a56735779db467538fb2e577eda28a9daacaca6", + "rev": "3f1dae074a12feb7327b4bf43cbac0d124488bb7", "type": "github" }, "original": { @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1719915848, - "narHash": "sha256-zq+CMkdT8A9z74HonwspXp8HsX4OvP4uaVdD98AO6as=", + "lastModified": 1722661201, + "narHash": "sha256-2JX3S1hmmUhHuyGyGWnaM4xT0SiaDdVkNzmBrEowwK0=", "owner": "catppuccin", "repo": "nix", - "rev": "9345073d27d91ab66c1b6ab65df322906992aa59", + "rev": "19a0f144f0204a12a89243363efb6a493b8cfc83", "type": "github" }, "original": { @@ -185,11 +185,11 @@ ] }, "locked": { - "lastModified": 1720167120, - "narHash": "sha256-K9JYdlPiyaXp33JRg7CT8rMwH56e4ncXSsXW/YKnNXc=", + "lastModified": 1722630065, + "narHash": "sha256-QfM/9BMRkCmgWzrPDK+KbgJOUlSJnfX4OvsUupEUZvA=", "owner": "nix-community", "repo": "home-manager", - "rev": "bbe6e94737289c8cb92d4d8f9199fbfe4f11c0ba", + "rev": "afc892db74d65042031a093adb6010c4c3378422", "type": "github" }, "original": { @@ -227,11 +227,11 @@ ] }, "locked": { - "lastModified": 1720025282, - "narHash": "sha256-I70ARXPm1YjGJ0efykd5zsapUZtmVZ/sIgwJ0F0j17w=", + "lastModified": 1722666143, + "narHash": "sha256-uTr3LiytFHFUYmIrhs5NoGlm5DCJxQlfyaZEKCU/DS8=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "8dd0f8383bd60b8ed66cd27c1b49cdbf7be4ad9d", + "rev": "bcfe9dc708c92590fec676692b3ed79443eda819", "type": "github" }, "original": { @@ -243,11 +243,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1720132382, - "narHash": "sha256-9+TCNMnynp+OzMhsUiVTZXJKGH3QkXWdmC3SNUOY2z4=", - "rev": "d00edfb28d0a52d9acd392c582a43f98e773cf4c", + "lastModified": 1722643724, + "narHash": "sha256-FrM0DN/i5kKB06/4KYNkY3mMGpC5hYQhaKtx1mneReU=", + "rev": "66469fc281fc4abb3284574f77a8051fee8116b9", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/d00edfb28d0a52d9acd392c582a43f98e773cf4c.tar.gz" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/66469fc281fc4abb3284574f77a8051fee8116b9.tar.gz" }, "original": { "type": "tarball", @@ -266,11 +266,11 @@ ] }, "locked": { - "lastModified": 1719353937, - "narHash": "sha256-86NBqDxAP20ET/UoKX0WvSItblNQ97czXb2q7lkMrwk=", - "rev": "5d9d94089fb1ca96222a34bfe245ef5c5ebefd37", + "lastModified": 1722485024, + "narHash": "sha256-+7RReWaFQUO8MfAhJYNm4FkALuM3rPGy2AlXXv9Jmc8=", + "rev": "e350380d72f94035c309e19fda2fd550f6ab7376", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/5d9d94089fb1ca96222a34bfe245ef5c5ebefd37.tar.gz" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/e350380d72f94035c309e19fda2fd550f6ab7376.tar.gz" }, "original": { "type": "tarball", @@ -289,11 +289,11 @@ ] }, "locked": { - "lastModified": 1719353937, - "narHash": "sha256-86NBqDxAP20ET/UoKX0WvSItblNQ97czXb2q7lkMrwk=", - "rev": "5d9d94089fb1ca96222a34bfe245ef5c5ebefd37", + "lastModified": 1722485024, + "narHash": "sha256-+7RReWaFQUO8MfAhJYNm4FkALuM3rPGy2AlXXv9Jmc8=", + "rev": "e350380d72f94035c309e19fda2fd550f6ab7376", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/5d9d94089fb1ca96222a34bfe245ef5c5ebefd37.tar.gz" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/e350380d72f94035c309e19fda2fd550f6ab7376.tar.gz" }, "original": { "type": "tarball", @@ -302,11 +302,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1711997375, - "narHash": "sha256-KvU4gOtuFMS9Il67glRGtdNfguAINT9pCaXtvCL8uI8=", + "lastModified": 1721549352, + "narHash": "sha256-nlXJa8RSOX0kykrIYW33ukoHYq+FOSNztHLLgqKwOp8=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "45bf66f7068db79b552da864c0e87452be624d6c", + "rev": "dbce39ea8664820ba9037caaf1e2fad365ed6b4b", "type": "github" }, "original": { @@ -360,11 +360,11 @@ ] }, "locked": { - "lastModified": 1719832725, - "narHash": "sha256-dr8DkeS74KVNTgi8BE0BiUKALb+EKlMIV86G2xPYO64=", + "lastModified": 1722740924, + "narHash": "sha256-UQPgA5d8azLZuDHZMPmvDszhuKF1Ek89SrTRtqsQ4Ss=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "2917972ed34ce292309b3a4976286f8b5c08db27", + "rev": "97ca0a0fca0391de835f57e44f369a283e37890f", "type": "github" }, "original": { @@ -380,11 +380,11 @@ ] }, "locked": { - "lastModified": 1719832725, - "narHash": "sha256-dr8DkeS74KVNTgi8BE0BiUKALb+EKlMIV86G2xPYO64=", + "lastModified": 1722740924, + "narHash": "sha256-UQPgA5d8azLZuDHZMPmvDszhuKF1Ek89SrTRtqsQ4Ss=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "2917972ed34ce292309b3a4976286f8b5c08db27", + "rev": "97ca0a0fca0391de835f57e44f369a283e37890f", "type": "github" }, "original": { @@ -395,11 +395,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1719895800, - "narHash": "sha256-xNbjISJTFailxass4LmdWeV4jNhAlmJPwj46a/GxE6M=", + "lastModified": 1722332872, + "narHash": "sha256-2xLM4sc5QBfi0U/AANJAW21Bj4ZX479MHPMPkB+eKBU=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "6e253f12b1009053eff5344be5e835f604bb64cd", + "rev": "14c333162ba53c02853add87a0000cbd7aa230c2", "type": "github" }, "original": { @@ -427,11 +427,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1720954236, - "narHash": "sha256-1mEKHp4m9brvfQ0rjCca8P1WHpymK3TOr3v34ydv9bs=", + "lastModified": 1722651103, + "narHash": "sha256-IRiJA0NVAoyaZeKZluwfb2DoTpBAj+FLI0KfybBeDU0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "53e81e790209e41f0c1efa9ff26ff2fd7ab35e27", + "rev": "a633d89c6dc9a2a8aae11813a62d7c58b2c0cc51", "type": "github" }, "original": { @@ -442,11 +442,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1720031269, - "narHash": "sha256-rwz8NJZV+387rnWpTYcXaRNvzUSnnF9aHONoJIYmiUQ=", + "lastModified": 1722630782, + "narHash": "sha256-hMyG9/WlUi0Ho9VkRrrez7SeNlDzLxalm9FwY7n/Noo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9f4128e00b0ae8ec65918efeba59db998750ead6", + "rev": "d04953086551086b44b6f3c6b7eeb26294f207da", "type": "github" }, "original": { @@ -457,11 +457,11 @@ }, "nur": { "locked": { - "lastModified": 1720176372, - "narHash": "sha256-T1EOgGxdT0cRFahK2RoY3tQ1c9WklguVEvC+zGvd5zo=", + "lastModified": 1722864865, + "narHash": "sha256-W271AVeWwMXYRCpTGmdku2/Sg0yfbgylO75/TMVhRnA=", "owner": "nix-community", "repo": "NUR", - "rev": "a7f3a4b394375acdd26a1a8c7aecacc71c824fbc", + "rev": "d3ba11250bf54f978969bdf202560321520ed336", "type": "github" }, "original": { @@ -480,11 +480,11 @@ ] }, "locked": { - "lastModified": 1719876998, - "narHash": "sha256-NPKL3Ri2dbOOtvsgezTiUYutEgZUjcIXpwKCgt4Eu4E=", + "lastModified": 1722166680, + "narHash": "sha256-K0p0zAFS+h27yczx3x/J1owUm/oGKz0E9+aPtkSbWZc=", "owner": "toast003", "repo": "plasma-manager", - "rev": "d12cb0ed42a81ff84330b5cc94bff6abfeeb6da8", + "rev": "72da6a5ed6bd3dd05a5cf4b88504717c2430a476", "type": "github" }, "original": { @@ -603,11 +603,11 @@ ] }, "locked": { - "lastModified": 1720142793, - "narHash": "sha256-KhKF1VEMT5vz0vv1HZy0IOTEp2ZU1UD4ZgJAkOFbhIg=", + "lastModified": 1722821408, + "narHash": "sha256-FMCo35ZmMfvAcae+9neKfu6QzXjU3WL6vW2OFMXx6wI=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "8d57c84024068180130f3c0a2103dda967a0ddc2", + "rev": "f25962fbd632afea744dc7e6868f24d2e73ccedb", "type": "github" }, "original": { From 0119c52db6bf709b30d7608b4c17245df6321bdc Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 16 Aug 2024 18:10:45 +0200 Subject: [PATCH 0699/1125] Machines/Everest: move nix subvolume to SSD --- machines/Everest/hardware-configuration.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/machines/Everest/hardware-configuration.nix b/machines/Everest/hardware-configuration.nix index 7a97c97..b4727f0 100755 --- a/machines/Everest/hardware-configuration.nix +++ b/machines/Everest/hardware-configuration.nix @@ -23,9 +23,9 @@ options = ["compress=zstd" "subvol=@"]; }; "/nix" = { - device = "/dev/disk/by-label/Everest"; + device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; fsType = "btrfs"; - options = ["compress=zstd" "subvol=@nix"]; + options = ["subvol=@nix-server"]; }; "/home" = { device = "/dev/disk/by-label/Everest"; From 16fa01ad7dcb392014ddc6bac93fdabbe56989b5 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 16 Aug 2024 19:54:39 +0200 Subject: [PATCH 0700/1125] Server/Caddy: start after tailscale:x --- roles/server/caddy.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index 484a716..71029b9 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -50,9 +50,9 @@ in { "${downloadsHostname},everest" ]; systemd = { - units.tailscaled.requiredBy = ["caddy.service"]; + services.caddy.after = ["tailscaled.service"]; # We have somewhat frequent power outages, and our ISP router takes - # ages to boot up. If I don't add a delay, traefik tries to bind to + # ages to boot up. If I don't add a delay, caddy tries to bind to # the tailscale interface before it's ready, making it crash too much # in too little time services.caddy.serviceConfig.RestartSec = lib.mkForce "120s"; From 2c45da48447867728672d96febc2fae762d17c2c Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 16 Aug 2024 19:57:08 +0200 Subject: [PATCH 0701/1125] Server/tailscale: wait to get ip address --- roles/server/tailscale.nix | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/roles/server/tailscale.nix b/roles/server/tailscale.nix index d0c6aed..7135368 100644 --- a/roles/server/tailscale.nix +++ b/roles/server/tailscale.nix @@ -1,6 +1,21 @@ -{...}: { +{pkgs, ...}: let + script = pkgs.writeShellApplication { + name = "tailscale-wait-for-ip"; + runtimeInputs = [pkgs.iproute2]; + text = '' + # Based on https://github.com/tailscale/tailscale/issues/11504#issuecomment-2113331262 + echo Waiting for tailscale0 to get an IP adress.. + for i in {1..15}; do + if ip addr show dev tailscale0 | grep -q 'inet '; then break; fi + echo "$i" + sleep 1 + done + ''; + }; +in { services.tailscale = { # This is needed for being an exit node useRoutingFeatures = "server"; }; + systemd.services.tailscaled.postStart = "${script}/bin/tailscale-wait-for-ip"; } From 97b30aa8fc0553f47ef03d9dc362c9e2d071be4c Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 16 Aug 2024 20:38:54 +0200 Subject: [PATCH 0702/1125] Server/rust_motd: add nix to filesystems --- roles/server/rust_motd.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/rust_motd.nix b/roles/server/rust_motd.nix index d92dafd..f8560c0 100644 --- a/roles/server/rust_motd.nix +++ b/roles/server/rust_motd.nix @@ -5,6 +5,7 @@ settings = { filesystems = { Root = "/"; + "Nix Store" = "/nix"; Boot = "/boot/efi"; }; last_run.last_run = true; From 64b4a1b6cbef38365c4c470fb6ff63b57f0ac348 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 18 Aug 2024 15:31:29 +0200 Subject: [PATCH 0703/1125] Flake: update lock file --- flake.lock | 90 +++++++++++++++++++++++++++--------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/flake.lock b/flake.lock index f04ae27..69b6ffa 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1722339003, - "narHash": "sha256-ZeS51uJI30ehNkcZ4uKqT4ZDARPyqrHADSKAwv5vVCU=", + "lastModified": 1723293904, + "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", "owner": "ryantm", "repo": "agenix", - "rev": "3f1dae074a12feb7327b4bf43cbac0d124488bb7", + "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", "type": "github" }, "original": { @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1722661201, - "narHash": "sha256-2JX3S1hmmUhHuyGyGWnaM4xT0SiaDdVkNzmBrEowwK0=", + "lastModified": 1723691425, + "narHash": "sha256-F25VvHFMaqr26b7goaVWspXaK6XTRFz8RnILV+9OPkk=", "owner": "catppuccin", "repo": "nix", - "rev": "19a0f144f0204a12a89243363efb6a493b8cfc83", + "rev": "552056779a136092eb6358c573d925630172fc30", "type": "github" }, "original": { @@ -185,11 +185,11 @@ ] }, "locked": { - "lastModified": 1722630065, - "narHash": "sha256-QfM/9BMRkCmgWzrPDK+KbgJOUlSJnfX4OvsUupEUZvA=", + "lastModified": 1723399884, + "narHash": "sha256-97wn0ihhGqfMb8WcUgzzkM/TuAxce2Gd20A8oiruju4=", "owner": "nix-community", "repo": "home-manager", - "rev": "afc892db74d65042031a093adb6010c4c3378422", + "rev": "086f619dd991a4d355c07837448244029fc2d9ab", "type": "github" }, "original": { @@ -227,11 +227,11 @@ ] }, "locked": { - "lastModified": 1722666143, - "narHash": "sha256-uTr3LiytFHFUYmIrhs5NoGlm5DCJxQlfyaZEKCU/DS8=", + "lastModified": 1723916191, + "narHash": "sha256-wbkh2Tyo1dUwY+35OtF2117u1QqdVAlvDx4vgaW/InU=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "bcfe9dc708c92590fec676692b3ed79443eda819", + "rev": "dcc9afeea9d086cde9731ca90362c7bda62db6d0", "type": "github" }, "original": { @@ -243,11 +243,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1722643724, - "narHash": "sha256-FrM0DN/i5kKB06/4KYNkY3mMGpC5hYQhaKtx1mneReU=", - "rev": "66469fc281fc4abb3284574f77a8051fee8116b9", + "lastModified": 1723972205, + "narHash": "sha256-Y2lrLNXJAibZJ4YTtNp7l3Cm/3WNsWTTVJO3WF627zM=", + "rev": "7506d680ac540f39944c2a9f573900c5b1e4a023", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/66469fc281fc4abb3284574f77a8051fee8116b9.tar.gz" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/7506d680ac540f39944c2a9f573900c5b1e4a023.tar.gz?rev=7506d680ac540f39944c2a9f573900c5b1e4a023" }, "original": { "type": "tarball", @@ -266,11 +266,11 @@ ] }, "locked": { - "lastModified": 1722485024, - "narHash": "sha256-+7RReWaFQUO8MfAhJYNm4FkALuM3rPGy2AlXXv9Jmc8=", - "rev": "e350380d72f94035c309e19fda2fd550f6ab7376", + "lastModified": 1723511483, + "narHash": "sha256-rT/OkVXKkns2YvyF1nFvl+8Gc3sld1c1sXPtGkbqaDY=", + "rev": "cecf70b77539c1a593f60ec9d0305b5e537ab6a9", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/e350380d72f94035c309e19fda2fd550f6ab7376.tar.gz" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/cecf70b77539c1a593f60ec9d0305b5e537ab6a9.tar.gz?rev=cecf70b77539c1a593f60ec9d0305b5e537ab6a9" }, "original": { "type": "tarball", @@ -289,11 +289,11 @@ ] }, "locked": { - "lastModified": 1722485024, - "narHash": "sha256-+7RReWaFQUO8MfAhJYNm4FkALuM3rPGy2AlXXv9Jmc8=", - "rev": "e350380d72f94035c309e19fda2fd550f6ab7376", + "lastModified": 1723511483, + "narHash": "sha256-rT/OkVXKkns2YvyF1nFvl+8Gc3sld1c1sXPtGkbqaDY=", + "rev": "cecf70b77539c1a593f60ec9d0305b5e537ab6a9", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/e350380d72f94035c309e19fda2fd550f6ab7376.tar.gz" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/cecf70b77539c1a593f60ec9d0305b5e537ab6a9.tar.gz?rev=cecf70b77539c1a593f60ec9d0305b5e537ab6a9" }, "original": { "type": "tarball", @@ -360,11 +360,11 @@ ] }, "locked": { - "lastModified": 1722740924, - "narHash": "sha256-UQPgA5d8azLZuDHZMPmvDszhuKF1Ek89SrTRtqsQ4Ss=", + "lastModified": 1723950649, + "narHash": "sha256-dHMkGjwwCGj0c2MKyCjRXVBXq2Sz3TWbbM23AS7/5Hc=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "97ca0a0fca0391de835f57e44f369a283e37890f", + "rev": "392828aafbed62a6ea6ccab13728df2e67481805", "type": "github" }, "original": { @@ -380,11 +380,11 @@ ] }, "locked": { - "lastModified": 1722740924, - "narHash": "sha256-UQPgA5d8azLZuDHZMPmvDszhuKF1Ek89SrTRtqsQ4Ss=", + "lastModified": 1723950649, + "narHash": "sha256-dHMkGjwwCGj0c2MKyCjRXVBXq2Sz3TWbbM23AS7/5Hc=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "97ca0a0fca0391de835f57e44f369a283e37890f", + "rev": "392828aafbed62a6ea6ccab13728df2e67481805", "type": "github" }, "original": { @@ -395,11 +395,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1722332872, - "narHash": "sha256-2xLM4sc5QBfi0U/AANJAW21Bj4ZX479MHPMPkB+eKBU=", + "lastModified": 1723310128, + "narHash": "sha256-IiH8jG6PpR4h9TxSGMYh+2/gQiJW9MwehFvheSb5rPc=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "14c333162ba53c02853add87a0000cbd7aa230c2", + "rev": "c54cf53e022b0b3c1d3b8207aa0f9b194c24f0cf", "type": "github" }, "original": { @@ -427,11 +427,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1722651103, - "narHash": "sha256-IRiJA0NVAoyaZeKZluwfb2DoTpBAj+FLI0KfybBeDU0=", + "lastModified": 1723688146, + "narHash": "sha256-sqLwJcHYeWLOeP/XoLwAtYjr01TISlkOfz+NG82pbdg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a633d89c6dc9a2a8aae11813a62d7c58b2c0cc51", + "rev": "c3d4ac725177c030b1e289015989da2ad9d56af0", "type": "github" }, "original": { @@ -442,11 +442,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1722630782, - "narHash": "sha256-hMyG9/WlUi0Ho9VkRrrez7SeNlDzLxalm9FwY7n/Noo=", + "lastModified": 1723637854, + "narHash": "sha256-med8+5DSWa2UnOqtdICndjDAEjxr5D7zaIiK4pn0Q7c=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d04953086551086b44b6f3c6b7eeb26294f207da", + "rev": "c3aa7b8938b17aebd2deecf7be0636000d62a2b9", "type": "github" }, "original": { @@ -457,11 +457,11 @@ }, "nur": { "locked": { - "lastModified": 1722864865, - "narHash": "sha256-W271AVeWwMXYRCpTGmdku2/Sg0yfbgylO75/TMVhRnA=", + "lastModified": 1723976478, + "narHash": "sha256-eF815/buOMQlX2XbtNgN3GtA9bwv4psLbckU9iTBsxs=", "owner": "nix-community", "repo": "NUR", - "rev": "d3ba11250bf54f978969bdf202560321520ed336", + "rev": "575ee4dc4dc7c031663bdcfe2e8779abacc80d0a", "type": "github" }, "original": { @@ -603,11 +603,11 @@ ] }, "locked": { - "lastModified": 1722821408, - "narHash": "sha256-FMCo35ZmMfvAcae+9neKfu6QzXjU3WL6vW2OFMXx6wI=", + "lastModified": 1723944889, + "narHash": "sha256-602FSRKgF9gRywuLZjMu/dnbfmgv8mlkfakH+LnsIgU=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "f25962fbd632afea744dc7e6868f24d2e73ccedb", + "rev": "5ea2b85a16c2d4b3c847854e7c8c188f3e0c6db8", "type": "github" }, "original": { From 6d6dab1764bf4e32e22a0756140da4122cffc68a Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 18 Aug 2024 15:32:25 +0200 Subject: [PATCH 0704/1125] Flake: add nixpkgs patches --- flake.nix | 2 ++ nixpkgs-patches/fix-cemu.patch | 30 +++++++++++++++++++++++++++++ nixpkgs-patches/fix-delta.patch | 34 +++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 nixpkgs-patches/fix-cemu.patch create mode 100644 nixpkgs-patches/fix-delta.patch diff --git a/flake.nix b/flake.nix index 7eff150..6877338 100644 --- a/flake.nix +++ b/flake.nix @@ -95,6 +95,8 @@ src = nixpkgs-unstable-raw; patches = [ ./nixpkgs-patches/handheld-daemon-ui-init.patch + ./nixpkgs-patches/fix-cemu.patch + ./nixpkgs-patches/fix-delta.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/fix-cemu.patch b/nixpkgs-patches/fix-cemu.patch new file mode 100644 index 0000000..94209c5 --- /dev/null +++ b/nixpkgs-patches/fix-cemu.patch @@ -0,0 +1,30 @@ +From e01163e1ddcf90ecd57a5ea271979c6a68890d61 Mon Sep 17 00:00:00 2001 +From: Reno Dakota <170618376+paparodeo@users.noreply.github.com> +Date: Fri, 16 Aug 2024 03:21:07 +0000 +Subject: [PATCH] cemu: move glslang to buildInputs + +fix build perhaps after change 9b7f1a3913168bc9b9c070dbc9720dad1d06b49c +--- + pkgs/by-name/ce/cemu/package.nix | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pkgs/by-name/ce/cemu/package.nix b/pkgs/by-name/ce/cemu/package.nix +index ad70bc9c79f9d76..a9808577c9c0258 100644 +--- a/pkgs/by-name/ce/cemu/package.nix ++++ b/pkgs/by-name/ce/cemu/package.nix +@@ -69,7 +69,6 @@ in stdenv.mkDerivation (finalAttrs: { + addDriverRunpath + wrapGAppsHook3 + cmake +- glslang + nasm + ninja + pkg-config +@@ -83,6 +82,7 @@ in stdenv.mkDerivation (finalAttrs: { + curl + fmt_9 + glm ++ glslang + gtk3 + hidapi + imgui' diff --git a/nixpkgs-patches/fix-delta.patch b/nixpkgs-patches/fix-delta.patch new file mode 100644 index 0000000..1ac5c2a --- /dev/null +++ b/nixpkgs-patches/fix-delta.patch @@ -0,0 +1,34 @@ +From 01bcd715f54030bb3fb20e4c63b0795c2cfd821e Mon Sep 17 00:00:00 2001 +From: zowoq <59103226+zowoq@users.noreply.github.com> +Date: Thu, 15 Aug 2024 19:20:26 +1000 +Subject: [PATCH] delta: 0.17.0 -> 0.17.0-unstable-2024-08-12 + +--- + pkgs/applications/version-management/delta/default.nix | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/pkgs/applications/version-management/delta/default.nix b/pkgs/applications/version-management/delta/default.nix +index 40f474f2c4c1de1..1547632119fd412 100644 +--- a/pkgs/applications/version-management/delta/default.nix ++++ b/pkgs/applications/version-management/delta/default.nix +@@ -11,16 +11,16 @@ + + rustPlatform.buildRustPackage rec { + pname = "delta"; +- version = "0.17.0"; ++ version = "0.17.0-unstable-2024-08-12"; + + src = fetchFromGitHub { + owner = "dandavison"; + repo = pname; +- rev = version; +- hash = "sha256-r0ED9o2UP91fe6Bng5ioJra5S1bg+UEXMLeSQPkMswI="; ++ rev = "a01141b72001f4c630d77cf5274267d7638851e4"; ++ hash = "sha256-My51pQw5a2Y2VTu39MmnjGfmCavg8pFqOmOntUildS0="; + }; + +- cargoHash = "sha256-3CxRNhcjfDK/xUuM3w+GwqE0+X6WT92/LGj/qRp0TwA="; ++ cargoHash = "sha256-Rlc3Bc6Jh89KLLEWBWQB5GjoeIuHnwIVZN/MVFMjY24="; + + nativeBuildInputs = [ + installShellFiles From cf2a201c7a768cfa31722bcf972ae064d27ba0a3 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Aug 2024 16:40:26 +0200 Subject: [PATCH 0705/1125] Flake: add nix-minecraft module to Everest --- flake.lock | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- flake.nix | 7 +++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/flake.lock b/flake.lock index 69b6ffa..b8eecd2 100644 --- a/flake.lock +++ b/flake.lock @@ -58,6 +58,22 @@ } }, "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { "flake": false, "locked": { "lastModified": 1696426674, @@ -113,6 +129,24 @@ "inputs": { "systems": "systems_4" }, + "locked": { + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_5" + }, "locked": { "lastModified": 1710146030, "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", @@ -393,6 +427,28 @@ "type": "github" } }, + "nix-minecraft": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils_3", + "nixpkgs": [ + "nixpkgs-raw" + ] + }, + "locked": { + "lastModified": 1724377000, + "narHash": "sha256-TITxaXuhO8vDScZoE7i7E2BTXoJzZmKTk6qRkmI2d+o=", + "owner": "Infinidoge", + "repo": "nix-minecraft", + "rev": "b464de49b4d6ea8faf1988e02fc59c4908a7ff91", + "type": "github" + }, + "original": { + "owner": "Infinidoge", + "repo": "nix-minecraft", + "type": "github" + } + }, "nixos-hardware": { "locked": { "lastModified": 1723310128, @@ -509,6 +565,7 @@ "nix-impermanence": "nix-impermanence", "nix-index-db": "nix-index-db", "nix-index-db-unstable": "nix-index-db-unstable", + "nix-minecraft": "nix-minecraft", "nixos-hardware": "nixos-hardware", "nixpkgs-raw": "nixpkgs-raw", "nixpkgs-unstable-raw": "nixpkgs-unstable-raw", @@ -594,10 +651,25 @@ "type": "github" } }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "vscode-extensions": { "inputs": { - "flake-compat": "flake-compat", - "flake-utils": "flake-utils_3", + "flake-compat": "flake-compat_2", + "flake-utils": "flake-utils_4", "nixpkgs": [ "nixpkgs-unstable-raw" ] diff --git a/flake.nix b/flake.nix index 6877338..3522f18 100644 --- a/flake.nix +++ b/flake.nix @@ -83,6 +83,11 @@ inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; inputs.lix.follows = "lix"; }; + + nix-minecraft = { + url = "github:Infinidoge/nix-minecraft"; + inputs.nixpkgs.follows = "nixpkgs-raw"; + }; }; outputs = {...} @ inputs: @@ -234,6 +239,8 @@ nix-index-db.nixosModules.nix-index catppuccin.nixosModules.catppuccin lix-module.nixosModules.default + nix-minecraft.nixosModules.minecraft-servers + {nixpkgs.overlays = [nix-minecraft.overlay];} ./roles/common ./roles/server ./machines/Everest From 5bf5c9f737aa10f564e2c09878c0a731e0cd1efe Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Aug 2024 18:06:12 +0200 Subject: [PATCH 0706/1125] Machines/Everest: mount root subvolume of ssd --- machines/Everest/hardware-configuration.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/machines/Everest/hardware-configuration.nix b/machines/Everest/hardware-configuration.nix index b4727f0..8689a77 100755 --- a/machines/Everest/hardware-configuration.nix +++ b/machines/Everest/hardware-configuration.nix @@ -37,6 +37,11 @@ fsType = "btrfs"; options = ["compress=zstd" "subvol=/" "ro"]; }; + "/mnt/ssd" = { + device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; + fsType = "btrfs"; + options = ["subvol=/" "ro"]; + }; "/persist" = { device = "/dev/disk/by-label/Everest"; fsType = "btrfs"; From 100f7ec33e9de414003519772a21c9e3ef9984a0 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 23 Aug 2024 20:36:58 +0200 Subject: [PATCH 0707/1125] Server/minecraft: make vr locals server --- roles/server/default.nix | 1 + roles/server/minecraft.nix | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 roles/server/minecraft.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index 5e32379..d1e29aa 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -14,5 +14,6 @@ ./caddy.nix ./dns.nix ./rust_motd.nix + ./minecraft.nix ]; } diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix new file mode 100644 index 0000000..94ce9e1 --- /dev/null +++ b/roles/server/minecraft.nix @@ -0,0 +1,23 @@ +{pkgs, lib, ...}: { + nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ + "minecraft-server" + ]; + + services.minecraft-servers = { + enable = true; + eula = true; + openFirewall = true; + servers = { + vrlocals = { + enable = true; + package = pkgs.fabricServers.fabric-1_20_1; + serverProperties = { + motd = "Test server. Don't build anything important!"; + server-port = 25565; + enable-command-block = true; + sync-chunk-writes = false; + }; + }; + }; + }; +} From 2626ac99c3ab39052092aeaf268492ba10f0f3e9 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 24 Aug 2024 03:05:19 +0200 Subject: [PATCH 0708/1125] Server/minecraft: change vr locals server settings --- roles/server/minecraft.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix index 94ce9e1..72c49c5 100644 --- a/roles/server/minecraft.nix +++ b/roles/server/minecraft.nix @@ -12,11 +12,16 @@ enable = true; package = pkgs.fabricServers.fabric-1_20_1; serverProperties = { - motd = "Test server. Don't build anything important!"; + motd = "\\u00A7aBigChadGuys \\u00A7lPlus \\u00A7a(w/Cobblemon!) v2.6.1\\u00A7r\\n\\u00A76Have fun!"; server-port = 25565; + level-seed = "-1450714289616987871"; + white-list = true; enable-command-block = true; sync-chunk-writes = false; }; + whitelist = { + Toast_003 = "b3ca4afb-a3da-4a78-85c3-2292fd0787e2"; + }; }; }; }; From d9d0ad7b733a7715b8af52d7bf4b04c6650220c0 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 25 Aug 2024 19:52:15 +0200 Subject: [PATCH 0709/1125] Server/minecraft: add more memory --- roles/server/minecraft.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix index 72c49c5..a38da91 100644 --- a/roles/server/minecraft.nix +++ b/roles/server/minecraft.nix @@ -11,6 +11,7 @@ vrlocals = { enable = true; package = pkgs.fabricServers.fabric-1_20_1; + jvmOpts = "-Xmx8G"; serverProperties = { motd = "\\u00A7aBigChadGuys \\u00A7lPlus \\u00A7a(w/Cobblemon!) v2.6.1\\u00A7r\\n\\u00A76Have fun!"; server-port = 25565; From 52cb4607dbfc29b80034aabdcf4b51ca646608a1 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 25 Aug 2024 19:53:00 +0200 Subject: [PATCH 0710/1125] Server/minecraft: don't set the whitelist declaratively --- roles/server/minecraft.nix | 3 --- 1 file changed, 3 deletions(-) diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix index a38da91..2247a7f 100644 --- a/roles/server/minecraft.nix +++ b/roles/server/minecraft.nix @@ -20,9 +20,6 @@ enable-command-block = true; sync-chunk-writes = false; }; - whitelist = { - Toast_003 = "b3ca4afb-a3da-4a78-85c3-2292fd0787e2"; - }; }; }; }; From 5981d50a726258ea00e47a2c12555c3df3206911 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 28 Aug 2024 03:42:55 +0200 Subject: [PATCH 0711/1125] Flake: update lock file --- flake.lock | 80 +++++++++++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/flake.lock b/flake.lock index b8eecd2..572ff1b 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1723691425, - "narHash": "sha256-F25VvHFMaqr26b7goaVWspXaK6XTRFz8RnILV+9OPkk=", + "lastModified": 1724469296, + "narHash": "sha256-p3R4LUNk6gC+fTKRUm9ByXaoRIocnQMwVuJSIxECQ8o=", "owner": "catppuccin", "repo": "nix", - "rev": "552056779a136092eb6358c573d925630172fc30", + "rev": "874e668ddaf3687e8d38ccd0188a641ffefe1cfb", "type": "github" }, "original": { @@ -219,11 +219,11 @@ ] }, "locked": { - "lastModified": 1723399884, - "narHash": "sha256-97wn0ihhGqfMb8WcUgzzkM/TuAxce2Gd20A8oiruju4=", + "lastModified": 1724435763, + "narHash": "sha256-UNky3lJNGQtUEXT2OY8gMxejakSWPTfWKvpFkpFlAfM=", "owner": "nix-community", "repo": "home-manager", - "rev": "086f619dd991a4d355c07837448244029fc2d9ab", + "rev": "c2cd2a52e02f1dfa1c88f95abeb89298d46023be", "type": "github" }, "original": { @@ -261,11 +261,11 @@ ] }, "locked": { - "lastModified": 1723916191, - "narHash": "sha256-wbkh2Tyo1dUwY+35OtF2117u1QqdVAlvDx4vgaW/InU=", + "lastModified": 1724753550, + "narHash": "sha256-idw4NE/j9j6LVD7nrw7lWq77z2J6S5oCHjJdIaPyGvw=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "dcc9afeea9d086cde9731ca90362c7bda62db6d0", + "rev": "1bda3a989a5785e09d710452c817ee2699c89a3a", "type": "github" }, "original": { @@ -277,11 +277,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1723972205, - "narHash": "sha256-Y2lrLNXJAibZJ4YTtNp7l3Cm/3WNsWTTVJO3WF627zM=", - "rev": "7506d680ac540f39944c2a9f573900c5b1e4a023", + "lastModified": 1724714224, + "narHash": "sha256-Fn72c2ycgYERAdwWEPmIUhuOmgOwuvZhTNdqOuiR0uw=", + "rev": "0dc486a5bf218870aafd5552586ab4330881647e", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/7506d680ac540f39944c2a9f573900c5b1e4a023.tar.gz?rev=7506d680ac540f39944c2a9f573900c5b1e4a023" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/0dc486a5bf218870aafd5552586ab4330881647e.tar.gz?rev=0dc486a5bf218870aafd5552586ab4330881647e" }, "original": { "type": "tarball", @@ -374,11 +374,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1719091691, - "narHash": "sha256-AxaLX5cBEcGtE02PeGsfscSb/fWMnyS7zMWBXQWDKbE=", + "lastModified": 1724489415, + "narHash": "sha256-ey8vhwY/6XCKoh7fyTn3aIQs7WeYSYtLbYEG87VCzX4=", "owner": "nix-community", "repo": "impermanence", - "rev": "23c1f06316b67cb5dabdfe2973da3785cfe9c34a", + "rev": "c7f5b394397398c023000cf843986ee2571a1fd7", "type": "github" }, "original": { @@ -394,11 +394,11 @@ ] }, "locked": { - "lastModified": 1723950649, - "narHash": "sha256-dHMkGjwwCGj0c2MKyCjRXVBXq2Sz3TWbbM23AS7/5Hc=", + "lastModified": 1724576102, + "narHash": "sha256-uM7n5nNL6fmA0bwMJBNll11f4cMWOFa2Ni6F5KeIldM=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "392828aafbed62a6ea6ccab13728df2e67481805", + "rev": "e333d62b70b179da1dd78d94315e8a390f2d12e5", "type": "github" }, "original": { @@ -414,11 +414,11 @@ ] }, "locked": { - "lastModified": 1723950649, - "narHash": "sha256-dHMkGjwwCGj0c2MKyCjRXVBXq2Sz3TWbbM23AS7/5Hc=", + "lastModified": 1724576102, + "narHash": "sha256-uM7n5nNL6fmA0bwMJBNll11f4cMWOFa2Ni6F5KeIldM=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "392828aafbed62a6ea6ccab13728df2e67481805", + "rev": "e333d62b70b179da1dd78d94315e8a390f2d12e5", "type": "github" }, "original": { @@ -436,11 +436,11 @@ ] }, "locked": { - "lastModified": 1724377000, - "narHash": "sha256-TITxaXuhO8vDScZoE7i7E2BTXoJzZmKTk6qRkmI2d+o=", + "lastModified": 1724722703, + "narHash": "sha256-5xhQLp0tLY/1nWlcU5uYsCUawxcwqEzAGi0b8wAQKxA=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "b464de49b4d6ea8faf1988e02fc59c4908a7ff91", + "rev": "f74de364f4354e509cc12399de4d4df834a0a45f", "type": "github" }, "original": { @@ -451,11 +451,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1723310128, - "narHash": "sha256-IiH8jG6PpR4h9TxSGMYh+2/gQiJW9MwehFvheSb5rPc=", + "lastModified": 1724575805, + "narHash": "sha256-OB/kEL3GAhUZmUfkbPfsPhKs0pRqJKs0EEBiLfyKZw8=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "c54cf53e022b0b3c1d3b8207aa0f9b194c24f0cf", + "rev": "9fc19be21f0807d6be092d70bf0b1de0c00ac895", "type": "github" }, "original": { @@ -483,11 +483,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1723688146, - "narHash": "sha256-sqLwJcHYeWLOeP/XoLwAtYjr01TISlkOfz+NG82pbdg=", + "lastModified": 1724531977, + "narHash": "sha256-XROVLf9ti4rrNCFLr+DmXRZtPjCQTW4cYy59owTEmxk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c3d4ac725177c030b1e289015989da2ad9d56af0", + "rev": "2527da1ef492c495d5391f3bcf9c1dd9f4514e32", "type": "github" }, "original": { @@ -498,11 +498,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1723637854, - "narHash": "sha256-med8+5DSWa2UnOqtdICndjDAEjxr5D7zaIiK4pn0Q7c=", + "lastModified": 1724479785, + "narHash": "sha256-pP3Azj5d6M5nmG68Fu4JqZmdGt4S4vqI5f8te+E/FTw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c3aa7b8938b17aebd2deecf7be0636000d62a2b9", + "rev": "d0e1602ddde669d5beb01aec49d71a51937ed7be", "type": "github" }, "original": { @@ -513,11 +513,11 @@ }, "nur": { "locked": { - "lastModified": 1723976478, - "narHash": "sha256-eF815/buOMQlX2XbtNgN3GtA9bwv4psLbckU9iTBsxs=", + "lastModified": 1724775364, + "narHash": "sha256-agN3Oaph2+2DH3+m6Jp4d1ji5s93joohKcV35DfJWQk=", "owner": "nix-community", "repo": "NUR", - "rev": "575ee4dc4dc7c031663bdcfe2e8779abacc80d0a", + "rev": "95f1862227c883581265a8801ea28af99635dd97", "type": "github" }, "original": { @@ -675,11 +675,11 @@ ] }, "locked": { - "lastModified": 1723944889, - "narHash": "sha256-602FSRKgF9gRywuLZjMu/dnbfmgv8mlkfakH+LnsIgU=", + "lastModified": 1724722238, + "narHash": "sha256-DLtiPBpKBIL4+lxu7H8e6gPZvZ3Rb7D8mMh8OieBURM=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "5ea2b85a16c2d4b3c847854e7c8c188f3e0c6db8", + "rev": "ad07ef4512e976b9537d05b7d2e4a5d7a2965ff7", "type": "github" }, "original": { From 8bc792fb2dc2ec9ab402e73b3f5cfd4fada2c9cb Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 28 Aug 2024 03:43:17 +0200 Subject: [PATCH 0712/1125] Flake: remove uneeded patches --- flake.nix | 2 -- nixpkgs-patches/fix-cemu.patch | 30 ----------------------------- nixpkgs-patches/fix-delta.patch | 34 --------------------------------- 3 files changed, 66 deletions(-) delete mode 100644 nixpkgs-patches/fix-cemu.patch delete mode 100644 nixpkgs-patches/fix-delta.patch diff --git a/flake.nix b/flake.nix index 3522f18..a227c04 100644 --- a/flake.nix +++ b/flake.nix @@ -100,8 +100,6 @@ src = nixpkgs-unstable-raw; patches = [ ./nixpkgs-patches/handheld-daemon-ui-init.patch - ./nixpkgs-patches/fix-cemu.patch - ./nixpkgs-patches/fix-delta.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/fix-cemu.patch b/nixpkgs-patches/fix-cemu.patch deleted file mode 100644 index 94209c5..0000000 --- a/nixpkgs-patches/fix-cemu.patch +++ /dev/null @@ -1,30 +0,0 @@ -From e01163e1ddcf90ecd57a5ea271979c6a68890d61 Mon Sep 17 00:00:00 2001 -From: Reno Dakota <170618376+paparodeo@users.noreply.github.com> -Date: Fri, 16 Aug 2024 03:21:07 +0000 -Subject: [PATCH] cemu: move glslang to buildInputs - -fix build perhaps after change 9b7f1a3913168bc9b9c070dbc9720dad1d06b49c ---- - pkgs/by-name/ce/cemu/package.nix | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pkgs/by-name/ce/cemu/package.nix b/pkgs/by-name/ce/cemu/package.nix -index ad70bc9c79f9d76..a9808577c9c0258 100644 ---- a/pkgs/by-name/ce/cemu/package.nix -+++ b/pkgs/by-name/ce/cemu/package.nix -@@ -69,7 +69,6 @@ in stdenv.mkDerivation (finalAttrs: { - addDriverRunpath - wrapGAppsHook3 - cmake -- glslang - nasm - ninja - pkg-config -@@ -83,6 +82,7 @@ in stdenv.mkDerivation (finalAttrs: { - curl - fmt_9 - glm -+ glslang - gtk3 - hidapi - imgui' diff --git a/nixpkgs-patches/fix-delta.patch b/nixpkgs-patches/fix-delta.patch deleted file mode 100644 index 1ac5c2a..0000000 --- a/nixpkgs-patches/fix-delta.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 01bcd715f54030bb3fb20e4c63b0795c2cfd821e Mon Sep 17 00:00:00 2001 -From: zowoq <59103226+zowoq@users.noreply.github.com> -Date: Thu, 15 Aug 2024 19:20:26 +1000 -Subject: [PATCH] delta: 0.17.0 -> 0.17.0-unstable-2024-08-12 - ---- - pkgs/applications/version-management/delta/default.nix | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/pkgs/applications/version-management/delta/default.nix b/pkgs/applications/version-management/delta/default.nix -index 40f474f2c4c1de1..1547632119fd412 100644 ---- a/pkgs/applications/version-management/delta/default.nix -+++ b/pkgs/applications/version-management/delta/default.nix -@@ -11,16 +11,16 @@ - - rustPlatform.buildRustPackage rec { - pname = "delta"; -- version = "0.17.0"; -+ version = "0.17.0-unstable-2024-08-12"; - - src = fetchFromGitHub { - owner = "dandavison"; - repo = pname; -- rev = version; -- hash = "sha256-r0ED9o2UP91fe6Bng5ioJra5S1bg+UEXMLeSQPkMswI="; -+ rev = "a01141b72001f4c630d77cf5274267d7638851e4"; -+ hash = "sha256-My51pQw5a2Y2VTu39MmnjGfmCavg8pFqOmOntUildS0="; - }; - -- cargoHash = "sha256-3CxRNhcjfDK/xUuM3w+GwqE0+X6WT92/LGj/qRp0TwA="; -+ cargoHash = "sha256-Rlc3Bc6Jh89KLLEWBWQB5GjoeIuHnwIVZN/MVFMjY24="; - - nativeBuildInputs = [ - installShellFiles From f836354767a9a60d613658e1734c8639befa6436 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 28 Aug 2024 03:44:18 +0200 Subject: [PATCH 0713/1125] Kde/neochat: disable temporarely --- roles/kde/programs/default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index bbfc028..4ede2bd 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -3,7 +3,8 @@ ./kate.nix ./firefox.nix ./skanpage.nix - ./neochat.nix + # Neochat depends on olm which is unsafe now + # ./neochat.nix ./konsole.nix ./git.nix ]; From d686b4f0b5159717f5daefa382589b908dbfc630 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 28 Aug 2024 13:52:17 +0200 Subject: [PATCH 0714/1125] Kde/plasma: redo panel configuration --- roles/kde/plasma.nix | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index b91dd3f..e6d6cfd 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -118,16 +118,18 @@ in { height = 44; widgets = [ { - name = "org.kde.plasma.kickoff"; - config.General.icon = "nix-snowflake-white"; + kickoff = { + icon = "nix-snowflake-white"; + }; } "org.kde.plasma.pager" "org.kde.plasma.icontasks" "org.kde.plasma.marginsseparator" "org.kde.plasma.systemtray" { - name = "org.kde.plasma.digitalclock"; - config.Appearance.showSeconds = "true"; + digitalClock = { + time.showSeconds = "always"; + }; } "org.kde.plasma.showdesktop" ]; From dad79e9b402886cac51ef7bf010dbb48b2ae60ee Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 28 Aug 2024 14:11:20 +0200 Subject: [PATCH 0715/1125] Kde/plasma: make the panel floating --- roles/kde/plasma.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index e6d6cfd..dd10a8f 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -116,6 +116,7 @@ in { { location = "bottom"; height = 44; + floating = true; widgets = [ { kickoff = { From 0991d4defbf4db702d4623c1d07703be1d1ea865 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 28 Aug 2024 17:07:23 +0200 Subject: [PATCH 0716/1125] Common: enable fstrim --- roles/common/configuration.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 4cbf013..047563e 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -83,7 +83,10 @@ }; }; - services.fwupd.enable = true; + services = { + fstrim.enable = true; + fwupd.enable = true; + }; # Set up my user users.users.toast = { From c7088d8b962541de05eb435ff796deeee85d0152 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 1 Sep 2024 14:12:14 +0200 Subject: [PATCH 0717/1125] Kde/plasma: install plasma vaults --- roles/kde/plasma.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index dd10a8f..9646b48 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -43,7 +43,11 @@ in { programs.dconf.enable = true; # Install the plasma default configs - environment.systemPackages = [plasmaDefaults pkgs.kdePackages.plasma-thunderbolt]; + environment.systemPackages = with pkgs.kdePackages; [ + plasmaDefaults + plasma-thunderbolt + plasma-vault + ]; # Plasma configs should be on all users home-manager.sharedModules = [ From 1aca0c5e64bc790344fd570917628632ab997979 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 2 Sep 2024 16:12:18 +0200 Subject: [PATCH 0718/1125] Server/minecraft: disable spawn protection --- roles/server/minecraft.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix index 2247a7f..ec019fc 100644 --- a/roles/server/minecraft.nix +++ b/roles/server/minecraft.nix @@ -17,6 +17,7 @@ server-port = 25565; level-seed = "-1450714289616987871"; white-list = true; + spawn-protection = 0; enable-command-block = true; sync-chunk-writes = false; }; From 10902ed69f32cac6ccf362dbd0daa922e9f577ac Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 6 Sep 2024 02:25:27 +0200 Subject: [PATCH 0719/1125] Flake: refactor nixos configurations --- flake.nix | 151 +++++++++++++++++++++++------------------------------- 1 file changed, 64 insertions(+), 87 deletions(-) diff --git a/flake.nix b/flake.nix index a227c04..79cb2ba 100644 --- a/flake.nix +++ b/flake.nix @@ -134,116 +134,93 @@ discord-krisp-fixer = callPackage ./pkgs/discord-krisp-fixer {}; }; }; - nixosConfigurations = { - Archie = nixpkgs-unstable.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { - systemPkgs = inputs.nixpkgs-unstable-raw; - flakeSelf = self; + nixosConfigurations = let + mkSystems = hosts: + builtins.mapAttrs ( + host: settings: let + pkgs = + if isStable + then nixpkgs + else nixpkgs-unstable; + isStable = (settings ? stable) && (settings.stable == true); + in + mkSystem host settings.modules pkgs isStable + ) + hosts; + mkSystem = host: modules: pkgs: stable: + pkgs.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { + systemPkgs = + if stable + then nixpkgs-patched + else nixpkgs-unstable-patched; + flakeSelf = self; + }; + modules = + [ + agenix.nixosModules.default + ( + if stable + then home-manager + else home-manager-unstable + ) + .nixosModule + ( + if stable + then nix-index-db + else nix-index-db-unstable + ) + .nixosModules + .nix-index + catppuccin.nixosModules.catppuccin + ( + if stable + then lix-module + else lix-module-unstable + ) + .nixosModules + .default + ./roles/common + (./machines + "/${host}") + ] + ++ modules; }; - /* - I used to set up nixpkgs in the flake, but doing that made - defining overlays in modules impossible (or at least I could - not figure out how) - Also has nice side effect of making it easier to add new systems :3 - */ - modules = [ - agenix.nixosModules.default - home-manager-unstable.nixosModule - nix-index-db-unstable.nixosModules.nix-index - catppuccin.nixosModules.catppuccin + in + mkSystems { + Archie.modules = [ nixos-hardware.nixosModules.common-cpu-amd-zenpower - lix-module-unstable.nixosModules.default - ./roles/common ./roles/desktop ./roles/kde ./roles/gaming - ./machines/Archie ]; - }; - - SurfaceGo = nixpkgs-unstable.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { - systemPkgs = inputs.nixpkgs-unstable-raw; - flakeSelf = self; - }; - modules = [ - agenix.nixosModules.default - home-manager-unstable.nixosModule + SurfaceGo.modules = [ nixos-hardware.nixosModules.microsoft-surface-go - nix-index-db-unstable.nixosModules.nix-index - catppuccin.nixosModules.catppuccin - lix-module-unstable.nixosModules.default - ./roles/common ./roles/desktop ./roles/kde ./machines/SurfaceGo ]; - }; - - SteamDeck = nixpkgs-unstable.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { - systemPkgs = inputs.nixpkgs-unstable-raw; - flakeSelf = self; - }; - modules = [ - agenix.nixosModules.default + SteamDeck.modules = [ jovian.nixosModules.default - home-manager-unstable.nixosModule - nix-index-db-unstable.nixosModules.nix-index - catppuccin.nixosModules.catppuccin - lix-module-unstable.nixosModules.default - ./roles/common ./roles/desktop ./roles/kde ./roles/gaming - ./machines/SteamDeck ]; - }; - - WinMax2 = nixpkgs-unstable.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { - systemPkgs = inputs.nixpkgs-unstable-raw; - flakeSelf = self; - }; - modules = [ - agenix.nixosModules.default + WinMax2.modules = [ jovian.nixosModules.default - home-manager-unstable.nixosModule - nix-index-db-unstable.nixosModules.nix-index nixos-hardware.nixosModules.gpd-win-max-2-2023 - catppuccin.nixosModules.catppuccin - lix-module-unstable.nixosModules.default - ./roles/common ./roles/desktop ./roles/kde ./roles/gaming - ./machines/WinMax2 ]; - }; - - Everest = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { - systemPkgs = inputs.nixpkgs-raw; - flakeSelf = self; + Everest = { + stable = true; + modules = [ + nix-minecraft.nixosModules.minecraft-servers + {nixpkgs.overlays = [nix-minecraft.overlay];} + ./roles/server + ]; }; - modules = [ - agenix.nixosModules.default - home-manager.nixosModule - nix-index-db.nixosModules.nix-index - catppuccin.nixosModules.catppuccin - lix-module.nixosModules.default - nix-minecraft.nixosModules.minecraft-servers - {nixpkgs.overlays = [nix-minecraft.overlay];} - ./roles/common - ./roles/server - ./machines/Everest - ]; }; - }; }; } From bdf8140765c085e712663016f4f5d1537aaa93da Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 6 Sep 2024 03:38:23 +0200 Subject: [PATCH 0720/1125] Server/minecraft: add toast to minecraft group --- roles/server/minecraft.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix index ec019fc..afb2fb8 100644 --- a/roles/server/minecraft.nix +++ b/roles/server/minecraft.nix @@ -3,6 +3,8 @@ "minecraft-server" ]; + users.users.toast.extraGroups = ["minecraft"]; + services.minecraft-servers = { enable = true; eula = true; From dc9cc8b6faf77fa17543257b7deb6c1c72f5e242 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 6 Sep 2024 03:38:46 +0200 Subject: [PATCH 0721/1125] Server/minecraft: format file --- roles/server/minecraft.nix | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix index afb2fb8..e8ed396 100644 --- a/roles/server/minecraft.nix +++ b/roles/server/minecraft.nix @@ -1,7 +1,12 @@ -{pkgs, lib, ...}: { - nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ - "minecraft-server" - ]; +{ + pkgs, + lib, + ... +}: { + nixpkgs.config.allowUnfreePredicate = pkg: + builtins.elem (lib.getName pkg) [ + "minecraft-server" + ]; users.users.toast.extraGroups = ["minecraft"]; From a3b8fe20d147008fedfb2bc3f0928d78e0e171f7 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 6 Sep 2024 03:57:26 +0200 Subject: [PATCH 0722/1125] Flake: update lock file --- flake.lock | 74 +++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/flake.lock b/flake.lock index 572ff1b..fef3436 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1724469296, - "narHash": "sha256-p3R4LUNk6gC+fTKRUm9ByXaoRIocnQMwVuJSIxECQ8o=", + "lastModified": 1725509983, + "narHash": "sha256-NHCgHVqumPraFJnLrkanoLDuhOoUHUvRhvp/RIHJR+A=", "owner": "catppuccin", "repo": "nix", - "rev": "874e668ddaf3687e8d38ccd0188a641ffefe1cfb", + "rev": "45745fe5960acaefef2b60f3455bcac6a0ca6bc9", "type": "github" }, "original": { @@ -219,11 +219,11 @@ ] }, "locked": { - "lastModified": 1724435763, - "narHash": "sha256-UNky3lJNGQtUEXT2OY8gMxejakSWPTfWKvpFkpFlAfM=", + "lastModified": 1725180166, + "narHash": "sha256-fzssXuGR/mCeGbzM1ExaTqDz7QDGta3WA4jJsZyRruo=", "owner": "nix-community", "repo": "home-manager", - "rev": "c2cd2a52e02f1dfa1c88f95abeb89298d46023be", + "rev": "471e3eb0a114265bcd62d11d58ba8d3421ee68eb", "type": "github" }, "original": { @@ -261,11 +261,11 @@ ] }, "locked": { - "lastModified": 1724753550, - "narHash": "sha256-idw4NE/j9j6LVD7nrw7lWq77z2J6S5oCHjJdIaPyGvw=", + "lastModified": 1725559615, + "narHash": "sha256-q24lAKpBubomTHcNKLoVyvnNwVJJyBwcb/Gkhl0LLbs=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "1bda3a989a5785e09d710452c817ee2699c89a3a", + "rev": "45e6dcff8489d75941468462c41fad0948a2c94b", "type": "github" }, "original": { @@ -277,11 +277,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1724714224, - "narHash": "sha256-Fn72c2ycgYERAdwWEPmIUhuOmgOwuvZhTNdqOuiR0uw=", - "rev": "0dc486a5bf218870aafd5552586ab4330881647e", + "lastModified": 1725389327, + "narHash": "sha256-UtHpRNYPabG0zW3XB8Dldb68O7n1JLSUczTwg37dcsA=", + "rev": "72589e703258e5cb4de091390291ff84c3a22bf2", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/0dc486a5bf218870aafd5552586ab4330881647e.tar.gz?rev=0dc486a5bf218870aafd5552586ab4330881647e" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/72589e703258e5cb4de091390291ff84c3a22bf2.tar.gz?rev=72589e703258e5cb4de091390291ff84c3a22bf2" }, "original": { "type": "tarball", @@ -394,11 +394,11 @@ ] }, "locked": { - "lastModified": 1724576102, - "narHash": "sha256-uM7n5nNL6fmA0bwMJBNll11f4cMWOFa2Ni6F5KeIldM=", + "lastModified": 1725161148, + "narHash": "sha256-WfAHq3Ag3vLNFfWxKHjFBFdPI6JIideWFJod9mx1eoo=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "e333d62b70b179da1dd78d94315e8a390f2d12e5", + "rev": "32058e9138248874773630c846563b1a78ee7a5b", "type": "github" }, "original": { @@ -414,11 +414,11 @@ ] }, "locked": { - "lastModified": 1724576102, - "narHash": "sha256-uM7n5nNL6fmA0bwMJBNll11f4cMWOFa2Ni6F5KeIldM=", + "lastModified": 1725161148, + "narHash": "sha256-WfAHq3Ag3vLNFfWxKHjFBFdPI6JIideWFJod9mx1eoo=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "e333d62b70b179da1dd78d94315e8a390f2d12e5", + "rev": "32058e9138248874773630c846563b1a78ee7a5b", "type": "github" }, "original": { @@ -436,11 +436,11 @@ ] }, "locked": { - "lastModified": 1724722703, - "narHash": "sha256-5xhQLp0tLY/1nWlcU5uYsCUawxcwqEzAGi0b8wAQKxA=", + "lastModified": 1725414050, + "narHash": "sha256-apEL1vA8A8skxokuNoaH1Jfx32XybeQpOo8uJDKPcjY=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "f74de364f4354e509cc12399de4d4df834a0a45f", + "rev": "55a9a8faee81d758e09f28ad395f9a4f29273c39", "type": "github" }, "original": { @@ -451,11 +451,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1724575805, - "narHash": "sha256-OB/kEL3GAhUZmUfkbPfsPhKs0pRqJKs0EEBiLfyKZw8=", + "lastModified": 1725477728, + "narHash": "sha256-ahej1VRqKmWbG7gewty+GlrSBEeGY/J2Zy8Nt8+3fdg=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "9fc19be21f0807d6be092d70bf0b1de0c00ac895", + "rev": "880be1ab837e1e9fe0449dae41ac4d034694d4ce", "type": "github" }, "original": { @@ -483,11 +483,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1724531977, - "narHash": "sha256-XROVLf9ti4rrNCFLr+DmXRZtPjCQTW4cYy59owTEmxk=", + "lastModified": 1725407940, + "narHash": "sha256-tiN5Rlg/jiY0tyky+soJZoRzLKbPyIdlQ77xVgREDNM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2527da1ef492c495d5391f3bcf9c1dd9f4514e32", + "rev": "6f6c45b5134a8ee2e465164811e451dcb5ad86e3", "type": "github" }, "original": { @@ -498,11 +498,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1724479785, - "narHash": "sha256-pP3Azj5d6M5nmG68Fu4JqZmdGt4S4vqI5f8te+E/FTw=", + "lastModified": 1725432240, + "narHash": "sha256-+yj+xgsfZaErbfYM3T+QvEE2hU7UuE+Jf0fJCJ8uPS0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d0e1602ddde669d5beb01aec49d71a51937ed7be", + "rev": "ad416d066ca1222956472ab7d0555a6946746a80", "type": "github" }, "original": { @@ -513,11 +513,11 @@ }, "nur": { "locked": { - "lastModified": 1724775364, - "narHash": "sha256-agN3Oaph2+2DH3+m6Jp4d1ji5s93joohKcV35DfJWQk=", + "lastModified": 1725579951, + "narHash": "sha256-6zrGQcn3SrY0OXabOLgcPGLADoKTvELTAiLczGUAZKg=", "owner": "nix-community", "repo": "NUR", - "rev": "95f1862227c883581265a8801ea28af99635dd97", + "rev": "bd6cc18af8ba7b48f3ac26dfab5adb701dafcd44", "type": "github" }, "original": { @@ -675,11 +675,11 @@ ] }, "locked": { - "lastModified": 1724722238, - "narHash": "sha256-DLtiPBpKBIL4+lxu7H8e6gPZvZ3Rb7D8mMh8OieBURM=", + "lastModified": 1725500139, + "narHash": "sha256-drJz8wZ5RORqtPMnYOMZAQZ43SfrMxMnH5EmQMlVV3A=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "ad07ef4512e976b9537d05b7d2e4a5d7a2965ff7", + "rev": "33839dcc1d5a9243fb5c18ed72b0e200501b31ff", "type": "github" }, "original": { From c3c4c32358749e4a69800f3fe27022f800610486 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 6 Sep 2024 04:15:35 +0200 Subject: [PATCH 0723/1125] Revert "Flake: pin catppuccin-vsc input" This reverts commit c0594967a7870d86dd3ca36fea446227044ac761. --- flake.lock | 1 - flake.nix | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index fef3436..91515f4 100644 --- a/flake.lock +++ b/flake.lock @@ -53,7 +53,6 @@ "original": { "owner": "catppuccin", "repo": "vscode", - "rev": "f0a6271f62ebb868f32c7ad4ecb31104c26f987a", "type": "github" } }, diff --git a/flake.nix b/flake.nix index 79cb2ba..23b8045 100644 --- a/flake.nix +++ b/flake.nix @@ -56,8 +56,7 @@ inputs.home-manager.follows = "home-manager-unstable"; }; - # The maintainer for this retired and the nix build is broken now :( - catppuccin-vsc.url = "github:catppuccin/vscode/f0a6271f62ebb868f32c7ad4ecb31104c26f987a"; + catppuccin-vsc.url = "github:catppuccin/vscode"; vscode-extensions = { url = "github:nix-community/nix-vscode-extensions"; From b442b1e5a9d10afed0ad699c2e2997f3a3bb750c Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 6 Sep 2024 19:32:37 +0200 Subject: [PATCH 0724/1125] Server/minecraft: update motd --- roles/server/minecraft.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix index e8ed396..9ad5971 100644 --- a/roles/server/minecraft.nix +++ b/roles/server/minecraft.nix @@ -20,7 +20,7 @@ package = pkgs.fabricServers.fabric-1_20_1; jvmOpts = "-Xmx8G"; serverProperties = { - motd = "\\u00A7aBigChadGuys \\u00A7lPlus \\u00A7a(w/Cobblemon!) v2.6.1\\u00A7r\\n\\u00A76Have fun!"; + motd = "\\u00A7aBigChadGuys \\u00A7lPlus \\u00A7a(w/Cobblemon!) v2.7.0\\u00A7r\\n\\u00A76Have fun!"; server-port = 25565; level-seed = "-1450714289616987871"; white-list = true; From b81cb471ccff21234ffa78fd5af11dcd06c164a9 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 11 Sep 2024 14:11:37 +0200 Subject: [PATCH 0725/1125] Machines: add initial support for iMac --- flake.nix | 3 + machines/iMac/configuration.nix | 88 ++++++++++++++++++++++++ machines/iMac/default.nix | 6 ++ machines/iMac/hardware-configuration.nix | 63 +++++++++++++++++ 4 files changed, 160 insertions(+) create mode 100644 machines/iMac/configuration.nix create mode 100755 machines/iMac/default.nix create mode 100644 machines/iMac/hardware-configuration.nix diff --git a/flake.nix b/flake.nix index 23b8045..86eae06 100644 --- a/flake.nix +++ b/flake.nix @@ -220,6 +220,9 @@ ./roles/server ]; }; + iMac.modules = [ + ./roles/desktop + ]; }; }; } diff --git a/machines/iMac/configuration.nix b/machines/iMac/configuration.nix new file mode 100644 index 0000000..96cd722 --- /dev/null +++ b/machines/iMac/configuration.nix @@ -0,0 +1,88 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page, on +# https://search.nixos.org/options and in the NixOS manual (`nixos-help`). +{ + config, + lib, + pkgs, + ... +}: { + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + nixpkgs.config.allowUnfree = true; + + networking.hostName = "iMac"; # Define your hostname. + + # Set your time zone. + time.timeZone = "Europe/Madrid"; + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Select internationalisation properties. + # i18n.defaultLocale = "en_US.UTF-8"; + # console = { + # font = "Lat2-Terminus16"; + # keyMap = "us"; + # useXkbConfig = true; # use xkb.options in tty. + # }; + + # Enable the X11 windowing system. + services.xserver.enable = true; + + # Enable the GNOME Desktop Environment. + services.xserver.displayManager.gdm.enable = true; + services.xserver.desktopManager.gnome.enable = true; + + # Configure keymap in X11 + services.xserver.xkb.layout = "es"; + # services.xserver.xkb.options = "eurosign:e,caps:escape"; + + # Enable CUPS to print documents. + # services.printing.enable = true; + + # Enable sound. + hardware.pulseaudio.enable = false; + # OR + # services.pipewire = { + # enable = true; + # pulse.enable = true; + # }; + + # Enable touchpad support (enabled default in most desktopManager). + # services.libinput.enable = true; + + # List packages installed in system profile. To search, run: + # $ nix search wget + # environment.systemPackages = with pkgs; [ + # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + # wget + # ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + # services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + # system.copySystemConfiguration = true; +} diff --git a/machines/iMac/default.nix b/machines/iMac/default.nix new file mode 100755 index 0000000..187a110 --- /dev/null +++ b/machines/iMac/default.nix @@ -0,0 +1,6 @@ +{...}: { + imports = [ + ./configuration.nix + ./hardware-configuration.nix + ]; +} diff --git a/machines/iMac/hardware-configuration.nix b/machines/iMac/hardware-configuration.nix new file mode 100644 index 0000000..f16c257 --- /dev/null +++ b/machines/iMac/hardware-configuration.nix @@ -0,0 +1,63 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + pkgs, + modulesPath, + ... +}: { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "sdhci_pci"]; + boot.initrd.kernelModules = []; + boot.kernelModules = ["kvm-intel" "wl"]; + boot.extraModulePackages = [config.boot.kernelPackages.broadcom_sta]; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/6062dfe3-6e70-4f30-aa45-e81933f116fb"; + fsType = "btrfs"; + options = ["subvol=@" "compress=zstd"]; + }; + + boot.initrd.luks.devices."SSD".device = "/dev/disk/by-uuid/482cd1b5-2a22-42f3-a497-4b4d7006d2e3"; + + fileSystems."/nix" = { + device = "/dev/disk/by-uuid/6062dfe3-6e70-4f30-aa45-e81933f116fb"; + fsType = "btrfs"; + options = ["subvol=@nix" "compress=zstd"]; + }; + + fileSystems."/home" = { + device = "/dev/disk/by-uuid/6062dfe3-6e70-4f30-aa45-e81933f116fb"; + fsType = "btrfs"; + options = ["subvol=@home" "compress=zstd"]; + }; + + fileSystems."/persist" = { + device = "/dev/disk/by-uuid/6062dfe3-6e70-4f30-aa45-e81933f116fb"; + fsType = "btrfs"; + options = ["subvol=@persist" "compress=zstd"]; + }; + + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/0D30-3CEE"; + fsType = "vfat"; + options = ["fmask=0022" "dmask=0022"]; + }; + + swapDevices = []; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp4s0f0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} From 8637b214ac3800ce6d69ae0d0c03e8420f6df5c3 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 11 Sep 2024 14:13:16 +0200 Subject: [PATCH 0726/1125] Flake: add nvd to devshell --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 86eae06..a36868f 100644 --- a/flake.nix +++ b/flake.nix @@ -118,6 +118,7 @@ packages = with nixpkgs.legacyPackages.x86_64-linux; [ agenix.packages.x86_64-linux.default git + nvd nix-output-monitor nix-diff just From 364537049879391311962bbc22fa591d970d83c4 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 12 Sep 2024 09:48:01 +0200 Subject: [PATCH 0727/1125] Flake: update secrets --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 91515f4..c435b3c 100644 --- a/flake.lock +++ b/flake.lock @@ -577,11 +577,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1715453060, - "narHash": "sha256-dhfjA0/x7V3Jug7a52wsELwb5jmNtJvPD0HC8jc2Ky8=", + "lastModified": 1726126607, + "narHash": "sha256-CMd+hkjciWowLKPZJIUVE2EaQzRH2EcLYonfiANilOE=", "ref": "refs/heads/main", - "rev": "08944755d22a7499b0b3fd39d48fdf1dabf4c83f", - "revCount": 19, + "rev": "75ce423d0b8c05927ef3b55d1f7d5e7deaac9aa6", + "revCount": 21, "type": "git", "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets" }, From 551c3e2b1176d0b897f5f12c009c8337a52391dc Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 12 Sep 2024 09:48:20 +0200 Subject: [PATCH 0728/1125] Roles: Add new school role --- flake.nix | 2 ++ roles/school/default.nix | 6 ++++++ roles/school/services/default.nix | 5 +++++ roles/school/services/networkmanager.nix | 19 +++++++++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 roles/school/default.nix create mode 100644 roles/school/services/default.nix create mode 100644 roles/school/services/networkmanager.nix diff --git a/flake.nix b/flake.nix index a36868f..7fa59c5 100644 --- a/flake.nix +++ b/flake.nix @@ -212,6 +212,7 @@ ./roles/desktop ./roles/kde ./roles/gaming + ./roles/school ]; Everest = { stable = true; @@ -223,6 +224,7 @@ }; iMac.modules = [ ./roles/desktop + ./roles/school ]; }; }; diff --git a/roles/school/default.nix b/roles/school/default.nix new file mode 100644 index 0000000..37b6326 --- /dev/null +++ b/roles/school/default.nix @@ -0,0 +1,6 @@ +{...}: { + imports = [ + # ./programs + ./services + ]; +} diff --git a/roles/school/services/default.nix b/roles/school/services/default.nix new file mode 100644 index 0000000..a2cfa5a --- /dev/null +++ b/roles/school/services/default.nix @@ -0,0 +1,5 @@ +{...}: { + imports = [ + ./networkmanager.nix + ]; +} diff --git a/roles/school/services/networkmanager.nix b/roles/school/services/networkmanager.nix new file mode 100644 index 0000000..72fabd4 --- /dev/null +++ b/roles/school/services/networkmanager.nix @@ -0,0 +1,19 @@ +{...}: { + networking.networkmanager.ensureProfiles = { + profiles."school-wifi" = { + connection = { + id = "Progresa"; + type = "wifi"; + }; + wifi = { + mode = "infrastructure"; + ssid = ".Progresa Invitados"; + }; + wifi-security = { + auth-alg = "open"; + key-mgmt = "wpa-psk"; + psk = "$SCHOOL"; + }; + }; + }; +} From 4bd53fc871447a39df73d494fd8330a740783515 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 12 Sep 2024 10:22:53 +0200 Subject: [PATCH 0729/1125] School: install intellij idea --- roles/school/default.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/school/default.nix b/roles/school/default.nix index 37b6326..a8593a0 100644 --- a/roles/school/default.nix +++ b/roles/school/default.nix @@ -1,6 +1,9 @@ -{...}: { +{pkgs, ...}: { imports = [ # ./programs ./services ]; + home-manager.users.toast.home.packages = with pkgs; [ + jetbrains.idea-ultimate + ]; } From ec6a77b76bbc8b7616c49b41c4f24c1797f53bc8 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 12 Sep 2024 11:53:42 +0200 Subject: [PATCH 0730/1125] Roles: add gnome role --- flake.nix | 1 + machines/iMac/configuration.nix | 4 ---- roles/gnome/default.nix | 5 +++++ roles/gnome/gnome.nix | 6 ++++++ 4 files changed, 12 insertions(+), 4 deletions(-) create mode 100755 roles/gnome/default.nix create mode 100644 roles/gnome/gnome.nix diff --git a/flake.nix b/flake.nix index 7fa59c5..fd21dc2 100644 --- a/flake.nix +++ b/flake.nix @@ -224,6 +224,7 @@ }; iMac.modules = [ ./roles/desktop + ./roles/gnome ./roles/school ]; }; diff --git a/machines/iMac/configuration.nix b/machines/iMac/configuration.nix index 96cd722..0d42eb7 100644 --- a/machines/iMac/configuration.nix +++ b/machines/iMac/configuration.nix @@ -33,10 +33,6 @@ # Enable the X11 windowing system. services.xserver.enable = true; - # Enable the GNOME Desktop Environment. - services.xserver.displayManager.gdm.enable = true; - services.xserver.desktopManager.gnome.enable = true; - # Configure keymap in X11 services.xserver.xkb.layout = "es"; # services.xserver.xkb.options = "eurosign:e,caps:escape"; diff --git a/roles/gnome/default.nix b/roles/gnome/default.nix new file mode 100755 index 0000000..7212ffb --- /dev/null +++ b/roles/gnome/default.nix @@ -0,0 +1,5 @@ +{...}: { + imports = [ + ./gnome.nix + ]; +} diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix new file mode 100644 index 0000000..a6c6e1e --- /dev/null +++ b/roles/gnome/gnome.nix @@ -0,0 +1,6 @@ +{...}: { + services.xserver = { + displayManager.gdm.enable = true; + desktopManager.gnome.enable = true; + }; +} From d5235f5bf3a0a77ebe62b6897d97a0f6cf5702b1 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 12 Sep 2024 12:44:10 +0200 Subject: [PATCH 0731/1125] Flake: update secrets --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index c435b3c..4a74ca9 100644 --- a/flake.lock +++ b/flake.lock @@ -577,11 +577,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1726126607, - "narHash": "sha256-CMd+hkjciWowLKPZJIUVE2EaQzRH2EcLYonfiANilOE=", + "lastModified": 1726137390, + "narHash": "sha256-RaTOgscAl0pnAT/1DwyitTfFNwFDPZaqN/vTaqAoCTM=", "ref": "refs/heads/main", - "rev": "75ce423d0b8c05927ef3b55d1f7d5e7deaac9aa6", - "revCount": 21, + "rev": "994526ba9affd6e6d617b1743126a36846530c93", + "revCount": 24, "type": "git", "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets" }, From c018979cb26ddfb2f25d6478cf8e6edc627d5dfa Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 12 Sep 2024 12:56:14 +0200 Subject: [PATCH 0732/1125] Gnome: add extensions --- roles/gnome/gnome.nix | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix index a6c6e1e..fdcd669 100644 --- a/roles/gnome/gnome.nix +++ b/roles/gnome/gnome.nix @@ -1,6 +1,12 @@ -{...}: { - services.xserver = { - displayManager.gdm.enable = true; - desktopManager.gnome.enable = true; +{pkgs, ...}: { + services = { + xserver = { + displayManager.gdm.enable = true; + desktopManager.gnome.enable = true; + }; + gnome.gnome-browser-connector.enable = true; }; + environment.systemPackages = with pkgs.gnomeExtensions; [ + appindicator + ]; } From 09274de08c160173cb6cc52480e3b7046910afe8 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 12 Sep 2024 13:18:11 +0200 Subject: [PATCH 0733/1125] Gnome: enable extensions --- roles/gnome/gnome.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix index fdcd669..8bf5198 100644 --- a/roles/gnome/gnome.nix +++ b/roles/gnome/gnome.nix @@ -6,7 +6,15 @@ }; gnome.gnome-browser-connector.enable = true; }; + + # Extensions environment.systemPackages = with pkgs.gnomeExtensions; [ appindicator ]; + + home-manager.users.toast = { + dconf.settings = { + "org/gnome/shell".enabled-extensions = ["appindicatorsupport@rgcjonas.gmail.com"]; + }; + }; } From 3baa80bf1f1c86ba6c4b569df1ac14a1d8c620db Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 12 Sep 2024 14:17:12 +0200 Subject: [PATCH 0734/1125] Gnome: add dash-to-dock --- roles/gnome/gnome.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix index 8bf5198..5911d3d 100644 --- a/roles/gnome/gnome.nix +++ b/roles/gnome/gnome.nix @@ -10,11 +10,15 @@ # Extensions environment.systemPackages = with pkgs.gnomeExtensions; [ appindicator + dash-to-dock ]; home-manager.users.toast = { dconf.settings = { - "org/gnome/shell".enabled-extensions = ["appindicatorsupport@rgcjonas.gmail.com"]; + "org/gnome/shell".enabled-extensions = [ + "appindicatorsupport@rgcjonas.gmail.com" + "dash-to-dock@micxgx.gmail.com" + ]; }; }; } From ca38820ac67ca4a75d1793c4b7ca8b86487756d6 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 12 Sep 2024 14:18:12 +0200 Subject: [PATCH 0735/1125] Machines/iMac: use the systemd initrd --- machines/iMac/hardware-configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/iMac/hardware-configuration.nix b/machines/iMac/hardware-configuration.nix index f16c257..30fc201 100644 --- a/machines/iMac/hardware-configuration.nix +++ b/machines/iMac/hardware-configuration.nix @@ -14,6 +14,7 @@ boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "sdhci_pci"]; boot.initrd.kernelModules = []; + boot.initrd.systemd.enable = true; boot.kernelModules = ["kvm-intel" "wl"]; boot.extraModulePackages = [config.boot.kernelPackages.broadcom_sta]; From 37823965c389e6918c53e0acb0d889c784b6709e Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 13 Sep 2024 10:55:24 +0200 Subject: [PATCH 0736/1125] Common/syncthing: add iMac --- roles/common/services/syncthing.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index 8d81a53..e181fe7 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -47,12 +47,17 @@ in { name = "Win Max 2"; id = "X2NILRM-ADRBQ23-AFREAZA-62GVFDF-UVMPR4L-KGHMUNY-BJ2C3CQ-RBT43QS"; }; + "imac" = { + name = "iMac"; + id = "KRHGSJF-64UXAE2-CNSDV6L-QAUV2HU-JTSIEIC-KSHLCBU-IFIQGDX-K5UCSQR"; + compression = "always"; + }; }; folders = { "passwords" = { label = "KeePassXC Passwords"; id = "rdyaq-ex659"; - devices = ["phone" "pc" "steamdeck" "server" "surface" "winmax2"]; + devices = ["phone" "pc" "steamdeck" "server" "surface" "winmax2" "imac"]; }; }; }; From ffc7d81f70f14c81e4df948dfc0fbbe117ab5d22 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 13 Sep 2024 11:45:26 +0200 Subject: [PATCH 0737/1125] Machines/iMac: mark /persist as needed for boot --- machines/iMac/hardware-configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/iMac/hardware-configuration.nix b/machines/iMac/hardware-configuration.nix index 30fc201..f0cb363 100644 --- a/machines/iMac/hardware-configuration.nix +++ b/machines/iMac/hardware-configuration.nix @@ -42,6 +42,7 @@ device = "/dev/disk/by-uuid/6062dfe3-6e70-4f30-aa45-e81933f116fb"; fsType = "btrfs"; options = ["subvol=@persist" "compress=zstd"]; + neededForBoot = true; }; fileSystems."/boot" = { From 1cac73de87c480a3f8ea7a642c31fa20ea347434 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 13 Sep 2024 12:38:15 +0200 Subject: [PATCH 0738/1125] Gnome: enable dynamic workspaces --- roles/gnome/gnome.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix index 5911d3d..e9c713a 100644 --- a/roles/gnome/gnome.nix +++ b/roles/gnome/gnome.nix @@ -19,6 +19,7 @@ "appindicatorsupport@rgcjonas.gmail.com" "dash-to-dock@micxgx.gmail.com" ]; + "org/gnome/mutter".dynamic-workspaces = true; }; }; } From eb7b34924a18403e69b02bbd72063fbef38d9050 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 13 Sep 2024 12:38:29 +0200 Subject: [PATCH 0739/1125] School: install android studio --- roles/school/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/school/default.nix b/roles/school/default.nix index a8593a0..a8b6a5e 100644 --- a/roles/school/default.nix +++ b/roles/school/default.nix @@ -5,5 +5,6 @@ ]; home-manager.users.toast.home.packages = with pkgs; [ jetbrains.idea-ultimate + android-studio ]; } From 3a2bc2cda54a4f715adca1bf4bb5be41d2a08645 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 13 Sep 2024 14:01:14 +0200 Subject: [PATCH 0740/1125] Gnome: replace gnome console with blackbox --- roles/gnome/default.nix | 1 + roles/gnome/programs/blackbox.nix | 6 ++++++ roles/gnome/programs/default.nix | 5 +++++ 3 files changed, 12 insertions(+) create mode 100644 roles/gnome/programs/blackbox.nix create mode 100644 roles/gnome/programs/default.nix diff --git a/roles/gnome/default.nix b/roles/gnome/default.nix index 7212ffb..46a06ea 100755 --- a/roles/gnome/default.nix +++ b/roles/gnome/default.nix @@ -1,5 +1,6 @@ {...}: { imports = [ + ./programs ./gnome.nix ]; } diff --git a/roles/gnome/programs/blackbox.nix b/roles/gnome/programs/blackbox.nix new file mode 100644 index 0000000..fa02281 --- /dev/null +++ b/roles/gnome/programs/blackbox.nix @@ -0,0 +1,6 @@ +{pkgs, ...}: { + programs.gnome-terminal.enable = false; + environment.systemPackages = with pkgs; [ + blackbox-terminal + ]; +} diff --git a/roles/gnome/programs/default.nix b/roles/gnome/programs/default.nix new file mode 100644 index 0000000..9f7a57e --- /dev/null +++ b/roles/gnome/programs/default.nix @@ -0,0 +1,5 @@ +{...}: { + imports = [ + ./blackbox.nix + ]; +} From 694104e62c771e6e3c18f96fc481654a750c8187 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 13 Sep 2024 14:14:00 +0200 Subject: [PATCH 0741/1125] Gnome/blackbox: set up preferences --- roles/gnome/programs/blackbox.nix | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/roles/gnome/programs/blackbox.nix b/roles/gnome/programs/blackbox.nix index fa02281..4f23c10 100644 --- a/roles/gnome/programs/blackbox.nix +++ b/roles/gnome/programs/blackbox.nix @@ -3,4 +3,16 @@ environment.systemPackages = with pkgs; [ blackbox-terminal ]; + + home-manager.users.toast = {lib, ...}: { + dconf.settings = with lib.hm.gvariant; { + "com/raggesilver/BlackBox" = { + # Dark mode + style-preference = mkUint32 2; + # Default working directory is home folder + working-directory-mode = mkUint32 1; + custom-font = "JetBrainsMono Nerd Font Mono 12"; + }; + }; + }; } From 6747aba0d3053a8a20ab7af1ab9e924157ee0b4d Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 13 Sep 2024 14:16:09 +0200 Subject: [PATCH 0742/1125] Gnome: enable dark mode --- roles/gnome/gnome.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix index e9c713a..f468f38 100644 --- a/roles/gnome/gnome.nix +++ b/roles/gnome/gnome.nix @@ -19,6 +19,7 @@ "appindicatorsupport@rgcjonas.gmail.com" "dash-to-dock@micxgx.gmail.com" ]; + "org/gnome/desktop/interface".color-scheme = "prefer-dark"; "org/gnome/mutter".dynamic-workspaces = true; }; }; From 32598541f333abb02db6c399e607d6d4d8a31456 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 13 Sep 2024 09:14:38 +0200 Subject: [PATCH 0743/1125] School: add webdev things --- roles/school/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/school/default.nix b/roles/school/default.nix index a8b6a5e..82a522f 100644 --- a/roles/school/default.nix +++ b/roles/school/default.nix @@ -6,5 +6,7 @@ home-manager.users.toast.home.packages = with pkgs; [ jetbrains.idea-ultimate android-studio + jetbrains.webstorm + nodejs ]; } From 2d911bc5911535f86828175c893a22d8a2ebf107 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 16 Sep 2024 09:31:22 +0200 Subject: [PATCH 0744/1125] Flake: update plasma-manager --- flake.lock | 11 +++++------ flake.nix | 2 +- machines/WinMax2/configuration.nix | 2 +- roles/kde/plasma.nix | 4 ++-- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index 4a74ca9..71c6ef2 100644 --- a/flake.lock +++ b/flake.lock @@ -535,16 +535,15 @@ ] }, "locked": { - "lastModified": 1722166680, - "narHash": "sha256-K0p0zAFS+h27yczx3x/J1owUm/oGKz0E9+aPtkSbWZc=", - "owner": "toast003", + "lastModified": 1725914634, + "narHash": "sha256-U74hu15xSb6JNySMOwyJrsh4uk1DVa182bdHLeHdYMc=", + "owner": "nix-community", "repo": "plasma-manager", - "rev": "72da6a5ed6bd3dd05a5cf4b88504717c2430a476", + "rev": "60becd0e994e25b372c8d0500fc944396f6c1085", "type": "github" }, "original": { - "owner": "toast003", - "ref": "libinput", + "owner": "nix-community", "repo": "plasma-manager", "type": "github" } diff --git a/flake.nix b/flake.nix index fd21dc2..15c5343 100644 --- a/flake.nix +++ b/flake.nix @@ -51,7 +51,7 @@ }; plasma-manager = { - url = "github:toast003/plasma-manager/libinput"; + url = "github:nix-community/plasma-manager/"; inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; inputs.home-manager.follows = "home-manager-unstable"; }; diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index a10e624..fbe42b3 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -114,7 +114,7 @@ settings.X-KDE-RunOnDiscreteGpu = "true"; }; }; - programs.plasma.input.keyboard.layouts = lib.mkForce ["us" "es"]; + programs.plasma.input.keyboard.layouts = lib.mkForce [{layout = "us";} {layout = "es";}]; } ]; diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 9646b48..b94b512 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -94,7 +94,7 @@ in { enable = true; workspace = { clickItemTo = "select"; - cursorTheme = "Breeze_Light"; + cursor.theme = "Breeze_Light"; iconTheme = "breeze-dark"; lookAndFeel = "Catppuccin-Mocha-Mauve"; theme = "default"; @@ -112,7 +112,7 @@ in { }; input = { keyboard = { - layouts = ["es"]; + layouts = [{layout = "es";}]; numlockOnStartup = "off"; }; }; From a68714db8d01fb9b9e1913810b7ff5e2403054ea Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 16 Sep 2024 09:59:17 +0200 Subject: [PATCH 0745/1125] Flake: update lock file --- flake.lock | 102 ++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/flake.lock b/flake.lock index 71c6ef2..db5b99f 100644 --- a/flake.lock +++ b/flake.lock @@ -43,11 +43,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1715401925, - "narHash": "sha256-EGZGHCv4OFqzFc9oP82LCKMWfMGsmadOOZ0DZHYSdns=", + "lastModified": 1725822842, + "narHash": "sha256-fOR805OwfINbMFzqSmE8piFAFHM9fE+BDdQQUahqDaQ=", "owner": "catppuccin", "repo": "vscode", - "rev": "f0a6271f62ebb868f32c7ad4ecb31104c26f987a", + "rev": "54316f9afc31c3b5070a242cd3ca47d66ab0e9ac", "type": "github" }, "original": { @@ -218,11 +218,11 @@ ] }, "locked": { - "lastModified": 1725180166, - "narHash": "sha256-fzssXuGR/mCeGbzM1ExaTqDz7QDGta3WA4jJsZyRruo=", + "lastModified": 1726440980, + "narHash": "sha256-ChhIrjtdu5d83W+YDRH+Ec5g1MmM0xk6hJnkz15Ot7M=", "owner": "nix-community", "repo": "home-manager", - "rev": "471e3eb0a114265bcd62d11d58ba8d3421ee68eb", + "rev": "a9c9cc6e50f7cbd2d58ccb1cd46a1e06e9e445ff", "type": "github" }, "original": { @@ -238,11 +238,11 @@ ] }, "locked": { - "lastModified": 1720042825, - "narHash": "sha256-A0vrUB6x82/jvf17qPCpxaM+ulJnD8YZwH9Ci0BsAzE=", + "lastModified": 1725703823, + "narHash": "sha256-tDgM4d8mLK0Hd6YMB2w1BqMto1XBXADOzPEaLl10VI4=", "owner": "nix-community", "repo": "home-manager", - "rev": "e1391fb22e18a36f57e6999c7a9f966dc80ac073", + "rev": "208df2e558b73b6a1f0faec98493cb59a25f62ba", "type": "github" }, "original": { @@ -260,11 +260,11 @@ ] }, "locked": { - "lastModified": 1725559615, - "narHash": "sha256-q24lAKpBubomTHcNKLoVyvnNwVJJyBwcb/Gkhl0LLbs=", + "lastModified": 1726115155, + "narHash": "sha256-VDylz5VX4JD4/TZv6xUJDwuvNdgLRGoOpue1dlZGdIQ=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "45e6dcff8489d75941468462c41fad0948a2c94b", + "rev": "02cf60ce20b6034fc0459e5116cec7016aaff6e4", "type": "github" }, "original": { @@ -276,11 +276,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1725389327, - "narHash": "sha256-UtHpRNYPabG0zW3XB8Dldb68O7n1JLSUczTwg37dcsA=", - "rev": "72589e703258e5cb4de091390291ff84c3a22bf2", + "lastModified": 1726342126, + "narHash": "sha256-SqATcoZoC90sjVXmjBpvXAiksQfTGR08nuZh4h8esY0=", + "rev": "727258241fc0b3c02691b72302d2c3092baca275", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/72589e703258e5cb4de091390291ff84c3a22bf2.tar.gz?rev=72589e703258e5cb4de091390291ff84c3a22bf2" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/727258241fc0b3c02691b72302d2c3092baca275.tar.gz?rev=727258241fc0b3c02691b72302d2c3092baca275" }, "original": { "type": "tarball", @@ -299,11 +299,11 @@ ] }, "locked": { - "lastModified": 1723511483, - "narHash": "sha256-rT/OkVXKkns2YvyF1nFvl+8Gc3sld1c1sXPtGkbqaDY=", - "rev": "cecf70b77539c1a593f60ec9d0305b5e537ab6a9", + "lastModified": 1725836728, + "narHash": "sha256-dCbHCwqrzcHlEsRilMX+KM3IfRV46ieGqDyAD3GgCSs=", + "rev": "353b25f0b6da5ede15206d416345a2ec4195b5c8", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/cecf70b77539c1a593f60ec9d0305b5e537ab6a9.tar.gz?rev=cecf70b77539c1a593f60ec9d0305b5e537ab6a9" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/353b25f0b6da5ede15206d416345a2ec4195b5c8.tar.gz?rev=353b25f0b6da5ede15206d416345a2ec4195b5c8" }, "original": { "type": "tarball", @@ -322,11 +322,11 @@ ] }, "locked": { - "lastModified": 1723511483, - "narHash": "sha256-rT/OkVXKkns2YvyF1nFvl+8Gc3sld1c1sXPtGkbqaDY=", - "rev": "cecf70b77539c1a593f60ec9d0305b5e537ab6a9", + "lastModified": 1725836728, + "narHash": "sha256-dCbHCwqrzcHlEsRilMX+KM3IfRV46ieGqDyAD3GgCSs=", + "rev": "353b25f0b6da5ede15206d416345a2ec4195b5c8", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/cecf70b77539c1a593f60ec9d0305b5e537ab6a9.tar.gz?rev=cecf70b77539c1a593f60ec9d0305b5e537ab6a9" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/353b25f0b6da5ede15206d416345a2ec4195b5c8.tar.gz?rev=353b25f0b6da5ede15206d416345a2ec4195b5c8" }, "original": { "type": "tarball", @@ -373,11 +373,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1724489415, - "narHash": "sha256-ey8vhwY/6XCKoh7fyTn3aIQs7WeYSYtLbYEG87VCzX4=", + "lastModified": 1725690722, + "narHash": "sha256-4qWg9sNh5g1qPGO6d/GV2ktY+eDikkBTbWSg5/iD2nY=", "owner": "nix-community", "repo": "impermanence", - "rev": "c7f5b394397398c023000cf843986ee2571a1fd7", + "rev": "63f4d0443e32b0dd7189001ee1894066765d18a5", "type": "github" }, "original": { @@ -393,11 +393,11 @@ ] }, "locked": { - "lastModified": 1725161148, - "narHash": "sha256-WfAHq3Ag3vLNFfWxKHjFBFdPI6JIideWFJod9mx1eoo=", + "lastModified": 1726449931, + "narHash": "sha256-1AX7MyYzP7sNgZiGF8jwehCCI75y2kBGwACeryJs+yE=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "32058e9138248874773630c846563b1a78ee7a5b", + "rev": "c1b0fa0bec5478185eae2fd3f39b9e906fc83995", "type": "github" }, "original": { @@ -413,11 +413,11 @@ ] }, "locked": { - "lastModified": 1725161148, - "narHash": "sha256-WfAHq3Ag3vLNFfWxKHjFBFdPI6JIideWFJod9mx1eoo=", + "lastModified": 1726449931, + "narHash": "sha256-1AX7MyYzP7sNgZiGF8jwehCCI75y2kBGwACeryJs+yE=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "32058e9138248874773630c846563b1a78ee7a5b", + "rev": "c1b0fa0bec5478185eae2fd3f39b9e906fc83995", "type": "github" }, "original": { @@ -435,11 +435,11 @@ ] }, "locked": { - "lastModified": 1725414050, - "narHash": "sha256-apEL1vA8A8skxokuNoaH1Jfx32XybeQpOo8uJDKPcjY=", + "lastModified": 1726451254, + "narHash": "sha256-ivZjW181daCisxmiR/bDcvmArlEmEtwnHd9B1ueKziY=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "55a9a8faee81d758e09f28ad395f9a4f29273c39", + "rev": "1a2594b6d8d3d87377ab8ea0d7ce1321defbca89", "type": "github" }, "original": { @@ -450,11 +450,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1725477728, - "narHash": "sha256-ahej1VRqKmWbG7gewty+GlrSBEeGY/J2Zy8Nt8+3fdg=", + "lastModified": 1726454253, + "narHash": "sha256-ikQs0QZGmCfk5cJ2N5nTT6oULMvWgxN6ebk4WsOq9io=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "880be1ab837e1e9fe0449dae41ac4d034694d4ce", + "rev": "b9ab7e57c5d1d456cdeef252d345f3bca9c55851", "type": "github" }, "original": { @@ -482,11 +482,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1725407940, - "narHash": "sha256-tiN5Rlg/jiY0tyky+soJZoRzLKbPyIdlQ77xVgREDNM=", + "lastModified": 1726320982, + "narHash": "sha256-RuVXUwcYwaUeks6h3OLrEmg14z9aFXdWppTWPMTwdQw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6f6c45b5134a8ee2e465164811e451dcb5ad86e3", + "rev": "8f7492cce28977fbf8bd12c72af08b1f6c7c3e49", "type": "github" }, "original": { @@ -497,11 +497,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1725432240, - "narHash": "sha256-+yj+xgsfZaErbfYM3T+QvEE2hU7UuE+Jf0fJCJ8uPS0=", + "lastModified": 1726243404, + "narHash": "sha256-sjiGsMh+1cWXb53Tecsm4skyFNag33GPbVgCdfj3n9I=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ad416d066ca1222956472ab7d0555a6946746a80", + "rev": "345c263f2f53a3710abe117f28a5cb86d0ba4059", "type": "github" }, "original": { @@ -512,11 +512,11 @@ }, "nur": { "locked": { - "lastModified": 1725579951, - "narHash": "sha256-6zrGQcn3SrY0OXabOLgcPGLADoKTvELTAiLczGUAZKg=", + "lastModified": 1726468868, + "narHash": "sha256-10IuBfHAVFZWHYYWW6HpIfNMuyoeP0sXFdCbYtkTAq4=", "owner": "nix-community", "repo": "NUR", - "rev": "bd6cc18af8ba7b48f3ac26dfab5adb701dafcd44", + "rev": "267a2199e49fd234553d987c7a21f721bcf2b82d", "type": "github" }, "original": { @@ -673,11 +673,11 @@ ] }, "locked": { - "lastModified": 1725500139, - "narHash": "sha256-drJz8wZ5RORqtPMnYOMZAQZ43SfrMxMnH5EmQMlVV3A=", + "lastModified": 1726451286, + "narHash": "sha256-hrNSd0rh8wZdNxzmFGAoQIQ7boY8OhRlzxb/lZ+5rW8=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "33839dcc1d5a9243fb5c18ed72b0e200501b31ff", + "rev": "156dc845e9e2193710b700aa92e4b5f1e7907cd8", "type": "github" }, "original": { From c084034269cc2276889c22dcda1ef50fe4056138 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 17 Sep 2024 09:45:19 +0200 Subject: [PATCH 0746/1125] School/syncthing: add school things folder --- roles/school/services/default.nix | 1 + roles/school/services/syncthing.nix | 8 ++++++++ roles/server/syncthing.nix | 6 ++++++ 3 files changed, 15 insertions(+) create mode 100644 roles/school/services/syncthing.nix diff --git a/roles/school/services/default.nix b/roles/school/services/default.nix index a2cfa5a..3978b73 100644 --- a/roles/school/services/default.nix +++ b/roles/school/services/default.nix @@ -1,5 +1,6 @@ {...}: { imports = [ ./networkmanager.nix + ./syncthing.nix ]; } diff --git a/roles/school/services/syncthing.nix b/roles/school/services/syncthing.nix new file mode 100644 index 0000000..e1eabd2 --- /dev/null +++ b/roles/school/services/syncthing.nix @@ -0,0 +1,8 @@ +{...}: { + services.syncthing.settings.folders. "school-things" = { + label = "School things"; + id = "btsth-vdu9c"; + devices = ["server" "pc" "winmax2" "imac"]; + path = "~/Documents/School things"; + }; +} diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index f684129..e6409a9 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -26,6 +26,12 @@ devices = ["steamdeck" "server" "pc" "winmax2"]; path = "${config.services.syncthing.dataDir}/pcsx2"; }; + "school-things" = { + label = "School things"; + id = "btsth-vdu9c"; + devices = ["server" "pc" "winmax2" "imac"]; + path = "${config.services.syncthing.dataDir}/school-things"; + }; }; }; systemd.services.syncthing.serviceConfig = { From 8004eba6d9bc0b8bfefb95fdd88ebd6a8b95aff5 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 17 Sep 2024 09:14:24 +0200 Subject: [PATCH 0747/1125] Kde/plasma: let kde configure gtk --- roles/kde/plasma.nix | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index b94b512..a529556 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -51,36 +51,8 @@ in { # Plasma configs should be on all users home-manager.sharedModules = [ - ( - {config, ...}: let - gtk2rc = "${config.xdg.configHome}/gtk-2.0/gtkrc"; - in { - gtk.gtk2.configLocation = gtk2rc; - # Kde has an annoying habit of overwriting the gtk2 config file - home.file."${gtk2rc}".force = true; - } - ) { imports = [flakeSelf.inputs.plasma-manager.homeManagerModules.plasma-manager]; - gtk = { - enable = true; - # Most apps are dark, so a white cursor is easier to spot - cursorTheme = { - package = pkgs.kdePackages.breeze; - name = "Breeze_Light"; - }; - iconTheme = { - package = pkgs.kdePackages.breeze-icons; - name = "breeze-dark"; - }; - theme = { - package = pkgs.kdePackages.breeze-gtk; - name = "Breeze"; - }; - # Gtk2 doesn't have a dark mode, so I just tell gtk 3 and 4 to use the dark variant - gtk3.extraConfig.gtk-application-prefer-dark-theme = true; - gtk4.extraConfig.gtk-application-prefer-dark-theme = true; - }; home.packages = [ ( pkgs.catppuccin-kde.override { From ab1ffbcfdf9f35e7202c775f2728d9c36d1d5f16 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 16 Sep 2024 13:35:50 +0200 Subject: [PATCH 0748/1125] Gnome: add panel workspace scroll extension --- roles/gnome/gnome.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix index f468f38..a84ff77 100644 --- a/roles/gnome/gnome.nix +++ b/roles/gnome/gnome.nix @@ -11,6 +11,7 @@ environment.systemPackages = with pkgs.gnomeExtensions; [ appindicator dash-to-dock + panel-workspace-scroll ]; home-manager.users.toast = { @@ -18,6 +19,7 @@ "org/gnome/shell".enabled-extensions = [ "appindicatorsupport@rgcjonas.gmail.com" "dash-to-dock@micxgx.gmail.com" + "panel-workspace-scroll@polymeilex.github.io" ]; "org/gnome/desktop/interface".color-scheme = "prefer-dark"; "org/gnome/mutter".dynamic-workspaces = true; From 45488dd25c61faa8d92a4036b08cd4562ae8be27 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Sep 2024 12:20:06 +0200 Subject: [PATCH 0749/1125] Run formatter --- roles/gnome/programs/blackbox.nix | 18 +++++++++--------- roles/gnome/programs/default.nix | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/roles/gnome/programs/blackbox.nix b/roles/gnome/programs/blackbox.nix index 4f23c10..2b18dc3 100644 --- a/roles/gnome/programs/blackbox.nix +++ b/roles/gnome/programs/blackbox.nix @@ -1,18 +1,18 @@ {pkgs, ...}: { - programs.gnome-terminal.enable = false; + programs.gnome-terminal.enable = false; environment.systemPackages = with pkgs; [ blackbox-terminal ]; - + home-manager.users.toast = {lib, ...}: { dconf.settings = with lib.hm.gvariant; { - "com/raggesilver/BlackBox" = { - # Dark mode - style-preference = mkUint32 2; - # Default working directory is home folder - working-directory-mode = mkUint32 1; - custom-font = "JetBrainsMono Nerd Font Mono 12"; - }; + "com/raggesilver/BlackBox" = { + # Dark mode + style-preference = mkUint32 2; + # Default working directory is home folder + working-directory-mode = mkUint32 1; + custom-font = "JetBrainsMono Nerd Font Mono 12"; + }; }; }; } diff --git a/roles/gnome/programs/default.nix b/roles/gnome/programs/default.nix index 9f7a57e..03b33d3 100644 --- a/roles/gnome/programs/default.nix +++ b/roles/gnome/programs/default.nix @@ -1,5 +1,5 @@ {...}: { - imports = [ - ./blackbox.nix - ]; + imports = [ + ./blackbox.nix + ]; } From 3730c8f01c4ecefd492e63bc50829c9ffbf72086 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Sep 2024 12:31:07 +0200 Subject: [PATCH 0750/1125] Gnome: change settings --- roles/gnome/gnome.nix | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix index a84ff77..56b9596 100644 --- a/roles/gnome/gnome.nix +++ b/roles/gnome/gnome.nix @@ -21,8 +21,16 @@ "dash-to-dock@micxgx.gmail.com" "panel-workspace-scroll@polymeilex.github.io" ]; - "org/gnome/desktop/interface".color-scheme = "prefer-dark"; - "org/gnome/mutter".dynamic-workspaces = true; + "org/gnome/desktop/interface" = { + color-scheme = "prefer-dark"; + }; + "org/gnome/desktop/wm/preferences" = { + resize-with-right-button = true; + }; + "org/gnome/mutter" = { + dynamic-workspaces = true; + edge-tiling = true; + }; }; }; } From f71901fc082373377949e9dba93f4feb2aaa479e Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Sep 2024 12:32:33 +0200 Subject: [PATCH 0751/1125] School: move android studio into it's own file --- roles/school/default.nix | 3 +-- roles/school/programs/android-studio.nix | 7 +++++++ roles/school/programs/default.nix | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 roles/school/programs/android-studio.nix create mode 100644 roles/school/programs/default.nix diff --git a/roles/school/default.nix b/roles/school/default.nix index 82a522f..9c84cca 100644 --- a/roles/school/default.nix +++ b/roles/school/default.nix @@ -1,11 +1,10 @@ {pkgs, ...}: { imports = [ - # ./programs + ./programs ./services ]; home-manager.users.toast.home.packages = with pkgs; [ jetbrains.idea-ultimate - android-studio jetbrains.webstorm nodejs ]; diff --git a/roles/school/programs/android-studio.nix b/roles/school/programs/android-studio.nix new file mode 100644 index 0000000..b2b0c5f --- /dev/null +++ b/roles/school/programs/android-studio.nix @@ -0,0 +1,7 @@ +{pkgs, ...}: { + programs.adb.enable = true; + users.users.toast.extraGroups = ["adbusers"]; + home-manager.users.toast.home.packages = with pkgs; [ + android-studio + ]; +} diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix new file mode 100644 index 0000000..13edfdf --- /dev/null +++ b/roles/school/programs/default.nix @@ -0,0 +1,5 @@ +{...}: { + imports = [ + ./android-studio.nix + ]; +} From 4872cdfb98ee9580fc6683fa63843f3d9a425913 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Sep 2024 13:18:35 +0200 Subject: [PATCH 0752/1125] Gnome: enable and set up QT --- roles/gnome/gnome.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix index 56b9596..112fdc1 100644 --- a/roles/gnome/gnome.nix +++ b/roles/gnome/gnome.nix @@ -7,6 +7,12 @@ gnome.gnome-browser-connector.enable = true; }; + qt = { + enable = true; + platformTheme = "gnome"; + style = "adwaita-dark"; + }; + # Extensions environment.systemPackages = with pkgs.gnomeExtensions; [ appindicator From f551e271279bf107c87a9b7946c9a55ebb7e5a78 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Sep 2024 14:01:02 +0200 Subject: [PATCH 0753/1125] Flake: package kasane teto cursor theme --- flake.nix | 1 + pkgs/kasane-teto-cursor | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 pkgs/kasane-teto-cursor diff --git a/flake.nix b/flake.nix index 15c5343..f6accae 100644 --- a/flake.nix +++ b/flake.nix @@ -132,6 +132,7 @@ x86_64-linux = with import nixpkgs-unstable-raw {system = "x86_64-linux";}; { anything-sync-daemon = callPackage ./pkgs/anything-sync-daemon {}; discord-krisp-fixer = callPackage ./pkgs/discord-krisp-fixer {}; + kasane-teto-cursor = callPackage ./pkgs/kasane-teto-cursor {}; }; }; nixosConfigurations = let diff --git a/pkgs/kasane-teto-cursor b/pkgs/kasane-teto-cursor new file mode 100644 index 0000000..af93194 --- /dev/null +++ b/pkgs/kasane-teto-cursor @@ -0,0 +1,18 @@ +{ + stdenvNoCC, + fetchzip, +}: +stdenvNoCC.mkDerivation { + name = "kasane-teto-cursors"; + + src = fetchzip { + url = "http://dl.everest.tailscale/Kasane%20Teto%20Cursor%20-%20by%20wobb.zip"; + hash = "sha256-4neZqApkK6hwufLTilUtPmgzyBih7onSdSZ9lezQbIU="; + }; + + dontBuild = true; + installPhase = '' + mkdir -p $out/share/icons + cp -dr --no-preserve='ownership' $src/Linux/Kasane\ Teto $out/share/icons + ''; +} From 1f6c51441a8a332d30b5d8ce67eb822a13a56f96 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Sep 2024 14:09:12 +0200 Subject: [PATCH 0754/1125] Gnome: set up gtk --- roles/gnome/gnome.nix | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix index 112fdc1..5f2b7f0 100644 --- a/roles/gnome/gnome.nix +++ b/roles/gnome/gnome.nix @@ -1,4 +1,4 @@ -{pkgs, ...}: { +{pkgs, flakeSelf, ...}: { services = { xserver = { displayManager.gdm.enable = true; @@ -21,6 +21,17 @@ ]; home-manager.users.toast = { + gtk = { + enable = true; + theme = { + name = "adw-gtk3-dark"; + package = pkgs.adw-gtk3; + }; + cursorTheme = { + name = "Kasane Teto"; + package = flakeSelf.outputs.packages.x86_64-linux.kasane-teto-cursor; + }; + }; dconf.settings = { "org/gnome/shell".enabled-extensions = [ "appindicatorsupport@rgcjonas.gmail.com" From c3ee394131876cde9c6caab426df2e3f7980f408 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 19 Sep 2024 10:34:18 +0200 Subject: [PATCH 0755/1125] Flake: update lock filw --- flake.lock | 96 +++++++++++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/flake.lock b/flake.lock index db5b99f..6401e30 100644 --- a/flake.lock +++ b/flake.lock @@ -93,11 +93,11 @@ "systems": "systems_2" }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", "type": "github" }, "original": { @@ -111,11 +111,11 @@ "systems": "systems_3" }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", "type": "github" }, "original": { @@ -218,11 +218,11 @@ ] }, "locked": { - "lastModified": 1726440980, - "narHash": "sha256-ChhIrjtdu5d83W+YDRH+Ec5g1MmM0xk6hJnkz15Ot7M=", + "lastModified": 1726611255, + "narHash": "sha256-/bxaYvIK6/d3zqpW26QFS0rqfd0cO4qreSNWvYLTl/w=", "owner": "nix-community", "repo": "home-manager", - "rev": "a9c9cc6e50f7cbd2d58ccb1cd46a1e06e9e445ff", + "rev": "d2493de5cd1da06b6a4c3e97f4e7d5dd791df457", "type": "github" }, "original": { @@ -238,11 +238,11 @@ ] }, "locked": { - "lastModified": 1725703823, - "narHash": "sha256-tDgM4d8mLK0Hd6YMB2w1BqMto1XBXADOzPEaLl10VI4=", + "lastModified": 1726592409, + "narHash": "sha256-2Y6CDvD/BD43WLS77PHu6dUHbdUfFhuzkY8oJAecD/U=", "owner": "nix-community", "repo": "home-manager", - "rev": "208df2e558b73b6a1f0faec98493cb59a25f62ba", + "rev": "2ab00f89dd3ecf8012f5090e6d7ca1a7ea30f594", "type": "github" }, "original": { @@ -260,11 +260,11 @@ ] }, "locked": { - "lastModified": 1726115155, - "narHash": "sha256-VDylz5VX4JD4/TZv6xUJDwuvNdgLRGoOpue1dlZGdIQ=", + "lastModified": 1726630303, + "narHash": "sha256-6xF6AqSGl/fNXeliuXAIOnEb4tMTUXOl1Yr1v4hURxg=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "02cf60ce20b6034fc0459e5116cec7016aaff6e4", + "rev": "f7a1bb0db21db79dfbee6950220e2816330a08b1", "type": "github" }, "original": { @@ -276,11 +276,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1726342126, - "narHash": "sha256-SqATcoZoC90sjVXmjBpvXAiksQfTGR08nuZh4h8esY0=", - "rev": "727258241fc0b3c02691b72302d2c3092baca275", + "lastModified": 1726702585, + "narHash": "sha256-oBo2DRCazfJV/qUTgUGcS9s694sHNsIs5U09cOszeAc=", + "rev": "79246a37337c5df2224dbc2461c722e1e678f6de", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/727258241fc0b3c02691b72302d2c3092baca275.tar.gz?rev=727258241fc0b3c02691b72302d2c3092baca275" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/79246a37337c5df2224dbc2461c722e1e678f6de.tar.gz?rev=79246a37337c5df2224dbc2461c722e1e678f6de" }, "original": { "type": "tarball", @@ -299,11 +299,11 @@ ] }, "locked": { - "lastModified": 1725836728, - "narHash": "sha256-dCbHCwqrzcHlEsRilMX+KM3IfRV46ieGqDyAD3GgCSs=", - "rev": "353b25f0b6da5ede15206d416345a2ec4195b5c8", + "lastModified": 1726631249, + "narHash": "sha256-b2rMO8+jKjY55d8uynX7FjV4NIPu/WzPux0kWOAzwoo=", + "rev": "b0e6f359500d66670cc16f521e4f62d6a0a4864e", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/353b25f0b6da5ede15206d416345a2ec4195b5c8.tar.gz?rev=353b25f0b6da5ede15206d416345a2ec4195b5c8" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/b0e6f359500d66670cc16f521e4f62d6a0a4864e.tar.gz?rev=b0e6f359500d66670cc16f521e4f62d6a0a4864e" }, "original": { "type": "tarball", @@ -322,11 +322,11 @@ ] }, "locked": { - "lastModified": 1725836728, - "narHash": "sha256-dCbHCwqrzcHlEsRilMX+KM3IfRV46ieGqDyAD3GgCSs=", - "rev": "353b25f0b6da5ede15206d416345a2ec4195b5c8", + "lastModified": 1726631249, + "narHash": "sha256-b2rMO8+jKjY55d8uynX7FjV4NIPu/WzPux0kWOAzwoo=", + "rev": "b0e6f359500d66670cc16f521e4f62d6a0a4864e", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/353b25f0b6da5ede15206d416345a2ec4195b5c8.tar.gz?rev=353b25f0b6da5ede15206d416345a2ec4195b5c8" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/b0e6f359500d66670cc16f521e4f62d6a0a4864e.tar.gz?rev=b0e6f359500d66670cc16f521e4f62d6a0a4864e" }, "original": { "type": "tarball", @@ -435,11 +435,11 @@ ] }, "locked": { - "lastModified": 1726451254, - "narHash": "sha256-ivZjW181daCisxmiR/bDcvmArlEmEtwnHd9B1ueKziY=", + "lastModified": 1726710193, + "narHash": "sha256-/C1qrD2SMm+K8IKz9kzudJti4q8OBDzkgq7qWDi5zcs=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "1a2594b6d8d3d87377ab8ea0d7ce1321defbca89", + "rev": "bc2a161add4b51580a2bde1f383b5c709d790030", "type": "github" }, "original": { @@ -450,11 +450,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1726454253, - "narHash": "sha256-ikQs0QZGmCfk5cJ2N5nTT6oULMvWgxN6ebk4WsOq9io=", + "lastModified": 1726724509, + "narHash": "sha256-sVeAM1tgVi52S1e29fFBTPUAFSzgQwgLon3CrztXGm8=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "b9ab7e57c5d1d456cdeef252d345f3bca9c55851", + "rev": "10d5e0ecc32984c1bf1a9a46586be3451c42fd94", "type": "github" }, "original": { @@ -482,11 +482,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1726320982, - "narHash": "sha256-RuVXUwcYwaUeks6h3OLrEmg14z9aFXdWppTWPMTwdQw=", + "lastModified": 1726447378, + "narHash": "sha256-2yV8nmYE1p9lfmLHhOCbYwQC/W8WYfGQABoGzJOb1JQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8f7492cce28977fbf8bd12c72af08b1f6c7c3e49", + "rev": "086b448a5d54fd117f4dc2dee55c9f0ff461bdc1", "type": "github" }, "original": { @@ -497,11 +497,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1726243404, - "narHash": "sha256-sjiGsMh+1cWXb53Tecsm4skyFNag33GPbVgCdfj3n9I=", + "lastModified": 1726463316, + "narHash": "sha256-gI9kkaH0ZjakJOKrdjaI/VbaMEo9qBbSUl93DnU7f4c=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "345c263f2f53a3710abe117f28a5cb86d0ba4059", + "rev": "99dc8785f6a0adac95f5e2ab05cc2e1bf666d172", "type": "github" }, "original": { @@ -512,11 +512,11 @@ }, "nur": { "locked": { - "lastModified": 1726468868, - "narHash": "sha256-10IuBfHAVFZWHYYWW6HpIfNMuyoeP0sXFdCbYtkTAq4=", + "lastModified": 1726727859, + "narHash": "sha256-ddZx7sY0T5TB+4qzbK6F4BcgPpSdtSWox4IYRyw76K4=", "owner": "nix-community", "repo": "NUR", - "rev": "267a2199e49fd234553d987c7a21f721bcf2b82d", + "rev": "a4da7b6995a1e35d09b98fd5a9f486f06968281c", "type": "github" }, "original": { @@ -535,11 +535,11 @@ ] }, "locked": { - "lastModified": 1725914634, - "narHash": "sha256-U74hu15xSb6JNySMOwyJrsh4uk1DVa182bdHLeHdYMc=", + "lastModified": 1726509788, + "narHash": "sha256-PmCmO8NDKzwHrTp9Ox/rcLiCYivqIpZlnLk8wZRjv2I=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "60becd0e994e25b372c8d0500fc944396f6c1085", + "rev": "5a0c70a007837e2db01e0bb68971792e8653d32c", "type": "github" }, "original": { @@ -673,11 +673,11 @@ ] }, "locked": { - "lastModified": 1726451286, - "narHash": "sha256-hrNSd0rh8wZdNxzmFGAoQIQ7boY8OhRlzxb/lZ+5rW8=", + "lastModified": 1726710255, + "narHash": "sha256-F7IpHzKsV9lzFhSZ5/8jMrAPNTLDAloazYlulnTyG9o=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "156dc845e9e2193710b700aa92e4b5f1e7907cd8", + "rev": "e7740781e76ff6495f6a0c8c69ddc2d3f62c41c0", "type": "github" }, "original": { From b061708ce70512a1b30458566b880bf565be48c3 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 19 Sep 2024 12:48:34 +0200 Subject: [PATCH 0756/1125] Gnome: install firefox gnome theme --- roles/gnome/programs/default.nix | 1 + roles/gnome/programs/firefox.nix | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 roles/gnome/programs/firefox.nix diff --git a/roles/gnome/programs/default.nix b/roles/gnome/programs/default.nix index 03b33d3..a89b8a2 100644 --- a/roles/gnome/programs/default.nix +++ b/roles/gnome/programs/default.nix @@ -1,5 +1,6 @@ {...}: { imports = [ ./blackbox.nix + ./firefox.nix ]; } diff --git a/roles/gnome/programs/firefox.nix b/roles/gnome/programs/firefox.nix new file mode 100644 index 0000000..c2460fa --- /dev/null +++ b/roles/gnome/programs/firefox.nix @@ -0,0 +1,22 @@ +{pkgs, ...}: let + firefox-gnome-theme = pkgs.fetchFromGitHub { + owner = "rafaelmardojai"; + repo = "firefox-gnome-theme"; + rev = "v129"; + hash = "sha256-MOE9NeU2i6Ws1GhGmppMnjOHkNLl2MQMJmGhaMzdoJM="; + }; + profile-location = ".mozilla/firefox/jdnxpg97.temp"; +in { + home-manager.users.toast = { + programs.firefox = { + enableGnomeExtensions = true; + }; + home.file."${profile-location}/chrome".source = firefox-gnome-theme; + }; + programs.firefox = { + autoConfig = '' + lockPref("toolkit.legacyUserProfileCustomizations.stylesheets",true); + lockPref("svg.context-properties.content.enabled",true); + ''; + }; +} From 1ba89c9548f30f44d2ca2beb0ba7f2a6f533ebef Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 20 Sep 2024 09:18:04 +0200 Subject: [PATCH 0757/1125] Machines/WinMax2: reboot on panic --- machines/WinMax2/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index fbe42b3..b367dc7 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -40,7 +40,7 @@ environment.sessionVariables."KWIN_DRM_NO_DIRECT_SCANOUT" = 1; # Sleep fixes - boot.kernelParams = ["rtc_cmos.use_acpi_alarm=1"]; + boot.kernelParams = ["rtc_cmos.use_acpi_alarm=1" "panic=5"]; services.udev.extraRules = '' ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="GXTP7385:00", ATTR{power/wakeup}="disabled" ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="disabled" From 17e929fe3ef4ece7974a3a5d0577dd32efa3a1c9 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 20 Sep 2024 10:09:55 +0200 Subject: [PATCH 0758/1125] Common: enable home-manager manual --- roles/common/configuration.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 047563e..3f1e6bf 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -131,6 +131,10 @@ catppuccin.flavor = osConfig.catppuccin.flavor; catppuccin.accent = osConfig.catppuccin.accent; home.stateVersion = "24.05"; + manual = { + manpages.enable = true; + html.enable = true; + }; xdg = { enable = true; userDirs = { From 565aae0710bc75a15ff53df07dbb336dd0ff9776 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 19 Sep 2024 12:49:28 +0200 Subject: [PATCH 0759/1125] Gnome: run formatter --- roles/gnome/gnome.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix index 5f2b7f0..d37d550 100644 --- a/roles/gnome/gnome.nix +++ b/roles/gnome/gnome.nix @@ -1,4 +1,8 @@ -{pkgs, flakeSelf, ...}: { +{ + pkgs, + flakeSelf, + ... +}: { services = { xserver = { displayManager.gdm.enable = true; From 1ed98c54b5ed92ed933560cb0f3cbd3163261e70 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 19 Sep 2024 13:57:19 +0200 Subject: [PATCH 0760/1125] Machines/iMac: enable backlight control --- machines/iMac/hardware-configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/iMac/hardware-configuration.nix b/machines/iMac/hardware-configuration.nix index f0cb363..b3dec1d 100644 --- a/machines/iMac/hardware-configuration.nix +++ b/machines/iMac/hardware-configuration.nix @@ -16,6 +16,7 @@ boot.initrd.kernelModules = []; boot.initrd.systemd.enable = true; boot.kernelModules = ["kvm-intel" "wl"]; + boot.kernelParams = ["acpi_backlight=video"]; boot.extraModulePackages = [config.boot.kernelPackages.broadcom_sta]; fileSystems."/" = { From 7d04111f4abc9b30eaf4d638ad3e066182994164 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 20 Sep 2024 12:10:17 +0200 Subject: [PATCH 0761/1125] Machines/iMac: set up gpu frequency --- machines/iMac/hardware-configuration.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/machines/iMac/hardware-configuration.nix b/machines/iMac/hardware-configuration.nix index b3dec1d..89570f6 100644 --- a/machines/iMac/hardware-configuration.nix +++ b/machines/iMac/hardware-configuration.nix @@ -16,7 +16,10 @@ boot.initrd.kernelModules = []; boot.initrd.systemd.enable = true; boot.kernelModules = ["kvm-intel" "wl"]; - boot.kernelParams = ["acpi_backlight=video"]; + boot.kernelParams = [ + "acpi_backlight=video" + "nouveau.config=NvClkMode=15" + ]; boot.extraModulePackages = [config.boot.kernelPackages.broadcom_sta]; fileSystems."/" = { From 428fd3f9f0c0f69e1dc1c24347839f9eaf31fdc6 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 20 Sep 2024 12:29:21 +0200 Subject: [PATCH 0762/1125] Gnome: change favorite apps --- roles/gnome/gnome.nix | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix index d37d550..492f70c 100644 --- a/roles/gnome/gnome.nix +++ b/roles/gnome/gnome.nix @@ -37,11 +37,14 @@ }; }; dconf.settings = { - "org/gnome/shell".enabled-extensions = [ - "appindicatorsupport@rgcjonas.gmail.com" - "dash-to-dock@micxgx.gmail.com" - "panel-workspace-scroll@polymeilex.github.io" - ]; + "org/gnome/shell" = { + enabled-extensions = [ + "appindicatorsupport@rgcjonas.gmail.com" + "dash-to-dock@micxgx.gmail.com" + "panel-workspace-scroll@polymeilex.github.io" + ]; + favorite-apps = ["firefox.desktop" "com.raggesilver.BlackBox.desktop" "org.gnome.Nautilus.desktop" "android-studio.desktop"]; + }; "org/gnome/desktop/interface" = { color-scheme = "prefer-dark"; }; From 99bce3fd149ba0cdce960300aea2a99c8e9a9df3 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 20 Sep 2024 12:48:59 +0200 Subject: [PATCH 0763/1125] Gnome/programs: install dconf editor and gnome tweaks --- roles/gnome/programs/default.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/roles/gnome/programs/default.nix b/roles/gnome/programs/default.nix index a89b8a2..a7b201a 100644 --- a/roles/gnome/programs/default.nix +++ b/roles/gnome/programs/default.nix @@ -1,6 +1,10 @@ -{...}: { +{pkgs, ...}: { imports = [ ./blackbox.nix ./firefox.nix ]; + environment.systemPackages = with pkgs; [ + gnome-tweaks + dconf-editor + ]; } From 12f190bbaab867464d837350ae1758f78a9e4dfa Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 20 Sep 2024 13:15:20 +0200 Subject: [PATCH 0764/1125] Gnome/nautilus: install and change settings --- roles/gnome/programs/default.nix | 1 + roles/gnome/programs/nautilus.nix | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 roles/gnome/programs/nautilus.nix diff --git a/roles/gnome/programs/default.nix b/roles/gnome/programs/default.nix index a7b201a..88c2cfb 100644 --- a/roles/gnome/programs/default.nix +++ b/roles/gnome/programs/default.nix @@ -2,6 +2,7 @@ imports = [ ./blackbox.nix ./firefox.nix + ./nautilus.nix ]; environment.systemPackages = with pkgs; [ gnome-tweaks diff --git a/roles/gnome/programs/nautilus.nix b/roles/gnome/programs/nautilus.nix new file mode 100644 index 0000000..d01fd83 --- /dev/null +++ b/roles/gnome/programs/nautilus.nix @@ -0,0 +1,15 @@ +{pkgs, ...}: { + environment.systemPackages = with pkgs; [ + nautilus-python + ]; + + home-manager.users.toast = { + dconf.settings = { + "org/gnome/preferences" = { + date-time-format = "detailed"; + show-create-link = true; + show-delete-permanently = true; + }; + }; + }; +} From ef324a47db21865eb6da49b99cf88c56a036d23f Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 20 Sep 2024 13:18:10 +0200 Subject: [PATCH 0765/1125] Gnome/blackbox: remove gnome console and add nautilus integration --- roles/gnome/programs/blackbox.nix | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/roles/gnome/programs/blackbox.nix b/roles/gnome/programs/blackbox.nix index 2b18dc3..c4f5c4d 100644 --- a/roles/gnome/programs/blackbox.nix +++ b/roles/gnome/programs/blackbox.nix @@ -1,8 +1,12 @@ {pkgs, ...}: { programs.gnome-terminal.enable = false; - environment.systemPackages = with pkgs; [ - blackbox-terminal - ]; + environment = with pkgs; { + gnome.excludePackages = [gnome-console]; + systemPackages = [ + blackbox-terminal + nautilus-open-in-blackbox + ]; + }; home-manager.users.toast = {lib, ...}: { dconf.settings = with lib.hm.gvariant; { From e497436f050134f90de83f13ecc35ef5a0c68655 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 20 Sep 2024 14:01:16 +0200 Subject: [PATCH 0766/1125] Gnome/blackbox: set up catpuccin theme --- roles/gnome/programs/blackbox.nix | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/roles/gnome/programs/blackbox.nix b/roles/gnome/programs/blackbox.nix index c4f5c4d..692aaad 100644 --- a/roles/gnome/programs/blackbox.nix +++ b/roles/gnome/programs/blackbox.nix @@ -8,11 +8,22 @@ ]; }; - home-manager.users.toast = {lib, ...}: { + home-manager.users.toast = { + lib, + pkgs, + ... + }: { + home.file.".local/share/blackbox/schemes".source = + (pkgs.fetchgit { + url = "https://github.com/catppuccin/tilix.git"; + hash = "sha256-jWnxEtoqqqitHsaDErQNNYjv8DBcrJD0XeIKNopbO3c="; + }) + + /themes; dconf.settings = with lib.hm.gvariant; { "com/raggesilver/BlackBox" = { # Dark mode style-preference = mkUint32 2; + theme-dark = "Catppuccin Mocha"; # Default working directory is home folder working-directory-mode = mkUint32 1; custom-font = "JetBrainsMono Nerd Font Mono 12"; From d0194b301afa89c1f4f2e94a22ebf7270179141e Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 22 Sep 2024 16:49:51 +0200 Subject: [PATCH 0767/1125] Server/minecraft: update motd --- roles/server/minecraft.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix index 9ad5971..1db04a1 100644 --- a/roles/server/minecraft.nix +++ b/roles/server/minecraft.nix @@ -20,7 +20,7 @@ package = pkgs.fabricServers.fabric-1_20_1; jvmOpts = "-Xmx8G"; serverProperties = { - motd = "\\u00A7aBigChadGuys \\u00A7lPlus \\u00A7a(w/Cobblemon!) v2.7.0\\u00A7r\\n\\u00A76Have fun!"; + motd = "\\u00A7aBigChadGuys \\u00A7lPlus \\u00A7a(w/Cobblemon!) v2.8.1\\u00A7r\\n\\u00A76Have fun!"; server-port = 25565; level-seed = "-1450714289616987871"; white-list = true; From 4dbe60e3147d70269760d556fd31d7addfd75641 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 23 Sep 2024 12:10:19 +0200 Subject: [PATCH 0768/1125] Gnome: manage keyring with home-manager, disable ssh --- roles/gnome/gnome.nix | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix index 492f70c..ed86051 100644 --- a/roles/gnome/gnome.nix +++ b/roles/gnome/gnome.nix @@ -1,5 +1,6 @@ { pkgs, + lib, flakeSelf, ... }: { @@ -17,6 +18,15 @@ style = "adwaita-dark"; }; + # Manage this with home-manager + services.gnome.gnome-keyring.enable = lib.mkForce false; + + home-manager.sharedModules = [ + { + services.gnome-keyring.enable = true; + } + ]; + # Extensions environment.systemPackages = with pkgs.gnomeExtensions; [ appindicator @@ -36,6 +46,8 @@ package = flakeSelf.outputs.packages.x86_64-linux.kasane-teto-cursor; }; }; + services.gnome-keyring.components = ["pkcs11" "secrets"]; + dconf.settings = { "org/gnome/shell" = { enabled-extensions = [ From cae6f707afd684c22d01ff32ccb5866f2b6fa683 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 2 Oct 2024 09:30:51 +0200 Subject: [PATCH 0769/1125] Desktop: enable user qmk access --- roles/desktop/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index 2f87103..9f9db1c 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -18,5 +18,7 @@ (pkgs.nerdfonts.override {fonts = ["Hack" "JetBrainsMono"];}) ]; + hardware.keyboard.qmk.enable = true; + boot.plymouth.enable = true; } From bd866ba7a29f759718d1ddd1e14c29de686a7b7e Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 2 Oct 2024 14:00:02 +0200 Subject: [PATCH 0770/1125] Flake: update lock file --- flake.lock | 108 ++++++++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/flake.lock b/flake.lock index 6401e30..d297db4 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1725509983, - "narHash": "sha256-NHCgHVqumPraFJnLrkanoLDuhOoUHUvRhvp/RIHJR+A=", + "lastModified": 1726952185, + "narHash": "sha256-l/HbsQjJMT6tlf8KCooFYi3J6wjIips3n6/aWAoLY4g=", "owner": "catppuccin", "repo": "nix", - "rev": "45745fe5960acaefef2b60f3455bcac6a0ca6bc9", + "rev": "630b559cc1cb4c0bdd525af506935323e4ccd5d1", "type": "github" }, "original": { @@ -218,11 +218,11 @@ ] }, "locked": { - "lastModified": 1726611255, - "narHash": "sha256-/bxaYvIK6/d3zqpW26QFS0rqfd0cO4qreSNWvYLTl/w=", + "lastModified": 1727817100, + "narHash": "sha256-dlyV9/eiWkm/Y/t2+k4CFZ29tBvCANmJogEYaHeAOTw=", "owner": "nix-community", "repo": "home-manager", - "rev": "d2493de5cd1da06b6a4c3e97f4e7d5dd791df457", + "rev": "437ec62009fa8ceb684eb447d455ffba25911cf9", "type": "github" }, "original": { @@ -238,11 +238,11 @@ ] }, "locked": { - "lastModified": 1726592409, - "narHash": "sha256-2Y6CDvD/BD43WLS77PHu6dUHbdUfFhuzkY8oJAecD/U=", + "lastModified": 1726989464, + "narHash": "sha256-Vl+WVTJwutXkimwGprnEtXc/s/s8sMuXzqXaspIGlwM=", "owner": "nix-community", "repo": "home-manager", - "rev": "2ab00f89dd3ecf8012f5090e6d7ca1a7ea30f594", + "rev": "2f23fa308a7c067e52dfcc30a0758f47043ec176", "type": "github" }, "original": { @@ -260,11 +260,11 @@ ] }, "locked": { - "lastModified": 1726630303, - "narHash": "sha256-6xF6AqSGl/fNXeliuXAIOnEb4tMTUXOl1Yr1v4hURxg=", + "lastModified": 1727760934, + "narHash": "sha256-xntX46lRTMQH383wCCi3d8xmjUnZ2jIoz0wn3aQQS1I=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "f7a1bb0db21db79dfbee6950220e2816330a08b1", + "rev": "477d11fc3f1352fb667177bb4712f5f976aaa7d9", "type": "github" }, "original": { @@ -276,11 +276,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1726702585, - "narHash": "sha256-oBo2DRCazfJV/qUTgUGcS9s694sHNsIs5U09cOszeAc=", - "rev": "79246a37337c5df2224dbc2461c722e1e678f6de", + "lastModified": 1727783747, + "narHash": "sha256-fLiDo55WLgikMaaZcFEpkCkL4fQiV7RNEjRn+LxiYao=", + "rev": "775292766025380d04004e42fefbdb8ca40b3fa3", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/79246a37337c5df2224dbc2461c722e1e678f6de.tar.gz?rev=79246a37337c5df2224dbc2461c722e1e678f6de" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/775292766025380d04004e42fefbdb8ca40b3fa3.tar.gz?rev=775292766025380d04004e42fefbdb8ca40b3fa3" }, "original": { "type": "tarball", @@ -299,11 +299,11 @@ ] }, "locked": { - "lastModified": 1726631249, - "narHash": "sha256-b2rMO8+jKjY55d8uynX7FjV4NIPu/WzPux0kWOAzwoo=", - "rev": "b0e6f359500d66670cc16f521e4f62d6a0a4864e", + "lastModified": 1727752861, + "narHash": "sha256-jowmo2aEzrEpPSM96IWtajuogdJm7DjAWxFTEb7Ct0s=", + "rev": "fd186f535a4ac7ae35d98c1dd5d79f0a81b7976d", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/b0e6f359500d66670cc16f521e4f62d6a0a4864e.tar.gz?rev=b0e6f359500d66670cc16f521e4f62d6a0a4864e" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/fd186f535a4ac7ae35d98c1dd5d79f0a81b7976d.tar.gz?rev=fd186f535a4ac7ae35d98c1dd5d79f0a81b7976d" }, "original": { "type": "tarball", @@ -322,11 +322,11 @@ ] }, "locked": { - "lastModified": 1726631249, - "narHash": "sha256-b2rMO8+jKjY55d8uynX7FjV4NIPu/WzPux0kWOAzwoo=", - "rev": "b0e6f359500d66670cc16f521e4f62d6a0a4864e", + "lastModified": 1727752861, + "narHash": "sha256-jowmo2aEzrEpPSM96IWtajuogdJm7DjAWxFTEb7Ct0s=", + "rev": "fd186f535a4ac7ae35d98c1dd5d79f0a81b7976d", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/b0e6f359500d66670cc16f521e4f62d6a0a4864e.tar.gz?rev=b0e6f359500d66670cc16f521e4f62d6a0a4864e" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/fd186f535a4ac7ae35d98c1dd5d79f0a81b7976d.tar.gz?rev=fd186f535a4ac7ae35d98c1dd5d79f0a81b7976d" }, "original": { "type": "tarball", @@ -373,11 +373,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1725690722, - "narHash": "sha256-4qWg9sNh5g1qPGO6d/GV2ktY+eDikkBTbWSg5/iD2nY=", + "lastModified": 1727649413, + "narHash": "sha256-FA53of86DjFdeQzRDVtvgWF9o52rWK70VHGx0Y8fElQ=", "owner": "nix-community", "repo": "impermanence", - "rev": "63f4d0443e32b0dd7189001ee1894066765d18a5", + "rev": "d0b38e550039a72aff896ee65b0918e975e6d48e", "type": "github" }, "original": { @@ -393,11 +393,11 @@ ] }, "locked": { - "lastModified": 1726449931, - "narHash": "sha256-1AX7MyYzP7sNgZiGF8jwehCCI75y2kBGwACeryJs+yE=", + "lastModified": 1727658919, + "narHash": "sha256-YAePt2GldkkRJ08LvZNHcuS6shIVStj+K+1DZN3gbnM=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "c1b0fa0bec5478185eae2fd3f39b9e906fc83995", + "rev": "f9fdf8285690a351e8998f1e703ebdf9cdf51dee", "type": "github" }, "original": { @@ -413,11 +413,11 @@ ] }, "locked": { - "lastModified": 1726449931, - "narHash": "sha256-1AX7MyYzP7sNgZiGF8jwehCCI75y2kBGwACeryJs+yE=", + "lastModified": 1727658919, + "narHash": "sha256-YAePt2GldkkRJ08LvZNHcuS6shIVStj+K+1DZN3gbnM=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "c1b0fa0bec5478185eae2fd3f39b9e906fc83995", + "rev": "f9fdf8285690a351e8998f1e703ebdf9cdf51dee", "type": "github" }, "original": { @@ -435,11 +435,11 @@ ] }, "locked": { - "lastModified": 1726710193, - "narHash": "sha256-/C1qrD2SMm+K8IKz9kzudJti4q8OBDzkgq7qWDi5zcs=", + "lastModified": 1727747697, + "narHash": "sha256-bNZ4ykMpxyTLrPsctiDwe5d69vafvIbNTbzbWfd2CH4=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "bc2a161add4b51580a2bde1f383b5c709d790030", + "rev": "30af58cedcc444da772a73286e16287f94a9fef1", "type": "github" }, "original": { @@ -450,11 +450,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1726724509, - "narHash": "sha256-sVeAM1tgVi52S1e29fFBTPUAFSzgQwgLon3CrztXGm8=", + "lastModified": 1727665282, + "narHash": "sha256-oKtfbQB1MBypqIyzkC8QCQcVGOa1soaXaGgcBIoh14o=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "10d5e0ecc32984c1bf1a9a46586be3451c42fd94", + "rev": "11c43c830e533dad1be527ecce379fcf994fbbb5", "type": "github" }, "original": { @@ -482,11 +482,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1726447378, - "narHash": "sha256-2yV8nmYE1p9lfmLHhOCbYwQC/W8WYfGQABoGzJOb1JQ=", + "lastModified": 1727672256, + "narHash": "sha256-9/79hjQc9+xyH+QxeMcRsA6hDyw6Z9Eo1/oxjvwirLk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "086b448a5d54fd117f4dc2dee55c9f0ff461bdc1", + "rev": "1719f27dd95fd4206afb9cec9f415b539978827e", "type": "github" }, "original": { @@ -497,11 +497,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1726463316, - "narHash": "sha256-gI9kkaH0ZjakJOKrdjaI/VbaMEo9qBbSUl93DnU7f4c=", + "lastModified": 1727634051, + "narHash": "sha256-S5kVU7U82LfpEukbn/ihcyNt2+EvG7Z5unsKW9H/yFA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "99dc8785f6a0adac95f5e2ab05cc2e1bf666d172", + "rev": "06cf0e1da4208d3766d898b7fdab6513366d45b9", "type": "github" }, "original": { @@ -512,11 +512,11 @@ }, "nur": { "locked": { - "lastModified": 1726727859, - "narHash": "sha256-ddZx7sY0T5TB+4qzbK6F4BcgPpSdtSWox4IYRyw76K4=", + "lastModified": 1727862373, + "narHash": "sha256-viH52KlflVeTo5++dEKvTjCQBoui5Shi6LIo0l6iEHI=", "owner": "nix-community", "repo": "NUR", - "rev": "a4da7b6995a1e35d09b98fd5a9f486f06968281c", + "rev": "5cf5605cb2630639a716450161e0bba47bd439f4", "type": "github" }, "original": { @@ -535,11 +535,11 @@ ] }, "locked": { - "lastModified": 1726509788, - "narHash": "sha256-PmCmO8NDKzwHrTp9Ox/rcLiCYivqIpZlnLk8wZRjv2I=", + "lastModified": 1727463368, + "narHash": "sha256-5glMknkwQejUrKy28iy/kCFlSMwHcVyf/whmxqD0ggk=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "5a0c70a007837e2db01e0bb68971792e8653d32c", + "rev": "29ad64f0ac4ae84710dfeb1d37572d95c94cbfd8", "type": "github" }, "original": { @@ -673,11 +673,11 @@ ] }, "locked": { - "lastModified": 1726710255, - "narHash": "sha256-F7IpHzKsV9lzFhSZ5/8jMrAPNTLDAloazYlulnTyG9o=", + "lastModified": 1727833615, + "narHash": "sha256-C/9XuEGFtCEVToOfY7JU/CVMa6AcluPGLW6krNDS0HQ=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "e7740781e76ff6495f6a0c8c69ddc2d3f62c41c0", + "rev": "718a9b948796e17ae2bfff11f023e2b2894e072d", "type": "github" }, "original": { From 39fcb86f6e7d679844ea8d35e6fc8a17f27ab553 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 3 Oct 2024 14:25:36 +0200 Subject: [PATCH 0771/1125] Common: temporarely downgrade adw-gtk3 --- roles/common/configuration.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 3f1e6bf..a0d9b39 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -111,6 +111,15 @@ "grub" ]; }; + adw-gtk3 = prev.adw-gtk3.overrideAttrs { + version = "5.3"; + src = final.fetchFromGitHub { + owner = "lassekongo83"; + repo = "adw-gtk3"; + rev = "v5.3"; + sha256 = "sha256-DpJLX9PJX1Q8dDOx7YOXQzgNECsKp5uGiCVTX6iSlbI="; + }; + }; } ) ]; From f3c83f4ac23983e78b19674499180420de8ecfcd Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 8 Oct 2024 09:25:43 +0200 Subject: [PATCH 0772/1125] Desktop: install qmk tools --- roles/desktop/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index 9f9db1c..5129810 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -19,6 +19,7 @@ ]; hardware.keyboard.qmk.enable = true; + home-manager.users.toast.home.packages = [pkgs.qmk]; boot.plymouth.enable = true; } From dbb688716835a0d8b0a811f0f0e5402e6059c884 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 8 Oct 2024 11:51:09 +0200 Subject: [PATCH 0773/1125] Flake: update nixpkgs patches --- nixpkgs-patches/handheld-daemon-ui-init.patch | 98 +++++++++++++++++-- 1 file changed, 92 insertions(+), 6 deletions(-) diff --git a/nixpkgs-patches/handheld-daemon-ui-init.patch b/nixpkgs-patches/handheld-daemon-ui-init.patch index 16cd662..2ace372 100644 --- a/nixpkgs-patches/handheld-daemon-ui-init.patch +++ b/nixpkgs-patches/handheld-daemon-ui-init.patch @@ -1,7 +1,7 @@ From 18cd88064d152491d5ba19602db5c5d65bc2d685 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Thu, 18 Apr 2024 11:22:24 +0200 -Subject: [PATCH 1/3] handheld-daemon-ui: init at 3.1.1 +Subject: [PATCH 1/6] handheld-daemon-ui: init at 3.1.1 --- .../by-name/ha/handheld-daemon-ui/package.nix | 39 +++++++++++++++++++ @@ -10,7 +10,7 @@ Subject: [PATCH 1/3] handheld-daemon-ui: init at 3.1.1 diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix new file mode 100644 -index 00000000000000..81d318d88b5abd +index 000000000000000..81d318d88b5abd3 --- /dev/null +++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix @@ -0,0 +1,39 @@ @@ -57,14 +57,14 @@ index 00000000000000..81d318d88b5abd From 8ebb1f0976c79c74eb0cea3975c348e36d86a7d1 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Wed, 10 Jul 2024 12:59:01 +0200 -Subject: [PATCH 2/3] handheld-daemon: add options for handheld-daemon-ui +Subject: [PATCH 2/6] handheld-daemon: add options for handheld-daemon-ui --- .../modules/services/hardware/handheld-daemon.nix | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix -index 6c9d5aa3e22c86..e8e283bca89413 100644 +index 6c9d5aa3e22c86b..e8e283bca894130 100644 --- a/nixos/modules/services/hardware/handheld-daemon.nix +++ b/nixos/modules/services/hardware/handheld-daemon.nix @@ -11,6 +11,11 @@ in @@ -107,14 +107,14 @@ index 6c9d5aa3e22c86..e8e283bca89413 100644 From 1b034ab22605b29195dabce893282b05077d0fe7 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Thu, 11 Jul 2024 12:11:00 +0200 -Subject: [PATCH 3/3] handheld-daemon: enable ui when enabling handheld-daemon +Subject: [PATCH 3/6] handheld-daemon: enable ui when enabling handheld-daemon --- nixos/modules/services/hardware/handheld-daemon.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix -index e8e283bca89413..d78bae5e9bc483 100644 +index e8e283bca894130..d78bae5e9bc4833 100644 --- a/nixos/modules/services/hardware/handheld-daemon.nix +++ b/nixos/modules/services/hardware/handheld-daemon.nix @@ -25,6 +25,7 @@ in @@ -125,3 +125,89 @@ index e8e283bca89413..d78bae5e9bc483 100644 environment.systemPackages = [ cfg.package (mkIf cfg.ui.enable cfg.ui.package) + +From 0686e34bb16f8538e28b0795a8e5957ead5abdf0 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Tue, 8 Oct 2024 10:51:00 +0200 +Subject: [PATCH 4/6] handheld-daemon-ui: 3.1.1 -> 3.2.1 + +--- + pkgs/by-name/ha/handheld-daemon-ui/package.nix | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix +index 81d318d88b5abd3..028ceeb58f05e96 100644 +--- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix +@@ -5,11 +5,11 @@ + }: + let + pname = "handheld-daemon-ui"; +- version = "3.1.1"; ++ version = "3.2.1"; + + src = fetchurl { + url = "https://github.com/hhd-dev/hhd-ui/releases/download/v${version}/hhd-ui.Appimage"; +- hash = "sha256-KH01MvcCbvCqjp1UZHnwfh9G3Yh50CO9Ecjl1Y8VY9E="; ++ hash = "sha256-RRXVoeWOO/pR+CAEY0J6Buf/RhA+G0PdxGQVMdAHfwA="; + }; + extractedFiles = appimageTools.extractType2 { inherit pname version src; }; + in +@@ -18,7 +18,7 @@ appimageTools.wrapType2 { + + extraInstallCommands = '' + # Handheld-daemon expects the UI binary to be called hhd-ui +- mv $out/bin/${pname} $out/bin/hhd-ui ++ mv $out/bin/${pname}* $out/bin/hhd-ui + + mkdir -p $out/share/applications + substitute ${extractedFiles}/hhd-ui.desktop \ + +From d602ac7ac385613c082fe5b87b8462b2a2627a3e Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Tue, 8 Oct 2024 11:14:00 +0200 +Subject: [PATCH 5/6] handheld-daemon-ui: fix desktop item category + +--- + pkgs/by-name/ha/handheld-daemon-ui/package.nix | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix +index 028ceeb58f05e96..1aa8266ece44849 100644 +--- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix +@@ -23,7 +23,8 @@ appimageTools.wrapType2 { + mkdir -p $out/share/applications + substitute ${extractedFiles}/hhd-ui.desktop \ + $out/share/applications/hhd-ui.desktop \ +- --replace-fail "Exec=AppRun" "Exec=hhd-ui" ++ --replace-fail "Exec=AppRun" "Exec=hhd-ui" \ ++ --replace-fail "Categories=game;" "Categories=Game;" + cp ${extractedFiles}/usr/share/icons $out/share -r + ''; + + +From 09b2e9dcb32eb3d6eaa4ba0e65cf7102b50d1d13 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Tue, 8 Oct 2024 11:40:05 +0200 +Subject: [PATCH 6/6] handheld-daemon-ui: copy icon to correct folder + +--- + pkgs/by-name/ha/handheld-daemon-ui/package.nix | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix +index 1aa8266ece44849..a1131ea5c23d64a 100644 +--- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix +@@ -25,7 +25,9 @@ appimageTools.wrapType2 { + $out/share/applications/hhd-ui.desktop \ + --replace-fail "Exec=AppRun" "Exec=hhd-ui" \ + --replace-fail "Categories=game;" "Categories=Game;" +- cp ${extractedFiles}/usr/share/icons $out/share -r ++ iconDir=$out/share/icons/hicolor/512x512/apps ++ mkdir -p $iconDir ++ cp ${extractedFiles}/hhd-ui.png $iconDir + ''; + + meta = with lib; { From 0466a64c1704c78e740de743f7d4f2b724a47ba5 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 8 Oct 2024 13:24:52 +0200 Subject: [PATCH 0774/1125] School/services: add mysql --- roles/school/services/default.nix | 1 + roles/school/services/mysql.nix | 33 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 roles/school/services/mysql.nix diff --git a/roles/school/services/default.nix b/roles/school/services/default.nix index 3978b73..9fa78cd 100644 --- a/roles/school/services/default.nix +++ b/roles/school/services/default.nix @@ -2,5 +2,6 @@ imports = [ ./networkmanager.nix ./syncthing.nix + ./mysql.nix ]; } diff --git a/roles/school/services/mysql.nix b/roles/school/services/mysql.nix new file mode 100644 index 0000000..8b957d5 --- /dev/null +++ b/roles/school/services/mysql.nix @@ -0,0 +1,33 @@ +{ + config, + pkgs, + lib, + ... +}: { + services.mysql = { + enable = true; + package = pkgs.mysql84; + user = "toast"; + group = "users"; + }; + + # Don't autostart MySQL + systemd.services.mysql.wantedBy = lib.mkForce []; + + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if ( + action.id == "org.freedesktop.systemd1.manage-units" && + action.lookup("unit") == "mysql.service" && + subject.user == "${config.services.mysql.user}" + ) + { + return polkit.Result.YES; + } + }) + ''; + + environment.systemPackages = with pkgs; [ + mycli + ]; +} From 72ec589771d2bd077f1d34ad16f70c32a1c213fb Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 14 Oct 2024 10:02:33 +0200 Subject: [PATCH 0775/1125] Flake: update lock file --- flake.lock | 86 +++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/flake.lock b/flake.lock index d297db4..22bac5a 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1726952185, - "narHash": "sha256-l/HbsQjJMT6tlf8KCooFYi3J6wjIips3n6/aWAoLY4g=", + "lastModified": 1728407414, + "narHash": "sha256-B8LaxUP93eh+it8RW1pGq4SsU2kj7f0ipzFuhBvpON8=", "owner": "catppuccin", "repo": "nix", - "rev": "630b559cc1cb4c0bdd525af506935323e4ccd5d1", + "rev": "96cf8b4a05fb23a53c027621b1147b5cf9e5439f", "type": "github" }, "original": { @@ -218,11 +218,11 @@ ] }, "locked": { - "lastModified": 1727817100, - "narHash": "sha256-dlyV9/eiWkm/Y/t2+k4CFZ29tBvCANmJogEYaHeAOTw=", + "lastModified": 1728791962, + "narHash": "sha256-nr5QiXwQcZmf6/auC1UpX8iAtINMtdi2mH+OkqJQVmU=", "owner": "nix-community", "repo": "home-manager", - "rev": "437ec62009fa8ceb684eb447d455ffba25911cf9", + "rev": "64c6325b28ebd708653dd41d88f306023f296184", "type": "github" }, "original": { @@ -260,11 +260,11 @@ ] }, "locked": { - "lastModified": 1727760934, - "narHash": "sha256-xntX46lRTMQH383wCCi3d8xmjUnZ2jIoz0wn3aQQS1I=", + "lastModified": 1728679815, + "narHash": "sha256-3IXvY30zzFq7lHFujMupPz3TiPXo8o8qiIjkXUvznCI=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "477d11fc3f1352fb667177bb4712f5f976aaa7d9", + "rev": "e4f4d7832cc559389b93798c1f0d615e3816f4ef", "type": "github" }, "original": { @@ -276,11 +276,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1727783747, - "narHash": "sha256-fLiDo55WLgikMaaZcFEpkCkL4fQiV7RNEjRn+LxiYao=", - "rev": "775292766025380d04004e42fefbdb8ca40b3fa3", + "lastModified": 1728885224, + "narHash": "sha256-GVY4KFJSGoNxz6Pk/SnUr3unBsYUso9uatpoN47LpZw=", + "rev": "326cbecb61d42ce73caa391cdcb21acb2581bf7c", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/775292766025380d04004e42fefbdb8ca40b3fa3.tar.gz?rev=775292766025380d04004e42fefbdb8ca40b3fa3" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/326cbecb61d42ce73caa391cdcb21acb2581bf7c.tar.gz?rev=326cbecb61d42ce73caa391cdcb21acb2581bf7c" }, "original": { "type": "tarball", @@ -335,11 +335,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1721549352, - "narHash": "sha256-nlXJa8RSOX0kykrIYW33ukoHYq+FOSNztHLLgqKwOp8=", + "lastModified": 1728416205, + "narHash": "sha256-t30gsrwiBc2oBsd89DwdsVZuEbMT5ed81PYY57CIOJE=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "dbce39ea8664820ba9037caaf1e2fad365ed6b4b", + "rev": "d65dbf59900de4beaaaba8b42a15994f8433c1bc", "type": "github" }, "original": { @@ -393,11 +393,11 @@ ] }, "locked": { - "lastModified": 1727658919, - "narHash": "sha256-YAePt2GldkkRJ08LvZNHcuS6shIVStj+K+1DZN3gbnM=", + "lastModified": 1728790083, + "narHash": "sha256-grMdAd4KSU6uPqsfLzA1B/3pb9GtGI9o8qb0qFzEU/Y=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f9fdf8285690a351e8998f1e703ebdf9cdf51dee", + "rev": "5c54c33aa04df5dd4b0984b7eb861d1981009b22", "type": "github" }, "original": { @@ -413,11 +413,11 @@ ] }, "locked": { - "lastModified": 1727658919, - "narHash": "sha256-YAePt2GldkkRJ08LvZNHcuS6shIVStj+K+1DZN3gbnM=", + "lastModified": 1728790083, + "narHash": "sha256-grMdAd4KSU6uPqsfLzA1B/3pb9GtGI9o8qb0qFzEU/Y=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f9fdf8285690a351e8998f1e703ebdf9cdf51dee", + "rev": "5c54c33aa04df5dd4b0984b7eb861d1981009b22", "type": "github" }, "original": { @@ -435,11 +435,11 @@ ] }, "locked": { - "lastModified": 1727747697, - "narHash": "sha256-bNZ4ykMpxyTLrPsctiDwe5d69vafvIbNTbzbWfd2CH4=", + "lastModified": 1728784327, + "narHash": "sha256-Ib1rAnxE4ZZtO3WE7E4+mwivz37gwNOW5qPToJb9RPQ=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "30af58cedcc444da772a73286e16287f94a9fef1", + "rev": "14f679c6eaba1ef43b6f6092ba82e24cba97c858", "type": "github" }, "original": { @@ -450,11 +450,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1727665282, - "narHash": "sha256-oKtfbQB1MBypqIyzkC8QCQcVGOa1soaXaGgcBIoh14o=", + "lastModified": 1728729581, + "narHash": "sha256-oazkQ/z7r43YkDLLQdMg8oIB3CwWNb+2ZrYOxtLEWTQ=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "11c43c830e533dad1be527ecce379fcf994fbbb5", + "rev": "a8dd1b21995964b115b1e3ec639dd6ce24ab9806", "type": "github" }, "original": { @@ -482,11 +482,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1727672256, - "narHash": "sha256-9/79hjQc9+xyH+QxeMcRsA6hDyw6Z9Eo1/oxjvwirLk=", + "lastModified": 1728740863, + "narHash": "sha256-u+rxA79a0lyhG+u+oPBRtTDtzz8kvkc9a6SWSt9ekVc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1719f27dd95fd4206afb9cec9f415b539978827e", + "rev": "a3f9ad65a0bf298ed5847629a57808b97e6e8077", "type": "github" }, "original": { @@ -497,11 +497,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1727634051, - "narHash": "sha256-S5kVU7U82LfpEukbn/ihcyNt2+EvG7Z5unsKW9H/yFA=", + "lastModified": 1728492678, + "narHash": "sha256-9UTxR8eukdg+XZeHgxW5hQA9fIKHsKCdOIUycTryeVw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "06cf0e1da4208d3766d898b7fdab6513366d45b9", + "rev": "5633bcff0c6162b9e4b5f1264264611e950c8ec7", "type": "github" }, "original": { @@ -512,11 +512,11 @@ }, "nur": { "locked": { - "lastModified": 1727862373, - "narHash": "sha256-viH52KlflVeTo5++dEKvTjCQBoui5Shi6LIo0l6iEHI=", + "lastModified": 1728889933, + "narHash": "sha256-ZqCutCb0MxSfLm5VyVq5p029kJ+++5j+E5e9qS8W+/8=", "owner": "nix-community", "repo": "NUR", - "rev": "5cf5605cb2630639a716450161e0bba47bd439f4", + "rev": "5572baaaacd0ff97783859f35eb20de9a5cf6000", "type": "github" }, "original": { @@ -535,11 +535,11 @@ ] }, "locked": { - "lastModified": 1727463368, - "narHash": "sha256-5glMknkwQejUrKy28iy/kCFlSMwHcVyf/whmxqD0ggk=", + "lastModified": 1728750492, + "narHash": "sha256-9IHlIsH4gLqQjS2lFbEnsl/ItdqzBBLWLsyXS0k0jf8=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "29ad64f0ac4ae84710dfeb1d37572d95c94cbfd8", + "rev": "c6d4b6f3e0138c08f37d66fcfbcbe37dab08f108", "type": "github" }, "original": { @@ -673,11 +673,11 @@ ] }, "locked": { - "lastModified": 1727833615, - "narHash": "sha256-C/9XuEGFtCEVToOfY7JU/CVMa6AcluPGLW6krNDS0HQ=", + "lastModified": 1728179514, + "narHash": "sha256-mOGZFPYm9SuEXnYiXhgs/JmLu7RofRaMpAYyJiWudkc=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "718a9b948796e17ae2bfff11f023e2b2894e072d", + "rev": "018196c371073d669510fd69dd2f6dc0ec608c41", "type": "github" }, "original": { From f85d3d5ac2c739f84a631f74dc4fb3c8dee28504 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 15 Oct 2024 19:08:30 +0200 Subject: [PATCH 0776/1125] School: install insomnia --- roles/school/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/school/default.nix b/roles/school/default.nix index 9c84cca..d50b99e 100644 --- a/roles/school/default.nix +++ b/roles/school/default.nix @@ -7,5 +7,6 @@ jetbrains.idea-ultimate jetbrains.webstorm nodejs + insomnia ]; } From 84113d53276150846c3bfeac74b0e65008814678 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 17 Oct 2024 09:11:42 +0200 Subject: [PATCH 0777/1125] Desktop/NetworkManager: change connection priorities --- roles/desktop/services/networkmanager.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/desktop/services/networkmanager.nix b/roles/desktop/services/networkmanager.nix index acf5834..c00d3e8 100644 --- a/roles/desktop/services/networkmanager.nix +++ b/roles/desktop/services/networkmanager.nix @@ -21,6 +21,7 @@ in { connection = { id = "4G Modem"; type = "wifi"; + autoconnect-priority = 5; }; ipv4.method = "auto"; wifi = { @@ -37,6 +38,7 @@ in { connection = { id = "Phone"; type = "wifi"; + autoconnect-priority = 5; }; ipv4.method = "auto"; wifi = { From 9b8a0629a16a1cb530928e4defd28fdfb6822f51 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 19 Oct 2024 20:34:57 +0200 Subject: [PATCH 0778/1125] Common/helix: add taplo as toml lsp --- roles/common/programs/helix.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index 553e7f8..b603369 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -10,6 +10,7 @@ extraPackages = with pkgs; [ nixpkgs-fmt nil + taplo ]; catppuccin = { enable = true; From 059ed79f33b9c40956e3cf39b860979a87762562 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 21 Oct 2024 00:58:09 +0200 Subject: [PATCH 0779/1125] Schooli/mysql: disable mycli temporarely --- roles/school/services/mysql.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/school/services/mysql.nix b/roles/school/services/mysql.nix index 8b957d5..6a3ebab 100644 --- a/roles/school/services/mysql.nix +++ b/roles/school/services/mysql.nix @@ -28,6 +28,6 @@ ''; environment.systemPackages = with pkgs; [ - mycli + # mycli ]; } From 85dc75ced4eee59495f574a8ed1fea6ff5209d8d Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 21 Oct 2024 00:59:27 +0200 Subject: [PATCH 0780/1125] Flake: update lock file --- flake.lock | 86 +++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/flake.lock b/flake.lock index 22bac5a..93650c0 100644 --- a/flake.lock +++ b/flake.lock @@ -218,11 +218,11 @@ ] }, "locked": { - "lastModified": 1728791962, - "narHash": "sha256-nr5QiXwQcZmf6/auC1UpX8iAtINMtdi2mH+OkqJQVmU=", + "lastModified": 1729459288, + "narHash": "sha256-gBOVJv+q6Mx8jGvwX7cE6J8+sZmi1uxpRVsO7WxvVuQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "64c6325b28ebd708653dd41d88f306023f296184", + "rev": "1e27f213d77fc842603628bcf2df6681d7d08f7e", "type": "github" }, "original": { @@ -260,11 +260,11 @@ ] }, "locked": { - "lastModified": 1728679815, - "narHash": "sha256-3IXvY30zzFq7lHFujMupPz3TiPXo8o8qiIjkXUvznCI=", + "lastModified": 1729177642, + "narHash": "sha256-DdKal+ZhB9QD/tnEwFg4cZ4j4YnrkvSljBxnyG+3eE0=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "e4f4d7832cc559389b93798c1f0d615e3816f4ef", + "rev": "bb69165ff372ddbd3228a03513922acd783040e8", "type": "github" }, "original": { @@ -276,11 +276,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1728885224, - "narHash": "sha256-GVY4KFJSGoNxz6Pk/SnUr3unBsYUso9uatpoN47LpZw=", - "rev": "326cbecb61d42ce73caa391cdcb21acb2581bf7c", + "lastModified": 1729455191, + "narHash": "sha256-8hqmXUj2NH7fqZLFtFer+FfldkTaTmbkghvxM2UNK10=", + "rev": "068f4b147d589f2a219ba917537b53a56089c1ba", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/326cbecb61d42ce73caa391cdcb21acb2581bf7c.tar.gz?rev=326cbecb61d42ce73caa391cdcb21acb2581bf7c" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/068f4b147d589f2a219ba917537b53a56089c1ba.tar.gz?rev=068f4b147d589f2a219ba917537b53a56089c1ba" }, "original": { "type": "tarball", @@ -335,11 +335,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1728416205, - "narHash": "sha256-t30gsrwiBc2oBsd89DwdsVZuEbMT5ed81PYY57CIOJE=", + "lastModified": 1729453639, + "narHash": "sha256-L19R5CXCfTU9IFs9FAaYhDiteegfhJQMiAHLfls4Pdw=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "d65dbf59900de4beaaaba8b42a15994f8433c1bc", + "rev": "68bc646058386e2ffbd9d78d79d6558e684f6b8c", "type": "github" }, "original": { @@ -373,11 +373,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1727649413, - "narHash": "sha256-FA53of86DjFdeQzRDVtvgWF9o52rWK70VHGx0Y8fElQ=", + "lastModified": 1729068498, + "narHash": "sha256-C2sGRJl1EmBq0nO98TNd4cbUy20ABSgnHWXLIJQWRFA=", "owner": "nix-community", "repo": "impermanence", - "rev": "d0b38e550039a72aff896ee65b0918e975e6d48e", + "rev": "e337457502571b23e449bf42153d7faa10c0a562", "type": "github" }, "original": { @@ -393,11 +393,11 @@ ] }, "locked": { - "lastModified": 1728790083, - "narHash": "sha256-grMdAd4KSU6uPqsfLzA1B/3pb9GtGI9o8qb0qFzEU/Y=", + "lastModified": 1729394935, + "narHash": "sha256-2ntUG+NJKdfhlrh/tF+jOU0fOesO7lm5ZZVSYitsvH8=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "5c54c33aa04df5dd4b0984b7eb861d1981009b22", + "rev": "04f8a11f247ba00263b060fbcdc95484fd046104", "type": "github" }, "original": { @@ -413,11 +413,11 @@ ] }, "locked": { - "lastModified": 1728790083, - "narHash": "sha256-grMdAd4KSU6uPqsfLzA1B/3pb9GtGI9o8qb0qFzEU/Y=", + "lastModified": 1729394935, + "narHash": "sha256-2ntUG+NJKdfhlrh/tF+jOU0fOesO7lm5ZZVSYitsvH8=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "5c54c33aa04df5dd4b0984b7eb861d1981009b22", + "rev": "04f8a11f247ba00263b060fbcdc95484fd046104", "type": "github" }, "original": { @@ -435,11 +435,11 @@ ] }, "locked": { - "lastModified": 1728784327, - "narHash": "sha256-Ib1rAnxE4ZZtO3WE7E4+mwivz37gwNOW5qPToJb9RPQ=", + "lastModified": 1729389245, + "narHash": "sha256-vkTEnmCpkMn0DzaQDkLLCBUDXe+zhMiCfykdeC/BQjc=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "14f679c6eaba1ef43b6f6092ba82e24cba97c858", + "rev": "4141afa4cc8f63b7c88788a319efef69459222ee", "type": "github" }, "original": { @@ -450,11 +450,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1728729581, - "narHash": "sha256-oazkQ/z7r43YkDLLQdMg8oIB3CwWNb+2ZrYOxtLEWTQ=", + "lastModified": 1729455275, + "narHash": "sha256-THqzn/7um3oMHUEGXyq+1CJQE7EogwR3HjLMNOlhFBE=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "a8dd1b21995964b115b1e3ec639dd6ce24ab9806", + "rev": "9fcf30fccf8435f6390efec4a4d38e69c2268a36", "type": "github" }, "original": { @@ -482,11 +482,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1728740863, - "narHash": "sha256-u+rxA79a0lyhG+u+oPBRtTDtzz8kvkc9a6SWSt9ekVc=", + "lastModified": 1729181673, + "narHash": "sha256-LDiPhQ3l+fBjRATNtnuDZsBS7hqoBtPkKBkhpoBHv3I=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a3f9ad65a0bf298ed5847629a57808b97e6e8077", + "rev": "4eb33fe664af7b41a4c446f87d20c9a0a6321fa3", "type": "github" }, "original": { @@ -497,11 +497,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1728492678, - "narHash": "sha256-9UTxR8eukdg+XZeHgxW5hQA9fIKHsKCdOIUycTryeVw=", + "lastModified": 1729256560, + "narHash": "sha256-/uilDXvCIEs3C9l73JTACm4quuHUsIHcns1c+cHUJwA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5633bcff0c6162b9e4b5f1264264611e950c8ec7", + "rev": "4c2fcb090b1f3e5b47eaa7bd33913b574a11e0a0", "type": "github" }, "original": { @@ -512,11 +512,11 @@ }, "nur": { "locked": { - "lastModified": 1728889933, - "narHash": "sha256-ZqCutCb0MxSfLm5VyVq5p029kJ+++5j+E5e9qS8W+/8=", + "lastModified": 1729460551, + "narHash": "sha256-/+63hDTCMSplnJ/V5dd7y43kRkiRVOCjGsQ+LWg+0jM=", "owner": "nix-community", "repo": "NUR", - "rev": "5572baaaacd0ff97783859f35eb20de9a5cf6000", + "rev": "f0da30b33a995a031ba331faa11b58b22dc69469", "type": "github" }, "original": { @@ -535,11 +535,11 @@ ] }, "locked": { - "lastModified": 1728750492, - "narHash": "sha256-9IHlIsH4gLqQjS2lFbEnsl/ItdqzBBLWLsyXS0k0jf8=", + "lastModified": 1729372184, + "narHash": "sha256-Tb2/jJ74pt0nmfprkOW1g5zZphJTNbzLnyDENM+c5+I=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "c6d4b6f3e0138c08f37d66fcfbcbe37dab08f108", + "rev": "9390dadadc58ffda8e494b31ef66a4ae041f6dd1", "type": "github" }, "original": { @@ -673,11 +673,11 @@ ] }, "locked": { - "lastModified": 1728179514, - "narHash": "sha256-mOGZFPYm9SuEXnYiXhgs/JmLu7RofRaMpAYyJiWudkc=", + "lastModified": 1729389220, + "narHash": "sha256-vHCkVYWrw03vn48Yihor5PXiSuxDSF1TcyO2kAs1Ehg=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "018196c371073d669510fd69dd2f6dc0ec608c41", + "rev": "f4dd6d6b728a61095b944de1fbc58c5bbdc87320", "type": "github" }, "original": { From 74cadfd80fd5f88bfa2481994c7f6c450339bcf5 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 24 Oct 2024 13:35:30 +0200 Subject: [PATCH 0781/1125] Common: enable eza --- roles/common/programs/default.nix | 1 + roles/common/programs/eza.nix | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 roles/common/programs/eza.nix diff --git a/roles/common/programs/default.nix b/roles/common/programs/default.nix index d4428e5..48b27ba 100755 --- a/roles/common/programs/default.nix +++ b/roles/common/programs/default.nix @@ -14,6 +14,7 @@ ./direnv.nix ./atuin.nix ./fish.nix + ./eza.nix ]; # Some programs dont have a programs.*.enable option, so I install their package here environment.systemPackages = with pkgs; [ diff --git a/roles/common/programs/eza.nix b/roles/common/programs/eza.nix new file mode 100644 index 0000000..4d36553 --- /dev/null +++ b/roles/common/programs/eza.nix @@ -0,0 +1,8 @@ +{pkgs, ...}: { + home-manager = { + users.toast.programs.eza = { + enable = true; + enableBashIntegration = true; + }; + }; +} From f58fdb8d49f1db1d7c4544ce835f1589e672761c Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 24 Oct 2024 13:50:48 +0200 Subject: [PATCH 0782/1125] Flake: add non-flake inputs --- flake.lock | 17 +++++++++++++++++ flake.nix | 15 +++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 93650c0..de04455 100644 --- a/flake.lock +++ b/flake.lock @@ -56,6 +56,22 @@ "type": "github" } }, + "eza-themes": { + "flake": false, + "locked": { + "lastModified": 1726839736, + "narHash": "sha256-dd9KBb3Upg+x/4ImQwSwKWtDHyfk/29zLkmrVgHVsh0=", + "owner": "eza-community", + "repo": "eza-themes", + "rev": "302f4783dcd84a8221f1da8223d1ea0885fd26e3", + "type": "github" + }, + "original": { + "owner": "eza-community", + "repo": "eza-themes", + "type": "github" + } + }, "flake-compat": { "flake": false, "locked": { @@ -553,6 +569,7 @@ "agenix": "agenix", "catppuccin": "catppuccin", "catppuccin-vsc": "catppuccin-vsc", + "eza-themes": "eza-themes", "home-manager": "home-manager_2", "home-manager-unstable": "home-manager-unstable", "jovian": "jovian", diff --git a/flake.nix b/flake.nix index f6accae..2832d46 100644 --- a/flake.nix +++ b/flake.nix @@ -68,10 +68,6 @@ catppuccin.url = "github:catppuccin/nix"; - lix = { - url = "https://git.lix.systems/lix-project/lix/archive/main.tar.gz"; - flake = false; - }; lix-module = { url = "https://git.lix.systems/lix-project/nixos-module/archive/main.tar.gz"; inputs.nixpkgs.follows = "nixpkgs-raw"; @@ -87,6 +83,17 @@ url = "github:Infinidoge/nix-minecraft"; inputs.nixpkgs.follows = "nixpkgs-raw"; }; + + # Non flake inputs / random things + lix = { + url = "https://git.lix.systems/lix-project/lix/archive/main.tar.gz"; + flake = false; + }; + + eza-themes = { + url = "github:eza-community/eza-themes"; + flake = false; + }; }; outputs = {...} @ inputs: From 67716baa547e7873f51971a5894d55aaa8261fdc Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 24 Oct 2024 14:07:32 +0200 Subject: [PATCH 0783/1125] Common/eza: enable git and icon support --- roles/common/programs/eza.nix | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/roles/common/programs/eza.nix b/roles/common/programs/eza.nix index 4d36553..23502f6 100644 --- a/roles/common/programs/eza.nix +++ b/roles/common/programs/eza.nix @@ -1,8 +1,12 @@ {pkgs, ...}: { home-manager = { - users.toast.programs.eza = { - enable = true; - enableBashIntegration = true; + users.toast = { + programs.eza = { + enable = true; + enableBashIntegration = true; + git = true; + icons = "auto"; + }; }; }; } From 582ac7314a7a8494aef20790fd64709f4a9d079e Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 24 Oct 2024 14:07:49 +0200 Subject: [PATCH 0784/1125] Common/eza: use catppuccin theme --- roles/common/programs/eza.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/eza.nix b/roles/common/programs/eza.nix index 23502f6..7e904e6 100644 --- a/roles/common/programs/eza.nix +++ b/roles/common/programs/eza.nix @@ -1,4 +1,4 @@ -{pkgs, ...}: { +{flakeSelf, ...}: { home-manager = { users.toast = { programs.eza = { @@ -7,6 +7,7 @@ git = true; icons = "auto"; }; + xdg.configFile."eza/theme.yml".source = "${flakeSelf.inputs.eza-themes}/themes/catppuccin.yml"; }; }; } From b51bea1785341578c304d35c30bbcad93cd23470 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 24 Oct 2024 11:33:34 +0200 Subject: [PATCH 0785/1125] Server/tailscale: increase tailscale timeout --- roles/server/tailscale.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/server/tailscale.nix b/roles/server/tailscale.nix index 7135368..610e592 100644 --- a/roles/server/tailscale.nix +++ b/roles/server/tailscale.nix @@ -5,9 +5,9 @@ text = '' # Based on https://github.com/tailscale/tailscale/issues/11504#issuecomment-2113331262 echo Waiting for tailscale0 to get an IP adress.. - for i in {1..15}; do + for i in {1..120}; do if ip addr show dev tailscale0 | grep -q 'inet '; then break; fi - echo "$i" + echo "Waiting $i/120 seconds" sleep 1 done ''; From cfa31cbe5137ab80a52096f84adb66ee552b7350 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 25 Oct 2024 10:56:47 +0200 Subject: [PATCH 0786/1125] Common/eza: fix icons config for 24.05 --- roles/common/programs/eza.nix | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/roles/common/programs/eza.nix b/roles/common/programs/eza.nix index 7e904e6..f9e980d 100644 --- a/roles/common/programs/eza.nix +++ b/roles/common/programs/eza.nix @@ -1,11 +1,18 @@ -{flakeSelf, ...}: { +{ + flakeSelf, + config, + ... +}: { home-manager = { users.toast = { programs.eza = { enable = true; enableBashIntegration = true; git = true; - icons = "auto"; + icons = + if config.system.nixos.release == "24.05" + then true + else "auto"; }; xdg.configFile."eza/theme.yml".source = "${flakeSelf.inputs.eza-themes}/themes/catppuccin.yml"; }; From a643254864a41b52c39ac7dc29819e108d2aceff Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 29 Oct 2024 09:44:59 +0100 Subject: [PATCH 0787/1125] Desktop/ssh: add config to connect to everest over the internet --- roles/desktop/programs/ssh.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/roles/desktop/programs/ssh.nix b/roles/desktop/programs/ssh.nix index 8449fe4..00c4c4d 100644 --- a/roles/desktop/programs/ssh.nix +++ b/roles/desktop/programs/ssh.nix @@ -14,6 +14,13 @@ enable = true; matchBlocks = { "everest" = { + host = "toast003.xyz"; + hostname = "toast003.xyz"; + forwardAgent = true; + sendEnv = ["COLORTERM"]; + port = 69; + }; + "everest-tailscale" = { host = "everest"; hostname = "everest.tailscale"; forwardAgent = true; From 59692e7651435a037417b69ff8c9ac58f4bc1a98 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 29 Oct 2024 11:50:08 +0100 Subject: [PATCH 0788/1125] Server/caddy: open http/s ports on firewall --- roles/server/caddy.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index 71029b9..b7b049e 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -58,4 +58,5 @@ in { services.caddy.serviceConfig.RestartSec = lib.mkForce "120s"; }; programs.rust-motd.settings.service_status.Caddy = "caddy"; + networking.firewall.allowedTCPPorts = [443 80]; } From dfd094ef674786babd9c18f4aafc07c3915241d2 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 29 Oct 2024 11:50:27 +0100 Subject: [PATCH 0789/1125] Server: add headscale --- roles/server/default.nix | 1 + roles/server/headscale.nix | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 roles/server/headscale.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index d1e29aa..4ba0396 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -11,6 +11,7 @@ ./ddclient.nix ./beep.nix ./tailscale.nix + ./headscale.nix ./caddy.nix ./dns.nix ./rust_motd.nix diff --git a/roles/server/headscale.nix b/roles/server/headscale.nix new file mode 100644 index 0000000..fb72484 --- /dev/null +++ b/roles/server/headscale.nix @@ -0,0 +1,16 @@ +{...}: { + services.headscale = { + enable = true; + settings = { + server_url = "https://headscale.toast003.xyz"; + }; + }; + services.caddy = { + virtualHosts.headscale = { + hostName = "headscale.toast003.xyz"; + extraConfig = '' + reverse_proxy localhost:8080 + ''; + }; + }; +} From 37f3b3fc6099a56959dd15ce5688c3cbeca2cd60 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Oct 2024 00:23:25 +0100 Subject: [PATCH 0790/1125] Server/headscale: set up ip prefixes --- roles/server/headscale.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/server/headscale.nix b/roles/server/headscale.nix index fb72484..7009922 100644 --- a/roles/server/headscale.nix +++ b/roles/server/headscale.nix @@ -3,6 +3,9 @@ enable = true; settings = { server_url = "https://headscale.toast003.xyz"; + ip_prefixes = [ + "100.100.0.0/16" + ]; }; }; services.caddy = { From d39890589b245357e8f80b850bbb6192dde51ac1 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Oct 2024 00:39:53 +0100 Subject: [PATCH 0791/1125] Server/caddy: update server IP --- roles/server/caddy.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index b7b049e..83cba86 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -23,7 +23,9 @@ in { extraConfig = '' (tailscale) { tls internal - bind 100.73.96.48 + # Old tailscale IP + # bind 100.73.96.48 + bind 100.100.0.1 } ''; virtualHosts = { From 492d870980ed2b9e6315713c2023a194679e5f33 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 31 Oct 2024 16:20:08 +0100 Subject: [PATCH 0792/1125] Server/headscale: setup dns --- roles/server/headscale.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/server/headscale.nix b/roles/server/headscale.nix index 7009922..bfd803f 100644 --- a/roles/server/headscale.nix +++ b/roles/server/headscale.nix @@ -6,6 +6,10 @@ ip_prefixes = [ "100.100.0.0/16" ]; + dns_config = { + base_domain = "tailscale"; + nameservers = ["9.9.9.9"]; + }; }; }; services.caddy = { From d18e059d1efe971ef9737359793c7a201c772918 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 1 Nov 2024 12:27:51 +0100 Subject: [PATCH 0793/1125] Flake: update lock file --- flake.lock | 104 ++++++++++++++++++++++++++--------------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/flake.lock b/flake.lock index de04455..44eab54 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1728407414, - "narHash": "sha256-B8LaxUP93eh+it8RW1pGq4SsU2kj7f0ipzFuhBvpON8=", + "lastModified": 1730036420, + "narHash": "sha256-rv2bz7J6Wo7AenPiu4+ptCB1AFyaMcS77y89zbRAtI8=", "owner": "catppuccin", "repo": "nix", - "rev": "96cf8b4a05fb23a53c027621b1147b5cf9e5439f", + "rev": "0b7bf04628414a402d255924f65e9a0d1a53d92b", "type": "github" }, "original": { @@ -59,11 +59,11 @@ "eza-themes": { "flake": false, "locked": { - "lastModified": 1726839736, - "narHash": "sha256-dd9KBb3Upg+x/4ImQwSwKWtDHyfk/29zLkmrVgHVsh0=", + "lastModified": 1730050654, + "narHash": "sha256-Gs21+A/to2AqjQsqMlWeOuSowYPOuSZ3fK6LRdBPUmI=", "owner": "eza-community", "repo": "eza-themes", - "rev": "302f4783dcd84a8221f1da8223d1ea0885fd26e3", + "rev": "74be26bbd2ce76b29c37250a2fb7cb5d6644c964", "type": "github" }, "original": { @@ -234,11 +234,11 @@ ] }, "locked": { - "lastModified": 1729459288, - "narHash": "sha256-gBOVJv+q6Mx8jGvwX7cE6J8+sZmi1uxpRVsO7WxvVuQ=", + "lastModified": 1730450782, + "narHash": "sha256-0AfApF8aexgB6o34qqLW2cCX4LaWJajBVdU6ddiWZBM=", "owner": "nix-community", "repo": "home-manager", - "rev": "1e27f213d77fc842603628bcf2df6681d7d08f7e", + "rev": "8ca921e5a806b5b6171add542defe7bdac79d189", "type": "github" }, "original": { @@ -276,11 +276,11 @@ ] }, "locked": { - "lastModified": 1729177642, - "narHash": "sha256-DdKal+ZhB9QD/tnEwFg4cZ4j4YnrkvSljBxnyG+3eE0=", + "lastModified": 1730441026, + "narHash": "sha256-xmZQFGeIm2TzXv4jGaQ3nfBoUbt4gKbIv/SHVWw93ag=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "bb69165ff372ddbd3228a03513922acd783040e8", + "rev": "bd1da5657b8903b293a0ff51eb896a91a544ebed", "type": "github" }, "original": { @@ -292,11 +292,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1729455191, - "narHash": "sha256-8hqmXUj2NH7fqZLFtFer+FfldkTaTmbkghvxM2UNK10=", - "rev": "068f4b147d589f2a219ba917537b53a56089c1ba", + "lastModified": 1730433081, + "narHash": "sha256-1oqkMcFQyAqCvqkjG9K3NaRLyB1qkXXiZoxe4rwM6ag=", + "rev": "834450e237b82230934b5d25ed212b5a55938cc5", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/068f4b147d589f2a219ba917537b53a56089c1ba.tar.gz?rev=068f4b147d589f2a219ba917537b53a56089c1ba" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/834450e237b82230934b5d25ed212b5a55938cc5.tar.gz?rev=834450e237b82230934b5d25ed212b5a55938cc5" }, "original": { "type": "tarball", @@ -351,11 +351,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1729453639, - "narHash": "sha256-L19R5CXCfTU9IFs9FAaYhDiteegfhJQMiAHLfls4Pdw=", + "lastModified": 1730108712, + "narHash": "sha256-vIvmXmjAQIY39hACGFe/cdBK2r3ZprpHLwX2HIy7Mj8=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "68bc646058386e2ffbd9d78d79d6558e684f6b8c", + "rev": "1cba177bb0a948c919af7596e40bef307543d40a", "type": "github" }, "original": { @@ -373,11 +373,11 @@ ] }, "locked": { - "lastModified": 1690328911, - "narHash": "sha256-fxtExYk+aGf2YbjeWQ8JY9/n9dwuEt+ma1eUFzF8Jeo=", + "lastModified": 1729697500, + "narHash": "sha256-VFTWrbzDlZyFHHb1AlKRiD/qqCJIripXKiCSFS8fAOY=", "owner": "zhaofengli", "repo": "nix-github-actions", - "rev": "96df4a39c52f53cb7098b923224d8ce941b64747", + "rev": "e418aeb728b6aa5ca8c5c71974e7159c2df1d8cf", "type": "github" }, "original": { @@ -389,11 +389,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1729068498, - "narHash": "sha256-C2sGRJl1EmBq0nO98TNd4cbUy20ABSgnHWXLIJQWRFA=", + "lastModified": 1730403150, + "narHash": "sha256-W1FH5aJ/GpRCOA7DXT/sJHFpa5r8sq2qAUncWwRZ3Gg=", "owner": "nix-community", "repo": "impermanence", - "rev": "e337457502571b23e449bf42153d7faa10c0a562", + "rev": "0d09341beeaa2367bac5d718df1404bf2ce45e6f", "type": "github" }, "original": { @@ -409,11 +409,11 @@ ] }, "locked": { - "lastModified": 1729394935, - "narHash": "sha256-2ntUG+NJKdfhlrh/tF+jOU0fOesO7lm5ZZVSYitsvH8=", + "lastModified": 1729999765, + "narHash": "sha256-LYsavZXitFjjyETZoij8usXjTa7fa9AIF3Sk3MJSX+Y=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "04f8a11f247ba00263b060fbcdc95484fd046104", + "rev": "0e3a8778c2ee218eff8de6aacf3d2fa6c33b2d4f", "type": "github" }, "original": { @@ -429,11 +429,11 @@ ] }, "locked": { - "lastModified": 1729394935, - "narHash": "sha256-2ntUG+NJKdfhlrh/tF+jOU0fOesO7lm5ZZVSYitsvH8=", + "lastModified": 1729999765, + "narHash": "sha256-LYsavZXitFjjyETZoij8usXjTa7fa9AIF3Sk3MJSX+Y=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "04f8a11f247ba00263b060fbcdc95484fd046104", + "rev": "0e3a8778c2ee218eff8de6aacf3d2fa6c33b2d4f", "type": "github" }, "original": { @@ -451,11 +451,11 @@ ] }, "locked": { - "lastModified": 1729389245, - "narHash": "sha256-vkTEnmCpkMn0DzaQDkLLCBUDXe+zhMiCfykdeC/BQjc=", + "lastModified": 1730426071, + "narHash": "sha256-2BkSiHqyWikpz9HSgTBk5kikaQ5m0Rs60C9KA2kf53o=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "4141afa4cc8f63b7c88788a319efef69459222ee", + "rev": "4b371c3d119493051d081ff5b6cff689a97ad1a1", "type": "github" }, "original": { @@ -466,11 +466,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1729455275, - "narHash": "sha256-THqzn/7um3oMHUEGXyq+1CJQE7EogwR3HjLMNOlhFBE=", + "lastModified": 1730368399, + "narHash": "sha256-F8vJtG389i9fp3k2/UDYHMed3PLCJYfxCqwiVP7b9ig=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "9fcf30fccf8435f6390efec4a4d38e69c2268a36", + "rev": "da14839ac5f38ee6adbdb4e6db09b5eef6d6ccdc", "type": "github" }, "original": { @@ -498,11 +498,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1729181673, - "narHash": "sha256-LDiPhQ3l+fBjRATNtnuDZsBS7hqoBtPkKBkhpoBHv3I=", + "lastModified": 1730327045, + "narHash": "sha256-xKel5kd1AbExymxoIfQ7pgcX6hjw9jCgbiBjiUfSVJ8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4eb33fe664af7b41a4c446f87d20c9a0a6321fa3", + "rev": "080166c15633801df010977d9d7474b4a6c549d7", "type": "github" }, "original": { @@ -513,11 +513,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1729256560, - "narHash": "sha256-/uilDXvCIEs3C9l73JTACm4quuHUsIHcns1c+cHUJwA=", + "lastModified": 1730200266, + "narHash": "sha256-l253w0XMT8nWHGXuXqyiIC/bMvh1VRszGXgdpQlfhvU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4c2fcb090b1f3e5b47eaa7bd33913b574a11e0a0", + "rev": "807e9154dcb16384b1b765ebe9cd2bba2ac287fd", "type": "github" }, "original": { @@ -528,11 +528,11 @@ }, "nur": { "locked": { - "lastModified": 1729460551, - "narHash": "sha256-/+63hDTCMSplnJ/V5dd7y43kRkiRVOCjGsQ+LWg+0jM=", + "lastModified": 1730455118, + "narHash": "sha256-E5yWeAUKohUot11JBfH7apOyPjqs3z2/fAtUc2LNfHw=", "owner": "nix-community", "repo": "NUR", - "rev": "f0da30b33a995a031ba331faa11b58b22dc69469", + "rev": "5bf603459b923edbee4955e9fc94b94662add85c", "type": "github" }, "original": { @@ -551,11 +551,11 @@ ] }, "locked": { - "lastModified": 1729372184, - "narHash": "sha256-Tb2/jJ74pt0nmfprkOW1g5zZphJTNbzLnyDENM+c5+I=", + "lastModified": 1730366788, + "narHash": "sha256-0Ezvv4KkyFdLAblPBFDgZbiMLlJZtpHruT2i4KC2wIY=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "9390dadadc58ffda8e494b31ef66a4ae041f6dd1", + "rev": "f634d5f6ee9be365b2ca08b2d00e0e3b0c240b9e", "type": "github" }, "original": { @@ -690,11 +690,11 @@ ] }, "locked": { - "lastModified": 1729389220, - "narHash": "sha256-vHCkVYWrw03vn48Yihor5PXiSuxDSF1TcyO2kAs1Ehg=", + "lastModified": 1730426202, + "narHash": "sha256-swwKpE3lrdvcSh6Hjyf/eSe/zPnsZgeVlSl+B4yBpeo=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "f4dd6d6b728a61095b944de1fbc58c5bbdc87320", + "rev": "96dcbddd24edc60ad47f41bb2a73e06099eba4af", "type": "github" }, "original": { From c7d2db076b7237a84dd24c8b2a43845902d41a67 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 2 Nov 2024 18:14:28 +0100 Subject: [PATCH 0794/1125] Server: get rid of dnsmasq I can add custom records to headscale's dns settings, so I don't need dnsmasq anymore. This will also bring back resolved's stub --- roles/server/default.nix | 1 - roles/server/dns.nix | 42 ---------------------------------------- 2 files changed, 43 deletions(-) delete mode 100644 roles/server/dns.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index 4ba0396..bc1a6ea 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -13,7 +13,6 @@ ./tailscale.nix ./headscale.nix ./caddy.nix - ./dns.nix ./rust_motd.nix ./minecraft.nix ]; diff --git a/roles/server/dns.nix b/roles/server/dns.nix deleted file mode 100644 index 1e446e5..0000000 --- a/roles/server/dns.nix +++ /dev/null @@ -1,42 +0,0 @@ -{...}: { - services.dnsmasq = { - enable = true; - - # Only using this for tailscale IPs, so better to let tailscale itself deal with it - resolveLocalQueries = false; - - settings = { - listen-address = ["100.73.96.48"]; - - /* - Dnsmasq tries to use the tailscale dns server, which is bad cause that points to dnsmasq - From the little testing I have done it seems to not cause any issues, but better to be safe - than sorry :P - */ - dns-loop-detect = true; - - host-record = [ - "winmax2,winmax2.tailscale,100.106.73.20" - "everest,everest.tailscale,100.73.96.48" - "archie,archie.tailscale,100.113.139.93" - "steamdeck,steamdeck.tailscale,100.85.48.85" - "surfacego,surfacego.tailscale,100.96.92.13" - ]; - - # If this isn't set a cname that targets a host might return the wrong ip - localise-queries = true; - ## IPv6 is not a thing in Spain so I'm guaranteed to not use it - filter-AAAA = true; - domain = "tailscale"; - domain-needed = true; - }; - }; - - programs.rust-motd.settings.service_status.dnsmasq = "dnsmasq"; - - # Dnsmasq conflicts with the resolved dns stub listener - services.resolved.extraConfig = '' - [Resolve] - DNSStubListener=no - ''; -} From 0e66939ab1c128a71571ca3321684bf6f633c01e Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 3 Nov 2024 01:18:39 +0100 Subject: [PATCH 0795/1125] Server: replace dnsmasq cnames with headscale extra dns records --- roles/server/caddy.nix | 15 +++++++++++---- roles/server/forgejo.nix | 10 ++++++++-- roles/server/syncthing.nix | 10 ++++++++-- roles/server/transmission.nix | 10 ++++++++-- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index 83cba86..439f231 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -47,10 +47,17 @@ in { }; }; }; - services.dnsmasq.settings.cname = [ - "${manualHostname},everest" - "${downloadsHostname},everest" - ]; + services.headscale.settings.dns_config.extra_records = let + makeRecords = builtins.map (recordName: { + name = recordName; + type = "A"; + value = "100.100.0.1"; + }); + in + makeRecords [ + manualHostname + downloadsHostname + ]; systemd = { services.caddy.after = ["tailscaled.service"]; # We have somewhat frequent power outages, and our ISP router takes diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index 65fbf83..52b6847 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -44,8 +44,14 @@ in { }; }; - # Add a cname for forgejo - services.dnsmasq.settings.cname = ["git.everest.tailscale,everest"]; + # Add a record for forgejo + services.headscale.settings.dns_config.extra_records = [ + { + name = "git.everest.tailscale"; + type = "A"; + value = "100.100.0.1"; + } + ]; # Set up caddy as the reverse proxy for Forgejo services.caddy.virtualHosts.forgejo = { diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index e6409a9..74caa4b 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -39,8 +39,14 @@ AmbientCapabilities = "CAP_CHOWN CAP_FOWNER"; }; - # Add a cname for syncthing - services.dnsmasq.settings.cname = ["sync.everest.tailscale,everest"]; + # Add a record for syncthing + services.headscale.settings.dns_config.extra_records = [ + { + name = "sync.everest.tailscale"; + type = "A"; + value = "100.100.0.1"; + } + ]; # Set up caddy as the reverse proxy for syncthing services.caddy.virtualHosts.syncthing = { diff --git a/roles/server/transmission.nix b/roles/server/transmission.nix index e52f286..a1aafdb 100755 --- a/roles/server/transmission.nix +++ b/roles/server/transmission.nix @@ -37,8 +37,14 @@ in { ''; }; - # Add a cname for transmission - services.dnsmasq.settings.cname = ["transmission.everest.tailscale,everest"]; + # Add a record for transmission + services.headscale.settings.dns_config.extra_records = [ + { + name = "transmission.everest.tailscale"; + type = "A"; + value = "100.100.0.1"; + } + ]; # Set up caddy as the reverse proxy for transmission services.caddy.virtualHosts.transmission = { From 34e1dd0bfca835083c366b9a3ae9c065d8fa2bd6 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 3 Nov 2024 01:19:30 +0100 Subject: [PATCH 0796/1125] Server/headscale: override local dns For some reason extra dns records don't apply without the override --- roles/server/headscale.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/headscale.nix b/roles/server/headscale.nix index bfd803f..4575327 100644 --- a/roles/server/headscale.nix +++ b/roles/server/headscale.nix @@ -9,6 +9,7 @@ dns_config = { base_domain = "tailscale"; nameservers = ["9.9.9.9"]; + override_local_dns = true; }; }; }; From cd802ab3a63d56834b1202f0a56f3575a2b9f8f9 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 3 Nov 2024 17:16:23 +0100 Subject: [PATCH 0797/1125] Flake: update lix --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 44eab54..20ca533 100644 --- a/flake.lock +++ b/flake.lock @@ -292,11 +292,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1730433081, - "narHash": "sha256-1oqkMcFQyAqCvqkjG9K3NaRLyB1qkXXiZoxe4rwM6ag=", - "rev": "834450e237b82230934b5d25ed212b5a55938cc5", + "lastModified": 1730610940, + "narHash": "sha256-ZsTpii4kZcioRF3bu3/pS374R9GYQVyrMpBNr2ZUnVg=", + "rev": "b1a0e3c0029c2dd5fb7c8dd2db4f9e0b309c9f54", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/834450e237b82230934b5d25ed212b5a55938cc5.tar.gz?rev=834450e237b82230934b5d25ed212b5a55938cc5" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/b1a0e3c0029c2dd5fb7c8dd2db4f9e0b309c9f54.tar.gz?rev=b1a0e3c0029c2dd5fb7c8dd2db4f9e0b309c9f54" }, "original": { "type": "tarball", From e15aa9ba44a1c0079de31013db91f63ef7fdb822 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 3 Nov 2024 20:20:07 +0100 Subject: [PATCH 0798/1125] Server/syncthing: bind to localhost --- roles/server/syncthing.nix | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 74caa4b..7982b1f 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -3,7 +3,7 @@ enable = true; key = config.age.secrets.syncthingKey.path; cert = config.age.secrets.syncthingCert.path; - guiAddress = "0.0.0.0:8384"; + guiAddress = "127.0.0.1:8384"; settings.folders = { "passwords" = { path = "${config.services.syncthing.dataDir}/passwords"; @@ -53,7 +53,9 @@ hostName = "sync.everest.tailscale"; extraConfig = '' import tailscale - reverse_proxy localhost:8384 + reverse_proxy localhost:8384 { + header_up Host {upstream_hostport} + } ''; }; } From e531e6cb6884687e7e8f5012e809793815ad52d1 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 5 Nov 2024 10:42:47 +0100 Subject: [PATCH 0799/1125] Services: add adguard --- roles/server/adguard.nix | 40 ++++++++++++++++++++++++++++++++++++++++ roles/server/default.nix | 1 + 2 files changed, 41 insertions(+) create mode 100644 roles/server/adguard.nix diff --git a/roles/server/adguard.nix b/roles/server/adguard.nix new file mode 100644 index 0000000..e1bf922 --- /dev/null +++ b/roles/server/adguard.nix @@ -0,0 +1,40 @@ +{lib, ...}: let + domain = "adguard.everest.tailscale"; + port = 3001; +in { + services = { + adguardhome = { + enable = true; + host = "127.0.0.1"; + port = port; + settings = { + dns = { + bind_hosts = [ + "192.168.0.160" + "100.100.0.1" + ]; + bootstrap_dns = ["9.9.9.9"]; + }; + }; + }; + + headscale.settings.dns_config = { + nameservers = lib.mkForce ["100.100.0.1"]; + extra_records = [ + { + name = domain; + type = "A"; + value = "100.100.0.1"; + } + ]; + }; + + caddy.virtualHosts.adguardhome = { + hostName = domain; + extraConfig = '' + import tailscale + reverse_proxy 127.0.0.1:${builtins.toString port} + ''; + }; + }; +} diff --git a/roles/server/default.nix b/roles/server/default.nix index bc1a6ea..3596f3a 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -15,5 +15,6 @@ ./caddy.nix ./rust_motd.nix ./minecraft.nix + ./adguard.nix ]; } From 3b5c8735be633544c9a1f1d22a5ade7c2274c0cd Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 5 Nov 2024 11:00:42 +0100 Subject: [PATCH 0800/1125] Services/rust_motd: add adguard status --- roles/server/adguard.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/adguard.nix b/roles/server/adguard.nix index e1bf922..ba9d995 100644 --- a/roles/server/adguard.nix +++ b/roles/server/adguard.nix @@ -37,4 +37,5 @@ in { ''; }; }; + programs.rust-motd.settings.service_status."AdGuard Home" = "adguardhome"; } From 32b291be200ad9ecc6e9e89fa04f149f5f44c7f7 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 5 Nov 2024 11:08:45 +0100 Subject: [PATCH 0801/1125] Server/rust_motd: add headscale status --- roles/server/headscale.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/headscale.nix b/roles/server/headscale.nix index 4575327..8619dd3 100644 --- a/roles/server/headscale.nix +++ b/roles/server/headscale.nix @@ -21,4 +21,5 @@ ''; }; }; + programs.rust-motd.settings.service_status.Headscale = "headscale"; } From fdad5d88bbf5942f89add50faf4e2ac7285e76ce Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 5 Nov 2024 19:22:35 +0100 Subject: [PATCH 0802/1125] Flake: backport headscale changes to stable nixpkgs --- flake.nix | 4 +- .../backport_unstable_headscale_changes.patch | 1757 +++++++++++++++++ 2 files changed, 1760 insertions(+), 1 deletion(-) create mode 100644 nixpkgs-patches/backport_unstable_headscale_changes.patch diff --git a/flake.nix b/flake.nix index 2832d46..18f8ed7 100644 --- a/flake.nix +++ b/flake.nix @@ -111,7 +111,9 @@ nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; src = nixpkgs-raw; - patches = []; + patches = [ + ./nixpkgs-patches/backport_unstable_headscale_changes.patch + ]; }; # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs {self = inputs.self;}; diff --git a/nixpkgs-patches/backport_unstable_headscale_changes.patch b/nixpkgs-patches/backport_unstable_headscale_changes.patch new file mode 100644 index 0000000..c173ef9 --- /dev/null +++ b/nixpkgs-patches/backport_unstable_headscale_changes.patch @@ -0,0 +1,1757 @@ +From 4a5c88eac3aaf1fb3d5ab15ee84787b9883c2465 Mon Sep 17 00:00:00 2001 +From: Kristoffer Dalby +Date: Fri, 6 Sep 2024 12:47:36 +0200 +Subject: [PATCH 1/8] nixos/headscale: modernize + +Signed-off-by: Kristoffer Dalby +--- + .../modules/services/networking/headscale.nix | 472 ++++++++++-------- + 1 file changed, 270 insertions(+), 202 deletions(-) + +diff --git a/nixos/modules/services/networking/headscale.nix b/nixos/modules/services/networking/headscale.nix +index ea66faeabbf2..645d4fe9c069 100644 +--- a/nixos/modules/services/networking/headscale.nix ++++ b/nixos/modules/services/networking/headscale.nix +@@ -1,8 +1,7 @@ +-{ +- config, +- lib, +- pkgs, +- ... ++{ config ++, lib ++, pkgs ++, ... + }: + with lib; let + cfg = config.services.headscale; +@@ -10,9 +9,19 @@ with lib; let + dataDir = "/var/lib/headscale"; + runDir = "/run/headscale"; + +- settingsFormat = pkgs.formats.yaml {}; ++ cliConfig = { ++ # Turn off update checks since the origin of our package ++ # is nixpkgs and not Github. ++ disable_check_updates = true; ++ ++ unix_socket = "${runDir}/headscale.sock"; ++ }; ++ ++ settingsFormat = pkgs.formats.yaml { }; + configFile = settingsFormat.generate "headscale.yaml" cfg.settings; +-in { ++ cliConfigFile = settingsFormat.generate "headscale.yaml" cliConfig; ++in ++{ + options = { + services.headscale = { + enable = mkEnableOption "headscale, Open Source coordination server for Tailscale"; +@@ -84,14 +93,6 @@ in { + example = "https://myheadscale.example.com:443"; + }; + +- private_key_path = mkOption { +- type = types.path; +- default = "${dataDir}/private.key"; +- description = '' +- Path to private key file, generated automatically if it does not exist. +- ''; +- }; +- + noise.private_key_path = mkOption { + type = types.path; + default = "${dataDir}/noise_private.key"; +@@ -100,10 +101,44 @@ in { + ''; + }; + ++ prefixes = ++ let ++ prefDesc = '' ++ Each prefix consists of either an IPv4 or IPv6 address, ++ and the associated prefix length, delimited by a slash. ++ It must be within IP ranges supported by the Tailscale ++ client - i.e., subnets of 100.64.0.0/10 and fd7a:115c:a1e0::/48. ++ ''; ++ in ++ { ++ v4 = mkOption { ++ type = types.str; ++ default = "100.64.0.0/10"; ++ description = prefDesc; ++ }; ++ ++ v6 = mkOption { ++ type = types.str; ++ default = "fd7a:115c:a1e0::/48"; ++ description = prefDesc; ++ }; ++ ++ allocation = mkOption { ++ type = types.enum [ "sequential" "random" ]; ++ example = "random"; ++ default = "sequential"; ++ description = '' ++ Strategy used for allocation of IPs to nodes, available options: ++ - sequential (default): assigns the next free IP from the previous given IP. ++ - random: assigns the next free IP from a pseudo-random IP generator (crypto/rand). ++ ''; ++ }; ++ }; ++ + derp = { + urls = mkOption { + type = types.listOf types.str; +- default = ["https://controlplane.tailscale.com/derpmap/default"]; ++ default = [ "https://controlplane.tailscale.com/derpmap/default" ]; + description = '' + List of urls containing DERP maps. + See [How Tailscale works](https://tailscale.com/blog/how-tailscale-works/) for more information on DERP maps. +@@ -112,7 +147,7 @@ in { + + paths = mkOption { + type = types.listOf types.path; +- default = []; ++ default = [ ]; + description = '' + List of file paths containing DERP maps. + See [How Tailscale works](https://tailscale.com/blog/how-tailscale-works/) for more information on DERP maps. +@@ -136,6 +171,14 @@ in { + ''; + example = "5m"; + }; ++ ++ server.private_key_path = lib.mkOption { ++ type = lib.types.path; ++ default = "${dataDir}/derp_server_private.key"; ++ description = '' ++ Path to derp private key file, generated automatically if it does not exist. ++ ''; ++ }; + }; + + ephemeral_node_inactivity_timeout = mkOption { +@@ -147,102 +190,98 @@ in { + example = "5m"; + }; + +- db_type = mkOption { +- type = types.enum ["sqlite3" "postgres"]; +- example = "postgres"; +- default = "sqlite3"; +- description = "Database engine to use."; +- }; +- +- db_host = mkOption { +- type = types.nullOr types.str; +- default = null; +- example = "127.0.0.1"; +- description = "Database host address."; +- }; +- +- db_port = mkOption { +- type = types.nullOr types.port; +- default = null; +- example = 3306; +- description = "Database host port."; +- }; ++ database = { ++ type = mkOption { ++ type = types.enum [ "sqlite" "sqlite3" "postgres" ]; ++ example = "postgres"; ++ default = "sqlite"; ++ description = '' ++ Database engine to use. ++ Please note that using Postgres is highly discouraged as it is only supported for legacy reasons. ++ All new development, testing and optimisations are done with SQLite in mind. ++ ''; ++ }; + +- db_name = mkOption { +- type = types.nullOr types.str; +- default = null; +- example = "headscale"; +- description = "Database name."; +- }; ++ sqlite = { ++ path = mkOption { ++ type = types.nullOr types.str; ++ default = "${dataDir}/db.sqlite"; ++ description = "Path to the sqlite3 database file."; ++ }; + +- db_user = mkOption { +- type = types.nullOr types.str; +- default = null; +- example = "headscale"; +- description = "Database user."; +- }; ++ write_ahead_log = mkOption { ++ type = types.bool; ++ default = true; ++ description = '' ++ Enable WAL mode for SQLite. This is recommended for production environments. ++ https://www.sqlite.org/wal.html ++ ''; ++ example = true; ++ }; ++ }; + +- db_password_file = mkOption { +- type = types.nullOr types.path; +- default = null; +- example = "/run/keys/headscale-dbpassword"; +- description = '' +- A file containing the password corresponding to +- {option}`database.user`. +- ''; +- }; ++ postgres = { ++ host = mkOption { ++ type = types.nullOr types.str; ++ default = null; ++ example = "127.0.0.1"; ++ description = "Database host address."; ++ }; + +- db_path = mkOption { +- type = types.nullOr types.str; +- default = "${dataDir}/db.sqlite"; +- description = "Path to the sqlite3 database file."; +- }; ++ port = mkOption { ++ type = types.nullOr types.port; ++ default = null; ++ example = 3306; ++ description = "Database host port."; ++ }; + +- log.level = mkOption { +- type = types.str; +- default = "info"; +- description = '' +- headscale log level. +- ''; +- example = "debug"; +- }; ++ name = mkOption { ++ type = types.nullOr types.str; ++ default = null; ++ example = "headscale"; ++ description = "Database name."; ++ }; + +- log.format = mkOption { +- type = types.str; +- default = "text"; +- description = '' +- headscale log format. +- ''; +- example = "json"; +- }; ++ user = mkOption { ++ type = types.nullOr types.str; ++ default = null; ++ example = "headscale"; ++ description = "Database user."; ++ }; + +- dns_config = { +- nameservers = mkOption { +- type = types.listOf types.str; +- default = ["1.1.1.1"]; +- description = '' +- List of nameservers to pass to Tailscale clients. +- ''; ++ password_file = mkOption { ++ type = types.nullOr types.path; ++ default = null; ++ example = "/run/keys/headscale-dbpassword"; ++ description = '' ++ A file containing the password corresponding to ++ {option}`database.user`. ++ ''; ++ }; + }; ++ }; + +- override_local_dns = mkOption { +- type = types.bool; +- default = false; ++ log = { ++ level = mkOption { ++ type = types.str; ++ default = "info"; + description = '' +- Whether to use [Override local DNS](https://tailscale.com/kb/1054/dns/). ++ headscale log level. + ''; +- example = true; ++ example = "debug"; + }; + +- domains = mkOption { +- type = types.listOf types.str; +- default = []; ++ format = mkOption { ++ type = types.str; ++ default = "text"; + description = '' +- Search domains to inject to Tailscale clients. ++ headscale log format. + ''; +- example = ["mydomain.internal"]; ++ example = "json"; + }; ++ }; + ++ dns = { + magic_dns = mkOption { + type = types.bool; + default = true; +@@ -264,6 +303,25 @@ in { + `myhost.mynamespace.example.com`). + ''; + }; ++ ++ nameservers = { ++ global = mkOption { ++ type = types.listOf types.str; ++ default = [ ]; ++ description = '' ++ List of nameservers to pass to Tailscale clients. ++ ''; ++ }; ++ }; ++ ++ search_domains = mkOption { ++ type = types.listOf types.str; ++ default = [ ]; ++ description = '' ++ Search domains to inject to Tailscale clients. ++ ''; ++ example = [ "mydomain.internal" ]; ++ }; + }; + + oidc = { +@@ -294,7 +352,7 @@ in { + + scope = mkOption { + type = types.listOf types.str; +- default = ["openid" "profile" "email"]; ++ default = [ "openid" "profile" "email" ]; + description = '' + Scopes used in the OIDC flow. + ''; +@@ -348,7 +406,7 @@ in { + }; + + tls_letsencrypt_challenge_type = mkOption { +- type = types.enum ["TLS-ALPN-01" "HTTP-01"]; ++ type = types.enum [ "TLS-ALPN-01" "HTTP-01" ]; + default = "HTTP-01"; + description = '' + Type of ACME challenge to use, currently supported types: +@@ -382,12 +440,24 @@ in { + ''; + }; + +- acl_policy_path = mkOption { +- type = types.nullOr types.path; +- default = null; +- description = '' +- Path to a file containing ACL policies. +- ''; ++ policy = { ++ mode = mkOption { ++ type = types.enum [ "file" "database" ]; ++ default = "file"; ++ description = '' ++ The mode can be "file" or "database" that defines ++ where the ACL policies are stored and read from. ++ ''; ++ }; ++ ++ path = mkOption { ++ type = types.nullOr types.path; ++ default = null; ++ description = '' ++ If the mode is set to "file", the path to a ++ HuJSON file containing ACL policies. ++ ''; ++ }; + }; + }; + }; +@@ -396,64 +466,63 @@ in { + }; + + imports = [ +- # TODO address + port = listen_addr +- (mkRenamedOptionModule ["services" "headscale" "serverUrl"] ["services" "headscale" "settings" "server_url"]) +- (mkRenamedOptionModule ["services" "headscale" "privateKeyFile"] ["services" "headscale" "settings" "private_key_path"]) +- (mkRenamedOptionModule ["services" "headscale" "derp" "urls"] ["services" "headscale" "settings" "derp" "urls"]) +- (mkRenamedOptionModule ["services" "headscale" "derp" "paths"] ["services" "headscale" "settings" "derp" "paths"]) +- (mkRenamedOptionModule ["services" "headscale" "derp" "autoUpdate"] ["services" "headscale" "settings" "derp" "auto_update_enable"]) +- (mkRenamedOptionModule ["services" "headscale" "derp" "updateFrequency"] ["services" "headscale" "settings" "derp" "update_frequency"]) +- (mkRenamedOptionModule ["services" "headscale" "ephemeralNodeInactivityTimeout"] ["services" "headscale" "settings" "ephemeral_node_inactivity_timeout"]) +- (mkRenamedOptionModule ["services" "headscale" "database" "type"] ["services" "headscale" "settings" "db_type"]) +- (mkRenamedOptionModule ["services" "headscale" "database" "path"] ["services" "headscale" "settings" "db_path"]) +- (mkRenamedOptionModule ["services" "headscale" "database" "host"] ["services" "headscale" "settings" "db_host"]) +- (mkRenamedOptionModule ["services" "headscale" "database" "port"] ["services" "headscale" "settings" "db_port"]) +- (mkRenamedOptionModule ["services" "headscale" "database" "name"] ["services" "headscale" "settings" "db_name"]) +- (mkRenamedOptionModule ["services" "headscale" "database" "user"] ["services" "headscale" "settings" "db_user"]) +- (mkRenamedOptionModule ["services" "headscale" "database" "passwordFile"] ["services" "headscale" "settings" "db_password_file"]) +- (mkRenamedOptionModule ["services" "headscale" "logLevel"] ["services" "headscale" "settings" "log" "level"]) +- (mkRenamedOptionModule ["services" "headscale" "dns" "nameservers"] ["services" "headscale" "settings" "dns_config" "nameservers"]) +- (mkRenamedOptionModule ["services" "headscale" "dns" "domains"] ["services" "headscale" "settings" "dns_config" "domains"]) +- (mkRenamedOptionModule ["services" "headscale" "dns" "magicDns"] ["services" "headscale" "settings" "dns_config" "magic_dns"]) +- (mkRenamedOptionModule ["services" "headscale" "dns" "baseDomain"] ["services" "headscale" "settings" "dns_config" "base_domain"]) +- (mkRenamedOptionModule ["services" "headscale" "openIdConnect" "issuer"] ["services" "headscale" "settings" "oidc" "issuer"]) +- (mkRenamedOptionModule ["services" "headscale" "openIdConnect" "clientId"] ["services" "headscale" "settings" "oidc" "client_id"]) +- (mkRenamedOptionModule ["services" "headscale" "openIdConnect" "clientSecretFile"] ["services" "headscale" "settings" "oidc" "client_secret_path"]) +- (mkRenamedOptionModule ["services" "headscale" "tls" "letsencrypt" "hostname"] ["services" "headscale" "settings" "tls_letsencrypt_hostname"]) +- (mkRenamedOptionModule ["services" "headscale" "tls" "letsencrypt" "challengeType"] ["services" "headscale" "settings" "tls_letsencrypt_challenge_type"]) +- (mkRenamedOptionModule ["services" "headscale" "tls" "letsencrypt" "httpListen"] ["services" "headscale" "settings" "tls_letsencrypt_listen"]) +- (mkRenamedOptionModule ["services" "headscale" "tls" "certFile"] ["services" "headscale" "settings" "tls_cert_path"]) +- (mkRenamedOptionModule ["services" "headscale" "tls" "keyFile"] ["services" "headscale" "settings" "tls_key_path"]) +- (mkRenamedOptionModule ["services" "headscale" "aclPolicyFile"] ["services" "headscale" "settings" "acl_policy_path"]) +- +- (mkRemovedOptionModule ["services" "headscale" "openIdConnect" "domainMap"] '' ++ (mkRenamedOptionModule [ "services" "headscale" "serverUrl" ] [ "services" "headscale" "settings" "server_url" ]) ++ (mkRenamedOptionModule [ "services" "headscale" "derp" "urls" ] [ "services" "headscale" "settings" "derp" "urls" ]) ++ (mkRenamedOptionModule [ "services" "headscale" "derp" "paths" ] [ "services" "headscale" "settings" "derp" "paths" ]) ++ (mkRenamedOptionModule [ "services" "headscale" "derp" "autoUpdate" ] [ "services" "headscale" "settings" "derp" "auto_update_enable" ]) ++ (mkRenamedOptionModule [ "services" "headscale" "derp" "updateFrequency" ] [ "services" "headscale" "settings" "derp" "update_frequency" ]) ++ (mkRenamedOptionModule [ "services" "headscale" "ephemeralNodeInactivityTimeout" ] [ "services" "headscale" "settings" "ephemeral_node_inactivity_timeout" ]) ++ ++ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_type"] ["services" "headscale" "settings" "database" "type"]) ++ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_path"] ["services" "headscale" "settings" "database" "sqlite" "path"]) ++ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_host"] ["services" "headscale" "settings" "database" "postgres" "host"]) ++ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_port"] ["services" "headscale" "settings" "database" "postgres" "port"]) ++ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_name"] ["services" "headscale" "settings" "database" "postgres" "name"]) ++ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_user"] ["services" "headscale" "settings" "database" "postgres" "user"]) ++ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_password_file"] ["services" "headscale" "settings" "database" "postgres" "password_file"]) ++ ++ (mkRenamedOptionModule [ "services" "headscale" "logLevel" ] [ "services" "headscale" "settings" "log" "level" ]) ++ ++ # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "nameservers"] ["services" "headscale" "settings" "dns" "nameservers" "global"]) ++ # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "domains"] ["services" "headscale" "settings" "dns" "search_domains"]) ++ # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "magic_dns"] ["services" "headscale" "settings" "dns" "magic_dns"]) ++ # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "base_domain"] ["services" "headscale" "settings" "dns" "base_domain"]) ++ ++ (mkRenamedOptionModule [ "services" "headscale" "openIdConnect" "issuer" ] [ "services" "headscale" "settings" "oidc" "issuer" ]) ++ (mkRenamedOptionModule [ "services" "headscale" "openIdConnect" "clientId" ] [ "services" "headscale" "settings" "oidc" "client_id" ]) ++ (mkRenamedOptionModule [ "services" "headscale" "openIdConnect" "clientSecretFile" ] [ "services" "headscale" "settings" "oidc" "client_secret_path" ]) ++ (mkRenamedOptionModule [ "services" "headscale" "tls" "letsencrypt" "hostname" ] [ "services" "headscale" "settings" "tls_letsencrypt_hostname" ]) ++ (mkRenamedOptionModule [ "services" "headscale" "tls" "letsencrypt" "challengeType" ] [ "services" "headscale" "settings" "tls_letsencrypt_challenge_type" ]) ++ (mkRenamedOptionModule [ "services" "headscale" "tls" "letsencrypt" "httpListen" ] [ "services" "headscale" "settings" "tls_letsencrypt_listen" ]) ++ (mkRenamedOptionModule [ "services" "headscale" "tls" "certFile" ] [ "services" "headscale" "settings" "tls_cert_path" ]) ++ (mkRenamedOptionModule [ "services" "headscale" "tls" "keyFile" ] [ "services" "headscale" "settings" "tls_key_path" ]) ++ ++ # (mkRenamedOptionModule ["services" "headscale" "settings" "acl_policy_path"] ["services" "headscale" "settings" "policy" "path"]) ++ ++ (mkRemovedOptionModule [ "services" "headscale" "openIdConnect" "domainMap" ] '' + Headscale no longer uses domain_map. If you're using an old version of headscale you can still set this option via services.headscale.settings.oidc.domain_map. + '') + ]; + + config = mkIf cfg.enable { +- services.headscale.settings = { +- listen_addr = mkDefault "${cfg.address}:${toString cfg.port}"; ++ services.headscale.settings = mkMerge [ ++ cliConfig ++ { ++ listen_addr = mkDefault "${cfg.address}:${toString cfg.port}"; + +- # Turn off update checks since the origin of our package +- # is nixpkgs and not Github. +- disable_check_updates = true; +- +- unix_socket = "${runDir}/headscale.sock"; +- +- tls_letsencrypt_cache_dir = "${dataDir}/.cache"; +- }; ++ tls_letsencrypt_cache_dir = "${dataDir}/.cache"; ++ } ++ ]; + + environment = { +- # Setup the headscale configuration in a known path in /etc to +- # allow both the Server and the Client use it to find the socket +- # for communication. +- etc."headscale/config.yaml".source = configFile; ++ # Headscale CLI needs a minimal config to be able to locate the unix socket ++ # to talk to the server instance. ++ etc."headscale/config.yaml".source = cliConfigFile; + + systemPackages = [ cfg.package ]; + }; + +- users.groups.headscale = mkIf (cfg.group == "headscale") {}; ++ users.groups.headscale = mkIf (cfg.group == "headscale") { }; + + users.users.headscale = mkIf (cfg.user == "headscale") { + description = "headscale user"; +@@ -465,65 +534,64 @@ in { + systemd.services.headscale = { + description = "headscale coordination server for Tailscale"; + wants = [ "network-online.target" ]; +- after = ["network-online.target"]; +- wantedBy = ["multi-user.target"]; +- restartTriggers = [configFile]; +- +- environment.GIN_MODE = "release"; ++ after = [ "network-online.target" ]; ++ wantedBy = [ "multi-user.target" ]; + + script = '' +- ${optionalString (cfg.settings.db_password_file != null) '' +- export HEADSCALE_DB_PASS="$(head -n1 ${escapeShellArg cfg.settings.db_password_file})" ++ ${optionalString (cfg.settings.database.postgres.password_file != null) '' ++ export HEADSCALE_DATABASE_POSTGRES_PASS="$(head -n1 ${escapeShellArg cfg.settings.database.postgres.password_file})" + ''} + +- exec ${cfg.package}/bin/headscale serve ++ exec ${lib.getExe cfg.package} serve --config ${configFile} + ''; + +- serviceConfig = let +- capabilityBoundingSet = ["CAP_CHOWN"] ++ optional (cfg.port < 1024) "CAP_NET_BIND_SERVICE"; +- in { +- Restart = "always"; +- Type = "simple"; +- User = cfg.user; +- Group = cfg.group; +- +- # Hardening options +- RuntimeDirectory = "headscale"; +- # Allow headscale group access so users can be added and use the CLI. +- RuntimeDirectoryMode = "0750"; +- +- StateDirectory = "headscale"; +- StateDirectoryMode = "0750"; +- +- ProtectSystem = "strict"; +- ProtectHome = true; +- PrivateTmp = true; +- PrivateDevices = true; +- ProtectKernelTunables = true; +- ProtectControlGroups = true; +- RestrictSUIDSGID = true; +- PrivateMounts = true; +- ProtectKernelModules = true; +- ProtectKernelLogs = true; +- ProtectHostname = true; +- ProtectClock = true; +- ProtectProc = "invisible"; +- ProcSubset = "pid"; +- RestrictNamespaces = true; +- RemoveIPC = true; +- UMask = "0077"; +- +- CapabilityBoundingSet = capabilityBoundingSet; +- AmbientCapabilities = capabilityBoundingSet; +- NoNewPrivileges = true; +- LockPersonality = true; +- RestrictRealtime = true; +- SystemCallFilter = ["@system-service" "~@privileged" "@chown"]; +- SystemCallArchitectures = "native"; +- RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX"; +- }; ++ serviceConfig = ++ let ++ capabilityBoundingSet = [ "CAP_CHOWN" ] ++ optional (cfg.port < 1024) "CAP_NET_BIND_SERVICE"; ++ in ++ { ++ Restart = "always"; ++ Type = "simple"; ++ User = cfg.user; ++ Group = cfg.group; ++ ++ # Hardening options ++ RuntimeDirectory = "headscale"; ++ # Allow headscale group access so users can be added and use the CLI. ++ RuntimeDirectoryMode = "0750"; ++ ++ StateDirectory = "headscale"; ++ StateDirectoryMode = "0750"; ++ ++ ProtectSystem = "strict"; ++ ProtectHome = true; ++ PrivateTmp = true; ++ PrivateDevices = true; ++ ProtectKernelTunables = true; ++ ProtectControlGroups = true; ++ RestrictSUIDSGID = true; ++ PrivateMounts = true; ++ ProtectKernelModules = true; ++ ProtectKernelLogs = true; ++ ProtectHostname = true; ++ ProtectClock = true; ++ ProtectProc = "invisible"; ++ ProcSubset = "pid"; ++ RestrictNamespaces = true; ++ RemoveIPC = true; ++ UMask = "0077"; ++ ++ CapabilityBoundingSet = capabilityBoundingSet; ++ AmbientCapabilities = capabilityBoundingSet; ++ NoNewPrivileges = true; ++ LockPersonality = true; ++ RestrictRealtime = true; ++ SystemCallFilter = [ "@system-service" "~@privileged" "@chown" ]; ++ SystemCallArchitectures = "native"; ++ RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX"; ++ }; + }; + }; + +- meta.maintainers = with maintainers; [kradalby misterio77]; ++ meta.maintainers = with maintainers; [ kradalby misterio77 ]; + } +-- +2.46.1 + + +From afff4fba9136ba0dbe8ff635cb3ead89d5240bf8 Mon Sep 17 00:00:00 2001 +From: Kristoffer Dalby +Date: Wed, 18 Sep 2024 10:24:19 +0100 +Subject: [PATCH 2/8] nixos/headscale: update module to headscale 0.23.0 + +Signed-off-by: Kristoffer Dalby +--- + .../modules/services/networking/headscale.nix | 445 +++++++++--------- + 1 file changed, 219 insertions(+), 226 deletions(-) + +diff --git a/nixos/modules/services/networking/headscale.nix b/nixos/modules/services/networking/headscale.nix +index 645d4fe9c069..622a13fe7b61 100644 +--- a/nixos/modules/services/networking/headscale.nix ++++ b/nixos/modules/services/networking/headscale.nix +@@ -1,9 +1,9 @@ +-{ config +-, lib +-, pkgs +-, ... +-}: +-with lib; let ++{ ++ config, ++ lib, ++ pkgs, ++ ... ++}: let + cfg = config.services.headscale; + + dataDir = "/var/lib/headscale"; +@@ -17,20 +17,19 @@ with lib; let + unix_socket = "${runDir}/headscale.sock"; + }; + +- settingsFormat = pkgs.formats.yaml { }; ++ settingsFormat = pkgs.formats.yaml {}; + configFile = settingsFormat.generate "headscale.yaml" cfg.settings; + cliConfigFile = settingsFormat.generate "headscale.yaml" cliConfig; +-in +-{ ++in { + options = { + services.headscale = { +- enable = mkEnableOption "headscale, Open Source coordination server for Tailscale"; ++ enable = lib.mkEnableOption "headscale, Open Source coordination server for Tailscale"; + +- package = mkPackageOption pkgs "headscale" { }; ++ package = lib.mkPackageOption pkgs "headscale" {}; + +- user = mkOption { ++ user = lib.mkOption { + default = "headscale"; +- type = types.str; ++ type = lib.types.str; + description = '' + User account under which headscale runs. + +@@ -42,9 +41,9 @@ in + ''; + }; + +- group = mkOption { ++ group = lib.mkOption { + default = "headscale"; +- type = types.str; ++ type = lib.types.str; + description = '' + Group under which headscale runs. + +@@ -56,8 +55,8 @@ in + ''; + }; + +- address = mkOption { +- type = types.str; ++ address = lib.mkOption { ++ type = lib.types.str; + default = "127.0.0.1"; + description = '' + Listening address of headscale. +@@ -65,8 +64,8 @@ in + example = "0.0.0.0"; + }; + +- port = mkOption { +- type = types.port; ++ port = lib.mkOption { ++ type = lib.types.port; + default = 8080; + description = '' + Listening port of headscale. +@@ -74,18 +73,33 @@ in + example = 443; + }; + +- settings = mkOption { ++ settings = lib.mkOption { + description = '' + Overrides to {file}`config.yaml` as a Nix attribute set. + Check the [example config](https://github.com/juanfont/headscale/blob/main/config-example.yaml) + for possible options. + ''; +- type = types.submodule { ++ type = lib.types.submodule { + freeformType = settingsFormat.type; + ++ imports = with lib; [ ++ (mkAliasOptionModule ["acl_policy_path"] ["policy" "path"]) ++ (mkAliasOptionModule ["db_host"] ["database" "postgres" "host"]) ++ (mkAliasOptionModule ["db_name"] ["database" "postgres" "name"]) ++ (mkAliasOptionModule ["db_password_file"] ["database" "postgres" "password_file"]) ++ (mkAliasOptionModule ["db_path"] ["database" "sqlite" "path"]) ++ (mkAliasOptionModule ["db_port"] ["database" "postgres" "port"]) ++ (mkAliasOptionModule ["db_type"] ["database" "type"]) ++ (mkAliasOptionModule ["db_user"] ["database" "postgres" "user"]) ++ (mkAliasOptionModule ["dns_config" "base_domain"] ["dns" "base_domain"]) ++ (mkAliasOptionModule ["dns_config" "domains"] ["dns" "search_domains"]) ++ (mkAliasOptionModule ["dns_config" "magic_dns"] ["dns" "magic_dns"]) ++ (mkAliasOptionModule ["dns_config" "nameservers"] ["dns" "nameservers" "global"]) ++ ]; ++ + options = { +- server_url = mkOption { +- type = types.str; ++ server_url = lib.mkOption { ++ type = lib.types.str; + default = "http://127.0.0.1:8080"; + description = '' + The url clients will connect to. +@@ -93,69 +107,67 @@ in + example = "https://myheadscale.example.com:443"; + }; + +- noise.private_key_path = mkOption { +- type = types.path; ++ noise.private_key_path = lib.mkOption { ++ type = lib.types.path; + default = "${dataDir}/noise_private.key"; + description = '' + Path to noise private key file, generated automatically if it does not exist. + ''; + }; + +- prefixes = +- let +- prefDesc = '' +- Each prefix consists of either an IPv4 or IPv6 address, +- and the associated prefix length, delimited by a slash. +- It must be within IP ranges supported by the Tailscale +- client - i.e., subnets of 100.64.0.0/10 and fd7a:115c:a1e0::/48. +- ''; +- in +- { +- v4 = mkOption { +- type = types.str; +- default = "100.64.0.0/10"; +- description = prefDesc; +- }; ++ prefixes = let ++ prefDesc = '' ++ Each prefix consists of either an IPv4 or IPv6 address, ++ and the associated prefix length, delimited by a slash. ++ It must be within IP ranges supported by the Tailscale ++ client - i.e., subnets of 100.64.0.0/10 and fd7a:115c:a1e0::/48. ++ ''; ++ in { ++ v4 = lib.mkOption { ++ type = lib.types.str; ++ default = "100.64.0.0/10"; ++ description = prefDesc; ++ }; + +- v6 = mkOption { +- type = types.str; +- default = "fd7a:115c:a1e0::/48"; +- description = prefDesc; +- }; ++ v6 = lib.mkOption { ++ type = lib.types.str; ++ default = "fd7a:115c:a1e0::/48"; ++ description = prefDesc; ++ }; + +- allocation = mkOption { +- type = types.enum [ "sequential" "random" ]; +- example = "random"; +- default = "sequential"; +- description = '' +- Strategy used for allocation of IPs to nodes, available options: +- - sequential (default): assigns the next free IP from the previous given IP. +- - random: assigns the next free IP from a pseudo-random IP generator (crypto/rand). +- ''; +- }; ++ allocation = lib.mkOption { ++ type = lib.types.enum ["sequential" "random"]; ++ example = "random"; ++ default = "sequential"; ++ description = '' ++ Strategy used for allocation of IPs to nodes, available options: ++ - sequential (default): assigns the next free IP from the previous given IP. ++ - random: assigns the next free IP from a pseudo-random IP generator (crypto/rand). ++ ''; + }; ++ }; + + derp = { +- urls = mkOption { +- type = types.listOf types.str; +- default = [ "https://controlplane.tailscale.com/derpmap/default" ]; ++ urls = lib.mkOption { ++ type = lib.types.listOf lib.types.str; ++ default = ["https://controlplane.tailscale.com/derpmap/default"]; + description = '' + List of urls containing DERP maps. + See [How Tailscale works](https://tailscale.com/blog/how-tailscale-works/) for more information on DERP maps. + ''; + }; + +- paths = mkOption { +- type = types.listOf types.path; +- default = [ ]; ++ paths = lib.mkOption { ++ type = lib.types.listOf lib.types.path; ++ default = []; + description = '' + List of file paths containing DERP maps. + See [How Tailscale works](https://tailscale.com/blog/how-tailscale-works/) for more information on DERP maps. + ''; + }; + +- auto_update_enable = mkOption { +- type = types.bool; ++ auto_update_enable = lib.mkOption { ++ type = lib.types.bool; + default = true; + description = '' + Whether to automatically update DERP maps on a set frequency. +@@ -163,8 +175,8 @@ in + example = false; + }; + +- update_frequency = mkOption { +- type = types.str; ++ update_frequency = lib.mkOption { ++ type = lib.types.str; + default = "24h"; + description = '' + Frequency to update DERP maps. +@@ -181,8 +193,8 @@ in + }; + }; + +- ephemeral_node_inactivity_timeout = mkOption { +- type = types.str; ++ ephemeral_node_inactivity_timeout = lib.mkOption { ++ type = lib.types.str; + default = "30m"; + description = '' + Time before an inactive ephemeral node is deleted. +@@ -191,8 +203,8 @@ in + }; + + database = { +- type = mkOption { +- type = types.enum [ "sqlite" "sqlite3" "postgres" ]; ++ type = lib.mkOption { ++ type = lib.types.enum ["sqlite" "sqlite3" "postgres"]; + example = "postgres"; + default = "sqlite"; + description = '' +@@ -203,14 +215,14 @@ in + }; + + sqlite = { +- path = mkOption { +- type = types.nullOr types.str; ++ path = lib.mkOption { ++ type = lib.types.nullOr lib.types.str; + default = "${dataDir}/db.sqlite"; + description = "Path to the sqlite3 database file."; + }; + +- write_ahead_log = mkOption { +- type = types.bool; ++ write_ahead_log = lib.mkOption { ++ type = lib.types.bool; + default = true; + description = '' + Enable WAL mode for SQLite. This is recommended for production environments. +@@ -221,36 +233,36 @@ in + }; + + postgres = { +- host = mkOption { +- type = types.nullOr types.str; ++ host = lib.mkOption { ++ type = lib.types.nullOr lib.types.str; + default = null; + example = "127.0.0.1"; + description = "Database host address."; + }; + +- port = mkOption { +- type = types.nullOr types.port; ++ port = lib.mkOption { ++ type = lib.types.nullOr lib.types.port; + default = null; + example = 3306; + description = "Database host port."; + }; + +- name = mkOption { +- type = types.nullOr types.str; ++ name = lib.mkOption { ++ type = lib.types.nullOr lib.types.str; + default = null; + example = "headscale"; + description = "Database name."; + }; + +- user = mkOption { +- type = types.nullOr types.str; ++ user = lib.mkOption { ++ type = lib.types.nullOr lib.types.str; + default = null; + example = "headscale"; + description = "Database user."; + }; + +- password_file = mkOption { +- type = types.nullOr types.path; ++ password_file = lib.mkOption { ++ type = lib.types.nullOr lib.types.path; + default = null; + example = "/run/keys/headscale-dbpassword"; + description = '' +@@ -262,8 +274,8 @@ in + }; + + log = { +- level = mkOption { +- type = types.str; ++ level = lib.mkOption { ++ type = lib.types.str; + default = "info"; + description = '' + headscale log level. +@@ -271,8 +283,8 @@ in + example = "debug"; + }; + +- format = mkOption { +- type = types.str; ++ format = lib.mkOption { ++ type = lib.types.str; + default = "text"; + description = '' + headscale log format. +@@ -282,8 +294,8 @@ in + }; + + dns = { +- magic_dns = mkOption { +- type = types.bool; ++ magic_dns = lib.mkOption { ++ type = lib.types.bool; + default = true; + description = '' + Whether to use [MagicDNS](https://tailscale.com/kb/1081/magicdns/). +@@ -292,8 +304,8 @@ in + example = false; + }; + +- base_domain = mkOption { +- type = types.str; ++ base_domain = lib.mkOption { ++ type = lib.types.str; + default = ""; + description = '' + Defines the base domain to create the hostnames for MagicDNS. +@@ -305,28 +317,28 @@ in + }; + + nameservers = { +- global = mkOption { +- type = types.listOf types.str; +- default = [ ]; ++ global = lib.mkOption { ++ type = lib.types.listOf lib.types.str; ++ default = []; + description = '' + List of nameservers to pass to Tailscale clients. + ''; + }; + }; + +- search_domains = mkOption { +- type = types.listOf types.str; +- default = [ ]; ++ search_domains = lib.mkOption { ++ type = lib.types.listOf lib.types.str; ++ default = []; + description = '' + Search domains to inject to Tailscale clients. + ''; +- example = [ "mydomain.internal" ]; ++ example = ["mydomain.internal"]; + }; + }; + + oidc = { +- issuer = mkOption { +- type = types.str; ++ issuer = lib.mkOption { ++ type = lib.types.str; + default = ""; + description = '' + URL to OpenID issuer. +@@ -334,33 +346,33 @@ in + example = "https://openid.example.com"; + }; + +- client_id = mkOption { +- type = types.str; ++ client_id = lib.mkOption { ++ type = lib.types.str; + default = ""; + description = '' + OpenID Connect client ID. + ''; + }; + +- client_secret_path = mkOption { +- type = types.nullOr types.str; ++ client_secret_path = lib.mkOption { ++ type = lib.types.nullOr lib.types.str; + default = null; + description = '' + Path to OpenID Connect client secret file. Expands environment variables in format ''${VAR}. + ''; + }; + +- scope = mkOption { +- type = types.listOf types.str; +- default = [ "openid" "profile" "email" ]; ++ scope = lib.mkOption { ++ type = lib.types.listOf lib.types.str; ++ default = ["openid" "profile" "email"]; + description = '' + Scopes used in the OIDC flow. + ''; + }; + +- extra_params = mkOption { +- type = types.attrsOf types.str; +- default = { }; ++ extra_params = lib.mkOption { ++ type = lib.types.attrsOf lib.types.str; ++ default = {}; + description = '' + Custom query parameters to send with the Authorize Endpoint request. + ''; +@@ -369,27 +381,27 @@ in + }; + }; + +- allowed_domains = mkOption { +- type = types.listOf types.str; +- default = [ ]; ++ allowed_domains = lib.mkOption { ++ type = lib.types.listOf lib.types.str; ++ default = []; + description = '' + Allowed principal domains. if an authenticated user's domain + is not in this list authentication request will be rejected. + ''; +- example = [ "example.com" ]; ++ example = ["example.com"]; + }; + +- allowed_users = mkOption { +- type = types.listOf types.str; +- default = [ ]; ++ allowed_users = lib.mkOption { ++ type = lib.types.listOf lib.types.str; ++ default = []; + description = '' + Users allowed to authenticate even if not in allowedDomains. + ''; +- example = [ "alice@example.com" ]; ++ example = ["alice@example.com"]; + }; + +- strip_email_domain = mkOption { +- type = types.bool; ++ strip_email_domain = lib.mkOption { ++ type = lib.types.bool; + default = true; + description = '' + Whether the domain part of the email address should be removed when generating namespaces. +@@ -397,16 +409,16 @@ in + }; + }; + +- tls_letsencrypt_hostname = mkOption { +- type = types.nullOr types.str; ++ tls_letsencrypt_hostname = lib.mkOption { ++ type = lib.types.nullOr lib.types.str; + default = ""; + description = '' + Domain name to request a TLS certificate for. + ''; + }; + +- tls_letsencrypt_challenge_type = mkOption { +- type = types.enum [ "TLS-ALPN-01" "HTTP-01" ]; ++ tls_letsencrypt_challenge_type = lib.mkOption { ++ type = lib.types.enum ["TLS-ALPN-01" "HTTP-01"]; + default = "HTTP-01"; + description = '' + Type of ACME challenge to use, currently supported types: +@@ -414,8 +426,8 @@ in + ''; + }; + +- tls_letsencrypt_listen = mkOption { +- type = types.nullOr types.str; ++ tls_letsencrypt_listen = lib.mkOption { ++ type = lib.types.nullOr lib.types.str; + default = ":http"; + description = '' + When HTTP-01 challenge is chosen, letsencrypt must set up a +@@ -424,16 +436,16 @@ in + ''; + }; + +- tls_cert_path = mkOption { +- type = types.nullOr types.path; ++ tls_cert_path = lib.mkOption { ++ type = lib.types.nullOr lib.types.path; + default = null; + description = '' + Path to already created certificate. + ''; + }; + +- tls_key_path = mkOption { +- type = types.nullOr types.path; ++ tls_key_path = lib.mkOption { ++ type = lib.types.nullOr lib.types.path; + default = null; + description = '' + Path to key for already created certificate. +@@ -441,8 +453,8 @@ in + }; + + policy = { +- mode = mkOption { +- type = types.enum [ "file" "database" ]; ++ mode = lib.mkOption { ++ type = lib.types.enum ["file" "database"]; + default = "file"; + description = '' + The mode can be "file" or "database" that defines +@@ -450,8 +462,8 @@ in + ''; + }; + +- path = mkOption { +- type = types.nullOr types.path; ++ path = lib.mkOption { ++ type = lib.types.nullOr lib.types.path; + default = null; + description = '' + If the mode is set to "file", the path to a +@@ -465,50 +477,33 @@ in + }; + }; + +- imports = [ +- (mkRenamedOptionModule [ "services" "headscale" "serverUrl" ] [ "services" "headscale" "settings" "server_url" ]) +- (mkRenamedOptionModule [ "services" "headscale" "derp" "urls" ] [ "services" "headscale" "settings" "derp" "urls" ]) +- (mkRenamedOptionModule [ "services" "headscale" "derp" "paths" ] [ "services" "headscale" "settings" "derp" "paths" ]) +- (mkRenamedOptionModule [ "services" "headscale" "derp" "autoUpdate" ] [ "services" "headscale" "settings" "derp" "auto_update_enable" ]) +- (mkRenamedOptionModule [ "services" "headscale" "derp" "updateFrequency" ] [ "services" "headscale" "settings" "derp" "update_frequency" ]) +- (mkRenamedOptionModule [ "services" "headscale" "ephemeralNodeInactivityTimeout" ] [ "services" "headscale" "settings" "ephemeral_node_inactivity_timeout" ]) +- +- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_type"] ["services" "headscale" "settings" "database" "type"]) +- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_path"] ["services" "headscale" "settings" "database" "sqlite" "path"]) +- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_host"] ["services" "headscale" "settings" "database" "postgres" "host"]) +- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_port"] ["services" "headscale" "settings" "database" "postgres" "port"]) +- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_name"] ["services" "headscale" "settings" "database" "postgres" "name"]) +- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_user"] ["services" "headscale" "settings" "database" "postgres" "user"]) +- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_password_file"] ["services" "headscale" "settings" "database" "postgres" "password_file"]) +- +- (mkRenamedOptionModule [ "services" "headscale" "logLevel" ] [ "services" "headscale" "settings" "log" "level" ]) +- +- # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "nameservers"] ["services" "headscale" "settings" "dns" "nameservers" "global"]) +- # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "domains"] ["services" "headscale" "settings" "dns" "search_domains"]) +- # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "magic_dns"] ["services" "headscale" "settings" "dns" "magic_dns"]) +- # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "base_domain"] ["services" "headscale" "settings" "dns" "base_domain"]) +- +- (mkRenamedOptionModule [ "services" "headscale" "openIdConnect" "issuer" ] [ "services" "headscale" "settings" "oidc" "issuer" ]) +- (mkRenamedOptionModule [ "services" "headscale" "openIdConnect" "clientId" ] [ "services" "headscale" "settings" "oidc" "client_id" ]) +- (mkRenamedOptionModule [ "services" "headscale" "openIdConnect" "clientSecretFile" ] [ "services" "headscale" "settings" "oidc" "client_secret_path" ]) +- (mkRenamedOptionModule [ "services" "headscale" "tls" "letsencrypt" "hostname" ] [ "services" "headscale" "settings" "tls_letsencrypt_hostname" ]) +- (mkRenamedOptionModule [ "services" "headscale" "tls" "letsencrypt" "challengeType" ] [ "services" "headscale" "settings" "tls_letsencrypt_challenge_type" ]) +- (mkRenamedOptionModule [ "services" "headscale" "tls" "letsencrypt" "httpListen" ] [ "services" "headscale" "settings" "tls_letsencrypt_listen" ]) +- (mkRenamedOptionModule [ "services" "headscale" "tls" "certFile" ] [ "services" "headscale" "settings" "tls_cert_path" ]) +- (mkRenamedOptionModule [ "services" "headscale" "tls" "keyFile" ] [ "services" "headscale" "settings" "tls_key_path" ]) +- +- # (mkRenamedOptionModule ["services" "headscale" "settings" "acl_policy_path"] ["services" "headscale" "settings" "policy" "path"]) +- +- (mkRemovedOptionModule [ "services" "headscale" "openIdConnect" "domainMap" ] '' ++ imports = with lib; [ ++ (mkRenamedOptionModule ["services" "headscale" "derp" "autoUpdate"] ["services" "headscale" "settings" "derp" "auto_update_enable"]) ++ (mkRenamedOptionModule ["services" "headscale" "derp" "paths"] ["services" "headscale" "settings" "derp" "paths"]) ++ (mkRenamedOptionModule ["services" "headscale" "derp" "updateFrequency"] ["services" "headscale" "settings" "derp" "update_frequency"]) ++ (mkRenamedOptionModule ["services" "headscale" "derp" "urls"] ["services" "headscale" "settings" "derp" "urls"]) ++ (mkRenamedOptionModule ["services" "headscale" "ephemeralNodeInactivityTimeout"] ["services" "headscale" "settings" "ephemeral_node_inactivity_timeout"]) ++ (mkRenamedOptionModule ["services" "headscale" "logLevel"] ["services" "headscale" "settings" "log" "level"]) ++ (mkRenamedOptionModule ["services" "headscale" "openIdConnect" "clientId"] ["services" "headscale" "settings" "oidc" "client_id"]) ++ (mkRenamedOptionModule ["services" "headscale" "openIdConnect" "clientSecretFile"] ["services" "headscale" "settings" "oidc" "client_secret_path"]) ++ (mkRenamedOptionModule ["services" "headscale" "openIdConnect" "issuer"] ["services" "headscale" "settings" "oidc" "issuer"]) ++ (mkRenamedOptionModule ["services" "headscale" "serverUrl"] ["services" "headscale" "settings" "server_url"]) ++ (mkRenamedOptionModule ["services" "headscale" "tls" "certFile"] ["services" "headscale" "settings" "tls_cert_path"]) ++ (mkRenamedOptionModule ["services" "headscale" "tls" "keyFile"] ["services" "headscale" "settings" "tls_key_path"]) ++ (mkRenamedOptionModule ["services" "headscale" "tls" "letsencrypt" "challengeType"] ["services" "headscale" "settings" "tls_letsencrypt_challenge_type"]) ++ (mkRenamedOptionModule ["services" "headscale" "tls" "letsencrypt" "hostname"] ["services" "headscale" "settings" "tls_letsencrypt_hostname"]) ++ (mkRenamedOptionModule ["services" "headscale" "tls" "letsencrypt" "httpListen"] ["services" "headscale" "settings" "tls_letsencrypt_listen"]) ++ ++ (mkRemovedOptionModule ["services" "headscale" "openIdConnect" "domainMap"] '' + Headscale no longer uses domain_map. If you're using an old version of headscale you can still set this option via services.headscale.settings.oidc.domain_map. + '') + ]; + +- config = mkIf cfg.enable { +- services.headscale.settings = mkMerge [ ++ config = lib.mkIf cfg.enable { ++ services.headscale.settings = lib.mkMerge [ + cliConfig + { +- listen_addr = mkDefault "${cfg.address}:${toString cfg.port}"; ++ listen_addr = lib.mkDefault "${cfg.address}:${toString cfg.port}"; + + tls_letsencrypt_cache_dir = "${dataDir}/.cache"; + } +@@ -519,12 +514,12 @@ in + # to talk to the server instance. + etc."headscale/config.yaml".source = cliConfigFile; + +- systemPackages = [ cfg.package ]; ++ systemPackages = [cfg.package]; + }; + +- users.groups.headscale = mkIf (cfg.group == "headscale") { }; ++ users.groups.headscale = lib.mkIf (cfg.group == "headscale") {}; + +- users.users.headscale = mkIf (cfg.user == "headscale") { ++ users.users.headscale = lib.mkIf (cfg.user == "headscale") { + description = "headscale user"; + home = dataDir; + group = cfg.group; +@@ -533,65 +528,63 @@ in + + systemd.services.headscale = { + description = "headscale coordination server for Tailscale"; +- wants = [ "network-online.target" ]; +- after = [ "network-online.target" ]; +- wantedBy = [ "multi-user.target" ]; ++ wants = ["network-online.target"]; ++ after = ["network-online.target"]; ++ wantedBy = ["multi-user.target"]; + + script = '' +- ${optionalString (cfg.settings.database.postgres.password_file != null) '' +- export HEADSCALE_DATABASE_POSTGRES_PASS="$(head -n1 ${escapeShellArg cfg.settings.database.postgres.password_file})" ++ ${lib.optionalString (cfg.settings.database.postgres.password_file != null) '' ++ export HEADSCALE_DATABASE_POSTGRES_PASS="$(head -n1 ${lib.escapeShellArg cfg.settings.database.postgres.password_file})" + ''} + + exec ${lib.getExe cfg.package} serve --config ${configFile} + ''; + +- serviceConfig = +- let +- capabilityBoundingSet = [ "CAP_CHOWN" ] ++ optional (cfg.port < 1024) "CAP_NET_BIND_SERVICE"; +- in +- { +- Restart = "always"; +- Type = "simple"; +- User = cfg.user; +- Group = cfg.group; +- +- # Hardening options +- RuntimeDirectory = "headscale"; +- # Allow headscale group access so users can be added and use the CLI. +- RuntimeDirectoryMode = "0750"; +- +- StateDirectory = "headscale"; +- StateDirectoryMode = "0750"; +- +- ProtectSystem = "strict"; +- ProtectHome = true; +- PrivateTmp = true; +- PrivateDevices = true; +- ProtectKernelTunables = true; +- ProtectControlGroups = true; +- RestrictSUIDSGID = true; +- PrivateMounts = true; +- ProtectKernelModules = true; +- ProtectKernelLogs = true; +- ProtectHostname = true; +- ProtectClock = true; +- ProtectProc = "invisible"; +- ProcSubset = "pid"; +- RestrictNamespaces = true; +- RemoveIPC = true; +- UMask = "0077"; +- +- CapabilityBoundingSet = capabilityBoundingSet; +- AmbientCapabilities = capabilityBoundingSet; +- NoNewPrivileges = true; +- LockPersonality = true; +- RestrictRealtime = true; +- SystemCallFilter = [ "@system-service" "~@privileged" "@chown" ]; +- SystemCallArchitectures = "native"; +- RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX"; +- }; ++ serviceConfig = let ++ capabilityBoundingSet = ["CAP_CHOWN"] ++ lib.optional (cfg.port < 1024) "CAP_NET_BIND_SERVICE"; ++ in { ++ Restart = "always"; ++ Type = "simple"; ++ User = cfg.user; ++ Group = cfg.group; ++ ++ # Hardening options ++ RuntimeDirectory = "headscale"; ++ # Allow headscale group access so users can be added and use the CLI. ++ RuntimeDirectoryMode = "0750"; ++ ++ StateDirectory = "headscale"; ++ StateDirectoryMode = "0750"; ++ ++ ProtectSystem = "strict"; ++ ProtectHome = true; ++ PrivateTmp = true; ++ PrivateDevices = true; ++ ProtectKernelTunables = true; ++ ProtectControlGroups = true; ++ RestrictSUIDSGID = true; ++ PrivateMounts = true; ++ ProtectKernelModules = true; ++ ProtectKernelLogs = true; ++ ProtectHostname = true; ++ ProtectClock = true; ++ ProtectProc = "invisible"; ++ ProcSubset = "pid"; ++ RestrictNamespaces = true; ++ RemoveIPC = true; ++ UMask = "0077"; ++ ++ CapabilityBoundingSet = capabilityBoundingSet; ++ AmbientCapabilities = capabilityBoundingSet; ++ NoNewPrivileges = true; ++ LockPersonality = true; ++ RestrictRealtime = true; ++ SystemCallFilter = ["@system-service" "~@privileged" "@chown"]; ++ SystemCallArchitectures = "native"; ++ RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX"; ++ }; + }; + }; + +- meta.maintainers = with maintainers; [ kradalby misterio77 ]; ++ meta.maintainers = with lib.maintainers; [kradalby misterio77]; + } +-- +2.46.1 + + +From 7b2c10bda8a50ea531a444526a3e89e2851bd681 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= +Date: Fri, 11 Oct 2024 13:23:36 -0700 +Subject: [PATCH 3/8] nixos/headscale: assert that server_url does not contain + base_domain + +--- + nixos/modules/services/networking/headscale.nix | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/nixos/modules/services/networking/headscale.nix b/nixos/modules/services/networking/headscale.nix +index 622a13fe7b61..c2e616d30e87 100644 +--- a/nixos/modules/services/networking/headscale.nix ++++ b/nixos/modules/services/networking/headscale.nix +@@ -500,6 +500,15 @@ in { + ]; + + config = lib.mkIf cfg.enable { ++ assertions = [ ++ { ++ # This is stricter than it needs to be but is exactly what upstream does: ++ # https://github.com/kradalby/headscale/blob/adc084f20f843d7963c999764fa83939668d2d2c/hscontrol/types/config.go#L799 ++ assertion = with cfg.settings; dns.use_username_in_magic_dns or false || dns.base_domain == "" || !lib.hasInfix dns.base_domain server_url; ++ message = "server_url cannot contain the base_domain, this will cause the headscale server and embedded DERP to become unreachable from the Tailscale node."; ++ } ++ ]; ++ + services.headscale.settings = lib.mkMerge [ + cliConfig + { +-- +2.46.1 + + +From 0c1215620750c8ca403827076f3a3d02ce419889 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= +Date: Fri, 11 Oct 2024 13:58:20 -0700 +Subject: [PATCH 4/8] nixos/headscale: don't set deprecated options in config + +We cannot use `mkRenamedOptionModule` or `mkRemovedOptionModule` inside +a freeform option. Thus we have to manually assert these deprecated +options aren't used rather than aliasing them to their replacement. +--- + .../modules/services/networking/headscale.nix | 31 ++++++++++--------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +diff --git a/nixos/modules/services/networking/headscale.nix b/nixos/modules/services/networking/headscale.nix +index c2e616d30e87..fd2fd8dbede9 100644 +--- a/nixos/modules/services/networking/headscale.nix ++++ b/nixos/modules/services/networking/headscale.nix +@@ -20,6 +20,11 @@ + settingsFormat = pkgs.formats.yaml {}; + configFile = settingsFormat.generate "headscale.yaml" cfg.settings; + cliConfigFile = settingsFormat.generate "headscale.yaml" cliConfig; ++ ++ assertRemovedOption = option: message: { ++ assertion = !lib.hasAttrByPath option cfg; ++ message = "The option `services.headscale.${lib.options.showOption option}` was removed. " + message; ++ }; + in { + options = { + services.headscale = { +@@ -82,21 +87,6 @@ in { + type = lib.types.submodule { + freeformType = settingsFormat.type; + +- imports = with lib; [ +- (mkAliasOptionModule ["acl_policy_path"] ["policy" "path"]) +- (mkAliasOptionModule ["db_host"] ["database" "postgres" "host"]) +- (mkAliasOptionModule ["db_name"] ["database" "postgres" "name"]) +- (mkAliasOptionModule ["db_password_file"] ["database" "postgres" "password_file"]) +- (mkAliasOptionModule ["db_path"] ["database" "sqlite" "path"]) +- (mkAliasOptionModule ["db_port"] ["database" "postgres" "port"]) +- (mkAliasOptionModule ["db_type"] ["database" "type"]) +- (mkAliasOptionModule ["db_user"] ["database" "postgres" "user"]) +- (mkAliasOptionModule ["dns_config" "base_domain"] ["dns" "base_domain"]) +- (mkAliasOptionModule ["dns_config" "domains"] ["dns" "search_domains"]) +- (mkAliasOptionModule ["dns_config" "magic_dns"] ["dns" "magic_dns"]) +- (mkAliasOptionModule ["dns_config" "nameservers"] ["dns" "nameservers" "global"]) +- ]; +- + options = { + server_url = lib.mkOption { + type = lib.types.str; +@@ -507,6 +497,17 @@ in { + assertion = with cfg.settings; dns.use_username_in_magic_dns or false || dns.base_domain == "" || !lib.hasInfix dns.base_domain server_url; + message = "server_url cannot contain the base_domain, this will cause the headscale server and embedded DERP to become unreachable from the Tailscale node."; + } ++ (assertRemovedOption ["settings" "acl_policy_path"] "Use `policy.path` instead.") ++ (assertRemovedOption ["settings" "db_host"] "Use `database.postgres.host` instead.") ++ (assertRemovedOption ["settings" "db_name"] "Use `database.postgres.name` instead.") ++ (assertRemovedOption ["settings" "db_password_file"] "Use `database.postgres.password_file` instead.") ++ (assertRemovedOption ["settings" "db_path"] "Use `database.sqlite.path` instead.") ++ (assertRemovedOption ["settings" "db_port"] "Use `database.postgres.port` instead.") ++ (assertRemovedOption ["settings" "db_type"] "Use `database.type` instead.") ++ (assertRemovedOption ["settings" "db_user"] "Use `database.postgres.user` instead.") ++ (assertRemovedOption ["settings" "dns_config"] "Use `dns` instead.") ++ (assertRemovedOption ["settings" "dns_config" "domains"] "Use `dns.search_domains` instead.") ++ (assertRemovedOption ["settings" "dns_config" "nameservers"] "Use `dns.nameservers.global` instead.") + ]; + + services.headscale.settings = lib.mkMerge [ +-- +2.46.1 + + +From 31de80dcfee97b024298128836c8ab49ca7ae798 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= +Date: Fri, 11 Oct 2024 20:17:15 -0700 +Subject: [PATCH 5/8] nixos/headscale: update option descriptions + +--- + nixos/modules/services/networking/headscale.nix | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/nixos/modules/services/networking/headscale.nix b/nixos/modules/services/networking/headscale.nix +index fd2fd8dbede9..aac6d331a027 100644 +--- a/nixos/modules/services/networking/headscale.nix ++++ b/nixos/modules/services/networking/headscale.nix +@@ -289,7 +289,6 @@ in { + default = true; + description = '' + Whether to use [MagicDNS](https://tailscale.com/kb/1081/magicdns/). +- Only works if there is at least a nameserver defined. + ''; + example = false; + }; +@@ -299,11 +298,13 @@ in { + default = ""; + description = '' + Defines the base domain to create the hostnames for MagicDNS. +- {option}`baseDomain` must be a FQDNs, without the trailing dot. +- The FQDN of the hosts will be +- `hostname.namespace.base_domain` (e.g. +- `myhost.mynamespace.example.com`). ++ This domain must be different from the {option}`server_url` ++ domain. ++ {option}`base_domain` must be a FQDN, without the trailing dot. ++ The FQDN of the hosts will be `hostname.base_domain` (e.g. ++ `myhost.tailnet.example.com`). + ''; ++ example = "tailnet.example.com"; + }; + + nameservers = { +-- +2.46.1 + + +From 083dec59811d7bfcaed1a34fc33d33eabc40fcc9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= +Date: Sat, 12 Oct 2024 18:28:17 -0700 +Subject: [PATCH 6/8] nixos/headscale: assert that dns.base_domain is set when + using MagicDNS + +--- + nixos/modules/services/networking/headscale.nix | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/nixos/modules/services/networking/headscale.nix b/nixos/modules/services/networking/headscale.nix +index aac6d331a027..9261ec03c532 100644 +--- a/nixos/modules/services/networking/headscale.nix ++++ b/nixos/modules/services/networking/headscale.nix +@@ -498,6 +498,10 @@ in { + assertion = with cfg.settings; dns.use_username_in_magic_dns or false || dns.base_domain == "" || !lib.hasInfix dns.base_domain server_url; + message = "server_url cannot contain the base_domain, this will cause the headscale server and embedded DERP to become unreachable from the Tailscale node."; + } ++ { ++ assertion = with cfg.settings; dns.magic_dns -> dns.base_domain != ""; ++ message = "dns.base_domain must be set when using MagicDNS"; ++ } + (assertRemovedOption ["settings" "acl_policy_path"] "Use `policy.path` instead.") + (assertRemovedOption ["settings" "db_host"] "Use `database.postgres.host` instead.") + (assertRemovedOption ["settings" "db_name"] "Use `database.postgres.name` instead.") +-- +2.46.1 + + +From 720b90273528c02a0fb865062fe44a45eb04f82e Mon Sep 17 00:00:00 2001 +From: Jennifer Graul +Date: Wed, 13 Sep 2023 13:32:47 +0200 +Subject: [PATCH 7/8] headscale: fix reacting to SIGTERM + +The current version of headscale does not react to SIGTERMs and so it +can only be terminated by a SIGKILL at the moment. This commit provides +a patch to fix this. +--- + pkgs/servers/headscale/default.nix | 4 ++++ + pkgs/servers/headscale/sigterm-fix.patch | 12 ++++++++++++ + 2 files changed, 16 insertions(+) + create mode 100644 pkgs/servers/headscale/sigterm-fix.patch + +diff --git a/pkgs/servers/headscale/default.nix b/pkgs/servers/headscale/default.nix +index fca56f5fc848..eb9ad79b1888 100644 +--- a/pkgs/servers/headscale/default.nix ++++ b/pkgs/servers/headscale/default.nix +@@ -21,6 +21,10 @@ buildGoModule rec { + patches = [ + # backport of https://github.com/juanfont/headscale/pull/1697 + ./trim-oidc-secret-path.patch ++ ++ # fix for headscale not reacting to SIGTERM ++ # see https://github.com/juanfont/headscale/pull/1480 and https://github.com/juanfont/headscale/issues/1461 ++ ./sigterm-fix.patch + ]; + + ldflags = ["-s" "-w" "-X github.com/juanfont/headscale/cmd/headscale/cli.Version=v${version}"]; +diff --git a/pkgs/servers/headscale/sigterm-fix.patch b/pkgs/servers/headscale/sigterm-fix.patch +new file mode 100644 +index 000000000000..22a97d98caac +--- /dev/null ++++ b/pkgs/servers/headscale/sigterm-fix.patch +@@ -0,0 +1,12 @@ ++diff --git a/hscontrol/app.go b/hscontrol/app.go ++index b8dceba..4bcf019 100644 ++--- a/hscontrol/app.go +++++ b/hscontrol/app.go ++@@ -821,6 +821,7 @@ func (h *Headscale) Serve() error { ++ ++ // And we're done: ++ cancel() +++ return ++ } ++ } ++ } +-- +2.46.1 + + +From 1a1fa839c7c8fafdea120b8b9af28d8839f8cafb Mon Sep 17 00:00:00 2001 +From: Kristoffer Dalby +Date: Fri, 6 Sep 2024 13:32:52 +0200 +Subject: [PATCH 8/8] headscale: 0.22.3 -> 0.23.0 + +Signed-off-by: Kristoffer Dalby +--- + pkgs/servers/headscale/default.nix | 20 +++++-------------- + pkgs/servers/headscale/sigterm-fix.patch | 12 ----------- + .../headscale/trim-oidc-secret-path.patch | 13 ------------ + pkgs/top-level/all-packages.nix | 4 +++- + 4 files changed, 8 insertions(+), 41 deletions(-) + delete mode 100644 pkgs/servers/headscale/sigterm-fix.patch + delete mode 100644 pkgs/servers/headscale/trim-oidc-secret-path.patch + +diff --git a/pkgs/servers/headscale/default.nix b/pkgs/servers/headscale/default.nix +index eb9ad79b1888..9f127946217e 100644 +--- a/pkgs/servers/headscale/default.nix ++++ b/pkgs/servers/headscale/default.nix +@@ -7,33 +7,22 @@ + }: + buildGoModule rec { + pname = "headscale"; +- version = "0.22.3"; ++ version = "0.23.0"; + + src = fetchFromGitHub { + owner = "juanfont"; + repo = "headscale"; + rev = "v${version}"; +- hash = "sha256-nqmTqe3F3Oh8rnJH0clwACD/0RpqmfOMXNubr3C8rEc="; ++ hash = "sha256-5tlnVNpn+hJayxHjTpbOO3kRInOYOFz0pe9pwjXZlBE="; + }; + +- vendorHash = "sha256-IOkbbFtE6+tNKnglE/8ZuNxhPSnloqM2sLgTvagMmnc="; +- +- patches = [ +- # backport of https://github.com/juanfont/headscale/pull/1697 +- ./trim-oidc-secret-path.patch +- +- # fix for headscale not reacting to SIGTERM +- # see https://github.com/juanfont/headscale/pull/1480 and https://github.com/juanfont/headscale/issues/1461 +- ./sigterm-fix.patch +- ]; ++ vendorHash = "sha256-+8dOxPG/Q+wuHgRwwWqdphHOuop0W9dVyClyQuh7aRc="; + + ldflags = ["-s" "-w" "-X github.com/juanfont/headscale/cmd/headscale/cli.Version=v${version}"]; + + nativeBuildInputs = [installShellFiles]; + checkFlags = ["-short"]; + +- tags = ["ts2019"]; +- + postInstall = '' + installShellCompletion --cmd headscale \ + --bash <($out/bin/headscale completion bash) \ +@@ -41,7 +30,7 @@ buildGoModule rec { + --zsh <($out/bin/headscale completion zsh) + ''; + +- passthru.tests = { inherit (nixosTests) headscale; }; ++ passthru.tests = {inherit (nixosTests) headscale;}; + + meta = with lib; { + homepage = "https://github.com/juanfont/headscale"; +@@ -63,6 +52,7 @@ buildGoModule rec { + Headscale implements this coordination server. + ''; + license = licenses.bsd3; ++ mainProgram = "headscale"; + maintainers = with maintainers; [nkje jk kradalby misterio77 ghuntley]; + }; + } +diff --git a/pkgs/servers/headscale/sigterm-fix.patch b/pkgs/servers/headscale/sigterm-fix.patch +deleted file mode 100644 +index 22a97d98caac..000000000000 +--- a/pkgs/servers/headscale/sigterm-fix.patch ++++ /dev/null +@@ -1,12 +0,0 @@ +-diff --git a/hscontrol/app.go b/hscontrol/app.go +-index b8dceba..4bcf019 100644 +---- a/hscontrol/app.go +-+++ b/hscontrol/app.go +-@@ -821,6 +821,7 @@ func (h *Headscale) Serve() error { +- +- // And we're done: +- cancel() +-+ return +- } +- } +- } +diff --git a/pkgs/servers/headscale/trim-oidc-secret-path.patch b/pkgs/servers/headscale/trim-oidc-secret-path.patch +deleted file mode 100644 +index 4275988aa7db..000000000000 +--- a/pkgs/servers/headscale/trim-oidc-secret-path.patch ++++ /dev/null +@@ -1,13 +0,0 @@ +-diff --git a/hscontrol/config.go b/hscontrol/config.go +-index 0e83a1c..71fbfb0 100644 +---- a/hscontrol/config.go +-+++ b/hscontrol/config.go +-@@ -573,7 +573,7 @@ func GetHeadscaleConfig() (*Config, error) { +- if err != nil { +- return nil, err +- } +-- oidcClientSecret = string(secretBytes) +-+ oidcClientSecret = strings.TrimSpace(string(secretBytes)) +- } +- +- return &Config{ +diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix +index 39aac77560e1..c1811da9b6a4 100644 +--- a/pkgs/top-level/all-packages.nix ++++ b/pkgs/top-level/all-packages.nix +@@ -8912,7 +8912,9 @@ with pkgs; + + heimdall-gui = heimdall.override { enableGUI = true; }; + +- headscale = callPackage ../servers/headscale { }; ++ headscale = callPackage ../servers/headscale { ++ buildGoModule = buildGo123Module; ++ }; + + health = callPackage ../applications/misc/health { }; + +-- +2.46.1 + From 7ad95300406d3016f510ab7a8e5674b1ee4564a7 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 6 Nov 2024 00:40:41 +0100 Subject: [PATCH 0803/1125] Server/headscale: update settings --- roles/server/adguard.nix | 4 ++-- roles/server/caddy.nix | 2 +- roles/server/forgejo.nix | 2 +- roles/server/headscale.nix | 4 ++-- roles/server/syncthing.nix | 2 +- roles/server/transmission.nix | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/roles/server/adguard.nix b/roles/server/adguard.nix index ba9d995..ab814f8 100644 --- a/roles/server/adguard.nix +++ b/roles/server/adguard.nix @@ -18,8 +18,8 @@ in { }; }; - headscale.settings.dns_config = { - nameservers = lib.mkForce ["100.100.0.1"]; + headscale.settings.dns= { + nameservers.global = lib.mkForce ["100.100.0.1"]; extra_records = [ { name = domain; diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index 439f231..b303d1a 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -47,7 +47,7 @@ in { }; }; }; - services.headscale.settings.dns_config.extra_records = let + services.headscale.settings.dns.extra_records = let makeRecords = builtins.map (recordName: { name = recordName; type = "A"; diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index 52b6847..ff51523 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -45,7 +45,7 @@ in { }; # Add a record for forgejo - services.headscale.settings.dns_config.extra_records = [ + services.headscale.settings.dns.extra_records = [ { name = "git.everest.tailscale"; type = "A"; diff --git a/roles/server/headscale.nix b/roles/server/headscale.nix index 8619dd3..17fb680 100644 --- a/roles/server/headscale.nix +++ b/roles/server/headscale.nix @@ -6,9 +6,9 @@ ip_prefixes = [ "100.100.0.0/16" ]; - dns_config = { + dns = { base_domain = "tailscale"; - nameservers = ["9.9.9.9"]; + nameservers.global = ["9.9.9.9"]; override_local_dns = true; }; }; diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 7982b1f..509d00b 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -40,7 +40,7 @@ }; # Add a record for syncthing - services.headscale.settings.dns_config.extra_records = [ + services.headscale.settings.dns.extra_records = [ { name = "sync.everest.tailscale"; type = "A"; diff --git a/roles/server/transmission.nix b/roles/server/transmission.nix index a1aafdb..2ce8b06 100755 --- a/roles/server/transmission.nix +++ b/roles/server/transmission.nix @@ -38,7 +38,7 @@ in { }; # Add a record for transmission - services.headscale.settings.dns_config.extra_records = [ + services.headscale.settings.dns.extra_records = [ { name = "transmission.everest.tailscale"; type = "A"; From b20c1b53d13943b8c8b5757a8a20480913b20cef Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 6 Nov 2024 18:08:56 +0100 Subject: [PATCH 0804/1125] Kde: delete old unused patch --- roles/kde/patches/BreezeTint.patch | 191 ----------------------------- 1 file changed, 191 deletions(-) delete mode 100644 roles/kde/patches/BreezeTint.patch diff --git a/roles/kde/patches/BreezeTint.patch b/roles/kde/patches/BreezeTint.patch deleted file mode 100644 index 8f17370..0000000 --- a/roles/kde/patches/BreezeTint.patch +++ /dev/null @@ -1,191 +0,0 @@ -diff --git a/share/color-schemes/BreezeClassic.colors b/share/color-schemes/BreezeClassicTint.colors -similarity index 70% -rename from share/color-schemes/BreezeClassic.colors -rename to share/color-schemes/BreezeClassicTint.colors -index 8dbc299..d64e300 100644 ---- a/share/color-schemes/BreezeClassic.colors -+++ b/share/color-schemes/BreezeClassicTint.colors -@@ -103,48 +103,12 @@ ForegroundPositive=46,204,113 - ForegroundVisited=61,174,230 - - [General] --ColorScheme=BreezeClassic --Name=Breeze Classic --Name[ar]=نسيم التقليدي --Name[az]=Breeze klassik --Name[bg]=Breeze Класически --Name[ca]=Brisa clàssica --Name[ca@valencia]=Brisa clàssica --Name[cs]=Breeze Classic --Name[da]=Breeze Classic --Name[de]=Breeze Klassisch --Name[el]=Breeze κλασικό --Name[en_GB]=Breeze Classic --Name[es]=Brisa clásico --Name[eu]=Breeze klasikoa --Name[fi]=Perinteinen Breeze --Name[fr]=Breeze classique --Name[gl]=Brisa clásica --Name[hi]=ब्रीज़ क्लासिक --Name[hu]=Breeze Classic --Name[ia]=Brisa Classic --Name[id]=Breeze Klasik --Name[it]=Brezza classico --Name[ja]=Breeze クラシック --Name[ka]=Breeze კლასიკური --Name[ko]=Breeze 고전 --Name[nl]=Breeze Classic --Name[nn]=Breeze klassisk --Name[pl]=Klasyczna Bryza --Name[pt]=Brisa Clássica --Name[pt_BR]=Breeze Classic --Name[ro]=Briză, clasic --Name[ru]=Breeze, классический вариант --Name[sk]=Klasický vánok --Name[sl]=Sapica, klasična --Name[sv]=Breeze klassisk --Name[tr]=Esinti Klasik --Name[uk]=Класична Breeze --Name[x-test]=xxBreeze Classicxx --Name[zh_CN]=Breeze 微风经典 --Name[zh_TW]=Breeze Classic -+ColorScheme=BreezeClassicTint -+Name=Breeze Classic (Tint) - accentActiveTitlebar=true - accentInactiveTitlebar=false -+TintFactor=0.2 -+TitlebarIsAccentColored=true - shadeSortColumn=true - - [KDE] -diff --git a/share/color-schemes/BreezeDark.colors b/share/color-schemes/BreezeDarkTint.colors -similarity index 71% -rename from share/color-schemes/BreezeDark.colors -rename to share/color-schemes/BreezeDarkTint.colors -index fc1fcb0..a97a552 100644 ---- a/share/color-schemes/BreezeDark.colors -+++ b/share/color-schemes/BreezeDarkTint.colors -@@ -131,57 +131,10 @@ ForegroundPositive=39,174,96 - ForegroundVisited=155,89,182 - - [General] --ColorScheme=BreezeDark --Name=Breeze Dark --Name[ar]=نسيم داكن --Name[az]=Breeze - Tünd --Name[bg]=Breeze Тъмен --Name[bs]=Breeze tamna --Name[ca]=Brisa fosca --Name[ca@valencia]=Brisa fosca --Name[cs]=Breeze Tmavé --Name[da]=Breeze Dark --Name[de]=Breeze Dunkel --Name[el]=Breeze σκούρο --Name[en_GB]=Breeze Dark --Name[es]=Brisa oscuro --Name[et]=Breeze tume --Name[eu]=Breeze iluna --Name[fi]=Tumma Breeze --Name[fr]=Brise sombre --Name[gl]=Brisa escura --Name[he]=Breeze Dark --Name[hi]=ब्रीज़ गहरा --Name[hu]=Breeze Dark --Name[ia]=Brisa obscure --Name[id]=Breeze Gelap --Name[it]=Brezza scuro --Name[ja]=Breeze ダーク --Name[ka]=Breeze მუქი --Name[ko]=어두운 Breeze --Name[lt]=Breeze tamsus --Name[nb]=Breeze mørk --Name[nl]=Breeze Dark --Name[nn]=Breeze mørk --Name[pa]=ਬਰੀਜ਼ ਗੂੜ੍ਹਾ --Name[pl]=Ciemna Bryza --Name[pt]=Brisa Escura --Name[pt_BR]=Breeze Dark --Name[ro]=Briză, întunecat --Name[ru]=Breeze, тёмный вариант --Name[sk]=Tmavý vánok --Name[sl]=Sapica, temna --Name[sr]=Поветарац тамни --Name[sr@ijekavian]=Поветарац тамни --Name[sr@ijekavianlatin]=Povetarac tamni --Name[sr@latin]=Povetarac tamni --Name[sv]=Breeze mörk --Name[tg]=Насими торик --Name[tr]=Esinti Koyu --Name[uk]=Темна Breeze --Name[x-test]=xxBreeze Darkxx --Name[zh_CN]=Breeze 微风深色 --Name[zh_TW]=Breeze Dark -+ColorScheme=BreezeDarkTint -+Name=Breeze Dark (Tint) -+TintFactor=0.2 -+TitlebarIsAccentColored=true - shadeSortColumn=true - - [KDE] -diff --git a/share/color-schemes/BreezeLight.colors b/share/color-schemes/BreezeLightTint.colors -similarity index 75% -rename from share/color-schemes/BreezeLight.colors -rename to share/color-schemes/BreezeLightTint.colors -index 5bfdc22..223509c 100644 ---- a/share/color-schemes/BreezeLight.colors -+++ b/share/color-schemes/BreezeLightTint.colors -@@ -131,50 +131,10 @@ ForegroundPositive=39,174,96 - ForegroundVisited=155,89,182 - - [General] --ColorScheme=BreezeLight --Name=Breeze Light --Name[ar]=نسيم فاتح --Name[az]=Breeze - İşıqlı --Name[bg]=Breeze Светъл --Name[ca]=Brisa clara --Name[ca@valencia]=Brisa clara --Name[cs]=Breeze Světlé --Name[da]=Breeze Light --Name[de]=Breeze Hell --Name[el]=Breeze φωτεινό --Name[en_GB]=Breeze Light --Name[es]=Brisa claro --Name[et]=Breeze hele --Name[eu]=Breeze argia --Name[fi]=Vaalea Breeze --Name[fr]=Brise clair --Name[gl]=Brisa clara --Name[hi]=ब्रीज़ हलका --Name[hu]=Breeze Light --Name[ia]=Brisa Ligier --Name[id]=Breeze Terang --Name[it]=Brezza chiaro --Name[ja]=Breeze ライト --Name[ka]=Breeze ღია --Name[ko]=밝은 Breeze --Name[lt]=Breeze šviesus --Name[nl]=Breeze Light --Name[nn]=Breeze lys --Name[pa]=ਬਰੀਜ਼ ਹਲਕਾ --Name[pl]=Jasna Bryza --Name[pt]=Brisa Clara --Name[pt_BR]=Breeze Light --Name[ro]=Briză, luminos --Name[ru]=Breeze, светлый вариант --Name[sk]=Svetlý vánok --Name[sl]=Sapica, svetla --Name[sv]=Breeze ljus --Name[tg]=Насими сабук --Name[tr]=Esinti Açık --Name[uk]=Світла Breeze --Name[x-test]=xxBreeze Lightxx --Name[zh_CN]=Breeze 微风浅色 --Name[zh_TW]=Breeze Light -+ColorScheme=BreezeLightTint -+Name=Breeze Light (Tint) -+TintFactor=0.2 -+TitlebarIsAccentColored=true - shadeSortColumn=true - - [KDE] From c666b582f6bb9460170db2c197d692ed174892cd Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 6 Nov 2024 18:14:06 +0100 Subject: [PATCH 0805/1125] Kde: add libplasma patch --- roles/kde/patches/libplasma-pr1214.patch | 48 ++++++++++++++++++++++++ roles/kde/plasma.nix | 16 ++++++++ 2 files changed, 64 insertions(+) create mode 100644 roles/kde/patches/libplasma-pr1214.patch diff --git a/roles/kde/patches/libplasma-pr1214.patch b/roles/kde/patches/libplasma-pr1214.patch new file mode 100644 index 0000000..709b13e --- /dev/null +++ b/roles/kde/patches/libplasma-pr1214.patch @@ -0,0 +1,48 @@ +From 626a52ae30dcda0ca407d1de02e30fcf5c109862 Mon Sep 17 00:00:00 2001 +From: Tem PQD +Date: Sun, 27 Oct 2024 03:54:44 +0000 +Subject: [PATCH] applets/taskmanager: Make group indicator icon follow accent + color + +The green plus icon is pretty eye-catching, and normally green plus buttons indicate something is going to be added or created. Change this to follow the user-selected color scheme, also matching the focus/active indicator color. +--- + src/desktoptheme/breeze/widgets/tasks.svg | Bin 78569 -> 78717 bytes + 1 file changed, 0 insertions(+), 0 deletions(-) + +diff --git a/src/desktoptheme/breeze/widgets/tasks.svg b/src/desktoptheme/breeze/widgets/tasks.svg +index b76d1a345fe59ca48cc3c52de53495202734d00f..c60707355f082749661ffc059744a0f2b0f94eee 100644 +--- a/src/desktoptheme/breeze/widgets/tasks.svg ++++ b/src/desktoptheme/breeze/widgets/tasks.svg +@@ -952,25 +952,25 @@ + + + +- ++ + + + + + +- ++ + + + + + +- ++ + + + + + +- ++ + + + +-- +GitLab + diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index a529556..e4a37ce 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -39,6 +39,22 @@ in { qt.enable = true; + nixpkgs.overlays = [ + ( + final: prev: { + kdePackages = prev.kdePackages.overrideScope ( + kFinal: kPrev: { + libplasma = kPrev.libplasma.overrideAttrs { + patches = [ + ../kde/patches/libplasma-pr1214.patch + ]; + }; + } + ); + } + ) + ]; + # GTK apps need dconf to grab the correct theme on Wayland programs.dconf.enable = true; From c569ed03d2fe4c31cf6ecad5601ee9d22a455cdd Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 7 Nov 2024 11:09:49 +0100 Subject: [PATCH 0806/1125] Kde: add kwin patch --- roles/kde/patches/kwin-pr6406.patch | 1029 +++++++++++++++++++++++++++ roles/kde/plasma.nix | 5 + 2 files changed, 1034 insertions(+) create mode 100644 roles/kde/patches/kwin-pr6406.patch diff --git a/roles/kde/patches/kwin-pr6406.patch b/roles/kde/patches/kwin-pr6406.patch new file mode 100644 index 0000000..b58678b --- /dev/null +++ b/roles/kde/patches/kwin-pr6406.patch @@ -0,0 +1,1029 @@ +From ffa4f312c750ae0e7e36a656612148b1fa9c020c Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Fri, 4 Oct 2024 22:49:16 +0300 +Subject: [PATCH 1/9] Resize X11 window immediately if it doesn't support + _NET_WM_SYNC_REQUEST + +The fact that X11Window::handleSyncTimeout() is shared by code that runs +when the client supports or doesn't support _NET_WM_SYNC_REQUEST makes +the XSync code difficult to follow and more error prone. + +On the other hand, it appears that other window managers, e.g. Mutter and +openbox, don't bother about throttling interactive resize when the client +doesn't opt in into _NET_WM_SYNC_REQUEST, so let's do the same to simplify +the code. + +As a backup plan, if it indeed becomes a problem later, we can always +save current monotonic time in X11Window::doInteractiveResizeSync() and +make X11Window::isWaitingForInteractiveResizeSync() check whether enough +of time has passed since the last resize sync. +--- + autotests/integration/x11_window_test.cpp | 16 +++-------- + src/x11window.cpp | 35 +++++++++-------------- + 2 files changed, 17 insertions(+), 34 deletions(-) + +diff --git a/autotests/integration/x11_window_test.cpp b/autotests/integration/x11_window_test.cpp +index 12f53c4220..a208fa3adb 100644 +--- a/autotests/integration/x11_window_test.cpp ++++ b/autotests/integration/x11_window_test.cpp +@@ -1492,7 +1492,6 @@ void X11WindowTest::testNetWmKeyboardResize() + QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted); + QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished); + QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped); +- QSignalSpy frameGeometryChangedSpy(window, &X11Window::frameGeometryChanged); + QVERIFY(interactiveMoveResizeStartedSpy.wait()); + QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0); + QVERIFY(window->isInteractiveResize()); +@@ -1503,7 +1502,6 @@ void X11WindowTest::testNetWmKeyboardResize() + Test::keyboardKeyPressed(KEY_RIGHT, timestamp++); + Test::keyboardKeyReleased(KEY_RIGHT, timestamp++); + QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1); +- QVERIFY(frameGeometryChangedSpy.wait()); + QCOMPARE(window->frameGeometry(), originalGeometry.adjusted(0, 0, 8, 0)); + + // Finish the interactive move. +@@ -1531,7 +1529,6 @@ void X11WindowTest::testNetWmKeyboardResizeCancel() + QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted); + QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished); + QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped); +- QSignalSpy frameGeometryChangedSpy(window, &X11Window::frameGeometryChanged); + QVERIFY(interactiveMoveResizeStartedSpy.wait()); + QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0); + QVERIFY(window->isInteractiveResize()); +@@ -1542,7 +1539,6 @@ void X11WindowTest::testNetWmKeyboardResizeCancel() + Test::keyboardKeyPressed(KEY_RIGHT, timestamp++); + Test::keyboardKeyReleased(KEY_RIGHT, timestamp++); + QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1); +- QVERIFY(frameGeometryChangedSpy.wait()); + QCOMPARE(window->frameGeometry(), originalGeometry.adjusted(0, 0, 8, 0)); + + // Cancel the interactive move. +@@ -1741,7 +1737,6 @@ void X11WindowTest::testNetWmButtonSize() + QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted); + QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished); + QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped); +- QSignalSpy frameGeometryChangedSpy(window, &X11Window::frameGeometryChanged); + QVERIFY(interactiveMoveResizeStartedSpy.wait()); + QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0); + QVERIFY(window->isInteractiveResize()); +@@ -1750,7 +1745,6 @@ void X11WindowTest::testNetWmButtonSize() + // Resize the window a tiny bit. + Test::pointerMotionRelative(directionToVector(direction, QSizeF(8, 8)), timestamp++); + QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1); +- QVERIFY(frameGeometryChangedSpy.wait()); + QCOMPARE(window->frameGeometry(), expandRect(originalGeometry, direction, QSizeF(8, 8))); + + // Finish the interactive move. +@@ -1803,7 +1797,6 @@ void X11WindowTest::testNetWmButtonSizeCancel() + QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted); + QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished); + QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped); +- QSignalSpy frameGeometryChangedSpy(window, &X11Window::frameGeometryChanged); + QVERIFY(interactiveMoveResizeStartedSpy.wait()); + QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0); + QVERIFY(window->isInteractiveResize()); +@@ -1811,7 +1804,6 @@ void X11WindowTest::testNetWmButtonSizeCancel() + // Resize the window a tiny bit. + Test::pointerMotionRelative(QPointF(-8, -8), timestamp++); + QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1); +- QVERIFY(frameGeometryChangedSpy.wait()); + QCOMPARE(window->frameGeometry(), originalGeometry.adjusted(-8, -8, 0, 0)); + + // Cancel the interactive resize. +@@ -1888,7 +1880,7 @@ void X11WindowTest::testMinimumSize() + window->updateInteractiveMoveResize(KWin::Cursors::self()->mouse()->pos(), Qt::KeyboardModifiers()); + QCOMPARE(KWin::Cursors::self()->mouse()->pos(), cursorPos + QPoint(8, 0)); + QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1); +- QVERIFY(frameGeometryChangedSpy.wait()); ++ QVERIFY(!frameGeometryChangedSpy.wait(10)); + // whilst X11 window size goes through scale, the increment is a logical value kwin side + QCOMPARE(window->clientSize().width(), 100 / scale + 8); + +@@ -1910,7 +1902,7 @@ void X11WindowTest::testMinimumSize() + window->updateInteractiveMoveResize(KWin::Cursors::self()->mouse()->pos(), Qt::KeyboardModifiers()); + QCOMPARE(KWin::Cursors::self()->mouse()->pos(), cursorPos + QPoint(8, 8)); + QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 2); +- QVERIFY(frameGeometryChangedSpy.wait()); ++ QVERIFY(!frameGeometryChangedSpy.wait(10)); + QCOMPARE(window->clientSize().height(), 200 / scale + 8); + + // Finish the resize operation. +@@ -1993,7 +1985,7 @@ void X11WindowTest::testMaximumSize() + window->updateInteractiveMoveResize(KWin::Cursors::self()->mouse()->pos(), Qt::KeyboardModifiers()); + QCOMPARE(KWin::Cursors::self()->mouse()->pos(), cursorPos + QPoint(-8, 0)); + QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1); +- QVERIFY(frameGeometryChangedSpy.wait()); ++ QVERIFY(!frameGeometryChangedSpy.wait(10)); + QCOMPARE(window->clientSize().width(), 100 / scale - 8); + + window->keyPressEvent(Qt::Key_Down); +@@ -2014,7 +2006,7 @@ void X11WindowTest::testMaximumSize() + window->updateInteractiveMoveResize(KWin::Cursors::self()->mouse()->pos(), Qt::KeyboardModifiers()); + QCOMPARE(KWin::Cursors::self()->mouse()->pos(), cursorPos + QPoint(-8, -8)); + QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 2); +- QVERIFY(frameGeometryChangedSpy.wait()); ++ QVERIFY(!frameGeometryChangedSpy.wait(10)); + QCOMPARE(window->clientSize().height(), 200 / scale - 8); + + // Finish the resize operation. +diff --git a/src/x11window.cpp b/src/x11window.cpp +index b71a9d3640..780ccfbc7e 100644 +--- a/src/x11window.cpp ++++ b/src/x11window.cpp +@@ -4857,36 +4857,27 @@ void X11Window::doInteractiveResizeSync(const QRectF &rect) + return; + } + +- setMoveResizeGeometry(moveResizeFrameGeometry); +- setAllowCommits(false); ++ if (m_syncRequest.counter == XCB_NONE) { ++ moveResize(rect); ++ } else { ++ if (!m_syncRequest.timeout) { ++ m_syncRequest.timeout = new QTimer(this); ++ connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Window::handleSyncTimeout); ++ m_syncRequest.timeout->setSingleShot(true); ++ } + +- if (!m_syncRequest.timeout) { +- m_syncRequest.timeout = new QTimer(this); +- connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Window::handleSyncTimeout); +- m_syncRequest.timeout->setSingleShot(true); +- } ++ setMoveResizeGeometry(moveResizeFrameGeometry); ++ setAllowCommits(false); + +- if (m_syncRequest.counter != XCB_NONE) { +- m_syncRequest.timeout->start(250); + sendSyncRequest(); +- } else { +- // For clients not supporting the XSYNC protocol, we limit the resizes to 30Hz +- // to take pointless load from X11 and the client, the mouse is still moved at +- // full speed and no human can control faster resizes anyway. +- m_syncRequest.isPending = true; +- m_syncRequest.interactiveResize = true; +- m_syncRequest.timeout->start(33); +- } ++ configure(nativeFrameGeometry, nativeWrapperGeometry, nativeClientGeometry); + +- configure(nativeFrameGeometry, nativeWrapperGeometry, nativeClientGeometry); ++ m_syncRequest.timeout->start(250); ++ } + } + + void X11Window::handleSyncTimeout() + { +- if (m_syncRequest.counter == XCB_NONE) { // client w/o XSYNC support. allow the next resize event +- m_syncRequest.isPending = false; // NEVER do this for clients with a valid counter +- m_syncRequest.interactiveResize = false; // (leads to sync request races in some clients) +- } + performInteractiveResize(); + } + +-- +2.46.1 + + +From bc87fc3d80ad525786a9b15df5c2488a6110b53d Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Fri, 4 Oct 2024 22:55:44 +0300 +Subject: [PATCH 2/9] Rename X11Window::handleSync,handleSyncTimeout + +--- + src/syncalarmx11filter.cpp | 2 +- + src/x11window.cpp | 6 +++--- + src/x11window.h | 4 ++-- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/syncalarmx11filter.cpp b/src/syncalarmx11filter.cpp +index f4b4d49caa..133c3c6b99 100644 +--- a/src/syncalarmx11filter.cpp ++++ b/src/syncalarmx11filter.cpp +@@ -28,7 +28,7 @@ bool SyncAlarmX11Filter::event(xcb_generic_event_t *event) + return alarmEvent->alarm == syncRequest.alarm && alarmEvent->counter_value.hi == syncRequest.value.hi && alarmEvent->counter_value.lo == syncRequest.value.lo; + }); + if (client) { +- client->handleSync(); ++ client->ackSync(); + } + return false; + } +diff --git a/src/x11window.cpp b/src/x11window.cpp +index 780ccfbc7e..14d45abb27 100644 +--- a/src/x11window.cpp ++++ b/src/x11window.cpp +@@ -3059,7 +3059,7 @@ void X11Window::checkApplicationMenuObjectPath() + readApplicationMenuObjectPath(property); + } + +-void X11Window::handleSync() ++void X11Window::ackSync() + { + setReadyForPainting(); + m_syncRequest.isPending = false; +@@ -4862,7 +4862,7 @@ void X11Window::doInteractiveResizeSync(const QRectF &rect) + } else { + if (!m_syncRequest.timeout) { + m_syncRequest.timeout = new QTimer(this); +- connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Window::handleSyncTimeout); ++ connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Window::ackSyncTimeout); + m_syncRequest.timeout->setSingleShot(true); + } + +@@ -4876,7 +4876,7 @@ void X11Window::doInteractiveResizeSync(const QRectF &rect) + } + } + +-void X11Window::handleSyncTimeout() ++void X11Window::ackSyncTimeout() + { + performInteractiveResize(); + } +diff --git a/src/x11window.h b/src/x11window.h +index 4f3b43c8b0..b54db23345 100644 +--- a/src/x11window.h ++++ b/src/x11window.h +@@ -293,8 +293,8 @@ public: + return m_syncRequest; + } + bool wantsSyncCounter() const; +- void handleSync(); +- void handleSyncTimeout(); ++ void ackSync(); ++ void ackSyncTimeout(); + + bool allowWindowActivation(xcb_timestamp_t time = -1U, bool focus_in = false); + +-- +2.46.1 + + +From b8016cbe28d847d052f1b0ee6c66bdaabbb88368 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Fri, 4 Oct 2024 22:59:34 +0300 +Subject: [PATCH 3/9] Rename X11Window::SyncRequest::isPending + +--- + src/x11window.cpp | 12 ++++++------ + src/x11window.h | 2 +- + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/src/x11window.cpp b/src/x11window.cpp +index 14d45abb27..2ebb4a5957 100644 +--- a/src/x11window.cpp ++++ b/src/x11window.cpp +@@ -309,7 +309,7 @@ X11Window::X11Window() + m_syncRequest.counter = m_syncRequest.alarm = XCB_NONE; + m_syncRequest.timeout = m_syncRequest.failsafeTimeout = nullptr; + m_syncRequest.lastTimestamp = xTime(); +- m_syncRequest.isPending = false; ++ m_syncRequest.pending = false; + m_syncRequest.interactiveResize = false; + + // Set the initial mapping state +@@ -2585,7 +2585,7 @@ void X11Window::getSyncCounter() + */ + void X11Window::sendSyncRequest() + { +- if (m_syncRequest.counter == XCB_NONE || m_syncRequest.isPending) { ++ if (m_syncRequest.counter == XCB_NONE || m_syncRequest.pending) { + return; // do NOT, NEVER send a sync request when there's one on the stack. the clients will just stop respoding. FOREVER! ... + } + +@@ -2599,7 +2599,7 @@ void X11Window::sendSyncRequest() + return; + } + // failed during resize +- m_syncRequest.isPending = false; ++ m_syncRequest.pending = false; + m_syncRequest.interactiveResize = false; + m_syncRequest.counter = XCB_NONE; + m_syncRequest.alarm = XCB_NONE; +@@ -2630,7 +2630,7 @@ void X11Window::sendSyncRequest() + // Send the message to client + sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_sync_request, + m_syncRequest.value.lo, m_syncRequest.value.hi); +- m_syncRequest.isPending = true; ++ m_syncRequest.pending = true; + m_syncRequest.interactiveResize = isInteractiveResize(); + m_syncRequest.lastTimestamp = xTime(); + } +@@ -3062,7 +3062,7 @@ void X11Window::checkApplicationMenuObjectPath() + void X11Window::ackSync() + { + setReadyForPainting(); +- m_syncRequest.isPending = false; ++ m_syncRequest.pending = false; + if (m_syncRequest.failsafeTimeout) { + m_syncRequest.failsafeTimeout->stop(); + } +@@ -4840,7 +4840,7 @@ void X11Window::leaveInteractiveMoveResize() + + bool X11Window::isWaitingForInteractiveResizeSync() const + { +- return m_syncRequest.isPending && m_syncRequest.interactiveResize; ++ return m_syncRequest.pending && m_syncRequest.interactiveResize; + } + + void X11Window::doInteractiveResizeSync(const QRectF &rect) +diff --git a/src/x11window.h b/src/x11window.h +index b54db23345..10fa57eaf2 100644 +--- a/src/x11window.h ++++ b/src/x11window.h +@@ -285,7 +285,7 @@ public: + xcb_sync_alarm_t alarm; + xcb_timestamp_t lastTimestamp; + QTimer *timeout, *failsafeTimeout; +- bool isPending; ++ bool pending; + bool interactiveResize; + }; + const SyncRequest &syncRequest() const +-- +2.46.1 + + +From 61e7061998ce3244325af62aac198ecf058a1aeb Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Fri, 4 Oct 2024 23:12:44 +0300 +Subject: [PATCH 4/9] Make XSync timeout more permissive + +There are two timeouts: a soft one and a hard one. If the soft timeout +occurs, then the scheduled operation will be performed. For example, +the window will be marked as ready for painting or resized. If the hard +timeout occurs, _NET_WM_SYNC_REQUEST will be disabled. + +Such an arrangement is fine in its current present form, but in order +to make Xwayland window resizing less glitchy, _NET_WM_SYNC_REQUEST +code needs to interact with wl_surface event flow, which in its turn +means that the timeout code also needs to be prepared for that. It is +very challenging to make the timeout code not break, so this change +seeks to re-arrange the timeout handling so it's easier to integrate +with wl_surface commits. + +With the proposed changes, there is going to be only one timer: timeout. +If it fires, the window will be resized immediately and XSync is going +to be kept disabled until an acknowledgement arrives from the client. +--- + src/x11window.cpp | 101 +++++++++++++++++----------------------------- + src/x11window.h | 5 ++- + 2 files changed, 41 insertions(+), 65 deletions(-) + +diff --git a/src/x11window.cpp b/src/x11window.cpp +index 2ebb4a5957..1d25ab82b1 100644 +--- a/src/x11window.cpp ++++ b/src/x11window.cpp +@@ -307,8 +307,9 @@ X11Window::X11Window() + + // TODO: Do all as initialization + m_syncRequest.counter = m_syncRequest.alarm = XCB_NONE; +- m_syncRequest.timeout = m_syncRequest.failsafeTimeout = nullptr; ++ m_syncRequest.timeout = nullptr; + m_syncRequest.lastTimestamp = xTime(); ++ m_syncRequest.enabled = false; + m_syncRequest.pending = false; + m_syncRequest.interactiveResize = false; + +@@ -460,9 +461,6 @@ void X11Window::releaseWindow(bool on_shutdown) + ungrabXServer(); + } + +- if (m_syncRequest.failsafeTimeout) { +- m_syncRequest.failsafeTimeout->stop(); +- } + if (m_syncRequest.timeout) { + m_syncRequest.timeout->stop(); + } +@@ -516,9 +514,6 @@ void X11Window::destroyWindow() + m_frame.reset(); + } + +- if (m_syncRequest.failsafeTimeout) { +- m_syncRequest.failsafeTimeout->stop(); +- } + if (m_syncRequest.timeout) { + m_syncRequest.timeout->stop(); + } +@@ -2550,6 +2545,7 @@ void X11Window::getSyncCounter() + Xcb::Property syncProp(false, window(), atoms->net_wm_sync_request_counter, XCB_ATOM_CARDINAL, 0, 1); + const xcb_sync_counter_t counter = syncProp.value(XCB_NONE); + if (counter != XCB_NONE) { ++ m_syncRequest.enabled = true; + m_syncRequest.counter = counter; + m_syncRequest.value.hi = 0; + m_syncRequest.value.lo = 0; +@@ -2585,35 +2581,16 @@ void X11Window::getSyncCounter() + */ + void X11Window::sendSyncRequest() + { +- if (m_syncRequest.counter == XCB_NONE || m_syncRequest.pending) { ++ if (!m_syncRequest.enabled || m_syncRequest.pending) { + return; // do NOT, NEVER send a sync request when there's one on the stack. the clients will just stop respoding. FOREVER! ... + } + +- if (!m_syncRequest.failsafeTimeout) { +- m_syncRequest.failsafeTimeout = new QTimer(this); +- connect(m_syncRequest.failsafeTimeout, &QTimer::timeout, this, [this]() { +- // client does not respond to XSYNC requests in reasonable time, remove support +- if (!ready_for_painting) { +- // failed on initial pre-show request +- setReadyForPainting(); +- return; +- } +- // failed during resize +- m_syncRequest.pending = false; +- m_syncRequest.interactiveResize = false; +- m_syncRequest.counter = XCB_NONE; +- m_syncRequest.alarm = XCB_NONE; +- delete m_syncRequest.timeout; +- delete m_syncRequest.failsafeTimeout; +- m_syncRequest.timeout = nullptr; +- m_syncRequest.failsafeTimeout = nullptr; +- m_syncRequest.lastTimestamp = XCB_CURRENT_TIME; +- }); +- m_syncRequest.failsafeTimeout->setSingleShot(true); ++ if (!m_syncRequest.timeout) { ++ m_syncRequest.timeout = new QTimer(this); ++ m_syncRequest.timeout->setSingleShot(true); ++ connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Window::ackSyncTimeout); + } +- // if there's no response within 10 seconds, sth. went wrong and we remove XSYNC support from this client. +- // see events.cpp X11Window::syncEvent() +- m_syncRequest.failsafeTimeout->start(ready_for_painting ? 10000 : 1000); ++ m_syncRequest.timeout->start(ready_for_painting ? 10000 : 1000); + + // We increment before the notify so that after the notify + // syncCounterSerial will equal the value we are expecting +@@ -3061,29 +3038,40 @@ void X11Window::checkApplicationMenuObjectPath() + + void X11Window::ackSync() + { +- setReadyForPainting(); ++ // Note that a sync request can be ack'ed after the timeout. If that happens, just re-enable ++ // XSync back and do nothing more. + m_syncRequest.pending = false; +- if (m_syncRequest.failsafeTimeout) { +- m_syncRequest.failsafeTimeout->stop(); ++ if (!m_syncRequest.enabled) { ++ m_syncRequest.enabled = true; ++ return; + } + +- // Sync request can be acknowledged shortly after finishing resize. ++ m_syncRequest.timeout->stop(); ++ ++ finishSync(); ++} ++ ++void X11Window::ackSyncTimeout() ++{ ++ // If a sync request times out, disable XSync temporarily until the client comes back to its senses. ++ m_syncRequest.enabled = false; ++ ++ finishSync(); ++} ++ ++void X11Window::finishSync() ++{ ++ setReadyForPainting(); ++ + if (m_syncRequest.interactiveResize) { + m_syncRequest.interactiveResize = false; +- if (m_syncRequest.timeout) { +- m_syncRequest.timeout->stop(); +- } +- performInteractiveResize(); ++ ++ moveResize(moveResizeGeometry()); + updateWindowPixmap(); ++ setAllowCommits(true); + } + } + +-void X11Window::performInteractiveResize() +-{ +- resize(moveResizeGeometry().size()); +- setAllowCommits(true); +-} +- + bool X11Window::belongToSameApplication(const X11Window *c1, const X11Window *c2, SameApplicationChecks checks) + { + bool same_app = false; +@@ -4840,7 +4828,7 @@ void X11Window::leaveInteractiveMoveResize() + + bool X11Window::isWaitingForInteractiveResizeSync() const + { +- return m_syncRequest.pending && m_syncRequest.interactiveResize; ++ return m_syncRequest.enabled && m_syncRequest.pending && m_syncRequest.interactiveResize; + } + + void X11Window::doInteractiveResizeSync(const QRectF &rect) +@@ -4857,30 +4845,17 @@ void X11Window::doInteractiveResizeSync(const QRectF &rect) + return; + } + +- if (m_syncRequest.counter == XCB_NONE) { ++ if (!m_syncRequest.enabled) { + moveResize(rect); + } else { +- if (!m_syncRequest.timeout) { +- m_syncRequest.timeout = new QTimer(this); +- connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Window::ackSyncTimeout); +- m_syncRequest.timeout->setSingleShot(true); +- } +- + setMoveResizeGeometry(moveResizeFrameGeometry); + setAllowCommits(false); + + sendSyncRequest(); + configure(nativeFrameGeometry, nativeWrapperGeometry, nativeClientGeometry); +- +- m_syncRequest.timeout->start(250); + } + } + +-void X11Window::ackSyncTimeout() +-{ +- performInteractiveResize(); +-} +- + NETExtendedStrut X11Window::strut() const + { + NETExtendedStrut ext = info->extendedStrut(); +@@ -4991,7 +4966,7 @@ void X11Window::damageNotifyEvent() + Q_ASSERT(kwinApp()->operationMode() == Application::OperationModeX11); + + if (!readyForPainting()) { // avoid "setReadyForPainting()" function calling overhead +- if (m_syncRequest.counter == XCB_NONE) { // cannot detect complete redraw, consider done now ++ if (!m_syncRequest.enabled) { // cannot detect complete redraw, consider done now + setReadyForPainting(); + } + } +@@ -5025,7 +5000,7 @@ void X11Window::updateWindowPixmap() + void X11Window::associate() + { + auto handleMapped = [this]() { +- if (syncRequest().counter == XCB_NONE) { // cannot detect complete redraw, consider done now ++ if (!m_syncRequest.enabled) { // cannot detect complete redraw, consider done now + setReadyForPainting(); + } + }; +diff --git a/src/x11window.h b/src/x11window.h +index 10fa57eaf2..6b430b861a 100644 +--- a/src/x11window.h ++++ b/src/x11window.h +@@ -284,7 +284,8 @@ public: + xcb_sync_int64_t value; + xcb_sync_alarm_t alarm; + xcb_timestamp_t lastTimestamp; +- QTimer *timeout, *failsafeTimeout; ++ QTimer *timeout; ++ bool enabled; + bool pending; + bool interactiveResize; + }; +@@ -295,6 +296,7 @@ public: + bool wantsSyncCounter() const; + void ackSync(); + void ackSyncTimeout(); ++ void finishSync(); + + bool allowWindowActivation(xcb_timestamp_t time = -1U, bool focus_in = false); + +@@ -385,7 +387,6 @@ private: + void getSyncCounter(); + void sendSyncRequest(); + void leaveInteractiveMoveResize() override; +- void performInteractiveResize(); + void establishCommandWindowGrab(uint8_t button); + void establishCommandAllGrab(uint8_t button); + +-- +2.46.1 + + +From dd10d1b329b06ab3377f669a610fec9726f28a70 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Fri, 4 Oct 2024 23:20:03 +0300 +Subject: [PATCH 5/9] Disable Xwayland surface commits for all sync requests + +--- + src/x11window.cpp | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/src/x11window.cpp b/src/x11window.cpp +index 1d25ab82b1..5688ea6da8 100644 +--- a/src/x11window.cpp ++++ b/src/x11window.cpp +@@ -2604,7 +2604,7 @@ void X11Window::sendSyncRequest() + kwinApp()->updateXTime(); + } + +- // Send the message to client ++ setAllowCommits(false); + sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_sync_request, + m_syncRequest.value.lo, m_syncRequest.value.hi); + m_syncRequest.pending = true; +@@ -3049,6 +3049,7 @@ void X11Window::ackSync() + m_syncRequest.timeout->stop(); + + finishSync(); ++ setAllowCommits(true); + } + + void X11Window::ackSyncTimeout() +@@ -3057,6 +3058,7 @@ void X11Window::ackSyncTimeout() + m_syncRequest.enabled = false; + + finishSync(); ++ setAllowCommits(true); + } + + void X11Window::finishSync() +@@ -3068,7 +3070,6 @@ void X11Window::finishSync() + + moveResize(moveResizeGeometry()); + updateWindowPixmap(); +- setAllowCommits(true); + } + } + +@@ -4849,8 +4850,6 @@ void X11Window::doInteractiveResizeSync(const QRectF &rect) + moveResize(rect); + } else { + setMoveResizeGeometry(moveResizeFrameGeometry); +- setAllowCommits(false); +- + sendSyncRequest(); + configure(nativeFrameGeometry, nativeWrapperGeometry, nativeClientGeometry); + } +-- +2.46.1 + + +From 60ef3223e42a06110693fef3ec493662c799af38 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Fri, 4 Oct 2024 23:40:41 +0300 +Subject: [PATCH 6/9] Make Xwayland resizing less glitchy + +XSYNC requests and wl_surface commits are unsynchronized. This results +in the window bouncing when it's being resized. + +Let's consider a concrete example. Assume that there is a window with 0,0 +100x100 geometry and it is being resized by dragging the left edge. If +the left edge is dragged by 10px, the following will occur: + +- wl_surface commits will be blocked (it is needed to ensure the + consistent order of XSync acknowledgements and wl_surface commits) +- an XSync request will be sent +- a ConfigureNotify event will be sent +- a client processes the ConfigureNotify by repainting the window and + acknowledges the XSync request +- kwin notices that the XSync request has been acked and updates the + window position to 10,0 and unblocks surface commits + +The problem is that it can take a while for Xwayland to attach a new +buffer to the surface with a size of 90x100. If kwin composes a frame in +meanwhile, the effective geometry of the window will be 10,0 100x100, +i.e. the right window edge will stick by 10px. Some time later, Xwayland +would attach a buffer with the right size (90x100), and the right window +edge will be put back in the right place. + +In order to address the bouncing, this change reworks how the +synchronization is performed: + +- when a window is asked to resize, kwin will freeze wl_surface commits, + send a sync request, and configure the window +- after the client repaints the window, it acks the sync request +- when kwin sees that the sync request has been acked, it will unfreeze + the wl_surface commits. And here's the most important part: it will NOT + update the window position until Xwayland commits something +- when Xwayland commits the wl_surface, kwin will update the window geometry + +It's important to wait until Xwayland commits the wl_surface because, as +it was said previously, it can take a while until Xwayland commits the +wl_surface and kwin could compose a frame with the new position but old +surface size in meanwhile. + +BUG: 486464 +--- + src/x11window.cpp | 40 +++++++++++++++++++++++++++++----------- + src/x11window.h | 2 ++ + 2 files changed, 31 insertions(+), 11 deletions(-) + +diff --git a/src/x11window.cpp b/src/x11window.cpp +index 5688ea6da8..b22de557d8 100644 +--- a/src/x11window.cpp ++++ b/src/x11window.cpp +@@ -311,6 +311,7 @@ X11Window::X11Window() + m_syncRequest.lastTimestamp = xTime(); + m_syncRequest.enabled = false; + m_syncRequest.pending = false; ++ m_syncRequest.acked = false; + m_syncRequest.interactiveResize = false; + + // Set the initial mapping state +@@ -3046,9 +3047,13 @@ void X11Window::ackSync() + return; + } + ++ m_syncRequest.acked = true; + m_syncRequest.timeout->stop(); + +- finishSync(); ++ // With Xwayland, the sync request will be completed after the wl_surface is committed. ++ if (!waylandServer()) { ++ finishSync(); ++ } + setAllowCommits(true); + } + +@@ -3071,6 +3076,8 @@ void X11Window::finishSync() + moveResize(moveResizeGeometry()); + updateWindowPixmap(); + } ++ ++ m_syncRequest.acked = false; + } + + bool X11Window::belongToSameApplication(const X11Window *c1, const X11Window *c2, SameApplicationChecks checks) +@@ -3945,6 +3952,19 @@ void X11Window::handleXwaylandScaleChanged() + resize(moveResizeGeometry().size()); + } + ++void X11Window::handleCommitted() ++{ ++ if (surface()->isMapped()) { ++ if (m_syncRequest.acked) { ++ finishSync(); ++ } ++ ++ if (!m_syncRequest.enabled) { ++ setReadyForPainting(); ++ } ++ } ++} ++ + void X11Window::setAllowCommits(bool allow) + { + if (!waylandServer()) { +@@ -4829,7 +4849,7 @@ void X11Window::leaveInteractiveMoveResize() + + bool X11Window::isWaitingForInteractiveResizeSync() const + { +- return m_syncRequest.enabled && m_syncRequest.pending && m_syncRequest.interactiveResize; ++ return m_syncRequest.enabled && m_syncRequest.interactiveResize && (m_syncRequest.pending || m_syncRequest.acked); + } + + void X11Window::doInteractiveResizeSync(const QRectF &rect) +@@ -4998,19 +5018,17 @@ void X11Window::updateWindowPixmap() + + void X11Window::associate() + { +- auto handleMapped = [this]() { +- if (!m_syncRequest.enabled) { // cannot detect complete redraw, consider done now +- setReadyForPainting(); ++ if (surface()->isMapped()) { ++ if (m_syncRequest.acked) { ++ finishSync(); + } +- }; + +- if (surface()->isMapped()) { +- handleMapped(); +- } else { +- connect(surface(), &SurfaceInterface::mapped, this, handleMapped); ++ if (!m_syncRequest.enabled) { ++ setReadyForPainting(); ++ } + } + +- m_pendingSurfaceId = 0; ++ connect(surface(), &SurfaceInterface::committed, this, &X11Window::handleCommitted); + } + + QWindow *X11Window::findInternalWindow() const +diff --git a/src/x11window.h b/src/x11window.h +index 6b430b861a..73d4c23a4c 100644 +--- a/src/x11window.h ++++ b/src/x11window.h +@@ -287,6 +287,7 @@ public: + QTimer *timeout; + bool enabled; + bool pending; ++ bool acked; + bool interactiveResize; + }; + const SyncRequest &syncRequest() const +@@ -438,6 +439,7 @@ private: + void checkOutput(); + void associate(); + void handleXwaylandScaleChanged(); ++ void handleCommitted(); + + void setAllowCommits(bool allow); + +-- +2.46.1 + + +From 59f45806953e05bbf289480b9e5882e4d87ee434 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Thu, 3 Oct 2024 00:43:57 +0300 +Subject: [PATCH 7/9] scene: Use standard wl_surface item for Xwayland surfaces + +Besides unifying the code, it fixes some visual glitches caused by the +opaque region getting out of sync. + +Xwayland MR: https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1698 +--- + src/scene/surfaceitem_wayland.cpp | 21 --------------------- + src/scene/surfaceitem_wayland.h | 19 ------------------- + src/scene/windowitem.cpp | 2 +- + 3 files changed, 1 insertion(+), 41 deletions(-) + +diff --git a/src/scene/surfaceitem_wayland.cpp b/src/scene/surfaceitem_wayland.cpp +index a4d012f774..04961952b9 100644 +--- a/src/scene/surfaceitem_wayland.cpp ++++ b/src/scene/surfaceitem_wayland.cpp +@@ -12,11 +12,6 @@ + #include "wayland/linuxdmabufv1clientbuffer.h" + #include "wayland/subcompositor.h" + #include "wayland/surface.h" +-#include "window.h" +- +-#if KWIN_BUILD_X11 +-#include "x11window.h" +-#endif + + namespace KWin + { +@@ -247,22 +242,6 @@ bool SurfacePixmapWayland::isValid() const + return m_bufferRef; + } + +-#if KWIN_BUILD_X11 +-SurfaceItemXwayland::SurfaceItemXwayland(X11Window *window, Item *parent) +- : SurfaceItemWayland(window->surface(), parent) +- , m_window(window) +-{ +-} +- +-QRegion SurfaceItemXwayland::opaque() const +-{ +- if (!m_window->hasAlpha()) { +- return rect().toRect(); +- } else { +- return m_window->opaqueRegion() & rect().toRect(); +- } +-} +-#endif + } // namespace KWin + + #include "moc_surfaceitem_wayland.cpp" +diff --git a/src/scene/surfaceitem_wayland.h b/src/scene/surfaceitem_wayland.h +index 991cd168c3..fbc7498446 100644 +--- a/src/scene/surfaceitem_wayland.h ++++ b/src/scene/surfaceitem_wayland.h +@@ -16,7 +16,6 @@ namespace KWin + class GraphicsBuffer; + class SubSurfaceInterface; + class SurfaceInterface; +-class X11Window; + + /** + * The SurfaceItemWayland class represents a Wayland surface in the scene. +@@ -83,22 +82,4 @@ private: + SurfaceItemWayland *m_item; + }; + +-#if KWIN_BUILD_X11 +-/** +- * The SurfaceItemXwayland class represents an Xwayland surface in the scene. +- */ +-class KWIN_EXPORT SurfaceItemXwayland : public SurfaceItemWayland +-{ +- Q_OBJECT +- +-public: +- explicit SurfaceItemXwayland(X11Window *window, Item *parent = nullptr); +- +- QRegion opaque() const override; +- +-private: +- X11Window *m_window; +-}; +-#endif +- + } // namespace KWin +diff --git a/src/scene/windowitem.cpp b/src/scene/windowitem.cpp +index 4283051e7e..913d2708f5 100644 +--- a/src/scene/windowitem.cpp ++++ b/src/scene/windowitem.cpp +@@ -323,7 +323,7 @@ void WindowItemX11::initialize() + if (!window()->surface()) { + updateSurfaceItem(nullptr); + } else { +- updateSurfaceItem(std::make_unique(static_cast(window()), this)); ++ updateSurfaceItem(std::make_unique(window()->surface(), this)); + } + break; + case Application::OperationModeWaylandOnly: +-- +2.46.1 + + +From 84f35749d9084692e0ea8ae4ea187178005457cc Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Mon, 14 Oct 2024 00:34:28 +0300 +Subject: [PATCH 8/9] Send the initial sync request before mapping the frame + window + +When the wl_surface commits are blocked by the initial sync request, it +is really important that Xwayland doesn't commit the surface until the +sync request is acked. However, with the current arrangement of the code, +Xwayland may render something before the sync request is acked. + +It can happen because the frame window is mapped before the initial sync +request is sent. There are many places where it can happen, e.g. in the +setupCompositing() function, or the setMinimized() function, etc. + +In order to ensure that Xwayland won't render the wl_surface while we +are waiting for the sync request to get acked, this change moves the initial +sync request all the way to the top of the manage() function so the +surface commits are blocked before the frame window is mapped. +--- + src/x11window.cpp | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/src/x11window.cpp b/src/x11window.cpp +index b22de557d8..be35fe07fd 100644 +--- a/src/x11window.cpp ++++ b/src/x11window.cpp +@@ -655,6 +655,18 @@ bool X11Window::manage(xcb_window_t w, bool isMapped) + getSyncCounter(); + setCaption(readName()); + ++ if (Compositor::compositing()) { ++ // Sending ConfigureNotify is done when setting mapping state below, getting the ++ // first sync response means window is ready for compositing. ++ // ++ // The sync request will block wl_surface commits, and with Xwayland, it is really ++ // important that wl_surfaces commits are blocked before the frame window is mapped. ++ // Otherwise Xwayland can attach a buffer before the sync request is acked. ++ sendSyncRequest(); ++ } else { ++ ready_for_painting = true; // set to true in case compositing is turned on later ++ } ++ + setupWindowRules(); + connect(this, &X11Window::windowClassChanged, this, &X11Window::evaluateWindowRules); + +@@ -1093,14 +1105,6 @@ bool X11Window::manage(xcb_window_t w, bool isMapped) + workspace()->restoreSessionStackingOrder(this); + } + +- if (Compositor::compositing()) { +- // Sending ConfigureNotify is done when setting mapping state below, +- // Getting the first sync response means window is ready for compositing +- sendSyncRequest(); +- } else { +- ready_for_painting = true; // set to true in case compositing is turned on later. bug #160393 +- } +- + if (isShown()) { + bool allow; + if (session) { +-- +2.46.1 + + +From 3ecac02f2f7573d7b2714c1fb23bebaec8afa0e0 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Thu, 17 Oct 2024 19:21:32 +0300 +Subject: [PATCH 9/9] Block interactive resizing if there is a pending XSync + request + +There cannot be two XSync requests in flight, the type of the sync +requests doesn't matter either, e.g. one for interactive resize or +one to determine whether the client has painted the initial frame. +--- + src/x11window.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/x11window.cpp b/src/x11window.cpp +index be35fe07fd..3e989f29bd 100644 +--- a/src/x11window.cpp ++++ b/src/x11window.cpp +@@ -4853,7 +4853,7 @@ void X11Window::leaveInteractiveMoveResize() + + bool X11Window::isWaitingForInteractiveResizeSync() const + { +- return m_syncRequest.enabled && m_syncRequest.interactiveResize && (m_syncRequest.pending || m_syncRequest.acked); ++ return m_syncRequest.enabled && (m_syncRequest.pending || m_syncRequest.acked); + } + + void X11Window::doInteractiveResizeSync(const QRectF &rect) +-- +2.46.1 + diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index e4a37ce..ca0a27c 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -49,6 +49,11 @@ in { ../kde/patches/libplasma-pr1214.patch ]; }; + kwin = kPrev.kwin.overrideAttrs { + patches = kPrev.kwin.patches ++ [ + ../kde/patches/kwin-pr6406.patch + ]; + }; } ); } From 38281315f7d22d81e33f3a04d90b23be0aa58b6b Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 7 Nov 2024 11:23:42 +0100 Subject: [PATCH 0807/1125] Kde: add konsole patch --- roles/kde/patches/konsole-pr767.patch | 96 +++++++++++++++++++++++++++ roles/kde/plasma.nix | 5 ++ 2 files changed, 101 insertions(+) create mode 100644 roles/kde/patches/konsole-pr767.patch diff --git a/roles/kde/patches/konsole-pr767.patch b/roles/kde/patches/konsole-pr767.patch new file mode 100644 index 0000000..8c757af --- /dev/null +++ b/roles/kde/patches/konsole-pr767.patch @@ -0,0 +1,96 @@ +From fa8f6054c992f8f28781933a23bccb91b3341d6e Mon Sep 17 00:00:00 2001 +From: Christian Muehlhaeuser +Date: Tue, 8 Nov 2022 08:55:14 +0100 +Subject: [PATCH] Add support for OSC-52 write-only clipboard access + +Implements OSC-52 write-only clipboard access. Already supported by +a wide range of other terminals, including alacritty, foot, kitty, +urxvt, wezterm, xterm, and others. + +I've intentionally omitted read access to the clipboard as that +comes with several security concerns, which should be discussed +first. +--- + src/Vt102Emulation.cpp | 36 ++++++++++++++++++++++++++++++++++++ + src/Vt102Emulation.h | 2 +- + 2 files changed, 37 insertions(+), 1 deletion(-) + +diff --git a/src/Vt102Emulation.cpp b/src/Vt102Emulation.cpp +index 49b23c77d4..3b1e389106 100644 +--- a/src/Vt102Emulation.cpp ++++ b/src/Vt102Emulation.cpp +@@ -12,8 +12,10 @@ + #include + + // Qt ++#include + #include + #include ++#include + #include + #include + #include +@@ -1153,6 +1155,40 @@ void Vt102Emulation::processSessionAttributeRequest(const int tokenSize, const u + connect(action, &KNotificationAction::activated, this, [this, notification]() { + _currentScreen->currentTerminalDisplay()->notificationClicked(notification->xdgActivationToken()); + }); ++ } ++ if (attribute == Clipboard) { ++ // Clipboard ++ QStringList params = value.split(QLatin1Char(';')); ++ if (params.length() == 0) { ++ return; ++ } ++ ++ bool clipboard = false; ++ bool selection = false; ++ if (params[0].isEmpty() || params[0].contains(QLatin1Char('c')) || params[0].contains(QLatin1Char('s'))) { ++ clipboard = true; ++ } ++ if (params[0].contains(QLatin1Char('p'))) { ++ selection = true; ++ } ++ ++ if (params.length() == 2) { ++ // Copy to clipboard ++ if (clipboard) { ++ QApplication::clipboard()->setText(QString::fromUtf8(QByteArray::fromBase64(params[1].toUtf8())), QClipboard::Clipboard); ++ } ++ if (selection) { ++ QApplication::clipboard()->setText(QString::fromUtf8(QByteArray::fromBase64(params[1].toUtf8())), QClipboard::Selection); ++ } ++ } else { ++ // Clear clipboard ++ if (clipboard) { ++ QApplication::clipboard()->clear(QClipboard::Clipboard); ++ } ++ if (selection) { ++ QApplication::clipboard()->clear(QClipboard::Selection); ++ } ++ } + + return; + } +diff --git a/src/Vt102Emulation.h b/src/Vt102Emulation.h +index 665e9f026d..3456e068d3 100644 +--- a/src/Vt102Emulation.h ++++ b/src/Vt102Emulation.h +@@ -126,7 +126,6 @@ private: + void resetModes(); + + void resetTokenizer(); +-#define MAX_TOKEN_LENGTH 256 // Max length of tokens (e.g. window title) + void addToCurrentToken(uint cc); + int tokenBufferPos; + +@@ -183,6 +182,7 @@ private: + enum osc { + // https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands + ReportColors = 4, ++ Clipboard = 52, + ResetColors = 104, + // https://gitlab.freedesktop.org/Per_Bothner/specifications/blob/master/proposals/semantic-prompts.md + SemanticPrompts = 133, +-- +GitLab + diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index ca0a27c..cbe8ff5 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -54,6 +54,11 @@ in { ../kde/patches/kwin-pr6406.patch ]; }; + konsole = kPrev.konsole.overrideAttrs { + patches = [ + ../kde/patches/konsole-pr767.patch + ]; + }; } ); } From 99e5c29a3b59ea2b9e350aeda77291999b748eb6 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 7 Nov 2024 12:39:23 +0100 Subject: [PATCH 0808/1125] Server/headscale: update ip prefixes setting --- roles/server/headscale.nix | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/roles/server/headscale.nix b/roles/server/headscale.nix index 17fb680..50ddc6a 100644 --- a/roles/server/headscale.nix +++ b/roles/server/headscale.nix @@ -3,9 +3,7 @@ enable = true; settings = { server_url = "https://headscale.toast003.xyz"; - ip_prefixes = [ - "100.100.0.0/16" - ]; + prefixes.v4 = "100.100.0.0/16"; dns = { base_domain = "tailscale"; nameservers.global = ["9.9.9.9"]; From 8bace4cb22c2570a9d407fcf16d127ea7e62f0a6 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 9 Nov 2024 12:59:27 +0100 Subject: [PATCH 0809/1125] Kde: add breeze cursor to steam --- roles/kde/programs/default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index 4ede2bd..36f0eab 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -1,4 +1,4 @@ -{...}: { +{pkgs, ...}: { imports = [ ./kate.nix ./firefox.nix @@ -11,4 +11,5 @@ # Enable the kde partition manager programs.partition-manager.enable = true; + programs.steam.extraPackages = [pkgs.kdePackages.breeze]; } From aa17ed51c8ee0cb3b1365dc801f4fbb7e9b43a41 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 10 Nov 2024 02:49:43 +0100 Subject: [PATCH 0810/1125] Flake: make devshell without compiler --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 18f8ed7..181507a 100644 --- a/flake.nix +++ b/flake.nix @@ -120,7 +120,7 @@ nixpkgs = (import "${nixpkgs-patched}/flake.nix").outputs {self = inputs.self;}; in { formatter.x86_64-linux = nixpkgs-unstable.legacyPackages.x86_64-linux.alejandra; - devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell { + devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShellNoCC { name = "toast-devshell"; # The agenix cli is not needed to activate a configuration, so instead of installing it # I'll just add it to de devShell, since that's the only real time I'm going to use it. From 3c72a10ec0c0ea623b739382510bfa2f9874059e Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 10 Nov 2024 18:58:25 +0100 Subject: [PATCH 0811/1125] Server/ssh: send a message to discord on login --- flake.lock | 8 ++++---- roles/server/ssh.nix | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 20ca533..f8b45ad 100644 --- a/flake.lock +++ b/flake.lock @@ -593,11 +593,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1726137390, - "narHash": "sha256-RaTOgscAl0pnAT/1DwyitTfFNwFDPZaqN/vTaqAoCTM=", + "lastModified": 1731258517, + "narHash": "sha256-zqYyWyZYK2FsRhqDRaZPmP6IqJ6QRXK37jthHcMAe+8=", "ref": "refs/heads/main", - "rev": "994526ba9affd6e6d617b1743126a36846530c93", - "revCount": 24, + "rev": "4d6184cf5e78978e26839690af7e1a3ff9af92ae", + "revCount": 25, "type": "git", "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets" }, diff --git a/roles/server/ssh.nix b/roles/server/ssh.nix index 07d5edf..d0735ae 100755 --- a/roles/server/ssh.nix +++ b/roles/server/ssh.nix @@ -1,10 +1,40 @@ { flakeSelf, config, + pkgs, + lib, ... }: let hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName + "/"; hostKeyPath = "/etc/ssh/everest_host_key"; + notify = + pkgs.writers.writePython3 "send-discord-login-notification" { + libraries = [pkgs.python3Packages.requests]; + } '' + import requests + import os + + if os.environ["PAM_TYPE"] != "open_session": + raise SystemExit + print("User logging in") + + secretPath = "${config.age.secrets.discord-webhook.path}" + + webhookUrl: str + + with open(secretPath) as file: + webhookUrl = file.read().strip() + + user = os.environ["PAM_USER"] + rhost = os.environ["PAM_RHOST"] + + data = { + "username": "SSH Login", + "content": user + " logged in from " + rhost + } + + result = requests.post(webhookUrl, json=data) + ''; in { age.secrets = { everest-host-key = { @@ -16,6 +46,9 @@ in { file = hostSecrets + "host-public-key.age"; path = hostKeyPath + ".pub"; }; + discord-webhook = { + file = hostSecrets + "discord-webhook.age"; + }; }; users.users.toast.openssh.authorizedKeys.keys = [ @@ -43,4 +76,8 @@ in { ]; startWhenNeeded = true; }; + + security.pam.services.sshd.text = lib.mkDefault (lib.mkAfter '' + session optional pam_exec.so debug stdout ${builtins.trace notify.outPath notify} + ''); } From 25db00118135f882a9c518bbcaf28bb952d9b15b Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 12 Nov 2024 00:07:38 +0100 Subject: [PATCH 0812/1125] Server/headscale: start before tailscale --- roles/server/headscale.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/headscale.nix b/roles/server/headscale.nix index 50ddc6a..dd4b0f6 100644 --- a/roles/server/headscale.nix +++ b/roles/server/headscale.nix @@ -20,4 +20,5 @@ }; }; programs.rust-motd.settings.service_status.Headscale = "headscale"; + systemd.services.tailscaled.after = ["headscale.service"]; } From 4159ee98cc51abe554eae7fa7251f118a05848f3 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 9 Nov 2024 13:10:43 +0100 Subject: [PATCH 0813/1125] Kde: move konsole patches into konsole.nix --- roles/kde/plasma.nix | 5 ----- roles/kde/programs/konsole.nix | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index cbe8ff5..ca0a27c 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -54,11 +54,6 @@ in { ../kde/patches/kwin-pr6406.patch ]; }; - konsole = kPrev.konsole.overrideAttrs { - patches = [ - ../kde/patches/konsole-pr767.patch - ]; - }; } ); } diff --git a/roles/kde/programs/konsole.nix b/roles/kde/programs/konsole.nix index 407e2ad..8f1642a 100644 --- a/roles/kde/programs/konsole.nix +++ b/roles/kde/programs/konsole.nix @@ -24,4 +24,19 @@ in { }; }; }; + nixpkgs.overlays = [ + ( + final: prev: { + kdePackages = prev.kdePackages.overrideScope ( + kFinal: kPrev: { + konsole = kPrev.konsole.overrideAttrs { + patches = [ + ../kde/patches/konsole-pr767.patch + ]; + }; + } + ); + } + ) + ]; } From 147c52ee20c651b213af80da47e48f56de0977fe Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 9 Nov 2024 13:22:34 +0100 Subject: [PATCH 0814/1125] Kde: rework patch paths --- roles/kde/plasma.nix | 4 ++-- roles/kde/programs/konsole.nix | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index ca0a27c..e5b8576 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -46,12 +46,12 @@ in { kFinal: kPrev: { libplasma = kPrev.libplasma.overrideAttrs { patches = [ - ../kde/patches/libplasma-pr1214.patch + ./patches/libplasma-pr1214.patch ]; }; kwin = kPrev.kwin.overrideAttrs { patches = kPrev.kwin.patches ++ [ - ../kde/patches/kwin-pr6406.patch + ./patches/kwin-pr6406.patch ]; }; } diff --git a/roles/kde/programs/konsole.nix b/roles/kde/programs/konsole.nix index 8f1642a..6bf8ae8 100644 --- a/roles/kde/programs/konsole.nix +++ b/roles/kde/programs/konsole.nix @@ -31,7 +31,7 @@ in { kFinal: kPrev: { konsole = kPrev.konsole.overrideAttrs { patches = [ - ../kde/patches/konsole-pr767.patch + ../patches/konsole-pr767.patch ]; }; } From 183ebd78d1088ff23c94c2fcba07fbe1f1d2a221 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 9 Nov 2024 13:32:55 +0100 Subject: [PATCH 0815/1125] Kde: move kwin configs and patches into separate file --- roles/kde/plasma.nix | 25 ------------------- roles/kde/programs/default.nix | 1 + roles/kde/programs/kwin.nix | 45 ++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 25 deletions(-) create mode 100644 roles/kde/programs/kwin.nix diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index e5b8576..ca29d2e 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -49,11 +49,6 @@ in { ./patches/libplasma-pr1214.patch ]; }; - kwin = kPrev.kwin.overrideAttrs { - patches = kPrev.kwin.patches ++ [ - ./patches/kwin-pr6406.patch - ]; - }; } ); } @@ -93,16 +88,6 @@ in { theme = "default"; colorScheme = "CatppuccinMochaMauve"; }; - kwin = { - titlebarButtons = { - left = ["on-all-desktops" "keep-above-windows"]; - right = ["minimize" "maximize" "close"]; - }; - virtualDesktops = { - rows = 1; - number = 2; - }; - }; input = { keyboard = { layouts = [{layout = "es";}]; @@ -133,17 +118,7 @@ in { ]; } ]; - shortcuts = { - "kwin" = { - "Switch One Desktop to the Left" = ["Meta+Ctrl+Left"]; - "Switch One Desktop to the Right" = ["Meta+Ctrl+Right"]; - }; - }; configFile = { - "kwinrc" = { - "org.kde.kdecoration2"."BorderSize".value = "None"; - "TabBox"."LayoutName".value = "thumbnail_grid"; - }; "kdeglobals"."General"."AccentColor".value = null; "auroraerc"."CatppuccinMocha-Classic"."ButtonSize".value = 0; "plasmanotifyrc"."Notifications"."NormalAlwaysOnTop".value = true; diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index 36f0eab..fe160e8 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -7,6 +7,7 @@ # ./neochat.nix ./konsole.nix ./git.nix + ./kwin.nix ]; # Enable the kde partition manager diff --git a/roles/kde/programs/kwin.nix b/roles/kde/programs/kwin.nix new file mode 100644 index 0000000..0dfddbb --- /dev/null +++ b/roles/kde/programs/kwin.nix @@ -0,0 +1,45 @@ +{...}: { + nixpkgs.overlays = [ + ( + final: prev: { + kdePackages = prev.kdePackages.overrideScope ( + kFinal: kPrev: { + kwin = kPrev.kwin.overrideAttrs { + patches = + kPrev.kwin.patches + ++ [ + ./patches/kwin-pr6406.patch + ]; + }; + } + ); + } + ) + ]; + home-manager.users.toast = { + programs.plasma = { + kwin = { + titlebarButtons = { + left = ["on-all-desktops" "keep-above-windows"]; + right = ["minimize" "maximize" "close"]; + }; + virtualDesktops = { + rows = 1; + number = 2; + }; + }; + configFile = { + "kwinrc" = { + "org.kde.kdecoration2"."BorderSize".value = "None"; + "TabBox"."LayoutName".value = "thumbnail_grid"; + }; + }; + shortcuts = { + "kwin" = { + "Switch One Desktop to the Left" = ["Meta+Ctrl+Left"]; + "Switch One Desktop to the Right" = ["Meta+Ctrl+Right"]; + }; + }; + }; + }; +} From 9cbd262e142a5bdaa6330592c57eb5e4064ccd93 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 12 Nov 2024 09:58:25 +0100 Subject: [PATCH 0816/1125] Kde/kwin: fix patch path --- roles/kde/programs/kwin.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/kde/programs/kwin.nix b/roles/kde/programs/kwin.nix index 0dfddbb..2d6a747 100644 --- a/roles/kde/programs/kwin.nix +++ b/roles/kde/programs/kwin.nix @@ -8,7 +8,7 @@ patches = kPrev.kwin.patches ++ [ - ./patches/kwin-pr6406.patch + ../patches/kwin-pr6406.patch ]; }; } From 84f5b7537be173737c36af6d3ae9d1bab4adebf8 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 12 Nov 2024 10:50:23 +0100 Subject: [PATCH 0817/1125] Kde: add plasma-workspace patch --- .../kde/patches/plasma_workspace-pr4883.patch | 40 +++++++++++++++++++ roles/kde/plasma.nix | 5 +++ 2 files changed, 45 insertions(+) create mode 100644 roles/kde/patches/plasma_workspace-pr4883.patch diff --git a/roles/kde/patches/plasma_workspace-pr4883.patch b/roles/kde/patches/plasma_workspace-pr4883.patch new file mode 100644 index 0000000..7b575d0 --- /dev/null +++ b/roles/kde/patches/plasma_workspace-pr4883.patch @@ -0,0 +1,40 @@ +From 11e7f5306fa013ec5c2b894a28457dabf5c42bad Mon Sep 17 00:00:00 2001 +From: Nate Graham +Date: Wed, 30 Oct 2024 21:55:49 -0600 +Subject: [PATCH] Merge "Settings" menu category into "System" + +This category is a bit of an odd duck. On a default install, it contains +only one item: System Settings. Random other apps you install will also +appear there, but all of these could just as logically live in the +"System" category. Let's put them there, so as to consolidate two +nebulous overlapping categories into one clear and obvious one. +--- + menu/desktop/plasma-applications.menu | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +diff --git a/menu/desktop/plasma-applications.menu b/menu/desktop/plasma-applications.menu +index e153604252e..85f842d6a04 100644 +--- a/menu/desktop/plasma-applications.menu ++++ b/menu/desktop/plasma-applications.menu +@@ -334,17 +334,11 @@ + + + +-

    +- Settingsmenu +- kf5-settingsmenu.directory +- +- Settings +- +- + + System + kf5-system.directory + ++ Settings + + System + X-KDE-More +-- +GitLab + diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index ca29d2e..dd6b234 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -49,6 +49,11 @@ in { ./patches/libplasma-pr1214.patch ]; }; + plasma-workspace = kPrev.plasma-workspace.overrideAttrs { + patches = kPrev.plasma-workspace.patches ++ [ + ./patches/plasma_workspace-pr4883.patch + ]; + }; } ); } From e952cfa34f617c996c6a3c3e65bf0f5f0dfcafc7 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 12 Nov 2024 11:01:00 +0100 Subject: [PATCH 0818/1125] Flake: update lock file --- flake.lock | 108 ++++++++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/flake.lock b/flake.lock index f8b45ad..b84b46e 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1730036420, - "narHash": "sha256-rv2bz7J6Wo7AenPiu4+ptCB1AFyaMcS77y89zbRAtI8=", + "lastModified": 1731232837, + "narHash": "sha256-0aIwr/RC/oe7rYkfJb47xjdEQDSNcqpFGsEa+EPlDEs=", "owner": "catppuccin", "repo": "nix", - "rev": "0b7bf04628414a402d255924f65e9a0d1a53d92b", + "rev": "32359bf226fe874d3b7a0a5753d291a4da9616fe", "type": "github" }, "original": { @@ -43,11 +43,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1725822842, - "narHash": "sha256-fOR805OwfINbMFzqSmE8piFAFHM9fE+BDdQQUahqDaQ=", + "lastModified": 1731107453, + "narHash": "sha256-U5+2/yP0NMFPHc8/HVz0pKApXvKHB+tNrnQcekGiauc=", "owner": "catppuccin", "repo": "vscode", - "rev": "54316f9afc31c3b5070a242cd3ca47d66ab0e9ac", + "rev": "bbb0b5a231a082790398613266e56268ae2e4de0", "type": "github" }, "original": { @@ -234,11 +234,11 @@ ] }, "locked": { - "lastModified": 1730450782, - "narHash": "sha256-0AfApF8aexgB6o34qqLW2cCX4LaWJajBVdU6ddiWZBM=", + "lastModified": 1731235328, + "narHash": "sha256-NjavpgE9/bMe/ABvZpyHIUeYF1mqR5lhaep3wB79ucs=", "owner": "nix-community", "repo": "home-manager", - "rev": "8ca921e5a806b5b6171add542defe7bdac79d189", + "rev": "60bb110917844d354f3c18e05450606a435d2d10", "type": "github" }, "original": { @@ -276,11 +276,11 @@ ] }, "locked": { - "lastModified": 1730441026, - "narHash": "sha256-xmZQFGeIm2TzXv4jGaQ3nfBoUbt4gKbIv/SHVWw93ag=", + "lastModified": 1731227601, + "narHash": "sha256-aGUQ6W/Oxd9xjH9RQbnUtC61sTK2fWlKr+J7kavT/RQ=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "bd1da5657b8903b293a0ff51eb896a91a544ebed", + "rev": "7691d0ac1deb6ac7482c5a22fe1a14a34ca608b0", "type": "github" }, "original": { @@ -292,11 +292,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1730610940, - "narHash": "sha256-ZsTpii4kZcioRF3bu3/pS374R9GYQVyrMpBNr2ZUnVg=", - "rev": "b1a0e3c0029c2dd5fb7c8dd2db4f9e0b309c9f54", + "lastModified": 1731334117, + "narHash": "sha256-GoddkPg0/UDv06KcQJiOYP/2IzruYorbI03QRCjN3K8=", + "rev": "8a9094303bc7873c979e54ea20b9f50464ee3965", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/b1a0e3c0029c2dd5fb7c8dd2db4f9e0b309c9f54.tar.gz?rev=b1a0e3c0029c2dd5fb7c8dd2db4f9e0b309c9f54" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/8a9094303bc7873c979e54ea20b9f50464ee3965.tar.gz?rev=8a9094303bc7873c979e54ea20b9f50464ee3965" }, "original": { "type": "tarball", @@ -315,11 +315,11 @@ ] }, "locked": { - "lastModified": 1727752861, - "narHash": "sha256-jowmo2aEzrEpPSM96IWtajuogdJm7DjAWxFTEb7Ct0s=", - "rev": "fd186f535a4ac7ae35d98c1dd5d79f0a81b7976d", + "lastModified": 1731185731, + "narHash": "sha256-RNaIu43b9PoXEhW4OqXUNZKY/jezQyCYWwdv1M0VjsA=", + "rev": "691193879d96bdfd1e6ab5ebcca2fadc7604cf34", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/fd186f535a4ac7ae35d98c1dd5d79f0a81b7976d.tar.gz?rev=fd186f535a4ac7ae35d98c1dd5d79f0a81b7976d" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/691193879d96bdfd1e6ab5ebcca2fadc7604cf34.tar.gz?rev=691193879d96bdfd1e6ab5ebcca2fadc7604cf34" }, "original": { "type": "tarball", @@ -338,11 +338,11 @@ ] }, "locked": { - "lastModified": 1727752861, - "narHash": "sha256-jowmo2aEzrEpPSM96IWtajuogdJm7DjAWxFTEb7Ct0s=", - "rev": "fd186f535a4ac7ae35d98c1dd5d79f0a81b7976d", + "lastModified": 1731185731, + "narHash": "sha256-RNaIu43b9PoXEhW4OqXUNZKY/jezQyCYWwdv1M0VjsA=", + "rev": "691193879d96bdfd1e6ab5ebcca2fadc7604cf34", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/fd186f535a4ac7ae35d98c1dd5d79f0a81b7976d.tar.gz?rev=fd186f535a4ac7ae35d98c1dd5d79f0a81b7976d" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/691193879d96bdfd1e6ab5ebcca2fadc7604cf34.tar.gz?rev=691193879d96bdfd1e6ab5ebcca2fadc7604cf34" }, "original": { "type": "tarball", @@ -389,11 +389,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1730403150, - "narHash": "sha256-W1FH5aJ/GpRCOA7DXT/sJHFpa5r8sq2qAUncWwRZ3Gg=", + "lastModified": 1731242966, + "narHash": "sha256-B3C3JLbGw0FtLSWCjBxU961gLNv+BOOBC6WvstKLYMw=", "owner": "nix-community", "repo": "impermanence", - "rev": "0d09341beeaa2367bac5d718df1404bf2ce45e6f", + "rev": "3ed3f0eaae9fcc0a8331e77e9319c8a4abd8a71a", "type": "github" }, "original": { @@ -409,11 +409,11 @@ ] }, "locked": { - "lastModified": 1729999765, - "narHash": "sha256-LYsavZXitFjjyETZoij8usXjTa7fa9AIF3Sk3MJSX+Y=", + "lastModified": 1731209121, + "narHash": "sha256-BF7FBh1hIYPDihdUlImHGsQzaJZVLLfYqfDx41wjuF0=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "0e3a8778c2ee218eff8de6aacf3d2fa6c33b2d4f", + "rev": "896019f04b22ce5db4c0ee4f89978694f44345c3", "type": "github" }, "original": { @@ -429,11 +429,11 @@ ] }, "locked": { - "lastModified": 1729999765, - "narHash": "sha256-LYsavZXitFjjyETZoij8usXjTa7fa9AIF3Sk3MJSX+Y=", + "lastModified": 1731209121, + "narHash": "sha256-BF7FBh1hIYPDihdUlImHGsQzaJZVLLfYqfDx41wjuF0=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "0e3a8778c2ee218eff8de6aacf3d2fa6c33b2d4f", + "rev": "896019f04b22ce5db4c0ee4f89978694f44345c3", "type": "github" }, "original": { @@ -451,11 +451,11 @@ ] }, "locked": { - "lastModified": 1730426071, - "narHash": "sha256-2BkSiHqyWikpz9HSgTBk5kikaQ5m0Rs60C9KA2kf53o=", + "lastModified": 1731375802, + "narHash": "sha256-CvWPEzrl2EA3xrtg9X6K8aqV7T5r0SaDz6PLpGA0yIY=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "4b371c3d119493051d081ff5b6cff689a97ad1a1", + "rev": "b873a123366b9a62f9262414ada8d83b03f1f0bf", "type": "github" }, "original": { @@ -466,11 +466,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1730368399, - "narHash": "sha256-F8vJtG389i9fp3k2/UDYHMed3PLCJYfxCqwiVP7b9ig=", + "lastModified": 1731332224, + "narHash": "sha256-0ctfVp27ingWtY7dbP5+QpSQ98HaOZleU0teyHQUAw0=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "da14839ac5f38ee6adbdb4e6db09b5eef6d6ccdc", + "rev": "184687ae1a3139faa4746168baf071f60d0310c8", "type": "github" }, "original": { @@ -498,11 +498,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1730327045, - "narHash": "sha256-xKel5kd1AbExymxoIfQ7pgcX6hjw9jCgbiBjiUfSVJ8=", + "lastModified": 1731239293, + "narHash": "sha256-q2yjIWFFcTzp5REWQUOU9L6kHdCDmFDpqeix86SOvDc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "080166c15633801df010977d9d7474b4a6c549d7", + "rev": "9256f7c71a195ebe7a218043d9f93390d49e6884", "type": "github" }, "original": { @@ -513,11 +513,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1730200266, - "narHash": "sha256-l253w0XMT8nWHGXuXqyiIC/bMvh1VRszGXgdpQlfhvU=", + "lastModified": 1731139594, + "narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "807e9154dcb16384b1b765ebe9cd2bba2ac287fd", + "rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2", "type": "github" }, "original": { @@ -528,11 +528,11 @@ }, "nur": { "locked": { - "lastModified": 1730455118, - "narHash": "sha256-E5yWeAUKohUot11JBfH7apOyPjqs3z2/fAtUc2LNfHw=", + "lastModified": 1731401176, + "narHash": "sha256-khh5dM0oofqK3wmoL3xD09DokRg8E2XpkeEoOK6ShBg=", "owner": "nix-community", "repo": "NUR", - "rev": "5bf603459b923edbee4955e9fc94b94662add85c", + "rev": "1f5438e9803717a9bbce8b54356e305b87f1fde5", "type": "github" }, "original": { @@ -551,11 +551,11 @@ ] }, "locked": { - "lastModified": 1730366788, - "narHash": "sha256-0Ezvv4KkyFdLAblPBFDgZbiMLlJZtpHruT2i4KC2wIY=", + "lastModified": 1731193165, + "narHash": "sha256-pGF8L5g9QpkQtJP9JmNIRNZfcyhJHf7uT+d8tqI1h6Y=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "f634d5f6ee9be365b2ca08b2d00e0e3b0c240b9e", + "rev": "f33173b9d22e554a6f869626bc01808d35995257", "type": "github" }, "original": { @@ -690,11 +690,11 @@ ] }, "locked": { - "lastModified": 1730426202, - "narHash": "sha256-swwKpE3lrdvcSh6Hjyf/eSe/zPnsZgeVlSl+B4yBpeo=", + "lastModified": 1731375910, + "narHash": "sha256-LSzQ2lj0Tt663NYNEo4R+Mh173zdi/FS0N5L9wYQv4w=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "96dcbddd24edc60ad47f41bb2a73e06099eba4af", + "rev": "db33a1df899d08e12160bc836d34d309d6ca372b", "type": "github" }, "original": { From 0f6f51975db34a25b6d9f6fcf245627c43c0effd Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Nov 2024 10:56:31 +0100 Subject: [PATCH 0819/1125] Flake: update nixpkgs patches --- nixpkgs-patches/handheld-daemon-ui-init.patch | 147 ++++++++++++++++-- 1 file changed, 130 insertions(+), 17 deletions(-) diff --git a/nixpkgs-patches/handheld-daemon-ui-init.patch b/nixpkgs-patches/handheld-daemon-ui-init.patch index 2ace372..bb7bb0d 100644 --- a/nixpkgs-patches/handheld-daemon-ui-init.patch +++ b/nixpkgs-patches/handheld-daemon-ui-init.patch @@ -1,7 +1,7 @@ From 18cd88064d152491d5ba19602db5c5d65bc2d685 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Thu, 18 Apr 2024 11:22:24 +0200 -Subject: [PATCH 1/6] handheld-daemon-ui: init at 3.1.1 +Subject: [PATCH 01/10] handheld-daemon-ui: init at 3.1.1 --- .../by-name/ha/handheld-daemon-ui/package.nix | 39 +++++++++++++++++++ @@ -10,7 +10,7 @@ Subject: [PATCH 1/6] handheld-daemon-ui: init at 3.1.1 diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix new file mode 100644 -index 000000000000000..81d318d88b5abd3 +index 0000000000000..81d318d88b5ab --- /dev/null +++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix @@ -0,0 +1,39 @@ @@ -54,17 +54,18 @@ index 000000000000000..81d318d88b5abd3 + }; +} -From 8ebb1f0976c79c74eb0cea3975c348e36d86a7d1 Mon Sep 17 00:00:00 2001 +From 49fc133081344cbe155eefd7189a6cff2e8b6c6b Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Wed, 10 Jul 2024 12:59:01 +0200 -Subject: [PATCH 2/6] handheld-daemon: add options for handheld-daemon-ui +Subject: [PATCH 02/10] nixos/handheld-daemon: add options for + handheld-daemon-ui --- .../modules/services/hardware/handheld-daemon.nix | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix -index 6c9d5aa3e22c86b..e8e283bca894130 100644 +index 6c9d5aa3e22c8..e8e283bca8941 100644 --- a/nixos/modules/services/hardware/handheld-daemon.nix +++ b/nixos/modules/services/hardware/handheld-daemon.nix @@ -11,6 +11,11 @@ in @@ -104,17 +105,18 @@ index 6c9d5aa3e22c86b..e8e283bca894130 100644 ExecStart = "${ lib.getExe cfg.package } --user ${ cfg.user }"; Nice = "-12"; -From 1b034ab22605b29195dabce893282b05077d0fe7 Mon Sep 17 00:00:00 2001 +From a8cbef4271d515e2733f3f9a32843135e3d255a5 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Thu, 11 Jul 2024 12:11:00 +0200 -Subject: [PATCH 3/6] handheld-daemon: enable ui when enabling handheld-daemon +Subject: [PATCH 03/10] nixos/handheld-daemon: enable ui when enabling + handheld-daemon --- nixos/modules/services/hardware/handheld-daemon.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix -index e8e283bca894130..d78bae5e9bc4833 100644 +index e8e283bca8941..d78bae5e9bc48 100644 --- a/nixos/modules/services/hardware/handheld-daemon.nix +++ b/nixos/modules/services/hardware/handheld-daemon.nix @@ -25,6 +25,7 @@ in @@ -126,17 +128,17 @@ index e8e283bca894130..d78bae5e9bc4833 100644 cfg.package (mkIf cfg.ui.enable cfg.ui.package) -From 0686e34bb16f8538e28b0795a8e5957ead5abdf0 Mon Sep 17 00:00:00 2001 +From 76e8f25d02d909e23dfb00bd02cb276dc4cf5c1c Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Tue, 8 Oct 2024 10:51:00 +0200 -Subject: [PATCH 4/6] handheld-daemon-ui: 3.1.1 -> 3.2.1 +Subject: [PATCH 04/10] handheld-daemon-ui: 3.1.1 -> 3.2.1 --- pkgs/by-name/ha/handheld-daemon-ui/package.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -index 81d318d88b5abd3..028ceeb58f05e96 100644 +index 81d318d88b5ab..028ceeb58f05e 100644 --- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix +++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix @@ -5,11 +5,11 @@ @@ -163,17 +165,17 @@ index 81d318d88b5abd3..028ceeb58f05e96 100644 mkdir -p $out/share/applications substitute ${extractedFiles}/hhd-ui.desktop \ -From d602ac7ac385613c082fe5b87b8462b2a2627a3e Mon Sep 17 00:00:00 2001 +From 1843526bfdf5b5015ab9a070cfad122ec4cfb290 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:14:00 +0200 -Subject: [PATCH 5/6] handheld-daemon-ui: fix desktop item category +Subject: [PATCH 05/10] handheld-daemon-ui: fix desktop item category --- pkgs/by-name/ha/handheld-daemon-ui/package.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -index 028ceeb58f05e96..1aa8266ece44849 100644 +index 028ceeb58f05e..1aa8266ece448 100644 --- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix +++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix @@ -23,7 +23,8 @@ appimageTools.wrapType2 { @@ -187,17 +189,17 @@ index 028ceeb58f05e96..1aa8266ece44849 100644 ''; -From 09b2e9dcb32eb3d6eaa4ba0e65cf7102b50d1d13 Mon Sep 17 00:00:00 2001 +From 9ff4790805b08d7b0ff1d501606eb4ee2c28f675 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:40:05 +0200 -Subject: [PATCH 6/6] handheld-daemon-ui: copy icon to correct folder +Subject: [PATCH 06/10] handheld-daemon-ui: copy icon to correct folder --- pkgs/by-name/ha/handheld-daemon-ui/package.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -index 1aa8266ece44849..a1131ea5c23d64a 100644 +index 1aa8266ece448..a1131ea5c23d6 100644 --- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix +++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix @@ -25,7 +25,9 @@ appimageTools.wrapType2 { @@ -211,3 +213,114 @@ index 1aa8266ece44849..a1131ea5c23d64a 100644 ''; meta = with lib; { + +From b70ac1d16444ae765c3273acb5a3bab27cdc06c6 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Tue, 8 Oct 2024 18:47:43 +0200 +Subject: [PATCH 07/10] nixos/handheld-daemon: replace mkIf with lib.optional + +Co-authored-by: Sandro +--- + nixos/modules/services/hardware/handheld-daemon.nix | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix +index d78bae5e9bc48..02684426b578d 100644 +--- a/nixos/modules/services/hardware/handheld-daemon.nix ++++ b/nixos/modules/services/hardware/handheld-daemon.nix +@@ -28,8 +28,7 @@ in + services.handheld-daemon.ui.enable = mkDefault true; + environment.systemPackages = [ + cfg.package +- (mkIf cfg.ui.enable cfg.ui.package) +- ]; ++ ] ++ lib.optional cfg.ui.enable cfg.ui.package; + services.udev.packages = [ cfg.package ]; + systemd.packages = [ cfg.package ]; + + +From ac8bb4e8ba115162e7140a47b55c0264ec8d830b Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Thu, 10 Oct 2024 11:08:48 +0200 +Subject: [PATCH 08/10] nixos/handheld-daemon: add correct ui package to + service path + +--- + nixos/modules/services/hardware/handheld-daemon.nix | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix +index 02684426b578d..cb20682ec592e 100644 +--- a/nixos/modules/services/hardware/handheld-daemon.nix ++++ b/nixos/modules/services/hardware/handheld-daemon.nix +@@ -40,7 +40,7 @@ in + restartIfChanged = true; + + path = mkIf cfg.ui.enable [ +- pkgs.handheld-daemon-ui ++ cfg.ui.package + pkgs.lsof + ]; + + +From 4f5a6840aed497f33ad61cd3a629288cde8c6dd2 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Wed, 6 Nov 2024 22:36:59 +0100 +Subject: [PATCH 09/10] handheld-daemon-ui: get rid off 'with lib' + +Co-authored-by: Arne Keller <2012gdwu+github@posteo.de> +--- + pkgs/by-name/ha/handheld-daemon-ui/package.nix | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix +index a1131ea5c23d6..92946c9fe0cd2 100644 +--- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix +@@ -30,13 +30,13 @@ appimageTools.wrapType2 { + cp ${extractedFiles}/hhd-ui.png $iconDir + ''; + +- meta = with lib; { +- description = "The main UI for the Handheld Daemon"; ++ meta = { ++ description = "UI for the Handheld Daemon"; + homepage = "https://github.com/hhd-dev/hhd-ui"; +- license = licenses.gpl3Only; +- maintainers = with maintainers; [ toast ]; ++ license = lib.licenses.gpl3Only; ++ maintainers = with lib.maintainers; [ toast ]; + mainProgram = "hhd-ui"; + platforms = [ "x86_64-linux" ]; +- sourceProvenance = with sourceTypes; [ binaryNativeCode ]; ++ sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ]; + }; + } + +From fb63f605c5a14c23d596d070fffc9e89da59526e Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Fri, 15 Nov 2024 10:49:15 +0100 +Subject: [PATCH 10/10] handheld-daemon-ui: 3.2.1 -> 3.2.3 + +--- + pkgs/by-name/ha/handheld-daemon-ui/package.nix | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix +index 92946c9fe0cd2..00c830bd3fc67 100644 +--- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix +@@ -5,11 +5,11 @@ + }: + let + pname = "handheld-daemon-ui"; +- version = "3.2.1"; ++ version = "3.2.3"; + + src = fetchurl { + url = "https://github.com/hhd-dev/hhd-ui/releases/download/v${version}/hhd-ui.Appimage"; +- hash = "sha256-RRXVoeWOO/pR+CAEY0J6Buf/RhA+G0PdxGQVMdAHfwA="; ++ hash = "sha256-VhJrOvE+BebJIAeQlwOOsPfqSrvBnJQavGT7glTrG2o="; + }; + extractedFiles = appimageTools.extractType2 { inherit pname version src; }; + in From 221e4878b4ad0e5527a5a7279dea199686a92c30 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Nov 2024 11:38:27 +0100 Subject: [PATCH 0820/1125] Flake: add nixpkgs patch --- flake.nix | 1 + nixpkgs-patches/pr306227.patch | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 nixpkgs-patches/pr306227.patch diff --git a/flake.nix b/flake.nix index 181507a..a0110f4 100644 --- a/flake.nix +++ b/flake.nix @@ -106,6 +106,7 @@ src = nixpkgs-unstable-raw; patches = [ ./nixpkgs-patches/handheld-daemon-ui-init.patch + ./nixpkgs-patches/pr306227.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr306227.patch b/nixpkgs-patches/pr306227.patch new file mode 100644 index 0000000..7f31202 --- /dev/null +++ b/nixpkgs-patches/pr306227.patch @@ -0,0 +1,24 @@ +From 8abd7b32202df6c492446edb05ef925af1515e18 Mon Sep 17 00:00:00 2001 +From: Dmitry Chermnykh <76gh6rvso@relay.firefox.com> +Date: Tue, 23 Apr 2024 14:00:40 +0500 +Subject: [PATCH] nixos/plasma6: add qtimageformats to the requiredPackages + +This is needed for qt6 apps to be able to work with certain image formats such as .webp and .avif + +Closes https://github.com/NixOS/nixpkgs/issues/304523 +--- + nixos/modules/services/desktop-managers/plasma6.nix | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/nixos/modules/services/desktop-managers/plasma6.nix b/nixos/modules/services/desktop-managers/plasma6.nix +index 856d36b8a3030..d102ef167e314 100644 +--- a/nixos/modules/services/desktop-managers/plasma6.nix ++++ b/nixos/modules/services/desktop-managers/plasma6.nix +@@ -74,6 +74,7 @@ in { + kguiaddons # provides geo URL handlers + kiconthemes # provides Qt plugins + kimageformats # provides Qt plugins ++ qtimageformats # provides optional image formats such as .webp and .avif + kio # provides helper service + a bunch of other stuff + kpackage # provides kpackagetool tool + kservice # provides kbuildsycoca6 tool From 147be344985a38baa28a758570c2003ece63effb Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Nov 2024 12:47:02 +0100 Subject: [PATCH 0821/1125] Revert "Common: temporarely downgrade adw-gtk3" This reverts commit 39fcb86f6e7d679844ea8d35e6fc8a17f27ab553. --- roles/common/configuration.nix | 9 --------- 1 file changed, 9 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index a0d9b39..3f1e6bf 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -111,15 +111,6 @@ "grub" ]; }; - adw-gtk3 = prev.adw-gtk3.overrideAttrs { - version = "5.3"; - src = final.fetchFromGitHub { - owner = "lassekongo83"; - repo = "adw-gtk3"; - rev = "v5.3"; - sha256 = "sha256-DpJLX9PJX1Q8dDOx7YOXQzgNECsKp5uGiCVTX6iSlbI="; - }; - }; } ) ]; From ed5cbe1a050e6ef6bfbf023b0ce3ea5358bffe6e Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 19 Nov 2024 00:36:56 +0100 Subject: [PATCH 0822/1125] Desktop: get rid of vscode --- flake.lock | 109 +---------------------------- flake.nix | 6 -- roles/desktop/programs/default.nix | 1 - roles/desktop/programs/vscode.nix | 44 ------------ 4 files changed, 1 insertion(+), 159 deletions(-) delete mode 100644 roles/desktop/programs/vscode.nix diff --git a/flake.lock b/flake.lock index b84b46e..01a379e 100644 --- a/flake.lock +++ b/flake.lock @@ -38,24 +38,6 @@ "type": "github" } }, - "catppuccin-vsc": { - "inputs": { - "nixpkgs": "nixpkgs" - }, - "locked": { - "lastModified": 1731107453, - "narHash": "sha256-U5+2/yP0NMFPHc8/HVz0pKApXvKHB+tNrnQcekGiauc=", - "owner": "catppuccin", - "repo": "vscode", - "rev": "bbb0b5a231a082790398613266e56268ae2e4de0", - "type": "github" - }, - "original": { - "owner": "catppuccin", - "repo": "vscode", - "type": "github" - } - }, "eza-themes": { "flake": false, "locked": { @@ -88,22 +70,6 @@ "type": "github" } }, - "flake-compat_2": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, "flake-utils": { "inputs": { "systems": "systems_2" @@ -158,24 +124,6 @@ "type": "github" } }, - "flake-utils_4": { - "inputs": { - "systems": "systems_5" - }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "flakey-profile": { "locked": { "lastModified": 1712898590, @@ -480,22 +428,6 @@ "type": "github" } }, - "nixpkgs": { - "locked": { - "lastModified": 1712963716, - "narHash": "sha256-WKm9CvgCldeIVvRz87iOMi8CFVB1apJlkUT4GGvA0iM=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "cfd6b5fc90b15709b780a5a1619695a88505a176", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, "nixpkgs-raw": { "locked": { "lastModified": 1731239293, @@ -568,7 +500,6 @@ "inputs": { "agenix": "agenix", "catppuccin": "catppuccin", - "catppuccin-vsc": "catppuccin-vsc", "eza-themes": "eza-themes", "home-manager": "home-manager_2", "home-manager-unstable": "home-manager-unstable", @@ -586,8 +517,7 @@ "nixpkgs-unstable-raw": "nixpkgs-unstable-raw", "nur": "nur", "plasma-manager": "plasma-manager", - "secrets": "secrets", - "vscode-extensions": "vscode-extensions" + "secrets": "secrets" } }, "secrets": { @@ -665,43 +595,6 @@ "repo": "default", "type": "github" } - }, - "systems_5": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "vscode-extensions": { - "inputs": { - "flake-compat": "flake-compat_2", - "flake-utils": "flake-utils_4", - "nixpkgs": [ - "nixpkgs-unstable-raw" - ] - }, - "locked": { - "lastModified": 1731375910, - "narHash": "sha256-LSzQ2lj0Tt663NYNEo4R+Mh173zdi/FS0N5L9wYQv4w=", - "owner": "nix-community", - "repo": "nix-vscode-extensions", - "rev": "db33a1df899d08e12160bc836d34d309d6ca372b", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nix-vscode-extensions", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index a0110f4..5082170 100644 --- a/flake.nix +++ b/flake.nix @@ -56,12 +56,6 @@ inputs.home-manager.follows = "home-manager-unstable"; }; - catppuccin-vsc.url = "github:catppuccin/vscode"; - - vscode-extensions = { - url = "github:nix-community/nix-vscode-extensions"; - inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; - }; nix-flatpak.url = "github:gmodena/nix-flatpak/main"; nur.url = "github:nix-community/NUR"; diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix index 6b6c94a..9caa2e4 100755 --- a/roles/desktop/programs/default.nix +++ b/roles/desktop/programs/default.nix @@ -4,7 +4,6 @@ ./firefox.nix ./keepassxc.nix ./jamesdsp.nix - ./vscode.nix ./git.nix ./ssh.nix ./appimage.nix diff --git a/roles/desktop/programs/vscode.nix b/roles/desktop/programs/vscode.nix deleted file mode 100644 index 0147762..0000000 --- a/roles/desktop/programs/vscode.nix +++ /dev/null @@ -1,44 +0,0 @@ -{ - pkgs, - flakeSelf, - ... -}: let - inputs = flakeSelf.inputs; -in { - nixpkgs.overlays = [inputs.catppuccin-vsc.overlays.default]; - home-manager.users.toast = { - home.packages = with pkgs; [ - nixpkgs-fmt - ]; - programs.vscode = { - enable = true; - package = pkgs.vscodium; - mutableExtensionsDir = false; - extensions = with inputs.vscode-extensions.extensions.x86_64-linux.open-vsx; [ - jnoortheen.nix-ide - (pkgs.catppuccin-vsc.override { - workbenchMode = "flat"; - extraBordersEnabled = true; - }) - catppuccin.catppuccin-vsc-icons - waderyan.gitblame - ]; - userSettings = { - # VSCode doesn't like nested settings - # https://stackoverflow.com/questions/74134436/is-it-possible-to-express-settings-in-vs-codes-settings-json-where-each-dot-sep - # TODO: write a function that unnests settings - "workbench.colorTheme" = "Catppuccin Mocha"; - "workbench.iconTheme" = "catppuccin-mocha"; - "editor.fontFamily" = "JetBrainsMono Nerd Font"; - "editor.semanticHighlighting.enabled" = true; - "nix.enableLanguageServer" = true; - "nix.serverPath" = "${pkgs.nil}/bin/nil"; - "nix.serverSettings" = { - "nil"."formatting"."command" = ["nixpkgs-fmt"]; - }; - "terminal.integrated.minimumContrastRatio" = 1; - "window.titleBarStyle" = "custom"; - }; - }; - }; -} From 69c9bfca268c26e5e2dfd0d0b1be1679bce8fc3b Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 23 Nov 2024 21:02:35 +0100 Subject: [PATCH 0823/1125] Common: start services managed bu home-manager --- roles/common/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 3f1e6bf..af07bef 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -143,6 +143,7 @@ publicShare = null; # Disable the public folder }; }; + systemd.user.startServices = true; }; }; From e4f9e94269dfdf192ab97016f7997033f7dab205 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 24 Nov 2024 04:18:50 +0100 Subject: [PATCH 0824/1125] Desktop/syncthing: run as a user service managed by home-manager --- flake.lock | 6 +-- roles/desktop/services/syncthing.nix | 67 ++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/flake.lock b/flake.lock index 01a379e..833ae51 100644 --- a/flake.lock +++ b/flake.lock @@ -182,11 +182,11 @@ ] }, "locked": { - "lastModified": 1731235328, - "narHash": "sha256-NjavpgE9/bMe/ABvZpyHIUeYF1mqR5lhaep3wB79ucs=", + "lastModified": 1732303962, + "narHash": "sha256-5Umjb5AdtxV5jSJd5jxoCckh5mlg+FBQDsyAilu637g=", "owner": "nix-community", "repo": "home-manager", - "rev": "60bb110917844d354f3c18e05450606a435d2d10", + "rev": "8cf9cb2ee78aa129e5b8220135a511a2be254c0c", "type": "github" }, "original": { diff --git a/roles/desktop/services/syncthing.nix b/roles/desktop/services/syncthing.nix index ba2ca9f..f3b0713 100644 --- a/roles/desktop/services/syncthing.nix +++ b/roles/desktop/services/syncthing.nix @@ -1,23 +1,54 @@ {config, ...}: { services.syncthing = { - enable = true; - user = "toast"; - group = "users"; - dataDir = config.users.users.toast.home; + # enable = true; + # user = "toast"; + # group = "users"; + # dataDir = config.users.users.toast.home; settings.folders."passwords".path = "~/Documents/Passwords"; }; - # Allow regular users to stop syncthing - # https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service - security.polkit.extraConfig = '' - polkit.addRule(function(action, subject) { - if ( - action.id == "org.freedesktop.systemd1.manage-units" && - action.lookup("unit") == "syncthing.service" && - subject.user == "${config.services.syncthing.user}" - ) - { - return polkit.Result.YES; - } - }) - ''; + age.secrets = { + syncthingCert = { + owner = "toast"; + group = "users"; + }; + syncthingKey = { + owner = "toast"; + group = "users"; + }; + }; + home-manager.users.toast = { + osConfig, + lib, + ... + }: let + systemConfig = osConfig.services.syncthing; + missingOptions = [ + "all_proxy" + "configDir" + "dataDir" + "databaseDir" + "declarative" + "devices" + "folders" + "extraFlags" + "user" + "group" + "systemService" + "openDefaultPorts" + "options" + "relay" + "useInotify" + ]; + removeMissingOptions = rawOptions: ( + # lib.attrsets.filterAttrs (n: v: n == "all_proxy") rawOptions + builtins.removeAttrs rawOptions missingOptions + ); + in { + services.syncthing = removeMissingOptions systemConfig // { + enable = true; + # Renamed options + allProxy = systemConfig.all_proxy; + extraOptions = systemConfig.extraFlags; + }; + }; } From dd079927511256ae7f7f41f227839c45c9e0f401 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 24 Nov 2024 22:26:22 +0100 Subject: [PATCH 0825/1125] Flake: update lock file and change nixpkgs patches --- flake.lock | 102 +++--- flake.nix | 3 +- nixpkgs-patches/handheld-daemon-ui-init.patch | 326 ------------------ nixpkgs-patches/pr306227.patch | 24 -- nixpkgs-patches/pr357897.patch | 145 ++++++++ 5 files changed, 197 insertions(+), 403 deletions(-) delete mode 100644 nixpkgs-patches/handheld-daemon-ui-init.patch delete mode 100644 nixpkgs-patches/pr306227.patch create mode 100644 nixpkgs-patches/pr357897.patch diff --git a/flake.lock b/flake.lock index 833ae51..bb041e1 100644 --- a/flake.lock +++ b/flake.lock @@ -75,11 +75,11 @@ "systems": "systems_2" }, "locked": { - "lastModified": 1726560853, - "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -93,11 +93,11 @@ "systems": "systems_3" }, "locked": { - "lastModified": 1726560853, - "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -182,11 +182,11 @@ ] }, "locked": { - "lastModified": 1732303962, - "narHash": "sha256-5Umjb5AdtxV5jSJd5jxoCckh5mlg+FBQDsyAilu637g=", + "lastModified": 1732453510, + "narHash": "sha256-mAOaLu++YRwOxCJ135Bhgf78WYhIKWHL2aGWCAoXoBg=", "owner": "nix-community", "repo": "home-manager", - "rev": "8cf9cb2ee78aa129e5b8220135a511a2be254c0c", + "rev": "bd58a1132e9b7f121f65313bc662ad6c8a05f878", "type": "github" }, "original": { @@ -224,11 +224,11 @@ ] }, "locked": { - "lastModified": 1731227601, - "narHash": "sha256-aGUQ6W/Oxd9xjH9RQbnUtC61sTK2fWlKr+J7kavT/RQ=", + "lastModified": 1732432618, + "narHash": "sha256-7MzATSBJcR9JUkaDgIJ3jEkQLXIbOjt0lqbmlGkcLDg=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "7691d0ac1deb6ac7482c5a22fe1a14a34ca608b0", + "rev": "98a61cf0708885abddebc6938ca7282928981d5e", "type": "github" }, "original": { @@ -240,11 +240,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1731334117, - "narHash": "sha256-GoddkPg0/UDv06KcQJiOYP/2IzruYorbI03QRCjN3K8=", - "rev": "8a9094303bc7873c979e54ea20b9f50464ee3965", + "lastModified": 1732112222, + "narHash": "sha256-H7GN4++a4vE49SUNojZx+FSk4mmpb2ifJUtJMJHProI=", + "rev": "66f6dbda32959dd5cf3a9aaba15af72d037ab7ff", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/8a9094303bc7873c979e54ea20b9f50464ee3965.tar.gz?rev=8a9094303bc7873c979e54ea20b9f50464ee3965" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/66f6dbda32959dd5cf3a9aaba15af72d037ab7ff.tar.gz?rev=66f6dbda32959dd5cf3a9aaba15af72d037ab7ff" }, "original": { "type": "tarball", @@ -263,11 +263,11 @@ ] }, "locked": { - "lastModified": 1731185731, - "narHash": "sha256-RNaIu43b9PoXEhW4OqXUNZKY/jezQyCYWwdv1M0VjsA=", - "rev": "691193879d96bdfd1e6ab5ebcca2fadc7604cf34", + "lastModified": 1731967274, + "narHash": "sha256-n6dPGRlMGdL8X5gviA6ZuRfUdbdD5KiNN/BpABA5YT0=", + "rev": "aa2846680fa9a2032939d720487942567fd9eb63", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/691193879d96bdfd1e6ab5ebcca2fadc7604cf34.tar.gz?rev=691193879d96bdfd1e6ab5ebcca2fadc7604cf34" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/aa2846680fa9a2032939d720487942567fd9eb63.tar.gz?rev=aa2846680fa9a2032939d720487942567fd9eb63" }, "original": { "type": "tarball", @@ -286,11 +286,11 @@ ] }, "locked": { - "lastModified": 1731185731, - "narHash": "sha256-RNaIu43b9PoXEhW4OqXUNZKY/jezQyCYWwdv1M0VjsA=", - "rev": "691193879d96bdfd1e6ab5ebcca2fadc7604cf34", + "lastModified": 1731967274, + "narHash": "sha256-n6dPGRlMGdL8X5gviA6ZuRfUdbdD5KiNN/BpABA5YT0=", + "rev": "aa2846680fa9a2032939d720487942567fd9eb63", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/691193879d96bdfd1e6ab5ebcca2fadc7604cf34.tar.gz?rev=691193879d96bdfd1e6ab5ebcca2fadc7604cf34" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/aa2846680fa9a2032939d720487942567fd9eb63.tar.gz?rev=aa2846680fa9a2032939d720487942567fd9eb63" }, "original": { "type": "tarball", @@ -299,11 +299,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1730108712, - "narHash": "sha256-vIvmXmjAQIY39hACGFe/cdBK2r3ZprpHLwX2HIy7Mj8=", + "lastModified": 1732304879, + "narHash": "sha256-/DOW8VadE//HA6tuV2++NowYWi7Wa/FmJHXRJoTQnfQ=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "1cba177bb0a948c919af7596e40bef307543d40a", + "rev": "c84579946c03c996916be0fb6e1340f444c277af", "type": "github" }, "original": { @@ -357,11 +357,11 @@ ] }, "locked": { - "lastModified": 1731209121, - "narHash": "sha256-BF7FBh1hIYPDihdUlImHGsQzaJZVLLfYqfDx41wjuF0=", + "lastModified": 1732458224, + "narHash": "sha256-6CHj+ce0yGOEuKbM0gERuNkLAOrkmcmw5kLYHaW8eMw=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "896019f04b22ce5db4c0ee4f89978694f44345c3", + "rev": "e5105f148c36e423377c6be187186b5bf706c268", "type": "github" }, "original": { @@ -377,11 +377,11 @@ ] }, "locked": { - "lastModified": 1731209121, - "narHash": "sha256-BF7FBh1hIYPDihdUlImHGsQzaJZVLLfYqfDx41wjuF0=", + "lastModified": 1732458224, + "narHash": "sha256-6CHj+ce0yGOEuKbM0gERuNkLAOrkmcmw5kLYHaW8eMw=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "896019f04b22ce5db4c0ee4f89978694f44345c3", + "rev": "e5105f148c36e423377c6be187186b5bf706c268", "type": "github" }, "original": { @@ -399,11 +399,11 @@ ] }, "locked": { - "lastModified": 1731375802, - "narHash": "sha256-CvWPEzrl2EA3xrtg9X6K8aqV7T5r0SaDz6PLpGA0yIY=", + "lastModified": 1732413484, + "narHash": "sha256-KZYNKQVAf53MvT4zs8ybtswyJUw5f1HzshZWgCDJQm4=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "b873a123366b9a62f9262414ada8d83b03f1f0bf", + "rev": "a950aa08f1868355d8b5fe89613f17468d2ae697", "type": "github" }, "original": { @@ -414,11 +414,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1731332224, - "narHash": "sha256-0ctfVp27ingWtY7dbP5+QpSQ98HaOZleU0teyHQUAw0=", + "lastModified": 1731797098, + "narHash": "sha256-UhWmEZhwJZmVZ1jfHZFzCg+ZLO9Tb/v3Y6LC0UNyeTo=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "184687ae1a3139faa4746168baf071f60d0310c8", + "rev": "672ac2ac86f7dff2f6f3406405bddecf960e0db6", "type": "github" }, "original": { @@ -430,11 +430,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1731239293, - "narHash": "sha256-q2yjIWFFcTzp5REWQUOU9L6kHdCDmFDpqeix86SOvDc=", + "lastModified": 1731797254, + "narHash": "sha256-df3dJApLPhd11AlueuoN0Q4fHo/hagP75LlM5K1sz9g=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9256f7c71a195ebe7a218043d9f93390d49e6884", + "rev": "e8c38b73aeb218e27163376a2d617e61a2ad9b59", "type": "github" }, "original": { @@ -445,11 +445,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1731139594, - "narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=", + "lastModified": 1732014248, + "narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2", + "rev": "23e89b7da85c3640bbc2173fe04f4bd114342367", "type": "github" }, "original": { @@ -460,11 +460,11 @@ }, "nur": { "locked": { - "lastModified": 1731401176, - "narHash": "sha256-khh5dM0oofqK3wmoL3xD09DokRg8E2XpkeEoOK6ShBg=", + "lastModified": 1732461014, + "narHash": "sha256-4KMZSCldwLImqrGxj8o5VpW5ej0L+EmxrlJzG2na8t4=", "owner": "nix-community", "repo": "NUR", - "rev": "1f5438e9803717a9bbce8b54356e305b87f1fde5", + "rev": "5951bcd835d728eb0db62425dba44a79d83c75d0", "type": "github" }, "original": { @@ -483,11 +483,11 @@ ] }, "locked": { - "lastModified": 1731193165, - "narHash": "sha256-pGF8L5g9QpkQtJP9JmNIRNZfcyhJHf7uT+d8tqI1h6Y=", + "lastModified": 1732450735, + "narHash": "sha256-QWNkWawDjoVWZx8bFUYxaCynK/r3+JyttzQ3TBoXaDg=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "f33173b9d22e554a6f869626bc01808d35995257", + "rev": "8e75ad96bfcc1a4da33b51c8a82adc146b2be011", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 5082170..8a7c4cb 100644 --- a/flake.nix +++ b/flake.nix @@ -99,8 +99,7 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/handheld-daemon-ui-init.patch - ./nixpkgs-patches/pr306227.patch + ./nixpkgs-patches/pr357897.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/handheld-daemon-ui-init.patch b/nixpkgs-patches/handheld-daemon-ui-init.patch deleted file mode 100644 index bb7bb0d..0000000 --- a/nixpkgs-patches/handheld-daemon-ui-init.patch +++ /dev/null @@ -1,326 +0,0 @@ -From 18cd88064d152491d5ba19602db5c5d65bc2d685 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Thu, 18 Apr 2024 11:22:24 +0200 -Subject: [PATCH 01/10] handheld-daemon-ui: init at 3.1.1 - ---- - .../by-name/ha/handheld-daemon-ui/package.nix | 39 +++++++++++++++++++ - 1 file changed, 39 insertions(+) - create mode 100644 pkgs/by-name/ha/handheld-daemon-ui/package.nix - -diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -new file mode 100644 -index 0000000000000..81d318d88b5ab ---- /dev/null -+++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -@@ -0,0 +1,39 @@ -+{ -+ lib, -+ appimageTools, -+ fetchurl, -+}: -+let -+ pname = "handheld-daemon-ui"; -+ version = "3.1.1"; -+ -+ src = fetchurl { -+ url = "https://github.com/hhd-dev/hhd-ui/releases/download/v${version}/hhd-ui.Appimage"; -+ hash = "sha256-KH01MvcCbvCqjp1UZHnwfh9G3Yh50CO9Ecjl1Y8VY9E="; -+ }; -+ extractedFiles = appimageTools.extractType2 { inherit pname version src; }; -+in -+appimageTools.wrapType2 { -+ inherit pname version src; -+ -+ extraInstallCommands = '' -+ # Handheld-daemon expects the UI binary to be called hhd-ui -+ mv $out/bin/${pname} $out/bin/hhd-ui -+ -+ mkdir -p $out/share/applications -+ substitute ${extractedFiles}/hhd-ui.desktop \ -+ $out/share/applications/hhd-ui.desktop \ -+ --replace-fail "Exec=AppRun" "Exec=hhd-ui" -+ cp ${extractedFiles}/usr/share/icons $out/share -r -+ ''; -+ -+ meta = with lib; { -+ description = "The main UI for the Handheld Daemon"; -+ homepage = "https://github.com/hhd-dev/hhd-ui"; -+ license = licenses.gpl3Only; -+ maintainers = with maintainers; [ toast ]; -+ mainProgram = "hhd-ui"; -+ platforms = [ "x86_64-linux" ]; -+ sourceProvenance = with sourceTypes; [ binaryNativeCode ]; -+ }; -+} - -From 49fc133081344cbe155eefd7189a6cff2e8b6c6b Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Wed, 10 Jul 2024 12:59:01 +0200 -Subject: [PATCH 02/10] nixos/handheld-daemon: add options for - handheld-daemon-ui - ---- - .../modules/services/hardware/handheld-daemon.nix | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - -diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix -index 6c9d5aa3e22c8..e8e283bca8941 100644 ---- a/nixos/modules/services/hardware/handheld-daemon.nix -+++ b/nixos/modules/services/hardware/handheld-daemon.nix -@@ -11,6 +11,11 @@ in - enable = mkEnableOption "Enable Handheld Daemon"; - package = mkPackageOption pkgs "handheld-daemon" { }; - -+ ui = { -+ enable = mkEnableOption "Handheld Daemon UI"; -+ package = mkPackageOption pkgs "handheld-daemon-ui" { }; -+ }; -+ - user = mkOption { - type = types.str; - description = '' -@@ -20,7 +25,10 @@ in - }; - - config = mkIf cfg.enable { -- environment.systemPackages = [ cfg.package ]; -+ environment.systemPackages = [ -+ cfg.package -+ (mkIf cfg.ui.enable cfg.ui.package) -+ ]; - services.udev.packages = [ cfg.package ]; - systemd.packages = [ cfg.package ]; - -@@ -31,6 +39,11 @@ in - - restartIfChanged = true; - -+ path = mkIf cfg.ui.enable [ -+ pkgs.handheld-daemon-ui -+ pkgs.lsof -+ ]; -+ - serviceConfig = { - ExecStart = "${ lib.getExe cfg.package } --user ${ cfg.user }"; - Nice = "-12"; - -From a8cbef4271d515e2733f3f9a32843135e3d255a5 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Thu, 11 Jul 2024 12:11:00 +0200 -Subject: [PATCH 03/10] nixos/handheld-daemon: enable ui when enabling - handheld-daemon - ---- - nixos/modules/services/hardware/handheld-daemon.nix | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix -index e8e283bca8941..d78bae5e9bc48 100644 ---- a/nixos/modules/services/hardware/handheld-daemon.nix -+++ b/nixos/modules/services/hardware/handheld-daemon.nix -@@ -25,6 +25,7 @@ in - }; - - config = mkIf cfg.enable { -+ services.handheld-daemon.ui.enable = mkDefault true; - environment.systemPackages = [ - cfg.package - (mkIf cfg.ui.enable cfg.ui.package) - -From 76e8f25d02d909e23dfb00bd02cb276dc4cf5c1c Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Tue, 8 Oct 2024 10:51:00 +0200 -Subject: [PATCH 04/10] handheld-daemon-ui: 3.1.1 -> 3.2.1 - ---- - pkgs/by-name/ha/handheld-daemon-ui/package.nix | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -index 81d318d88b5ab..028ceeb58f05e 100644 ---- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -@@ -5,11 +5,11 @@ - }: - let - pname = "handheld-daemon-ui"; -- version = "3.1.1"; -+ version = "3.2.1"; - - src = fetchurl { - url = "https://github.com/hhd-dev/hhd-ui/releases/download/v${version}/hhd-ui.Appimage"; -- hash = "sha256-KH01MvcCbvCqjp1UZHnwfh9G3Yh50CO9Ecjl1Y8VY9E="; -+ hash = "sha256-RRXVoeWOO/pR+CAEY0J6Buf/RhA+G0PdxGQVMdAHfwA="; - }; - extractedFiles = appimageTools.extractType2 { inherit pname version src; }; - in -@@ -18,7 +18,7 @@ appimageTools.wrapType2 { - - extraInstallCommands = '' - # Handheld-daemon expects the UI binary to be called hhd-ui -- mv $out/bin/${pname} $out/bin/hhd-ui -+ mv $out/bin/${pname}* $out/bin/hhd-ui - - mkdir -p $out/share/applications - substitute ${extractedFiles}/hhd-ui.desktop \ - -From 1843526bfdf5b5015ab9a070cfad122ec4cfb290 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Tue, 8 Oct 2024 11:14:00 +0200 -Subject: [PATCH 05/10] handheld-daemon-ui: fix desktop item category - ---- - pkgs/by-name/ha/handheld-daemon-ui/package.nix | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -index 028ceeb58f05e..1aa8266ece448 100644 ---- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -@@ -23,7 +23,8 @@ appimageTools.wrapType2 { - mkdir -p $out/share/applications - substitute ${extractedFiles}/hhd-ui.desktop \ - $out/share/applications/hhd-ui.desktop \ -- --replace-fail "Exec=AppRun" "Exec=hhd-ui" -+ --replace-fail "Exec=AppRun" "Exec=hhd-ui" \ -+ --replace-fail "Categories=game;" "Categories=Game;" - cp ${extractedFiles}/usr/share/icons $out/share -r - ''; - - -From 9ff4790805b08d7b0ff1d501606eb4ee2c28f675 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Tue, 8 Oct 2024 11:40:05 +0200 -Subject: [PATCH 06/10] handheld-daemon-ui: copy icon to correct folder - ---- - pkgs/by-name/ha/handheld-daemon-ui/package.nix | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -index 1aa8266ece448..a1131ea5c23d6 100644 ---- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -@@ -25,7 +25,9 @@ appimageTools.wrapType2 { - $out/share/applications/hhd-ui.desktop \ - --replace-fail "Exec=AppRun" "Exec=hhd-ui" \ - --replace-fail "Categories=game;" "Categories=Game;" -- cp ${extractedFiles}/usr/share/icons $out/share -r -+ iconDir=$out/share/icons/hicolor/512x512/apps -+ mkdir -p $iconDir -+ cp ${extractedFiles}/hhd-ui.png $iconDir - ''; - - meta = with lib; { - -From b70ac1d16444ae765c3273acb5a3bab27cdc06c6 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Tue, 8 Oct 2024 18:47:43 +0200 -Subject: [PATCH 07/10] nixos/handheld-daemon: replace mkIf with lib.optional - -Co-authored-by: Sandro ---- - nixos/modules/services/hardware/handheld-daemon.nix | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix -index d78bae5e9bc48..02684426b578d 100644 ---- a/nixos/modules/services/hardware/handheld-daemon.nix -+++ b/nixos/modules/services/hardware/handheld-daemon.nix -@@ -28,8 +28,7 @@ in - services.handheld-daemon.ui.enable = mkDefault true; - environment.systemPackages = [ - cfg.package -- (mkIf cfg.ui.enable cfg.ui.package) -- ]; -+ ] ++ lib.optional cfg.ui.enable cfg.ui.package; - services.udev.packages = [ cfg.package ]; - systemd.packages = [ cfg.package ]; - - -From ac8bb4e8ba115162e7140a47b55c0264ec8d830b Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Thu, 10 Oct 2024 11:08:48 +0200 -Subject: [PATCH 08/10] nixos/handheld-daemon: add correct ui package to - service path - ---- - nixos/modules/services/hardware/handheld-daemon.nix | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/nixos/modules/services/hardware/handheld-daemon.nix b/nixos/modules/services/hardware/handheld-daemon.nix -index 02684426b578d..cb20682ec592e 100644 ---- a/nixos/modules/services/hardware/handheld-daemon.nix -+++ b/nixos/modules/services/hardware/handheld-daemon.nix -@@ -40,7 +40,7 @@ in - restartIfChanged = true; - - path = mkIf cfg.ui.enable [ -- pkgs.handheld-daemon-ui -+ cfg.ui.package - pkgs.lsof - ]; - - -From 4f5a6840aed497f33ad61cd3a629288cde8c6dd2 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Wed, 6 Nov 2024 22:36:59 +0100 -Subject: [PATCH 09/10] handheld-daemon-ui: get rid off 'with lib' - -Co-authored-by: Arne Keller <2012gdwu+github@posteo.de> ---- - pkgs/by-name/ha/handheld-daemon-ui/package.nix | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -index a1131ea5c23d6..92946c9fe0cd2 100644 ---- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -@@ -30,13 +30,13 @@ appimageTools.wrapType2 { - cp ${extractedFiles}/hhd-ui.png $iconDir - ''; - -- meta = with lib; { -- description = "The main UI for the Handheld Daemon"; -+ meta = { -+ description = "UI for the Handheld Daemon"; - homepage = "https://github.com/hhd-dev/hhd-ui"; -- license = licenses.gpl3Only; -- maintainers = with maintainers; [ toast ]; -+ license = lib.licenses.gpl3Only; -+ maintainers = with lib.maintainers; [ toast ]; - mainProgram = "hhd-ui"; - platforms = [ "x86_64-linux" ]; -- sourceProvenance = with sourceTypes; [ binaryNativeCode ]; -+ sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ]; - }; - } - -From fb63f605c5a14c23d596d070fffc9e89da59526e Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Fri, 15 Nov 2024 10:49:15 +0100 -Subject: [PATCH 10/10] handheld-daemon-ui: 3.2.1 -> 3.2.3 - ---- - pkgs/by-name/ha/handheld-daemon-ui/package.nix | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon-ui/package.nix b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -index 92946c9fe0cd2..00c830bd3fc67 100644 ---- a/pkgs/by-name/ha/handheld-daemon-ui/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon-ui/package.nix -@@ -5,11 +5,11 @@ - }: - let - pname = "handheld-daemon-ui"; -- version = "3.2.1"; -+ version = "3.2.3"; - - src = fetchurl { - url = "https://github.com/hhd-dev/hhd-ui/releases/download/v${version}/hhd-ui.Appimage"; -- hash = "sha256-RRXVoeWOO/pR+CAEY0J6Buf/RhA+G0PdxGQVMdAHfwA="; -+ hash = "sha256-VhJrOvE+BebJIAeQlwOOsPfqSrvBnJQavGT7glTrG2o="; - }; - extractedFiles = appimageTools.extractType2 { inherit pname version src; }; - in diff --git a/nixpkgs-patches/pr306227.patch b/nixpkgs-patches/pr306227.patch deleted file mode 100644 index 7f31202..0000000 --- a/nixpkgs-patches/pr306227.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 8abd7b32202df6c492446edb05ef925af1515e18 Mon Sep 17 00:00:00 2001 -From: Dmitry Chermnykh <76gh6rvso@relay.firefox.com> -Date: Tue, 23 Apr 2024 14:00:40 +0500 -Subject: [PATCH] nixos/plasma6: add qtimageformats to the requiredPackages - -This is needed for qt6 apps to be able to work with certain image formats such as .webp and .avif - -Closes https://github.com/NixOS/nixpkgs/issues/304523 ---- - nixos/modules/services/desktop-managers/plasma6.nix | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/nixos/modules/services/desktop-managers/plasma6.nix b/nixos/modules/services/desktop-managers/plasma6.nix -index 856d36b8a3030..d102ef167e314 100644 ---- a/nixos/modules/services/desktop-managers/plasma6.nix -+++ b/nixos/modules/services/desktop-managers/plasma6.nix -@@ -74,6 +74,7 @@ in { - kguiaddons # provides geo URL handlers - kiconthemes # provides Qt plugins - kimageformats # provides Qt plugins -+ qtimageformats # provides optional image formats such as .webp and .avif - kio # provides helper service + a bunch of other stuff - kpackage # provides kpackagetool tool - kservice # provides kbuildsycoca6 tool diff --git a/nixpkgs-patches/pr357897.patch b/nixpkgs-patches/pr357897.patch new file mode 100644 index 0000000..117fdf0 --- /dev/null +++ b/nixpkgs-patches/pr357897.patch @@ -0,0 +1,145 @@ +From 91c18e48e58517b176e8b87959293de71789c715 Mon Sep 17 00:00:00 2001 +From: GetPsyched +Date: Thu, 21 Nov 2024 17:03:57 +0400 +Subject: [PATCH] nixos-render-docs: don't validate redirects if none were + given + +--- + .../src/nixos_render_docs/manual.py | 40 ++++++++++--------- + .../src/tests/test_auto_id_prefix.py | 6 +-- + 2 files changed, 25 insertions(+), 21 deletions(-) + +diff --git a/pkgs/by-name/ni/nixos-render-docs/src/nixos_render_docs/manual.py b/pkgs/by-name/ni/nixos-render-docs/src/nixos_render_docs/manual.py +index 64b3740c83522..52b51f63f4d85 100644 +--- a/pkgs/by-name/ni/nixos-render-docs/src/nixos_render_docs/manual.py ++++ b/pkgs/by-name/ni/nixos-render-docs/src/nixos_render_docs/manual.py +@@ -217,11 +217,11 @@ class ManualHTMLRenderer(RendererMixin, HTMLRenderer): + _base_path: Path + _in_dir: Path + _html_params: HTMLParameters +- _redirects: Redirects ++ _redirects: Redirects | None + + def __init__(self, toplevel_tag: str, revision: str, html_params: HTMLParameters, + manpage_urls: Mapping[str, str], xref_targets: dict[str, XrefTarget], +- redirects: Redirects, in_dir: Path, base_path: Path): ++ redirects: Redirects | None, in_dir: Path, base_path: Path): + super().__init__(toplevel_tag, revision, manpage_urls, xref_targets) + self._in_dir = in_dir + self._base_path = base_path.absolute() +@@ -310,9 +310,12 @@ def _file_header(self, toc: TocEntry) -> str: + ' ', + ]) + +- redirects_path = f'{self._base_path}/{toc.target.path.split('.html')[0]}-redirects.js' +- with open(redirects_path, 'w') as file: +- file.write(self._redirects.get_redirect_script(toc.target.path)) ++ scripts = self._html_params.scripts ++ if self._redirects: ++ redirects_path = f'{self._base_path}/{toc.target.path.split('.html')[0]}-redirects.js' ++ with open(redirects_path, 'w') as file: ++ file.write(self._redirects.get_redirect_script(toc.target.path)) ++ scripts.append(redirects_path) + + return "\n".join([ + '', +@@ -325,7 +328,7 @@ def _file_header(self, toc: TocEntry) -> str: + "".join((f'' + for style in self._html_params.stylesheets)), + "".join((f'' +- for script in [*self._html_params.scripts, redirects_path])), ++ for script in scripts)), + f' ', + f' ' if home.target.href() else "", + f' {up_link}{prev_link}{next_link}', +@@ -509,7 +512,7 @@ class HTMLConverter(BaseConverter[ManualHTMLRenderer]): + _revision: str + _html_params: HTMLParameters + _manpage_urls: Mapping[str, str] +- _redirects: Redirects ++ _redirects: Redirects | None + _xref_targets: dict[str, XrefTarget] + _redirection_targets: set[str] + _appendix_count: int = 0 +@@ -518,7 +521,7 @@ def _next_appendix_id(self) -> str: + self._appendix_count += 1 + return _to_base26(self._appendix_count - 1) + +- def __init__(self, revision: str, html_params: HTMLParameters, manpage_urls: Mapping[str, str], redirects: Redirects): ++ def __init__(self, revision: str, html_params: HTMLParameters, manpage_urls: Mapping[str, str], redirects: Redirects | None = None): + super().__init__() + self._revision, self._html_params, self._manpage_urls, self._redirects = revision, html_params, manpage_urls, redirects + self._xref_targets = {} +@@ -679,13 +682,14 @@ def _postprocess(self, infile: Path, outfile: Path, tokens: Sequence[Token]) -> + ) + + TocEntry.collect_and_link(self._xref_targets, tokens) +- self._redirects.validate(self._xref_targets) +- server_redirects = self._redirects.get_server_redirects() +- with open(outfile.parent / '_redirects', 'w') as server_redirects_file: +- formatted_server_redirects = [] +- for from_path, to_path in server_redirects.items(): +- formatted_server_redirects.append(f"{from_path} {to_path} 301") +- server_redirects_file.write("\n".join(formatted_server_redirects)) ++ if self._redirects: ++ self._redirects.validate(self._xref_targets) ++ server_redirects = self._redirects.get_server_redirects() ++ with open(outfile.parent / '_redirects', 'w') as server_redirects_file: ++ formatted_server_redirects = [] ++ for from_path, to_path in server_redirects.items(): ++ formatted_server_redirects.append(f"{from_path} {to_path} 301") ++ server_redirects_file.write("\n".join(formatted_server_redirects)) + + + def _build_cli_html(p: argparse.ArgumentParser) -> None: +@@ -704,16 +708,16 @@ def _build_cli_html(p: argparse.ArgumentParser) -> None: + + def _run_cli_html(args: argparse.Namespace) -> None: + with open(args.manpage_urls) as manpage_urls, open(Path(__file__).parent / "redirects.js") as redirects_script: +- redirects = {} ++ redirects = None + if args.redirects: + with open(args.redirects) as raw_redirects: +- redirects = json.load(raw_redirects) ++ redirects = Redirects(json.load(raw_redirects), redirects_script.read()) + + md = HTMLConverter( + args.revision, + HTMLParameters(args.generator, args.stylesheet, args.script, args.toc_depth, + args.chunk_toc_depth, args.section_toc_depth, args.media_dir), +- json.load(manpage_urls), Redirects(redirects, redirects_script.read())) ++ json.load(manpage_urls), redirects) + md.convert(args.infile, args.outfile) + + def build_cli(p: argparse.ArgumentParser) -> None: +diff --git a/pkgs/by-name/ni/nixos-render-docs/src/tests/test_auto_id_prefix.py b/pkgs/by-name/ni/nixos-render-docs/src/tests/test_auto_id_prefix.py +index a3d33930b3035..ae847de6b8a8d 100644 +--- a/pkgs/by-name/ni/nixos-render-docs/src/tests/test_auto_id_prefix.py ++++ b/pkgs/by-name/ni/nixos-render-docs/src/tests/test_auto_id_prefix.py +@@ -11,7 +11,7 @@ def set_prefix(token: Token, ident: str) -> None: + + + def test_auto_id_prefix_simple() -> None: +- md = HTMLConverter("1.0.0", HTMLParameters("", [], [], 2, 2, 2, Path("")), {}, Redirects({}, '')) ++ md = HTMLConverter("1.0.0", HTMLParameters("", [], [], 2, 2, 2, Path("")), {}) + + src = f""" + # title +@@ -32,7 +32,7 @@ def test_auto_id_prefix_simple() -> None: + + + def test_auto_id_prefix_repeated() -> None: +- md = HTMLConverter("1.0.0", HTMLParameters("", [], [], 2, 2, 2, Path("")), {}, Redirects({}, '')) ++ md = HTMLConverter("1.0.0", HTMLParameters("", [], [], 2, 2, 2, Path("")), {}) + + src = f""" + # title +@@ -58,7 +58,7 @@ def test_auto_id_prefix_repeated() -> None: + ] + + def test_auto_id_prefix_maximum_nested() -> None: +- md = HTMLConverter("1.0.0", HTMLParameters("", [], [], 2, 2, 2, Path("")), {}, Redirects({}, '')) ++ md = HTMLConverter("1.0.0", HTMLParameters("", [], [], 2, 2, 2, Path("")), {}) + + src = f""" + # h1 From 74d858d5c51cd38ef25d49c8250e671c0056545d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 26 Nov 2024 09:57:22 +0100 Subject: [PATCH 0826/1125] Kde: configure baloo --- roles/kde/programs/baloo.nix | 16 ++++++++++++++++ roles/kde/programs/default.nix | 1 + 2 files changed, 17 insertions(+) create mode 100644 roles/kde/programs/baloo.nix diff --git a/roles/kde/programs/baloo.nix b/roles/kde/programs/baloo.nix new file mode 100644 index 0000000..572376a --- /dev/null +++ b/roles/kde/programs/baloo.nix @@ -0,0 +1,16 @@ +{lib, ...}: { + home-manager.users.toast = { + programs.plasma.configFile = { + "baloofilerc"."General" = { + "exclude folders".shellExpand = true; + "exclude folders".value = with lib.strings; + concatStrings ( + intersperse "," [ + "$HOME/Documents/Repos" + "$HOME/Documents/Android" + ] + ); + }; + }; + }; +} diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index fe160e8..84ff7f6 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -8,6 +8,7 @@ ./konsole.nix ./git.nix ./kwin.nix + ./baloo.nix ]; # Enable the kde partition manager From bcb20eb1caac28aaf550d435a8b9020d2b1d5c90 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 26 Nov 2024 12:12:56 +0100 Subject: [PATCH 0827/1125] School/programs: install mongodb compass --- roles/school/programs/default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 13edfdf..4d4442f 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -1,5 +1,6 @@ -{...}: { +{pkgs, ...}: { imports = [ ./android-studio.nix ]; + home-manager.users.toast.home.packages = [pkgs.mongodb-compass]; } From 4a4284bce2652e42d323f074de9f054a2e6afc2e Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 27 Nov 2024 10:15:11 +0100 Subject: [PATCH 0828/1125] Flake: add pr 359282 --- flake.nix | 1 + nixpkgs-patches/pr359282.patch | 92 ++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 nixpkgs-patches/pr359282.patch diff --git a/flake.nix b/flake.nix index 8a7c4cb..8482899 100644 --- a/flake.nix +++ b/flake.nix @@ -100,6 +100,7 @@ src = nixpkgs-unstable-raw; patches = [ ./nixpkgs-patches/pr357897.patch + ./nixpkgs-patches/pr359282.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr359282.patch b/nixpkgs-patches/pr359282.patch new file mode 100644 index 0000000..df16636 --- /dev/null +++ b/nixpkgs-patches/pr359282.patch @@ -0,0 +1,92 @@ +From 40b3e9f1d39626c1bf38a315e78a1aafd3f378d4 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Tue, 26 Nov 2024 13:36:45 +0100 +Subject: [PATCH 1/2] handheld-daemon: 3.4.1 -> 3.5.7 + +Also install hhd's hwdb file, since it is needed for buttons to work +properly on the MSI Claw, among other things +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 286566a2710a4..e21fe848b0942 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -8,14 +8,14 @@ + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "3.4.1"; ++ version = "3.5.7"; + pyproject = true; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + rev = "refs/tags/v${version}"; +- hash = "sha256-hup9G4pTlTl68zLzhaDmH7nV8fp/I94Nuis68B8K2wY="; ++ hash = "sha256-nUHEPyTHU7LD6BZg+2cLl4M/ZPb5MQl6xxtJW1iZkEY="; + }; + + propagatedBuildInputs = with python3.pkgs; [ +@@ -27,6 +27,7 @@ python3.pkgs.buildPythonApplication rec { + setuptools + toybox + xlib ++ pyserial + ]; + + # This package doesn't have upstream tests. +@@ -46,6 +47,7 @@ python3.pkgs.buildPythonApplication rec { + + postInstall = '' + install -Dm644 $src/usr/lib/udev/rules.d/83-hhd.rules -t $out/lib/udev/rules.d/ ++ install -Dm644 $src/usr/lib/udev/hwdb.d/83-hhd.hwdb -t $out/lib/udev/hwdb.d/ + ''; + + meta = with lib; { + +From efc1301777818548a2f23f31248486e680502456 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Tue, 26 Nov 2024 17:50:06 +0100 +Subject: [PATCH 2/2] handheld-daemon: 3.5.7 -> 3.6.1 + +Version 3.6.0 added lsof as a dependency +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index e21fe848b0942..b99cd1c581476 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -5,17 +5,18 @@ + lib, + python3, + toybox, ++ lsof + }: + python3.pkgs.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "3.5.7"; ++ version = "3.6.1"; + pyproject = true; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + rev = "refs/tags/v${version}"; +- hash = "sha256-nUHEPyTHU7LD6BZg+2cLl4M/ZPb5MQl6xxtJW1iZkEY="; ++ hash = "sha256-IdpSRb66G+WzTv/BC29r2OjO1b4VdWbV6OSzOoiFAO0="; + }; + + propagatedBuildInputs = with python3.pkgs; [ +@@ -28,6 +29,7 @@ python3.pkgs.buildPythonApplication rec { + toybox + xlib + pyserial ++ lsof + ]; + + # This package doesn't have upstream tests. From bdc9c97289910f0e641b3e7ac8b86355e852c49f Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 28 Nov 2024 10:45:52 +0100 Subject: [PATCH 0829/1125] Flake: remove unneeded patch --- flake.nix | 1 - nixpkgs-patches/pr357897.patch | 145 --------------------------------- 2 files changed, 146 deletions(-) delete mode 100644 nixpkgs-patches/pr357897.patch diff --git a/flake.nix b/flake.nix index 8482899..41b14d0 100644 --- a/flake.nix +++ b/flake.nix @@ -99,7 +99,6 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/pr357897.patch ./nixpkgs-patches/pr359282.patch ]; }; diff --git a/nixpkgs-patches/pr357897.patch b/nixpkgs-patches/pr357897.patch deleted file mode 100644 index 117fdf0..0000000 --- a/nixpkgs-patches/pr357897.patch +++ /dev/null @@ -1,145 +0,0 @@ -From 91c18e48e58517b176e8b87959293de71789c715 Mon Sep 17 00:00:00 2001 -From: GetPsyched -Date: Thu, 21 Nov 2024 17:03:57 +0400 -Subject: [PATCH] nixos-render-docs: don't validate redirects if none were - given - ---- - .../src/nixos_render_docs/manual.py | 40 ++++++++++--------- - .../src/tests/test_auto_id_prefix.py | 6 +-- - 2 files changed, 25 insertions(+), 21 deletions(-) - -diff --git a/pkgs/by-name/ni/nixos-render-docs/src/nixos_render_docs/manual.py b/pkgs/by-name/ni/nixos-render-docs/src/nixos_render_docs/manual.py -index 64b3740c83522..52b51f63f4d85 100644 ---- a/pkgs/by-name/ni/nixos-render-docs/src/nixos_render_docs/manual.py -+++ b/pkgs/by-name/ni/nixos-render-docs/src/nixos_render_docs/manual.py -@@ -217,11 +217,11 @@ class ManualHTMLRenderer(RendererMixin, HTMLRenderer): - _base_path: Path - _in_dir: Path - _html_params: HTMLParameters -- _redirects: Redirects -+ _redirects: Redirects | None - - def __init__(self, toplevel_tag: str, revision: str, html_params: HTMLParameters, - manpage_urls: Mapping[str, str], xref_targets: dict[str, XrefTarget], -- redirects: Redirects, in_dir: Path, base_path: Path): -+ redirects: Redirects | None, in_dir: Path, base_path: Path): - super().__init__(toplevel_tag, revision, manpage_urls, xref_targets) - self._in_dir = in_dir - self._base_path = base_path.absolute() -@@ -310,9 +310,12 @@ def _file_header(self, toc: TocEntry) -> str: - ' ', - ]) - -- redirects_path = f'{self._base_path}/{toc.target.path.split('.html')[0]}-redirects.js' -- with open(redirects_path, 'w') as file: -- file.write(self._redirects.get_redirect_script(toc.target.path)) -+ scripts = self._html_params.scripts -+ if self._redirects: -+ redirects_path = f'{self._base_path}/{toc.target.path.split('.html')[0]}-redirects.js' -+ with open(redirects_path, 'w') as file: -+ file.write(self._redirects.get_redirect_script(toc.target.path)) -+ scripts.append(redirects_path) - - return "\n".join([ - '', -@@ -325,7 +328,7 @@ def _file_header(self, toc: TocEntry) -> str: - "".join((f'' - for style in self._html_params.stylesheets)), - "".join((f'' -- for script in [*self._html_params.scripts, redirects_path])), -+ for script in scripts)), - f' ', - f' ' if home.target.href() else "", - f' {up_link}{prev_link}{next_link}', -@@ -509,7 +512,7 @@ class HTMLConverter(BaseConverter[ManualHTMLRenderer]): - _revision: str - _html_params: HTMLParameters - _manpage_urls: Mapping[str, str] -- _redirects: Redirects -+ _redirects: Redirects | None - _xref_targets: dict[str, XrefTarget] - _redirection_targets: set[str] - _appendix_count: int = 0 -@@ -518,7 +521,7 @@ def _next_appendix_id(self) -> str: - self._appendix_count += 1 - return _to_base26(self._appendix_count - 1) - -- def __init__(self, revision: str, html_params: HTMLParameters, manpage_urls: Mapping[str, str], redirects: Redirects): -+ def __init__(self, revision: str, html_params: HTMLParameters, manpage_urls: Mapping[str, str], redirects: Redirects | None = None): - super().__init__() - self._revision, self._html_params, self._manpage_urls, self._redirects = revision, html_params, manpage_urls, redirects - self._xref_targets = {} -@@ -679,13 +682,14 @@ def _postprocess(self, infile: Path, outfile: Path, tokens: Sequence[Token]) -> - ) - - TocEntry.collect_and_link(self._xref_targets, tokens) -- self._redirects.validate(self._xref_targets) -- server_redirects = self._redirects.get_server_redirects() -- with open(outfile.parent / '_redirects', 'w') as server_redirects_file: -- formatted_server_redirects = [] -- for from_path, to_path in server_redirects.items(): -- formatted_server_redirects.append(f"{from_path} {to_path} 301") -- server_redirects_file.write("\n".join(formatted_server_redirects)) -+ if self._redirects: -+ self._redirects.validate(self._xref_targets) -+ server_redirects = self._redirects.get_server_redirects() -+ with open(outfile.parent / '_redirects', 'w') as server_redirects_file: -+ formatted_server_redirects = [] -+ for from_path, to_path in server_redirects.items(): -+ formatted_server_redirects.append(f"{from_path} {to_path} 301") -+ server_redirects_file.write("\n".join(formatted_server_redirects)) - - - def _build_cli_html(p: argparse.ArgumentParser) -> None: -@@ -704,16 +708,16 @@ def _build_cli_html(p: argparse.ArgumentParser) -> None: - - def _run_cli_html(args: argparse.Namespace) -> None: - with open(args.manpage_urls) as manpage_urls, open(Path(__file__).parent / "redirects.js") as redirects_script: -- redirects = {} -+ redirects = None - if args.redirects: - with open(args.redirects) as raw_redirects: -- redirects = json.load(raw_redirects) -+ redirects = Redirects(json.load(raw_redirects), redirects_script.read()) - - md = HTMLConverter( - args.revision, - HTMLParameters(args.generator, args.stylesheet, args.script, args.toc_depth, - args.chunk_toc_depth, args.section_toc_depth, args.media_dir), -- json.load(manpage_urls), Redirects(redirects, redirects_script.read())) -+ json.load(manpage_urls), redirects) - md.convert(args.infile, args.outfile) - - def build_cli(p: argparse.ArgumentParser) -> None: -diff --git a/pkgs/by-name/ni/nixos-render-docs/src/tests/test_auto_id_prefix.py b/pkgs/by-name/ni/nixos-render-docs/src/tests/test_auto_id_prefix.py -index a3d33930b3035..ae847de6b8a8d 100644 ---- a/pkgs/by-name/ni/nixos-render-docs/src/tests/test_auto_id_prefix.py -+++ b/pkgs/by-name/ni/nixos-render-docs/src/tests/test_auto_id_prefix.py -@@ -11,7 +11,7 @@ def set_prefix(token: Token, ident: str) -> None: - - - def test_auto_id_prefix_simple() -> None: -- md = HTMLConverter("1.0.0", HTMLParameters("", [], [], 2, 2, 2, Path("")), {}, Redirects({}, '')) -+ md = HTMLConverter("1.0.0", HTMLParameters("", [], [], 2, 2, 2, Path("")), {}) - - src = f""" - # title -@@ -32,7 +32,7 @@ def test_auto_id_prefix_simple() -> None: - - - def test_auto_id_prefix_repeated() -> None: -- md = HTMLConverter("1.0.0", HTMLParameters("", [], [], 2, 2, 2, Path("")), {}, Redirects({}, '')) -+ md = HTMLConverter("1.0.0", HTMLParameters("", [], [], 2, 2, 2, Path("")), {}) - - src = f""" - # title -@@ -58,7 +58,7 @@ def test_auto_id_prefix_repeated() -> None: - ] - - def test_auto_id_prefix_maximum_nested() -> None: -- md = HTMLConverter("1.0.0", HTMLParameters("", [], [], 2, 2, 2, Path("")), {}, Redirects({}, '')) -+ md = HTMLConverter("1.0.0", HTMLParameters("", [], [], 2, 2, 2, Path("")), {}) - - src = f""" - # h1 From 565e5f822487a5fd91a72b70ca679cbf8dbb8ccb Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 28 Nov 2024 10:52:44 +0100 Subject: [PATCH 0830/1125] Flake: update lock file --- flake.lock | 82 +++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/flake.lock b/flake.lock index bb041e1..4e86656 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1731232837, - "narHash": "sha256-0aIwr/RC/oe7rYkfJb47xjdEQDSNcqpFGsEa+EPlDEs=", + "lastModified": 1732703064, + "narHash": "sha256-n8XOmn0WGtQhAMJKTnhL/3ttV2ZahPRf6gtlqZ6R4QE=", "owner": "catppuccin", "repo": "nix", - "rev": "32359bf226fe874d3b7a0a5753d291a4da9616fe", + "rev": "2e2bdecf0bae287d74947cd5cf967c5c499c23c1", "type": "github" }, "original": { @@ -182,11 +182,11 @@ ] }, "locked": { - "lastModified": 1732453510, - "narHash": "sha256-mAOaLu++YRwOxCJ135Bhgf78WYhIKWHL2aGWCAoXoBg=", + "lastModified": 1732482255, + "narHash": "sha256-GUffLwzawz5WRVfWaWCg78n/HrBJrOG7QadFY6rtV8A=", "owner": "nix-community", "repo": "home-manager", - "rev": "bd58a1132e9b7f121f65313bc662ad6c8a05f878", + "rev": "a9953635d7f34e7358d5189751110f87e3ac17da", "type": "github" }, "original": { @@ -224,11 +224,11 @@ ] }, "locked": { - "lastModified": 1732432618, - "narHash": "sha256-7MzATSBJcR9JUkaDgIJ3jEkQLXIbOjt0lqbmlGkcLDg=", + "lastModified": 1732739177, + "narHash": "sha256-iL32+TA/8geCzcL1r3uthrH/GPvbUak5QE++WJUkaiI=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "98a61cf0708885abddebc6938ca7282928981d5e", + "rev": "8d7b2149e618696d5100c2683af1ffa893f02a75", "type": "github" }, "original": { @@ -263,11 +263,11 @@ ] }, "locked": { - "lastModified": 1731967274, - "narHash": "sha256-n6dPGRlMGdL8X5gviA6ZuRfUdbdD5KiNN/BpABA5YT0=", - "rev": "aa2846680fa9a2032939d720487942567fd9eb63", + "lastModified": 1732603698, + "narHash": "sha256-Jw2MhzgCCrKV2MJytehG0cCLIAosBX71p8qmQ6XQlR4=", + "rev": "15b999f9c958c475f71fb8c543b9fc2f36ae8730", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/aa2846680fa9a2032939d720487942567fd9eb63.tar.gz?rev=aa2846680fa9a2032939d720487942567fd9eb63" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/15b999f9c958c475f71fb8c543b9fc2f36ae8730.tar.gz?rev=15b999f9c958c475f71fb8c543b9fc2f36ae8730" }, "original": { "type": "tarball", @@ -286,11 +286,11 @@ ] }, "locked": { - "lastModified": 1731967274, - "narHash": "sha256-n6dPGRlMGdL8X5gviA6ZuRfUdbdD5KiNN/BpABA5YT0=", - "rev": "aa2846680fa9a2032939d720487942567fd9eb63", + "lastModified": 1732603698, + "narHash": "sha256-Jw2MhzgCCrKV2MJytehG0cCLIAosBX71p8qmQ6XQlR4=", + "rev": "15b999f9c958c475f71fb8c543b9fc2f36ae8730", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/aa2846680fa9a2032939d720487942567fd9eb63.tar.gz?rev=aa2846680fa9a2032939d720487942567fd9eb63" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/15b999f9c958c475f71fb8c543b9fc2f36ae8730.tar.gz?rev=15b999f9c958c475f71fb8c543b9fc2f36ae8730" }, "original": { "type": "tarball", @@ -357,11 +357,11 @@ ] }, "locked": { - "lastModified": 1732458224, - "narHash": "sha256-6CHj+ce0yGOEuKbM0gERuNkLAOrkmcmw5kLYHaW8eMw=", + "lastModified": 1732519917, + "narHash": "sha256-AGXhwHdJV0q/WNgqwrR2zriubLr785b02FphaBtyt1Q=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "e5105f148c36e423377c6be187186b5bf706c268", + "rev": "f4a5ca5771ba9ca31ad24a62c8d511a405303436", "type": "github" }, "original": { @@ -377,11 +377,11 @@ ] }, "locked": { - "lastModified": 1732458224, - "narHash": "sha256-6CHj+ce0yGOEuKbM0gERuNkLAOrkmcmw5kLYHaW8eMw=", + "lastModified": 1732519917, + "narHash": "sha256-AGXhwHdJV0q/WNgqwrR2zriubLr785b02FphaBtyt1Q=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "e5105f148c36e423377c6be187186b5bf706c268", + "rev": "f4a5ca5771ba9ca31ad24a62c8d511a405303436", "type": "github" }, "original": { @@ -399,11 +399,11 @@ ] }, "locked": { - "lastModified": 1732413484, - "narHash": "sha256-KZYNKQVAf53MvT4zs8ybtswyJUw5f1HzshZWgCDJQm4=", + "lastModified": 1732758830, + "narHash": "sha256-bmMRjp4U3RDvLuwOWXMTHitMBMrmmpzP4x0dckJMZD4=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "a950aa08f1868355d8b5fe89613f17468d2ae697", + "rev": "09c3d43938e7b535ecada974759e9ed84ee91235", "type": "github" }, "original": { @@ -414,11 +414,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1731797098, - "narHash": "sha256-UhWmEZhwJZmVZ1jfHZFzCg+ZLO9Tb/v3Y6LC0UNyeTo=", + "lastModified": 1732483221, + "narHash": "sha256-kF6rDeCshoCgmQz+7uiuPdREVFuzhIorGOoPXMalL2U=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "672ac2ac86f7dff2f6f3406405bddecf960e0db6", + "rev": "45348ad6fb8ac0e8415f6e5e96efe47dd7f39405", "type": "github" }, "original": { @@ -430,11 +430,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1731797254, - "narHash": "sha256-df3dJApLPhd11AlueuoN0Q4fHo/hagP75LlM5K1sz9g=", + "lastModified": 1732632634, + "narHash": "sha256-+G7n/ZD635aN0sEXQLynU7pWMd3PKDM7yBIXvYmjABQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e8c38b73aeb218e27163376a2d617e61a2ad9b59", + "rev": "6f6076c37180ea3a916f84928cf3a714c5207a30", "type": "github" }, "original": { @@ -445,11 +445,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1732014248, - "narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=", + "lastModified": 1732521221, + "narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "23e89b7da85c3640bbc2173fe04f4bd114342367", + "rev": "4633a7c72337ea8fd23a4f2ba3972865e3ec685d", "type": "github" }, "original": { @@ -460,11 +460,11 @@ }, "nur": { "locked": { - "lastModified": 1732461014, - "narHash": "sha256-4KMZSCldwLImqrGxj8o5VpW5ej0L+EmxrlJzG2na8t4=", + "lastModified": 1732784817, + "narHash": "sha256-I37vvlS+qk4TMzMouw9kJCilahl8+fOjnCWsBJmPv+U=", "owner": "nix-community", "repo": "NUR", - "rev": "5951bcd835d728eb0db62425dba44a79d83c75d0", + "rev": "7c412613e5ed3d49f2e198c0b0187add6b897b3d", "type": "github" }, "original": { @@ -483,11 +483,11 @@ ] }, "locked": { - "lastModified": 1732450735, - "narHash": "sha256-QWNkWawDjoVWZx8bFUYxaCynK/r3+JyttzQ3TBoXaDg=", + "lastModified": 1732639391, + "narHash": "sha256-kFtXjoCIqx9xe0ZryPXpqS6l/HVg71aNcuL8Y5e8+pI=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "8e75ad96bfcc1a4da33b51c8a82adc146b2be011", + "rev": "06e3209d11797d9c741e25df06ab61048746bf93", "type": "github" }, "original": { From dc4f02531862a46d9735604b0e11bd00852f1d14 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 25 Nov 2024 10:51:39 +0100 Subject: [PATCH 0831/1125] Server/caddy: double restartSec duration --- roles/server/caddy.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index b303d1a..f7697fc 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -64,7 +64,7 @@ in { # ages to boot up. If I don't add a delay, caddy tries to bind to # the tailscale interface before it's ready, making it crash too much # in too little time - services.caddy.serviceConfig.RestartSec = lib.mkForce "120s"; + services.caddy.serviceConfig.RestartSec = lib.mkForce "240s"; }; programs.rust-motd.settings.service_status.Caddy = "caddy"; networking.firewall.allowedTCPPorts = [443 80]; From 5c8044283a16fb49e033923c24b31124768f1cc6 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 2 Dec 2024 12:11:26 +0100 Subject: [PATCH 0832/1125] Flake: upgrade stable nixpkgs and home-manager --- flake.lock | 16 ++++++++-------- flake.nix | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index 4e86656..fb48812 100644 --- a/flake.lock +++ b/flake.lock @@ -202,16 +202,16 @@ ] }, "locked": { - "lastModified": 1726989464, - "narHash": "sha256-Vl+WVTJwutXkimwGprnEtXc/s/s8sMuXzqXaspIGlwM=", + "lastModified": 1733050161, + "narHash": "sha256-lYnT+EYE47f5yY3KS/Kd4pJ6CO9fhCqumkYYkQ3TK20=", "owner": "nix-community", "repo": "home-manager", - "rev": "2f23fa308a7c067e52dfcc30a0758f47043ec176", + "rev": "62d536255879be574ebfe9b87c4ac194febf47c5", "type": "github" }, "original": { "owner": "nix-community", - "ref": "release-24.05", + "ref": "release-24.11", "repo": "home-manager", "type": "github" } @@ -430,16 +430,16 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1732632634, - "narHash": "sha256-+G7n/ZD635aN0sEXQLynU7pWMd3PKDM7yBIXvYmjABQ=", + "lastModified": 1732981179, + "narHash": "sha256-F7thesZPvAMSwjRu0K8uFshTk3ZZSNAsXTIFvXBT+34=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6f6076c37180ea3a916f84928cf3a714c5207a30", + "rev": "62c435d93bf046a5396f3016472e8f7c8e2aed65", "type": "github" }, "original": { "id": "nixpkgs", - "ref": "nixos-24.05", + "ref": "nixos-24.11", "type": "indirect" } }, diff --git a/flake.nix b/flake.nix index 41b14d0..bc8ddca 100644 --- a/flake.nix +++ b/flake.nix @@ -6,7 +6,7 @@ url = "git+ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets"; flake = false; }; - nixpkgs-raw.url = "nixpkgs/nixos-24.05"; + nixpkgs-raw.url = "nixpkgs/nixos-24.11"; nixpkgs-unstable-raw.url = "nixpkgs/nixos-unstable"; agenix = { @@ -18,7 +18,7 @@ }; home-manager = { - url = "github:nix-community/home-manager/release-24.05"; + url = "github:nix-community/home-manager/release-24.11"; inputs.nixpkgs.follows = "nixpkgs-raw"; }; From fc51305ad666fbf8e4639e6d7c5d58e4abebc55d Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 2 Dec 2024 12:14:09 +0100 Subject: [PATCH 0833/1125] Revert "Flake: backport headscale changes to stable nixpkgs" This reverts commit fdad5d88bbf5942f89add50faf4e2ac7285e76ce. --- flake.nix | 4 +- .../backport_unstable_headscale_changes.patch | 1757 ----------------- 2 files changed, 1 insertion(+), 1760 deletions(-) delete mode 100644 nixpkgs-patches/backport_unstable_headscale_changes.patch diff --git a/flake.nix b/flake.nix index bc8ddca..b4bad73 100644 --- a/flake.nix +++ b/flake.nix @@ -105,9 +105,7 @@ nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; src = nixpkgs-raw; - patches = [ - ./nixpkgs-patches/backport_unstable_headscale_changes.patch - ]; + patches = []; }; # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs {self = inputs.self;}; diff --git a/nixpkgs-patches/backport_unstable_headscale_changes.patch b/nixpkgs-patches/backport_unstable_headscale_changes.patch deleted file mode 100644 index c173ef9..0000000 --- a/nixpkgs-patches/backport_unstable_headscale_changes.patch +++ /dev/null @@ -1,1757 +0,0 @@ -From 4a5c88eac3aaf1fb3d5ab15ee84787b9883c2465 Mon Sep 17 00:00:00 2001 -From: Kristoffer Dalby -Date: Fri, 6 Sep 2024 12:47:36 +0200 -Subject: [PATCH 1/8] nixos/headscale: modernize - -Signed-off-by: Kristoffer Dalby ---- - .../modules/services/networking/headscale.nix | 472 ++++++++++-------- - 1 file changed, 270 insertions(+), 202 deletions(-) - -diff --git a/nixos/modules/services/networking/headscale.nix b/nixos/modules/services/networking/headscale.nix -index ea66faeabbf2..645d4fe9c069 100644 ---- a/nixos/modules/services/networking/headscale.nix -+++ b/nixos/modules/services/networking/headscale.nix -@@ -1,8 +1,7 @@ --{ -- config, -- lib, -- pkgs, -- ... -+{ config -+, lib -+, pkgs -+, ... - }: - with lib; let - cfg = config.services.headscale; -@@ -10,9 +9,19 @@ with lib; let - dataDir = "/var/lib/headscale"; - runDir = "/run/headscale"; - -- settingsFormat = pkgs.formats.yaml {}; -+ cliConfig = { -+ # Turn off update checks since the origin of our package -+ # is nixpkgs and not Github. -+ disable_check_updates = true; -+ -+ unix_socket = "${runDir}/headscale.sock"; -+ }; -+ -+ settingsFormat = pkgs.formats.yaml { }; - configFile = settingsFormat.generate "headscale.yaml" cfg.settings; --in { -+ cliConfigFile = settingsFormat.generate "headscale.yaml" cliConfig; -+in -+{ - options = { - services.headscale = { - enable = mkEnableOption "headscale, Open Source coordination server for Tailscale"; -@@ -84,14 +93,6 @@ in { - example = "https://myheadscale.example.com:443"; - }; - -- private_key_path = mkOption { -- type = types.path; -- default = "${dataDir}/private.key"; -- description = '' -- Path to private key file, generated automatically if it does not exist. -- ''; -- }; -- - noise.private_key_path = mkOption { - type = types.path; - default = "${dataDir}/noise_private.key"; -@@ -100,10 +101,44 @@ in { - ''; - }; - -+ prefixes = -+ let -+ prefDesc = '' -+ Each prefix consists of either an IPv4 or IPv6 address, -+ and the associated prefix length, delimited by a slash. -+ It must be within IP ranges supported by the Tailscale -+ client - i.e., subnets of 100.64.0.0/10 and fd7a:115c:a1e0::/48. -+ ''; -+ in -+ { -+ v4 = mkOption { -+ type = types.str; -+ default = "100.64.0.0/10"; -+ description = prefDesc; -+ }; -+ -+ v6 = mkOption { -+ type = types.str; -+ default = "fd7a:115c:a1e0::/48"; -+ description = prefDesc; -+ }; -+ -+ allocation = mkOption { -+ type = types.enum [ "sequential" "random" ]; -+ example = "random"; -+ default = "sequential"; -+ description = '' -+ Strategy used for allocation of IPs to nodes, available options: -+ - sequential (default): assigns the next free IP from the previous given IP. -+ - random: assigns the next free IP from a pseudo-random IP generator (crypto/rand). -+ ''; -+ }; -+ }; -+ - derp = { - urls = mkOption { - type = types.listOf types.str; -- default = ["https://controlplane.tailscale.com/derpmap/default"]; -+ default = [ "https://controlplane.tailscale.com/derpmap/default" ]; - description = '' - List of urls containing DERP maps. - See [How Tailscale works](https://tailscale.com/blog/how-tailscale-works/) for more information on DERP maps. -@@ -112,7 +147,7 @@ in { - - paths = mkOption { - type = types.listOf types.path; -- default = []; -+ default = [ ]; - description = '' - List of file paths containing DERP maps. - See [How Tailscale works](https://tailscale.com/blog/how-tailscale-works/) for more information on DERP maps. -@@ -136,6 +171,14 @@ in { - ''; - example = "5m"; - }; -+ -+ server.private_key_path = lib.mkOption { -+ type = lib.types.path; -+ default = "${dataDir}/derp_server_private.key"; -+ description = '' -+ Path to derp private key file, generated automatically if it does not exist. -+ ''; -+ }; - }; - - ephemeral_node_inactivity_timeout = mkOption { -@@ -147,102 +190,98 @@ in { - example = "5m"; - }; - -- db_type = mkOption { -- type = types.enum ["sqlite3" "postgres"]; -- example = "postgres"; -- default = "sqlite3"; -- description = "Database engine to use."; -- }; -- -- db_host = mkOption { -- type = types.nullOr types.str; -- default = null; -- example = "127.0.0.1"; -- description = "Database host address."; -- }; -- -- db_port = mkOption { -- type = types.nullOr types.port; -- default = null; -- example = 3306; -- description = "Database host port."; -- }; -+ database = { -+ type = mkOption { -+ type = types.enum [ "sqlite" "sqlite3" "postgres" ]; -+ example = "postgres"; -+ default = "sqlite"; -+ description = '' -+ Database engine to use. -+ Please note that using Postgres is highly discouraged as it is only supported for legacy reasons. -+ All new development, testing and optimisations are done with SQLite in mind. -+ ''; -+ }; - -- db_name = mkOption { -- type = types.nullOr types.str; -- default = null; -- example = "headscale"; -- description = "Database name."; -- }; -+ sqlite = { -+ path = mkOption { -+ type = types.nullOr types.str; -+ default = "${dataDir}/db.sqlite"; -+ description = "Path to the sqlite3 database file."; -+ }; - -- db_user = mkOption { -- type = types.nullOr types.str; -- default = null; -- example = "headscale"; -- description = "Database user."; -- }; -+ write_ahead_log = mkOption { -+ type = types.bool; -+ default = true; -+ description = '' -+ Enable WAL mode for SQLite. This is recommended for production environments. -+ https://www.sqlite.org/wal.html -+ ''; -+ example = true; -+ }; -+ }; - -- db_password_file = mkOption { -- type = types.nullOr types.path; -- default = null; -- example = "/run/keys/headscale-dbpassword"; -- description = '' -- A file containing the password corresponding to -- {option}`database.user`. -- ''; -- }; -+ postgres = { -+ host = mkOption { -+ type = types.nullOr types.str; -+ default = null; -+ example = "127.0.0.1"; -+ description = "Database host address."; -+ }; - -- db_path = mkOption { -- type = types.nullOr types.str; -- default = "${dataDir}/db.sqlite"; -- description = "Path to the sqlite3 database file."; -- }; -+ port = mkOption { -+ type = types.nullOr types.port; -+ default = null; -+ example = 3306; -+ description = "Database host port."; -+ }; - -- log.level = mkOption { -- type = types.str; -- default = "info"; -- description = '' -- headscale log level. -- ''; -- example = "debug"; -- }; -+ name = mkOption { -+ type = types.nullOr types.str; -+ default = null; -+ example = "headscale"; -+ description = "Database name."; -+ }; - -- log.format = mkOption { -- type = types.str; -- default = "text"; -- description = '' -- headscale log format. -- ''; -- example = "json"; -- }; -+ user = mkOption { -+ type = types.nullOr types.str; -+ default = null; -+ example = "headscale"; -+ description = "Database user."; -+ }; - -- dns_config = { -- nameservers = mkOption { -- type = types.listOf types.str; -- default = ["1.1.1.1"]; -- description = '' -- List of nameservers to pass to Tailscale clients. -- ''; -+ password_file = mkOption { -+ type = types.nullOr types.path; -+ default = null; -+ example = "/run/keys/headscale-dbpassword"; -+ description = '' -+ A file containing the password corresponding to -+ {option}`database.user`. -+ ''; -+ }; - }; -+ }; - -- override_local_dns = mkOption { -- type = types.bool; -- default = false; -+ log = { -+ level = mkOption { -+ type = types.str; -+ default = "info"; - description = '' -- Whether to use [Override local DNS](https://tailscale.com/kb/1054/dns/). -+ headscale log level. - ''; -- example = true; -+ example = "debug"; - }; - -- domains = mkOption { -- type = types.listOf types.str; -- default = []; -+ format = mkOption { -+ type = types.str; -+ default = "text"; - description = '' -- Search domains to inject to Tailscale clients. -+ headscale log format. - ''; -- example = ["mydomain.internal"]; -+ example = "json"; - }; -+ }; - -+ dns = { - magic_dns = mkOption { - type = types.bool; - default = true; -@@ -264,6 +303,25 @@ in { - `myhost.mynamespace.example.com`). - ''; - }; -+ -+ nameservers = { -+ global = mkOption { -+ type = types.listOf types.str; -+ default = [ ]; -+ description = '' -+ List of nameservers to pass to Tailscale clients. -+ ''; -+ }; -+ }; -+ -+ search_domains = mkOption { -+ type = types.listOf types.str; -+ default = [ ]; -+ description = '' -+ Search domains to inject to Tailscale clients. -+ ''; -+ example = [ "mydomain.internal" ]; -+ }; - }; - - oidc = { -@@ -294,7 +352,7 @@ in { - - scope = mkOption { - type = types.listOf types.str; -- default = ["openid" "profile" "email"]; -+ default = [ "openid" "profile" "email" ]; - description = '' - Scopes used in the OIDC flow. - ''; -@@ -348,7 +406,7 @@ in { - }; - - tls_letsencrypt_challenge_type = mkOption { -- type = types.enum ["TLS-ALPN-01" "HTTP-01"]; -+ type = types.enum [ "TLS-ALPN-01" "HTTP-01" ]; - default = "HTTP-01"; - description = '' - Type of ACME challenge to use, currently supported types: -@@ -382,12 +440,24 @@ in { - ''; - }; - -- acl_policy_path = mkOption { -- type = types.nullOr types.path; -- default = null; -- description = '' -- Path to a file containing ACL policies. -- ''; -+ policy = { -+ mode = mkOption { -+ type = types.enum [ "file" "database" ]; -+ default = "file"; -+ description = '' -+ The mode can be "file" or "database" that defines -+ where the ACL policies are stored and read from. -+ ''; -+ }; -+ -+ path = mkOption { -+ type = types.nullOr types.path; -+ default = null; -+ description = '' -+ If the mode is set to "file", the path to a -+ HuJSON file containing ACL policies. -+ ''; -+ }; - }; - }; - }; -@@ -396,64 +466,63 @@ in { - }; - - imports = [ -- # TODO address + port = listen_addr -- (mkRenamedOptionModule ["services" "headscale" "serverUrl"] ["services" "headscale" "settings" "server_url"]) -- (mkRenamedOptionModule ["services" "headscale" "privateKeyFile"] ["services" "headscale" "settings" "private_key_path"]) -- (mkRenamedOptionModule ["services" "headscale" "derp" "urls"] ["services" "headscale" "settings" "derp" "urls"]) -- (mkRenamedOptionModule ["services" "headscale" "derp" "paths"] ["services" "headscale" "settings" "derp" "paths"]) -- (mkRenamedOptionModule ["services" "headscale" "derp" "autoUpdate"] ["services" "headscale" "settings" "derp" "auto_update_enable"]) -- (mkRenamedOptionModule ["services" "headscale" "derp" "updateFrequency"] ["services" "headscale" "settings" "derp" "update_frequency"]) -- (mkRenamedOptionModule ["services" "headscale" "ephemeralNodeInactivityTimeout"] ["services" "headscale" "settings" "ephemeral_node_inactivity_timeout"]) -- (mkRenamedOptionModule ["services" "headscale" "database" "type"] ["services" "headscale" "settings" "db_type"]) -- (mkRenamedOptionModule ["services" "headscale" "database" "path"] ["services" "headscale" "settings" "db_path"]) -- (mkRenamedOptionModule ["services" "headscale" "database" "host"] ["services" "headscale" "settings" "db_host"]) -- (mkRenamedOptionModule ["services" "headscale" "database" "port"] ["services" "headscale" "settings" "db_port"]) -- (mkRenamedOptionModule ["services" "headscale" "database" "name"] ["services" "headscale" "settings" "db_name"]) -- (mkRenamedOptionModule ["services" "headscale" "database" "user"] ["services" "headscale" "settings" "db_user"]) -- (mkRenamedOptionModule ["services" "headscale" "database" "passwordFile"] ["services" "headscale" "settings" "db_password_file"]) -- (mkRenamedOptionModule ["services" "headscale" "logLevel"] ["services" "headscale" "settings" "log" "level"]) -- (mkRenamedOptionModule ["services" "headscale" "dns" "nameservers"] ["services" "headscale" "settings" "dns_config" "nameservers"]) -- (mkRenamedOptionModule ["services" "headscale" "dns" "domains"] ["services" "headscale" "settings" "dns_config" "domains"]) -- (mkRenamedOptionModule ["services" "headscale" "dns" "magicDns"] ["services" "headscale" "settings" "dns_config" "magic_dns"]) -- (mkRenamedOptionModule ["services" "headscale" "dns" "baseDomain"] ["services" "headscale" "settings" "dns_config" "base_domain"]) -- (mkRenamedOptionModule ["services" "headscale" "openIdConnect" "issuer"] ["services" "headscale" "settings" "oidc" "issuer"]) -- (mkRenamedOptionModule ["services" "headscale" "openIdConnect" "clientId"] ["services" "headscale" "settings" "oidc" "client_id"]) -- (mkRenamedOptionModule ["services" "headscale" "openIdConnect" "clientSecretFile"] ["services" "headscale" "settings" "oidc" "client_secret_path"]) -- (mkRenamedOptionModule ["services" "headscale" "tls" "letsencrypt" "hostname"] ["services" "headscale" "settings" "tls_letsencrypt_hostname"]) -- (mkRenamedOptionModule ["services" "headscale" "tls" "letsencrypt" "challengeType"] ["services" "headscale" "settings" "tls_letsencrypt_challenge_type"]) -- (mkRenamedOptionModule ["services" "headscale" "tls" "letsencrypt" "httpListen"] ["services" "headscale" "settings" "tls_letsencrypt_listen"]) -- (mkRenamedOptionModule ["services" "headscale" "tls" "certFile"] ["services" "headscale" "settings" "tls_cert_path"]) -- (mkRenamedOptionModule ["services" "headscale" "tls" "keyFile"] ["services" "headscale" "settings" "tls_key_path"]) -- (mkRenamedOptionModule ["services" "headscale" "aclPolicyFile"] ["services" "headscale" "settings" "acl_policy_path"]) -- -- (mkRemovedOptionModule ["services" "headscale" "openIdConnect" "domainMap"] '' -+ (mkRenamedOptionModule [ "services" "headscale" "serverUrl" ] [ "services" "headscale" "settings" "server_url" ]) -+ (mkRenamedOptionModule [ "services" "headscale" "derp" "urls" ] [ "services" "headscale" "settings" "derp" "urls" ]) -+ (mkRenamedOptionModule [ "services" "headscale" "derp" "paths" ] [ "services" "headscale" "settings" "derp" "paths" ]) -+ (mkRenamedOptionModule [ "services" "headscale" "derp" "autoUpdate" ] [ "services" "headscale" "settings" "derp" "auto_update_enable" ]) -+ (mkRenamedOptionModule [ "services" "headscale" "derp" "updateFrequency" ] [ "services" "headscale" "settings" "derp" "update_frequency" ]) -+ (mkRenamedOptionModule [ "services" "headscale" "ephemeralNodeInactivityTimeout" ] [ "services" "headscale" "settings" "ephemeral_node_inactivity_timeout" ]) -+ -+ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_type"] ["services" "headscale" "settings" "database" "type"]) -+ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_path"] ["services" "headscale" "settings" "database" "sqlite" "path"]) -+ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_host"] ["services" "headscale" "settings" "database" "postgres" "host"]) -+ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_port"] ["services" "headscale" "settings" "database" "postgres" "port"]) -+ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_name"] ["services" "headscale" "settings" "database" "postgres" "name"]) -+ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_user"] ["services" "headscale" "settings" "database" "postgres" "user"]) -+ # (mkRenamedOptionModule ["services" "headscale" "settings" "db_password_file"] ["services" "headscale" "settings" "database" "postgres" "password_file"]) -+ -+ (mkRenamedOptionModule [ "services" "headscale" "logLevel" ] [ "services" "headscale" "settings" "log" "level" ]) -+ -+ # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "nameservers"] ["services" "headscale" "settings" "dns" "nameservers" "global"]) -+ # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "domains"] ["services" "headscale" "settings" "dns" "search_domains"]) -+ # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "magic_dns"] ["services" "headscale" "settings" "dns" "magic_dns"]) -+ # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "base_domain"] ["services" "headscale" "settings" "dns" "base_domain"]) -+ -+ (mkRenamedOptionModule [ "services" "headscale" "openIdConnect" "issuer" ] [ "services" "headscale" "settings" "oidc" "issuer" ]) -+ (mkRenamedOptionModule [ "services" "headscale" "openIdConnect" "clientId" ] [ "services" "headscale" "settings" "oidc" "client_id" ]) -+ (mkRenamedOptionModule [ "services" "headscale" "openIdConnect" "clientSecretFile" ] [ "services" "headscale" "settings" "oidc" "client_secret_path" ]) -+ (mkRenamedOptionModule [ "services" "headscale" "tls" "letsencrypt" "hostname" ] [ "services" "headscale" "settings" "tls_letsencrypt_hostname" ]) -+ (mkRenamedOptionModule [ "services" "headscale" "tls" "letsencrypt" "challengeType" ] [ "services" "headscale" "settings" "tls_letsencrypt_challenge_type" ]) -+ (mkRenamedOptionModule [ "services" "headscale" "tls" "letsencrypt" "httpListen" ] [ "services" "headscale" "settings" "tls_letsencrypt_listen" ]) -+ (mkRenamedOptionModule [ "services" "headscale" "tls" "certFile" ] [ "services" "headscale" "settings" "tls_cert_path" ]) -+ (mkRenamedOptionModule [ "services" "headscale" "tls" "keyFile" ] [ "services" "headscale" "settings" "tls_key_path" ]) -+ -+ # (mkRenamedOptionModule ["services" "headscale" "settings" "acl_policy_path"] ["services" "headscale" "settings" "policy" "path"]) -+ -+ (mkRemovedOptionModule [ "services" "headscale" "openIdConnect" "domainMap" ] '' - Headscale no longer uses domain_map. If you're using an old version of headscale you can still set this option via services.headscale.settings.oidc.domain_map. - '') - ]; - - config = mkIf cfg.enable { -- services.headscale.settings = { -- listen_addr = mkDefault "${cfg.address}:${toString cfg.port}"; -+ services.headscale.settings = mkMerge [ -+ cliConfig -+ { -+ listen_addr = mkDefault "${cfg.address}:${toString cfg.port}"; - -- # Turn off update checks since the origin of our package -- # is nixpkgs and not Github. -- disable_check_updates = true; -- -- unix_socket = "${runDir}/headscale.sock"; -- -- tls_letsencrypt_cache_dir = "${dataDir}/.cache"; -- }; -+ tls_letsencrypt_cache_dir = "${dataDir}/.cache"; -+ } -+ ]; - - environment = { -- # Setup the headscale configuration in a known path in /etc to -- # allow both the Server and the Client use it to find the socket -- # for communication. -- etc."headscale/config.yaml".source = configFile; -+ # Headscale CLI needs a minimal config to be able to locate the unix socket -+ # to talk to the server instance. -+ etc."headscale/config.yaml".source = cliConfigFile; - - systemPackages = [ cfg.package ]; - }; - -- users.groups.headscale = mkIf (cfg.group == "headscale") {}; -+ users.groups.headscale = mkIf (cfg.group == "headscale") { }; - - users.users.headscale = mkIf (cfg.user == "headscale") { - description = "headscale user"; -@@ -465,65 +534,64 @@ in { - systemd.services.headscale = { - description = "headscale coordination server for Tailscale"; - wants = [ "network-online.target" ]; -- after = ["network-online.target"]; -- wantedBy = ["multi-user.target"]; -- restartTriggers = [configFile]; -- -- environment.GIN_MODE = "release"; -+ after = [ "network-online.target" ]; -+ wantedBy = [ "multi-user.target" ]; - - script = '' -- ${optionalString (cfg.settings.db_password_file != null) '' -- export HEADSCALE_DB_PASS="$(head -n1 ${escapeShellArg cfg.settings.db_password_file})" -+ ${optionalString (cfg.settings.database.postgres.password_file != null) '' -+ export HEADSCALE_DATABASE_POSTGRES_PASS="$(head -n1 ${escapeShellArg cfg.settings.database.postgres.password_file})" - ''} - -- exec ${cfg.package}/bin/headscale serve -+ exec ${lib.getExe cfg.package} serve --config ${configFile} - ''; - -- serviceConfig = let -- capabilityBoundingSet = ["CAP_CHOWN"] ++ optional (cfg.port < 1024) "CAP_NET_BIND_SERVICE"; -- in { -- Restart = "always"; -- Type = "simple"; -- User = cfg.user; -- Group = cfg.group; -- -- # Hardening options -- RuntimeDirectory = "headscale"; -- # Allow headscale group access so users can be added and use the CLI. -- RuntimeDirectoryMode = "0750"; -- -- StateDirectory = "headscale"; -- StateDirectoryMode = "0750"; -- -- ProtectSystem = "strict"; -- ProtectHome = true; -- PrivateTmp = true; -- PrivateDevices = true; -- ProtectKernelTunables = true; -- ProtectControlGroups = true; -- RestrictSUIDSGID = true; -- PrivateMounts = true; -- ProtectKernelModules = true; -- ProtectKernelLogs = true; -- ProtectHostname = true; -- ProtectClock = true; -- ProtectProc = "invisible"; -- ProcSubset = "pid"; -- RestrictNamespaces = true; -- RemoveIPC = true; -- UMask = "0077"; -- -- CapabilityBoundingSet = capabilityBoundingSet; -- AmbientCapabilities = capabilityBoundingSet; -- NoNewPrivileges = true; -- LockPersonality = true; -- RestrictRealtime = true; -- SystemCallFilter = ["@system-service" "~@privileged" "@chown"]; -- SystemCallArchitectures = "native"; -- RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX"; -- }; -+ serviceConfig = -+ let -+ capabilityBoundingSet = [ "CAP_CHOWN" ] ++ optional (cfg.port < 1024) "CAP_NET_BIND_SERVICE"; -+ in -+ { -+ Restart = "always"; -+ Type = "simple"; -+ User = cfg.user; -+ Group = cfg.group; -+ -+ # Hardening options -+ RuntimeDirectory = "headscale"; -+ # Allow headscale group access so users can be added and use the CLI. -+ RuntimeDirectoryMode = "0750"; -+ -+ StateDirectory = "headscale"; -+ StateDirectoryMode = "0750"; -+ -+ ProtectSystem = "strict"; -+ ProtectHome = true; -+ PrivateTmp = true; -+ PrivateDevices = true; -+ ProtectKernelTunables = true; -+ ProtectControlGroups = true; -+ RestrictSUIDSGID = true; -+ PrivateMounts = true; -+ ProtectKernelModules = true; -+ ProtectKernelLogs = true; -+ ProtectHostname = true; -+ ProtectClock = true; -+ ProtectProc = "invisible"; -+ ProcSubset = "pid"; -+ RestrictNamespaces = true; -+ RemoveIPC = true; -+ UMask = "0077"; -+ -+ CapabilityBoundingSet = capabilityBoundingSet; -+ AmbientCapabilities = capabilityBoundingSet; -+ NoNewPrivileges = true; -+ LockPersonality = true; -+ RestrictRealtime = true; -+ SystemCallFilter = [ "@system-service" "~@privileged" "@chown" ]; -+ SystemCallArchitectures = "native"; -+ RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX"; -+ }; - }; - }; - -- meta.maintainers = with maintainers; [kradalby misterio77]; -+ meta.maintainers = with maintainers; [ kradalby misterio77 ]; - } --- -2.46.1 - - -From afff4fba9136ba0dbe8ff635cb3ead89d5240bf8 Mon Sep 17 00:00:00 2001 -From: Kristoffer Dalby -Date: Wed, 18 Sep 2024 10:24:19 +0100 -Subject: [PATCH 2/8] nixos/headscale: update module to headscale 0.23.0 - -Signed-off-by: Kristoffer Dalby ---- - .../modules/services/networking/headscale.nix | 445 +++++++++--------- - 1 file changed, 219 insertions(+), 226 deletions(-) - -diff --git a/nixos/modules/services/networking/headscale.nix b/nixos/modules/services/networking/headscale.nix -index 645d4fe9c069..622a13fe7b61 100644 ---- a/nixos/modules/services/networking/headscale.nix -+++ b/nixos/modules/services/networking/headscale.nix -@@ -1,9 +1,9 @@ --{ config --, lib --, pkgs --, ... --}: --with lib; let -+{ -+ config, -+ lib, -+ pkgs, -+ ... -+}: let - cfg = config.services.headscale; - - dataDir = "/var/lib/headscale"; -@@ -17,20 +17,19 @@ with lib; let - unix_socket = "${runDir}/headscale.sock"; - }; - -- settingsFormat = pkgs.formats.yaml { }; -+ settingsFormat = pkgs.formats.yaml {}; - configFile = settingsFormat.generate "headscale.yaml" cfg.settings; - cliConfigFile = settingsFormat.generate "headscale.yaml" cliConfig; --in --{ -+in { - options = { - services.headscale = { -- enable = mkEnableOption "headscale, Open Source coordination server for Tailscale"; -+ enable = lib.mkEnableOption "headscale, Open Source coordination server for Tailscale"; - -- package = mkPackageOption pkgs "headscale" { }; -+ package = lib.mkPackageOption pkgs "headscale" {}; - -- user = mkOption { -+ user = lib.mkOption { - default = "headscale"; -- type = types.str; -+ type = lib.types.str; - description = '' - User account under which headscale runs. - -@@ -42,9 +41,9 @@ in - ''; - }; - -- group = mkOption { -+ group = lib.mkOption { - default = "headscale"; -- type = types.str; -+ type = lib.types.str; - description = '' - Group under which headscale runs. - -@@ -56,8 +55,8 @@ in - ''; - }; - -- address = mkOption { -- type = types.str; -+ address = lib.mkOption { -+ type = lib.types.str; - default = "127.0.0.1"; - description = '' - Listening address of headscale. -@@ -65,8 +64,8 @@ in - example = "0.0.0.0"; - }; - -- port = mkOption { -- type = types.port; -+ port = lib.mkOption { -+ type = lib.types.port; - default = 8080; - description = '' - Listening port of headscale. -@@ -74,18 +73,33 @@ in - example = 443; - }; - -- settings = mkOption { -+ settings = lib.mkOption { - description = '' - Overrides to {file}`config.yaml` as a Nix attribute set. - Check the [example config](https://github.com/juanfont/headscale/blob/main/config-example.yaml) - for possible options. - ''; -- type = types.submodule { -+ type = lib.types.submodule { - freeformType = settingsFormat.type; - -+ imports = with lib; [ -+ (mkAliasOptionModule ["acl_policy_path"] ["policy" "path"]) -+ (mkAliasOptionModule ["db_host"] ["database" "postgres" "host"]) -+ (mkAliasOptionModule ["db_name"] ["database" "postgres" "name"]) -+ (mkAliasOptionModule ["db_password_file"] ["database" "postgres" "password_file"]) -+ (mkAliasOptionModule ["db_path"] ["database" "sqlite" "path"]) -+ (mkAliasOptionModule ["db_port"] ["database" "postgres" "port"]) -+ (mkAliasOptionModule ["db_type"] ["database" "type"]) -+ (mkAliasOptionModule ["db_user"] ["database" "postgres" "user"]) -+ (mkAliasOptionModule ["dns_config" "base_domain"] ["dns" "base_domain"]) -+ (mkAliasOptionModule ["dns_config" "domains"] ["dns" "search_domains"]) -+ (mkAliasOptionModule ["dns_config" "magic_dns"] ["dns" "magic_dns"]) -+ (mkAliasOptionModule ["dns_config" "nameservers"] ["dns" "nameservers" "global"]) -+ ]; -+ - options = { -- server_url = mkOption { -- type = types.str; -+ server_url = lib.mkOption { -+ type = lib.types.str; - default = "http://127.0.0.1:8080"; - description = '' - The url clients will connect to. -@@ -93,69 +107,67 @@ in - example = "https://myheadscale.example.com:443"; - }; - -- noise.private_key_path = mkOption { -- type = types.path; -+ noise.private_key_path = lib.mkOption { -+ type = lib.types.path; - default = "${dataDir}/noise_private.key"; - description = '' - Path to noise private key file, generated automatically if it does not exist. - ''; - }; - -- prefixes = -- let -- prefDesc = '' -- Each prefix consists of either an IPv4 or IPv6 address, -- and the associated prefix length, delimited by a slash. -- It must be within IP ranges supported by the Tailscale -- client - i.e., subnets of 100.64.0.0/10 and fd7a:115c:a1e0::/48. -- ''; -- in -- { -- v4 = mkOption { -- type = types.str; -- default = "100.64.0.0/10"; -- description = prefDesc; -- }; -+ prefixes = let -+ prefDesc = '' -+ Each prefix consists of either an IPv4 or IPv6 address, -+ and the associated prefix length, delimited by a slash. -+ It must be within IP ranges supported by the Tailscale -+ client - i.e., subnets of 100.64.0.0/10 and fd7a:115c:a1e0::/48. -+ ''; -+ in { -+ v4 = lib.mkOption { -+ type = lib.types.str; -+ default = "100.64.0.0/10"; -+ description = prefDesc; -+ }; - -- v6 = mkOption { -- type = types.str; -- default = "fd7a:115c:a1e0::/48"; -- description = prefDesc; -- }; -+ v6 = lib.mkOption { -+ type = lib.types.str; -+ default = "fd7a:115c:a1e0::/48"; -+ description = prefDesc; -+ }; - -- allocation = mkOption { -- type = types.enum [ "sequential" "random" ]; -- example = "random"; -- default = "sequential"; -- description = '' -- Strategy used for allocation of IPs to nodes, available options: -- - sequential (default): assigns the next free IP from the previous given IP. -- - random: assigns the next free IP from a pseudo-random IP generator (crypto/rand). -- ''; -- }; -+ allocation = lib.mkOption { -+ type = lib.types.enum ["sequential" "random"]; -+ example = "random"; -+ default = "sequential"; -+ description = '' -+ Strategy used for allocation of IPs to nodes, available options: -+ - sequential (default): assigns the next free IP from the previous given IP. -+ - random: assigns the next free IP from a pseudo-random IP generator (crypto/rand). -+ ''; - }; -+ }; - - derp = { -- urls = mkOption { -- type = types.listOf types.str; -- default = [ "https://controlplane.tailscale.com/derpmap/default" ]; -+ urls = lib.mkOption { -+ type = lib.types.listOf lib.types.str; -+ default = ["https://controlplane.tailscale.com/derpmap/default"]; - description = '' - List of urls containing DERP maps. - See [How Tailscale works](https://tailscale.com/blog/how-tailscale-works/) for more information on DERP maps. - ''; - }; - -- paths = mkOption { -- type = types.listOf types.path; -- default = [ ]; -+ paths = lib.mkOption { -+ type = lib.types.listOf lib.types.path; -+ default = []; - description = '' - List of file paths containing DERP maps. - See [How Tailscale works](https://tailscale.com/blog/how-tailscale-works/) for more information on DERP maps. - ''; - }; - -- auto_update_enable = mkOption { -- type = types.bool; -+ auto_update_enable = lib.mkOption { -+ type = lib.types.bool; - default = true; - description = '' - Whether to automatically update DERP maps on a set frequency. -@@ -163,8 +175,8 @@ in - example = false; - }; - -- update_frequency = mkOption { -- type = types.str; -+ update_frequency = lib.mkOption { -+ type = lib.types.str; - default = "24h"; - description = '' - Frequency to update DERP maps. -@@ -181,8 +193,8 @@ in - }; - }; - -- ephemeral_node_inactivity_timeout = mkOption { -- type = types.str; -+ ephemeral_node_inactivity_timeout = lib.mkOption { -+ type = lib.types.str; - default = "30m"; - description = '' - Time before an inactive ephemeral node is deleted. -@@ -191,8 +203,8 @@ in - }; - - database = { -- type = mkOption { -- type = types.enum [ "sqlite" "sqlite3" "postgres" ]; -+ type = lib.mkOption { -+ type = lib.types.enum ["sqlite" "sqlite3" "postgres"]; - example = "postgres"; - default = "sqlite"; - description = '' -@@ -203,14 +215,14 @@ in - }; - - sqlite = { -- path = mkOption { -- type = types.nullOr types.str; -+ path = lib.mkOption { -+ type = lib.types.nullOr lib.types.str; - default = "${dataDir}/db.sqlite"; - description = "Path to the sqlite3 database file."; - }; - -- write_ahead_log = mkOption { -- type = types.bool; -+ write_ahead_log = lib.mkOption { -+ type = lib.types.bool; - default = true; - description = '' - Enable WAL mode for SQLite. This is recommended for production environments. -@@ -221,36 +233,36 @@ in - }; - - postgres = { -- host = mkOption { -- type = types.nullOr types.str; -+ host = lib.mkOption { -+ type = lib.types.nullOr lib.types.str; - default = null; - example = "127.0.0.1"; - description = "Database host address."; - }; - -- port = mkOption { -- type = types.nullOr types.port; -+ port = lib.mkOption { -+ type = lib.types.nullOr lib.types.port; - default = null; - example = 3306; - description = "Database host port."; - }; - -- name = mkOption { -- type = types.nullOr types.str; -+ name = lib.mkOption { -+ type = lib.types.nullOr lib.types.str; - default = null; - example = "headscale"; - description = "Database name."; - }; - -- user = mkOption { -- type = types.nullOr types.str; -+ user = lib.mkOption { -+ type = lib.types.nullOr lib.types.str; - default = null; - example = "headscale"; - description = "Database user."; - }; - -- password_file = mkOption { -- type = types.nullOr types.path; -+ password_file = lib.mkOption { -+ type = lib.types.nullOr lib.types.path; - default = null; - example = "/run/keys/headscale-dbpassword"; - description = '' -@@ -262,8 +274,8 @@ in - }; - - log = { -- level = mkOption { -- type = types.str; -+ level = lib.mkOption { -+ type = lib.types.str; - default = "info"; - description = '' - headscale log level. -@@ -271,8 +283,8 @@ in - example = "debug"; - }; - -- format = mkOption { -- type = types.str; -+ format = lib.mkOption { -+ type = lib.types.str; - default = "text"; - description = '' - headscale log format. -@@ -282,8 +294,8 @@ in - }; - - dns = { -- magic_dns = mkOption { -- type = types.bool; -+ magic_dns = lib.mkOption { -+ type = lib.types.bool; - default = true; - description = '' - Whether to use [MagicDNS](https://tailscale.com/kb/1081/magicdns/). -@@ -292,8 +304,8 @@ in - example = false; - }; - -- base_domain = mkOption { -- type = types.str; -+ base_domain = lib.mkOption { -+ type = lib.types.str; - default = ""; - description = '' - Defines the base domain to create the hostnames for MagicDNS. -@@ -305,28 +317,28 @@ in - }; - - nameservers = { -- global = mkOption { -- type = types.listOf types.str; -- default = [ ]; -+ global = lib.mkOption { -+ type = lib.types.listOf lib.types.str; -+ default = []; - description = '' - List of nameservers to pass to Tailscale clients. - ''; - }; - }; - -- search_domains = mkOption { -- type = types.listOf types.str; -- default = [ ]; -+ search_domains = lib.mkOption { -+ type = lib.types.listOf lib.types.str; -+ default = []; - description = '' - Search domains to inject to Tailscale clients. - ''; -- example = [ "mydomain.internal" ]; -+ example = ["mydomain.internal"]; - }; - }; - - oidc = { -- issuer = mkOption { -- type = types.str; -+ issuer = lib.mkOption { -+ type = lib.types.str; - default = ""; - description = '' - URL to OpenID issuer. -@@ -334,33 +346,33 @@ in - example = "https://openid.example.com"; - }; - -- client_id = mkOption { -- type = types.str; -+ client_id = lib.mkOption { -+ type = lib.types.str; - default = ""; - description = '' - OpenID Connect client ID. - ''; - }; - -- client_secret_path = mkOption { -- type = types.nullOr types.str; -+ client_secret_path = lib.mkOption { -+ type = lib.types.nullOr lib.types.str; - default = null; - description = '' - Path to OpenID Connect client secret file. Expands environment variables in format ''${VAR}. - ''; - }; - -- scope = mkOption { -- type = types.listOf types.str; -- default = [ "openid" "profile" "email" ]; -+ scope = lib.mkOption { -+ type = lib.types.listOf lib.types.str; -+ default = ["openid" "profile" "email"]; - description = '' - Scopes used in the OIDC flow. - ''; - }; - -- extra_params = mkOption { -- type = types.attrsOf types.str; -- default = { }; -+ extra_params = lib.mkOption { -+ type = lib.types.attrsOf lib.types.str; -+ default = {}; - description = '' - Custom query parameters to send with the Authorize Endpoint request. - ''; -@@ -369,27 +381,27 @@ in - }; - }; - -- allowed_domains = mkOption { -- type = types.listOf types.str; -- default = [ ]; -+ allowed_domains = lib.mkOption { -+ type = lib.types.listOf lib.types.str; -+ default = []; - description = '' - Allowed principal domains. if an authenticated user's domain - is not in this list authentication request will be rejected. - ''; -- example = [ "example.com" ]; -+ example = ["example.com"]; - }; - -- allowed_users = mkOption { -- type = types.listOf types.str; -- default = [ ]; -+ allowed_users = lib.mkOption { -+ type = lib.types.listOf lib.types.str; -+ default = []; - description = '' - Users allowed to authenticate even if not in allowedDomains. - ''; -- example = [ "alice@example.com" ]; -+ example = ["alice@example.com"]; - }; - -- strip_email_domain = mkOption { -- type = types.bool; -+ strip_email_domain = lib.mkOption { -+ type = lib.types.bool; - default = true; - description = '' - Whether the domain part of the email address should be removed when generating namespaces. -@@ -397,16 +409,16 @@ in - }; - }; - -- tls_letsencrypt_hostname = mkOption { -- type = types.nullOr types.str; -+ tls_letsencrypt_hostname = lib.mkOption { -+ type = lib.types.nullOr lib.types.str; - default = ""; - description = '' - Domain name to request a TLS certificate for. - ''; - }; - -- tls_letsencrypt_challenge_type = mkOption { -- type = types.enum [ "TLS-ALPN-01" "HTTP-01" ]; -+ tls_letsencrypt_challenge_type = lib.mkOption { -+ type = lib.types.enum ["TLS-ALPN-01" "HTTP-01"]; - default = "HTTP-01"; - description = '' - Type of ACME challenge to use, currently supported types: -@@ -414,8 +426,8 @@ in - ''; - }; - -- tls_letsencrypt_listen = mkOption { -- type = types.nullOr types.str; -+ tls_letsencrypt_listen = lib.mkOption { -+ type = lib.types.nullOr lib.types.str; - default = ":http"; - description = '' - When HTTP-01 challenge is chosen, letsencrypt must set up a -@@ -424,16 +436,16 @@ in - ''; - }; - -- tls_cert_path = mkOption { -- type = types.nullOr types.path; -+ tls_cert_path = lib.mkOption { -+ type = lib.types.nullOr lib.types.path; - default = null; - description = '' - Path to already created certificate. - ''; - }; - -- tls_key_path = mkOption { -- type = types.nullOr types.path; -+ tls_key_path = lib.mkOption { -+ type = lib.types.nullOr lib.types.path; - default = null; - description = '' - Path to key for already created certificate. -@@ -441,8 +453,8 @@ in - }; - - policy = { -- mode = mkOption { -- type = types.enum [ "file" "database" ]; -+ mode = lib.mkOption { -+ type = lib.types.enum ["file" "database"]; - default = "file"; - description = '' - The mode can be "file" or "database" that defines -@@ -450,8 +462,8 @@ in - ''; - }; - -- path = mkOption { -- type = types.nullOr types.path; -+ path = lib.mkOption { -+ type = lib.types.nullOr lib.types.path; - default = null; - description = '' - If the mode is set to "file", the path to a -@@ -465,50 +477,33 @@ in - }; - }; - -- imports = [ -- (mkRenamedOptionModule [ "services" "headscale" "serverUrl" ] [ "services" "headscale" "settings" "server_url" ]) -- (mkRenamedOptionModule [ "services" "headscale" "derp" "urls" ] [ "services" "headscale" "settings" "derp" "urls" ]) -- (mkRenamedOptionModule [ "services" "headscale" "derp" "paths" ] [ "services" "headscale" "settings" "derp" "paths" ]) -- (mkRenamedOptionModule [ "services" "headscale" "derp" "autoUpdate" ] [ "services" "headscale" "settings" "derp" "auto_update_enable" ]) -- (mkRenamedOptionModule [ "services" "headscale" "derp" "updateFrequency" ] [ "services" "headscale" "settings" "derp" "update_frequency" ]) -- (mkRenamedOptionModule [ "services" "headscale" "ephemeralNodeInactivityTimeout" ] [ "services" "headscale" "settings" "ephemeral_node_inactivity_timeout" ]) -- -- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_type"] ["services" "headscale" "settings" "database" "type"]) -- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_path"] ["services" "headscale" "settings" "database" "sqlite" "path"]) -- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_host"] ["services" "headscale" "settings" "database" "postgres" "host"]) -- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_port"] ["services" "headscale" "settings" "database" "postgres" "port"]) -- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_name"] ["services" "headscale" "settings" "database" "postgres" "name"]) -- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_user"] ["services" "headscale" "settings" "database" "postgres" "user"]) -- # (mkRenamedOptionModule ["services" "headscale" "settings" "db_password_file"] ["services" "headscale" "settings" "database" "postgres" "password_file"]) -- -- (mkRenamedOptionModule [ "services" "headscale" "logLevel" ] [ "services" "headscale" "settings" "log" "level" ]) -- -- # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "nameservers"] ["services" "headscale" "settings" "dns" "nameservers" "global"]) -- # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "domains"] ["services" "headscale" "settings" "dns" "search_domains"]) -- # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "magic_dns"] ["services" "headscale" "settings" "dns" "magic_dns"]) -- # (mkRenamedOptionModule ["services" "headscale" "settings" "dns_config" "base_domain"] ["services" "headscale" "settings" "dns" "base_domain"]) -- -- (mkRenamedOptionModule [ "services" "headscale" "openIdConnect" "issuer" ] [ "services" "headscale" "settings" "oidc" "issuer" ]) -- (mkRenamedOptionModule [ "services" "headscale" "openIdConnect" "clientId" ] [ "services" "headscale" "settings" "oidc" "client_id" ]) -- (mkRenamedOptionModule [ "services" "headscale" "openIdConnect" "clientSecretFile" ] [ "services" "headscale" "settings" "oidc" "client_secret_path" ]) -- (mkRenamedOptionModule [ "services" "headscale" "tls" "letsencrypt" "hostname" ] [ "services" "headscale" "settings" "tls_letsencrypt_hostname" ]) -- (mkRenamedOptionModule [ "services" "headscale" "tls" "letsencrypt" "challengeType" ] [ "services" "headscale" "settings" "tls_letsencrypt_challenge_type" ]) -- (mkRenamedOptionModule [ "services" "headscale" "tls" "letsencrypt" "httpListen" ] [ "services" "headscale" "settings" "tls_letsencrypt_listen" ]) -- (mkRenamedOptionModule [ "services" "headscale" "tls" "certFile" ] [ "services" "headscale" "settings" "tls_cert_path" ]) -- (mkRenamedOptionModule [ "services" "headscale" "tls" "keyFile" ] [ "services" "headscale" "settings" "tls_key_path" ]) -- -- # (mkRenamedOptionModule ["services" "headscale" "settings" "acl_policy_path"] ["services" "headscale" "settings" "policy" "path"]) -- -- (mkRemovedOptionModule [ "services" "headscale" "openIdConnect" "domainMap" ] '' -+ imports = with lib; [ -+ (mkRenamedOptionModule ["services" "headscale" "derp" "autoUpdate"] ["services" "headscale" "settings" "derp" "auto_update_enable"]) -+ (mkRenamedOptionModule ["services" "headscale" "derp" "paths"] ["services" "headscale" "settings" "derp" "paths"]) -+ (mkRenamedOptionModule ["services" "headscale" "derp" "updateFrequency"] ["services" "headscale" "settings" "derp" "update_frequency"]) -+ (mkRenamedOptionModule ["services" "headscale" "derp" "urls"] ["services" "headscale" "settings" "derp" "urls"]) -+ (mkRenamedOptionModule ["services" "headscale" "ephemeralNodeInactivityTimeout"] ["services" "headscale" "settings" "ephemeral_node_inactivity_timeout"]) -+ (mkRenamedOptionModule ["services" "headscale" "logLevel"] ["services" "headscale" "settings" "log" "level"]) -+ (mkRenamedOptionModule ["services" "headscale" "openIdConnect" "clientId"] ["services" "headscale" "settings" "oidc" "client_id"]) -+ (mkRenamedOptionModule ["services" "headscale" "openIdConnect" "clientSecretFile"] ["services" "headscale" "settings" "oidc" "client_secret_path"]) -+ (mkRenamedOptionModule ["services" "headscale" "openIdConnect" "issuer"] ["services" "headscale" "settings" "oidc" "issuer"]) -+ (mkRenamedOptionModule ["services" "headscale" "serverUrl"] ["services" "headscale" "settings" "server_url"]) -+ (mkRenamedOptionModule ["services" "headscale" "tls" "certFile"] ["services" "headscale" "settings" "tls_cert_path"]) -+ (mkRenamedOptionModule ["services" "headscale" "tls" "keyFile"] ["services" "headscale" "settings" "tls_key_path"]) -+ (mkRenamedOptionModule ["services" "headscale" "tls" "letsencrypt" "challengeType"] ["services" "headscale" "settings" "tls_letsencrypt_challenge_type"]) -+ (mkRenamedOptionModule ["services" "headscale" "tls" "letsencrypt" "hostname"] ["services" "headscale" "settings" "tls_letsencrypt_hostname"]) -+ (mkRenamedOptionModule ["services" "headscale" "tls" "letsencrypt" "httpListen"] ["services" "headscale" "settings" "tls_letsencrypt_listen"]) -+ -+ (mkRemovedOptionModule ["services" "headscale" "openIdConnect" "domainMap"] '' - Headscale no longer uses domain_map. If you're using an old version of headscale you can still set this option via services.headscale.settings.oidc.domain_map. - '') - ]; - -- config = mkIf cfg.enable { -- services.headscale.settings = mkMerge [ -+ config = lib.mkIf cfg.enable { -+ services.headscale.settings = lib.mkMerge [ - cliConfig - { -- listen_addr = mkDefault "${cfg.address}:${toString cfg.port}"; -+ listen_addr = lib.mkDefault "${cfg.address}:${toString cfg.port}"; - - tls_letsencrypt_cache_dir = "${dataDir}/.cache"; - } -@@ -519,12 +514,12 @@ in - # to talk to the server instance. - etc."headscale/config.yaml".source = cliConfigFile; - -- systemPackages = [ cfg.package ]; -+ systemPackages = [cfg.package]; - }; - -- users.groups.headscale = mkIf (cfg.group == "headscale") { }; -+ users.groups.headscale = lib.mkIf (cfg.group == "headscale") {}; - -- users.users.headscale = mkIf (cfg.user == "headscale") { -+ users.users.headscale = lib.mkIf (cfg.user == "headscale") { - description = "headscale user"; - home = dataDir; - group = cfg.group; -@@ -533,65 +528,63 @@ in - - systemd.services.headscale = { - description = "headscale coordination server for Tailscale"; -- wants = [ "network-online.target" ]; -- after = [ "network-online.target" ]; -- wantedBy = [ "multi-user.target" ]; -+ wants = ["network-online.target"]; -+ after = ["network-online.target"]; -+ wantedBy = ["multi-user.target"]; - - script = '' -- ${optionalString (cfg.settings.database.postgres.password_file != null) '' -- export HEADSCALE_DATABASE_POSTGRES_PASS="$(head -n1 ${escapeShellArg cfg.settings.database.postgres.password_file})" -+ ${lib.optionalString (cfg.settings.database.postgres.password_file != null) '' -+ export HEADSCALE_DATABASE_POSTGRES_PASS="$(head -n1 ${lib.escapeShellArg cfg.settings.database.postgres.password_file})" - ''} - - exec ${lib.getExe cfg.package} serve --config ${configFile} - ''; - -- serviceConfig = -- let -- capabilityBoundingSet = [ "CAP_CHOWN" ] ++ optional (cfg.port < 1024) "CAP_NET_BIND_SERVICE"; -- in -- { -- Restart = "always"; -- Type = "simple"; -- User = cfg.user; -- Group = cfg.group; -- -- # Hardening options -- RuntimeDirectory = "headscale"; -- # Allow headscale group access so users can be added and use the CLI. -- RuntimeDirectoryMode = "0750"; -- -- StateDirectory = "headscale"; -- StateDirectoryMode = "0750"; -- -- ProtectSystem = "strict"; -- ProtectHome = true; -- PrivateTmp = true; -- PrivateDevices = true; -- ProtectKernelTunables = true; -- ProtectControlGroups = true; -- RestrictSUIDSGID = true; -- PrivateMounts = true; -- ProtectKernelModules = true; -- ProtectKernelLogs = true; -- ProtectHostname = true; -- ProtectClock = true; -- ProtectProc = "invisible"; -- ProcSubset = "pid"; -- RestrictNamespaces = true; -- RemoveIPC = true; -- UMask = "0077"; -- -- CapabilityBoundingSet = capabilityBoundingSet; -- AmbientCapabilities = capabilityBoundingSet; -- NoNewPrivileges = true; -- LockPersonality = true; -- RestrictRealtime = true; -- SystemCallFilter = [ "@system-service" "~@privileged" "@chown" ]; -- SystemCallArchitectures = "native"; -- RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX"; -- }; -+ serviceConfig = let -+ capabilityBoundingSet = ["CAP_CHOWN"] ++ lib.optional (cfg.port < 1024) "CAP_NET_BIND_SERVICE"; -+ in { -+ Restart = "always"; -+ Type = "simple"; -+ User = cfg.user; -+ Group = cfg.group; -+ -+ # Hardening options -+ RuntimeDirectory = "headscale"; -+ # Allow headscale group access so users can be added and use the CLI. -+ RuntimeDirectoryMode = "0750"; -+ -+ StateDirectory = "headscale"; -+ StateDirectoryMode = "0750"; -+ -+ ProtectSystem = "strict"; -+ ProtectHome = true; -+ PrivateTmp = true; -+ PrivateDevices = true; -+ ProtectKernelTunables = true; -+ ProtectControlGroups = true; -+ RestrictSUIDSGID = true; -+ PrivateMounts = true; -+ ProtectKernelModules = true; -+ ProtectKernelLogs = true; -+ ProtectHostname = true; -+ ProtectClock = true; -+ ProtectProc = "invisible"; -+ ProcSubset = "pid"; -+ RestrictNamespaces = true; -+ RemoveIPC = true; -+ UMask = "0077"; -+ -+ CapabilityBoundingSet = capabilityBoundingSet; -+ AmbientCapabilities = capabilityBoundingSet; -+ NoNewPrivileges = true; -+ LockPersonality = true; -+ RestrictRealtime = true; -+ SystemCallFilter = ["@system-service" "~@privileged" "@chown"]; -+ SystemCallArchitectures = "native"; -+ RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX"; -+ }; - }; - }; - -- meta.maintainers = with maintainers; [ kradalby misterio77 ]; -+ meta.maintainers = with lib.maintainers; [kradalby misterio77]; - } --- -2.46.1 - - -From 7b2c10bda8a50ea531a444526a3e89e2851bd681 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= -Date: Fri, 11 Oct 2024 13:23:36 -0700 -Subject: [PATCH 3/8] nixos/headscale: assert that server_url does not contain - base_domain - ---- - nixos/modules/services/networking/headscale.nix | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/nixos/modules/services/networking/headscale.nix b/nixos/modules/services/networking/headscale.nix -index 622a13fe7b61..c2e616d30e87 100644 ---- a/nixos/modules/services/networking/headscale.nix -+++ b/nixos/modules/services/networking/headscale.nix -@@ -500,6 +500,15 @@ in { - ]; - - config = lib.mkIf cfg.enable { -+ assertions = [ -+ { -+ # This is stricter than it needs to be but is exactly what upstream does: -+ # https://github.com/kradalby/headscale/blob/adc084f20f843d7963c999764fa83939668d2d2c/hscontrol/types/config.go#L799 -+ assertion = with cfg.settings; dns.use_username_in_magic_dns or false || dns.base_domain == "" || !lib.hasInfix dns.base_domain server_url; -+ message = "server_url cannot contain the base_domain, this will cause the headscale server and embedded DERP to become unreachable from the Tailscale node."; -+ } -+ ]; -+ - services.headscale.settings = lib.mkMerge [ - cliConfig - { --- -2.46.1 - - -From 0c1215620750c8ca403827076f3a3d02ce419889 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= -Date: Fri, 11 Oct 2024 13:58:20 -0700 -Subject: [PATCH 4/8] nixos/headscale: don't set deprecated options in config - -We cannot use `mkRenamedOptionModule` or `mkRemovedOptionModule` inside -a freeform option. Thus we have to manually assert these deprecated -options aren't used rather than aliasing them to their replacement. ---- - .../modules/services/networking/headscale.nix | 31 ++++++++++--------- - 1 file changed, 16 insertions(+), 15 deletions(-) - -diff --git a/nixos/modules/services/networking/headscale.nix b/nixos/modules/services/networking/headscale.nix -index c2e616d30e87..fd2fd8dbede9 100644 ---- a/nixos/modules/services/networking/headscale.nix -+++ b/nixos/modules/services/networking/headscale.nix -@@ -20,6 +20,11 @@ - settingsFormat = pkgs.formats.yaml {}; - configFile = settingsFormat.generate "headscale.yaml" cfg.settings; - cliConfigFile = settingsFormat.generate "headscale.yaml" cliConfig; -+ -+ assertRemovedOption = option: message: { -+ assertion = !lib.hasAttrByPath option cfg; -+ message = "The option `services.headscale.${lib.options.showOption option}` was removed. " + message; -+ }; - in { - options = { - services.headscale = { -@@ -82,21 +87,6 @@ in { - type = lib.types.submodule { - freeformType = settingsFormat.type; - -- imports = with lib; [ -- (mkAliasOptionModule ["acl_policy_path"] ["policy" "path"]) -- (mkAliasOptionModule ["db_host"] ["database" "postgres" "host"]) -- (mkAliasOptionModule ["db_name"] ["database" "postgres" "name"]) -- (mkAliasOptionModule ["db_password_file"] ["database" "postgres" "password_file"]) -- (mkAliasOptionModule ["db_path"] ["database" "sqlite" "path"]) -- (mkAliasOptionModule ["db_port"] ["database" "postgres" "port"]) -- (mkAliasOptionModule ["db_type"] ["database" "type"]) -- (mkAliasOptionModule ["db_user"] ["database" "postgres" "user"]) -- (mkAliasOptionModule ["dns_config" "base_domain"] ["dns" "base_domain"]) -- (mkAliasOptionModule ["dns_config" "domains"] ["dns" "search_domains"]) -- (mkAliasOptionModule ["dns_config" "magic_dns"] ["dns" "magic_dns"]) -- (mkAliasOptionModule ["dns_config" "nameservers"] ["dns" "nameservers" "global"]) -- ]; -- - options = { - server_url = lib.mkOption { - type = lib.types.str; -@@ -507,6 +497,17 @@ in { - assertion = with cfg.settings; dns.use_username_in_magic_dns or false || dns.base_domain == "" || !lib.hasInfix dns.base_domain server_url; - message = "server_url cannot contain the base_domain, this will cause the headscale server and embedded DERP to become unreachable from the Tailscale node."; - } -+ (assertRemovedOption ["settings" "acl_policy_path"] "Use `policy.path` instead.") -+ (assertRemovedOption ["settings" "db_host"] "Use `database.postgres.host` instead.") -+ (assertRemovedOption ["settings" "db_name"] "Use `database.postgres.name` instead.") -+ (assertRemovedOption ["settings" "db_password_file"] "Use `database.postgres.password_file` instead.") -+ (assertRemovedOption ["settings" "db_path"] "Use `database.sqlite.path` instead.") -+ (assertRemovedOption ["settings" "db_port"] "Use `database.postgres.port` instead.") -+ (assertRemovedOption ["settings" "db_type"] "Use `database.type` instead.") -+ (assertRemovedOption ["settings" "db_user"] "Use `database.postgres.user` instead.") -+ (assertRemovedOption ["settings" "dns_config"] "Use `dns` instead.") -+ (assertRemovedOption ["settings" "dns_config" "domains"] "Use `dns.search_domains` instead.") -+ (assertRemovedOption ["settings" "dns_config" "nameservers"] "Use `dns.nameservers.global` instead.") - ]; - - services.headscale.settings = lib.mkMerge [ --- -2.46.1 - - -From 31de80dcfee97b024298128836c8ab49ca7ae798 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= -Date: Fri, 11 Oct 2024 20:17:15 -0700 -Subject: [PATCH 5/8] nixos/headscale: update option descriptions - ---- - nixos/modules/services/networking/headscale.nix | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - -diff --git a/nixos/modules/services/networking/headscale.nix b/nixos/modules/services/networking/headscale.nix -index fd2fd8dbede9..aac6d331a027 100644 ---- a/nixos/modules/services/networking/headscale.nix -+++ b/nixos/modules/services/networking/headscale.nix -@@ -289,7 +289,6 @@ in { - default = true; - description = '' - Whether to use [MagicDNS](https://tailscale.com/kb/1081/magicdns/). -- Only works if there is at least a nameserver defined. - ''; - example = false; - }; -@@ -299,11 +298,13 @@ in { - default = ""; - description = '' - Defines the base domain to create the hostnames for MagicDNS. -- {option}`baseDomain` must be a FQDNs, without the trailing dot. -- The FQDN of the hosts will be -- `hostname.namespace.base_domain` (e.g. -- `myhost.mynamespace.example.com`). -+ This domain must be different from the {option}`server_url` -+ domain. -+ {option}`base_domain` must be a FQDN, without the trailing dot. -+ The FQDN of the hosts will be `hostname.base_domain` (e.g. -+ `myhost.tailnet.example.com`). - ''; -+ example = "tailnet.example.com"; - }; - - nameservers = { --- -2.46.1 - - -From 083dec59811d7bfcaed1a34fc33d33eabc40fcc9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= -Date: Sat, 12 Oct 2024 18:28:17 -0700 -Subject: [PATCH 6/8] nixos/headscale: assert that dns.base_domain is set when - using MagicDNS - ---- - nixos/modules/services/networking/headscale.nix | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/nixos/modules/services/networking/headscale.nix b/nixos/modules/services/networking/headscale.nix -index aac6d331a027..9261ec03c532 100644 ---- a/nixos/modules/services/networking/headscale.nix -+++ b/nixos/modules/services/networking/headscale.nix -@@ -498,6 +498,10 @@ in { - assertion = with cfg.settings; dns.use_username_in_magic_dns or false || dns.base_domain == "" || !lib.hasInfix dns.base_domain server_url; - message = "server_url cannot contain the base_domain, this will cause the headscale server and embedded DERP to become unreachable from the Tailscale node."; - } -+ { -+ assertion = with cfg.settings; dns.magic_dns -> dns.base_domain != ""; -+ message = "dns.base_domain must be set when using MagicDNS"; -+ } - (assertRemovedOption ["settings" "acl_policy_path"] "Use `policy.path` instead.") - (assertRemovedOption ["settings" "db_host"] "Use `database.postgres.host` instead.") - (assertRemovedOption ["settings" "db_name"] "Use `database.postgres.name` instead.") --- -2.46.1 - - -From 720b90273528c02a0fb865062fe44a45eb04f82e Mon Sep 17 00:00:00 2001 -From: Jennifer Graul -Date: Wed, 13 Sep 2023 13:32:47 +0200 -Subject: [PATCH 7/8] headscale: fix reacting to SIGTERM - -The current version of headscale does not react to SIGTERMs and so it -can only be terminated by a SIGKILL at the moment. This commit provides -a patch to fix this. ---- - pkgs/servers/headscale/default.nix | 4 ++++ - pkgs/servers/headscale/sigterm-fix.patch | 12 ++++++++++++ - 2 files changed, 16 insertions(+) - create mode 100644 pkgs/servers/headscale/sigterm-fix.patch - -diff --git a/pkgs/servers/headscale/default.nix b/pkgs/servers/headscale/default.nix -index fca56f5fc848..eb9ad79b1888 100644 ---- a/pkgs/servers/headscale/default.nix -+++ b/pkgs/servers/headscale/default.nix -@@ -21,6 +21,10 @@ buildGoModule rec { - patches = [ - # backport of https://github.com/juanfont/headscale/pull/1697 - ./trim-oidc-secret-path.patch -+ -+ # fix for headscale not reacting to SIGTERM -+ # see https://github.com/juanfont/headscale/pull/1480 and https://github.com/juanfont/headscale/issues/1461 -+ ./sigterm-fix.patch - ]; - - ldflags = ["-s" "-w" "-X github.com/juanfont/headscale/cmd/headscale/cli.Version=v${version}"]; -diff --git a/pkgs/servers/headscale/sigterm-fix.patch b/pkgs/servers/headscale/sigterm-fix.patch -new file mode 100644 -index 000000000000..22a97d98caac ---- /dev/null -+++ b/pkgs/servers/headscale/sigterm-fix.patch -@@ -0,0 +1,12 @@ -+diff --git a/hscontrol/app.go b/hscontrol/app.go -+index b8dceba..4bcf019 100644 -+--- a/hscontrol/app.go -++++ b/hscontrol/app.go -+@@ -821,6 +821,7 @@ func (h *Headscale) Serve() error { -+ -+ // And we're done: -+ cancel() -++ return -+ } -+ } -+ } --- -2.46.1 - - -From 1a1fa839c7c8fafdea120b8b9af28d8839f8cafb Mon Sep 17 00:00:00 2001 -From: Kristoffer Dalby -Date: Fri, 6 Sep 2024 13:32:52 +0200 -Subject: [PATCH 8/8] headscale: 0.22.3 -> 0.23.0 - -Signed-off-by: Kristoffer Dalby ---- - pkgs/servers/headscale/default.nix | 20 +++++-------------- - pkgs/servers/headscale/sigterm-fix.patch | 12 ----------- - .../headscale/trim-oidc-secret-path.patch | 13 ------------ - pkgs/top-level/all-packages.nix | 4 +++- - 4 files changed, 8 insertions(+), 41 deletions(-) - delete mode 100644 pkgs/servers/headscale/sigterm-fix.patch - delete mode 100644 pkgs/servers/headscale/trim-oidc-secret-path.patch - -diff --git a/pkgs/servers/headscale/default.nix b/pkgs/servers/headscale/default.nix -index eb9ad79b1888..9f127946217e 100644 ---- a/pkgs/servers/headscale/default.nix -+++ b/pkgs/servers/headscale/default.nix -@@ -7,33 +7,22 @@ - }: - buildGoModule rec { - pname = "headscale"; -- version = "0.22.3"; -+ version = "0.23.0"; - - src = fetchFromGitHub { - owner = "juanfont"; - repo = "headscale"; - rev = "v${version}"; -- hash = "sha256-nqmTqe3F3Oh8rnJH0clwACD/0RpqmfOMXNubr3C8rEc="; -+ hash = "sha256-5tlnVNpn+hJayxHjTpbOO3kRInOYOFz0pe9pwjXZlBE="; - }; - -- vendorHash = "sha256-IOkbbFtE6+tNKnglE/8ZuNxhPSnloqM2sLgTvagMmnc="; -- -- patches = [ -- # backport of https://github.com/juanfont/headscale/pull/1697 -- ./trim-oidc-secret-path.patch -- -- # fix for headscale not reacting to SIGTERM -- # see https://github.com/juanfont/headscale/pull/1480 and https://github.com/juanfont/headscale/issues/1461 -- ./sigterm-fix.patch -- ]; -+ vendorHash = "sha256-+8dOxPG/Q+wuHgRwwWqdphHOuop0W9dVyClyQuh7aRc="; - - ldflags = ["-s" "-w" "-X github.com/juanfont/headscale/cmd/headscale/cli.Version=v${version}"]; - - nativeBuildInputs = [installShellFiles]; - checkFlags = ["-short"]; - -- tags = ["ts2019"]; -- - postInstall = '' - installShellCompletion --cmd headscale \ - --bash <($out/bin/headscale completion bash) \ -@@ -41,7 +30,7 @@ buildGoModule rec { - --zsh <($out/bin/headscale completion zsh) - ''; - -- passthru.tests = { inherit (nixosTests) headscale; }; -+ passthru.tests = {inherit (nixosTests) headscale;}; - - meta = with lib; { - homepage = "https://github.com/juanfont/headscale"; -@@ -63,6 +52,7 @@ buildGoModule rec { - Headscale implements this coordination server. - ''; - license = licenses.bsd3; -+ mainProgram = "headscale"; - maintainers = with maintainers; [nkje jk kradalby misterio77 ghuntley]; - }; - } -diff --git a/pkgs/servers/headscale/sigterm-fix.patch b/pkgs/servers/headscale/sigterm-fix.patch -deleted file mode 100644 -index 22a97d98caac..000000000000 ---- a/pkgs/servers/headscale/sigterm-fix.patch -+++ /dev/null -@@ -1,12 +0,0 @@ --diff --git a/hscontrol/app.go b/hscontrol/app.go --index b8dceba..4bcf019 100644 ----- a/hscontrol/app.go --+++ b/hscontrol/app.go --@@ -821,6 +821,7 @@ func (h *Headscale) Serve() error { -- -- // And we're done: -- cancel() --+ return -- } -- } -- } -diff --git a/pkgs/servers/headscale/trim-oidc-secret-path.patch b/pkgs/servers/headscale/trim-oidc-secret-path.patch -deleted file mode 100644 -index 4275988aa7db..000000000000 ---- a/pkgs/servers/headscale/trim-oidc-secret-path.patch -+++ /dev/null -@@ -1,13 +0,0 @@ --diff --git a/hscontrol/config.go b/hscontrol/config.go --index 0e83a1c..71fbfb0 100644 ----- a/hscontrol/config.go --+++ b/hscontrol/config.go --@@ -573,7 +573,7 @@ func GetHeadscaleConfig() (*Config, error) { -- if err != nil { -- return nil, err -- } --- oidcClientSecret = string(secretBytes) --+ oidcClientSecret = strings.TrimSpace(string(secretBytes)) -- } -- -- return &Config{ -diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix -index 39aac77560e1..c1811da9b6a4 100644 ---- a/pkgs/top-level/all-packages.nix -+++ b/pkgs/top-level/all-packages.nix -@@ -8912,7 +8912,9 @@ with pkgs; - - heimdall-gui = heimdall.override { enableGUI = true; }; - -- headscale = callPackage ../servers/headscale { }; -+ headscale = callPackage ../servers/headscale { -+ buildGoModule = buildGo123Module; -+ }; - - health = callPackage ../applications/misc/health { }; - --- -2.46.1 - From 7c98655a99e4c65cb877a09b5108834359745192 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 2 Dec 2024 12:14:35 +0100 Subject: [PATCH 0834/1125] Common/eza: remove workaround for 24.05 --- roles/common/programs/eza.nix | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/roles/common/programs/eza.nix b/roles/common/programs/eza.nix index f9e980d..e15b9db 100644 --- a/roles/common/programs/eza.nix +++ b/roles/common/programs/eza.nix @@ -9,10 +9,7 @@ enable = true; enableBashIntegration = true; git = true; - icons = - if config.system.nixos.release == "24.05" - then true - else "auto"; + icons = "auto"; }; xdg.configFile."eza/theme.yml".source = "${flakeSelf.inputs.eza-themes}/themes/catppuccin.yml"; }; From ff4ceecd679358830084e1d88c8e222b13b11cc0 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 2 Dec 2024 12:15:01 +0100 Subject: [PATCH 0835/1125] Server/samba: update options --- roles/server/samba.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/roles/server/samba.nix b/roles/server/samba.nix index f4fd086..85f3c9f 100755 --- a/roles/server/samba.nix +++ b/roles/server/samba.nix @@ -3,11 +3,11 @@ samba = { enable = true; openFirewall = true; - extraConfig = '' - map to guest = bad user - guest account = transmission - ''; - shares = { + settings = { + "global" = { + "map to guest" = "bad user"; + "guest account" = "transmission"; + }; "Transmission downloads" = { path = "${config.services.transmission.settings.download-dir}"; "read only" = true; From 30e89ac9d38e97c80dff7a077bda6971c5c562f4 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 3 Dec 2024 09:29:27 +0100 Subject: [PATCH 0836/1125] Flake: add pr 361364 --- flake.nix | 1 + nixpkgs-patches/pr361364.patch | 84 ++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 nixpkgs-patches/pr361364.patch diff --git a/flake.nix b/flake.nix index b4bad73..d1b5f54 100644 --- a/flake.nix +++ b/flake.nix @@ -100,6 +100,7 @@ src = nixpkgs-unstable-raw; patches = [ ./nixpkgs-patches/pr359282.patch + ./nixpkgs-patches/pr361364.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr361364.patch b/nixpkgs-patches/pr361364.patch new file mode 100644 index 0000000..71a2791 --- /dev/null +++ b/nixpkgs-patches/pr361364.patch @@ -0,0 +1,84 @@ +From 437bcf5ec44352a643ce4baecb61e2bde2128e8d Mon Sep 17 00:00:00 2001 +From: Gaetan Lepage +Date: Tue, 3 Dec 2024 08:47:26 +0100 +Subject: [PATCH] handheld-daemon: 3.6.1 -> 3.6.2 + +Diff: https://github.com/hhd-dev/hhd/compare/refs/tags/v3.6.1...v3.6.2 + +Changelog: https://github.com/hhd-dev/hhd/releases/tag/v3.6.2 +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 32 ++++++++++++--------- + 1 file changed, 19 insertions(+), 13 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index b99cd1c581476..77c898381a004 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -1,35 +1,37 @@ + { ++ lib, ++ python3Packages, + fetchFromGitHub, ++ ++ # dependencies + hidapi, + kmod, +- lib, +- python3, ++ lsof, + toybox, +- lsof + }: +-python3.pkgs.buildPythonApplication rec { ++python3Packages.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "3.6.1"; ++ version = "3.6.2"; + pyproject = true; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + rev = "refs/tags/v${version}"; +- hash = "sha256-IdpSRb66G+WzTv/BC29r2OjO1b4VdWbV6OSzOoiFAO0="; ++ hash = "sha256-W1Ap6yTryBDozKe3aO413Fu0RBul9kEA9ACUTdYyOKM="; + }; + +- propagatedBuildInputs = with python3.pkgs; [ ++ dependencies = with python3Packages; [ + evdev + hidapi + kmod ++ lsof ++ pyserial + pyyaml + rich + setuptools + toybox + xlib +- pyserial +- lsof + ]; + + # This package doesn't have upstream tests. +@@ -52,12 +54,16 @@ python3.pkgs.buildPythonApplication rec { + install -Dm644 $src/usr/lib/udev/hwdb.d/83-hhd.hwdb -t $out/lib/udev/hwdb.d/ + ''; + +- meta = with lib; { ++ meta = { + homepage = "https://github.com/hhd-dev/hhd/"; + description = "Linux support for handheld gaming devices like the Legion Go, ROG Ally, and GPD Win"; +- platforms = platforms.linux; +- license = licenses.mit; +- maintainers = with maintainers; [ appsforartists toast ]; ++ platforms = lib.platforms.linux; ++ changelog = "https://github.com/hhd-dev/hhd/releases/tag/v${version}"; ++ license = lib.licenses.mit; ++ maintainers = with lib.maintainers; [ ++ appsforartists ++ toast ++ ]; + mainProgram = "hhd"; + }; + } From aee3b502127c3d261a990a742187f842dfcb3b4d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 3 Dec 2024 10:24:34 +0100 Subject: [PATCH 0837/1125] Machines/WinMax2: enable bluetooth wake from sleep --- machines/WinMax2/configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index b367dc7..7c4ea9a 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -45,6 +45,9 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="GXTP7385:00", ATTR{power/wakeup}="disabled" ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="disabled" SUBSYSTEM=="usb", ATTR{idVendor}=="2541", ATTR{idProduct}=="9711", ATTR{remove}="1" + + # Enable wake from bluetooth + SUBSYSTEM=="usb", ATTRS{idVendor}=="8087", ATTRS{idProduct}=="0032" RUN+="/bin/sh -c 'echo enabled > /sys$env{DEVPATH}/../power/wakeup;" ''; services = { From 581f281950aac68c05fe9d272dd6662ec6d4ffc0 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 2 Dec 2024 12:30:54 +0100 Subject: [PATCH 0838/1125] Server/ssh: remove trace --- roles/server/ssh.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/ssh.nix b/roles/server/ssh.nix index d0735ae..b9b7860 100755 --- a/roles/server/ssh.nix +++ b/roles/server/ssh.nix @@ -78,6 +78,6 @@ in { }; security.pam.services.sshd.text = lib.mkDefault (lib.mkAfter '' - session optional pam_exec.so debug stdout ${builtins.trace notify.outPath notify} + session optional pam_exec.so debug stdout ${notify} ''); } From a6a4f594cff585ef9b657b60caa4c96465fa805e Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 2 Dec 2024 13:55:10 +0100 Subject: [PATCH 0839/1125] Server/ddclient: update options --- roles/server/ddclient.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/server/ddclient.nix b/roles/server/ddclient.nix index d747a30..d25d411 100755 --- a/roles/server/ddclient.nix +++ b/roles/server/ddclient.nix @@ -10,7 +10,8 @@ in { services.ddclient = { enable = true; - use = "web, web=dynamicdns.park-your-domain.com/getip"; + usev4 = "webv4, webv4=dynamicdns.park-your-domain.com/getip"; + usev6 = ""; protocol = "namecheap"; server = "dynamicdns.park-your-domain.com"; username = "toast003.xyz"; From d7f7561cbb1917b7473bcdee6091e629106c8cc1 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 5 Dec 2024 12:49:31 +0100 Subject: [PATCH 0840/1125] Kde/kate: install qt6 version --- roles/kde/programs/kate.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/kde/programs/kate.nix b/roles/kde/programs/kate.nix index 7f034fc..3e8ff36 100644 --- a/roles/kde/programs/kate.nix +++ b/roles/kde/programs/kate.nix @@ -1,5 +1,5 @@ {pkgs, ...}: { - environment.systemPackages = [pkgs.kate]; + environment.systemPackages = [pkgs.kdePackages.kate]; # Use kwrite to open text files, and kate if I'm developing stuff xdg.mime.defaultApplications = { From 22dc0e191580631ea1f43ec6ad0f239c258e5495 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 9 Dec 2024 18:34:24 +0100 Subject: [PATCH 0841/1125] Flake: fix giving patched nixpkgs the wrong arguments --- flake.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index d1b5f54..f705a0d 100644 --- a/flake.nix +++ b/flake.nix @@ -109,8 +109,8 @@ patches = []; }; # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 - nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs {self = inputs.self;}; - nixpkgs = (import "${nixpkgs-patched}/flake.nix").outputs {self = inputs.self;}; + nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs {self = inputs.nixpkgs-unstable-raw;}; + nixpkgs = (import "${nixpkgs-patched}/flake.nix").outputs {self = inputs.nixpkgs-raw;}; in { formatter.x86_64-linux = nixpkgs-unstable.legacyPackages.x86_64-linux.alejandra; devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShellNoCC { From cf666635344035021d13d70de8409d52bf69fbcb Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Dec 2024 00:27:15 +0100 Subject: [PATCH 0842/1125] Flake: add nixpkgs pr --- flake.nix | 1 + nixpkgs-patches/pr355973.patch | 213 +++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 nixpkgs-patches/pr355973.patch diff --git a/flake.nix b/flake.nix index f705a0d..6d54e22 100644 --- a/flake.nix +++ b/flake.nix @@ -101,6 +101,7 @@ patches = [ ./nixpkgs-patches/pr359282.patch ./nixpkgs-patches/pr361364.patch + ./nixpkgs-patches/pr355973.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr355973.patch b/nixpkgs-patches/pr355973.patch new file mode 100644 index 0000000..579b9d2 --- /dev/null +++ b/nixpkgs-patches/pr355973.patch @@ -0,0 +1,213 @@ +From cb9f9a1e5a51a87d59b373db7016cee1608debd5 Mon Sep 17 00:00:00 2001 +From: Atemu +Date: Thu, 14 Nov 2024 20:07:25 +0100 +Subject: [PATCH 1/2] fetchgit{,hub}: add tag argument + +It's become a common pattern to use `rev = "refs/tags/${version}"` rather than +just `rev = version` to ensure that the tag gets fetched rather than a branch +that has the same name. This has so far been done using boilerplate though, so +let's add a simple abstraction to fetch a tag instead. +--- + doc/build-helpers/fetchers.chapter.md | 5 ++++- + pkgs/build-support/fetchgit/default.nix | 5 ++++- + pkgs/build-support/fetchgithub/default.nix | 11 ++++++++--- + 3 files changed, 16 insertions(+), 5 deletions(-) + +diff --git a/doc/build-helpers/fetchers.chapter.md b/doc/build-helpers/fetchers.chapter.md +index d37a2fecaccda..567d47a1499be 100644 +--- a/doc/build-helpers/fetchers.chapter.md ++++ b/doc/build-helpers/fetchers.chapter.md +@@ -755,6 +755,9 @@ Used with Subversion. Expects `url` to a Subversion directory, `rev`, and `hash` + + Used with Git. Expects `url` to a Git repo, `rev`, and `hash`. `rev` in this case can be full the git commit id (SHA1 hash) or a tag name like `refs/tags/v1.0`. + ++If you want to fetch a tag you should pass the `tag` parameter instead of `rev` which has the same effect as setting `rev = "refs/tags"/${version}"`. ++This is safer than just setting `rev = version` w.r.t. possible branch and tag name conflicts. ++ + Additionally, the following optional arguments can be given: + + *`fetchSubmodules`* (Boolean) +@@ -833,7 +836,7 @@ A number of fetcher functions wrap part of `fetchurl` and `fetchzip`. They are m + + ## `fetchFromGitHub` {#fetchfromgithub} + +-`fetchFromGitHub` expects four arguments. `owner` is a string corresponding to the GitHub user or organization that controls this repository. `repo` corresponds to the name of the software repository. These are located at the top of every GitHub HTML page as `owner`/`repo`. `rev` corresponds to the Git commit hash or tag (e.g `v1.0`) that will be downloaded from Git. Finally, `hash` corresponds to the hash of the extracted directory. Again, other hash algorithms are also available, but `hash` is currently preferred. ++`fetchFromGitHub` expects four arguments. `owner` is a string corresponding to the GitHub user or organization that controls this repository. `repo` corresponds to the name of the software repository. These are located at the top of every GitHub HTML page as `owner`/`repo`. `rev` corresponds to the Git commit hash or tag (e.g `v1.0`) that will be downloaded from Git. If you need to fetch a tag however, you should prefer to use the `tag` parameter which achieves this in a safer way with less boilerplate. Finally, `hash` corresponds to the hash of the extracted directory. Again, other hash algorithms are also available, but `hash` is currently preferred. + + To use a different GitHub instance, use `githubBase` (defaults to `"github.com"`). + +diff --git a/pkgs/build-support/fetchgit/default.nix b/pkgs/build-support/fetchgit/default.nix +index 4c40cbcef7e16..6f4cbba982a0e 100644 +--- a/pkgs/build-support/fetchgit/default.nix ++++ b/pkgs/build-support/fetchgit/default.nix +@@ -13,7 +13,10 @@ in + lib.makeOverridable (lib.fetchers.withNormalizedHash { } ( + # NOTE Please document parameter additions or changes in + # doc/build-helpers/fetchers.chapter.md +-{ url, rev ? "HEAD", leaveDotGit ? deepClone ++{ url ++, tag ? null ++, rev ? if tag != null then "refs/tags/${tag}" else "HEAD" # FIXME fetching HEAD by default is problematic at best ++, leaveDotGit ? deepClone + , outputHash ? lib.fakeHash, outputHashAlgo ? null + , fetchSubmodules ? true, deepClone ? false + , branchName ? null +diff --git a/pkgs/build-support/fetchgithub/default.nix b/pkgs/build-support/fetchgithub/default.nix +index d27a3df7d3df7..de9912465a937 100644 +--- a/pkgs/build-support/fetchgithub/default.nix ++++ b/pkgs/build-support/fetchgithub/default.nix +@@ -1,7 +1,10 @@ + { lib, fetchgit, fetchzip }: + + lib.makeOverridable ( +-{ owner, repo, rev, name ? "source" ++{ owner, repo ++, tag ? null ++, rev ? if tag != null then "refs/tags/${tag}" else null ++, name ? "source" + , fetchSubmodules ? false, leaveDotGit ? null + , deepClone ? false, private ? false, forceFetchGit ? false + , fetchLFS ? false +@@ -11,6 +14,8 @@ lib.makeOverridable ( + , ... # For hash agility + }@args: + ++assert (lib.assertMsg (rev != null) "You must provide `fetchFromGitHub with a `rev` or `tag`."); ++ + let + + position = (if args.meta.description or null != null +@@ -24,7 +29,7 @@ let + # to indicate where derivation originates, similar to make-derivation.nix's mkDerivation + position = "${position.file}:${toString position.line}"; + }; +- passthruAttrs = removeAttrs args [ "owner" "repo" "rev" "fetchSubmodules" "forceFetchGit" "private" "githubBase" "varPrefix" ]; ++ passthruAttrs = removeAttrs args [ "owner" "repo" "tag" "rev" "fetchSubmodules" "forceFetchGit" "private" "githubBase" "varPrefix" ]; + varBase = "NIX${lib.optionalString (varPrefix != null) "_${varPrefix}"}_GITHUB_PRIVATE_"; + useFetchGit = fetchSubmodules || (leaveDotGit == true) || deepClone || forceFetchGit || fetchLFS || (sparseCheckout != []); + # We prefer fetchzip in cases we don't need submodules as the hash +@@ -53,7 +58,7 @@ let + + fetcherArgs = (if useFetchGit + then { +- inherit rev deepClone fetchSubmodules sparseCheckout fetchLFS; url = gitRepoUrl; ++ inherit tag rev deepClone fetchSubmodules sparseCheckout fetchLFS; url = gitRepoUrl; + } // lib.optionalAttrs (leaveDotGit != null) { inherit leaveDotGit; } + else { + url = "${baseUrl}/archive/${rev}.tar.gz"; + +From e9a31f51468e43aaf8df79d10dca5a3d6447877b Mon Sep 17 00:00:00 2001 +From: Atemu +Date: Wed, 4 Dec 2024 01:37:01 +0100 +Subject: [PATCH 2/2] fetchgit{,hub}: assert illegal tag + rev combinations + +It's quite a bit more complex due to this but this was asked for during review +--- + pkgs/build-support/fetchgit/default.nix | 27 ++++++++++++++++++---- + pkgs/build-support/fetchgithub/default.nix | 11 +++++---- + 2 files changed, 30 insertions(+), 8 deletions(-) + +diff --git a/pkgs/build-support/fetchgit/default.nix b/pkgs/build-support/fetchgit/default.nix +index 6f4cbba982a0e..f2b4726fef09d 100644 +--- a/pkgs/build-support/fetchgit/default.nix ++++ b/pkgs/build-support/fetchgit/default.nix +@@ -15,14 +15,14 @@ lib.makeOverridable (lib.fetchers.withNormalizedHash { } ( + # doc/build-helpers/fetchers.chapter.md + { url + , tag ? null +-, rev ? if tag != null then "refs/tags/${tag}" else "HEAD" # FIXME fetching HEAD by default is problematic at best ++, rev ? null + , leaveDotGit ? deepClone + , outputHash ? lib.fakeHash, outputHashAlgo ? null + , fetchSubmodules ? true, deepClone ? false + , branchName ? null + , sparseCheckout ? [] + , nonConeMode ? false +-, name ? urlToName url rev ++, name ? null + , # Shell code executed after the file has been fetched + # successfully. This can do things like check or transform the file. + postFetch ? "" +@@ -62,12 +62,30 @@ lib.makeOverridable (lib.fetchers.withNormalizedHash { } ( + assert deepClone -> leaveDotGit; + assert nonConeMode -> (sparseCheckout != []); + ++let ++ revWithTag = ++ let ++ warningMsg = "fetchgit requires one of either `rev` or `tag` to be provided (not both)."; ++ otherIsNull = other: lib.assertMsg (other == null) warningMsg; ++ in ++ if tag != null then ++ assert (otherIsNull rev); ++ "refs/tags/${tag}" ++ else if rev != null then ++ assert (otherIsNull tag); ++ rev ++ else ++ # FIXME fetching HEAD if no rev or tag is provided is problematic at best ++ "HEAD"; ++in ++ + if builtins.isString sparseCheckout then + # Changed to throw on 2023-06-04 + throw "Please provide directories/patterns for sparse checkout as a list of strings. Passing a (multi-line) string is not supported any more." + else + stdenvNoCC.mkDerivation { +- inherit name; ++ name = if name != null then name else urlToName url revWithTag; ++ + builder = ./builder.sh; + fetcher = ./nix-prefetch-git; + +@@ -82,7 +100,8 @@ stdenvNoCC.mkDerivation { + # > from standard in as a newline-delimited list instead of from the arguments. + sparseCheckout = builtins.concatStringsSep "\n" sparseCheckout; + +- inherit url rev leaveDotGit fetchLFS fetchSubmodules deepClone branchName nonConeMode postFetch; ++ inherit url leaveDotGit fetchLFS fetchSubmodules deepClone branchName nonConeMode postFetch; ++ rev = revWithTag; + + postHook = if netrcPhase == null then null else '' + ${netrcPhase} +diff --git a/pkgs/build-support/fetchgithub/default.nix b/pkgs/build-support/fetchgithub/default.nix +index de9912465a937..f80e012955336 100644 +--- a/pkgs/build-support/fetchgithub/default.nix ++++ b/pkgs/build-support/fetchgithub/default.nix +@@ -3,7 +3,7 @@ + lib.makeOverridable ( + { owner, repo + , tag ? null +-, rev ? if tag != null then "refs/tags/${tag}" else null ++, rev ? null + , name ? "source" + , fetchSubmodules ? false, leaveDotGit ? null + , deepClone ? false, private ? false, forceFetchGit ? false +@@ -14,13 +14,16 @@ lib.makeOverridable ( + , ... # For hash agility + }@args: + +-assert (lib.assertMsg (rev != null) "You must provide `fetchFromGitHub with a `rev` or `tag`."); ++assert (lib.assertMsg (lib.xor (tag == null) (rev == null)) "fetchFromGitHub requires one of either `rev` or `tag` to be provided (not both)."); + + let + + position = (if args.meta.description or null != null + then builtins.unsafeGetAttrPos "description" args.meta +- else builtins.unsafeGetAttrPos "rev" args ++ else if tag != null then ++ builtins.unsafeGetAttrPos "tag" args ++ else ++ builtins.unsafeGetAttrPos "rev" args + ); + baseUrl = "https://${githubBase}/${owner}/${repo}"; + newMeta = meta // { +@@ -61,7 +64,7 @@ let + inherit tag rev deepClone fetchSubmodules sparseCheckout fetchLFS; url = gitRepoUrl; + } // lib.optionalAttrs (leaveDotGit != null) { inherit leaveDotGit; } + else { +- url = "${baseUrl}/archive/${rev}.tar.gz"; ++ url = "${baseUrl}/archive/${if tag != null then "refs/tags/${tag}" else rev}.tar.gz"; + + passthru = { + inherit gitRepoUrl; From 818bb17a3f962688b3910b51ad629d19a422f3cf Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Dec 2024 00:27:27 +0100 Subject: [PATCH 0843/1125] Flake: update hhd nixpkgs pr --- nixpkgs-patches/pr361364.patch | 133 +++++++++++++++++++++++++++++---- 1 file changed, 118 insertions(+), 15 deletions(-) diff --git a/nixpkgs-patches/pr361364.patch b/nixpkgs-patches/pr361364.patch index 71a2791..74a7942 100644 --- a/nixpkgs-patches/pr361364.patch +++ b/nixpkgs-patches/pr361364.patch @@ -1,33 +1,36 @@ -From 437bcf5ec44352a643ce4baecb61e2bde2128e8d Mon Sep 17 00:00:00 2001 +From c94ae7a159eb8cd86f46ca1ea81dbdca651510f4 Mon Sep 17 00:00:00 2001 From: Gaetan Lepage Date: Tue, 3 Dec 2024 08:47:26 +0100 -Subject: [PATCH] handheld-daemon: 3.6.1 -> 3.6.2 +Subject: [PATCH 1/2] handheld-daemon: 3.6.1 -> 3.6.2 Diff: https://github.com/hhd-dev/hhd/compare/refs/tags/v3.6.1...v3.6.2 Changelog: https://github.com/hhd-dev/hhd/releases/tag/v3.6.2 --- - pkgs/by-name/ha/handheld-daemon/package.nix | 32 ++++++++++++--------- - 1 file changed, 19 insertions(+), 13 deletions(-) + pkgs/by-name/ha/handheld-daemon/package.nix | 87 ++++++++++++++------- + 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index b99cd1c581476..77c898381a004 100644 +index b99cd1c581476..6b5965e06e645 100644 --- a/pkgs/by-name/ha/handheld-daemon/package.nix +++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -1,35 +1,37 @@ +@@ -1,63 +1,90 @@ { + lib, + python3Packages, fetchFromGitHub, + + # dependencies ++ systemd, hidapi, ++ coreutils, kmod, - lib, - python3, -+ lsof, - toybox, +- toybox, - lsof ++ dbus, ++ lsof, }: -python3.pkgs.buildPythonApplication rec { +python3Packages.buildPythonApplication rec { @@ -39,29 +42,79 @@ index b99cd1c581476..77c898381a004 100644 src = fetchFromGitHub { owner = "hhd-dev"; repo = "hhd"; - rev = "refs/tags/v${version}"; +- rev = "refs/tags/v${version}"; - hash = "sha256-IdpSRb66G+WzTv/BC29r2OjO1b4VdWbV6OSzOoiFAO0="; ++ tag = "v${version}"; + hash = "sha256-W1Ap6yTryBDozKe3aO413Fu0RBul9kEA9ACUTdYyOKM="; }; - propagatedBuildInputs = with python3.pkgs; [ ++ # This package relies on several programs expected to be on the user's PATH. ++ # We take a more reproducible approach by patching the absolute path to each of these required ++ # binaries. ++ postPatch = '' ++ substituteInPlace src/hhd/controller/lib/hid.py \ ++ --replace-fail "libhidapi" "${lib.getLib hidapi}/lib/libhidapi" ++ ++ substituteInPlace src/hhd/controller/lib/hide.py \ ++ --replace-fail "/bin/chmod" "${lib.getExe' coreutils "chmod"}" \ ++ --replace-fail "udevadm" "${lib.getExe' systemd "udevadm"}" ++ ++ substituteInPlace src/hhd/controller/physical/evdev.py \ ++ --replace-fail "udevadm" "${lib.getExe' systemd "udevadm"}" ++ ++ substituteInPlace src/hhd/controller/physical/imu.py \ ++ --replace-fail '"modprobe' '"${lib.getExe' kmod "modprobe"}' ++ ++ substituteInPlace src/hhd/device/oxp/serial.py \ ++ --replace-fail "udevadm" "${lib.getExe' systemd "udevadm"}" ++ ++ substituteInPlace src/hhd/plugins/overlay/systemd.py \ ++ --replace-fail "dbus-monitor" "${lib.getExe' dbus "dbus-monitor"}" \ ++ --replace-fail "systemd-inhibit" "${lib.getExe' systemd "systemd-inhibit"}" ++ ++ substituteInPlace src/hhd/plugins/overlay/x11.py \ ++ --replace-fail "lsof" "${lib.getExe lsof}" ++ ++ substituteInPlace src/hhd/plugins/plugin.py \ ++ --replace-fail '"id"' '"${lib.getExe' coreutils "id"}"' ++ ''; ++ ++ build-system = with python3Packages; [ ++ setuptools ++ ]; ++ + dependencies = with python3Packages; [ evdev - hidapi - kmod -+ lsof +- hidapi +- kmod + pyserial pyyaml rich setuptools - toybox +- toybox xlib - pyserial - lsof ]; # This package doesn't have upstream tests. -@@ -52,12 +54,16 @@ python3.pkgs.buildPythonApplication rec { + doCheck = false; + +- postPatch = '' +- # handheld-daemon contains a fork of the python module `hid`, so this hook +- # is borrowed from the `hid` derivation. +- hidapi=${hidapi}/lib/ +- test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } +- sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py +- +- # The generated udev rules point to /bin/chmod, which does not exist in NixOS +- chmod=${toybox}/bin/chmod +- sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py +- ''; +- + postInstall = '' + install -Dm644 $src/usr/lib/udev/rules.d/83-hhd.rules -t $out/lib/udev/rules.d/ install -Dm644 $src/usr/lib/udev/hwdb.d/83-hhd.hwdb -t $out/lib/udev/hwdb.d/ ''; @@ -74,7 +127,7 @@ index b99cd1c581476..77c898381a004 100644 - maintainers = with maintainers; [ appsforartists toast ]; + platforms = lib.platforms.linux; + changelog = "https://github.com/hhd-dev/hhd/releases/tag/v${version}"; -+ license = lib.licenses.mit; ++ license = lib.licenses.gpl3Only; + maintainers = with lib.maintainers; [ + appsforartists + toast @@ -82,3 +135,53 @@ index b99cd1c581476..77c898381a004 100644 mainProgram = "hhd"; }; } + +From 2cf68f2bf37655d730202f2e551b40172181801c Mon Sep 17 00:00:00 2001 +From: Gaetan Lepage +Date: Mon, 9 Dec 2024 10:26:53 +0100 +Subject: [PATCH 2/2] handheld-daemon: 3.6.2 -> 3.7.0 + +Diff: https://github.com/hhd-dev/hhd/compare/None...v3.7.0 + +Changelog: https://github.com/hhd-dev/hhd/releases/tag/v3.7.0 +--- + pkgs/by-name/ha/handheld-daemon/package.nix | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 6b5965e06e645..2fe0c45eca77f 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -8,19 +8,20 @@ + hidapi, + coreutils, + kmod, ++ efibootmgr, + dbus, + lsof, + }: + python3Packages.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "3.6.2"; ++ version = "3.7.0"; + pyproject = true; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + tag = "v${version}"; +- hash = "sha256-W1Ap6yTryBDozKe3aO413Fu0RBul9kEA9ACUTdYyOKM="; ++ hash = "sha256-DkVdYnSEeaNZj76lhdU+9Pl0yzam2A2QGa3aHCmSHEA="; + }; + + # This package relies on several programs expected to be on the user's PATH. +@@ -40,6 +41,9 @@ python3Packages.buildPythonApplication rec { + substituteInPlace src/hhd/controller/physical/imu.py \ + --replace-fail '"modprobe' '"${lib.getExe' kmod "modprobe"}' + ++ substituteInPlace src/hhd/plugins/overlay/power.py \ ++ --replace-fail '"efibootmgr"' '"${lib.getExe' efibootmgr "id"}"' ++ + substituteInPlace src/hhd/device/oxp/serial.py \ + --replace-fail "udevadm" "${lib.getExe' systemd "udevadm"}" + From 45daaddfb6a71aef6fa835aaecb3a0a35f5f0a79 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Dec 2024 00:28:17 +0100 Subject: [PATCH 0844/1125] Revert "Machines/WinMax2: enable bluetooth wake from sleep" This reverts commit aee3b502127c3d261a990a742187f842dfcb3b4d. Turns out this makes it so that I get instant wakeup after sleep --- machines/WinMax2/configuration.nix | 3 --- 1 file changed, 3 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 7c4ea9a..b367dc7 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -45,9 +45,6 @@ ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="GXTP7385:00", ATTR{power/wakeup}="disabled" ACTION=="add", SUBSYSTEM=="i2c", ATTR{name}=="PNP0C50:00", ATTR{power/wakeup}="disabled" SUBSYSTEM=="usb", ATTR{idVendor}=="2541", ATTR{idProduct}=="9711", ATTR{remove}="1" - - # Enable wake from bluetooth - SUBSYSTEM=="usb", ATTRS{idVendor}=="8087", ATTRS{idProduct}=="0032" RUN+="/bin/sh -c 'echo enabled > /sys$env{DEVPATH}/../power/wakeup;" ''; services = { From 16d61d8d737e8056d163a7fa77ab9aa065979a2d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Dec 2024 00:35:17 +0100 Subject: [PATCH 0845/1125] Machines/WinMax2: remove now uneeded steam HiDPI workaround --- machines/WinMax2/configuration.nix | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index b367dc7..e5a8782 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -102,18 +102,6 @@ # services.printing.enable = true; home-manager.sharedModules = [ { - # Steam's hidpi support is bugged so it needds to be hardcoded - xdg.desktopEntries = { - steam-noScaling = { - name = "Steam (2x scale)"; - exec = "env STEAM_FORCE_DESKTOPUI_SCALING=2 steam %U"; - icon = "steam"; - categories = ["Network" "FileTransfer" "Game"]; - comment = "Application for managing and playing games on Steam"; - prefersNonDefaultGPU = true; - settings.X-KDE-RunOnDiscreteGpu = "true"; - }; - }; programs.plasma.input.keyboard.layouts = lib.mkForce [{layout = "us";} {layout = "es";}]; } ]; From 49e920ac97ecf2db3f7e8d7cbdaa2843b3b6bfd2 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Dec 2024 11:08:59 +0100 Subject: [PATCH 0846/1125] Flake: update nur --- flake.lock | 69 +++++++++++++++++++++++++++++++-- roles/common/configuration.nix | 2 +- roles/gaming/programs/rpcs3.nix | 4 +- 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index fb48812..e8514aa 100644 --- a/flake.lock +++ b/flake.lock @@ -70,6 +70,27 @@ "type": "github" } }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "nur", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733312601, + "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems_2" @@ -428,6 +449,22 @@ "type": "github" } }, + "nixpkgs": { + "locked": { + "lastModified": 1733581040, + "narHash": "sha256-Qn3nPMSopRQJgmvHzVqPcE3I03zJyl8cSbgnnltfFDY=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "22c3f2cf41a0e70184334a958e6b124fb0ce3e01", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs-raw": { "locked": { "lastModified": 1732981179, @@ -459,12 +496,17 @@ } }, "nur": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs", + "treefmt-nix": "treefmt-nix" + }, "locked": { - "lastModified": 1732784817, - "narHash": "sha256-I37vvlS+qk4TMzMouw9kJCilahl8+fOjnCWsBJmPv+U=", + "lastModified": 1733824207, + "narHash": "sha256-qGXcFigGMSFba29CtCnTgf/c9h+Dzh6yHcXTK16jXJ8=", "owner": "nix-community", "repo": "NUR", - "rev": "7c412613e5ed3d49f2e198c0b0187add6b897b3d", + "rev": "f1ea8bb704f71d74dcc885d6bd149b5b661bb858", "type": "github" }, "original": { @@ -595,6 +637,27 @@ "repo": "default", "type": "github" } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nur", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733222881, + "narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "49717b5af6f80172275d47a418c9719a31a78b53", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } } }, "root": "root", diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index af07bef..7024b74 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -5,7 +5,7 @@ flakeSelf, ... }: { - imports = [flakeSelf.inputs.nur.nixosModules.nur]; + imports = [flakeSelf.inputs.nur.modules.nixos.default]; environment = { # As of the 1st of May 2023, the default packages are nano, perl, rsync and strace # I don't need any of them, so I just empty the list diff --git a/roles/gaming/programs/rpcs3.nix b/roles/gaming/programs/rpcs3.nix index ef1be51..b8c48c0 100644 --- a/roles/gaming/programs/rpcs3.nix +++ b/roles/gaming/programs/rpcs3.nix @@ -1,5 +1,5 @@ -{config, ...}: { - environment.systemPackages = with config; [ +{pkgs, ...}: { + environment.systemPackages = with pkgs; [ nur.repos.ataraxiasjel.rpcs3 ]; # Compiling RPCS3 takes quite a while From 5eab2e1cccca51abf53a5d1d4efb248a9d0ef0ea Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Dec 2024 11:10:33 +0100 Subject: [PATCH 0847/1125] Flake: update lock file --- flake.lock | 102 ++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/flake.lock b/flake.lock index e8514aa..8a596eb 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1732703064, - "narHash": "sha256-n8XOmn0WGtQhAMJKTnhL/3ttV2ZahPRf6gtlqZ6R4QE=", + "lastModified": 1733001911, + "narHash": "sha256-uX/9m0TbdhEzuWA0muM5mI/AaWcLiDLjCCyu5Qr9MRk=", "owner": "catppuccin", "repo": "nix", - "rev": "2e2bdecf0bae287d74947cd5cf967c5c499c23c1", + "rev": "a817009ebfd2cca7f70a77884e5098d0a8c83f8e", "type": "github" }, "original": { @@ -41,11 +41,11 @@ "eza-themes": { "flake": false, "locked": { - "lastModified": 1730050654, - "narHash": "sha256-Gs21+A/to2AqjQsqMlWeOuSowYPOuSZ3fK6LRdBPUmI=", + "lastModified": 1733264582, + "narHash": "sha256-PJ0zSmAiS2iK3bW/HJ7YtYjjLvkgBSAhbbMezjHU0yA=", "owner": "eza-community", "repo": "eza-themes", - "rev": "74be26bbd2ce76b29c37250a2fb7cb5d6644c964", + "rev": "78601bf47075a8b3681f7b4a7fbe5e258ad469f8", "type": "github" }, "original": { @@ -203,11 +203,11 @@ ] }, "locked": { - "lastModified": 1732482255, - "narHash": "sha256-GUffLwzawz5WRVfWaWCg78n/HrBJrOG7QadFY6rtV8A=", + "lastModified": 1733754861, + "narHash": "sha256-3JKzIou54yjiMVmvgdJwopekEvZxX3JDT8DpKZs4oXY=", "owner": "nix-community", "repo": "home-manager", - "rev": "a9953635d7f34e7358d5189751110f87e3ac17da", + "rev": "9ebaa80a227eaca9c87c53ed515ade013bc2bca9", "type": "github" }, "original": { @@ -223,11 +223,11 @@ ] }, "locked": { - "lastModified": 1733050161, - "narHash": "sha256-lYnT+EYE47f5yY3KS/Kd4pJ6CO9fhCqumkYYkQ3TK20=", + "lastModified": 1733572789, + "narHash": "sha256-zjO6m5BqxXIyjrnUziAzk4+T4VleqjstNudSqWcpsHI=", "owner": "nix-community", "repo": "home-manager", - "rev": "62d536255879be574ebfe9b87c4ac194febf47c5", + "rev": "c7ffc9727d115e433fd884a62dc164b587ff651d", "type": "github" }, "original": { @@ -245,11 +245,11 @@ ] }, "locked": { - "lastModified": 1732739177, - "narHash": "sha256-iL32+TA/8geCzcL1r3uthrH/GPvbUak5QE++WJUkaiI=", + "lastModified": 1733762021, + "narHash": "sha256-QAc+GvjJXLyp7oy2Vt1LEjYnq6UXPAmncwpL5aZUsUM=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "8d7b2149e618696d5100c2683af1ffa893f02a75", + "rev": "f2180c6fcfca4eaecd79eadba0b5874e9a1c70c1", "type": "github" }, "original": { @@ -261,11 +261,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1732112222, - "narHash": "sha256-H7GN4++a4vE49SUNojZx+FSk4mmpb2ifJUtJMJHProI=", - "rev": "66f6dbda32959dd5cf3a9aaba15af72d037ab7ff", + "lastModified": 1733740102, + "narHash": "sha256-zIm58tETZ5Z6Scsjrn9rPISLzH4kWb2MIoC/jdii5ts=", + "rev": "369e3f82f066866b4d75abc5fc66e5b8e2149b4c", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/66f6dbda32959dd5cf3a9aaba15af72d037ab7ff.tar.gz?rev=66f6dbda32959dd5cf3a9aaba15af72d037ab7ff" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/369e3f82f066866b4d75abc5fc66e5b8e2149b4c.tar.gz?rev=369e3f82f066866b4d75abc5fc66e5b8e2149b4c" }, "original": { "type": "tarball", @@ -284,11 +284,11 @@ ] }, "locked": { - "lastModified": 1732603698, - "narHash": "sha256-Jw2MhzgCCrKV2MJytehG0cCLIAosBX71p8qmQ6XQlR4=", - "rev": "15b999f9c958c475f71fb8c543b9fc2f36ae8730", + "lastModified": 1733522213, + "narHash": "sha256-H+Pk19MzvI/TAbXWimUPZAoKkD56OSyxJBm8lVIA5n0=", + "rev": "c374ebf5548c7b6d4bf884369a5b6879cfc916ea", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/15b999f9c958c475f71fb8c543b9fc2f36ae8730.tar.gz?rev=15b999f9c958c475f71fb8c543b9fc2f36ae8730" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/c374ebf5548c7b6d4bf884369a5b6879cfc916ea.tar.gz?rev=c374ebf5548c7b6d4bf884369a5b6879cfc916ea" }, "original": { "type": "tarball", @@ -307,11 +307,11 @@ ] }, "locked": { - "lastModified": 1732603698, - "narHash": "sha256-Jw2MhzgCCrKV2MJytehG0cCLIAosBX71p8qmQ6XQlR4=", - "rev": "15b999f9c958c475f71fb8c543b9fc2f36ae8730", + "lastModified": 1733522213, + "narHash": "sha256-H+Pk19MzvI/TAbXWimUPZAoKkD56OSyxJBm8lVIA5n0=", + "rev": "c374ebf5548c7b6d4bf884369a5b6879cfc916ea", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/15b999f9c958c475f71fb8c543b9fc2f36ae8730.tar.gz?rev=15b999f9c958c475f71fb8c543b9fc2f36ae8730" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/c374ebf5548c7b6d4bf884369a5b6879cfc916ea.tar.gz?rev=c374ebf5548c7b6d4bf884369a5b6879cfc916ea" }, "original": { "type": "tarball", @@ -320,11 +320,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1732304879, - "narHash": "sha256-/DOW8VadE//HA6tuV2++NowYWi7Wa/FmJHXRJoTQnfQ=", + "lastModified": 1733345341, + "narHash": "sha256-8S58zrdpzGhax6tmn1i+R3AA0N9DJMu5FQI8JkA0NNU=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "c84579946c03c996916be0fb6e1340f444c277af", + "rev": "ebb0be49fc381112ff37726c6dd6df4df2ef5a1b", "type": "github" }, "original": { @@ -378,11 +378,11 @@ ] }, "locked": { - "lastModified": 1732519917, - "narHash": "sha256-AGXhwHdJV0q/WNgqwrR2zriubLr785b02FphaBtyt1Q=", + "lastModified": 1733629314, + "narHash": "sha256-U0vivjQFAwjNDYt49Krevs1murX9hKBFe2Ye0cHpgbU=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f4a5ca5771ba9ca31ad24a62c8d511a405303436", + "rev": "f1e477a7dd11e27e7f98b646349cd66bbabf2fb8", "type": "github" }, "original": { @@ -398,11 +398,11 @@ ] }, "locked": { - "lastModified": 1732519917, - "narHash": "sha256-AGXhwHdJV0q/WNgqwrR2zriubLr785b02FphaBtyt1Q=", + "lastModified": 1733629314, + "narHash": "sha256-U0vivjQFAwjNDYt49Krevs1murX9hKBFe2Ye0cHpgbU=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f4a5ca5771ba9ca31ad24a62c8d511a405303436", + "rev": "f1e477a7dd11e27e7f98b646349cd66bbabf2fb8", "type": "github" }, "original": { @@ -420,11 +420,11 @@ ] }, "locked": { - "lastModified": 1732758830, - "narHash": "sha256-bmMRjp4U3RDvLuwOWXMTHitMBMrmmpzP4x0dckJMZD4=", + "lastModified": 1733709556, + "narHash": "sha256-u0ll0DDrKlO7tiLGGtmphv3wFy5ReDuf0USo/OlfROU=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "09c3d43938e7b535ecada974759e9ed84ee91235", + "rev": "8d11f147df83fe137d3d94f6f3646e3a52bec855", "type": "github" }, "original": { @@ -435,11 +435,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1732483221, - "narHash": "sha256-kF6rDeCshoCgmQz+7uiuPdREVFuzhIorGOoPXMalL2U=", + "lastModified": 1733481457, + "narHash": "sha256-IS3bxa4N1VMSh3/P6vhEAHQZecQ3oAlKCDvzCQSO5Is=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "45348ad6fb8ac0e8415f6e5e96efe47dd7f39405", + "rev": "e563803af3526852b6b1d77107a81908c66a9fcf", "type": "github" }, "original": { @@ -467,11 +467,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1732981179, - "narHash": "sha256-F7thesZPvAMSwjRu0K8uFshTk3ZZSNAsXTIFvXBT+34=", + "lastModified": 1733550349, + "narHash": "sha256-NcGumB4Lr6KSDq+nIqXtNA8QwAQKDSZT7N9OTGWbTrs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "62c435d93bf046a5396f3016472e8f7c8e2aed65", + "rev": "e2605d0744c2417b09f8bf850dfca42fcf537d34", "type": "github" }, "original": { @@ -482,11 +482,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1732521221, - "narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=", + "lastModified": 1733581040, + "narHash": "sha256-Qn3nPMSopRQJgmvHzVqPcE3I03zJyl8cSbgnnltfFDY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4633a7c72337ea8fd23a4f2ba3972865e3ec685d", + "rev": "22c3f2cf41a0e70184334a958e6b124fb0ce3e01", "type": "github" }, "original": { @@ -525,11 +525,11 @@ ] }, "locked": { - "lastModified": 1732639391, - "narHash": "sha256-kFtXjoCIqx9xe0ZryPXpqS6l/HVg71aNcuL8Y5e8+pI=", + "lastModified": 1733578387, + "narHash": "sha256-XkMZGeqg0GCRoSXvMcaHP7bdvWPRZxCK1sw1ASsc16E=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "06e3209d11797d9c741e25df06ab61048746bf93", + "rev": "2a64e173f1effdcc86e25cba0601e8feedf89115", "type": "github" }, "original": { From 9aabffc52a6c030fde527dcef57f570895060789 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Dec 2024 11:13:29 +0100 Subject: [PATCH 0848/1125] Flake: remove uneeded nixpkgs patches --- flake.nix | 2 - nixpkgs-patches/pr355973.patch | 213 --------------------------------- nixpkgs-patches/pr359282.patch | 92 -------------- 3 files changed, 307 deletions(-) delete mode 100644 nixpkgs-patches/pr355973.patch delete mode 100644 nixpkgs-patches/pr359282.patch diff --git a/flake.nix b/flake.nix index 6d54e22..7da03e7 100644 --- a/flake.nix +++ b/flake.nix @@ -99,9 +99,7 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/pr359282.patch ./nixpkgs-patches/pr361364.patch - ./nixpkgs-patches/pr355973.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr355973.patch b/nixpkgs-patches/pr355973.patch deleted file mode 100644 index 579b9d2..0000000 --- a/nixpkgs-patches/pr355973.patch +++ /dev/null @@ -1,213 +0,0 @@ -From cb9f9a1e5a51a87d59b373db7016cee1608debd5 Mon Sep 17 00:00:00 2001 -From: Atemu -Date: Thu, 14 Nov 2024 20:07:25 +0100 -Subject: [PATCH 1/2] fetchgit{,hub}: add tag argument - -It's become a common pattern to use `rev = "refs/tags/${version}"` rather than -just `rev = version` to ensure that the tag gets fetched rather than a branch -that has the same name. This has so far been done using boilerplate though, so -let's add a simple abstraction to fetch a tag instead. ---- - doc/build-helpers/fetchers.chapter.md | 5 ++++- - pkgs/build-support/fetchgit/default.nix | 5 ++++- - pkgs/build-support/fetchgithub/default.nix | 11 ++++++++--- - 3 files changed, 16 insertions(+), 5 deletions(-) - -diff --git a/doc/build-helpers/fetchers.chapter.md b/doc/build-helpers/fetchers.chapter.md -index d37a2fecaccda..567d47a1499be 100644 ---- a/doc/build-helpers/fetchers.chapter.md -+++ b/doc/build-helpers/fetchers.chapter.md -@@ -755,6 +755,9 @@ Used with Subversion. Expects `url` to a Subversion directory, `rev`, and `hash` - - Used with Git. Expects `url` to a Git repo, `rev`, and `hash`. `rev` in this case can be full the git commit id (SHA1 hash) or a tag name like `refs/tags/v1.0`. - -+If you want to fetch a tag you should pass the `tag` parameter instead of `rev` which has the same effect as setting `rev = "refs/tags"/${version}"`. -+This is safer than just setting `rev = version` w.r.t. possible branch and tag name conflicts. -+ - Additionally, the following optional arguments can be given: - - *`fetchSubmodules`* (Boolean) -@@ -833,7 +836,7 @@ A number of fetcher functions wrap part of `fetchurl` and `fetchzip`. They are m - - ## `fetchFromGitHub` {#fetchfromgithub} - --`fetchFromGitHub` expects four arguments. `owner` is a string corresponding to the GitHub user or organization that controls this repository. `repo` corresponds to the name of the software repository. These are located at the top of every GitHub HTML page as `owner`/`repo`. `rev` corresponds to the Git commit hash or tag (e.g `v1.0`) that will be downloaded from Git. Finally, `hash` corresponds to the hash of the extracted directory. Again, other hash algorithms are also available, but `hash` is currently preferred. -+`fetchFromGitHub` expects four arguments. `owner` is a string corresponding to the GitHub user or organization that controls this repository. `repo` corresponds to the name of the software repository. These are located at the top of every GitHub HTML page as `owner`/`repo`. `rev` corresponds to the Git commit hash or tag (e.g `v1.0`) that will be downloaded from Git. If you need to fetch a tag however, you should prefer to use the `tag` parameter which achieves this in a safer way with less boilerplate. Finally, `hash` corresponds to the hash of the extracted directory. Again, other hash algorithms are also available, but `hash` is currently preferred. - - To use a different GitHub instance, use `githubBase` (defaults to `"github.com"`). - -diff --git a/pkgs/build-support/fetchgit/default.nix b/pkgs/build-support/fetchgit/default.nix -index 4c40cbcef7e16..6f4cbba982a0e 100644 ---- a/pkgs/build-support/fetchgit/default.nix -+++ b/pkgs/build-support/fetchgit/default.nix -@@ -13,7 +13,10 @@ in - lib.makeOverridable (lib.fetchers.withNormalizedHash { } ( - # NOTE Please document parameter additions or changes in - # doc/build-helpers/fetchers.chapter.md --{ url, rev ? "HEAD", leaveDotGit ? deepClone -+{ url -+, tag ? null -+, rev ? if tag != null then "refs/tags/${tag}" else "HEAD" # FIXME fetching HEAD by default is problematic at best -+, leaveDotGit ? deepClone - , outputHash ? lib.fakeHash, outputHashAlgo ? null - , fetchSubmodules ? true, deepClone ? false - , branchName ? null -diff --git a/pkgs/build-support/fetchgithub/default.nix b/pkgs/build-support/fetchgithub/default.nix -index d27a3df7d3df7..de9912465a937 100644 ---- a/pkgs/build-support/fetchgithub/default.nix -+++ b/pkgs/build-support/fetchgithub/default.nix -@@ -1,7 +1,10 @@ - { lib, fetchgit, fetchzip }: - - lib.makeOverridable ( --{ owner, repo, rev, name ? "source" -+{ owner, repo -+, tag ? null -+, rev ? if tag != null then "refs/tags/${tag}" else null -+, name ? "source" - , fetchSubmodules ? false, leaveDotGit ? null - , deepClone ? false, private ? false, forceFetchGit ? false - , fetchLFS ? false -@@ -11,6 +14,8 @@ lib.makeOverridable ( - , ... # For hash agility - }@args: - -+assert (lib.assertMsg (rev != null) "You must provide `fetchFromGitHub with a `rev` or `tag`."); -+ - let - - position = (if args.meta.description or null != null -@@ -24,7 +29,7 @@ let - # to indicate where derivation originates, similar to make-derivation.nix's mkDerivation - position = "${position.file}:${toString position.line}"; - }; -- passthruAttrs = removeAttrs args [ "owner" "repo" "rev" "fetchSubmodules" "forceFetchGit" "private" "githubBase" "varPrefix" ]; -+ passthruAttrs = removeAttrs args [ "owner" "repo" "tag" "rev" "fetchSubmodules" "forceFetchGit" "private" "githubBase" "varPrefix" ]; - varBase = "NIX${lib.optionalString (varPrefix != null) "_${varPrefix}"}_GITHUB_PRIVATE_"; - useFetchGit = fetchSubmodules || (leaveDotGit == true) || deepClone || forceFetchGit || fetchLFS || (sparseCheckout != []); - # We prefer fetchzip in cases we don't need submodules as the hash -@@ -53,7 +58,7 @@ let - - fetcherArgs = (if useFetchGit - then { -- inherit rev deepClone fetchSubmodules sparseCheckout fetchLFS; url = gitRepoUrl; -+ inherit tag rev deepClone fetchSubmodules sparseCheckout fetchLFS; url = gitRepoUrl; - } // lib.optionalAttrs (leaveDotGit != null) { inherit leaveDotGit; } - else { - url = "${baseUrl}/archive/${rev}.tar.gz"; - -From e9a31f51468e43aaf8df79d10dca5a3d6447877b Mon Sep 17 00:00:00 2001 -From: Atemu -Date: Wed, 4 Dec 2024 01:37:01 +0100 -Subject: [PATCH 2/2] fetchgit{,hub}: assert illegal tag + rev combinations - -It's quite a bit more complex due to this but this was asked for during review ---- - pkgs/build-support/fetchgit/default.nix | 27 ++++++++++++++++++---- - pkgs/build-support/fetchgithub/default.nix | 11 +++++---- - 2 files changed, 30 insertions(+), 8 deletions(-) - -diff --git a/pkgs/build-support/fetchgit/default.nix b/pkgs/build-support/fetchgit/default.nix -index 6f4cbba982a0e..f2b4726fef09d 100644 ---- a/pkgs/build-support/fetchgit/default.nix -+++ b/pkgs/build-support/fetchgit/default.nix -@@ -15,14 +15,14 @@ lib.makeOverridable (lib.fetchers.withNormalizedHash { } ( - # doc/build-helpers/fetchers.chapter.md - { url - , tag ? null --, rev ? if tag != null then "refs/tags/${tag}" else "HEAD" # FIXME fetching HEAD by default is problematic at best -+, rev ? null - , leaveDotGit ? deepClone - , outputHash ? lib.fakeHash, outputHashAlgo ? null - , fetchSubmodules ? true, deepClone ? false - , branchName ? null - , sparseCheckout ? [] - , nonConeMode ? false --, name ? urlToName url rev -+, name ? null - , # Shell code executed after the file has been fetched - # successfully. This can do things like check or transform the file. - postFetch ? "" -@@ -62,12 +62,30 @@ lib.makeOverridable (lib.fetchers.withNormalizedHash { } ( - assert deepClone -> leaveDotGit; - assert nonConeMode -> (sparseCheckout != []); - -+let -+ revWithTag = -+ let -+ warningMsg = "fetchgit requires one of either `rev` or `tag` to be provided (not both)."; -+ otherIsNull = other: lib.assertMsg (other == null) warningMsg; -+ in -+ if tag != null then -+ assert (otherIsNull rev); -+ "refs/tags/${tag}" -+ else if rev != null then -+ assert (otherIsNull tag); -+ rev -+ else -+ # FIXME fetching HEAD if no rev or tag is provided is problematic at best -+ "HEAD"; -+in -+ - if builtins.isString sparseCheckout then - # Changed to throw on 2023-06-04 - throw "Please provide directories/patterns for sparse checkout as a list of strings. Passing a (multi-line) string is not supported any more." - else - stdenvNoCC.mkDerivation { -- inherit name; -+ name = if name != null then name else urlToName url revWithTag; -+ - builder = ./builder.sh; - fetcher = ./nix-prefetch-git; - -@@ -82,7 +100,8 @@ stdenvNoCC.mkDerivation { - # > from standard in as a newline-delimited list instead of from the arguments. - sparseCheckout = builtins.concatStringsSep "\n" sparseCheckout; - -- inherit url rev leaveDotGit fetchLFS fetchSubmodules deepClone branchName nonConeMode postFetch; -+ inherit url leaveDotGit fetchLFS fetchSubmodules deepClone branchName nonConeMode postFetch; -+ rev = revWithTag; - - postHook = if netrcPhase == null then null else '' - ${netrcPhase} -diff --git a/pkgs/build-support/fetchgithub/default.nix b/pkgs/build-support/fetchgithub/default.nix -index de9912465a937..f80e012955336 100644 ---- a/pkgs/build-support/fetchgithub/default.nix -+++ b/pkgs/build-support/fetchgithub/default.nix -@@ -3,7 +3,7 @@ - lib.makeOverridable ( - { owner, repo - , tag ? null --, rev ? if tag != null then "refs/tags/${tag}" else null -+, rev ? null - , name ? "source" - , fetchSubmodules ? false, leaveDotGit ? null - , deepClone ? false, private ? false, forceFetchGit ? false -@@ -14,13 +14,16 @@ lib.makeOverridable ( - , ... # For hash agility - }@args: - --assert (lib.assertMsg (rev != null) "You must provide `fetchFromGitHub with a `rev` or `tag`."); -+assert (lib.assertMsg (lib.xor (tag == null) (rev == null)) "fetchFromGitHub requires one of either `rev` or `tag` to be provided (not both)."); - - let - - position = (if args.meta.description or null != null - then builtins.unsafeGetAttrPos "description" args.meta -- else builtins.unsafeGetAttrPos "rev" args -+ else if tag != null then -+ builtins.unsafeGetAttrPos "tag" args -+ else -+ builtins.unsafeGetAttrPos "rev" args - ); - baseUrl = "https://${githubBase}/${owner}/${repo}"; - newMeta = meta // { -@@ -61,7 +64,7 @@ let - inherit tag rev deepClone fetchSubmodules sparseCheckout fetchLFS; url = gitRepoUrl; - } // lib.optionalAttrs (leaveDotGit != null) { inherit leaveDotGit; } - else { -- url = "${baseUrl}/archive/${rev}.tar.gz"; -+ url = "${baseUrl}/archive/${if tag != null then "refs/tags/${tag}" else rev}.tar.gz"; - - passthru = { - inherit gitRepoUrl; diff --git a/nixpkgs-patches/pr359282.patch b/nixpkgs-patches/pr359282.patch deleted file mode 100644 index df16636..0000000 --- a/nixpkgs-patches/pr359282.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 40b3e9f1d39626c1bf38a315e78a1aafd3f378d4 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Tue, 26 Nov 2024 13:36:45 +0100 -Subject: [PATCH 1/2] handheld-daemon: 3.4.1 -> 3.5.7 - -Also install hhd's hwdb file, since it is needed for buttons to work -properly on the MSI Claw, among other things ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 286566a2710a4..e21fe848b0942 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -8,14 +8,14 @@ - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "3.4.1"; -+ version = "3.5.7"; - pyproject = true; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - rev = "refs/tags/v${version}"; -- hash = "sha256-hup9G4pTlTl68zLzhaDmH7nV8fp/I94Nuis68B8K2wY="; -+ hash = "sha256-nUHEPyTHU7LD6BZg+2cLl4M/ZPb5MQl6xxtJW1iZkEY="; - }; - - propagatedBuildInputs = with python3.pkgs; [ -@@ -27,6 +27,7 @@ python3.pkgs.buildPythonApplication rec { - setuptools - toybox - xlib -+ pyserial - ]; - - # This package doesn't have upstream tests. -@@ -46,6 +47,7 @@ python3.pkgs.buildPythonApplication rec { - - postInstall = '' - install -Dm644 $src/usr/lib/udev/rules.d/83-hhd.rules -t $out/lib/udev/rules.d/ -+ install -Dm644 $src/usr/lib/udev/hwdb.d/83-hhd.hwdb -t $out/lib/udev/hwdb.d/ - ''; - - meta = with lib; { - -From efc1301777818548a2f23f31248486e680502456 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Tue, 26 Nov 2024 17:50:06 +0100 -Subject: [PATCH 2/2] handheld-daemon: 3.5.7 -> 3.6.1 - -Version 3.6.0 added lsof as a dependency ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index e21fe848b0942..b99cd1c581476 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -5,17 +5,18 @@ - lib, - python3, - toybox, -+ lsof - }: - python3.pkgs.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "3.5.7"; -+ version = "3.6.1"; - pyproject = true; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - rev = "refs/tags/v${version}"; -- hash = "sha256-nUHEPyTHU7LD6BZg+2cLl4M/ZPb5MQl6xxtJW1iZkEY="; -+ hash = "sha256-IdpSRb66G+WzTv/BC29r2OjO1b4VdWbV6OSzOoiFAO0="; - }; - - propagatedBuildInputs = with python3.pkgs; [ -@@ -28,6 +29,7 @@ python3.pkgs.buildPythonApplication rec { - toybox - xlib - pyserial -+ lsof - ]; - - # This package doesn't have upstream tests. From 75e75a571ebc13df80b2c6b146474a306b95b68c Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Dec 2024 11:23:16 +0100 Subject: [PATCH 0849/1125] Kde/kwin: update patch --- roles/kde/patches/kwin-pr6406.patch | 74 ++++++++++++++++++----------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/roles/kde/patches/kwin-pr6406.patch b/roles/kde/patches/kwin-pr6406.patch index b58678b..e3a55a8 100644 --- a/roles/kde/patches/kwin-pr6406.patch +++ b/roles/kde/patches/kwin-pr6406.patch @@ -1,4 +1,4 @@ -From ffa4f312c750ae0e7e36a656612148b1fa9c020c Mon Sep 17 00:00:00 2001 +From 3ea8c3758e75f06c71b0b279c4e51f22ec554954 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 4 Oct 2024 22:49:16 +0300 Subject: [PATCH 1/9] Resize X11 window immediately if it doesn't support @@ -181,10 +181,10 @@ index b71a9d3640..780ccfbc7e 100644 } -- -2.46.1 +2.47.0 -From bc87fc3d80ad525786a9b15df5c2488a6110b53d Mon Sep 17 00:00:00 2001 +From 1be3dfa4b40732997ecb1bd1959ba775331d603a Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 4 Oct 2024 22:55:44 +0300 Subject: [PATCH 2/9] Rename X11Window::handleSync,handleSyncTimeout @@ -255,10 +255,10 @@ index 4f3b43c8b0..b54db23345 100644 bool allowWindowActivation(xcb_timestamp_t time = -1U, bool focus_in = false); -- -2.46.1 +2.47.0 -From b8016cbe28d847d052f1b0ee6c66bdaabbb88368 Mon Sep 17 00:00:00 2001 +From ea53098c38b64cb5870ef4f3b47fb53f509e03a4 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 4 Oct 2024 22:59:34 +0300 Subject: [PATCH 3/9] Rename X11Window::SyncRequest::isPending @@ -340,10 +340,10 @@ index b54db23345..10fa57eaf2 100644 }; const SyncRequest &syncRequest() const -- -2.46.1 +2.47.0 -From 61e7061998ce3244325af62aac198ecf058a1aeb Mon Sep 17 00:00:00 2001 +From 49319a3f3e2a1d468e12bdf3dfd7eeb2e3db0899 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 4 Oct 2024 23:12:44 +0300 Subject: [PATCH 4/9] Make XSync timeout more permissive @@ -599,10 +599,10 @@ index 10fa57eaf2..6b430b861a 100644 void establishCommandAllGrab(uint8_t button); -- -2.46.1 +2.47.0 -From dd10d1b329b06ab3377f669a610fec9726f28a70 Mon Sep 17 00:00:00 2001 +From 79e1853e9ecd20c1d9549399b46d434475b753bd Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 4 Oct 2024 23:20:03 +0300 Subject: [PATCH 5/9] Disable Xwayland surface commits for all sync requests @@ -658,10 +658,10 @@ index 1d25ab82b1..5688ea6da8 100644 configure(nativeFrameGeometry, nativeWrapperGeometry, nativeClientGeometry); } -- -2.46.1 +2.47.0 -From 60ef3223e42a06110693fef3ec493662c799af38 Mon Sep 17 00:00:00 2001 +From 038a798c8be170eb5b7132b823d77474d118ca42 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 4 Oct 2024 23:40:41 +0300 Subject: [PATCH 6/9] Make Xwayland resizing less glitchy @@ -824,10 +824,10 @@ index 6b430b861a..73d4c23a4c 100644 void setAllowCommits(bool allow); -- -2.46.1 +2.47.0 -From 59f45806953e05bbf289480b9e5882e4d87ee434 Mon Sep 17 00:00:00 2001 +From 10c5298221f5dc3cc90255846580b608f6f3c18c Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Thu, 3 Oct 2024 00:43:57 +0300 Subject: [PATCH 7/9] scene: Use standard wl_surface item for Xwayland surfaces @@ -837,13 +837,13 @@ opaque region getting out of sync. Xwayland MR: https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1698 --- - src/scene/surfaceitem_wayland.cpp | 21 --------------------- - src/scene/surfaceitem_wayland.h | 19 ------------------- + src/scene/surfaceitem_wayland.cpp | 36 ------------------------------- + src/scene/surfaceitem_wayland.h | 20 ----------------- src/scene/windowitem.cpp | 2 +- - 3 files changed, 1 insertion(+), 41 deletions(-) + 3 files changed, 1 insertion(+), 57 deletions(-) diff --git a/src/scene/surfaceitem_wayland.cpp b/src/scene/surfaceitem_wayland.cpp -index a4d012f774..04961952b9 100644 +index 4a307565c0..04961952b9 100644 --- a/src/scene/surfaceitem_wayland.cpp +++ b/src/scene/surfaceitem_wayland.cpp @@ -12,11 +12,6 @@ @@ -858,7 +858,7 @@ index a4d012f774..04961952b9 100644 namespace KWin { -@@ -247,22 +242,6 @@ bool SurfacePixmapWayland::isValid() const +@@ -247,37 +242,6 @@ bool SurfacePixmapWayland::isValid() const return m_bufferRef; } @@ -867,22 +867,37 @@ index a4d012f774..04961952b9 100644 - : SurfaceItemWayland(window->surface(), parent) - , m_window(window) -{ +- connect(window, &X11Window::shapeChanged, this, &SurfaceItemXwayland::discardQuads); +-} +- +-QList SurfaceItemXwayland::shape() const +-{ +- QList shape = m_window->shapeRegion(); +- for (QRectF &shapePart : shape) { +- shapePart = shapePart.intersected(rect()); +- } +- return shape; -} - -QRegion SurfaceItemXwayland::opaque() const -{ -- if (!m_window->hasAlpha()) { -- return rect().toRect(); -- } else { -- return m_window->opaqueRegion() & rect().toRect(); +- QRegion shapeRegion; +- for (const QRectF &shapePart : shape()) { +- shapeRegion += shapePart.toRect(); - } +- if (!m_window->hasAlpha()) { +- return shapeRegion; +- } else { +- return m_window->opaqueRegion() & shapeRegion; +- } +- return QRegion(); -} -#endif } // namespace KWin #include "moc_surfaceitem_wayland.cpp" diff --git a/src/scene/surfaceitem_wayland.h b/src/scene/surfaceitem_wayland.h -index 991cd168c3..fbc7498446 100644 +index f769284172..fbc7498446 100644 --- a/src/scene/surfaceitem_wayland.h +++ b/src/scene/surfaceitem_wayland.h @@ -16,7 +16,6 @@ namespace KWin @@ -893,7 +908,7 @@ index 991cd168c3..fbc7498446 100644 /** * The SurfaceItemWayland class represents a Wayland surface in the scene. -@@ -83,22 +82,4 @@ private: +@@ -83,23 +82,4 @@ private: SurfaceItemWayland *m_item; }; @@ -909,6 +924,7 @@ index 991cd168c3..fbc7498446 100644 - explicit SurfaceItemXwayland(X11Window *window, Item *parent = nullptr); - - QRegion opaque() const override; +- QList shape() const override; - -private: - X11Window *m_window; @@ -930,10 +946,10 @@ index 4283051e7e..913d2708f5 100644 break; case Application::OperationModeWaylandOnly: -- -2.46.1 +2.47.0 -From 84f35749d9084692e0ea8ae4ea187178005457cc Mon Sep 17 00:00:00 2001 +From 91ca5127fbf590a383fe311b76da8dce553e2a8a Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Mon, 14 Oct 2024 00:34:28 +0300 Subject: [PATCH 8/9] Send the initial sync request before mapping the frame @@ -995,10 +1011,10 @@ index b22de557d8..be35fe07fd 100644 bool allow; if (session) { -- -2.46.1 +2.47.0 -From 3ecac02f2f7573d7b2714c1fb23bebaec8afa0e0 Mon Sep 17 00:00:00 2001 +From cffaa20e83b7d9de69dcc835f6ab5d2609a49be5 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Thu, 17 Oct 2024 19:21:32 +0300 Subject: [PATCH 9/9] Block interactive resizing if there is a pending XSync @@ -1025,5 +1041,5 @@ index be35fe07fd..3e989f29bd 100644 void X11Window::doInteractiveResizeSync(const QRectF &rect) -- -2.46.1 +2.47.0 From 10f09226ebb2c30510345f2f699404f67a7475cc Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Dec 2024 11:23:35 +0100 Subject: [PATCH 0850/1125] Update changed options --- roles/desktop/configuration.nix | 5 +++-- roles/gaming/programs/retroarch.nix | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index 5129810..4348234 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -14,8 +14,9 @@ }; # Set up fonts - fonts.packages = [ - (pkgs.nerdfonts.override {fonts = ["Hack" "JetBrainsMono"];}) + fonts.packages = with pkgs.nerd-fonts; [ + hack + jetbrains-mono ]; hardware.keyboard.qmk.enable = true; diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index 3088ab2..ffa46a3 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -21,7 +21,7 @@ in { home = { packages = [ ( - pkgs.retroarch.override { + pkgs.wrapRetroArch { cores = with pkgs.libretro; [ snes9x ]; From 049a95e7b082d474ae148582940a1c2853039594 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Dec 2024 17:13:18 +0100 Subject: [PATCH 0851/1125] Server/forgejo: chage root url to https --- roles/server/forgejo.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index ff51523..d202b88 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -30,7 +30,7 @@ in { }; server = { OFFLINE_MODE = false; - ROOT_URL = "http://git.everest.tailscale"; + ROOT_URL = "https://git.everest.tailscale"; START_SSH_SERVER = true; SSH_PORT = 4222; SSH_SERVER_HOST_KEYS = config.age.secrets.forgejo-host-key.path; From efc4b199a49dbf6249ad0e12869f14d344248a38 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Dec 2024 17:34:22 +0100 Subject: [PATCH 0852/1125] Common: update state version --- roles/common/configuration.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 7024b74..ec4abbd 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -130,7 +130,7 @@ users.toast = {osConfig, ...}: { catppuccin.flavor = osConfig.catppuccin.flavor; catppuccin.accent = osConfig.catppuccin.accent; - home.stateVersion = "24.05"; + home.stateVersion = "24.11"; manual = { manpages.enable = true; html.enable = true; @@ -165,7 +165,7 @@ */ system = { - stateVersion = "24.05"; + stateVersion = "24.11"; # Nix on nixos 23.05 does not have dirtyRev configurationRevision = flakeSelf.sourceInfo.rev or flakeSelf.sourceInfo.dirtyRev or "dirty"; nixos.variant_id = lib.strings.toLower config.networking.hostName; From 4bb34105f1d89a6b3d3e86ce08008023ba2f1d96 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 15 Dec 2024 02:28:56 +0100 Subject: [PATCH 0853/1125] Machines/Archie: replace usb_storage module with nvme --- machines/Archie/hardware-configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index bd32dc6..29e1a5b 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -14,7 +14,7 @@ # Enable support for the Xbox One wireless dongle hardware.xone.enable = true; - boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod"]; + boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usbhid" "nvme" "sd_mod"]; boot.initrd.kernelModules = ["amdgpu"]; boot.kernelModules = ["kvm-amd"]; boot.extraModulePackages = []; From 3eaabeacd9961f1d55bb082048cfb21fea1646b1 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 15 Dec 2024 02:30:44 +0100 Subject: [PATCH 0854/1125] Machines/Archie: remove btrfs compression --- machines/Archie/hardware-configuration.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index 29e1a5b..da6c290 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -22,19 +22,19 @@ fileSystems."/" = { device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; fsType = "btrfs"; - options = ["subvol=@root" "compress=zstd"]; + options = ["subvol=@root"]; }; fileSystems."/nix" = { device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; fsType = "btrfs"; - options = ["subvol=@nix" "compress=zstd"]; + options = ["subvol=@nix"]; }; fileSystems."/boot" = { device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; fsType = "btrfs"; - options = ["subvol=@boot" "compress=zstd"]; + options = ["subvol=@boot"]; }; fileSystems."/boot/efi" = { @@ -62,12 +62,12 @@ "/home" = { device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; fsType = "btrfs"; - options = ["subvol=@home" "compress=zstd"]; + options = ["subvol=@home"]; }; "/persist" = { device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; fsType = "btrfs"; - options = ["subvol=@persist" "compress=zstd"]; + options = ["subvol=@persist"]; neededForBoot = true; }; }; From a2eacddd44bbca7e571e570b51cd59f768e3a6dc Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 15 Dec 2024 03:07:23 +0100 Subject: [PATCH 0855/1125] Kde/konsole: replace fetchFromGitHub with flake input --- flake.lock | 17 +++++++++++++++++ flake.nix | 5 +++++ roles/kde/programs/konsole.nix | 12 ++---------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index 8a596eb..15dfcba 100644 --- a/flake.lock +++ b/flake.lock @@ -38,6 +38,22 @@ "type": "github" } }, + "catppuccin-konsole": { + "flake": false, + "locked": { + "lastModified": 1720277724, + "narHash": "sha256-d5+ygDrNl2qBxZ5Cn4U7d836+ZHz77m6/yxTIANd9BU=", + "owner": "catppuccin", + "repo": "konsole", + "rev": "3b64040e3f4ae5afb2347e7be8a38bc3cd8c73a8", + "type": "github" + }, + "original": { + "owner": "catppuccin", + "repo": "konsole", + "type": "github" + } + }, "eza-themes": { "flake": false, "locked": { @@ -542,6 +558,7 @@ "inputs": { "agenix": "agenix", "catppuccin": "catppuccin", + "catppuccin-konsole": "catppuccin-konsole", "eza-themes": "eza-themes", "home-manager": "home-manager_2", "home-manager-unstable": "home-manager-unstable", diff --git a/flake.nix b/flake.nix index 7da03e7..f567c75 100644 --- a/flake.nix +++ b/flake.nix @@ -88,6 +88,11 @@ url = "github:eza-community/eza-themes"; flake = false; }; + + catppuccin-konsole = { + url = "github:catppuccin/konsole"; + flake = false; + }; }; outputs = {...} @ inputs: diff --git a/roles/kde/programs/konsole.nix b/roles/kde/programs/konsole.nix index 6bf8ae8..ecf812f 100644 --- a/roles/kde/programs/konsole.nix +++ b/roles/kde/programs/konsole.nix @@ -1,13 +1,5 @@ -{pkgs, ...}: let - catppuccinKonsole = - pkgs.fetchFromGitHub { - owner = "catppuccin"; - repo = "konsole"; - # Latest commit is 7d86b8a1e56e58f6b5649cdaac543a573ac194ca - rev = "main"; - hash = "sha256-EwSJMTxnaj2UlNJm1t6znnatfzgm1awIQQUF3VPfCTM="; - } - + /Catppuccin-Mocha.colorscheme; +{flakeSelf, ...}: let + catppuccinKonsole = "${flakeSelf.inputs.catppuccin-konsole}/themes/catppuccin-mocha.colorscheme"; in { home-manager.users.toast = { xdg.dataFile = { From 5895f4beb1418a73102900d98681a0c67d64378b Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 15 Dec 2024 15:42:25 +0100 Subject: [PATCH 0856/1125] Kde/plasma: add mouse settings --- roles/kde/plasma.nix | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index dd6b234..7dadf13 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -98,6 +98,25 @@ in { layouts = [{layout = "es";}]; numlockOnStartup = "off"; }; + mice = let + settings = { + enable = true; + accelerationProfile = "none"; + }; + mice = [ + { + productId = "d030"; + vendorId = "3434"; + name = "Keychron Keychron Link "; + } + { + productId = "d03f"; + vendorId = "3434"; + name = "Keychron Keychron M6 "; + } + ]; + in + lib.lists.forEach mice (miceInfo: miceInfo // settings); }; panels = [ { From 99056c9f32af428e02a65944fb2ea19b26c23657 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 15 Dec 2024 15:43:36 +0100 Subject: [PATCH 0857/1125] Run formatter --- roles/desktop/services/syncthing.nix | 14 ++++++++------ roles/kde/plasma.nix | 8 +++++--- roles/server/adguard.nix | 2 +- roles/server/samba.nix | 4 ++-- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/roles/desktop/services/syncthing.nix b/roles/desktop/services/syncthing.nix index f3b0713..dee6a2a 100644 --- a/roles/desktop/services/syncthing.nix +++ b/roles/desktop/services/syncthing.nix @@ -44,11 +44,13 @@ builtins.removeAttrs rawOptions missingOptions ); in { - services.syncthing = removeMissingOptions systemConfig // { - enable = true; - # Renamed options - allProxy = systemConfig.all_proxy; - extraOptions = systemConfig.extraFlags; - }; + services.syncthing = + removeMissingOptions systemConfig + // { + enable = true; + # Renamed options + allProxy = systemConfig.all_proxy; + extraOptions = systemConfig.extraFlags; + }; }; } diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 7dadf13..20d6267 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -50,9 +50,11 @@ in { ]; }; plasma-workspace = kPrev.plasma-workspace.overrideAttrs { - patches = kPrev.plasma-workspace.patches ++ [ - ./patches/plasma_workspace-pr4883.patch - ]; + patches = + kPrev.plasma-workspace.patches + ++ [ + ./patches/plasma_workspace-pr4883.patch + ]; }; } ); diff --git a/roles/server/adguard.nix b/roles/server/adguard.nix index ab814f8..42da331 100644 --- a/roles/server/adguard.nix +++ b/roles/server/adguard.nix @@ -18,7 +18,7 @@ in { }; }; - headscale.settings.dns= { + headscale.settings.dns = { nameservers.global = lib.mkForce ["100.100.0.1"]; extra_records = [ { diff --git a/roles/server/samba.nix b/roles/server/samba.nix index 85f3c9f..ae6d9e6 100755 --- a/roles/server/samba.nix +++ b/roles/server/samba.nix @@ -5,8 +5,8 @@ openFirewall = true; settings = { "global" = { - "map to guest" = "bad user"; - "guest account" = "transmission"; + "map to guest" = "bad user"; + "guest account" = "transmission"; }; "Transmission downloads" = { path = "${config.services.transmission.settings.download-dir}"; From d130ffb20d6bea749d700bfcf09ed1fcdc2cff28 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 15 Dec 2024 16:25:48 +0100 Subject: [PATCH 0858/1125] Common/nix: remove unneeded nixpath workaround, update comment --- roles/common/programs/nix.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index de6a729..7a96dbf 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -58,9 +58,10 @@ }; # Write the system's nixpkgs into the registry to avoid mixing nixpkgs versions # https://dataswamp.org/~solene/2022-07-20-nixos-flakes-command-sync-with-system.html + + # Since 24.05 this is already done for nixpkgs, but it doesn't keep the patches + # so I'm keeping this around just in case system.flake = systemPkgs; }; - # I removed this in the past since I thought that I didn't need it, but turns out comma does :) - nixPath = ["nixpkgs=${systemPkgs}"]; }; } From ce51dd5dd30f0ccdc4bb77d4e460c49db77a0305 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 10 Dec 2024 17:37:15 +0100 Subject: [PATCH 0859/1125] Gitignore: ignore nix repl result files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e81be07..32cf8df 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # Ignore build outputs from performing a nix-build or `nix build` command result result-* +repl-result* # ---> Kate # Ignore kate's swap files From 0b3613086c52fde421d71d97d522e212abbb6fc6 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 15 Dec 2024 19:40:48 +0100 Subject: [PATCH 0860/1125] Kde/plasma: add entry for mouse over bluetooth --- roles/kde/plasma.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 20d6267..9c8943c 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -116,6 +116,11 @@ in { vendorId = "3434"; name = "Keychron Keychron M6 "; } + { + productId = "d03f"; + vendorId = "3434"; + name = "Keychron M6 Mouse"; + } ]; in lib.lists.forEach mice (miceInfo: miceInfo // settings); From 49130f062d174004cdf6c8f2b5b104c731b0284e Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 16 Dec 2024 10:32:41 +0100 Subject: [PATCH 0861/1125] Gaming/syncthing: sync project diva mods --- roles/gaming/services/syncthing.nix | 6 ++++++ roles/server/syncthing.nix | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/roles/gaming/services/syncthing.nix b/roles/gaming/services/syncthing.nix index f511c87..77bbd87 100644 --- a/roles/gaming/services/syncthing.nix +++ b/roles/gaming/services/syncthing.nix @@ -11,6 +11,12 @@ devices = ["steamdeck" "server" "pc" "winmax2"]; path = "~/.local/share/Steam/steamapps/compatdata/201810/pfx/drive_c/users/steamuser/Saved Games/MachineGames/Wolfenstein The New Order/"; }; + "project-diva-mods" = { + label = "Project Diva Mods"; + id = "7pscj-6egww"; + devices = ["steamdeck" "server" "pc" "winmax2"]; + path = "~/.local/share/Steam/steamapps/common/Hatsune Miku Project DIVA Mega Mix Plus/mods/"; + }; }; home-manager.users.toast.home.file."steam-201810-ignore" = { target = ".local/share/Steam/steamapps/compatdata/201810/pfx/drive_c/users/steamuser/Saved Games/MachineGames/Wolfenstein The New Order/.stignore"; diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 509d00b..50e1857 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -14,6 +14,12 @@ devices = ["steamdeck" "server" "pc" "winmax2"]; path = "${config.services.syncthing.dataDir}/steam-201810"; }; + "project-diva-mods" = { + label = "Project Diva Mods"; + id = "7pscj-6egww"; + devices = ["steamdeck" "server" "pc" "winmax2"]; + path = "${config.services.syncthing.dataDir}/project-diva-mods"; + }; "retroarch" = { label = "RetroArch"; id = "jxuou-2yjnu"; From fe9678388d4f34683e079873923664b6fac11e6e Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Dec 2024 15:47:03 +0100 Subject: [PATCH 0862/1125] Flake: update lock file and remove unneeded nixpkgs patches --- flake.lock | 98 ++++++++--------- flake.nix | 4 +- nixpkgs-patches/pr361364.patch | 187 --------------------------------- 3 files changed, 50 insertions(+), 239 deletions(-) delete mode 100644 nixpkgs-patches/pr361364.patch diff --git a/flake.lock b/flake.lock index 15dfcba..d6945dd 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "catppuccin": { "locked": { - "lastModified": 1733001911, - "narHash": "sha256-uX/9m0TbdhEzuWA0muM5mI/AaWcLiDLjCCyu5Qr9MRk=", + "lastModified": 1734397929, + "narHash": "sha256-VCTVpU/RlrI9StxzDnqc1R3ZTQloLVALSkiN/Fgiad4=", "owner": "catppuccin", "repo": "nix", - "rev": "a817009ebfd2cca7f70a77884e5098d0a8c83f8e", + "rev": "21310cde33d3ee8023679dec01a9724a346c63ff", "type": "github" }, "original": { @@ -219,11 +219,11 @@ ] }, "locked": { - "lastModified": 1733754861, - "narHash": "sha256-3JKzIou54yjiMVmvgdJwopekEvZxX3JDT8DpKZs4oXY=", + "lastModified": 1734344598, + "narHash": "sha256-wNX3hsScqDdqKWOO87wETUEi7a/QlPVgpC/Lh5rFOuA=", "owner": "nix-community", "repo": "home-manager", - "rev": "9ebaa80a227eaca9c87c53ed515ade013bc2bca9", + "rev": "83ecd50915a09dca928971139d3a102377a8d242", "type": "github" }, "original": { @@ -239,11 +239,11 @@ ] }, "locked": { - "lastModified": 1733572789, - "narHash": "sha256-zjO6m5BqxXIyjrnUziAzk4+T4VleqjstNudSqWcpsHI=", + "lastModified": 1734366194, + "narHash": "sha256-vykpJ1xsdkv0j8WOVXrRFHUAdp9NXHpxdnn1F4pYgSw=", "owner": "nix-community", "repo": "home-manager", - "rev": "c7ffc9727d115e433fd884a62dc164b587ff651d", + "rev": "80b0fdf483c5d1cb75aaad909bd390d48673857f", "type": "github" }, "original": { @@ -261,11 +261,11 @@ ] }, "locked": { - "lastModified": 1733762021, - "narHash": "sha256-QAc+GvjJXLyp7oy2Vt1LEjYnq6UXPAmncwpL5aZUsUM=", + "lastModified": 1734162608, + "narHash": "sha256-m2AX+3eiVqIK6uO7GbGY7SFnkkYOlR5fQiNI0eRvWOQ=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "f2180c6fcfca4eaecd79eadba0b5874e9a1c70c1", + "rev": "31bdf4c7c91204d65afbde01146deee0259a8fb7", "type": "github" }, "original": { @@ -277,11 +277,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1733740102, - "narHash": "sha256-zIm58tETZ5Z6Scsjrn9rPISLzH4kWb2MIoC/jdii5ts=", - "rev": "369e3f82f066866b4d75abc5fc66e5b8e2149b4c", + "lastModified": 1733932114, + "narHash": "sha256-LN4pgLjGWztTlJ4oDcKWvDuTFeUUVgbmXoZ2EXG20Gw=", + "rev": "92ed9fee7d169febf53ea85961174fc0a22c2115", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/369e3f82f066866b4d75abc5fc66e5b8e2149b4c.tar.gz?rev=369e3f82f066866b4d75abc5fc66e5b8e2149b4c" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/92ed9fee7d169febf53ea85961174fc0a22c2115.tar.gz?rev=92ed9fee7d169febf53ea85961174fc0a22c2115" }, "original": { "type": "tarball", @@ -336,11 +336,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1733345341, - "narHash": "sha256-8S58zrdpzGhax6tmn1i+R3AA0N9DJMu5FQI8JkA0NNU=", + "lastModified": 1734128415, + "narHash": "sha256-HLwdVNxpuTsLlM3tCkpbQU6yCehdgf3kOS1G2SDlkzY=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "ebb0be49fc381112ff37726c6dd6df4df2ef5a1b", + "rev": "8bdc2540da516006d07b04019eb57ae0781a04b3", "type": "github" }, "original": { @@ -374,11 +374,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1731242966, - "narHash": "sha256-B3C3JLbGw0FtLSWCjBxU961gLNv+BOOBC6WvstKLYMw=", + "lastModified": 1734200366, + "narHash": "sha256-0NursoP4BUdnc+wy+Mq3icHkXu/RgP1Sjo0MJxV2+Dw=", "owner": "nix-community", "repo": "impermanence", - "rev": "3ed3f0eaae9fcc0a8331e77e9319c8a4abd8a71a", + "rev": "c6323585fa0035d780e3d8906eb1b24b65d19a48", "type": "github" }, "original": { @@ -394,11 +394,11 @@ ] }, "locked": { - "lastModified": 1733629314, - "narHash": "sha256-U0vivjQFAwjNDYt49Krevs1murX9hKBFe2Ye0cHpgbU=", + "lastModified": 1734234111, + "narHash": "sha256-icEMqBt4HtGH52PU5FHidgBrNJvOfXH6VQKNtnD1aw8=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f1e477a7dd11e27e7f98b646349cd66bbabf2fb8", + "rev": "311d6cf3ad3f56cb051ffab1f480b2909b3f754d", "type": "github" }, "original": { @@ -414,11 +414,11 @@ ] }, "locked": { - "lastModified": 1733629314, - "narHash": "sha256-U0vivjQFAwjNDYt49Krevs1murX9hKBFe2Ye0cHpgbU=", + "lastModified": 1734234111, + "narHash": "sha256-icEMqBt4HtGH52PU5FHidgBrNJvOfXH6VQKNtnD1aw8=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "f1e477a7dd11e27e7f98b646349cd66bbabf2fb8", + "rev": "311d6cf3ad3f56cb051ffab1f480b2909b3f754d", "type": "github" }, "original": { @@ -436,11 +436,11 @@ ] }, "locked": { - "lastModified": 1733709556, - "narHash": "sha256-u0ll0DDrKlO7tiLGGtmphv3wFy5ReDuf0USo/OlfROU=", + "lastModified": 1734314370, + "narHash": "sha256-9PhjDAAuXP4tuJg+kM1AozKwBFyHHJ8ZqhQD+peqGtg=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "8d11f147df83fe137d3d94f6f3646e3a52bec855", + "rev": "616634de04e87b621bc3d495af114c4e9c6ccd36", "type": "github" }, "original": { @@ -451,11 +451,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1733481457, - "narHash": "sha256-IS3bxa4N1VMSh3/P6vhEAHQZecQ3oAlKCDvzCQSO5Is=", + "lastModified": 1734352517, + "narHash": "sha256-mfv+J/vO4nqmIOlq8Y1rRW8hVsGH3M+I2ESMjhuebDs=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "e563803af3526852b6b1d77107a81908c66a9fcf", + "rev": "b12e314726a4226298fe82776b4baeaa7bcf3dcd", "type": "github" }, "original": { @@ -467,11 +467,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1733581040, - "narHash": "sha256-Qn3nPMSopRQJgmvHzVqPcE3I03zJyl8cSbgnnltfFDY=", + "lastModified": 1734424634, + "narHash": "sha256-cHar1vqHOOyC7f1+tVycPoWTfKIaqkoe1Q6TnKzuti4=", "owner": "nixos", "repo": "nixpkgs", - "rev": "22c3f2cf41a0e70184334a958e6b124fb0ce3e01", + "rev": "d3c42f187194c26d9f0309a8ecc469d6c878ce33", "type": "github" }, "original": { @@ -483,11 +483,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1733550349, - "narHash": "sha256-NcGumB4Lr6KSDq+nIqXtNA8QwAQKDSZT7N9OTGWbTrs=", + "lastModified": 1734323986, + "narHash": "sha256-m/lh6hYMIWDYHCAsn81CDAiXoT3gmxXI9J987W5tZrE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e2605d0744c2417b09f8bf850dfca42fcf537d34", + "rev": "394571358ce82dff7411395829aa6a3aad45b907", "type": "github" }, "original": { @@ -498,11 +498,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1733581040, - "narHash": "sha256-Qn3nPMSopRQJgmvHzVqPcE3I03zJyl8cSbgnnltfFDY=", + "lastModified": 1734424634, + "narHash": "sha256-cHar1vqHOOyC7f1+tVycPoWTfKIaqkoe1Q6TnKzuti4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "22c3f2cf41a0e70184334a958e6b124fb0ce3e01", + "rev": "d3c42f187194c26d9f0309a8ecc469d6c878ce33", "type": "github" }, "original": { @@ -518,11 +518,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1733824207, - "narHash": "sha256-qGXcFigGMSFba29CtCnTgf/c9h+Dzh6yHcXTK16jXJ8=", + "lastModified": 1734529681, + "narHash": "sha256-pe/fHd6nuz8nxwyVsLDDilgy+0rXJ1iYhCFojFlV8QE=", "owner": "nix-community", "repo": "NUR", - "rev": "f1ea8bb704f71d74dcc885d6bd149b5b661bb858", + "rev": "29cbfd0aad3f30ed30312668b3d8dca522175349", "type": "github" }, "original": { @@ -541,11 +541,11 @@ ] }, "locked": { - "lastModified": 1733578387, - "narHash": "sha256-XkMZGeqg0GCRoSXvMcaHP7bdvWPRZxCK1sw1ASsc16E=", + "lastModified": 1733858086, + "narHash": "sha256-h2BDIDKiqgMpA6E+mu0RgMGy3FeM6k+EuJ9xgOQ1+zw=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "2a64e173f1effdcc86e25cba0601e8feedf89115", + "rev": "7e2010249529931a3848054d5ff0dbf24675ab68", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index f567c75..586e9f5 100644 --- a/flake.nix +++ b/flake.nix @@ -103,9 +103,7 @@ nixpkgs-unstable-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; - patches = [ - ./nixpkgs-patches/pr361364.patch - ]; + patches = []; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; diff --git a/nixpkgs-patches/pr361364.patch b/nixpkgs-patches/pr361364.patch deleted file mode 100644 index 74a7942..0000000 --- a/nixpkgs-patches/pr361364.patch +++ /dev/null @@ -1,187 +0,0 @@ -From c94ae7a159eb8cd86f46ca1ea81dbdca651510f4 Mon Sep 17 00:00:00 2001 -From: Gaetan Lepage -Date: Tue, 3 Dec 2024 08:47:26 +0100 -Subject: [PATCH 1/2] handheld-daemon: 3.6.1 -> 3.6.2 - -Diff: https://github.com/hhd-dev/hhd/compare/refs/tags/v3.6.1...v3.6.2 - -Changelog: https://github.com/hhd-dev/hhd/releases/tag/v3.6.2 ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 87 ++++++++++++++------- - 1 file changed, 57 insertions(+), 30 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index b99cd1c581476..6b5965e06e645 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -1,63 +1,90 @@ - { -+ lib, -+ python3Packages, - fetchFromGitHub, -+ -+ # dependencies -+ systemd, - hidapi, -+ coreutils, - kmod, -- lib, -- python3, -- toybox, -- lsof -+ dbus, -+ lsof, - }: --python3.pkgs.buildPythonApplication rec { -+python3Packages.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "3.6.1"; -+ version = "3.6.2"; - pyproject = true; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; -- rev = "refs/tags/v${version}"; -- hash = "sha256-IdpSRb66G+WzTv/BC29r2OjO1b4VdWbV6OSzOoiFAO0="; -+ tag = "v${version}"; -+ hash = "sha256-W1Ap6yTryBDozKe3aO413Fu0RBul9kEA9ACUTdYyOKM="; - }; - -- propagatedBuildInputs = with python3.pkgs; [ -+ # This package relies on several programs expected to be on the user's PATH. -+ # We take a more reproducible approach by patching the absolute path to each of these required -+ # binaries. -+ postPatch = '' -+ substituteInPlace src/hhd/controller/lib/hid.py \ -+ --replace-fail "libhidapi" "${lib.getLib hidapi}/lib/libhidapi" -+ -+ substituteInPlace src/hhd/controller/lib/hide.py \ -+ --replace-fail "/bin/chmod" "${lib.getExe' coreutils "chmod"}" \ -+ --replace-fail "udevadm" "${lib.getExe' systemd "udevadm"}" -+ -+ substituteInPlace src/hhd/controller/physical/evdev.py \ -+ --replace-fail "udevadm" "${lib.getExe' systemd "udevadm"}" -+ -+ substituteInPlace src/hhd/controller/physical/imu.py \ -+ --replace-fail '"modprobe' '"${lib.getExe' kmod "modprobe"}' -+ -+ substituteInPlace src/hhd/device/oxp/serial.py \ -+ --replace-fail "udevadm" "${lib.getExe' systemd "udevadm"}" -+ -+ substituteInPlace src/hhd/plugins/overlay/systemd.py \ -+ --replace-fail "dbus-monitor" "${lib.getExe' dbus "dbus-monitor"}" \ -+ --replace-fail "systemd-inhibit" "${lib.getExe' systemd "systemd-inhibit"}" -+ -+ substituteInPlace src/hhd/plugins/overlay/x11.py \ -+ --replace-fail "lsof" "${lib.getExe lsof}" -+ -+ substituteInPlace src/hhd/plugins/plugin.py \ -+ --replace-fail '"id"' '"${lib.getExe' coreutils "id"}"' -+ ''; -+ -+ build-system = with python3Packages; [ -+ setuptools -+ ]; -+ -+ dependencies = with python3Packages; [ - evdev -- hidapi -- kmod -+ pyserial - pyyaml - rich - setuptools -- toybox - xlib -- pyserial -- lsof - ]; - - # This package doesn't have upstream tests. - doCheck = false; - -- postPatch = '' -- # handheld-daemon contains a fork of the python module `hid`, so this hook -- # is borrowed from the `hid` derivation. -- hidapi=${hidapi}/lib/ -- test -d $hidapi || { echo "ERROR: $hidapi doesn't exist, please update/fix this build expression."; exit 1; } -- sed -i -e "s|libhidapi|$hidapi/libhidapi|" src/hhd/controller/lib/hid.py -- -- # The generated udev rules point to /bin/chmod, which does not exist in NixOS -- chmod=${toybox}/bin/chmod -- sed -i -e "s|/bin/chmod|$chmod|" src/hhd/controller/lib/hide.py -- ''; -- - postInstall = '' - install -Dm644 $src/usr/lib/udev/rules.d/83-hhd.rules -t $out/lib/udev/rules.d/ - install -Dm644 $src/usr/lib/udev/hwdb.d/83-hhd.hwdb -t $out/lib/udev/hwdb.d/ - ''; - -- meta = with lib; { -+ meta = { - homepage = "https://github.com/hhd-dev/hhd/"; - description = "Linux support for handheld gaming devices like the Legion Go, ROG Ally, and GPD Win"; -- platforms = platforms.linux; -- license = licenses.mit; -- maintainers = with maintainers; [ appsforartists toast ]; -+ platforms = lib.platforms.linux; -+ changelog = "https://github.com/hhd-dev/hhd/releases/tag/v${version}"; -+ license = lib.licenses.gpl3Only; -+ maintainers = with lib.maintainers; [ -+ appsforartists -+ toast -+ ]; - mainProgram = "hhd"; - }; - } - -From 2cf68f2bf37655d730202f2e551b40172181801c Mon Sep 17 00:00:00 2001 -From: Gaetan Lepage -Date: Mon, 9 Dec 2024 10:26:53 +0100 -Subject: [PATCH 2/2] handheld-daemon: 3.6.2 -> 3.7.0 - -Diff: https://github.com/hhd-dev/hhd/compare/None...v3.7.0 - -Changelog: https://github.com/hhd-dev/hhd/releases/tag/v3.7.0 ---- - pkgs/by-name/ha/handheld-daemon/package.nix | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 6b5965e06e645..2fe0c45eca77f 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -8,19 +8,20 @@ - hidapi, - coreutils, - kmod, -+ efibootmgr, - dbus, - lsof, - }: - python3Packages.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "3.6.2"; -+ version = "3.7.0"; - pyproject = true; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - tag = "v${version}"; -- hash = "sha256-W1Ap6yTryBDozKe3aO413Fu0RBul9kEA9ACUTdYyOKM="; -+ hash = "sha256-DkVdYnSEeaNZj76lhdU+9Pl0yzam2A2QGa3aHCmSHEA="; - }; - - # This package relies on several programs expected to be on the user's PATH. -@@ -40,6 +41,9 @@ python3Packages.buildPythonApplication rec { - substituteInPlace src/hhd/controller/physical/imu.py \ - --replace-fail '"modprobe' '"${lib.getExe' kmod "modprobe"}' - -+ substituteInPlace src/hhd/plugins/overlay/power.py \ -+ --replace-fail '"efibootmgr"' '"${lib.getExe' efibootmgr "id"}"' -+ - substituteInPlace src/hhd/device/oxp/serial.py \ - --replace-fail "udevadm" "${lib.getExe' systemd "udevadm"}" - From 577aa1cc33357edbafe465f1de55a0f04e413bab Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Dec 2024 15:49:04 +0100 Subject: [PATCH 0863/1125] Kde/konsole: remove now-upstreamed patch --- roles/kde/patches/konsole-pr767.patch | 96 --------------------------- roles/kde/programs/konsole.nix | 4 +- 2 files changed, 1 insertion(+), 99 deletions(-) delete mode 100644 roles/kde/patches/konsole-pr767.patch diff --git a/roles/kde/patches/konsole-pr767.patch b/roles/kde/patches/konsole-pr767.patch deleted file mode 100644 index 8c757af..0000000 --- a/roles/kde/patches/konsole-pr767.patch +++ /dev/null @@ -1,96 +0,0 @@ -From fa8f6054c992f8f28781933a23bccb91b3341d6e Mon Sep 17 00:00:00 2001 -From: Christian Muehlhaeuser -Date: Tue, 8 Nov 2022 08:55:14 +0100 -Subject: [PATCH] Add support for OSC-52 write-only clipboard access - -Implements OSC-52 write-only clipboard access. Already supported by -a wide range of other terminals, including alacritty, foot, kitty, -urxvt, wezterm, xterm, and others. - -I've intentionally omitted read access to the clipboard as that -comes with several security concerns, which should be discussed -first. ---- - src/Vt102Emulation.cpp | 36 ++++++++++++++++++++++++++++++++++++ - src/Vt102Emulation.h | 2 +- - 2 files changed, 37 insertions(+), 1 deletion(-) - -diff --git a/src/Vt102Emulation.cpp b/src/Vt102Emulation.cpp -index 49b23c77d4..3b1e389106 100644 ---- a/src/Vt102Emulation.cpp -+++ b/src/Vt102Emulation.cpp -@@ -12,8 +12,10 @@ - #include - - // Qt -+#include - #include - #include -+#include - #include - #include - #include -@@ -1153,6 +1155,40 @@ void Vt102Emulation::processSessionAttributeRequest(const int tokenSize, const u - connect(action, &KNotificationAction::activated, this, [this, notification]() { - _currentScreen->currentTerminalDisplay()->notificationClicked(notification->xdgActivationToken()); - }); -+ } -+ if (attribute == Clipboard) { -+ // Clipboard -+ QStringList params = value.split(QLatin1Char(';')); -+ if (params.length() == 0) { -+ return; -+ } -+ -+ bool clipboard = false; -+ bool selection = false; -+ if (params[0].isEmpty() || params[0].contains(QLatin1Char('c')) || params[0].contains(QLatin1Char('s'))) { -+ clipboard = true; -+ } -+ if (params[0].contains(QLatin1Char('p'))) { -+ selection = true; -+ } -+ -+ if (params.length() == 2) { -+ // Copy to clipboard -+ if (clipboard) { -+ QApplication::clipboard()->setText(QString::fromUtf8(QByteArray::fromBase64(params[1].toUtf8())), QClipboard::Clipboard); -+ } -+ if (selection) { -+ QApplication::clipboard()->setText(QString::fromUtf8(QByteArray::fromBase64(params[1].toUtf8())), QClipboard::Selection); -+ } -+ } else { -+ // Clear clipboard -+ if (clipboard) { -+ QApplication::clipboard()->clear(QClipboard::Clipboard); -+ } -+ if (selection) { -+ QApplication::clipboard()->clear(QClipboard::Selection); -+ } -+ } - - return; - } -diff --git a/src/Vt102Emulation.h b/src/Vt102Emulation.h -index 665e9f026d..3456e068d3 100644 ---- a/src/Vt102Emulation.h -+++ b/src/Vt102Emulation.h -@@ -126,7 +126,6 @@ private: - void resetModes(); - - void resetTokenizer(); --#define MAX_TOKEN_LENGTH 256 // Max length of tokens (e.g. window title) - void addToCurrentToken(uint cc); - int tokenBufferPos; - -@@ -183,6 +182,7 @@ private: - enum osc { - // https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands - ReportColors = 4, -+ Clipboard = 52, - ResetColors = 104, - // https://gitlab.freedesktop.org/Per_Bothner/specifications/blob/master/proposals/semantic-prompts.md - SemanticPrompts = 133, --- -GitLab - diff --git a/roles/kde/programs/konsole.nix b/roles/kde/programs/konsole.nix index ecf812f..25040e8 100644 --- a/roles/kde/programs/konsole.nix +++ b/roles/kde/programs/konsole.nix @@ -22,9 +22,7 @@ in { kdePackages = prev.kdePackages.overrideScope ( kFinal: kPrev: { konsole = kPrev.konsole.overrideAttrs { - patches = [ - ../patches/konsole-pr767.patch - ]; + patches = []; }; } ); From 0c754f1930ef3ee45aa8d89988791f5b74d02cb1 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 18 Dec 2024 16:19:39 +0100 Subject: [PATCH 0864/1125] Kde/kwin: app pr 6878 --- roles/kde/patches/kwin-pr6878.patch | 753 ++++++++++++++++++++++++++++ roles/kde/programs/kwin.nix | 1 + 2 files changed, 754 insertions(+) create mode 100644 roles/kde/patches/kwin-pr6878.patch diff --git a/roles/kde/patches/kwin-pr6878.patch b/roles/kde/patches/kwin-pr6878.patch new file mode 100644 index 0000000..41fffc9 --- /dev/null +++ b/roles/kde/patches/kwin-pr6878.patch @@ -0,0 +1,753 @@ +diff --git a/src/plugins/zoom/CMakeLists.txt b/src/plugins/zoom/CMakeLists.txt +index c27bdbbb2d..b5fb343e17 100644 +--- a/src/plugins/zoom/CMakeLists.txt ++++ b/src/plugins/zoom/CMakeLists.txt +@@ -4,6 +4,7 @@ + set(zoom_SOURCES + main.cpp + zoom.cpp ++ zoom.qrc + ) + + if (HAVE_ACCESSIBILITY) +diff --git a/src/plugins/zoom/shaders/pixelgrid.frag b/src/plugins/zoom/shaders/pixelgrid.frag +new file mode 100644 +index 0000000000..1e9ee9431f +--- /dev/null ++++ b/src/plugins/zoom/shaders/pixelgrid.frag +@@ -0,0 +1,25 @@ ++#include "colormanagement.glsl" ++ ++uniform sampler2D sampler; ++uniform int textureWidth; ++uniform int textureHeight; ++ ++varying vec2 texcoord0; ++ ++void main() ++{ ++ vec2 texSize = vec2(textureWidth, textureHeight); ++ vec2 samplePosition = texcoord0 * texSize; ++ vec2 pixelCenter = floor(samplePosition) + vec2(0.5); ++ vec2 pixelCenterDistance = abs(samplePosition - pixelCenter); ++ ++ vec4 tex; ++ if (pixelCenterDistance.x > 0.4 || pixelCenterDistance.y > 0.4) { ++ tex = vec4(0, 0, 0, 1); ++ } else { ++ tex = texture2D(sampler, pixelCenter / texSize); ++ } ++ ++ tex = sourceEncodingToNitsInDestinationColorspace(tex); ++ gl_FragColor = nitsToDestinationEncoding(tex); ++} +diff --git a/src/plugins/zoom/shaders/pixelgrid_core.frag b/src/plugins/zoom/shaders/pixelgrid_core.frag +new file mode 100644 +index 0000000000..a1cc7f27f2 +--- /dev/null ++++ b/src/plugins/zoom/shaders/pixelgrid_core.frag +@@ -0,0 +1,24 @@ ++#version 140 ++ ++#include "colormanagement.glsl" ++ ++uniform sampler2D sampler; ++uniform int textureWidth; ++uniform int textureHeight; ++ ++in vec2 texcoord0; ++ ++out vec4 fragColor; ++ ++void main() ++{ ++ vec2 texSize = vec2(textureWidth, textureHeight); ++ vec2 samplePosition = texcoord0 * texSize; ++ vec2 pixelCenter = floor(samplePosition) + vec2(0.5); ++ vec2 pixelCenterDistance = abs(samplePosition - pixelCenter); ++ ++ float t = smoothstep(0.4, 0.5, max(pixelCenterDistance.x, pixelCenterDistance.y)); ++ vec4 tex = mix(texture(sampler, pixelCenter / texSize), vec4(0, 0, 0, 1), t); ++ tex = sourceEncodingToNitsInDestinationColorspace(tex); ++ fragColor = nitsToDestinationEncoding(tex); ++} +diff --git a/src/plugins/zoom/ui_zoom_config.h b/src/plugins/zoom/ui_zoom_config.h +new file mode 100644 +index 0000000000..7e5944a902 +--- /dev/null ++++ b/src/plugins/zoom/ui_zoom_config.h +@@ -0,0 +1,195 @@ ++/******************************************************************************** ++** Form generated from reading UI file 'zoom_config.ui' ++** ++** Created by: Qt User Interface Compiler version 6.8.1 ++** ++** WARNING! All changes made in this file will be lost when recompiling UI file! ++********************************************************************************/ ++ ++#ifndef UI_ZOOM_CONFIG_H ++#define UI_ZOOM_CONFIG_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "kshortcutseditor.h" ++ ++namespace KWin { ++ ++class Ui_ZoomEffectConfigForm ++{ ++public: ++ QVBoxLayout *verticalLayout_2; ++ QGroupBox *groupSize; ++ QHBoxLayout *horizontalLayout; ++ QGridLayout *gridLayout; ++ QLabel *label; ++ QDoubleSpinBox *kcfg_ZoomFactor; ++ QCheckBox *kcfg_EnableFocusTracking; ++ QCheckBox *kcfg_EnableTextCaretTracking; ++ QLabel *label_2; ++ QComboBox *kcfg_MousePointer; ++ QComboBox *kcfg_MouseTracking; ++ QLabel *label_3; ++ KShortcutsEditor *editor; ++ ++ void setupUi(QWidget *KWin__ZoomEffectConfigForm) ++ { ++ if (KWin__ZoomEffectConfigForm->objectName().isEmpty()) ++ KWin__ZoomEffectConfigForm->setObjectName("KWin__ZoomEffectConfigForm"); ++ KWin__ZoomEffectConfigForm->resize(304, 288); ++ verticalLayout_2 = new QVBoxLayout(KWin__ZoomEffectConfigForm); ++ verticalLayout_2->setObjectName("verticalLayout_2"); ++ groupSize = new QGroupBox(KWin__ZoomEffectConfigForm); ++ groupSize->setObjectName("groupSize"); ++ horizontalLayout = new QHBoxLayout(groupSize); ++ horizontalLayout->setObjectName("horizontalLayout"); ++ gridLayout = new QGridLayout(); ++ gridLayout->setObjectName("gridLayout"); ++ label = new QLabel(groupSize); ++ label->setObjectName("label"); ++ label->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); ++ ++ gridLayout->addWidget(label, 0, 0, 1, 1); ++ ++ kcfg_ZoomFactor = new QDoubleSpinBox(groupSize); ++ kcfg_ZoomFactor->setObjectName("kcfg_ZoomFactor"); ++ kcfg_ZoomFactor->setDecimals(2); ++ kcfg_ZoomFactor->setMaximum(9999.000000000000000); ++ kcfg_ZoomFactor->setSingleStep(0.050000000000000); ++ kcfg_ZoomFactor->setValue(1.250000000000000); ++ ++ gridLayout->addWidget(kcfg_ZoomFactor, 0, 1, 1, 1); ++ ++ kcfg_EnableFocusTracking = new QCheckBox(groupSize); ++ kcfg_EnableFocusTracking->setObjectName("kcfg_EnableFocusTracking"); ++ ++ gridLayout->addWidget(kcfg_EnableFocusTracking, 4, 0, 1, 2); ++ ++ kcfg_EnableTextCaretTracking = new QCheckBox(groupSize); ++ kcfg_EnableTextCaretTracking->setObjectName("kcfg_EnableTextCaretTracking"); ++ ++ gridLayout->addWidget(kcfg_EnableTextCaretTracking, 5, 0, 1, 2); ++ ++ label_2 = new QLabel(groupSize); ++ label_2->setObjectName("label_2"); ++ label_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); ++ ++ gridLayout->addWidget(label_2, 2, 0, 1, 1); ++ ++ kcfg_MousePointer = new QComboBox(groupSize); ++ kcfg_MousePointer->addItem(QString()); ++ kcfg_MousePointer->addItem(QString()); ++ kcfg_MousePointer->addItem(QString()); ++ kcfg_MousePointer->setObjectName("kcfg_MousePointer"); ++ ++ gridLayout->addWidget(kcfg_MousePointer, 2, 1, 1, 1); ++ ++ kcfg_MouseTracking = new QComboBox(groupSize); ++ kcfg_MouseTracking->addItem(QString()); ++ kcfg_MouseTracking->addItem(QString()); ++ kcfg_MouseTracking->addItem(QString()); ++ kcfg_MouseTracking->addItem(QString()); ++ kcfg_MouseTracking->setObjectName("kcfg_MouseTracking"); ++ ++ gridLayout->addWidget(kcfg_MouseTracking, 3, 1, 1, 1); ++ ++ label_3 = new QLabel(groupSize); ++ label_3->setObjectName("label_3"); ++ label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); ++ ++ gridLayout->addWidget(label_3, 3, 0, 1, 1); ++ ++ ++ horizontalLayout->addLayout(gridLayout); ++ ++ ++ verticalLayout_2->addWidget(groupSize); ++ ++ editor = new KShortcutsEditor(KWin__ZoomEffectConfigForm); ++ editor->setObjectName("editor"); ++ QSizePolicy sizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding); ++ sizePolicy.setHorizontalStretch(0); ++ sizePolicy.setVerticalStretch(0); ++ sizePolicy.setHeightForWidth(editor->sizePolicy().hasHeightForWidth()); ++ editor->setSizePolicy(sizePolicy); ++ editor->setActionTypes(KShortcutsEditor::GlobalAction); ++ ++ verticalLayout_2->addWidget(editor); ++ ++#if QT_CONFIG(shortcut) ++ label->setBuddy(kcfg_ZoomFactor); ++ label_2->setBuddy(kcfg_MousePointer); ++ label_3->setBuddy(kcfg_MouseTracking); ++#endif // QT_CONFIG(shortcut) ++ QWidget::setTabOrder(kcfg_ZoomFactor, kcfg_MousePointer); ++ QWidget::setTabOrder(kcfg_MousePointer, kcfg_MouseTracking); ++ QWidget::setTabOrder(kcfg_MouseTracking, kcfg_EnableFocusTracking); ++ QWidget::setTabOrder(kcfg_EnableFocusTracking, kcfg_EnableTextCaretTracking); ++ ++ retranslateUi(KWin__ZoomEffectConfigForm); ++ ++ QMetaObject::connectSlotsByName(KWin__ZoomEffectConfigForm); ++ } // setupUi ++ ++ void retranslateUi(QWidget *KWin__ZoomEffectConfigForm) ++ { ++ groupSize->setTitle(QString()); ++#if QT_CONFIG(whatsthis) ++ label->setWhatsThis(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "On zoom-in and zoom-out change the zoom by the defined zoom-factor.", nullptr)); ++#endif // QT_CONFIG(whatsthis) ++ label->setText(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Zoom Factor:", nullptr)); ++#if QT_CONFIG(whatsthis) ++ kcfg_ZoomFactor->setWhatsThis(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "On zoom-in and zoom-out change the zoom by the defined zoom-factor.", nullptr)); ++#endif // QT_CONFIG(whatsthis) ++ kcfg_ZoomFactor->setSuffix(QString()); ++#if QT_CONFIG(tooltip) ++ kcfg_EnableFocusTracking->setToolTip(QString()); ++#endif // QT_CONFIG(tooltip) ++#if QT_CONFIG(whatsthis) ++ kcfg_EnableFocusTracking->setWhatsThis(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Enable tracking of the focused location. This needs QAccessible to be enabled per application (\"export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1\").", nullptr)); ++#endif // QT_CONFIG(whatsthis) ++ kcfg_EnableFocusTracking->setText(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Enable Focus Tracking", nullptr)); ++#if QT_CONFIG(whatsthis) ++ kcfg_EnableTextCaretTracking->setWhatsThis(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Enable tracking of the text cursor. This needs QAccessible to be enabled per application (\"export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1\").", nullptr)); ++#endif // QT_CONFIG(whatsthis) ++ kcfg_EnableTextCaretTracking->setText(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Enable Text Cursor Tracking", nullptr)); ++ label_2->setText(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Mouse Pointer:", nullptr)); ++ kcfg_MousePointer->setItemText(0, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Scale", nullptr)); ++ kcfg_MousePointer->setItemText(1, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Keep", nullptr)); ++ kcfg_MousePointer->setItemText(2, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Hide", nullptr)); ++ ++#if QT_CONFIG(whatsthis) ++ kcfg_MousePointer->setWhatsThis(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Visibility of the mouse-pointer.", nullptr)); ++#endif // QT_CONFIG(whatsthis) ++ kcfg_MouseTracking->setItemText(0, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Proportional", nullptr)); ++ kcfg_MouseTracking->setItemText(1, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Centered", nullptr)); ++ kcfg_MouseTracking->setItemText(2, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Push", nullptr)); ++ kcfg_MouseTracking->setItemText(3, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Disabled", nullptr)); ++ ++#if QT_CONFIG(whatsthis) ++ kcfg_MouseTracking->setWhatsThis(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Track moving of the mouse.", nullptr)); ++#endif // QT_CONFIG(whatsthis) ++ label_3->setText(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Mouse Tracking:", nullptr)); ++ (void)KWin__ZoomEffectConfigForm; ++ } // retranslateUi ++ ++}; ++ ++} // namespace KWin ++ ++namespace KWin { ++namespace Ui { ++ class ZoomEffectConfigForm: public Ui_ZoomEffectConfigForm {}; ++} // namespace Ui ++} // namespace KWin ++ ++#endif // UI_ZOOM_CONFIG_H +diff --git a/src/plugins/zoom/zoom.cpp b/src/plugins/zoom/zoom.cpp +index a6eb528767..950583c15b 100644 +--- a/src/plugins/zoom/zoom.cpp ++++ b/src/plugins/zoom/zoom.cpp +@@ -31,6 +31,12 @@ + + using namespace std::chrono_literals; + ++static void ensureResources() ++{ ++ // Must initialize resources manually because the effect is a static lib. ++ Q_INIT_RESOURCE(zoom); ++} ++ + namespace KWin + { + +@@ -48,6 +54,8 @@ ZoomEffect::ZoomEffect() + , moveFactor(20.0) + , lastPresentTime(std::chrono::milliseconds::zero()) + { ++ ensureResources(); ++ + ZoomConfig::instance(effects->config()); + QAction *a = nullptr; + a = KStandardAction::zoomIn(this, SLOT(zoomIn()), this); +@@ -214,6 +222,7 @@ void ZoomEffect::reconfigure(ReconfigureFlags) + ZoomConfig::self()->read(); + // On zoom-in and zoom-out change the zoom by the defined zoom-factor. + zoomFactor = std::max(0.1, ZoomConfig::zoomFactor()); ++ m_pixelGridZoom = ZoomConfig::pixelGridZoom(); + // Visibility of the mouse-pointer. + mousePointer = MousePointerType(ZoomConfig::mousePointer()); + // Track moving of the mouse. +@@ -271,12 +280,10 @@ void ZoomEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseco + + ZoomEffect::OffscreenData *ZoomEffect::ensureOffscreenData(const RenderTarget &renderTarget, const RenderViewport &viewport, Output *screen) + { +- const QRect rect = viewport.renderRect().toRect(); +- const qreal devicePixelRatio = viewport.scale(); +- const QSize nativeSize = (viewport.renderRect().size() * devicePixelRatio).toSize(); ++ const QSize nativeSize = renderTarget.size(); + + OffscreenData &data = m_offscreenData[effects->waylandDisplay() ? screen : nullptr]; +- data.viewport = rect; ++ data.viewport = viewport.renderRect(); + data.color = renderTarget.colorDescription(); + + const GLenum textureFormat = renderTarget.colorDescription() == ColorDescription::sRGB ? GL_RGBA8 : GL_RGBA16F; +@@ -290,9 +297,22 @@ ZoomEffect::OffscreenData *ZoomEffect::ensureOffscreenData(const RenderTarget &r + data.framebuffer = std::make_unique(data.texture.get()); + } + ++ data.texture->setContentTransform(renderTarget.transform()); + return &data; + } + ++GLShader *ZoomEffect::shaderForZoom(double zoom) ++{ ++ if (zoom < m_pixelGridZoom) { ++ return ShaderManager::instance()->shader(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace); ++ } else { ++ if (!m_pixelGridShader) { ++ m_pixelGridShader = ShaderManager::instance()->generateShaderFromFile(ShaderTrait::MapTexture, QString(), QStringLiteral(":/effects/zoom/shaders/pixelgrid.frag")); ++ } ++ return m_pixelGridShader.get(); ++ } ++} ++ + void ZoomEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen) + { + OffscreenData *offscreenData = ensureOffscreenData(renderTarget, viewport, screen); +@@ -391,7 +411,8 @@ void ZoomEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewp + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + +- auto shader = ShaderManager::instance()->pushShader(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace); ++ GLShader *shader = shaderForZoom(zoom); ++ ShaderManager::instance()->pushShader(shader); + for (auto &[screen, offscreen] : m_offscreenData) { + QMatrix4x4 matrix; + matrix.translate(xTranslation * scale, yTranslation * scale); +@@ -399,6 +420,8 @@ void ZoomEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewp + matrix.translate(offscreen.viewport.x() * scale, offscreen.viewport.y() * scale); + + shader->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, viewport.projectionMatrix() * matrix); ++ shader->setUniform(GLShader::IntUniform::TextureWidth, offscreen.texture->width()); ++ shader->setUniform(GLShader::IntUniform::TextureHeight, offscreen.texture->height()); + shader->setColorspaceUniforms(offscreen.color, renderTarget.colorDescription(), RenderingIntent::Perceptual); + + offscreen.texture->render(offscreen.viewport.size() * scale); +diff --git a/src/plugins/zoom/zoom.h b/src/plugins/zoom/zoom.h +index 2a44395d74..1c9abb4b4e 100644 +--- a/src/plugins/zoom/zoom.h ++++ b/src/plugins/zoom/zoom.h +@@ -26,6 +26,7 @@ class ZoomAccessibilityIntegration; + class GLFramebuffer; + class GLTexture; + class GLVertexBuffer; ++class GLShader; + + class ZoomEffect + : public Effect +@@ -94,7 +95,7 @@ private: + { + std::unique_ptr texture; + std::unique_ptr framebuffer; +- QRect viewport; ++ QRectF viewport; + ColorDescription color = ColorDescription::sRGB; + }; + +@@ -102,6 +103,8 @@ private: + OffscreenData *ensureOffscreenData(const RenderTarget &renderTarget, const RenderViewport &viewport, Output *screen); + void markCursorTextureDirty(); + ++ GLShader *shaderForZoom(double zoom); ++ + #if HAVE_ACCESSIBILITY + ZoomAccessibilityIntegration *m_accessibilityIntegration = nullptr; + #endif +@@ -136,6 +139,8 @@ private: + double moveFactor; + std::chrono::milliseconds lastPresentTime; + std::map m_offscreenData; ++ std::unique_ptr m_pixelGridShader; ++ double m_pixelGridZoom; + }; + + } // namespace +diff --git a/src/plugins/zoom/zoom.kcfg b/src/plugins/zoom/zoom.kcfg +index 63887e32aa..ed43e225c8 100644 +--- a/src/plugins/zoom/zoom.kcfg ++++ b/src/plugins/zoom/zoom.kcfg +@@ -29,5 +29,8 @@ + + 1.0 + ++ ++ 15.0 ++ + + +diff --git a/src/plugins/zoom/zoom.qrc b/src/plugins/zoom/zoom.qrc +new file mode 100644 +index 0000000000..56e7369003 +--- /dev/null ++++ b/src/plugins/zoom/zoom.qrc +@@ -0,0 +1,6 @@ ++ ++ ++ shaders/pixelgrid.frag ++ shaders/pixelgrid_core.frag ++ ++ +diff --git a/src/plugins/zoom/zoom_config.ui b/src/plugins/zoom/zoom_config.ui +index 454f9f9161..4b8a5c000e 100644 +--- a/src/plugins/zoom/zoom_config.ui ++++ b/src/plugins/zoom/zoom_config.ui +@@ -6,159 +6,157 @@ + + 0 + 0 +- 304 +- 288 ++ 595 ++ 551 + + + + +- +- +- ++ ++ ++ Qt::AlignHCenter|Qt::AlignTop + +- +- +- +- +- +- +- On zoom-in and zoom-out change the zoom by the defined zoom-factor. +- +- +- Zoom Factor: +- +- +- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter +- +- +- kcfg_ZoomFactor +- +- +- +- +- +- +- On zoom-in and zoom-out change the zoom by the defined zoom-factor. +- +- +- +- +- +- 2 +- +- +- 9999.000000000000000 +- +- +- 0.050000000000000 +- +- +- 1.250000000000000 +- +- +- +- +- +- +- +- +- +- Enable tracking of the focused location. This needs QAccessible to be enabled per application ("export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1"). +- +- +- Enable Focus Tracking +- +- +- +- +- +- +- Enable tracking of the text cursor. This needs QAccessible to be enabled per application ("export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1"). +- +- +- Enable Text Cursor Tracking +- +- +- +- +- +- +- Mouse Pointer: +- +- +- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter +- +- +- kcfg_MousePointer +- +- +- +- +- +- +- Visibility of the mouse-pointer. +- +- +- +- Scale +- +- +- +- +- Keep +- +- +- +- +- Hide +- +- +- +- +- +- +- +- Track moving of the mouse. +- +- +- +- Proportional +- +- +- +- +- Centered +- +- +- +- +- Push +- +- +- +- +- Disabled +- +- +- +- +- +- +- +- Mouse Tracking: +- +- +- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter +- +- +- kcfg_MouseTracking +- +- +- +- +- +- +- ++ ++ ++ ++ On zoom-in and zoom-out change the zoom by the defined zoom-factor. ++ ++ ++ Zoom factor: ++ ++ ++ kcfg_ZoomFactor ++ ++ ++ ++ ++ ++ ++ On zoom-in and zoom-out change the zoom by the defined zoom-factor. ++ ++ ++ ++ ++ ++ 2 ++ ++ ++ 9999.000000000000000 ++ ++ ++ 0.050000000000000 ++ ++ ++ 1.250000000000000 ++ ++ ++ ++ ++ ++ ++ Show pixel grid at zoom level: ++ ++ ++ kcfg_PixelGridZoom ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Mouse pointer: ++ ++ ++ kcfg_MousePointer ++ ++ ++ ++ ++ ++ ++ Visibility of the mouse-pointer. ++ ++ ++ ++ Scale ++ ++ ++ ++ ++ Keep ++ ++ ++ ++ ++ Hide ++ ++ ++ ++ ++ ++ ++ ++ Mouse tracking: ++ ++ ++ kcfg_MouseTracking ++ ++ ++ ++ ++ ++ ++ Track moving of the mouse. ++ ++ ++ ++ Proportional ++ ++ ++ ++ ++ Centered ++ ++ ++ ++ ++ Push ++ ++ ++ ++ ++ Disabled ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Enable tracking of the focused location. This needs QAccessible to be enabled per application ("export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1"). ++ ++ ++ Enable focus tracking ++ ++ ++ ++ ++ ++ ++ Enable tracking of the text cursor. This needs QAccessible to be enabled per application ("export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1"). ++ ++ ++ Enable text cursor tracking ++ ++ ++ ++ + + + +@@ -183,13 +181,6 @@ + 1 + + +- +- kcfg_ZoomFactor +- kcfg_MousePointer +- kcfg_MouseTracking +- kcfg_EnableFocusTracking +- kcfg_EnableTextCaretTracking +- + + + diff --git a/roles/kde/programs/kwin.nix b/roles/kde/programs/kwin.nix index 2d6a747..9b1a64c 100644 --- a/roles/kde/programs/kwin.nix +++ b/roles/kde/programs/kwin.nix @@ -9,6 +9,7 @@ kPrev.kwin.patches ++ [ ../patches/kwin-pr6406.patch + ../patches/kwin-pr6878.patch ]; }; } From ba2d6eb02af1af922dfa120299c15906286c255b Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 19 Dec 2024 00:47:20 +0100 Subject: [PATCH 0865/1125] Kde/kwin: add kwin pr 6844 --- roles/kde/patches/kwin-pr6844.patch | 41 +++++++++++++++++++++++++++++ roles/kde/programs/kwin.nix | 1 + 2 files changed, 42 insertions(+) create mode 100644 roles/kde/patches/kwin-pr6844.patch diff --git a/roles/kde/patches/kwin-pr6844.patch b/roles/kde/patches/kwin-pr6844.patch new file mode 100644 index 0000000..f6e5e63 --- /dev/null +++ b/roles/kde/patches/kwin-pr6844.patch @@ -0,0 +1,41 @@ +diff --git a/src/plugins/private/expolayout.cpp b/src/plugins/private/expolayout.cpp +index 52e8bd6616..d4f2a41acc 100644 +--- a/src/plugins/private/expolayout.cpp ++++ b/src/plugins/private/expolayout.cpp +@@ -7,6 +7,7 @@ + + #include "expolayout.h" + ++#include + #include + #include + #include +@@ -41,6 +42,12 @@ ExpoCell::~ExpoCell() + void ExpoCell::componentComplete() + { + QQuickItem::componentComplete(); ++ ++ QQmlProperty xProperty(this, "Kirigami.ScenePosition.x", qmlContext(this)); ++ xProperty.connectNotifySignal(this, SLOT(updateContentItemGeometry())); ++ QQmlProperty yProperty(this, "Kirigami.ScenePosition.y", qmlContext(this)); ++ yProperty.connectNotifySignal(this, SLOT(updateContentItemGeometry())); ++ + updateContentItemGeometry(); + } + +diff --git a/src/plugins/private/expolayout.h b/src/plugins/private/expolayout.h +index 0d4f9d5cde..d980c2aabb 100644 +--- a/src/plugins/private/expolayout.h ++++ b/src/plugins/private/expolayout.h +@@ -264,8 +264,10 @@ Q_SIGNALS: + void persistentKeyChanged(); + void bottomMarginChanged(); + +-private: ++private Q_SLOTS: + void updateContentItemGeometry(); ++ ++private: + void updateLayout(); + + QString m_persistentKey; diff --git a/roles/kde/programs/kwin.nix b/roles/kde/programs/kwin.nix index 9b1a64c..e7dd2b7 100644 --- a/roles/kde/programs/kwin.nix +++ b/roles/kde/programs/kwin.nix @@ -10,6 +10,7 @@ ++ [ ../patches/kwin-pr6406.patch ../patches/kwin-pr6878.patch + ../patches/kwin-pr6844.patch ]; }; } From 2d4374899c54c0a080bba4e7ce4a6e54f0fb9053 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 19 Dec 2024 00:47:48 +0100 Subject: [PATCH 0866/1125] Kde/plasma: add plasma_desktop pr 2661 --- roles/kde/patches/plasma_desktop-pr2661.patch | 39 +++++++++++++++++++ roles/kde/plasma.nix | 7 ++++ 2 files changed, 46 insertions(+) create mode 100644 roles/kde/patches/plasma_desktop-pr2661.patch diff --git a/roles/kde/patches/plasma_desktop-pr2661.patch b/roles/kde/patches/plasma_desktop-pr2661.patch new file mode 100644 index 0000000..b2ce58d --- /dev/null +++ b/roles/kde/patches/plasma_desktop-pr2661.patch @@ -0,0 +1,39 @@ +From 5301b211fc87f1b2253e87da61ff82618be9e899 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Niccol=C3=B2=20Venerandi?= +Date: Thu, 5 Dec 2024 16:12:58 +0100 +Subject: [PATCH] Only return valid task item size if task manager has been + resized to fit panel + +Previously the task manager would briefly have null width and height, before +being resized to fit the panel. However, the "preferredMaxWidth" for tasks +would still be positive, as it adds margins to it, and tasks would then +assume a positive width. When the proper values are set, this casuses +an extra resize animation. + +CCBUG:447476 +--- + .../taskmanager/package/contents/ui/code/layoutmetrics.js | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/applets/taskmanager/package/contents/ui/code/layoutmetrics.js b/applets/taskmanager/package/contents/ui/code/layoutmetrics.js +index c7f11c99a6..895cc725d2 100644 +--- a/applets/taskmanager/package/contents/ui/code/layoutmetrics.js ++++ b/applets/taskmanager/package/contents/ui/code/layoutmetrics.js +@@ -63,8 +63,14 @@ function preferredMinWidth() { + function preferredMaxWidth() { + if (tasks.iconsOnly) { + if (tasks.vertical) { ++ if (tasks.width === 0) { ++ return 0 ++ } + return tasks.width + verticalMargins(); + } else { ++ if (tasks.height === 0) { ++ return 0 ++ } + return tasks.height + horizontalMargins(); + } + } +-- +GitLab + diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 9c8943c..8339715 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -56,6 +56,13 @@ in { ./patches/plasma_workspace-pr4883.patch ]; }; + plasma-desktop = kPrev.plasma-desktop.overrideAttrs { + patches = + kPrev.plasma-desktop.patches + ++ [ + ./patches/plasma_desktop-pr2661.patch + ]; + }; } ); } From 3733eb8b3a43af986acedf33d1c2aeec6bfb47d3 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 12 Dec 2024 10:26:31 +0100 Subject: [PATCH 0867/1125] Server: add changedetection-io --- roles/server/changedetection-io.nix | 31 +++++++++++++++++++++++++++++ roles/server/default.nix | 1 + 2 files changed, 32 insertions(+) create mode 100755 roles/server/changedetection-io.nix diff --git a/roles/server/changedetection-io.nix b/roles/server/changedetection-io.nix new file mode 100755 index 0000000..3eae202 --- /dev/null +++ b/roles/server/changedetection-io.nix @@ -0,0 +1,31 @@ +{...}: { + services.changedetection-io = { + enable = true; + baseURL = "changedetection.everest.tailscale"; + behindProxy = true; + playwrightSupport = true; + }; + systemd.services.changedetection-io.serviceConfig.Environment = [ + "HIDE_REFERER=false" + ]; + + # Add a record for changedetection-io + services.headscale.settings.dns.extra_records = [ + { + name = "changedetection.everest.tailscale"; + type = "A"; + value = "100.100.0.1"; + } + ]; + + # Set up caddy as the reverse proxy for changedetection-io + services.caddy.virtualHosts.changedetection-io = { + hostName = "changedetection.everest.tailscale"; + extraConfig = '' + import tailscale + reverse_proxy localhost:5000 { + header_up Referer {header.Referer} + } + ''; + }; +} diff --git a/roles/server/default.nix b/roles/server/default.nix index 3596f3a..7b3787d 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -16,5 +16,6 @@ ./rust_motd.nix ./minecraft.nix ./adguard.nix + ./changedetection-io.nix ]; } From 135cd0642b706fb47b4b86e8727d28161b7018ae Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 24 Dec 2024 14:46:51 +0100 Subject: [PATCH 0868/1125] Gaming/syncthing: sync project eden save files --- roles/gaming/services/syncthing.nix | 6 ++++++ roles/server/syncthing.nix | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/roles/gaming/services/syncthing.nix b/roles/gaming/services/syncthing.nix index 77bbd87..7b27b67 100644 --- a/roles/gaming/services/syncthing.nix +++ b/roles/gaming/services/syncthing.nix @@ -17,6 +17,12 @@ devices = ["steamdeck" "server" "pc" "winmax2"]; path = "~/.local/share/Steam/steamapps/common/Hatsune Miku Project DIVA Mega Mix Plus/mods/"; }; + "project-eden-saves" = { + label = "Project Eden saves"; + id = "xa3qx-3ax5k"; + devices = ["server" "pc" "winmax2" "steamdeck"]; + path = "~/.local/share/Steam/steamapps/compatdata/1761390/pfx/drive_c/users/steamuser/AppData/Roaming/EDEN/"; + }; }; home-manager.users.toast.home.file."steam-201810-ignore" = { target = ".local/share/Steam/steamapps/compatdata/201810/pfx/drive_c/users/steamuser/Saved Games/MachineGames/Wolfenstein The New Order/.stignore"; diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 50e1857..fe174f1 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -38,6 +38,12 @@ devices = ["server" "pc" "winmax2" "imac"]; path = "${config.services.syncthing.dataDir}/school-things"; }; + "project-eden-saves" = { + label = "Project Eden saves"; + id = "xa3qx-3ax5k"; + devices = ["server" "pc" "winmax2" "steamdeck"]; + path = "${config.services.syncthing.dataDir}/project-eden-saves"; + }; }; }; systemd.services.syncthing.serviceConfig = { From 62cf076375d9843974688f19e5fc404461666d8b Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 29 Dec 2024 16:05:51 +0100 Subject: [PATCH 0869/1125] Gaming: don't add games to the store --- roles/gaming/programs/cemu.nix | 14 ------------ roles/gaming/programs/pcsx2.nix | 35 +++-------------------------- roles/gaming/programs/retroarch.nix | 29 +----------------------- 3 files changed, 4 insertions(+), 74 deletions(-) diff --git a/roles/gaming/programs/cemu.nix b/roles/gaming/programs/cemu.nix index 80178f8..588fd39 100644 --- a/roles/gaming/programs/cemu.nix +++ b/roles/gaming/programs/cemu.nix @@ -2,20 +2,6 @@ home-manager.users.toast = { home = { packages = [pkgs.cemu]; - file = { - "Games/Isos/Wii U/Kirby and the Rainbow Paintbrush.wux".source = ( - pkgs.fetchurl { - url = "http://dl.everest.tailscale/Wii%20U/Kirby%20and%20the%20Rainbow%20Paintbrush.wux"; - hash = "sha256-taPGf709N2p3GlqqT92+SbOeD7QNKFUfB9X5urWVQps="; - } - ); - "Games/Isos/Wii U/Mario Kary 8.wux".source = ( - pkgs.fetchurl { - url = "http://dl.everest.tailscale/Wii%20U/Mario%20Kart%208.wux"; - hash = "sha256-O6lOkLUKPZi+FiEWJQQEeiEXOo+GTUecoSpGjE811k0="; - } - ); - }; }; }; } diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index b378ca2..4bf28a4 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -3,44 +3,15 @@ lib, ... }: let - ps2-isos = pkgs.symlinkJoin { - name = "ps2-isos"; - paths = - lib.lists.forEach [ - (pkgs.fetchzip { - url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202/007%20-%20Nightfire%20%28USA%29.zip"; - hash = "sha256-66Ey0SqC3Tk02Af+xR6rpxYSkO0n83NWYPCt4M3CUWo="; - }) - (pkgs.fetchzip { - url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202/TimeSplitters%202%20%28USA%29.zip"; - hash = "sha256-UPED4/MF9fjTOgiIJy+CSbuO9cJr3CsR/gEquY6GfsU="; - }) - ] - compress; - }; - - compress = iso: - pkgs.runCommand "compressed-ps2-isos" {} '' - mkdir $out - cd ${iso} - for file in ./* - do - ${pkgs.mame-tools}/bin/chdman createdvd -i "$file" -o "$out/''${file%.iso}.chd" - done - ''; - pcsx2-bios = pkgs.fetchzip { url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202%20-%20BIOS%20Images/ps2-0200a-20040614.zip"; hash = "sha256-wMvswgmsKl+cJl49VlVW84tvU5Jzd+2dl07SOiUDtwA="; }; in { home-manager.users.toast = { - home = { - packages = with pkgs; [ - pcsx2 - ]; - file."Games/Isos/PS2".source = ps2-isos; - }; + home.packages = with pkgs; [ + pcsx2 + ]; xdg.configFile = { #PCSX2 silently overwrites the symlink so I need to force it's creation "PCSX2/inis/PCSX2.ini".force = true; diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index ffa46a3..f9263cd 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -1,22 +1,4 @@ -{pkgs, ...}: let - snes-roms = [ - # ActRaiser - (pkgs.fetchzip { - url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/ActRaiser%20%28USA%29.zip"; - hash = "sha256-yxIL5Pqlp8xsx7wvNO1MlB8ffDjS0xpE+yrEfMj61As="; - }) - # Kirby Super Star - (pkgs.fetchzip { - url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/Kirby%20Super%20Star%20%28USA%29.zip"; - hash = "sha256-NX5OjCthf4ZiAhamclRBRk8GiMjZX3JLeShm8sQdDfc="; - }) - # Super Mario Kart - (pkgs.fetchzip { - url = "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/Super%20Mario%20Kart%20%28USA%29.zip"; - hash = "sha256-RLBxPBmBrXCuPdnWE07KamBNgGJ5IntQVUPeij+2HUI="; - }) - ]; -in { +{pkgs, ...}: { home-manager.users.toast = { home = { packages = [ @@ -62,15 +44,6 @@ in { } ) ]; - file."Games/Roms/SNES/" = { - onChange = '' - ${pkgs.retroarch}/bin/retroarch --scan "/home/toast/Games/Roms/SNES" - ''; - source = pkgs.symlinkJoin { - name = "snes-roms"; - paths = [snes-roms]; - }; - }; }; # Retroarch is dumb since it doesn't generate some folders (but it does for others) systemd.user.tmpfiles.rules = [ From 68994153d03c6aa6fc849f9dc9b842594bb04f75 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 29 Dec 2024 16:08:08 +0100 Subject: [PATCH 0870/1125] Gaming/pcsx2: fix typos in syncthing ignore file --- roles/gaming/programs/pcsx2.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index 4bf28a4..b6ac4b2 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -121,10 +121,10 @@ in { }; home-manager.users.toast.xdg.configFile = { "PCSX2/.stignore".text = '' - cahe + cache bios gamesettings - inis/PCSX2.int* + inis/PCSX2.ini* inis/debuggersettings inputprofiles logs From fcba25620bb19e8f05dd8b1e06487a2051db825c Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 29 Dec 2024 16:09:15 +0100 Subject: [PATCH 0871/1125] Gaming/syncthing: sync games with syncthing --- roles/gaming/services/syncthing.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/gaming/services/syncthing.nix b/roles/gaming/services/syncthing.nix index 7b27b67..0219bac 100644 --- a/roles/gaming/services/syncthing.nix +++ b/roles/gaming/services/syncthing.nix @@ -23,6 +23,12 @@ devices = ["server" "pc" "winmax2" "steamdeck"]; path = "~/.local/share/Steam/steamapps/compatdata/1761390/pfx/drive_c/users/steamuser/AppData/Roaming/EDEN/"; }; + "games" = { + label = "Games"; + id = "mwzph-gf2df"; + devices = ["server" "pc" "winmax2" "steamdeck"]; + path = "~/Games"; + }; }; home-manager.users.toast.home.file."steam-201810-ignore" = { target = ".local/share/Steam/steamapps/compatdata/201810/pfx/drive_c/users/steamuser/Saved Games/MachineGames/Wolfenstein The New Order/.stignore"; From 16d339171490231188ee9cd180e077898b07e6fe Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 29 Dec 2024 16:10:02 +0100 Subject: [PATCH 0872/1125] Gaming/retroarch: update retroarch library automatically --- roles/gaming/programs/retroarch.nix | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/roles/gaming/programs/retroarch.nix b/roles/gaming/programs/retroarch.nix index f9263cd..60f4bb7 100644 --- a/roles/gaming/programs/retroarch.nix +++ b/roles/gaming/programs/retroarch.nix @@ -51,6 +51,28 @@ "d /%h/.local/share/retroarch/saves" "d /%h/.local/share/retroarch/states" ]; + systemd.user.paths = { + snes-roms = { + Unit.Description = "Monitor SNES rom path for changes"; + Path = { + PathChanged = "/%h/Games/SNES"; + Unit = "update-retroarch-library.service"; + }; + Install.WantedBy = ["default.target"]; + }; + }; + systemd.user.services.update-retroarch-library = { + Service = { + Type = "oneshot"; + ExecStart = pkgs.writeShellScript "scan-snes-games" '' + ${pkgs.libnotify}/bin/notify-send -a RetroArch \ + -i retroarch \ + "SNES games changed!" \ + "Scanning $TRIGGER_PATH..." + ${pkgs.retroarch}/bin/retroarch --scan "/home/toast/Games/SNES" + ''; + }; + }; }; # Sync saves and some other stuff From 7eeff4c125f9cd9cca2465d4db8540e1965369e2 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 29 Dec 2024 16:13:33 +0100 Subject: [PATCH 0873/1125] Server/syncthing: add games folder --- roles/server/syncthing.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index fe174f1..84d20cc 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -44,6 +44,12 @@ devices = ["server" "pc" "winmax2" "steamdeck"]; path = "${config.services.syncthing.dataDir}/project-eden-saves"; }; + "games" = { + label = "Games"; + id = "jxuou-2yjnu"; + devices = ["steamdeck" "server" "pc" "winmax2"]; + path = "${config.services.syncthing.dataDir}/games"; + }; }; }; systemd.services.syncthing.serviceConfig = { From 98ebbcfbd3434e296b930a5aee33d4c86d7062a8 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 2 Jan 2025 20:32:06 +0100 Subject: [PATCH 0874/1125] Server/minecraft: remove --- roles/server/default.nix | 1 - roles/server/minecraft.nix | 34 ---------------------------------- 2 files changed, 35 deletions(-) delete mode 100644 roles/server/minecraft.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index 7b3787d..2ad30f6 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -14,7 +14,6 @@ ./headscale.nix ./caddy.nix ./rust_motd.nix - ./minecraft.nix ./adguard.nix ./changedetection-io.nix ]; diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix deleted file mode 100644 index 1db04a1..0000000 --- a/roles/server/minecraft.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ - pkgs, - lib, - ... -}: { - nixpkgs.config.allowUnfreePredicate = pkg: - builtins.elem (lib.getName pkg) [ - "minecraft-server" - ]; - - users.users.toast.extraGroups = ["minecraft"]; - - services.minecraft-servers = { - enable = true; - eula = true; - openFirewall = true; - servers = { - vrlocals = { - enable = true; - package = pkgs.fabricServers.fabric-1_20_1; - jvmOpts = "-Xmx8G"; - serverProperties = { - motd = "\\u00A7aBigChadGuys \\u00A7lPlus \\u00A7a(w/Cobblemon!) v2.8.1\\u00A7r\\n\\u00A76Have fun!"; - server-port = 25565; - level-seed = "-1450714289616987871"; - white-list = true; - spawn-protection = 0; - enable-command-block = true; - sync-chunk-writes = false; - }; - }; - }; - }; -} From 21c8f8c7e4e4a7e54a9a437e1293b28a9d3aa4e0 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 2 Jan 2025 21:24:50 +0100 Subject: [PATCH 0875/1125] Machines/Everest: remove unneeded firewall options --- machines/Everest/configuration.nix | 7 ------- 1 file changed, 7 deletions(-) diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index fdacf1b..49e1805 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -53,11 +53,4 @@ }; }; }; - - # Open ports in the firewall. - # No idea what ports 5201 and 21027 do tho - networking.firewall.allowedTCPPorts = [5201]; - networking.firewall.allowedUDPPorts = [5201 21027]; - # Or disable the firewall altogether. - # networking.firewall.enable = false; } From 74ed35e5f4608d965a92efd0692174c3e9cda72f Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 2 Jan 2025 22:51:52 +0100 Subject: [PATCH 0876/1125] Server/caddy: adjust systemd restart parameters --- roles/server/caddy.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index f7697fc..0f2edea 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -64,7 +64,8 @@ in { # ages to boot up. If I don't add a delay, caddy tries to bind to # the tailscale interface before it's ready, making it crash too much # in too little time - services.caddy.serviceConfig.RestartSec = lib.mkForce "240s"; + services.caddy.serviceConfig.RestartSec = lib.mkForce "120s"; + services.caddy.unitConfig.StartLimitBurst = lib.mkForce "infinity"; }; programs.rust-motd.settings.service_status.Caddy = "caddy"; networking.firewall.allowedTCPPorts = [443 80]; From a275c8d43e35bdea4e0af6a6351766c7e4da7b62 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 2 Jan 2025 22:59:37 +0100 Subject: [PATCH 0877/1125] Common/syncthing: open firewall ports --- roles/common/services/syncthing.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index e181fe7..9f191a1 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -62,4 +62,8 @@ in { }; }; }; + networking.firewall = { + allowedTCPPorts = [22000]; + allowedUDPPorts = [22000 21027]; + }; } From c396ca74003dc582b1b288b447be80bf07064f28 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 4 Jan 2025 01:57:25 +0100 Subject: [PATCH 0878/1125] Common/helix: disable nano --- roles/common/programs/helix.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index b603369..738fe65 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -3,6 +3,7 @@ config, ... }: { + programs.nano.enable = false; home-manager.users.toast = { programs.helix = { enable = true; From a1d47a2744c10da444974c7bdbd6c7f37a745cfb Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 4 Jan 2025 02:32:18 +0100 Subject: [PATCH 0879/1125] Common: update catppuccin options --- roles/common/configuration.nix | 2 +- roles/common/programs/bat.nix | 6 +++--- roles/common/programs/btop.nix | 6 ++---- roles/common/programs/fish.nix | 6 ++---- roles/common/programs/git.nix | 6 ++---- roles/common/programs/helix.nix | 8 ++++---- 6 files changed, 14 insertions(+), 20 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index ec4abbd..4084ae6 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -154,7 +154,7 @@ ]; }; - boot.loader.grub.catppuccin.enable = true; + catppuccin.grub.enable = true; /* I used to keep the host keys in the repo as a secret, but since I use the diff --git a/roles/common/programs/bat.nix b/roles/common/programs/bat.nix index cce65c9..068cc1d 100644 --- a/roles/common/programs/bat.nix +++ b/roles/common/programs/bat.nix @@ -1,8 +1,8 @@ {...}: { home-manager = { - users.toast.programs.bat = { - enable = true; - catppuccin.enable = true; + users.toast = { + programs.bat.enable = true; + catppuccin.bat.enable = true; }; }; } diff --git a/roles/common/programs/btop.nix b/roles/common/programs/btop.nix index 1e25cbe..75fd33b 100644 --- a/roles/common/programs/btop.nix +++ b/roles/common/programs/btop.nix @@ -1,10 +1,8 @@ {...}: { home-manager = { users.toast = { - programs.btop = { - enable = true; - catppuccin.enable = true; - }; + catppuccin.btop.enable = true; + programs.btop.enable = true; }; }; } diff --git a/roles/common/programs/fish.nix b/roles/common/programs/fish.nix index 25c43cd..3bafd1c 100644 --- a/roles/common/programs/fish.nix +++ b/roles/common/programs/fish.nix @@ -4,9 +4,7 @@ }; home-manager.users.toast = { - programs.fish = { - enable = true; - catppuccin.enable = true; - }; + catppuccin.fish.enable = true; + programs.fish.enable = true; }; } diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index 037bc6d..0ef96f3 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -9,15 +9,13 @@ enable = true; userName = "Toast"; userEmail = "toast003@tutamail.com"; - delta = { - enable = true; - catppuccin.enable = true; - }; + delta.enable = true; extraConfig = { init.defaultBranch = "main"; diff.colorMoved = "default"; commit.verbose = "true"; }; }; + catppuccin.delta.enable = true; }; } diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index 738fe65..ed430a0 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -5,6 +5,10 @@ }: { programs.nano.enable = false; home-manager.users.toast = { + catppuccin.helix = { + enable = true; + useItalics = true; + }; programs.helix = { enable = true; defaultEditor = true; @@ -13,10 +17,6 @@ nil taplo ]; - catppuccin = { - enable = true; - useItalics = true; - }; settings = { editor = { mouse = true; From f83298f63261ab657bebcfa33dd03524276ec149 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 4 Jan 2025 02:52:16 +0100 Subject: [PATCH 0880/1125] Flake: update lock file --- flake.lock | 342 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 269 insertions(+), 73 deletions(-) diff --git a/flake.lock b/flake.lock index d6945dd..691c873 100644 --- a/flake.lock +++ b/flake.lock @@ -24,12 +24,21 @@ } }, "catppuccin": { + "inputs": { + "catppuccin-v1_1": "catppuccin-v1_1", + "catppuccin-v1_2": "catppuccin-v1_2", + "home-manager": "home-manager_2", + "home-manager-stable": "home-manager-stable", + "nixpkgs": "nixpkgs", + "nixpkgs-stable": "nixpkgs-stable", + "nuscht-search": "nuscht-search" + }, "locked": { - "lastModified": 1734397929, - "narHash": "sha256-VCTVpU/RlrI9StxzDnqc1R3ZTQloLVALSkiN/Fgiad4=", + "lastModified": 1735895235, + "narHash": "sha256-MtsfkMikkPjnZUMqsqXQ29cHzlRD2lMe27jXua28cHU=", "owner": "catppuccin", "repo": "nix", - "rev": "21310cde33d3ee8023679dec01a9724a346c63ff", + "rev": "b326f48f17023fc0060590ba299d55f7da8350a5", "type": "github" }, "original": { @@ -54,14 +63,42 @@ "type": "github" } }, + "catppuccin-v1_1": { + "locked": { + "lastModified": 1734055249, + "narHash": "sha256-pCWJgwo77KD7EJpwynwKrWPZ//dwypHq2TfdzZWqK68=", + "rev": "7221d6ca17ac36ed20588e1c3a80177ac5843fa7", + "revCount": 326, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/catppuccin/nix/1.1.1/0193bdc0-b045-7eed-bbec-95611a8ecdf5/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/catppuccin/nix/1.1.%2A.tar.gz" + } + }, + "catppuccin-v1_2": { + "locked": { + "lastModified": 1734728407, + "narHash": "sha256-Let3uJo4YDyfqbqaw66dpZxhJB2TrDyZWSFd5rpPLJA=", + "rev": "23ee86dbf4ed347878115a78971d43025362fab1", + "revCount": 341, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/catppuccin/nix/1.2.0/0193e5e0-33b7-7149-a362-bfe56b20f64e/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/catppuccin/nix/1.2.%2A.tar.gz" + } + }, "eza-themes": { "flake": false, "locked": { - "lastModified": 1733264582, - "narHash": "sha256-PJ0zSmAiS2iK3bW/HJ7YtYjjLvkgBSAhbbMezjHU0yA=", + "lastModified": 1735244910, + "narHash": "sha256-sfQLMjtAcYTLAA664v6CaYlkoBCPtykhzSQCrcMEA2c=", "owner": "eza-community", "repo": "eza-themes", - "rev": "78601bf47075a8b3681f7b4a7fbe5e258ad469f8", + "rev": "39c1a6640ceaaa4b59f354e1cb229c292a199e68", "type": "github" }, "original": { @@ -147,6 +184,24 @@ "inputs": { "systems": "systems_4" }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_5" + }, "locked": { "lastModified": 1681202837, "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", @@ -212,30 +267,11 @@ "type": "github" } }, - "home-manager-unstable": { + "home-manager-stable": { "inputs": { "nixpkgs": [ - "nixpkgs-unstable-raw" - ] - }, - "locked": { - "lastModified": 1734344598, - "narHash": "sha256-wNX3hsScqDdqKWOO87wETUEi7a/QlPVgpC/Lh5rFOuA=", - "owner": "nix-community", - "repo": "home-manager", - "rev": "83ecd50915a09dca928971139d3a102377a8d242", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "home-manager", - "type": "github" - } - }, - "home-manager_2": { - "inputs": { - "nixpkgs": [ - "nixpkgs-raw" + "catppuccin", + "nixpkgs-stable" ] }, "locked": { @@ -253,6 +289,96 @@ "type": "github" } }, + "home-manager-unstable": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable-raw" + ] + }, + "locked": { + "lastModified": 1735900408, + "narHash": "sha256-U+oZBQ3f5fF2hHsupKQH4ihgTKLHgcJh6jEmKDg+W10=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "1c8d4c8d592e8fab4cff4397db5529ec6f078cf9", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "catppuccin", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1734622215, + "narHash": "sha256-OOfI0XhSJGHblfdNDhfnn8QnZxng63rWk9eeJ2tCbiI=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "1395379a7a36e40f2a76e7b9936cc52950baa1be", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_3": { + "inputs": { + "nixpkgs": [ + "nixpkgs-raw" + ] + }, + "locked": { + "lastModified": 1735344290, + "narHash": "sha256-oJDtWPH1oJT34RJK1FSWjwX4qcGOBRkcNQPD0EbSfNM=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "613691f285dad87694c2ba1c9e6298d04736292d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-24.11", + "repo": "home-manager", + "type": "github" + } + }, + "ixx": { + "inputs": { + "flake-utils": [ + "catppuccin", + "nuscht-search", + "flake-utils" + ], + "nixpkgs": [ + "catppuccin", + "nuscht-search", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1729958008, + "narHash": "sha256-EiOq8jF4Z/zQe0QYVc3+qSKxRK//CFHMB84aYrYGwEs=", + "owner": "NuschtOS", + "repo": "ixx", + "rev": "9fd01aad037f345350eab2cd45e1946cc66da4eb", + "type": "github" + }, + "original": { + "owner": "NuschtOS", + "ref": "v0.0.6", + "repo": "ixx", + "type": "github" + } + }, "jovian": { "inputs": { "nix-github-actions": "nix-github-actions", @@ -261,11 +387,11 @@ ] }, "locked": { - "lastModified": 1734162608, - "narHash": "sha256-m2AX+3eiVqIK6uO7GbGY7SFnkkYOlR5fQiNI0eRvWOQ=", + "lastModified": 1735330405, + "narHash": "sha256-MhXgu1oymyjhhZGY9yewNonJknNAjilzMGPY1FfMR7s=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "31bdf4c7c91204d65afbde01146deee0259a8fb7", + "rev": "a86d9cf841eff8b33a05d2bf25788abd8e018dbd", "type": "github" }, "original": { @@ -277,11 +403,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1733932114, - "narHash": "sha256-LN4pgLjGWztTlJ4oDcKWvDuTFeUUVgbmXoZ2EXG20Gw=", - "rev": "92ed9fee7d169febf53ea85961174fc0a22c2115", + "lastModified": 1735572323, + "narHash": "sha256-Wjt+PK15IdaOUoI0sgsRzaNMxKQGSROLe9sOd44+fwM=", + "rev": "5c7ea4f446de58aa64f78087bb4ec26b9c4111aa", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/92ed9fee7d169febf53ea85961174fc0a22c2115.tar.gz?rev=92ed9fee7d169febf53ea85961174fc0a22c2115" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/5c7ea4f446de58aa64f78087bb4ec26b9c4111aa.tar.gz?rev=5c7ea4f446de58aa64f78087bb4ec26b9c4111aa" }, "original": { "type": "tarball", @@ -290,7 +416,7 @@ }, "lix-module": { "inputs": { - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "flakey-profile": "flakey-profile", "lix": [ "lix" @@ -313,7 +439,7 @@ }, "lix-module-unstable": { "inputs": { - "flake-utils": "flake-utils_2", + "flake-utils": "flake-utils_3", "flakey-profile": "flakey-profile_2", "lix": [ "lix" @@ -336,11 +462,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1734128415, - "narHash": "sha256-HLwdVNxpuTsLlM3tCkpbQU6yCehdgf3kOS1G2SDlkzY=", + "lastModified": 1735913600, + "narHash": "sha256-370z+WLVnD7LrN/SvTCZxPl/XPTshS5NS2dHN4iyK6o=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "8bdc2540da516006d07b04019eb57ae0781a04b3", + "rev": "78ed84ff81e8d8510926e7165d508bcacef49ff1", "type": "github" }, "original": { @@ -374,11 +500,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1734200366, - "narHash": "sha256-0NursoP4BUdnc+wy+Mq3icHkXu/RgP1Sjo0MJxV2+Dw=", + "lastModified": 1734945620, + "narHash": "sha256-olIfsfJK4/GFmPH8mXMmBDAkzVQ1TWJmeGT3wBGfQPY=", "owner": "nix-community", "repo": "impermanence", - "rev": "c6323585fa0035d780e3d8906eb1b24b65d19a48", + "rev": "d000479f4f41390ff7cf9204979660ad5dd16176", "type": "github" }, "original": { @@ -394,11 +520,11 @@ ] }, "locked": { - "lastModified": 1734234111, - "narHash": "sha256-icEMqBt4HtGH52PU5FHidgBrNJvOfXH6VQKNtnD1aw8=", + "lastModified": 1735443188, + "narHash": "sha256-AydPpRBh8+NOkrLylG7vTsHrGO2b5L7XkMEL5HlzcA8=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "311d6cf3ad3f56cb051ffab1f480b2909b3f754d", + "rev": "55ab1e1df5daf2476e6b826b69a82862dcbd7544", "type": "github" }, "original": { @@ -414,11 +540,11 @@ ] }, "locked": { - "lastModified": 1734234111, - "narHash": "sha256-icEMqBt4HtGH52PU5FHidgBrNJvOfXH6VQKNtnD1aw8=", + "lastModified": 1735443188, + "narHash": "sha256-AydPpRBh8+NOkrLylG7vTsHrGO2b5L7XkMEL5HlzcA8=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "311d6cf3ad3f56cb051ffab1f480b2909b3f754d", + "rev": "55ab1e1df5daf2476e6b826b69a82862dcbd7544", "type": "github" }, "original": { @@ -430,17 +556,17 @@ "nix-minecraft": { "inputs": { "flake-compat": "flake-compat", - "flake-utils": "flake-utils_3", + "flake-utils": "flake-utils_4", "nixpkgs": [ "nixpkgs-raw" ] }, "locked": { - "lastModified": 1734314370, - "narHash": "sha256-9PhjDAAuXP4tuJg+kM1AozKwBFyHHJ8ZqhQD+peqGtg=", + "lastModified": 1735868792, + "narHash": "sha256-gt0XDvCl5WwQ6+vo4oz4ELz4mXNnr3Hmb0dkdqfqpxE=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "616634de04e87b621bc3d495af114c4e9c6ccd36", + "rev": "04a8ea0bf27da393e4e0b9fd53e1837b8712a0ff", "type": "github" }, "original": { @@ -451,11 +577,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1734352517, - "narHash": "sha256-mfv+J/vO4nqmIOlq8Y1rRW8hVsGH3M+I2ESMjhuebDs=", + "lastModified": 1735388221, + "narHash": "sha256-e5IOgjQf0SZcFCEV/gMGrsI0gCJyqOKShBQU0iiM3Kg=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "b12e314726a4226298fe82776b4baeaa7bcf3dcd", + "rev": "7c674c6734f61157e321db595dbfcd8523e04e19", "type": "github" }, "original": { @@ -469,13 +595,13 @@ "locked": { "lastModified": 1734424634, "narHash": "sha256-cHar1vqHOOyC7f1+tVycPoWTfKIaqkoe1Q6TnKzuti4=", - "owner": "nixos", + "owner": "NixOS", "repo": "nixpkgs", "rev": "d3c42f187194c26d9f0309a8ecc469d6c878ce33", "type": "github" }, "original": { - "owner": "nixos", + "owner": "NixOS", "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" @@ -483,11 +609,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1734323986, - "narHash": "sha256-m/lh6hYMIWDYHCAsn81CDAiXoT3gmxXI9J987W5tZrE=", + "lastModified": 1735669367, + "narHash": "sha256-tfYRbFhMOnYaM4ippqqid3BaLOXoFNdImrfBfCp4zn0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "394571358ce82dff7411395829aa6a3aad45b907", + "rev": "edf04b75c13c2ac0e54df5ec5c543e300f76f1c9", "type": "github" }, "original": { @@ -496,13 +622,29 @@ "type": "indirect" } }, - "nixpkgs-unstable-raw": { + "nixpkgs-stable": { "locked": { - "lastModified": 1734424634, - "narHash": "sha256-cHar1vqHOOyC7f1+tVycPoWTfKIaqkoe1Q6TnKzuti4=", + "lastModified": 1734600368, + "narHash": "sha256-nbG9TijTMcfr+au7ZVbKpAhMJzzE2nQBYmRvSdXUD8g=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d3c42f187194c26d9f0309a8ecc469d6c878ce33", + "rev": "b47fd6fa00c6afca88b8ee46cfdb00e104f50bca", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable-raw": { + "locked": { + "lastModified": 1735834308, + "narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6df24922a1400241dae323af55f30e4318a6ca65", "type": "github" }, "original": { @@ -511,18 +653,34 @@ "type": "indirect" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1735471104, + "narHash": "sha256-0q9NGQySwDQc7RhAV2ukfnu7Gxa5/ybJ2ANT8DQrQrs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "88195a94f390381c6afcdaa933c2f6ff93959cb4", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "nur": { "inputs": { "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs", + "nixpkgs": "nixpkgs_2", "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1734529681, - "narHash": "sha256-pe/fHd6nuz8nxwyVsLDDilgy+0rXJ1iYhCFojFlV8QE=", + "lastModified": 1735920791, + "narHash": "sha256-DPP/ioDJ283YMxU+U+URmTPECHLrFRUcXG2pbKA/MNY=", "owner": "nix-community", "repo": "NUR", - "rev": "29cbfd0aad3f30ed30312668b3d8dca522175349", + "rev": "3af14b22ef7fa1eeb169840d9ee3010a43ed61ea", "type": "github" }, "original": { @@ -531,6 +689,29 @@ "type": "github" } }, + "nuscht-search": { + "inputs": { + "flake-utils": "flake-utils", + "ixx": "ixx", + "nixpkgs": [ + "catppuccin", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733773348, + "narHash": "sha256-Y47y+LesOCkJaLvj+dI/Oa6FAKj/T9sKVKDXLNsViPw=", + "owner": "NuschtOS", + "repo": "search", + "rev": "3051be7f403bff1d1d380e4612f0c70675b44fc9", + "type": "github" + }, + "original": { + "owner": "NuschtOS", + "repo": "search", + "type": "github" + } + }, "plasma-manager": { "inputs": { "home-manager": [ @@ -541,11 +722,11 @@ ] }, "locked": { - "lastModified": 1733858086, - "narHash": "sha256-h2BDIDKiqgMpA6E+mu0RgMGy3FeM6k+EuJ9xgOQ1+zw=", + "lastModified": 1735049224, + "narHash": "sha256-fWUd9kyXdepphJ7cCzOsuSo7l0kbFCkUqfgKqZyFZzE=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "7e2010249529931a3848054d5ff0dbf24675ab68", + "rev": "d16bbded0ae452bc088489e7dca3ef58d8d1830b", "type": "github" }, "original": { @@ -560,7 +741,7 @@ "catppuccin": "catppuccin", "catppuccin-konsole": "catppuccin-konsole", "eza-themes": "eza-themes", - "home-manager": "home-manager_2", + "home-manager": "home-manager_3", "home-manager-unstable": "home-manager-unstable", "jovian": "jovian", "lix": "lix", @@ -655,6 +836,21 @@ "type": "github" } }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "treefmt-nix": { "inputs": { "nixpkgs": [ From dca3d05aec12196b17ee9d739385f56332ee374a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 3 Jan 2025 18:20:02 +0100 Subject: [PATCH 0881/1125] Server/forgejo: enable repo indexer --- roles/server/forgejo.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index d202b88..7dc3911 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -41,6 +41,9 @@ in { DEFAULT_PUSH_CREATE_PRIVATE = true; DEFAULT_BRANCH = "main"; }; + indexer = { + REPO_INDEXER_ENABLED = true; + }; }; }; From ebbbc8da585418c664c3924931f937e9f500b59a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 3 Jan 2025 18:56:00 +0100 Subject: [PATCH 0882/1125] Server/caddy: precompress the NixOS manual --- roles/server/caddy.nix | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index 0f2edea..6542295 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -1,6 +1,7 @@ { config, lib, + pkgs, ... }: let manualHostname = "manual.everest.tailscale"; @@ -31,10 +32,14 @@ in { virtualHosts = { nixos-manual = { hostName = manualHostname; - extraConfig = '' + extraConfig = let + manual = pkgs.compressDrvWeb config.system.build.manual.manualHTML {}; + in '' import tailscale - file_server - root * ${config.system.build.manual.manualHTML}/share/doc/nixos + file_server { + precompressed zstd br gzip + } + root * ${manual}/share/doc/nixos ''; }; downloads = { From 335205338f8a8ed5543cc991401c5c53436bb3e5 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 4 Jan 2025 02:26:25 +0100 Subject: [PATCH 0883/1125] Server/forgejo: upgrade to non lts version --- roles/server/forgejo.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index 7dc3911..9a69380 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -2,6 +2,7 @@ config, lib, flakeSelf, + pkgs, ... }: let hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName + "/"; @@ -24,6 +25,7 @@ in { specialisation.forgejoEnableRegistration.configuration.services.forgejo.settings.service.DISABLE_REGISTRATION = false; services.forgejo = { enable = true; + package = pkgs.forgejo; settings = { service = { DISABLE_REGISTRATION = lib.mkDefault true; From fb7b164a6cd86aa4276fe38283455d028319acc6 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 7 Jan 2025 09:54:31 +0100 Subject: [PATCH 0884/1125] Common/atuin: change options --- roles/common/programs/atuin.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/common/programs/atuin.nix b/roles/common/programs/atuin.nix index ecfe0b9..105f79b 100644 --- a/roles/common/programs/atuin.nix +++ b/roles/common/programs/atuin.nix @@ -2,8 +2,9 @@ home-manager.users.toast.programs.atuin = { enable = true; settings = { - enter_accept = false; + enter_accept = true; workspaces = true; + style = "auto"; stats = { common_prefix = [ "sudo" From 710e431dad3d179b763f854e04e9907aa2d82a5d Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 9 Jan 2025 09:43:01 +0100 Subject: [PATCH 0885/1125] Machines/WinMax2: add boot debugging specialisation --- machines/WinMax2/configuration.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index e5a8782..366ed21 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -146,4 +146,13 @@ # (/run/current-system/configuration.nix). This is useful in case you # accidentally delete configuration.nix. # system.copySystemConfiguration = true; + specialisation.bootDebug.configuration = { + boot.kernelParams = [ + "systemd.debug-shell=1" + "systemd.log_level=debug" + "systemd.log_target=kmsg" + "log_buf_len=1M" + "printk.devkmsg=on" + ]; + }; } From a2bce9715d31555170a937ece451c0397b85c1dc Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 8 Jan 2025 13:25:27 +0100 Subject: [PATCH 0886/1125] Server: add prometheus with node exporter --- roles/server/default.nix | 1 + roles/server/prometheus.nix | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 roles/server/prometheus.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index 2ad30f6..e705ce0 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -15,6 +15,7 @@ ./caddy.nix ./rust_motd.nix ./adguard.nix + ./prometheus.nix ./changedetection-io.nix ]; } diff --git a/roles/server/prometheus.nix b/roles/server/prometheus.nix new file mode 100644 index 0000000..9512e29 --- /dev/null +++ b/roles/server/prometheus.nix @@ -0,0 +1,24 @@ +{...}: { + services.prometheus = { + enable = true; + enableReload = true; + exporters = { + node = { + enable = true; + enabledCollectors = ["systemd"]; + listenAddress = "127.0.0.1"; + port = 9002; + }; + }; + scrapeConfigs = [ + { + job_name = "everest-node"; + static_configs = [ + { + targets = ["127.0.0.1:9002"]; + } + ]; + } + ]; + }; +} From 88235bb32ef4ddd28a1c5c03bda32cee8cd785f8 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 8 Jan 2025 13:50:10 +0100 Subject: [PATCH 0887/1125] Server: add grafana --- roles/server/default.nix | 1 + roles/server/grafana.nix | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 roles/server/grafana.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index e705ce0..2048887 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -15,6 +15,7 @@ ./caddy.nix ./rust_motd.nix ./adguard.nix + ./grafana.nix ./prometheus.nix ./changedetection-io.nix ]; diff --git a/roles/server/grafana.nix b/roles/server/grafana.nix new file mode 100644 index 0000000..940a9ae --- /dev/null +++ b/roles/server/grafana.nix @@ -0,0 +1,30 @@ +{config, ...}: let + domain = "monitoring.everest.tailscale"; +in { + users.users.caddy.extraGroups = ["grafana"]; + services = { + grafana = { + enable = true; + settings = { + server = { + protocol = "socket"; + }; + }; + }; + + headscale.settings.dns.extra_records = [ + { + name = domain; + type = "A"; + value = "100.100.0.1"; + } + ]; + caddy.virtualHosts.grafana = { + hostName = domain; + extraConfig = '' + import tailscale + reverse_proxy unix/${config.services.grafana.settings.server.socket} + ''; + }; + }; +} From bd0d7e54954bda314d6151804678a4b543e8bfdf Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 9 Jan 2025 09:51:15 +0100 Subject: [PATCH 0888/1125] Server/endlessh: don't open firewall, add prometheus integration --- roles/server/endlessh.nix | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/roles/server/endlessh.nix b/roles/server/endlessh.nix index 9650d7c..f1d9ecd 100755 --- a/roles/server/endlessh.nix +++ b/roles/server/endlessh.nix @@ -1,8 +1,20 @@ -{...}: { +{config,...}: { # I prefer using the go implementation services.endlessh-go = { enable = true; - openFirewall = true; + prometheus = { + enable = true; + listenAddress = "127.0.0.1"; + }; extraOptions = ["-alsologtostderr" "-v=1"]; }; + + services.prometheus.scrapeConfigs = [ + { + job_name = "everest-endlessh"; + static_configs = [ + {targets = ["127.0.0.1:${builtins.toString config.services.endlessh-go.prometheus.port}"];} + ]; + } + ]; } From c66d7c21da58ff9a3db4fe839de6553cefeaf948 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 9 Jan 2025 09:58:30 +0100 Subject: [PATCH 0889/1125] Flake: add nixpkgs pr --- flake.nix | 4 ++- .../fix-endlessh-dns-resolution.patch | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 nixpkgs-patches/fix-endlessh-dns-resolution.patch diff --git a/flake.nix b/flake.nix index 586e9f5..0e82d41 100644 --- a/flake.nix +++ b/flake.nix @@ -108,7 +108,9 @@ nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; src = nixpkgs-raw; - patches = []; + patches = [ + ./nixpkgs-patches/fix-endlessh-dns-resolution.patch + ]; }; # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs {self = inputs.nixpkgs-unstable-raw;}; diff --git a/nixpkgs-patches/fix-endlessh-dns-resolution.patch b/nixpkgs-patches/fix-endlessh-dns-resolution.patch new file mode 100644 index 0000000..dc55d97 --- /dev/null +++ b/nixpkgs-patches/fix-endlessh-dns-resolution.patch @@ -0,0 +1,31 @@ +From 99778e1bb590c984d91f39322e57d59220402c59 Mon Sep 17 00:00:00 2001 +From: azahi +Date: Wed, 8 Jan 2025 13:47:09 +0300 +Subject: [PATCH] nixos/endlessh-go: fix DNS resolution + +As suggested by toast003[1]. + +[1]: https://github.com/shizunge/endlessh-go/discussions/127#discussioncomment-11760912 +--- + nixos/modules/services/security/endlessh-go.nix | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/nixos/modules/services/security/endlessh-go.nix b/nixos/modules/services/security/endlessh-go.nix +index b8b51acc81d0e..5c69d412a7d3c 100644 +--- a/nixos/modules/services/security/endlessh-go.nix ++++ b/nixos/modules/services/security/endlessh-go.nix +@@ -110,7 +110,13 @@ in + ); + DynamicUser = true; + RootDirectory = rootDirectory; +- BindReadOnlyPaths = [ builtins.storeDir ]; ++ BindReadOnlyPaths = [ ++ builtins.storeDir ++ "-/etc/hosts" ++ "-/etc/localtime" ++ "-/etc/nsswitch.conf" ++ "-/etc/resolv.conf" ++ ]; + InaccessiblePaths = [ "-+${rootDirectory}" ]; + RuntimeDirectory = baseNameOf rootDirectory; + RuntimeDirectoryMode = "700"; From 8933b405d43655966e0d7263b20cf54e85fb5e24 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 9 Jan 2025 10:17:38 +0100 Subject: [PATCH 0890/1125] Server/endlessh: disable stderr logging, enable geoip --- roles/server/endlessh.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/endlessh.nix b/roles/server/endlessh.nix index f1d9ecd..80492bb 100755 --- a/roles/server/endlessh.nix +++ b/roles/server/endlessh.nix @@ -6,7 +6,7 @@ enable = true; listenAddress = "127.0.0.1"; }; - extraOptions = ["-alsologtostderr" "-v=1"]; + extraOptions = ["-geoip_supplier ip-api"]; }; services.prometheus.scrapeConfigs = [ From 5631236aff75db80e6c37be93ff2150d7ebf83ff Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 9 Jan 2025 11:06:50 +0100 Subject: [PATCH 0891/1125] Flake: udate secrets --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 691c873..c45c883 100644 --- a/flake.lock +++ b/flake.lock @@ -763,11 +763,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1731258517, - "narHash": "sha256-zqYyWyZYK2FsRhqDRaZPmP6IqJ6QRXK37jthHcMAe+8=", + "lastModified": 1736417093, + "narHash": "sha256-3MRzAQaYpggkWuhZBofBjDQm02NGhUk1K4LJhf9z4k0=", "ref": "refs/heads/main", - "rev": "4d6184cf5e78978e26839690af7e1a3ff9af92ae", - "revCount": 25, + "rev": "48d048bb2089631e758072561d95b4b7d1130178", + "revCount": 27, "type": "git", "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets" }, From c154d91613ef8d9d5106ef75c9b144f1c7debf37 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 9 Jan 2025 11:07:02 +0100 Subject: [PATCH 0892/1125] Server/grafana: configure default username and password --- roles/server/grafana.nix | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/roles/server/grafana.nix b/roles/server/grafana.nix index 940a9ae..030fddb 100644 --- a/roles/server/grafana.nix +++ b/roles/server/grafana.nix @@ -1,11 +1,33 @@ -{config, ...}: let +{ + config, + flakeSelf, + ... +}: let domain = "monitoring.everest.tailscale"; in { users.users.caddy.extraGroups = ["grafana"]; + age.secrets = let + hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName + "/"; + in { + grafanaAdminName = { + file = hostSecrets + "grafana/admin_name.age"; + owner = "grafana"; + group = "grafana"; + }; + grafanaAdminPassword= { + file = hostSecrets + "grafana/admin_password.age"; + owner = "grafana"; + group = "grafana"; + }; + }; services = { grafana = { enable = true; settings = { + security = { + admin_user = "$__file{${config.age.secrets.grafanaAdminName.path}}"; + admin_password = "$__file{${config.age.secrets.grafanaAdminPassword.path}}"; + }; server = { protocol = "socket"; }; From daf1e39df35dffb5fd6513a1c44c4b60f9ec9565 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 9 Jan 2025 11:15:41 +0100 Subject: [PATCH 0893/1125] Justfile: remove update-input recipe --- .justfile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.justfile b/.justfile index 09e5f48..99e2d75 100644 --- a/.justfile +++ b/.justfile @@ -14,14 +14,10 @@ print-recipes: update: nix flake update -# Update a single input -update-input input: - nix flake lock --update-input {{input}} - @edit-secrets: git clone ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets.git /tmp/secrets sed -i 's\git+ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets\/tmp/secrets\g' flake.nix - just -q update-input secrets + nix flake update secrets echo "{{bold}}All done!" echo "{{normal}}Remember to restore flake.nix" echo "" From 3d4deae65a7f41baf2fa137beb3e1dbdcd43b24d Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 10 Jan 2025 10:10:47 +0100 Subject: [PATCH 0894/1125] Server/grafana: disable telemetry --- roles/server/grafana.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/server/grafana.nix b/roles/server/grafana.nix index 030fddb..336b23d 100644 --- a/roles/server/grafana.nix +++ b/roles/server/grafana.nix @@ -14,7 +14,7 @@ in { owner = "grafana"; group = "grafana"; }; - grafanaAdminPassword= { + grafanaAdminPassword = { file = hostSecrets + "grafana/admin_password.age"; owner = "grafana"; group = "grafana"; @@ -24,6 +24,7 @@ in { grafana = { enable = true; settings = { + analytics.reporting_enabled = false; security = { admin_user = "$__file{${config.age.secrets.grafanaAdminName.path}}"; admin_password = "$__file{${config.age.secrets.grafanaAdminPassword.path}}"; From d65b4380e77bfe7fe5175f1e8e808a6d45389eaf Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 10 Jan 2025 10:45:40 +0100 Subject: [PATCH 0895/1125] Server/grafana: provision prometheus datasource --- roles/server/grafana.nix | 8 ++++++++ roles/server/prometheus.nix | 9 ++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/roles/server/grafana.nix b/roles/server/grafana.nix index 336b23d..a09ff0e 100644 --- a/roles/server/grafana.nix +++ b/roles/server/grafana.nix @@ -23,6 +23,14 @@ in { services = { grafana = { enable = true; + + provision = { + enable = true; + datasources.settings = { + apiVersion = 1; + }; + }; + settings = { analytics.reporting_enabled = false; security = { diff --git a/roles/server/prometheus.nix b/roles/server/prometheus.nix index 9512e29..999d9c6 100644 --- a/roles/server/prometheus.nix +++ b/roles/server/prometheus.nix @@ -1,4 +1,4 @@ -{...}: { +{config, ...}: { services.prometheus = { enable = true; enableReload = true; @@ -21,4 +21,11 @@ } ]; }; + services.grafana.provision = { + datasources.settings.datasources = [{ + name = "Prometheus"; + type = "prometheus"; + url = "http://127.0.0.1:${builtins.toString config.services.prometheus.port}"; + }]; + }; } From 67989ca1a8acc3e465c4b7c238ee4938fab4a12b Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 10 Jan 2025 11:26:57 +0100 Subject: [PATCH 0896/1125] Server/endlessh: open firewal I got confused and closed the firewall thinking it was for the prometheus metrics --- roles/server/endlessh.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/endlessh.nix b/roles/server/endlessh.nix index 80492bb..6c56997 100755 --- a/roles/server/endlessh.nix +++ b/roles/server/endlessh.nix @@ -2,6 +2,7 @@ # I prefer using the go implementation services.endlessh-go = { enable = true; + openFirewall = true; prometheus = { enable = true; listenAddress = "127.0.0.1"; From d93a2a7993994c728fbc90955a793a3369612669 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 4 Jan 2025 12:40:02 +0100 Subject: [PATCH 0897/1125] Flake: remove nix-minecraft --- flake.lock | 72 ------------------------------------------------------ flake.nix | 5 ---- 2 files changed, 77 deletions(-) diff --git a/flake.lock b/flake.lock index c45c883..40c00a4 100644 --- a/flake.lock +++ b/flake.lock @@ -107,22 +107,6 @@ "type": "github" } }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, "flake-parts": { "inputs": { "nixpkgs-lib": [ @@ -198,24 +182,6 @@ "type": "github" } }, - "flake-utils_4": { - "inputs": { - "systems": "systems_5" - }, - "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "flakey-profile": { "locked": { "lastModified": 1712898590, @@ -553,28 +519,6 @@ "type": "github" } }, - "nix-minecraft": { - "inputs": { - "flake-compat": "flake-compat", - "flake-utils": "flake-utils_4", - "nixpkgs": [ - "nixpkgs-raw" - ] - }, - "locked": { - "lastModified": 1735868792, - "narHash": "sha256-gt0XDvCl5WwQ6+vo4oz4ELz4mXNnr3Hmb0dkdqfqpxE=", - "owner": "Infinidoge", - "repo": "nix-minecraft", - "rev": "04a8ea0bf27da393e4e0b9fd53e1837b8712a0ff", - "type": "github" - }, - "original": { - "owner": "Infinidoge", - "repo": "nix-minecraft", - "type": "github" - } - }, "nixos-hardware": { "locked": { "lastModified": 1735388221, @@ -751,7 +695,6 @@ "nix-impermanence": "nix-impermanence", "nix-index-db": "nix-index-db", "nix-index-db-unstable": "nix-index-db-unstable", - "nix-minecraft": "nix-minecraft", "nixos-hardware": "nixos-hardware", "nixpkgs-raw": "nixpkgs-raw", "nixpkgs-unstable-raw": "nixpkgs-unstable-raw", @@ -836,21 +779,6 @@ "type": "github" } }, - "systems_5": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, "treefmt-nix": { "inputs": { "nixpkgs": [ diff --git a/flake.nix b/flake.nix index 0e82d41..1ad8d71 100644 --- a/flake.nix +++ b/flake.nix @@ -73,11 +73,6 @@ inputs.lix.follows = "lix"; }; - nix-minecraft = { - url = "github:Infinidoge/nix-minecraft"; - inputs.nixpkgs.follows = "nixpkgs-raw"; - }; - # Non flake inputs / random things lix = { url = "https://git.lix.systems/lix-project/lix/archive/main.tar.gz"; From 24f4f270c1380aeada31c6ac50fc6dba0e9994b9 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 10 Jan 2025 19:51:00 +0100 Subject: [PATCH 0898/1125] Server/grafana: set root url --- roles/server/grafana.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/grafana.nix b/roles/server/grafana.nix index a09ff0e..99eb5d9 100644 --- a/roles/server/grafana.nix +++ b/roles/server/grafana.nix @@ -39,6 +39,7 @@ in { }; server = { protocol = "socket"; + root_url = "https://${domain}"; }; }; }; From 36ac10c6dd963654ce983a6fddc88e473d57ccd5 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 10 Jan 2025 20:02:29 +0100 Subject: [PATCH 0899/1125] Server/grafana: change security settings --- roles/server/grafana.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/server/grafana.nix b/roles/server/grafana.nix index 99eb5d9..957c41b 100644 --- a/roles/server/grafana.nix +++ b/roles/server/grafana.nix @@ -36,6 +36,9 @@ in { security = { admin_user = "$__file{${config.age.secrets.grafanaAdminName.path}}"; admin_password = "$__file{${config.age.secrets.grafanaAdminPassword.path}}"; + cookie_secure = true; + strict_transport_security = true; + content_security_policy = true; }; server = { protocol = "socket"; From 904bb98f3661c15b60aa7e3d3223d97e92bc8f37 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 13 Jan 2025 12:44:37 +0100 Subject: [PATCH 0900/1125] Flake: fully remove nix-minecraft references --- flake.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/flake.nix b/flake.nix index 1ad8d71..d18b3ac 100644 --- a/flake.nix +++ b/flake.nix @@ -219,8 +219,6 @@ Everest = { stable = true; modules = [ - nix-minecraft.nixosModules.minecraft-servers - {nixpkgs.overlays = [nix-minecraft.overlay];} ./roles/server ]; }; From d713ba1f155633983538d0596e049927c99a1d8c Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 14 Jan 2025 10:45:11 +0100 Subject: [PATCH 0901/1125] Flake: add nixpkgs patch --- flake.nix | 4 +- nixpkgs-patches/update-hhd.patch | 102 +++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 nixpkgs-patches/update-hhd.patch diff --git a/flake.nix b/flake.nix index d18b3ac..f05c44b 100644 --- a/flake.nix +++ b/flake.nix @@ -98,7 +98,9 @@ nixpkgs-unstable-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; - patches = []; + patches = [ + ./nixpkgs-patches/update-hhd.patch + ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; diff --git a/nixpkgs-patches/update-hhd.patch b/nixpkgs-patches/update-hhd.patch new file mode 100644 index 0000000..7857a3f --- /dev/null +++ b/nixpkgs-patches/update-hhd.patch @@ -0,0 +1,102 @@ +From 87eb53c446492fbd4ace80bda5bb6ec94c1e19e6 Mon Sep 17 00:00:00 2001 +From: Toast <39011842+toast003@users.noreply.github.com> +Date: Tue, 14 Jan 2025 10:18:45 +0100 +Subject: [PATCH] handheld-daemon: 3.9.0 -> 3.10.2 + +--- + .../0001-remove-selinux-fixes.patch | 37 +++++++++++++++++++ + pkgs/by-name/ha/handheld-daemon/package.nix | 19 ++++++++-- + 2 files changed, 52 insertions(+), 4 deletions(-) + create mode 100644 pkgs/by-name/ha/handheld-daemon/0001-remove-selinux-fixes.patch + +diff --git a/pkgs/by-name/ha/handheld-daemon/0001-remove-selinux-fixes.patch b/pkgs/by-name/ha/handheld-daemon/0001-remove-selinux-fixes.patch +new file mode 100644 +index 0000000000000..2fe3ae78a1a47 +--- /dev/null ++++ b/pkgs/by-name/ha/handheld-daemon/0001-remove-selinux-fixes.patch +@@ -0,0 +1,37 @@ ++diff --git a/src/hhd/plugins/power/power.py b/src/hhd/plugins/power/power.py ++index 5ece857..be41542 100644 ++--- a/src/hhd/plugins/power/power.py +++++ b/src/hhd/plugins/power/power.py ++@@ -79,12 +79,6 @@ def create_subvol(): ++ ) ++ return ++ ++- # Fixup selinux for swap ++- subprocess.run( ++- ["semanage", "fcontext", "-a", "-t", "var_t", HHD_SWAP_SUBVOL], ++- ) ++- subprocess.run(["restorecon", HHD_SWAP_SUBVOL]) ++- ++ logger.info(f"Creating swap subvolume {HHD_SWAP_SUBVOL}") ++ os.system(f"btrfs subvolume create {HHD_SWAP_SUBVOL}") ++ ++@@ -153,19 +147,6 @@ def create_temporary_swap(): ++ subprocess.run(["chmod", "600", HHD_SWAP_FILE], check=True) ++ subprocess.run(["mkswap", HHD_SWAP_FILE], check=True) ++ ++- # Fixup selinux for swap ++- subprocess.run( ++- [ ++- "semanage", ++- "fcontext", ++- "-a", ++- "-t", ++- "swapfile_t", ++- HHD_SWAP_FILE, ++- ], ++- ) ++- subprocess.run(["restorecon", HHD_SWAP_FILE]) ++- ++ # Enable swap ++ subprocess.run(["swapon", HHD_SWAP_FILE], check=True) ++ +diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix +index 1c11cd3b59b28..f76b47225d671 100644 +--- a/pkgs/by-name/ha/handheld-daemon/package.nix ++++ b/pkgs/by-name/ha/handheld-daemon/package.nix +@@ -11,19 +11,25 @@ + efibootmgr, + dbus, + lsof, ++ btrfs-progs, ++ util-linux, + }: + python3Packages.buildPythonApplication rec { + pname = "handheld-daemon"; +- version = "3.9.0"; ++ version = "3.10.2"; + pyproject = true; + + src = fetchFromGitHub { + owner = "hhd-dev"; + repo = "hhd"; + tag = "v${version}"; +- hash = "sha256-y3CxdWqQEwdNYs4m1NEUeRjTvvhEpS5S739wyFlluWo="; ++ hash = "sha256-6BjXqqNe2u/rh1cnuJ13L/1KimprcyatIr53b0GOBSM="; + }; + ++ # Handheld-daemon runs some selinux-related utils which are not in nixpkgs. ++ # NixOS doesn't support selinux so we can safely remove them ++ patches = [ ./0001-remove-selinux-fixes.patch ]; ++ + # This package relies on several programs expected to be on the user's PATH. + # We take a more reproducible approach by patching the absolute path to each of these required + # binaries. +@@ -41,8 +47,13 @@ python3Packages.buildPythonApplication rec { + substituteInPlace src/hhd/controller/physical/imu.py \ + --replace-fail '"modprobe' '"${lib.getExe' kmod "modprobe"}' + +- substituteInPlace src/hhd/plugins/overlay/power.py \ +- --replace-fail '"efibootmgr"' '"${lib.getExe' efibootmgr "id"}"' ++ substituteInPlace src/hhd/plugins/power/power.py \ ++ --replace-fail '"efibootmgr"' '"${lib.getExe' efibootmgr "id"}"' \ ++ --replace-fail '"systemctl"' '"${lib.getExe' systemd "systemctl"}"' \ ++ --replace-fail '"stat"' '"${lib.getExe' coreutils "stat"}"' \ ++ --replace-fail '"btrfs"' '"${lib.getExe' btrfs-progs "btrfs"}"' \ ++ --replace-fail '"swapon"' '"${lib.getExe' util-linux "swapon"}"' \ ++ --replace-fail '"swapoff"' '"${lib.getExe' util-linux "swapoff"}"' + + substituteInPlace src/hhd/device/oxp/serial.py \ + --replace-fail "udevadm" "${lib.getExe' systemd "udevadm"}" From a60ca21925a56d1ede100ee3114cb0803f472aae Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 15 Jan 2025 11:04:26 +0100 Subject: [PATCH 0902/1125] Machines/Everest: change ip address and default gateway --- machines/Everest/configuration.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index 49e1805..6cd78cb 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -22,14 +22,14 @@ wakeOnLan.enable = true; ipv4.addresses = [ { - address = "192.168.0.160"; - prefixLength = 24; + address = "10.0.0.2"; + prefixLength = 8; } ]; }; # I use networkd, so I need to declare the interface for the default gateway defaultGateway = { - address = "192.168.0.1"; + address = "10.0.0.1"; interface = "eno1"; }; nameservers = ["9.9.9.9"]; From b6bd1ec321eefd110a59a2ca5e6824123730622d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 14 Jan 2025 13:49:29 +0100 Subject: [PATCH 0903/1125] Flake: update nixpkgs patch --- nixpkgs-patches/update-hhd.patch | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/nixpkgs-patches/update-hhd.patch b/nixpkgs-patches/update-hhd.patch index 7857a3f..65ff661 100644 --- a/nixpkgs-patches/update-hhd.patch +++ b/nixpkgs-patches/update-hhd.patch @@ -1,12 +1,12 @@ -From 87eb53c446492fbd4ace80bda5bb6ec94c1e19e6 Mon Sep 17 00:00:00 2001 +From 32d076a87fa6611f62e050047442564b27d36bc1 Mon Sep 17 00:00:00 2001 From: Toast <39011842+toast003@users.noreply.github.com> Date: Tue, 14 Jan 2025 10:18:45 +0100 Subject: [PATCH] handheld-daemon: 3.9.0 -> 3.10.2 --- .../0001-remove-selinux-fixes.patch | 37 +++++++++++++++++++ - pkgs/by-name/ha/handheld-daemon/package.nix | 19 ++++++++-- - 2 files changed, 52 insertions(+), 4 deletions(-) + pkgs/by-name/ha/handheld-daemon/package.nix | 22 +++++++++-- + 2 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 pkgs/by-name/ha/handheld-daemon/0001-remove-selinux-fixes.patch diff --git a/pkgs/by-name/ha/handheld-daemon/0001-remove-selinux-fixes.patch b/pkgs/by-name/ha/handheld-daemon/0001-remove-selinux-fixes.patch @@ -53,7 +53,7 @@ index 0000000000000..2fe3ae78a1a47 + subprocess.run(["swapon", HHD_SWAP_FILE], check=True) + diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 1c11cd3b59b28..f76b47225d671 100644 +index 1c11cd3b59b28..aad4a57e50c22 100644 --- a/pkgs/by-name/ha/handheld-daemon/package.nix +++ b/pkgs/by-name/ha/handheld-daemon/package.nix @@ -11,19 +11,25 @@ @@ -84,7 +84,7 @@ index 1c11cd3b59b28..f76b47225d671 100644 # This package relies on several programs expected to be on the user's PATH. # We take a more reproducible approach by patching the absolute path to each of these required # binaries. -@@ -41,8 +47,13 @@ python3Packages.buildPythonApplication rec { +@@ -41,8 +47,16 @@ python3Packages.buildPythonApplication rec { substituteInPlace src/hhd/controller/physical/imu.py \ --replace-fail '"modprobe' '"${lib.getExe' kmod "modprobe"}' @@ -94,9 +94,12 @@ index 1c11cd3b59b28..f76b47225d671 100644 + --replace-fail '"efibootmgr"' '"${lib.getExe' efibootmgr "id"}"' \ + --replace-fail '"systemctl"' '"${lib.getExe' systemd "systemctl"}"' \ + --replace-fail '"stat"' '"${lib.getExe' coreutils "stat"}"' \ -+ --replace-fail '"btrfs"' '"${lib.getExe' btrfs-progs "btrfs"}"' \ + --replace-fail '"swapon"' '"${lib.getExe' util-linux "swapon"}"' \ -+ --replace-fail '"swapoff"' '"${lib.getExe' util-linux "swapoff"}"' ++ --replace-fail '"swapoff"' '"${lib.getExe' util-linux "swapoff"}"' \ ++ --replace-fail '"fallocate"' '"${lib.getExe' util-linux "fallocate"}"' \ ++ --replace-fail '"chmod"' '"${lib.getExe' coreutils "chmod"}"' \ ++ --replace-fail '"mkswap"' '"${lib.getExe' util-linux "mkswap"}"' \ ++ --replace-fail '"btrfs",' '"${lib.getExe' btrfs-progs "btrfs"}",' substituteInPlace src/hhd/device/oxp/serial.py \ --replace-fail "udevadm" "${lib.getExe' systemd "udevadm"}" From 77edacc9d441131cc3ab0ce54bdb05896b99d57c Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 17 Jan 2025 22:21:12 +0100 Subject: [PATCH 0904/1125] Roles/kde: add kwin and plasma-workspace patches --- roles/kde/patches/kwin-pr6985.patch | 41 + .../kde/patches/plasma_workspace-pr4965.patch | 915 ++++++++++++++++++ roles/kde/plasma.nix | 1 + roles/kde/programs/kwin.nix | 1 + 4 files changed, 958 insertions(+) create mode 100644 roles/kde/patches/kwin-pr6985.patch create mode 100644 roles/kde/patches/plasma_workspace-pr4965.patch diff --git a/roles/kde/patches/kwin-pr6985.patch b/roles/kde/patches/kwin-pr6985.patch new file mode 100644 index 0000000..95d196d --- /dev/null +++ b/roles/kde/patches/kwin-pr6985.patch @@ -0,0 +1,41 @@ +From 45a5d8844b36404334301f5da6e75f1a345e0c80 Mon Sep 17 00:00:00 2001 +From: Xaver Hugl +Date: Fri, 10 Jan 2025 13:45:30 +0000 +Subject: [PATCH] plugins/screencast: call ItemRenderer::begin/endFrame + +The OpenGL renderer references the explicit sync release points for client buffers +during rendering, and releases them in endFrame. If endFrame never gets called though +(for example because we're doing direct scanout) then the release points never get +signaled, and the client very quickly runs out of buffers to use and freezes. + +BUG: 495287 + + +(cherry picked from commit b1031ea63eaa8c9bf5c70157d1b6bf8eb0f5a74a) + +Co-authored-by: Xaver Hugl +--- + src/plugins/screencast/windowscreencastsource.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/plugins/screencast/windowscreencastsource.cpp b/src/plugins/screencast/windowscreencastsource.cpp +index 24ef92aad7b..b396eed46f9 100644 +--- a/src/plugins/screencast/windowscreencastsource.cpp ++++ b/src/plugins/screencast/windowscreencastsource.cpp +@@ -75,11 +75,11 @@ void WindowScreenCastSource::render(GLFramebuffer *target) + RenderTarget renderTarget(target); + RenderViewport viewport(m_window->clientGeometry(), 1, renderTarget); + +- GLFramebuffer::pushFramebuffer(target); ++ Compositor::self()->scene()->renderer()->beginFrame(renderTarget, viewport); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + Compositor::self()->scene()->renderer()->renderItem(renderTarget, viewport, m_window->windowItem(), Scene::PAINT_WINDOW_TRANSFORMED, infiniteRegion(), WindowPaintData{}); +- GLFramebuffer::popFramebuffer(); ++ Compositor::self()->scene()->renderer()->endFrame(); + } + + std::chrono::nanoseconds WindowScreenCastSource::clock() const +-- +GitLab + diff --git a/roles/kde/patches/plasma_workspace-pr4965.patch b/roles/kde/patches/plasma_workspace-pr4965.patch new file mode 100644 index 0000000..f677504 --- /dev/null +++ b/roles/kde/patches/plasma_workspace-pr4965.patch @@ -0,0 +1,915 @@ +diff --git a/appiumtests/applets/CMakeLists.txt b/appiumtests/applets/CMakeLists.txt +index 19229541aa..6715dd1f8f 100644 +--- a/appiumtests/applets/CMakeLists.txt ++++ b/appiumtests/applets/CMakeLists.txt +@@ -59,7 +59,7 @@ add_test( + NAME notificationstest + COMMAND selenium-webdriver-at-spi-run ${CMAKE_CURRENT_SOURCE_DIR}/notificationstest.py --failfast + ) +-set_tests_properties(notificationstest PROPERTIES TIMEOUT 120) ++set_tests_properties(notificationstest PROPERTIES TIMEOUT 120 ENVIRONMENT "KACTIVITYMANAGERD_PATH=${KDE_INSTALL_FULL_LIBEXECDIR}/kactivitymanagerd;USE_CUSTOM_BUS=1") + + add_test( + NAME digitalclocktest +diff --git a/appiumtests/applets/kicker/favoritetest.py b/appiumtests/applets/kicker/favoritetest.py +new file mode 100755 +index 0000000000..50613c3db1 +--- /dev/null ++++ b/appiumtests/applets/kicker/favoritetest.py +@@ -0,0 +1,162 @@ ++#!/usr/bin/env python3 ++ ++# SPDX-License-Identifier: BSD-3-Clause ++# SPDX-FileCopyrightText: 2022-2023 Harald Sitter ++ ++import logging ++import os ++import shutil ++import subprocess ++import sys ++import tempfile ++import time ++import unittest ++from typing import Final ++ ++from gi.repository import Gio, GLib ++ ++sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir, "utils")) ++from GLibMainLoopThread import GLibMainLoopThread ++ ++KDE_VERSION: Final = 6 ++KACTIVITYMANAGERD_SERVICE_NAME: Final = "org.kde.ActivityManager" ++KACTIVITYMANAGERD_PATH: Final = os.getenv("KACTIVITYMANAGERD_PATH", "/usr/libexec/kactivitymanagerd") ++QMLTEST_EXEC: Final = os.getenv("QMLTEST_EXEC", "/usr/bin/qmltestrunner6") ++ ++ ++def name_has_owner(session_bus: Gio.DBusConnection, name: str) -> bool: ++ """ ++ Whether the given name is available on session bus ++ """ ++ message: Gio.DBusMessage = Gio.DBusMessage.new_method_call("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "NameHasOwner") ++ message.set_body(GLib.Variant("(s)", [name])) ++ reply, _ = session_bus.send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE, 1000) ++ return reply and reply.get_signature() == 'b' and reply.get_body().get_child_value(0).get_boolean() ++ ++ ++def build_ksycoca() -> None: ++ subprocess.check_call([f"kbuildsycoca{KDE_VERSION}"], stdout=sys.stderr, stderr=sys.stderr, env=os.environ) ++ ++ ++def start_kactivitymanagerd() -> subprocess.Popen: ++ session_bus: Gio.DBusConnection = Gio.bus_get_sync(Gio.BusType.SESSION) ++ assert not name_has_owner(session_bus, KACTIVITYMANAGERD_SERVICE_NAME) ++ ++ os.makedirs(os.path.join(GLib.get_user_config_dir(), "menus")) ++ shutil.copy(os.path.join(os.path.dirname(os.path.abspath(__file__)), "applications.menu"), os.path.join(GLib.get_user_config_dir(), "menus")) ++ ++ kactivitymanagerd = subprocess.Popen([KACTIVITYMANAGERD_PATH], stdout=sys.stderr, stderr=sys.stderr, env=os.environ) ++ kactivitymanagerd_started: bool = False ++ for _ in range(10): ++ if name_has_owner(session_bus, KACTIVITYMANAGERD_SERVICE_NAME): ++ kactivitymanagerd_started = True ++ break ++ logging.info("waiting for kactivitymanagerd to appear on the DBus session") ++ time.sleep(1) ++ assert kactivitymanagerd_started ++ ++ build_ksycoca() ++ ++ return kactivitymanagerd ++ ++ ++class TestDBusInterface: ++ """ ++ D-Bus interface for org.kde.kickertest ++ """ ++ ++ BUS_NAME: Final = "org.kde.kickertest" ++ OBJECT_PATH: Final = "/test" ++ INTERFACE_NAME: Final = "org.kde.kickertest" ++ ++ connection: Gio.DBusConnection ++ ++ def __init__(self) -> None: ++ self.reg_id: int = 0 ++ self.owner_id: int = Gio.bus_own_name(Gio.BusType.SESSION, self.BUS_NAME, Gio.BusNameOwnerFlags.NONE, self.on_bus_acquired, None, None) ++ assert self.owner_id > 0 ++ ++ def on_bus_acquired(self, connection: Gio.DBusConnection, name: str, *args) -> None: ++ """ ++ The interface is ready, now register objects. ++ """ ++ self.connection = connection ++ introspection_data = Gio.DBusNodeInfo.new_for_xml(""" ++ ++ ++ ++ ++ ++ ++ ++""") ++ self.reg_id = connection.register_object(self.OBJECT_PATH, introspection_data.interfaces[0], self.handle_method_call, None, None) ++ assert self.reg_id > 0 ++ logging.info("interface registered") ++ ++ def handle_method_call(self, connection: Gio.DBusConnection, sender: str, object_path: str, interface_name: str, method_name: str, parameters: GLib.Variant, invocation: Gio.DBusMethodInvocation) -> None: ++ logging.info("method call %s", method_name) ++ ++ if method_name == "DeleteAndRebuildDatabase1": ++ os.remove(KickerTest.desktop_entry_1) ++ build_ksycoca() ++ invocation.return_value(None) ++ elif method_name == "DeleteAndRebuildDatabase2": ++ os.remove(KickerTest.desktop_entry_2) ++ build_ksycoca() ++ invocation.return_value(None) ++ ++ ++class KickerTest(unittest.TestCase): ++ kactivitymanagerd: subprocess.Popen ++ loop_thread: GLibMainLoopThread ++ dbus_interface: TestDBusInterface ++ ++ temp_dir: tempfile.TemporaryDirectory ++ desktop_entry_1: str ++ desktop_entry_2: str ++ ++ @classmethod ++ def setUpClass(cls) -> None: ++ # Prepare desktop files ++ # 1 ++ os.makedirs(os.path.join(GLib.get_user_data_dir(), "applications")) ++ shutil.copy(os.path.join(os.path.dirname(os.path.abspath(__file__)), "kickertest.desktop"), os.path.join(GLib.get_user_data_dir(), "applications")) ++ cls.desktop_entry_1 = os.path.join(GLib.get_user_data_dir(), "applications", "kickertest.desktop") ++ # 2 ++ cls.temp_dir = tempfile.TemporaryDirectory() ++ os.makedirs(os.path.join(cls.temp_dir.name, "applications")) ++ shutil.copy(os.path.join(os.path.dirname(os.path.abspath(__file__)), "kickertest.desktop"), os.path.join(cls.temp_dir.name, "applications")) ++ cls.desktop_entry_2 = os.path.join(cls.temp_dir.name, "applications", "kickertest.desktop") ++ ++ os.environ["LC_ALL"] = "en_US.UTF-8" ++ os.environ["QT_LOGGING_RULES"] = "org.kde.plasma.kicker.debug=true;kf.coreaddons.kdirwatch.debug=true" ++ os.environ["XDG_DATA_DIRS"] = os.environ["XDG_DATA_DIRS"] + ":" + cls.temp_dir.name ++ ++ cls.kactivitymanagerd = start_kactivitymanagerd() ++ ++ cls.loop_thread = GLibMainLoopThread() ++ cls.loop_thread.start() ++ cls.dbus_interface = TestDBusInterface() ++ ++ @classmethod ++ def tearDownClass(cls) -> None: ++ cls.loop_thread.quit() ++ cls.kactivitymanagerd.kill() ++ cls.kactivitymanagerd.wait(10) ++ ++ def test_qml(self) -> None: ++ """ ++ 1. Add an entry to Favorites ++ 2. Remove the entry from Favorites ++ 3. Hide invalid entries automatically and don't crash when there are multiple entries with the same desktop name ++ """ ++ with subprocess.Popen([QMLTEST_EXEC, "-input", os.path.join(os.path.dirname(os.path.abspath(__file__)), 'favoritetest.qml')], stdout=sys.stderr, stderr=sys.stderr) as process: ++ self.assertEqual(process.wait(60), 0) ++ ++ ++if __name__ == '__main__': ++ assert "USE_CUSTOM_BUS" in os.environ ++ logging.getLogger().setLevel(logging.INFO) ++ unittest.main() +diff --git a/appiumtests/applets/notificationstest.py b/appiumtests/applets/notificationstest.py +index 8917121a94..cd34a32905 100755 +--- a/appiumtests/applets/notificationstest.py ++++ b/appiumtests/applets/notificationstest.py +@@ -5,6 +5,7 @@ + + import base64 + import os ++import shutil + import subprocess + import tempfile + import time +@@ -15,6 +16,7 @@ import gi + from appium import webdriver + from appium.options.common.base import AppiumOptions + from appium.webdriver.common.appiumby import AppiumBy ++from selenium.common.exceptions import (NoSuchElementException, WebDriverException) + from selenium.webdriver.support import expected_conditions as EC + from selenium.webdriver.support.ui import WebDriverWait + +@@ -22,6 +24,8 @@ gi.require_version('Gdk', '4.0') + gi.require_version('GdkPixbuf', '2.0') + from gi.repository import Gdk, GdkPixbuf, Gio, GLib + ++from kicker.favoritetest import start_kactivitymanagerd ++ + WIDGET_ID: Final = "org.kde.plasma.notifications" + KDE_VERSION: Final = 6 + +@@ -48,17 +52,25 @@ class NotificationsTest(unittest.TestCase): + """ + + driver: webdriver.Remote ++ kactivitymanagerd: subprocess.Popen + + @classmethod + def setUpClass(cls) -> None: + """ + Opens the widget and initialize the webdriver + """ ++ # Make history work ++ cls.kactivitymanagerd = start_kactivitymanagerd() ++ ++ os.makedirs(os.path.join(GLib.get_user_data_dir(), "knotifications6")) ++ shutil.copy(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir, "libnotificationmanager", "libnotificationmanager.notifyrc"), os.path.join(GLib.get_user_data_dir(), "knotifications6")) ++ + options = AppiumOptions() + options.set_capability("app", f"plasmawindowed -p org.kde.plasma.nano {WIDGET_ID}") + options.set_capability("timeouts", {'implicit': 10000}) + options.set_capability("environ", { + "LC_ALL": "en_US.UTF-8", ++ "QT_LOGGING_RULES": "kf.notification*.debug=true;org.kde.plasma.notificationmanager.debug=true", + }) + cls.driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', options=options) + +@@ -75,6 +87,8 @@ class NotificationsTest(unittest.TestCase): + Make sure to terminate the driver again, lest it dangles. + """ + subprocess.check_call([f"kquitapp{KDE_VERSION}", "plasmawindowed"]) ++ cls.kactivitymanagerd.kill() ++ cls.kactivitymanagerd.wait(10) + for _ in range(10): + try: + subprocess.check_call(["pidof", "plasmawindowed"]) +@@ -83,6 +97,15 @@ class NotificationsTest(unittest.TestCase): + time.sleep(1) + cls.driver.quit() + ++ def close_notifications(self) -> None: ++ wait = WebDriverWait(self.driver, 5) ++ for button in self.driver.find_elements(AppiumBy.XPATH, "//button[@name='Close']"): ++ try: ++ button.click() ++ wait.until_not(lambda _: button.is_displayed()) ++ except WebDriverException: ++ pass ++ + def test_0_open(self) -> None: + """ + Tests the widget can be opened +@@ -106,6 +129,10 @@ class NotificationsTest(unittest.TestCase): + + wait = WebDriverWait(self.driver, 5) + wait.until(EC.presence_of_element_located((AppiumBy.NAME, summary))) ++<<<<<<< HEAD ++======= ++ self.close_notifications() ++>>>>>>> 5145d877d8 (applets/notifications: suppress inhibited notifications after "Do not disturb" is off) + + def take_screenshot(self) -> str: + with tempfile.TemporaryDirectory() as temp_dir: +@@ -123,6 +150,7 @@ class NotificationsTest(unittest.TestCase): + partial_pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 16, 16) + colors = (0xff0000ff, 0x00ff00ff, 0x0000ffff) + for color in colors: ++ logging.info(f"Testing color: {color}") + pixbuf.fill(color) + send_notification({ + "app_name": "Appium Test", +@@ -145,7 +173,29 @@ class NotificationsTest(unittest.TestCase): + wait.until(EC.presence_of_element_located((AppiumBy.NAME, summary + str(color)))) + partial_pixbuf.fill(color) + partial_image = base64.b64encode(Gdk.Texture.new_for_pixbuf(partial_pixbuf).save_to_png_bytes().get_data()).decode() ++<<<<<<< HEAD + self.driver.find_image_occurrence(self.take_screenshot(), partial_image) ++======= ++ try: ++ self.driver.find_image_occurrence(self.take_screenshot(), partial_image) ++ except WebDriverException: # Popup animation ++ self.driver.find_image_occurrence(self.take_screenshot(), partial_image) ++ self.close_notifications() ++ ++ def test_2_notification_with_explicit_timeout(self) -> None: ++ """ ++ Sends notifications with expire_timeout ++ """ ++ summary = "expire_timeout" ++ send_notification({ ++ "app_name": "Appium Test", ++ "summary": summary, ++ "body": "Will it disappear automatically?", ++ "timeout": 2000, ++ }) ++ element = self.driver.find_element(AppiumBy.NAME, summary) ++ WebDriverWait(self.driver, 5).until_not(lambda _: element.is_displayed()) ++>>>>>>> 5145d877d8 (applets/notifications: suppress inhibited notifications after "Do not disturb" is off) + + def test_3_accessible_description_html_to_plaintext(self) -> None: + """ +@@ -157,6 +207,202 @@ class NotificationsTest(unittest.TestCase): + }) + wait = WebDriverWait(self.driver, 5) + wait.until(EC.presence_of_element_located(("description", "biublinkwww.example.org from Appium Test"))) ++<<<<<<< HEAD ++======= ++ self.close_notifications() ++ ++ def test_4_actions(self) -> None: ++ """ ++ When the "actions" key is set, a notification can provide actions. ++ """ ++ loop = GLib.MainLoop() ++ activation_token = False ++ params_1: list[Any] = [] ++ action_invoked = False ++ params_2: list[Any] = [] ++ notification_closed = False ++ params_3: list[Any] = [] ++ ++ def notification_signal_handler(d_bus_proxy: Gio.DBusProxy, sender_name: str, signal_name: str, parameters: GLib.Variant) -> None: ++ nonlocal params_2, params_3, params_1, activation_token, action_invoked, notification_closed ++ logging.info(f"received signal {signal_name}") ++ match signal_name: ++ case "ActivationToken": ++ params_1 = parameters.unpack() ++ activation_token = True ++ case "ActionInvoked": ++ params_2 = parameters.unpack() ++ action_invoked = True ++ case "NotificationClosed": ++ params_3 = parameters.unpack() ++ notification_closed = True ++ loop.quit() ++ ++ connection_id = self.notification_proxy.connect("g-signal", notification_signal_handler) ++ self.addCleanup(lambda: self.notification_proxy.disconnect(connection_id)) ++ ++ notification_id = send_notification({ ++ "app_name": "Appium Test", ++ "body": "A notification with actions", ++ "actions": ["action1", "FooAction", "action2", "BarAction"], ++ }) ++ self.driver.find_element(AppiumBy.NAME, "BarAction") ++ element = self.driver.find_element(AppiumBy.NAME, "FooAction") ++ element.click() ++ loop.run() ++ self.assertTrue(activation_token) ++ self.assertEqual(params_1[0], notification_id) ++ self.assertTrue(action_invoked) ++ self.assertEqual(params_2[0], notification_id) ++ self.assertEqual(params_2[1], "action1") ++ self.assertTrue(notification_closed) ++ self.assertEqual(params_3[0], notification_id) ++ self.assertEqual(params_3[1], 3) # reason: Revoked ++ self.assertFalse(element.is_displayed()) ++ ++ def test_5_inline_reply(self) -> None: ++ """ ++ When the action list has "inline-reply", the notification popup will contain a text field and a reply button. ++ """ ++ loop = GLib.MainLoop() ++ notification_replied = False ++ params: list[Any] = [] # id, text ++ ++ def notification_signal_handler(d_bus_proxy: Gio.DBusProxy, sender_name: str, signal_name: str, parameters: GLib.Variant) -> None: ++ nonlocal params, notification_replied ++ logging.info(f"received signal {signal_name}") ++ if signal_name == "NotificationReplied": ++ params = parameters.unpack() ++ notification_replied = True ++ loop.quit() ++ ++ connection_id = self.notification_proxy.connect("g-signal", notification_signal_handler) ++ self.addCleanup(lambda: self.notification_proxy.disconnect(connection_id)) ++ ++ # When there is only one action and it is a reply action, show text field right away ++ notification_id = send_notification({ ++ "app_name": "Appium Test", ++ "body": "A notification with actions 1", ++ "actions": ["inline-reply", ""], # Use the default label ++ }) ++ reply_text = "this is a reply" ++ self.driver.find_element(AppiumBy.NAME, "begin reply").click() ++ self.driver.find_element(AppiumBy.NAME, "Type a reply…").send_keys(reply_text) ++ element = self.driver.find_element(AppiumBy.NAME, "Send") ++ element.click() ++ loop.run() ++ self.assertTrue(notification_replied) ++ self.assertEqual(params[0], notification_id) ++ self.assertEqual(params[1], reply_text) ++ self.assertFalse(element.is_displayed()) ++ ++ notification_replied = False ++ notification_id = send_notification({ ++ "app_name": "Appium Test", ++ "body": "A notification with actions 2", ++ "actions": ["inline-reply", ""], ++ "hints": { ++ "x-kde-reply-submit-button-text": GLib.Variant("s", "Reeply"), # Use a custom label ++ "x-kde-reply-placeholder-text": GLib.Variant("s", "A placeholder"), # Use a custom placeholder ++ }, ++ }) ++ reply_text = "this is another reply" ++ self.driver.find_element(AppiumBy.NAME, "begin reply").click() ++ self.driver.find_element(AppiumBy.NAME, "A placeholder").send_keys(reply_text) ++ element = self.driver.find_element(AppiumBy.NAME, "Reeply") ++ element.click() ++ loop.run() ++ self.assertTrue(notification_replied) ++ self.assertEqual(params[0], notification_id) ++ self.assertEqual(params[1], reply_text) ++ self.assertFalse(element.is_displayed()) ++ ++ notification_replied = False ++ notification_id = send_notification({ ++ "app_name": "Appium Test", ++ "body": "A notification with actions 3", ++ "actions": ["inline-reply", "Replyy", "foo", "Foo", "bar", "Bar"], # Click to show the text field ++ }) ++ self.driver.find_element(AppiumBy.NAME, "Foo") ++ self.driver.find_element(AppiumBy.NAME, "Bar") ++ element = self.driver.find_element(AppiumBy.NAME, "Replyy") ++ element.click() ++ reply_text = "Click Replyy to reply" ++ self.driver.find_element(AppiumBy.NAME, "Type a reply…").send_keys(reply_text) ++ self.assertFalse(element.is_displayed()) ++ element = self.driver.find_element(AppiumBy.NAME, "Send") ++ element.click() ++ loop.run() ++ self.assertTrue(notification_replied) ++ self.assertEqual(params[0], notification_id) ++ self.assertEqual(params[1], reply_text) ++ ++ def test_6_thumbnail(self) -> None: ++ """ ++ When a notification has "x-kde-urls" hint, a thumbnail will be shown for the first url in the list ++ """ ++ with tempfile.TemporaryDirectory() as temp_dir: ++ pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 256, 256) ++ colors = (0xff0000ff, 0x00ff00ff, 0x0000ffff) ++ for color in colors: ++ pixbuf.fill(color) ++ pixbuf.savev(os.path.join(temp_dir, f"{str(color)}.png"), "png") ++ ++ url_list = [f"file://{os.path.join(temp_dir, path)}" for path in os.listdir(temp_dir)] ++ url_list.sort() ++ send_notification({ ++ "app_name": "Appium Test", ++ "body": "Thumbnail", ++ "hints": { ++ "x-kde-urls": GLib.Variant("as", url_list), ++ }, ++ "timeout": 10 * 1000, ++ }) ++ ++ self.driver.find_element(AppiumBy.NAME, "More Options…") ++ ++ partial_pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 100, 100) ++ partial_pixbuf.fill(colors[1]) # Green is the first item ++ partial_image = base64.b64encode(Gdk.Texture.new_for_pixbuf(partial_pixbuf).save_to_png_bytes().get_data()).decode() ++ ++ def match_image(driver) -> bool: ++ try: ++ self.driver.find_image_occurrence(self.take_screenshot(), partial_image) ++ return True ++ except WebDriverException: ++ return False ++ ++ WebDriverWait(self.driver, 10).until(match_image) ++ self.close_notifications() ++ ++ def test_7_do_not_disturb(self) -> None: ++ """ ++ Suppress inhibited notifications after "Do not disturb" is turned off, and show a summary for unread inhibited notifications. ++ """ ++ self.driver.find_element(AppiumBy.NAME, "Do not disturb").click() ++ dnd_button = self.driver.find_element(AppiumBy.XPATH, "//*[@name='Do not disturb' and contains(@states, 'checked')]") ++ ++ summary = "Do not disturb me" ++ for i in range(2): ++ send_notification({ ++ "app_name": "Appium Test", ++ "summary": summary + str(i), ++ "hints": { ++ "desktop-entry": GLib.Variant("s", "org.kde.plasmashell"), ++ }, ++ "timeout": 60 * 1000, ++ }) ++ title = self.driver.find_element(AppiumBy.XPATH, f"//heading[starts-with(@name, '{summary}') and contains(@accessibility-id, 'FullRepresentation')]") ++ self.assertRaises(NoSuchElementException, self.driver.find_element, AppiumBy.XPATH, f"//notification[starts-with(@name, '{summary}')]") ++ ++ dnd_button.click() ++ self.driver.find_element(AppiumBy.XPATH, "//notification[@name='Unread Notifications' and @description='2 notifications were received while Do Not Disturb was active. from Notification Manager']") ++ self.driver.find_element(AppiumBy.XPATH, "//button[@name='Close' and contains(@accessibility-id, 'NotificationPopup')]").click() ++ ++ # Notifications can only be cleared after they are expired, otherwise they will stay in the list ++ self.driver.find_element(AppiumBy.NAME, "Clear All Notifications").click() ++ WebDriverWait(self.driver, 5).until_not(lambda _: title.is_displayed()) ++>>>>>>> 5145d877d8 (applets/notifications: suppress inhibited notifications after "Do not disturb" is off) + + + if __name__ == '__main__': +diff --git a/applets/notifications/package/contents/ui/FullRepresentation.qml b/applets/notifications/package/contents/ui/FullRepresentation.qml +index f949dad46a..33838599f6 100644 +--- a/applets/notifications/package/contents/ui/FullRepresentation.qml ++++ b/applets/notifications/package/contents/ui/FullRepresentation.qml +@@ -71,6 +71,14 @@ PlasmaExtras.Representation { + checkable: true + checked: Globals.inhibited + ++ Accessible.onPressAction: if (Globals.inhibited) { ++ Globals.revokeInhibitions(); ++ } else { ++ let date = new Date(); ++ date.setFullYear(date.getFullYear() + 1); ++ notificationSettings.notificationsInhibitedUntil = date; ++ notificationSettings.save(); ++ } + KeyNavigation.down: list + KeyNavigation.tab: list + +diff --git a/applets/notifications/package/contents/ui/global/Globals.qml b/applets/notifications/package/contents/ui/global/Globals.qml +index c46c32921a..2238653eff 100644 +--- a/applets/notifications/package/contents/ui/global/Globals.qml ++++ b/applets/notifications/package/contents/ui/global/Globals.qml +@@ -34,6 +34,10 @@ QtObject { + property bool inhibited: false + + onInhibitedChanged: { ++ if (!inhibited) { ++ popupNotificationsModel.showInhibitionSummary(); ++ } ++ + var pa = pulseAudio.item; + if (!pa) { + return; +@@ -405,6 +409,7 @@ QtObject { + limit: plasmoid ? (Math.ceil(globals.screenRect.height / (Kirigami.Units.gridUnit * 4))) : 0 + showExpired: false + showDismissed: false ++ showAddedDuringInhibition: false + blacklistedDesktopEntries: notificationSettings.popupBlacklistedApplications + blacklistedNotifyRcNames: notificationSettings.popupBlacklistedServices + whitelistedDesktopEntries: globals.inhibited ? notificationSettings.doNotDisturbPopupWhitelistedApplications : [] +@@ -613,9 +618,13 @@ QtObject { + onKillJobClicked: popupNotificationsModel.killJob(popupNotificationsModel.index(index, 0)) + + // popup width is fixed +- onHeightChanged: positionPopups() ++ onHeightChanged: globals.positionPopups() + + Component.onCompleted: { ++ if (globals.inhibited) { ++ model.wasAddedDuringInhibition = false; // Don't count already shown notifications ++ } ++ + if (model.type === NotificationManager.Notifications.NotificationType && model.desktopEntry) { + // Register apps that were seen spawning a popup so they can be configured later + // Apps with notifyrc can already be configured anyway +diff --git a/libnotificationmanager/CMakeLists.txt b/libnotificationmanager/CMakeLists.txt +index d04d8a4a24..5c48653ede 100644 +--- a/libnotificationmanager/CMakeLists.txt ++++ b/libnotificationmanager/CMakeLists.txt +@@ -84,6 +84,7 @@ target_link_libraries(notificationmanager + KF6::I18n + KF6::WindowSystem + KF6::ItemModels # KDescendantsProxyModel ++ KF6::Notifications # Inhibition summary + KF6::KIOFileWidgets + Plasma::Plasma + KF6::Screen +@@ -135,3 +136,6 @@ install(EXPORT notificationmanagerLibraryTargets + + install(FILES plasmanotifyrc + DESTINATION ${KDE_INSTALL_CONFDIR}) ++ ++install(FILES libnotificationmanager.notifyrc ++ DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR}) +diff --git a/libnotificationmanager/abstractnotificationsmodel.cpp b/libnotificationmanager/abstractnotificationsmodel.cpp +index 8bd55bc26c..8307a1e8f7 100644 +--- a/libnotificationmanager/abstractnotificationsmodel.cpp ++++ b/libnotificationmanager/abstractnotificationsmodel.cpp +@@ -104,6 +104,7 @@ void AbstractNotificationsModel::Private::onNotificationReplaced(uint replacedId + newNotification.setExpired(oldNotification.expired()); + newNotification.setDismissed(oldNotification.dismissed()); + newNotification.setRead(oldNotification.read()); ++ newNotification.setWasAddedDuringInhibition(Server::self().inhibited()); + + notifications[row] = newNotification; + const QModelIndex idx = q->index(row, 0); +@@ -378,6 +379,9 @@ QVariant AbstractNotificationsModel::data(const QModelIndex &index, int role) co + case Notifications::TransientRole: + return notification.transient(); + ++ case Notifications::WasAddedDuringInhibitionRole: ++ return notification.wasAddedDuringInhibition(); ++ + case Notifications::HasReplyActionRole: + return notification.hasReplyAction(); + case Notifications::ReplyActionLabelRole: +@@ -416,6 +420,12 @@ bool AbstractNotificationsModel::setData(const QModelIndex &index, const QVarian + dirty = true; + } + break; ++ case Notifications::WasAddedDuringInhibitionRole: ++ if (bool v = value.toBool(); v != notification.wasAddedDuringInhibition()) { ++ notification.setWasAddedDuringInhibition(v); ++ dirty = true; ++ } ++ break; + } + + if (dirty) { +@@ -471,7 +481,7 @@ void AbstractNotificationsModel::clear(Notifications::ClearFlags flags) + for (int i = 0; i < d->notifications.count(); ++i) { + const Notification ¬ification = d->notifications.at(i); + +- if (flags.testFlag(Notifications::ClearExpired) && notification.expired()) { ++ if (flags.testFlag(Notifications::ClearExpired) && (notification.expired() || notification.wasAddedDuringInhibition())) { + close(notification.id()); + } + } +diff --git a/libnotificationmanager/libnotificationmanager.notifyrc b/libnotificationmanager/libnotificationmanager.notifyrc +new file mode 100644 +index 0000000000..79304e62bc +--- /dev/null ++++ b/libnotificationmanager/libnotificationmanager.notifyrc +@@ -0,0 +1,11 @@ ++# SPDX-License-Identifier: CC0-1.0 ++# SPDX-FileCopyrightText: None ++ ++[Global] ++Name=Notification Manager ++IconName=preferences-desktop-notification-bell ++ ++[Event/inhibitionSummary] ++Name=Summary for unread inhibited notifications ++Action=Popup ++Urgency=Low +diff --git a/libnotificationmanager/notification.cpp b/libnotificationmanager/notification.cpp +index 276611310c..320c837617 100644 +--- a/libnotificationmanager/notification.cpp ++++ b/libnotificationmanager/notification.cpp +@@ -826,3 +826,13 @@ void Notification::processHints(const QVariantMap &hints) + { + d->processHints(hints); + } ++ ++bool Notification::wasAddedDuringInhibition() const ++{ ++ return d->wasAddedDuringInhibition; ++} ++ ++void Notification::setWasAddedDuringInhibition(bool value) ++{ ++ d->wasAddedDuringInhibition = value; ++} +diff --git a/libnotificationmanager/notification.h b/libnotificationmanager/notification.h +index 9f04a4e200..8613534fd2 100644 +--- a/libnotificationmanager/notification.h ++++ b/libnotificationmanager/notification.h +@@ -131,6 +131,9 @@ public: + + void processHints(const QVariantMap &hints); + ++ bool wasAddedDuringInhibition() const; ++ void setWasAddedDuringInhibition(bool value); ++ + private: + friend class NotificationsModel; + friend class AbstractNotificationsModel; +diff --git a/libnotificationmanager/notification_p.h b/libnotificationmanager/notification_p.h +index 6cae23c21e..923bde7882 100644 +--- a/libnotificationmanager/notification_p.h ++++ b/libnotificationmanager/notification_p.h +@@ -96,6 +96,8 @@ public: + + bool resident = false; + bool transient = false; ++ ++ bool wasAddedDuringInhibition = false; + }; + + } // namespace NotificationManager +diff --git a/libnotificationmanager/notificationfilterproxymodel.cpp b/libnotificationmanager/notificationfilterproxymodel.cpp +index 98a32b6645..bb573713af 100644 +--- a/libnotificationmanager/notificationfilterproxymodel.cpp ++++ b/libnotificationmanager/notificationfilterproxymodel.cpp +@@ -58,6 +58,20 @@ void NotificationFilterProxyModel::setShowDismissed(bool show) + } + } + ++bool NotificationFilterProxyModel::showAddedDuringInhibition() const ++{ ++ return m_showDismissed; ++} ++ ++void NotificationFilterProxyModel::setShowAddedDuringInhibition(bool show) ++{ ++ if (m_showAddedDuringInhibition != show) { ++ m_showAddedDuringInhibition = show; ++ invalidateFilter(); ++ Q_EMIT showAddedDuringInhibitionChanged(); ++ } ++} ++ + QStringList NotificationFilterProxyModel::blacklistedDesktopEntries() const + { + return m_blacklistedDesktopEntries; +@@ -177,5 +191,9 @@ bool NotificationFilterProxyModel::filterAcceptsRow(int source_row, const QModel + } + } + ++ if (!m_showAddedDuringInhibition && sourceIdx.data(Notifications::WasAddedDuringInhibitionRole).toBool()) { ++ return false; ++ } ++ + return true; + } +diff --git a/libnotificationmanager/notificationfilterproxymodel_p.h b/libnotificationmanager/notificationfilterproxymodel_p.h +index 4029320e8e..af04a9fac1 100644 +--- a/libnotificationmanager/notificationfilterproxymodel_p.h ++++ b/libnotificationmanager/notificationfilterproxymodel_p.h +@@ -30,6 +30,9 @@ public: + bool showDismissed() const; + void setShowDismissed(bool show); + ++ bool showAddedDuringInhibition() const; ++ void setShowAddedDuringInhibition(bool show); ++ + QStringList blacklistedDesktopEntries() const; + void setBlackListedDesktopEntries(const QStringList &blacklist); + +@@ -46,6 +49,7 @@ Q_SIGNALS: + void urgenciesChanged(); + void showExpiredChanged(); + void showDismissedChanged(); ++ void showAddedDuringInhibitionChanged(); + void blacklistedDesktopEntriesChanged(); + void blacklistedNotifyRcNamesChanged(); + void whitelistedDesktopEntriesChanged(); +@@ -58,6 +62,7 @@ private: + Notifications::Urgencies m_urgencies = Notifications::LowUrgency | Notifications::NormalUrgency | Notifications::CriticalUrgency; + bool m_showDismissed = false; + bool m_showExpired = false; ++ bool m_showAddedDuringInhibition = true; + + QStringList m_blacklistedDesktopEntries; + QStringList m_blacklistedNotifyRcNames; +diff --git a/libnotificationmanager/notifications.cpp b/libnotificationmanager/notifications.cpp +index 9b3e18018b..3d5662f926 100644 +--- a/libnotificationmanager/notifications.cpp ++++ b/libnotificationmanager/notifications.cpp +@@ -12,6 +12,8 @@ + #include + + #include ++#include ++#include + + #include "limitedrowcountproxymodel_p.h" + #include "notificationfilterproxymodel_p.h" +@@ -30,6 +32,7 @@ + + #include "debug.h" + ++using namespace Qt::StringLiterals; + using namespace NotificationManager; + + class Q_DECL_HIDDEN Notifications::Private +@@ -166,6 +169,7 @@ void Notifications::Private::initProxyModels() + connect(filterModel, &NotificationFilterProxyModel::urgenciesChanged, q, &Notifications::urgenciesChanged); + connect(filterModel, &NotificationFilterProxyModel::showExpiredChanged, q, &Notifications::showExpiredChanged); + connect(filterModel, &NotificationFilterProxyModel::showDismissedChanged, q, &Notifications::showDismissedChanged); ++ connect(filterModel, &NotificationFilterProxyModel::showAddedDuringInhibitionChanged, q, &Notifications::showAddedDuringInhibitionChanged); + connect(filterModel, &NotificationFilterProxyModel::blacklistedDesktopEntriesChanged, q, &Notifications::blacklistedDesktopEntriesChanged); + connect(filterModel, &NotificationFilterProxyModel::blacklistedNotifyRcNamesChanged, q, &Notifications::blacklistedNotifyRcNamesChanged); + +@@ -245,7 +249,7 @@ void Notifications::Private::updateCount() + for (int i = 0; i < filterModel->rowCount(); ++i) { + const QModelIndex idx = filterModel->index(i, 0); + +- if (idx.data(Notifications::ExpiredRole).toBool()) { ++ if (idx.data(Notifications::ExpiredRole).toBool() || idx.data(Notifications::WasAddedDuringInhibitionRole).toBool()) { + ++expired; + } else { + ++active; +@@ -477,6 +481,16 @@ void Notifications::setShowDismissed(bool show) + d->filterModel->setShowDismissed(show); + } + ++bool Notifications::showAddedDuringInhibition() const ++{ ++ return d->filterModel->showAddedDuringInhibition(); ++} ++ ++void Notifications::setShowAddedDuringInhibition(bool show) ++{ ++ d->filterModel->setShowAddedDuringInhibition(show); ++} ++ + QStringList Notifications::blacklistedDesktopEntries() const + { + return d->filterModel->blacklistedDesktopEntries(); +@@ -812,6 +826,28 @@ void Notifications::collapseAllGroups() + } + } + ++void Notifications::showInhibitionSummary() ++{ ++ int inhibited = 0; ++ for (int i = 0, count = d->notificationsAndJobsModel->rowCount(); i < count; ++i) { ++ const QModelIndex idx = d->notificationsAndJobsModel->index(i, 0); ++ if (!idx.data(Notifications::ReadRole).toBool() && idx.data(Notifications::WasAddedDuringInhibitionRole).toBool()) { ++ ++inhibited; ++ } ++ } ++ ++ if (!inhibited) { ++ return; ++ } ++ ++ KNotification::event(u"inhibitionSummary"_s, ++ i18nc("@title", "Unread Notifications"), ++ i18nc("@info", "%1 notifications were received while Do Not Disturb was active.", QString::number(inhibited)), ++ u"preferences-desktop-notification-bell"_s, ++ KNotification::CloseOnTimeout, ++ u"libnotificationmanager"_s); ++} ++ + QVariant Notifications::data(const QModelIndex &index, int role) const + { + return QSortFilterProxyModel::data(index, role); +diff --git a/libnotificationmanager/notifications.h b/libnotificationmanager/notifications.h +index edb898988f..ef500b0c7b 100644 +--- a/libnotificationmanager/notifications.h ++++ b/libnotificationmanager/notifications.h +@@ -61,6 +61,15 @@ class NOTIFICATIONMANAGER_EXPORT Notifications : public QSortFilterProxyModel, p + */ + Q_PROPERTY(bool showDismissed READ showDismissed WRITE setShowDismissed NOTIFY showDismissedChanged) + ++ /** ++ * Whether to show notifications added during inhibition. ++ * ++ * If set to @c false, notifications are suppressed even after leaving "Do not disturb" mode. ++ * ++ * Default is @c true. ++ */ ++ Q_PROPERTY(bool showAddedDuringInhibition READ showAddedDuringInhibition WRITE setShowAddedDuringInhibition NOTIFY showAddedDuringInhibitionChanged) ++ + /** + * A list of desktop entries for which no notifications should be shown. + * +@@ -285,6 +294,8 @@ public: + ///< notification in a certain way, or group notifications of similar types. @since 5.21 + ResidentRole, ///< Whether the notification should keep its actions even when they were invoked. @since 5.22 + TransientRole, ///< Whether the notification is transient and should not be kept in history. @since 5.22 ++ ++ WasAddedDuringInhibitionRole, ///< Whether the notification was added while inhibition was active. @since 6.3 + }; + Q_ENUM(Roles) + +@@ -371,6 +382,9 @@ public: + bool showDismissed() const; + void setShowDismissed(bool show); + ++ bool showAddedDuringInhibition() const; ++ void setShowAddedDuringInhibition(bool show); ++ + QStringList blacklistedDesktopEntries() const; + void setBlacklistedDesktopEntries(const QStringList &blacklist); + +@@ -529,6 +543,11 @@ public: + + Q_INVOKABLE void collapseAllGroups(); + ++ /** ++ * Shows a notification to report the number of unread inhibited notifications. ++ */ ++ Q_INVOKABLE void showInhibitionSummary(); ++ + QVariant data(const QModelIndex &index, int role) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role) override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; +@@ -541,6 +560,7 @@ Q_SIGNALS: + void limitChanged(); + void showExpiredChanged(); + void showDismissedChanged(); ++ void showAddedDuringInhibitionChanged(); + void blacklistedDesktopEntriesChanged(); + void blacklistedNotifyRcNamesChanged(); + void whitelistedDesktopEntriesChanged(); +diff --git a/libnotificationmanager/server_p.cpp b/libnotificationmanager/server_p.cpp +index 84fe37afa9..66cd621033 100644 +--- a/libnotificationmanager/server_p.cpp ++++ b/libnotificationmanager/server_p.cpp +@@ -164,6 +164,7 @@ uint ServerPrivate::Notify(const QString &app_name, + notification.setActions(actions); + + notification.setTimeout(timeout); ++ notification.setWasAddedDuringInhibition(m_inhibited); + + // might override some of the things we set above (like application name) + notification.d->processHints(hints); diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 8339715..1f0f5db 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -54,6 +54,7 @@ in { kPrev.plasma-workspace.patches ++ [ ./patches/plasma_workspace-pr4883.patch + ./patches/plasma_workspace-pr4965.patch ]; }; plasma-desktop = kPrev.plasma-desktop.overrideAttrs { diff --git a/roles/kde/programs/kwin.nix b/roles/kde/programs/kwin.nix index e7dd2b7..f6b176b 100644 --- a/roles/kde/programs/kwin.nix +++ b/roles/kde/programs/kwin.nix @@ -11,6 +11,7 @@ ../patches/kwin-pr6406.patch ../patches/kwin-pr6878.patch ../patches/kwin-pr6844.patch + ../patches/kwin-pr6985.patch ]; }; } From 2f970835b257943bc550dec6f1304c57ecc2db40 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 Jan 2025 00:27:52 +0100 Subject: [PATCH 0905/1125] Flake: remove unneeded nixpkgs patch --- flake.nix | 4 +-- .../fix-endlessh-dns-resolution.patch | 31 ------------------- 2 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 nixpkgs-patches/fix-endlessh-dns-resolution.patch diff --git a/flake.nix b/flake.nix index f05c44b..3bdb7f1 100644 --- a/flake.nix +++ b/flake.nix @@ -105,9 +105,7 @@ nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; src = nixpkgs-raw; - patches = [ - ./nixpkgs-patches/fix-endlessh-dns-resolution.patch - ]; + patches = []; }; # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs {self = inputs.nixpkgs-unstable-raw;}; diff --git a/nixpkgs-patches/fix-endlessh-dns-resolution.patch b/nixpkgs-patches/fix-endlessh-dns-resolution.patch deleted file mode 100644 index dc55d97..0000000 --- a/nixpkgs-patches/fix-endlessh-dns-resolution.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 99778e1bb590c984d91f39322e57d59220402c59 Mon Sep 17 00:00:00 2001 -From: azahi -Date: Wed, 8 Jan 2025 13:47:09 +0300 -Subject: [PATCH] nixos/endlessh-go: fix DNS resolution - -As suggested by toast003[1]. - -[1]: https://github.com/shizunge/endlessh-go/discussions/127#discussioncomment-11760912 ---- - nixos/modules/services/security/endlessh-go.nix | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/nixos/modules/services/security/endlessh-go.nix b/nixos/modules/services/security/endlessh-go.nix -index b8b51acc81d0e..5c69d412a7d3c 100644 ---- a/nixos/modules/services/security/endlessh-go.nix -+++ b/nixos/modules/services/security/endlessh-go.nix -@@ -110,7 +110,13 @@ in - ); - DynamicUser = true; - RootDirectory = rootDirectory; -- BindReadOnlyPaths = [ builtins.storeDir ]; -+ BindReadOnlyPaths = [ -+ builtins.storeDir -+ "-/etc/hosts" -+ "-/etc/localtime" -+ "-/etc/nsswitch.conf" -+ "-/etc/resolv.conf" -+ ]; - InaccessiblePaths = [ "-+${rootDirectory}" ]; - RuntimeDirectory = baseNameOf rootDirectory; - RuntimeDirectoryMode = "700"; From 02fcfb5008996666022231d5358179e5167aafd1 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 Jan 2025 00:28:22 +0100 Subject: [PATCH 0906/1125] Flake: update lock file --- flake.lock | 144 ++++++++++++++++++++++++++--------------------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/flake.lock b/flake.lock index 40c00a4..5345bb4 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1723293904, - "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", + "lastModified": 1736955230, + "narHash": "sha256-uenf8fv2eG5bKM8C/UvFaiJMZ4IpUFaQxk9OH5t/1gA=", "owner": "ryantm", "repo": "agenix", - "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", + "rev": "e600439ec4c273cf11e06fe4d9d906fb98fa097c", "type": "github" }, "original": { @@ -34,11 +34,11 @@ "nuscht-search": "nuscht-search" }, "locked": { - "lastModified": 1735895235, - "narHash": "sha256-MtsfkMikkPjnZUMqsqXQ29cHzlRD2lMe27jXua28cHU=", + "lastModified": 1736957255, + "narHash": "sha256-qZZ/K5XheRMjCNYgle90QESuys0PIFJNPJJswMJ0GEA=", "owner": "catppuccin", "repo": "nix", - "rev": "b326f48f17023fc0060590ba299d55f7da8350a5", + "rev": "f06fcadf9a61b6581b392e72f230fa6783fe36e4", "type": "github" }, "original": { @@ -79,12 +79,12 @@ }, "catppuccin-v1_2": { "locked": { - "lastModified": 1734728407, - "narHash": "sha256-Let3uJo4YDyfqbqaw66dpZxhJB2TrDyZWSFd5rpPLJA=", - "rev": "23ee86dbf4ed347878115a78971d43025362fab1", - "revCount": 341, + "lastModified": 1734734291, + "narHash": "sha256-CFX4diEQHKvZYjnhf7TLg20m3ge1O4vqgplsk/Kuaek=", + "rev": "1e4c3803b8da874ff75224ec8512cb173036bbd8", + "revCount": 344, "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/catppuccin/nix/1.2.0/0193e5e0-33b7-7149-a362-bfe56b20f64e/source.tar.gz" + "url": "https://api.flakehub.com/f/pinned/catppuccin/nix/1.2.1/0193e646-1107-7f69-a402-f2a3988ecf1d/source.tar.gz" }, "original": { "type": "tarball", @@ -94,11 +94,11 @@ "eza-themes": { "flake": false, "locked": { - "lastModified": 1735244910, - "narHash": "sha256-sfQLMjtAcYTLAA664v6CaYlkoBCPtykhzSQCrcMEA2c=", + "lastModified": 1736468386, + "narHash": "sha256-K9k+jE27kK8PlN6BbTfMLhCagnWCc6CIO1lkqvWl9fE=", "owner": "eza-community", "repo": "eza-themes", - "rev": "39c1a6640ceaaa4b59f354e1cb229c292a199e68", + "rev": "266feb8d373ac201bd28d7522e4e65cb2865f082", "type": "github" }, "original": { @@ -241,11 +241,11 @@ ] }, "locked": { - "lastModified": 1734366194, - "narHash": "sha256-vykpJ1xsdkv0j8WOVXrRFHUAdp9NXHpxdnn1F4pYgSw=", + "lastModified": 1736373539, + "narHash": "sha256-dinzAqCjenWDxuy+MqUQq0I4zUSfaCvN9rzuCmgMZJY=", "owner": "nix-community", "repo": "home-manager", - "rev": "80b0fdf483c5d1cb75aaad909bd390d48673857f", + "rev": "bd65bc3cde04c16755955630b344bc9e35272c56", "type": "github" }, "original": { @@ -262,11 +262,11 @@ ] }, "locked": { - "lastModified": 1735900408, - "narHash": "sha256-U+oZBQ3f5fF2hHsupKQH4ihgTKLHgcJh6jEmKDg+W10=", + "lastModified": 1737120639, + "narHash": "sha256-p5e/45V41YD3tMELuiNIoVCa25/w4nhOTm0B9MtdHFI=", "owner": "nix-community", "repo": "home-manager", - "rev": "1c8d4c8d592e8fab4cff4397db5529ec6f078cf9", + "rev": "a0046af169ce7b1da503974e1b22c48ef4d71887", "type": "github" }, "original": { @@ -283,11 +283,11 @@ ] }, "locked": { - "lastModified": 1734622215, - "narHash": "sha256-OOfI0XhSJGHblfdNDhfnn8QnZxng63rWk9eeJ2tCbiI=", + "lastModified": 1736508663, + "narHash": "sha256-ZOaGwa+WnB7Zn3YXimqjmIugAnHePdXCmNu+AHkq808=", "owner": "nix-community", "repo": "home-manager", - "rev": "1395379a7a36e40f2a76e7b9936cc52950baa1be", + "rev": "2532b500c3ed2b8940e831039dcec5a5ea093afc", "type": "github" }, "original": { @@ -303,11 +303,11 @@ ] }, "locked": { - "lastModified": 1735344290, - "narHash": "sha256-oJDtWPH1oJT34RJK1FSWjwX4qcGOBRkcNQPD0EbSfNM=", + "lastModified": 1736373539, + "narHash": "sha256-dinzAqCjenWDxuy+MqUQq0I4zUSfaCvN9rzuCmgMZJY=", "owner": "nix-community", "repo": "home-manager", - "rev": "613691f285dad87694c2ba1c9e6298d04736292d", + "rev": "bd65bc3cde04c16755955630b344bc9e35272c56", "type": "github" }, "original": { @@ -353,11 +353,11 @@ ] }, "locked": { - "lastModified": 1735330405, - "narHash": "sha256-MhXgu1oymyjhhZGY9yewNonJknNAjilzMGPY1FfMR7s=", + "lastModified": 1737126697, + "narHash": "sha256-k1YhjONkiKBHzbjNy4ZsjysBac5UJSolCVq9cTKLeKM=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "a86d9cf841eff8b33a05d2bf25788abd8e018dbd", + "rev": "27a0ddac1a14e10ba98530f59db728951495f2ce", "type": "github" }, "original": { @@ -369,11 +369,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1735572323, - "narHash": "sha256-Wjt+PK15IdaOUoI0sgsRzaNMxKQGSROLe9sOd44+fwM=", - "rev": "5c7ea4f446de58aa64f78087bb4ec26b9c4111aa", + "lastModified": 1737086202, + "narHash": "sha256-33tcNERQt1R7tr/W7pvQj8R6NJktyTOKMIfY16RHLK8=", + "rev": "0d14c2b67a407825e3427bf079b31de069d9653a", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/5c7ea4f446de58aa64f78087bb4ec26b9c4111aa.tar.gz?rev=5c7ea4f446de58aa64f78087bb4ec26b9c4111aa" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/0d14c2b67a407825e3427bf079b31de069d9653a.tar.gz?rev=0d14c2b67a407825e3427bf079b31de069d9653a" }, "original": { "type": "tarball", @@ -428,11 +428,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1735913600, - "narHash": "sha256-370z+WLVnD7LrN/SvTCZxPl/XPTshS5NS2dHN4iyK6o=", + "lastModified": 1736952876, + "narHash": "sha256-dJXuLP2CBkIG333L+Rb3e1D0oXHYbl0MgmKPGuvFuAI=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "78ed84ff81e8d8510926e7165d508bcacef49ff1", + "rev": "b6966d5fa96b0fae99a4da0b5bdfbb0a75f5c058", "type": "github" }, "original": { @@ -466,11 +466,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1734945620, - "narHash": "sha256-olIfsfJK4/GFmPH8mXMmBDAkzVQ1TWJmeGT3wBGfQPY=", + "lastModified": 1736688610, + "narHash": "sha256-1Zl9xahw399UiZSJ9Vxs1W4WRFjO1SsNdVZQD4nghz0=", "owner": "nix-community", "repo": "impermanence", - "rev": "d000479f4f41390ff7cf9204979660ad5dd16176", + "rev": "c64bed13b562fc3bb454b48773d4155023ac31b7", "type": "github" }, "original": { @@ -486,11 +486,11 @@ ] }, "locked": { - "lastModified": 1735443188, - "narHash": "sha256-AydPpRBh8+NOkrLylG7vTsHrGO2b5L7XkMEL5HlzcA8=", + "lastModified": 1736652904, + "narHash": "sha256-8uolHABgroXqzs03QdulHp8H9e5kWQZnnhcda1MKbBM=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "55ab1e1df5daf2476e6b826b69a82862dcbd7544", + "rev": "271e5bd7c57e1f001693799518b10a02d1123b12", "type": "github" }, "original": { @@ -506,11 +506,11 @@ ] }, "locked": { - "lastModified": 1735443188, - "narHash": "sha256-AydPpRBh8+NOkrLylG7vTsHrGO2b5L7XkMEL5HlzcA8=", + "lastModified": 1736652904, + "narHash": "sha256-8uolHABgroXqzs03QdulHp8H9e5kWQZnnhcda1MKbBM=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "55ab1e1df5daf2476e6b826b69a82862dcbd7544", + "rev": "271e5bd7c57e1f001693799518b10a02d1123b12", "type": "github" }, "original": { @@ -521,11 +521,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1735388221, - "narHash": "sha256-e5IOgjQf0SZcFCEV/gMGrsI0gCJyqOKShBQU0iiM3Kg=", + "lastModified": 1736978406, + "narHash": "sha256-oMr3PVIQ8XPDI8/x6BHxsWEPBRU98Pam6KGVwUh8MPk=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "7c674c6734f61157e321db595dbfcd8523e04e19", + "rev": "b678606690027913f3434dea3864e712b862dde5", "type": "github" }, "original": { @@ -537,11 +537,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1734424634, - "narHash": "sha256-cHar1vqHOOyC7f1+tVycPoWTfKIaqkoe1Q6TnKzuti4=", + "lastModified": 1736012469, + "narHash": "sha256-/qlNWm/IEVVH7GfgAIyP6EsVZI6zjAx1cV5zNyrs+rI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d3c42f187194c26d9f0309a8ecc469d6c878ce33", + "rev": "8f3e1f807051e32d8c95cd12b9b421623850a34d", "type": "github" }, "original": { @@ -553,11 +553,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1735669367, - "narHash": "sha256-tfYRbFhMOnYaM4ippqqid3BaLOXoFNdImrfBfCp4zn0=", + "lastModified": 1736916166, + "narHash": "sha256-puPDoVKxkuNmYIGMpMQiK8bEjaACcCksolsG36gdaNQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "edf04b75c13c2ac0e54df5ec5c543e300f76f1c9", + "rev": "e24b4c09e963677b1beea49d411cd315a024ad3a", "type": "github" }, "original": { @@ -568,11 +568,11 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1734600368, - "narHash": "sha256-nbG9TijTMcfr+au7ZVbKpAhMJzzE2nQBYmRvSdXUD8g=", + "lastModified": 1736061677, + "narHash": "sha256-DjkQPnkAfd7eB522PwnkGhOMuT9QVCZspDpJJYyOj60=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b47fd6fa00c6afca88b8ee46cfdb00e104f50bca", + "rev": "cbd8ec4de4469333c82ff40d057350c30e9f7d36", "type": "github" }, "original": { @@ -584,11 +584,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1735834308, - "narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=", + "lastModified": 1737062831, + "narHash": "sha256-Tbk1MZbtV2s5aG+iM99U8FqwxU/YNArMcWAv6clcsBc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6df24922a1400241dae323af55f30e4318a6ca65", + "rev": "5df43628fdf08d642be8ba5b3625a6c70731c19c", "type": "github" }, "original": { @@ -599,11 +599,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1735471104, - "narHash": "sha256-0q9NGQySwDQc7RhAV2ukfnu7Gxa5/ybJ2ANT8DQrQrs=", + "lastModified": 1736883708, + "narHash": "sha256-uQ+NQ0/xYU0N1CnXsa2zghgNaOPxWpMJXSUJJ9W7140=", "owner": "nixos", "repo": "nixpkgs", - "rev": "88195a94f390381c6afcdaa933c2f6ff93959cb4", + "rev": "eb62e6aa39ea67e0b8018ba8ea077efe65807dc8", "type": "github" }, "original": { @@ -620,11 +620,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1735920791, - "narHash": "sha256-DPP/ioDJ283YMxU+U+URmTPECHLrFRUcXG2pbKA/MNY=", + "lastModified": 1737147292, + "narHash": "sha256-y5ALxyA2en4I81mwdeJgatg0u/SWi0LMAv+uakJ9czE=", "owner": "nix-community", "repo": "NUR", - "rev": "3af14b22ef7fa1eeb169840d9ee3010a43ed61ea", + "rev": "a55bbc7cf3f8772ef6274a32520ce117f32f9d0e", "type": "github" }, "original": { @@ -643,11 +643,11 @@ ] }, "locked": { - "lastModified": 1733773348, - "narHash": "sha256-Y47y+LesOCkJaLvj+dI/Oa6FAKj/T9sKVKDXLNsViPw=", + "lastModified": 1735854821, + "narHash": "sha256-Iv59gMDZajNfezTO0Fw6LHE7uKAShxbvMidmZREit7c=", "owner": "NuschtOS", "repo": "search", - "rev": "3051be7f403bff1d1d380e4612f0c70675b44fc9", + "rev": "836908e3bddd837ae0f13e215dd48767aee355f0", "type": "github" }, "original": { @@ -666,11 +666,11 @@ ] }, "locked": { - "lastModified": 1735049224, - "narHash": "sha256-fWUd9kyXdepphJ7cCzOsuSo7l0kbFCkUqfgKqZyFZzE=", + "lastModified": 1736549395, + "narHash": "sha256-XzwkB62Tt5UYoL1jXiHzgk/qz2fUpGHExcSIbyGTtI0=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "d16bbded0ae452bc088489e7dca3ef58d8d1830b", + "rev": "a53af7f1514ef4cce8620a9d6a50f238cdedec8b", "type": "github" }, "original": { From 91da240751110c5e619ad08a53891ddbba920d9d Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 17 Jan 2025 13:48:09 +0100 Subject: [PATCH 0907/1125] Server/adguard: change local IP address --- roles/server/adguard.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/adguard.nix b/roles/server/adguard.nix index 42da331..59e4f94 100644 --- a/roles/server/adguard.nix +++ b/roles/server/adguard.nix @@ -10,7 +10,7 @@ in { settings = { dns = { bind_hosts = [ - "192.168.0.160" + "10.0.0.2" "100.100.0.1" ]; bootstrap_dns = ["9.9.9.9"]; From 83f7d01824fe32972d0250e1e04ae018d6bbd17c Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 Jan 2025 13:14:06 +0100 Subject: [PATCH 0908/1125] Flake: backport nixpkgs pr to stable nixpkgs --- flake.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 3bdb7f1..ff45e62 100644 --- a/flake.nix +++ b/flake.nix @@ -105,7 +105,12 @@ nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; src = nixpkgs-raw; - patches = []; + patches = [ + (nixpkgs-raw.legacyPackages.x86_64-linux.fetchpatch { + url = "https://github.com/NixOS/nixpkgs/pull/370713.patch"; + hash = "sha256-gZPP99e42XdYrQz9wWHpS0ChRhK7m9Yitmy7UT5OxiM="; + }) + ]; }; # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 nixpkgs-unstable = (import "${nixpkgs-unstable-patched}/flake.nix").outputs {self = inputs.nixpkgs-unstable-raw;}; From dec75b3f7e2d10923d1da1ece8e4dea58521dc86 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 Jan 2025 16:30:45 +0100 Subject: [PATCH 0909/1125] Common/helix: change diagnostics options --- roles/common/programs/helix.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/common/programs/helix.nix b/roles/common/programs/helix.nix index ed430a0..7a52995 100644 --- a/roles/common/programs/helix.nix +++ b/roles/common/programs/helix.nix @@ -29,6 +29,8 @@ select = "Select"; }; indent-guides.render = true; + end-of-line-diagnostics = "hint"; + inline-diagnostics.cursor-line = "warning"; }; }; languages = { From a59b356e9d266b8deef7ec920b3871217aa5a0f8 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 19 Jan 2025 12:37:01 +0100 Subject: [PATCH 0910/1125] Flake: add the school role to archie --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index ff45e62..bc6be42 100644 --- a/flake.nix +++ b/flake.nix @@ -200,6 +200,7 @@ ./roles/desktop ./roles/kde ./roles/gaming + ./roles/school ]; SurfaceGo.modules = [ nixos-hardware.nixosModules.microsoft-surface-go From 65b7cf4ab69f5caf59cf97646476911794d2c99d Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 19 Jan 2025 20:45:57 +0100 Subject: [PATCH 0911/1125] School: configure helix with typecript lsp --- roles/school/programs/default.nix | 1 + roles/school/programs/helix.nix | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 roles/school/programs/helix.nix diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix index 4d4442f..60764e0 100644 --- a/roles/school/programs/default.nix +++ b/roles/school/programs/default.nix @@ -1,6 +1,7 @@ {pkgs, ...}: { imports = [ ./android-studio.nix + ./helix.nix ]; home-manager.users.toast.home.packages = [pkgs.mongodb-compass]; } diff --git a/roles/school/programs/helix.nix b/roles/school/programs/helix.nix new file mode 100644 index 0000000..e430823 --- /dev/null +++ b/roles/school/programs/helix.nix @@ -0,0 +1,10 @@ +{pkgs, ...}: { + home-manager.users.toast = { + programs.helix = { + extraPackages = with pkgs; [ + typescript-language-server + nodePackages.prettier + ]; + }; + }; +} From 573fbdd24001e7f9251c8a13ab53f714da31f073 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 21 Jan 2025 19:28:42 +0100 Subject: [PATCH 0912/1125] School/helix: set up prettier as js/ts/tsx formatter --- roles/school/programs/helix.nix | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/roles/school/programs/helix.nix b/roles/school/programs/helix.nix index e430823..8d1d235 100644 --- a/roles/school/programs/helix.nix +++ b/roles/school/programs/helix.nix @@ -3,7 +3,22 @@ programs.helix = { extraPackages = with pkgs; [ typescript-language-server - nodePackages.prettier + prettierd + ]; + languages.language = let + mkPrettierdConfig = ( + langName: fileExt: { + name = langName; + formatter = { + command = "prettierd"; + args = [".${fileExt}"]; + }; + } + ); + in [ + (mkPrettierdConfig "javascript" "js") + (mkPrettierdConfig "typescript" "ts") + (mkPrettierdConfig "tsx" "tsx") ]; }; }; From 5847ecfe1bce52ec113bd9f76890fffcdfd58617 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 23 Jan 2025 19:28:32 +0100 Subject: [PATCH 0913/1125] Machines/everest: change boot partition location --- machines/Everest/hardware-configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/Everest/hardware-configuration.nix b/machines/Everest/hardware-configuration.nix index 8689a77..5ccf3d7 100755 --- a/machines/Everest/hardware-configuration.nix +++ b/machines/Everest/hardware-configuration.nix @@ -51,7 +51,7 @@ }; fileSystems."/boot/efi" = { - device = "/dev/disk/by-label/Boot"; + device = "/dev/disk/by-uuid/FB87-4CBC"; fsType = "vfat"; }; From 251f88df020902a15996329173351ed896dd8ec2 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 23 Jan 2025 23:12:42 +0100 Subject: [PATCH 0914/1125] Server: add immich --- roles/server/default.nix | 1 + roles/server/immich.nix | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 roles/server/immich.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index 2048887..05fa471 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -18,5 +18,6 @@ ./grafana.nix ./prometheus.nix ./changedetection-io.nix + ./immich.nix ]; } diff --git a/roles/server/immich.nix b/roles/server/immich.nix new file mode 100644 index 0000000..e9a2999 --- /dev/null +++ b/roles/server/immich.nix @@ -0,0 +1,24 @@ +{...}: { + services.immich = { + enable = true; + settings = { + server.externalDomain = "https://photos.everest.tailscale"; + server.publicUsers = false; + }; + }; + # Add a record for transmission + services.headscale.settings.dns.extra_records = [ + { + name = "photos.everest.tailscale"; + type = "A"; + value = "100.100.0.1"; + } + ]; + services.caddy.virtualHosts.immich = { + hostName = "photos.everest.tailscale"; + extraConfig = '' + import tailscale + reverse_proxy localhost:2283 + ''; + }; +} From bcff4d2cbeef292be494ad60c2ab68059697f90c Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 25 Jan 2025 15:37:45 +0100 Subject: [PATCH 0915/1125] Server/immich: add too rust-motd service status --- roles/server/immich.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/immich.nix b/roles/server/immich.nix index e9a2999..5992181 100644 --- a/roles/server/immich.nix +++ b/roles/server/immich.nix @@ -21,4 +21,5 @@ reverse_proxy localhost:2283 ''; }; + programs.rust-motd.settings.service_status."Immich" = "immich-server"; } From f8bf8ed7a42b80e01d85f54684644b6c37ca1a49 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 27 Jan 2025 10:55:28 +0100 Subject: [PATCH 0916/1125] Flake: update lock file --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 5345bb4..96bd81a 100644 --- a/flake.lock +++ b/flake.lock @@ -706,11 +706,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1736417093, - "narHash": "sha256-3MRzAQaYpggkWuhZBofBjDQm02NGhUk1K4LJhf9z4k0=", + "lastModified": 1737970846, + "narHash": "sha256-+b44nvv+rKiRdABSHGaTLbp9ysRaHE+s/CuUsA9zNac=", "ref": "refs/heads/main", - "rev": "48d048bb2089631e758072561d95b4b7d1130178", - "revCount": 27, + "rev": "d8262fb108d0810d21c5e098b54a105e867e72ce", + "revCount": 28, "type": "git", "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets" }, From 786e3967e3164ea90e417fda982ef39564b7926c Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 27 Jan 2025 10:59:00 +0100 Subject: [PATCH 0917/1125] Server: add school container This container is for hosting things that I need for school I don't trust my code to be secure yet, so that's why it's in a container --- roles/server/default.nix | 1 + roles/server/school.nix | 110 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 roles/server/school.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index 05fa471..701062f 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -19,5 +19,6 @@ ./prometheus.nix ./changedetection-io.nix ./immich.nix + ./school.nix ]; } diff --git a/roles/server/school.nix b/roles/server/school.nix new file mode 100644 index 0000000..bd8ca21 --- /dev/null +++ b/roles/server/school.nix @@ -0,0 +1,110 @@ +{ + flakeSelf, + config, + ... +}: let + hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName + "/"; +in { + networking.nat = { + enable = true; + internalInterfaces = ["ve-+"]; + externalInterface = "eno1"; + }; + + age.secrets.mongodb-uri = { + file = hostSecrets + "mongodb-uri.age"; + }; + + containers.school = { + autoStart = true; + privateNetwork = true; + ephemeral = true; + hostAddress = "192.168.100.10"; + localAddress = "192.168.100.11"; + specialArgs = { + showsApi = flakeSelf.inputs.shows-api; + }; + bindMounts = { + secret = { + mountPoint = "/mongodb.env"; + isReadOnly = true; + hostPath = config.age.secrets.mongodb-uri.path; + }; + }; + config = { + config, + pkgs, + lib, + showsApi, + ... + }: { + environment.systemPackages = [pkgs.htop]; + + users.users.shows = { + name = "shows"; + group = "shows"; + isSystemUser = true; + }; + users.groups.shows = {}; + + systemd.services = let + commonServiceConfig = { + Type = "simple"; + Restart = "on-failure"; + RestartSec = 3; + + # Hardening + CapabilityBoundingSet = ""; + NoNewPrivileges = true; + PrivateUsers = true; + PrivateTmp = true; + PrivateDevices = true; + PrivateMounts = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_UNIX" + ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + }; + in { + shows-api = { + description = "NestJS API to store info about shows on a MongoDB database"; + after = ["network.target"]; + wantedBy = ["multi-user.target"]; + serviceConfig = + commonServiceConfig + // { + ExecStart = lib.getExe showsApi.packages.x86_64-linux.default; + StateDirectory = ["shows-api"]; + RuntimeDirectory = ["shows-api"]; + User = "shows"; + Group = "shows"; + EnvironmentFile = "/mongodb.env"; + }; + }; + }; + + networking = { + firewall.allowedTCPPorts = [3000]; + + # Use systemd-resolved inside the container + # Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686 + useHostResolvConf = lib.mkForce false; + }; + + services.resolved.enable = true; + + system.stateVersion = "24.11"; + }; + }; +} From 8a700174b1ce1c1da24262f05845d116bc14ceac Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 27 Jan 2025 11:17:09 +0100 Subject: [PATCH 0918/1125] Flake: add shows-api input --- flake.lock | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++- flake.nix | 2 ++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/flake.lock b/flake.lock index 96bd81a..4a15203 100644 --- a/flake.lock +++ b/flake.lock @@ -613,6 +613,18 @@ "type": "github" } }, + "nixpkgs_3": { + "locked": { + "lastModified": 0, + "narHash": "sha256-Tbk1MZbtV2s5aG+iM99U8FqwxU/YNArMcWAv6clcsBc=", + "path": "/nix/store/l9nb64iii15y0nr37qrs1cfm6rlpg6gh-source", + "type": "path" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, "nur": { "inputs": { "flake-parts": "flake-parts", @@ -700,7 +712,8 @@ "nixpkgs-unstable-raw": "nixpkgs-unstable-raw", "nur": "nur", "plasma-manager": "plasma-manager", - "secrets": "secrets" + "secrets": "secrets", + "shows-api": "shows-api" } }, "secrets": { @@ -719,6 +732,25 @@ "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets" } }, + "shows-api": { + "inputs": { + "nixpkgs": "nixpkgs_3", + "utils": "utils" + }, + "locked": { + "lastModified": 1737914989, + "narHash": "sha256-9rOs5bFZ3BQb3SgGn0dF3fCdVQZ0Zdr9nj2LhO+t5uc=", + "ref": "refs/heads/main", + "rev": "be97a926ce75b9fbe278e4ba519e9273c238316c", + "revCount": 13, + "type": "git", + "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/shows-api.git" + }, + "original": { + "type": "git", + "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/shows-api.git" + } + }, "systems": { "locked": { "lastModified": 1681028828, @@ -779,6 +811,21 @@ "type": "github" } }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "treefmt-nix": { "inputs": { "nixpkgs": [ @@ -799,6 +846,24 @@ "repo": "treefmt-nix", "type": "github" } + }, + "utils": { + "inputs": { + "systems": "systems_5" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index bc6be42..92cad5f 100644 --- a/flake.nix +++ b/flake.nix @@ -88,6 +88,8 @@ url = "github:catppuccin/konsole"; flake = false; }; + + shows-api.url = "git+ssh://forgejo@git.everest.tailscale:4222/Toast/shows-api.git"; }; outputs = {...} @ inputs: From ac36661d4e7808a6e07cfa8e46a5bfb68c6c519b Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 27 Jan 2025 13:29:31 +0100 Subject: [PATCH 0919/1125] Server/school: add dns record and caddy reverse proxy --- roles/server/school.nix | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/roles/server/school.nix b/roles/server/school.nix index bd8ca21..e255c1f 100644 --- a/roles/server/school.nix +++ b/roles/server/school.nix @@ -107,4 +107,32 @@ in { system.stateVersion = "24.11"; }; }; + services = { + headscale.settings.dns.extra_records = [ + { + name = "shows.everest.tailscale"; + type = "A"; + value = "100.100.0.1"; + } + ]; + caddy.virtualHosts.shows= { + hostName = "shows.everest.tailscale"; + extraConfig = '' + import tailscale + handle { + respond "Ionic app goes here" + } + + redir /admin /admin/ + handle_path /admin/* { + respond "Angular admin panel goes here" + } + + redir /api /api/ + handle_path /api/* { + reverse_proxy ${config.containers.school.localAddress}:3000 + } + ''; + }; + }; } From 6adbd2d38ca6b8dd0907f935f4f248b0eeb66900 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 31 Jan 2025 10:48:05 +0100 Subject: [PATCH 0920/1125] Flake: remove unneeded patch --- flake.nix | 4 +- nixpkgs-patches/update-hhd.patch | 105 ------------------------------- 2 files changed, 1 insertion(+), 108 deletions(-) delete mode 100644 nixpkgs-patches/update-hhd.patch diff --git a/flake.nix b/flake.nix index 92cad5f..cb474fd 100644 --- a/flake.nix +++ b/flake.nix @@ -100,9 +100,7 @@ nixpkgs-unstable-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; - patches = [ - ./nixpkgs-patches/update-hhd.patch - ]; + patches = []; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; diff --git a/nixpkgs-patches/update-hhd.patch b/nixpkgs-patches/update-hhd.patch deleted file mode 100644 index 65ff661..0000000 --- a/nixpkgs-patches/update-hhd.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 32d076a87fa6611f62e050047442564b27d36bc1 Mon Sep 17 00:00:00 2001 -From: Toast <39011842+toast003@users.noreply.github.com> -Date: Tue, 14 Jan 2025 10:18:45 +0100 -Subject: [PATCH] handheld-daemon: 3.9.0 -> 3.10.2 - ---- - .../0001-remove-selinux-fixes.patch | 37 +++++++++++++++++++ - pkgs/by-name/ha/handheld-daemon/package.nix | 22 +++++++++-- - 2 files changed, 55 insertions(+), 4 deletions(-) - create mode 100644 pkgs/by-name/ha/handheld-daemon/0001-remove-selinux-fixes.patch - -diff --git a/pkgs/by-name/ha/handheld-daemon/0001-remove-selinux-fixes.patch b/pkgs/by-name/ha/handheld-daemon/0001-remove-selinux-fixes.patch -new file mode 100644 -index 0000000000000..2fe3ae78a1a47 ---- /dev/null -+++ b/pkgs/by-name/ha/handheld-daemon/0001-remove-selinux-fixes.patch -@@ -0,0 +1,37 @@ -+diff --git a/src/hhd/plugins/power/power.py b/src/hhd/plugins/power/power.py -+index 5ece857..be41542 100644 -+--- a/src/hhd/plugins/power/power.py -++++ b/src/hhd/plugins/power/power.py -+@@ -79,12 +79,6 @@ def create_subvol(): -+ ) -+ return -+ -+- # Fixup selinux for swap -+- subprocess.run( -+- ["semanage", "fcontext", "-a", "-t", "var_t", HHD_SWAP_SUBVOL], -+- ) -+- subprocess.run(["restorecon", HHD_SWAP_SUBVOL]) -+- -+ logger.info(f"Creating swap subvolume {HHD_SWAP_SUBVOL}") -+ os.system(f"btrfs subvolume create {HHD_SWAP_SUBVOL}") -+ -+@@ -153,19 +147,6 @@ def create_temporary_swap(): -+ subprocess.run(["chmod", "600", HHD_SWAP_FILE], check=True) -+ subprocess.run(["mkswap", HHD_SWAP_FILE], check=True) -+ -+- # Fixup selinux for swap -+- subprocess.run( -+- [ -+- "semanage", -+- "fcontext", -+- "-a", -+- "-t", -+- "swapfile_t", -+- HHD_SWAP_FILE, -+- ], -+- ) -+- subprocess.run(["restorecon", HHD_SWAP_FILE]) -+- -+ # Enable swap -+ subprocess.run(["swapon", HHD_SWAP_FILE], check=True) -+ -diff --git a/pkgs/by-name/ha/handheld-daemon/package.nix b/pkgs/by-name/ha/handheld-daemon/package.nix -index 1c11cd3b59b28..aad4a57e50c22 100644 ---- a/pkgs/by-name/ha/handheld-daemon/package.nix -+++ b/pkgs/by-name/ha/handheld-daemon/package.nix -@@ -11,19 +11,25 @@ - efibootmgr, - dbus, - lsof, -+ btrfs-progs, -+ util-linux, - }: - python3Packages.buildPythonApplication rec { - pname = "handheld-daemon"; -- version = "3.9.0"; -+ version = "3.10.2"; - pyproject = true; - - src = fetchFromGitHub { - owner = "hhd-dev"; - repo = "hhd"; - tag = "v${version}"; -- hash = "sha256-y3CxdWqQEwdNYs4m1NEUeRjTvvhEpS5S739wyFlluWo="; -+ hash = "sha256-6BjXqqNe2u/rh1cnuJ13L/1KimprcyatIr53b0GOBSM="; - }; - -+ # Handheld-daemon runs some selinux-related utils which are not in nixpkgs. -+ # NixOS doesn't support selinux so we can safely remove them -+ patches = [ ./0001-remove-selinux-fixes.patch ]; -+ - # This package relies on several programs expected to be on the user's PATH. - # We take a more reproducible approach by patching the absolute path to each of these required - # binaries. -@@ -41,8 +47,16 @@ python3Packages.buildPythonApplication rec { - substituteInPlace src/hhd/controller/physical/imu.py \ - --replace-fail '"modprobe' '"${lib.getExe' kmod "modprobe"}' - -- substituteInPlace src/hhd/plugins/overlay/power.py \ -- --replace-fail '"efibootmgr"' '"${lib.getExe' efibootmgr "id"}"' -+ substituteInPlace src/hhd/plugins/power/power.py \ -+ --replace-fail '"efibootmgr"' '"${lib.getExe' efibootmgr "id"}"' \ -+ --replace-fail '"systemctl"' '"${lib.getExe' systemd "systemctl"}"' \ -+ --replace-fail '"stat"' '"${lib.getExe' coreutils "stat"}"' \ -+ --replace-fail '"swapon"' '"${lib.getExe' util-linux "swapon"}"' \ -+ --replace-fail '"swapoff"' '"${lib.getExe' util-linux "swapoff"}"' \ -+ --replace-fail '"fallocate"' '"${lib.getExe' util-linux "fallocate"}"' \ -+ --replace-fail '"chmod"' '"${lib.getExe' coreutils "chmod"}"' \ -+ --replace-fail '"mkswap"' '"${lib.getExe' util-linux "mkswap"}"' \ -+ --replace-fail '"btrfs",' '"${lib.getExe' btrfs-progs "btrfs"}",' - - substituteInPlace src/hhd/device/oxp/serial.py \ - --replace-fail "udevadm" "${lib.getExe' systemd "udevadm"}" From b123ab87dfc9cb3f7cfbab6a8beaf92e2cf7165a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 31 Jan 2025 10:48:21 +0100 Subject: [PATCH 0921/1125] Machines/WinMax2: temporarely change to default kernel --- machines/WinMax2/configuration.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 366ed21..55acc71 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -31,7 +31,8 @@ # Plymouth doesn't support fractional scaling :( plymouth.extraConfig = "DeviceScale=2"; - kernelPackages = pkgs.linuxPackages_latest; + # kernelPackages = pkgs.linuxPackages_latest; + # Commented out since bmi-260 doesn't compile for 6.13 }; networking.hostName = "WinMax2"; # Define your hostname. From 8bfd76f23c83a8123ca5c15475b32f8af9fc0bb0 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 31 Jan 2025 10:48:46 +0100 Subject: [PATCH 0922/1125] Flake: update lock file --- flake.lock | 297 +++++++++++------------------------------------------ 1 file changed, 60 insertions(+), 237 deletions(-) diff --git a/flake.lock b/flake.lock index 4a15203..d620561 100644 --- a/flake.lock +++ b/flake.lock @@ -25,20 +25,14 @@ }, "catppuccin": { "inputs": { - "catppuccin-v1_1": "catppuccin-v1_1", - "catppuccin-v1_2": "catppuccin-v1_2", - "home-manager": "home-manager_2", - "home-manager-stable": "home-manager-stable", - "nixpkgs": "nixpkgs", - "nixpkgs-stable": "nixpkgs-stable", - "nuscht-search": "nuscht-search" + "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1736957255, - "narHash": "sha256-qZZ/K5XheRMjCNYgle90QESuys0PIFJNPJJswMJ0GEA=", + "lastModified": 1737579274, + "narHash": "sha256-8kBIYfn8TI9jbffhDNS12SdbQHb9ITXflwcgIJBeGqw=", "owner": "catppuccin", "repo": "nix", - "rev": "f06fcadf9a61b6581b392e72f230fa6783fe36e4", + "rev": "06f0ea19334bcc8112e6d671fd53e61f9e3ad63a", "type": "github" }, "original": { @@ -63,42 +57,14 @@ "type": "github" } }, - "catppuccin-v1_1": { - "locked": { - "lastModified": 1734055249, - "narHash": "sha256-pCWJgwo77KD7EJpwynwKrWPZ//dwypHq2TfdzZWqK68=", - "rev": "7221d6ca17ac36ed20588e1c3a80177ac5843fa7", - "revCount": 326, - "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/catppuccin/nix/1.1.1/0193bdc0-b045-7eed-bbec-95611a8ecdf5/source.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://flakehub.com/f/catppuccin/nix/1.1.%2A.tar.gz" - } - }, - "catppuccin-v1_2": { - "locked": { - "lastModified": 1734734291, - "narHash": "sha256-CFX4diEQHKvZYjnhf7TLg20m3ge1O4vqgplsk/Kuaek=", - "rev": "1e4c3803b8da874ff75224ec8512cb173036bbd8", - "revCount": 344, - "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/catppuccin/nix/1.2.1/0193e646-1107-7f69-a402-f2a3988ecf1d/source.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://flakehub.com/f/catppuccin/nix/1.2.%2A.tar.gz" - } - }, "eza-themes": { "flake": false, "locked": { - "lastModified": 1736468386, - "narHash": "sha256-K9k+jE27kK8PlN6BbTfMLhCagnWCc6CIO1lkqvWl9fE=", + "lastModified": 1737730475, + "narHash": "sha256-d+bbjgI1JrOGenqZ2aIRK8itkTUV2L4L3vtEN9tEgf8=", "owner": "eza-community", "repo": "eza-themes", - "rev": "266feb8d373ac201bd28d7522e4e65cb2865f082", + "rev": "a99a5f1bbb5fec2c0bfa945ec8e2aabcb6f24d71", "type": "github" }, "original": { @@ -164,24 +130,6 @@ "type": "github" } }, - "flake-utils_3": { - "inputs": { - "systems": "systems_4" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "flakey-profile": { "locked": { "lastModified": 1712898590, @@ -233,28 +181,6 @@ "type": "github" } }, - "home-manager-stable": { - "inputs": { - "nixpkgs": [ - "catppuccin", - "nixpkgs-stable" - ] - }, - "locked": { - "lastModified": 1736373539, - "narHash": "sha256-dinzAqCjenWDxuy+MqUQq0I4zUSfaCvN9rzuCmgMZJY=", - "owner": "nix-community", - "repo": "home-manager", - "rev": "bd65bc3cde04c16755955630b344bc9e35272c56", - "type": "github" - }, - "original": { - "owner": "nix-community", - "ref": "release-24.11", - "repo": "home-manager", - "type": "github" - } - }, "home-manager-unstable": { "inputs": { "nixpkgs": [ @@ -262,11 +188,11 @@ ] }, "locked": { - "lastModified": 1737120639, - "narHash": "sha256-p5e/45V41YD3tMELuiNIoVCa25/w4nhOTm0B9MtdHFI=", + "lastModified": 1738275749, + "narHash": "sha256-PM+cGduJ05EZ+YXulqAwUFjvfKpPmW080mcuN6R1POw=", "owner": "nix-community", "repo": "home-manager", - "rev": "a0046af169ce7b1da503974e1b22c48ef4d71887", + "rev": "a8159195bfaef3c64df75d3b1e6a68d49d392be9", "type": "github" }, "original": { @@ -276,27 +202,6 @@ } }, "home-manager_2": { - "inputs": { - "nixpkgs": [ - "catppuccin", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1736508663, - "narHash": "sha256-ZOaGwa+WnB7Zn3YXimqjmIugAnHePdXCmNu+AHkq808=", - "owner": "nix-community", - "repo": "home-manager", - "rev": "2532b500c3ed2b8940e831039dcec5a5ea093afc", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "home-manager", - "type": "github" - } - }, - "home-manager_3": { "inputs": { "nixpkgs": [ "nixpkgs-raw" @@ -317,34 +222,6 @@ "type": "github" } }, - "ixx": { - "inputs": { - "flake-utils": [ - "catppuccin", - "nuscht-search", - "flake-utils" - ], - "nixpkgs": [ - "catppuccin", - "nuscht-search", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1729958008, - "narHash": "sha256-EiOq8jF4Z/zQe0QYVc3+qSKxRK//CFHMB84aYrYGwEs=", - "owner": "NuschtOS", - "repo": "ixx", - "rev": "9fd01aad037f345350eab2cd45e1946cc66da4eb", - "type": "github" - }, - "original": { - "owner": "NuschtOS", - "ref": "v0.0.6", - "repo": "ixx", - "type": "github" - } - }, "jovian": { "inputs": { "nix-github-actions": "nix-github-actions", @@ -353,11 +230,11 @@ ] }, "locked": { - "lastModified": 1737126697, - "narHash": "sha256-k1YhjONkiKBHzbjNy4ZsjysBac5UJSolCVq9cTKLeKM=", + "lastModified": 1737617533, + "narHash": "sha256-9hHaUxeRDZ5PTk7TqBbHPAjgKuBl67asaMdyehYLqFs=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "27a0ddac1a14e10ba98530f59db728951495f2ce", + "rev": "2dd65c3c92a4b8b1bf653657ae8648b883a4d427", "type": "github" }, "original": { @@ -369,11 +246,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1737086202, - "narHash": "sha256-33tcNERQt1R7tr/W7pvQj8R6NJktyTOKMIfY16RHLK8=", - "rev": "0d14c2b67a407825e3427bf079b31de069d9653a", + "lastModified": 1738295316, + "narHash": "sha256-i6dSbuPQXv3iqARBqxL0tIbSZw4Rq5UuoVrI9a8vjV0=", + "rev": "e529074cb2c21e66c300806ebf6bf03abcd681b3", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/0d14c2b67a407825e3427bf079b31de069d9653a.tar.gz?rev=0d14c2b67a407825e3427bf079b31de069d9653a" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/e529074cb2c21e66c300806ebf6bf03abcd681b3.tar.gz?rev=e529074cb2c21e66c300806ebf6bf03abcd681b3" }, "original": { "type": "tarball", @@ -382,7 +259,7 @@ }, "lix-module": { "inputs": { - "flake-utils": "flake-utils_2", + "flake-utils": "flake-utils", "flakey-profile": "flakey-profile", "lix": [ "lix" @@ -392,11 +269,11 @@ ] }, "locked": { - "lastModified": 1733522213, - "narHash": "sha256-H+Pk19MzvI/TAbXWimUPZAoKkD56OSyxJBm8lVIA5n0=", - "rev": "c374ebf5548c7b6d4bf884369a5b6879cfc916ea", + "lastModified": 1738176840, + "narHash": "sha256-NG3IRvRs3u3btVCN861FqHvgOwqcNT/Oy6PBG86F5/E=", + "rev": "621aae0f3cceaffa6d73a4fb0f89c08d338d729e", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/c374ebf5548c7b6d4bf884369a5b6879cfc916ea.tar.gz?rev=c374ebf5548c7b6d4bf884369a5b6879cfc916ea" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/621aae0f3cceaffa6d73a4fb0f89c08d338d729e.tar.gz?rev=621aae0f3cceaffa6d73a4fb0f89c08d338d729e" }, "original": { "type": "tarball", @@ -405,7 +282,7 @@ }, "lix-module-unstable": { "inputs": { - "flake-utils": "flake-utils_3", + "flake-utils": "flake-utils_2", "flakey-profile": "flakey-profile_2", "lix": [ "lix" @@ -415,11 +292,11 @@ ] }, "locked": { - "lastModified": 1733522213, - "narHash": "sha256-H+Pk19MzvI/TAbXWimUPZAoKkD56OSyxJBm8lVIA5n0=", - "rev": "c374ebf5548c7b6d4bf884369a5b6879cfc916ea", + "lastModified": 1738176840, + "narHash": "sha256-NG3IRvRs3u3btVCN861FqHvgOwqcNT/Oy6PBG86F5/E=", + "rev": "621aae0f3cceaffa6d73a4fb0f89c08d338d729e", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/c374ebf5548c7b6d4bf884369a5b6879cfc916ea.tar.gz?rev=c374ebf5548c7b6d4bf884369a5b6879cfc916ea" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/621aae0f3cceaffa6d73a4fb0f89c08d338d729e.tar.gz?rev=621aae0f3cceaffa6d73a4fb0f89c08d338d729e" }, "original": { "type": "tarball", @@ -428,11 +305,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1736952876, - "narHash": "sha256-dJXuLP2CBkIG333L+Rb3e1D0oXHYbl0MgmKPGuvFuAI=", + "lastModified": 1738175805, + "narHash": "sha256-fPjaARmK522JLJ7wxFebxG4eE/3HHSmuAA78iAZ+A7g=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "b6966d5fa96b0fae99a4da0b5bdfbb0a75f5c058", + "rev": "d4c75a33c4a7a16bf87cfd804fb5444a1ec53d49", "type": "github" }, "original": { @@ -466,11 +343,11 @@ }, "nix-impermanence": { "locked": { - "lastModified": 1736688610, - "narHash": "sha256-1Zl9xahw399UiZSJ9Vxs1W4WRFjO1SsNdVZQD4nghz0=", + "lastModified": 1737831083, + "narHash": "sha256-LJggUHbpyeDvNagTUrdhe/pRVp4pnS6wVKALS782gRI=", "owner": "nix-community", "repo": "impermanence", - "rev": "c64bed13b562fc3bb454b48773d4155023ac31b7", + "rev": "4b3e914cdf97a5b536a889e939fb2fd2b043a170", "type": "github" }, "original": { @@ -486,11 +363,11 @@ ] }, "locked": { - "lastModified": 1736652904, - "narHash": "sha256-8uolHABgroXqzs03QdulHp8H9e5kWQZnnhcda1MKbBM=", + "lastModified": 1737861961, + "narHash": "sha256-LIRtMvAwLGb8pBoamzgEF67oKlNPz4LuXiRPVZf+TpE=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "271e5bd7c57e1f001693799518b10a02d1123b12", + "rev": "79b7b8eae3243fc5aa9aad34ba6b9bbb2266f523", "type": "github" }, "original": { @@ -506,11 +383,11 @@ ] }, "locked": { - "lastModified": 1736652904, - "narHash": "sha256-8uolHABgroXqzs03QdulHp8H9e5kWQZnnhcda1MKbBM=", + "lastModified": 1737861961, + "narHash": "sha256-LIRtMvAwLGb8pBoamzgEF67oKlNPz4LuXiRPVZf+TpE=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "271e5bd7c57e1f001693799518b10a02d1123b12", + "rev": "79b7b8eae3243fc5aa9aad34ba6b9bbb2266f523", "type": "github" }, "original": { @@ -521,11 +398,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1736978406, - "narHash": "sha256-oMr3PVIQ8XPDI8/x6BHxsWEPBRU98Pam6KGVwUh8MPk=", + "lastModified": 1737751639, + "narHash": "sha256-ZEbOJ9iT72iwqXsiEMbEa8wWjyFvRA9Ugx8utmYbpz4=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "b678606690027913f3434dea3864e712b862dde5", + "rev": "dfad538f751a5aa5d4436d9781ab27a6128ec9d4", "type": "github" }, "original": { @@ -553,11 +430,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1736916166, - "narHash": "sha256-puPDoVKxkuNmYIGMpMQiK8bEjaACcCksolsG36gdaNQ=", + "lastModified": 1738163270, + "narHash": "sha256-B/7Y1v4y+msFFBW1JAdFjNvVthvNdJKiN6EGRPnqfno=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e24b4c09e963677b1beea49d411cd315a024ad3a", + "rev": "59e618d90c065f55ae48446f307e8c09565d5ab0", "type": "github" }, "original": { @@ -566,29 +443,13 @@ "type": "indirect" } }, - "nixpkgs-stable": { - "locked": { - "lastModified": 1736061677, - "narHash": "sha256-DjkQPnkAfd7eB522PwnkGhOMuT9QVCZspDpJJYyOj60=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "cbd8ec4de4469333c82ff40d057350c30e9f7d36", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-24.11", - "repo": "nixpkgs", - "type": "github" - } - }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1737062831, - "narHash": "sha256-Tbk1MZbtV2s5aG+iM99U8FqwxU/YNArMcWAv6clcsBc=", + "lastModified": 1738142207, + "narHash": "sha256-NGqpVVxNAHwIicXpgaVqJEJWeyqzoQJ9oc8lnK9+WC4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5df43628fdf08d642be8ba5b3625a6c70731c19c", + "rev": "9d3ae807ebd2981d593cddd0080856873139aa40", "type": "github" }, "original": { @@ -599,11 +460,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1736883708, - "narHash": "sha256-uQ+NQ0/xYU0N1CnXsa2zghgNaOPxWpMJXSUJJ9W7140=", + "lastModified": 1738142207, + "narHash": "sha256-NGqpVVxNAHwIicXpgaVqJEJWeyqzoQJ9oc8lnK9+WC4=", "owner": "nixos", "repo": "nixpkgs", - "rev": "eb62e6aa39ea67e0b8018ba8ea077efe65807dc8", + "rev": "9d3ae807ebd2981d593cddd0080856873139aa40", "type": "github" }, "original": { @@ -632,11 +493,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1737147292, - "narHash": "sha256-y5ALxyA2en4I81mwdeJgatg0u/SWi0LMAv+uakJ9czE=", + "lastModified": 1738308670, + "narHash": "sha256-88WNLo6WdYmlO5u+1vaVRIakliO0B9hiNxBEMTZ9yOM=", "owner": "nix-community", "repo": "NUR", - "rev": "a55bbc7cf3f8772ef6274a32520ce117f32f9d0e", + "rev": "a75432a6ffa9ca5af9f885194b64e0d4ad10b96b", "type": "github" }, "original": { @@ -645,29 +506,6 @@ "type": "github" } }, - "nuscht-search": { - "inputs": { - "flake-utils": "flake-utils", - "ixx": "ixx", - "nixpkgs": [ - "catppuccin", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1735854821, - "narHash": "sha256-Iv59gMDZajNfezTO0Fw6LHE7uKAShxbvMidmZREit7c=", - "owner": "NuschtOS", - "repo": "search", - "rev": "836908e3bddd837ae0f13e215dd48767aee355f0", - "type": "github" - }, - "original": { - "owner": "NuschtOS", - "repo": "search", - "type": "github" - } - }, "plasma-manager": { "inputs": { "home-manager": [ @@ -697,7 +535,7 @@ "catppuccin": "catppuccin", "catppuccin-konsole": "catppuccin-konsole", "eza-themes": "eza-themes", - "home-manager": "home-manager_3", + "home-manager": "home-manager_2", "home-manager-unstable": "home-manager-unstable", "jovian": "jovian", "lix": "lix", @@ -738,11 +576,11 @@ "utils": "utils" }, "locked": { - "lastModified": 1737914989, - "narHash": "sha256-9rOs5bFZ3BQb3SgGn0dF3fCdVQZ0Zdr9nj2LhO+t5uc=", + "lastModified": 1738235282, + "narHash": "sha256-UpKVpjZwlse6aFNuke9J0AvQtnDNs8yLZqoDd5W2WWw=", "ref": "refs/heads/main", - "rev": "be97a926ce75b9fbe278e4ba519e9273c238316c", - "revCount": 13, + "rev": "b4eae5b0b39934e558dac957da7feaa5e21d183c", + "revCount": 21, "type": "git", "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/shows-api.git" }, @@ -811,21 +649,6 @@ "type": "github" } }, - "systems_5": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, "treefmt-nix": { "inputs": { "nixpkgs": [ @@ -849,7 +672,7 @@ }, "utils": { "inputs": { - "systems": "systems_5" + "systems": "systems_4" }, "locked": { "lastModified": 1731533236, From bdff3d97e93e4a0f7e97b94ebbfe9264e4ddc74d Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 31 Jan 2025 11:11:23 +0100 Subject: [PATCH 0923/1125] Desktop: enable xdg autostart --- roles/desktop/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index 4348234..02fc317 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -22,5 +22,7 @@ hardware.keyboard.qmk.enable = true; home-manager.users.toast.home.packages = [pkgs.qmk]; + home-manager.users.toast.xdg.autostart.enable = true; + boot.plymouth.enable = true; } From 3dd73e0b24c8ef0edb77bb0467a6c90e5f74bd25 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 31 Jan 2025 11:11:43 +0100 Subject: [PATCH 0924/1125] Desktop/keepassxc: replace manual autostart config with home-manager module --- roles/desktop/programs/keepassxc.nix | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/roles/desktop/programs/keepassxc.nix b/roles/desktop/programs/keepassxc.nix index ad2dbb2..fd5321a 100644 --- a/roles/desktop/programs/keepassxc.nix +++ b/roles/desktop/programs/keepassxc.nix @@ -34,30 +34,11 @@ in { # No module for KeePassXC config :( home = { packages = [pkgs.keepassxc]; - file = { - ".config/keepassxc/keepassxc.ini".text = kpxcSettings; - # For some reason the autostart .desktop is not the same as the regular one - ".config/autostart/org.keepassxc.KeePassXC.desktop".text = '' - [Desktop Entry] - Name=KeePassXC - GenericName=Password Manager - Exec=keepassxc - TryExec=keepassxc - Icon=keepassxc - StartupWMClass=keepassxc - StartupNotify=true - Terminal=false - Type=Application - Version=1.0 - Categories=Utility;Security;Qt; - MimeType=application/x-keepass2; - X-GNOME-Autostart-enabled=true - X-GNOME-Autostart-Delay=2 - X-KDE-autostart-after=panel - X-LXQt-Need-Tray=true - ''; - }; + file.".config/keepassxc/keepassxc.ini".text = kpxcSettings; }; + xdg.autostart.entries = [ + "${pkgs.keepassxc}/share/applications/org.keepassxc.KeePassXC.desktop" + ]; }; }; } From c46418c78335194f9c4436cd2aa222c112bc2fc6 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Feb 2025 09:52:20 +0100 Subject: [PATCH 0925/1125] Gaming/PCSX2: fix games location --- roles/gaming/programs/pcsx2.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index b6ac4b2..cb2cda2 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -29,7 +29,7 @@ in { Bios = "/home/toast/.local/share/PCSX2/bios"; }; GameList.RecursivePaths = [ - "/home/toast/Games/Isos/PS2/" + "/home/toast/Games/PS2/" ]; "EmuCore/GS" = { dithering_ps2 = 1; From 1c7d4a513d64fd1b7db56fd85018e3e1226d78ef Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Feb 2025 09:30:12 +0100 Subject: [PATCH 0926/1125] Server/headscale: never stop trying to restart --- roles/server/headscale.nix | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/roles/server/headscale.nix b/roles/server/headscale.nix index dd4b0f6..c926c0b 100644 --- a/roles/server/headscale.nix +++ b/roles/server/headscale.nix @@ -1,4 +1,4 @@ -{...}: { +{lib, ...}: { services.headscale = { enable = true; settings = { @@ -20,5 +20,11 @@ }; }; programs.rust-motd.settings.service_status.Headscale = "headscale"; - systemd.services.tailscaled.after = ["headscale.service"]; + systemd = { + services.tailscaled.after = ["headscale.service"]; + services.headscale = { + serviceConfig.RestartSec = lib.mkForce "120s"; + unitConfig.StartLimitBurst = lib.mkForce "infinity"; + }; + }; } From 789157e3bf5ebc93f9c040bf42314a0d0838f6e0 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 7 Feb 2025 20:12:41 +0100 Subject: [PATCH 0927/1125] Flake: update shows-api input --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index d620561..f6a3060 100644 --- a/flake.lock +++ b/flake.lock @@ -576,11 +576,11 @@ "utils": "utils" }, "locked": { - "lastModified": 1738235282, - "narHash": "sha256-UpKVpjZwlse6aFNuke9J0AvQtnDNs8yLZqoDd5W2WWw=", + "lastModified": 1738967312, + "narHash": "sha256-U8p5la0UDcrwYM7+DYWeFUcCjKIePQMXWV3nT9UaPvQ=", "ref": "refs/heads/main", - "rev": "b4eae5b0b39934e558dac957da7feaa5e21d183c", - "revCount": 21, + "rev": "72e0b07f71445b6f16942b2db1bd888ed587879b", + "revCount": 46, "type": "git", "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/shows-api.git" }, From 5640408d9f1792d891f9aeb13f7312a8d8d759c9 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 15 Feb 2025 16:04:10 +0100 Subject: [PATCH 0928/1125] Roles/kde: remove patches All of this patches are in 6.3, so they're not needed anymore --- roles/kde/patches/kwin-pr6406.patch | 1045 ----------------- roles/kde/patches/kwin-pr6844.patch | 41 - roles/kde/patches/kwin-pr6878.patch | 753 ------------ roles/kde/patches/kwin-pr6985.patch | 41 - roles/kde/patches/libplasma-pr1214.patch | 48 - roles/kde/patches/plasma_desktop-pr2661.patch | 39 - .../kde/patches/plasma_workspace-pr4883.patch | 40 - .../kde/patches/plasma_workspace-pr4965.patch | 915 --------------- roles/kde/plasma.nix | 31 - roles/kde/programs/kwin.nix | 20 - 10 files changed, 2973 deletions(-) delete mode 100644 roles/kde/patches/kwin-pr6406.patch delete mode 100644 roles/kde/patches/kwin-pr6844.patch delete mode 100644 roles/kde/patches/kwin-pr6878.patch delete mode 100644 roles/kde/patches/kwin-pr6985.patch delete mode 100644 roles/kde/patches/libplasma-pr1214.patch delete mode 100644 roles/kde/patches/plasma_desktop-pr2661.patch delete mode 100644 roles/kde/patches/plasma_workspace-pr4883.patch delete mode 100644 roles/kde/patches/plasma_workspace-pr4965.patch diff --git a/roles/kde/patches/kwin-pr6406.patch b/roles/kde/patches/kwin-pr6406.patch deleted file mode 100644 index e3a55a8..0000000 --- a/roles/kde/patches/kwin-pr6406.patch +++ /dev/null @@ -1,1045 +0,0 @@ -From 3ea8c3758e75f06c71b0b279c4e51f22ec554954 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Fri, 4 Oct 2024 22:49:16 +0300 -Subject: [PATCH 1/9] Resize X11 window immediately if it doesn't support - _NET_WM_SYNC_REQUEST - -The fact that X11Window::handleSyncTimeout() is shared by code that runs -when the client supports or doesn't support _NET_WM_SYNC_REQUEST makes -the XSync code difficult to follow and more error prone. - -On the other hand, it appears that other window managers, e.g. Mutter and -openbox, don't bother about throttling interactive resize when the client -doesn't opt in into _NET_WM_SYNC_REQUEST, so let's do the same to simplify -the code. - -As a backup plan, if it indeed becomes a problem later, we can always -save current monotonic time in X11Window::doInteractiveResizeSync() and -make X11Window::isWaitingForInteractiveResizeSync() check whether enough -of time has passed since the last resize sync. ---- - autotests/integration/x11_window_test.cpp | 16 +++-------- - src/x11window.cpp | 35 +++++++++-------------- - 2 files changed, 17 insertions(+), 34 deletions(-) - -diff --git a/autotests/integration/x11_window_test.cpp b/autotests/integration/x11_window_test.cpp -index 12f53c4220..a208fa3adb 100644 ---- a/autotests/integration/x11_window_test.cpp -+++ b/autotests/integration/x11_window_test.cpp -@@ -1492,7 +1492,6 @@ void X11WindowTest::testNetWmKeyboardResize() - QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted); - QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished); - QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped); -- QSignalSpy frameGeometryChangedSpy(window, &X11Window::frameGeometryChanged); - QVERIFY(interactiveMoveResizeStartedSpy.wait()); - QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0); - QVERIFY(window->isInteractiveResize()); -@@ -1503,7 +1502,6 @@ void X11WindowTest::testNetWmKeyboardResize() - Test::keyboardKeyPressed(KEY_RIGHT, timestamp++); - Test::keyboardKeyReleased(KEY_RIGHT, timestamp++); - QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1); -- QVERIFY(frameGeometryChangedSpy.wait()); - QCOMPARE(window->frameGeometry(), originalGeometry.adjusted(0, 0, 8, 0)); - - // Finish the interactive move. -@@ -1531,7 +1529,6 @@ void X11WindowTest::testNetWmKeyboardResizeCancel() - QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted); - QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished); - QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped); -- QSignalSpy frameGeometryChangedSpy(window, &X11Window::frameGeometryChanged); - QVERIFY(interactiveMoveResizeStartedSpy.wait()); - QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0); - QVERIFY(window->isInteractiveResize()); -@@ -1542,7 +1539,6 @@ void X11WindowTest::testNetWmKeyboardResizeCancel() - Test::keyboardKeyPressed(KEY_RIGHT, timestamp++); - Test::keyboardKeyReleased(KEY_RIGHT, timestamp++); - QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1); -- QVERIFY(frameGeometryChangedSpy.wait()); - QCOMPARE(window->frameGeometry(), originalGeometry.adjusted(0, 0, 8, 0)); - - // Cancel the interactive move. -@@ -1741,7 +1737,6 @@ void X11WindowTest::testNetWmButtonSize() - QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted); - QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished); - QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped); -- QSignalSpy frameGeometryChangedSpy(window, &X11Window::frameGeometryChanged); - QVERIFY(interactiveMoveResizeStartedSpy.wait()); - QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0); - QVERIFY(window->isInteractiveResize()); -@@ -1750,7 +1745,6 @@ void X11WindowTest::testNetWmButtonSize() - // Resize the window a tiny bit. - Test::pointerMotionRelative(directionToVector(direction, QSizeF(8, 8)), timestamp++); - QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1); -- QVERIFY(frameGeometryChangedSpy.wait()); - QCOMPARE(window->frameGeometry(), expandRect(originalGeometry, direction, QSizeF(8, 8))); - - // Finish the interactive move. -@@ -1803,7 +1797,6 @@ void X11WindowTest::testNetWmButtonSizeCancel() - QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted); - QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished); - QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped); -- QSignalSpy frameGeometryChangedSpy(window, &X11Window::frameGeometryChanged); - QVERIFY(interactiveMoveResizeStartedSpy.wait()); - QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0); - QVERIFY(window->isInteractiveResize()); -@@ -1811,7 +1804,6 @@ void X11WindowTest::testNetWmButtonSizeCancel() - // Resize the window a tiny bit. - Test::pointerMotionRelative(QPointF(-8, -8), timestamp++); - QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1); -- QVERIFY(frameGeometryChangedSpy.wait()); - QCOMPARE(window->frameGeometry(), originalGeometry.adjusted(-8, -8, 0, 0)); - - // Cancel the interactive resize. -@@ -1888,7 +1880,7 @@ void X11WindowTest::testMinimumSize() - window->updateInteractiveMoveResize(KWin::Cursors::self()->mouse()->pos(), Qt::KeyboardModifiers()); - QCOMPARE(KWin::Cursors::self()->mouse()->pos(), cursorPos + QPoint(8, 0)); - QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1); -- QVERIFY(frameGeometryChangedSpy.wait()); -+ QVERIFY(!frameGeometryChangedSpy.wait(10)); - // whilst X11 window size goes through scale, the increment is a logical value kwin side - QCOMPARE(window->clientSize().width(), 100 / scale + 8); - -@@ -1910,7 +1902,7 @@ void X11WindowTest::testMinimumSize() - window->updateInteractiveMoveResize(KWin::Cursors::self()->mouse()->pos(), Qt::KeyboardModifiers()); - QCOMPARE(KWin::Cursors::self()->mouse()->pos(), cursorPos + QPoint(8, 8)); - QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 2); -- QVERIFY(frameGeometryChangedSpy.wait()); -+ QVERIFY(!frameGeometryChangedSpy.wait(10)); - QCOMPARE(window->clientSize().height(), 200 / scale + 8); - - // Finish the resize operation. -@@ -1993,7 +1985,7 @@ void X11WindowTest::testMaximumSize() - window->updateInteractiveMoveResize(KWin::Cursors::self()->mouse()->pos(), Qt::KeyboardModifiers()); - QCOMPARE(KWin::Cursors::self()->mouse()->pos(), cursorPos + QPoint(-8, 0)); - QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1); -- QVERIFY(frameGeometryChangedSpy.wait()); -+ QVERIFY(!frameGeometryChangedSpy.wait(10)); - QCOMPARE(window->clientSize().width(), 100 / scale - 8); - - window->keyPressEvent(Qt::Key_Down); -@@ -2014,7 +2006,7 @@ void X11WindowTest::testMaximumSize() - window->updateInteractiveMoveResize(KWin::Cursors::self()->mouse()->pos(), Qt::KeyboardModifiers()); - QCOMPARE(KWin::Cursors::self()->mouse()->pos(), cursorPos + QPoint(-8, -8)); - QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 2); -- QVERIFY(frameGeometryChangedSpy.wait()); -+ QVERIFY(!frameGeometryChangedSpy.wait(10)); - QCOMPARE(window->clientSize().height(), 200 / scale - 8); - - // Finish the resize operation. -diff --git a/src/x11window.cpp b/src/x11window.cpp -index b71a9d3640..780ccfbc7e 100644 ---- a/src/x11window.cpp -+++ b/src/x11window.cpp -@@ -4857,36 +4857,27 @@ void X11Window::doInteractiveResizeSync(const QRectF &rect) - return; - } - -- setMoveResizeGeometry(moveResizeFrameGeometry); -- setAllowCommits(false); -+ if (m_syncRequest.counter == XCB_NONE) { -+ moveResize(rect); -+ } else { -+ if (!m_syncRequest.timeout) { -+ m_syncRequest.timeout = new QTimer(this); -+ connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Window::handleSyncTimeout); -+ m_syncRequest.timeout->setSingleShot(true); -+ } - -- if (!m_syncRequest.timeout) { -- m_syncRequest.timeout = new QTimer(this); -- connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Window::handleSyncTimeout); -- m_syncRequest.timeout->setSingleShot(true); -- } -+ setMoveResizeGeometry(moveResizeFrameGeometry); -+ setAllowCommits(false); - -- if (m_syncRequest.counter != XCB_NONE) { -- m_syncRequest.timeout->start(250); - sendSyncRequest(); -- } else { -- // For clients not supporting the XSYNC protocol, we limit the resizes to 30Hz -- // to take pointless load from X11 and the client, the mouse is still moved at -- // full speed and no human can control faster resizes anyway. -- m_syncRequest.isPending = true; -- m_syncRequest.interactiveResize = true; -- m_syncRequest.timeout->start(33); -- } -+ configure(nativeFrameGeometry, nativeWrapperGeometry, nativeClientGeometry); - -- configure(nativeFrameGeometry, nativeWrapperGeometry, nativeClientGeometry); -+ m_syncRequest.timeout->start(250); -+ } - } - - void X11Window::handleSyncTimeout() - { -- if (m_syncRequest.counter == XCB_NONE) { // client w/o XSYNC support. allow the next resize event -- m_syncRequest.isPending = false; // NEVER do this for clients with a valid counter -- m_syncRequest.interactiveResize = false; // (leads to sync request races in some clients) -- } - performInteractiveResize(); - } - --- -2.47.0 - - -From 1be3dfa4b40732997ecb1bd1959ba775331d603a Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Fri, 4 Oct 2024 22:55:44 +0300 -Subject: [PATCH 2/9] Rename X11Window::handleSync,handleSyncTimeout - ---- - src/syncalarmx11filter.cpp | 2 +- - src/x11window.cpp | 6 +++--- - src/x11window.h | 4 ++-- - 3 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/syncalarmx11filter.cpp b/src/syncalarmx11filter.cpp -index f4b4d49caa..133c3c6b99 100644 ---- a/src/syncalarmx11filter.cpp -+++ b/src/syncalarmx11filter.cpp -@@ -28,7 +28,7 @@ bool SyncAlarmX11Filter::event(xcb_generic_event_t *event) - return alarmEvent->alarm == syncRequest.alarm && alarmEvent->counter_value.hi == syncRequest.value.hi && alarmEvent->counter_value.lo == syncRequest.value.lo; - }); - if (client) { -- client->handleSync(); -+ client->ackSync(); - } - return false; - } -diff --git a/src/x11window.cpp b/src/x11window.cpp -index 780ccfbc7e..14d45abb27 100644 ---- a/src/x11window.cpp -+++ b/src/x11window.cpp -@@ -3059,7 +3059,7 @@ void X11Window::checkApplicationMenuObjectPath() - readApplicationMenuObjectPath(property); - } - --void X11Window::handleSync() -+void X11Window::ackSync() - { - setReadyForPainting(); - m_syncRequest.isPending = false; -@@ -4862,7 +4862,7 @@ void X11Window::doInteractiveResizeSync(const QRectF &rect) - } else { - if (!m_syncRequest.timeout) { - m_syncRequest.timeout = new QTimer(this); -- connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Window::handleSyncTimeout); -+ connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Window::ackSyncTimeout); - m_syncRequest.timeout->setSingleShot(true); - } - -@@ -4876,7 +4876,7 @@ void X11Window::doInteractiveResizeSync(const QRectF &rect) - } - } - --void X11Window::handleSyncTimeout() -+void X11Window::ackSyncTimeout() - { - performInteractiveResize(); - } -diff --git a/src/x11window.h b/src/x11window.h -index 4f3b43c8b0..b54db23345 100644 ---- a/src/x11window.h -+++ b/src/x11window.h -@@ -293,8 +293,8 @@ public: - return m_syncRequest; - } - bool wantsSyncCounter() const; -- void handleSync(); -- void handleSyncTimeout(); -+ void ackSync(); -+ void ackSyncTimeout(); - - bool allowWindowActivation(xcb_timestamp_t time = -1U, bool focus_in = false); - --- -2.47.0 - - -From ea53098c38b64cb5870ef4f3b47fb53f509e03a4 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Fri, 4 Oct 2024 22:59:34 +0300 -Subject: [PATCH 3/9] Rename X11Window::SyncRequest::isPending - ---- - src/x11window.cpp | 12 ++++++------ - src/x11window.h | 2 +- - 2 files changed, 7 insertions(+), 7 deletions(-) - -diff --git a/src/x11window.cpp b/src/x11window.cpp -index 14d45abb27..2ebb4a5957 100644 ---- a/src/x11window.cpp -+++ b/src/x11window.cpp -@@ -309,7 +309,7 @@ X11Window::X11Window() - m_syncRequest.counter = m_syncRequest.alarm = XCB_NONE; - m_syncRequest.timeout = m_syncRequest.failsafeTimeout = nullptr; - m_syncRequest.lastTimestamp = xTime(); -- m_syncRequest.isPending = false; -+ m_syncRequest.pending = false; - m_syncRequest.interactiveResize = false; - - // Set the initial mapping state -@@ -2585,7 +2585,7 @@ void X11Window::getSyncCounter() - */ - void X11Window::sendSyncRequest() - { -- if (m_syncRequest.counter == XCB_NONE || m_syncRequest.isPending) { -+ if (m_syncRequest.counter == XCB_NONE || m_syncRequest.pending) { - return; // do NOT, NEVER send a sync request when there's one on the stack. the clients will just stop respoding. FOREVER! ... - } - -@@ -2599,7 +2599,7 @@ void X11Window::sendSyncRequest() - return; - } - // failed during resize -- m_syncRequest.isPending = false; -+ m_syncRequest.pending = false; - m_syncRequest.interactiveResize = false; - m_syncRequest.counter = XCB_NONE; - m_syncRequest.alarm = XCB_NONE; -@@ -2630,7 +2630,7 @@ void X11Window::sendSyncRequest() - // Send the message to client - sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_sync_request, - m_syncRequest.value.lo, m_syncRequest.value.hi); -- m_syncRequest.isPending = true; -+ m_syncRequest.pending = true; - m_syncRequest.interactiveResize = isInteractiveResize(); - m_syncRequest.lastTimestamp = xTime(); - } -@@ -3062,7 +3062,7 @@ void X11Window::checkApplicationMenuObjectPath() - void X11Window::ackSync() - { - setReadyForPainting(); -- m_syncRequest.isPending = false; -+ m_syncRequest.pending = false; - if (m_syncRequest.failsafeTimeout) { - m_syncRequest.failsafeTimeout->stop(); - } -@@ -4840,7 +4840,7 @@ void X11Window::leaveInteractiveMoveResize() - - bool X11Window::isWaitingForInteractiveResizeSync() const - { -- return m_syncRequest.isPending && m_syncRequest.interactiveResize; -+ return m_syncRequest.pending && m_syncRequest.interactiveResize; - } - - void X11Window::doInteractiveResizeSync(const QRectF &rect) -diff --git a/src/x11window.h b/src/x11window.h -index b54db23345..10fa57eaf2 100644 ---- a/src/x11window.h -+++ b/src/x11window.h -@@ -285,7 +285,7 @@ public: - xcb_sync_alarm_t alarm; - xcb_timestamp_t lastTimestamp; - QTimer *timeout, *failsafeTimeout; -- bool isPending; -+ bool pending; - bool interactiveResize; - }; - const SyncRequest &syncRequest() const --- -2.47.0 - - -From 49319a3f3e2a1d468e12bdf3dfd7eeb2e3db0899 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Fri, 4 Oct 2024 23:12:44 +0300 -Subject: [PATCH 4/9] Make XSync timeout more permissive - -There are two timeouts: a soft one and a hard one. If the soft timeout -occurs, then the scheduled operation will be performed. For example, -the window will be marked as ready for painting or resized. If the hard -timeout occurs, _NET_WM_SYNC_REQUEST will be disabled. - -Such an arrangement is fine in its current present form, but in order -to make Xwayland window resizing less glitchy, _NET_WM_SYNC_REQUEST -code needs to interact with wl_surface event flow, which in its turn -means that the timeout code also needs to be prepared for that. It is -very challenging to make the timeout code not break, so this change -seeks to re-arrange the timeout handling so it's easier to integrate -with wl_surface commits. - -With the proposed changes, there is going to be only one timer: timeout. -If it fires, the window will be resized immediately and XSync is going -to be kept disabled until an acknowledgement arrives from the client. ---- - src/x11window.cpp | 101 +++++++++++++++++----------------------------- - src/x11window.h | 5 ++- - 2 files changed, 41 insertions(+), 65 deletions(-) - -diff --git a/src/x11window.cpp b/src/x11window.cpp -index 2ebb4a5957..1d25ab82b1 100644 ---- a/src/x11window.cpp -+++ b/src/x11window.cpp -@@ -307,8 +307,9 @@ X11Window::X11Window() - - // TODO: Do all as initialization - m_syncRequest.counter = m_syncRequest.alarm = XCB_NONE; -- m_syncRequest.timeout = m_syncRequest.failsafeTimeout = nullptr; -+ m_syncRequest.timeout = nullptr; - m_syncRequest.lastTimestamp = xTime(); -+ m_syncRequest.enabled = false; - m_syncRequest.pending = false; - m_syncRequest.interactiveResize = false; - -@@ -460,9 +461,6 @@ void X11Window::releaseWindow(bool on_shutdown) - ungrabXServer(); - } - -- if (m_syncRequest.failsafeTimeout) { -- m_syncRequest.failsafeTimeout->stop(); -- } - if (m_syncRequest.timeout) { - m_syncRequest.timeout->stop(); - } -@@ -516,9 +514,6 @@ void X11Window::destroyWindow() - m_frame.reset(); - } - -- if (m_syncRequest.failsafeTimeout) { -- m_syncRequest.failsafeTimeout->stop(); -- } - if (m_syncRequest.timeout) { - m_syncRequest.timeout->stop(); - } -@@ -2550,6 +2545,7 @@ void X11Window::getSyncCounter() - Xcb::Property syncProp(false, window(), atoms->net_wm_sync_request_counter, XCB_ATOM_CARDINAL, 0, 1); - const xcb_sync_counter_t counter = syncProp.value(XCB_NONE); - if (counter != XCB_NONE) { -+ m_syncRequest.enabled = true; - m_syncRequest.counter = counter; - m_syncRequest.value.hi = 0; - m_syncRequest.value.lo = 0; -@@ -2585,35 +2581,16 @@ void X11Window::getSyncCounter() - */ - void X11Window::sendSyncRequest() - { -- if (m_syncRequest.counter == XCB_NONE || m_syncRequest.pending) { -+ if (!m_syncRequest.enabled || m_syncRequest.pending) { - return; // do NOT, NEVER send a sync request when there's one on the stack. the clients will just stop respoding. FOREVER! ... - } - -- if (!m_syncRequest.failsafeTimeout) { -- m_syncRequest.failsafeTimeout = new QTimer(this); -- connect(m_syncRequest.failsafeTimeout, &QTimer::timeout, this, [this]() { -- // client does not respond to XSYNC requests in reasonable time, remove support -- if (!ready_for_painting) { -- // failed on initial pre-show request -- setReadyForPainting(); -- return; -- } -- // failed during resize -- m_syncRequest.pending = false; -- m_syncRequest.interactiveResize = false; -- m_syncRequest.counter = XCB_NONE; -- m_syncRequest.alarm = XCB_NONE; -- delete m_syncRequest.timeout; -- delete m_syncRequest.failsafeTimeout; -- m_syncRequest.timeout = nullptr; -- m_syncRequest.failsafeTimeout = nullptr; -- m_syncRequest.lastTimestamp = XCB_CURRENT_TIME; -- }); -- m_syncRequest.failsafeTimeout->setSingleShot(true); -+ if (!m_syncRequest.timeout) { -+ m_syncRequest.timeout = new QTimer(this); -+ m_syncRequest.timeout->setSingleShot(true); -+ connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Window::ackSyncTimeout); - } -- // if there's no response within 10 seconds, sth. went wrong and we remove XSYNC support from this client. -- // see events.cpp X11Window::syncEvent() -- m_syncRequest.failsafeTimeout->start(ready_for_painting ? 10000 : 1000); -+ m_syncRequest.timeout->start(ready_for_painting ? 10000 : 1000); - - // We increment before the notify so that after the notify - // syncCounterSerial will equal the value we are expecting -@@ -3061,29 +3038,40 @@ void X11Window::checkApplicationMenuObjectPath() - - void X11Window::ackSync() - { -- setReadyForPainting(); -+ // Note that a sync request can be ack'ed after the timeout. If that happens, just re-enable -+ // XSync back and do nothing more. - m_syncRequest.pending = false; -- if (m_syncRequest.failsafeTimeout) { -- m_syncRequest.failsafeTimeout->stop(); -+ if (!m_syncRequest.enabled) { -+ m_syncRequest.enabled = true; -+ return; - } - -- // Sync request can be acknowledged shortly after finishing resize. -+ m_syncRequest.timeout->stop(); -+ -+ finishSync(); -+} -+ -+void X11Window::ackSyncTimeout() -+{ -+ // If a sync request times out, disable XSync temporarily until the client comes back to its senses. -+ m_syncRequest.enabled = false; -+ -+ finishSync(); -+} -+ -+void X11Window::finishSync() -+{ -+ setReadyForPainting(); -+ - if (m_syncRequest.interactiveResize) { - m_syncRequest.interactiveResize = false; -- if (m_syncRequest.timeout) { -- m_syncRequest.timeout->stop(); -- } -- performInteractiveResize(); -+ -+ moveResize(moveResizeGeometry()); - updateWindowPixmap(); -+ setAllowCommits(true); - } - } - --void X11Window::performInteractiveResize() --{ -- resize(moveResizeGeometry().size()); -- setAllowCommits(true); --} -- - bool X11Window::belongToSameApplication(const X11Window *c1, const X11Window *c2, SameApplicationChecks checks) - { - bool same_app = false; -@@ -4840,7 +4828,7 @@ void X11Window::leaveInteractiveMoveResize() - - bool X11Window::isWaitingForInteractiveResizeSync() const - { -- return m_syncRequest.pending && m_syncRequest.interactiveResize; -+ return m_syncRequest.enabled && m_syncRequest.pending && m_syncRequest.interactiveResize; - } - - void X11Window::doInteractiveResizeSync(const QRectF &rect) -@@ -4857,30 +4845,17 @@ void X11Window::doInteractiveResizeSync(const QRectF &rect) - return; - } - -- if (m_syncRequest.counter == XCB_NONE) { -+ if (!m_syncRequest.enabled) { - moveResize(rect); - } else { -- if (!m_syncRequest.timeout) { -- m_syncRequest.timeout = new QTimer(this); -- connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Window::ackSyncTimeout); -- m_syncRequest.timeout->setSingleShot(true); -- } -- - setMoveResizeGeometry(moveResizeFrameGeometry); - setAllowCommits(false); - - sendSyncRequest(); - configure(nativeFrameGeometry, nativeWrapperGeometry, nativeClientGeometry); -- -- m_syncRequest.timeout->start(250); - } - } - --void X11Window::ackSyncTimeout() --{ -- performInteractiveResize(); --} -- - NETExtendedStrut X11Window::strut() const - { - NETExtendedStrut ext = info->extendedStrut(); -@@ -4991,7 +4966,7 @@ void X11Window::damageNotifyEvent() - Q_ASSERT(kwinApp()->operationMode() == Application::OperationModeX11); - - if (!readyForPainting()) { // avoid "setReadyForPainting()" function calling overhead -- if (m_syncRequest.counter == XCB_NONE) { // cannot detect complete redraw, consider done now -+ if (!m_syncRequest.enabled) { // cannot detect complete redraw, consider done now - setReadyForPainting(); - } - } -@@ -5025,7 +5000,7 @@ void X11Window::updateWindowPixmap() - void X11Window::associate() - { - auto handleMapped = [this]() { -- if (syncRequest().counter == XCB_NONE) { // cannot detect complete redraw, consider done now -+ if (!m_syncRequest.enabled) { // cannot detect complete redraw, consider done now - setReadyForPainting(); - } - }; -diff --git a/src/x11window.h b/src/x11window.h -index 10fa57eaf2..6b430b861a 100644 ---- a/src/x11window.h -+++ b/src/x11window.h -@@ -284,7 +284,8 @@ public: - xcb_sync_int64_t value; - xcb_sync_alarm_t alarm; - xcb_timestamp_t lastTimestamp; -- QTimer *timeout, *failsafeTimeout; -+ QTimer *timeout; -+ bool enabled; - bool pending; - bool interactiveResize; - }; -@@ -295,6 +296,7 @@ public: - bool wantsSyncCounter() const; - void ackSync(); - void ackSyncTimeout(); -+ void finishSync(); - - bool allowWindowActivation(xcb_timestamp_t time = -1U, bool focus_in = false); - -@@ -385,7 +387,6 @@ private: - void getSyncCounter(); - void sendSyncRequest(); - void leaveInteractiveMoveResize() override; -- void performInteractiveResize(); - void establishCommandWindowGrab(uint8_t button); - void establishCommandAllGrab(uint8_t button); - --- -2.47.0 - - -From 79e1853e9ecd20c1d9549399b46d434475b753bd Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Fri, 4 Oct 2024 23:20:03 +0300 -Subject: [PATCH 5/9] Disable Xwayland surface commits for all sync requests - ---- - src/x11window.cpp | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/src/x11window.cpp b/src/x11window.cpp -index 1d25ab82b1..5688ea6da8 100644 ---- a/src/x11window.cpp -+++ b/src/x11window.cpp -@@ -2604,7 +2604,7 @@ void X11Window::sendSyncRequest() - kwinApp()->updateXTime(); - } - -- // Send the message to client -+ setAllowCommits(false); - sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_sync_request, - m_syncRequest.value.lo, m_syncRequest.value.hi); - m_syncRequest.pending = true; -@@ -3049,6 +3049,7 @@ void X11Window::ackSync() - m_syncRequest.timeout->stop(); - - finishSync(); -+ setAllowCommits(true); - } - - void X11Window::ackSyncTimeout() -@@ -3057,6 +3058,7 @@ void X11Window::ackSyncTimeout() - m_syncRequest.enabled = false; - - finishSync(); -+ setAllowCommits(true); - } - - void X11Window::finishSync() -@@ -3068,7 +3070,6 @@ void X11Window::finishSync() - - moveResize(moveResizeGeometry()); - updateWindowPixmap(); -- setAllowCommits(true); - } - } - -@@ -4849,8 +4850,6 @@ void X11Window::doInteractiveResizeSync(const QRectF &rect) - moveResize(rect); - } else { - setMoveResizeGeometry(moveResizeFrameGeometry); -- setAllowCommits(false); -- - sendSyncRequest(); - configure(nativeFrameGeometry, nativeWrapperGeometry, nativeClientGeometry); - } --- -2.47.0 - - -From 038a798c8be170eb5b7132b823d77474d118ca42 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Fri, 4 Oct 2024 23:40:41 +0300 -Subject: [PATCH 6/9] Make Xwayland resizing less glitchy - -XSYNC requests and wl_surface commits are unsynchronized. This results -in the window bouncing when it's being resized. - -Let's consider a concrete example. Assume that there is a window with 0,0 -100x100 geometry and it is being resized by dragging the left edge. If -the left edge is dragged by 10px, the following will occur: - -- wl_surface commits will be blocked (it is needed to ensure the - consistent order of XSync acknowledgements and wl_surface commits) -- an XSync request will be sent -- a ConfigureNotify event will be sent -- a client processes the ConfigureNotify by repainting the window and - acknowledges the XSync request -- kwin notices that the XSync request has been acked and updates the - window position to 10,0 and unblocks surface commits - -The problem is that it can take a while for Xwayland to attach a new -buffer to the surface with a size of 90x100. If kwin composes a frame in -meanwhile, the effective geometry of the window will be 10,0 100x100, -i.e. the right window edge will stick by 10px. Some time later, Xwayland -would attach a buffer with the right size (90x100), and the right window -edge will be put back in the right place. - -In order to address the bouncing, this change reworks how the -synchronization is performed: - -- when a window is asked to resize, kwin will freeze wl_surface commits, - send a sync request, and configure the window -- after the client repaints the window, it acks the sync request -- when kwin sees that the sync request has been acked, it will unfreeze - the wl_surface commits. And here's the most important part: it will NOT - update the window position until Xwayland commits something -- when Xwayland commits the wl_surface, kwin will update the window geometry - -It's important to wait until Xwayland commits the wl_surface because, as -it was said previously, it can take a while until Xwayland commits the -wl_surface and kwin could compose a frame with the new position but old -surface size in meanwhile. - -BUG: 486464 ---- - src/x11window.cpp | 40 +++++++++++++++++++++++++++++----------- - src/x11window.h | 2 ++ - 2 files changed, 31 insertions(+), 11 deletions(-) - -diff --git a/src/x11window.cpp b/src/x11window.cpp -index 5688ea6da8..b22de557d8 100644 ---- a/src/x11window.cpp -+++ b/src/x11window.cpp -@@ -311,6 +311,7 @@ X11Window::X11Window() - m_syncRequest.lastTimestamp = xTime(); - m_syncRequest.enabled = false; - m_syncRequest.pending = false; -+ m_syncRequest.acked = false; - m_syncRequest.interactiveResize = false; - - // Set the initial mapping state -@@ -3046,9 +3047,13 @@ void X11Window::ackSync() - return; - } - -+ m_syncRequest.acked = true; - m_syncRequest.timeout->stop(); - -- finishSync(); -+ // With Xwayland, the sync request will be completed after the wl_surface is committed. -+ if (!waylandServer()) { -+ finishSync(); -+ } - setAllowCommits(true); - } - -@@ -3071,6 +3076,8 @@ void X11Window::finishSync() - moveResize(moveResizeGeometry()); - updateWindowPixmap(); - } -+ -+ m_syncRequest.acked = false; - } - - bool X11Window::belongToSameApplication(const X11Window *c1, const X11Window *c2, SameApplicationChecks checks) -@@ -3945,6 +3952,19 @@ void X11Window::handleXwaylandScaleChanged() - resize(moveResizeGeometry().size()); - } - -+void X11Window::handleCommitted() -+{ -+ if (surface()->isMapped()) { -+ if (m_syncRequest.acked) { -+ finishSync(); -+ } -+ -+ if (!m_syncRequest.enabled) { -+ setReadyForPainting(); -+ } -+ } -+} -+ - void X11Window::setAllowCommits(bool allow) - { - if (!waylandServer()) { -@@ -4829,7 +4849,7 @@ void X11Window::leaveInteractiveMoveResize() - - bool X11Window::isWaitingForInteractiveResizeSync() const - { -- return m_syncRequest.enabled && m_syncRequest.pending && m_syncRequest.interactiveResize; -+ return m_syncRequest.enabled && m_syncRequest.interactiveResize && (m_syncRequest.pending || m_syncRequest.acked); - } - - void X11Window::doInteractiveResizeSync(const QRectF &rect) -@@ -4998,19 +5018,17 @@ void X11Window::updateWindowPixmap() - - void X11Window::associate() - { -- auto handleMapped = [this]() { -- if (!m_syncRequest.enabled) { // cannot detect complete redraw, consider done now -- setReadyForPainting(); -+ if (surface()->isMapped()) { -+ if (m_syncRequest.acked) { -+ finishSync(); - } -- }; - -- if (surface()->isMapped()) { -- handleMapped(); -- } else { -- connect(surface(), &SurfaceInterface::mapped, this, handleMapped); -+ if (!m_syncRequest.enabled) { -+ setReadyForPainting(); -+ } - } - -- m_pendingSurfaceId = 0; -+ connect(surface(), &SurfaceInterface::committed, this, &X11Window::handleCommitted); - } - - QWindow *X11Window::findInternalWindow() const -diff --git a/src/x11window.h b/src/x11window.h -index 6b430b861a..73d4c23a4c 100644 ---- a/src/x11window.h -+++ b/src/x11window.h -@@ -287,6 +287,7 @@ public: - QTimer *timeout; - bool enabled; - bool pending; -+ bool acked; - bool interactiveResize; - }; - const SyncRequest &syncRequest() const -@@ -438,6 +439,7 @@ private: - void checkOutput(); - void associate(); - void handleXwaylandScaleChanged(); -+ void handleCommitted(); - - void setAllowCommits(bool allow); - --- -2.47.0 - - -From 10c5298221f5dc3cc90255846580b608f6f3c18c Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Thu, 3 Oct 2024 00:43:57 +0300 -Subject: [PATCH 7/9] scene: Use standard wl_surface item for Xwayland surfaces - -Besides unifying the code, it fixes some visual glitches caused by the -opaque region getting out of sync. - -Xwayland MR: https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1698 ---- - src/scene/surfaceitem_wayland.cpp | 36 ------------------------------- - src/scene/surfaceitem_wayland.h | 20 ----------------- - src/scene/windowitem.cpp | 2 +- - 3 files changed, 1 insertion(+), 57 deletions(-) - -diff --git a/src/scene/surfaceitem_wayland.cpp b/src/scene/surfaceitem_wayland.cpp -index 4a307565c0..04961952b9 100644 ---- a/src/scene/surfaceitem_wayland.cpp -+++ b/src/scene/surfaceitem_wayland.cpp -@@ -12,11 +12,6 @@ - #include "wayland/linuxdmabufv1clientbuffer.h" - #include "wayland/subcompositor.h" - #include "wayland/surface.h" --#include "window.h" -- --#if KWIN_BUILD_X11 --#include "x11window.h" --#endif - - namespace KWin - { -@@ -247,37 +242,6 @@ bool SurfacePixmapWayland::isValid() const - return m_bufferRef; - } - --#if KWIN_BUILD_X11 --SurfaceItemXwayland::SurfaceItemXwayland(X11Window *window, Item *parent) -- : SurfaceItemWayland(window->surface(), parent) -- , m_window(window) --{ -- connect(window, &X11Window::shapeChanged, this, &SurfaceItemXwayland::discardQuads); --} -- --QList SurfaceItemXwayland::shape() const --{ -- QList shape = m_window->shapeRegion(); -- for (QRectF &shapePart : shape) { -- shapePart = shapePart.intersected(rect()); -- } -- return shape; --} -- --QRegion SurfaceItemXwayland::opaque() const --{ -- QRegion shapeRegion; -- for (const QRectF &shapePart : shape()) { -- shapeRegion += shapePart.toRect(); -- } -- if (!m_window->hasAlpha()) { -- return shapeRegion; -- } else { -- return m_window->opaqueRegion() & shapeRegion; -- } -- return QRegion(); --} --#endif - } // namespace KWin - - #include "moc_surfaceitem_wayland.cpp" -diff --git a/src/scene/surfaceitem_wayland.h b/src/scene/surfaceitem_wayland.h -index f769284172..fbc7498446 100644 ---- a/src/scene/surfaceitem_wayland.h -+++ b/src/scene/surfaceitem_wayland.h -@@ -16,7 +16,6 @@ namespace KWin - class GraphicsBuffer; - class SubSurfaceInterface; - class SurfaceInterface; --class X11Window; - - /** - * The SurfaceItemWayland class represents a Wayland surface in the scene. -@@ -83,23 +82,4 @@ private: - SurfaceItemWayland *m_item; - }; - --#if KWIN_BUILD_X11 --/** -- * The SurfaceItemXwayland class represents an Xwayland surface in the scene. -- */ --class KWIN_EXPORT SurfaceItemXwayland : public SurfaceItemWayland --{ -- Q_OBJECT -- --public: -- explicit SurfaceItemXwayland(X11Window *window, Item *parent = nullptr); -- -- QRegion opaque() const override; -- QList shape() const override; -- --private: -- X11Window *m_window; --}; --#endif -- - } // namespace KWin -diff --git a/src/scene/windowitem.cpp b/src/scene/windowitem.cpp -index 4283051e7e..913d2708f5 100644 ---- a/src/scene/windowitem.cpp -+++ b/src/scene/windowitem.cpp -@@ -323,7 +323,7 @@ void WindowItemX11::initialize() - if (!window()->surface()) { - updateSurfaceItem(nullptr); - } else { -- updateSurfaceItem(std::make_unique(static_cast(window()), this)); -+ updateSurfaceItem(std::make_unique(window()->surface(), this)); - } - break; - case Application::OperationModeWaylandOnly: --- -2.47.0 - - -From 91ca5127fbf590a383fe311b76da8dce553e2a8a Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Mon, 14 Oct 2024 00:34:28 +0300 -Subject: [PATCH 8/9] Send the initial sync request before mapping the frame - window - -When the wl_surface commits are blocked by the initial sync request, it -is really important that Xwayland doesn't commit the surface until the -sync request is acked. However, with the current arrangement of the code, -Xwayland may render something before the sync request is acked. - -It can happen because the frame window is mapped before the initial sync -request is sent. There are many places where it can happen, e.g. in the -setupCompositing() function, or the setMinimized() function, etc. - -In order to ensure that Xwayland won't render the wl_surface while we -are waiting for the sync request to get acked, this change moves the initial -sync request all the way to the top of the manage() function so the -surface commits are blocked before the frame window is mapped. ---- - src/x11window.cpp | 20 ++++++++++++-------- - 1 file changed, 12 insertions(+), 8 deletions(-) - -diff --git a/src/x11window.cpp b/src/x11window.cpp -index b22de557d8..be35fe07fd 100644 ---- a/src/x11window.cpp -+++ b/src/x11window.cpp -@@ -655,6 +655,18 @@ bool X11Window::manage(xcb_window_t w, bool isMapped) - getSyncCounter(); - setCaption(readName()); - -+ if (Compositor::compositing()) { -+ // Sending ConfigureNotify is done when setting mapping state below, getting the -+ // first sync response means window is ready for compositing. -+ // -+ // The sync request will block wl_surface commits, and with Xwayland, it is really -+ // important that wl_surfaces commits are blocked before the frame window is mapped. -+ // Otherwise Xwayland can attach a buffer before the sync request is acked. -+ sendSyncRequest(); -+ } else { -+ ready_for_painting = true; // set to true in case compositing is turned on later -+ } -+ - setupWindowRules(); - connect(this, &X11Window::windowClassChanged, this, &X11Window::evaluateWindowRules); - -@@ -1093,14 +1105,6 @@ bool X11Window::manage(xcb_window_t w, bool isMapped) - workspace()->restoreSessionStackingOrder(this); - } - -- if (Compositor::compositing()) { -- // Sending ConfigureNotify is done when setting mapping state below, -- // Getting the first sync response means window is ready for compositing -- sendSyncRequest(); -- } else { -- ready_for_painting = true; // set to true in case compositing is turned on later. bug #160393 -- } -- - if (isShown()) { - bool allow; - if (session) { --- -2.47.0 - - -From cffaa20e83b7d9de69dcc835f6ab5d2609a49be5 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Thu, 17 Oct 2024 19:21:32 +0300 -Subject: [PATCH 9/9] Block interactive resizing if there is a pending XSync - request - -There cannot be two XSync requests in flight, the type of the sync -requests doesn't matter either, e.g. one for interactive resize or -one to determine whether the client has painted the initial frame. ---- - src/x11window.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/x11window.cpp b/src/x11window.cpp -index be35fe07fd..3e989f29bd 100644 ---- a/src/x11window.cpp -+++ b/src/x11window.cpp -@@ -4853,7 +4853,7 @@ void X11Window::leaveInteractiveMoveResize() - - bool X11Window::isWaitingForInteractiveResizeSync() const - { -- return m_syncRequest.enabled && m_syncRequest.interactiveResize && (m_syncRequest.pending || m_syncRequest.acked); -+ return m_syncRequest.enabled && (m_syncRequest.pending || m_syncRequest.acked); - } - - void X11Window::doInteractiveResizeSync(const QRectF &rect) --- -2.47.0 - diff --git a/roles/kde/patches/kwin-pr6844.patch b/roles/kde/patches/kwin-pr6844.patch deleted file mode 100644 index f6e5e63..0000000 --- a/roles/kde/patches/kwin-pr6844.patch +++ /dev/null @@ -1,41 +0,0 @@ -diff --git a/src/plugins/private/expolayout.cpp b/src/plugins/private/expolayout.cpp -index 52e8bd6616..d4f2a41acc 100644 ---- a/src/plugins/private/expolayout.cpp -+++ b/src/plugins/private/expolayout.cpp -@@ -7,6 +7,7 @@ - - #include "expolayout.h" - -+#include - #include - #include - #include -@@ -41,6 +42,12 @@ ExpoCell::~ExpoCell() - void ExpoCell::componentComplete() - { - QQuickItem::componentComplete(); -+ -+ QQmlProperty xProperty(this, "Kirigami.ScenePosition.x", qmlContext(this)); -+ xProperty.connectNotifySignal(this, SLOT(updateContentItemGeometry())); -+ QQmlProperty yProperty(this, "Kirigami.ScenePosition.y", qmlContext(this)); -+ yProperty.connectNotifySignal(this, SLOT(updateContentItemGeometry())); -+ - updateContentItemGeometry(); - } - -diff --git a/src/plugins/private/expolayout.h b/src/plugins/private/expolayout.h -index 0d4f9d5cde..d980c2aabb 100644 ---- a/src/plugins/private/expolayout.h -+++ b/src/plugins/private/expolayout.h -@@ -264,8 +264,10 @@ Q_SIGNALS: - void persistentKeyChanged(); - void bottomMarginChanged(); - --private: -+private Q_SLOTS: - void updateContentItemGeometry(); -+ -+private: - void updateLayout(); - - QString m_persistentKey; diff --git a/roles/kde/patches/kwin-pr6878.patch b/roles/kde/patches/kwin-pr6878.patch deleted file mode 100644 index 41fffc9..0000000 --- a/roles/kde/patches/kwin-pr6878.patch +++ /dev/null @@ -1,753 +0,0 @@ -diff --git a/src/plugins/zoom/CMakeLists.txt b/src/plugins/zoom/CMakeLists.txt -index c27bdbbb2d..b5fb343e17 100644 ---- a/src/plugins/zoom/CMakeLists.txt -+++ b/src/plugins/zoom/CMakeLists.txt -@@ -4,6 +4,7 @@ - set(zoom_SOURCES - main.cpp - zoom.cpp -+ zoom.qrc - ) - - if (HAVE_ACCESSIBILITY) -diff --git a/src/plugins/zoom/shaders/pixelgrid.frag b/src/plugins/zoom/shaders/pixelgrid.frag -new file mode 100644 -index 0000000000..1e9ee9431f ---- /dev/null -+++ b/src/plugins/zoom/shaders/pixelgrid.frag -@@ -0,0 +1,25 @@ -+#include "colormanagement.glsl" -+ -+uniform sampler2D sampler; -+uniform int textureWidth; -+uniform int textureHeight; -+ -+varying vec2 texcoord0; -+ -+void main() -+{ -+ vec2 texSize = vec2(textureWidth, textureHeight); -+ vec2 samplePosition = texcoord0 * texSize; -+ vec2 pixelCenter = floor(samplePosition) + vec2(0.5); -+ vec2 pixelCenterDistance = abs(samplePosition - pixelCenter); -+ -+ vec4 tex; -+ if (pixelCenterDistance.x > 0.4 || pixelCenterDistance.y > 0.4) { -+ tex = vec4(0, 0, 0, 1); -+ } else { -+ tex = texture2D(sampler, pixelCenter / texSize); -+ } -+ -+ tex = sourceEncodingToNitsInDestinationColorspace(tex); -+ gl_FragColor = nitsToDestinationEncoding(tex); -+} -diff --git a/src/plugins/zoom/shaders/pixelgrid_core.frag b/src/plugins/zoom/shaders/pixelgrid_core.frag -new file mode 100644 -index 0000000000..a1cc7f27f2 ---- /dev/null -+++ b/src/plugins/zoom/shaders/pixelgrid_core.frag -@@ -0,0 +1,24 @@ -+#version 140 -+ -+#include "colormanagement.glsl" -+ -+uniform sampler2D sampler; -+uniform int textureWidth; -+uniform int textureHeight; -+ -+in vec2 texcoord0; -+ -+out vec4 fragColor; -+ -+void main() -+{ -+ vec2 texSize = vec2(textureWidth, textureHeight); -+ vec2 samplePosition = texcoord0 * texSize; -+ vec2 pixelCenter = floor(samplePosition) + vec2(0.5); -+ vec2 pixelCenterDistance = abs(samplePosition - pixelCenter); -+ -+ float t = smoothstep(0.4, 0.5, max(pixelCenterDistance.x, pixelCenterDistance.y)); -+ vec4 tex = mix(texture(sampler, pixelCenter / texSize), vec4(0, 0, 0, 1), t); -+ tex = sourceEncodingToNitsInDestinationColorspace(tex); -+ fragColor = nitsToDestinationEncoding(tex); -+} -diff --git a/src/plugins/zoom/ui_zoom_config.h b/src/plugins/zoom/ui_zoom_config.h -new file mode 100644 -index 0000000000..7e5944a902 ---- /dev/null -+++ b/src/plugins/zoom/ui_zoom_config.h -@@ -0,0 +1,195 @@ -+/******************************************************************************** -+** Form generated from reading UI file 'zoom_config.ui' -+** -+** Created by: Qt User Interface Compiler version 6.8.1 -+** -+** WARNING! All changes made in this file will be lost when recompiling UI file! -+********************************************************************************/ -+ -+#ifndef UI_ZOOM_CONFIG_H -+#define UI_ZOOM_CONFIG_H -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "kshortcutseditor.h" -+ -+namespace KWin { -+ -+class Ui_ZoomEffectConfigForm -+{ -+public: -+ QVBoxLayout *verticalLayout_2; -+ QGroupBox *groupSize; -+ QHBoxLayout *horizontalLayout; -+ QGridLayout *gridLayout; -+ QLabel *label; -+ QDoubleSpinBox *kcfg_ZoomFactor; -+ QCheckBox *kcfg_EnableFocusTracking; -+ QCheckBox *kcfg_EnableTextCaretTracking; -+ QLabel *label_2; -+ QComboBox *kcfg_MousePointer; -+ QComboBox *kcfg_MouseTracking; -+ QLabel *label_3; -+ KShortcutsEditor *editor; -+ -+ void setupUi(QWidget *KWin__ZoomEffectConfigForm) -+ { -+ if (KWin__ZoomEffectConfigForm->objectName().isEmpty()) -+ KWin__ZoomEffectConfigForm->setObjectName("KWin__ZoomEffectConfigForm"); -+ KWin__ZoomEffectConfigForm->resize(304, 288); -+ verticalLayout_2 = new QVBoxLayout(KWin__ZoomEffectConfigForm); -+ verticalLayout_2->setObjectName("verticalLayout_2"); -+ groupSize = new QGroupBox(KWin__ZoomEffectConfigForm); -+ groupSize->setObjectName("groupSize"); -+ horizontalLayout = new QHBoxLayout(groupSize); -+ horizontalLayout->setObjectName("horizontalLayout"); -+ gridLayout = new QGridLayout(); -+ gridLayout->setObjectName("gridLayout"); -+ label = new QLabel(groupSize); -+ label->setObjectName("label"); -+ label->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); -+ -+ gridLayout->addWidget(label, 0, 0, 1, 1); -+ -+ kcfg_ZoomFactor = new QDoubleSpinBox(groupSize); -+ kcfg_ZoomFactor->setObjectName("kcfg_ZoomFactor"); -+ kcfg_ZoomFactor->setDecimals(2); -+ kcfg_ZoomFactor->setMaximum(9999.000000000000000); -+ kcfg_ZoomFactor->setSingleStep(0.050000000000000); -+ kcfg_ZoomFactor->setValue(1.250000000000000); -+ -+ gridLayout->addWidget(kcfg_ZoomFactor, 0, 1, 1, 1); -+ -+ kcfg_EnableFocusTracking = new QCheckBox(groupSize); -+ kcfg_EnableFocusTracking->setObjectName("kcfg_EnableFocusTracking"); -+ -+ gridLayout->addWidget(kcfg_EnableFocusTracking, 4, 0, 1, 2); -+ -+ kcfg_EnableTextCaretTracking = new QCheckBox(groupSize); -+ kcfg_EnableTextCaretTracking->setObjectName("kcfg_EnableTextCaretTracking"); -+ -+ gridLayout->addWidget(kcfg_EnableTextCaretTracking, 5, 0, 1, 2); -+ -+ label_2 = new QLabel(groupSize); -+ label_2->setObjectName("label_2"); -+ label_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); -+ -+ gridLayout->addWidget(label_2, 2, 0, 1, 1); -+ -+ kcfg_MousePointer = new QComboBox(groupSize); -+ kcfg_MousePointer->addItem(QString()); -+ kcfg_MousePointer->addItem(QString()); -+ kcfg_MousePointer->addItem(QString()); -+ kcfg_MousePointer->setObjectName("kcfg_MousePointer"); -+ -+ gridLayout->addWidget(kcfg_MousePointer, 2, 1, 1, 1); -+ -+ kcfg_MouseTracking = new QComboBox(groupSize); -+ kcfg_MouseTracking->addItem(QString()); -+ kcfg_MouseTracking->addItem(QString()); -+ kcfg_MouseTracking->addItem(QString()); -+ kcfg_MouseTracking->addItem(QString()); -+ kcfg_MouseTracking->setObjectName("kcfg_MouseTracking"); -+ -+ gridLayout->addWidget(kcfg_MouseTracking, 3, 1, 1, 1); -+ -+ label_3 = new QLabel(groupSize); -+ label_3->setObjectName("label_3"); -+ label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); -+ -+ gridLayout->addWidget(label_3, 3, 0, 1, 1); -+ -+ -+ horizontalLayout->addLayout(gridLayout); -+ -+ -+ verticalLayout_2->addWidget(groupSize); -+ -+ editor = new KShortcutsEditor(KWin__ZoomEffectConfigForm); -+ editor->setObjectName("editor"); -+ QSizePolicy sizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding); -+ sizePolicy.setHorizontalStretch(0); -+ sizePolicy.setVerticalStretch(0); -+ sizePolicy.setHeightForWidth(editor->sizePolicy().hasHeightForWidth()); -+ editor->setSizePolicy(sizePolicy); -+ editor->setActionTypes(KShortcutsEditor::GlobalAction); -+ -+ verticalLayout_2->addWidget(editor); -+ -+#if QT_CONFIG(shortcut) -+ label->setBuddy(kcfg_ZoomFactor); -+ label_2->setBuddy(kcfg_MousePointer); -+ label_3->setBuddy(kcfg_MouseTracking); -+#endif // QT_CONFIG(shortcut) -+ QWidget::setTabOrder(kcfg_ZoomFactor, kcfg_MousePointer); -+ QWidget::setTabOrder(kcfg_MousePointer, kcfg_MouseTracking); -+ QWidget::setTabOrder(kcfg_MouseTracking, kcfg_EnableFocusTracking); -+ QWidget::setTabOrder(kcfg_EnableFocusTracking, kcfg_EnableTextCaretTracking); -+ -+ retranslateUi(KWin__ZoomEffectConfigForm); -+ -+ QMetaObject::connectSlotsByName(KWin__ZoomEffectConfigForm); -+ } // setupUi -+ -+ void retranslateUi(QWidget *KWin__ZoomEffectConfigForm) -+ { -+ groupSize->setTitle(QString()); -+#if QT_CONFIG(whatsthis) -+ label->setWhatsThis(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "On zoom-in and zoom-out change the zoom by the defined zoom-factor.", nullptr)); -+#endif // QT_CONFIG(whatsthis) -+ label->setText(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Zoom Factor:", nullptr)); -+#if QT_CONFIG(whatsthis) -+ kcfg_ZoomFactor->setWhatsThis(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "On zoom-in and zoom-out change the zoom by the defined zoom-factor.", nullptr)); -+#endif // QT_CONFIG(whatsthis) -+ kcfg_ZoomFactor->setSuffix(QString()); -+#if QT_CONFIG(tooltip) -+ kcfg_EnableFocusTracking->setToolTip(QString()); -+#endif // QT_CONFIG(tooltip) -+#if QT_CONFIG(whatsthis) -+ kcfg_EnableFocusTracking->setWhatsThis(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Enable tracking of the focused location. This needs QAccessible to be enabled per application (\"export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1\").", nullptr)); -+#endif // QT_CONFIG(whatsthis) -+ kcfg_EnableFocusTracking->setText(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Enable Focus Tracking", nullptr)); -+#if QT_CONFIG(whatsthis) -+ kcfg_EnableTextCaretTracking->setWhatsThis(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Enable tracking of the text cursor. This needs QAccessible to be enabled per application (\"export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1\").", nullptr)); -+#endif // QT_CONFIG(whatsthis) -+ kcfg_EnableTextCaretTracking->setText(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Enable Text Cursor Tracking", nullptr)); -+ label_2->setText(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Mouse Pointer:", nullptr)); -+ kcfg_MousePointer->setItemText(0, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Scale", nullptr)); -+ kcfg_MousePointer->setItemText(1, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Keep", nullptr)); -+ kcfg_MousePointer->setItemText(2, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Hide", nullptr)); -+ -+#if QT_CONFIG(whatsthis) -+ kcfg_MousePointer->setWhatsThis(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Visibility of the mouse-pointer.", nullptr)); -+#endif // QT_CONFIG(whatsthis) -+ kcfg_MouseTracking->setItemText(0, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Proportional", nullptr)); -+ kcfg_MouseTracking->setItemText(1, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Centered", nullptr)); -+ kcfg_MouseTracking->setItemText(2, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Push", nullptr)); -+ kcfg_MouseTracking->setItemText(3, QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Disabled", nullptr)); -+ -+#if QT_CONFIG(whatsthis) -+ kcfg_MouseTracking->setWhatsThis(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Track moving of the mouse.", nullptr)); -+#endif // QT_CONFIG(whatsthis) -+ label_3->setText(QCoreApplication::translate("KWin::ZoomEffectConfigForm", "Mouse Tracking:", nullptr)); -+ (void)KWin__ZoomEffectConfigForm; -+ } // retranslateUi -+ -+}; -+ -+} // namespace KWin -+ -+namespace KWin { -+namespace Ui { -+ class ZoomEffectConfigForm: public Ui_ZoomEffectConfigForm {}; -+} // namespace Ui -+} // namespace KWin -+ -+#endif // UI_ZOOM_CONFIG_H -diff --git a/src/plugins/zoom/zoom.cpp b/src/plugins/zoom/zoom.cpp -index a6eb528767..950583c15b 100644 ---- a/src/plugins/zoom/zoom.cpp -+++ b/src/plugins/zoom/zoom.cpp -@@ -31,6 +31,12 @@ - - using namespace std::chrono_literals; - -+static void ensureResources() -+{ -+ // Must initialize resources manually because the effect is a static lib. -+ Q_INIT_RESOURCE(zoom); -+} -+ - namespace KWin - { - -@@ -48,6 +54,8 @@ ZoomEffect::ZoomEffect() - , moveFactor(20.0) - , lastPresentTime(std::chrono::milliseconds::zero()) - { -+ ensureResources(); -+ - ZoomConfig::instance(effects->config()); - QAction *a = nullptr; - a = KStandardAction::zoomIn(this, SLOT(zoomIn()), this); -@@ -214,6 +222,7 @@ void ZoomEffect::reconfigure(ReconfigureFlags) - ZoomConfig::self()->read(); - // On zoom-in and zoom-out change the zoom by the defined zoom-factor. - zoomFactor = std::max(0.1, ZoomConfig::zoomFactor()); -+ m_pixelGridZoom = ZoomConfig::pixelGridZoom(); - // Visibility of the mouse-pointer. - mousePointer = MousePointerType(ZoomConfig::mousePointer()); - // Track moving of the mouse. -@@ -271,12 +280,10 @@ void ZoomEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseco - - ZoomEffect::OffscreenData *ZoomEffect::ensureOffscreenData(const RenderTarget &renderTarget, const RenderViewport &viewport, Output *screen) - { -- const QRect rect = viewport.renderRect().toRect(); -- const qreal devicePixelRatio = viewport.scale(); -- const QSize nativeSize = (viewport.renderRect().size() * devicePixelRatio).toSize(); -+ const QSize nativeSize = renderTarget.size(); - - OffscreenData &data = m_offscreenData[effects->waylandDisplay() ? screen : nullptr]; -- data.viewport = rect; -+ data.viewport = viewport.renderRect(); - data.color = renderTarget.colorDescription(); - - const GLenum textureFormat = renderTarget.colorDescription() == ColorDescription::sRGB ? GL_RGBA8 : GL_RGBA16F; -@@ -290,9 +297,22 @@ ZoomEffect::OffscreenData *ZoomEffect::ensureOffscreenData(const RenderTarget &r - data.framebuffer = std::make_unique(data.texture.get()); - } - -+ data.texture->setContentTransform(renderTarget.transform()); - return &data; - } - -+GLShader *ZoomEffect::shaderForZoom(double zoom) -+{ -+ if (zoom < m_pixelGridZoom) { -+ return ShaderManager::instance()->shader(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace); -+ } else { -+ if (!m_pixelGridShader) { -+ m_pixelGridShader = ShaderManager::instance()->generateShaderFromFile(ShaderTrait::MapTexture, QString(), QStringLiteral(":/effects/zoom/shaders/pixelgrid.frag")); -+ } -+ return m_pixelGridShader.get(); -+ } -+} -+ - void ZoomEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen) - { - OffscreenData *offscreenData = ensureOffscreenData(renderTarget, viewport, screen); -@@ -391,7 +411,8 @@ void ZoomEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewp - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - -- auto shader = ShaderManager::instance()->pushShader(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace); -+ GLShader *shader = shaderForZoom(zoom); -+ ShaderManager::instance()->pushShader(shader); - for (auto &[screen, offscreen] : m_offscreenData) { - QMatrix4x4 matrix; - matrix.translate(xTranslation * scale, yTranslation * scale); -@@ -399,6 +420,8 @@ void ZoomEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewp - matrix.translate(offscreen.viewport.x() * scale, offscreen.viewport.y() * scale); - - shader->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, viewport.projectionMatrix() * matrix); -+ shader->setUniform(GLShader::IntUniform::TextureWidth, offscreen.texture->width()); -+ shader->setUniform(GLShader::IntUniform::TextureHeight, offscreen.texture->height()); - shader->setColorspaceUniforms(offscreen.color, renderTarget.colorDescription(), RenderingIntent::Perceptual); - - offscreen.texture->render(offscreen.viewport.size() * scale); -diff --git a/src/plugins/zoom/zoom.h b/src/plugins/zoom/zoom.h -index 2a44395d74..1c9abb4b4e 100644 ---- a/src/plugins/zoom/zoom.h -+++ b/src/plugins/zoom/zoom.h -@@ -26,6 +26,7 @@ class ZoomAccessibilityIntegration; - class GLFramebuffer; - class GLTexture; - class GLVertexBuffer; -+class GLShader; - - class ZoomEffect - : public Effect -@@ -94,7 +95,7 @@ private: - { - std::unique_ptr texture; - std::unique_ptr framebuffer; -- QRect viewport; -+ QRectF viewport; - ColorDescription color = ColorDescription::sRGB; - }; - -@@ -102,6 +103,8 @@ private: - OffscreenData *ensureOffscreenData(const RenderTarget &renderTarget, const RenderViewport &viewport, Output *screen); - void markCursorTextureDirty(); - -+ GLShader *shaderForZoom(double zoom); -+ - #if HAVE_ACCESSIBILITY - ZoomAccessibilityIntegration *m_accessibilityIntegration = nullptr; - #endif -@@ -136,6 +139,8 @@ private: - double moveFactor; - std::chrono::milliseconds lastPresentTime; - std::map m_offscreenData; -+ std::unique_ptr m_pixelGridShader; -+ double m_pixelGridZoom; - }; - - } // namespace -diff --git a/src/plugins/zoom/zoom.kcfg b/src/plugins/zoom/zoom.kcfg -index 63887e32aa..ed43e225c8 100644 ---- a/src/plugins/zoom/zoom.kcfg -+++ b/src/plugins/zoom/zoom.kcfg -@@ -29,5 +29,8 @@ - - 1.0 - -+ -+ 15.0 -+ - - -diff --git a/src/plugins/zoom/zoom.qrc b/src/plugins/zoom/zoom.qrc -new file mode 100644 -index 0000000000..56e7369003 ---- /dev/null -+++ b/src/plugins/zoom/zoom.qrc -@@ -0,0 +1,6 @@ -+ -+ -+ shaders/pixelgrid.frag -+ shaders/pixelgrid_core.frag -+ -+ -diff --git a/src/plugins/zoom/zoom_config.ui b/src/plugins/zoom/zoom_config.ui -index 454f9f9161..4b8a5c000e 100644 ---- a/src/plugins/zoom/zoom_config.ui -+++ b/src/plugins/zoom/zoom_config.ui -@@ -6,159 +6,157 @@ - - 0 - 0 -- 304 -- 288 -+ 595 -+ 551 - - - - -- -- -- -+ -+ -+ Qt::AlignHCenter|Qt::AlignTop - -- -- -- -- -- -- -- On zoom-in and zoom-out change the zoom by the defined zoom-factor. -- -- -- Zoom Factor: -- -- -- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter -- -- -- kcfg_ZoomFactor -- -- -- -- -- -- -- On zoom-in and zoom-out change the zoom by the defined zoom-factor. -- -- -- -- -- -- 2 -- -- -- 9999.000000000000000 -- -- -- 0.050000000000000 -- -- -- 1.250000000000000 -- -- -- -- -- -- -- -- -- -- Enable tracking of the focused location. This needs QAccessible to be enabled per application ("export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1"). -- -- -- Enable Focus Tracking -- -- -- -- -- -- -- Enable tracking of the text cursor. This needs QAccessible to be enabled per application ("export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1"). -- -- -- Enable Text Cursor Tracking -- -- -- -- -- -- -- Mouse Pointer: -- -- -- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter -- -- -- kcfg_MousePointer -- -- -- -- -- -- -- Visibility of the mouse-pointer. -- -- -- -- Scale -- -- -- -- -- Keep -- -- -- -- -- Hide -- -- -- -- -- -- -- -- Track moving of the mouse. -- -- -- -- Proportional -- -- -- -- -- Centered -- -- -- -- -- Push -- -- -- -- -- Disabled -- -- -- -- -- -- -- -- Mouse Tracking: -- -- -- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter -- -- -- kcfg_MouseTracking -- -- -- -- -- -- -- -+ -+ -+ -+ On zoom-in and zoom-out change the zoom by the defined zoom-factor. -+ -+ -+ Zoom factor: -+ -+ -+ kcfg_ZoomFactor -+ -+ -+ -+ -+ -+ -+ On zoom-in and zoom-out change the zoom by the defined zoom-factor. -+ -+ -+ -+ -+ -+ 2 -+ -+ -+ 9999.000000000000000 -+ -+ -+ 0.050000000000000 -+ -+ -+ 1.250000000000000 -+ -+ -+ -+ -+ -+ -+ Show pixel grid at zoom level: -+ -+ -+ kcfg_PixelGridZoom -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Mouse pointer: -+ -+ -+ kcfg_MousePointer -+ -+ -+ -+ -+ -+ -+ Visibility of the mouse-pointer. -+ -+ -+ -+ Scale -+ -+ -+ -+ -+ Keep -+ -+ -+ -+ -+ Hide -+ -+ -+ -+ -+ -+ -+ -+ Mouse tracking: -+ -+ -+ kcfg_MouseTracking -+ -+ -+ -+ -+ -+ -+ Track moving of the mouse. -+ -+ -+ -+ Proportional -+ -+ -+ -+ -+ Centered -+ -+ -+ -+ -+ Push -+ -+ -+ -+ -+ Disabled -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Enable tracking of the focused location. This needs QAccessible to be enabled per application ("export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1"). -+ -+ -+ Enable focus tracking -+ -+ -+ -+ -+ -+ -+ Enable tracking of the text cursor. This needs QAccessible to be enabled per application ("export QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1"). -+ -+ -+ Enable text cursor tracking -+ -+ -+ -+ - - - -@@ -183,13 +181,6 @@ - 1 - - -- -- kcfg_ZoomFactor -- kcfg_MousePointer -- kcfg_MouseTracking -- kcfg_EnableFocusTracking -- kcfg_EnableTextCaretTracking -- - - - diff --git a/roles/kde/patches/kwin-pr6985.patch b/roles/kde/patches/kwin-pr6985.patch deleted file mode 100644 index 95d196d..0000000 --- a/roles/kde/patches/kwin-pr6985.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 45a5d8844b36404334301f5da6e75f1a345e0c80 Mon Sep 17 00:00:00 2001 -From: Xaver Hugl -Date: Fri, 10 Jan 2025 13:45:30 +0000 -Subject: [PATCH] plugins/screencast: call ItemRenderer::begin/endFrame - -The OpenGL renderer references the explicit sync release points for client buffers -during rendering, and releases them in endFrame. If endFrame never gets called though -(for example because we're doing direct scanout) then the release points never get -signaled, and the client very quickly runs out of buffers to use and freezes. - -BUG: 495287 - - -(cherry picked from commit b1031ea63eaa8c9bf5c70157d1b6bf8eb0f5a74a) - -Co-authored-by: Xaver Hugl ---- - src/plugins/screencast/windowscreencastsource.cpp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/plugins/screencast/windowscreencastsource.cpp b/src/plugins/screencast/windowscreencastsource.cpp -index 24ef92aad7b..b396eed46f9 100644 ---- a/src/plugins/screencast/windowscreencastsource.cpp -+++ b/src/plugins/screencast/windowscreencastsource.cpp -@@ -75,11 +75,11 @@ void WindowScreenCastSource::render(GLFramebuffer *target) - RenderTarget renderTarget(target); - RenderViewport viewport(m_window->clientGeometry(), 1, renderTarget); - -- GLFramebuffer::pushFramebuffer(target); -+ Compositor::self()->scene()->renderer()->beginFrame(renderTarget, viewport); - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - Compositor::self()->scene()->renderer()->renderItem(renderTarget, viewport, m_window->windowItem(), Scene::PAINT_WINDOW_TRANSFORMED, infiniteRegion(), WindowPaintData{}); -- GLFramebuffer::popFramebuffer(); -+ Compositor::self()->scene()->renderer()->endFrame(); - } - - std::chrono::nanoseconds WindowScreenCastSource::clock() const --- -GitLab - diff --git a/roles/kde/patches/libplasma-pr1214.patch b/roles/kde/patches/libplasma-pr1214.patch deleted file mode 100644 index 709b13e..0000000 --- a/roles/kde/patches/libplasma-pr1214.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 626a52ae30dcda0ca407d1de02e30fcf5c109862 Mon Sep 17 00:00:00 2001 -From: Tem PQD -Date: Sun, 27 Oct 2024 03:54:44 +0000 -Subject: [PATCH] applets/taskmanager: Make group indicator icon follow accent - color - -The green plus icon is pretty eye-catching, and normally green plus buttons indicate something is going to be added or created. Change this to follow the user-selected color scheme, also matching the focus/active indicator color. ---- - src/desktoptheme/breeze/widgets/tasks.svg | Bin 78569 -> 78717 bytes - 1 file changed, 0 insertions(+), 0 deletions(-) - -diff --git a/src/desktoptheme/breeze/widgets/tasks.svg b/src/desktoptheme/breeze/widgets/tasks.svg -index b76d1a345fe59ca48cc3c52de53495202734d00f..c60707355f082749661ffc059744a0f2b0f94eee 100644 ---- a/src/desktoptheme/breeze/widgets/tasks.svg -+++ b/src/desktoptheme/breeze/widgets/tasks.svg -@@ -952,25 +952,25 @@ - - - -- -+ - - - - - -- -+ - - - - - -- -+ - - - - - -- -+ - - - --- -GitLab - diff --git a/roles/kde/patches/plasma_desktop-pr2661.patch b/roles/kde/patches/plasma_desktop-pr2661.patch deleted file mode 100644 index b2ce58d..0000000 --- a/roles/kde/patches/plasma_desktop-pr2661.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 5301b211fc87f1b2253e87da61ff82618be9e899 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Niccol=C3=B2=20Venerandi?= -Date: Thu, 5 Dec 2024 16:12:58 +0100 -Subject: [PATCH] Only return valid task item size if task manager has been - resized to fit panel - -Previously the task manager would briefly have null width and height, before -being resized to fit the panel. However, the "preferredMaxWidth" for tasks -would still be positive, as it adds margins to it, and tasks would then -assume a positive width. When the proper values are set, this casuses -an extra resize animation. - -CCBUG:447476 ---- - .../taskmanager/package/contents/ui/code/layoutmetrics.js | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/applets/taskmanager/package/contents/ui/code/layoutmetrics.js b/applets/taskmanager/package/contents/ui/code/layoutmetrics.js -index c7f11c99a6..895cc725d2 100644 ---- a/applets/taskmanager/package/contents/ui/code/layoutmetrics.js -+++ b/applets/taskmanager/package/contents/ui/code/layoutmetrics.js -@@ -63,8 +63,14 @@ function preferredMinWidth() { - function preferredMaxWidth() { - if (tasks.iconsOnly) { - if (tasks.vertical) { -+ if (tasks.width === 0) { -+ return 0 -+ } - return tasks.width + verticalMargins(); - } else { -+ if (tasks.height === 0) { -+ return 0 -+ } - return tasks.height + horizontalMargins(); - } - } --- -GitLab - diff --git a/roles/kde/patches/plasma_workspace-pr4883.patch b/roles/kde/patches/plasma_workspace-pr4883.patch deleted file mode 100644 index 7b575d0..0000000 --- a/roles/kde/patches/plasma_workspace-pr4883.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 11e7f5306fa013ec5c2b894a28457dabf5c42bad Mon Sep 17 00:00:00 2001 -From: Nate Graham -Date: Wed, 30 Oct 2024 21:55:49 -0600 -Subject: [PATCH] Merge "Settings" menu category into "System" - -This category is a bit of an odd duck. On a default install, it contains -only one item: System Settings. Random other apps you install will also -appear there, but all of these could just as logically live in the -"System" category. Let's put them there, so as to consolidate two -nebulous overlapping categories into one clear and obvious one. ---- - menu/desktop/plasma-applications.menu | 8 +------- - 1 file changed, 1 insertion(+), 7 deletions(-) - -diff --git a/menu/desktop/plasma-applications.menu b/menu/desktop/plasma-applications.menu -index e153604252e..85f842d6a04 100644 ---- a/menu/desktop/plasma-applications.menu -+++ b/menu/desktop/plasma-applications.menu -@@ -334,17 +334,11 @@ - - - -- -- Settingsmenu -- kf5-settingsmenu.directory -- -- Settings -- -- -
    - System - kf5-system.directory - -+ Settings - - System - X-KDE-More --- -GitLab - diff --git a/roles/kde/patches/plasma_workspace-pr4965.patch b/roles/kde/patches/plasma_workspace-pr4965.patch deleted file mode 100644 index f677504..0000000 --- a/roles/kde/patches/plasma_workspace-pr4965.patch +++ /dev/null @@ -1,915 +0,0 @@ -diff --git a/appiumtests/applets/CMakeLists.txt b/appiumtests/applets/CMakeLists.txt -index 19229541aa..6715dd1f8f 100644 ---- a/appiumtests/applets/CMakeLists.txt -+++ b/appiumtests/applets/CMakeLists.txt -@@ -59,7 +59,7 @@ add_test( - NAME notificationstest - COMMAND selenium-webdriver-at-spi-run ${CMAKE_CURRENT_SOURCE_DIR}/notificationstest.py --failfast - ) --set_tests_properties(notificationstest PROPERTIES TIMEOUT 120) -+set_tests_properties(notificationstest PROPERTIES TIMEOUT 120 ENVIRONMENT "KACTIVITYMANAGERD_PATH=${KDE_INSTALL_FULL_LIBEXECDIR}/kactivitymanagerd;USE_CUSTOM_BUS=1") - - add_test( - NAME digitalclocktest -diff --git a/appiumtests/applets/kicker/favoritetest.py b/appiumtests/applets/kicker/favoritetest.py -new file mode 100755 -index 0000000000..50613c3db1 ---- /dev/null -+++ b/appiumtests/applets/kicker/favoritetest.py -@@ -0,0 +1,162 @@ -+#!/usr/bin/env python3 -+ -+# SPDX-License-Identifier: BSD-3-Clause -+# SPDX-FileCopyrightText: 2022-2023 Harald Sitter -+ -+import logging -+import os -+import shutil -+import subprocess -+import sys -+import tempfile -+import time -+import unittest -+from typing import Final -+ -+from gi.repository import Gio, GLib -+ -+sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir, "utils")) -+from GLibMainLoopThread import GLibMainLoopThread -+ -+KDE_VERSION: Final = 6 -+KACTIVITYMANAGERD_SERVICE_NAME: Final = "org.kde.ActivityManager" -+KACTIVITYMANAGERD_PATH: Final = os.getenv("KACTIVITYMANAGERD_PATH", "/usr/libexec/kactivitymanagerd") -+QMLTEST_EXEC: Final = os.getenv("QMLTEST_EXEC", "/usr/bin/qmltestrunner6") -+ -+ -+def name_has_owner(session_bus: Gio.DBusConnection, name: str) -> bool: -+ """ -+ Whether the given name is available on session bus -+ """ -+ message: Gio.DBusMessage = Gio.DBusMessage.new_method_call("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "NameHasOwner") -+ message.set_body(GLib.Variant("(s)", [name])) -+ reply, _ = session_bus.send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE, 1000) -+ return reply and reply.get_signature() == 'b' and reply.get_body().get_child_value(0).get_boolean() -+ -+ -+def build_ksycoca() -> None: -+ subprocess.check_call([f"kbuildsycoca{KDE_VERSION}"], stdout=sys.stderr, stderr=sys.stderr, env=os.environ) -+ -+ -+def start_kactivitymanagerd() -> subprocess.Popen: -+ session_bus: Gio.DBusConnection = Gio.bus_get_sync(Gio.BusType.SESSION) -+ assert not name_has_owner(session_bus, KACTIVITYMANAGERD_SERVICE_NAME) -+ -+ os.makedirs(os.path.join(GLib.get_user_config_dir(), "menus")) -+ shutil.copy(os.path.join(os.path.dirname(os.path.abspath(__file__)), "applications.menu"), os.path.join(GLib.get_user_config_dir(), "menus")) -+ -+ kactivitymanagerd = subprocess.Popen([KACTIVITYMANAGERD_PATH], stdout=sys.stderr, stderr=sys.stderr, env=os.environ) -+ kactivitymanagerd_started: bool = False -+ for _ in range(10): -+ if name_has_owner(session_bus, KACTIVITYMANAGERD_SERVICE_NAME): -+ kactivitymanagerd_started = True -+ break -+ logging.info("waiting for kactivitymanagerd to appear on the DBus session") -+ time.sleep(1) -+ assert kactivitymanagerd_started -+ -+ build_ksycoca() -+ -+ return kactivitymanagerd -+ -+ -+class TestDBusInterface: -+ """ -+ D-Bus interface for org.kde.kickertest -+ """ -+ -+ BUS_NAME: Final = "org.kde.kickertest" -+ OBJECT_PATH: Final = "/test" -+ INTERFACE_NAME: Final = "org.kde.kickertest" -+ -+ connection: Gio.DBusConnection -+ -+ def __init__(self) -> None: -+ self.reg_id: int = 0 -+ self.owner_id: int = Gio.bus_own_name(Gio.BusType.SESSION, self.BUS_NAME, Gio.BusNameOwnerFlags.NONE, self.on_bus_acquired, None, None) -+ assert self.owner_id > 0 -+ -+ def on_bus_acquired(self, connection: Gio.DBusConnection, name: str, *args) -> None: -+ """ -+ The interface is ready, now register objects. -+ """ -+ self.connection = connection -+ introspection_data = Gio.DBusNodeInfo.new_for_xml(""" -+ -+ -+ -+ -+ -+ -+ -+""") -+ self.reg_id = connection.register_object(self.OBJECT_PATH, introspection_data.interfaces[0], self.handle_method_call, None, None) -+ assert self.reg_id > 0 -+ logging.info("interface registered") -+ -+ def handle_method_call(self, connection: Gio.DBusConnection, sender: str, object_path: str, interface_name: str, method_name: str, parameters: GLib.Variant, invocation: Gio.DBusMethodInvocation) -> None: -+ logging.info("method call %s", method_name) -+ -+ if method_name == "DeleteAndRebuildDatabase1": -+ os.remove(KickerTest.desktop_entry_1) -+ build_ksycoca() -+ invocation.return_value(None) -+ elif method_name == "DeleteAndRebuildDatabase2": -+ os.remove(KickerTest.desktop_entry_2) -+ build_ksycoca() -+ invocation.return_value(None) -+ -+ -+class KickerTest(unittest.TestCase): -+ kactivitymanagerd: subprocess.Popen -+ loop_thread: GLibMainLoopThread -+ dbus_interface: TestDBusInterface -+ -+ temp_dir: tempfile.TemporaryDirectory -+ desktop_entry_1: str -+ desktop_entry_2: str -+ -+ @classmethod -+ def setUpClass(cls) -> None: -+ # Prepare desktop files -+ # 1 -+ os.makedirs(os.path.join(GLib.get_user_data_dir(), "applications")) -+ shutil.copy(os.path.join(os.path.dirname(os.path.abspath(__file__)), "kickertest.desktop"), os.path.join(GLib.get_user_data_dir(), "applications")) -+ cls.desktop_entry_1 = os.path.join(GLib.get_user_data_dir(), "applications", "kickertest.desktop") -+ # 2 -+ cls.temp_dir = tempfile.TemporaryDirectory() -+ os.makedirs(os.path.join(cls.temp_dir.name, "applications")) -+ shutil.copy(os.path.join(os.path.dirname(os.path.abspath(__file__)), "kickertest.desktop"), os.path.join(cls.temp_dir.name, "applications")) -+ cls.desktop_entry_2 = os.path.join(cls.temp_dir.name, "applications", "kickertest.desktop") -+ -+ os.environ["LC_ALL"] = "en_US.UTF-8" -+ os.environ["QT_LOGGING_RULES"] = "org.kde.plasma.kicker.debug=true;kf.coreaddons.kdirwatch.debug=true" -+ os.environ["XDG_DATA_DIRS"] = os.environ["XDG_DATA_DIRS"] + ":" + cls.temp_dir.name -+ -+ cls.kactivitymanagerd = start_kactivitymanagerd() -+ -+ cls.loop_thread = GLibMainLoopThread() -+ cls.loop_thread.start() -+ cls.dbus_interface = TestDBusInterface() -+ -+ @classmethod -+ def tearDownClass(cls) -> None: -+ cls.loop_thread.quit() -+ cls.kactivitymanagerd.kill() -+ cls.kactivitymanagerd.wait(10) -+ -+ def test_qml(self) -> None: -+ """ -+ 1. Add an entry to Favorites -+ 2. Remove the entry from Favorites -+ 3. Hide invalid entries automatically and don't crash when there are multiple entries with the same desktop name -+ """ -+ with subprocess.Popen([QMLTEST_EXEC, "-input", os.path.join(os.path.dirname(os.path.abspath(__file__)), 'favoritetest.qml')], stdout=sys.stderr, stderr=sys.stderr) as process: -+ self.assertEqual(process.wait(60), 0) -+ -+ -+if __name__ == '__main__': -+ assert "USE_CUSTOM_BUS" in os.environ -+ logging.getLogger().setLevel(logging.INFO) -+ unittest.main() -diff --git a/appiumtests/applets/notificationstest.py b/appiumtests/applets/notificationstest.py -index 8917121a94..cd34a32905 100755 ---- a/appiumtests/applets/notificationstest.py -+++ b/appiumtests/applets/notificationstest.py -@@ -5,6 +5,7 @@ - - import base64 - import os -+import shutil - import subprocess - import tempfile - import time -@@ -15,6 +16,7 @@ import gi - from appium import webdriver - from appium.options.common.base import AppiumOptions - from appium.webdriver.common.appiumby import AppiumBy -+from selenium.common.exceptions import (NoSuchElementException, WebDriverException) - from selenium.webdriver.support import expected_conditions as EC - from selenium.webdriver.support.ui import WebDriverWait - -@@ -22,6 +24,8 @@ gi.require_version('Gdk', '4.0') - gi.require_version('GdkPixbuf', '2.0') - from gi.repository import Gdk, GdkPixbuf, Gio, GLib - -+from kicker.favoritetest import start_kactivitymanagerd -+ - WIDGET_ID: Final = "org.kde.plasma.notifications" - KDE_VERSION: Final = 6 - -@@ -48,17 +52,25 @@ class NotificationsTest(unittest.TestCase): - """ - - driver: webdriver.Remote -+ kactivitymanagerd: subprocess.Popen - - @classmethod - def setUpClass(cls) -> None: - """ - Opens the widget and initialize the webdriver - """ -+ # Make history work -+ cls.kactivitymanagerd = start_kactivitymanagerd() -+ -+ os.makedirs(os.path.join(GLib.get_user_data_dir(), "knotifications6")) -+ shutil.copy(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir, "libnotificationmanager", "libnotificationmanager.notifyrc"), os.path.join(GLib.get_user_data_dir(), "knotifications6")) -+ - options = AppiumOptions() - options.set_capability("app", f"plasmawindowed -p org.kde.plasma.nano {WIDGET_ID}") - options.set_capability("timeouts", {'implicit': 10000}) - options.set_capability("environ", { - "LC_ALL": "en_US.UTF-8", -+ "QT_LOGGING_RULES": "kf.notification*.debug=true;org.kde.plasma.notificationmanager.debug=true", - }) - cls.driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', options=options) - -@@ -75,6 +87,8 @@ class NotificationsTest(unittest.TestCase): - Make sure to terminate the driver again, lest it dangles. - """ - subprocess.check_call([f"kquitapp{KDE_VERSION}", "plasmawindowed"]) -+ cls.kactivitymanagerd.kill() -+ cls.kactivitymanagerd.wait(10) - for _ in range(10): - try: - subprocess.check_call(["pidof", "plasmawindowed"]) -@@ -83,6 +97,15 @@ class NotificationsTest(unittest.TestCase): - time.sleep(1) - cls.driver.quit() - -+ def close_notifications(self) -> None: -+ wait = WebDriverWait(self.driver, 5) -+ for button in self.driver.find_elements(AppiumBy.XPATH, "//button[@name='Close']"): -+ try: -+ button.click() -+ wait.until_not(lambda _: button.is_displayed()) -+ except WebDriverException: -+ pass -+ - def test_0_open(self) -> None: - """ - Tests the widget can be opened -@@ -106,6 +129,10 @@ class NotificationsTest(unittest.TestCase): - - wait = WebDriverWait(self.driver, 5) - wait.until(EC.presence_of_element_located((AppiumBy.NAME, summary))) -+<<<<<<< HEAD -+======= -+ self.close_notifications() -+>>>>>>> 5145d877d8 (applets/notifications: suppress inhibited notifications after "Do not disturb" is off) - - def take_screenshot(self) -> str: - with tempfile.TemporaryDirectory() as temp_dir: -@@ -123,6 +150,7 @@ class NotificationsTest(unittest.TestCase): - partial_pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 16, 16) - colors = (0xff0000ff, 0x00ff00ff, 0x0000ffff) - for color in colors: -+ logging.info(f"Testing color: {color}") - pixbuf.fill(color) - send_notification({ - "app_name": "Appium Test", -@@ -145,7 +173,29 @@ class NotificationsTest(unittest.TestCase): - wait.until(EC.presence_of_element_located((AppiumBy.NAME, summary + str(color)))) - partial_pixbuf.fill(color) - partial_image = base64.b64encode(Gdk.Texture.new_for_pixbuf(partial_pixbuf).save_to_png_bytes().get_data()).decode() -+<<<<<<< HEAD - self.driver.find_image_occurrence(self.take_screenshot(), partial_image) -+======= -+ try: -+ self.driver.find_image_occurrence(self.take_screenshot(), partial_image) -+ except WebDriverException: # Popup animation -+ self.driver.find_image_occurrence(self.take_screenshot(), partial_image) -+ self.close_notifications() -+ -+ def test_2_notification_with_explicit_timeout(self) -> None: -+ """ -+ Sends notifications with expire_timeout -+ """ -+ summary = "expire_timeout" -+ send_notification({ -+ "app_name": "Appium Test", -+ "summary": summary, -+ "body": "Will it disappear automatically?", -+ "timeout": 2000, -+ }) -+ element = self.driver.find_element(AppiumBy.NAME, summary) -+ WebDriverWait(self.driver, 5).until_not(lambda _: element.is_displayed()) -+>>>>>>> 5145d877d8 (applets/notifications: suppress inhibited notifications after "Do not disturb" is off) - - def test_3_accessible_description_html_to_plaintext(self) -> None: - """ -@@ -157,6 +207,202 @@ class NotificationsTest(unittest.TestCase): - }) - wait = WebDriverWait(self.driver, 5) - wait.until(EC.presence_of_element_located(("description", "biublinkwww.example.org from Appium Test"))) -+<<<<<<< HEAD -+======= -+ self.close_notifications() -+ -+ def test_4_actions(self) -> None: -+ """ -+ When the "actions" key is set, a notification can provide actions. -+ """ -+ loop = GLib.MainLoop() -+ activation_token = False -+ params_1: list[Any] = [] -+ action_invoked = False -+ params_2: list[Any] = [] -+ notification_closed = False -+ params_3: list[Any] = [] -+ -+ def notification_signal_handler(d_bus_proxy: Gio.DBusProxy, sender_name: str, signal_name: str, parameters: GLib.Variant) -> None: -+ nonlocal params_2, params_3, params_1, activation_token, action_invoked, notification_closed -+ logging.info(f"received signal {signal_name}") -+ match signal_name: -+ case "ActivationToken": -+ params_1 = parameters.unpack() -+ activation_token = True -+ case "ActionInvoked": -+ params_2 = parameters.unpack() -+ action_invoked = True -+ case "NotificationClosed": -+ params_3 = parameters.unpack() -+ notification_closed = True -+ loop.quit() -+ -+ connection_id = self.notification_proxy.connect("g-signal", notification_signal_handler) -+ self.addCleanup(lambda: self.notification_proxy.disconnect(connection_id)) -+ -+ notification_id = send_notification({ -+ "app_name": "Appium Test", -+ "body": "A notification with actions", -+ "actions": ["action1", "FooAction", "action2", "BarAction"], -+ }) -+ self.driver.find_element(AppiumBy.NAME, "BarAction") -+ element = self.driver.find_element(AppiumBy.NAME, "FooAction") -+ element.click() -+ loop.run() -+ self.assertTrue(activation_token) -+ self.assertEqual(params_1[0], notification_id) -+ self.assertTrue(action_invoked) -+ self.assertEqual(params_2[0], notification_id) -+ self.assertEqual(params_2[1], "action1") -+ self.assertTrue(notification_closed) -+ self.assertEqual(params_3[0], notification_id) -+ self.assertEqual(params_3[1], 3) # reason: Revoked -+ self.assertFalse(element.is_displayed()) -+ -+ def test_5_inline_reply(self) -> None: -+ """ -+ When the action list has "inline-reply", the notification popup will contain a text field and a reply button. -+ """ -+ loop = GLib.MainLoop() -+ notification_replied = False -+ params: list[Any] = [] # id, text -+ -+ def notification_signal_handler(d_bus_proxy: Gio.DBusProxy, sender_name: str, signal_name: str, parameters: GLib.Variant) -> None: -+ nonlocal params, notification_replied -+ logging.info(f"received signal {signal_name}") -+ if signal_name == "NotificationReplied": -+ params = parameters.unpack() -+ notification_replied = True -+ loop.quit() -+ -+ connection_id = self.notification_proxy.connect("g-signal", notification_signal_handler) -+ self.addCleanup(lambda: self.notification_proxy.disconnect(connection_id)) -+ -+ # When there is only one action and it is a reply action, show text field right away -+ notification_id = send_notification({ -+ "app_name": "Appium Test", -+ "body": "A notification with actions 1", -+ "actions": ["inline-reply", ""], # Use the default label -+ }) -+ reply_text = "this is a reply" -+ self.driver.find_element(AppiumBy.NAME, "begin reply").click() -+ self.driver.find_element(AppiumBy.NAME, "Type a reply…").send_keys(reply_text) -+ element = self.driver.find_element(AppiumBy.NAME, "Send") -+ element.click() -+ loop.run() -+ self.assertTrue(notification_replied) -+ self.assertEqual(params[0], notification_id) -+ self.assertEqual(params[1], reply_text) -+ self.assertFalse(element.is_displayed()) -+ -+ notification_replied = False -+ notification_id = send_notification({ -+ "app_name": "Appium Test", -+ "body": "A notification with actions 2", -+ "actions": ["inline-reply", ""], -+ "hints": { -+ "x-kde-reply-submit-button-text": GLib.Variant("s", "Reeply"), # Use a custom label -+ "x-kde-reply-placeholder-text": GLib.Variant("s", "A placeholder"), # Use a custom placeholder -+ }, -+ }) -+ reply_text = "this is another reply" -+ self.driver.find_element(AppiumBy.NAME, "begin reply").click() -+ self.driver.find_element(AppiumBy.NAME, "A placeholder").send_keys(reply_text) -+ element = self.driver.find_element(AppiumBy.NAME, "Reeply") -+ element.click() -+ loop.run() -+ self.assertTrue(notification_replied) -+ self.assertEqual(params[0], notification_id) -+ self.assertEqual(params[1], reply_text) -+ self.assertFalse(element.is_displayed()) -+ -+ notification_replied = False -+ notification_id = send_notification({ -+ "app_name": "Appium Test", -+ "body": "A notification with actions 3", -+ "actions": ["inline-reply", "Replyy", "foo", "Foo", "bar", "Bar"], # Click to show the text field -+ }) -+ self.driver.find_element(AppiumBy.NAME, "Foo") -+ self.driver.find_element(AppiumBy.NAME, "Bar") -+ element = self.driver.find_element(AppiumBy.NAME, "Replyy") -+ element.click() -+ reply_text = "Click Replyy to reply" -+ self.driver.find_element(AppiumBy.NAME, "Type a reply…").send_keys(reply_text) -+ self.assertFalse(element.is_displayed()) -+ element = self.driver.find_element(AppiumBy.NAME, "Send") -+ element.click() -+ loop.run() -+ self.assertTrue(notification_replied) -+ self.assertEqual(params[0], notification_id) -+ self.assertEqual(params[1], reply_text) -+ -+ def test_6_thumbnail(self) -> None: -+ """ -+ When a notification has "x-kde-urls" hint, a thumbnail will be shown for the first url in the list -+ """ -+ with tempfile.TemporaryDirectory() as temp_dir: -+ pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 256, 256) -+ colors = (0xff0000ff, 0x00ff00ff, 0x0000ffff) -+ for color in colors: -+ pixbuf.fill(color) -+ pixbuf.savev(os.path.join(temp_dir, f"{str(color)}.png"), "png") -+ -+ url_list = [f"file://{os.path.join(temp_dir, path)}" for path in os.listdir(temp_dir)] -+ url_list.sort() -+ send_notification({ -+ "app_name": "Appium Test", -+ "body": "Thumbnail", -+ "hints": { -+ "x-kde-urls": GLib.Variant("as", url_list), -+ }, -+ "timeout": 10 * 1000, -+ }) -+ -+ self.driver.find_element(AppiumBy.NAME, "More Options…") -+ -+ partial_pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 100, 100) -+ partial_pixbuf.fill(colors[1]) # Green is the first item -+ partial_image = base64.b64encode(Gdk.Texture.new_for_pixbuf(partial_pixbuf).save_to_png_bytes().get_data()).decode() -+ -+ def match_image(driver) -> bool: -+ try: -+ self.driver.find_image_occurrence(self.take_screenshot(), partial_image) -+ return True -+ except WebDriverException: -+ return False -+ -+ WebDriverWait(self.driver, 10).until(match_image) -+ self.close_notifications() -+ -+ def test_7_do_not_disturb(self) -> None: -+ """ -+ Suppress inhibited notifications after "Do not disturb" is turned off, and show a summary for unread inhibited notifications. -+ """ -+ self.driver.find_element(AppiumBy.NAME, "Do not disturb").click() -+ dnd_button = self.driver.find_element(AppiumBy.XPATH, "//*[@name='Do not disturb' and contains(@states, 'checked')]") -+ -+ summary = "Do not disturb me" -+ for i in range(2): -+ send_notification({ -+ "app_name": "Appium Test", -+ "summary": summary + str(i), -+ "hints": { -+ "desktop-entry": GLib.Variant("s", "org.kde.plasmashell"), -+ }, -+ "timeout": 60 * 1000, -+ }) -+ title = self.driver.find_element(AppiumBy.XPATH, f"//heading[starts-with(@name, '{summary}') and contains(@accessibility-id, 'FullRepresentation')]") -+ self.assertRaises(NoSuchElementException, self.driver.find_element, AppiumBy.XPATH, f"//notification[starts-with(@name, '{summary}')]") -+ -+ dnd_button.click() -+ self.driver.find_element(AppiumBy.XPATH, "//notification[@name='Unread Notifications' and @description='2 notifications were received while Do Not Disturb was active. from Notification Manager']") -+ self.driver.find_element(AppiumBy.XPATH, "//button[@name='Close' and contains(@accessibility-id, 'NotificationPopup')]").click() -+ -+ # Notifications can only be cleared after they are expired, otherwise they will stay in the list -+ self.driver.find_element(AppiumBy.NAME, "Clear All Notifications").click() -+ WebDriverWait(self.driver, 5).until_not(lambda _: title.is_displayed()) -+>>>>>>> 5145d877d8 (applets/notifications: suppress inhibited notifications after "Do not disturb" is off) - - - if __name__ == '__main__': -diff --git a/applets/notifications/package/contents/ui/FullRepresentation.qml b/applets/notifications/package/contents/ui/FullRepresentation.qml -index f949dad46a..33838599f6 100644 ---- a/applets/notifications/package/contents/ui/FullRepresentation.qml -+++ b/applets/notifications/package/contents/ui/FullRepresentation.qml -@@ -71,6 +71,14 @@ PlasmaExtras.Representation { - checkable: true - checked: Globals.inhibited - -+ Accessible.onPressAction: if (Globals.inhibited) { -+ Globals.revokeInhibitions(); -+ } else { -+ let date = new Date(); -+ date.setFullYear(date.getFullYear() + 1); -+ notificationSettings.notificationsInhibitedUntil = date; -+ notificationSettings.save(); -+ } - KeyNavigation.down: list - KeyNavigation.tab: list - -diff --git a/applets/notifications/package/contents/ui/global/Globals.qml b/applets/notifications/package/contents/ui/global/Globals.qml -index c46c32921a..2238653eff 100644 ---- a/applets/notifications/package/contents/ui/global/Globals.qml -+++ b/applets/notifications/package/contents/ui/global/Globals.qml -@@ -34,6 +34,10 @@ QtObject { - property bool inhibited: false - - onInhibitedChanged: { -+ if (!inhibited) { -+ popupNotificationsModel.showInhibitionSummary(); -+ } -+ - var pa = pulseAudio.item; - if (!pa) { - return; -@@ -405,6 +409,7 @@ QtObject { - limit: plasmoid ? (Math.ceil(globals.screenRect.height / (Kirigami.Units.gridUnit * 4))) : 0 - showExpired: false - showDismissed: false -+ showAddedDuringInhibition: false - blacklistedDesktopEntries: notificationSettings.popupBlacklistedApplications - blacklistedNotifyRcNames: notificationSettings.popupBlacklistedServices - whitelistedDesktopEntries: globals.inhibited ? notificationSettings.doNotDisturbPopupWhitelistedApplications : [] -@@ -613,9 +618,13 @@ QtObject { - onKillJobClicked: popupNotificationsModel.killJob(popupNotificationsModel.index(index, 0)) - - // popup width is fixed -- onHeightChanged: positionPopups() -+ onHeightChanged: globals.positionPopups() - - Component.onCompleted: { -+ if (globals.inhibited) { -+ model.wasAddedDuringInhibition = false; // Don't count already shown notifications -+ } -+ - if (model.type === NotificationManager.Notifications.NotificationType && model.desktopEntry) { - // Register apps that were seen spawning a popup so they can be configured later - // Apps with notifyrc can already be configured anyway -diff --git a/libnotificationmanager/CMakeLists.txt b/libnotificationmanager/CMakeLists.txt -index d04d8a4a24..5c48653ede 100644 ---- a/libnotificationmanager/CMakeLists.txt -+++ b/libnotificationmanager/CMakeLists.txt -@@ -84,6 +84,7 @@ target_link_libraries(notificationmanager - KF6::I18n - KF6::WindowSystem - KF6::ItemModels # KDescendantsProxyModel -+ KF6::Notifications # Inhibition summary - KF6::KIOFileWidgets - Plasma::Plasma - KF6::Screen -@@ -135,3 +136,6 @@ install(EXPORT notificationmanagerLibraryTargets - - install(FILES plasmanotifyrc - DESTINATION ${KDE_INSTALL_CONFDIR}) -+ -+install(FILES libnotificationmanager.notifyrc -+ DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR}) -diff --git a/libnotificationmanager/abstractnotificationsmodel.cpp b/libnotificationmanager/abstractnotificationsmodel.cpp -index 8bd55bc26c..8307a1e8f7 100644 ---- a/libnotificationmanager/abstractnotificationsmodel.cpp -+++ b/libnotificationmanager/abstractnotificationsmodel.cpp -@@ -104,6 +104,7 @@ void AbstractNotificationsModel::Private::onNotificationReplaced(uint replacedId - newNotification.setExpired(oldNotification.expired()); - newNotification.setDismissed(oldNotification.dismissed()); - newNotification.setRead(oldNotification.read()); -+ newNotification.setWasAddedDuringInhibition(Server::self().inhibited()); - - notifications[row] = newNotification; - const QModelIndex idx = q->index(row, 0); -@@ -378,6 +379,9 @@ QVariant AbstractNotificationsModel::data(const QModelIndex &index, int role) co - case Notifications::TransientRole: - return notification.transient(); - -+ case Notifications::WasAddedDuringInhibitionRole: -+ return notification.wasAddedDuringInhibition(); -+ - case Notifications::HasReplyActionRole: - return notification.hasReplyAction(); - case Notifications::ReplyActionLabelRole: -@@ -416,6 +420,12 @@ bool AbstractNotificationsModel::setData(const QModelIndex &index, const QVarian - dirty = true; - } - break; -+ case Notifications::WasAddedDuringInhibitionRole: -+ if (bool v = value.toBool(); v != notification.wasAddedDuringInhibition()) { -+ notification.setWasAddedDuringInhibition(v); -+ dirty = true; -+ } -+ break; - } - - if (dirty) { -@@ -471,7 +481,7 @@ void AbstractNotificationsModel::clear(Notifications::ClearFlags flags) - for (int i = 0; i < d->notifications.count(); ++i) { - const Notification ¬ification = d->notifications.at(i); - -- if (flags.testFlag(Notifications::ClearExpired) && notification.expired()) { -+ if (flags.testFlag(Notifications::ClearExpired) && (notification.expired() || notification.wasAddedDuringInhibition())) { - close(notification.id()); - } - } -diff --git a/libnotificationmanager/libnotificationmanager.notifyrc b/libnotificationmanager/libnotificationmanager.notifyrc -new file mode 100644 -index 0000000000..79304e62bc ---- /dev/null -+++ b/libnotificationmanager/libnotificationmanager.notifyrc -@@ -0,0 +1,11 @@ -+# SPDX-License-Identifier: CC0-1.0 -+# SPDX-FileCopyrightText: None -+ -+[Global] -+Name=Notification Manager -+IconName=preferences-desktop-notification-bell -+ -+[Event/inhibitionSummary] -+Name=Summary for unread inhibited notifications -+Action=Popup -+Urgency=Low -diff --git a/libnotificationmanager/notification.cpp b/libnotificationmanager/notification.cpp -index 276611310c..320c837617 100644 ---- a/libnotificationmanager/notification.cpp -+++ b/libnotificationmanager/notification.cpp -@@ -826,3 +826,13 @@ void Notification::processHints(const QVariantMap &hints) - { - d->processHints(hints); - } -+ -+bool Notification::wasAddedDuringInhibition() const -+{ -+ return d->wasAddedDuringInhibition; -+} -+ -+void Notification::setWasAddedDuringInhibition(bool value) -+{ -+ d->wasAddedDuringInhibition = value; -+} -diff --git a/libnotificationmanager/notification.h b/libnotificationmanager/notification.h -index 9f04a4e200..8613534fd2 100644 ---- a/libnotificationmanager/notification.h -+++ b/libnotificationmanager/notification.h -@@ -131,6 +131,9 @@ public: - - void processHints(const QVariantMap &hints); - -+ bool wasAddedDuringInhibition() const; -+ void setWasAddedDuringInhibition(bool value); -+ - private: - friend class NotificationsModel; - friend class AbstractNotificationsModel; -diff --git a/libnotificationmanager/notification_p.h b/libnotificationmanager/notification_p.h -index 6cae23c21e..923bde7882 100644 ---- a/libnotificationmanager/notification_p.h -+++ b/libnotificationmanager/notification_p.h -@@ -96,6 +96,8 @@ public: - - bool resident = false; - bool transient = false; -+ -+ bool wasAddedDuringInhibition = false; - }; - - } // namespace NotificationManager -diff --git a/libnotificationmanager/notificationfilterproxymodel.cpp b/libnotificationmanager/notificationfilterproxymodel.cpp -index 98a32b6645..bb573713af 100644 ---- a/libnotificationmanager/notificationfilterproxymodel.cpp -+++ b/libnotificationmanager/notificationfilterproxymodel.cpp -@@ -58,6 +58,20 @@ void NotificationFilterProxyModel::setShowDismissed(bool show) - } - } - -+bool NotificationFilterProxyModel::showAddedDuringInhibition() const -+{ -+ return m_showDismissed; -+} -+ -+void NotificationFilterProxyModel::setShowAddedDuringInhibition(bool show) -+{ -+ if (m_showAddedDuringInhibition != show) { -+ m_showAddedDuringInhibition = show; -+ invalidateFilter(); -+ Q_EMIT showAddedDuringInhibitionChanged(); -+ } -+} -+ - QStringList NotificationFilterProxyModel::blacklistedDesktopEntries() const - { - return m_blacklistedDesktopEntries; -@@ -177,5 +191,9 @@ bool NotificationFilterProxyModel::filterAcceptsRow(int source_row, const QModel - } - } - -+ if (!m_showAddedDuringInhibition && sourceIdx.data(Notifications::WasAddedDuringInhibitionRole).toBool()) { -+ return false; -+ } -+ - return true; - } -diff --git a/libnotificationmanager/notificationfilterproxymodel_p.h b/libnotificationmanager/notificationfilterproxymodel_p.h -index 4029320e8e..af04a9fac1 100644 ---- a/libnotificationmanager/notificationfilterproxymodel_p.h -+++ b/libnotificationmanager/notificationfilterproxymodel_p.h -@@ -30,6 +30,9 @@ public: - bool showDismissed() const; - void setShowDismissed(bool show); - -+ bool showAddedDuringInhibition() const; -+ void setShowAddedDuringInhibition(bool show); -+ - QStringList blacklistedDesktopEntries() const; - void setBlackListedDesktopEntries(const QStringList &blacklist); - -@@ -46,6 +49,7 @@ Q_SIGNALS: - void urgenciesChanged(); - void showExpiredChanged(); - void showDismissedChanged(); -+ void showAddedDuringInhibitionChanged(); - void blacklistedDesktopEntriesChanged(); - void blacklistedNotifyRcNamesChanged(); - void whitelistedDesktopEntriesChanged(); -@@ -58,6 +62,7 @@ private: - Notifications::Urgencies m_urgencies = Notifications::LowUrgency | Notifications::NormalUrgency | Notifications::CriticalUrgency; - bool m_showDismissed = false; - bool m_showExpired = false; -+ bool m_showAddedDuringInhibition = true; - - QStringList m_blacklistedDesktopEntries; - QStringList m_blacklistedNotifyRcNames; -diff --git a/libnotificationmanager/notifications.cpp b/libnotificationmanager/notifications.cpp -index 9b3e18018b..3d5662f926 100644 ---- a/libnotificationmanager/notifications.cpp -+++ b/libnotificationmanager/notifications.cpp -@@ -12,6 +12,8 @@ - #include - - #include -+#include -+#include - - #include "limitedrowcountproxymodel_p.h" - #include "notificationfilterproxymodel_p.h" -@@ -30,6 +32,7 @@ - - #include "debug.h" - -+using namespace Qt::StringLiterals; - using namespace NotificationManager; - - class Q_DECL_HIDDEN Notifications::Private -@@ -166,6 +169,7 @@ void Notifications::Private::initProxyModels() - connect(filterModel, &NotificationFilterProxyModel::urgenciesChanged, q, &Notifications::urgenciesChanged); - connect(filterModel, &NotificationFilterProxyModel::showExpiredChanged, q, &Notifications::showExpiredChanged); - connect(filterModel, &NotificationFilterProxyModel::showDismissedChanged, q, &Notifications::showDismissedChanged); -+ connect(filterModel, &NotificationFilterProxyModel::showAddedDuringInhibitionChanged, q, &Notifications::showAddedDuringInhibitionChanged); - connect(filterModel, &NotificationFilterProxyModel::blacklistedDesktopEntriesChanged, q, &Notifications::blacklistedDesktopEntriesChanged); - connect(filterModel, &NotificationFilterProxyModel::blacklistedNotifyRcNamesChanged, q, &Notifications::blacklistedNotifyRcNamesChanged); - -@@ -245,7 +249,7 @@ void Notifications::Private::updateCount() - for (int i = 0; i < filterModel->rowCount(); ++i) { - const QModelIndex idx = filterModel->index(i, 0); - -- if (idx.data(Notifications::ExpiredRole).toBool()) { -+ if (idx.data(Notifications::ExpiredRole).toBool() || idx.data(Notifications::WasAddedDuringInhibitionRole).toBool()) { - ++expired; - } else { - ++active; -@@ -477,6 +481,16 @@ void Notifications::setShowDismissed(bool show) - d->filterModel->setShowDismissed(show); - } - -+bool Notifications::showAddedDuringInhibition() const -+{ -+ return d->filterModel->showAddedDuringInhibition(); -+} -+ -+void Notifications::setShowAddedDuringInhibition(bool show) -+{ -+ d->filterModel->setShowAddedDuringInhibition(show); -+} -+ - QStringList Notifications::blacklistedDesktopEntries() const - { - return d->filterModel->blacklistedDesktopEntries(); -@@ -812,6 +826,28 @@ void Notifications::collapseAllGroups() - } - } - -+void Notifications::showInhibitionSummary() -+{ -+ int inhibited = 0; -+ for (int i = 0, count = d->notificationsAndJobsModel->rowCount(); i < count; ++i) { -+ const QModelIndex idx = d->notificationsAndJobsModel->index(i, 0); -+ if (!idx.data(Notifications::ReadRole).toBool() && idx.data(Notifications::WasAddedDuringInhibitionRole).toBool()) { -+ ++inhibited; -+ } -+ } -+ -+ if (!inhibited) { -+ return; -+ } -+ -+ KNotification::event(u"inhibitionSummary"_s, -+ i18nc("@title", "Unread Notifications"), -+ i18nc("@info", "%1 notifications were received while Do Not Disturb was active.", QString::number(inhibited)), -+ u"preferences-desktop-notification-bell"_s, -+ KNotification::CloseOnTimeout, -+ u"libnotificationmanager"_s); -+} -+ - QVariant Notifications::data(const QModelIndex &index, int role) const - { - return QSortFilterProxyModel::data(index, role); -diff --git a/libnotificationmanager/notifications.h b/libnotificationmanager/notifications.h -index edb898988f..ef500b0c7b 100644 ---- a/libnotificationmanager/notifications.h -+++ b/libnotificationmanager/notifications.h -@@ -61,6 +61,15 @@ class NOTIFICATIONMANAGER_EXPORT Notifications : public QSortFilterProxyModel, p - */ - Q_PROPERTY(bool showDismissed READ showDismissed WRITE setShowDismissed NOTIFY showDismissedChanged) - -+ /** -+ * Whether to show notifications added during inhibition. -+ * -+ * If set to @c false, notifications are suppressed even after leaving "Do not disturb" mode. -+ * -+ * Default is @c true. -+ */ -+ Q_PROPERTY(bool showAddedDuringInhibition READ showAddedDuringInhibition WRITE setShowAddedDuringInhibition NOTIFY showAddedDuringInhibitionChanged) -+ - /** - * A list of desktop entries for which no notifications should be shown. - * -@@ -285,6 +294,8 @@ public: - ///< notification in a certain way, or group notifications of similar types. @since 5.21 - ResidentRole, ///< Whether the notification should keep its actions even when they were invoked. @since 5.22 - TransientRole, ///< Whether the notification is transient and should not be kept in history. @since 5.22 -+ -+ WasAddedDuringInhibitionRole, ///< Whether the notification was added while inhibition was active. @since 6.3 - }; - Q_ENUM(Roles) - -@@ -371,6 +382,9 @@ public: - bool showDismissed() const; - void setShowDismissed(bool show); - -+ bool showAddedDuringInhibition() const; -+ void setShowAddedDuringInhibition(bool show); -+ - QStringList blacklistedDesktopEntries() const; - void setBlacklistedDesktopEntries(const QStringList &blacklist); - -@@ -529,6 +543,11 @@ public: - - Q_INVOKABLE void collapseAllGroups(); - -+ /** -+ * Shows a notification to report the number of unread inhibited notifications. -+ */ -+ Q_INVOKABLE void showInhibitionSummary(); -+ - QVariant data(const QModelIndex &index, int role) const override; - bool setData(const QModelIndex &index, const QVariant &value, int role) override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; -@@ -541,6 +560,7 @@ Q_SIGNALS: - void limitChanged(); - void showExpiredChanged(); - void showDismissedChanged(); -+ void showAddedDuringInhibitionChanged(); - void blacklistedDesktopEntriesChanged(); - void blacklistedNotifyRcNamesChanged(); - void whitelistedDesktopEntriesChanged(); -diff --git a/libnotificationmanager/server_p.cpp b/libnotificationmanager/server_p.cpp -index 84fe37afa9..66cd621033 100644 ---- a/libnotificationmanager/server_p.cpp -+++ b/libnotificationmanager/server_p.cpp -@@ -164,6 +164,7 @@ uint ServerPrivate::Notify(const QString &app_name, - notification.setActions(actions); - - notification.setTimeout(timeout); -+ notification.setWasAddedDuringInhibition(m_inhibited); - - // might override some of the things we set above (like application name) - notification.d->processHints(hints); diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 1f0f5db..00c4099 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -39,37 +39,6 @@ in { qt.enable = true; - nixpkgs.overlays = [ - ( - final: prev: { - kdePackages = prev.kdePackages.overrideScope ( - kFinal: kPrev: { - libplasma = kPrev.libplasma.overrideAttrs { - patches = [ - ./patches/libplasma-pr1214.patch - ]; - }; - plasma-workspace = kPrev.plasma-workspace.overrideAttrs { - patches = - kPrev.plasma-workspace.patches - ++ [ - ./patches/plasma_workspace-pr4883.patch - ./patches/plasma_workspace-pr4965.patch - ]; - }; - plasma-desktop = kPrev.plasma-desktop.overrideAttrs { - patches = - kPrev.plasma-desktop.patches - ++ [ - ./patches/plasma_desktop-pr2661.patch - ]; - }; - } - ); - } - ) - ]; - # GTK apps need dconf to grab the correct theme on Wayland programs.dconf.enable = true; diff --git a/roles/kde/programs/kwin.nix b/roles/kde/programs/kwin.nix index f6b176b..68b9f0a 100644 --- a/roles/kde/programs/kwin.nix +++ b/roles/kde/programs/kwin.nix @@ -1,24 +1,4 @@ {...}: { - nixpkgs.overlays = [ - ( - final: prev: { - kdePackages = prev.kdePackages.overrideScope ( - kFinal: kPrev: { - kwin = kPrev.kwin.overrideAttrs { - patches = - kPrev.kwin.patches - ++ [ - ../patches/kwin-pr6406.patch - ../patches/kwin-pr6878.patch - ../patches/kwin-pr6844.patch - ../patches/kwin-pr6985.patch - ]; - }; - } - ); - } - ) - ]; home-manager.users.toast = { programs.plasma = { kwin = { From 40d2622862df418358e209e8629fa690d222e5a2 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 19 Feb 2025 16:08:11 +0100 Subject: [PATCH 0929/1125] Flake: update lock file --- flake.lock | 92 +++++++++++++++++++++++++++--------------------------- flake.nix | 2 +- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/flake.lock b/flake.lock index f6a3060..57afc98 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1737579274, - "narHash": "sha256-8kBIYfn8TI9jbffhDNS12SdbQHb9ITXflwcgIJBeGqw=", + "lastModified": 1739934729, + "narHash": "sha256-PcrLk10meIJICzUJqtCMOJxoITzbH52fZg2XAB7SSsM=", "owner": "catppuccin", "repo": "nix", - "rev": "06f0ea19334bcc8112e6d671fd53e61f9e3ad63a", + "rev": "b1ff2a638afa827f1473498190a2c1cae1cf41cf", "type": "github" }, "original": { @@ -60,11 +60,11 @@ "eza-themes": { "flake": false, "locked": { - "lastModified": 1737730475, - "narHash": "sha256-d+bbjgI1JrOGenqZ2aIRK8itkTUV2L4L3vtEN9tEgf8=", + "lastModified": 1739960775, + "narHash": "sha256-vu6QLz0RvPavpD2VED25D2PJlHgQ8Yis+DnL+BPlvHw=", "owner": "eza-community", "repo": "eza-themes", - "rev": "a99a5f1bbb5fec2c0bfa945ec8e2aabcb6f24d71", + "rev": "57149851f07b3ee6ca94f5fe3d9d552f73f8b8b4", "type": "github" }, "original": { @@ -188,11 +188,11 @@ ] }, "locked": { - "lastModified": 1738275749, - "narHash": "sha256-PM+cGduJ05EZ+YXulqAwUFjvfKpPmW080mcuN6R1POw=", + "lastModified": 1739913864, + "narHash": "sha256-WhzgQjadrwnwPJQLLxZUUEIxojxa7UWDkf7raAkB1Lw=", "owner": "nix-community", "repo": "home-manager", - "rev": "a8159195bfaef3c64df75d3b1e6a68d49d392be9", + "rev": "97ac0801d187b2911e8caa45316399de12f6f199", "type": "github" }, "original": { @@ -208,11 +208,11 @@ ] }, "locked": { - "lastModified": 1736373539, - "narHash": "sha256-dinzAqCjenWDxuy+MqUQq0I4zUSfaCvN9rzuCmgMZJY=", + "lastModified": 1739757849, + "narHash": "sha256-Gs076ot1YuAAsYVcyidLKUMIc4ooOaRGO0PqTY7sBzA=", "owner": "nix-community", "repo": "home-manager", - "rev": "bd65bc3cde04c16755955630b344bc9e35272c56", + "rev": "9d3d080aec2a35e05a15cedd281c2384767c2cfe", "type": "github" }, "original": { @@ -230,11 +230,11 @@ ] }, "locked": { - "lastModified": 1737617533, - "narHash": "sha256-9hHaUxeRDZ5PTk7TqBbHPAjgKuBl67asaMdyehYLqFs=", + "lastModified": 1739952453, + "narHash": "sha256-+tyFW6nNj1fJ1VTtLeqe1PMp5F7Fb9zIkT6mUvdQHrM=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "2dd65c3c92a4b8b1bf653657ae8648b883a4d427", + "rev": "b2ed82d3ff837960df4518308dfe409dda3ae406", "type": "github" }, "original": { @@ -246,11 +246,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1738295316, - "narHash": "sha256-i6dSbuPQXv3iqARBqxL0tIbSZw4Rq5UuoVrI9a8vjV0=", - "rev": "e529074cb2c21e66c300806ebf6bf03abcd681b3", + "lastModified": 1739940699, + "narHash": "sha256-9jlwrVWXzqdEEl611VE+fMnBLKzRFoONJYHUQeeKM0Q=", + "rev": "df336747e6d9fdd36330ca4105fa30232b23a202", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/e529074cb2c21e66c300806ebf6bf03abcd681b3.tar.gz?rev=e529074cb2c21e66c300806ebf6bf03abcd681b3" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/df336747e6d9fdd36330ca4105fa30232b23a202.tar.gz?rev=df336747e6d9fdd36330ca4105fa30232b23a202" }, "original": { "type": "tarball", @@ -305,11 +305,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1738175805, - "narHash": "sha256-fPjaARmK522JLJ7wxFebxG4eE/3HHSmuAA78iAZ+A7g=", + "lastModified": 1739444422, + "narHash": "sha256-iAVVHi7X3kWORftY+LVbRiStRnQEob2TULWyjMS6dWg=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "d4c75a33c4a7a16bf87cfd804fb5444a1ec53d49", + "rev": "5e54c3ca05a7c7d968ae1ddeabe01d2a9bc1e177", "type": "github" }, "original": { @@ -363,11 +363,11 @@ ] }, "locked": { - "lastModified": 1737861961, - "narHash": "sha256-LIRtMvAwLGb8pBoamzgEF67oKlNPz4LuXiRPVZf+TpE=", + "lastModified": 1739676768, + "narHash": "sha256-U1HQ7nzhJyVVXUgjU028UCkbLQLEIkg42+G7iIiBmlU=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "79b7b8eae3243fc5aa9aad34ba6b9bbb2266f523", + "rev": "ae15068e79e22b76c344f0d7f8aed1bb1c5b0b63", "type": "github" }, "original": { @@ -383,11 +383,11 @@ ] }, "locked": { - "lastModified": 1737861961, - "narHash": "sha256-LIRtMvAwLGb8pBoamzgEF67oKlNPz4LuXiRPVZf+TpE=", + "lastModified": 1739676768, + "narHash": "sha256-U1HQ7nzhJyVVXUgjU028UCkbLQLEIkg42+G7iIiBmlU=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "79b7b8eae3243fc5aa9aad34ba6b9bbb2266f523", + "rev": "ae15068e79e22b76c344f0d7f8aed1bb1c5b0b63", "type": "github" }, "original": { @@ -398,11 +398,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1737751639, - "narHash": "sha256-ZEbOJ9iT72iwqXsiEMbEa8wWjyFvRA9Ugx8utmYbpz4=", + "lastModified": 1739798439, + "narHash": "sha256-GyipmjbbQEaosel/+wq1xihCKbv0/e1LU00x/8b/fP4=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "dfad538f751a5aa5d4436d9781ab27a6128ec9d4", + "rev": "3e2ea8a49d4d76276b0f4e2041df8ca5c0771371", "type": "github" }, "original": { @@ -430,11 +430,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1738163270, - "narHash": "sha256-B/7Y1v4y+msFFBW1JAdFjNvVthvNdJKiN6EGRPnqfno=", + "lastModified": 1739758141, + "narHash": "sha256-uq6A2L7o1/tR6VfmYhZWoVAwb3gTy7j4Jx30MIrH0rE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "59e618d90c065f55ae48446f307e8c09565d5ab0", + "rev": "c618e28f70257593de75a7044438efc1c1fc0791", "type": "github" }, "original": { @@ -445,11 +445,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1738142207, - "narHash": "sha256-NGqpVVxNAHwIicXpgaVqJEJWeyqzoQJ9oc8lnK9+WC4=", + "lastModified": 1739866667, + "narHash": "sha256-EO1ygNKZlsAC9avfcwHkKGMsmipUk1Uc0TbrEZpkn64=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9d3ae807ebd2981d593cddd0080856873139aa40", + "rev": "73cf49b8ad837ade2de76f87eb53fc85ed5d4680", "type": "github" }, "original": { @@ -460,11 +460,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1738142207, - "narHash": "sha256-NGqpVVxNAHwIicXpgaVqJEJWeyqzoQJ9oc8lnK9+WC4=", + "lastModified": 1739736696, + "narHash": "sha256-zON2GNBkzsIyALlOCFiEBcIjI4w38GYOb+P+R4S8Jsw=", "owner": "nixos", "repo": "nixpkgs", - "rev": "9d3ae807ebd2981d593cddd0080856873139aa40", + "rev": "d74a2335ac9c133d6bbec9fc98d91a77f1604c1f", "type": "github" }, "original": { @@ -493,11 +493,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1738308670, - "narHash": "sha256-88WNLo6WdYmlO5u+1vaVRIakliO0B9hiNxBEMTZ9yOM=", + "lastModified": 1739903703, + "narHash": "sha256-w2tTcjx39lJoPDaFbIxi+INIjAKE0jbIx9TNjj9ghmg=", "owner": "nix-community", "repo": "NUR", - "rev": "a75432a6ffa9ca5af9f885194b64e0d4ad10b96b", + "rev": "2215ad5c4347f522523715e809f5f2022509f504", "type": "github" }, "original": { @@ -516,11 +516,11 @@ ] }, "locked": { - "lastModified": 1736549395, - "narHash": "sha256-XzwkB62Tt5UYoL1jXiHzgk/qz2fUpGHExcSIbyGTtI0=", + "lastModified": 1739557722, + "narHash": "sha256-XikzLpPUDYiNyJ4w2SfRShdbSkIgE3btYdxCGInmtc4=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "a53af7f1514ef4cce8620a9d6a50f238cdedec8b", + "rev": "1f3e1f38dedbbb8aad77e184fb54ec518e2d9522", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index cb474fd..af19980 100644 --- a/flake.nix +++ b/flake.nix @@ -172,7 +172,7 @@ then home-manager else home-manager-unstable ) - .nixosModule + .nixosModules.home-manager ( if stable then nix-index-db From d0a38fbfa301b7908d8e868109c5814a66b06501 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 19 Feb 2025 17:25:45 +0100 Subject: [PATCH 0930/1125] Server/forgejo: enable catppuccin theme --- roles/server/forgejo.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index 9a69380..a276179 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -49,6 +49,10 @@ in { }; }; + catppuccin.forgejo = { + enable = true; + }; + # Add a record for forgejo services.headscale.settings.dns.extra_records = [ { From 36d0ee851e67d2a700189ee1f37a785f7634b091 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 19 Feb 2025 16:19:07 +0100 Subject: [PATCH 0931/1125] Flake: Add patch to fix nixpkgs-unstable grup install script --- flake.nix | 7 +++++-- nixpkgs_patches/pr383269.patch | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 nixpkgs_patches/pr383269.patch diff --git a/flake.nix b/flake.nix index af19980..1c6311a 100644 --- a/flake.nix +++ b/flake.nix @@ -100,7 +100,9 @@ nixpkgs-unstable-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; - patches = []; + patches = [ + ./nixpkgs_patches/pr383269.patch + ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; @@ -172,7 +174,8 @@ then home-manager else home-manager-unstable ) - .nixosModules.home-manager + .nixosModules + .home-manager ( if stable then nix-index-db diff --git a/nixpkgs_patches/pr383269.patch b/nixpkgs_patches/pr383269.patch new file mode 100644 index 0000000..414f921 --- /dev/null +++ b/nixpkgs_patches/pr383269.patch @@ -0,0 +1,22 @@ +From 39dd19122fdabf519c256796df0ed998515990a6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= +Date: Wed, 19 Feb 2025 14:33:33 +0700 +Subject: [PATCH] install-grub: add missing rmtree + +--- + nixos/modules/system/boot/loader/grub/install-grub.pl | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl +index 4a588a75da147..f5ae844da21f9 100644 +--- a/nixos/modules/system/boot/loader/grub/install-grub.pl ++++ b/nixos/modules/system/boot/loader/grub/install-grub.pl +@@ -3,7 +3,7 @@ + use Class::Struct; + use XML::LibXML; + use File::Basename; +-use File::Path qw(make_path); ++use File::Path qw(make_path rmtree); + use File::stat; + use File::Copy; + use File::Copy::Recursive qw(rcopy pathrm); From 922c4924128b7b99c99dfa7221d90f30fcbeb233 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 20 Feb 2025 17:29:53 +0100 Subject: [PATCH 0932/1125] Desktop/discord: revert vesktop to electron 33 --- roles/desktop/programs/discord.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 3df1659..eed249b 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -4,6 +4,9 @@ withOpenASAR = true; withVencord = true; }; + vesktop = super.vesktop.override { + electron = _self.electron_33; + }; }; in { nixpkgs.overlays = [discordOverlay]; From 82797211023ed2352334ba0d4daba374ad5b7381 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 3 Mar 2025 17:14:09 +0100 Subject: [PATCH 0933/1125] Kde/skanpage: use qt6 package --- roles/kde/programs/skanpage.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/kde/programs/skanpage.nix b/roles/kde/programs/skanpage.nix index 08ed4e4..114ef84 100644 --- a/roles/kde/programs/skanpage.nix +++ b/roles/kde/programs/skanpage.nix @@ -6,7 +6,7 @@ }: { # Only install skanpage if scanning is set up config = lib.mkIf config.hardware.sane.enable { - environment.systemPackages = [pkgs.skanpage]; + environment.systemPackages = [pkgs.kdePackages.skanpage]; }; # environment.systemPackages = if config.hardware.sane.enable == true then [ pkgs.skanpage ] else []; } From cbbef2a3a631b20d222cee63681610f4246182d5 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 3 Mar 2025 18:07:55 +0100 Subject: [PATCH 0934/1125] Flake: update lock file --- flake.lock | 76 +++++++++++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/flake.lock b/flake.lock index 57afc98..44e891c 100644 --- a/flake.lock +++ b/flake.lock @@ -188,11 +188,11 @@ ] }, "locked": { - "lastModified": 1739913864, - "narHash": "sha256-WhzgQjadrwnwPJQLLxZUUEIxojxa7UWDkf7raAkB1Lw=", + "lastModified": 1740845322, + "narHash": "sha256-AXEgFj3C0YJhu9k1OhbRhiA6FnDr81dQZ65U3DhaWpw=", "owner": "nix-community", "repo": "home-manager", - "rev": "97ac0801d187b2911e8caa45316399de12f6f199", + "rev": "fcac3d6d88302a5e64f6cb8014ac785e08874c8d", "type": "github" }, "original": { @@ -230,11 +230,11 @@ ] }, "locked": { - "lastModified": 1739952453, - "narHash": "sha256-+tyFW6nNj1fJ1VTtLeqe1PMp5F7Fb9zIkT6mUvdQHrM=", + "lastModified": 1740892961, + "narHash": "sha256-RpuRrwn4Iu3ColOUfQJITSB3Pu8p979zELXv1zihWwU=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "b2ed82d3ff837960df4518308dfe409dda3ae406", + "rev": "483fc372ebcc522ef0226bf5a211942203edda90", "type": "github" }, "original": { @@ -246,11 +246,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1739940699, - "narHash": "sha256-9jlwrVWXzqdEEl611VE+fMnBLKzRFoONJYHUQeeKM0Q=", - "rev": "df336747e6d9fdd36330ca4105fa30232b23a202", + "lastModified": 1740991434, + "narHash": "sha256-9N14m5KRYEUV3nRHNO1myMR/2J/seFj37biiMHqujEk=", + "rev": "18975fa016fbe6c13525d6a833b22bb55703fffb", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/df336747e6d9fdd36330ca4105fa30232b23a202.tar.gz?rev=df336747e6d9fdd36330ca4105fa30232b23a202" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/18975fa016fbe6c13525d6a833b22bb55703fffb.tar.gz?rev=18975fa016fbe6c13525d6a833b22bb55703fffb" }, "original": { "type": "tarball", @@ -363,11 +363,11 @@ ] }, "locked": { - "lastModified": 1739676768, - "narHash": "sha256-U1HQ7nzhJyVVXUgjU028UCkbLQLEIkg42+G7iIiBmlU=", + "lastModified": 1740886574, + "narHash": "sha256-jN6kJ41B6jUVDTebIWeebTvrKP6YiLd1/wMej4uq4Sk=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "ae15068e79e22b76c344f0d7f8aed1bb1c5b0b63", + "rev": "26a0f969549cf4d56f6e9046b9e0418b3f3b94a5", "type": "github" }, "original": { @@ -383,11 +383,11 @@ ] }, "locked": { - "lastModified": 1739676768, - "narHash": "sha256-U1HQ7nzhJyVVXUgjU028UCkbLQLEIkg42+G7iIiBmlU=", + "lastModified": 1740886574, + "narHash": "sha256-jN6kJ41B6jUVDTebIWeebTvrKP6YiLd1/wMej4uq4Sk=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "ae15068e79e22b76c344f0d7f8aed1bb1c5b0b63", + "rev": "26a0f969549cf4d56f6e9046b9e0418b3f3b94a5", "type": "github" }, "original": { @@ -398,11 +398,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1739798439, - "narHash": "sha256-GyipmjbbQEaosel/+wq1xihCKbv0/e1LU00x/8b/fP4=", + "lastModified": 1740646007, + "narHash": "sha256-dMReDQobS3kqoiUCQIYI9c0imPXRZnBubX20yX/G5LE=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "3e2ea8a49d4d76276b0f4e2041df8ca5c0771371", + "rev": "009b764ac98a3602d41fc68072eeec5d24fc0e49", "type": "github" }, "original": { @@ -430,11 +430,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1739758141, - "narHash": "sha256-uq6A2L7o1/tR6VfmYhZWoVAwb3gTy7j4Jx30MIrH0rE=", + "lastModified": 1740865531, + "narHash": "sha256-h00vGIh/jxcGl8aWdfnVRD74KuLpyY3mZgMFMy7iKIc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c618e28f70257593de75a7044438efc1c1fc0791", + "rev": "5ef6c425980847c78a80d759abc476e941a9bf42", "type": "github" }, "original": { @@ -445,11 +445,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1739866667, - "narHash": "sha256-EO1ygNKZlsAC9avfcwHkKGMsmipUk1Uc0TbrEZpkn64=", + "lastModified": 1740828860, + "narHash": "sha256-cjbHI+zUzK5CPsQZqMhE3npTyYFt9tJ3+ohcfaOF/WM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "73cf49b8ad837ade2de76f87eb53fc85ed5d4680", + "rev": "303bd8071377433a2d8f76e684ec773d70c5b642", "type": "github" }, "original": { @@ -460,11 +460,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1739736696, - "narHash": "sha256-zON2GNBkzsIyALlOCFiEBcIjI4w38GYOb+P+R4S8Jsw=", + "lastModified": 1740828860, + "narHash": "sha256-cjbHI+zUzK5CPsQZqMhE3npTyYFt9tJ3+ohcfaOF/WM=", "owner": "nixos", "repo": "nixpkgs", - "rev": "d74a2335ac9c133d6bbec9fc98d91a77f1604c1f", + "rev": "303bd8071377433a2d8f76e684ec773d70c5b642", "type": "github" }, "original": { @@ -493,11 +493,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1739903703, - "narHash": "sha256-w2tTcjx39lJoPDaFbIxi+INIjAKE0jbIx9TNjj9ghmg=", + "lastModified": 1741014528, + "narHash": "sha256-Nez5gUmX8wX1fxZXgiuzIe4wEtmkzRNM9/zIts6hyfQ=", "owner": "nix-community", "repo": "NUR", - "rev": "2215ad5c4347f522523715e809f5f2022509f504", + "rev": "e5b6c67aaac0b58a91fe25b0497f9377f5945f34", "type": "github" }, "original": { @@ -516,11 +516,11 @@ ] }, "locked": { - "lastModified": 1739557722, - "narHash": "sha256-XikzLpPUDYiNyJ4w2SfRShdbSkIgE3btYdxCGInmtc4=", + "lastModified": 1740569341, + "narHash": "sha256-WV8nY2IOfWdzBF5syVgCcgOchg/qQtpYh6LECYS9XkY=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "1f3e1f38dedbbb8aad77e184fb54ec518e2d9522", + "rev": "5eeb0172fb74392053b66a8149e61b5e191b2845", "type": "github" }, "original": { @@ -576,11 +576,11 @@ "utils": "utils" }, "locked": { - "lastModified": 1738967312, - "narHash": "sha256-U8p5la0UDcrwYM7+DYWeFUcCjKIePQMXWV3nT9UaPvQ=", + "lastModified": 1740160663, + "narHash": "sha256-cRD5boGthyiecpL/jzSVaeoLG27Ve2gEVhZFhC5rjHQ=", "ref": "refs/heads/main", - "rev": "72e0b07f71445b6f16942b2db1bd888ed587879b", - "revCount": 46, + "rev": "b4fdee776aa7aa2ae6648070cad449a6c88c65c5", + "revCount": 50, "type": "git", "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/shows-api.git" }, From 68ea0f03f22a44d1f679ef214870c3d8b0d4df76 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 3 Mar 2025 18:08:06 +0100 Subject: [PATCH 0935/1125] Flake: remove unneeded patch --- flake.nix | 1 - nixpkgs_patches/pr383269.patch | 22 ---------------------- 2 files changed, 23 deletions(-) delete mode 100644 nixpkgs_patches/pr383269.patch diff --git a/flake.nix b/flake.nix index 1c6311a..43f805a 100644 --- a/flake.nix +++ b/flake.nix @@ -101,7 +101,6 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs_patches/pr383269.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs_patches/pr383269.patch b/nixpkgs_patches/pr383269.patch deleted file mode 100644 index 414f921..0000000 --- a/nixpkgs_patches/pr383269.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 39dd19122fdabf519c256796df0ed998515990a6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= -Date: Wed, 19 Feb 2025 14:33:33 +0700 -Subject: [PATCH] install-grub: add missing rmtree - ---- - nixos/modules/system/boot/loader/grub/install-grub.pl | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl -index 4a588a75da147..f5ae844da21f9 100644 ---- a/nixos/modules/system/boot/loader/grub/install-grub.pl -+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl -@@ -3,7 +3,7 @@ - use Class::Struct; - use XML::LibXML; - use File::Basename; --use File::Path qw(make_path); -+use File::Path qw(make_path rmtree); - use File::stat; - use File::Copy; - use File::Copy::Recursive qw(rcopy pathrm); From a483112a32288eaa886d1cf16b34f51d42e6a74c Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 2 Mar 2025 20:00:18 +0100 Subject: [PATCH 0936/1125] Server/transmission: upgrade to transmission 4 --- roles/server/transmission.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/server/transmission.nix b/roles/server/transmission.nix index 2ce8b06..a6e7e3c 100755 --- a/roles/server/transmission.nix +++ b/roles/server/transmission.nix @@ -1,4 +1,4 @@ -{config, ...}: let +{config, pkgs, ...}: let transmissionUid = toString config.users.users.transmission.uid; transmissionGid = toString config.users.groups.transmission.gid; mountPoint = config.fileSystems."nfs_transmission".mountPoint; @@ -6,6 +6,7 @@ in { services.transmission = { enable = true; openFirewall = true; + package = pkgs.transmission_4; settings = { incomplete-dir-enabled = false; rpc-bind-address = "0.0.0.0"; From da57debd66fe92b181ad8b05593feb3edd5b2e58 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 3 Mar 2025 20:34:33 +0100 Subject: [PATCH 0937/1125] Kde: load patches automatically --- roles/kde/default.nix | 1 + roles/kde/patches/default.nix | 30 ++++++++++++++++++++++++++++++ roles/kde/programs/konsole.nix | 13 ------------- 3 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 roles/kde/patches/default.nix diff --git a/roles/kde/default.nix b/roles/kde/default.nix index 363920a..f80328a 100755 --- a/roles/kde/default.nix +++ b/roles/kde/default.nix @@ -3,5 +3,6 @@ ./plasma.nix ./sddm.nix ./programs + ./patches ]; } diff --git a/roles/kde/patches/default.nix b/roles/kde/patches/default.nix new file mode 100644 index 0000000..1e14271 --- /dev/null +++ b/roles/kde/patches/default.nix @@ -0,0 +1,30 @@ +{lib, ...}: let + rootDirs = builtins.readDir ./.; + removeFiles = lib.attrsets.filterAttrs (n: v: v == "directory") rootDirs; + + getPatches = name: + builtins.map (value: ./${name}/${value}) (builtins.attrNames ( + lib.attrsets.filterAttrs ( + n: v: + v == "regular" && lib.strings.hasSuffix ".patch" n + ) (builtins.readDir ./${name}) + )); + + bigOverlay = final: prev: + builtins.mapAttrs ( + name: _value: + prev."${name}".overrideAttrs { + version = prev."${name}".version + "-patched"; + patches = prev."${name}".patches ++ getPatches name; + } + ) + removeFiles; +in { + nixpkgs.overlays = [ + ( + final: prev: { + kdePackages = prev.kdePackages.overrideScope bigOverlay; + } + ) + ]; +} diff --git a/roles/kde/programs/konsole.nix b/roles/kde/programs/konsole.nix index 25040e8..ef3b429 100644 --- a/roles/kde/programs/konsole.nix +++ b/roles/kde/programs/konsole.nix @@ -16,17 +16,4 @@ in { }; }; }; - nixpkgs.overlays = [ - ( - final: prev: { - kdePackages = prev.kdePackages.overrideScope ( - kFinal: kPrev: { - konsole = kPrev.konsole.overrideAttrs { - patches = []; - }; - } - ); - } - ) - ]; } From f3ee33177f38cfb2d76ec5fcc81b220b32625325 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Mar 2025 14:27:20 +0100 Subject: [PATCH 0938/1125] Kde: fix qt wayland --- roles/kde/plasma.nix | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 00c4099..728b560 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -37,6 +37,34 @@ in { # Enable the Plasma 6 Desktop Environment services.desktopManager.plasma6.enable = true; + # Same as https://github.com/NixOS/nixpkgs/pull/386932 + nixpkgs.overlays = [ + ( + final: prev: { + kdePackages = prev.kdePackages.overrideScope ( + kFinal: kPrev: { + qtbase-vulkan = kPrev.qtbase.overrideAttrs { + postFixup = '' + moveToOutput "mkspecs/modules" "$dev" + fixQtModulePaths "$dev/mkspecs/modules" + fixQtBuiltinPaths "$out" '*.pr?' + patchelf --add-rpath "${final.libmysqlclient}/lib/mariadb" $out/lib/qt-6/plugins/sqldrivers/libqsqlmysql.so + patchelf --add-rpath "${final.vulkan-loader}/lib" --add-needed "libvulkan.so" $out/lib/libQt6Gui.so + ''; + }; + } + ); + } + ) + ]; + + system.replaceDependencies.replacements = with pkgs.kdePackages; [ + { + oldDependency = qtbase; + newDependency = qtbase-vulkan; + } + ]; + qt.enable = true; # GTK apps need dconf to grab the correct theme on Wayland From 92a6c20c18ed1419741d3eff4faa350fbcefca97 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Mar 2025 14:31:15 +0100 Subject: [PATCH 0939/1125] Kde: add kinfocenter patches --- roles/kde/patches/kinfocenter/00-pr238.patch | 72 ++++ roles/kde/patches/kinfocenter/pr234.patch | 426 +++++++++++++++++++ 2 files changed, 498 insertions(+) create mode 100644 roles/kde/patches/kinfocenter/00-pr238.patch create mode 100644 roles/kde/patches/kinfocenter/pr234.patch diff --git a/roles/kde/patches/kinfocenter/00-pr238.patch b/roles/kde/patches/kinfocenter/00-pr238.patch new file mode 100644 index 0000000..a199e2b --- /dev/null +++ b/roles/kde/patches/kinfocenter/00-pr238.patch @@ -0,0 +1,72 @@ +From 7cc7fe9783a68e086369bd0b96b280082097d60a Mon Sep 17 00:00:00 2001 +From: Oliver Beard +Date: Thu, 20 Feb 2025 22:49:25 +0000 +Subject: [PATCH] kcms/about-distro: Fix hint expanding height of parent layout + Instead, use an label with padding to match the height of normal text. A + background is used to fill this padded area. + +If smallFont is larger than normal text, the text will draw outside the label which would be restricted to the same height as normal text by negative padding. I don't see this as worth fixing - if the small font is larger than normal text, that would be the problem, not this... + +When valueLabel spans multiple lines, it will be vertically centered. + +CCBUG: 500355 +--- + kcms/about-distro/src/ui/main.qml | 35 +++++++++++++++++++------------ + 1 file changed, 22 insertions(+), 13 deletions(-) + +diff --git a/kcms/about-distro/src/ui/main.qml b/kcms/about-distro/src/ui/main.qml +index 7a3f72bfb..80fbc2c13 100644 +--- a/kcms/about-distro/src/ui/main.qml ++++ b/kcms/about-distro/src/ui/main.qml +@@ -136,26 +136,35 @@ KCMUtils.SimpleKCM { + } + } + +- QQC2.Control { ++ QQC2.Label { ++ Kirigami.Theme.colorSet: Kirigami.Theme.Window + visible: hint !== "" +- topPadding: Kirigami.Units.smallSpacing +- rightPadding: Kirigami.Units.smallSpacing +- bottomPadding: Kirigami.Units.smallSpacing +- leftPadding: Kirigami.Units.smallSpacing + +- Kirigami.Theme.colorSet: Kirigami.Theme.Window ++ // Vertical padding accounts for the difference in normal label height and the content height of this small label ++ readonly property real verticalPadding: (hintMetrics.height - contentHeight) / 2 ++ // Horizontal padding also accounts for the difference in content height and the font's pixelSize to better balance the text ++ readonly property real horizontalPadding: ((hintMetrics.height - contentHeight) + (contentHeight - font.pixelSize)) / 2 ++ ++ TextMetrics { ++ // Necessary as valueLabel could be multiple lines ++ id: hintMetrics ++ text: " " ++ } ++ ++ topPadding: verticalPadding ++ bottomPadding: verticalPadding ++ leftPadding: horizontalPadding ++ rightPadding: horizontalPadding ++ ++ text: hint ++ color: hintColorForeground ++ font.bold: true ++ font.pixelSize: Kirigami.Theme.smallFont.pixelSize + + background: Rectangle { + color: hintColorBackground + radius: Kirigami.Units.cornerRadius + } +- +- contentItem: QQC2.Label { +- text: hint +- color: hintColorForeground +- font.bold: true +- font.pixelSize: Kirigami.Theme.smallFont.pixelSize +- } + } + + QQC2.Button { +-- +GitLab + diff --git a/roles/kde/patches/kinfocenter/pr234.patch b/roles/kde/patches/kinfocenter/pr234.patch new file mode 100644 index 0000000..e683a76 --- /dev/null +++ b/roles/kde/patches/kinfocenter/pr234.patch @@ -0,0 +1,426 @@ +From f44af69b07ed19d076819fe4cc84e5777747d957 Mon Sep 17 00:00:00 2001 +From: Oliver Beard +Date: Thu, 20 Feb 2025 22:43:47 +0000 +Subject: [PATCH 1/2] kcms/about-distro: Add help property to Entry & show + total amount of installed memory in MemoryEntry This provides additional + information to the user, with a new help tooltip that clarifies the displayed + values as is contextually appropriate. For example, if the shown message is + "32 GB of RAM (31.3 GB usable)", the tooltip will elucidate that some memory + is reserved for use by system hardware. BUG: 500412 + +--- + CMakeLists.txt | 4 + + kcms/about-distro/src/CMakeLists.txt | 5 + + kcms/about-distro/src/Entry.cpp | 5 + + kcms/about-distro/src/Entry.h | 3 + + kcms/about-distro/src/MemoryEntry.cpp | 144 +++++++++++++++++++++++--- + kcms/about-distro/src/MemoryEntry.h | 9 +- + kcms/about-distro/src/ui/main.qml | 5 + + 7 files changed, 157 insertions(+), 18 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 51f940789..e3005878a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -41,6 +41,10 @@ find_package(KF6 ${KF6_MIN_VERSION} REQUIRED COMPONENTS + find_package(PkgConfig) + pkg_check_modules(libdrm REQUIRED IMPORTED_TARGET libdrm) + ++if(CMAKE_SYSTEM_NAME MATCHES "Linux") ++ find_package(UDev REQUIRED COMPONENTS UDev) ++endif() ++ + ecm_find_qmlmodule(org.kde.kirigami 2.5) + + macro(kinfocenter_add_kcm target) +diff --git a/kcms/about-distro/src/CMakeLists.txt b/kcms/about-distro/src/CMakeLists.txt +index 13ad8d0af..d731d81a1 100644 +--- a/kcms/about-distro/src/CMakeLists.txt ++++ b/kcms/about-distro/src/CMakeLists.txt +@@ -43,6 +43,11 @@ target_link_libraries(kcm_about-distro PRIVATE + PkgConfig::libdrm + ) + ++if(UDev_FOUND) ++ target_link_libraries(kcm_about-distro PRIVATE UDev::UDev) ++ target_compile_definitions(kcm_about-distro PRIVATE UDEV_FOUND) ++endif() ++ + cmake_path(RELATIVE_PATH KDE_INSTALL_FULL_LIBEXECDIR BASE_DIRECTORY "${KDE_INSTALL_FULL_PLUGINDIR}/plasma/kcms/" OUTPUT_VARIABLE LIBEXECDIR_FROM_KCM) + + target_compile_options( +diff --git a/kcms/about-distro/src/Entry.cpp b/kcms/about-distro/src/Entry.cpp +index a4077efda..63dc71fbb 100644 +--- a/kcms/about-distro/src/Entry.cpp ++++ b/kcms/about-distro/src/Entry.cpp +@@ -82,4 +82,9 @@ Hint Entry::localizedHint(Language) const + return {}; + } + ++QString Entry::localizedHelp(Language) const ++{ ++ return {}; ++} ++ + #include "moc_Entry.cpp" +diff --git a/kcms/about-distro/src/Entry.h b/kcms/about-distro/src/Entry.h +index e5c3f6f17..bc053a4f4 100644 +--- a/kcms/about-distro/src/Entry.h ++++ b/kcms/about-distro/src/Entry.h +@@ -78,6 +78,9 @@ public: + // Returns a hint for the user to consider when interpreting the value. + Q_INVOKABLE [[nodiscard]] virtual Hint localizedHint(Language language = Language::System) const; + ++ // Returns a help string for the entry, shown with a ContextualHelpButton ++ Q_SCRIPTABLE [[nodiscard]] virtual QString localizedHelp(Language language = Language::System) const; ++ + protected: + // Returns localized QString for the given language. + QString localize(const KLocalizedString &string, Language language) const; +diff --git a/kcms/about-distro/src/MemoryEntry.cpp b/kcms/about-distro/src/MemoryEntry.cpp +index 1baaea2ac..b58b55237 100644 +--- a/kcms/about-distro/src/MemoryEntry.cpp ++++ b/kcms/about-distro/src/MemoryEntry.cpp +@@ -9,6 +9,9 @@ + + #ifdef Q_OS_LINUX + #include ++#ifdef UDEV_FOUND ++#include ++#endif + #elif defined(Q_OS_FREEBSD) + // clang-format off + #include +@@ -21,34 +24,141 @@ MemoryEntry::MemoryEntry() + { + } + +-qlonglong MemoryEntry::calculateTotalRam() ++std::optional MemoryEntry::calculateTotalRam() ++{ ++#if defined(Q_OS_LINUX) && defined(UDEV_FOUND) ++ std::unique_ptr udev(udev_new(), &udev_unref); ++ if (!udev) { ++ return {}; ++ } ++ ++ std::unique_ptr dmi(udev_device_new_from_syspath(udev.get(), "/sys/class/dmi/id/"), &udev_device_unref); ++ if (!dmi) { ++ return {}; ++ } ++ ++ const char *numMemoryDevicesCStr = udev_device_get_property_value(dmi.get(), "MEMORY_ARRAY_NUM_DEVICES"); ++ if (!numMemoryDevicesCStr) { ++ return {}; ++ } ++ ++ bool ok; ++ int numMemoryDevices = QByteArray(numMemoryDevicesCStr).toInt(&ok); ++ if (!ok) { ++ return {}; ++ } ++ ++ qlonglong totalBytes = 0; ++ for (int i = 0; i < numMemoryDevices; ++i) { ++ const char *memoryBytesCStr = udev_device_get_property_value(dmi.get(), QStringLiteral("MEMORY_DEVICE_%1_SIZE").arg(i).toLatin1()); ++ qlonglong memoryBytes = QByteArray(memoryBytesCStr).toLongLong(&ok); ++ if (ok) { ++ totalBytes += memoryBytes; ++ } ++ } ++ ++ return totalBytes; ++#endif ++ ++ /* ++ * TODO: A FreeBSD impl is likely possible, but it appears that ++ * sysctlbyname() cannot get what we want with either "hw.physmem", ++ * "hw.usermem" or "hw.realmem". ++ * On a system with 2 x 4 GiB memory modules installed, we would need ++ * to return a value of 8 GiB in bytes. ++ */ ++ ++ return {}; ++} ++ ++std::optional MemoryEntry::calculateAvailableRam() + { +- qlonglong ret = -1; + #ifdef Q_OS_LINUX + struct sysinfo info; +- if (sysinfo(&info) == 0) +- // manpage "sizes are given as multiples of mem_unit bytes" +- ret = qlonglong(info.totalram) * info.mem_unit; ++ if (sysinfo(&info) == 0) { ++ // manpage: "sizes are given as multiples of mem_unit bytes" ++ return qlonglong(info.totalram) * info.mem_unit; ++ } + #elif defined(Q_OS_FREEBSD) + /* Stuff for sysctl */ +- size_t len; +- + unsigned long memory; +- len = sizeof(memory); +- sysctlbyname("hw.physmem", &memory, &len, NULL, 0); +- +- ret = memory; ++ size_t len = sizeof(memory); ++ if (sysctlbyname("hw.physmem", &memory, &len, NULL, 0) == 0) { ++ return memory; ++ } + #endif +- return ret; ++ ++ return {}; + } + + QString MemoryEntry::localizedValue(Language language) const + { +- const qlonglong totalRam = calculateTotalRam(); +- if (totalRam > 0) { +- const auto string = ki18nc("@label %1 is the formatted amount of system memory (e.g. 7,7 GiB)", "%1 of RAM") +- .subs(KFormat(localeForLanguage(language)).formatByteSize(totalRam)); ++ auto precisionForGiB = [](std::optional bytes) -> int { ++ if (!bytes.has_value()) { ++ return 0; ++ } ++ ++ constexpr qlonglong GiB = 1024 * 1024 * 1024; ++ return (bytes.value() % GiB == 0) ? 0 : 1; ++ }; ++ ++ const int totalRamPrecision = precisionForGiB(m_totalRam); ++ const int availableRamPrecision = precisionForGiB(m_availableRam); ++ ++ if (m_totalRam.has_value() && m_availableRam.has_value()) { ++ // Both known ++ const auto string = ki18nc("@label, %1 is the total amount of installed system memory, %2 is the amount of which is usable, both expressed as 7.7 GiB", ++ "%1 of RAM (%2 usable)") ++ .subs(KFormat(localeForLanguage(language)).formatByteSize(m_totalRam.value(), totalRamPrecision)) ++ .subs(KFormat(localeForLanguage(language)).formatByteSize(m_availableRam.value(), availableRamPrecision)); ++ return localize(string, language); ++ } ++ ++ if (m_totalRam.has_value() && !m_availableRam.has_value()) { ++ // Known total, unknown available ++ const auto string = ki18nc("@label, %1 is the amount of installed system memory expressed as 7.7 GiB", "%1 of RAM") ++ .subs(KFormat(localeForLanguage(language)).formatByteSize(m_totalRam.value(), totalRamPrecision)); ++ return localize(string, language); ++ } ++ ++ if (!m_totalRam.has_value() && m_availableRam.has_value()) { ++ // Unknown total, known available ++ const auto string = ki18nc("@label, %1 is the amount of usable system memory expressed as 7.7 GiB", "%1 of usable RAM") ++ .subs(KFormat(localeForLanguage(language)).formatByteSize(m_availableRam.value(), availableRamPrecision)); + return localize(string, language); + } +- return localize(ki18nc("Unknown amount of RAM", "Unknown"), language); ++ ++ // Both unknown ++ return localize(ki18nc("@label, Unknown amount of system memory", "Unknown"), language); ++} ++ ++QString MemoryEntry::localizedHelp(Language language) const ++{ ++ if (m_totalRam.has_value() && m_availableRam.has_value()) { ++ // Both known ++ return localize(ki18nc("@info:tooltip, referring to system memory or RAM", ++ "Some memory is reserved for use by the kernel or system hardware such as integrated graphics memory."), ++ language); ++ } ++ ++ if (m_totalRam.has_value() && !m_availableRam.has_value()) { ++ // Known total, unknown available ++ return localize( ++ ki18nc("@info:tooltip, referring to system memory or RAM", ++ "The amount of usable memory may be lower than the displayed amount because some memory is reserved for use by the kernel or system " ++ "hardware, such as integrated graphics memory."), ++ language); ++ } ++ ++ if (!m_totalRam.has_value() && m_availableRam.has_value()) { ++ // Unknown total, known available ++ return localize( ++ ki18nc("@info:tooltip, referring to system memory or RAM", ++ "The amount of memory displayed may be lower than the installed amount because some memory is reserved for use by the kernel or system " ++ "hardware, such as integrated graphics memory."), ++ language); ++ } ++ ++ // Both unknown ++ return QString(); + } +diff --git a/kcms/about-distro/src/MemoryEntry.h b/kcms/about-distro/src/MemoryEntry.h +index 43beb2e87..d0757651f 100644 +--- a/kcms/about-distro/src/MemoryEntry.h ++++ b/kcms/about-distro/src/MemoryEntry.h +@@ -12,10 +12,17 @@ class MemoryEntry : public Entry + { + public: + MemoryEntry(); +- static qlonglong calculateTotalRam(); + + // Overwrite to get correct localization for the value. + QString localizedValue(Language language = Language::System) const final; ++ QString localizedHelp(Language language = Language::System) const final; ++ ++private: ++ static std::optional calculateTotalRam(); ++ static std::optional calculateAvailableRam(); ++ ++ std::optional m_totalRam = calculateTotalRam(); ++ std::optional m_availableRam = calculateAvailableRam(); + }; + + #endif // MEMORYENTRY_H +diff --git a/kcms/about-distro/src/ui/main.qml b/kcms/about-distro/src/ui/main.qml +index 80fbc2c13..e80b7fe93 100644 +--- a/kcms/about-distro/src/ui/main.qml ++++ b/kcms/about-distro/src/ui/main.qml +@@ -167,6 +167,11 @@ KCMUtils.SimpleKCM { + } + } + ++ Kirigami.ContextualHelpButton { ++ visible: toolTipText.length > 0 ++ toolTipText: entry.localizedHelp() ++ } ++ + QQC2.Button { + visible: hidden + property var dialog: null +-- +GitLab + + +From fc2e540dc6f4784c2602a520f4b3285355213f5a Mon Sep 17 00:00:00 2001 +From: Oliver Beard +Date: Mon, 24 Feb 2025 23:17:48 +0000 +Subject: [PATCH 2/2] kcms/about-distro: Clean-up and refactoring - Spacing + specified on RowLayout - Instead of specifying properties up-front for each + entry, entries use them as needed. - Use .length > 0 instead of !== "" - + [[nodiscard]] and Q_INVOKABLE specified on virtual Entry methods + +--- + kcms/about-distro/src/Entry.h | 8 +++--- + kcms/about-distro/src/ui/main.qml | 42 +++++++++++++++---------------- + 2 files changed, 25 insertions(+), 25 deletions(-) + +diff --git a/kcms/about-distro/src/Entry.h b/kcms/about-distro/src/Entry.h +index bc053a4f4..3c7dd8491 100644 +--- a/kcms/about-distro/src/Entry.h ++++ b/kcms/about-distro/src/Entry.h +@@ -66,20 +66,20 @@ public: + // Returns textual representation of entry. + QString diagnosticLine(Language language = Language::System) const; + +- Q_SCRIPTABLE virtual QString localizedLabel(Language language = Language::System) const; ++ Q_INVOKABLE [[nodiscard]] virtual QString localizedLabel(Language language = Language::System) const; + + // Returns the value by default. Needs to be overridden in subclasses if localization + // is needed for the value. +- Q_SCRIPTABLE virtual QString localizedValue(Language language = Language::System) const; ++ Q_INVOKABLE [[nodiscard]] virtual QString localizedValue(Language language = Language::System) const; + + // Returns whether this Entry should be hidden by default (i.e. only shown upon user request) +- Q_INVOKABLE virtual bool isHidden() const; ++ Q_INVOKABLE [[nodiscard]] virtual bool isHidden() const; + + // Returns a hint for the user to consider when interpreting the value. + Q_INVOKABLE [[nodiscard]] virtual Hint localizedHint(Language language = Language::System) const; + + // Returns a help string for the entry, shown with a ContextualHelpButton +- Q_SCRIPTABLE [[nodiscard]] virtual QString localizedHelp(Language language = Language::System) const; ++ Q_INVOKABLE [[nodiscard]] virtual QString localizedHelp(Language language = Language::System) const; + + protected: + // Returns localized QString for the given language. +diff --git a/kcms/about-distro/src/ui/main.qml b/kcms/about-distro/src/ui/main.qml +index e80b7fe93..547f4b665 100644 +--- a/kcms/about-distro/src/ui/main.qml ++++ b/kcms/about-distro/src/ui/main.qml +@@ -54,14 +54,14 @@ KCMUtils.SimpleKCM { + } + + Kirigami.Heading { +- visible: kcm.distroVariant !== "" ++ visible: kcm.distroVariant.length > 0 + text: kcm.distroVariant + level: 2 + type: Kirigami.Heading.Type.Secondary + } + + QQC2.Label { +- visible: kcm.distroUrl !== "" ++ visible: kcm.distroUrl.length > 0 + text: "%1".arg(kcm.distroUrl) + textFormat: Text.RichText + onLinkActivated: link => Qt.openUrlExternally(link) +@@ -82,23 +82,11 @@ KCMUtils.SimpleKCM { + Kirigami.FormData.label: entry.localizedLabel() + Kirigami.FormData.labelAlignment: idealAlignment + Layout.alignment: idealAlignment ++ + readonly property int idealAlignment: valueLabel.lineCount > 1 ? Qt.AlignTop : Qt.AlignVCenter // looks tidier this way + readonly property bool hidden: entry.isHidden() +- readonly property string hint: entry.localizedHint().text +- readonly property color hintColorForeground: { +- switch (entry.localizedHint().color) { +- case Private.Hint.Color.One: return Kirigami.Theme.linkColor +- case Private.Hint.Color.Two: return Kirigami.Theme.positiveTextColor +- case Private.Hint.Color.Three: return Kirigami.Theme.alternateTextColor +- } +- } +- readonly property color hintColorBackground: { +- switch (entry.localizedHint().color) { +- case Private.Hint.Color.One: return Kirigami.Theme.linkBackgroundColor +- case Private.Hint.Color.Two: return Kirigami.Theme.positiveBackgroundColor +- case Private.Hint.Color.Three: return Kirigami.Theme.alternateBackgroundColor +- } +- } ++ ++ spacing: Kirigami.Units.smallSpacing + + Component { + id: unhideDialog +@@ -138,7 +126,7 @@ KCMUtils.SimpleKCM { + + QQC2.Label { + Kirigami.Theme.colorSet: Kirigami.Theme.Window +- visible: hint !== "" ++ visible: text.length > 0 + + // Vertical padding accounts for the difference in normal label height and the content height of this small label + readonly property real verticalPadding: (hintMetrics.height - contentHeight) / 2 +@@ -156,13 +144,25 @@ KCMUtils.SimpleKCM { + leftPadding: horizontalPadding + rightPadding: horizontalPadding + +- text: hint +- color: hintColorForeground ++ text: entry.localizedHint().text ++ color: { ++ switch (entry.localizedHint().color) { ++ case Private.Hint.Color.One: return Kirigami.Theme.linkColor ++ case Private.Hint.Color.Two: return Kirigami.Theme.positiveTextColor ++ case Private.Hint.Color.Three: return Kirigami.Theme.alternateTextColor ++ } ++ } + font.bold: true + font.pixelSize: Kirigami.Theme.smallFont.pixelSize + + background: Rectangle { +- color: hintColorBackground ++ color: { ++ switch (entry.localizedHint().color) { ++ case Private.Hint.Color.One: return Kirigami.Theme.linkBackgroundColor ++ case Private.Hint.Color.Two: return Kirigami.Theme.positiveBackgroundColor ++ case Private.Hint.Color.Three: return Kirigami.Theme.alternateBackgroundColor ++ } ++ } + radius: Kirigami.Units.cornerRadius + } + } +-- +GitLab + From a7545faa4542502d09ea69550635c60b112603a0 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 4 Mar 2025 21:07:55 +0100 Subject: [PATCH 0940/1125] Kde: add spectacle patch --- roles/kde/patches/spectacle/pr431.patch | 3393 +++++++++++++++++++++++ 1 file changed, 3393 insertions(+) create mode 100644 roles/kde/patches/spectacle/pr431.patch diff --git a/roles/kde/patches/spectacle/pr431.patch b/roles/kde/patches/spectacle/pr431.patch new file mode 100644 index 0000000..aef0059 --- /dev/null +++ b/roles/kde/patches/spectacle/pr431.patch @@ -0,0 +1,3393 @@ +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index c95d17e9..8a6994f8 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -37,6 +37,8 @@ target_sources(spectacle PRIVATE + Gui/ExportMenu.cpp + Gui/HelpMenu.cpp + Gui/OptionsMenu.cpp ++ Gui/RecordingModeMenu.cpp ++ Gui/ScreenshotModeMenu.cpp + Gui/SmartSpinBox.cpp + Gui/Selection.cpp + Gui/SelectionEditor.cpp +@@ -147,6 +149,7 @@ set_source_files_properties(Gui/QmlUtils.qml PROPERTIES + + qt_target_qml_sources(spectacle + QML_FILES ++ Gui/AcceptAction.qml + Gui/AnimatedLoader.qml + Gui/AnnotationOptionsToolBarContents.qml + Gui/Annotations/AnnotationEditor.qml +@@ -160,38 +163,49 @@ qt_target_qml_sources(spectacle + Gui/CaptureOptions.qml + Gui/CaptureSettingsColumn.qml + Gui/CopiedMessage.qml ++ Gui/CopyImageAction.qml ++ Gui/CopyLocationAction.qml + Gui/DashedOutline.qml + Gui/DelaySpinBox.qml + Gui/DialogPage.qml ++ Gui/EditAction.qml + Gui/EmptyPage.qml ++ Gui/ExportMenuButton.qml + Gui/FloatingBackground.qml + Gui/FloatingToolBar.qml + Gui/Handle.qml ++ Gui/HelpMenuButton.qml + Gui/ImageCaptureOverlay.qml + Gui/ImageView.qml + Gui/InlineMessage.qml + Gui/LocationCopiedMessage.qml + Gui/Magnifier.qml +- Gui/MainToolBarContents.qml ++ Gui/NewScreenshotToolButton.qml ++ Gui/OptionsMenuButton.qml + Gui/Outline.qml + Gui/QRCodeScannedMessage.qml + Gui/QmlUtils.qml ++ Gui/RecordAction.qml + Gui/RecordOptions.qml + Gui/RecordingFailedMessage.qml + Gui/RecordingModeButtonsColumn.qml ++ Gui/RecordingModeMenuButton.qml + Gui/RecordingSettingsColumn.qml + Gui/RecordingView.qml ++ Gui/SaveAction.qml ++ Gui/SaveAsAction.qml + Gui/SavedAndCopiedMessage.qml + Gui/SavedAndLocationCopied.qml + Gui/SavedMessage.qml + Gui/ScreenshotFailedMessage.qml ++ Gui/ScreenshotModeMenuButton.qml + Gui/ScreenshotView.qml + Gui/ShareErrorMessage.qml + Gui/SharedMessage.qml + Gui/ShortcutsTextBox.qml + Gui/SizeLabel.qml ++ Gui/TtToolButton.qml + Gui/UndoRedoGroup.qml +- Gui/VideoCaptureOverlay.qml + ) + + install(TARGETS spectacle ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) +diff --git a/src/CaptureModeModel.cpp b/src/CaptureModeModel.cpp +index 1b7720dc..2037b97f 100644 +--- a/src/CaptureModeModel.cpp ++++ b/src/CaptureModeModel.cpp +@@ -15,6 +15,16 @@ + + using namespace Qt::StringLiterals; + ++static std::unique_ptr s_instance; ++ ++CaptureModeModel *CaptureModeModel::instance() ++{ ++ if (!s_instance) { ++ s_instance = std::make_unique(); ++ } ++ return s_instance.get(); ++} ++ + static QString actionShortcutsToString(QAction *action) + { + QString value; +diff --git a/src/CaptureModeModel.h b/src/CaptureModeModel.h +index 574936cb..ef78756a 100644 +--- a/src/CaptureModeModel.h ++++ b/src/CaptureModeModel.h +@@ -7,6 +7,7 @@ + #include "Platforms/ImagePlatform.h" + + #include ++#include + + /** + * This is a model containing the current supported capture modes and their labels and shortcuts. +@@ -15,11 +16,23 @@ class CaptureModeModel : public QAbstractListModel + { + Q_OBJECT + QML_ELEMENT ++ QML_SINGLETON + Q_PROPERTY(int count READ rowCount NOTIFY countChanged FINAL) + + public: + CaptureModeModel(QObject *parent = nullptr); + ++ static CaptureModeModel *instance(); ++ ++ static CaptureModeModel *create(QQmlEngine *engine, QJSEngine *) ++ { ++ auto inst = instance(); ++ Q_ASSERT(inst); ++ Q_ASSERT(inst->thread() == engine->thread()); ++ QJSEngine::setObjectOwnership(inst, QJSEngine::CppOwnership); ++ return inst; ++ } ++ + enum CaptureMode { + RectangularRegion, + AllScreens, +diff --git a/src/Gui/AcceptAction.qml b/src/Gui/AcceptAction.qml +new file mode 100644 +index 00000000..436066bc +--- /dev/null ++++ b/src/Gui/AcceptAction.qml +@@ -0,0 +1,11 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick.Templates as T ++ ++T.Action { ++ icon.name: "dialog-ok" ++ text: i18nc("@action accept selection", "Accept") ++ onTriggered: contextWindow.accept() ++} +diff --git a/src/Gui/AnnotationOptionsToolBarContents.qml b/src/Gui/AnnotationOptionsToolBarContents.qml +index 89198ac1..e7428127 100644 +--- a/src/Gui/AnnotationOptionsToolBarContents.qml ++++ b/src/Gui/AnnotationOptionsToolBarContents.qml +@@ -38,14 +38,9 @@ Row { + } + } + +- component ToolButton: QQC.ToolButton { +- implicitHeight: QmlUtils.iconTextButtonHeight +- width: display === QQC.ToolButton.IconOnly ? height : implicitWidth ++ component ToolButton: TtToolButton { + focusPolicy: root.focusPolicy + display: root.displayMode +- QQC.ToolTip.text: text +- QQC.ToolTip.visible: (hovered || pressed) && display === QQC.ToolButton.IconOnly +- QQC.ToolTip.delay: Kirigami.Units.toolTipDelay + } + + Loader { // stroke +diff --git a/src/Gui/Annotations/CropTool.qml b/src/Gui/Annotations/CropTool.qml +index c17557da..80b3588c 100644 +--- a/src/Gui/Annotations/CropTool.qml ++++ b/src/Gui/Annotations/CropTool.qml +@@ -153,6 +153,7 @@ Loader { + } + + Outline { ++ pathHints: ShapePath.PathLinear + x: selectionRect.x - strokeWidth + y: selectionRect.y - strokeWidth + width: selectionRect.width + strokeWidth * 2 +diff --git a/src/Gui/Annotations/TextTool.qml b/src/Gui/Annotations/TextTool.qml +index a2def4a8..b687b7fb 100644 +--- a/src/Gui/Annotations/TextTool.qml ++++ b/src/Gui/Annotations/TextTool.qml +@@ -183,6 +183,7 @@ AnimatedLoader { + topInset: -background.strokeWidth + bottomInset: -background.strokeWidth + background: DashedOutline { ++ pathHints: ShapePath.PathLinear + strokeWidth: QmlUtils.clampPx(dprRound(1) / root.viewport.scale) + } + +diff --git a/src/Gui/ButtonGrid.qml b/src/Gui/ButtonGrid.qml +index bb158446..a3e7b834 100644 +--- a/src/Gui/ButtonGrid.qml ++++ b/src/Gui/ButtonGrid.qml +@@ -12,14 +12,23 @@ Grid { + property int displayMode: QQC.AbstractButton.TextBesideIcon + property int focusPolicy: Qt.StrongFocus + readonly property bool mirrored: effectiveLayoutDirection === Qt.RightToLeft +- property bool animationsEnabled: true ++ property bool animationsEnabled: false + + clip: childrenRect.width > width || childrenRect.height > height + horizontalItemAlignment: Grid.AlignHCenter + verticalItemAlignment: Grid.AlignVCenter + spacing: Kirigami.Units.mediumSpacing +- columns: flow === Grid.LeftToRight ? visibleChildren.length : 1 +- rows: flow === Grid.TopToBottom ? visibleChildren.length : 1 ++ /* Using -1 for either rows or columns sets the amount to unlimited, ++ * but not if you set both to -1. Using `visibleChildren.length` to set ++ * unlimited rows or columns can generate errors about not having enough ++ * rows/columns when a child item's `visible` property is toggled. ++ * Internally, rows and columns are set to defaults like this: ++ * if (rows <= 0 && columns <= 0) { columns = 4; rows = (numVisible+3)/4; } ++ * else if (rows <= 0) { rows = (numVisible+(columns-1))/columns; } ++ * else if (columns <= 0) { columns = (numVisible+(rows-1))/rows; } ++ */ ++ columns: flow === Grid.LeftToRight ? -1 : 1 ++ rows: flow === Grid.TopToBottom ? -1 : 1 + move: Transition { + enabled: root.animationsEnabled + NumberAnimation { properties: "x,y"; duration: Kirigami.Units.longDuration; easing.type: Easing.OutCubic } +diff --git a/src/Gui/CaptureModeButtonsColumn.qml b/src/Gui/CaptureModeButtonsColumn.qml +index 08b78be1..9071a5e6 100644 +--- a/src/Gui/CaptureModeButtonsColumn.qml ++++ b/src/Gui/CaptureModeButtonsColumn.qml +@@ -11,7 +11,7 @@ import org.kde.spectacle.private + ColumnLayout { + spacing: Kirigami.Units.mediumSpacing + Repeater { +- model: CaptureModeModel { } ++ model: CaptureModeModel + delegate: QQC.DelayButton { + id: button + readonly property bool showCancel: Settings.captureMode === model.captureMode && SpectacleCore.captureTimeRemaining > 0 +diff --git a/src/Gui/CaptureWindow.cpp b/src/Gui/CaptureWindow.cpp +index 462a1344..7568b8c4 100644 +--- a/src/Gui/CaptureWindow.cpp ++++ b/src/Gui/CaptureWindow.cpp +@@ -107,25 +107,14 @@ QScreen *CaptureWindow::screenToFollow() const + + void CaptureWindow::setMode(CaptureWindow::Mode mode) + { +- if (mode == Image) { +- syncGeometryWithScreen(); +- QVariantMap initialProperties = { +- // Set the parent in initialProperties to avoid having +- // the parent and window be null in Component.onCompleted +- {u"parent"_s, QVariant::fromValue(contentItem())} +- }; +- setSource(QUrl("%1/Gui/ImageCaptureOverlay.qml"_L1.arg(SPECTACLE_QML_PATH)), +- initialProperties); +- } else if (mode == Video) { +- syncGeometryWithScreen(); +- QVariantMap initialProperties = { +- // Set the parent in initialProperties to avoid having +- // the parent and window be null in Component.onCompleted +- {u"parent"_s, QVariant::fromValue(contentItem())} +- }; +- setSource(QUrl("%1/Gui/VideoCaptureOverlay.qml"_L1.arg(SPECTACLE_QML_PATH)), +- initialProperties); +- } ++ syncGeometryWithScreen(); ++ QVariantMap initialProperties = { ++ // Set the parent in initialProperties to avoid having ++ // the parent and window be null in Component.onCompleted ++ {u"parent"_s, QVariant::fromValue(contentItem())} ++ }; ++ setSource(QUrl("%1/Gui/ImageCaptureOverlay.qml"_L1.arg(SPECTACLE_QML_PATH)), ++ initialProperties); + } + + bool CaptureWindow::accept() +diff --git a/src/Gui/CopyImageAction.qml b/src/Gui/CopyImageAction.qml +new file mode 100644 +index 00000000..8a4718a9 +--- /dev/null ++++ b/src/Gui/CopyImageAction.qml +@@ -0,0 +1,15 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick.Templates as T ++import org.kde.spectacle.private ++ ++T.Action { ++ // We don't use this in video mode because you can't copy raw video to the ++ // clipboard, or at least not elegantly. ++ enabled: !SpectacleCore.videoMode ++ icon.name: "edit-copy" ++ text: i18nc("@action", "Copy") ++ onTriggered: contextWindow.copyImage() ++} +diff --git a/src/Gui/CopyLocationAction.qml b/src/Gui/CopyLocationAction.qml +new file mode 100644 +index 00000000..d52255f0 +--- /dev/null ++++ b/src/Gui/CopyLocationAction.qml +@@ -0,0 +1,11 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick.Templates as T ++ ++T.Action { ++ icon.name: "edit-copy-path" ++ text: i18nc("@action", "Copy Location") ++ onTriggered: contextWindow.copyLocation() ++} +diff --git a/src/Gui/DashedOutline.qml b/src/Gui/DashedOutline.qml +index d3d7d40d..a1067305 100644 +--- a/src/Gui/DashedOutline.qml ++++ b/src/Gui/DashedOutline.qml +@@ -19,6 +19,7 @@ Outline { + property alias dashOffset: dashPath.dashOffset + property alias dashSvgPath: dashPathSvg.path + property alias dashPathScale: dashPath.scale ++ property alias dashPathHints: dashPath.pathHints + + // A regular alternative pattern with a spacing in logical pixels + function regularDashPattern(spacing, strokeWidth = root.strokeWidth) { +@@ -38,6 +39,7 @@ Outline { + capStyle: ShapePath.FlatCap + joinStyle: root.joinStyle + scale: root.pathScale ++ pathHints: root.pathHints + PathSvg { + id: dashPathSvg + path: root.svgPath +diff --git a/src/Gui/EditAction.qml b/src/Gui/EditAction.qml +new file mode 100644 +index 00000000..988af740 +--- /dev/null ++++ b/src/Gui/EditAction.qml +@@ -0,0 +1,15 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick.Templates as T ++import org.kde.spectacle.private ++ ++T.Action { ++ enabled: !SpectacleCore.videoMode ++ icon.name: "edit-image" ++ text: i18nc("@action edit screenshot", "Edit…") ++ checkable: true ++ checked: contextWindow.annotating ++ onToggled: contextWindow.annotating = checked ++} +diff --git a/src/Gui/ExportMenu.cpp b/src/Gui/ExportMenu.cpp +index d994179c..1a1a041c 100644 +--- a/src/Gui/ExportMenu.cpp ++++ b/src/Gui/ExportMenu.cpp +@@ -47,6 +47,8 @@ ExportMenu::ExportMenu(QWidget *parent) + , mPurposeMenu(new Purpose::Menu) + #endif + { ++ setTitle(i18nc("@title:menu", "Export")); ++ setIcon(QIcon::fromTheme(u"document-share"_s)); + addAction(QIcon::fromTheme(u"document-open-folder"_s), + i18n("Open Default Screenshots Folder"), + this, &ExportMenu::openScreenshotsFolder); +diff --git a/src/Gui/ExportMenuButton.qml b/src/Gui/ExportMenuButton.qml +new file mode 100644 +index 00000000..769f8053 +--- /dev/null ++++ b/src/Gui/ExportMenuButton.qml +@@ -0,0 +1,17 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick ++import org.kde.kirigami as Kirigami ++import org.kde.spectacle.private ++ ++TtToolButton { ++ // FIXME: make export menu actually work with videos ++ visible: !SpectacleCore.videoMode ++ icon.name: "document-share" ++ text: i18nc("@action", "Export") ++ down: pressed || ExportMenu.visible ++ Accessible.role: Accessible.ButtonMenu ++ onPressed: ExportMenu.popup(this) ++} +diff --git a/src/Gui/FloatingToolBar.qml b/src/Gui/FloatingToolBar.qml +index a42fc3dc..3fe9d1d8 100644 +--- a/src/Gui/FloatingToolBar.qml ++++ b/src/Gui/FloatingToolBar.qml +@@ -14,6 +14,7 @@ T.Pane { + property real topRightRadius: radius + property real bottomLeftRadius: radius + property real bottomRightRadius: radius ++ property real backgroundColorOpacity: 0.95 + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding) +@@ -26,7 +27,7 @@ T.Pane { + background: FloatingBackground { + color: Qt.rgba(root.palette.window.r, + root.palette.window.g, +- root.palette.window.b, 0.85) ++ root.palette.window.b, root.backgroundColorOpacity) + border.color: Qt.rgba(root.palette.windowText.r, + root.palette.windowText.g, + root.palette.windowText.b, 0.2) +diff --git a/src/Gui/Handle.qml b/src/Gui/Handle.qml +index fbb386d0..a6c241ba 100644 +--- a/src/Gui/Handle.qml ++++ b/src/Gui/Handle.qml +@@ -153,6 +153,9 @@ Shape { + strokeStyle: root.strokeStyle + joinStyle: root.joinStyle + capStyle: root.capStyle ++ pathHints: (Math.abs(root.sweepAngle) === 360 || Math.abs(root.sweepAngle) <= 180 ++ ? ShapePath.PathConvex : ShapePath.PathSolid) ++ | ShapePath.PathNonOverlappingControlPointTriangles + PathAngleArc { + moveToStart: true // this path should not be affected by startX/startY + radiusX: root.radiusX +diff --git a/src/Gui/HelpMenu.cpp b/src/Gui/HelpMenu.cpp +index cadeb22c..ccc66adc 100644 +--- a/src/Gui/HelpMenu.cpp ++++ b/src/Gui/HelpMenu.cpp +@@ -6,6 +6,7 @@ + #include "WidgetWindowUtils.h" + + #include ++#include + + #include + #include +@@ -13,6 +14,8 @@ + + #include + ++using namespace Qt::StringLiterals; ++ + class HelpMenuSingleton + { + public: +@@ -39,6 +42,8 @@ HelpMenu::HelpMenu(QWidget* parent) + : SpectacleMenu(parent) + , kHelpMenu(new KHelpMenu(parent, KAboutData::applicationData(), true)) + { ++ setTitle(i18nc("@title:menu", "Help")); ++ setIcon(QIcon::fromTheme(u"help-contents"_s)); + addActions(kHelpMenu->menu()->actions()); + connect(this, &QMenu::triggered, this, &HelpMenu::onTriggered); + } +diff --git a/src/Gui/HelpMenuButton.qml b/src/Gui/HelpMenuButton.qml +new file mode 100644 +index 00000000..be30b32f +--- /dev/null ++++ b/src/Gui/HelpMenuButton.qml +@@ -0,0 +1,14 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick ++import org.kde.spectacle.private ++ ++TtToolButton { ++ icon.name: "help-contents" ++ text: i18nc("@action", "Help") ++ down: pressed || HelpMenu.visible ++ Accessible.role: Accessible.ButtonMenu ++ onPressed: HelpMenu.popup(this) ++} +diff --git a/src/Gui/ImageCaptureOverlay.qml b/src/Gui/ImageCaptureOverlay.qml +index d94a649c..da4cf33d 100644 +--- a/src/Gui/ImageCaptureOverlay.qml ++++ b/src/Gui/ImageCaptureOverlay.qml +@@ -6,6 +6,7 @@ + import QtQuick + import QtQuick.Window + import QtQuick.Layouts ++import QtQuick.Shapes + import QtQuick.Controls as QQC + import org.kde.kirigami as Kirigami + import org.kde.spectacle.private +@@ -25,42 +26,58 @@ import "Annotations" + MouseArea { + // This needs to be a mousearea in orcer for the proper mouse events to be correctly filtered + id: root ++ readonly property rect viewportRect: Geometry.mapFromPlatformRect(screenToFollow.geometry, screenToFollow.devicePixelRatio) ++ readonly property AnnotationDocument document: annotationsLoader.item?.document ?? null + focus: true + acceptedButtons: Qt.LeftButton | Qt.RightButton + hoverEnabled: true + LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft + LayoutMirroring.childrenInherit: true + anchors.fill: parent ++ enabled: !SpectacleCore.videoPlatform.isRecording + +- readonly property Selection selection: SelectionEditor.selection +- +- AnnotationEditor { +- id: annotations ++ AnimatedLoader { ++ id: annotationsLoader + anchors.fill: parent +- visible: true +- enabled: contextWindow.annotating +- viewportRect: Geometry.mapFromPlatformRect(screenToFollow.geometry, screenToFollow.devicePixelRatio) ++ state: !SpectacleCore.videoMode ? "active" : "inactive" ++ animationDuration: Kirigami.Units.veryLongDuration ++ sourceComponent: AnnotationEditor { ++ enabled: contextWindow.annotating ++ viewportRect: root.viewportRect ++ } ++ } ++ ++ component ToolButton : TtToolButton { ++ focusPolicy: Qt.NoFocus ++ } ++ ++ component ToolBarSizeLabel: SizeLabel { ++ height: QmlUtils.iconTextButtonHeight ++ size: { ++ const sz = SelectionEditor.selection.empty ++ ? Qt.size(SelectionEditor.screensRect.width, ++ SelectionEditor.screensRect.height) ++ : SelectionEditor.selection.size ++ return Geometry.rawSize(sz, SelectionEditor.devicePixelRatio) ++ } ++ leftPadding: Kirigami.Units.mediumSpacing + QmlUtils.fontMetrics.descent ++ rightPadding: leftPadding + } + + component Overlay: Rectangle { + color: Settings.useLightMaskColor ? "white" : "black" +- opacity: 0.5 +- LayoutMirroring.enabled: false +- } +- Overlay { // top / full overlay when nothing selected +- id: topOverlay +- anchors.top: parent.top +- anchors.left: parent.left +- anchors.right: parent.right +- anchors.bottom: selectionRectangle.visible ? selectionRectangle.top : parent.bottom +- opacity: if (root.selection.empty +- && (!annotations.document.tool.isNoTool || annotations.document.undoStackDepth > 0)) { ++ opacity: if (SpectacleCore.videoPlatform.isRecording ++ || (annotationsLoader.visible ++ && SelectionEditor.selection.empty ++ && root.document && (!root.document.tool.isNoTool ++ || root.document.undoStackDepth > 0))) { + return 0 +- } else if (root.selection.empty) { ++ } else if (SelectionEditor.selection.empty) { + return 0.25 + } else { + return 0.5 + } ++ LayoutMirroring.enabled: false + Behavior on opacity { + NumberAnimation { + duration: Kirigami.Units.longDuration +@@ -68,6 +85,13 @@ MouseArea { + } + } + } ++ Overlay { // top / full overlay when nothing selected ++ id: topOverlay ++ anchors.top: parent.top ++ anchors.left: parent.left ++ anchors.right: parent.right ++ anchors.bottom: selectionRectangle.visible ? selectionRectangle.top : parent.bottom ++ } + Overlay { // bottom + id: bottomOverlay + anchors.left: parent.left +@@ -95,37 +119,69 @@ MouseArea { + visible: selectionRectangle.visible && height > 0 && width > 0 + } + +- Rectangle { ++ AnimatedLoader { ++ anchors.centerIn: parent ++ visible: opacity > 0 && !SpectacleCore.videoPlatform.isRecording ++ state: topOverlay.opacity === 0.25 ? "active" : "inactive" ++ sourceComponent: Kirigami.Heading { ++ id: cropToolHelp ++ horizontalAlignment: Text.AlignHCenter ++ verticalAlignment: Text.AlignVCenter ++ text: i18nc("@info basic crop tool explanation", "Click and drag to make a selection.") ++ padding: cropToolHelpMetrics.height - cropToolHelpMetrics.descent ++ leftPadding: cropToolHelpMetrics.height ++ rightPadding: cropToolHelpMetrics.height ++ background: FloatingBackground { ++ radius: cropToolHelpMetrics.height ++ color: Qt.alpha(palette.window, 0.9) ++ } ++ FontMetrics { ++ id: cropToolHelpMetrics ++ font: cropToolHelp.font ++ } ++ } ++ } ++ ++ ++ DashedOutline { + id: selectionRectangle +- enabled: annotations.document.tool.isNoTool +- color: "transparent" +- border.color: if (enabled) { ++ // We need to be a bit careful about staying out of the recorded area ++ function roundPos(value: real) : real { ++ return SpectacleCore.videoPlatform.isRecording ? dprFloor(value - (strokeWidth + 1 / Screen.devicePixelRatio)) : dprRound(value - strokeWidth) ++ } ++ function roundSize(value: real) : real { ++ return SpectacleCore.videoPlatform.isRecording ? dprCeil(value + (strokeWidth + 1 / Screen.devicePixelRatio)) : dprRound(value + strokeWidth) ++ } ++ pathHints: ShapePath.PathLinear ++ dashSvgPath: SpectacleCore.videoPlatform.isRecording ? svgPath : "" ++ visible: !SelectionEditor.selection.empty ++ && Geometry.rectIntersects(Qt.rect(x,y,width,height), Qt.rect(0,0,parent.width, parent.height)) ++ enabled: root.document?.tool.isNoTool || SpectacleCore.videoMode ++ strokeWidth: dprRound(1) ++ strokeColor: if (enabled) { + return palette.active.highlight + } else if (Settings.useLightMaskColor) { + return "black" + } else { + return "white" + } +- border.width: contextWindow.dprRound(1) +- visible: !root.selection.empty && Geometry.rectIntersects(Qt.rect(x,y,width,height), Qt.rect(0,0,parent.width, parent.height)) +- x: root.selection.x - border.width - annotations.viewportRect.x +- y: root.selection.y - border.width - annotations.viewportRect.y +- width: root.selection.width + border.width * 2 +- height: root.selection.height + border.width * 2 +- +- LayoutMirroring.enabled: false +- LayoutMirroring.childrenInherit: true ++ dashColor: SpectacleCore.videoPlatform.isRecording ? palette.active.base : strokeColor ++ // We need to be a bit careful about staying out of the recorded area ++ x: roundPos(SelectionEditor.selection.x - root.viewportRect.x) ++ y: roundPos(SelectionEditor.selection.y - root.viewportRect.y) ++ width: roundSize(SelectionEditor.selection.right - root.viewportRect.x) - x ++ height: roundSize(SelectionEditor.selection.bottom - root.viewportRect.y) - y + } + + Item { +- x: -annotations.viewportRect.x +- y: -annotations.viewportRect.y ++ x: -root.viewportRect.x ++ y: -root.viewportRect.y + enabled: selectionRectangle.enabled + component SelectionHandle: Handle { + visible: enabled && selectionRectangle.visible + && SelectionEditor.dragLocation === SelectionEditor.None +- && Geometry.rectIntersects(Qt.rect(x,y,width,height), annotations.viewportRect) +- fillColor: selectionRectangle.border.color ++ && Geometry.rectIntersects(Qt.rect(x,y,width,height), root.viewportRect) ++ fillColor: selectionRectangle.strokeColor + } + + SelectionHandle { +@@ -170,34 +226,23 @@ MouseArea { + } + } + +- ShortcutsTextBox { +- anchors { +- horizontalCenter: parent.horizontalCenter +- bottom: parent.bottom +- } +- visible: opacity > 0 && Settings.showCaptureInstructions +- // Assume SelectionEditor covers all screens. +- // Use parent's coordinate system. +- opacity: root.containsMouse +- && !contains(mapFromItem(root, root.mouseX, root.mouseY)) +- && !root.pressed +- && annotations.document.tool.isNoTool +- && !mtbDragHandler.active +- && !atbDragHandler.active +- && !Geometry.rectIntersects(SelectionEditor.handlesRect, Qt.rect(x, y, width, height)) +- Behavior on opacity { +- NumberAnimation { +- duration: Kirigami.Units.longDuration +- easing.type: Easing.OutCubic +- } +- } +- } +- + Item { // separate item because it needs to be above the stuff defined above ++ id: screensRectItem ++ readonly property bool allowToolbars: { ++ let emptyHovered = (root.containsMouse || annotationsLoader.item?.hovered) && SelectionEditor.selection.empty ++ let menuVisible = ExportMenu.visible ++ menuVisible |= OptionsMenu.visible ++ menuVisible |= HelpMenu.visible ++ menuVisible |= ScreenshotModeMenu.visible ++ menuVisible |= RecordingModeMenu.visible ++ let pressed = SelectionEditor.dragLocation || annotationsLoader.item?.anyPressed ++ return !SpectacleCore.videoPlatform.isRecording && !pressed ++ && (emptyHovered || !SelectionEditor.selection.empty || menuVisible) ++ } + width: SelectionEditor.screensRect.width + height: SelectionEditor.screensRect.height +- x: -annotations.viewportRect.x +- y: -annotations.viewportRect.y ++ x: -root.viewportRect.x ++ y: -root.viewportRect.y + + // Magnifier + Loader { +@@ -211,33 +256,33 @@ MouseArea { + if (SelectionEditor.magnifierLocation === SelectionEditor.TopLeft + || SelectionEditor.magnifierLocation === SelectionEditor.Left + || SelectionEditor.magnifierLocation === SelectionEditor.BottomLeft) { +- x = root.selection.left ++ x = SelectionEditor.selection.left + } else if (SelectionEditor.magnifierLocation === SelectionEditor.TopRight + || SelectionEditor.magnifierLocation === SelectionEditor.Right + || SelectionEditor.magnifierLocation === SelectionEditor.BottomRight) { +- x = root.selection.right ++ x = SelectionEditor.selection.right + } else if (SelectionEditor.magnifierLocation === SelectionEditor.Top + || SelectionEditor.magnifierLocation === SelectionEditor.Bottom) { + if (SelectionEditor.dragLocation !== SelectionEditor.None) { + x = SelectionEditor.mousePosition.x + } else { +- x = root.selection.horizontalCenter ++ x = SelectionEditor.selection.horizontalCenter + } + } + if (SelectionEditor.magnifierLocation === SelectionEditor.TopLeft + || SelectionEditor.magnifierLocation === SelectionEditor.Top + || SelectionEditor.magnifierLocation === SelectionEditor.TopRight) { +- y = root.selection.top ++ y = SelectionEditor.selection.top + } else if (SelectionEditor.magnifierLocation === SelectionEditor.BottomLeft + || SelectionEditor.magnifierLocation === SelectionEditor.Bottom + || SelectionEditor.magnifierLocation === SelectionEditor.BottomRight) { +- y = root.selection.bottom ++ y = SelectionEditor.selection.bottom + } else if (SelectionEditor.magnifierLocation === SelectionEditor.Left + || SelectionEditor.magnifierLocation === SelectionEditor.Right) { + if (SelectionEditor.dragLocation !== SelectionEditor.None) { + y = SelectionEditor.mousePosition.y + } else { +- y = root.selection.verticalCenter ++ y = SelectionEditor.selection.verticalCenter + } + } + return Qt.point(x, y) +@@ -281,91 +326,30 @@ MouseArea { + z: 100 + visible: SelectionEditor.showMagnifier + && SelectionEditor.magnifierLocation !== SelectionEditor.None +- && Geometry.rectIntersects(rect, annotations.viewportRect) +- active: Settings.showMagnifier !== Settings.ShowMagnifierNever ++ && Geometry.rectIntersects(rect, root.viewportRect) ++ active: Settings.showMagnifier !== Settings.ShowMagnifierNever && annotationsLoader.item !== null + sourceComponent: Magnifier { +- viewport: annotations ++ viewport: annotationsLoader.item + targetPoint: magnifierLoader.targetPoint + } + } + +- // Size ToolTip +- SizeLabel { +- id: ssToolTip +- readonly property int valignment: { +- if (root.selection.empty) { +- return Qt.AlignVCenter +- } +- const margin = Kirigami.Units.mediumSpacing * 2 +- const w = width + margin +- const h = height + margin +- if (SelectionEditor.handlesRect.top >= h) { +- return Qt.AlignTop +- } else if (SelectionEditor.screensRect.height - SelectionEditor.handlesRect.bottom >= h) { +- return Qt.AlignBottom +- } else { +- // At the bottom of the inside of the selection rect. +- return Qt.AlignBaseline +- } +- } +- readonly property bool normallyVisible: !root.selection.empty && !(mainToolBar.visible && mainToolBar.valignment === ssToolTip.valignment) +- Binding on x { +- value: contextWindow.dprRound(root.selection.horizontalCenter - ssToolTip.width / 2) +- when: ssToolTip.normallyVisible +- restoreMode: Binding.RestoreNone +- } +- Binding on y { +- value: { +- let v = 0 +- if (ssToolTip.valignment & Qt.AlignBaseline) { +- v = Math.min(root.selection.bottom, SelectionEditor.handlesRect.bottom - Kirigami.Units.gridUnit) +- - ssToolTip.height - Kirigami.Units.mediumSpacing * 2 +- } else if (ssToolTip.valignment & Qt.AlignTop) { +- v = SelectionEditor.handlesRect.top +- - ssToolTip.height - Kirigami.Units.mediumSpacing * 2 +- } else if (ssToolTip.valignment & Qt.AlignBottom) { +- v = SelectionEditor.handlesRect.bottom + Kirigami.Units.mediumSpacing * 2 +- } else { +- v = (root.height - ssToolTip.height) / 2 - parent.y +- } +- return contextWindow.dprRound(v) +- } +- when: ssToolTip.normallyVisible +- restoreMode: Binding.RestoreNone +- } +- visible: opacity > 0 +- opacity: ssToolTip.normallyVisible +- && Geometry.rectIntersects(Qt.rect(x,y,width,height), annotations.viewportRect) +- Behavior on opacity { +- NumberAnimation { +- duration: Kirigami.Units.longDuration +- easing.type: Easing.OutCubic +- } +- } +- size: Geometry.rawSize(root.selection.size, SelectionEditor.devicePixelRatio) +- padding: Kirigami.Units.mediumSpacing * 2 +- topPadding: padding - QmlUtils.fontMetrics.descent +- bottomPadding: topPadding +- background: FloatingBackground { +- implicitWidth: Math.ceil(parent.contentWidth) + parent.leftPadding + parent.rightPadding +- implicitHeight: Math.ceil(parent.contentHeight) + parent.topPadding + parent.bottomPadding +- color: Qt.rgba(parent.palette.window.r, +- parent.palette.window.g, +- parent.palette.window.b, 0.85) +- border.color: Qt.rgba(parent.palette.windowText.r, +- parent.palette.windowText.g, +- parent.palette.windowText.b, 0.2) +- border.width: contextWindow.dprRound(1) +- } +- } +- + Connections { +- target: root.selection ++ target: SelectionEditor.selection + function onEmptyChanged() { +- if (!root.selection.empty +- && (mainToolBar.rememberPosition || atbLoader.rememberPosition)) { +- mainToolBar.rememberPosition = false +- atbLoader.rememberPosition = false ++ if (!SelectionEditor.selection.empty) { ++ if (mainToolBar.rememberPosition) { ++ mainToolBar.z = 0 ++ mainToolBar.rememberPosition = false ++ } ++ if (ftbLoader.item?.rememberPosition) { ++ ftbLoader.z = 0 ++ ftbLoader.item.rememberPosition = false ++ } ++ if (atbLoader.item?.rememberPosition) { ++ atbLoader.z = 0 ++ atbLoader.item.rememberPosition = false ++ } + } + } + } +@@ -373,65 +357,27 @@ MouseArea { + // Main ToolBar + FloatingToolBar { + id: mainToolBar ++ readonly property rect rect: Qt.rect(x, y, width, height) + property bool rememberPosition: false +- readonly property int valignment: { +- if (root.selection.empty) { +- return 0 +- } +- if (3 * height + topPadding + Kirigami.Units.mediumSpacing +- <= SelectionEditor.screensRect.height - SelectionEditor.handlesRect.bottom +- ) { +- return Qt.AlignBottom +- } else if (3 * height + bottomPadding + Kirigami.Units.mediumSpacing +- <= SelectionEditor.handlesRect.top +- ) { +- return Qt.AlignTop +- } else { +- // At the bottom of the inside of the selection rect. +- return Qt.AlignBaseline +- } +- } +- readonly property bool normallyVisible: { +- let emptyHovered = (root.containsMouse || annotations.hovered) && root.selection.empty +- let menuVisible = ExportMenu.visible +- menuVisible |= OptionsMenu.visible +- menuVisible |= HelpMenu.visible +- let pressed = SelectionEditor.dragLocation || annotations.anyPressed +- return (emptyHovered || !root.selection.empty || menuVisible) && !pressed +- } ++ property alias dragging: mtbDragHandler.active + Binding on x { +- value: { +- const v = root.selection.empty ? (root.width - mainToolBar.width) / 2 + annotations.viewportRect.x +- : root.selection.horizontalCenter - mainToolBar.width / 2 +- return Math.max(mainToolBar.leftPadding, // min value +- Math.min(contextWindow.dprRound(v), +- SelectionEditor.screensRect.width - mainToolBar.width - mainToolBar.rightPadding)) // max value +- } +- when: mainToolBar.normallyVisible && !mainToolBar.rememberPosition ++ value: Math.max(root.viewportRect.x + mainToolBar.leftPadding, // min value ++ Math.min(dprRound(root.viewportRect.x + (root.width - mainToolBar.width) / 2), ++ root.viewportRect.x + root.width - mainToolBar.width - mainToolBar.rightPadding)) // max value ++ when: screensRectItem.allowToolbars && !mainToolBar.rememberPosition + restoreMode: Binding.RestoreNone + } + Binding on y { +- value: { +- let v = 0 +- // put above selection if not enough room below selection +- if (mainToolBar.valignment & Qt.AlignTop) { +- v = SelectionEditor.handlesRect.top +- - mainToolBar.height - mainToolBar.bottomPadding +- } else if (mainToolBar.valignment & Qt.AlignBottom) { +- v = SelectionEditor.handlesRect.bottom + mainToolBar.topPadding +- } else if (mainToolBar.valignment & Qt.AlignBaseline) { +- v = Math.min(root.selection.bottom, SelectionEditor.handlesRect.bottom - Kirigami.Units.gridUnit) +- - mainToolBar.height - mainToolBar.bottomPadding +- } else { +- v = (mainToolBar.height / 2) - mainToolBar.parent.y +- } +- return contextWindow.dprRound(v) +- } +- when: mainToolBar.normallyVisible && !mainToolBar.rememberPosition ++ value: dprRound(root.viewportRect.y + root.height - mainToolBar.height - mainToolBar.bottomPadding) ++ when: screensRectItem.allowToolbars && !mainToolBar.rememberPosition + restoreMode: Binding.RestoreNone + } +- visible: opacity > 0 +- opacity: normallyVisible && Geometry.rectIntersects(Qt.rect(x,y,width,height), annotations.viewportRect) ++ visible: opacity > 0 && !SpectacleCore.videoPlatform.isRecording ++ opacity: screensRectItem.allowToolbars ++ && (mainToolBar.rememberPosition ++ || SelectionEditor.selection.empty ++ || (!Geometry.rectIntersects(mainToolBar.rect, ftbLoader.rect) ++ && !Geometry.rectIntersects(mainToolBar.rect, SelectionEditor.handlesRect))) + Behavior on opacity { + NumberAnimation { + duration: Kirigami.Units.longDuration +@@ -440,120 +386,261 @@ MouseArea { + } + layer.enabled: true // improves the visuals of the opacity animation + focusPolicy: Qt.NoFocus +- contentItem: MainToolBarContents { +- id: mainToolBarContents +- focusPolicy: Qt.NoFocus +- displayMode: QQC.AbstractButton.TextBesideIcon +- showSizeLabel: mainToolBar.valignment === ssToolTip.valignment +- imageSize: Geometry.rawSize(root.selection.size, SelectionEditor.devicePixelRatio) ++ contentItem: ButtonGrid { ++ spacing: parent.spacing ++ Loader { ++ id: mtbImageVideoContentLoader ++ visible: SelectionEditor.selection.empty ++ active: visible ++ sourceComponent: SpectacleCore.videoMode ? videoToolBarComponent : imageMainToolBarComponent ++ } ++ QQC.ToolSeparator { ++ visible: mtbImageVideoContentLoader.visible ++ height: QmlUtils.iconTextButtonHeight ++ } ++ ScreenshotModeMenuButton { ++ focusPolicy: Qt.NoFocus ++ } ++ RecordingModeMenuButton { ++ focusPolicy: Qt.NoFocus ++ } ++ OptionsMenuButton { ++ focusPolicy: Qt.NoFocus ++ } + } + ++ HoverHandler { ++ target: mainToolBar ++ margin: mainToolBar.padding ++ cursorShape: enabled ? ++ (mtbDragHandler.active ? Qt.ClosedHandCursor : Qt.OpenHandCursor) ++ : undefined ++ } + DragHandler { // parent is contentItem and parent is a read-only property + id: mtbDragHandler +- enabled: root.selection.empty + target: mainToolBar + acceptedButtons: Qt.LeftButton + margin: mainToolBar.padding +- xAxis.minimum: annotations.viewportRect.x +- xAxis.maximum: annotations.viewportRect.x + root.width - mainToolBar.width +- yAxis.minimum: annotations.viewportRect.y +- yAxis.maximum: annotations.viewportRect.y + root.height - mainToolBar.height +- cursorShape: enabled ? +- (active ? Qt.ClosedHandCursor : Qt.OpenHandCursor) +- : undefined +- onActiveChanged: if (active && !mainToolBar.rememberPosition) { +- mainToolBar.rememberPosition = true ++ xAxis.minimum: root.viewportRect.x ++ xAxis.maximum: root.viewportRect.x + root.width - mainToolBar.width ++ yAxis.minimum: root.viewportRect.y ++ yAxis.maximum: root.viewportRect.y + root.height - mainToolBar.height ++ onActiveChanged: if (active) { ++ mainToolBar.z = 2 ++ atbLoader.z = atbLoader.z > ftbLoader.z ? 1 : 0 ++ ftbLoader.z = atbLoader.z < ftbLoader.z ? 1 : 0 ++ if (!mainToolBar.rememberPosition) { ++ mainToolBar.rememberPosition = true ++ } + } + } + } + +- AnimatedLoader { +- id: atbLoader +- property bool rememberPosition: false +- readonly property int valignment: mainToolBar.valignment & (Qt.AlignTop | Qt.AlignBaseline) ? +- Qt.AlignTop : Qt.AlignBottom +- active: visible && mainToolBar.visible +- onActiveChanged: if (!active && rememberPosition +- && !contextWindow.annotating) { +- rememberPosition = false +- } +- state: mainToolBar.normallyVisible +- && contextWindow.annotating ? "active" : "inactive" +- +- Binding on x { +- value: { +- const min = mainToolBar.x +- const target = contextWindow.dprRound(mainToolBar.x + (mainToolBar.width - atbLoader.width) / 2) +- const max = mainToolBar.x + mainToolBar.width - atbLoader.width +- return Math.max(min, Math.min(target, max)) ++ Component { ++ id: imageMainToolBarComponent ++ ButtonGrid { ++ spacing: parent.parent.spacing ++ ToolBarSizeLabel {} ++ ToolButton { ++ display: TtToolButton.TextBesideIcon ++ visible: action.enabled ++ action: AcceptAction {} ++ } ++ ToolButton { ++ display: TtToolButton.IconOnly ++ visible: action.enabled ++ action: SaveAction {} ++ } ++ ToolButton { ++ display: TtToolButton.IconOnly ++ visible: action.enabled ++ action: SaveAsAction {} ++ } ++ ToolButton { ++ display: TtToolButton.IconOnly ++ visible: action.enabled ++ action: CopyImageAction {} ++ } ++ ExportMenuButton { ++ focusPolicy: Qt.NoFocus + } +- when: !atbLoader.rememberPosition +- restoreMode: Binding.RestoreNone + } +- Binding on y { +- value: contextWindow.dprRound(atbLoader.valignment & Qt.AlignTop ? +- mainToolBar.y - atbLoader.height - Kirigami.Units.mediumSpacing +- : mainToolBar.y + mainToolBar.height + Kirigami.Units.mediumSpacing) +- when: !atbLoader.rememberPosition +- restoreMode: Binding.RestoreNone ++ } ++ Component { ++ id: imageFinalizerToolBarComponent ++ ButtonGrid { ++ spacing: parent.parent.spacing ++ ToolBarSizeLabel {} ++ ToolButton { ++ visible: action.enabled ++ action: AcceptAction {} ++ } ++ ToolButton { ++ visible: action.enabled ++ action: SaveAction {} ++ } ++ ToolButton { ++ visible: action.enabled ++ action: SaveAsAction {} ++ } ++ ToolButton { ++ visible: action.enabled ++ action: CopyImageAction {} ++ } ++ ExportMenuButton { ++ focusPolicy: Qt.NoFocus ++ } + } +- +- DragHandler { // parented to contentItem +- id: atbDragHandler +- enabled: root.selection.empty +- acceptedButtons: Qt.LeftButton +- xAxis.minimum: annotations.viewportRect.x +- xAxis.maximum: annotations.viewportRect.x + root.width - atbLoader.width +- yAxis.minimum: annotations.viewportRect.y +- yAxis.maximum: annotations.viewportRect.y + root.height - atbLoader.height +- cursorShape: enabled ? +- (active ? Qt.ClosedHandCursor : Qt.OpenHandCursor) +- : undefined +- onActiveChanged: if (active && !atbLoader.rememberPosition) { +- atbLoader.rememberPosition = true ++ } ++ Component { ++ id: videoToolBarComponent ++ ButtonGrid { ++ spacing: parent.parent.spacing ++ ToolBarSizeLabel {} ++ ToolButton { ++ display: TtToolButton.TextBesideIcon ++ visible: action.enabled ++ action: RecordAction {} + } + } ++ } + ++ Loader { ++ id: atbLoader ++ readonly property rect rect: Qt.rect(x, y, width, height) ++ visible: annotationsLoader.visible ++ active: visible ++ z: 2 + sourceComponent: FloatingToolBar { + id: annotationsToolBar ++ property bool rememberPosition: false ++ readonly property int valignment: { ++ if (SelectionEditor.handlesRect.top >= height + annotationsToolBar.bottomPadding || SelectionEditor.selection.empty) { ++ // the top of the top side of the selection ++ // or the top of the screen ++ return Qt.AlignTop ++ } else { ++ // the bottom of the top side of the selection ++ return Qt.AlignBottom ++ } ++ } ++ property alias dragging: dragHandler.active ++ visible: opacity > 0 ++ opacity: screensRectItem.allowToolbars && Geometry.rectIntersects(atbLoader.rect, root.viewportRect) ++ Behavior on opacity { ++ NumberAnimation { ++ duration: Kirigami.Units.longDuration ++ easing.type: Easing.OutCubic ++ } ++ } ++ // Can't use layer.enabled to improve opacity animation because ++ // that makes the options toolbar invisible + focusPolicy: Qt.NoFocus + contentItem: AnnotationsToolBarContents { + id: annotationsContents ++ spacing: parent.spacing + displayMode: QQC.AbstractButton.IconOnly + focusPolicy: Qt.NoFocus + } + +- topLeftRadius: optionsToolBar.visible +- && optionsToolBar.x === 0 +- && atbLoader.valignment & Qt.AlignTop ? 0 : radius +- topRightRadius: optionsToolBar.visible +- && optionsToolBar.x === width - optionsToolBar.width +- && atbLoader.valignment & Qt.AlignTop ? 0 : radius +- bottomLeftRadius: optionsToolBar.visible +- && optionsToolBar.x === 0 +- && atbLoader.valignment & Qt.AlignBottom ? 0 : radius +- bottomRightRadius: optionsToolBar.visible +- && optionsToolBar.x === width - optionsToolBar.width +- && atbLoader.valignment & Qt.AlignBottom ? 0 : radius ++ topLeftRadius: otbLoader.visible ++ && otbLoader.x === 0 ++ && (annotationsToolBar.valignment & Qt.AlignTop) ++ && !SelectionEditor.selection.empty ? 0 : radius ++ topRightRadius: otbLoader.visible ++ && otbLoader.x === width - otbLoader.width ++ && (annotationsToolBar.valignment & Qt.AlignTop) ++ && !SelectionEditor.selection.empty? 0 : radius ++ bottomLeftRadius: otbLoader.visible ++ && otbLoader.x === 0 ++ && ((annotationsToolBar.valignment & Qt.AlignBottom) ++ || SelectionEditor.selection.empty) ? 0 : radius ++ bottomRightRadius: otbLoader.visible ++ && otbLoader.x === width - otbLoader.width ++ && ((annotationsToolBar.valignment & Qt.AlignBottom) ++ || SelectionEditor.selection.empty) ? 0 : radius ++ ++ Binding { ++ property: "x" ++ target: atbLoader ++ value: { ++ const v = SelectionEditor.selection.empty ? (root.width - annotationsToolBar.width) / 2 + root.viewportRect.x ++ : SelectionEditor.selection.horizontalCenter - annotationsToolBar.width / 2 ++ return Math.max(annotationsToolBar.leftPadding, // min value ++ Math.min(dprRound(v), ++ SelectionEditor.screensRect.width - annotationsToolBar.width - annotationsToolBar.rightPadding)) // max value ++ } ++ when: screensRectItem.allowToolbars && !annotationsToolBar.rememberPosition ++ restoreMode: Binding.RestoreNone ++ } ++ Binding { ++ property: "y" ++ target: atbLoader ++ value: { ++ let v = 0 ++ if (SelectionEditor.selection.empty) { ++ v = root.viewportRect.y + annotationsToolBar.topPadding ++ } else if (annotationsToolBar.valignment & Qt.AlignTop) { ++ v = SelectionEditor.handlesRect.top - annotationsToolBar.height - annotationsToolBar.bottomPadding ++ } else if (annotationsToolBar.valignment & Qt.AlignBottom) { ++ v = Math.max(SelectionEditor.selection.top, SelectionEditor.handlesRect.top + Kirigami.Units.gridUnit) ++ + annotationsToolBar.topPadding ++ } else { ++ v = (root.height - annotationsToolBar.height) / 2 - parent.y ++ } ++ return dprRound(v) ++ } ++ when: screensRectItem.allowToolbars && !annotationsToolBar.rememberPosition ++ restoreMode: Binding.RestoreNone ++ } + + // Exists purely for cosmetic reasons to make the border of + // optionsToolBar that meets annotationsToolBar look better + Rectangle { + id: borderBg + z: -1 +- visible: optionsToolBar.visible +- opacity: optionsToolBar.opacity ++ visible: otbLoader.visible ++ opacity: otbLoader.opacity + parent: annotationsToolBar +- x: optionsToolBar.x + annotationsToolBar.background.border.width +- y: atbLoader.valignment & Qt.AlignTop ? +- optionsToolBar.y + optionsToolBar.height : optionsToolBar.y +- width: optionsToolBar.width - annotationsToolBar.background.border.width * 2 +- height: contextWindow.dprRound(1) ++ x: otbLoader.x + annotationsToolBar.background.border.width ++ y: (annotationsToolBar.valignment & Qt.AlignTop) ++ && !SelectionEditor.selection.empty ++ ? otbLoader.y + otbLoader.height : otbLoader.y ++ width: otbLoader.width - annotationsToolBar.background.border.width * 2 ++ height: dprRound(1) + color: annotationsToolBar.background.color + } + ++ HoverHandler { ++ enabled: dragHandler.enabled ++ target: annotationsToolBar ++ margin: annotationsToolBar.padding ++ cursorShape: enabled ? ++ (dragHandler.active ? Qt.ClosedHandCursor : Qt.OpenHandCursor) ++ : undefined ++ } ++ DragHandler { // parented to contentItem ++ id: dragHandler ++ enabled: SelectionEditor.selection.empty || !selectionRectangle.enabled ++ target: atbLoader ++ acceptedButtons: Qt.LeftButton ++ margin: annotationsToolBar.padding ++ xAxis.minimum: root.viewportRect.x ++ xAxis.maximum: root.viewportRect.x + root.width - annotationsToolBar.width ++ yAxis.minimum: root.viewportRect.y ++ yAxis.maximum: root.viewportRect.y + root.height - annotationsToolBar.height ++ onActiveChanged: if (active) { ++ mainToolBar.z = mainToolBar.z > ftbLoader.z ? 1 : 0 ++ atbLoader.z = 2 ++ ftbLoader.z = mainToolBar.z < ftbLoader.z ? 1 : 0 ++ if (!annotationsToolBar.rememberPosition) { ++ annotationsToolBar.rememberPosition = true ++ } ++ } ++ } ++ + AnimatedLoader { +- id: optionsToolBar ++ id: otbLoader + parent: annotationsToolBar + x: { + let targetX = annotationsContents.x +@@ -562,15 +649,16 @@ MouseArea { + targetX += checkedButton.x + (checkedButton.width - width) / 2 + } + return Math.max(0, // min value +- Math.min(contextWindow.dprRound(targetX), ++ Math.min(contextWindow.dprRound(targetX), + parent.width - width)) // max value + } +- y: atbLoader.valignment & Qt.AlignTop ? +- -optionsToolBar.height + borderBg.height +- : optionsToolBar.height - borderBg.height +- state: if (SpectacleCore.annotationDocument.tool.options !== AnnotationTool.NoOptions +- || (SpectacleCore.annotationDocument.tool.type === AnnotationTool.SelectTool +- && SpectacleCore.annotationDocument.selectedItem.options !== AnnotationTool.NoOptions) ++ y: (annotationsToolBar.valignment & Qt.AlignTop) ++ && !SelectionEditor.selection.empty ++ ? -otbLoader.height + borderBg.height ++ : otbLoader.height - borderBg.height ++ state: if (root.document?.tool.options !== AnnotationTool.NoOptions ++ || (root.document?.tool.type === AnnotationTool.SelectTool ++ && root.document?.selectedItem.options !== AnnotationTool.NoOptions) + ) { + return "active" + } else { +@@ -579,13 +667,111 @@ MouseArea { + sourceComponent: FloatingToolBar { + focusPolicy: Qt.NoFocus + contentItem: AnnotationOptionsToolBarContents { ++ spacing: parent.spacing + displayMode: QQC.AbstractButton.IconOnly + focusPolicy: Qt.NoFocus + } +- topLeftRadius: atbLoader.valignment & Qt.AlignBottom && x >= 0 ? 0 : radius +- topRightRadius: atbLoader.valignment & Qt.AlignBottom && x + width <= annotationsToolBar.width ? 0 : radius +- bottomLeftRadius: atbLoader.valignment & Qt.AlignTop && x >= 0 ? 0 : radius +- bottomRightRadius: atbLoader.valignment & Qt.AlignTop && x + width <= annotationsToolBar.width ? 0 : radius ++ topLeftRadius: ((annotationsToolBar.valignment & Qt.AlignBottom) || SelectionEditor.selection.empty) && otbLoader.x >= 0 ? 0 : radius ++ topRightRadius: ((annotationsToolBar.valignment & Qt.AlignBottom) || SelectionEditor.selection.empty) && otbLoader.x + width <= annotationsToolBar.width ? 0 : radius ++ bottomLeftRadius: (annotationsToolBar.valignment & Qt.AlignTop) && !SelectionEditor.selection.empty && otbLoader.x >= 0 ? 0 : radius ++ bottomRightRadius: (annotationsToolBar.valignment & Qt.AlignTop) && !SelectionEditor.selection.empty && otbLoader.x + width <= annotationsToolBar.width ? 0 : radius ++ } ++ } ++ } ++ } ++ ++ // Finalizer ToolBar ++ Loader { ++ id: ftbLoader ++ readonly property rect rect: Qt.rect(x, y, width, height) ++ visible: !SpectacleCore.videoPlatform.isRecording && !SelectionEditor.selection.empty ++ active: visible ++ sourceComponent: FloatingToolBar { ++ id: toolBar ++ property bool rememberPosition: false ++ property alias dragging: dragHandler.active ++ readonly property int valignment: { ++ if (SelectionEditor.screensRect.height - SelectionEditor.handlesRect.bottom >= height + toolBar.topPadding || SelectionEditor.selection.empty) { ++ // the bottom of the bottom side of the selection ++ // or the bottom of the screen ++ return Qt.AlignBottom ++ } else { ++ // the top of the bottom side of the selection ++ return Qt.AlignTop ++ } ++ } ++ Binding { ++ property: "x" ++ target: ftbLoader ++ value: { ++ const v = SelectionEditor.selection.empty ? (root.width - toolBar.width) / 2 + root.viewportRect.x ++ : SelectionEditor.selection.horizontalCenter - toolBar.width / 2 ++ return Math.max(toolBar.leftPadding, // min value ++ Math.min(dprRound(v), ++ SelectionEditor.screensRect.width - toolBar.width - toolBar.rightPadding)) // max value ++ } ++ when: screensRectItem.allowToolbars && !toolBar.rememberPosition ++ restoreMode: Binding.RestoreNone ++ } ++ Binding { ++ property: "y" ++ target: ftbLoader ++ value: { ++ let v = 0 ++ if (SelectionEditor.selection.empty) { ++ v = root.viewportRect.y + root.height - toolBar.height - toolBar.bottomPadding ++ } else if (toolBar.valignment & Qt.AlignBottom) { ++ v = SelectionEditor.handlesRect.bottom + toolBar.topPadding ++ } else if (toolBar.valignment & Qt.AlignTop) { ++ v = Math.min(SelectionEditor.selection.bottom, SelectionEditor.handlesRect.bottom - Kirigami.Units.gridUnit) ++ - toolBar.height - toolBar.bottomPadding ++ } else { ++ v = (toolBar.height / 2) - toolBar.parent.y ++ } ++ return dprRound(v) ++ } ++ when: screensRectItem.allowToolbars && !toolBar.rememberPosition ++ restoreMode: Binding.RestoreNone ++ } ++ visible: opacity > 0 ++ opacity: screensRectItem.allowToolbars && Geometry.rectIntersects(ftbLoader.rect, root.viewportRect) ++ Behavior on opacity { ++ NumberAnimation { ++ duration: Kirigami.Units.longDuration ++ easing.type: Easing.OutCubic ++ } ++ } ++ layer.enabled: true // improves the visuals of the opacity animation ++ focusPolicy: Qt.NoFocus ++ contentItem: Loader { ++ sourceComponent: SpectacleCore.videoMode ? videoToolBarComponent : imageFinalizerToolBarComponent ++ } ++ ++ HoverHandler { ++ enabled: dragHandler.enabled ++ target: toolBar ++ margin: toolBar.padding ++ cursorShape: enabled ? ++ (dragHandler.active ? Qt.ClosedHandCursor : Qt.OpenHandCursor) ++ : undefined ++ } ++ DragHandler { // parent is contentItem and parent is a read-only property ++ id: dragHandler ++ enabled: SelectionEditor.selection.empty || !selectionRectangle.enabled ++ target: ftbLoader ++ acceptedButtons: Qt.LeftButton ++ margin: toolBar.padding ++ xAxis.minimum: root.viewportRect.x ++ xAxis.maximum: root.viewportRect.x + root.width - toolBar.width ++ yAxis.minimum: root.viewportRect.y ++ yAxis.maximum: root.viewportRect.y + root.height - toolBar.height ++ onActiveChanged: if (active) { ++ mainToolBar.z = mainToolBar.z > atbLoader.z ? 1 : 0 ++ atbLoader.z = mainToolBar.z < atbLoader.z ? 1 : 0 ++ ftbLoader.z = 2 ++ if (!toolBar.rememberPosition) { ++ toolBar.rememberPosition = true ++ } + } + } + } +diff --git a/src/Gui/ImageView.qml b/src/Gui/ImageView.qml +index ba68e4ca..2be177ec 100644 +--- a/src/Gui/ImageView.qml ++++ b/src/Gui/ImageView.qml +@@ -26,12 +26,11 @@ EmptyPage { + readonly property real minimumWidth: Math.max( + header.implicitWidth, + annotationsToolBar.implicitWidth + separator.implicitWidth + footerLoader.implicitWidth, +- captureOptionsLoader.implicitWidth + 480 // leave some room for content if necessary ++ 480 // leave some room for content if necessary + ) + readonly property real minimumHeight: header.implicitHeight + + Math.max(annotationsToolBar.implicitHeight, +- footerLoader.implicitHeight, +- captureOptionsLoader.implicitHeight) ++ footerLoader.implicitHeight) + + property var inlineMessageData: {} + property string inlineMessageSource: "" +@@ -47,12 +46,46 @@ EmptyPage { + + header: QQC.ToolBar { + id: header +- contentItem: MainToolBarContents { ++ contentItem: ButtonGrid { + id: mainToolBarContents +- showNewScreenshotButton: false +- showOptionsMenu: false +- showUndoRedo: contextWindow.annotating +- displayMode: QQC.AbstractButton.TextBesideIcon ++ animationsEnabled: true ++ AnimatedLoader { ++ state: contextWindow.annotating ? "active" : "inactive" ++ sourceComponent: UndoRedoGroup { ++ buttonHeight: QmlUtils.iconTextButtonHeight ++ spacing: mainToolBarContents.spacing ++ } ++ } ++ TtToolButton { ++ display: TtToolButton.IconOnly ++ visible: action.enabled ++ action: SaveAction {} ++ } ++ TtToolButton { ++ display: SpectacleCore.videoMode ? TtToolButton.TextBesideIcon : TtToolButton.IconOnly ++ action: SaveAsAction {} ++ } ++ TtToolButton { ++ display: TtToolButton.IconOnly ++ visible: action.enabled ++ action: CopyImageAction {} ++ } ++ // We only show this in video mode to save space in screenshot mode ++ TtToolButton { ++ visible: SpectacleCore.videoMode ++ action: CopyLocationAction {} ++ } ++ ExportMenuButton {} ++ TtToolButton { ++ visible: action.enabled ++ action: EditAction {} ++ } ++ QQC.ToolSeparator { ++ height: QmlUtils.iconTextButtonHeight ++ } ++ ScreenshotModeMenuButton {} ++ RecordingModeMenuButton {} ++ OptionsMenuButton {} + } + } + +@@ -64,7 +97,7 @@ EmptyPage { + AnimatedLoader { // parent is contentItem + id: inlineMessageLoader + anchors.left: annotationsToolBar.right +- anchors.right: captureOptionsLoader.left ++ anchors.right: parent.right + anchors.top: parent.top + state: "inactive" + height: visible ? implicitHeight : 0 +@@ -111,7 +144,7 @@ EmptyPage { + id: contentLoader + anchors { + left: footerLoader.left +- right: captureOptionsLoader.left ++ right: parent.right + top: inlineMessageLoader.bottom + bottom: footerLoader.top + } +@@ -126,78 +159,10 @@ EmptyPage { + } + } + +- Loader { // parent is contentItem +- id: captureOptionsLoader +- visible: true +- active: visible +- anchors { +- top: parent.top +- bottom: parent.bottom +- right: parent.right +- } +- width: Math.max(implicitWidth, Kirigami.Units.gridUnit * 15) +- sourceComponent: QQC.Page { +- +- leftPadding: Kirigami.Units.mediumSpacing * 2 +- + (!mirrored ? sideBarSeparator.implicitWidth : 0) +- rightPadding: Kirigami.Units.mediumSpacing * 2 +- + (mirrored ? sideBarSeparator.implicitWidth : 0) +- topPadding: Kirigami.Units.mediumSpacing * 2 +- bottomPadding: Kirigami.Units.mediumSpacing * 2 +- +- header: RowLayout { +- spacing: 0 +- Kirigami.Separator { +- Layout.fillHeight: true +- } +- Kirigami.NavigationTabBar { +- id: tabBar +- Layout.fillWidth: true +- visible: SpectacleCore.videoPlatform.supportedRecordingModes +- currentIndex: 0 +- Kirigami.Theme.colorSet: Kirigami.Theme.Window +- +- actions: [ +- Kirigami.Action { +- text: i18n("Screenshot") +- icon.name: "camera-photo" +- checked: tabBar.currentIndex === 0 +- }, +- Kirigami.Action { +- text: i18n("Recording") +- icon.name: "camera-video" +- checked: tabBar.currentIndex === 1 +- } +- ] +- } +- } +- +- contentItem: Loader { +- source: switch (tabBar.currentIndex) { +- case 0: return "CaptureOptions.qml" +- case 1: return "RecordOptions.qml" +- default: return "" +- } +- } +- +- background: Rectangle { +- color: Kirigami.Theme.backgroundColor +- Kirigami.Separator { +- id: sideBarSeparator +- anchors { +- left: parent.left +- top: parent.top +- bottom: parent.bottom +- } +- } +- } +- } +- } +- + Loader { + id: footerLoader + anchors.left: separator.right +- anchors.right: captureOptionsLoader.left ++ anchors.right: parent.right + anchors.top: parent.bottom + visible: false + active: visible +@@ -294,11 +259,6 @@ EmptyPage { + anchors.bottom: parent.bottom + anchors.top: undefined + } +- AnchorChanges { +- target: captureOptionsLoader +- anchors.left: parent.right +- anchors.right: undefined +- } + }, + State { + name: "normal" +@@ -315,11 +275,6 @@ EmptyPage { + anchors.bottom: undefined + anchors.top: parent.bottom + } +- AnchorChanges { +- target: captureOptionsLoader +- anchors.left: undefined +- anchors.right: parent.right +- } + } + ] + transitions: [ +@@ -335,21 +290,11 @@ EmptyPage { + duration: Kirigami.Units.longDuration + easing.type: Easing.OutCubic + } +- PropertyAction { +- targets: captureOptionsLoader +- property: "visible" +- value: false +- } + } + }, + Transition { + to: "normal" + SequentialAnimation { +- PropertyAction { +- targets: captureOptionsLoader +- property: "visible" +- value: true +- } + AnchorAnimation { + duration: Kirigami.Units.longDuration + easing.type: Easing.OutCubic +diff --git a/src/Gui/MainToolBarContents.qml b/src/Gui/MainToolBarContents.qml +deleted file mode 100644 +index eaf2ad01..00000000 +--- a/src/Gui/MainToolBarContents.qml ++++ /dev/null +@@ -1,153 +0,0 @@ +-/* SPDX-FileCopyrightText: 2022 Noah Davis +- * SPDX-License-Identifier: LGPL-2.0-or-later +- */ +- +-import QtQuick +-import QtQuick.Controls as QQC +-import org.kde.kirigami as Kirigami +-import org.kde.spectacle.private +- +-ButtonGrid { +- id: root +- property size imageSize: Qt.size(0, 0) +- property bool showSizeLabel: false +- property bool showUndoRedo: false +- property bool showNewScreenshotButton: true +- property bool showOptionsMenu: true +- +- component ToolButton: QQC.ToolButton { +- implicitHeight: QmlUtils.iconTextButtonHeight +- width: display === QQC.ToolButton.IconOnly ? height : implicitWidth +- focusPolicy: root.focusPolicy +- display: root.displayMode +- QQC.ToolTip.text: text +- QQC.ToolTip.visible: (hovered || pressed) && display === QQC.ToolButton.IconOnly +- QQC.ToolTip.delay: Kirigami.Units.toolTipDelay +- } +- +- AnimatedLoader { +- id: sizeLabelLoader +- state: root.showSizeLabel && root.imageSize.width > 0 && root.imageSize.height > 0 ? +- "active" : "inactive" +- sourceComponent: SizeLabel { +- height: QmlUtils.iconTextButtonHeight +- size: root.imageSize +- leftPadding: Kirigami.Units.mediumSpacing + QmlUtils.fontMetrics.descent +- rightPadding: leftPadding +- } +- } +- +- AnimatedLoader { +- state: root.showUndoRedo ? "active" : "inactive" +- sourceComponent: UndoRedoGroup { +- animationsEnabled: root.animationsEnabled +- buttonHeight: QmlUtils.iconTextButtonHeight +- focusPolicy: root.focusPolicy +- flow: root.flow +- spacing: root.spacing +- } +- } +- +- // We don't show this in video mode because the video is already automatically saved. +- // and you can't edit the video. +- ToolButton { +- visible: !SpectacleCore.videoMode +- icon.name: "document-save" +- text: i18n("Save") +- onClicked: contextWindow.save() +- } +- +- ToolButton { +- icon.name: "document-save-as" +- text: i18n("Save As...") +- onClicked: contextWindow.saveAs() +- } +- +- // We don't show this in video mode because you can't copy raw video to the clipboard, +- // or at least not elegantly. +- ToolButton { +- visible: !SpectacleCore.videoMode +- icon.name: "edit-copy" +- text: i18n("Copy") +- onClicked: contextWindow.copyImage() +- } +- +- // We only show this in video mode to save space in screenshot mode +- ToolButton { +- visible: SpectacleCore.videoMode +- icon.name: "edit-copy-path" +- text: i18n("Copy Location") +- onClicked: contextWindow.copyLocation() +- } +- +- ToolButton { +- // FIXME: make export menu actually work with videos +- visible: !SpectacleCore.videoMode +- icon.name: "document-share" +- text: i18n("Export") +- down: pressed || ExportMenu.visible +- Accessible.role: Accessible.ButtonMenu +- onPressed: ExportMenu.popup(this) +- } +- +- ToolButton { +- id: annotationsButton +- icon.name: "edit-image" +- text: i18nc("@action:button edit screenshot", "Edit…") +- visible: !SpectacleCore.videoMode +- checkable: true +- checked: contextWindow.annotating +- onToggled: contextWindow.annotating = checked +- } +- +- ToolButton { +- // Can't rely on checked since clicking also toggles checked +- readonly property bool showCancel: SpectacleCore.captureTimeRemaining > 0 +- readonly property real cancelWidth: QmlUtils.getButtonSize(display, cancelText(Settings.captureDelay), icon.name).width +- +- function cancelText(seconds) { +- return i18np("Cancel (%1 second)", "Cancel (%1 seconds)", Math.ceil(seconds)) +- } +- +- visible: root.showNewScreenshotButton +- checked: showCancel +- width: if (showCancel) { +- return cancelWidth +- } else { +- return display === QQC.ToolButton.IconOnly ? height : implicitWidth +- } +- icon.name: showCancel ? "dialog-cancel" : "list-add" +- text: showCancel ? +- cancelText(SpectacleCore.captureTimeRemaining / 1000) +- : i18n("New Screenshot") +- onClicked: if (showCancel) { +- SpectacleCore.cancelScreenshot() +- } else { +- SpectacleCore.takeNewScreenshot() +- } +- } +- +- ToolButton { +- visible: root.showOptionsMenu +- icon.name: "configure" +- text: i18n("Options") +- down: pressed || OptionsMenu.visible +- Accessible.role: Accessible.ButtonMenu +- onPressed: OptionsMenu.popup(this) +- } +- ToolButton { +- visible: !root.showOptionsMenu +- icon.name: "configure" +- text: i18n("Configure...") +- onClicked: OptionsMenu.showPreferencesDialog(); +- } +- +- ToolButton { +- id: helpButton +- icon.name: "help-contents" +- text: i18n("Help") +- down: pressed || HelpMenu.visible +- Accessible.role: Accessible.ButtonMenu +- onPressed: HelpMenu.popup(this) +- } +-} +diff --git a/src/Gui/NewScreenshotToolButton.qml b/src/Gui/NewScreenshotToolButton.qml +new file mode 100644 +index 00000000..4c7aa91a +--- /dev/null ++++ b/src/Gui/NewScreenshotToolButton.qml +@@ -0,0 +1,33 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick ++import org.kde.kirigami as Kirigami ++import org.kde.spectacle.private ++ ++TtToolButton { ++ // Can't rely on checked since clicking also toggles checked ++ readonly property bool showCancel: SpectacleCore.captureTimeRemaining > 0 ++ readonly property real cancelWidth: QmlUtils.getButtonSize(display, cancelText(Settings.captureDelay), icon.name).width ++ ++ function cancelText(seconds) { ++ return i18np("Cancel (%1 second)", "Cancel (%1 seconds)", Math.ceil(seconds)) ++ } ++ ++ checked: showCancel ++ width: if (showCancel) { ++ return cancelWidth ++ } else { ++ return display === TtToolButton.IconOnly ? height : implicitWidth ++ } ++ icon.name: showCancel ? "dialog-cancel" : "list-add" ++ text: showCancel ? ++ cancelText(SpectacleCore.captureTimeRemaining / 1000) ++ : i18n("New Screenshot") ++ onClicked: if (showCancel) { ++ SpectacleCore.cancelScreenshot() ++ } else { ++ SpectacleCore.takeNewScreenshot() ++ } ++} +diff --git a/src/Gui/OptionsMenu.cpp b/src/Gui/OptionsMenu.cpp +index e031f8f1..d9ac01da 100644 +--- a/src/Gui/OptionsMenu.cpp ++++ b/src/Gui/OptionsMenu.cpp +@@ -5,15 +5,21 @@ + #include "OptionsMenu.h" + + #include "CaptureModeModel.h" ++#include "Gui/SmartSpinBox.h" + #include "Gui/SettingsDialog/SettingsDialog.h" + #include "SpectacleCore.h" + #include "WidgetWindowUtils.h" ++#include "HelpMenu.h" + #include "settings.h" + + #include + #include + ++#include ++#include ++#include + #include ++#include + + using namespace Qt::StringLiterals; + +@@ -21,158 +27,129 @@ static QPointer s_instance = nullptr; + + OptionsMenu::OptionsMenu(QWidget *parent) + : SpectacleMenu(parent) +- , captureModeSection(new QAction(this)) +- , captureModeGroup(new QActionGroup(this)) // exclusive by default) +- , captureSettingsSection(new QAction(this)) +- , includeMousePointerAction(new QAction(this)) +- , includeWindowDecorationsAction(new QAction(this)) +- , includeWindowShadowAction(new QAction(this)) +- , onlyCapturePopupAction(new QAction(this)) +- , quitAfterSaveAction(new QAction(this)) +- , captureOnClickAction(new QAction(this)) +- , delayAction(new QWidgetAction(this)) +- , delayWidget(new QWidget(this)) +- , delayLayout(new QHBoxLayout(delayWidget.get())) +- , delayLabel(new QLabel(delayWidget.get())) +- , delaySpinBox(new SmartSpinBox(delayWidget.get())) ++ , m_delayAction(new QWidgetAction(this)) ++ , m_delayWidget(new QWidget(this)) ++ , m_delayLayout(new QHBoxLayout(m_delayWidget.get())) ++ , m_delayLabel(new QLabel(m_delayWidget.get())) ++ , m_delaySpinBox(new SmartSpinBox(m_delayWidget.get())) + { +- addAction(KStandardActions::preferences(this, &OptionsMenu::showPreferencesDialog, this)); +- ++ setToolTipsVisible(true); + // QMenu::addSection just adds an action with text and separator mode enabled +- captureModeSection->setText(i18n("Capture Mode")); +- captureModeSection->setSeparator(true); +- addAction(captureModeSection.get()); ++ addSection(i18nc("@title:menu", "Screenshot Settings")); + +- // Add capture mode actions. +- // This cannot be done in the constructor because captureModeModel will be null at this time. +- connect(this, &OptionsMenu::aboutToShow, +- this, &OptionsMenu::updateCaptureModes); +- +- // make capture mode actions do things +- connect(captureModeGroup.get(), &QActionGroup::triggered, this, [](QAction *action){ +- int mode = action->data().toInt(); +- Settings::setCaptureMode(mode); +- }); +- connect(Settings::self(), &Settings::captureModeChanged, this, [this](){ +- int mode = Settings::captureMode(); +- if (captureModeGroup->checkedAction() && mode == captureModeGroup->checkedAction()->data().toInt()) { +- return; +- } +- for (auto action : std::as_const(captureModeActions)) { +- if (mode == action->data().toInt()) { +- action->setChecked(true); +- } +- } +- }); +- +- captureSettingsSection->setText(i18n("Capture Settings")); +- captureSettingsSection->setSeparator(true); +- addAction(captureSettingsSection.get()); +- +- includeMousePointerAction->setText(i18n("Include mouse pointer")); +- includeMousePointerAction->setToolTip(i18n("Show the mouse cursor in the screenshot image")); ++ auto includeMousePointerAction = addAction(i18nc("@option:check for screenshots", "Include mouse pointer")); ++ includeMousePointerAction->setToolTip(i18nc("@info:tooltip", "Show the mouse cursor in the screenshot image")); + includeMousePointerAction->setCheckable(true); + includeMousePointerAction->setChecked(Settings::includePointer()); +- connect(includeMousePointerAction.get(), &QAction::toggled, this, [](bool checked){ +- Settings::setIncludePointer(checked); +- }); +- connect(Settings::self(), &Settings::includePointerChanged, this, [this](){ ++ QObject::connect(includeMousePointerAction, &QAction::toggled, Settings::self(), &Settings::setIncludePointer); ++ QObject::connect(Settings::self(), &Settings::includePointerChanged, includeMousePointerAction, [includeMousePointerAction](){ + includeMousePointerAction->setChecked(Settings::includePointer()); + }); +- addAction(includeMousePointerAction.get()); + +- includeWindowDecorationsAction->setText(i18n("Include window titlebar and borders")); +- includeWindowDecorationsAction->setToolTip(i18n("Show the window title bar, the minimize/maximize/close buttons, and the window border")); ++ auto includeWindowDecorationsAction = addAction(i18nc("@option:check", "Include window titlebar and borders")); ++ includeWindowDecorationsAction->setToolTip(i18nc("@info:tooltip", "Show the window title bar, the minimize/maximize/close buttons, and the window border")); + includeWindowDecorationsAction->setCheckable(true); + includeWindowDecorationsAction->setChecked(Settings::includeDecorations()); +- connect(includeWindowDecorationsAction.get(), &QAction::toggled, this, [](bool checked){ +- Settings::setIncludeDecorations(checked); +- }); +- connect(Settings::self(), &Settings::includeDecorationsChanged, this, [this](){ ++ QObject::connect(includeWindowDecorationsAction, &QAction::toggled, Settings::self(), Settings::setIncludeDecorations); ++ QObject::connect(Settings::self(), &Settings::includeDecorationsChanged, includeWindowDecorationsAction, [includeWindowDecorationsAction](){ + includeWindowDecorationsAction->setChecked(Settings::includeDecorations()); + }); +- addAction(includeWindowDecorationsAction.get()); + +- includeWindowShadowAction->setText(i18n("Include window shadow")); +- includeWindowShadowAction->setToolTip(i18n("Show the window shadow")); ++ auto includeWindowShadowAction = addAction(i18nc("@option:check", "Include window shadow")); ++ includeWindowShadowAction->setToolTip(i18nc("@info:tooltip", "Show the window shadow")); + includeWindowShadowAction->setCheckable(true); + includeWindowShadowAction->setChecked(Settings::includeShadow()); +- connect(includeWindowShadowAction.get(), &QAction::toggled, this, [](bool checked) { +- Settings::setIncludeShadow(checked); +- }); +- connect(Settings::self(), &Settings::includeShadowChanged, this, [this]() { ++ QObject::connect(includeWindowShadowAction, &QAction::toggled, Settings::self(), &Settings::setIncludeShadow); ++ QObject::connect(Settings::self(), &Settings::includeShadowChanged, includeWindowShadowAction, [includeWindowShadowAction]() { + includeWindowShadowAction->setChecked(Settings::includeShadow()); + }); +- addAction(includeWindowShadowAction.get()); + +- onlyCapturePopupAction->setText(i18n("Capture the current pop-up only")); +- onlyCapturePopupAction->setToolTip( +- i18n("Capture only the current pop-up window (like a menu, tooltip etc).\n" +- "If disabled, the pop-up is captured along with the parent window")); +- onlyCapturePopupAction->setCheckable(true); +- onlyCapturePopupAction->setChecked(Settings::transientOnly()); +- connect(onlyCapturePopupAction.get(), &QAction::toggled, this, [](bool checked){ +- Settings::setTransientOnly(checked); +- }); +- connect(Settings::self(), &Settings::transientOnlyChanged, this, [this](){ ++ const bool hasTransientWithParent = SpectacleCore::instance()->imagePlatform()->supportedGrabModes().testFlag(ImagePlatform::TransientWithParent); ++ if (hasTransientWithParent) { ++ auto onlyCapturePopupAction = addAction(i18nc("@option:check", "Capture the current pop-up only")); ++ onlyCapturePopupAction->setToolTip( ++ i18nc("@info:tooltip", "Capture only the current pop-up window (like a menu, tooltip etc).\n" ++ "If disabled, the pop-up is captured along with the parent window")); ++ onlyCapturePopupAction->setCheckable(true); + onlyCapturePopupAction->setChecked(Settings::transientOnly()); +- }); +- addAction(onlyCapturePopupAction.get()); ++ QObject::connect(onlyCapturePopupAction, &QAction::toggled, Settings::self(), &Settings::setTransientOnly); ++ QObject::connect(Settings::self(), &Settings::transientOnlyChanged, onlyCapturePopupAction, [onlyCapturePopupAction](){ ++ onlyCapturePopupAction->setChecked(Settings::transientOnly()); ++ }); ++ } + +- quitAfterSaveAction->setText(i18n("Quit after manual Save or Copy")); +- quitAfterSaveAction->setToolTip(i18n("Quit Spectacle after manually saving or copying the image")); ++ auto quitAfterSaveAction = addAction(i18nc("@option:check", "Quit after manual Save or Copy")); ++ quitAfterSaveAction->setToolTip(i18nc("@info:tooltip", "Quit Spectacle after manually saving or copying the image")); + quitAfterSaveAction->setCheckable(true); + quitAfterSaveAction->setChecked(Settings::quitAfterSaveCopyExport()); +- connect(quitAfterSaveAction.get(), &QAction::toggled, this, [](bool checked){ +- Settings::setQuitAfterSaveCopyExport(checked); +- }); +- connect(Settings::self(), &Settings::quitAfterSaveCopyExportChanged, this, [this](){ ++ QObject::connect(quitAfterSaveAction, &QAction::toggled, Settings::self(), &Settings::setQuitAfterSaveCopyExport); ++ QObject::connect(Settings::self(), &Settings::quitAfterSaveCopyExportChanged, quitAfterSaveAction, [quitAfterSaveAction](){ + quitAfterSaveAction->setChecked(Settings::quitAfterSaveCopyExport()); + }); +- addAction(quitAfterSaveAction.get()); + + // add capture on click + const bool hasOnClick = SpectacleCore::instance()->imagePlatform()->supportedShutterModes().testFlag(ImagePlatform::OnClick); +- addSeparator()->setVisible(hasOnClick); +- captureOnClickAction->setText(i18n("Capture On Click")); +- captureOnClickAction->setCheckable(true); +- captureOnClickAction->setChecked(Settings::captureOnClick() && hasOnClick); +- captureOnClickAction->setVisible(hasOnClick); +- connect(captureOnClickAction.get(), &QAction::toggled, this, [this](bool checked){ +- Settings::setCaptureOnClick(checked); +- delayAction->setEnabled(!checked); +- }); +- connect(Settings::self(), &Settings::captureOnClickChanged, this, [this](){ ++ if (hasOnClick) { ++ addSeparator(); ++ auto captureOnClickAction = addAction(i18nc("@option:check", "Capture On Click")); ++ captureOnClickAction->setCheckable(true); + captureOnClickAction->setChecked(Settings::captureOnClick()); +- }); +- addAction(captureOnClickAction.get()); ++ QObject::connect(captureOnClickAction, &QAction::toggled, this, [this](bool checked){ ++ Settings::setCaptureOnClick(checked); ++ m_delayAction->setEnabled(!checked); ++ }); ++ QObject::connect(Settings::self(), &Settings::captureOnClickChanged, captureOnClickAction, [captureOnClickAction](){ ++ captureOnClickAction->setChecked(Settings::captureOnClick()); ++ }); ++ } + + // set up delay widget +- auto spinbox = delaySpinBox.get(); +- auto label = delayLabel.get(); +- label->setText(i18n("Delay:")); ++ auto spinbox = m_delaySpinBox.get(); ++ auto label = m_delayLabel.get(); ++ label->setText(i18nc("@label:spinbox", "Delay:")); + spinbox->setDecimals(1); + spinbox->setSingleStep(1.0); + spinbox->setMinimum(0.0); + spinbox->setMaximum(999); +- spinbox->setSpecialValueText(i18n("No Delay")); ++ spinbox->setSpecialValueText(i18nc("@item 0 delay special value", "No Delay")); + delayActionLayoutUpdate(); +- connect(spinbox, qOverload(&SmartSpinBox::valueChanged), this, [this](){ +- if (updatingDelayActionLayout) { ++ QObject::connect(spinbox, qOverload(&SmartSpinBox::valueChanged), this, [this](){ ++ if (m_updatingDelayActionLayout) { + return; + } +- Settings::setCaptureDelay(delaySpinBox->value()); ++ Settings::setCaptureDelay(m_delaySpinBox->value()); ++ }); ++ QObject::connect(Settings::self(), &Settings::captureDelayChanged, spinbox, [this](){ ++ m_delaySpinBox->setValue(Settings::captureDelay()); + }); +- connect(Settings::self(), &Settings::captureDelayChanged, this, [this](){ +- delaySpinBox->setValue(Settings::captureDelay()); ++ m_delayWidget->setLayout(m_delayLayout.get()); ++ m_delayLayout->addWidget(label); ++ m_delayLayout->addWidget(spinbox); ++ m_delayLayout->setAlignment(Qt::AlignLeft); ++ m_delayAction->setDefaultWidget(m_delayWidget.get()); ++ m_delayAction->setEnabled(!hasOnClick || !Settings::captureOnClick()); ++ addAction(m_delayAction.get()); ++ ++ addSection(i18nc("@title:menu", "Recording Settings")); ++ ++ auto videoIncludeMousePointerAction = addAction(i18nc("@option:check for recordings", "Include mouse pointer")); ++ videoIncludeMousePointerAction->setToolTip(i18nc("@info:tooltip", "Show the mouse cursor in the recording")); ++ videoIncludeMousePointerAction->setCheckable(true); ++ videoIncludeMousePointerAction->setChecked(Settings::videoIncludePointer()); ++ QObject::connect(videoIncludeMousePointerAction, &QAction::toggled, Settings::self(), &Settings::setVideoIncludePointer); ++ QObject::connect(Settings::self(), &Settings::videoIncludePointerChanged, videoIncludeMousePointerAction, [videoIncludeMousePointerAction](){ ++ videoIncludeMousePointerAction->setChecked(Settings::videoIncludePointer()); + }); +- delayWidget->setLayout(delayLayout.get()); +- delayLayout->addWidget(label); +- delayLayout->addWidget(spinbox); +- delayLayout->setAlignment(Qt::AlignLeft); +- delayAction->setDefaultWidget(delayWidget.get()); +- delayAction->setEnabled(!captureOnClickAction->isChecked()); +- addAction(delayAction.get()); ++ ++ addSeparator(); ++ ++ addAction(KStandardActions::preferences(this, &OptionsMenu::showPreferencesDialog, this)); ++ ++ addMenu(HelpMenu::instance()); ++ connect(this, &OptionsMenu::aboutToShow, ++ this, [this] { ++ setWidgetTransientParentToWidget(HelpMenu::instance(), this); ++ }); + } + + OptionsMenu *OptionsMenu::instance() +@@ -201,9 +178,26 @@ void OptionsMenu::showPreferencesDialog() + dialog->show(); + } + +-void OptionsMenu::setCaptureModeOptionsEnabled(bool enabled) ++void OptionsMenu::delayActionLayoutUpdate() + { +- captureModeOptionsEnabled = enabled; ++ // We can't block signals while doing this to prevent unnecessary ++ // processing because the spinbox has internal connections that need ++ // to work in order to get the correct size. ++ // We use our own guarding variable instead. ++ m_updatingDelayActionLayout = true; ++ m_delaySpinBox->setValue(m_delaySpinBox->maximum()); ++ m_delaySpinBox->setMinimumWidth(m_delaySpinBox->sizeHint().width()); ++ m_delaySpinBox->setValue(Settings::captureDelay()); ++ m_updatingDelayActionLayout = false; ++ ++ int menuHMargin = style()->pixelMetric(QStyle::PM_MenuHMargin); ++ int menuVMargin = style()->pixelMetric(QStyle::PM_MenuVMargin); ++ if (layoutDirection() == Qt::RightToLeft) { ++ m_delayLabel->setContentsMargins(0, 0, menuHMargin + m_delayLabel->fontMetrics().descent(), 0); ++ } else { ++ m_delayLabel->setContentsMargins(menuHMargin + m_delayLabel->fontMetrics().descent(), 0, 0, 0); ++ } ++ m_delayLayout->setContentsMargins(0, menuVMargin, 0, 0); + } + + void OptionsMenu::changeEvent(QEvent *event) +@@ -219,80 +213,30 @@ void OptionsMenu::changeEvent(QEvent *event) + QWidget::changeEvent(event); + } + +-void OptionsMenu::delayActionLayoutUpdate() ++void OptionsMenu::keyPressEvent(QKeyEvent *event) + { +- // We can't block signals while doing this to prevent unnecessary +- // processing because the spinbox has internal connections that need +- // to work in order to get the correct size. +- // We use our own guarding variable instead. +- updatingDelayActionLayout = true; +- delaySpinBox->setValue(delaySpinBox->maximum()); +- delaySpinBox->setMinimumWidth(delaySpinBox->sizeHint().width()); +- delaySpinBox->setValue(Settings::captureDelay()); +- updatingDelayActionLayout = false; +- +- int menuHMargin = style()->pixelMetric(QStyle::PM_MenuHMargin); +- int menuVMargin = style()->pixelMetric(QStyle::PM_MenuVMargin); +- if (layoutDirection() == Qt::RightToLeft) { +- delayLabel->setContentsMargins(0, 0, menuHMargin + delayLabel->fontMetrics().descent(), 0); +- } else { +- delayLabel->setContentsMargins(menuHMargin + delayLabel->fontMetrics().descent(), 0, 0, 0); ++ // Try to keep menu open when triggering checkable actions ++ const auto key = event->key(); ++ const auto action = activeAction(); ++ if (action && action->isEnabled() && action->isCheckable() // ++ && (key == Qt::Key_Return || key == Qt::Key_Enter // ++ || (key == Qt::Key_Space && style()->styleHint(QStyle::SH_Menu_SpaceActivatesItem, nullptr, this)))) { ++ action->trigger(); ++ event->accept(); ++ return; + } +- delayLayout->setContentsMargins(0, menuVMargin, 0, 0); ++ SpectacleMenu::keyPressEvent(event); + } + +-void OptionsMenu::updateCaptureModes() ++void OptionsMenu::mouseReleaseEvent(QMouseEvent *event) + { +- captureModeSection->setVisible(captureModeOptionsEnabled); +- if (!captureModeOptionsEnabled) { +- for (auto action : std::as_const(captureModeActions)) { +- captureModeGroup->removeAction(action); +- removeAction(action); +- action->deleteLater(); +- } +- captureModeActions.clear(); +- return; +- } +- +- if (!captureModeModel) { +- captureModeModel = std::make_unique(); +- } +- +- // Only make this conneciton once. +- // Can't be done in the constructor because captureModeModel is null at that time. +- if (!captureModesInitialized) { +- connect(captureModeModel.get(), &CaptureModeModel::captureModesChanged, this, [this]() { +- shouldUpdateCaptureModes = true; +- }); +- captureModesInitialized = true; +- } +- // avoid unnecessarily resetting actions +- if (!shouldUpdateCaptureModes) { ++ // Try to keep menu open when triggering checkable actions ++ const auto action = activeAction() == actionAt(event->position().toPoint()) ? activeAction() : nullptr; ++ if (action && action->isEnabled() && action->isCheckable()) { ++ action->trigger(); + return; + } +- shouldUpdateCaptureModes = false; +- for (auto action : std::as_const(captureModeActions)) { +- captureModeGroup->removeAction(action); +- removeAction(action); +- action->deleteLater(); +- } +- captureModeActions.clear(); +- for (int i = 0; i < captureModeModel->rowCount(); ++i) { +- auto index = captureModeModel->index(i); +- auto action = new QAction(this); +- captureModeActions.append(action); +- action->setText(captureModeModel->data(index, Qt::DisplayRole).toString()); +- const auto mode = captureModeModel->data(index, CaptureModeModel::CaptureModeRole).toInt(); +- action->setData(mode); +- action->setCheckable(true); +- if (!CaptureWindow::instances().empty() && !SpectacleCore::instance()->videoMode()) { +- action->setChecked(mode == CaptureModeModel::RectangularRegion); +- } else if (mode == Settings::captureMode()) { +- action->setChecked(true); +- } +- captureModeGroup->addAction(action); +- insertAction(captureSettingsSection.get(), action); +- } ++ SpectacleMenu::mouseReleaseEvent(event); + } + + #include "moc_OptionsMenu.cpp" +diff --git a/src/Gui/OptionsMenu.h b/src/Gui/OptionsMenu.h +index 5f87d097..b600f3f4 100644 +--- a/src/Gui/OptionsMenu.h ++++ b/src/Gui/OptionsMenu.h +@@ -6,20 +6,13 @@ + #define OPTIONSMENU_H + + #include "SpectacleMenu.h" +- + #include "Gui/SmartSpinBox.h" + +-#include + #include + #include +-#include + #include + #include + +-#include +- +-class CaptureModeModel; +- + /** + * A menu that allows choosing capture modes and related options. + */ +@@ -34,8 +27,6 @@ public: + + Q_SLOT void showPreferencesDialog(); + +- void setCaptureModeOptionsEnabled(bool enabled); +- + static OptionsMenu *create(QQmlEngine *engine, QJSEngine *) + { + auto inst = instance(); +@@ -47,37 +38,18 @@ public: + + protected: + void changeEvent(QEvent *event) override; ++ void keyPressEvent(QKeyEvent *event) override; ++ void mouseReleaseEvent(QMouseEvent *event) override; + +-private: + explicit OptionsMenu(QWidget *parent = nullptr); + + void delayActionLayoutUpdate(); +- Q_SLOT void updateCaptureModes(); +- +- QList captureModeActions; +- const std::unique_ptr captureModeSection; +- const std::unique_ptr captureModeGroup; +- const std::unique_ptr captureSettingsSection; +- const std::unique_ptr includeMousePointerAction; +- const std::unique_ptr includeWindowDecorationsAction; +- const std::unique_ptr includeWindowShadowAction; +- const std::unique_ptr onlyCapturePopupAction; +- const std::unique_ptr quitAfterSaveAction; +- const std::unique_ptr captureOnClickAction; +- const std::unique_ptr delayAction; +- const std::unique_ptr delayWidget; +- const std::unique_ptr delayLayout; +- const std::unique_ptr delayLabel; +- const std::unique_ptr delaySpinBox; +- +- std::unique_ptr captureModeModel; +- +- bool captureModesInitialized = false; +- bool shouldUpdateCaptureModes = true; +- bool updatingDelayActionLayout = false; +- bool captureModeOptionsEnabled = true; +- +- friend class OptionsMenuSingleton; ++ const std::unique_ptr m_delayAction; ++ const std::unique_ptr m_delayWidget; ++ const std::unique_ptr m_delayLayout; ++ const std::unique_ptr m_delayLabel; ++ const std::unique_ptr m_delaySpinBox; ++ bool m_updatingDelayActionLayout = false; + }; + + #endif // OPTIONSMENU_H +diff --git a/src/Gui/OptionsMenuButton.qml b/src/Gui/OptionsMenuButton.qml +new file mode 100644 +index 00000000..5a86ff96 +--- /dev/null ++++ b/src/Gui/OptionsMenuButton.qml +@@ -0,0 +1,14 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick ++import org.kde.spectacle.private ++ ++TtToolButton { ++ icon.name: "configure" ++ text: i18nc("@action", "Options") ++ down: pressed || OptionsMenu.visible ++ Accessible.role: Accessible.ButtonMenu ++ onPressed: OptionsMenu.popup(this) ++} +diff --git a/src/Gui/Outline.qml b/src/Gui/Outline.qml +index 158e356f..85d9f6ca 100644 +--- a/src/Gui/Outline.qml ++++ b/src/Gui/Outline.qml +@@ -17,6 +17,7 @@ Shape { + property alias joinStyle: shapePath.joinStyle + property alias svgPath: pathSvg.path + property alias pathScale: shapePath.scale ++ property alias pathHints: shapePath.pathHints + + // Get a rectangular SVG path + function rectanglePath(x, y, w, h) { +diff --git a/src/Gui/RecordAction.qml b/src/Gui/RecordAction.qml +new file mode 100644 +index 00000000..7c7a83df +--- /dev/null ++++ b/src/Gui/RecordAction.qml +@@ -0,0 +1,13 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick.Templates as T ++import org.kde.spectacle.private ++ ++T.Action { ++ enabled: SpectacleCore.videoMode ++ icon.name: "media-record" ++ text: i18nc("@action start recording", "Record") ++ onTriggered: contextWindow.accept() ++} +diff --git a/src/Gui/RecordingModeButtonsColumn.qml b/src/Gui/RecordingModeButtonsColumn.qml +index 58644a97..2737f620 100644 +--- a/src/Gui/RecordingModeButtonsColumn.qml ++++ b/src/Gui/RecordingModeButtonsColumn.qml +@@ -12,7 +12,7 @@ import org.kde.spectacle.private + ColumnLayout { + spacing: Kirigami.Units.mediumSpacing + Repeater { +- model: RecordingModeModel { } ++ model: RecordingModeModel + delegate: QQC.Button { + id: button + Layout.fillWidth: true +diff --git a/src/Gui/RecordingModeMenu.cpp b/src/Gui/RecordingModeMenu.cpp +new file mode 100644 +index 00000000..d7451fa7 +--- /dev/null ++++ b/src/Gui/RecordingModeMenu.cpp +@@ -0,0 +1,65 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++#include "RecordingModeMenu.h" ++#include "RecordingModeModel.h" ++#include "SpectacleCore.h" ++#include "ShortcutActions.h" ++#include ++ ++using namespace Qt::StringLiterals; ++ ++static QPointer s_instance = nullptr; ++ ++RecordingModeMenu::RecordingModeMenu(QWidget *parent) ++ : SpectacleMenu(i18nc("@title:menu", "Recording Modes"), parent) ++{ ++ auto addModes = [this] { ++ clear(); ++ auto model = RecordingModeModel::instance(); ++ for (auto idx = model->index(0); idx.isValid(); idx = idx.siblingAtRow(idx.row() + 1)) { ++ const auto action = addAction(idx.data(Qt::DisplayRole).toString()); ++ const auto mode = idx.data(RecordingModeModel::RecordingModeRole).value(); ++ QAction *globalAction = nullptr; ++ auto globalShortcuts = [](QAction *globalAction) { ++ if (!globalAction) { ++ return QList{}; ++ } ++ auto component = ShortcutActions::self()->componentName(); ++ auto id = globalAction->objectName(); ++ return KGlobalAccel::self()->globalShortcut(component, id); ++ }; ++ switch (mode) { ++ case VideoPlatform::Region: ++ globalAction = ShortcutActions::self()->recordRegionAction(); ++ break; ++ case VideoPlatform::Screen: ++ globalAction = ShortcutActions::self()->recordScreenAction(); ++ break; ++ case VideoPlatform::Window: ++ globalAction = ShortcutActions::self()->recordWindowAction(); ++ break; ++ default: ++ break; ++ } ++ action->setShortcuts(globalShortcuts(globalAction)); ++ auto onTriggered = [mode] { ++ SpectacleCore::instance()->startRecording(mode); ++ }; ++ connect(action, &QAction::triggered, action, onTriggered); ++ } ++ }; ++ addModes(); ++ connect(RecordingModeModel::instance(), &RecordingModeModel::recordingModesChanged, this, addModes); ++} ++ ++RecordingModeMenu *RecordingModeMenu::instance() ++{ ++ if (!s_instance) { ++ s_instance = new RecordingModeMenu; ++ } ++ return s_instance; ++} ++ ++#include "moc_RecordingModeMenu.cpp" +diff --git a/src/Gui/RecordingModeMenu.h b/src/Gui/RecordingModeMenu.h +new file mode 100644 +index 00000000..fe8f0a71 +--- /dev/null ++++ b/src/Gui/RecordingModeMenu.h +@@ -0,0 +1,30 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++#pragma once ++ ++#include "SpectacleMenu.h" ++#include ++ ++class RecordingModeMenu : public SpectacleMenu ++{ ++ Q_OBJECT ++ QML_ELEMENT ++ QML_SINGLETON ++ ++public: ++ static RecordingModeMenu *instance(); ++ ++ static RecordingModeMenu *create(QQmlEngine *engine, QJSEngine *) ++ { ++ auto inst = instance(); ++ Q_ASSERT(inst); ++ Q_ASSERT(inst->thread() == engine->thread()); ++ QJSEngine::setObjectOwnership(inst, QJSEngine::CppOwnership); ++ return inst; ++ } ++ ++private: ++ explicit RecordingModeMenu(QWidget *parent = nullptr); ++}; +diff --git a/src/Gui/RecordingModeMenuButton.qml b/src/Gui/RecordingModeMenuButton.qml +new file mode 100644 +index 00000000..54d40666 +--- /dev/null ++++ b/src/Gui/RecordingModeMenuButton.qml +@@ -0,0 +1,15 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick ++import QtQuick.Controls as QQC ++import org.kde.spectacle.private ++ ++TtToolButton { ++ icon.name: "camera-video" ++ text: i18nc("@action select new recording mode", "New Recording") ++ down: pressed || RecordingModeMenu.visible ++ Accessible.role: Accessible.ButtonMenu ++ onPressed: RecordingModeMenu.popup(this) ++} +diff --git a/src/Gui/RecordingView.qml b/src/Gui/RecordingView.qml +index fc7b6040..a4e747ae 100644 +--- a/src/Gui/RecordingView.qml ++++ b/src/Gui/RecordingView.qml +@@ -87,13 +87,6 @@ FocusScope { + id: tbHoverHandler + } + +- component ToolButton: QQC.ToolButton { +- display: QQC.ToolButton.IconOnly +- QQC.ToolTip.text: text +- QQC.ToolTip.visible: (hovered || pressed) && display === QQC.ToolButton.IconOnly +- QQC.ToolTip.delay: Kirigami.Units.toolTipDelay +- } +- + FloatingToolBar { + id: toolBar + anchors.left: parent.left +@@ -105,7 +98,7 @@ FocusScope { + enabled: root.hasContent + contentItem: RowLayout { + spacing: parent.spacing +- ToolButton { ++ TtToolButton { + id: playPauseButton + containmentMask: Item { + parent: playPauseButton +diff --git a/src/Gui/SaveAction.qml b/src/Gui/SaveAction.qml +new file mode 100644 +index 00000000..084bda25 +--- /dev/null ++++ b/src/Gui/SaveAction.qml +@@ -0,0 +1,15 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick.Templates as T ++import org.kde.spectacle.private ++ ++T.Action { ++ // We don't use this in video mode because the video is already ++ // automatically saved and you can't edit the video. ++ enabled: !SpectacleCore.videoMode ++ icon.name: "document-save" ++ text: i18nc("@action", "Save") ++ onTriggered: contextWindow.save() ++} +diff --git a/src/Gui/SaveAsAction.qml b/src/Gui/SaveAsAction.qml +new file mode 100644 +index 00000000..371dfeca +--- /dev/null ++++ b/src/Gui/SaveAsAction.qml +@@ -0,0 +1,11 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick.Templates as T ++ ++T.Action { ++ icon.name: "document-save-as" ++ text: i18nc("@action", "Save As…") ++ onTriggered: contextWindow.saveAs() ++} +diff --git a/src/Gui/ScreenshotModeMenu.cpp b/src/Gui/ScreenshotModeMenu.cpp +new file mode 100644 +index 00000000..341ae7ec +--- /dev/null ++++ b/src/Gui/ScreenshotModeMenu.cpp +@@ -0,0 +1,74 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++#include "ScreenshotModeMenu.h" ++#include "CaptureModeModel.h" ++#include "SpectacleCore.h" ++#include "ShortcutActions.h" ++#include ++ ++using namespace Qt::StringLiterals; ++ ++static QPointer s_instance = nullptr; ++ ++ScreenshotModeMenu::ScreenshotModeMenu(QWidget *parent) ++ : SpectacleMenu(i18nc("@title:menu", "Screenshot Modes"), parent) ++{ ++ auto addModes = [this] { ++ clear(); ++ auto model = CaptureModeModel::instance(); ++ for (auto idx = model->index(0); idx.isValid(); idx = idx.siblingAtRow(idx.row() + 1)) { ++ const auto action = addAction(idx.data(Qt::DisplayRole).toString()); ++ const auto mode = idx.data(CaptureModeModel::CaptureModeRole).value(); ++ QAction *globalAction = nullptr; ++ auto globalShortcuts = [](QAction *globalAction) { ++ if (!globalAction) { ++ return QList{}; ++ } ++ auto component = ShortcutActions::self()->componentName(); ++ auto id = globalAction->objectName(); ++ return KGlobalAccel::self()->globalShortcut(component, id); ++ }; ++ switch (mode) { ++ case CaptureModeModel::RectangularRegion: ++ globalAction = ShortcutActions::self()->regionAction(); ++ break; ++ case CaptureModeModel::AllScreens: ++ globalAction = ShortcutActions::self()->fullScreenAction(); ++ break; ++ case CaptureModeModel::CurrentScreen: ++ globalAction = ShortcutActions::self()->currentScreenAction(); ++ break; ++ case CaptureModeModel::ActiveWindow: ++ globalAction = ShortcutActions::self()->activeWindowAction(); ++ break; ++ case CaptureModeModel::WindowUnderCursor: ++ globalAction = ShortcutActions::self()->windowUnderCursorAction(); ++ break; ++ case CaptureModeModel::FullScreen: ++ globalAction = ShortcutActions::self()->fullScreenAction(); ++ break; ++ default: ++ break; ++ } ++ action->setShortcuts(globalShortcuts(globalAction)); ++ auto onTriggered = [mode] { ++ SpectacleCore::instance()->takeNewScreenshot(mode); ++ }; ++ connect(action, &QAction::triggered, action, onTriggered); ++ } ++ }; ++ addModes(); ++ connect(CaptureModeModel::instance(), &CaptureModeModel::captureModesChanged, this, addModes); ++} ++ ++ScreenshotModeMenu *ScreenshotModeMenu::instance() ++{ ++ if (!s_instance) { ++ s_instance = new ScreenshotModeMenu; ++ } ++ return s_instance; ++} ++ ++#include "moc_ScreenshotModeMenu.cpp" +diff --git a/src/Gui/ScreenshotModeMenu.h b/src/Gui/ScreenshotModeMenu.h +new file mode 100644 +index 00000000..387a05db +--- /dev/null ++++ b/src/Gui/ScreenshotModeMenu.h +@@ -0,0 +1,30 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++#pragma once ++ ++#include "SpectacleMenu.h" ++#include ++ ++class ScreenshotModeMenu : public SpectacleMenu ++{ ++ Q_OBJECT ++ QML_ELEMENT ++ QML_SINGLETON ++ ++public: ++ static ScreenshotModeMenu *instance(); ++ ++ static ScreenshotModeMenu *create(QQmlEngine *engine, QJSEngine *) ++ { ++ auto inst = instance(); ++ Q_ASSERT(inst); ++ Q_ASSERT(inst->thread() == engine->thread()); ++ QJSEngine::setObjectOwnership(inst, QJSEngine::CppOwnership); ++ return inst; ++ } ++ ++private: ++ explicit ScreenshotModeMenu(QWidget *parent = nullptr); ++}; +diff --git a/src/Gui/ScreenshotModeMenuButton.qml b/src/Gui/ScreenshotModeMenuButton.qml +new file mode 100644 +index 00000000..5440f17d +--- /dev/null ++++ b/src/Gui/ScreenshotModeMenuButton.qml +@@ -0,0 +1,15 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick ++import QtQuick.Controls as QQC ++import org.kde.spectacle.private ++ ++TtToolButton { ++ icon.name: "camera-photo" ++ text: i18nc("@action select new screenshot mode", "New Screenshot") ++ down: pressed || ScreenshotModeMenu.visible ++ Accessible.role: Accessible.ButtonMenu ++ onPressed: ScreenshotModeMenu.popup(this) ++} +diff --git a/src/Gui/SettingsDialog/GeneralOptions.ui b/src/Gui/SettingsDialog/GeneralOptions.ui +index 474ae28d..b7d6ddb5 100644 +--- a/src/Gui/SettingsDialog/GeneralOptions.ui ++++ b/src/Gui/SettingsDialog/GeneralOptions.ui +@@ -20,6 +20,11 @@ + + + ++ ++ ++ Take rectangular screenshot ++ ++ + + + Take full screen screenshot +diff --git a/src/Gui/SettingsDialog/spectacle.kcfg b/src/Gui/SettingsDialog/spectacle.kcfg +index 3d916aee..f58f28fc 100644 +--- a/src/Gui/SettingsDialog/spectacle.kcfg ++++ b/src/Gui/SettingsDialog/spectacle.kcfg +@@ -15,11 +15,12 @@ + + + ++ + + + + +- TakeFullscreenScreenshot ++ TakeRectangularScreenshot + + + +diff --git a/src/Gui/TtToolButton.qml b/src/Gui/TtToolButton.qml +new file mode 100644 +index 00000000..31de1309 +--- /dev/null ++++ b/src/Gui/TtToolButton.qml +@@ -0,0 +1,16 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick ++import QtQuick.Controls as QQC ++import org.kde.kirigami as Kirigami ++import org.kde.spectacle.private ++ ++QQC.ToolButton { ++ implicitHeight: QmlUtils.iconTextButtonHeight ++ width: display === QQC.ToolButton.IconOnly ? height : implicitWidth ++ QQC.ToolTip.text: text ++ QQC.ToolTip.visible: (hovered || pressed) && display === QQC.ToolButton.IconOnly ++ QQC.ToolTip.delay: Kirigami.Units.toolTipDelay ++} +diff --git a/src/Gui/UndoRedoGroup.qml b/src/Gui/UndoRedoGroup.qml +index 83fa44fa..19deb798 100644 +--- a/src/Gui/UndoRedoGroup.qml ++++ b/src/Gui/UndoRedoGroup.qml +@@ -22,7 +22,7 @@ Grid { + NumberAnimation { properties: "x,y"; duration: Kirigami.Units.longDuration; easing.type: Easing.OutCubic } + } + +- QQC.ToolButton { ++ TtToolButton { + id: undoButton + enabled: SpectacleCore.annotationDocument.undoStackDepth > 0 + height: root.buttonHeight +@@ -31,13 +31,10 @@ Grid { + text: i18n("Undo") + icon.name: "edit-undo" + autoRepeat: true +- QQC.ToolTip.text: text +- QQC.ToolTip.visible: hovered || pressed +- QQC.ToolTip.delay: Kirigami.Units.toolTipDelay + onClicked: SpectacleCore.annotationDocument.undo() + } + +- QQC.ToolButton { ++ TtToolButton { + enabled: SpectacleCore.annotationDocument.redoStackDepth > 0 + height: root.buttonHeight + focusPolicy: root.focusPolicy +@@ -45,9 +42,6 @@ Grid { + text: i18n("Redo") + icon.name: "edit-redo" + autoRepeat: true +- QQC.ToolTip.text: text +- QQC.ToolTip.visible: hovered || pressed +- QQC.ToolTip.delay: Kirigami.Units.toolTipDelay + onClicked: SpectacleCore.annotationDocument.redo() + } + +diff --git a/src/Gui/VideoCaptureOverlay.qml b/src/Gui/VideoCaptureOverlay.qml +deleted file mode 100644 +index 09ad4d61..00000000 +--- a/src/Gui/VideoCaptureOverlay.qml ++++ /dev/null +@@ -1,243 +0,0 @@ +-/* SPDX-FileCopyrightText: 2023 Noah Davis +- * SPDX-License-Identifier: LGPL-2.0-or-later +- */ +- +-import QtQuick +-import QtQuick.Shapes +-import QtQuick.Window +-import QtQuick.Layouts +-import QtQuick.Controls as QQC +-import org.kde.kirigami as Kirigami +-import org.kde.spectacle.private +- +-MouseArea { +- id: root +- readonly property rect viewportRect: Geometry.mapFromPlatformRect(screenToFollow.geometry, +- screenToFollow.devicePixelRatio) +- focus: true +- acceptedButtons: Qt.LeftButton | Qt.RightButton +- hoverEnabled: true +- LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft +- LayoutMirroring.childrenInherit: true +- anchors.fill: parent +- enabled: !SpectacleCore.videoPlatform.isRecording +- +- component Overlay: Rectangle { +- color: Settings.useLightMaskColor ? "white" : "black" +- opacity: if (SpectacleCore.videoPlatform.isRecording) { +- return 0 +- } else if (SelectionEditor.selection.empty) { +- return 0.25 +- } else { +- return 0.5 +- } +- LayoutMirroring.enabled: false +- Behavior on opacity { +- NumberAnimation { +- duration: Kirigami.Units.longDuration +- easing.type: Easing.OutCubic +- } +- } +- } +- Overlay { // top / full overlay when nothing selected +- id: topOverlay +- anchors.top: parent.top +- anchors.left: parent.left +- anchors.right: parent.right +- anchors.bottom: selectionRectangle.visible ? selectionRectangle.top : parent.bottom +- } +- Overlay { // bottom +- id: bottomOverlay +- anchors.left: parent.left +- anchors.top: selectionRectangle.visible ? selectionRectangle.bottom : undefined +- anchors.right: parent.right +- anchors.bottom: parent.bottom +- visible: selectionRectangle.visible && height > 0 +- } +- Overlay { // left +- anchors { +- left: topOverlay.left +- top: topOverlay.bottom +- right: selectionRectangle.visible ? selectionRectangle.left : undefined +- bottom: bottomOverlay.top +- } +- visible: selectionRectangle.visible && height > 0 && width > 0 +- } +- Overlay { // right +- anchors { +- left: selectionRectangle.visible ? selectionRectangle.right : undefined +- top: topOverlay.bottom +- right: topOverlay.right +- bottom: bottomOverlay.top +- } +- visible: selectionRectangle.visible && height > 0 && width > 0 +- } +- +- DashedOutline { +- id: selectionRectangle +- readonly property real margin: strokeWidth + 1 / Screen.devicePixelRatio +- dashSvgPath: SpectacleCore.videoPlatform.isRecording ? svgPath : "" +- visible: !SelectionEditor.selection.empty +- && Geometry.rectIntersects(Qt.rect(x,y,width,height), Qt.rect(0,0,parent.width, parent.height)) +- strokeWidth: dprRound(1) +- strokeColor: palette.active.highlight +- dashColor: SpectacleCore.videoPlatform.isRecording ? palette.active.base : strokeColor +- // We need to be a bit careful about staying out of the recorded area +- x: dprFloor(SelectionEditor.selection.x - margin - root.viewportRect.x) +- y: dprFloor(SelectionEditor.selection.y - margin - root.viewportRect.y) +- width: dprCeil(SelectionEditor.selection.right + margin - root.viewportRect.x) - x +- height: dprCeil(SelectionEditor.selection.bottom + margin - root.viewportRect.y) - y +- } +- +- Item { +- x: -root.viewportRect.x +- y: -root.viewportRect.y +- enabled: selectionRectangle.enabled +- visible: !SpectacleCore.videoPlatform.isRecording +- +- component SelectionHandle: Handle { +- id: handle +- visible: enabled && selectionRectangle.visible +- && SelectionEditor.dragLocation === SelectionEditor.None +- && Geometry.rectIntersects(Qt.rect(x,y,width,height), root.viewportRect) +- fillColor: selectionRectangle.strokeColor +- width: Kirigami.Units.gridUnit +- height: width +- transform: Translate { +- x: handle.xOffsetForEdges(selectionRectangle.strokeWidth) +- y: handle.yOffsetForEdges(selectionRectangle.strokeWidth) +- } +- } +- +- SelectionHandle { +- edges: Qt.TopEdge | Qt.LeftEdge +- x: dprFloor(SelectionEditor.handlesRect.x) +- y: dprFloor(SelectionEditor.handlesRect.y) +- } +- SelectionHandle { +- edges: Qt.LeftEdge +- x: dprFloor(SelectionEditor.handlesRect.x) +- y: dprRound(SelectionEditor.handlesRect.y + SelectionEditor.handlesRect.height/2 - height/2) +- } +- SelectionHandle { +- edges: Qt.LeftEdge | Qt.BottomEdge +- x: dprFloor(SelectionEditor.handlesRect.x) +- y: dprCeil(SelectionEditor.handlesRect.y + SelectionEditor.handlesRect.height - height) +- } +- SelectionHandle { +- edges: Qt.TopEdge +- x: dprRound(SelectionEditor.handlesRect.x + SelectionEditor.handlesRect.width/2 - width/2) +- y: dprFloor(SelectionEditor.handlesRect.y) +- } +- SelectionHandle { +- edges: Qt.BottomEdge +- x: dprRound(SelectionEditor.handlesRect.x + SelectionEditor.handlesRect.width/2 - width/2) +- y: dprCeil(SelectionEditor.handlesRect.y + SelectionEditor.handlesRect.height - height) +- } +- SelectionHandle { +- edges: Qt.RightEdge +- x: dprCeil(SelectionEditor.handlesRect.x + SelectionEditor.handlesRect.width - width) +- y: dprRound(SelectionEditor.handlesRect.y + SelectionEditor.handlesRect.height/2 - height/2) +- } +- SelectionHandle { +- edges: Qt.TopEdge | Qt.RightEdge +- x: dprCeil(SelectionEditor.handlesRect.x + SelectionEditor.handlesRect.width - width) +- y: dprFloor(SelectionEditor.handlesRect.y) +- } +- SelectionHandle { +- edges: Qt.RightEdge | Qt.BottomEdge +- x: dprCeil(SelectionEditor.handlesRect.x + SelectionEditor.handlesRect.width - width) +- y: dprCeil(SelectionEditor.handlesRect.y + SelectionEditor.handlesRect.height - height) +- } +- } +- +- Item { // separate item because it needs to be above the stuff defined above +- visible: !SpectacleCore.videoPlatform.isRecording +- width: SelectionEditor.screensRect.width +- height: SelectionEditor.screensRect.height +- x: -root.viewportRect.x +- y: -root.viewportRect.y +- +- // Size ToolTip +- SizeLabel { +- id: ssToolTip +- readonly property int valignment: { +- if (SelectionEditor.selection.empty) { +- return Qt.AlignVCenter +- } +- const margin = Kirigami.Units.mediumSpacing * 2 +- const w = width + margin +- const h = height + margin +- if (SelectionEditor.handlesRect.top >= h) { +- return Qt.AlignTop +- } else if (SelectionEditor.screensRect.height - SelectionEditor.handlesRect.bottom >= h) { +- return Qt.AlignBottom +- } else { +- // At the bottom of the inside of the selection rect. +- return Qt.AlignBaseline +- } +- } +- readonly property bool normallyVisible: !SelectionEditor.selection.empty +- Binding on x { +- value: contextWindow.dprRound(SelectionEditor.selection.horizontalCenter - ssToolTip.width / 2) +- when: ssToolTip.normallyVisible +- restoreMode: Binding.RestoreNone +- } +- Binding on y { +- value: { +- let v = 0 +- if (ssToolTip.valignment & Qt.AlignBaseline) { +- v = Math.min(SelectionEditor.selection.bottom, SelectionEditor.handlesRect.bottom - Kirigami.Units.gridUnit) +- - ssToolTip.height - Kirigami.Units.mediumSpacing * 2 +- } else if (ssToolTip.valignment & Qt.AlignTop) { +- v = SelectionEditor.handlesRect.top +- - ssToolTip.height - Kirigami.Units.mediumSpacing * 2 +- } else if (ssToolTip.valignment & Qt.AlignBottom) { +- v = SelectionEditor.handlesRect.bottom + Kirigami.Units.mediumSpacing * 2 +- } else { +- v = (root.height - ssToolTip.height) / 2 - parent.y +- } +- return contextWindow.dprRound(v) +- } +- when: ssToolTip.normallyVisible +- restoreMode: Binding.RestoreNone +- } +- visible: opacity > 0 +- opacity: ssToolTip.normallyVisible +- && Geometry.rectIntersects(Qt.rect(x,y,width,height), root.viewportRect) +- Behavior on opacity { +- NumberAnimation { +- duration: Kirigami.Units.longDuration +- easing.type: Easing.OutCubic +- } +- } +- size: Geometry.rawSize(SelectionEditor.selection.size, SelectionEditor.devicePixelRatio) // TODO: real pixel size on wayland +- padding: Kirigami.Units.mediumSpacing * 2 +- topPadding: padding - QmlUtils.fontMetrics.descent +- bottomPadding: topPadding +- background: FloatingBackground { +- implicitWidth: Math.ceil(parent.contentWidth) + parent.leftPadding + parent.rightPadding +- implicitHeight: Math.ceil(parent.contentHeight) + parent.topPadding + parent.bottomPadding +- color: Qt.rgba(parent.palette.window.r, +- parent.palette.window.g, +- parent.palette.window.b, 0.85) +- border.color: Qt.rgba(parent.palette.windowText.r, +- parent.palette.windowText.g, +- parent.palette.windowText.b, 0.2) +- border.width: contextWindow.dprRound(1) +- } +- } +- } +- +- Connections { +- target: contextWindow +- function onVisibilityChanged(visibility) { +- if (visibility !== Window.Hidden && visibility !== Window.Minimized) { +- contextWindow.raise() +- if (root.containsMouse) { +- contextWindow.requestActivate() +- } +- } +- } +- } +-} +diff --git a/src/Platforms/ImagePlatform.h b/src/Platforms/ImagePlatform.h +index 7e51db95..de766f52 100644 +--- a/src/Platforms/ImagePlatform.h ++++ b/src/Platforms/ImagePlatform.h +@@ -57,6 +57,7 @@ Q_SIGNALS: + void newCroppableScreenshotTaken(const QImage &image); + + void newScreenshotFailed(const QString &message = {}); ++ void newScreenshotCanceled(); + }; + + Q_DECLARE_OPERATORS_FOR_FLAGS(ImagePlatform::GrabModes) +diff --git a/src/Platforms/ImagePlatformKWin.cpp b/src/Platforms/ImagePlatformKWin.cpp +index 237130c9..67fc7375 100644 +--- a/src/Platforms/ImagePlatformKWin.cpp ++++ b/src/Platforms/ImagePlatformKWin.cpp +@@ -468,6 +468,8 @@ void ImagePlatformKWin::trackSource(ScreenShotSource2 *source) + Q_EMIT newScreenshotTaken(std::get(result)); + } else if (index == ResultVariant::ErrorString) { + Q_EMIT newScreenshotFailed(std::get(result)); ++ } else if (index == ResultVariant::CanceledState) { ++ Q_EMIT newScreenshotCanceled(); + } + }); + } +diff --git a/src/RecordingModeModel.cpp b/src/RecordingModeModel.cpp +index 4388daa8..220dcd7e 100644 +--- a/src/RecordingModeModel.cpp ++++ b/src/RecordingModeModel.cpp +@@ -18,6 +18,16 @@ + + using namespace Qt::StringLiterals; + ++static std::unique_ptr s_instance; ++ ++RecordingModeModel *RecordingModeModel::instance() ++{ ++ if (!s_instance) { ++ s_instance = std::make_unique(); ++ } ++ return s_instance.get(); ++} ++ + RecordingModeModel::RecordingModeModel(QObject *parent) + : QAbstractListModel(parent) + { +@@ -71,6 +81,7 @@ int RecordingModeModel::indexOfRecordingMode(VideoPlatform::RecordingMode mode) + + void RecordingModeModel::setRecordingModes(VideoPlatform::RecordingModes modes) + { ++ auto count = m_data.size(); + m_data.clear(); + if (modes & VideoPlatform::Region) { + m_data.append({VideoPlatform::Region, recordingModeLabel(VideoPlatform::Region)}); +@@ -81,7 +92,10 @@ void RecordingModeModel::setRecordingModes(VideoPlatform::RecordingModes modes) + if (modes & VideoPlatform::Window) { + m_data.append({VideoPlatform::Window, recordingModeLabel(VideoPlatform::Window)}); + } +- Q_EMIT countChanged(); ++ Q_EMIT recordingModesChanged(); ++ if (count != m_data.size()) { ++ Q_EMIT countChanged(); ++ } + } + + QString RecordingModeModel::recordingModeLabel(VideoPlatform::RecordingMode mode) +diff --git a/src/RecordingModeModel.h b/src/RecordingModeModel.h +index 383f98f4..e56492ae 100644 +--- a/src/RecordingModeModel.h ++++ b/src/RecordingModeModel.h +@@ -7,15 +7,28 @@ + #include "Platforms/VideoPlatform.h" + + #include ++#include + + class RecordingModeModel : public QAbstractListModel + { + Q_OBJECT + QML_ELEMENT ++ QML_SINGLETON + Q_PROPERTY(int count READ rowCount NOTIFY countChanged FINAL) + public: + explicit RecordingModeModel(QObject *parent = nullptr); + ++ static RecordingModeModel *instance(); ++ ++ static RecordingModeModel *create(QQmlEngine *engine, QJSEngine *) ++ { ++ auto inst = instance(); ++ Q_ASSERT(inst); ++ Q_ASSERT(inst->thread() == engine->thread()); ++ QJSEngine::setObjectOwnership(inst, QJSEngine::CppOwnership); ++ return inst; ++ } ++ + enum { + RecordingModeRole = Qt::UserRole + 1, + }; +@@ -32,6 +45,7 @@ public: + + Q_SIGNALS: + void countChanged(); ++ void recordingModesChanged(); + + private: + struct Item { +diff --git a/src/SpectacleCore.cpp b/src/SpectacleCore.cpp +index bfbb3085..820852df 100644 +--- a/src/SpectacleCore.cpp ++++ b/src/SpectacleCore.cpp +@@ -128,6 +128,7 @@ SpectacleCore::SpectacleCore(QObject *parent) + connect(SelectionEditor::instance(), &SelectionEditor::accepted, + this, [this](const QRectF &rect, const ExportManager::Actions &actions){ + ExportManager::instance()->updateTimestamp(); ++ m_returnToViewer = m_startMode == StartMode::Gui; + if (m_videoMode) { + const auto captureWindows = CaptureWindow::instances(); + SpectacleWindow::setVisibilityForAll(QWindow::Hidden); +@@ -160,10 +161,14 @@ SpectacleCore::SpectacleCore(QObject *parent) + deleteWindows(); + m_annotationDocument->cropCanvas(rect); + syncExportImage(); ++ const auto &exportActions = actions & ExportManager::AnyAction ? actions : autoExportActions(); ++ const bool willQuit = exportActions.testFlag(ExportManager::AnyAction) // ++ && exportActions.testFlag(ExportManager::UserAction) // ++ && Settings::quitAfterSaveCopyExport(); ++ m_returnToViewer &= !willQuit; + showViewerIfGuiMode(); + SpectacleWindow::setTitleForAll(SpectacleWindow::Unsaved); + ExportManager::instance()->scanQRCode(); +- const auto &exportActions = actions & ExportManager::AnyAction ? actions : autoExportActions(); + ExportManager::instance()->exportImage(exportActions, outputUrl()); + } + }); +@@ -173,6 +178,7 @@ SpectacleCore::SpectacleCore(QObject *parent) + m_annotationDocument->setBaseImage(image); + setExportImage(image); + ExportManager::instance()->updateTimestamp(); ++ m_returnToViewer = true; + showViewerIfGuiMode(); + SpectacleWindow::setTitleForAll(SpectacleWindow::Unsaved); + ExportManager::instance()->scanQRCode(); +@@ -237,6 +243,21 @@ SpectacleCore::SpectacleCore(QObject *parent) + auto uiMessage = i18nc("@info", "An error occurred while taking a screenshot."); + onScreenshotOrRecordingFailed(message, uiMessage, &SpectacleCore::dbusScreenshotFailed, &ViewerWindow::showScreenshotFailedMessage); + }); ++ connect(imagePlatform, &ImagePlatform::newScreenshotCanceled, this, [this]() { ++ if (m_startMode != StartMode::Gui || !m_returnToViewer || isGuiNull()) { ++ Q_EMIT allDone(); ++ return; ++ } ++ SpectacleWindow::setTitleForAll(SpectacleWindow::Previous); ++ const auto windows = SpectacleWindow::instances(); ++ if (windows.empty()) { ++ initViewerWindow(ViewerWindow::Image); ++ return; ++ } ++ for (auto w : windows) { ++ w->setVisible(true); ++ } ++ }); + + auto videoPlatform = m_videoPlatform.get(); + connect(videoPlatform, &VideoPlatform::recordingChanged, this, [this](bool isRecording) { +@@ -314,11 +335,19 @@ SpectacleCore::SpectacleCore(QObject *parent) + ExportManager::instance()->exportVideo(autoExportActions() | ExportManager::Save, fileUrl, videoOutputUrl()); + }); + connect(videoPlatform, &VideoPlatform::recordingCanceled, this, [this] { +- if (m_startMode != StartMode::Gui || isGuiNull()) { ++ if (m_startMode != StartMode::Gui || !m_returnToViewer || isGuiNull()) { + Q_EMIT allDone(); + return; + } + SpectacleWindow::setTitleForAll(SpectacleWindow::Previous); ++ const auto windows = SpectacleWindow::instances(); ++ if (windows.empty()) { ++ initViewerWindow(ViewerWindow::Image); ++ return; ++ } ++ for (auto w : windows) { ++ w->setVisible(true); ++ } + }); + connect(videoPlatform, &VideoPlatform::recordingFailed, this, [onScreenshotOrRecordingFailed](const QString &message){ + auto uiMessage = i18nc("@info", "An error occurred while attempting to record the screen."); +@@ -578,7 +607,7 @@ void SpectacleCore::activate(const QStringList &arguments, const QString &workin + } + } + +- if (parser.optionNames().size() > 0 || m_startMode != StartMode::Gui) { ++ if (parser.optionNames().size() > 0 || m_startMode != StartMode::Gui || !m_returnToViewer) { + // Delete windows if we have CLI options or not in GUI mode. + // We don't want to delete them otherwise because that will mess with the + // settings for PrintScreen key behavior. +@@ -672,20 +701,33 @@ void SpectacleCore::activate(const QStringList &arguments, const QString &workin + // Determine grab mode + using CaptureMode = CaptureModeModel::CaptureMode; + using GrabMode = ImagePlatform::GrabMode; +- GrabMode grabMode = GrabMode::AllScreens; // Default to all screens +- if (m_cliOptions[Option::Fullscreen]) { +- grabMode = GrabMode::AllScreens; +- } else if (m_cliOptions[Option::Current]) { +- grabMode = GrabMode::CurrentScreen; +- } else if (m_cliOptions[Option::ActiveWindow]) { +- grabMode = GrabMode::ActiveWindow; +- } else if (m_cliOptions[Option::Region]) { +- grabMode = GrabMode::PerScreenImageNative; +- } else if (m_cliOptions[Option::WindowUnderCursor]) { +- grabMode = GrabMode::WindowUnderCursor; +- } else if (Settings::launchAction() == Settings::UseLastUsedCapturemode) { +- grabMode = toGrabMode(CaptureMode(Settings::captureMode()), transientOnly); +- } ++ auto cliGrabMode = [&]() -> std::optional { ++ if (m_cliOptions[Option::Fullscreen]) { ++ return GrabMode::AllScreens; ++ } else if (m_cliOptions[Option::Current]) { ++ return GrabMode::CurrentScreen; ++ } else if (m_cliOptions[Option::ActiveWindow]) { ++ return GrabMode::ActiveWindow; ++ } else if (m_cliOptions[Option::Region]) { ++ return GrabMode::PerScreenImageNative; ++ } else if (m_cliOptions[Option::WindowUnderCursor]) { ++ return GrabMode::WindowUnderCursor; ++ } ++ return std::nullopt; ++ }; ++ auto launchActionGrabMode = [&] { ++ switch (Settings::launchAction()) { ++ case Settings::TakeRectangularScreenshot: ++ return GrabMode::PerScreenImageNative; ++ case Settings::TakeFullscreenScreenshot: ++ return GrabMode::AllScreens; ++ case Settings::UseLastUsedCapturemode: ++ return toGrabMode(CaptureMode(Settings::captureMode()), transientOnly); ++ default: ++ return GrabMode::NoGrabModes; ++ } ++ }; ++ auto grabMode = cliGrabMode().value_or(m_startMode == StartMode::Background ? GrabMode::AllScreens : launchActionGrabMode()); + + using RecordingMode = VideoPlatform::RecordingMode; + RecordingMode recordingMode = RecordingMode::NoRecordingModes; +@@ -855,7 +897,7 @@ void SpectacleCore::takeNewScreenshot(int captureMode, int timeout, bool include + + void SpectacleCore::cancelScreenshot() + { +- if (m_startMode != StartMode::Gui) { ++ if (m_startMode != StartMode::Gui || !m_returnToViewer) { + Q_EMIT allDone(); + return; + } +@@ -883,7 +925,7 @@ void SpectacleCore::showErrorMessage(const QString &message) + + void SpectacleCore::showViewerIfGuiMode(bool minimized) + { +- if (m_startMode != StartMode::Gui) { ++ if (m_startMode != StartMode::Gui || !m_returnToViewer) { + return; + } + initViewerWindow(ViewerWindow::Image); +@@ -1140,6 +1182,7 @@ void SpectacleCore::initViewerWindow(ViewerWindow::Mode mode) + { + // always switch to gui mode when a viewer window is used. + m_startMode = SpectacleCore::StartMode::Gui; ++ m_returnToViewer = true; + deleteWindows(); + + // Transparency isn't needed for this window. +@@ -1168,6 +1211,12 @@ void SpectacleCore::startRecording(VideoPlatform::RecordingMode mode, bool withP + if (m_videoPlatform->isRecording() || mode == VideoPlatform::NoRecordingModes) { + return; + } ++ if (!CaptureWindow::instances().empty()) { ++ SpectacleWindow::setVisibilityForAll(QWindow::Hidden); ++ if (mode != VideoPlatform::Region) { ++ m_returnToViewer = true; ++ } ++ } + m_lastRecordingMode = mode; + setVideoMode(true); + const auto &output = m_outputUrl.isLocalFile() ? videoOutputUrl() : QUrl(); +@@ -1191,6 +1240,10 @@ void SpectacleCore::setVideoMode(bool videoMode) + return; + } + m_videoMode = videoMode; ++ if (!videoMode && m_annotationDocument->baseImage().isNull()) { ++ // Change this if there ends up being a way to toggle video mode outside of rectangle capture mode. ++ takeNewScreenshot(ImagePlatform::PerScreenImageNative, 0, Settings::includePointer(), Settings::includeDecorations(), Settings::includeShadow()); ++ } + Q_EMIT videoModeChanged(videoMode); + } + +diff --git a/src/SpectacleCore.h b/src/SpectacleCore.h +index 246e8944..23d65ead 100644 +--- a/src/SpectacleCore.h ++++ b/src/SpectacleCore.h +@@ -37,7 +37,7 @@ class SpectacleCore : public QObject + Q_PROPERTY(int captureTimeRemaining READ captureTimeRemaining NOTIFY captureTimeRemainingChanged FINAL) + Q_PROPERTY(qreal captureProgress READ captureProgress NOTIFY captureProgressChanged FINAL) + Q_PROPERTY(QString recordedTime READ recordedTime NOTIFY recordedTimeChanged) +- Q_PROPERTY(bool videoMode READ videoMode NOTIFY videoModeChanged) ++ Q_PROPERTY(bool videoMode READ videoMode WRITE setVideoMode NOTIFY videoModeChanged) + Q_PROPERTY(QUrl currentVideo READ currentVideo NOTIFY currentVideoChanged) + Q_PROPERTY(AnnotationDocument *annotationDocument READ annotationDocument CONSTANT FINAL) + +@@ -67,15 +67,21 @@ public: + int captureTimeRemaining() const; + qreal captureProgress() const; + ++ QString recordedTime() const; ++ ++ bool videoMode() const; ++ void setVideoMode(bool enabled); ++ ++ QUrl currentVideo() const; ++ ++ + void initGuiNoScreenshot(); + + void syncExportImage(); + + Q_INVOKABLE void startRecording(VideoPlatform::RecordingMode mode, bool withPointer = Settings::videoIncludePointer()); + Q_INVOKABLE void finishRecording(); +- bool videoMode() const; +- QUrl currentVideo() const; +- QString recordedTime() const; ++ + Q_INVOKABLE QString timeFromMilliseconds(qint64 milliseconds) const; + + ExportManager::Actions autoExportActions() const; +@@ -140,13 +146,13 @@ private: + void initViewerWindow(ViewerWindow::Mode mode); + void deleteWindows(); + void unityLauncherUpdate(const QVariantMap &properties) const; +- void setVideoMode(bool enabled); + void setCurrentVideo(const QUrl ¤tVideo); + QUrl videoOutputUrl() const; + + static SpectacleCore *s_self; + std::unique_ptr m_annotationDocument = nullptr; + StartMode m_startMode = StartMode::Gui; ++ bool m_returnToViewer = false; + QUrl m_screenCaptureUrl; + std::unique_ptr m_imagePlatform; + std::unique_ptr m_videoPlatform; From 23d426f0ea24bbd9553ef274559ebc367e54fa68 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 5 Mar 2025 13:06:41 +0100 Subject: [PATCH 0941/1125] Kde/plasma: reenable kickoff's switch on hover --- roles/kde/plasma.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 728b560..288f14b 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -139,6 +139,7 @@ in { { kickoff = { icon = "nix-snowflake-white"; + settings.General.switchCategoryOnHover = true; }; } "org.kde.plasma.pager" From 0617934f317937740f3288c3a76106d573b71cdf Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 7 Mar 2025 02:59:58 +0100 Subject: [PATCH 0942/1125] Flake: make nur follow nixpkgs unstable --- flake.lock | 22 ++++------------------ flake.nix | 5 ++++- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/flake.lock b/flake.lock index 44e891c..432d086 100644 --- a/flake.lock +++ b/flake.lock @@ -459,22 +459,6 @@ } }, "nixpkgs_2": { - "locked": { - "lastModified": 1740828860, - "narHash": "sha256-cjbHI+zUzK5CPsQZqMhE3npTyYFt9tJ3+ohcfaOF/WM=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "303bd8071377433a2d8f76e684ec773d70c5b642", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_3": { "locked": { "lastModified": 0, "narHash": "sha256-Tbk1MZbtV2s5aG+iM99U8FqwxU/YNArMcWAv6clcsBc=", @@ -489,7 +473,9 @@ "nur": { "inputs": { "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2", + "nixpkgs": [ + "nixpkgs-unstable-raw" + ], "treefmt-nix": "treefmt-nix" }, "locked": { @@ -572,7 +558,7 @@ }, "shows-api": { "inputs": { - "nixpkgs": "nixpkgs_3", + "nixpkgs": "nixpkgs_2", "utils": "utils" }, "locked": { diff --git a/flake.nix b/flake.nix index 43f805a..d1e5bdc 100644 --- a/flake.nix +++ b/flake.nix @@ -58,7 +58,10 @@ nix-flatpak.url = "github:gmodena/nix-flatpak/main"; - nur.url = "github:nix-community/NUR"; + nur = { + url = "github:nix-community/NUR"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; + }; catppuccin.url = "github:catppuccin/nix"; From 965a5eef135ad461c67922c71ffc558df27d9324 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 9 Mar 2025 11:55:52 +0100 Subject: [PATCH 0943/1125] Server/ssh: remove log --- roles/server/ssh.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/roles/server/ssh.nix b/roles/server/ssh.nix index b9b7860..e4d0da1 100755 --- a/roles/server/ssh.nix +++ b/roles/server/ssh.nix @@ -16,8 +16,6 @@ if os.environ["PAM_TYPE"] != "open_session": raise SystemExit - print("User logging in") - secretPath = "${config.age.secrets.discord-webhook.path}" webhookUrl: str From 6be10e325a4a310c6a419ba40b358e127e4dea73 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 10 Mar 2025 14:18:29 +0100 Subject: [PATCH 0944/1125] Server/adguard: get host ip dinamically --- roles/server/adguard.nix | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/roles/server/adguard.nix b/roles/server/adguard.nix index 59e4f94..8a57525 100644 --- a/roles/server/adguard.nix +++ b/roles/server/adguard.nix @@ -1,4 +1,8 @@ -{lib, ...}: let +{ + lib, + config, + ... +}: let domain = "adguard.everest.tailscale"; port = 3001; in { @@ -10,7 +14,7 @@ in { settings = { dns = { bind_hosts = [ - "10.0.0.2" + ((lib.lists.last config.networking.interfaces.eno1.ipv4.addresses).address) "100.100.0.1" ]; bootstrap_dns = ["9.9.9.9"]; From 790b5ec4e71a6ad433fb4830e366b5aa909f6a7e Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 10 Mar 2025 14:18:51 +0100 Subject: [PATCH 0945/1125] Machines/everest: change eno1 ip --- machines/Everest/configuration.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index 6cd78cb..9e3c081 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -22,14 +22,14 @@ wakeOnLan.enable = true; ipv4.addresses = [ { - address = "10.0.0.2"; + address = "192.168.1.160"; prefixLength = 8; } ]; }; # I use networkd, so I need to declare the interface for the default gateway defaultGateway = { - address = "10.0.0.1"; + address = "192.168.1.1"; interface = "eno1"; }; nameservers = ["9.9.9.9"]; From ba96c9b6877de53af767ad2170a6538f8e8c358b Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 7 Mar 2025 18:26:51 +0100 Subject: [PATCH 0946/1125] Revert "Desktop/discord: revert vesktop to electron 33" This reverts commit 922c4924128b7b99c99dfa7221d90f30fcbeb233. --- roles/desktop/programs/discord.nix | 3 --- 1 file changed, 3 deletions(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index eed249b..3df1659 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -4,9 +4,6 @@ withOpenASAR = true; withVencord = true; }; - vesktop = super.vesktop.override { - electron = _self.electron_33; - }; }; in { nixpkgs.overlays = [discordOverlay]; From c366ce1cbe6d6c6b15b273f984192cf64aa54242 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 14 Mar 2025 19:42:22 +0100 Subject: [PATCH 0947/1125] Common: add .local/bin to path --- roles/common/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 4084ae6..762b4c5 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -19,6 +19,8 @@ cleanOnBoot = !config.boot.tmp.useTmpfs; }; + environment.localBinInPath = lib.mkDefault true; + # Set up zram zramSwap = { enable = true; From a0fadd7a1b7cfaf5a9423b0ae41e2b5efcfbf74f Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 15 Mar 2025 09:39:23 +0100 Subject: [PATCH 0948/1125] Revert "Kde: fix qt wayland" This reverts commit f3ee33177f38cfb2d76ec5fcc81b220b32625325. --- roles/kde/plasma.nix | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 288f14b..467ff8a 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -37,34 +37,6 @@ in { # Enable the Plasma 6 Desktop Environment services.desktopManager.plasma6.enable = true; - # Same as https://github.com/NixOS/nixpkgs/pull/386932 - nixpkgs.overlays = [ - ( - final: prev: { - kdePackages = prev.kdePackages.overrideScope ( - kFinal: kPrev: { - qtbase-vulkan = kPrev.qtbase.overrideAttrs { - postFixup = '' - moveToOutput "mkspecs/modules" "$dev" - fixQtModulePaths "$dev/mkspecs/modules" - fixQtBuiltinPaths "$out" '*.pr?' - patchelf --add-rpath "${final.libmysqlclient}/lib/mariadb" $out/lib/qt-6/plugins/sqldrivers/libqsqlmysql.so - patchelf --add-rpath "${final.vulkan-loader}/lib" --add-needed "libvulkan.so" $out/lib/libQt6Gui.so - ''; - }; - } - ); - } - ) - ]; - - system.replaceDependencies.replacements = with pkgs.kdePackages; [ - { - oldDependency = qtbase; - newDependency = qtbase-vulkan; - } - ]; - qt.enable = true; # GTK apps need dconf to grab the correct theme on Wayland From 0c64697063552461d56ccac0d459144c2eeafec2 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 15 Mar 2025 17:05:23 +0100 Subject: [PATCH 0949/1125] Flake: update lock file --- flake.lock | 90 +++++++++++++++++++++++++++--------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/flake.lock b/flake.lock index 432d086..0b76f3e 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1739934729, - "narHash": "sha256-PcrLk10meIJICzUJqtCMOJxoITzbH52fZg2XAB7SSsM=", + "lastModified": 1741985801, + "narHash": "sha256-EnjiCpEi8p1kFgNUCVPuDUYoOSYBlr7ByMEF8qMGZws=", "owner": "catppuccin", "repo": "nix", - "rev": "b1ff2a638afa827f1473498190a2c1cae1cf41cf", + "rev": "f833a338ff6c091c84e041ee77ce88f8b242ca79", "type": "github" }, "original": { @@ -188,11 +188,11 @@ ] }, "locked": { - "lastModified": 1740845322, - "narHash": "sha256-AXEgFj3C0YJhu9k1OhbRhiA6FnDr81dQZ65U3DhaWpw=", + "lastModified": 1741955947, + "narHash": "sha256-2lbURKclgKqBNm7hVRtWh0A7NrdsibD0EaWhahUVhhY=", "owner": "nix-community", "repo": "home-manager", - "rev": "fcac3d6d88302a5e64f6cb8014ac785e08874c8d", + "rev": "4e12151c9e014e2449e0beca2c0e9534b96a26b4", "type": "github" }, "original": { @@ -230,11 +230,11 @@ ] }, "locked": { - "lastModified": 1740892961, - "narHash": "sha256-RpuRrwn4Iu3ColOUfQJITSB3Pu8p979zELXv1zihWwU=", + "lastModified": 1742021951, + "narHash": "sha256-Nxrkvh353BeG6/D8yPq50VCaYnCMKviS7krw4DfzLVU=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "483fc372ebcc522ef0226bf5a211942203edda90", + "rev": "ecaf8b6aa7d28cb7b87da334310fbe1ba31f8d64", "type": "github" }, "original": { @@ -246,11 +246,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1740991434, - "narHash": "sha256-9N14m5KRYEUV3nRHNO1myMR/2J/seFj37biiMHqujEk=", - "rev": "18975fa016fbe6c13525d6a833b22bb55703fffb", + "lastModified": 1741976543, + "narHash": "sha256-hSiO4cq2ub0Hs1bH+Qnne7pF8596wKZxmbWH2Kqe9UE=", + "rev": "85d614538fd1e6fa8a230d5f1c4d6e5587e9e3ef", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/18975fa016fbe6c13525d6a833b22bb55703fffb.tar.gz?rev=18975fa016fbe6c13525d6a833b22bb55703fffb" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/85d614538fd1e6fa8a230d5f1c4d6e5587e9e3ef.tar.gz?rev=85d614538fd1e6fa8a230d5f1c4d6e5587e9e3ef" }, "original": { "type": "tarball", @@ -269,11 +269,11 @@ ] }, "locked": { - "lastModified": 1738176840, - "narHash": "sha256-NG3IRvRs3u3btVCN861FqHvgOwqcNT/Oy6PBG86F5/E=", - "rev": "621aae0f3cceaffa6d73a4fb0f89c08d338d729e", + "lastModified": 1741894565, + "narHash": "sha256-2FD0NDJbEjUHloVrtEIms5miJsj1tvQCc/0YK5ambyc=", + "rev": "a6da43f8193d9e329bba1795c42590c27966082e", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/621aae0f3cceaffa6d73a4fb0f89c08d338d729e.tar.gz?rev=621aae0f3cceaffa6d73a4fb0f89c08d338d729e" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/a6da43f8193d9e329bba1795c42590c27966082e.tar.gz?rev=a6da43f8193d9e329bba1795c42590c27966082e" }, "original": { "type": "tarball", @@ -292,11 +292,11 @@ ] }, "locked": { - "lastModified": 1738176840, - "narHash": "sha256-NG3IRvRs3u3btVCN861FqHvgOwqcNT/Oy6PBG86F5/E=", - "rev": "621aae0f3cceaffa6d73a4fb0f89c08d338d729e", + "lastModified": 1741894565, + "narHash": "sha256-2FD0NDJbEjUHloVrtEIms5miJsj1tvQCc/0YK5ambyc=", + "rev": "a6da43f8193d9e329bba1795c42590c27966082e", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/621aae0f3cceaffa6d73a4fb0f89c08d338d729e.tar.gz?rev=621aae0f3cceaffa6d73a4fb0f89c08d338d729e" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/a6da43f8193d9e329bba1795c42590c27966082e.tar.gz?rev=a6da43f8193d9e329bba1795c42590c27966082e" }, "original": { "type": "tarball", @@ -305,11 +305,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1739444422, - "narHash": "sha256-iAVVHi7X3kWORftY+LVbRiStRnQEob2TULWyjMS6dWg=", + "lastModified": 1741903049, + "narHash": "sha256-8Y8brH04JjSLrCLvBEbhK9vOu7lhQhqUBW4kI3tifdI=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "5e54c3ca05a7c7d968ae1ddeabe01d2a9bc1e177", + "rev": "42c7fb2702219b86a8f5969c3475ce594c28f5d0", "type": "github" }, "original": { @@ -363,11 +363,11 @@ ] }, "locked": { - "lastModified": 1740886574, - "narHash": "sha256-jN6kJ41B6jUVDTebIWeebTvrKP6YiLd1/wMej4uq4Sk=", + "lastModified": 1741619381, + "narHash": "sha256-koZtlJRqi0/MD/AKd0KrXLA2NuBOVzlIyAJprjzpxZE=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "26a0f969549cf4d56f6e9046b9e0418b3f3b94a5", + "rev": "66537fb185462ba9b07f4e6f2d54894a1b2d04ab", "type": "github" }, "original": { @@ -383,11 +383,11 @@ ] }, "locked": { - "lastModified": 1740886574, - "narHash": "sha256-jN6kJ41B6jUVDTebIWeebTvrKP6YiLd1/wMej4uq4Sk=", + "lastModified": 1741619381, + "narHash": "sha256-koZtlJRqi0/MD/AKd0KrXLA2NuBOVzlIyAJprjzpxZE=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "26a0f969549cf4d56f6e9046b9e0418b3f3b94a5", + "rev": "66537fb185462ba9b07f4e6f2d54894a1b2d04ab", "type": "github" }, "original": { @@ -398,11 +398,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1740646007, - "narHash": "sha256-dMReDQobS3kqoiUCQIYI9c0imPXRZnBubX20yX/G5LE=", + "lastModified": 1741792691, + "narHash": "sha256-f0BVt1/cvA0DQ/q3rB+HY4g4tKksd03ZkzI4xehC2Ew=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "009b764ac98a3602d41fc68072eeec5d24fc0e49", + "rev": "e1f12151258b12c567f456d8248e4694e9390613", "type": "github" }, "original": { @@ -414,11 +414,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1736012469, - "narHash": "sha256-/qlNWm/IEVVH7GfgAIyP6EsVZI6zjAx1cV5zNyrs+rI=", + "lastModified": 1741851582, + "narHash": "sha256-cPfs8qMccim2RBgtKGF+x9IBCduRvd/N5F4nYpU0TVE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8f3e1f807051e32d8c95cd12b9b421623850a34d", + "rev": "6607cf789e541e7873d40d3a8f7815ea92204f32", "type": "github" }, "original": { @@ -430,11 +430,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1740865531, - "narHash": "sha256-h00vGIh/jxcGl8aWdfnVRD74KuLpyY3mZgMFMy7iKIc=", + "lastModified": 1741862977, + "narHash": "sha256-prZ0M8vE/ghRGGZcflvxCu40ObKaB+ikn74/xQoNrGQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5ef6c425980847c78a80d759abc476e941a9bf42", + "rev": "cdd2ef009676ac92b715ff26630164bb88fec4e0", "type": "github" }, "original": { @@ -445,11 +445,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1740828860, - "narHash": "sha256-cjbHI+zUzK5CPsQZqMhE3npTyYFt9tJ3+ohcfaOF/WM=", + "lastModified": 1741851582, + "narHash": "sha256-cPfs8qMccim2RBgtKGF+x9IBCduRvd/N5F4nYpU0TVE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "303bd8071377433a2d8f76e684ec773d70c5b642", + "rev": "6607cf789e541e7873d40d3a8f7815ea92204f32", "type": "github" }, "original": { @@ -479,11 +479,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1741014528, - "narHash": "sha256-Nez5gUmX8wX1fxZXgiuzIe4wEtmkzRNM9/zIts6hyfQ=", + "lastModified": 1742039093, + "narHash": "sha256-hu+f1IV6joPX3eUoUeSkNrnFvoJlcuVv8ZzGW1cC6qk=", "owner": "nix-community", "repo": "NUR", - "rev": "e5b6c67aaac0b58a91fe25b0497f9377f5945f34", + "rev": "7887073e8a73588c4450a190af4c648aa2ec3cd1", "type": "github" }, "original": { From 8385b2d6e6695179ccecfbb423f86a8752c02f08 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 15 Mar 2025 17:07:09 +0100 Subject: [PATCH 0950/1125] Gaming/rpcs3: use package from nixpkgs --- roles/gaming/programs/rpcs3.nix | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/roles/gaming/programs/rpcs3.nix b/roles/gaming/programs/rpcs3.nix index b8c48c0..8fe81fa 100644 --- a/roles/gaming/programs/rpcs3.nix +++ b/roles/gaming/programs/rpcs3.nix @@ -1,12 +1,7 @@ {pkgs, ...}: { environment.systemPackages = with pkgs; [ - nur.repos.ataraxiasjel.rpcs3 + rpcs3 ]; - # Compiling RPCS3 takes quite a while - nix.settings = { - substituters = ["https://ataraxiadev-foss.cachix.org"]; - trusted-public-keys = ["ataraxiadev-foss.cachix.org-1:ws/jmPRUF5R8TkirnV1b525lP9F/uTBsz2KraV61058="]; - }; # Increase the memory lock limit security.pam.loginLimits = [ From 71a1bad913f7cb2e2c6c1fb0989e84fd4528ade7 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 15 Mar 2025 17:07:47 +0100 Subject: [PATCH 0951/1125] Flake: drop nur --- flake.lock | 65 ---------------------------------- flake.nix | 5 --- roles/common/configuration.nix | 1 - 3 files changed, 71 deletions(-) diff --git a/flake.lock b/flake.lock index 0b76f3e..0ac8fcd 100644 --- a/flake.lock +++ b/flake.lock @@ -73,27 +73,6 @@ "type": "github" } }, - "flake-parts": { - "inputs": { - "nixpkgs-lib": [ - "nur", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1733312601, - "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, "flake-utils": { "inputs": { "systems": "systems_2" @@ -470,28 +449,6 @@ "type": "indirect" } }, - "nur": { - "inputs": { - "flake-parts": "flake-parts", - "nixpkgs": [ - "nixpkgs-unstable-raw" - ], - "treefmt-nix": "treefmt-nix" - }, - "locked": { - "lastModified": 1742039093, - "narHash": "sha256-hu+f1IV6joPX3eUoUeSkNrnFvoJlcuVv8ZzGW1cC6qk=", - "owner": "nix-community", - "repo": "NUR", - "rev": "7887073e8a73588c4450a190af4c648aa2ec3cd1", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "NUR", - "type": "github" - } - }, "plasma-manager": { "inputs": { "home-manager": [ @@ -534,7 +491,6 @@ "nixos-hardware": "nixos-hardware", "nixpkgs-raw": "nixpkgs-raw", "nixpkgs-unstable-raw": "nixpkgs-unstable-raw", - "nur": "nur", "plasma-manager": "plasma-manager", "secrets": "secrets", "shows-api": "shows-api" @@ -635,27 +591,6 @@ "type": "github" } }, - "treefmt-nix": { - "inputs": { - "nixpkgs": [ - "nur", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1733222881, - "narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=", - "owner": "numtide", - "repo": "treefmt-nix", - "rev": "49717b5af6f80172275d47a418c9719a31a78b53", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "treefmt-nix", - "type": "github" - } - }, "utils": { "inputs": { "systems": "systems_4" diff --git a/flake.nix b/flake.nix index d1e5bdc..0b7bae9 100644 --- a/flake.nix +++ b/flake.nix @@ -58,11 +58,6 @@ nix-flatpak.url = "github:gmodena/nix-flatpak/main"; - nur = { - url = "github:nix-community/NUR"; - inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; - }; - catppuccin.url = "github:catppuccin/nix"; lix-module = { diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 762b4c5..6eed62a 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -5,7 +5,6 @@ flakeSelf, ... }: { - imports = [flakeSelf.inputs.nur.modules.nixos.default]; environment = { # As of the 1st of May 2023, the default packages are nano, perl, rsync and strace # I don't need any of them, so I just empty the list From 5d77bb0959ef85cbbe86ecdf7b40d8499de5bfec Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 15 Mar 2025 17:08:45 +0100 Subject: [PATCH 0952/1125] Desktop/jamesdsp: install using home-manager, fix build --- roles/desktop/programs/jamesdsp.nix | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/roles/desktop/programs/jamesdsp.nix b/roles/desktop/programs/jamesdsp.nix index a9933bc..cb2056c 100644 --- a/roles/desktop/programs/jamesdsp.nix +++ b/roles/desktop/programs/jamesdsp.nix @@ -1,3 +1,24 @@ {pkgs, ...}: { - users.users.toast.packages = [pkgs.jamesdsp]; + home-manager.users.toast = { + home.packages = with pkgs; [ + jamesdsp + ]; + }; + nixpkgs.overlays = [ + ( + final: prev: { + # https://github.com/wwmm/easyeffects/commit/38bef46bffdb535e2a70c3332719c557ff577e56 + jamesdsp = prev.jamesdsp.overrideAttrs { + patchPhase = '' + substituteInPlace src/audio/pipewire/PwPipelineManager.cpp \ + --replace-fail "pw_node_add_listener" "pw_proxy_add_object_listener" \ + --replace-fail "pw_link_add_listener" "pw_proxy_add_object_listener" \ + --replace-fail "pw_module_add_listener" "pw_proxy_add_object_listener" \ + --replace-fail "pw_client_add_listener" "pw_proxy_add_object_listener" \ + --replace-fail "pw_device_add_listener" "pw_proxy_add_object_listener" + ''; + }; + } + ) + ]; } From c9250261835cd5b75d1948a213f22535dfbad10e Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 15 Mar 2025 17:29:27 +0100 Subject: [PATCH 0953/1125] Revert "Machines/WinMax2: temporarely change to default kernel" This reverts commit b123ab87dfc9cb3f7cfbab6a8beaf92e2cf7165a. --- machines/WinMax2/configuration.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 55acc71..366ed21 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -31,8 +31,7 @@ # Plymouth doesn't support fractional scaling :( plymouth.extraConfig = "DeviceScale=2"; - # kernelPackages = pkgs.linuxPackages_latest; - # Commented out since bmi-260 doesn't compile for 6.13 + kernelPackages = pkgs.linuxPackages_latest; }; networking.hostName = "WinMax2"; # Define your hostname. From 421a389bdb7dabc9544c78cdbc3d342be4529138 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 25 Mar 2025 22:30:49 +0100 Subject: [PATCH 0954/1125] Server/ddclient: change ip provider --- roles/server/ddclient.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/ddclient.nix b/roles/server/ddclient.nix index d25d411..d9102f9 100755 --- a/roles/server/ddclient.nix +++ b/roles/server/ddclient.nix @@ -10,7 +10,7 @@ in { services.ddclient = { enable = true; - usev4 = "webv4, webv4=dynamicdns.park-your-domain.com/getip"; + usev4 = "webv4, webv4=https://api.ipify.org"; usev6 = ""; protocol = "namecheap"; server = "dynamicdns.park-your-domain.com"; From b8a2c3c10d821f01ee16dc22e3645607d4b9b6a1 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 25 Mar 2025 22:31:06 +0100 Subject: [PATCH 0955/1125] Server/tailscale: wait more time for ip to be up --- roles/server/tailscale.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/server/tailscale.nix b/roles/server/tailscale.nix index 610e592..7ed054e 100644 --- a/roles/server/tailscale.nix +++ b/roles/server/tailscale.nix @@ -5,9 +5,9 @@ text = '' # Based on https://github.com/tailscale/tailscale/issues/11504#issuecomment-2113331262 echo Waiting for tailscale0 to get an IP adress.. - for i in {1..120}; do + for i in {1..240}; do if ip addr show dev tailscale0 | grep -q 'inet '; then break; fi - echo "Waiting $i/120 seconds" + echo "Waiting $i/240 seconds" sleep 1 done ''; From 00cbe6876e48ecaa551784b3467c473ffbc5b528 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 17 Mar 2025 03:08:08 +0100 Subject: [PATCH 0956/1125] Kde/patches: refactor overlay function --- roles/kde/patches/default.nix | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/roles/kde/patches/default.nix b/roles/kde/patches/default.nix index 1e14271..4469398 100644 --- a/roles/kde/patches/default.nix +++ b/roles/kde/patches/default.nix @@ -1,6 +1,7 @@ {lib, ...}: let rootDirs = builtins.readDir ./.; removeFiles = lib.attrsets.filterAttrs (n: v: v == "directory") rootDirs; + programsToPatch = builtins.attrNames removeFiles; getPatches = name: builtins.map (value: ./${name}/${value}) (builtins.attrNames ( @@ -11,14 +12,18 @@ )); bigOverlay = final: prev: - builtins.mapAttrs ( - name: _value: - prev."${name}".overrideAttrs { - version = prev."${name}".version + "-patched"; - patches = prev."${name}".patches ++ getPatches name; + lib.attrsets.mergeAttrsList ( + lib.lists.forEach programsToPatch ( + program: let + unpatchedProgram = prev."${program}"; + in { + "${program}" = unpatchedProgram.overrideAttrs { + version = "${unpatchedProgram.version}-patched"; + patches = unpatchedProgram.patches ++ getPatches program; + }; } - ) - removeFiles; + ) + ); in { nixpkgs.overlays = [ ( From 5832fcb26beff6bd1524b21384e73c547d28c77c Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 17 Mar 2025 19:32:59 +0100 Subject: [PATCH 0957/1125] Flake: add nixpkgs patches --- flake.nix | 2 ++ .../kinfocenter-preserve-argv0.patch | 13 ++++++++++ nixpkgs-patches/pr390197.patch | 25 +++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 nixpkgs-patches/kinfocenter-preserve-argv0.patch create mode 100644 nixpkgs-patches/pr390197.patch diff --git a/flake.nix b/flake.nix index 0b7bae9..83cbdee 100644 --- a/flake.nix +++ b/flake.nix @@ -99,6 +99,8 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ + ./nixpkgs-patches/kinfocenter-preserve-argv0.patch + ./nixpkgs-patches/pr390197.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/kinfocenter-preserve-argv0.patch b/nixpkgs-patches/kinfocenter-preserve-argv0.patch new file mode 100644 index 0000000..ef96709 --- /dev/null +++ b/nixpkgs-patches/kinfocenter-preserve-argv0.patch @@ -0,0 +1,13 @@ +diff --git a/pkgs/kde/plasma/kinfocenter/default.nix b/pkgs/kde/plasma/kinfocenter/default.nix +index d9a0c171dbdb..fb337f4fabdc 100644 +--- a/pkgs/kde/plasma/kinfocenter/default.nix ++++ b/pkgs/kde/plasma/kinfocenter/default.nix +@@ -67,6 +67,8 @@ mkKdeDerivation { + ln -sf ${systemsettings}/bin/systemsettings $out/bin/kinfocenter + ''; + ++ qtWrapperArgs = [ "--inherit-argv0" ]; ++ + # Hardcoded as a QString, which is UTF-16 so Nix can't pick it up automatically + postFixup = '' + mkdir -p $out/nix-support diff --git a/nixpkgs-patches/pr390197.patch b/nixpkgs-patches/pr390197.patch new file mode 100644 index 0000000..77cfa72 --- /dev/null +++ b/nixpkgs-patches/pr390197.patch @@ -0,0 +1,25 @@ +From 6c12682c6d2e822dcabf3a016124de0a86214053 Mon Sep 17 00:00:00 2001 +From: K900 +Date: Sat, 15 Mar 2025 20:33:34 +0300 +Subject: [PATCH] kdePackages.plasma-workspace: wrap with --inherit-argv0 + +kcminit_startup checks its own argv[0] to determine what mode to run in. + +Fixes #390179. +--- + pkgs/kde/plasma/plasma-workspace/default.nix | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/pkgs/kde/plasma/plasma-workspace/default.nix b/pkgs/kde/plasma/plasma-workspace/default.nix +index a5b80f8ab351f6..b5a8b5d3657f6c 100644 +--- a/pkgs/kde/plasma/plasma-workspace/default.nix ++++ b/pkgs/kde/plasma/plasma-workspace/default.nix +@@ -62,6 +62,8 @@ mkKdeDerivation { + gpsd + ]; + ++ qtWrapperArgs = [ "--inherit-argv0" ]; ++ + # Hardcoded as QStrings, which are UTF-16 so Nix can't pick these up automatically + postFixup = '' + mkdir -p $out/nix-support From a47d0a090ddff1ae4bc313e703855cec1a4797ef Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 17 Mar 2025 23:52:17 +0100 Subject: [PATCH 0958/1125] Kde/patches: use replaceDependencies to avoid mass rebuilds --- roles/kde/patches/default.nix | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/roles/kde/patches/default.nix b/roles/kde/patches/default.nix index 4469398..86198ed 100644 --- a/roles/kde/patches/default.nix +++ b/roles/kde/patches/default.nix @@ -1,4 +1,4 @@ -{lib, ...}: let +{lib, pkgs, ...}: let rootDirs = builtins.readDir ./.; removeFiles = lib.attrsets.filterAttrs (n: v: v == "directory") rootDirs; programsToPatch = builtins.attrNames removeFiles; @@ -17,8 +17,7 @@ program: let unpatchedProgram = prev."${program}"; in { - "${program}" = unpatchedProgram.overrideAttrs { - version = "${unpatchedProgram.version}-patched"; + "${program}-patched" = unpatchedProgram.overrideAttrs { patches = unpatchedProgram.patches ++ getPatches program; }; } @@ -32,4 +31,11 @@ in { } ) ]; + + system.replaceDependencies.replacements = lib.lists.forEach programsToPatch ( + package: { + oldDependency = pkgs.kdePackages.${package}; + newDependency = pkgs.kdePackages."${package}-patched"; + } + ); } From 1815e8e3f6355243bd38b6c24d705af06792d471 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 20 Mar 2025 17:30:38 +0100 Subject: [PATCH 0959/1125] Desktop/firefox: enable autoplay on synctube --- roles/desktop/programs/firefox.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index 96b50a9..fec3b8c 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -45,7 +45,10 @@ "PasswordManagerEnabled" = false; "Permissions" = { "Autoplay" = { - "Allow" = ["https://www.youtube.com"]; + "Allow" = [ + "https://www.youtube.com" + "https://sync-tube.de" + ]; "Default" = "block-audio-video"; }; }; From 7fce74c605bcac2503f4965ea53c2101d1f56094 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 25 Mar 2025 11:52:24 +0100 Subject: [PATCH 0960/1125] Desktop: install spotify --- roles/desktop/programs/default.nix | 1 + roles/desktop/programs/spotify.nix | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 roles/desktop/programs/spotify.nix diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix index 9caa2e4..42fe870 100755 --- a/roles/desktop/programs/default.nix +++ b/roles/desktop/programs/default.nix @@ -9,5 +9,6 @@ ./appimage.nix ./mpv.nix ./sysdvr-qt.nix + ./spotify.nix ]; } diff --git a/roles/desktop/programs/spotify.nix b/roles/desktop/programs/spotify.nix new file mode 100644 index 0000000..c895f52 --- /dev/null +++ b/roles/desktop/programs/spotify.nix @@ -0,0 +1,5 @@ +{pkgs, ...}: { + home-manager.users.toast = { + home.packages = [pkgs.spotify]; + }; +} From 90b1e43b99a15d81d33724f15af0c28cab9b59a4 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 25 Mar 2025 12:40:29 +0100 Subject: [PATCH 0961/1125] Desktop/firefox: manage firefox with home-manager --- roles/desktop/programs/firefox.nix | 112 +++++++++++++++-------------- 1 file changed, 58 insertions(+), 54 deletions(-) diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index fec3b8c..25fc99b 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -1,58 +1,62 @@ {lib, ...}: { - # System wide firefox settings - programs.firefox = { - enable = true; - policies = { - "DisablePocket" = true; - "DisableTelemetry" = true; - # You need these for Spotify - "EncryptedMediaExtensions" = {"Enabled" = true;}; - "ExtensionSettings" = { - # TODO: Install extensions the NUR instead of from AMO - "uBlock0@raymondhill.net" = { - "installation_mode" = "force_installed"; - "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; - }; - # Decentraleyes - "jid1-BoFifL9Vbdl2zQ@jetpack" = { - "installation_mode" = "normal_installed"; - "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/decentraleyes/latest.xpi"; - }; - "jid1-MnnxcxisBPnSXQ@jetpack" = { - "installation_mode" = "normal_installed"; - "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/privacy-badger17/latest.xpi"; - }; - # Uninstall the kde plasma integration extension if KDE is not installed - "plasma-browser-integration@kde.org"."installation_mode" = lib.mkDefault "blocked"; - }; - "Preferences" = { - # Enable video hardware acceleration - "media.ffmpeg.vaapi.enabled" = { - "Value" = true; - "Status" = "default"; - }; - "dom.security.https_only_mode" = { - "Value" = true; - "Status" = "locked"; - }; - "general.smoothScroll.msdPhysics.enabled" = { - "Value" = true; - "Status" = "default"; + home-manager.sharedModules = [ + { + # System wide firefox settings + programs.firefox = { + enable = true; + policies = { + DisablePocket = true; + DisableTelemetry = true; + # You need these for Spotify + EncryptedMediaExtensions.Enabled = true; + ExtensionSettings = { + # TODO: Install extensions the NUR instead of from AMO + "uBlock0@raymondhill.net" = { + installation_mode = "force_installed"; + install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; + }; + # Decentraleyes + "jid1-BoFifL9Vbdl2zQ@jetpack" = { + installation_mode = "normal_installed"; + install_url = "https://addons.mozilla.org/firefox/downloads/latest/decentraleyes/latest.xpi"; + }; + "jid1-MnnxcxisBPnSXQ@jetpack" = { + installation_mode = "normal_installed"; + install_url = "https://addons.mozilla.org/firefox/downloads/latest/privacy-badger17/latest.xpi"; + }; + # Uninstall the kde plasma integration extension if KDE is not installed + "plasma-browser-integration@kde.org".installation_mode = lib.mkDefault "blocked"; + }; + Preferences = { + # Enable video hardware acceleration + "media.ffmpeg.vaapi.enabled" = { + Value = true; + Status = "default"; + }; + "dom.security.https_only_mode" = { + Value = true; + Status = "locked"; + }; + "general.smoothScroll.msdPhysics.enabled" = { + Value = true; + Status = "default"; + }; + }; + PromptForDownloadLocation = true; + # I use an external password manager, so the built in one just bothers me + PasswordManagerEnabled = false; + Permissions = { + Autoplay = { + Allow = [ + "https://www.youtube.com" + "https://sync-tube.de" + ]; + Default = "block-audio-video"; + }; + }; + FirefoxHome.SponsoredTopSites = false; }; }; - "PromptForDownloadLocation" = true; - # I use an external password manager, so the built in one just bothers me - "PasswordManagerEnabled" = false; - "Permissions" = { - "Autoplay" = { - "Allow" = [ - "https://www.youtube.com" - "https://sync-tube.de" - ]; - "Default" = "block-audio-video"; - }; - }; - "FirefoxHome" = {"SponsoredTopSites" = false;}; - }; - }; + } + ]; } From 0bd973fb258f6572844a2a028685c2dc0bf19b66 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 25 Mar 2025 12:41:23 +0100 Subject: [PATCH 0962/1125] Kde/firefox: manage with home-manager --- roles/kde/programs/firefox.nix | 59 ++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/roles/kde/programs/firefox.nix b/roles/kde/programs/firefox.nix index bbe1638..41f81e2 100644 --- a/roles/kde/programs/firefox.nix +++ b/roles/kde/programs/firefox.nix @@ -1,30 +1,35 @@ -{...}: { - # KDE specific firefox settings - programs.firefox = { - policies = { - "ExtensionSettings" = { - # TODO: Install extensions the NUR instead of from AMO - "plasma-browser-integration@kde.org" = { - "installation_mode" = "normal_installed"; - "install_url" = "https://addons.mozilla.org/firefox/downloads/latest/plasma-integration/latest.xpi"; +{pkgs, ...}: { + home-manager.sharedModules = [ + { + # KDE specific firefox settings + programs.firefox = { + nativeMessagingHosts = [pkgs.kdePackages.plasma-browser-integration]; + policies = { + ExtensionSettings = { + # TODO: Install extensions the NUR instead of from AMO + "plasma-browser-integration@kde.org" = { + installation_mode = "normal_installed"; + install_url = "https://addons.mozilla.org/firefox/downloads/latest/plasma-integration/latest.xpi"; + }; + }; + Preferences = { + # Make firefox use the kde file picker + "widget.use-xdg-desktop-portal.file-picker" = { + Value = 1; + Status = "default"; + }; + /* + https://wiki.archlinux.org/title/Firefox#KDE_integration tells me to enable this, + but strangely enough doing so makes firefox ask to be set as the default browser + every time you start it up, so I'll disable it + */ + "widget.use-xdg-desktop-portal.mime-handler" = { + Value = 0; + Status = "default"; + }; + }; }; }; - "Preferences" = { - # Make firefox use the kde file picker - "widget.use-xdg-desktop-portal.file-picker" = { - "Value" = 1; - "Status" = "default"; - }; - /* - https://wiki.archlinux.org/title/Firefox#KDE_integration tells me to enable this, - but strangely enough doing so makes firefox ask to be set as the default browser - every time you start it up, so I'll disable it - */ - "widget.use-xdg-desktop-portal.mime-handler" = { - "Value" = 0; - "Status" = "default"; - }; - }; - }; - }; + } + ]; } From bc9098525b7c6070f0e8fe9e0b8ee149e534e587 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 25 Mar 2025 15:34:29 +0100 Subject: [PATCH 0963/1125] Desktop/firefox: set up per user settings --- roles/desktop/programs/firefox.nix | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index 25fc99b..3bfb206 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -5,7 +5,6 @@ programs.firefox = { enable = true; policies = { - DisablePocket = true; DisableTelemetry = true; # You need these for Spotify EncryptedMediaExtensions.Enabled = true; @@ -37,10 +36,6 @@ Value = true; Status = "locked"; }; - "general.smoothScroll.msdPhysics.enabled" = { - Value = true; - Status = "default"; - }; }; PromptForDownloadLocation = true; # I use an external password manager, so the built in one just bothers me @@ -59,4 +54,23 @@ }; } ]; + # Per-user settings + home-manager.users.toast = { + programs.firefox.policies = { + DisablePocket = true; + Preferences = { + "general.smoothScroll.msdPhysics.enabled" = { + Value = true; + Status = "default"; + }; + }; + }; + programs.firefox.profiles = { + personal = { + name = "Personal"; + id = 0; + isDefault = true; + }; + }; + }; } From cb1230214a72e97255d28c6f3cdf74f000551a7d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 25 Mar 2025 15:39:02 +0100 Subject: [PATCH 0964/1125] Desktop/firefox: uninstall undeclared extensions --- roles/desktop/programs/firefox.nix | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index 3bfb206..be52db3 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -23,8 +23,11 @@ installation_mode = "normal_installed"; install_url = "https://addons.mozilla.org/firefox/downloads/latest/privacy-badger17/latest.xpi"; }; - # Uninstall the kde plasma integration extension if KDE is not installed - "plasma-browser-integration@kde.org".installation_mode = lib.mkDefault "blocked"; + # Uninstall undeclared extensions + "*" = { + installation_mode = "blocked"; + blocked_install_message = "Extensions are managed by home-manager"; + }; }; Preferences = { # Enable video hardware acceleration From 989f5407ec431034ad10d44a1ac8dca494d0f9e1 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 25 Mar 2025 16:04:52 +0100 Subject: [PATCH 0965/1125] Desktop/firefox: install sponsorblock for toast --- roles/desktop/programs/firefox.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index be52db3..1e96a80 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -61,6 +61,12 @@ home-manager.users.toast = { programs.firefox.policies = { DisablePocket = true; + ExtensionSettings = { + "sponsorBlocker@ajay.app" = { + installation_mode = "normal_installed"; + install_url = "https://addons.mozilla.org/firefox/downloads/latest/sponsorblock/latest.xpi"; + }; + }; Preferences = { "general.smoothScroll.msdPhysics.enabled" = { Value = true; From 35f9aaca7dd42f837585525bc2d18fdc2b3a7a57 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 25 Mar 2025 16:05:10 +0100 Subject: [PATCH 0966/1125] Desktop/firefox: change tab switcher order for toast --- roles/desktop/programs/firefox.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index 1e96a80..3474c8f 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -72,6 +72,10 @@ Value = true; Status = "default"; }; + "browser.ctrlTab.sortByRecentlyUsed" = { + Value = true; + Status = "default"; + }; }; }; programs.firefox.profiles = { From f7a528a94f66d211fd6795060d1c715fee412040 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 28 Mar 2025 20:05:42 +0100 Subject: [PATCH 0967/1125] Firefox: install and configure containers extension --- roles/desktop/programs/firefox.nix | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index 3474c8f..aac3918 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -66,6 +66,10 @@ installation_mode = "normal_installed"; install_url = "https://addons.mozilla.org/firefox/downloads/latest/sponsorblock/latest.xpi"; }; + "@testpilot-containers" = { + installation_mode = "normal_installed"; + install_url = "https://addons.mozilla.org/firefox/downloads/latest/multi-account-containers/latest.xpi"; + }; }; Preferences = { "general.smoothScroll.msdPhysics.enabled" = { @@ -76,6 +80,11 @@ Value = true; Status = "default"; }; + # This should be set automatically, but it isn't for some reason + "extensions.webextensions.ExtensionStorageIDB.enabled" = { + Value = false; + Status = "locked"; + }; }; }; programs.firefox.profiles = { @@ -83,6 +92,31 @@ name = "Personal"; id = 0; isDefault = true; + containersForce = true; + containers = { + work = { + name = "Work"; + id = 1; + icon = "briefcase"; + color = "green"; + }; + }; + extensions.force = true; + extensions.settings = { + "@testpilot-containers".settings = { + onboarding-stage = 8; + "siteContainerMap@@_teams.microsoft.com" = { + userContextId = "1"; + neverAsk = false; + identityMacAddonUUID = "b50e5b1e-6f3b-4245-8eac-5654d889156e"; + }; + "siteContainerMap@@_outlook.office.com" = { + userContextId = "1"; + neverAsk = false; + identityMacAddonUUID = "b50e5b1e-6f3b-4245-8eac-5654d889156e"; + }; + }; + }; }; }; }; From 630e634cd27c4551fcd5a562873d215c876d1739 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 3 Apr 2025 18:37:03 +0200 Subject: [PATCH 0968/1125] Flake: remove unneeded patches --- flake.nix | 6 ----- .../kinfocenter-preserve-argv0.patch | 13 ---------- nixpkgs-patches/pr390197.patch | 25 ------------------- 3 files changed, 44 deletions(-) delete mode 100644 nixpkgs-patches/kinfocenter-preserve-argv0.patch delete mode 100644 nixpkgs-patches/pr390197.patch diff --git a/flake.nix b/flake.nix index 83cbdee..2de1703 100644 --- a/flake.nix +++ b/flake.nix @@ -99,18 +99,12 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/kinfocenter-preserve-argv0.patch - ./nixpkgs-patches/pr390197.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { name = "patched-nixpkgs"; src = nixpkgs-raw; patches = [ - (nixpkgs-raw.legacyPackages.x86_64-linux.fetchpatch { - url = "https://github.com/NixOS/nixpkgs/pull/370713.patch"; - hash = "sha256-gZPP99e42XdYrQz9wWHpS0ChRhK7m9Yitmy7UT5OxiM="; - }) ]; }; # https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26 diff --git a/nixpkgs-patches/kinfocenter-preserve-argv0.patch b/nixpkgs-patches/kinfocenter-preserve-argv0.patch deleted file mode 100644 index ef96709..0000000 --- a/nixpkgs-patches/kinfocenter-preserve-argv0.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/pkgs/kde/plasma/kinfocenter/default.nix b/pkgs/kde/plasma/kinfocenter/default.nix -index d9a0c171dbdb..fb337f4fabdc 100644 ---- a/pkgs/kde/plasma/kinfocenter/default.nix -+++ b/pkgs/kde/plasma/kinfocenter/default.nix -@@ -67,6 +67,8 @@ mkKdeDerivation { - ln -sf ${systemsettings}/bin/systemsettings $out/bin/kinfocenter - ''; - -+ qtWrapperArgs = [ "--inherit-argv0" ]; -+ - # Hardcoded as a QString, which is UTF-16 so Nix can't pick it up automatically - postFixup = '' - mkdir -p $out/nix-support diff --git a/nixpkgs-patches/pr390197.patch b/nixpkgs-patches/pr390197.patch deleted file mode 100644 index 77cfa72..0000000 --- a/nixpkgs-patches/pr390197.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 6c12682c6d2e822dcabf3a016124de0a86214053 Mon Sep 17 00:00:00 2001 -From: K900 -Date: Sat, 15 Mar 2025 20:33:34 +0300 -Subject: [PATCH] kdePackages.plasma-workspace: wrap with --inherit-argv0 - -kcminit_startup checks its own argv[0] to determine what mode to run in. - -Fixes #390179. ---- - pkgs/kde/plasma/plasma-workspace/default.nix | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/pkgs/kde/plasma/plasma-workspace/default.nix b/pkgs/kde/plasma/plasma-workspace/default.nix -index a5b80f8ab351f6..b5a8b5d3657f6c 100644 ---- a/pkgs/kde/plasma/plasma-workspace/default.nix -+++ b/pkgs/kde/plasma/plasma-workspace/default.nix -@@ -62,6 +62,8 @@ mkKdeDerivation { - gpsd - ]; - -+ qtWrapperArgs = [ "--inherit-argv0" ]; -+ - # Hardcoded as QStrings, which are UTF-16 so Nix can't pick these up automatically - postFixup = '' - mkdir -p $out/nix-support From 513dab012d96f3d0b77b7c30f67d5e09f70f22d0 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 3 Apr 2025 19:34:07 +0200 Subject: [PATCH 0969/1125] Flake: update lock file --- flake.lock | 90 +++++++++++++++++----------------- roles/common/configuration.nix | 2 +- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/flake.lock b/flake.lock index 0ac8fcd..5355653 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1741985801, - "narHash": "sha256-EnjiCpEi8p1kFgNUCVPuDUYoOSYBlr7ByMEF8qMGZws=", + "lastModified": 1743414153, + "narHash": "sha256-bFIXz7SvLlSNR4M3vYPYS1CpEN9vTUiH01R4iR/BDmA=", "owner": "catppuccin", "repo": "nix", - "rev": "f833a338ff6c091c84e041ee77ce88f8b242ca79", + "rev": "2f52f9ead26f80d7b391cedcbb3eb309bd83fff4", "type": "github" }, "original": { @@ -167,11 +167,11 @@ ] }, "locked": { - "lastModified": 1741955947, - "narHash": "sha256-2lbURKclgKqBNm7hVRtWh0A7NrdsibD0EaWhahUVhhY=", + "lastModified": 1743648554, + "narHash": "sha256-23JFd+zd2GamTTdnGuFVeIg8x8C3hLpQJRh/PGTORzo=", "owner": "nix-community", "repo": "home-manager", - "rev": "4e12151c9e014e2449e0beca2c0e9534b96a26b4", + "rev": "107352dde4ff3c01cb5a0b3fe17f5beef37215bc", "type": "github" }, "original": { @@ -187,11 +187,11 @@ ] }, "locked": { - "lastModified": 1739757849, - "narHash": "sha256-Gs076ot1YuAAsYVcyidLKUMIc4ooOaRGO0PqTY7sBzA=", + "lastModified": 1743387206, + "narHash": "sha256-24N3NAuZZbYqZ39NgToZgHUw6M7xHrtrAm18kv0+2Wo=", "owner": "nix-community", "repo": "home-manager", - "rev": "9d3d080aec2a35e05a15cedd281c2384767c2cfe", + "rev": "15c5f9d04fabd176f30286c8f52bbdb2c853a146", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1742021951, - "narHash": "sha256-Nxrkvh353BeG6/D8yPq50VCaYnCMKviS7krw4DfzLVU=", + "lastModified": 1743660830, + "narHash": "sha256-ezJqPIuB25iMJeugwHKWnB1DjMvrdpkrPxE3TCULjGk=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "ecaf8b6aa7d28cb7b87da334310fbe1ba31f8d64", + "rev": "c7ade1c8fe2bdb70d38b3b9a97b874dcaf33b755", "type": "github" }, "original": { @@ -225,11 +225,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1741976543, - "narHash": "sha256-hSiO4cq2ub0Hs1bH+Qnne7pF8596wKZxmbWH2Kqe9UE=", - "rev": "85d614538fd1e6fa8a230d5f1c4d6e5587e9e3ef", + "lastModified": 1743523803, + "narHash": "sha256-L/8tnMbfwOmRXRrzzDJBlkRUiVOxy8cxWTdaN3n3AGI=", + "rev": "5a7e9e17464008904403af4297823443281bef12", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/85d614538fd1e6fa8a230d5f1c4d6e5587e9e3ef.tar.gz?rev=85d614538fd1e6fa8a230d5f1c4d6e5587e9e3ef" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/5a7e9e17464008904403af4297823443281bef12.tar.gz?rev=5a7e9e17464008904403af4297823443281bef12" }, "original": { "type": "tarball", @@ -248,11 +248,11 @@ ] }, "locked": { - "lastModified": 1741894565, - "narHash": "sha256-2FD0NDJbEjUHloVrtEIms5miJsj1tvQCc/0YK5ambyc=", - "rev": "a6da43f8193d9e329bba1795c42590c27966082e", + "lastModified": 1742945498, + "narHash": "sha256-MB/b/xcDKqaVBxJIIxwb81r8ZiGLeKEcqokATRRroo8=", + "rev": "fa69ae26cc32dda178117b46487c2165c0e08316", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/a6da43f8193d9e329bba1795c42590c27966082e.tar.gz?rev=a6da43f8193d9e329bba1795c42590c27966082e" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/fa69ae26cc32dda178117b46487c2165c0e08316.tar.gz?rev=fa69ae26cc32dda178117b46487c2165c0e08316" }, "original": { "type": "tarball", @@ -271,11 +271,11 @@ ] }, "locked": { - "lastModified": 1741894565, - "narHash": "sha256-2FD0NDJbEjUHloVrtEIms5miJsj1tvQCc/0YK5ambyc=", - "rev": "a6da43f8193d9e329bba1795c42590c27966082e", + "lastModified": 1742945498, + "narHash": "sha256-MB/b/xcDKqaVBxJIIxwb81r8ZiGLeKEcqokATRRroo8=", + "rev": "fa69ae26cc32dda178117b46487c2165c0e08316", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/a6da43f8193d9e329bba1795c42590c27966082e.tar.gz?rev=a6da43f8193d9e329bba1795c42590c27966082e" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/fa69ae26cc32dda178117b46487c2165c0e08316.tar.gz?rev=fa69ae26cc32dda178117b46487c2165c0e08316" }, "original": { "type": "tarball", @@ -342,11 +342,11 @@ ] }, "locked": { - "lastModified": 1741619381, - "narHash": "sha256-koZtlJRqi0/MD/AKd0KrXLA2NuBOVzlIyAJprjzpxZE=", + "lastModified": 1743306489, + "narHash": "sha256-LROaIjSLo347cwcHRfSpqzEOa2FoLSeJwU4dOrGm55E=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "66537fb185462ba9b07f4e6f2d54894a1b2d04ab", + "rev": "b3696bfb6c24aa61428839a99e8b40c53ac3a82d", "type": "github" }, "original": { @@ -362,11 +362,11 @@ ] }, "locked": { - "lastModified": 1741619381, - "narHash": "sha256-koZtlJRqi0/MD/AKd0KrXLA2NuBOVzlIyAJprjzpxZE=", + "lastModified": 1743306489, + "narHash": "sha256-LROaIjSLo347cwcHRfSpqzEOa2FoLSeJwU4dOrGm55E=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "66537fb185462ba9b07f4e6f2d54894a1b2d04ab", + "rev": "b3696bfb6c24aa61428839a99e8b40c53ac3a82d", "type": "github" }, "original": { @@ -377,11 +377,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1741792691, - "narHash": "sha256-f0BVt1/cvA0DQ/q3rB+HY4g4tKksd03ZkzI4xehC2Ew=", + "lastModified": 1743420942, + "narHash": "sha256-b/exDDQSLmENZZgbAEI3qi9yHkuXAXCPbormD8CSJXo=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "e1f12151258b12c567f456d8248e4694e9390613", + "rev": "de6fc5551121c59c01e2a3d45b277a6d05077bc4", "type": "github" }, "original": { @@ -393,11 +393,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1741851582, - "narHash": "sha256-cPfs8qMccim2RBgtKGF+x9IBCduRvd/N5F4nYpU0TVE=", + "lastModified": 1742889210, + "narHash": "sha256-hw63HnwnqU3ZQfsMclLhMvOezpM7RSB0dMAtD5/sOiw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6607cf789e541e7873d40d3a8f7815ea92204f32", + "rev": "698214a32beb4f4c8e3942372c694f40848b360d", "type": "github" }, "original": { @@ -409,11 +409,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1741862977, - "narHash": "sha256-prZ0M8vE/ghRGGZcflvxCu40ObKaB+ikn74/xQoNrGQ=", + "lastModified": 1743576891, + "narHash": "sha256-vXiKURtntURybE6FMNFAVpRPr8+e8KoLPrYs9TGuAKc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "cdd2ef009676ac92b715ff26630164bb88fec4e0", + "rev": "44a69ed688786e98a101f02b712c313f1ade37ab", "type": "github" }, "original": { @@ -424,11 +424,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1741851582, - "narHash": "sha256-cPfs8qMccim2RBgtKGF+x9IBCduRvd/N5F4nYpU0TVE=", + "lastModified": 1743583204, + "narHash": "sha256-F7n4+KOIfWrwoQjXrL2wD9RhFYLs2/GGe/MQY1sSdlE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6607cf789e541e7873d40d3a8f7815ea92204f32", + "rev": "2c8d3f48d33929642c1c12cd243df4cc7d2ce434", "type": "github" }, "original": { @@ -459,11 +459,11 @@ ] }, "locked": { - "lastModified": 1740569341, - "narHash": "sha256-WV8nY2IOfWdzBF5syVgCcgOchg/qQtpYh6LECYS9XkY=", + "lastModified": 1742765550, + "narHash": "sha256-2vVIh2JrL6GAGfgCeY9e6iNKrBjs0Hw3bGQEAbwVs68=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "5eeb0172fb74392053b66a8149e61b5e191b2845", + "rev": "b70be387276e632fe51232887f9e04e2b6ef8c16", "type": "github" }, "original": { diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 6eed62a..7c18fe3 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -127,7 +127,7 @@ backupFileExtension = "hm-backup"; useGlobalPkgs = true; verbose = true; - sharedModules = [flakeSelf.inputs.catppuccin.homeManagerModules.catppuccin]; + sharedModules = [flakeSelf.inputs.catppuccin.homeModules.catppuccin]; users.toast = {osConfig, ...}: { catppuccin.flavor = osConfig.catppuccin.flavor; catppuccin.accent = osConfig.catppuccin.accent; From dafbcb9f8d58ac1ef0785fa2820270719ee9b242 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 3 Apr 2025 20:05:47 +0200 Subject: [PATCH 0970/1125] Server: remove school things --- flake.lock | 67 +--------------------------------------- flake.nix | 2 -- roles/server/default.nix | 1 - 3 files changed, 1 insertion(+), 69 deletions(-) diff --git a/flake.lock b/flake.lock index 5355653..c5cd8a1 100644 --- a/flake.lock +++ b/flake.lock @@ -437,18 +437,6 @@ "type": "indirect" } }, - "nixpkgs_2": { - "locked": { - "lastModified": 0, - "narHash": "sha256-Tbk1MZbtV2s5aG+iM99U8FqwxU/YNArMcWAv6clcsBc=", - "path": "/nix/store/l9nb64iii15y0nr37qrs1cfm6rlpg6gh-source", - "type": "path" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, "plasma-manager": { "inputs": { "home-manager": [ @@ -492,8 +480,7 @@ "nixpkgs-raw": "nixpkgs-raw", "nixpkgs-unstable-raw": "nixpkgs-unstable-raw", "plasma-manager": "plasma-manager", - "secrets": "secrets", - "shows-api": "shows-api" + "secrets": "secrets" } }, "secrets": { @@ -512,25 +499,6 @@ "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets" } }, - "shows-api": { - "inputs": { - "nixpkgs": "nixpkgs_2", - "utils": "utils" - }, - "locked": { - "lastModified": 1740160663, - "narHash": "sha256-cRD5boGthyiecpL/jzSVaeoLG27Ve2gEVhZFhC5rjHQ=", - "ref": "refs/heads/main", - "rev": "b4fdee776aa7aa2ae6648070cad449a6c88c65c5", - "revCount": 50, - "type": "git", - "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/shows-api.git" - }, - "original": { - "type": "git", - "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/shows-api.git" - } - }, "systems": { "locked": { "lastModified": 1681028828, @@ -575,39 +543,6 @@ "repo": "default", "type": "github" } - }, - "systems_4": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "utils": { - "inputs": { - "systems": "systems_4" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 2de1703..4c0a742 100644 --- a/flake.nix +++ b/flake.nix @@ -86,8 +86,6 @@ url = "github:catppuccin/konsole"; flake = false; }; - - shows-api.url = "git+ssh://forgejo@git.everest.tailscale:4222/Toast/shows-api.git"; }; outputs = {...} @ inputs: diff --git a/roles/server/default.nix b/roles/server/default.nix index 701062f..05fa471 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -19,6 +19,5 @@ ./prometheus.nix ./changedetection-io.nix ./immich.nix - ./school.nix ]; } From a377ad8176a6f4dce1f33de155b2f11e5aee79e9 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 12 Apr 2025 01:00:05 +0200 Subject: [PATCH 0971/1125] Server/samba: overhaul config --- roles/server/samba.nix | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/roles/server/samba.nix b/roles/server/samba.nix index ae6d9e6..3e551ac 100755 --- a/roles/server/samba.nix +++ b/roles/server/samba.nix @@ -4,22 +4,17 @@ enable = true; openFirewall = true; settings = { - "global" = { - "map to guest" = "bad user"; - "guest account" = "transmission"; - }; "Transmission downloads" = { - path = "${config.services.transmission.settings.download-dir}"; - "read only" = true; - public = true; - "guest only" = true; - browseable = true; + "path" = "${config.services.transmission.settings.download-dir}"; + "public" = true; + "writable" = false; + "force user" = "transmission"; }; }; }; avahi.extraServiceFiles = { - Transmission-downloads-smb = '' + everest-smb = '' From 28c64bd45483e6ff0a1b850e5bead09eaa08cbcb Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 15 Apr 2025 16:28:20 +0200 Subject: [PATCH 0972/1125] Kde/kwin: add patches --- roles/kde/patches/kwin/pr7429.patch | 193 ++++++++++++++++++++++++++++ roles/kde/patches/kwin/pr7430.patch | 151 ++++++++++++++++++++++ roles/kde/patches/kwin/pr7441.patch | 61 +++++++++ 3 files changed, 405 insertions(+) create mode 100644 roles/kde/patches/kwin/pr7429.patch create mode 100644 roles/kde/patches/kwin/pr7430.patch create mode 100644 roles/kde/patches/kwin/pr7441.patch diff --git a/roles/kde/patches/kwin/pr7429.patch b/roles/kde/patches/kwin/pr7429.patch new file mode 100644 index 0000000..599e8f7 --- /dev/null +++ b/roles/kde/patches/kwin/pr7429.patch @@ -0,0 +1,193 @@ +diff --git a/autotests/integration/lockscreen.cpp b/autotests/integration/lockscreen.cpp +index 8d3b5d1a72..4786617ca6 100644 +--- a/autotests/integration/lockscreen.cpp ++++ b/autotests/integration/lockscreen.cpp +@@ -665,18 +665,18 @@ void LockScreenTest::testAxisShortcut() + + // try to trigger the shortcut + quint32 timestamp = 1; +-#define PERFORM(expectedCount) \ +- do { \ +- Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++); \ +- if (direction == Qt::Vertical) \ +- Test::pointerAxisVertical(sign * 5.0, timestamp++); \ +- else \ +- Test::pointerAxisHorizontal(sign * 5.0, timestamp++); \ +- QCoreApplication::instance()->processEvents(); \ +- QCOMPARE(actionSpy.count(), expectedCount); \ +- Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++); \ +- QCoreApplication::instance()->processEvents(); \ +- QCOMPARE(actionSpy.count(), expectedCount); \ ++#define PERFORM(expectedCount) \ ++ do { \ ++ Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++); \ ++ if (direction == Qt::Vertical) \ ++ Test::pointerAxisVertical(sign * 15.0, timestamp++); \ ++ else \ ++ Test::pointerAxisHorizontal(sign * 15.0, timestamp++); \ ++ QCoreApplication::instance()->processEvents(); \ ++ QCOMPARE(actionSpy.count(), expectedCount); \ ++ Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++); \ ++ QCoreApplication::instance()->processEvents(); \ ++ QCOMPARE(actionSpy.count(), expectedCount); \ + } while (false) + + PERFORM(1); +diff --git a/src/globalshortcuts.cpp b/src/globalshortcuts.cpp +index 5682e2a797..40b99d2018 100644 +--- a/src/globalshortcuts.cpp ++++ b/src/globalshortcuts.cpp +@@ -240,17 +240,16 @@ bool GlobalShortcutsManager::processKeyRelease(Qt::KeyboardModifiers mods, int k + } + + template +-bool match(QList &shortcuts, Args... args) ++GlobalShortcut *match(QList &shortcuts, Args... args) + { + for (auto &sc : shortcuts) { + if (std::holds_alternative(sc.shortcut())) { + if (std::get(sc.shortcut()) == ShortcutKind{args...}) { +- sc.invoke(); +- return true; ++ return ≻ + } + } + } +- return false; ++ return nullptr; + } + + // TODO(C++20): use ranges for a nicer way of filtering by shortcut type +@@ -266,10 +265,14 @@ bool GlobalShortcutsManager::processPointerPressed(Qt::KeyboardModifiers mods, Q + Q_ARG(Qt::MouseButtons, pointerButtons)); + } + #endif +- return match(m_shortcuts, mods, pointerButtons); ++ GlobalShortcut *shortcut = match(m_shortcuts, mods, pointerButtons); ++ if (shortcut) { ++ shortcut->invoke(); ++ } ++ return shortcut != nullptr; + } + +-bool GlobalShortcutsManager::processAxis(Qt::KeyboardModifiers mods, PointerAxisDirection axis) ++bool GlobalShortcutsManager::processAxis(Qt::KeyboardModifiers mods, PointerAxisDirection axis, qreal delta) + { + #if KWIN_BUILD_GLOBALSHORTCUTS + // currently only used to better support modifier only shortcuts +@@ -281,7 +284,11 @@ bool GlobalShortcutsManager::processAxis(Qt::KeyboardModifiers mods, PointerAxis + Q_ARG(int, axis)); + } + #endif +- return match(m_shortcuts, mods, axis); ++ GlobalShortcut *shortcut = match(m_shortcuts, mods, axis); ++ if (shortcut && std::abs(delta) >= 1.0f) { ++ shortcut->invoke(); ++ } ++ return shortcut != nullptr; + } + + void GlobalShortcutsManager::processSwipeStart(DeviceType device, uint fingerCount) +diff --git a/src/globalshortcuts.h b/src/globalshortcuts.h +index 13c4239cae..4a2748cf39 100644 +--- a/src/globalshortcuts.h ++++ b/src/globalshortcuts.h +@@ -98,7 +98,7 @@ public: + * @param axis The axis direction which has triggered this event + * @return @c true if a shortcut triggered, @c false otherwise + */ +- bool processAxis(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis); ++ bool processAxis(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, qreal delta); + + void processSwipeStart(DeviceType device, uint fingerCount); + void processSwipeUpdate(DeviceType device, const QPointF &delta); +diff --git a/src/input.cpp b/src/input.cpp +index 52dd7be865..4bc5b7f719 100644 +--- a/src/input.cpp ++++ b/src/input.cpp +@@ -976,6 +976,29 @@ private: + QMap m_touchPoints; + }; + ++class MouseWheelAccumulator ++{ ++public: ++ qreal accumulate(PointerAxisEvent *event) ++ { ++ const qreal delta = event->deltaV120 != 0 ? event->deltaV120 / 120.0 : event->delta / 15.0; ++ if (std::signbit(m_scrollDistance) != std::signbit(delta)) { ++ m_scrollDistance = 0; ++ } ++ m_scrollDistance += delta; ++ if (std::abs(m_scrollDistance) >= 1.0) { ++ const qreal ret = m_scrollDistance; ++ m_scrollDistance = std::fmod(m_scrollDistance, 1.0f); ++ return ret - m_scrollDistance; ++ } else { ++ return 0; ++ } ++ } ++ ++private: ++ qreal m_scrollDistance = 0; ++}; ++ + #if KWIN_BUILD_GLOBALSHORTCUTS + class GlobalShortcutFilter : public InputEventFilter + { +@@ -1008,15 +1031,15 @@ public: + } else if (event->delta > 0) { + direction = PointerAxisLeft; + } ++ return input()->shortcuts()->processAxis(event->modifiers, direction, m_horizontalAccumulator.accumulate(event)); + } else { + if (event->delta < 0) { + direction = PointerAxisDown; + } else if (event->delta > 0) { + direction = PointerAxisUp; + } ++ return input()->shortcuts()->processAxis(event->modifiers, direction, m_verticalAccumulator.accumulate(event)); + } +- +- return input()->shortcuts()->processAxis(event->modifiers, direction); + } + bool keyboardKey(KeyboardKeyEvent *event) override + { +@@ -1229,6 +1252,8 @@ private: + QPointF m_lastAverageDistance; + QMap m_touchPoints; + int m_touchpadGestureFingerCount = 0; ++ MouseWheelAccumulator m_horizontalAccumulator; ++ MouseWheelAccumulator m_verticalAccumulator; + + QTimer m_powerDown; + }; +@@ -1515,28 +1540,6 @@ private: + QList m_touchPoints; + }; + +-class MouseWheelAccumulator +-{ +-public: +- float accumulate(PointerAxisEvent *event) +- { +- m_scrollV120 += event->deltaV120; +- m_scrollDistance += event->delta; +- if (std::abs(m_scrollV120) >= 120 || (!event->deltaV120 && std::abs(m_scrollDistance) >= 15)) { +- float ret = m_scrollDistance; +- m_scrollV120 = 0; +- m_scrollDistance = 0; +- return ret; +- } else { +- return 0; +- } +- } +- +-private: +- float m_scrollDistance = 0; +- int m_scrollV120 = 0; +-}; +- + class DecorationEventFilter : public InputEventFilter + { + public: diff --git a/roles/kde/patches/kwin/pr7430.patch b/roles/kde/patches/kwin/pr7430.patch new file mode 100644 index 0000000..053e084 --- /dev/null +++ b/roles/kde/patches/kwin/pr7430.patch @@ -0,0 +1,151 @@ +diff --git a/autotests/integration/decoration_input_test.cpp b/autotests/integration/decoration_input_test.cpp +index 7390b34aab..61312a389b 100644 +--- a/autotests/integration/decoration_input_test.cpp ++++ b/autotests/integration/decoration_input_test.cpp +@@ -655,9 +655,9 @@ void DecorationInputTest::testModifierScrollOpacity() + } + QFETCH(int, modifierKey); + Test::keyboardKeyPressed(modifierKey, timestamp++); +- Test::pointerAxisVertical(-5, timestamp++); ++ Test::pointerAxisVertical(-15, timestamp++); + QCOMPARE(window->opacity(), 0.6); +- Test::pointerAxisVertical(5, timestamp++); ++ Test::pointerAxisVertical(15, timestamp++); + QCOMPARE(window->opacity(), 0.5); + Test::keyboardKeyReleased(modifierKey, timestamp++); + if (capsLock) { +diff --git a/autotests/integration/internal_window.cpp b/autotests/integration/internal_window.cpp +index 338ad6eca9..8ebd191e9a 100644 +--- a/autotests/integration/internal_window.cpp ++++ b/autotests/integration/internal_window.cpp +@@ -291,9 +291,9 @@ void InternalWindowTest::testPointerAxis() + quint32 timestamp = 1; + Test::pointerMotion(QPoint(50, 50), timestamp++); + +- Test::pointerAxisVertical(5.0, timestamp++); ++ Test::pointerAxisVertical(15.0, timestamp++); + QTRY_COMPARE(wheelSpy.count(), 1); +- Test::pointerAxisHorizontal(5.0, timestamp++); ++ Test::pointerAxisHorizontal(15.0, timestamp++); + QTRY_COMPARE(wheelSpy.count(), 2); + } + +@@ -465,9 +465,9 @@ void InternalWindowTest::testModifierScroll() + QCOMPARE(internalWindow->opacity(), 0.5); + quint32 timestamp = 1; + Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++); +- Test::pointerAxisVertical(-5, timestamp++); ++ Test::pointerAxisVertical(-15, timestamp++); + QCOMPARE(internalWindow->opacity(), 0.6); +- Test::pointerAxisVertical(5, timestamp++); ++ Test::pointerAxisVertical(15, timestamp++); + QCOMPARE(internalWindow->opacity(), 0.5); + Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++); + } +diff --git a/autotests/integration/lockscreen.cpp b/autotests/integration/lockscreen.cpp +index 8d3b5d1a72..62fe990550 100644 +--- a/autotests/integration/lockscreen.cpp ++++ b/autotests/integration/lockscreen.cpp +@@ -339,7 +339,7 @@ void LockScreenTest::testPointerAxis() + // and simulate axis + Test::pointerAxisHorizontal(5.0, timestamp++); + QVERIFY(!axisChangedSpy.wait(10)); +- Test::pointerAxisVertical(5.0, timestamp++); ++ Test::pointerAxisVertical(15.0, timestamp++); + QVERIFY(!axisChangedSpy.wait(10)); + + // and unlock +@@ -348,9 +348,9 @@ void LockScreenTest::testPointerAxis() + QCOMPARE(enteredSpy.count(), 2); + + // and move axis again +- Test::pointerAxisHorizontal(5.0, timestamp++); ++ Test::pointerAxisHorizontal(15.0, timestamp++); + QVERIFY(axisChangedSpy.wait()); +- Test::pointerAxisVertical(5.0, timestamp++); ++ Test::pointerAxisVertical(15.0, timestamp++); + QVERIFY(axisChangedSpy.wait()); + } + +diff --git a/autotests/integration/no_global_shortcuts_test.cpp b/autotests/integration/no_global_shortcuts_test.cpp +index 5e5ea1676b..65add952ea 100644 +--- a/autotests/integration/no_global_shortcuts_test.cpp ++++ b/autotests/integration/no_global_shortcuts_test.cpp +@@ -177,9 +177,9 @@ void NoGlobalShortcutsTest::testAxisShortcut() + quint32 timestamp = 1; + Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++); + if (direction == Qt::Vertical) { +- Test::pointerAxisVertical(sign * 5.0, timestamp++); ++ Test::pointerAxisVertical(sign * 15.0, timestamp++); + } else { +- Test::pointerAxisHorizontal(sign * 5.0, timestamp++); ++ Test::pointerAxisHorizontal(sign * 15.0, timestamp++); + } + QCoreApplication::instance()->processEvents(); + QCOMPARE(actionSpy.count(), 0); +diff --git a/autotests/integration/pointer_constraints_test.cpp b/autotests/integration/pointer_constraints_test.cpp +index 06ab277863..497bb5ac73 100644 +--- a/autotests/integration/pointer_constraints_test.cpp ++++ b/autotests/integration/pointer_constraints_test.cpp +@@ -189,9 +189,9 @@ void TestPointerConstraints::testConfinedPointer() + QCOMPARE(window->opacity(), 0.5); + + // pointer is confined so shortcut should not work +- Test::pointerAxisVertical(-5, timestamp++); ++ Test::pointerAxisVertical(-15, timestamp++); + QCOMPARE(window->opacity(), 0.5); +- Test::pointerAxisVertical(5, timestamp++); ++ Test::pointerAxisVertical(15, timestamp++); + QCOMPARE(window->opacity(), 0.5); + + Test::keyboardKeyReleased(KEY_LEFTALT, timestamp++); +diff --git a/autotests/integration/pointer_input.cpp b/autotests/integration/pointer_input.cpp +index f444471562..12c8c5736b 100644 +--- a/autotests/integration/pointer_input.cpp ++++ b/autotests/integration/pointer_input.cpp +@@ -695,9 +695,9 @@ void PointerInputTest::testModifierScrollOpacity() + } + QFETCH(int, modifierKey); + Test::keyboardKeyPressed(modifierKey, timestamp++); +- Test::pointerAxisVertical(-5, timestamp++); ++ Test::pointerAxisVertical(-15, timestamp++); + QCOMPARE(window->opacity(), 0.6); +- Test::pointerAxisVertical(5, timestamp++); ++ Test::pointerAxisVertical(15, timestamp++); + QCOMPARE(window->opacity(), 0.5); + Test::keyboardKeyReleased(modifierKey, timestamp++); + if (capsLock) { +@@ -753,9 +753,9 @@ void PointerInputTest::testModifierScrollOpacityGlobalShortcutsDisabled() + // simulate modifier+wheel + quint32 timestamp = 1; + Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++); +- Test::pointerAxisVertical(-5, timestamp++); ++ Test::pointerAxisVertical(-15, timestamp++); + QCOMPARE(window->opacity(), 0.5); +- Test::pointerAxisVertical(5, timestamp++); ++ Test::pointerAxisVertical(15, timestamp++); + QCOMPARE(window->opacity(), 0.5); + Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++); + +@@ -800,7 +800,7 @@ void PointerInputTest::testScrollAction() + + quint32 timestamp = 1; + QVERIFY(!window1->isActive()); +- Test::pointerAxisVertical(5, timestamp++); ++ Test::pointerAxisVertical(15, timestamp++); + QVERIFY(window1->isActive()); + + // but also the wheel event should be passed to the window +diff --git a/autotests/integration/touch_input_test.cpp b/autotests/integration/touch_input_test.cpp +index 8f739ff2a5..df68e1b47e 100644 +--- a/autotests/integration/touch_input_test.cpp ++++ b/autotests/integration/touch_input_test.cpp +@@ -146,7 +146,7 @@ void TouchInputTest::testTouchHidesCursor() + QCOMPARE(Cursors::self()->isCursorHidden(), true); + + // wheel should also show +- Test::pointerAxisVertical(1.0, timestamp++); ++ Test::pointerAxisVertical(15.0, timestamp++); + QCOMPARE(Cursors::self()->isCursorHidden(), false); + } + diff --git a/roles/kde/patches/kwin/pr7441.patch b/roles/kde/patches/kwin/pr7441.patch new file mode 100644 index 0000000..e2422af --- /dev/null +++ b/roles/kde/patches/kwin/pr7441.patch @@ -0,0 +1,61 @@ +From 2022febc84989dba04a4677f3c187a057dece522 Mon Sep 17 00:00:00 2001 +From: Aleix Pol +Date: Fri, 4 Apr 2025 00:59:29 +0200 +Subject: [PATCH] screenedge: Hardcode the cornerOffset value + +At the moment we were using fonts to calculate it which would slow us +down at startup for little pay-off. +We were using visual metrics for a touch scaling which is wrong so let's +just hardcode a value. +On my system (running default fonts) gridUnit was 9 and thus was +resulting on 36, rounded up to 40. +--- + src/screenedge.cpp | 9 +-------- + src/screenedge.h | 2 +- + 2 files changed, 2 insertions(+), 9 deletions(-) + +diff --git a/src/screenedge.cpp b/src/screenedge.cpp +index adbac936f20..fb42ecc9330 100644 +--- a/src/screenedge.cpp ++++ b/src/screenedge.cpp +@@ -42,12 +42,6 @@ + #include + #include + #include +-#include +-#include +-#include +-#include +-#include +-#include + #include + + using namespace std::chrono_literals; +@@ -766,10 +760,9 @@ ScreenEdges::ScreenEdges() + , m_actionBottom(ElectricActionNone) + , m_actionBottomLeft(ElectricActionNone) + , m_actionLeft(ElectricActionNone) ++ , m_cornerOffset(40) + , m_gestureRecognizer(new GestureRecognizer(this)) + { +- const int gridUnit = QFontMetrics(QFontDatabase::systemFont(QFontDatabase::GeneralFont)).boundingRect(QLatin1Char('M')).height(); +- m_cornerOffset = 4 * gridUnit; + } + + void ScreenEdges::init() +diff --git a/src/screenedge.h b/src/screenedge.h +index b208edf3c98..8417f2aee57 100644 +--- a/src/screenedge.h ++++ b/src/screenedge.h +@@ -388,7 +388,7 @@ private: + ElectricBorderAction m_actionBottomLeft; + ElectricBorderAction m_actionLeft; + QMap m_touchCallbacks; +- int m_cornerOffset; ++ const int m_cornerOffset; + GestureRecognizer *m_gestureRecognizer; + bool m_remainActiveOnFullscreen = false; + }; +-- +GitLab + From 6292a84a01a9e044e2da8d484e52991b817be42d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 15 Apr 2025 17:26:54 +0200 Subject: [PATCH 0973/1125] Flake: remove school role --- flake.nix | 3 --- roles/school/default.nix | 12 --------- roles/school/programs/android-studio.nix | 7 ----- roles/school/programs/default.nix | 7 ----- roles/school/programs/helix.nix | 25 ------------------ roles/school/services/default.nix | 7 ----- roles/school/services/mysql.nix | 33 ------------------------ roles/school/services/networkmanager.nix | 19 -------------- roles/school/services/syncthing.nix | 8 ------ 9 files changed, 121 deletions(-) delete mode 100644 roles/school/default.nix delete mode 100644 roles/school/programs/android-studio.nix delete mode 100644 roles/school/programs/default.nix delete mode 100644 roles/school/programs/helix.nix delete mode 100644 roles/school/services/default.nix delete mode 100644 roles/school/services/mysql.nix delete mode 100644 roles/school/services/networkmanager.nix delete mode 100644 roles/school/services/syncthing.nix diff --git a/flake.nix b/flake.nix index 4c0a742..4a27077 100644 --- a/flake.nix +++ b/flake.nix @@ -194,7 +194,6 @@ ./roles/desktop ./roles/kde ./roles/gaming - ./roles/school ]; SurfaceGo.modules = [ nixos-hardware.nixosModules.microsoft-surface-go @@ -214,7 +213,6 @@ ./roles/desktop ./roles/kde ./roles/gaming - ./roles/school ]; Everest = { stable = true; @@ -225,7 +223,6 @@ iMac.modules = [ ./roles/desktop ./roles/gnome - ./roles/school ]; }; }; diff --git a/roles/school/default.nix b/roles/school/default.nix deleted file mode 100644 index d50b99e..0000000 --- a/roles/school/default.nix +++ /dev/null @@ -1,12 +0,0 @@ -{pkgs, ...}: { - imports = [ - ./programs - ./services - ]; - home-manager.users.toast.home.packages = with pkgs; [ - jetbrains.idea-ultimate - jetbrains.webstorm - nodejs - insomnia - ]; -} diff --git a/roles/school/programs/android-studio.nix b/roles/school/programs/android-studio.nix deleted file mode 100644 index b2b0c5f..0000000 --- a/roles/school/programs/android-studio.nix +++ /dev/null @@ -1,7 +0,0 @@ -{pkgs, ...}: { - programs.adb.enable = true; - users.users.toast.extraGroups = ["adbusers"]; - home-manager.users.toast.home.packages = with pkgs; [ - android-studio - ]; -} diff --git a/roles/school/programs/default.nix b/roles/school/programs/default.nix deleted file mode 100644 index 60764e0..0000000 --- a/roles/school/programs/default.nix +++ /dev/null @@ -1,7 +0,0 @@ -{pkgs, ...}: { - imports = [ - ./android-studio.nix - ./helix.nix - ]; - home-manager.users.toast.home.packages = [pkgs.mongodb-compass]; -} diff --git a/roles/school/programs/helix.nix b/roles/school/programs/helix.nix deleted file mode 100644 index 8d1d235..0000000 --- a/roles/school/programs/helix.nix +++ /dev/null @@ -1,25 +0,0 @@ -{pkgs, ...}: { - home-manager.users.toast = { - programs.helix = { - extraPackages = with pkgs; [ - typescript-language-server - prettierd - ]; - languages.language = let - mkPrettierdConfig = ( - langName: fileExt: { - name = langName; - formatter = { - command = "prettierd"; - args = [".${fileExt}"]; - }; - } - ); - in [ - (mkPrettierdConfig "javascript" "js") - (mkPrettierdConfig "typescript" "ts") - (mkPrettierdConfig "tsx" "tsx") - ]; - }; - }; -} diff --git a/roles/school/services/default.nix b/roles/school/services/default.nix deleted file mode 100644 index 9fa78cd..0000000 --- a/roles/school/services/default.nix +++ /dev/null @@ -1,7 +0,0 @@ -{...}: { - imports = [ - ./networkmanager.nix - ./syncthing.nix - ./mysql.nix - ]; -} diff --git a/roles/school/services/mysql.nix b/roles/school/services/mysql.nix deleted file mode 100644 index 6a3ebab..0000000 --- a/roles/school/services/mysql.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ - config, - pkgs, - lib, - ... -}: { - services.mysql = { - enable = true; - package = pkgs.mysql84; - user = "toast"; - group = "users"; - }; - - # Don't autostart MySQL - systemd.services.mysql.wantedBy = lib.mkForce []; - - security.polkit.extraConfig = '' - polkit.addRule(function(action, subject) { - if ( - action.id == "org.freedesktop.systemd1.manage-units" && - action.lookup("unit") == "mysql.service" && - subject.user == "${config.services.mysql.user}" - ) - { - return polkit.Result.YES; - } - }) - ''; - - environment.systemPackages = with pkgs; [ - # mycli - ]; -} diff --git a/roles/school/services/networkmanager.nix b/roles/school/services/networkmanager.nix deleted file mode 100644 index 72fabd4..0000000 --- a/roles/school/services/networkmanager.nix +++ /dev/null @@ -1,19 +0,0 @@ -{...}: { - networking.networkmanager.ensureProfiles = { - profiles."school-wifi" = { - connection = { - id = "Progresa"; - type = "wifi"; - }; - wifi = { - mode = "infrastructure"; - ssid = ".Progresa Invitados"; - }; - wifi-security = { - auth-alg = "open"; - key-mgmt = "wpa-psk"; - psk = "$SCHOOL"; - }; - }; - }; -} diff --git a/roles/school/services/syncthing.nix b/roles/school/services/syncthing.nix deleted file mode 100644 index e1eabd2..0000000 --- a/roles/school/services/syncthing.nix +++ /dev/null @@ -1,8 +0,0 @@ -{...}: { - services.syncthing.settings.folders. "school-things" = { - label = "School things"; - id = "btsth-vdu9c"; - devices = ["server" "pc" "winmax2" "imac"]; - path = "~/Documents/School things"; - }; -} From 83977d50ae9c2209e33ebf7a5a63ad6b16170030 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 18 Apr 2025 00:38:38 +0200 Subject: [PATCH 0974/1125] Gaming: install azahar --- roles/gaming/programs/azahar.nix | 18 ++++++++++++++++++ roles/gaming/programs/default.nix | 1 + 2 files changed, 19 insertions(+) create mode 100644 roles/gaming/programs/azahar.nix diff --git a/roles/gaming/programs/azahar.nix b/roles/gaming/programs/azahar.nix new file mode 100644 index 0000000..1c77688 --- /dev/null +++ b/roles/gaming/programs/azahar.nix @@ -0,0 +1,18 @@ +{pkgs, ...}: { + nixpkgs.overlays = [ + ( + final: prev: { + azahar = prev.azahar.overrideAttrs (old: { + version = "2120.3"; + src = final.fetchzip { + url = "https://github.com/azahar-emu/azahar/releases/download/2120.3/azahar-unified-source-20250414-00e3bbb.tar.xz"; + hash = "sha256-3QKicmpmWDM7x9GDJ8sxm2Xu+0Yfho4LkSWMp+ixzRk="; + }; + }); + } + ) + ]; + home-manager.users.toast = { + home.packages = [pkgs.azahar]; + }; +} diff --git a/roles/gaming/programs/default.nix b/roles/gaming/programs/default.nix index 6686119..fda1ac9 100755 --- a/roles/gaming/programs/default.nix +++ b/roles/gaming/programs/default.nix @@ -6,6 +6,7 @@ ./retroarch.nix ./pcsx2.nix ./cemu.nix + ./azahar.nix ]; environment.systemPackages = with pkgs; [ heroic From f06d9b0e01638af253338f40fb7fe7cd08483f08 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 16 Apr 2025 09:07:40 +0200 Subject: [PATCH 0975/1125] Machines/WinMax2: don't disable direct scanout --- machines/WinMax2/configuration.nix | 3 --- 1 file changed, 3 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 366ed21..96bad5b 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -36,9 +36,6 @@ networking.hostName = "WinMax2"; # Define your hostname. - # Direct scanout has some issues with my egpu so I just disable it - environment.sessionVariables."KWIN_DRM_NO_DIRECT_SCANOUT" = 1; - # Sleep fixes boot.kernelParams = ["rtc_cmos.use_acpi_alarm=1" "panic=5"]; services.udev.extraRules = '' From 1a927b60be3bc3f9931f5b5bd31d089540822e37 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 24 Apr 2025 11:19:19 +0200 Subject: [PATCH 0976/1125] Keep nixpkgs-patches folder --- nixpkgs-patches/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 nixpkgs-patches/.gitkeep diff --git a/nixpkgs-patches/.gitkeep b/nixpkgs-patches/.gitkeep new file mode 100644 index 0000000..e69de29 From f8140164d121ca5e51e9cc180a0ddfdfb9661127 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 25 Apr 2025 10:57:31 +0200 Subject: [PATCH 0977/1125] Desktop/jamesdsp: remove old build fix Patch that fixes the build is already upstreamed, so this is entirely unneeded. Not even sure how it still compiled with the fix twize tbh --- roles/desktop/programs/jamesdsp.nix | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/roles/desktop/programs/jamesdsp.nix b/roles/desktop/programs/jamesdsp.nix index cb2056c..0aaa341 100644 --- a/roles/desktop/programs/jamesdsp.nix +++ b/roles/desktop/programs/jamesdsp.nix @@ -4,21 +4,4 @@ jamesdsp ]; }; - nixpkgs.overlays = [ - ( - final: prev: { - # https://github.com/wwmm/easyeffects/commit/38bef46bffdb535e2a70c3332719c557ff577e56 - jamesdsp = prev.jamesdsp.overrideAttrs { - patchPhase = '' - substituteInPlace src/audio/pipewire/PwPipelineManager.cpp \ - --replace-fail "pw_node_add_listener" "pw_proxy_add_object_listener" \ - --replace-fail "pw_link_add_listener" "pw_proxy_add_object_listener" \ - --replace-fail "pw_module_add_listener" "pw_proxy_add_object_listener" \ - --replace-fail "pw_client_add_listener" "pw_proxy_add_object_listener" \ - --replace-fail "pw_device_add_listener" "pw_proxy_add_object_listener" - ''; - }; - } - ) - ]; } From db6366a4911990bf753ff7986a45c204e2d686ef Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 27 Apr 2025 00:21:53 +0200 Subject: [PATCH 0978/1125] Flake: update lock file --- flake.lock | 74 +++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/flake.lock b/flake.lock index c5cd8a1..e9c40cb 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1743414153, - "narHash": "sha256-bFIXz7SvLlSNR4M3vYPYS1CpEN9vTUiH01R4iR/BDmA=", + "lastModified": 1745571143, + "narHash": "sha256-BndQEgBtQh6kPC+2PYdf9iWTSmrbaPjTFkVei2OtuKk=", "owner": "catppuccin", "repo": "nix", - "rev": "2f52f9ead26f80d7b391cedcbb3eb309bd83fff4", + "rev": "19919d666ead54e97f7886813db08f76ae0981dc", "type": "github" }, "original": { @@ -167,11 +167,11 @@ ] }, "locked": { - "lastModified": 1743648554, - "narHash": "sha256-23JFd+zd2GamTTdnGuFVeIg8x8C3hLpQJRh/PGTORzo=", + "lastModified": 1745555634, + "narHash": "sha256-lhVyVn1utb2UVTbyKJ6mfKB7wLTjrj14OlebvO0WU2s=", "owner": "nix-community", "repo": "home-manager", - "rev": "107352dde4ff3c01cb5a0b3fe17f5beef37215bc", + "rev": "98f4fef7fd7b4a77245db12e33616023162bc6d9", "type": "github" }, "original": { @@ -187,11 +187,11 @@ ] }, "locked": { - "lastModified": 1743387206, - "narHash": "sha256-24N3NAuZZbYqZ39NgToZgHUw6M7xHrtrAm18kv0+2Wo=", + "lastModified": 1745557122, + "narHash": "sha256-eqSo9ugzsqhFgaDFYUZj943nurlX4L6f+AW0skJ4W+M=", "owner": "nix-community", "repo": "home-manager", - "rev": "15c5f9d04fabd176f30286c8f52bbdb2c853a146", + "rev": "dd26f75fb4ec1c731d4b1396eaf4439ce40a91c1", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1743660830, - "narHash": "sha256-ezJqPIuB25iMJeugwHKWnB1DjMvrdpkrPxE3TCULjGk=", + "lastModified": 1745487384, + "narHash": "sha256-WvQ4XXi0vMtEpPqhfo8ztxjeaeHkbW5tfR4O5+w8r5U=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "c7ade1c8fe2bdb70d38b3b9a97b874dcaf33b755", + "rev": "0168e4a65c9d43c22ac38ff27f5fa31c7d535148", "type": "github" }, "original": { @@ -225,11 +225,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1743523803, - "narHash": "sha256-L/8tnMbfwOmRXRrzzDJBlkRUiVOxy8cxWTdaN3n3AGI=", - "rev": "5a7e9e17464008904403af4297823443281bef12", + "lastModified": 1745521626, + "narHash": "sha256-+7DQIKTkvpWYz8bjYfye9T61C5QAUKPEy1YCsXUDCkE=", + "rev": "a133633ecc4ca3aed65899cb37c17601c95f5b2b", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/5a7e9e17464008904403af4297823443281bef12.tar.gz?rev=5a7e9e17464008904403af4297823443281bef12" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/a133633ecc4ca3aed65899cb37c17601c95f5b2b.tar.gz?rev=a133633ecc4ca3aed65899cb37c17601c95f5b2b" }, "original": { "type": "tarball", @@ -284,11 +284,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1741903049, - "narHash": "sha256-8Y8brH04JjSLrCLvBEbhK9vOu7lhQhqUBW4kI3tifdI=", + "lastModified": 1744659587, + "narHash": "sha256-xJnbmRVte13akgn+Prg06IaRHJ5OX3uVltwsCP/mxoc=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "42c7fb2702219b86a8f5969c3475ce594c28f5d0", + "rev": "928d868a9141b48f152d3b2b00c433e688d4b106", "type": "github" }, "original": { @@ -342,11 +342,11 @@ ] }, "locked": { - "lastModified": 1743306489, - "narHash": "sha256-LROaIjSLo347cwcHRfSpqzEOa2FoLSeJwU4dOrGm55E=", + "lastModified": 1745120797, + "narHash": "sha256-owQ0VQ+7cSanTVPxaZMWEzI22Q4bGnuvhVjLAJBNQ3E=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "b3696bfb6c24aa61428839a99e8b40c53ac3a82d", + "rev": "69716041f881a2af935021c1182ed5b0cc04d40e", "type": "github" }, "original": { @@ -362,11 +362,11 @@ ] }, "locked": { - "lastModified": 1743306489, - "narHash": "sha256-LROaIjSLo347cwcHRfSpqzEOa2FoLSeJwU4dOrGm55E=", + "lastModified": 1745120797, + "narHash": "sha256-owQ0VQ+7cSanTVPxaZMWEzI22Q4bGnuvhVjLAJBNQ3E=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "b3696bfb6c24aa61428839a99e8b40c53ac3a82d", + "rev": "69716041f881a2af935021c1182ed5b0cc04d40e", "type": "github" }, "original": { @@ -377,11 +377,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1743420942, - "narHash": "sha256-b/exDDQSLmENZZgbAEI3qi9yHkuXAXCPbormD8CSJXo=", + "lastModified": 1745503349, + "narHash": "sha256-bUGjvaPVsOfQeTz9/rLTNLDyqbzhl0CQtJJlhFPhIYw=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "de6fc5551121c59c01e2a3d45b277a6d05077bc4", + "rev": "f7bee55a5e551bd8e7b5b82c9bc559bc50d868d1", "type": "github" }, "original": { @@ -393,11 +393,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1742889210, - "narHash": "sha256-hw63HnwnqU3ZQfsMclLhMvOezpM7RSB0dMAtD5/sOiw=", + "lastModified": 1744463964, + "narHash": "sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR+Xhw3kr/3Xd0GPTM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "698214a32beb4f4c8e3942372c694f40848b360d", + "rev": "2631b0b7abcea6e640ce31cd78ea58910d31e650", "type": "github" }, "original": { @@ -409,11 +409,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1743576891, - "narHash": "sha256-vXiKURtntURybE6FMNFAVpRPr8+e8KoLPrYs9TGuAKc=", + "lastModified": 1745487689, + "narHash": "sha256-FQoi3R0NjQeBAsEOo49b5tbDPcJSMWc3QhhaIi9eddw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "44a69ed688786e98a101f02b712c313f1ade37ab", + "rev": "5630cf13cceac06cefe9fc607e8dfa8fb342dde3", "type": "github" }, "original": { @@ -424,11 +424,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1743583204, - "narHash": "sha256-F7n4+KOIfWrwoQjXrL2wD9RhFYLs2/GGe/MQY1sSdlE=", + "lastModified": 1745391562, + "narHash": "sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2c8d3f48d33929642c1c12cd243df4cc7d2ce434", + "rev": "8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7", "type": "github" }, "original": { From 85c3c570ddd1c78cd64e50c902d2e2f4ab75aa78 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 27 Apr 2025 00:23:28 +0200 Subject: [PATCH 0979/1125] Flake: add nixpkgs patches Update and fix rpcs3 package --- flake.nix | 2 + nixpkgs-patches/pr386360.patch | 71 +++++++++++++++++++++++ nixpkgs-patches/pr400900.patch | 101 +++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 nixpkgs-patches/pr386360.patch create mode 100644 nixpkgs-patches/pr400900.patch diff --git a/flake.nix b/flake.nix index 4a27077..ae0560c 100644 --- a/flake.nix +++ b/flake.nix @@ -97,6 +97,8 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ + ./nixpkgs-patches/pr400900.patch + ./nixpkgs-patches/pr386360.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr386360.patch b/nixpkgs-patches/pr386360.patch new file mode 100644 index 0000000..9733a0a --- /dev/null +++ b/nixpkgs-patches/pr386360.patch @@ -0,0 +1,71 @@ +From ec004ef5f30f4ea66ce0b77bab5ce778883aff5d Mon Sep 17 00:00:00 2001 +From: Zane van Iperen +Date: Tue, 1 Apr 2025 20:23:42 +0900 +Subject: [PATCH] rpcs3: 0.0.34-17323-92d070729 -> 0.0.36-17736-c86a25079 + +--- + pkgs/by-name/rp/rpcs3/package.nix | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/pkgs/by-name/rp/rpcs3/package.nix b/pkgs/by-name/rp/rpcs3/package.nix +index 779d9048ca0ea0..dc39a9bc61e384 100644 +--- a/pkgs/by-name/rp/rpcs3/package.nix ++++ b/pkgs/by-name/rp/rpcs3/package.nix +@@ -21,12 +21,14 @@ + python3, + pugixml, + flatbuffers, +- llvm_16, ++ llvm_18, + cubeb, ++ opencv, + enableDiscordRpc ? false, + faudioSupport ? true, + faudio, + SDL2, ++ sdl3, + waylandSupport ? true, + wayland, + wrapGAppsHook3, +@@ -34,10 +36,10 @@ + + let + # Keep these separate so the update script can regex them +- rpcs3GitVersion = "17323-92d070729"; +- rpcs3Version = "0.0.34-17323-92d070729"; +- rpcs3Revision = "92d07072915b99917892dd7833c06eb44a09e234"; +- rpcs3Hash = "sha256-GH2sXw1AYdqwzxucXFhVS0nM0eRhC+XDHS6RTZY8pYY="; ++ rpcs3GitVersion = "17736-c86a25079"; ++ rpcs3Version = "0.0.36-17736-c86a25079"; ++ rpcs3Revision = "c86a25079518032d73395a79979970acb2581a91"; ++ rpcs3Hash = "sha256-e+mT3qn1oz1fh2bqu5YM+m774Can34If57Kd1T1EGbk="; + + inherit (qt6Packages) + qtbase +@@ -77,9 +79,11 @@ stdenv.mkDerivation { + (lib.cmakeBool "USE_SYSTEM_CURL" true) + (lib.cmakeBool "USE_SYSTEM_WOLFSSL" true) + (lib.cmakeBool "USE_SYSTEM_FAUDIO" true) ++ (lib.cmakeBool "USE_SYSTEM_OPENAL" true) + (lib.cmakeBool "USE_SYSTEM_PUGIXML" true) + (lib.cmakeBool "USE_SYSTEM_FLATBUFFERS" true) + (lib.cmakeBool "USE_SYSTEM_SDL" true) ++ (lib.cmakeBool "USE_SYSTEM_OPENCV" true) + (lib.cmakeBool "USE_SDL" true) + (lib.cmakeBool "WITH_LLVM" true) + (lib.cmakeBool "BUILD_LLVM" false) +@@ -115,10 +119,12 @@ stdenv.mkDerivation { + wolfssl + python3 + pugixml +- SDL2 ++ SDL2 # Still needed by FAudio's CMake ++ sdl3 + flatbuffers +- llvm_16 ++ llvm_18 + libSM ++ opencv + ] + ++ cubeb.passthru.backendLibs + ++ lib.optional faudioSupport faudio diff --git a/nixpkgs-patches/pr400900.patch b/nixpkgs-patches/pr400900.patch new file mode 100644 index 0000000..457acfc --- /dev/null +++ b/nixpkgs-patches/pr400900.patch @@ -0,0 +1,101 @@ +From 66e2bdbc88f1985c0960c29e991ffcbb8b180cc0 Mon Sep 17 00:00:00 2001 +From: Marcin Serwin +Date: Tue, 22 Apr 2025 20:04:11 +0200 +Subject: [PATCH] rpcs3: unbreak + +--- + .../rp/rpcs3/fix-qt6.9-compilation.patch | 68 +++++++++++++++++++ + pkgs/by-name/rp/rpcs3/package.nix | 5 ++ + 2 files changed, 73 insertions(+) + create mode 100644 pkgs/by-name/rp/rpcs3/fix-qt6.9-compilation.patch + +diff --git a/pkgs/by-name/rp/rpcs3/fix-qt6.9-compilation.patch b/pkgs/by-name/rp/rpcs3/fix-qt6.9-compilation.patch +new file mode 100644 +index 00000000000000..13ca314d3022ba +--- /dev/null ++++ b/pkgs/by-name/rp/rpcs3/fix-qt6.9-compilation.patch +@@ -0,0 +1,68 @@ ++From 600e4604169464c64cbf548e7629e483ad2aad1e Mon Sep 17 00:00:00 2001 ++From: Megamouse ++Date: Mon, 7 Apr 2025 20:49:15 +0200 ++Subject: [PATCH] Fix compilation with newer Qt ++ ++--- ++ rpcs3/rpcs3qt/game_list_base.cpp | 2 +- ++ rpcs3/rpcs3qt/game_list_frame.cpp | 4 ++-- ++ rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp | 4 ++-- ++ 3 files changed, 5 insertions(+), 5 deletions(-) ++ ++diff --git a/rpcs3/rpcs3qt/game_list_base.cpp b/rpcs3/rpcs3qt/game_list_base.cpp ++index 72b45d33bfbb..21640906ee7e 100644 ++--- a/rpcs3/rpcs3qt/game_list_base.cpp +++++ b/rpcs3/rpcs3qt/game_list_base.cpp ++@@ -25,7 +25,7 @@ void game_list_base::repaint_icons(std::vector& game_data, const QCol ++ for (game_info& game : game_data) ++ { ++ game->pxmap = placeholder; ++- +++ ++ if (movie_item_base* item = game->item) ++ { ++ item->set_icon_load_func([this, game, device_pixel_ratio, cancel = item->icon_loading_aborted()](int) ++diff --git a/rpcs3/rpcs3qt/game_list_frame.cpp b/rpcs3/rpcs3qt/game_list_frame.cpp ++index a294d69cc68e..439913760053 100644 ++--- a/rpcs3/rpcs3qt/game_list_frame.cpp +++++ b/rpcs3/rpcs3qt/game_list_frame.cpp ++@@ -2363,7 +2363,7 @@ void game_list_frame::BatchActionBySerials(progress_dialog* pdlg, const std::set ++ ++ connect(future_watcher, &QFutureWatcher::finished, this, [=, this]() ++ { ++- pdlg->setLabelText(progressLabel.arg(*index).arg(serials_size)); +++ pdlg->setLabelText(progressLabel.arg(index->load()).arg(serials_size)); ++ pdlg->setCancelButtonText(tr("OK")); ++ QApplication::beep(); ++ ++@@ -2396,7 +2396,7 @@ void game_list_frame::BatchActionBySerials(progress_dialog* pdlg, const std::set ++ return; ++ } ++ ++- pdlg->setLabelText(progressLabel.arg(*index).arg(serials_size)); +++ pdlg->setLabelText(progressLabel.arg(index->load()).arg(serials_size)); ++ pdlg->setCancelButtonText(tr("OK")); ++ connect(pdlg, &progress_dialog::canceled, this, [pdlg](){ pdlg->deleteLater(); }); ++ QApplication::beep(); ++diff --git a/rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp b/rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp ++index 45fbe6f59e7d..4b9bc5dd6e4f 100644 ++--- a/rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp +++++ b/rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp ++@@ -362,7 +362,7 @@ void ps_move_tracker_dialog::update_saturation_threshold(bool update_slider) ++ } ++ void ps_move_tracker_dialog::update_min_radius(bool update_slider) ++ { ++- ui->minRadiusGb->setTitle(tr("Min Radius: %0 %").arg(g_cfg_move.min_radius)); +++ ui->minRadiusGb->setTitle(tr("Min Radius: %0 %").arg(g_cfg_move.min_radius.get())); ++ ++ if (update_slider) ++ { ++@@ -372,7 +372,7 @@ void ps_move_tracker_dialog::update_min_radius(bool update_slider) ++ ++ void ps_move_tracker_dialog::update_max_radius(bool update_slider) ++ { ++- ui->maxRadiusGb->setTitle(tr("Max Radius: %0 %").arg(g_cfg_move.max_radius)); +++ ui->maxRadiusGb->setTitle(tr("Max Radius: %0 %").arg(g_cfg_move.max_radius.get())); ++ ++ if (update_slider) ++ { +diff --git a/pkgs/by-name/rp/rpcs3/package.nix b/pkgs/by-name/rp/rpcs3/package.nix +index 779d9048ca0ea0..b633453a77e61d 100644 +--- a/pkgs/by-name/rp/rpcs3/package.nix ++++ b/pkgs/by-name/rp/rpcs3/package.nix +@@ -58,6 +58,11 @@ stdenv.mkDerivation { + hash = rpcs3Hash; + }; + ++ patches = [ ++ # Modified from https://github.com/RPCS3/rpcs3/pull/17009; doesn't apply cleanly due to intermediate commits ++ ./fix-qt6.9-compilation.patch ++ ]; ++ + passthru.updateScript = ./update.sh; + + preConfigure = '' From 6e5a9ca20849964225b6ee34877389497a18e0ca Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 27 Apr 2025 02:32:00 +0200 Subject: [PATCH 0980/1125] Desktop/keepassxc: move to new module --- roles/desktop/programs/keepassxc.nix | 62 ++++++++++++---------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/roles/desktop/programs/keepassxc.nix b/roles/desktop/programs/keepassxc.nix index fd5321a..20c0d9c 100644 --- a/roles/desktop/programs/keepassxc.nix +++ b/roles/desktop/programs/keepassxc.nix @@ -1,40 +1,32 @@ -{lib, ...}: let - kpxcSettings = lib.generators.toINI {} { - General = { - # Not sure what changing this does, I'll leave it alone - ConfigVersion = 2; - MinimizeAfterUnlock = true; - AutoSaveAfterEveryChange = false; - }; - GUI = { - ApplicationTheme = "classic"; - MinimizeOnStartup = false; - MinimizeOnClose = true; - MinimizeToTray = true; - ShowTrayIcon = true; - # 0 is icons, 1 is text, 2 is text next to icons, 3 is text under icons, and 4 is follow style - ToolButtonStyle = 0; # Would choose 4 but it's too big for a small window - # monochrome-light, monochrome-dark or colorful - TrayIconAppearance = "monochrome-light"; - }; - Security = { - HideNotes = true; - IconDownloadFallback = true; - }; - SSHAgent.Enabled = true; - }; -in { +{pkgs, ...}: { home-manager = { - extraSpecialArgs = {kpxcSettings = kpxcSettings;}; users.toast = { - pkgs, - kpxcSettings, - ... - }: { - # No module for KeePassXC config :( - home = { - packages = [pkgs.keepassxc]; - file.".config/keepassxc/keepassxc.ini".text = kpxcSettings; + programs.keepassxc = { + enable = true; + settings = { + General = { + # Not sure what changing this does, I'll leave it alone + ConfigVersion = 2; + MinimizeAfterUnlock = true; + AutoSaveAfterEveryChange = false; + }; + GUI = { + ApplicationTheme = "classic"; + MinimizeOnStartup = false; + MinimizeOnClose = true; + MinimizeToTray = true; + ShowTrayIcon = true; + # 0 is icons, 1 is text, 2 is text next to icons, 3 is text under icons, and 4 is follow style + ToolButtonStyle = 0; # Would choose 4 but it's too big for a small window + # monochrome-light, monochrome-dark or colorful + TrayIconAppearance = "monochrome-light"; + }; + Security = { + HideNotes = true; + IconDownloadFallback = true; + }; + SSHAgent.Enabled = true; + }; }; xdg.autostart.entries = [ "${pkgs.keepassxc}/share/applications/org.keepassxc.KeePassXC.desktop" From f7e9fd9cada0998e5bec393e115b4dc2c214b903 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 27 Apr 2025 02:53:25 +0200 Subject: [PATCH 0981/1125] Desktop/discord: use vesktop module --- roles/desktop/programs/discord.nix | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 3df1659..abf4ec4 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -8,8 +8,16 @@ in { nixpkgs.overlays = [discordOverlay]; home-manager.users.toast = { - home.packages = with pkgs; [ - vesktop - ]; + programs.vesktop = { + enable = true; + settings = { + arRPC = true; + minimizeToTray = true; + discordBranch = "stable"; + customTitleBar = true; + spellCheckLanguages = ["en-US" "en" "es"]; + enableMenu = false; + }; + }; }; } From d2d28a968fef73f9d5585d2a03f5e05b70c062dd Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 27 Apr 2025 18:43:04 +0200 Subject: [PATCH 0982/1125] Desktop/discord: configure vencord --- roles/desktop/programs/discord.nix | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index abf4ec4..da499be 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -18,6 +18,56 @@ in { spellCheckLanguages = ["en-US" "en" "es"]; enableMenu = false; }; + vencord = { + settings = { + enabledThemes = ["catpuccin-mocha.css"]; + plugins = { + BetterGifPicker.enabled = true; + BetterSettings.enabled = true; + CallTimer.enabled = true; + ClearURLs.enabled = true; + FakeNitro.enabled = true; + FixSpotifyEmbeds.enabled = true; + FixYoutubeEmbeds.enabled = true; + FriendsSince.enabled = true; + iLoveSpam.enabled = true; + LoadingQuotes = { + enabled = true; + enableDiscordPresetQuotes = true; + }; + MessageClickActions.enabled = true; + MessageLinkEmbeds.enabled = true; + MessageLogger.enabled = true; + Moyai = { + enabled = true; + volume = 1; + quality = "HD"; + }; + OpenInApp.enabled = true; + petpet.enabled = true; + PlatformIndicators.enabled = true; + ShowHiddenChannels.enabled = true; + ShowHiddenThings.enabled = true; + SpotifyControls.enabled = true; + YoutubeAdblock.enabled = true; + }; + }; + themes = { + "catpuccin-mocha" = '' + /** + * @name Catppuccin Mocha + * @author winston#0001 + * @authorId 505490445468696576 + * @version 0.2.0 + * @description 🎮 Soothing pastel theme for Discord + * @website https://github.com/catppuccin/discord + * @invite r6Mdz5dpFc + * **/ + + @import url("https://catppuccin.github.io/discord/dist/catppuccin-mocha.theme.css"); + ''; + }; + }; }; }; } From 203ffb3738a8e95f88a461c85fcc37df592a3a5a Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 27 Apr 2025 19:01:34 +0200 Subject: [PATCH 0983/1125] Common/atuin: bring back pre 18.4 behaviour --- roles/common/programs/atuin.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/programs/atuin.nix b/roles/common/programs/atuin.nix index 105f79b..8e18cf6 100644 --- a/roles/common/programs/atuin.nix +++ b/roles/common/programs/atuin.nix @@ -5,6 +5,7 @@ enter_accept = true; workspaces = true; style = "auto"; + inline_height = 0; stats = { common_prefix = [ "sudo" From 22896ea9235a9ef822f44635144a606ba9c97896 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 27 Apr 2025 19:25:24 +0200 Subject: [PATCH 0984/1125] Common/atuin: use catppuccin theme --- roles/common/programs/atuin.nix | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/roles/common/programs/atuin.nix b/roles/common/programs/atuin.nix index 8e18cf6..71c9c71 100644 --- a/roles/common/programs/atuin.nix +++ b/roles/common/programs/atuin.nix @@ -1,16 +1,19 @@ {...}: { - home-manager.users.toast.programs.atuin = { - enable = true; - settings = { - enter_accept = true; - workspaces = true; - style = "auto"; - inline_height = 0; - stats = { - common_prefix = [ - "sudo" - "," - ]; + home-manager.users.toast = { + catppuccin.atuin.enable = true; + programs.atuin = { + enable = true; + settings = { + enter_accept = true; + workspaces = true; + style = "auto"; + inline_height = 0; + stats = { + common_prefix = [ + "sudo" + "," + ]; + }; }; }; }; From c2d28ac798678c18a88f0da071d05a6880d20b95 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 30 Apr 2025 17:48:42 +0200 Subject: [PATCH 0985/1125] Desktop/discord: get mauve catpuccin theme --- roles/desktop/programs/discord.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index da499be..7e851c7 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -64,7 +64,7 @@ in { * @invite r6Mdz5dpFc * **/ - @import url("https://catppuccin.github.io/discord/dist/catppuccin-mocha.theme.css"); + @import url("https://catppuccin.github.io/discord/dist/catppuccin-mocha-mauve.theme.css"); ''; }; }; From ce69f89492ebd646cf12e6fc09a49e99029437b3 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 6 May 2025 13:33:13 +0200 Subject: [PATCH 0986/1125] Desktop: remove git cola --- roles/desktop/programs/git.nix | 13 +------------ roles/kde/programs/default.nix | 1 - roles/kde/programs/git.nix | 11 ----------- 3 files changed, 1 insertion(+), 24 deletions(-) delete mode 100644 roles/kde/programs/git.nix diff --git a/roles/desktop/programs/git.nix b/roles/desktop/programs/git.nix index 594c3e7..90233b0 100644 --- a/roles/desktop/programs/git.nix +++ b/roles/desktop/programs/git.nix @@ -1,18 +1,7 @@ -{ - pkgs, - lib, - ... -}: { +{pkgs, ...}: { home-manager.users.toast = { programs.git = { package = pkgs.gitFull; - extraConfig = { - cola = { - icontheme = lib.mkDefault "dark"; - }; - }; }; - - home.packages = [pkgs.git-cola]; }; } diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index 84ff7f6..13dc61a 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -6,7 +6,6 @@ # Neochat depends on olm which is unsafe now # ./neochat.nix ./konsole.nix - ./git.nix ./kwin.nix ./baloo.nix ]; diff --git a/roles/kde/programs/git.nix b/roles/kde/programs/git.nix deleted file mode 100644 index e4e40d4..0000000 --- a/roles/kde/programs/git.nix +++ /dev/null @@ -1,11 +0,0 @@ -{...}: { - home-manager.users.toast = { - programs.git = { - extraConfig = { - cola = { - terminal = "konsole"; - }; - }; - }; - }; -} From 50e6fac40629a41735c6d513b947aa1b2a0665c6 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 15 May 2025 18:40:27 +0200 Subject: [PATCH 0987/1125] Gaming/azahar: use nixpkgs version --- roles/gaming/programs/azahar.nix | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/roles/gaming/programs/azahar.nix b/roles/gaming/programs/azahar.nix index 1c77688..2b88164 100644 --- a/roles/gaming/programs/azahar.nix +++ b/roles/gaming/programs/azahar.nix @@ -1,17 +1,17 @@ {pkgs, ...}: { - nixpkgs.overlays = [ - ( - final: prev: { - azahar = prev.azahar.overrideAttrs (old: { - version = "2120.3"; - src = final.fetchzip { - url = "https://github.com/azahar-emu/azahar/releases/download/2120.3/azahar-unified-source-20250414-00e3bbb.tar.xz"; - hash = "sha256-3QKicmpmWDM7x9GDJ8sxm2Xu+0Yfho4LkSWMp+ixzRk="; - }; - }); - } - ) - ]; + # nixpkgs.overlays = [ + # ( + # final: prev: { + # azahar = prev.azahar.overrideAttrs (old: { + # version = "2120.3"; + # src = final.fetchzip { + # url = "https://github.com/azahar-emu/azahar/releases/download/2120.3/azahar-unified-source-20250414-00e3bbb.tar.xz"; + # hash = "sha256-3QKicmpmWDM7x9GDJ8sxm2Xu+0Yfho4LkSWMp+ixzRk="; + # }; + # }); + # } + # ) + # ]; home-manager.users.toast = { home.packages = [pkgs.azahar]; }; From 9666439eeb798d95a50a38d85cdbc7df9590f9e7 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 15 May 2025 19:29:17 +0200 Subject: [PATCH 0988/1125] Flake: update lock file --- flake.lock | 90 +++++++++++++++++++++++++++--------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/flake.lock b/flake.lock index e9c40cb..b4a884b 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1736955230, - "narHash": "sha256-uenf8fv2eG5bKM8C/UvFaiJMZ4IpUFaQxk9OH5t/1gA=", + "lastModified": 1745630506, + "narHash": "sha256-bHCFgGeu8XjWlVuaWzi3QONjDW3coZDqSHvnd4l7xus=", "owner": "ryantm", "repo": "agenix", - "rev": "e600439ec4c273cf11e06fe4d9d906fb98fa097c", + "rev": "96e078c646b711aee04b82ba01aefbff87004ded", "type": "github" }, "original": { @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1745571143, - "narHash": "sha256-BndQEgBtQh6kPC+2PYdf9iWTSmrbaPjTFkVei2OtuKk=", + "lastModified": 1747268376, + "narHash": "sha256-JDcdINnB1bfbUAy1eEgwIXLrfZeuntxuxTu7UWcQrQY=", "owner": "catppuccin", "repo": "nix", - "rev": "19919d666ead54e97f7886813db08f76ae0981dc", + "rev": "7a6ccdeba6e761bec9601e2192983e6b9dff630c", "type": "github" }, "original": { @@ -147,11 +147,11 @@ ] }, "locked": { - "lastModified": 1703113217, - "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", + "lastModified": 1745494811, + "narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=", "owner": "nix-community", "repo": "home-manager", - "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", + "rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be", "type": "github" }, "original": { @@ -167,11 +167,11 @@ ] }, "locked": { - "lastModified": 1745555634, - "narHash": "sha256-lhVyVn1utb2UVTbyKJ6mfKB7wLTjrj14OlebvO0WU2s=", + "lastModified": 1747279714, + "narHash": "sha256-UdxlE8yyrKiGq3bgGyJ78AdFwh+fuRAruKtyFY5Zq5I=", "owner": "nix-community", "repo": "home-manager", - "rev": "98f4fef7fd7b4a77245db12e33616023162bc6d9", + "rev": "954615c510c9faa3ee7fb6607ff72e55905e69f2", "type": "github" }, "original": { @@ -187,11 +187,11 @@ ] }, "locked": { - "lastModified": 1745557122, - "narHash": "sha256-eqSo9ugzsqhFgaDFYUZj943nurlX4L6f+AW0skJ4W+M=", + "lastModified": 1747020534, + "narHash": "sha256-D/6rkiC6w2p+4SwRiVKrWIeYzun8FBg7NlMKMwQMxO0=", "owner": "nix-community", "repo": "home-manager", - "rev": "dd26f75fb4ec1c731d4b1396eaf4439ce40a91c1", + "rev": "b4bbdc6fde16fc2051fcde232f6e288cd22007ca", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1745487384, - "narHash": "sha256-WvQ4XXi0vMtEpPqhfo8ztxjeaeHkbW5tfR4O5+w8r5U=", + "lastModified": 1747221863, + "narHash": "sha256-2sHoet8Dj16i6fiwlZh9r5Hs9mRIInKvewk8JjU91KQ=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "0168e4a65c9d43c22ac38ff27f5fa31c7d535148", + "rev": "e6189e1e6e019dea8c0ee4f7eba2a435b232e294", "type": "github" }, "original": { @@ -225,11 +225,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1745521626, - "narHash": "sha256-+7DQIKTkvpWYz8bjYfye9T61C5QAUKPEy1YCsXUDCkE=", - "rev": "a133633ecc4ca3aed65899cb37c17601c95f5b2b", + "lastModified": 1747273354, + "narHash": "sha256-LUzJQ0T6XtlZLuFZ9ovLLCdzaCc4YhotPlMLoMcGD5w=", + "rev": "b7ce00fc55dea4fa1e282921beebff25e6b2d1f0", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/a133633ecc4ca3aed65899cb37c17601c95f5b2b.tar.gz?rev=a133633ecc4ca3aed65899cb37c17601c95f5b2b" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/b7ce00fc55dea4fa1e282921beebff25e6b2d1f0.tar.gz?rev=b7ce00fc55dea4fa1e282921beebff25e6b2d1f0" }, "original": { "type": "tarball", @@ -248,11 +248,11 @@ ] }, "locked": { - "lastModified": 1742945498, - "narHash": "sha256-MB/b/xcDKqaVBxJIIxwb81r8ZiGLeKEcqokATRRroo8=", - "rev": "fa69ae26cc32dda178117b46487c2165c0e08316", + "lastModified": 1746839253, + "narHash": "sha256-pRwi8Wn8Yofj459gq+3oIRy8F3SXeEJ6mzfIAUgM9nA=", + "rev": "58baedd53f9da81fd728a4f3b08c378e5ba9ae58", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/fa69ae26cc32dda178117b46487c2165c0e08316.tar.gz?rev=fa69ae26cc32dda178117b46487c2165c0e08316" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/58baedd53f9da81fd728a4f3b08c378e5ba9ae58.tar.gz?rev=58baedd53f9da81fd728a4f3b08c378e5ba9ae58" }, "original": { "type": "tarball", @@ -271,11 +271,11 @@ ] }, "locked": { - "lastModified": 1742945498, - "narHash": "sha256-MB/b/xcDKqaVBxJIIxwb81r8ZiGLeKEcqokATRRroo8=", - "rev": "fa69ae26cc32dda178117b46487c2165c0e08316", + "lastModified": 1746839253, + "narHash": "sha256-pRwi8Wn8Yofj459gq+3oIRy8F3SXeEJ6mzfIAUgM9nA=", + "rev": "58baedd53f9da81fd728a4f3b08c378e5ba9ae58", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/fa69ae26cc32dda178117b46487c2165c0e08316.tar.gz?rev=fa69ae26cc32dda178117b46487c2165c0e08316" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/58baedd53f9da81fd728a4f3b08c378e5ba9ae58.tar.gz?rev=58baedd53f9da81fd728a4f3b08c378e5ba9ae58" }, "original": { "type": "tarball", @@ -342,11 +342,11 @@ ] }, "locked": { - "lastModified": 1745120797, - "narHash": "sha256-owQ0VQ+7cSanTVPxaZMWEzI22Q4bGnuvhVjLAJBNQ3E=", + "lastModified": 1746934494, + "narHash": "sha256-3n6i+F0sDASjkhbvgFDpPDZGp7z19IrRtjfF9TwJpCA=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "69716041f881a2af935021c1182ed5b0cc04d40e", + "rev": "e9b21b01e4307176b9718a29ac514838e7f6f4ff", "type": "github" }, "original": { @@ -362,11 +362,11 @@ ] }, "locked": { - "lastModified": 1745120797, - "narHash": "sha256-owQ0VQ+7cSanTVPxaZMWEzI22Q4bGnuvhVjLAJBNQ3E=", + "lastModified": 1746934494, + "narHash": "sha256-3n6i+F0sDASjkhbvgFDpPDZGp7z19IrRtjfF9TwJpCA=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "69716041f881a2af935021c1182ed5b0cc04d40e", + "rev": "e9b21b01e4307176b9718a29ac514838e7f6f4ff", "type": "github" }, "original": { @@ -377,11 +377,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1745503349, - "narHash": "sha256-bUGjvaPVsOfQeTz9/rLTNLDyqbzhl0CQtJJlhFPhIYw=", + "lastModified": 1747129300, + "narHash": "sha256-L3clA5YGeYCF47ghsI7Tcex+DnaaN/BbQ4dR2wzoiKg=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "f7bee55a5e551bd8e7b5b82c9bc559bc50d868d1", + "rev": "e81fd167b33121269149c57806599045fd33eeed", "type": "github" }, "original": { @@ -409,11 +409,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1745487689, - "narHash": "sha256-FQoi3R0NjQeBAsEOo49b5tbDPcJSMWc3QhhaIi9eddw=", + "lastModified": 1747209494, + "narHash": "sha256-fLise+ys+bpyjuUUkbwqo5W/UyIELvRz9lPBPoB0fbM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5630cf13cceac06cefe9fc607e8dfa8fb342dde3", + "rev": "5d736263df906c5da72ab0f372427814de2f52f8", "type": "github" }, "original": { @@ -424,11 +424,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1745391562, - "narHash": "sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo=", + "lastModified": 1747179050, + "narHash": "sha256-qhFMmDkeJX9KJwr5H32f1r7Prs7XbQWtO0h3V0a0rFY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7", + "rev": "adaa24fbf46737f3f1b5497bf64bae750f82942e", "type": "github" }, "original": { From 9aea5cd1f6f8863bad554a94baa3427045e1719c Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 15 May 2025 19:29:57 +0200 Subject: [PATCH 0989/1125] Flake: remove uneeded nixpkgs patches --- flake.nix | 2 - nixpkgs-patches/pr386360.patch | 71 ----------------------- nixpkgs-patches/pr400900.patch | 101 --------------------------------- 3 files changed, 174 deletions(-) delete mode 100644 nixpkgs-patches/pr386360.patch delete mode 100644 nixpkgs-patches/pr400900.patch diff --git a/flake.nix b/flake.nix index ae0560c..4a27077 100644 --- a/flake.nix +++ b/flake.nix @@ -97,8 +97,6 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/pr400900.patch - ./nixpkgs-patches/pr386360.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr386360.patch b/nixpkgs-patches/pr386360.patch deleted file mode 100644 index 9733a0a..0000000 --- a/nixpkgs-patches/pr386360.patch +++ /dev/null @@ -1,71 +0,0 @@ -From ec004ef5f30f4ea66ce0b77bab5ce778883aff5d Mon Sep 17 00:00:00 2001 -From: Zane van Iperen -Date: Tue, 1 Apr 2025 20:23:42 +0900 -Subject: [PATCH] rpcs3: 0.0.34-17323-92d070729 -> 0.0.36-17736-c86a25079 - ---- - pkgs/by-name/rp/rpcs3/package.nix | 20 +++++++++++++------- - 1 file changed, 13 insertions(+), 7 deletions(-) - -diff --git a/pkgs/by-name/rp/rpcs3/package.nix b/pkgs/by-name/rp/rpcs3/package.nix -index 779d9048ca0ea0..dc39a9bc61e384 100644 ---- a/pkgs/by-name/rp/rpcs3/package.nix -+++ b/pkgs/by-name/rp/rpcs3/package.nix -@@ -21,12 +21,14 @@ - python3, - pugixml, - flatbuffers, -- llvm_16, -+ llvm_18, - cubeb, -+ opencv, - enableDiscordRpc ? false, - faudioSupport ? true, - faudio, - SDL2, -+ sdl3, - waylandSupport ? true, - wayland, - wrapGAppsHook3, -@@ -34,10 +36,10 @@ - - let - # Keep these separate so the update script can regex them -- rpcs3GitVersion = "17323-92d070729"; -- rpcs3Version = "0.0.34-17323-92d070729"; -- rpcs3Revision = "92d07072915b99917892dd7833c06eb44a09e234"; -- rpcs3Hash = "sha256-GH2sXw1AYdqwzxucXFhVS0nM0eRhC+XDHS6RTZY8pYY="; -+ rpcs3GitVersion = "17736-c86a25079"; -+ rpcs3Version = "0.0.36-17736-c86a25079"; -+ rpcs3Revision = "c86a25079518032d73395a79979970acb2581a91"; -+ rpcs3Hash = "sha256-e+mT3qn1oz1fh2bqu5YM+m774Can34If57Kd1T1EGbk="; - - inherit (qt6Packages) - qtbase -@@ -77,9 +79,11 @@ stdenv.mkDerivation { - (lib.cmakeBool "USE_SYSTEM_CURL" true) - (lib.cmakeBool "USE_SYSTEM_WOLFSSL" true) - (lib.cmakeBool "USE_SYSTEM_FAUDIO" true) -+ (lib.cmakeBool "USE_SYSTEM_OPENAL" true) - (lib.cmakeBool "USE_SYSTEM_PUGIXML" true) - (lib.cmakeBool "USE_SYSTEM_FLATBUFFERS" true) - (lib.cmakeBool "USE_SYSTEM_SDL" true) -+ (lib.cmakeBool "USE_SYSTEM_OPENCV" true) - (lib.cmakeBool "USE_SDL" true) - (lib.cmakeBool "WITH_LLVM" true) - (lib.cmakeBool "BUILD_LLVM" false) -@@ -115,10 +119,12 @@ stdenv.mkDerivation { - wolfssl - python3 - pugixml -- SDL2 -+ SDL2 # Still needed by FAudio's CMake -+ sdl3 - flatbuffers -- llvm_16 -+ llvm_18 - libSM -+ opencv - ] - ++ cubeb.passthru.backendLibs - ++ lib.optional faudioSupport faudio diff --git a/nixpkgs-patches/pr400900.patch b/nixpkgs-patches/pr400900.patch deleted file mode 100644 index 457acfc..0000000 --- a/nixpkgs-patches/pr400900.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 66e2bdbc88f1985c0960c29e991ffcbb8b180cc0 Mon Sep 17 00:00:00 2001 -From: Marcin Serwin -Date: Tue, 22 Apr 2025 20:04:11 +0200 -Subject: [PATCH] rpcs3: unbreak - ---- - .../rp/rpcs3/fix-qt6.9-compilation.patch | 68 +++++++++++++++++++ - pkgs/by-name/rp/rpcs3/package.nix | 5 ++ - 2 files changed, 73 insertions(+) - create mode 100644 pkgs/by-name/rp/rpcs3/fix-qt6.9-compilation.patch - -diff --git a/pkgs/by-name/rp/rpcs3/fix-qt6.9-compilation.patch b/pkgs/by-name/rp/rpcs3/fix-qt6.9-compilation.patch -new file mode 100644 -index 00000000000000..13ca314d3022ba ---- /dev/null -+++ b/pkgs/by-name/rp/rpcs3/fix-qt6.9-compilation.patch -@@ -0,0 +1,68 @@ -+From 600e4604169464c64cbf548e7629e483ad2aad1e Mon Sep 17 00:00:00 2001 -+From: Megamouse -+Date: Mon, 7 Apr 2025 20:49:15 +0200 -+Subject: [PATCH] Fix compilation with newer Qt -+ -+--- -+ rpcs3/rpcs3qt/game_list_base.cpp | 2 +- -+ rpcs3/rpcs3qt/game_list_frame.cpp | 4 ++-- -+ rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp | 4 ++-- -+ 3 files changed, 5 insertions(+), 5 deletions(-) -+ -+diff --git a/rpcs3/rpcs3qt/game_list_base.cpp b/rpcs3/rpcs3qt/game_list_base.cpp -+index 72b45d33bfbb..21640906ee7e 100644 -+--- a/rpcs3/rpcs3qt/game_list_base.cpp -++++ b/rpcs3/rpcs3qt/game_list_base.cpp -+@@ -25,7 +25,7 @@ void game_list_base::repaint_icons(std::vector& game_data, const QCol -+ for (game_info& game : game_data) -+ { -+ game->pxmap = placeholder; -+- -++ -+ if (movie_item_base* item = game->item) -+ { -+ item->set_icon_load_func([this, game, device_pixel_ratio, cancel = item->icon_loading_aborted()](int) -+diff --git a/rpcs3/rpcs3qt/game_list_frame.cpp b/rpcs3/rpcs3qt/game_list_frame.cpp -+index a294d69cc68e..439913760053 100644 -+--- a/rpcs3/rpcs3qt/game_list_frame.cpp -++++ b/rpcs3/rpcs3qt/game_list_frame.cpp -+@@ -2363,7 +2363,7 @@ void game_list_frame::BatchActionBySerials(progress_dialog* pdlg, const std::set -+ -+ connect(future_watcher, &QFutureWatcher::finished, this, [=, this]() -+ { -+- pdlg->setLabelText(progressLabel.arg(*index).arg(serials_size)); -++ pdlg->setLabelText(progressLabel.arg(index->load()).arg(serials_size)); -+ pdlg->setCancelButtonText(tr("OK")); -+ QApplication::beep(); -+ -+@@ -2396,7 +2396,7 @@ void game_list_frame::BatchActionBySerials(progress_dialog* pdlg, const std::set -+ return; -+ } -+ -+- pdlg->setLabelText(progressLabel.arg(*index).arg(serials_size)); -++ pdlg->setLabelText(progressLabel.arg(index->load()).arg(serials_size)); -+ pdlg->setCancelButtonText(tr("OK")); -+ connect(pdlg, &progress_dialog::canceled, this, [pdlg](){ pdlg->deleteLater(); }); -+ QApplication::beep(); -+diff --git a/rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp b/rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp -+index 45fbe6f59e7d..4b9bc5dd6e4f 100644 -+--- a/rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp -++++ b/rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp -+@@ -362,7 +362,7 @@ void ps_move_tracker_dialog::update_saturation_threshold(bool update_slider) -+ } -+ void ps_move_tracker_dialog::update_min_radius(bool update_slider) -+ { -+- ui->minRadiusGb->setTitle(tr("Min Radius: %0 %").arg(g_cfg_move.min_radius)); -++ ui->minRadiusGb->setTitle(tr("Min Radius: %0 %").arg(g_cfg_move.min_radius.get())); -+ -+ if (update_slider) -+ { -+@@ -372,7 +372,7 @@ void ps_move_tracker_dialog::update_min_radius(bool update_slider) -+ -+ void ps_move_tracker_dialog::update_max_radius(bool update_slider) -+ { -+- ui->maxRadiusGb->setTitle(tr("Max Radius: %0 %").arg(g_cfg_move.max_radius)); -++ ui->maxRadiusGb->setTitle(tr("Max Radius: %0 %").arg(g_cfg_move.max_radius.get())); -+ -+ if (update_slider) -+ { -diff --git a/pkgs/by-name/rp/rpcs3/package.nix b/pkgs/by-name/rp/rpcs3/package.nix -index 779d9048ca0ea0..b633453a77e61d 100644 ---- a/pkgs/by-name/rp/rpcs3/package.nix -+++ b/pkgs/by-name/rp/rpcs3/package.nix -@@ -58,6 +58,11 @@ stdenv.mkDerivation { - hash = rpcs3Hash; - }; - -+ patches = [ -+ # Modified from https://github.com/RPCS3/rpcs3/pull/17009; doesn't apply cleanly due to intermediate commits -+ ./fix-qt6.9-compilation.patch -+ ]; -+ - passthru.updateScript = ./update.sh; - - preConfigure = '' From f29d5d4207180facf08776c9e905b1af87659a49 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 26 May 2025 16:19:52 +0200 Subject: [PATCH 0990/1125] Desktop/NetworkManager: change dhcp implementation --- roles/desktop/services/networkmanager.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/desktop/services/networkmanager.nix b/roles/desktop/services/networkmanager.nix index c00d3e8..919cd19 100644 --- a/roles/desktop/services/networkmanager.nix +++ b/roles/desktop/services/networkmanager.nix @@ -10,6 +10,8 @@ in { }; networking.networkmanager = { enable = true; + # Internal dhcp implementation does not like my isp router + dhcp = "dhcpcd"; unmanaged = [ "interface-name:${tailscaleName}" ]; From 53df8381824c22a1be5283fece9df43df29eb43e Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 31 May 2025 11:40:50 +0200 Subject: [PATCH 0991/1125] Server: remove changedetection.io --- roles/server/changedetection-io.nix | 31 ----------------------------- roles/server/default.nix | 1 - 2 files changed, 32 deletions(-) delete mode 100755 roles/server/changedetection-io.nix diff --git a/roles/server/changedetection-io.nix b/roles/server/changedetection-io.nix deleted file mode 100755 index 3eae202..0000000 --- a/roles/server/changedetection-io.nix +++ /dev/null @@ -1,31 +0,0 @@ -{...}: { - services.changedetection-io = { - enable = true; - baseURL = "changedetection.everest.tailscale"; - behindProxy = true; - playwrightSupport = true; - }; - systemd.services.changedetection-io.serviceConfig.Environment = [ - "HIDE_REFERER=false" - ]; - - # Add a record for changedetection-io - services.headscale.settings.dns.extra_records = [ - { - name = "changedetection.everest.tailscale"; - type = "A"; - value = "100.100.0.1"; - } - ]; - - # Set up caddy as the reverse proxy for changedetection-io - services.caddy.virtualHosts.changedetection-io = { - hostName = "changedetection.everest.tailscale"; - extraConfig = '' - import tailscale - reverse_proxy localhost:5000 { - header_up Referer {header.Referer} - } - ''; - }; -} diff --git a/roles/server/default.nix b/roles/server/default.nix index 05fa471..5891e05 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -17,7 +17,6 @@ ./adguard.nix ./grafana.nix ./prometheus.nix - ./changedetection-io.nix ./immich.nix ]; } From 0bfc27e90fb97f50c7ed3159eff1c3dbfde223bc Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 3 Jun 2025 18:19:41 +0200 Subject: [PATCH 0992/1125] Flake: update lock file --- flake.lock | 90 +++++++++++++++++++++++++++--------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/flake.lock b/flake.lock index b4a884b..c276662 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1745630506, - "narHash": "sha256-bHCFgGeu8XjWlVuaWzi3QONjDW3coZDqSHvnd4l7xus=", + "lastModified": 1747575206, + "narHash": "sha256-NwmAFuDUO/PFcgaGGr4j3ozG9Pe5hZ/ogitWhY+D81k=", "owner": "ryantm", "repo": "agenix", - "rev": "96e078c646b711aee04b82ba01aefbff87004ded", + "rev": "4835b1dc898959d8547a871ef484930675cb47f1", "type": "github" }, "original": { @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1747268376, - "narHash": "sha256-JDcdINnB1bfbUAy1eEgwIXLrfZeuntxuxTu7UWcQrQY=", + "lastModified": 1748080874, + "narHash": "sha256-sUebEzAkrY8Aq5G0GHFyRddmRNGP/a2iTtV7ISNvi/c=", "owner": "catppuccin", "repo": "nix", - "rev": "7a6ccdeba6e761bec9601e2192983e6b9dff630c", + "rev": "0ba11b12be81f0849a89ed17ab635164ea8f0112", "type": "github" }, "original": { @@ -167,11 +167,11 @@ ] }, "locked": { - "lastModified": 1747279714, - "narHash": "sha256-UdxlE8yyrKiGq3bgGyJ78AdFwh+fuRAruKtyFY5Zq5I=", + "lastModified": 1748955489, + "narHash": "sha256-OmZXyW2g5qIuo5Te74McwR0TwauCO2sF3/SjGDVuxyg=", "owner": "nix-community", "repo": "home-manager", - "rev": "954615c510c9faa3ee7fb6607ff72e55905e69f2", + "rev": "bb846c031be68a96466b683be32704ef6e07b159", "type": "github" }, "original": { @@ -187,11 +187,11 @@ ] }, "locked": { - "lastModified": 1747020534, - "narHash": "sha256-D/6rkiC6w2p+4SwRiVKrWIeYzun8FBg7NlMKMwQMxO0=", + "lastModified": 1747688870, + "narHash": "sha256-ypL9WAZfmJr5V70jEVzqGjjQzF0uCkz+AFQF7n9NmNc=", "owner": "nix-community", "repo": "home-manager", - "rev": "b4bbdc6fde16fc2051fcde232f6e288cd22007ca", + "rev": "d5f1f641b289553927b3801580598d200a501863", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1747221863, - "narHash": "sha256-2sHoet8Dj16i6fiwlZh9r5Hs9mRIInKvewk8JjU91KQ=", + "lastModified": 1748683484, + "narHash": "sha256-RXiY6t9E9oLEtfdGChHk/OIPqxYg1tu8XLvbPnJlfi4=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "e6189e1e6e019dea8c0ee4f7eba2a435b232e294", + "rev": "6f6bd4a27fb01c9dd623a157d769f34561407f47", "type": "github" }, "original": { @@ -225,11 +225,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1747273354, - "narHash": "sha256-LUzJQ0T6XtlZLuFZ9ovLLCdzaCc4YhotPlMLoMcGD5w=", - "rev": "b7ce00fc55dea4fa1e282921beebff25e6b2d1f0", + "lastModified": 1748893954, + "narHash": "sha256-Vj1GHarIzlJI3We5KnYcAQlSjn++fx7/lKRaiIVz3tg=", + "rev": "019b17f4e93c098f99a9bc691be1f1c4df026c7d", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/b7ce00fc55dea4fa1e282921beebff25e6b2d1f0.tar.gz?rev=b7ce00fc55dea4fa1e282921beebff25e6b2d1f0" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/019b17f4e93c098f99a9bc691be1f1c4df026c7d.tar.gz?rev=019b17f4e93c098f99a9bc691be1f1c4df026c7d" }, "original": { "type": "tarball", @@ -248,11 +248,11 @@ ] }, "locked": { - "lastModified": 1746839253, - "narHash": "sha256-pRwi8Wn8Yofj459gq+3oIRy8F3SXeEJ6mzfIAUgM9nA=", - "rev": "58baedd53f9da81fd728a4f3b08c378e5ba9ae58", + "lastModified": 1747667424, + "narHash": "sha256-7EICjbmG6lApWKhFtwvZovdcdORY1CEe6/K7JwtpYfs=", + "rev": "3c23c6ae2aecc1f76ae7993efe1a78b5316f0700", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/58baedd53f9da81fd728a4f3b08c378e5ba9ae58.tar.gz?rev=58baedd53f9da81fd728a4f3b08c378e5ba9ae58" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/3c23c6ae2aecc1f76ae7993efe1a78b5316f0700.tar.gz?rev=3c23c6ae2aecc1f76ae7993efe1a78b5316f0700" }, "original": { "type": "tarball", @@ -271,11 +271,11 @@ ] }, "locked": { - "lastModified": 1746839253, - "narHash": "sha256-pRwi8Wn8Yofj459gq+3oIRy8F3SXeEJ6mzfIAUgM9nA=", - "rev": "58baedd53f9da81fd728a4f3b08c378e5ba9ae58", + "lastModified": 1747667424, + "narHash": "sha256-7EICjbmG6lApWKhFtwvZovdcdORY1CEe6/K7JwtpYfs=", + "rev": "3c23c6ae2aecc1f76ae7993efe1a78b5316f0700", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/58baedd53f9da81fd728a4f3b08c378e5ba9ae58.tar.gz?rev=58baedd53f9da81fd728a4f3b08c378e5ba9ae58" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/3c23c6ae2aecc1f76ae7993efe1a78b5316f0700.tar.gz?rev=3c23c6ae2aecc1f76ae7993efe1a78b5316f0700" }, "original": { "type": "tarball", @@ -342,11 +342,11 @@ ] }, "locked": { - "lastModified": 1746934494, - "narHash": "sha256-3n6i+F0sDASjkhbvgFDpPDZGp7z19IrRtjfF9TwJpCA=", + "lastModified": 1748751003, + "narHash": "sha256-i4GZdKAK97S0ZMU3w4fqgEJr0cVywzqjugt2qZPrScs=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "e9b21b01e4307176b9718a29ac514838e7f6f4ff", + "rev": "2860bee699248d828c2ed9097a1cd82c2f991b43", "type": "github" }, "original": { @@ -362,11 +362,11 @@ ] }, "locked": { - "lastModified": 1746934494, - "narHash": "sha256-3n6i+F0sDASjkhbvgFDpPDZGp7z19IrRtjfF9TwJpCA=", + "lastModified": 1748751003, + "narHash": "sha256-i4GZdKAK97S0ZMU3w4fqgEJr0cVywzqjugt2qZPrScs=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "e9b21b01e4307176b9718a29ac514838e7f6f4ff", + "rev": "2860bee699248d828c2ed9097a1cd82c2f991b43", "type": "github" }, "original": { @@ -377,11 +377,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1747129300, - "narHash": "sha256-L3clA5YGeYCF47ghsI7Tcex+DnaaN/BbQ4dR2wzoiKg=", + "lastModified": 1748942041, + "narHash": "sha256-HEu2gTct7nY0tAPRgBtqYepallryBKR1U8B4v2zEEqA=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "e81fd167b33121269149c57806599045fd33eeed", + "rev": "fc7c4714125cfaa19b048e8aaf86b9c53e04d853", "type": "github" }, "original": { @@ -409,11 +409,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1747209494, - "narHash": "sha256-fLise+ys+bpyjuUUkbwqo5W/UyIELvRz9lPBPoB0fbM=", + "lastModified": 1748810746, + "narHash": "sha256-1na8blYvU1F6HLwx/aFjrhUqpqZ0SCsnqqW9n2vXvok=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5d736263df906c5da72ab0f372427814de2f52f8", + "rev": "78d9f40fd6941a1543ffc3ed358e19c69961d3c1", "type": "github" }, "original": { @@ -424,11 +424,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1747179050, - "narHash": "sha256-qhFMmDkeJX9KJwr5H32f1r7Prs7XbQWtO0h3V0a0rFY=", + "lastModified": 1748693115, + "narHash": "sha256-StSrWhklmDuXT93yc3GrTlb0cKSS0agTAxMGjLKAsY8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "adaa24fbf46737f3f1b5497bf64bae750f82942e", + "rev": "910796cabe436259a29a72e8d3f5e180fc6dfacc", "type": "github" }, "original": { @@ -447,11 +447,11 @@ ] }, "locked": { - "lastModified": 1742765550, - "narHash": "sha256-2vVIh2JrL6GAGfgCeY9e6iNKrBjs0Hw3bGQEAbwVs68=", + "lastModified": 1748196248, + "narHash": "sha256-1iHjsH6/5UOerJEoZKE+Gx1BgAoge/YcnUsOA4wQ/BU=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "b70be387276e632fe51232887f9e04e2b6ef8c16", + "rev": "b7697abe89967839b273a863a3805345ea54ab56", "type": "github" }, "original": { From c37d347ba1885b064e747cf3e890faa1b56c4b8c Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 3 Jun 2025 20:44:05 +0200 Subject: [PATCH 0993/1125] Flake: switch stable nixpkgs and home-manager to 25.05 --- flake.lock | 16 ++++++++-------- flake.nix | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index c276662..b2ee6df 100644 --- a/flake.lock +++ b/flake.lock @@ -187,16 +187,16 @@ ] }, "locked": { - "lastModified": 1747688870, - "narHash": "sha256-ypL9WAZfmJr5V70jEVzqGjjQzF0uCkz+AFQF7n9NmNc=", + "lastModified": 1748665073, + "narHash": "sha256-RMhjnPKWtCoIIHiuR9QKD7xfsKb3agxzMfJY8V9MOew=", "owner": "nix-community", "repo": "home-manager", - "rev": "d5f1f641b289553927b3801580598d200a501863", + "rev": "282e1e029cb6ab4811114fc85110613d72771dea", "type": "github" }, "original": { "owner": "nix-community", - "ref": "release-24.11", + "ref": "release-25.05", "repo": "home-manager", "type": "github" } @@ -409,16 +409,16 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1748810746, - "narHash": "sha256-1na8blYvU1F6HLwx/aFjrhUqpqZ0SCsnqqW9n2vXvok=", + "lastModified": 1748889542, + "narHash": "sha256-Hb4iMhIbjX45GcrgOp3b8xnyli+ysRPqAgZ/LZgyT5k=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "78d9f40fd6941a1543ffc3ed358e19c69961d3c1", + "rev": "10d7f8d34e5eb9c0f9a0485186c1ca691d2c5922", "type": "github" }, "original": { "id": "nixpkgs", - "ref": "nixos-24.11", + "ref": "nixos-25.05", "type": "indirect" } }, diff --git a/flake.nix b/flake.nix index 4a27077..f17518f 100644 --- a/flake.nix +++ b/flake.nix @@ -6,7 +6,7 @@ url = "git+ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets"; flake = false; }; - nixpkgs-raw.url = "nixpkgs/nixos-24.11"; + nixpkgs-raw.url = "nixpkgs/nixos-25.05"; nixpkgs-unstable-raw.url = "nixpkgs/nixos-unstable"; agenix = { @@ -18,7 +18,7 @@ }; home-manager = { - url = "github:nix-community/home-manager/release-24.11"; + url = "github:nix-community/home-manager/release-25.05"; inputs.nixpkgs.follows = "nixpkgs-raw"; }; From bb801f4e4c784c5a639b3534025200a5fdecac41 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 3 Jun 2025 21:19:02 +0200 Subject: [PATCH 0994/1125] Common: update stateVersion --- roles/common/configuration.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 7c18fe3..d1441be 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -131,7 +131,7 @@ users.toast = {osConfig, ...}: { catppuccin.flavor = osConfig.catppuccin.flavor; catppuccin.accent = osConfig.catppuccin.accent; - home.stateVersion = "24.11"; + home.stateVersion = "25.05"; manual = { manpages.enable = true; html.enable = true; @@ -166,7 +166,7 @@ */ system = { - stateVersion = "24.11"; + stateVersion = "25.05"; # Nix on nixos 23.05 does not have dirtyRev configurationRevision = flakeSelf.sourceInfo.rev or flakeSelf.sourceInfo.dirtyRev or "dirty"; nixos.variant_id = lib.strings.toLower config.networking.hostName; From a741b9b559b229c07b7a6c87323aa527a87c2c2f Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 6 Jun 2025 18:54:14 +0200 Subject: [PATCH 0995/1125] Server/forgejo: expose to the internet --- roles/common/programs/git.nix | 2 +- roles/server/forgejo.nix | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index 0ef96f3..69866ba 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -1,6 +1,6 @@ {...}: { programs.ssh.knownHosts = { - "[git.everest.tailscale]:4222".publicKey = '' + "[git.toast003.xyz]:4222".publicKey = '' ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKoUcWx56NZ3kqydN3d0gLNz6SlBm1ArkHhqR9Fwd8qs ''; }; diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index a276179..f4e72df 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -32,7 +32,7 @@ in { }; server = { OFFLINE_MODE = false; - ROOT_URL = "https://git.everest.tailscale"; + ROOT_URL = "https://git.toast003.xyz"; START_SSH_SERVER = true; SSH_PORT = 4222; SSH_SERVER_HOST_KEYS = config.age.secrets.forgejo-host-key.path; @@ -49,24 +49,18 @@ in { }; }; + networking.firewall.allowedTCPPorts = with config; [ + services.forgejo.settings.server.SSH_PORT + ]; + catppuccin.forgejo = { enable = true; }; - # Add a record for forgejo - services.headscale.settings.dns.extra_records = [ - { - name = "git.everest.tailscale"; - type = "A"; - value = "100.100.0.1"; - } - ]; - # Set up caddy as the reverse proxy for Forgejo services.caddy.virtualHosts.forgejo = { - hostName = "git.everest.tailscale"; + hostName = "git.toast003.xyz"; extraConfig = '' - import tailscale reverse_proxy localhost:${toString config.services.forgejo.settings.server.HTTP_PORT} ''; }; From 2c6009b5b84737227fd76f814c165d62e7da4304 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 24 Jun 2025 13:24:31 +0200 Subject: [PATCH 0996/1125] Flake: update secrets url --- flake.lock | 4 ++-- flake.nix | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index b2ee6df..d35435b 100644 --- a/flake.lock +++ b/flake.lock @@ -492,11 +492,11 @@ "rev": "d8262fb108d0810d21c5e098b54a105e867e72ce", "revCount": 28, "type": "git", - "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets" + "url": "ssh://forgejo@git.toast003.xyz:4222/Toast/nix-secrets" }, "original": { "type": "git", - "url": "ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets" + "url": "ssh://forgejo@git.toast003.xyz:4222/Toast/nix-secrets" } }, "systems": { diff --git a/flake.nix b/flake.nix index f17518f..688fc21 100644 --- a/flake.nix +++ b/flake.nix @@ -3,7 +3,7 @@ inputs = { secrets = { - url = "git+ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets"; + url = "git+ssh://forgejo@git.toast003.xyz:4222/Toast/nix-secrets"; flake = false; }; nixpkgs-raw.url = "nixpkgs/nixos-25.05"; From d87450b3053612ba53f8e65b452a41e276597fb6 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 4 Jul 2025 17:06:07 +0200 Subject: [PATCH 0997/1125] Roles/desktop: add japanese fonts --- roles/desktop/configuration.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index 02fc317..351893c 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -17,6 +17,10 @@ fonts.packages = with pkgs.nerd-fonts; [ hack jetbrains-mono + + # Japanese fonts + pkgs.noto-fonts-cjk-sans + pkgs.noto-fonts-cjk-serif ]; hardware.keyboard.qmk.enable = true; From d05764d3dd3c3f7cc34beffd8fbe926a144c6ffa Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 4 Jul 2025 18:00:51 +0200 Subject: [PATCH 0998/1125] Roles/kde: remove all patches --- roles/kde/patches/kinfocenter/00-pr238.patch | 72 - roles/kde/patches/kinfocenter/pr234.patch | 426 --- roles/kde/patches/kwin/pr7429.patch | 193 - roles/kde/patches/kwin/pr7430.patch | 151 - roles/kde/patches/kwin/pr7441.patch | 61 - roles/kde/patches/spectacle/pr431.patch | 3393 ------------------ 6 files changed, 4296 deletions(-) delete mode 100644 roles/kde/patches/kinfocenter/00-pr238.patch delete mode 100644 roles/kde/patches/kinfocenter/pr234.patch delete mode 100644 roles/kde/patches/kwin/pr7429.patch delete mode 100644 roles/kde/patches/kwin/pr7430.patch delete mode 100644 roles/kde/patches/kwin/pr7441.patch delete mode 100644 roles/kde/patches/spectacle/pr431.patch diff --git a/roles/kde/patches/kinfocenter/00-pr238.patch b/roles/kde/patches/kinfocenter/00-pr238.patch deleted file mode 100644 index a199e2b..0000000 --- a/roles/kde/patches/kinfocenter/00-pr238.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 7cc7fe9783a68e086369bd0b96b280082097d60a Mon Sep 17 00:00:00 2001 -From: Oliver Beard -Date: Thu, 20 Feb 2025 22:49:25 +0000 -Subject: [PATCH] kcms/about-distro: Fix hint expanding height of parent layout - Instead, use an label with padding to match the height of normal text. A - background is used to fill this padded area. - -If smallFont is larger than normal text, the text will draw outside the label which would be restricted to the same height as normal text by negative padding. I don't see this as worth fixing - if the small font is larger than normal text, that would be the problem, not this... - -When valueLabel spans multiple lines, it will be vertically centered. - -CCBUG: 500355 ---- - kcms/about-distro/src/ui/main.qml | 35 +++++++++++++++++++------------ - 1 file changed, 22 insertions(+), 13 deletions(-) - -diff --git a/kcms/about-distro/src/ui/main.qml b/kcms/about-distro/src/ui/main.qml -index 7a3f72bfb..80fbc2c13 100644 ---- a/kcms/about-distro/src/ui/main.qml -+++ b/kcms/about-distro/src/ui/main.qml -@@ -136,26 +136,35 @@ KCMUtils.SimpleKCM { - } - } - -- QQC2.Control { -+ QQC2.Label { -+ Kirigami.Theme.colorSet: Kirigami.Theme.Window - visible: hint !== "" -- topPadding: Kirigami.Units.smallSpacing -- rightPadding: Kirigami.Units.smallSpacing -- bottomPadding: Kirigami.Units.smallSpacing -- leftPadding: Kirigami.Units.smallSpacing - -- Kirigami.Theme.colorSet: Kirigami.Theme.Window -+ // Vertical padding accounts for the difference in normal label height and the content height of this small label -+ readonly property real verticalPadding: (hintMetrics.height - contentHeight) / 2 -+ // Horizontal padding also accounts for the difference in content height and the font's pixelSize to better balance the text -+ readonly property real horizontalPadding: ((hintMetrics.height - contentHeight) + (contentHeight - font.pixelSize)) / 2 -+ -+ TextMetrics { -+ // Necessary as valueLabel could be multiple lines -+ id: hintMetrics -+ text: " " -+ } -+ -+ topPadding: verticalPadding -+ bottomPadding: verticalPadding -+ leftPadding: horizontalPadding -+ rightPadding: horizontalPadding -+ -+ text: hint -+ color: hintColorForeground -+ font.bold: true -+ font.pixelSize: Kirigami.Theme.smallFont.pixelSize - - background: Rectangle { - color: hintColorBackground - radius: Kirigami.Units.cornerRadius - } -- -- contentItem: QQC2.Label { -- text: hint -- color: hintColorForeground -- font.bold: true -- font.pixelSize: Kirigami.Theme.smallFont.pixelSize -- } - } - - QQC2.Button { --- -GitLab - diff --git a/roles/kde/patches/kinfocenter/pr234.patch b/roles/kde/patches/kinfocenter/pr234.patch deleted file mode 100644 index e683a76..0000000 --- a/roles/kde/patches/kinfocenter/pr234.patch +++ /dev/null @@ -1,426 +0,0 @@ -From f44af69b07ed19d076819fe4cc84e5777747d957 Mon Sep 17 00:00:00 2001 -From: Oliver Beard -Date: Thu, 20 Feb 2025 22:43:47 +0000 -Subject: [PATCH 1/2] kcms/about-distro: Add help property to Entry & show - total amount of installed memory in MemoryEntry This provides additional - information to the user, with a new help tooltip that clarifies the displayed - values as is contextually appropriate. For example, if the shown message is - "32 GB of RAM (31.3 GB usable)", the tooltip will elucidate that some memory - is reserved for use by system hardware. BUG: 500412 - ---- - CMakeLists.txt | 4 + - kcms/about-distro/src/CMakeLists.txt | 5 + - kcms/about-distro/src/Entry.cpp | 5 + - kcms/about-distro/src/Entry.h | 3 + - kcms/about-distro/src/MemoryEntry.cpp | 144 +++++++++++++++++++++++--- - kcms/about-distro/src/MemoryEntry.h | 9 +- - kcms/about-distro/src/ui/main.qml | 5 + - 7 files changed, 157 insertions(+), 18 deletions(-) - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 51f940789..e3005878a 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -41,6 +41,10 @@ find_package(KF6 ${KF6_MIN_VERSION} REQUIRED COMPONENTS - find_package(PkgConfig) - pkg_check_modules(libdrm REQUIRED IMPORTED_TARGET libdrm) - -+if(CMAKE_SYSTEM_NAME MATCHES "Linux") -+ find_package(UDev REQUIRED COMPONENTS UDev) -+endif() -+ - ecm_find_qmlmodule(org.kde.kirigami 2.5) - - macro(kinfocenter_add_kcm target) -diff --git a/kcms/about-distro/src/CMakeLists.txt b/kcms/about-distro/src/CMakeLists.txt -index 13ad8d0af..d731d81a1 100644 ---- a/kcms/about-distro/src/CMakeLists.txt -+++ b/kcms/about-distro/src/CMakeLists.txt -@@ -43,6 +43,11 @@ target_link_libraries(kcm_about-distro PRIVATE - PkgConfig::libdrm - ) - -+if(UDev_FOUND) -+ target_link_libraries(kcm_about-distro PRIVATE UDev::UDev) -+ target_compile_definitions(kcm_about-distro PRIVATE UDEV_FOUND) -+endif() -+ - cmake_path(RELATIVE_PATH KDE_INSTALL_FULL_LIBEXECDIR BASE_DIRECTORY "${KDE_INSTALL_FULL_PLUGINDIR}/plasma/kcms/" OUTPUT_VARIABLE LIBEXECDIR_FROM_KCM) - - target_compile_options( -diff --git a/kcms/about-distro/src/Entry.cpp b/kcms/about-distro/src/Entry.cpp -index a4077efda..63dc71fbb 100644 ---- a/kcms/about-distro/src/Entry.cpp -+++ b/kcms/about-distro/src/Entry.cpp -@@ -82,4 +82,9 @@ Hint Entry::localizedHint(Language) const - return {}; - } - -+QString Entry::localizedHelp(Language) const -+{ -+ return {}; -+} -+ - #include "moc_Entry.cpp" -diff --git a/kcms/about-distro/src/Entry.h b/kcms/about-distro/src/Entry.h -index e5c3f6f17..bc053a4f4 100644 ---- a/kcms/about-distro/src/Entry.h -+++ b/kcms/about-distro/src/Entry.h -@@ -78,6 +78,9 @@ public: - // Returns a hint for the user to consider when interpreting the value. - Q_INVOKABLE [[nodiscard]] virtual Hint localizedHint(Language language = Language::System) const; - -+ // Returns a help string for the entry, shown with a ContextualHelpButton -+ Q_SCRIPTABLE [[nodiscard]] virtual QString localizedHelp(Language language = Language::System) const; -+ - protected: - // Returns localized QString for the given language. - QString localize(const KLocalizedString &string, Language language) const; -diff --git a/kcms/about-distro/src/MemoryEntry.cpp b/kcms/about-distro/src/MemoryEntry.cpp -index 1baaea2ac..b58b55237 100644 ---- a/kcms/about-distro/src/MemoryEntry.cpp -+++ b/kcms/about-distro/src/MemoryEntry.cpp -@@ -9,6 +9,9 @@ - - #ifdef Q_OS_LINUX - #include -+#ifdef UDEV_FOUND -+#include -+#endif - #elif defined(Q_OS_FREEBSD) - // clang-format off - #include -@@ -21,34 +24,141 @@ MemoryEntry::MemoryEntry() - { - } - --qlonglong MemoryEntry::calculateTotalRam() -+std::optional MemoryEntry::calculateTotalRam() -+{ -+#if defined(Q_OS_LINUX) && defined(UDEV_FOUND) -+ std::unique_ptr udev(udev_new(), &udev_unref); -+ if (!udev) { -+ return {}; -+ } -+ -+ std::unique_ptr dmi(udev_device_new_from_syspath(udev.get(), "/sys/class/dmi/id/"), &udev_device_unref); -+ if (!dmi) { -+ return {}; -+ } -+ -+ const char *numMemoryDevicesCStr = udev_device_get_property_value(dmi.get(), "MEMORY_ARRAY_NUM_DEVICES"); -+ if (!numMemoryDevicesCStr) { -+ return {}; -+ } -+ -+ bool ok; -+ int numMemoryDevices = QByteArray(numMemoryDevicesCStr).toInt(&ok); -+ if (!ok) { -+ return {}; -+ } -+ -+ qlonglong totalBytes = 0; -+ for (int i = 0; i < numMemoryDevices; ++i) { -+ const char *memoryBytesCStr = udev_device_get_property_value(dmi.get(), QStringLiteral("MEMORY_DEVICE_%1_SIZE").arg(i).toLatin1()); -+ qlonglong memoryBytes = QByteArray(memoryBytesCStr).toLongLong(&ok); -+ if (ok) { -+ totalBytes += memoryBytes; -+ } -+ } -+ -+ return totalBytes; -+#endif -+ -+ /* -+ * TODO: A FreeBSD impl is likely possible, but it appears that -+ * sysctlbyname() cannot get what we want with either "hw.physmem", -+ * "hw.usermem" or "hw.realmem". -+ * On a system with 2 x 4 GiB memory modules installed, we would need -+ * to return a value of 8 GiB in bytes. -+ */ -+ -+ return {}; -+} -+ -+std::optional MemoryEntry::calculateAvailableRam() - { -- qlonglong ret = -1; - #ifdef Q_OS_LINUX - struct sysinfo info; -- if (sysinfo(&info) == 0) -- // manpage "sizes are given as multiples of mem_unit bytes" -- ret = qlonglong(info.totalram) * info.mem_unit; -+ if (sysinfo(&info) == 0) { -+ // manpage: "sizes are given as multiples of mem_unit bytes" -+ return qlonglong(info.totalram) * info.mem_unit; -+ } - #elif defined(Q_OS_FREEBSD) - /* Stuff for sysctl */ -- size_t len; -- - unsigned long memory; -- len = sizeof(memory); -- sysctlbyname("hw.physmem", &memory, &len, NULL, 0); -- -- ret = memory; -+ size_t len = sizeof(memory); -+ if (sysctlbyname("hw.physmem", &memory, &len, NULL, 0) == 0) { -+ return memory; -+ } - #endif -- return ret; -+ -+ return {}; - } - - QString MemoryEntry::localizedValue(Language language) const - { -- const qlonglong totalRam = calculateTotalRam(); -- if (totalRam > 0) { -- const auto string = ki18nc("@label %1 is the formatted amount of system memory (e.g. 7,7 GiB)", "%1 of RAM") -- .subs(KFormat(localeForLanguage(language)).formatByteSize(totalRam)); -+ auto precisionForGiB = [](std::optional bytes) -> int { -+ if (!bytes.has_value()) { -+ return 0; -+ } -+ -+ constexpr qlonglong GiB = 1024 * 1024 * 1024; -+ return (bytes.value() % GiB == 0) ? 0 : 1; -+ }; -+ -+ const int totalRamPrecision = precisionForGiB(m_totalRam); -+ const int availableRamPrecision = precisionForGiB(m_availableRam); -+ -+ if (m_totalRam.has_value() && m_availableRam.has_value()) { -+ // Both known -+ const auto string = ki18nc("@label, %1 is the total amount of installed system memory, %2 is the amount of which is usable, both expressed as 7.7 GiB", -+ "%1 of RAM (%2 usable)") -+ .subs(KFormat(localeForLanguage(language)).formatByteSize(m_totalRam.value(), totalRamPrecision)) -+ .subs(KFormat(localeForLanguage(language)).formatByteSize(m_availableRam.value(), availableRamPrecision)); -+ return localize(string, language); -+ } -+ -+ if (m_totalRam.has_value() && !m_availableRam.has_value()) { -+ // Known total, unknown available -+ const auto string = ki18nc("@label, %1 is the amount of installed system memory expressed as 7.7 GiB", "%1 of RAM") -+ .subs(KFormat(localeForLanguage(language)).formatByteSize(m_totalRam.value(), totalRamPrecision)); -+ return localize(string, language); -+ } -+ -+ if (!m_totalRam.has_value() && m_availableRam.has_value()) { -+ // Unknown total, known available -+ const auto string = ki18nc("@label, %1 is the amount of usable system memory expressed as 7.7 GiB", "%1 of usable RAM") -+ .subs(KFormat(localeForLanguage(language)).formatByteSize(m_availableRam.value(), availableRamPrecision)); - return localize(string, language); - } -- return localize(ki18nc("Unknown amount of RAM", "Unknown"), language); -+ -+ // Both unknown -+ return localize(ki18nc("@label, Unknown amount of system memory", "Unknown"), language); -+} -+ -+QString MemoryEntry::localizedHelp(Language language) const -+{ -+ if (m_totalRam.has_value() && m_availableRam.has_value()) { -+ // Both known -+ return localize(ki18nc("@info:tooltip, referring to system memory or RAM", -+ "Some memory is reserved for use by the kernel or system hardware such as integrated graphics memory."), -+ language); -+ } -+ -+ if (m_totalRam.has_value() && !m_availableRam.has_value()) { -+ // Known total, unknown available -+ return localize( -+ ki18nc("@info:tooltip, referring to system memory or RAM", -+ "The amount of usable memory may be lower than the displayed amount because some memory is reserved for use by the kernel or system " -+ "hardware, such as integrated graphics memory."), -+ language); -+ } -+ -+ if (!m_totalRam.has_value() && m_availableRam.has_value()) { -+ // Unknown total, known available -+ return localize( -+ ki18nc("@info:tooltip, referring to system memory or RAM", -+ "The amount of memory displayed may be lower than the installed amount because some memory is reserved for use by the kernel or system " -+ "hardware, such as integrated graphics memory."), -+ language); -+ } -+ -+ // Both unknown -+ return QString(); - } -diff --git a/kcms/about-distro/src/MemoryEntry.h b/kcms/about-distro/src/MemoryEntry.h -index 43beb2e87..d0757651f 100644 ---- a/kcms/about-distro/src/MemoryEntry.h -+++ b/kcms/about-distro/src/MemoryEntry.h -@@ -12,10 +12,17 @@ class MemoryEntry : public Entry - { - public: - MemoryEntry(); -- static qlonglong calculateTotalRam(); - - // Overwrite to get correct localization for the value. - QString localizedValue(Language language = Language::System) const final; -+ QString localizedHelp(Language language = Language::System) const final; -+ -+private: -+ static std::optional calculateTotalRam(); -+ static std::optional calculateAvailableRam(); -+ -+ std::optional m_totalRam = calculateTotalRam(); -+ std::optional m_availableRam = calculateAvailableRam(); - }; - - #endif // MEMORYENTRY_H -diff --git a/kcms/about-distro/src/ui/main.qml b/kcms/about-distro/src/ui/main.qml -index 80fbc2c13..e80b7fe93 100644 ---- a/kcms/about-distro/src/ui/main.qml -+++ b/kcms/about-distro/src/ui/main.qml -@@ -167,6 +167,11 @@ KCMUtils.SimpleKCM { - } - } - -+ Kirigami.ContextualHelpButton { -+ visible: toolTipText.length > 0 -+ toolTipText: entry.localizedHelp() -+ } -+ - QQC2.Button { - visible: hidden - property var dialog: null --- -GitLab - - -From fc2e540dc6f4784c2602a520f4b3285355213f5a Mon Sep 17 00:00:00 2001 -From: Oliver Beard -Date: Mon, 24 Feb 2025 23:17:48 +0000 -Subject: [PATCH 2/2] kcms/about-distro: Clean-up and refactoring - Spacing - specified on RowLayout - Instead of specifying properties up-front for each - entry, entries use them as needed. - Use .length > 0 instead of !== "" - - [[nodiscard]] and Q_INVOKABLE specified on virtual Entry methods - ---- - kcms/about-distro/src/Entry.h | 8 +++--- - kcms/about-distro/src/ui/main.qml | 42 +++++++++++++++---------------- - 2 files changed, 25 insertions(+), 25 deletions(-) - -diff --git a/kcms/about-distro/src/Entry.h b/kcms/about-distro/src/Entry.h -index bc053a4f4..3c7dd8491 100644 ---- a/kcms/about-distro/src/Entry.h -+++ b/kcms/about-distro/src/Entry.h -@@ -66,20 +66,20 @@ public: - // Returns textual representation of entry. - QString diagnosticLine(Language language = Language::System) const; - -- Q_SCRIPTABLE virtual QString localizedLabel(Language language = Language::System) const; -+ Q_INVOKABLE [[nodiscard]] virtual QString localizedLabel(Language language = Language::System) const; - - // Returns the value by default. Needs to be overridden in subclasses if localization - // is needed for the value. -- Q_SCRIPTABLE virtual QString localizedValue(Language language = Language::System) const; -+ Q_INVOKABLE [[nodiscard]] virtual QString localizedValue(Language language = Language::System) const; - - // Returns whether this Entry should be hidden by default (i.e. only shown upon user request) -- Q_INVOKABLE virtual bool isHidden() const; -+ Q_INVOKABLE [[nodiscard]] virtual bool isHidden() const; - - // Returns a hint for the user to consider when interpreting the value. - Q_INVOKABLE [[nodiscard]] virtual Hint localizedHint(Language language = Language::System) const; - - // Returns a help string for the entry, shown with a ContextualHelpButton -- Q_SCRIPTABLE [[nodiscard]] virtual QString localizedHelp(Language language = Language::System) const; -+ Q_INVOKABLE [[nodiscard]] virtual QString localizedHelp(Language language = Language::System) const; - - protected: - // Returns localized QString for the given language. -diff --git a/kcms/about-distro/src/ui/main.qml b/kcms/about-distro/src/ui/main.qml -index e80b7fe93..547f4b665 100644 ---- a/kcms/about-distro/src/ui/main.qml -+++ b/kcms/about-distro/src/ui/main.qml -@@ -54,14 +54,14 @@ KCMUtils.SimpleKCM { - } - - Kirigami.Heading { -- visible: kcm.distroVariant !== "" -+ visible: kcm.distroVariant.length > 0 - text: kcm.distroVariant - level: 2 - type: Kirigami.Heading.Type.Secondary - } - - QQC2.Label { -- visible: kcm.distroUrl !== "" -+ visible: kcm.distroUrl.length > 0 - text: "%1".arg(kcm.distroUrl) - textFormat: Text.RichText - onLinkActivated: link => Qt.openUrlExternally(link) -@@ -82,23 +82,11 @@ KCMUtils.SimpleKCM { - Kirigami.FormData.label: entry.localizedLabel() - Kirigami.FormData.labelAlignment: idealAlignment - Layout.alignment: idealAlignment -+ - readonly property int idealAlignment: valueLabel.lineCount > 1 ? Qt.AlignTop : Qt.AlignVCenter // looks tidier this way - readonly property bool hidden: entry.isHidden() -- readonly property string hint: entry.localizedHint().text -- readonly property color hintColorForeground: { -- switch (entry.localizedHint().color) { -- case Private.Hint.Color.One: return Kirigami.Theme.linkColor -- case Private.Hint.Color.Two: return Kirigami.Theme.positiveTextColor -- case Private.Hint.Color.Three: return Kirigami.Theme.alternateTextColor -- } -- } -- readonly property color hintColorBackground: { -- switch (entry.localizedHint().color) { -- case Private.Hint.Color.One: return Kirigami.Theme.linkBackgroundColor -- case Private.Hint.Color.Two: return Kirigami.Theme.positiveBackgroundColor -- case Private.Hint.Color.Three: return Kirigami.Theme.alternateBackgroundColor -- } -- } -+ -+ spacing: Kirigami.Units.smallSpacing - - Component { - id: unhideDialog -@@ -138,7 +126,7 @@ KCMUtils.SimpleKCM { - - QQC2.Label { - Kirigami.Theme.colorSet: Kirigami.Theme.Window -- visible: hint !== "" -+ visible: text.length > 0 - - // Vertical padding accounts for the difference in normal label height and the content height of this small label - readonly property real verticalPadding: (hintMetrics.height - contentHeight) / 2 -@@ -156,13 +144,25 @@ KCMUtils.SimpleKCM { - leftPadding: horizontalPadding - rightPadding: horizontalPadding - -- text: hint -- color: hintColorForeground -+ text: entry.localizedHint().text -+ color: { -+ switch (entry.localizedHint().color) { -+ case Private.Hint.Color.One: return Kirigami.Theme.linkColor -+ case Private.Hint.Color.Two: return Kirigami.Theme.positiveTextColor -+ case Private.Hint.Color.Three: return Kirigami.Theme.alternateTextColor -+ } -+ } - font.bold: true - font.pixelSize: Kirigami.Theme.smallFont.pixelSize - - background: Rectangle { -- color: hintColorBackground -+ color: { -+ switch (entry.localizedHint().color) { -+ case Private.Hint.Color.One: return Kirigami.Theme.linkBackgroundColor -+ case Private.Hint.Color.Two: return Kirigami.Theme.positiveBackgroundColor -+ case Private.Hint.Color.Three: return Kirigami.Theme.alternateBackgroundColor -+ } -+ } - radius: Kirigami.Units.cornerRadius - } - } --- -GitLab - diff --git a/roles/kde/patches/kwin/pr7429.patch b/roles/kde/patches/kwin/pr7429.patch deleted file mode 100644 index 599e8f7..0000000 --- a/roles/kde/patches/kwin/pr7429.patch +++ /dev/null @@ -1,193 +0,0 @@ -diff --git a/autotests/integration/lockscreen.cpp b/autotests/integration/lockscreen.cpp -index 8d3b5d1a72..4786617ca6 100644 ---- a/autotests/integration/lockscreen.cpp -+++ b/autotests/integration/lockscreen.cpp -@@ -665,18 +665,18 @@ void LockScreenTest::testAxisShortcut() - - // try to trigger the shortcut - quint32 timestamp = 1; --#define PERFORM(expectedCount) \ -- do { \ -- Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++); \ -- if (direction == Qt::Vertical) \ -- Test::pointerAxisVertical(sign * 5.0, timestamp++); \ -- else \ -- Test::pointerAxisHorizontal(sign * 5.0, timestamp++); \ -- QCoreApplication::instance()->processEvents(); \ -- QCOMPARE(actionSpy.count(), expectedCount); \ -- Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++); \ -- QCoreApplication::instance()->processEvents(); \ -- QCOMPARE(actionSpy.count(), expectedCount); \ -+#define PERFORM(expectedCount) \ -+ do { \ -+ Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++); \ -+ if (direction == Qt::Vertical) \ -+ Test::pointerAxisVertical(sign * 15.0, timestamp++); \ -+ else \ -+ Test::pointerAxisHorizontal(sign * 15.0, timestamp++); \ -+ QCoreApplication::instance()->processEvents(); \ -+ QCOMPARE(actionSpy.count(), expectedCount); \ -+ Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++); \ -+ QCoreApplication::instance()->processEvents(); \ -+ QCOMPARE(actionSpy.count(), expectedCount); \ - } while (false) - - PERFORM(1); -diff --git a/src/globalshortcuts.cpp b/src/globalshortcuts.cpp -index 5682e2a797..40b99d2018 100644 ---- a/src/globalshortcuts.cpp -+++ b/src/globalshortcuts.cpp -@@ -240,17 +240,16 @@ bool GlobalShortcutsManager::processKeyRelease(Qt::KeyboardModifiers mods, int k - } - - template --bool match(QList &shortcuts, Args... args) -+GlobalShortcut *match(QList &shortcuts, Args... args) - { - for (auto &sc : shortcuts) { - if (std::holds_alternative(sc.shortcut())) { - if (std::get(sc.shortcut()) == ShortcutKind{args...}) { -- sc.invoke(); -- return true; -+ return ≻ - } - } - } -- return false; -+ return nullptr; - } - - // TODO(C++20): use ranges for a nicer way of filtering by shortcut type -@@ -266,10 +265,14 @@ bool GlobalShortcutsManager::processPointerPressed(Qt::KeyboardModifiers mods, Q - Q_ARG(Qt::MouseButtons, pointerButtons)); - } - #endif -- return match(m_shortcuts, mods, pointerButtons); -+ GlobalShortcut *shortcut = match(m_shortcuts, mods, pointerButtons); -+ if (shortcut) { -+ shortcut->invoke(); -+ } -+ return shortcut != nullptr; - } - --bool GlobalShortcutsManager::processAxis(Qt::KeyboardModifiers mods, PointerAxisDirection axis) -+bool GlobalShortcutsManager::processAxis(Qt::KeyboardModifiers mods, PointerAxisDirection axis, qreal delta) - { - #if KWIN_BUILD_GLOBALSHORTCUTS - // currently only used to better support modifier only shortcuts -@@ -281,7 +284,11 @@ bool GlobalShortcutsManager::processAxis(Qt::KeyboardModifiers mods, PointerAxis - Q_ARG(int, axis)); - } - #endif -- return match(m_shortcuts, mods, axis); -+ GlobalShortcut *shortcut = match(m_shortcuts, mods, axis); -+ if (shortcut && std::abs(delta) >= 1.0f) { -+ shortcut->invoke(); -+ } -+ return shortcut != nullptr; - } - - void GlobalShortcutsManager::processSwipeStart(DeviceType device, uint fingerCount) -diff --git a/src/globalshortcuts.h b/src/globalshortcuts.h -index 13c4239cae..4a2748cf39 100644 ---- a/src/globalshortcuts.h -+++ b/src/globalshortcuts.h -@@ -98,7 +98,7 @@ public: - * @param axis The axis direction which has triggered this event - * @return @c true if a shortcut triggered, @c false otherwise - */ -- bool processAxis(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis); -+ bool processAxis(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, qreal delta); - - void processSwipeStart(DeviceType device, uint fingerCount); - void processSwipeUpdate(DeviceType device, const QPointF &delta); -diff --git a/src/input.cpp b/src/input.cpp -index 52dd7be865..4bc5b7f719 100644 ---- a/src/input.cpp -+++ b/src/input.cpp -@@ -976,6 +976,29 @@ private: - QMap m_touchPoints; - }; - -+class MouseWheelAccumulator -+{ -+public: -+ qreal accumulate(PointerAxisEvent *event) -+ { -+ const qreal delta = event->deltaV120 != 0 ? event->deltaV120 / 120.0 : event->delta / 15.0; -+ if (std::signbit(m_scrollDistance) != std::signbit(delta)) { -+ m_scrollDistance = 0; -+ } -+ m_scrollDistance += delta; -+ if (std::abs(m_scrollDistance) >= 1.0) { -+ const qreal ret = m_scrollDistance; -+ m_scrollDistance = std::fmod(m_scrollDistance, 1.0f); -+ return ret - m_scrollDistance; -+ } else { -+ return 0; -+ } -+ } -+ -+private: -+ qreal m_scrollDistance = 0; -+}; -+ - #if KWIN_BUILD_GLOBALSHORTCUTS - class GlobalShortcutFilter : public InputEventFilter - { -@@ -1008,15 +1031,15 @@ public: - } else if (event->delta > 0) { - direction = PointerAxisLeft; - } -+ return input()->shortcuts()->processAxis(event->modifiers, direction, m_horizontalAccumulator.accumulate(event)); - } else { - if (event->delta < 0) { - direction = PointerAxisDown; - } else if (event->delta > 0) { - direction = PointerAxisUp; - } -+ return input()->shortcuts()->processAxis(event->modifiers, direction, m_verticalAccumulator.accumulate(event)); - } -- -- return input()->shortcuts()->processAxis(event->modifiers, direction); - } - bool keyboardKey(KeyboardKeyEvent *event) override - { -@@ -1229,6 +1252,8 @@ private: - QPointF m_lastAverageDistance; - QMap m_touchPoints; - int m_touchpadGestureFingerCount = 0; -+ MouseWheelAccumulator m_horizontalAccumulator; -+ MouseWheelAccumulator m_verticalAccumulator; - - QTimer m_powerDown; - }; -@@ -1515,28 +1540,6 @@ private: - QList m_touchPoints; - }; - --class MouseWheelAccumulator --{ --public: -- float accumulate(PointerAxisEvent *event) -- { -- m_scrollV120 += event->deltaV120; -- m_scrollDistance += event->delta; -- if (std::abs(m_scrollV120) >= 120 || (!event->deltaV120 && std::abs(m_scrollDistance) >= 15)) { -- float ret = m_scrollDistance; -- m_scrollV120 = 0; -- m_scrollDistance = 0; -- return ret; -- } else { -- return 0; -- } -- } -- --private: -- float m_scrollDistance = 0; -- int m_scrollV120 = 0; --}; -- - class DecorationEventFilter : public InputEventFilter - { - public: diff --git a/roles/kde/patches/kwin/pr7430.patch b/roles/kde/patches/kwin/pr7430.patch deleted file mode 100644 index 053e084..0000000 --- a/roles/kde/patches/kwin/pr7430.patch +++ /dev/null @@ -1,151 +0,0 @@ -diff --git a/autotests/integration/decoration_input_test.cpp b/autotests/integration/decoration_input_test.cpp -index 7390b34aab..61312a389b 100644 ---- a/autotests/integration/decoration_input_test.cpp -+++ b/autotests/integration/decoration_input_test.cpp -@@ -655,9 +655,9 @@ void DecorationInputTest::testModifierScrollOpacity() - } - QFETCH(int, modifierKey); - Test::keyboardKeyPressed(modifierKey, timestamp++); -- Test::pointerAxisVertical(-5, timestamp++); -+ Test::pointerAxisVertical(-15, timestamp++); - QCOMPARE(window->opacity(), 0.6); -- Test::pointerAxisVertical(5, timestamp++); -+ Test::pointerAxisVertical(15, timestamp++); - QCOMPARE(window->opacity(), 0.5); - Test::keyboardKeyReleased(modifierKey, timestamp++); - if (capsLock) { -diff --git a/autotests/integration/internal_window.cpp b/autotests/integration/internal_window.cpp -index 338ad6eca9..8ebd191e9a 100644 ---- a/autotests/integration/internal_window.cpp -+++ b/autotests/integration/internal_window.cpp -@@ -291,9 +291,9 @@ void InternalWindowTest::testPointerAxis() - quint32 timestamp = 1; - Test::pointerMotion(QPoint(50, 50), timestamp++); - -- Test::pointerAxisVertical(5.0, timestamp++); -+ Test::pointerAxisVertical(15.0, timestamp++); - QTRY_COMPARE(wheelSpy.count(), 1); -- Test::pointerAxisHorizontal(5.0, timestamp++); -+ Test::pointerAxisHorizontal(15.0, timestamp++); - QTRY_COMPARE(wheelSpy.count(), 2); - } - -@@ -465,9 +465,9 @@ void InternalWindowTest::testModifierScroll() - QCOMPARE(internalWindow->opacity(), 0.5); - quint32 timestamp = 1; - Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++); -- Test::pointerAxisVertical(-5, timestamp++); -+ Test::pointerAxisVertical(-15, timestamp++); - QCOMPARE(internalWindow->opacity(), 0.6); -- Test::pointerAxisVertical(5, timestamp++); -+ Test::pointerAxisVertical(15, timestamp++); - QCOMPARE(internalWindow->opacity(), 0.5); - Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++); - } -diff --git a/autotests/integration/lockscreen.cpp b/autotests/integration/lockscreen.cpp -index 8d3b5d1a72..62fe990550 100644 ---- a/autotests/integration/lockscreen.cpp -+++ b/autotests/integration/lockscreen.cpp -@@ -339,7 +339,7 @@ void LockScreenTest::testPointerAxis() - // and simulate axis - Test::pointerAxisHorizontal(5.0, timestamp++); - QVERIFY(!axisChangedSpy.wait(10)); -- Test::pointerAxisVertical(5.0, timestamp++); -+ Test::pointerAxisVertical(15.0, timestamp++); - QVERIFY(!axisChangedSpy.wait(10)); - - // and unlock -@@ -348,9 +348,9 @@ void LockScreenTest::testPointerAxis() - QCOMPARE(enteredSpy.count(), 2); - - // and move axis again -- Test::pointerAxisHorizontal(5.0, timestamp++); -+ Test::pointerAxisHorizontal(15.0, timestamp++); - QVERIFY(axisChangedSpy.wait()); -- Test::pointerAxisVertical(5.0, timestamp++); -+ Test::pointerAxisVertical(15.0, timestamp++); - QVERIFY(axisChangedSpy.wait()); - } - -diff --git a/autotests/integration/no_global_shortcuts_test.cpp b/autotests/integration/no_global_shortcuts_test.cpp -index 5e5ea1676b..65add952ea 100644 ---- a/autotests/integration/no_global_shortcuts_test.cpp -+++ b/autotests/integration/no_global_shortcuts_test.cpp -@@ -177,9 +177,9 @@ void NoGlobalShortcutsTest::testAxisShortcut() - quint32 timestamp = 1; - Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++); - if (direction == Qt::Vertical) { -- Test::pointerAxisVertical(sign * 5.0, timestamp++); -+ Test::pointerAxisVertical(sign * 15.0, timestamp++); - } else { -- Test::pointerAxisHorizontal(sign * 5.0, timestamp++); -+ Test::pointerAxisHorizontal(sign * 15.0, timestamp++); - } - QCoreApplication::instance()->processEvents(); - QCOMPARE(actionSpy.count(), 0); -diff --git a/autotests/integration/pointer_constraints_test.cpp b/autotests/integration/pointer_constraints_test.cpp -index 06ab277863..497bb5ac73 100644 ---- a/autotests/integration/pointer_constraints_test.cpp -+++ b/autotests/integration/pointer_constraints_test.cpp -@@ -189,9 +189,9 @@ void TestPointerConstraints::testConfinedPointer() - QCOMPARE(window->opacity(), 0.5); - - // pointer is confined so shortcut should not work -- Test::pointerAxisVertical(-5, timestamp++); -+ Test::pointerAxisVertical(-15, timestamp++); - QCOMPARE(window->opacity(), 0.5); -- Test::pointerAxisVertical(5, timestamp++); -+ Test::pointerAxisVertical(15, timestamp++); - QCOMPARE(window->opacity(), 0.5); - - Test::keyboardKeyReleased(KEY_LEFTALT, timestamp++); -diff --git a/autotests/integration/pointer_input.cpp b/autotests/integration/pointer_input.cpp -index f444471562..12c8c5736b 100644 ---- a/autotests/integration/pointer_input.cpp -+++ b/autotests/integration/pointer_input.cpp -@@ -695,9 +695,9 @@ void PointerInputTest::testModifierScrollOpacity() - } - QFETCH(int, modifierKey); - Test::keyboardKeyPressed(modifierKey, timestamp++); -- Test::pointerAxisVertical(-5, timestamp++); -+ Test::pointerAxisVertical(-15, timestamp++); - QCOMPARE(window->opacity(), 0.6); -- Test::pointerAxisVertical(5, timestamp++); -+ Test::pointerAxisVertical(15, timestamp++); - QCOMPARE(window->opacity(), 0.5); - Test::keyboardKeyReleased(modifierKey, timestamp++); - if (capsLock) { -@@ -753,9 +753,9 @@ void PointerInputTest::testModifierScrollOpacityGlobalShortcutsDisabled() - // simulate modifier+wheel - quint32 timestamp = 1; - Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++); -- Test::pointerAxisVertical(-5, timestamp++); -+ Test::pointerAxisVertical(-15, timestamp++); - QCOMPARE(window->opacity(), 0.5); -- Test::pointerAxisVertical(5, timestamp++); -+ Test::pointerAxisVertical(15, timestamp++); - QCOMPARE(window->opacity(), 0.5); - Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++); - -@@ -800,7 +800,7 @@ void PointerInputTest::testScrollAction() - - quint32 timestamp = 1; - QVERIFY(!window1->isActive()); -- Test::pointerAxisVertical(5, timestamp++); -+ Test::pointerAxisVertical(15, timestamp++); - QVERIFY(window1->isActive()); - - // but also the wheel event should be passed to the window -diff --git a/autotests/integration/touch_input_test.cpp b/autotests/integration/touch_input_test.cpp -index 8f739ff2a5..df68e1b47e 100644 ---- a/autotests/integration/touch_input_test.cpp -+++ b/autotests/integration/touch_input_test.cpp -@@ -146,7 +146,7 @@ void TouchInputTest::testTouchHidesCursor() - QCOMPARE(Cursors::self()->isCursorHidden(), true); - - // wheel should also show -- Test::pointerAxisVertical(1.0, timestamp++); -+ Test::pointerAxisVertical(15.0, timestamp++); - QCOMPARE(Cursors::self()->isCursorHidden(), false); - } - diff --git a/roles/kde/patches/kwin/pr7441.patch b/roles/kde/patches/kwin/pr7441.patch deleted file mode 100644 index e2422af..0000000 --- a/roles/kde/patches/kwin/pr7441.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 2022febc84989dba04a4677f3c187a057dece522 Mon Sep 17 00:00:00 2001 -From: Aleix Pol -Date: Fri, 4 Apr 2025 00:59:29 +0200 -Subject: [PATCH] screenedge: Hardcode the cornerOffset value - -At the moment we were using fonts to calculate it which would slow us -down at startup for little pay-off. -We were using visual metrics for a touch scaling which is wrong so let's -just hardcode a value. -On my system (running default fonts) gridUnit was 9 and thus was -resulting on 36, rounded up to 40. ---- - src/screenedge.cpp | 9 +-------- - src/screenedge.h | 2 +- - 2 files changed, 2 insertions(+), 9 deletions(-) - -diff --git a/src/screenedge.cpp b/src/screenedge.cpp -index adbac936f20..fb42ecc9330 100644 ---- a/src/screenedge.cpp -+++ b/src/screenedge.cpp -@@ -42,12 +42,6 @@ - #include - #include - #include --#include --#include --#include --#include --#include --#include - #include - - using namespace std::chrono_literals; -@@ -766,10 +760,9 @@ ScreenEdges::ScreenEdges() - , m_actionBottom(ElectricActionNone) - , m_actionBottomLeft(ElectricActionNone) - , m_actionLeft(ElectricActionNone) -+ , m_cornerOffset(40) - , m_gestureRecognizer(new GestureRecognizer(this)) - { -- const int gridUnit = QFontMetrics(QFontDatabase::systemFont(QFontDatabase::GeneralFont)).boundingRect(QLatin1Char('M')).height(); -- m_cornerOffset = 4 * gridUnit; - } - - void ScreenEdges::init() -diff --git a/src/screenedge.h b/src/screenedge.h -index b208edf3c98..8417f2aee57 100644 ---- a/src/screenedge.h -+++ b/src/screenedge.h -@@ -388,7 +388,7 @@ private: - ElectricBorderAction m_actionBottomLeft; - ElectricBorderAction m_actionLeft; - QMap m_touchCallbacks; -- int m_cornerOffset; -+ const int m_cornerOffset; - GestureRecognizer *m_gestureRecognizer; - bool m_remainActiveOnFullscreen = false; - }; --- -GitLab - diff --git a/roles/kde/patches/spectacle/pr431.patch b/roles/kde/patches/spectacle/pr431.patch deleted file mode 100644 index aef0059..0000000 --- a/roles/kde/patches/spectacle/pr431.patch +++ /dev/null @@ -1,3393 +0,0 @@ -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index c95d17e9..8a6994f8 100644 ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -37,6 +37,8 @@ target_sources(spectacle PRIVATE - Gui/ExportMenu.cpp - Gui/HelpMenu.cpp - Gui/OptionsMenu.cpp -+ Gui/RecordingModeMenu.cpp -+ Gui/ScreenshotModeMenu.cpp - Gui/SmartSpinBox.cpp - Gui/Selection.cpp - Gui/SelectionEditor.cpp -@@ -147,6 +149,7 @@ set_source_files_properties(Gui/QmlUtils.qml PROPERTIES - - qt_target_qml_sources(spectacle - QML_FILES -+ Gui/AcceptAction.qml - Gui/AnimatedLoader.qml - Gui/AnnotationOptionsToolBarContents.qml - Gui/Annotations/AnnotationEditor.qml -@@ -160,38 +163,49 @@ qt_target_qml_sources(spectacle - Gui/CaptureOptions.qml - Gui/CaptureSettingsColumn.qml - Gui/CopiedMessage.qml -+ Gui/CopyImageAction.qml -+ Gui/CopyLocationAction.qml - Gui/DashedOutline.qml - Gui/DelaySpinBox.qml - Gui/DialogPage.qml -+ Gui/EditAction.qml - Gui/EmptyPage.qml -+ Gui/ExportMenuButton.qml - Gui/FloatingBackground.qml - Gui/FloatingToolBar.qml - Gui/Handle.qml -+ Gui/HelpMenuButton.qml - Gui/ImageCaptureOverlay.qml - Gui/ImageView.qml - Gui/InlineMessage.qml - Gui/LocationCopiedMessage.qml - Gui/Magnifier.qml -- Gui/MainToolBarContents.qml -+ Gui/NewScreenshotToolButton.qml -+ Gui/OptionsMenuButton.qml - Gui/Outline.qml - Gui/QRCodeScannedMessage.qml - Gui/QmlUtils.qml -+ Gui/RecordAction.qml - Gui/RecordOptions.qml - Gui/RecordingFailedMessage.qml - Gui/RecordingModeButtonsColumn.qml -+ Gui/RecordingModeMenuButton.qml - Gui/RecordingSettingsColumn.qml - Gui/RecordingView.qml -+ Gui/SaveAction.qml -+ Gui/SaveAsAction.qml - Gui/SavedAndCopiedMessage.qml - Gui/SavedAndLocationCopied.qml - Gui/SavedMessage.qml - Gui/ScreenshotFailedMessage.qml -+ Gui/ScreenshotModeMenuButton.qml - Gui/ScreenshotView.qml - Gui/ShareErrorMessage.qml - Gui/SharedMessage.qml - Gui/ShortcutsTextBox.qml - Gui/SizeLabel.qml -+ Gui/TtToolButton.qml - Gui/UndoRedoGroup.qml -- Gui/VideoCaptureOverlay.qml - ) - - install(TARGETS spectacle ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) -diff --git a/src/CaptureModeModel.cpp b/src/CaptureModeModel.cpp -index 1b7720dc..2037b97f 100644 ---- a/src/CaptureModeModel.cpp -+++ b/src/CaptureModeModel.cpp -@@ -15,6 +15,16 @@ - - using namespace Qt::StringLiterals; - -+static std::unique_ptr s_instance; -+ -+CaptureModeModel *CaptureModeModel::instance() -+{ -+ if (!s_instance) { -+ s_instance = std::make_unique(); -+ } -+ return s_instance.get(); -+} -+ - static QString actionShortcutsToString(QAction *action) - { - QString value; -diff --git a/src/CaptureModeModel.h b/src/CaptureModeModel.h -index 574936cb..ef78756a 100644 ---- a/src/CaptureModeModel.h -+++ b/src/CaptureModeModel.h -@@ -7,6 +7,7 @@ - #include "Platforms/ImagePlatform.h" - - #include -+#include - - /** - * This is a model containing the current supported capture modes and their labels and shortcuts. -@@ -15,11 +16,23 @@ class CaptureModeModel : public QAbstractListModel - { - Q_OBJECT - QML_ELEMENT -+ QML_SINGLETON - Q_PROPERTY(int count READ rowCount NOTIFY countChanged FINAL) - - public: - CaptureModeModel(QObject *parent = nullptr); - -+ static CaptureModeModel *instance(); -+ -+ static CaptureModeModel *create(QQmlEngine *engine, QJSEngine *) -+ { -+ auto inst = instance(); -+ Q_ASSERT(inst); -+ Q_ASSERT(inst->thread() == engine->thread()); -+ QJSEngine::setObjectOwnership(inst, QJSEngine::CppOwnership); -+ return inst; -+ } -+ - enum CaptureMode { - RectangularRegion, - AllScreens, -diff --git a/src/Gui/AcceptAction.qml b/src/Gui/AcceptAction.qml -new file mode 100644 -index 00000000..436066bc ---- /dev/null -+++ b/src/Gui/AcceptAction.qml -@@ -0,0 +1,11 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick.Templates as T -+ -+T.Action { -+ icon.name: "dialog-ok" -+ text: i18nc("@action accept selection", "Accept") -+ onTriggered: contextWindow.accept() -+} -diff --git a/src/Gui/AnnotationOptionsToolBarContents.qml b/src/Gui/AnnotationOptionsToolBarContents.qml -index 89198ac1..e7428127 100644 ---- a/src/Gui/AnnotationOptionsToolBarContents.qml -+++ b/src/Gui/AnnotationOptionsToolBarContents.qml -@@ -38,14 +38,9 @@ Row { - } - } - -- component ToolButton: QQC.ToolButton { -- implicitHeight: QmlUtils.iconTextButtonHeight -- width: display === QQC.ToolButton.IconOnly ? height : implicitWidth -+ component ToolButton: TtToolButton { - focusPolicy: root.focusPolicy - display: root.displayMode -- QQC.ToolTip.text: text -- QQC.ToolTip.visible: (hovered || pressed) && display === QQC.ToolButton.IconOnly -- QQC.ToolTip.delay: Kirigami.Units.toolTipDelay - } - - Loader { // stroke -diff --git a/src/Gui/Annotations/CropTool.qml b/src/Gui/Annotations/CropTool.qml -index c17557da..80b3588c 100644 ---- a/src/Gui/Annotations/CropTool.qml -+++ b/src/Gui/Annotations/CropTool.qml -@@ -153,6 +153,7 @@ Loader { - } - - Outline { -+ pathHints: ShapePath.PathLinear - x: selectionRect.x - strokeWidth - y: selectionRect.y - strokeWidth - width: selectionRect.width + strokeWidth * 2 -diff --git a/src/Gui/Annotations/TextTool.qml b/src/Gui/Annotations/TextTool.qml -index a2def4a8..b687b7fb 100644 ---- a/src/Gui/Annotations/TextTool.qml -+++ b/src/Gui/Annotations/TextTool.qml -@@ -183,6 +183,7 @@ AnimatedLoader { - topInset: -background.strokeWidth - bottomInset: -background.strokeWidth - background: DashedOutline { -+ pathHints: ShapePath.PathLinear - strokeWidth: QmlUtils.clampPx(dprRound(1) / root.viewport.scale) - } - -diff --git a/src/Gui/ButtonGrid.qml b/src/Gui/ButtonGrid.qml -index bb158446..a3e7b834 100644 ---- a/src/Gui/ButtonGrid.qml -+++ b/src/Gui/ButtonGrid.qml -@@ -12,14 +12,23 @@ Grid { - property int displayMode: QQC.AbstractButton.TextBesideIcon - property int focusPolicy: Qt.StrongFocus - readonly property bool mirrored: effectiveLayoutDirection === Qt.RightToLeft -- property bool animationsEnabled: true -+ property bool animationsEnabled: false - - clip: childrenRect.width > width || childrenRect.height > height - horizontalItemAlignment: Grid.AlignHCenter - verticalItemAlignment: Grid.AlignVCenter - spacing: Kirigami.Units.mediumSpacing -- columns: flow === Grid.LeftToRight ? visibleChildren.length : 1 -- rows: flow === Grid.TopToBottom ? visibleChildren.length : 1 -+ /* Using -1 for either rows or columns sets the amount to unlimited, -+ * but not if you set both to -1. Using `visibleChildren.length` to set -+ * unlimited rows or columns can generate errors about not having enough -+ * rows/columns when a child item's `visible` property is toggled. -+ * Internally, rows and columns are set to defaults like this: -+ * if (rows <= 0 && columns <= 0) { columns = 4; rows = (numVisible+3)/4; } -+ * else if (rows <= 0) { rows = (numVisible+(columns-1))/columns; } -+ * else if (columns <= 0) { columns = (numVisible+(rows-1))/rows; } -+ */ -+ columns: flow === Grid.LeftToRight ? -1 : 1 -+ rows: flow === Grid.TopToBottom ? -1 : 1 - move: Transition { - enabled: root.animationsEnabled - NumberAnimation { properties: "x,y"; duration: Kirigami.Units.longDuration; easing.type: Easing.OutCubic } -diff --git a/src/Gui/CaptureModeButtonsColumn.qml b/src/Gui/CaptureModeButtonsColumn.qml -index 08b78be1..9071a5e6 100644 ---- a/src/Gui/CaptureModeButtonsColumn.qml -+++ b/src/Gui/CaptureModeButtonsColumn.qml -@@ -11,7 +11,7 @@ import org.kde.spectacle.private - ColumnLayout { - spacing: Kirigami.Units.mediumSpacing - Repeater { -- model: CaptureModeModel { } -+ model: CaptureModeModel - delegate: QQC.DelayButton { - id: button - readonly property bool showCancel: Settings.captureMode === model.captureMode && SpectacleCore.captureTimeRemaining > 0 -diff --git a/src/Gui/CaptureWindow.cpp b/src/Gui/CaptureWindow.cpp -index 462a1344..7568b8c4 100644 ---- a/src/Gui/CaptureWindow.cpp -+++ b/src/Gui/CaptureWindow.cpp -@@ -107,25 +107,14 @@ QScreen *CaptureWindow::screenToFollow() const - - void CaptureWindow::setMode(CaptureWindow::Mode mode) - { -- if (mode == Image) { -- syncGeometryWithScreen(); -- QVariantMap initialProperties = { -- // Set the parent in initialProperties to avoid having -- // the parent and window be null in Component.onCompleted -- {u"parent"_s, QVariant::fromValue(contentItem())} -- }; -- setSource(QUrl("%1/Gui/ImageCaptureOverlay.qml"_L1.arg(SPECTACLE_QML_PATH)), -- initialProperties); -- } else if (mode == Video) { -- syncGeometryWithScreen(); -- QVariantMap initialProperties = { -- // Set the parent in initialProperties to avoid having -- // the parent and window be null in Component.onCompleted -- {u"parent"_s, QVariant::fromValue(contentItem())} -- }; -- setSource(QUrl("%1/Gui/VideoCaptureOverlay.qml"_L1.arg(SPECTACLE_QML_PATH)), -- initialProperties); -- } -+ syncGeometryWithScreen(); -+ QVariantMap initialProperties = { -+ // Set the parent in initialProperties to avoid having -+ // the parent and window be null in Component.onCompleted -+ {u"parent"_s, QVariant::fromValue(contentItem())} -+ }; -+ setSource(QUrl("%1/Gui/ImageCaptureOverlay.qml"_L1.arg(SPECTACLE_QML_PATH)), -+ initialProperties); - } - - bool CaptureWindow::accept() -diff --git a/src/Gui/CopyImageAction.qml b/src/Gui/CopyImageAction.qml -new file mode 100644 -index 00000000..8a4718a9 ---- /dev/null -+++ b/src/Gui/CopyImageAction.qml -@@ -0,0 +1,15 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick.Templates as T -+import org.kde.spectacle.private -+ -+T.Action { -+ // We don't use this in video mode because you can't copy raw video to the -+ // clipboard, or at least not elegantly. -+ enabled: !SpectacleCore.videoMode -+ icon.name: "edit-copy" -+ text: i18nc("@action", "Copy") -+ onTriggered: contextWindow.copyImage() -+} -diff --git a/src/Gui/CopyLocationAction.qml b/src/Gui/CopyLocationAction.qml -new file mode 100644 -index 00000000..d52255f0 ---- /dev/null -+++ b/src/Gui/CopyLocationAction.qml -@@ -0,0 +1,11 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick.Templates as T -+ -+T.Action { -+ icon.name: "edit-copy-path" -+ text: i18nc("@action", "Copy Location") -+ onTriggered: contextWindow.copyLocation() -+} -diff --git a/src/Gui/DashedOutline.qml b/src/Gui/DashedOutline.qml -index d3d7d40d..a1067305 100644 ---- a/src/Gui/DashedOutline.qml -+++ b/src/Gui/DashedOutline.qml -@@ -19,6 +19,7 @@ Outline { - property alias dashOffset: dashPath.dashOffset - property alias dashSvgPath: dashPathSvg.path - property alias dashPathScale: dashPath.scale -+ property alias dashPathHints: dashPath.pathHints - - // A regular alternative pattern with a spacing in logical pixels - function regularDashPattern(spacing, strokeWidth = root.strokeWidth) { -@@ -38,6 +39,7 @@ Outline { - capStyle: ShapePath.FlatCap - joinStyle: root.joinStyle - scale: root.pathScale -+ pathHints: root.pathHints - PathSvg { - id: dashPathSvg - path: root.svgPath -diff --git a/src/Gui/EditAction.qml b/src/Gui/EditAction.qml -new file mode 100644 -index 00000000..988af740 ---- /dev/null -+++ b/src/Gui/EditAction.qml -@@ -0,0 +1,15 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick.Templates as T -+import org.kde.spectacle.private -+ -+T.Action { -+ enabled: !SpectacleCore.videoMode -+ icon.name: "edit-image" -+ text: i18nc("@action edit screenshot", "Edit…") -+ checkable: true -+ checked: contextWindow.annotating -+ onToggled: contextWindow.annotating = checked -+} -diff --git a/src/Gui/ExportMenu.cpp b/src/Gui/ExportMenu.cpp -index d994179c..1a1a041c 100644 ---- a/src/Gui/ExportMenu.cpp -+++ b/src/Gui/ExportMenu.cpp -@@ -47,6 +47,8 @@ ExportMenu::ExportMenu(QWidget *parent) - , mPurposeMenu(new Purpose::Menu) - #endif - { -+ setTitle(i18nc("@title:menu", "Export")); -+ setIcon(QIcon::fromTheme(u"document-share"_s)); - addAction(QIcon::fromTheme(u"document-open-folder"_s), - i18n("Open Default Screenshots Folder"), - this, &ExportMenu::openScreenshotsFolder); -diff --git a/src/Gui/ExportMenuButton.qml b/src/Gui/ExportMenuButton.qml -new file mode 100644 -index 00000000..769f8053 ---- /dev/null -+++ b/src/Gui/ExportMenuButton.qml -@@ -0,0 +1,17 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick -+import org.kde.kirigami as Kirigami -+import org.kde.spectacle.private -+ -+TtToolButton { -+ // FIXME: make export menu actually work with videos -+ visible: !SpectacleCore.videoMode -+ icon.name: "document-share" -+ text: i18nc("@action", "Export") -+ down: pressed || ExportMenu.visible -+ Accessible.role: Accessible.ButtonMenu -+ onPressed: ExportMenu.popup(this) -+} -diff --git a/src/Gui/FloatingToolBar.qml b/src/Gui/FloatingToolBar.qml -index a42fc3dc..3fe9d1d8 100644 ---- a/src/Gui/FloatingToolBar.qml -+++ b/src/Gui/FloatingToolBar.qml -@@ -14,6 +14,7 @@ T.Pane { - property real topRightRadius: radius - property real bottomLeftRadius: radius - property real bottomRightRadius: radius -+ property real backgroundColorOpacity: 0.95 - - implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, - contentWidth + leftPadding + rightPadding) -@@ -26,7 +27,7 @@ T.Pane { - background: FloatingBackground { - color: Qt.rgba(root.palette.window.r, - root.palette.window.g, -- root.palette.window.b, 0.85) -+ root.palette.window.b, root.backgroundColorOpacity) - border.color: Qt.rgba(root.palette.windowText.r, - root.palette.windowText.g, - root.palette.windowText.b, 0.2) -diff --git a/src/Gui/Handle.qml b/src/Gui/Handle.qml -index fbb386d0..a6c241ba 100644 ---- a/src/Gui/Handle.qml -+++ b/src/Gui/Handle.qml -@@ -153,6 +153,9 @@ Shape { - strokeStyle: root.strokeStyle - joinStyle: root.joinStyle - capStyle: root.capStyle -+ pathHints: (Math.abs(root.sweepAngle) === 360 || Math.abs(root.sweepAngle) <= 180 -+ ? ShapePath.PathConvex : ShapePath.PathSolid) -+ | ShapePath.PathNonOverlappingControlPointTriangles - PathAngleArc { - moveToStart: true // this path should not be affected by startX/startY - radiusX: root.radiusX -diff --git a/src/Gui/HelpMenu.cpp b/src/Gui/HelpMenu.cpp -index cadeb22c..ccc66adc 100644 ---- a/src/Gui/HelpMenu.cpp -+++ b/src/Gui/HelpMenu.cpp -@@ -6,6 +6,7 @@ - #include "WidgetWindowUtils.h" - - #include -+#include - - #include - #include -@@ -13,6 +14,8 @@ - - #include - -+using namespace Qt::StringLiterals; -+ - class HelpMenuSingleton - { - public: -@@ -39,6 +42,8 @@ HelpMenu::HelpMenu(QWidget* parent) - : SpectacleMenu(parent) - , kHelpMenu(new KHelpMenu(parent, KAboutData::applicationData(), true)) - { -+ setTitle(i18nc("@title:menu", "Help")); -+ setIcon(QIcon::fromTheme(u"help-contents"_s)); - addActions(kHelpMenu->menu()->actions()); - connect(this, &QMenu::triggered, this, &HelpMenu::onTriggered); - } -diff --git a/src/Gui/HelpMenuButton.qml b/src/Gui/HelpMenuButton.qml -new file mode 100644 -index 00000000..be30b32f ---- /dev/null -+++ b/src/Gui/HelpMenuButton.qml -@@ -0,0 +1,14 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick -+import org.kde.spectacle.private -+ -+TtToolButton { -+ icon.name: "help-contents" -+ text: i18nc("@action", "Help") -+ down: pressed || HelpMenu.visible -+ Accessible.role: Accessible.ButtonMenu -+ onPressed: HelpMenu.popup(this) -+} -diff --git a/src/Gui/ImageCaptureOverlay.qml b/src/Gui/ImageCaptureOverlay.qml -index d94a649c..da4cf33d 100644 ---- a/src/Gui/ImageCaptureOverlay.qml -+++ b/src/Gui/ImageCaptureOverlay.qml -@@ -6,6 +6,7 @@ - import QtQuick - import QtQuick.Window - import QtQuick.Layouts -+import QtQuick.Shapes - import QtQuick.Controls as QQC - import org.kde.kirigami as Kirigami - import org.kde.spectacle.private -@@ -25,42 +26,58 @@ import "Annotations" - MouseArea { - // This needs to be a mousearea in orcer for the proper mouse events to be correctly filtered - id: root -+ readonly property rect viewportRect: Geometry.mapFromPlatformRect(screenToFollow.geometry, screenToFollow.devicePixelRatio) -+ readonly property AnnotationDocument document: annotationsLoader.item?.document ?? null - focus: true - acceptedButtons: Qt.LeftButton | Qt.RightButton - hoverEnabled: true - LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft - LayoutMirroring.childrenInherit: true - anchors.fill: parent -+ enabled: !SpectacleCore.videoPlatform.isRecording - -- readonly property Selection selection: SelectionEditor.selection -- -- AnnotationEditor { -- id: annotations -+ AnimatedLoader { -+ id: annotationsLoader - anchors.fill: parent -- visible: true -- enabled: contextWindow.annotating -- viewportRect: Geometry.mapFromPlatformRect(screenToFollow.geometry, screenToFollow.devicePixelRatio) -+ state: !SpectacleCore.videoMode ? "active" : "inactive" -+ animationDuration: Kirigami.Units.veryLongDuration -+ sourceComponent: AnnotationEditor { -+ enabled: contextWindow.annotating -+ viewportRect: root.viewportRect -+ } -+ } -+ -+ component ToolButton : TtToolButton { -+ focusPolicy: Qt.NoFocus -+ } -+ -+ component ToolBarSizeLabel: SizeLabel { -+ height: QmlUtils.iconTextButtonHeight -+ size: { -+ const sz = SelectionEditor.selection.empty -+ ? Qt.size(SelectionEditor.screensRect.width, -+ SelectionEditor.screensRect.height) -+ : SelectionEditor.selection.size -+ return Geometry.rawSize(sz, SelectionEditor.devicePixelRatio) -+ } -+ leftPadding: Kirigami.Units.mediumSpacing + QmlUtils.fontMetrics.descent -+ rightPadding: leftPadding - } - - component Overlay: Rectangle { - color: Settings.useLightMaskColor ? "white" : "black" -- opacity: 0.5 -- LayoutMirroring.enabled: false -- } -- Overlay { // top / full overlay when nothing selected -- id: topOverlay -- anchors.top: parent.top -- anchors.left: parent.left -- anchors.right: parent.right -- anchors.bottom: selectionRectangle.visible ? selectionRectangle.top : parent.bottom -- opacity: if (root.selection.empty -- && (!annotations.document.tool.isNoTool || annotations.document.undoStackDepth > 0)) { -+ opacity: if (SpectacleCore.videoPlatform.isRecording -+ || (annotationsLoader.visible -+ && SelectionEditor.selection.empty -+ && root.document && (!root.document.tool.isNoTool -+ || root.document.undoStackDepth > 0))) { - return 0 -- } else if (root.selection.empty) { -+ } else if (SelectionEditor.selection.empty) { - return 0.25 - } else { - return 0.5 - } -+ LayoutMirroring.enabled: false - Behavior on opacity { - NumberAnimation { - duration: Kirigami.Units.longDuration -@@ -68,6 +85,13 @@ MouseArea { - } - } - } -+ Overlay { // top / full overlay when nothing selected -+ id: topOverlay -+ anchors.top: parent.top -+ anchors.left: parent.left -+ anchors.right: parent.right -+ anchors.bottom: selectionRectangle.visible ? selectionRectangle.top : parent.bottom -+ } - Overlay { // bottom - id: bottomOverlay - anchors.left: parent.left -@@ -95,37 +119,69 @@ MouseArea { - visible: selectionRectangle.visible && height > 0 && width > 0 - } - -- Rectangle { -+ AnimatedLoader { -+ anchors.centerIn: parent -+ visible: opacity > 0 && !SpectacleCore.videoPlatform.isRecording -+ state: topOverlay.opacity === 0.25 ? "active" : "inactive" -+ sourceComponent: Kirigami.Heading { -+ id: cropToolHelp -+ horizontalAlignment: Text.AlignHCenter -+ verticalAlignment: Text.AlignVCenter -+ text: i18nc("@info basic crop tool explanation", "Click and drag to make a selection.") -+ padding: cropToolHelpMetrics.height - cropToolHelpMetrics.descent -+ leftPadding: cropToolHelpMetrics.height -+ rightPadding: cropToolHelpMetrics.height -+ background: FloatingBackground { -+ radius: cropToolHelpMetrics.height -+ color: Qt.alpha(palette.window, 0.9) -+ } -+ FontMetrics { -+ id: cropToolHelpMetrics -+ font: cropToolHelp.font -+ } -+ } -+ } -+ -+ -+ DashedOutline { - id: selectionRectangle -- enabled: annotations.document.tool.isNoTool -- color: "transparent" -- border.color: if (enabled) { -+ // We need to be a bit careful about staying out of the recorded area -+ function roundPos(value: real) : real { -+ return SpectacleCore.videoPlatform.isRecording ? dprFloor(value - (strokeWidth + 1 / Screen.devicePixelRatio)) : dprRound(value - strokeWidth) -+ } -+ function roundSize(value: real) : real { -+ return SpectacleCore.videoPlatform.isRecording ? dprCeil(value + (strokeWidth + 1 / Screen.devicePixelRatio)) : dprRound(value + strokeWidth) -+ } -+ pathHints: ShapePath.PathLinear -+ dashSvgPath: SpectacleCore.videoPlatform.isRecording ? svgPath : "" -+ visible: !SelectionEditor.selection.empty -+ && Geometry.rectIntersects(Qt.rect(x,y,width,height), Qt.rect(0,0,parent.width, parent.height)) -+ enabled: root.document?.tool.isNoTool || SpectacleCore.videoMode -+ strokeWidth: dprRound(1) -+ strokeColor: if (enabled) { - return palette.active.highlight - } else if (Settings.useLightMaskColor) { - return "black" - } else { - return "white" - } -- border.width: contextWindow.dprRound(1) -- visible: !root.selection.empty && Geometry.rectIntersects(Qt.rect(x,y,width,height), Qt.rect(0,0,parent.width, parent.height)) -- x: root.selection.x - border.width - annotations.viewportRect.x -- y: root.selection.y - border.width - annotations.viewportRect.y -- width: root.selection.width + border.width * 2 -- height: root.selection.height + border.width * 2 -- -- LayoutMirroring.enabled: false -- LayoutMirroring.childrenInherit: true -+ dashColor: SpectacleCore.videoPlatform.isRecording ? palette.active.base : strokeColor -+ // We need to be a bit careful about staying out of the recorded area -+ x: roundPos(SelectionEditor.selection.x - root.viewportRect.x) -+ y: roundPos(SelectionEditor.selection.y - root.viewportRect.y) -+ width: roundSize(SelectionEditor.selection.right - root.viewportRect.x) - x -+ height: roundSize(SelectionEditor.selection.bottom - root.viewportRect.y) - y - } - - Item { -- x: -annotations.viewportRect.x -- y: -annotations.viewportRect.y -+ x: -root.viewportRect.x -+ y: -root.viewportRect.y - enabled: selectionRectangle.enabled - component SelectionHandle: Handle { - visible: enabled && selectionRectangle.visible - && SelectionEditor.dragLocation === SelectionEditor.None -- && Geometry.rectIntersects(Qt.rect(x,y,width,height), annotations.viewportRect) -- fillColor: selectionRectangle.border.color -+ && Geometry.rectIntersects(Qt.rect(x,y,width,height), root.viewportRect) -+ fillColor: selectionRectangle.strokeColor - } - - SelectionHandle { -@@ -170,34 +226,23 @@ MouseArea { - } - } - -- ShortcutsTextBox { -- anchors { -- horizontalCenter: parent.horizontalCenter -- bottom: parent.bottom -- } -- visible: opacity > 0 && Settings.showCaptureInstructions -- // Assume SelectionEditor covers all screens. -- // Use parent's coordinate system. -- opacity: root.containsMouse -- && !contains(mapFromItem(root, root.mouseX, root.mouseY)) -- && !root.pressed -- && annotations.document.tool.isNoTool -- && !mtbDragHandler.active -- && !atbDragHandler.active -- && !Geometry.rectIntersects(SelectionEditor.handlesRect, Qt.rect(x, y, width, height)) -- Behavior on opacity { -- NumberAnimation { -- duration: Kirigami.Units.longDuration -- easing.type: Easing.OutCubic -- } -- } -- } -- - Item { // separate item because it needs to be above the stuff defined above -+ id: screensRectItem -+ readonly property bool allowToolbars: { -+ let emptyHovered = (root.containsMouse || annotationsLoader.item?.hovered) && SelectionEditor.selection.empty -+ let menuVisible = ExportMenu.visible -+ menuVisible |= OptionsMenu.visible -+ menuVisible |= HelpMenu.visible -+ menuVisible |= ScreenshotModeMenu.visible -+ menuVisible |= RecordingModeMenu.visible -+ let pressed = SelectionEditor.dragLocation || annotationsLoader.item?.anyPressed -+ return !SpectacleCore.videoPlatform.isRecording && !pressed -+ && (emptyHovered || !SelectionEditor.selection.empty || menuVisible) -+ } - width: SelectionEditor.screensRect.width - height: SelectionEditor.screensRect.height -- x: -annotations.viewportRect.x -- y: -annotations.viewportRect.y -+ x: -root.viewportRect.x -+ y: -root.viewportRect.y - - // Magnifier - Loader { -@@ -211,33 +256,33 @@ MouseArea { - if (SelectionEditor.magnifierLocation === SelectionEditor.TopLeft - || SelectionEditor.magnifierLocation === SelectionEditor.Left - || SelectionEditor.magnifierLocation === SelectionEditor.BottomLeft) { -- x = root.selection.left -+ x = SelectionEditor.selection.left - } else if (SelectionEditor.magnifierLocation === SelectionEditor.TopRight - || SelectionEditor.magnifierLocation === SelectionEditor.Right - || SelectionEditor.magnifierLocation === SelectionEditor.BottomRight) { -- x = root.selection.right -+ x = SelectionEditor.selection.right - } else if (SelectionEditor.magnifierLocation === SelectionEditor.Top - || SelectionEditor.magnifierLocation === SelectionEditor.Bottom) { - if (SelectionEditor.dragLocation !== SelectionEditor.None) { - x = SelectionEditor.mousePosition.x - } else { -- x = root.selection.horizontalCenter -+ x = SelectionEditor.selection.horizontalCenter - } - } - if (SelectionEditor.magnifierLocation === SelectionEditor.TopLeft - || SelectionEditor.magnifierLocation === SelectionEditor.Top - || SelectionEditor.magnifierLocation === SelectionEditor.TopRight) { -- y = root.selection.top -+ y = SelectionEditor.selection.top - } else if (SelectionEditor.magnifierLocation === SelectionEditor.BottomLeft - || SelectionEditor.magnifierLocation === SelectionEditor.Bottom - || SelectionEditor.magnifierLocation === SelectionEditor.BottomRight) { -- y = root.selection.bottom -+ y = SelectionEditor.selection.bottom - } else if (SelectionEditor.magnifierLocation === SelectionEditor.Left - || SelectionEditor.magnifierLocation === SelectionEditor.Right) { - if (SelectionEditor.dragLocation !== SelectionEditor.None) { - y = SelectionEditor.mousePosition.y - } else { -- y = root.selection.verticalCenter -+ y = SelectionEditor.selection.verticalCenter - } - } - return Qt.point(x, y) -@@ -281,91 +326,30 @@ MouseArea { - z: 100 - visible: SelectionEditor.showMagnifier - && SelectionEditor.magnifierLocation !== SelectionEditor.None -- && Geometry.rectIntersects(rect, annotations.viewportRect) -- active: Settings.showMagnifier !== Settings.ShowMagnifierNever -+ && Geometry.rectIntersects(rect, root.viewportRect) -+ active: Settings.showMagnifier !== Settings.ShowMagnifierNever && annotationsLoader.item !== null - sourceComponent: Magnifier { -- viewport: annotations -+ viewport: annotationsLoader.item - targetPoint: magnifierLoader.targetPoint - } - } - -- // Size ToolTip -- SizeLabel { -- id: ssToolTip -- readonly property int valignment: { -- if (root.selection.empty) { -- return Qt.AlignVCenter -- } -- const margin = Kirigami.Units.mediumSpacing * 2 -- const w = width + margin -- const h = height + margin -- if (SelectionEditor.handlesRect.top >= h) { -- return Qt.AlignTop -- } else if (SelectionEditor.screensRect.height - SelectionEditor.handlesRect.bottom >= h) { -- return Qt.AlignBottom -- } else { -- // At the bottom of the inside of the selection rect. -- return Qt.AlignBaseline -- } -- } -- readonly property bool normallyVisible: !root.selection.empty && !(mainToolBar.visible && mainToolBar.valignment === ssToolTip.valignment) -- Binding on x { -- value: contextWindow.dprRound(root.selection.horizontalCenter - ssToolTip.width / 2) -- when: ssToolTip.normallyVisible -- restoreMode: Binding.RestoreNone -- } -- Binding on y { -- value: { -- let v = 0 -- if (ssToolTip.valignment & Qt.AlignBaseline) { -- v = Math.min(root.selection.bottom, SelectionEditor.handlesRect.bottom - Kirigami.Units.gridUnit) -- - ssToolTip.height - Kirigami.Units.mediumSpacing * 2 -- } else if (ssToolTip.valignment & Qt.AlignTop) { -- v = SelectionEditor.handlesRect.top -- - ssToolTip.height - Kirigami.Units.mediumSpacing * 2 -- } else if (ssToolTip.valignment & Qt.AlignBottom) { -- v = SelectionEditor.handlesRect.bottom + Kirigami.Units.mediumSpacing * 2 -- } else { -- v = (root.height - ssToolTip.height) / 2 - parent.y -- } -- return contextWindow.dprRound(v) -- } -- when: ssToolTip.normallyVisible -- restoreMode: Binding.RestoreNone -- } -- visible: opacity > 0 -- opacity: ssToolTip.normallyVisible -- && Geometry.rectIntersects(Qt.rect(x,y,width,height), annotations.viewportRect) -- Behavior on opacity { -- NumberAnimation { -- duration: Kirigami.Units.longDuration -- easing.type: Easing.OutCubic -- } -- } -- size: Geometry.rawSize(root.selection.size, SelectionEditor.devicePixelRatio) -- padding: Kirigami.Units.mediumSpacing * 2 -- topPadding: padding - QmlUtils.fontMetrics.descent -- bottomPadding: topPadding -- background: FloatingBackground { -- implicitWidth: Math.ceil(parent.contentWidth) + parent.leftPadding + parent.rightPadding -- implicitHeight: Math.ceil(parent.contentHeight) + parent.topPadding + parent.bottomPadding -- color: Qt.rgba(parent.palette.window.r, -- parent.palette.window.g, -- parent.palette.window.b, 0.85) -- border.color: Qt.rgba(parent.palette.windowText.r, -- parent.palette.windowText.g, -- parent.palette.windowText.b, 0.2) -- border.width: contextWindow.dprRound(1) -- } -- } -- - Connections { -- target: root.selection -+ target: SelectionEditor.selection - function onEmptyChanged() { -- if (!root.selection.empty -- && (mainToolBar.rememberPosition || atbLoader.rememberPosition)) { -- mainToolBar.rememberPosition = false -- atbLoader.rememberPosition = false -+ if (!SelectionEditor.selection.empty) { -+ if (mainToolBar.rememberPosition) { -+ mainToolBar.z = 0 -+ mainToolBar.rememberPosition = false -+ } -+ if (ftbLoader.item?.rememberPosition) { -+ ftbLoader.z = 0 -+ ftbLoader.item.rememberPosition = false -+ } -+ if (atbLoader.item?.rememberPosition) { -+ atbLoader.z = 0 -+ atbLoader.item.rememberPosition = false -+ } - } - } - } -@@ -373,65 +357,27 @@ MouseArea { - // Main ToolBar - FloatingToolBar { - id: mainToolBar -+ readonly property rect rect: Qt.rect(x, y, width, height) - property bool rememberPosition: false -- readonly property int valignment: { -- if (root.selection.empty) { -- return 0 -- } -- if (3 * height + topPadding + Kirigami.Units.mediumSpacing -- <= SelectionEditor.screensRect.height - SelectionEditor.handlesRect.bottom -- ) { -- return Qt.AlignBottom -- } else if (3 * height + bottomPadding + Kirigami.Units.mediumSpacing -- <= SelectionEditor.handlesRect.top -- ) { -- return Qt.AlignTop -- } else { -- // At the bottom of the inside of the selection rect. -- return Qt.AlignBaseline -- } -- } -- readonly property bool normallyVisible: { -- let emptyHovered = (root.containsMouse || annotations.hovered) && root.selection.empty -- let menuVisible = ExportMenu.visible -- menuVisible |= OptionsMenu.visible -- menuVisible |= HelpMenu.visible -- let pressed = SelectionEditor.dragLocation || annotations.anyPressed -- return (emptyHovered || !root.selection.empty || menuVisible) && !pressed -- } -+ property alias dragging: mtbDragHandler.active - Binding on x { -- value: { -- const v = root.selection.empty ? (root.width - mainToolBar.width) / 2 + annotations.viewportRect.x -- : root.selection.horizontalCenter - mainToolBar.width / 2 -- return Math.max(mainToolBar.leftPadding, // min value -- Math.min(contextWindow.dprRound(v), -- SelectionEditor.screensRect.width - mainToolBar.width - mainToolBar.rightPadding)) // max value -- } -- when: mainToolBar.normallyVisible && !mainToolBar.rememberPosition -+ value: Math.max(root.viewportRect.x + mainToolBar.leftPadding, // min value -+ Math.min(dprRound(root.viewportRect.x + (root.width - mainToolBar.width) / 2), -+ root.viewportRect.x + root.width - mainToolBar.width - mainToolBar.rightPadding)) // max value -+ when: screensRectItem.allowToolbars && !mainToolBar.rememberPosition - restoreMode: Binding.RestoreNone - } - Binding on y { -- value: { -- let v = 0 -- // put above selection if not enough room below selection -- if (mainToolBar.valignment & Qt.AlignTop) { -- v = SelectionEditor.handlesRect.top -- - mainToolBar.height - mainToolBar.bottomPadding -- } else if (mainToolBar.valignment & Qt.AlignBottom) { -- v = SelectionEditor.handlesRect.bottom + mainToolBar.topPadding -- } else if (mainToolBar.valignment & Qt.AlignBaseline) { -- v = Math.min(root.selection.bottom, SelectionEditor.handlesRect.bottom - Kirigami.Units.gridUnit) -- - mainToolBar.height - mainToolBar.bottomPadding -- } else { -- v = (mainToolBar.height / 2) - mainToolBar.parent.y -- } -- return contextWindow.dprRound(v) -- } -- when: mainToolBar.normallyVisible && !mainToolBar.rememberPosition -+ value: dprRound(root.viewportRect.y + root.height - mainToolBar.height - mainToolBar.bottomPadding) -+ when: screensRectItem.allowToolbars && !mainToolBar.rememberPosition - restoreMode: Binding.RestoreNone - } -- visible: opacity > 0 -- opacity: normallyVisible && Geometry.rectIntersects(Qt.rect(x,y,width,height), annotations.viewportRect) -+ visible: opacity > 0 && !SpectacleCore.videoPlatform.isRecording -+ opacity: screensRectItem.allowToolbars -+ && (mainToolBar.rememberPosition -+ || SelectionEditor.selection.empty -+ || (!Geometry.rectIntersects(mainToolBar.rect, ftbLoader.rect) -+ && !Geometry.rectIntersects(mainToolBar.rect, SelectionEditor.handlesRect))) - Behavior on opacity { - NumberAnimation { - duration: Kirigami.Units.longDuration -@@ -440,120 +386,261 @@ MouseArea { - } - layer.enabled: true // improves the visuals of the opacity animation - focusPolicy: Qt.NoFocus -- contentItem: MainToolBarContents { -- id: mainToolBarContents -- focusPolicy: Qt.NoFocus -- displayMode: QQC.AbstractButton.TextBesideIcon -- showSizeLabel: mainToolBar.valignment === ssToolTip.valignment -- imageSize: Geometry.rawSize(root.selection.size, SelectionEditor.devicePixelRatio) -+ contentItem: ButtonGrid { -+ spacing: parent.spacing -+ Loader { -+ id: mtbImageVideoContentLoader -+ visible: SelectionEditor.selection.empty -+ active: visible -+ sourceComponent: SpectacleCore.videoMode ? videoToolBarComponent : imageMainToolBarComponent -+ } -+ QQC.ToolSeparator { -+ visible: mtbImageVideoContentLoader.visible -+ height: QmlUtils.iconTextButtonHeight -+ } -+ ScreenshotModeMenuButton { -+ focusPolicy: Qt.NoFocus -+ } -+ RecordingModeMenuButton { -+ focusPolicy: Qt.NoFocus -+ } -+ OptionsMenuButton { -+ focusPolicy: Qt.NoFocus -+ } - } - -+ HoverHandler { -+ target: mainToolBar -+ margin: mainToolBar.padding -+ cursorShape: enabled ? -+ (mtbDragHandler.active ? Qt.ClosedHandCursor : Qt.OpenHandCursor) -+ : undefined -+ } - DragHandler { // parent is contentItem and parent is a read-only property - id: mtbDragHandler -- enabled: root.selection.empty - target: mainToolBar - acceptedButtons: Qt.LeftButton - margin: mainToolBar.padding -- xAxis.minimum: annotations.viewportRect.x -- xAxis.maximum: annotations.viewportRect.x + root.width - mainToolBar.width -- yAxis.minimum: annotations.viewportRect.y -- yAxis.maximum: annotations.viewportRect.y + root.height - mainToolBar.height -- cursorShape: enabled ? -- (active ? Qt.ClosedHandCursor : Qt.OpenHandCursor) -- : undefined -- onActiveChanged: if (active && !mainToolBar.rememberPosition) { -- mainToolBar.rememberPosition = true -+ xAxis.minimum: root.viewportRect.x -+ xAxis.maximum: root.viewportRect.x + root.width - mainToolBar.width -+ yAxis.minimum: root.viewportRect.y -+ yAxis.maximum: root.viewportRect.y + root.height - mainToolBar.height -+ onActiveChanged: if (active) { -+ mainToolBar.z = 2 -+ atbLoader.z = atbLoader.z > ftbLoader.z ? 1 : 0 -+ ftbLoader.z = atbLoader.z < ftbLoader.z ? 1 : 0 -+ if (!mainToolBar.rememberPosition) { -+ mainToolBar.rememberPosition = true -+ } - } - } - } - -- AnimatedLoader { -- id: atbLoader -- property bool rememberPosition: false -- readonly property int valignment: mainToolBar.valignment & (Qt.AlignTop | Qt.AlignBaseline) ? -- Qt.AlignTop : Qt.AlignBottom -- active: visible && mainToolBar.visible -- onActiveChanged: if (!active && rememberPosition -- && !contextWindow.annotating) { -- rememberPosition = false -- } -- state: mainToolBar.normallyVisible -- && contextWindow.annotating ? "active" : "inactive" -- -- Binding on x { -- value: { -- const min = mainToolBar.x -- const target = contextWindow.dprRound(mainToolBar.x + (mainToolBar.width - atbLoader.width) / 2) -- const max = mainToolBar.x + mainToolBar.width - atbLoader.width -- return Math.max(min, Math.min(target, max)) -+ Component { -+ id: imageMainToolBarComponent -+ ButtonGrid { -+ spacing: parent.parent.spacing -+ ToolBarSizeLabel {} -+ ToolButton { -+ display: TtToolButton.TextBesideIcon -+ visible: action.enabled -+ action: AcceptAction {} -+ } -+ ToolButton { -+ display: TtToolButton.IconOnly -+ visible: action.enabled -+ action: SaveAction {} -+ } -+ ToolButton { -+ display: TtToolButton.IconOnly -+ visible: action.enabled -+ action: SaveAsAction {} -+ } -+ ToolButton { -+ display: TtToolButton.IconOnly -+ visible: action.enabled -+ action: CopyImageAction {} -+ } -+ ExportMenuButton { -+ focusPolicy: Qt.NoFocus - } -- when: !atbLoader.rememberPosition -- restoreMode: Binding.RestoreNone - } -- Binding on y { -- value: contextWindow.dprRound(atbLoader.valignment & Qt.AlignTop ? -- mainToolBar.y - atbLoader.height - Kirigami.Units.mediumSpacing -- : mainToolBar.y + mainToolBar.height + Kirigami.Units.mediumSpacing) -- when: !atbLoader.rememberPosition -- restoreMode: Binding.RestoreNone -+ } -+ Component { -+ id: imageFinalizerToolBarComponent -+ ButtonGrid { -+ spacing: parent.parent.spacing -+ ToolBarSizeLabel {} -+ ToolButton { -+ visible: action.enabled -+ action: AcceptAction {} -+ } -+ ToolButton { -+ visible: action.enabled -+ action: SaveAction {} -+ } -+ ToolButton { -+ visible: action.enabled -+ action: SaveAsAction {} -+ } -+ ToolButton { -+ visible: action.enabled -+ action: CopyImageAction {} -+ } -+ ExportMenuButton { -+ focusPolicy: Qt.NoFocus -+ } - } -- -- DragHandler { // parented to contentItem -- id: atbDragHandler -- enabled: root.selection.empty -- acceptedButtons: Qt.LeftButton -- xAxis.minimum: annotations.viewportRect.x -- xAxis.maximum: annotations.viewportRect.x + root.width - atbLoader.width -- yAxis.minimum: annotations.viewportRect.y -- yAxis.maximum: annotations.viewportRect.y + root.height - atbLoader.height -- cursorShape: enabled ? -- (active ? Qt.ClosedHandCursor : Qt.OpenHandCursor) -- : undefined -- onActiveChanged: if (active && !atbLoader.rememberPosition) { -- atbLoader.rememberPosition = true -+ } -+ Component { -+ id: videoToolBarComponent -+ ButtonGrid { -+ spacing: parent.parent.spacing -+ ToolBarSizeLabel {} -+ ToolButton { -+ display: TtToolButton.TextBesideIcon -+ visible: action.enabled -+ action: RecordAction {} - } - } -+ } - -+ Loader { -+ id: atbLoader -+ readonly property rect rect: Qt.rect(x, y, width, height) -+ visible: annotationsLoader.visible -+ active: visible -+ z: 2 - sourceComponent: FloatingToolBar { - id: annotationsToolBar -+ property bool rememberPosition: false -+ readonly property int valignment: { -+ if (SelectionEditor.handlesRect.top >= height + annotationsToolBar.bottomPadding || SelectionEditor.selection.empty) { -+ // the top of the top side of the selection -+ // or the top of the screen -+ return Qt.AlignTop -+ } else { -+ // the bottom of the top side of the selection -+ return Qt.AlignBottom -+ } -+ } -+ property alias dragging: dragHandler.active -+ visible: opacity > 0 -+ opacity: screensRectItem.allowToolbars && Geometry.rectIntersects(atbLoader.rect, root.viewportRect) -+ Behavior on opacity { -+ NumberAnimation { -+ duration: Kirigami.Units.longDuration -+ easing.type: Easing.OutCubic -+ } -+ } -+ // Can't use layer.enabled to improve opacity animation because -+ // that makes the options toolbar invisible - focusPolicy: Qt.NoFocus - contentItem: AnnotationsToolBarContents { - id: annotationsContents -+ spacing: parent.spacing - displayMode: QQC.AbstractButton.IconOnly - focusPolicy: Qt.NoFocus - } - -- topLeftRadius: optionsToolBar.visible -- && optionsToolBar.x === 0 -- && atbLoader.valignment & Qt.AlignTop ? 0 : radius -- topRightRadius: optionsToolBar.visible -- && optionsToolBar.x === width - optionsToolBar.width -- && atbLoader.valignment & Qt.AlignTop ? 0 : radius -- bottomLeftRadius: optionsToolBar.visible -- && optionsToolBar.x === 0 -- && atbLoader.valignment & Qt.AlignBottom ? 0 : radius -- bottomRightRadius: optionsToolBar.visible -- && optionsToolBar.x === width - optionsToolBar.width -- && atbLoader.valignment & Qt.AlignBottom ? 0 : radius -+ topLeftRadius: otbLoader.visible -+ && otbLoader.x === 0 -+ && (annotationsToolBar.valignment & Qt.AlignTop) -+ && !SelectionEditor.selection.empty ? 0 : radius -+ topRightRadius: otbLoader.visible -+ && otbLoader.x === width - otbLoader.width -+ && (annotationsToolBar.valignment & Qt.AlignTop) -+ && !SelectionEditor.selection.empty? 0 : radius -+ bottomLeftRadius: otbLoader.visible -+ && otbLoader.x === 0 -+ && ((annotationsToolBar.valignment & Qt.AlignBottom) -+ || SelectionEditor.selection.empty) ? 0 : radius -+ bottomRightRadius: otbLoader.visible -+ && otbLoader.x === width - otbLoader.width -+ && ((annotationsToolBar.valignment & Qt.AlignBottom) -+ || SelectionEditor.selection.empty) ? 0 : radius -+ -+ Binding { -+ property: "x" -+ target: atbLoader -+ value: { -+ const v = SelectionEditor.selection.empty ? (root.width - annotationsToolBar.width) / 2 + root.viewportRect.x -+ : SelectionEditor.selection.horizontalCenter - annotationsToolBar.width / 2 -+ return Math.max(annotationsToolBar.leftPadding, // min value -+ Math.min(dprRound(v), -+ SelectionEditor.screensRect.width - annotationsToolBar.width - annotationsToolBar.rightPadding)) // max value -+ } -+ when: screensRectItem.allowToolbars && !annotationsToolBar.rememberPosition -+ restoreMode: Binding.RestoreNone -+ } -+ Binding { -+ property: "y" -+ target: atbLoader -+ value: { -+ let v = 0 -+ if (SelectionEditor.selection.empty) { -+ v = root.viewportRect.y + annotationsToolBar.topPadding -+ } else if (annotationsToolBar.valignment & Qt.AlignTop) { -+ v = SelectionEditor.handlesRect.top - annotationsToolBar.height - annotationsToolBar.bottomPadding -+ } else if (annotationsToolBar.valignment & Qt.AlignBottom) { -+ v = Math.max(SelectionEditor.selection.top, SelectionEditor.handlesRect.top + Kirigami.Units.gridUnit) -+ + annotationsToolBar.topPadding -+ } else { -+ v = (root.height - annotationsToolBar.height) / 2 - parent.y -+ } -+ return dprRound(v) -+ } -+ when: screensRectItem.allowToolbars && !annotationsToolBar.rememberPosition -+ restoreMode: Binding.RestoreNone -+ } - - // Exists purely for cosmetic reasons to make the border of - // optionsToolBar that meets annotationsToolBar look better - Rectangle { - id: borderBg - z: -1 -- visible: optionsToolBar.visible -- opacity: optionsToolBar.opacity -+ visible: otbLoader.visible -+ opacity: otbLoader.opacity - parent: annotationsToolBar -- x: optionsToolBar.x + annotationsToolBar.background.border.width -- y: atbLoader.valignment & Qt.AlignTop ? -- optionsToolBar.y + optionsToolBar.height : optionsToolBar.y -- width: optionsToolBar.width - annotationsToolBar.background.border.width * 2 -- height: contextWindow.dprRound(1) -+ x: otbLoader.x + annotationsToolBar.background.border.width -+ y: (annotationsToolBar.valignment & Qt.AlignTop) -+ && !SelectionEditor.selection.empty -+ ? otbLoader.y + otbLoader.height : otbLoader.y -+ width: otbLoader.width - annotationsToolBar.background.border.width * 2 -+ height: dprRound(1) - color: annotationsToolBar.background.color - } - -+ HoverHandler { -+ enabled: dragHandler.enabled -+ target: annotationsToolBar -+ margin: annotationsToolBar.padding -+ cursorShape: enabled ? -+ (dragHandler.active ? Qt.ClosedHandCursor : Qt.OpenHandCursor) -+ : undefined -+ } -+ DragHandler { // parented to contentItem -+ id: dragHandler -+ enabled: SelectionEditor.selection.empty || !selectionRectangle.enabled -+ target: atbLoader -+ acceptedButtons: Qt.LeftButton -+ margin: annotationsToolBar.padding -+ xAxis.minimum: root.viewportRect.x -+ xAxis.maximum: root.viewportRect.x + root.width - annotationsToolBar.width -+ yAxis.minimum: root.viewportRect.y -+ yAxis.maximum: root.viewportRect.y + root.height - annotationsToolBar.height -+ onActiveChanged: if (active) { -+ mainToolBar.z = mainToolBar.z > ftbLoader.z ? 1 : 0 -+ atbLoader.z = 2 -+ ftbLoader.z = mainToolBar.z < ftbLoader.z ? 1 : 0 -+ if (!annotationsToolBar.rememberPosition) { -+ annotationsToolBar.rememberPosition = true -+ } -+ } -+ } -+ - AnimatedLoader { -- id: optionsToolBar -+ id: otbLoader - parent: annotationsToolBar - x: { - let targetX = annotationsContents.x -@@ -562,15 +649,16 @@ MouseArea { - targetX += checkedButton.x + (checkedButton.width - width) / 2 - } - return Math.max(0, // min value -- Math.min(contextWindow.dprRound(targetX), -+ Math.min(contextWindow.dprRound(targetX), - parent.width - width)) // max value - } -- y: atbLoader.valignment & Qt.AlignTop ? -- -optionsToolBar.height + borderBg.height -- : optionsToolBar.height - borderBg.height -- state: if (SpectacleCore.annotationDocument.tool.options !== AnnotationTool.NoOptions -- || (SpectacleCore.annotationDocument.tool.type === AnnotationTool.SelectTool -- && SpectacleCore.annotationDocument.selectedItem.options !== AnnotationTool.NoOptions) -+ y: (annotationsToolBar.valignment & Qt.AlignTop) -+ && !SelectionEditor.selection.empty -+ ? -otbLoader.height + borderBg.height -+ : otbLoader.height - borderBg.height -+ state: if (root.document?.tool.options !== AnnotationTool.NoOptions -+ || (root.document?.tool.type === AnnotationTool.SelectTool -+ && root.document?.selectedItem.options !== AnnotationTool.NoOptions) - ) { - return "active" - } else { -@@ -579,13 +667,111 @@ MouseArea { - sourceComponent: FloatingToolBar { - focusPolicy: Qt.NoFocus - contentItem: AnnotationOptionsToolBarContents { -+ spacing: parent.spacing - displayMode: QQC.AbstractButton.IconOnly - focusPolicy: Qt.NoFocus - } -- topLeftRadius: atbLoader.valignment & Qt.AlignBottom && x >= 0 ? 0 : radius -- topRightRadius: atbLoader.valignment & Qt.AlignBottom && x + width <= annotationsToolBar.width ? 0 : radius -- bottomLeftRadius: atbLoader.valignment & Qt.AlignTop && x >= 0 ? 0 : radius -- bottomRightRadius: atbLoader.valignment & Qt.AlignTop && x + width <= annotationsToolBar.width ? 0 : radius -+ topLeftRadius: ((annotationsToolBar.valignment & Qt.AlignBottom) || SelectionEditor.selection.empty) && otbLoader.x >= 0 ? 0 : radius -+ topRightRadius: ((annotationsToolBar.valignment & Qt.AlignBottom) || SelectionEditor.selection.empty) && otbLoader.x + width <= annotationsToolBar.width ? 0 : radius -+ bottomLeftRadius: (annotationsToolBar.valignment & Qt.AlignTop) && !SelectionEditor.selection.empty && otbLoader.x >= 0 ? 0 : radius -+ bottomRightRadius: (annotationsToolBar.valignment & Qt.AlignTop) && !SelectionEditor.selection.empty && otbLoader.x + width <= annotationsToolBar.width ? 0 : radius -+ } -+ } -+ } -+ } -+ -+ // Finalizer ToolBar -+ Loader { -+ id: ftbLoader -+ readonly property rect rect: Qt.rect(x, y, width, height) -+ visible: !SpectacleCore.videoPlatform.isRecording && !SelectionEditor.selection.empty -+ active: visible -+ sourceComponent: FloatingToolBar { -+ id: toolBar -+ property bool rememberPosition: false -+ property alias dragging: dragHandler.active -+ readonly property int valignment: { -+ if (SelectionEditor.screensRect.height - SelectionEditor.handlesRect.bottom >= height + toolBar.topPadding || SelectionEditor.selection.empty) { -+ // the bottom of the bottom side of the selection -+ // or the bottom of the screen -+ return Qt.AlignBottom -+ } else { -+ // the top of the bottom side of the selection -+ return Qt.AlignTop -+ } -+ } -+ Binding { -+ property: "x" -+ target: ftbLoader -+ value: { -+ const v = SelectionEditor.selection.empty ? (root.width - toolBar.width) / 2 + root.viewportRect.x -+ : SelectionEditor.selection.horizontalCenter - toolBar.width / 2 -+ return Math.max(toolBar.leftPadding, // min value -+ Math.min(dprRound(v), -+ SelectionEditor.screensRect.width - toolBar.width - toolBar.rightPadding)) // max value -+ } -+ when: screensRectItem.allowToolbars && !toolBar.rememberPosition -+ restoreMode: Binding.RestoreNone -+ } -+ Binding { -+ property: "y" -+ target: ftbLoader -+ value: { -+ let v = 0 -+ if (SelectionEditor.selection.empty) { -+ v = root.viewportRect.y + root.height - toolBar.height - toolBar.bottomPadding -+ } else if (toolBar.valignment & Qt.AlignBottom) { -+ v = SelectionEditor.handlesRect.bottom + toolBar.topPadding -+ } else if (toolBar.valignment & Qt.AlignTop) { -+ v = Math.min(SelectionEditor.selection.bottom, SelectionEditor.handlesRect.bottom - Kirigami.Units.gridUnit) -+ - toolBar.height - toolBar.bottomPadding -+ } else { -+ v = (toolBar.height / 2) - toolBar.parent.y -+ } -+ return dprRound(v) -+ } -+ when: screensRectItem.allowToolbars && !toolBar.rememberPosition -+ restoreMode: Binding.RestoreNone -+ } -+ visible: opacity > 0 -+ opacity: screensRectItem.allowToolbars && Geometry.rectIntersects(ftbLoader.rect, root.viewportRect) -+ Behavior on opacity { -+ NumberAnimation { -+ duration: Kirigami.Units.longDuration -+ easing.type: Easing.OutCubic -+ } -+ } -+ layer.enabled: true // improves the visuals of the opacity animation -+ focusPolicy: Qt.NoFocus -+ contentItem: Loader { -+ sourceComponent: SpectacleCore.videoMode ? videoToolBarComponent : imageFinalizerToolBarComponent -+ } -+ -+ HoverHandler { -+ enabled: dragHandler.enabled -+ target: toolBar -+ margin: toolBar.padding -+ cursorShape: enabled ? -+ (dragHandler.active ? Qt.ClosedHandCursor : Qt.OpenHandCursor) -+ : undefined -+ } -+ DragHandler { // parent is contentItem and parent is a read-only property -+ id: dragHandler -+ enabled: SelectionEditor.selection.empty || !selectionRectangle.enabled -+ target: ftbLoader -+ acceptedButtons: Qt.LeftButton -+ margin: toolBar.padding -+ xAxis.minimum: root.viewportRect.x -+ xAxis.maximum: root.viewportRect.x + root.width - toolBar.width -+ yAxis.minimum: root.viewportRect.y -+ yAxis.maximum: root.viewportRect.y + root.height - toolBar.height -+ onActiveChanged: if (active) { -+ mainToolBar.z = mainToolBar.z > atbLoader.z ? 1 : 0 -+ atbLoader.z = mainToolBar.z < atbLoader.z ? 1 : 0 -+ ftbLoader.z = 2 -+ if (!toolBar.rememberPosition) { -+ toolBar.rememberPosition = true -+ } - } - } - } -diff --git a/src/Gui/ImageView.qml b/src/Gui/ImageView.qml -index ba68e4ca..2be177ec 100644 ---- a/src/Gui/ImageView.qml -+++ b/src/Gui/ImageView.qml -@@ -26,12 +26,11 @@ EmptyPage { - readonly property real minimumWidth: Math.max( - header.implicitWidth, - annotationsToolBar.implicitWidth + separator.implicitWidth + footerLoader.implicitWidth, -- captureOptionsLoader.implicitWidth + 480 // leave some room for content if necessary -+ 480 // leave some room for content if necessary - ) - readonly property real minimumHeight: header.implicitHeight - + Math.max(annotationsToolBar.implicitHeight, -- footerLoader.implicitHeight, -- captureOptionsLoader.implicitHeight) -+ footerLoader.implicitHeight) - - property var inlineMessageData: {} - property string inlineMessageSource: "" -@@ -47,12 +46,46 @@ EmptyPage { - - header: QQC.ToolBar { - id: header -- contentItem: MainToolBarContents { -+ contentItem: ButtonGrid { - id: mainToolBarContents -- showNewScreenshotButton: false -- showOptionsMenu: false -- showUndoRedo: contextWindow.annotating -- displayMode: QQC.AbstractButton.TextBesideIcon -+ animationsEnabled: true -+ AnimatedLoader { -+ state: contextWindow.annotating ? "active" : "inactive" -+ sourceComponent: UndoRedoGroup { -+ buttonHeight: QmlUtils.iconTextButtonHeight -+ spacing: mainToolBarContents.spacing -+ } -+ } -+ TtToolButton { -+ display: TtToolButton.IconOnly -+ visible: action.enabled -+ action: SaveAction {} -+ } -+ TtToolButton { -+ display: SpectacleCore.videoMode ? TtToolButton.TextBesideIcon : TtToolButton.IconOnly -+ action: SaveAsAction {} -+ } -+ TtToolButton { -+ display: TtToolButton.IconOnly -+ visible: action.enabled -+ action: CopyImageAction {} -+ } -+ // We only show this in video mode to save space in screenshot mode -+ TtToolButton { -+ visible: SpectacleCore.videoMode -+ action: CopyLocationAction {} -+ } -+ ExportMenuButton {} -+ TtToolButton { -+ visible: action.enabled -+ action: EditAction {} -+ } -+ QQC.ToolSeparator { -+ height: QmlUtils.iconTextButtonHeight -+ } -+ ScreenshotModeMenuButton {} -+ RecordingModeMenuButton {} -+ OptionsMenuButton {} - } - } - -@@ -64,7 +97,7 @@ EmptyPage { - AnimatedLoader { // parent is contentItem - id: inlineMessageLoader - anchors.left: annotationsToolBar.right -- anchors.right: captureOptionsLoader.left -+ anchors.right: parent.right - anchors.top: parent.top - state: "inactive" - height: visible ? implicitHeight : 0 -@@ -111,7 +144,7 @@ EmptyPage { - id: contentLoader - anchors { - left: footerLoader.left -- right: captureOptionsLoader.left -+ right: parent.right - top: inlineMessageLoader.bottom - bottom: footerLoader.top - } -@@ -126,78 +159,10 @@ EmptyPage { - } - } - -- Loader { // parent is contentItem -- id: captureOptionsLoader -- visible: true -- active: visible -- anchors { -- top: parent.top -- bottom: parent.bottom -- right: parent.right -- } -- width: Math.max(implicitWidth, Kirigami.Units.gridUnit * 15) -- sourceComponent: QQC.Page { -- -- leftPadding: Kirigami.Units.mediumSpacing * 2 -- + (!mirrored ? sideBarSeparator.implicitWidth : 0) -- rightPadding: Kirigami.Units.mediumSpacing * 2 -- + (mirrored ? sideBarSeparator.implicitWidth : 0) -- topPadding: Kirigami.Units.mediumSpacing * 2 -- bottomPadding: Kirigami.Units.mediumSpacing * 2 -- -- header: RowLayout { -- spacing: 0 -- Kirigami.Separator { -- Layout.fillHeight: true -- } -- Kirigami.NavigationTabBar { -- id: tabBar -- Layout.fillWidth: true -- visible: SpectacleCore.videoPlatform.supportedRecordingModes -- currentIndex: 0 -- Kirigami.Theme.colorSet: Kirigami.Theme.Window -- -- actions: [ -- Kirigami.Action { -- text: i18n("Screenshot") -- icon.name: "camera-photo" -- checked: tabBar.currentIndex === 0 -- }, -- Kirigami.Action { -- text: i18n("Recording") -- icon.name: "camera-video" -- checked: tabBar.currentIndex === 1 -- } -- ] -- } -- } -- -- contentItem: Loader { -- source: switch (tabBar.currentIndex) { -- case 0: return "CaptureOptions.qml" -- case 1: return "RecordOptions.qml" -- default: return "" -- } -- } -- -- background: Rectangle { -- color: Kirigami.Theme.backgroundColor -- Kirigami.Separator { -- id: sideBarSeparator -- anchors { -- left: parent.left -- top: parent.top -- bottom: parent.bottom -- } -- } -- } -- } -- } -- - Loader { - id: footerLoader - anchors.left: separator.right -- anchors.right: captureOptionsLoader.left -+ anchors.right: parent.right - anchors.top: parent.bottom - visible: false - active: visible -@@ -294,11 +259,6 @@ EmptyPage { - anchors.bottom: parent.bottom - anchors.top: undefined - } -- AnchorChanges { -- target: captureOptionsLoader -- anchors.left: parent.right -- anchors.right: undefined -- } - }, - State { - name: "normal" -@@ -315,11 +275,6 @@ EmptyPage { - anchors.bottom: undefined - anchors.top: parent.bottom - } -- AnchorChanges { -- target: captureOptionsLoader -- anchors.left: undefined -- anchors.right: parent.right -- } - } - ] - transitions: [ -@@ -335,21 +290,11 @@ EmptyPage { - duration: Kirigami.Units.longDuration - easing.type: Easing.OutCubic - } -- PropertyAction { -- targets: captureOptionsLoader -- property: "visible" -- value: false -- } - } - }, - Transition { - to: "normal" - SequentialAnimation { -- PropertyAction { -- targets: captureOptionsLoader -- property: "visible" -- value: true -- } - AnchorAnimation { - duration: Kirigami.Units.longDuration - easing.type: Easing.OutCubic -diff --git a/src/Gui/MainToolBarContents.qml b/src/Gui/MainToolBarContents.qml -deleted file mode 100644 -index eaf2ad01..00000000 ---- a/src/Gui/MainToolBarContents.qml -+++ /dev/null -@@ -1,153 +0,0 @@ --/* SPDX-FileCopyrightText: 2022 Noah Davis -- * SPDX-License-Identifier: LGPL-2.0-or-later -- */ -- --import QtQuick --import QtQuick.Controls as QQC --import org.kde.kirigami as Kirigami --import org.kde.spectacle.private -- --ButtonGrid { -- id: root -- property size imageSize: Qt.size(0, 0) -- property bool showSizeLabel: false -- property bool showUndoRedo: false -- property bool showNewScreenshotButton: true -- property bool showOptionsMenu: true -- -- component ToolButton: QQC.ToolButton { -- implicitHeight: QmlUtils.iconTextButtonHeight -- width: display === QQC.ToolButton.IconOnly ? height : implicitWidth -- focusPolicy: root.focusPolicy -- display: root.displayMode -- QQC.ToolTip.text: text -- QQC.ToolTip.visible: (hovered || pressed) && display === QQC.ToolButton.IconOnly -- QQC.ToolTip.delay: Kirigami.Units.toolTipDelay -- } -- -- AnimatedLoader { -- id: sizeLabelLoader -- state: root.showSizeLabel && root.imageSize.width > 0 && root.imageSize.height > 0 ? -- "active" : "inactive" -- sourceComponent: SizeLabel { -- height: QmlUtils.iconTextButtonHeight -- size: root.imageSize -- leftPadding: Kirigami.Units.mediumSpacing + QmlUtils.fontMetrics.descent -- rightPadding: leftPadding -- } -- } -- -- AnimatedLoader { -- state: root.showUndoRedo ? "active" : "inactive" -- sourceComponent: UndoRedoGroup { -- animationsEnabled: root.animationsEnabled -- buttonHeight: QmlUtils.iconTextButtonHeight -- focusPolicy: root.focusPolicy -- flow: root.flow -- spacing: root.spacing -- } -- } -- -- // We don't show this in video mode because the video is already automatically saved. -- // and you can't edit the video. -- ToolButton { -- visible: !SpectacleCore.videoMode -- icon.name: "document-save" -- text: i18n("Save") -- onClicked: contextWindow.save() -- } -- -- ToolButton { -- icon.name: "document-save-as" -- text: i18n("Save As...") -- onClicked: contextWindow.saveAs() -- } -- -- // We don't show this in video mode because you can't copy raw video to the clipboard, -- // or at least not elegantly. -- ToolButton { -- visible: !SpectacleCore.videoMode -- icon.name: "edit-copy" -- text: i18n("Copy") -- onClicked: contextWindow.copyImage() -- } -- -- // We only show this in video mode to save space in screenshot mode -- ToolButton { -- visible: SpectacleCore.videoMode -- icon.name: "edit-copy-path" -- text: i18n("Copy Location") -- onClicked: contextWindow.copyLocation() -- } -- -- ToolButton { -- // FIXME: make export menu actually work with videos -- visible: !SpectacleCore.videoMode -- icon.name: "document-share" -- text: i18n("Export") -- down: pressed || ExportMenu.visible -- Accessible.role: Accessible.ButtonMenu -- onPressed: ExportMenu.popup(this) -- } -- -- ToolButton { -- id: annotationsButton -- icon.name: "edit-image" -- text: i18nc("@action:button edit screenshot", "Edit…") -- visible: !SpectacleCore.videoMode -- checkable: true -- checked: contextWindow.annotating -- onToggled: contextWindow.annotating = checked -- } -- -- ToolButton { -- // Can't rely on checked since clicking also toggles checked -- readonly property bool showCancel: SpectacleCore.captureTimeRemaining > 0 -- readonly property real cancelWidth: QmlUtils.getButtonSize(display, cancelText(Settings.captureDelay), icon.name).width -- -- function cancelText(seconds) { -- return i18np("Cancel (%1 second)", "Cancel (%1 seconds)", Math.ceil(seconds)) -- } -- -- visible: root.showNewScreenshotButton -- checked: showCancel -- width: if (showCancel) { -- return cancelWidth -- } else { -- return display === QQC.ToolButton.IconOnly ? height : implicitWidth -- } -- icon.name: showCancel ? "dialog-cancel" : "list-add" -- text: showCancel ? -- cancelText(SpectacleCore.captureTimeRemaining / 1000) -- : i18n("New Screenshot") -- onClicked: if (showCancel) { -- SpectacleCore.cancelScreenshot() -- } else { -- SpectacleCore.takeNewScreenshot() -- } -- } -- -- ToolButton { -- visible: root.showOptionsMenu -- icon.name: "configure" -- text: i18n("Options") -- down: pressed || OptionsMenu.visible -- Accessible.role: Accessible.ButtonMenu -- onPressed: OptionsMenu.popup(this) -- } -- ToolButton { -- visible: !root.showOptionsMenu -- icon.name: "configure" -- text: i18n("Configure...") -- onClicked: OptionsMenu.showPreferencesDialog(); -- } -- -- ToolButton { -- id: helpButton -- icon.name: "help-contents" -- text: i18n("Help") -- down: pressed || HelpMenu.visible -- Accessible.role: Accessible.ButtonMenu -- onPressed: HelpMenu.popup(this) -- } --} -diff --git a/src/Gui/NewScreenshotToolButton.qml b/src/Gui/NewScreenshotToolButton.qml -new file mode 100644 -index 00000000..4c7aa91a ---- /dev/null -+++ b/src/Gui/NewScreenshotToolButton.qml -@@ -0,0 +1,33 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick -+import org.kde.kirigami as Kirigami -+import org.kde.spectacle.private -+ -+TtToolButton { -+ // Can't rely on checked since clicking also toggles checked -+ readonly property bool showCancel: SpectacleCore.captureTimeRemaining > 0 -+ readonly property real cancelWidth: QmlUtils.getButtonSize(display, cancelText(Settings.captureDelay), icon.name).width -+ -+ function cancelText(seconds) { -+ return i18np("Cancel (%1 second)", "Cancel (%1 seconds)", Math.ceil(seconds)) -+ } -+ -+ checked: showCancel -+ width: if (showCancel) { -+ return cancelWidth -+ } else { -+ return display === TtToolButton.IconOnly ? height : implicitWidth -+ } -+ icon.name: showCancel ? "dialog-cancel" : "list-add" -+ text: showCancel ? -+ cancelText(SpectacleCore.captureTimeRemaining / 1000) -+ : i18n("New Screenshot") -+ onClicked: if (showCancel) { -+ SpectacleCore.cancelScreenshot() -+ } else { -+ SpectacleCore.takeNewScreenshot() -+ } -+} -diff --git a/src/Gui/OptionsMenu.cpp b/src/Gui/OptionsMenu.cpp -index e031f8f1..d9ac01da 100644 ---- a/src/Gui/OptionsMenu.cpp -+++ b/src/Gui/OptionsMenu.cpp -@@ -5,15 +5,21 @@ - #include "OptionsMenu.h" - - #include "CaptureModeModel.h" -+#include "Gui/SmartSpinBox.h" - #include "Gui/SettingsDialog/SettingsDialog.h" - #include "SpectacleCore.h" - #include "WidgetWindowUtils.h" -+#include "HelpMenu.h" - #include "settings.h" - - #include - #include - -+#include -+#include -+#include - #include -+#include - - using namespace Qt::StringLiterals; - -@@ -21,158 +27,129 @@ static QPointer s_instance = nullptr; - - OptionsMenu::OptionsMenu(QWidget *parent) - : SpectacleMenu(parent) -- , captureModeSection(new QAction(this)) -- , captureModeGroup(new QActionGroup(this)) // exclusive by default) -- , captureSettingsSection(new QAction(this)) -- , includeMousePointerAction(new QAction(this)) -- , includeWindowDecorationsAction(new QAction(this)) -- , includeWindowShadowAction(new QAction(this)) -- , onlyCapturePopupAction(new QAction(this)) -- , quitAfterSaveAction(new QAction(this)) -- , captureOnClickAction(new QAction(this)) -- , delayAction(new QWidgetAction(this)) -- , delayWidget(new QWidget(this)) -- , delayLayout(new QHBoxLayout(delayWidget.get())) -- , delayLabel(new QLabel(delayWidget.get())) -- , delaySpinBox(new SmartSpinBox(delayWidget.get())) -+ , m_delayAction(new QWidgetAction(this)) -+ , m_delayWidget(new QWidget(this)) -+ , m_delayLayout(new QHBoxLayout(m_delayWidget.get())) -+ , m_delayLabel(new QLabel(m_delayWidget.get())) -+ , m_delaySpinBox(new SmartSpinBox(m_delayWidget.get())) - { -- addAction(KStandardActions::preferences(this, &OptionsMenu::showPreferencesDialog, this)); -- -+ setToolTipsVisible(true); - // QMenu::addSection just adds an action with text and separator mode enabled -- captureModeSection->setText(i18n("Capture Mode")); -- captureModeSection->setSeparator(true); -- addAction(captureModeSection.get()); -+ addSection(i18nc("@title:menu", "Screenshot Settings")); - -- // Add capture mode actions. -- // This cannot be done in the constructor because captureModeModel will be null at this time. -- connect(this, &OptionsMenu::aboutToShow, -- this, &OptionsMenu::updateCaptureModes); -- -- // make capture mode actions do things -- connect(captureModeGroup.get(), &QActionGroup::triggered, this, [](QAction *action){ -- int mode = action->data().toInt(); -- Settings::setCaptureMode(mode); -- }); -- connect(Settings::self(), &Settings::captureModeChanged, this, [this](){ -- int mode = Settings::captureMode(); -- if (captureModeGroup->checkedAction() && mode == captureModeGroup->checkedAction()->data().toInt()) { -- return; -- } -- for (auto action : std::as_const(captureModeActions)) { -- if (mode == action->data().toInt()) { -- action->setChecked(true); -- } -- } -- }); -- -- captureSettingsSection->setText(i18n("Capture Settings")); -- captureSettingsSection->setSeparator(true); -- addAction(captureSettingsSection.get()); -- -- includeMousePointerAction->setText(i18n("Include mouse pointer")); -- includeMousePointerAction->setToolTip(i18n("Show the mouse cursor in the screenshot image")); -+ auto includeMousePointerAction = addAction(i18nc("@option:check for screenshots", "Include mouse pointer")); -+ includeMousePointerAction->setToolTip(i18nc("@info:tooltip", "Show the mouse cursor in the screenshot image")); - includeMousePointerAction->setCheckable(true); - includeMousePointerAction->setChecked(Settings::includePointer()); -- connect(includeMousePointerAction.get(), &QAction::toggled, this, [](bool checked){ -- Settings::setIncludePointer(checked); -- }); -- connect(Settings::self(), &Settings::includePointerChanged, this, [this](){ -+ QObject::connect(includeMousePointerAction, &QAction::toggled, Settings::self(), &Settings::setIncludePointer); -+ QObject::connect(Settings::self(), &Settings::includePointerChanged, includeMousePointerAction, [includeMousePointerAction](){ - includeMousePointerAction->setChecked(Settings::includePointer()); - }); -- addAction(includeMousePointerAction.get()); - -- includeWindowDecorationsAction->setText(i18n("Include window titlebar and borders")); -- includeWindowDecorationsAction->setToolTip(i18n("Show the window title bar, the minimize/maximize/close buttons, and the window border")); -+ auto includeWindowDecorationsAction = addAction(i18nc("@option:check", "Include window titlebar and borders")); -+ includeWindowDecorationsAction->setToolTip(i18nc("@info:tooltip", "Show the window title bar, the minimize/maximize/close buttons, and the window border")); - includeWindowDecorationsAction->setCheckable(true); - includeWindowDecorationsAction->setChecked(Settings::includeDecorations()); -- connect(includeWindowDecorationsAction.get(), &QAction::toggled, this, [](bool checked){ -- Settings::setIncludeDecorations(checked); -- }); -- connect(Settings::self(), &Settings::includeDecorationsChanged, this, [this](){ -+ QObject::connect(includeWindowDecorationsAction, &QAction::toggled, Settings::self(), Settings::setIncludeDecorations); -+ QObject::connect(Settings::self(), &Settings::includeDecorationsChanged, includeWindowDecorationsAction, [includeWindowDecorationsAction](){ - includeWindowDecorationsAction->setChecked(Settings::includeDecorations()); - }); -- addAction(includeWindowDecorationsAction.get()); - -- includeWindowShadowAction->setText(i18n("Include window shadow")); -- includeWindowShadowAction->setToolTip(i18n("Show the window shadow")); -+ auto includeWindowShadowAction = addAction(i18nc("@option:check", "Include window shadow")); -+ includeWindowShadowAction->setToolTip(i18nc("@info:tooltip", "Show the window shadow")); - includeWindowShadowAction->setCheckable(true); - includeWindowShadowAction->setChecked(Settings::includeShadow()); -- connect(includeWindowShadowAction.get(), &QAction::toggled, this, [](bool checked) { -- Settings::setIncludeShadow(checked); -- }); -- connect(Settings::self(), &Settings::includeShadowChanged, this, [this]() { -+ QObject::connect(includeWindowShadowAction, &QAction::toggled, Settings::self(), &Settings::setIncludeShadow); -+ QObject::connect(Settings::self(), &Settings::includeShadowChanged, includeWindowShadowAction, [includeWindowShadowAction]() { - includeWindowShadowAction->setChecked(Settings::includeShadow()); - }); -- addAction(includeWindowShadowAction.get()); - -- onlyCapturePopupAction->setText(i18n("Capture the current pop-up only")); -- onlyCapturePopupAction->setToolTip( -- i18n("Capture only the current pop-up window (like a menu, tooltip etc).\n" -- "If disabled, the pop-up is captured along with the parent window")); -- onlyCapturePopupAction->setCheckable(true); -- onlyCapturePopupAction->setChecked(Settings::transientOnly()); -- connect(onlyCapturePopupAction.get(), &QAction::toggled, this, [](bool checked){ -- Settings::setTransientOnly(checked); -- }); -- connect(Settings::self(), &Settings::transientOnlyChanged, this, [this](){ -+ const bool hasTransientWithParent = SpectacleCore::instance()->imagePlatform()->supportedGrabModes().testFlag(ImagePlatform::TransientWithParent); -+ if (hasTransientWithParent) { -+ auto onlyCapturePopupAction = addAction(i18nc("@option:check", "Capture the current pop-up only")); -+ onlyCapturePopupAction->setToolTip( -+ i18nc("@info:tooltip", "Capture only the current pop-up window (like a menu, tooltip etc).\n" -+ "If disabled, the pop-up is captured along with the parent window")); -+ onlyCapturePopupAction->setCheckable(true); - onlyCapturePopupAction->setChecked(Settings::transientOnly()); -- }); -- addAction(onlyCapturePopupAction.get()); -+ QObject::connect(onlyCapturePopupAction, &QAction::toggled, Settings::self(), &Settings::setTransientOnly); -+ QObject::connect(Settings::self(), &Settings::transientOnlyChanged, onlyCapturePopupAction, [onlyCapturePopupAction](){ -+ onlyCapturePopupAction->setChecked(Settings::transientOnly()); -+ }); -+ } - -- quitAfterSaveAction->setText(i18n("Quit after manual Save or Copy")); -- quitAfterSaveAction->setToolTip(i18n("Quit Spectacle after manually saving or copying the image")); -+ auto quitAfterSaveAction = addAction(i18nc("@option:check", "Quit after manual Save or Copy")); -+ quitAfterSaveAction->setToolTip(i18nc("@info:tooltip", "Quit Spectacle after manually saving or copying the image")); - quitAfterSaveAction->setCheckable(true); - quitAfterSaveAction->setChecked(Settings::quitAfterSaveCopyExport()); -- connect(quitAfterSaveAction.get(), &QAction::toggled, this, [](bool checked){ -- Settings::setQuitAfterSaveCopyExport(checked); -- }); -- connect(Settings::self(), &Settings::quitAfterSaveCopyExportChanged, this, [this](){ -+ QObject::connect(quitAfterSaveAction, &QAction::toggled, Settings::self(), &Settings::setQuitAfterSaveCopyExport); -+ QObject::connect(Settings::self(), &Settings::quitAfterSaveCopyExportChanged, quitAfterSaveAction, [quitAfterSaveAction](){ - quitAfterSaveAction->setChecked(Settings::quitAfterSaveCopyExport()); - }); -- addAction(quitAfterSaveAction.get()); - - // add capture on click - const bool hasOnClick = SpectacleCore::instance()->imagePlatform()->supportedShutterModes().testFlag(ImagePlatform::OnClick); -- addSeparator()->setVisible(hasOnClick); -- captureOnClickAction->setText(i18n("Capture On Click")); -- captureOnClickAction->setCheckable(true); -- captureOnClickAction->setChecked(Settings::captureOnClick() && hasOnClick); -- captureOnClickAction->setVisible(hasOnClick); -- connect(captureOnClickAction.get(), &QAction::toggled, this, [this](bool checked){ -- Settings::setCaptureOnClick(checked); -- delayAction->setEnabled(!checked); -- }); -- connect(Settings::self(), &Settings::captureOnClickChanged, this, [this](){ -+ if (hasOnClick) { -+ addSeparator(); -+ auto captureOnClickAction = addAction(i18nc("@option:check", "Capture On Click")); -+ captureOnClickAction->setCheckable(true); - captureOnClickAction->setChecked(Settings::captureOnClick()); -- }); -- addAction(captureOnClickAction.get()); -+ QObject::connect(captureOnClickAction, &QAction::toggled, this, [this](bool checked){ -+ Settings::setCaptureOnClick(checked); -+ m_delayAction->setEnabled(!checked); -+ }); -+ QObject::connect(Settings::self(), &Settings::captureOnClickChanged, captureOnClickAction, [captureOnClickAction](){ -+ captureOnClickAction->setChecked(Settings::captureOnClick()); -+ }); -+ } - - // set up delay widget -- auto spinbox = delaySpinBox.get(); -- auto label = delayLabel.get(); -- label->setText(i18n("Delay:")); -+ auto spinbox = m_delaySpinBox.get(); -+ auto label = m_delayLabel.get(); -+ label->setText(i18nc("@label:spinbox", "Delay:")); - spinbox->setDecimals(1); - spinbox->setSingleStep(1.0); - spinbox->setMinimum(0.0); - spinbox->setMaximum(999); -- spinbox->setSpecialValueText(i18n("No Delay")); -+ spinbox->setSpecialValueText(i18nc("@item 0 delay special value", "No Delay")); - delayActionLayoutUpdate(); -- connect(spinbox, qOverload(&SmartSpinBox::valueChanged), this, [this](){ -- if (updatingDelayActionLayout) { -+ QObject::connect(spinbox, qOverload(&SmartSpinBox::valueChanged), this, [this](){ -+ if (m_updatingDelayActionLayout) { - return; - } -- Settings::setCaptureDelay(delaySpinBox->value()); -+ Settings::setCaptureDelay(m_delaySpinBox->value()); -+ }); -+ QObject::connect(Settings::self(), &Settings::captureDelayChanged, spinbox, [this](){ -+ m_delaySpinBox->setValue(Settings::captureDelay()); - }); -- connect(Settings::self(), &Settings::captureDelayChanged, this, [this](){ -- delaySpinBox->setValue(Settings::captureDelay()); -+ m_delayWidget->setLayout(m_delayLayout.get()); -+ m_delayLayout->addWidget(label); -+ m_delayLayout->addWidget(spinbox); -+ m_delayLayout->setAlignment(Qt::AlignLeft); -+ m_delayAction->setDefaultWidget(m_delayWidget.get()); -+ m_delayAction->setEnabled(!hasOnClick || !Settings::captureOnClick()); -+ addAction(m_delayAction.get()); -+ -+ addSection(i18nc("@title:menu", "Recording Settings")); -+ -+ auto videoIncludeMousePointerAction = addAction(i18nc("@option:check for recordings", "Include mouse pointer")); -+ videoIncludeMousePointerAction->setToolTip(i18nc("@info:tooltip", "Show the mouse cursor in the recording")); -+ videoIncludeMousePointerAction->setCheckable(true); -+ videoIncludeMousePointerAction->setChecked(Settings::videoIncludePointer()); -+ QObject::connect(videoIncludeMousePointerAction, &QAction::toggled, Settings::self(), &Settings::setVideoIncludePointer); -+ QObject::connect(Settings::self(), &Settings::videoIncludePointerChanged, videoIncludeMousePointerAction, [videoIncludeMousePointerAction](){ -+ videoIncludeMousePointerAction->setChecked(Settings::videoIncludePointer()); - }); -- delayWidget->setLayout(delayLayout.get()); -- delayLayout->addWidget(label); -- delayLayout->addWidget(spinbox); -- delayLayout->setAlignment(Qt::AlignLeft); -- delayAction->setDefaultWidget(delayWidget.get()); -- delayAction->setEnabled(!captureOnClickAction->isChecked()); -- addAction(delayAction.get()); -+ -+ addSeparator(); -+ -+ addAction(KStandardActions::preferences(this, &OptionsMenu::showPreferencesDialog, this)); -+ -+ addMenu(HelpMenu::instance()); -+ connect(this, &OptionsMenu::aboutToShow, -+ this, [this] { -+ setWidgetTransientParentToWidget(HelpMenu::instance(), this); -+ }); - } - - OptionsMenu *OptionsMenu::instance() -@@ -201,9 +178,26 @@ void OptionsMenu::showPreferencesDialog() - dialog->show(); - } - --void OptionsMenu::setCaptureModeOptionsEnabled(bool enabled) -+void OptionsMenu::delayActionLayoutUpdate() - { -- captureModeOptionsEnabled = enabled; -+ // We can't block signals while doing this to prevent unnecessary -+ // processing because the spinbox has internal connections that need -+ // to work in order to get the correct size. -+ // We use our own guarding variable instead. -+ m_updatingDelayActionLayout = true; -+ m_delaySpinBox->setValue(m_delaySpinBox->maximum()); -+ m_delaySpinBox->setMinimumWidth(m_delaySpinBox->sizeHint().width()); -+ m_delaySpinBox->setValue(Settings::captureDelay()); -+ m_updatingDelayActionLayout = false; -+ -+ int menuHMargin = style()->pixelMetric(QStyle::PM_MenuHMargin); -+ int menuVMargin = style()->pixelMetric(QStyle::PM_MenuVMargin); -+ if (layoutDirection() == Qt::RightToLeft) { -+ m_delayLabel->setContentsMargins(0, 0, menuHMargin + m_delayLabel->fontMetrics().descent(), 0); -+ } else { -+ m_delayLabel->setContentsMargins(menuHMargin + m_delayLabel->fontMetrics().descent(), 0, 0, 0); -+ } -+ m_delayLayout->setContentsMargins(0, menuVMargin, 0, 0); - } - - void OptionsMenu::changeEvent(QEvent *event) -@@ -219,80 +213,30 @@ void OptionsMenu::changeEvent(QEvent *event) - QWidget::changeEvent(event); - } - --void OptionsMenu::delayActionLayoutUpdate() -+void OptionsMenu::keyPressEvent(QKeyEvent *event) - { -- // We can't block signals while doing this to prevent unnecessary -- // processing because the spinbox has internal connections that need -- // to work in order to get the correct size. -- // We use our own guarding variable instead. -- updatingDelayActionLayout = true; -- delaySpinBox->setValue(delaySpinBox->maximum()); -- delaySpinBox->setMinimumWidth(delaySpinBox->sizeHint().width()); -- delaySpinBox->setValue(Settings::captureDelay()); -- updatingDelayActionLayout = false; -- -- int menuHMargin = style()->pixelMetric(QStyle::PM_MenuHMargin); -- int menuVMargin = style()->pixelMetric(QStyle::PM_MenuVMargin); -- if (layoutDirection() == Qt::RightToLeft) { -- delayLabel->setContentsMargins(0, 0, menuHMargin + delayLabel->fontMetrics().descent(), 0); -- } else { -- delayLabel->setContentsMargins(menuHMargin + delayLabel->fontMetrics().descent(), 0, 0, 0); -+ // Try to keep menu open when triggering checkable actions -+ const auto key = event->key(); -+ const auto action = activeAction(); -+ if (action && action->isEnabled() && action->isCheckable() // -+ && (key == Qt::Key_Return || key == Qt::Key_Enter // -+ || (key == Qt::Key_Space && style()->styleHint(QStyle::SH_Menu_SpaceActivatesItem, nullptr, this)))) { -+ action->trigger(); -+ event->accept(); -+ return; - } -- delayLayout->setContentsMargins(0, menuVMargin, 0, 0); -+ SpectacleMenu::keyPressEvent(event); - } - --void OptionsMenu::updateCaptureModes() -+void OptionsMenu::mouseReleaseEvent(QMouseEvent *event) - { -- captureModeSection->setVisible(captureModeOptionsEnabled); -- if (!captureModeOptionsEnabled) { -- for (auto action : std::as_const(captureModeActions)) { -- captureModeGroup->removeAction(action); -- removeAction(action); -- action->deleteLater(); -- } -- captureModeActions.clear(); -- return; -- } -- -- if (!captureModeModel) { -- captureModeModel = std::make_unique(); -- } -- -- // Only make this conneciton once. -- // Can't be done in the constructor because captureModeModel is null at that time. -- if (!captureModesInitialized) { -- connect(captureModeModel.get(), &CaptureModeModel::captureModesChanged, this, [this]() { -- shouldUpdateCaptureModes = true; -- }); -- captureModesInitialized = true; -- } -- // avoid unnecessarily resetting actions -- if (!shouldUpdateCaptureModes) { -+ // Try to keep menu open when triggering checkable actions -+ const auto action = activeAction() == actionAt(event->position().toPoint()) ? activeAction() : nullptr; -+ if (action && action->isEnabled() && action->isCheckable()) { -+ action->trigger(); - return; - } -- shouldUpdateCaptureModes = false; -- for (auto action : std::as_const(captureModeActions)) { -- captureModeGroup->removeAction(action); -- removeAction(action); -- action->deleteLater(); -- } -- captureModeActions.clear(); -- for (int i = 0; i < captureModeModel->rowCount(); ++i) { -- auto index = captureModeModel->index(i); -- auto action = new QAction(this); -- captureModeActions.append(action); -- action->setText(captureModeModel->data(index, Qt::DisplayRole).toString()); -- const auto mode = captureModeModel->data(index, CaptureModeModel::CaptureModeRole).toInt(); -- action->setData(mode); -- action->setCheckable(true); -- if (!CaptureWindow::instances().empty() && !SpectacleCore::instance()->videoMode()) { -- action->setChecked(mode == CaptureModeModel::RectangularRegion); -- } else if (mode == Settings::captureMode()) { -- action->setChecked(true); -- } -- captureModeGroup->addAction(action); -- insertAction(captureSettingsSection.get(), action); -- } -+ SpectacleMenu::mouseReleaseEvent(event); - } - - #include "moc_OptionsMenu.cpp" -diff --git a/src/Gui/OptionsMenu.h b/src/Gui/OptionsMenu.h -index 5f87d097..b600f3f4 100644 ---- a/src/Gui/OptionsMenu.h -+++ b/src/Gui/OptionsMenu.h -@@ -6,20 +6,13 @@ - #define OPTIONSMENU_H - - #include "SpectacleMenu.h" -- - #include "Gui/SmartSpinBox.h" - --#include - #include - #include --#include - #include - #include - --#include -- --class CaptureModeModel; -- - /** - * A menu that allows choosing capture modes and related options. - */ -@@ -34,8 +27,6 @@ public: - - Q_SLOT void showPreferencesDialog(); - -- void setCaptureModeOptionsEnabled(bool enabled); -- - static OptionsMenu *create(QQmlEngine *engine, QJSEngine *) - { - auto inst = instance(); -@@ -47,37 +38,18 @@ public: - - protected: - void changeEvent(QEvent *event) override; -+ void keyPressEvent(QKeyEvent *event) override; -+ void mouseReleaseEvent(QMouseEvent *event) override; - --private: - explicit OptionsMenu(QWidget *parent = nullptr); - - void delayActionLayoutUpdate(); -- Q_SLOT void updateCaptureModes(); -- -- QList captureModeActions; -- const std::unique_ptr captureModeSection; -- const std::unique_ptr captureModeGroup; -- const std::unique_ptr captureSettingsSection; -- const std::unique_ptr includeMousePointerAction; -- const std::unique_ptr includeWindowDecorationsAction; -- const std::unique_ptr includeWindowShadowAction; -- const std::unique_ptr onlyCapturePopupAction; -- const std::unique_ptr quitAfterSaveAction; -- const std::unique_ptr captureOnClickAction; -- const std::unique_ptr delayAction; -- const std::unique_ptr delayWidget; -- const std::unique_ptr delayLayout; -- const std::unique_ptr delayLabel; -- const std::unique_ptr delaySpinBox; -- -- std::unique_ptr captureModeModel; -- -- bool captureModesInitialized = false; -- bool shouldUpdateCaptureModes = true; -- bool updatingDelayActionLayout = false; -- bool captureModeOptionsEnabled = true; -- -- friend class OptionsMenuSingleton; -+ const std::unique_ptr m_delayAction; -+ const std::unique_ptr m_delayWidget; -+ const std::unique_ptr m_delayLayout; -+ const std::unique_ptr m_delayLabel; -+ const std::unique_ptr m_delaySpinBox; -+ bool m_updatingDelayActionLayout = false; - }; - - #endif // OPTIONSMENU_H -diff --git a/src/Gui/OptionsMenuButton.qml b/src/Gui/OptionsMenuButton.qml -new file mode 100644 -index 00000000..5a86ff96 ---- /dev/null -+++ b/src/Gui/OptionsMenuButton.qml -@@ -0,0 +1,14 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick -+import org.kde.spectacle.private -+ -+TtToolButton { -+ icon.name: "configure" -+ text: i18nc("@action", "Options") -+ down: pressed || OptionsMenu.visible -+ Accessible.role: Accessible.ButtonMenu -+ onPressed: OptionsMenu.popup(this) -+} -diff --git a/src/Gui/Outline.qml b/src/Gui/Outline.qml -index 158e356f..85d9f6ca 100644 ---- a/src/Gui/Outline.qml -+++ b/src/Gui/Outline.qml -@@ -17,6 +17,7 @@ Shape { - property alias joinStyle: shapePath.joinStyle - property alias svgPath: pathSvg.path - property alias pathScale: shapePath.scale -+ property alias pathHints: shapePath.pathHints - - // Get a rectangular SVG path - function rectanglePath(x, y, w, h) { -diff --git a/src/Gui/RecordAction.qml b/src/Gui/RecordAction.qml -new file mode 100644 -index 00000000..7c7a83df ---- /dev/null -+++ b/src/Gui/RecordAction.qml -@@ -0,0 +1,13 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick.Templates as T -+import org.kde.spectacle.private -+ -+T.Action { -+ enabled: SpectacleCore.videoMode -+ icon.name: "media-record" -+ text: i18nc("@action start recording", "Record") -+ onTriggered: contextWindow.accept() -+} -diff --git a/src/Gui/RecordingModeButtonsColumn.qml b/src/Gui/RecordingModeButtonsColumn.qml -index 58644a97..2737f620 100644 ---- a/src/Gui/RecordingModeButtonsColumn.qml -+++ b/src/Gui/RecordingModeButtonsColumn.qml -@@ -12,7 +12,7 @@ import org.kde.spectacle.private - ColumnLayout { - spacing: Kirigami.Units.mediumSpacing - Repeater { -- model: RecordingModeModel { } -+ model: RecordingModeModel - delegate: QQC.Button { - id: button - Layout.fillWidth: true -diff --git a/src/Gui/RecordingModeMenu.cpp b/src/Gui/RecordingModeMenu.cpp -new file mode 100644 -index 00000000..d7451fa7 ---- /dev/null -+++ b/src/Gui/RecordingModeMenu.cpp -@@ -0,0 +1,65 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+#include "RecordingModeMenu.h" -+#include "RecordingModeModel.h" -+#include "SpectacleCore.h" -+#include "ShortcutActions.h" -+#include -+ -+using namespace Qt::StringLiterals; -+ -+static QPointer s_instance = nullptr; -+ -+RecordingModeMenu::RecordingModeMenu(QWidget *parent) -+ : SpectacleMenu(i18nc("@title:menu", "Recording Modes"), parent) -+{ -+ auto addModes = [this] { -+ clear(); -+ auto model = RecordingModeModel::instance(); -+ for (auto idx = model->index(0); idx.isValid(); idx = idx.siblingAtRow(idx.row() + 1)) { -+ const auto action = addAction(idx.data(Qt::DisplayRole).toString()); -+ const auto mode = idx.data(RecordingModeModel::RecordingModeRole).value(); -+ QAction *globalAction = nullptr; -+ auto globalShortcuts = [](QAction *globalAction) { -+ if (!globalAction) { -+ return QList{}; -+ } -+ auto component = ShortcutActions::self()->componentName(); -+ auto id = globalAction->objectName(); -+ return KGlobalAccel::self()->globalShortcut(component, id); -+ }; -+ switch (mode) { -+ case VideoPlatform::Region: -+ globalAction = ShortcutActions::self()->recordRegionAction(); -+ break; -+ case VideoPlatform::Screen: -+ globalAction = ShortcutActions::self()->recordScreenAction(); -+ break; -+ case VideoPlatform::Window: -+ globalAction = ShortcutActions::self()->recordWindowAction(); -+ break; -+ default: -+ break; -+ } -+ action->setShortcuts(globalShortcuts(globalAction)); -+ auto onTriggered = [mode] { -+ SpectacleCore::instance()->startRecording(mode); -+ }; -+ connect(action, &QAction::triggered, action, onTriggered); -+ } -+ }; -+ addModes(); -+ connect(RecordingModeModel::instance(), &RecordingModeModel::recordingModesChanged, this, addModes); -+} -+ -+RecordingModeMenu *RecordingModeMenu::instance() -+{ -+ if (!s_instance) { -+ s_instance = new RecordingModeMenu; -+ } -+ return s_instance; -+} -+ -+#include "moc_RecordingModeMenu.cpp" -diff --git a/src/Gui/RecordingModeMenu.h b/src/Gui/RecordingModeMenu.h -new file mode 100644 -index 00000000..fe8f0a71 ---- /dev/null -+++ b/src/Gui/RecordingModeMenu.h -@@ -0,0 +1,30 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+#pragma once -+ -+#include "SpectacleMenu.h" -+#include -+ -+class RecordingModeMenu : public SpectacleMenu -+{ -+ Q_OBJECT -+ QML_ELEMENT -+ QML_SINGLETON -+ -+public: -+ static RecordingModeMenu *instance(); -+ -+ static RecordingModeMenu *create(QQmlEngine *engine, QJSEngine *) -+ { -+ auto inst = instance(); -+ Q_ASSERT(inst); -+ Q_ASSERT(inst->thread() == engine->thread()); -+ QJSEngine::setObjectOwnership(inst, QJSEngine::CppOwnership); -+ return inst; -+ } -+ -+private: -+ explicit RecordingModeMenu(QWidget *parent = nullptr); -+}; -diff --git a/src/Gui/RecordingModeMenuButton.qml b/src/Gui/RecordingModeMenuButton.qml -new file mode 100644 -index 00000000..54d40666 ---- /dev/null -+++ b/src/Gui/RecordingModeMenuButton.qml -@@ -0,0 +1,15 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick -+import QtQuick.Controls as QQC -+import org.kde.spectacle.private -+ -+TtToolButton { -+ icon.name: "camera-video" -+ text: i18nc("@action select new recording mode", "New Recording") -+ down: pressed || RecordingModeMenu.visible -+ Accessible.role: Accessible.ButtonMenu -+ onPressed: RecordingModeMenu.popup(this) -+} -diff --git a/src/Gui/RecordingView.qml b/src/Gui/RecordingView.qml -index fc7b6040..a4e747ae 100644 ---- a/src/Gui/RecordingView.qml -+++ b/src/Gui/RecordingView.qml -@@ -87,13 +87,6 @@ FocusScope { - id: tbHoverHandler - } - -- component ToolButton: QQC.ToolButton { -- display: QQC.ToolButton.IconOnly -- QQC.ToolTip.text: text -- QQC.ToolTip.visible: (hovered || pressed) && display === QQC.ToolButton.IconOnly -- QQC.ToolTip.delay: Kirigami.Units.toolTipDelay -- } -- - FloatingToolBar { - id: toolBar - anchors.left: parent.left -@@ -105,7 +98,7 @@ FocusScope { - enabled: root.hasContent - contentItem: RowLayout { - spacing: parent.spacing -- ToolButton { -+ TtToolButton { - id: playPauseButton - containmentMask: Item { - parent: playPauseButton -diff --git a/src/Gui/SaveAction.qml b/src/Gui/SaveAction.qml -new file mode 100644 -index 00000000..084bda25 ---- /dev/null -+++ b/src/Gui/SaveAction.qml -@@ -0,0 +1,15 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick.Templates as T -+import org.kde.spectacle.private -+ -+T.Action { -+ // We don't use this in video mode because the video is already -+ // automatically saved and you can't edit the video. -+ enabled: !SpectacleCore.videoMode -+ icon.name: "document-save" -+ text: i18nc("@action", "Save") -+ onTriggered: contextWindow.save() -+} -diff --git a/src/Gui/SaveAsAction.qml b/src/Gui/SaveAsAction.qml -new file mode 100644 -index 00000000..371dfeca ---- /dev/null -+++ b/src/Gui/SaveAsAction.qml -@@ -0,0 +1,11 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick.Templates as T -+ -+T.Action { -+ icon.name: "document-save-as" -+ text: i18nc("@action", "Save As…") -+ onTriggered: contextWindow.saveAs() -+} -diff --git a/src/Gui/ScreenshotModeMenu.cpp b/src/Gui/ScreenshotModeMenu.cpp -new file mode 100644 -index 00000000..341ae7ec ---- /dev/null -+++ b/src/Gui/ScreenshotModeMenu.cpp -@@ -0,0 +1,74 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+#include "ScreenshotModeMenu.h" -+#include "CaptureModeModel.h" -+#include "SpectacleCore.h" -+#include "ShortcutActions.h" -+#include -+ -+using namespace Qt::StringLiterals; -+ -+static QPointer s_instance = nullptr; -+ -+ScreenshotModeMenu::ScreenshotModeMenu(QWidget *parent) -+ : SpectacleMenu(i18nc("@title:menu", "Screenshot Modes"), parent) -+{ -+ auto addModes = [this] { -+ clear(); -+ auto model = CaptureModeModel::instance(); -+ for (auto idx = model->index(0); idx.isValid(); idx = idx.siblingAtRow(idx.row() + 1)) { -+ const auto action = addAction(idx.data(Qt::DisplayRole).toString()); -+ const auto mode = idx.data(CaptureModeModel::CaptureModeRole).value(); -+ QAction *globalAction = nullptr; -+ auto globalShortcuts = [](QAction *globalAction) { -+ if (!globalAction) { -+ return QList{}; -+ } -+ auto component = ShortcutActions::self()->componentName(); -+ auto id = globalAction->objectName(); -+ return KGlobalAccel::self()->globalShortcut(component, id); -+ }; -+ switch (mode) { -+ case CaptureModeModel::RectangularRegion: -+ globalAction = ShortcutActions::self()->regionAction(); -+ break; -+ case CaptureModeModel::AllScreens: -+ globalAction = ShortcutActions::self()->fullScreenAction(); -+ break; -+ case CaptureModeModel::CurrentScreen: -+ globalAction = ShortcutActions::self()->currentScreenAction(); -+ break; -+ case CaptureModeModel::ActiveWindow: -+ globalAction = ShortcutActions::self()->activeWindowAction(); -+ break; -+ case CaptureModeModel::WindowUnderCursor: -+ globalAction = ShortcutActions::self()->windowUnderCursorAction(); -+ break; -+ case CaptureModeModel::FullScreen: -+ globalAction = ShortcutActions::self()->fullScreenAction(); -+ break; -+ default: -+ break; -+ } -+ action->setShortcuts(globalShortcuts(globalAction)); -+ auto onTriggered = [mode] { -+ SpectacleCore::instance()->takeNewScreenshot(mode); -+ }; -+ connect(action, &QAction::triggered, action, onTriggered); -+ } -+ }; -+ addModes(); -+ connect(CaptureModeModel::instance(), &CaptureModeModel::captureModesChanged, this, addModes); -+} -+ -+ScreenshotModeMenu *ScreenshotModeMenu::instance() -+{ -+ if (!s_instance) { -+ s_instance = new ScreenshotModeMenu; -+ } -+ return s_instance; -+} -+ -+#include "moc_ScreenshotModeMenu.cpp" -diff --git a/src/Gui/ScreenshotModeMenu.h b/src/Gui/ScreenshotModeMenu.h -new file mode 100644 -index 00000000..387a05db ---- /dev/null -+++ b/src/Gui/ScreenshotModeMenu.h -@@ -0,0 +1,30 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+#pragma once -+ -+#include "SpectacleMenu.h" -+#include -+ -+class ScreenshotModeMenu : public SpectacleMenu -+{ -+ Q_OBJECT -+ QML_ELEMENT -+ QML_SINGLETON -+ -+public: -+ static ScreenshotModeMenu *instance(); -+ -+ static ScreenshotModeMenu *create(QQmlEngine *engine, QJSEngine *) -+ { -+ auto inst = instance(); -+ Q_ASSERT(inst); -+ Q_ASSERT(inst->thread() == engine->thread()); -+ QJSEngine::setObjectOwnership(inst, QJSEngine::CppOwnership); -+ return inst; -+ } -+ -+private: -+ explicit ScreenshotModeMenu(QWidget *parent = nullptr); -+}; -diff --git a/src/Gui/ScreenshotModeMenuButton.qml b/src/Gui/ScreenshotModeMenuButton.qml -new file mode 100644 -index 00000000..5440f17d ---- /dev/null -+++ b/src/Gui/ScreenshotModeMenuButton.qml -@@ -0,0 +1,15 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick -+import QtQuick.Controls as QQC -+import org.kde.spectacle.private -+ -+TtToolButton { -+ icon.name: "camera-photo" -+ text: i18nc("@action select new screenshot mode", "New Screenshot") -+ down: pressed || ScreenshotModeMenu.visible -+ Accessible.role: Accessible.ButtonMenu -+ onPressed: ScreenshotModeMenu.popup(this) -+} -diff --git a/src/Gui/SettingsDialog/GeneralOptions.ui b/src/Gui/SettingsDialog/GeneralOptions.ui -index 474ae28d..b7d6ddb5 100644 ---- a/src/Gui/SettingsDialog/GeneralOptions.ui -+++ b/src/Gui/SettingsDialog/GeneralOptions.ui -@@ -20,6 +20,11 @@ - - - -+ -+ -+ Take rectangular screenshot -+ -+ - - - Take full screen screenshot -diff --git a/src/Gui/SettingsDialog/spectacle.kcfg b/src/Gui/SettingsDialog/spectacle.kcfg -index 3d916aee..f58f28fc 100644 ---- a/src/Gui/SettingsDialog/spectacle.kcfg -+++ b/src/Gui/SettingsDialog/spectacle.kcfg -@@ -15,11 +15,12 @@ - - - -+ - - - - -- TakeFullscreenScreenshot -+ TakeRectangularScreenshot - - - -diff --git a/src/Gui/TtToolButton.qml b/src/Gui/TtToolButton.qml -new file mode 100644 -index 00000000..31de1309 ---- /dev/null -+++ b/src/Gui/TtToolButton.qml -@@ -0,0 +1,16 @@ -+/* SPDX-FileCopyrightText: 2025 Noah Davis -+ * SPDX-License-Identifier: LGPL-2.0-or-later -+ */ -+ -+import QtQuick -+import QtQuick.Controls as QQC -+import org.kde.kirigami as Kirigami -+import org.kde.spectacle.private -+ -+QQC.ToolButton { -+ implicitHeight: QmlUtils.iconTextButtonHeight -+ width: display === QQC.ToolButton.IconOnly ? height : implicitWidth -+ QQC.ToolTip.text: text -+ QQC.ToolTip.visible: (hovered || pressed) && display === QQC.ToolButton.IconOnly -+ QQC.ToolTip.delay: Kirigami.Units.toolTipDelay -+} -diff --git a/src/Gui/UndoRedoGroup.qml b/src/Gui/UndoRedoGroup.qml -index 83fa44fa..19deb798 100644 ---- a/src/Gui/UndoRedoGroup.qml -+++ b/src/Gui/UndoRedoGroup.qml -@@ -22,7 +22,7 @@ Grid { - NumberAnimation { properties: "x,y"; duration: Kirigami.Units.longDuration; easing.type: Easing.OutCubic } - } - -- QQC.ToolButton { -+ TtToolButton { - id: undoButton - enabled: SpectacleCore.annotationDocument.undoStackDepth > 0 - height: root.buttonHeight -@@ -31,13 +31,10 @@ Grid { - text: i18n("Undo") - icon.name: "edit-undo" - autoRepeat: true -- QQC.ToolTip.text: text -- QQC.ToolTip.visible: hovered || pressed -- QQC.ToolTip.delay: Kirigami.Units.toolTipDelay - onClicked: SpectacleCore.annotationDocument.undo() - } - -- QQC.ToolButton { -+ TtToolButton { - enabled: SpectacleCore.annotationDocument.redoStackDepth > 0 - height: root.buttonHeight - focusPolicy: root.focusPolicy -@@ -45,9 +42,6 @@ Grid { - text: i18n("Redo") - icon.name: "edit-redo" - autoRepeat: true -- QQC.ToolTip.text: text -- QQC.ToolTip.visible: hovered || pressed -- QQC.ToolTip.delay: Kirigami.Units.toolTipDelay - onClicked: SpectacleCore.annotationDocument.redo() - } - -diff --git a/src/Gui/VideoCaptureOverlay.qml b/src/Gui/VideoCaptureOverlay.qml -deleted file mode 100644 -index 09ad4d61..00000000 ---- a/src/Gui/VideoCaptureOverlay.qml -+++ /dev/null -@@ -1,243 +0,0 @@ --/* SPDX-FileCopyrightText: 2023 Noah Davis -- * SPDX-License-Identifier: LGPL-2.0-or-later -- */ -- --import QtQuick --import QtQuick.Shapes --import QtQuick.Window --import QtQuick.Layouts --import QtQuick.Controls as QQC --import org.kde.kirigami as Kirigami --import org.kde.spectacle.private -- --MouseArea { -- id: root -- readonly property rect viewportRect: Geometry.mapFromPlatformRect(screenToFollow.geometry, -- screenToFollow.devicePixelRatio) -- focus: true -- acceptedButtons: Qt.LeftButton | Qt.RightButton -- hoverEnabled: true -- LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft -- LayoutMirroring.childrenInherit: true -- anchors.fill: parent -- enabled: !SpectacleCore.videoPlatform.isRecording -- -- component Overlay: Rectangle { -- color: Settings.useLightMaskColor ? "white" : "black" -- opacity: if (SpectacleCore.videoPlatform.isRecording) { -- return 0 -- } else if (SelectionEditor.selection.empty) { -- return 0.25 -- } else { -- return 0.5 -- } -- LayoutMirroring.enabled: false -- Behavior on opacity { -- NumberAnimation { -- duration: Kirigami.Units.longDuration -- easing.type: Easing.OutCubic -- } -- } -- } -- Overlay { // top / full overlay when nothing selected -- id: topOverlay -- anchors.top: parent.top -- anchors.left: parent.left -- anchors.right: parent.right -- anchors.bottom: selectionRectangle.visible ? selectionRectangle.top : parent.bottom -- } -- Overlay { // bottom -- id: bottomOverlay -- anchors.left: parent.left -- anchors.top: selectionRectangle.visible ? selectionRectangle.bottom : undefined -- anchors.right: parent.right -- anchors.bottom: parent.bottom -- visible: selectionRectangle.visible && height > 0 -- } -- Overlay { // left -- anchors { -- left: topOverlay.left -- top: topOverlay.bottom -- right: selectionRectangle.visible ? selectionRectangle.left : undefined -- bottom: bottomOverlay.top -- } -- visible: selectionRectangle.visible && height > 0 && width > 0 -- } -- Overlay { // right -- anchors { -- left: selectionRectangle.visible ? selectionRectangle.right : undefined -- top: topOverlay.bottom -- right: topOverlay.right -- bottom: bottomOverlay.top -- } -- visible: selectionRectangle.visible && height > 0 && width > 0 -- } -- -- DashedOutline { -- id: selectionRectangle -- readonly property real margin: strokeWidth + 1 / Screen.devicePixelRatio -- dashSvgPath: SpectacleCore.videoPlatform.isRecording ? svgPath : "" -- visible: !SelectionEditor.selection.empty -- && Geometry.rectIntersects(Qt.rect(x,y,width,height), Qt.rect(0,0,parent.width, parent.height)) -- strokeWidth: dprRound(1) -- strokeColor: palette.active.highlight -- dashColor: SpectacleCore.videoPlatform.isRecording ? palette.active.base : strokeColor -- // We need to be a bit careful about staying out of the recorded area -- x: dprFloor(SelectionEditor.selection.x - margin - root.viewportRect.x) -- y: dprFloor(SelectionEditor.selection.y - margin - root.viewportRect.y) -- width: dprCeil(SelectionEditor.selection.right + margin - root.viewportRect.x) - x -- height: dprCeil(SelectionEditor.selection.bottom + margin - root.viewportRect.y) - y -- } -- -- Item { -- x: -root.viewportRect.x -- y: -root.viewportRect.y -- enabled: selectionRectangle.enabled -- visible: !SpectacleCore.videoPlatform.isRecording -- -- component SelectionHandle: Handle { -- id: handle -- visible: enabled && selectionRectangle.visible -- && SelectionEditor.dragLocation === SelectionEditor.None -- && Geometry.rectIntersects(Qt.rect(x,y,width,height), root.viewportRect) -- fillColor: selectionRectangle.strokeColor -- width: Kirigami.Units.gridUnit -- height: width -- transform: Translate { -- x: handle.xOffsetForEdges(selectionRectangle.strokeWidth) -- y: handle.yOffsetForEdges(selectionRectangle.strokeWidth) -- } -- } -- -- SelectionHandle { -- edges: Qt.TopEdge | Qt.LeftEdge -- x: dprFloor(SelectionEditor.handlesRect.x) -- y: dprFloor(SelectionEditor.handlesRect.y) -- } -- SelectionHandle { -- edges: Qt.LeftEdge -- x: dprFloor(SelectionEditor.handlesRect.x) -- y: dprRound(SelectionEditor.handlesRect.y + SelectionEditor.handlesRect.height/2 - height/2) -- } -- SelectionHandle { -- edges: Qt.LeftEdge | Qt.BottomEdge -- x: dprFloor(SelectionEditor.handlesRect.x) -- y: dprCeil(SelectionEditor.handlesRect.y + SelectionEditor.handlesRect.height - height) -- } -- SelectionHandle { -- edges: Qt.TopEdge -- x: dprRound(SelectionEditor.handlesRect.x + SelectionEditor.handlesRect.width/2 - width/2) -- y: dprFloor(SelectionEditor.handlesRect.y) -- } -- SelectionHandle { -- edges: Qt.BottomEdge -- x: dprRound(SelectionEditor.handlesRect.x + SelectionEditor.handlesRect.width/2 - width/2) -- y: dprCeil(SelectionEditor.handlesRect.y + SelectionEditor.handlesRect.height - height) -- } -- SelectionHandle { -- edges: Qt.RightEdge -- x: dprCeil(SelectionEditor.handlesRect.x + SelectionEditor.handlesRect.width - width) -- y: dprRound(SelectionEditor.handlesRect.y + SelectionEditor.handlesRect.height/2 - height/2) -- } -- SelectionHandle { -- edges: Qt.TopEdge | Qt.RightEdge -- x: dprCeil(SelectionEditor.handlesRect.x + SelectionEditor.handlesRect.width - width) -- y: dprFloor(SelectionEditor.handlesRect.y) -- } -- SelectionHandle { -- edges: Qt.RightEdge | Qt.BottomEdge -- x: dprCeil(SelectionEditor.handlesRect.x + SelectionEditor.handlesRect.width - width) -- y: dprCeil(SelectionEditor.handlesRect.y + SelectionEditor.handlesRect.height - height) -- } -- } -- -- Item { // separate item because it needs to be above the stuff defined above -- visible: !SpectacleCore.videoPlatform.isRecording -- width: SelectionEditor.screensRect.width -- height: SelectionEditor.screensRect.height -- x: -root.viewportRect.x -- y: -root.viewportRect.y -- -- // Size ToolTip -- SizeLabel { -- id: ssToolTip -- readonly property int valignment: { -- if (SelectionEditor.selection.empty) { -- return Qt.AlignVCenter -- } -- const margin = Kirigami.Units.mediumSpacing * 2 -- const w = width + margin -- const h = height + margin -- if (SelectionEditor.handlesRect.top >= h) { -- return Qt.AlignTop -- } else if (SelectionEditor.screensRect.height - SelectionEditor.handlesRect.bottom >= h) { -- return Qt.AlignBottom -- } else { -- // At the bottom of the inside of the selection rect. -- return Qt.AlignBaseline -- } -- } -- readonly property bool normallyVisible: !SelectionEditor.selection.empty -- Binding on x { -- value: contextWindow.dprRound(SelectionEditor.selection.horizontalCenter - ssToolTip.width / 2) -- when: ssToolTip.normallyVisible -- restoreMode: Binding.RestoreNone -- } -- Binding on y { -- value: { -- let v = 0 -- if (ssToolTip.valignment & Qt.AlignBaseline) { -- v = Math.min(SelectionEditor.selection.bottom, SelectionEditor.handlesRect.bottom - Kirigami.Units.gridUnit) -- - ssToolTip.height - Kirigami.Units.mediumSpacing * 2 -- } else if (ssToolTip.valignment & Qt.AlignTop) { -- v = SelectionEditor.handlesRect.top -- - ssToolTip.height - Kirigami.Units.mediumSpacing * 2 -- } else if (ssToolTip.valignment & Qt.AlignBottom) { -- v = SelectionEditor.handlesRect.bottom + Kirigami.Units.mediumSpacing * 2 -- } else { -- v = (root.height - ssToolTip.height) / 2 - parent.y -- } -- return contextWindow.dprRound(v) -- } -- when: ssToolTip.normallyVisible -- restoreMode: Binding.RestoreNone -- } -- visible: opacity > 0 -- opacity: ssToolTip.normallyVisible -- && Geometry.rectIntersects(Qt.rect(x,y,width,height), root.viewportRect) -- Behavior on opacity { -- NumberAnimation { -- duration: Kirigami.Units.longDuration -- easing.type: Easing.OutCubic -- } -- } -- size: Geometry.rawSize(SelectionEditor.selection.size, SelectionEditor.devicePixelRatio) // TODO: real pixel size on wayland -- padding: Kirigami.Units.mediumSpacing * 2 -- topPadding: padding - QmlUtils.fontMetrics.descent -- bottomPadding: topPadding -- background: FloatingBackground { -- implicitWidth: Math.ceil(parent.contentWidth) + parent.leftPadding + parent.rightPadding -- implicitHeight: Math.ceil(parent.contentHeight) + parent.topPadding + parent.bottomPadding -- color: Qt.rgba(parent.palette.window.r, -- parent.palette.window.g, -- parent.palette.window.b, 0.85) -- border.color: Qt.rgba(parent.palette.windowText.r, -- parent.palette.windowText.g, -- parent.palette.windowText.b, 0.2) -- border.width: contextWindow.dprRound(1) -- } -- } -- } -- -- Connections { -- target: contextWindow -- function onVisibilityChanged(visibility) { -- if (visibility !== Window.Hidden && visibility !== Window.Minimized) { -- contextWindow.raise() -- if (root.containsMouse) { -- contextWindow.requestActivate() -- } -- } -- } -- } --} -diff --git a/src/Platforms/ImagePlatform.h b/src/Platforms/ImagePlatform.h -index 7e51db95..de766f52 100644 ---- a/src/Platforms/ImagePlatform.h -+++ b/src/Platforms/ImagePlatform.h -@@ -57,6 +57,7 @@ Q_SIGNALS: - void newCroppableScreenshotTaken(const QImage &image); - - void newScreenshotFailed(const QString &message = {}); -+ void newScreenshotCanceled(); - }; - - Q_DECLARE_OPERATORS_FOR_FLAGS(ImagePlatform::GrabModes) -diff --git a/src/Platforms/ImagePlatformKWin.cpp b/src/Platforms/ImagePlatformKWin.cpp -index 237130c9..67fc7375 100644 ---- a/src/Platforms/ImagePlatformKWin.cpp -+++ b/src/Platforms/ImagePlatformKWin.cpp -@@ -468,6 +468,8 @@ void ImagePlatformKWin::trackSource(ScreenShotSource2 *source) - Q_EMIT newScreenshotTaken(std::get(result)); - } else if (index == ResultVariant::ErrorString) { - Q_EMIT newScreenshotFailed(std::get(result)); -+ } else if (index == ResultVariant::CanceledState) { -+ Q_EMIT newScreenshotCanceled(); - } - }); - } -diff --git a/src/RecordingModeModel.cpp b/src/RecordingModeModel.cpp -index 4388daa8..220dcd7e 100644 ---- a/src/RecordingModeModel.cpp -+++ b/src/RecordingModeModel.cpp -@@ -18,6 +18,16 @@ - - using namespace Qt::StringLiterals; - -+static std::unique_ptr s_instance; -+ -+RecordingModeModel *RecordingModeModel::instance() -+{ -+ if (!s_instance) { -+ s_instance = std::make_unique(); -+ } -+ return s_instance.get(); -+} -+ - RecordingModeModel::RecordingModeModel(QObject *parent) - : QAbstractListModel(parent) - { -@@ -71,6 +81,7 @@ int RecordingModeModel::indexOfRecordingMode(VideoPlatform::RecordingMode mode) - - void RecordingModeModel::setRecordingModes(VideoPlatform::RecordingModes modes) - { -+ auto count = m_data.size(); - m_data.clear(); - if (modes & VideoPlatform::Region) { - m_data.append({VideoPlatform::Region, recordingModeLabel(VideoPlatform::Region)}); -@@ -81,7 +92,10 @@ void RecordingModeModel::setRecordingModes(VideoPlatform::RecordingModes modes) - if (modes & VideoPlatform::Window) { - m_data.append({VideoPlatform::Window, recordingModeLabel(VideoPlatform::Window)}); - } -- Q_EMIT countChanged(); -+ Q_EMIT recordingModesChanged(); -+ if (count != m_data.size()) { -+ Q_EMIT countChanged(); -+ } - } - - QString RecordingModeModel::recordingModeLabel(VideoPlatform::RecordingMode mode) -diff --git a/src/RecordingModeModel.h b/src/RecordingModeModel.h -index 383f98f4..e56492ae 100644 ---- a/src/RecordingModeModel.h -+++ b/src/RecordingModeModel.h -@@ -7,15 +7,28 @@ - #include "Platforms/VideoPlatform.h" - - #include -+#include - - class RecordingModeModel : public QAbstractListModel - { - Q_OBJECT - QML_ELEMENT -+ QML_SINGLETON - Q_PROPERTY(int count READ rowCount NOTIFY countChanged FINAL) - public: - explicit RecordingModeModel(QObject *parent = nullptr); - -+ static RecordingModeModel *instance(); -+ -+ static RecordingModeModel *create(QQmlEngine *engine, QJSEngine *) -+ { -+ auto inst = instance(); -+ Q_ASSERT(inst); -+ Q_ASSERT(inst->thread() == engine->thread()); -+ QJSEngine::setObjectOwnership(inst, QJSEngine::CppOwnership); -+ return inst; -+ } -+ - enum { - RecordingModeRole = Qt::UserRole + 1, - }; -@@ -32,6 +45,7 @@ public: - - Q_SIGNALS: - void countChanged(); -+ void recordingModesChanged(); - - private: - struct Item { -diff --git a/src/SpectacleCore.cpp b/src/SpectacleCore.cpp -index bfbb3085..820852df 100644 ---- a/src/SpectacleCore.cpp -+++ b/src/SpectacleCore.cpp -@@ -128,6 +128,7 @@ SpectacleCore::SpectacleCore(QObject *parent) - connect(SelectionEditor::instance(), &SelectionEditor::accepted, - this, [this](const QRectF &rect, const ExportManager::Actions &actions){ - ExportManager::instance()->updateTimestamp(); -+ m_returnToViewer = m_startMode == StartMode::Gui; - if (m_videoMode) { - const auto captureWindows = CaptureWindow::instances(); - SpectacleWindow::setVisibilityForAll(QWindow::Hidden); -@@ -160,10 +161,14 @@ SpectacleCore::SpectacleCore(QObject *parent) - deleteWindows(); - m_annotationDocument->cropCanvas(rect); - syncExportImage(); -+ const auto &exportActions = actions & ExportManager::AnyAction ? actions : autoExportActions(); -+ const bool willQuit = exportActions.testFlag(ExportManager::AnyAction) // -+ && exportActions.testFlag(ExportManager::UserAction) // -+ && Settings::quitAfterSaveCopyExport(); -+ m_returnToViewer &= !willQuit; - showViewerIfGuiMode(); - SpectacleWindow::setTitleForAll(SpectacleWindow::Unsaved); - ExportManager::instance()->scanQRCode(); -- const auto &exportActions = actions & ExportManager::AnyAction ? actions : autoExportActions(); - ExportManager::instance()->exportImage(exportActions, outputUrl()); - } - }); -@@ -173,6 +178,7 @@ SpectacleCore::SpectacleCore(QObject *parent) - m_annotationDocument->setBaseImage(image); - setExportImage(image); - ExportManager::instance()->updateTimestamp(); -+ m_returnToViewer = true; - showViewerIfGuiMode(); - SpectacleWindow::setTitleForAll(SpectacleWindow::Unsaved); - ExportManager::instance()->scanQRCode(); -@@ -237,6 +243,21 @@ SpectacleCore::SpectacleCore(QObject *parent) - auto uiMessage = i18nc("@info", "An error occurred while taking a screenshot."); - onScreenshotOrRecordingFailed(message, uiMessage, &SpectacleCore::dbusScreenshotFailed, &ViewerWindow::showScreenshotFailedMessage); - }); -+ connect(imagePlatform, &ImagePlatform::newScreenshotCanceled, this, [this]() { -+ if (m_startMode != StartMode::Gui || !m_returnToViewer || isGuiNull()) { -+ Q_EMIT allDone(); -+ return; -+ } -+ SpectacleWindow::setTitleForAll(SpectacleWindow::Previous); -+ const auto windows = SpectacleWindow::instances(); -+ if (windows.empty()) { -+ initViewerWindow(ViewerWindow::Image); -+ return; -+ } -+ for (auto w : windows) { -+ w->setVisible(true); -+ } -+ }); - - auto videoPlatform = m_videoPlatform.get(); - connect(videoPlatform, &VideoPlatform::recordingChanged, this, [this](bool isRecording) { -@@ -314,11 +335,19 @@ SpectacleCore::SpectacleCore(QObject *parent) - ExportManager::instance()->exportVideo(autoExportActions() | ExportManager::Save, fileUrl, videoOutputUrl()); - }); - connect(videoPlatform, &VideoPlatform::recordingCanceled, this, [this] { -- if (m_startMode != StartMode::Gui || isGuiNull()) { -+ if (m_startMode != StartMode::Gui || !m_returnToViewer || isGuiNull()) { - Q_EMIT allDone(); - return; - } - SpectacleWindow::setTitleForAll(SpectacleWindow::Previous); -+ const auto windows = SpectacleWindow::instances(); -+ if (windows.empty()) { -+ initViewerWindow(ViewerWindow::Image); -+ return; -+ } -+ for (auto w : windows) { -+ w->setVisible(true); -+ } - }); - connect(videoPlatform, &VideoPlatform::recordingFailed, this, [onScreenshotOrRecordingFailed](const QString &message){ - auto uiMessage = i18nc("@info", "An error occurred while attempting to record the screen."); -@@ -578,7 +607,7 @@ void SpectacleCore::activate(const QStringList &arguments, const QString &workin - } - } - -- if (parser.optionNames().size() > 0 || m_startMode != StartMode::Gui) { -+ if (parser.optionNames().size() > 0 || m_startMode != StartMode::Gui || !m_returnToViewer) { - // Delete windows if we have CLI options or not in GUI mode. - // We don't want to delete them otherwise because that will mess with the - // settings for PrintScreen key behavior. -@@ -672,20 +701,33 @@ void SpectacleCore::activate(const QStringList &arguments, const QString &workin - // Determine grab mode - using CaptureMode = CaptureModeModel::CaptureMode; - using GrabMode = ImagePlatform::GrabMode; -- GrabMode grabMode = GrabMode::AllScreens; // Default to all screens -- if (m_cliOptions[Option::Fullscreen]) { -- grabMode = GrabMode::AllScreens; -- } else if (m_cliOptions[Option::Current]) { -- grabMode = GrabMode::CurrentScreen; -- } else if (m_cliOptions[Option::ActiveWindow]) { -- grabMode = GrabMode::ActiveWindow; -- } else if (m_cliOptions[Option::Region]) { -- grabMode = GrabMode::PerScreenImageNative; -- } else if (m_cliOptions[Option::WindowUnderCursor]) { -- grabMode = GrabMode::WindowUnderCursor; -- } else if (Settings::launchAction() == Settings::UseLastUsedCapturemode) { -- grabMode = toGrabMode(CaptureMode(Settings::captureMode()), transientOnly); -- } -+ auto cliGrabMode = [&]() -> std::optional { -+ if (m_cliOptions[Option::Fullscreen]) { -+ return GrabMode::AllScreens; -+ } else if (m_cliOptions[Option::Current]) { -+ return GrabMode::CurrentScreen; -+ } else if (m_cliOptions[Option::ActiveWindow]) { -+ return GrabMode::ActiveWindow; -+ } else if (m_cliOptions[Option::Region]) { -+ return GrabMode::PerScreenImageNative; -+ } else if (m_cliOptions[Option::WindowUnderCursor]) { -+ return GrabMode::WindowUnderCursor; -+ } -+ return std::nullopt; -+ }; -+ auto launchActionGrabMode = [&] { -+ switch (Settings::launchAction()) { -+ case Settings::TakeRectangularScreenshot: -+ return GrabMode::PerScreenImageNative; -+ case Settings::TakeFullscreenScreenshot: -+ return GrabMode::AllScreens; -+ case Settings::UseLastUsedCapturemode: -+ return toGrabMode(CaptureMode(Settings::captureMode()), transientOnly); -+ default: -+ return GrabMode::NoGrabModes; -+ } -+ }; -+ auto grabMode = cliGrabMode().value_or(m_startMode == StartMode::Background ? GrabMode::AllScreens : launchActionGrabMode()); - - using RecordingMode = VideoPlatform::RecordingMode; - RecordingMode recordingMode = RecordingMode::NoRecordingModes; -@@ -855,7 +897,7 @@ void SpectacleCore::takeNewScreenshot(int captureMode, int timeout, bool include - - void SpectacleCore::cancelScreenshot() - { -- if (m_startMode != StartMode::Gui) { -+ if (m_startMode != StartMode::Gui || !m_returnToViewer) { - Q_EMIT allDone(); - return; - } -@@ -883,7 +925,7 @@ void SpectacleCore::showErrorMessage(const QString &message) - - void SpectacleCore::showViewerIfGuiMode(bool minimized) - { -- if (m_startMode != StartMode::Gui) { -+ if (m_startMode != StartMode::Gui || !m_returnToViewer) { - return; - } - initViewerWindow(ViewerWindow::Image); -@@ -1140,6 +1182,7 @@ void SpectacleCore::initViewerWindow(ViewerWindow::Mode mode) - { - // always switch to gui mode when a viewer window is used. - m_startMode = SpectacleCore::StartMode::Gui; -+ m_returnToViewer = true; - deleteWindows(); - - // Transparency isn't needed for this window. -@@ -1168,6 +1211,12 @@ void SpectacleCore::startRecording(VideoPlatform::RecordingMode mode, bool withP - if (m_videoPlatform->isRecording() || mode == VideoPlatform::NoRecordingModes) { - return; - } -+ if (!CaptureWindow::instances().empty()) { -+ SpectacleWindow::setVisibilityForAll(QWindow::Hidden); -+ if (mode != VideoPlatform::Region) { -+ m_returnToViewer = true; -+ } -+ } - m_lastRecordingMode = mode; - setVideoMode(true); - const auto &output = m_outputUrl.isLocalFile() ? videoOutputUrl() : QUrl(); -@@ -1191,6 +1240,10 @@ void SpectacleCore::setVideoMode(bool videoMode) - return; - } - m_videoMode = videoMode; -+ if (!videoMode && m_annotationDocument->baseImage().isNull()) { -+ // Change this if there ends up being a way to toggle video mode outside of rectangle capture mode. -+ takeNewScreenshot(ImagePlatform::PerScreenImageNative, 0, Settings::includePointer(), Settings::includeDecorations(), Settings::includeShadow()); -+ } - Q_EMIT videoModeChanged(videoMode); - } - -diff --git a/src/SpectacleCore.h b/src/SpectacleCore.h -index 246e8944..23d65ead 100644 ---- a/src/SpectacleCore.h -+++ b/src/SpectacleCore.h -@@ -37,7 +37,7 @@ class SpectacleCore : public QObject - Q_PROPERTY(int captureTimeRemaining READ captureTimeRemaining NOTIFY captureTimeRemainingChanged FINAL) - Q_PROPERTY(qreal captureProgress READ captureProgress NOTIFY captureProgressChanged FINAL) - Q_PROPERTY(QString recordedTime READ recordedTime NOTIFY recordedTimeChanged) -- Q_PROPERTY(bool videoMode READ videoMode NOTIFY videoModeChanged) -+ Q_PROPERTY(bool videoMode READ videoMode WRITE setVideoMode NOTIFY videoModeChanged) - Q_PROPERTY(QUrl currentVideo READ currentVideo NOTIFY currentVideoChanged) - Q_PROPERTY(AnnotationDocument *annotationDocument READ annotationDocument CONSTANT FINAL) - -@@ -67,15 +67,21 @@ public: - int captureTimeRemaining() const; - qreal captureProgress() const; - -+ QString recordedTime() const; -+ -+ bool videoMode() const; -+ void setVideoMode(bool enabled); -+ -+ QUrl currentVideo() const; -+ -+ - void initGuiNoScreenshot(); - - void syncExportImage(); - - Q_INVOKABLE void startRecording(VideoPlatform::RecordingMode mode, bool withPointer = Settings::videoIncludePointer()); - Q_INVOKABLE void finishRecording(); -- bool videoMode() const; -- QUrl currentVideo() const; -- QString recordedTime() const; -+ - Q_INVOKABLE QString timeFromMilliseconds(qint64 milliseconds) const; - - ExportManager::Actions autoExportActions() const; -@@ -140,13 +146,13 @@ private: - void initViewerWindow(ViewerWindow::Mode mode); - void deleteWindows(); - void unityLauncherUpdate(const QVariantMap &properties) const; -- void setVideoMode(bool enabled); - void setCurrentVideo(const QUrl ¤tVideo); - QUrl videoOutputUrl() const; - - static SpectacleCore *s_self; - std::unique_ptr m_annotationDocument = nullptr; - StartMode m_startMode = StartMode::Gui; -+ bool m_returnToViewer = false; - QUrl m_screenCaptureUrl; - std::unique_ptr m_imagePlatform; - std::unique_ptr m_videoPlatform; From fd0f27145aecf1db4ccc132de216d3b694441b2c Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 4 Jul 2025 18:01:12 +0200 Subject: [PATCH 0999/1125] Flake: update lock file --- flake.lock | 96 +++++++++++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/flake.lock b/flake.lock index d35435b..5ba81fe 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1747575206, - "narHash": "sha256-NwmAFuDUO/PFcgaGGr4j3ozG9Pe5hZ/ogitWhY+D81k=", + "lastModified": 1750173260, + "narHash": "sha256-9P1FziAwl5+3edkfFcr5HeGtQUtrSdk/MksX39GieoA=", "owner": "ryantm", "repo": "agenix", - "rev": "4835b1dc898959d8547a871ef484930675cb47f1", + "rev": "531beac616433bac6f9e2a19feb8e99a22a66baf", "type": "github" }, "original": { @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1748080874, - "narHash": "sha256-sUebEzAkrY8Aq5G0GHFyRddmRNGP/a2iTtV7ISNvi/c=", + "lastModified": 1751620524, + "narHash": "sha256-zuIiAbZJPaUPzo7nAvN6VpC44rNYju5vNPROvYaEBy4=", "owner": "catppuccin", "repo": "nix", - "rev": "0ba11b12be81f0849a89ed17ab635164ea8f0112", + "rev": "194881dd2ad6303bc2d49f9ce484d127372d7465", "type": "github" }, "original": { @@ -167,11 +167,11 @@ ] }, "locked": { - "lastModified": 1748955489, - "narHash": "sha256-OmZXyW2g5qIuo5Te74McwR0TwauCO2sF3/SjGDVuxyg=", + "lastModified": 1751589297, + "narHash": "sha256-3q35cq6BPuwIRL3IoVKYPc72r3OleeuRyf4YAPjEqzA=", "owner": "nix-community", "repo": "home-manager", - "rev": "bb846c031be68a96466b683be32704ef6e07b159", + "rev": "83f978812c37511ef2ffaf75ffa72160483f738a", "type": "github" }, "original": { @@ -187,11 +187,11 @@ ] }, "locked": { - "lastModified": 1748665073, - "narHash": "sha256-RMhjnPKWtCoIIHiuR9QKD7xfsKb3agxzMfJY8V9MOew=", + "lastModified": 1751468302, + "narHash": "sha256-tWosziZTT039x6PgEZUhzGlV8oLvdDmIgKTE8ESMaEA=", "owner": "nix-community", "repo": "home-manager", - "rev": "282e1e029cb6ab4811114fc85110613d72771dea", + "rev": "501cfec8277f931a9c9af9f23d3105c537faeafe", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1748683484, - "narHash": "sha256-RXiY6t9E9oLEtfdGChHk/OIPqxYg1tu8XLvbPnJlfi4=", + "lastModified": 1751529406, + "narHash": "sha256-jwKDHyUycp678zDYa5Hyfq3msO73YMXdZPxp96dU7po=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "6f6bd4a27fb01c9dd623a157d769f34561407f47", + "rev": "b2e5ce654e4f5bf8905c2e07a96dcf4966e6277d", "type": "github" }, "original": { @@ -225,11 +225,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1748893954, - "narHash": "sha256-Vj1GHarIzlJI3We5KnYcAQlSjn++fx7/lKRaiIVz3tg=", - "rev": "019b17f4e93c098f99a9bc691be1f1c4df026c7d", + "lastModified": 1751575060, + "narHash": "sha256-nDlS4deJqTbLAulAr8bwE5lt/AVnBhVMrFlYZr78ToY=", + "rev": "897f87e76ac051b50b8438d2355463b95f6cd805", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/019b17f4e93c098f99a9bc691be1f1c4df026c7d.tar.gz?rev=019b17f4e93c098f99a9bc691be1f1c4df026c7d" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/897f87e76ac051b50b8438d2355463b95f6cd805.tar.gz?rev=897f87e76ac051b50b8438d2355463b95f6cd805" }, "original": { "type": "tarball", @@ -248,11 +248,11 @@ ] }, "locked": { - "lastModified": 1747667424, - "narHash": "sha256-7EICjbmG6lApWKhFtwvZovdcdORY1CEe6/K7JwtpYfs=", - "rev": "3c23c6ae2aecc1f76ae7993efe1a78b5316f0700", + "lastModified": 1751240140, + "narHash": "sha256-gbFOUtmkzzNAiHoUtySwbi+AVDgWOW8CpWmTmkoaQiI=", + "rev": "ea74d925e650948d296fb85e4671fb0ce944f550", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/3c23c6ae2aecc1f76ae7993efe1a78b5316f0700.tar.gz?rev=3c23c6ae2aecc1f76ae7993efe1a78b5316f0700" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/ea74d925e650948d296fb85e4671fb0ce944f550.tar.gz?rev=ea74d925e650948d296fb85e4671fb0ce944f550" }, "original": { "type": "tarball", @@ -271,11 +271,11 @@ ] }, "locked": { - "lastModified": 1747667424, - "narHash": "sha256-7EICjbmG6lApWKhFtwvZovdcdORY1CEe6/K7JwtpYfs=", - "rev": "3c23c6ae2aecc1f76ae7993efe1a78b5316f0700", + "lastModified": 1751240140, + "narHash": "sha256-gbFOUtmkzzNAiHoUtySwbi+AVDgWOW8CpWmTmkoaQiI=", + "rev": "ea74d925e650948d296fb85e4671fb0ce944f550", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/3c23c6ae2aecc1f76ae7993efe1a78b5316f0700.tar.gz?rev=3c23c6ae2aecc1f76ae7993efe1a78b5316f0700" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/ea74d925e650948d296fb85e4671fb0ce944f550.tar.gz?rev=ea74d925e650948d296fb85e4671fb0ce944f550" }, "original": { "type": "tarball", @@ -284,11 +284,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1744659587, - "narHash": "sha256-xJnbmRVte13akgn+Prg06IaRHJ5OX3uVltwsCP/mxoc=", + "lastModified": 1751276396, + "narHash": "sha256-oOYrnKStMsOXST+wKnzuSZ49h8Dr1Q3mIn2f5Kb5GAw=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "928d868a9141b48f152d3b2b00c433e688d4b106", + "rev": "59adb9ad1cbd915494fc35cd0e0a9d582ca9de74", "type": "github" }, "original": { @@ -342,11 +342,11 @@ ] }, "locked": { - "lastModified": 1748751003, - "narHash": "sha256-i4GZdKAK97S0ZMU3w4fqgEJr0cVywzqjugt2qZPrScs=", + "lastModified": 1751170039, + "narHash": "sha256-3EKpUmyGmHYA/RuhZjINTZPU+OFWko0eDwazUOW64nw=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "2860bee699248d828c2ed9097a1cd82c2f991b43", + "rev": "9c932ae632d6b5150515e5749b198c175d8565db", "type": "github" }, "original": { @@ -362,11 +362,11 @@ ] }, "locked": { - "lastModified": 1748751003, - "narHash": "sha256-i4GZdKAK97S0ZMU3w4fqgEJr0cVywzqjugt2qZPrScs=", + "lastModified": 1751170039, + "narHash": "sha256-3EKpUmyGmHYA/RuhZjINTZPU+OFWko0eDwazUOW64nw=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "2860bee699248d828c2ed9097a1cd82c2f991b43", + "rev": "9c932ae632d6b5150515e5749b198c175d8565db", "type": "github" }, "original": { @@ -377,11 +377,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1748942041, - "narHash": "sha256-HEu2gTct7nY0tAPRgBtqYepallryBKR1U8B4v2zEEqA=", + "lastModified": 1751432711, + "narHash": "sha256-136MeWtckSHTN9Z2WRNRdZ8oRP3vyx3L8UxeBYE+J9w=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "fc7c4714125cfaa19b048e8aaf86b9c53e04d853", + "rev": "497ae1357f1ac97f1aea31a4cb74ad0d534ef41f", "type": "github" }, "original": { @@ -393,11 +393,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1744463964, - "narHash": "sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR+Xhw3kr/3Xd0GPTM=", + "lastModified": 1750776420, + "narHash": "sha256-/CG+w0o0oJ5itVklOoLbdn2dGB0wbZVOoDm4np6w09A=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2631b0b7abcea6e640ce31cd78ea58910d31e650", + "rev": "30a61f056ac492e3b7cdcb69c1e6abdcf00e39cf", "type": "github" }, "original": { @@ -409,11 +409,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1748889542, - "narHash": "sha256-Hb4iMhIbjX45GcrgOp3b8xnyli+ysRPqAgZ/LZgyT5k=", + "lastModified": 1751479989, + "narHash": "sha256-M5KgdpVBVcW4HRVq9/OSRbrxlwsQ1ogEKqnvzsClDqU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "10d7f8d34e5eb9c0f9a0485186c1ca691d2c5922", + "rev": "34627c90f062da515ea358360f448da57769236e", "type": "github" }, "original": { @@ -424,11 +424,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1748693115, - "narHash": "sha256-StSrWhklmDuXT93yc3GrTlb0cKSS0agTAxMGjLKAsY8=", + "lastModified": 1751271578, + "narHash": "sha256-P/SQmKDu06x8yv7i0s8bvnnuJYkxVGBWLWHaU+tt4YY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "910796cabe436259a29a72e8d3f5e180fc6dfacc", + "rev": "3016b4b15d13f3089db8a41ef937b13a9e33a8df", "type": "github" }, "original": { From 98f9b3a8fc4c429c6350362353c65354828f7c6c Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 4 Jul 2025 22:31:07 +0200 Subject: [PATCH 1000/1125] Add kde patches The nixpkgs patch is to clear out a conflict with a patch that's applied to plasma-workspace by nixpkgs --- flake.nix | 1 + .../plasma-workspace-patch-trimming.patch | 65 + roles/kde/patches/bluedevil/patches.txt | 2 + roles/kde/patches/bluedevil/pr218.patch | 53 + roles/kde/patches/breeze/patches.txt | 2 + roles/kde/patches/breeze/pr545.patch | 333 ++ roles/kde/patches/dolphin/patches.txt | 3 + roles/kde/patches/dolphin/pr946.patch | 3978 +++++++++++++++++ roles/kde/patches/kwin/patches.txt | 7 + roles/kde/patches/kwin/pr3612.patch | 2101 +++++++++ roles/kde/patches/kwin/pr7822.patch | 40 + roles/kde/patches/kwin/pr7823.patch | 26 + roles/kde/patches/kwin/pr7829.patch | 85 + roles/kde/patches/plasma-nm/patches.txt | 4 + roles/kde/patches/plasma-nm/pr439.patch | 140 + roles/kde/patches/plasma-nm/pr442.patch | 168 + .../kde/patches/plasma-workspace/patches.txt | 6 + .../kde/patches/plasma-workspace/pr5589.patch | 37 + .../kde/patches/plasma-workspace/pr5626.patch | 102 + .../kde/patches/plasma-workspace/pr5627.patch | 157 + .../kde/patches/plasma-workspace/pr5628.patch | 277 ++ roles/kde/patches/spectacle/patches.txt | 3 + roles/kde/patches/spectacle/pr460.patch | 228 + 23 files changed, 7818 insertions(+) create mode 100644 nixpkgs-patches/plasma-workspace-patch-trimming.patch create mode 100644 roles/kde/patches/bluedevil/patches.txt create mode 100644 roles/kde/patches/bluedevil/pr218.patch create mode 100644 roles/kde/patches/breeze/patches.txt create mode 100644 roles/kde/patches/breeze/pr545.patch create mode 100644 roles/kde/patches/dolphin/patches.txt create mode 100644 roles/kde/patches/dolphin/pr946.patch create mode 100644 roles/kde/patches/kwin/patches.txt create mode 100644 roles/kde/patches/kwin/pr3612.patch create mode 100644 roles/kde/patches/kwin/pr7822.patch create mode 100644 roles/kde/patches/kwin/pr7823.patch create mode 100644 roles/kde/patches/kwin/pr7829.patch create mode 100644 roles/kde/patches/plasma-nm/patches.txt create mode 100644 roles/kde/patches/plasma-nm/pr439.patch create mode 100644 roles/kde/patches/plasma-nm/pr442.patch create mode 100644 roles/kde/patches/plasma-workspace/patches.txt create mode 100644 roles/kde/patches/plasma-workspace/pr5589.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5626.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5627.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5628.patch create mode 100644 roles/kde/patches/spectacle/patches.txt create mode 100644 roles/kde/patches/spectacle/pr460.patch diff --git a/flake.nix b/flake.nix index 688fc21..275efa9 100644 --- a/flake.nix +++ b/flake.nix @@ -97,6 +97,7 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ + ./nixpkgs-patches/plasma-workspace-patch-trimming.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/plasma-workspace-patch-trimming.patch b/nixpkgs-patches/plasma-workspace-patch-trimming.patch new file mode 100644 index 0000000..bfd45ce --- /dev/null +++ b/nixpkgs-patches/plasma-workspace-patch-trimming.patch @@ -0,0 +1,65 @@ +diff --git a/pkgs/kde/plasma/plasma-workspace/dependency-paths.patch b/pkgs/kde/plasma/plasma-workspace/dependency-paths.patch +index b4d46cd869bb..ca5bfd2c4889 100644 +--- a/pkgs/kde/plasma/plasma-workspace/dependency-paths.patch ++++ b/pkgs/kde/plasma/plasma-workspace/dependency-paths.patch +@@ -1,13 +1,14 @@ + diff --git a/applets/devicenotifier/plugin/deviceerrormonitor_p.cpp b/applets/devicenotifier/plugin/deviceerrormonitor_p.cpp +-index ba214a555d..421d940738 100644 ++index 183f207946..0f64b068ab 100644 + --- a/applets/devicenotifier/plugin/deviceerrormonitor_p.cpp + +++ b/applets/devicenotifier/plugin/deviceerrormonitor_p.cpp +-@@ -155,7 +155,7 @@ void DeviceErrorMonitor::queryBlockingApps(const QString &devicePath) ++@@ -168,7 +168,8 @@ void DeviceErrorMonitor::queryBlockingApps(const QString &devicePath) + Q_EMIT blockingAppsReady(blockApps); + p->deleteLater(); + }); + - p->start(QStringLiteral("lsof"), {QStringLiteral("-t"), devicePath}); + + p->start(QStringLiteral("@lsof@"), {QStringLiteral("-t"), devicePath}); +++ // @dbusSend@ + // p.start(QStringLiteral("fuser"), {QStringLiteral("-m"), devicePath}); + } + +@@ -51,7 +52,7 @@ index e4d1ad4311..d45bdfad98 100644 + + void CFcQuery::procExited() + diff --git a/kcms/krdb/krdb.cpp b/kcms/krdb/krdb.cpp +-index f3c9956921..09c818739d 100644 ++index 53f77d0a18..680e81b6e4 100644 + --- a/kcms/krdb/krdb.cpp + +++ b/kcms/krdb/krdb.cpp + @@ -425,7 +425,7 @@ void runRdb(unsigned int flags) +@@ -107,7 +108,7 @@ index 7218628ce9..9126475ea4 100644 + +ExecStart=@qdbus@ org.kde.kcminit /kcminit org.kde.KCMInit.runPhase1 + Slice=session.slice + diff --git a/startkde/startplasma.cpp b/startkde/startplasma.cpp +-index 4d31c6f408..17418b1ff7 100644 ++index 02c3f260fb..795244064d 100644 + --- a/startkde/startplasma.cpp + +++ b/startkde/startplasma.cpp + @@ -57,7 +57,7 @@ void sigtermHandler(int signalNumber) +@@ -119,7 +120,7 @@ index 4d31c6f408..17418b1ff7 100644 + } + + QStringList allServices(const QLatin1String &prefix) +-@@ -512,7 +512,7 @@ QProcess *setupKSplash() ++@@ -508,7 +508,7 @@ QProcess *setupKSplash() + if (ksplashCfg.readEntry("Engine", QStringLiteral("KSplashQML")) == QLatin1String("KSplashQML")) { + p = new QProcess; + p->setProcessChannelMode(QProcess::ForwardedChannels); +@@ -128,14 +129,4 @@ index 4d31c6f408..17418b1ff7 100644 + } + } + return p; +-diff --git a/startkde/systemd/plasma-ksplash-ready.service.in b/startkde/systemd/plasma-ksplash-ready.service.in +-index 1e903130a9..0861c3d136 100644 +---- a/startkde/systemd/plasma-ksplash-ready.service.in +-+++ b/startkde/systemd/plasma-ksplash-ready.service.in +-@@ -6,5 +6,5 @@ PartOf=graphical-session.target +- +- [Service] +- Type=oneshot +--ExecStart=dbus-send --session --reply-timeout=1 --type=method_call --dest=org.kde.KSplash /KSplash org.kde.KSplash.setStage string:ready +-+ExecStart=@dbusSend@ --session --reply-timeout=1 --type=method_call --dest=org.kde.KSplash /KSplash org.kde.KSplash.setStage string:ready +- Slice=session.slice ++ + diff --git a/roles/kde/patches/bluedevil/patches.txt b/roles/kde/patches/bluedevil/patches.txt new file mode 100644 index 0000000..f1e689d --- /dev/null +++ b/roles/kde/patches/bluedevil/patches.txt @@ -0,0 +1,2 @@ +Plasma 6.5.0: +Pr 218 https://invent.kde.org/plasma/bluedevil/-/merge_requests/218 diff --git a/roles/kde/patches/bluedevil/pr218.patch b/roles/kde/patches/bluedevil/pr218.patch new file mode 100644 index 0000000..c9eca02 --- /dev/null +++ b/roles/kde/patches/bluedevil/pr218.patch @@ -0,0 +1,53 @@ +From ddbf7452c6f2fe8849de723175710dbf39242422 Mon Sep 17 00:00:00 2001 +From: Nate Graham +Date: Fri, 13 Jun 2025 11:55:47 -0600 +Subject: [PATCH] applet: use standard section headers + +We have them; might as well use them. This lets us get rid of a bunch of +complex and fragile code that's responsible for the existing separator. +--- + .../contents/ui/FullRepresentation.qml | 27 +++---------------- + 1 file changed, 3 insertions(+), 24 deletions(-) + +diff --git a/src/applet/package/contents/ui/FullRepresentation.qml b/src/applet/package/contents/ui/FullRepresentation.qml +index df989267d..27295de21 100644 +--- a/src/applet/package/contents/ui/FullRepresentation.qml ++++ b/src/applet/package/contents/ui/FullRepresentation.qml +@@ -111,31 +111,10 @@ PlasmaExtras.Representation { + bottomMargin: Kirigami.Units.largeSpacing + + section.property: "Section" +- // We want to hide the section delegate for the "Connected" +- // group because it's unnecessary; all we want to do here is +- // separate the connected devices from the available ones +- section.delegate: Loader { ++ section.delegate: PlasmaExtras.ListSectionHeader { + required property string section +- +- active: section !== "Connected" && BluezQt.Manager.connectedDevices.length > 0 +- +- width: ListView.view.width - ListView.view.leftMargin - ListView.view.rightMargin +- // Need to manually set the height or else the loader takes up +- // space after the first time it unloads a previously-loaded item +- height: active ? Kirigami.Units.gridUnit : 0 +- +- // give us 2 frames to try and figure out a layout, this reduces jumpyness quite a bit but doesn't +- // entirely eliminate it https://bugs.kde.org/show_bug.cgi?id=438610 +- Behavior on height { PropertyAnimation { duration: 32 } } +- +- sourceComponent: Item { +- KSvg.SvgItem { +- width: parent.width - Kirigami.Units.gridUnit * 2 +- anchors.centerIn: parent +- imagePath: "widgets/line" +- elementId: "horizontal-line" +- } +- } ++ width: listView.width - listView.leftMargin - listView.rightMargin ++ text: section + } + highlight: PlasmaExtras.Highlight {} + highlightMoveDuration: Kirigami.Units.shortDuration +-- +GitLab + diff --git a/roles/kde/patches/breeze/patches.txt b/roles/kde/patches/breeze/patches.txt new file mode 100644 index 0000000..bf22bd1 --- /dev/null +++ b/roles/kde/patches/breeze/patches.txt @@ -0,0 +1,2 @@ +Plasma 6.5.0: +Pr 545 https://invent.kde.org/plasma/breeze/-/merge_requests/545 diff --git a/roles/kde/patches/breeze/pr545.patch b/roles/kde/patches/breeze/pr545.patch new file mode 100644 index 0000000..926a40d --- /dev/null +++ b/roles/kde/patches/breeze/pr545.patch @@ -0,0 +1,333 @@ +From 38567c2f2d2d0f8524e42224dff53a929cbf086a Mon Sep 17 00:00:00 2001 +From: Kai Uwe Broulik +Date: Sat, 24 May 2025 09:33:44 +0200 +Subject: [PATCH 1/3] kstyle/animations: Use QObject as base type rather than + QWidget + +This prepares for the animation engine being used with Qt Quick Controls. + +In most cases the type is cast to the relevant widget type for checking +anyway, so might as well use the cast object further down but not require +a QWidget at the beginning. +--- + kstyle/animations/breezeanimations.cpp | 48 +++++++++++++------------- + kstyle/animations/breezeanimations.h | 4 +-- + 2 files changed, 26 insertions(+), 26 deletions(-) + +diff --git a/kstyle/animations/breezeanimations.cpp b/kstyle/animations/breezeanimations.cpp +index 12e5107c5..ceab53802 100644 +--- a/kstyle/animations/breezeanimations.cpp ++++ b/kstyle/animations/breezeanimations.cpp +@@ -82,7 +82,7 @@ void Animations::setupEngines() + } + + //____________________________________________________________ +-void Animations::registerWidget(QWidget *widget) const ++void Animations::registerWidget(QObject *widget) const + { + if (!widget) { + return; +@@ -101,37 +101,37 @@ void Animations::registerWidget(QWidget *widget) const + // for optimization, one should put with most used widgets here first + + // buttons +- if (qobject_cast(widget)) { +- _toolButtonEngine->registerWidget(widget, AnimationHover | AnimationFocus); +- _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus); ++ if (auto toolButton = qobject_cast(widget)) { ++ _toolButtonEngine->registerWidget(toolButton, AnimationHover | AnimationFocus); ++ _widgetStateEngine->registerWidget(toolButton, AnimationHover | AnimationFocus); + + } else if (qobject_cast(widget) || qobject_cast(widget)) { + _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus | AnimationPressed); + +- } else if (qobject_cast(widget)) { ++ } else if (auto button = qobject_cast(widget)) { + // register to toolbox engine if needed +- if (qobject_cast(widget->parent())) { +- _toolBoxEngine->registerWidget(widget); ++ if (auto toolBox = qobject_cast(widget->parent())) { ++ _toolBoxEngine->registerWidget(toolBox); + } + +- _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus); ++ _widgetStateEngine->registerWidget(button, AnimationHover | AnimationFocus); + + } + + // groupboxes + else if (QGroupBox *groupBox = qobject_cast(widget)) { + if (groupBox->isCheckable()) { +- _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus); ++ _widgetStateEngine->registerWidget(groupBox, AnimationHover | AnimationFocus); + } + } + + // sliders +- else if (qobject_cast(widget)) { +- _scrollBarEngine->registerWidget(widget, AnimationHover | AnimationFocus); +- } else if (qobject_cast(widget)) { +- _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus); +- } else if (qobject_cast(widget)) { +- _dialEngine->registerWidget(widget, AnimationHover | AnimationFocus); ++ else if (auto scrollBar = qobject_cast(widget)) { ++ _scrollBarEngine->registerWidget(scrollBar, AnimationHover | AnimationFocus); ++ } else if (auto slider = qobject_cast(widget)) { ++ _widgetStateEngine->registerWidget(slider, AnimationHover | AnimationFocus); ++ } else if (auto dial = qobject_cast(widget)) { ++ _dialEngine->registerWidget(dial, AnimationHover | AnimationFocus); + } + + // progress bar +@@ -162,24 +162,24 @@ void Animations::registerWidget(QWidget *widget) const + + // header views + // need to come before abstract item view, otherwise is skipped +- else if (qobject_cast(widget)) { +- _headerViewEngine->registerWidget(widget); ++ else if (auto headerView = qobject_cast(widget)) { ++ _headerViewEngine->registerWidget(headerView); + } + + // lists +- else if (qobject_cast(widget)) { +- _inputWidgetEngine->registerWidget(widget, AnimationHover | AnimationFocus); ++ else if (auto itemView = qobject_cast(widget)) { ++ _inputWidgetEngine->registerWidget(itemView, AnimationHover | AnimationFocus); + } + + // tabbar +- else if (qobject_cast(widget)) { +- _tabBarEngine->registerWidget(widget); ++ else if (auto tabBar = qobject_cast(widget)) { ++ _tabBarEngine->registerWidget(tabBar); + } + + // scrollarea + else if (QAbstractScrollArea *scrollArea = qobject_cast(widget)) { +- if (scrollArea->frameShadow() == QFrame::Sunken && (widget->focusPolicy() & Qt::StrongFocus)) { +- _inputWidgetEngine->registerWidget(widget, AnimationHover | AnimationFocus); ++ if (scrollArea->frameShadow() == QFrame::Sunken && (scrollArea->focusPolicy() & Qt::StrongFocus)) { ++ _inputWidgetEngine->registerWidget(scrollArea, AnimationHover | AnimationFocus); + } + } + +@@ -190,7 +190,7 @@ void Animations::registerWidget(QWidget *widget) const + } + + //____________________________________________________________ +-void Animations::unregisterWidget(QWidget *widget) const ++void Animations::unregisterWidget(QObject *widget) const + { + if (!widget) { + return; +diff --git a/kstyle/animations/breezeanimations.h b/kstyle/animations/breezeanimations.h +index 6551900a5..3215e8fb9 100644 +--- a/kstyle/animations/breezeanimations.h ++++ b/kstyle/animations/breezeanimations.h +@@ -31,10 +31,10 @@ public: + explicit Animations(); + + //* register animations corresponding to given widget, depending on its type. +- void registerWidget(QWidget *widget) const; ++ void registerWidget(QObject *widget) const; + + /** unregister all animations associated to a widget */ +- void unregisterWidget(QWidget *widget) const; ++ void unregisterWidget(QObject *widget) const; + + //* enability engine + [[nodiscard]] WidgetStateEngine &widgetEnabilityEngine() const +-- +GitLab + + +From 75201d1e63d82f7282c8bedcc7cc3d2417b1e123 Mon Sep 17 00:00:00 2001 +From: Kai Uwe Broulik +Date: Sat, 24 May 2025 09:40:01 +0200 +Subject: [PATCH 2/3] kstyle: Use styleObject for widgetStateEngine in + CheckBox/RadioButton + +Prepares it for doing the animation also with Qt Quick Controls +without an actual QWidget. +--- + kstyle/breezestyle.cpp | 44 ++++++++++++++++++++++++++++-------------- + 1 file changed, 29 insertions(+), 15 deletions(-) + +diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp +index 09cee6003..19149c382 100644 +--- a/kstyle/breezestyle.cpp ++++ b/kstyle/breezestyle.cpp +@@ -4738,6 +4738,8 @@ bool Style::drawPanelItemViewItemPrimitive(const QStyleOption *option, QPainter + //___________________________________________________________________________________ + bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const + { ++ const QObject *styleObject = widget ? widget : option->styleObject; ++ + // copy rect and palette + const auto &rect(option->rect); + const auto &palette(option->palette); +@@ -4757,15 +4759,15 @@ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter + } + + // animation state +- _animations->widgetStateEngine().updateState(widget, AnimationHover, mouseOver); +- _animations->widgetStateEngine().updateState(widget, AnimationPressed, checkBoxState != CheckOff); ++ _animations->widgetStateEngine().updateState(styleObject, AnimationHover, mouseOver); ++ _animations->widgetStateEngine().updateState(styleObject, AnimationPressed, checkBoxState != CheckOff); + auto target = checkBoxState; +- if (_animations->widgetStateEngine().isAnimated(widget, AnimationPressed)) { ++ if (_animations->widgetStateEngine().isAnimated(styleObject, AnimationPressed)) { + checkBoxState = CheckAnimated; + } +- const qreal animation(_animations->widgetStateEngine().opacity(widget, AnimationPressed)); ++ const qreal animation(_animations->widgetStateEngine().opacity(styleObject, AnimationPressed)); + +- const qreal opacity(_animations->widgetStateEngine().opacity(widget, AnimationHover)); ++ const qreal opacity(_animations->widgetStateEngine().opacity(styleObject, AnimationHover)); + + // render + _helper->renderCheckBoxBackground(painter, rect, palette, checkBoxState, hasHighlightNeutral(widget, option, mouseOver), sunken, animation); +@@ -4777,6 +4779,8 @@ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter + //___________________________________________________________________________________ + bool Style::drawIndicatorRadioButtonPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const + { ++ const QObject *styleObject = widget ? widget : option->styleObject; ++ + // copy rect and palette + const auto &rect(option->rect); + const auto &palette(option->palette); +@@ -4791,19 +4795,27 @@ bool Style::drawIndicatorRadioButtonPrimitive(const QStyleOption *option, QPaint + RadioButtonState radioButtonState((state & State_On) ? RadioOn : RadioOff); + + // animation state +- _animations->widgetStateEngine().updateState(widget, AnimationHover, mouseOver); +- _animations->widgetStateEngine().updateState(widget, AnimationPressed, radioButtonState != RadioOff); +- if (_animations->widgetStateEngine().isAnimated(widget, AnimationPressed)) { ++ _animations->widgetStateEngine().updateState(styleObject, AnimationHover, mouseOver); ++ _animations->widgetStateEngine().updateState(styleObject, AnimationPressed, radioButtonState != RadioOff); ++ if (_animations->widgetStateEngine().isAnimated(styleObject, AnimationPressed)) { + radioButtonState = RadioAnimated; + } +- const qreal animation(_animations->widgetStateEngine().opacity(widget, AnimationPressed)); ++ const qreal animation(_animations->widgetStateEngine().opacity(styleObject, AnimationPressed)); + + // colors +- const qreal opacity(_animations->widgetStateEngine().opacity(widget, AnimationHover)); ++ const qreal opacity(_animations->widgetStateEngine().opacity(styleObject, AnimationHover)); + + // render +- _helper->renderRadioButtonBackground(painter, rect, palette, radioButtonState, hasHighlightNeutral(widget, option, mouseOver), sunken, animation); +- _helper->renderRadioButton(painter, rect, palette, mouseOver, radioButtonState, hasHighlightNeutral(widget, option, mouseOver), sunken, animation, opacity); ++ _helper->renderRadioButtonBackground(painter, rect, palette, radioButtonState, hasHighlightNeutral(styleObject, option, mouseOver), sunken, animation); ++ _helper->renderRadioButton(painter, ++ rect, ++ palette, ++ mouseOver, ++ radioButtonState, ++ hasHighlightNeutral(styleObject, option, mouseOver), ++ sunken, ++ animation, ++ opacity); + + return true; + } +@@ -5450,6 +5462,8 @@ bool Style::drawCheckBoxLabelControl(const QStyleOption *option, QPainter *paint + return true; + } + ++ const QObject *styleObject = widget ? widget : option->styleObject; ++ + // copy palette and rect + const auto &palette(option->palette); + const auto &rect(option->rect); +@@ -5501,10 +5515,10 @@ bool Style::drawCheckBoxLabelControl(const QStyleOption *option, QPainter *paint + const bool hasFocus(enabled && (state & State_HasFocus)); + + // update animation state +- _animations->widgetStateEngine().updateState(widget, AnimationFocus, hasFocus); ++ _animations->widgetStateEngine().updateState(styleObject, AnimationFocus, hasFocus); + +- const bool isFocusAnimated(_animations->widgetStateEngine().isAnimated(widget, AnimationFocus)); +- const qreal opacity(_animations->widgetStateEngine().opacity(widget, AnimationFocus)); ++ const bool isFocusAnimated(_animations->widgetStateEngine().isAnimated(styleObject, AnimationFocus)); ++ const qreal opacity(_animations->widgetStateEngine().opacity(styleObject, AnimationFocus)); + // focus color + QColor focusColor; + if (isFocusAnimated) { +-- +GitLab + + +From a572df8f099969919544dbc2478de6aa2082a705 Mon Sep 17 00:00:00 2001 +From: Kai Uwe Broulik +Date: Sat, 24 May 2025 09:54:44 +0200 +Subject: [PATCH 3/3] kstyle: Register Qt Quick Controls with animations + +Since it's all software-rendered and indirect, only the +CheckBox and RadioButton controls are actually wired up +since the rest of the animations is quite subtle. +--- + kstyle/animations/breezeanimations.cpp | 9 +++++++++ + kstyle/breezestyle.cpp | 4 ++++ + 2 files changed, 13 insertions(+) + +diff --git a/kstyle/animations/breezeanimations.cpp b/kstyle/animations/breezeanimations.cpp +index ceab53802..5285f5daf 100644 +--- a/kstyle/animations/breezeanimations.cpp ++++ b/kstyle/animations/breezeanimations.cpp +@@ -100,6 +100,15 @@ void Animations::registerWidget(QObject *widget) const + // install animation timers + // for optimization, one should put with most used widgets here first + ++ // KQuickStyleItem. ++ const QString elementType = widget->property("elementType").toString(); ++ if (!elementType.isEmpty()) { ++ if (elementType == QLatin1String("checkbox") || elementType == QLatin1String("radiobutton")) { ++ _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus | AnimationPressed); ++ } ++ return; ++ } ++ + // buttons + if (auto toolButton = qobject_cast(widget)) { + _toolButtonEngine->registerWidget(toolButton, AnimationHover | AnimationFocus); +diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp +index 19149c382..e549803f1 100644 +--- a/kstyle/breezestyle.cpp ++++ b/kstyle/breezestyle.cpp +@@ -4739,6 +4739,7 @@ bool Style::drawPanelItemViewItemPrimitive(const QStyleOption *option, QPainter + bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const + { + const QObject *styleObject = widget ? widget : option->styleObject; ++ isQtQuickControl(option, widget); // registers it with widgetStateEngine. + + // copy rect and palette + const auto &rect(option->rect); +@@ -4780,6 +4781,7 @@ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter + bool Style::drawIndicatorRadioButtonPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const + { + const QObject *styleObject = widget ? widget : option->styleObject; ++ isQtQuickControl(option, widget); // registers it with widgetStateEngine. + + // copy rect and palette + const auto &rect(option->rect); +@@ -5463,6 +5465,7 @@ bool Style::drawCheckBoxLabelControl(const QStyleOption *option, QPainter *paint + } + + const QObject *styleObject = widget ? widget : option->styleObject; ++ isQtQuickControl(option, widget); // registers it with widgetStateEngine. + + // copy palette and rect + const auto &palette(option->palette); +@@ -8460,6 +8463,7 @@ bool Style::isQtQuickControl(const QStyleOption *option, const QWidget *widget) + if (!widget && option) { + if (const auto item = qobject_cast(option->styleObject)) { + _windowManager->registerQuickItem(item); ++ _animations->registerWidget(item); + return true; + } + } +-- +GitLab + diff --git a/roles/kde/patches/dolphin/patches.txt b/roles/kde/patches/dolphin/patches.txt new file mode 100644 index 0000000..a7f0a2a --- /dev/null +++ b/roles/kde/patches/dolphin/patches.txt @@ -0,0 +1,3 @@ +Gear 25.08.0: + +Pr 946 https://invent.kde.org/system/dolphin/-/merge_requests/946 diff --git a/roles/kde/patches/dolphin/pr946.patch b/roles/kde/patches/dolphin/pr946.patch new file mode 100644 index 0000000..f01f4bd --- /dev/null +++ b/roles/kde/patches/dolphin/pr946.patch @@ -0,0 +1,3978 @@ +From 21990d59c176084af615b97a6e586d32aa47fb66 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Fri, 11 Apr 2025 17:31:12 +0300 +Subject: [PATCH 01/69] WIP: new selection effect stuff + +based on felix branch +https://invent.kde.org/felixernst/dolphin/-/commit/b3fa4479c1c23da08c120e8462bae42c712381d3 +--- + src/kitemviews/kitemlistwidget.cpp | 49 +++++++++++------ + src/kitemviews/kstandarditemlistwidget.cpp | 63 +++++++--------------- + 2 files changed, 52 insertions(+), 60 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index baf2445726..a6fd75a347 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -124,23 +124,11 @@ void KItemListWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *o + painter->fillRect(backgroundRect, backgroundColor); + } + +- if (m_selected && m_editedRole.isEmpty()) { ++ if ((m_selected || m_current) && m_editedRole.isEmpty()) { + const QStyle::State activeState(isActiveWindow() && widget->hasFocus() ? QStyle::State_Active : 0); + drawItemStyleOption(painter, widget, activeState | QStyle::State_Enabled | QStyle::State_Selected | QStyle::State_Item); + } + +- if (m_current && m_editedRole.isEmpty()) { +- QStyleOptionFocusRect focusRectOption; +- initStyleOption(&focusRectOption); +- focusRectOption.rect = textFocusRect().toRect(); +- focusRectOption.state = QStyle::State_Enabled | QStyle::State_Item | QStyle::State_KeyboardFocusChange; +- if (m_selected && widget->hasFocus()) { +- focusRectOption.state |= QStyle::State_Selected; +- } +- +- style()->drawPrimitive(QStyle::PE_FrameFocusRect, &focusRectOption, painter, widget); +- } +- + if (m_hoverOpacity > 0.0) { + if (!m_hoverCache) { + // Initialize the m_hoverCache pixmap to improve the drawing performance +@@ -623,8 +611,39 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + viewItemOption.state = styleState; + viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; + viewItemOption.showDecorationSelected = true; +- viewItemOption.rect = selectionRect().toRect(); +- style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, painter, widget); ++ viewItemOption.rect = selectionRect().toRect().adjusted(2, 2, -2, -2); ++ QPainterPath path; ++ path.addRoundedRect(viewItemOption.rect, 5, 5); ++ QColor accentColor{widget->palette().color(QPalette::Accent)}; ++ painter->setRenderHint(QPainter::Antialiasing); ++ bool current = m_current && styleState & QStyle::State_Active; ++ ++ // Background item ++ accentColor.setAlphaF(0.0); ++ if (m_selected && m_hovered) { ++ accentColor.setAlphaF(0.5); ++ } else if (m_selected) { ++ accentColor.setAlphaF(0.4); ++ } else if (m_hovered && current) { ++ accentColor.setAlphaF(0.3); ++ } else if (m_hovered) { ++ accentColor.setAlphaF(0.1); ++ } ++ painter->fillPath(path, accentColor); ++ ++ // Focus decoration ++ if (current && m_hovered) { ++ accentColor.setAlphaF(1.0); ++ } else if (current || m_hovered) { ++ accentColor.setAlphaF(0.9); ++ } else if (m_current) { ++ accentColor.setAlphaF(0.3); ++ } ++ if (m_current || m_hovered) { ++ const QPen pen{accentColor, 2}; ++ painter->setPen(pen); ++ painter->drawPath(path); ++ } + } + + #include "moc_kitemlistwidget.cpp" +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 49d2f26bfd..c320e375b4 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -541,31 +541,23 @@ QRectF KStandardItemListWidget::selectionRect() const + { + const_cast(this)->triggerCacheRefreshing(); + +- switch (m_layout) { +- case IconsLayout: +- return m_textRect; +- +- case CompactLayout: +- case DetailsLayout: { +- const int padding = styleOption().padding; +- QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); +- QRectF result = adjustedIconRect | m_textRect; +- if (m_highlightEntireRow) { +- if (layoutDirection() == Qt::LeftToRight) { +- result.setRight(leftPadding() + m_columnWidthSum); +- } else { +- result.setLeft(size().width() - m_columnWidthSum - rightPadding()); +- } ++ const int padding = styleOption().padding; ++ QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); ++ QRectF result = adjustedIconRect | m_textRect; ++ if (m_highlightEntireRow) { ++ if (layoutDirection() == Qt::LeftToRight) { ++ result.setRight(leftPadding() + m_columnWidthSum); ++ } else { ++ result.setLeft(size().width() - m_columnWidthSum - rightPadding()); + } +- return result; + } + +- default: +- Q_ASSERT(false); +- break; ++ if (m_layout == IconsLayout) { ++ const int availableWidth = size().width() - 2 * padding - result.width(); ++ result = result.adjusted(-0.5 * availableWidth, 0, 0.5 * availableWidth, 0); + } + +- return m_textRect; ++ return result; + } + + QRectF KStandardItemListWidget::expansionToggleRect() const +@@ -578,7 +570,6 @@ QRectF KStandardItemListWidget::selectionToggleRect() const + { + const_cast(this)->triggerCacheRefreshing(); + +- const QRectF widgetIconRect = iconRect(); + const int widgetIconSize = iconSize(); + int toggleSize = KIconLoader::SizeSmall; + if (widgetIconSize >= KIconLoader::SizeEnormous) { +@@ -587,29 +578,11 @@ QRectF KStandardItemListWidget::selectionToggleRect() const + toggleSize = KIconLoader::SizeSmallMedium; + } + +- QPointF pos = widgetIconRect.topLeft(); +- +- // If the selection toggle has a very small distance to the +- // widget borders, the size of the selection toggle will get +- // increased to prevent an accidental clicking of the item +- // when trying to hit the toggle. +- const int widgetHeight = size().height(); +- const int widgetWidth = size().width(); +- const int minMargin = 2; +- +- if (toggleSize + minMargin * 2 >= widgetHeight) { +- pos.rx() -= (widgetHeight - toggleSize) / 2; +- toggleSize = widgetHeight; +- pos.setY(0); +- } +- if (toggleSize + minMargin * 2 >= widgetWidth) { +- pos.ry() -= (widgetWidth - toggleSize) / 2; +- toggleSize = widgetWidth; +- pos.setX(0); +- } +- ++ const int padding = styleOption().padding; ++ const QRectF selectionRectMinusPadding = selectionRect().adjusted(padding, padding, -padding, -padding); ++ QPointF pos = selectionRectMinusPadding.topLeft(); + if (QApplication::isRightToLeft()) { +- pos.setX(widgetIconRect.right() - (pos.x() + toggleSize - widgetIconRect.left())); ++ pos.setX(selectionRectMinusPadding.right() - (pos.x() + toggleSize - selectionRectMinusPadding.left())); + } + + return QRectF(pos, QSizeF(toggleSize, toggleSize)); +@@ -748,7 +721,7 @@ QColor KStandardItemListWidget::textColor(const QWidget &widget) const + } + + const QPalette::ColorGroup group = isActiveWindow() && widget.hasFocus() ? QPalette::Active : QPalette::Inactive; +- const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : normalTextColorRole(); ++ const QPalette::ColorRole role = /*isSelected() ? QPalette::HighlightedText :*/ normalTextColorRole(); + return styleOption().palette.color(group, role); + } + +@@ -1568,7 +1541,7 @@ void KStandardItemListWidget::updateAdditionalInfoTextColor() + const bool hasFocus = scene()->views()[0]->parentWidget()->hasFocus(); + if (m_customTextColor.isValid()) { + c1 = m_customTextColor; +- } else if (isSelected() && hasFocus && (m_layout != DetailsLayout || m_highlightEntireRow)) { ++ } else if (false && isSelected() && hasFocus && (m_layout != DetailsLayout || m_highlightEntireRow)) { + // The detail text color needs to match the main text (HighlightedText) for the same level + // of readability. We short circuit early here to avoid interpolating with another color. + m_additionalInfoTextColor = styleOption().palette.color(QPalette::HighlightedText); +-- +GitLab + + +From 64650add73385948fd76b487a90da2c7635a2b7a Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 14 Apr 2025 14:53:01 +0300 +Subject: [PATCH 02/69] Show a gap between selection and focus + +--- + src/kitemviews/kitemlistwidget.cpp | 35 ++++++++++++++++-------------- + 1 file changed, 19 insertions(+), 16 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index a6fd75a347..1e82c27b1b 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -607,13 +607,16 @@ void KItemListWidget::clearHoverCache() + void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState) + { + QStyleOptionViewItem viewItemOption; ++ const int focusPenWidth = 2; ++ const int roundness = 5; + initStyleOption(&viewItemOption); + viewItemOption.state = styleState; + viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; + viewItemOption.showDecorationSelected = true; +- viewItemOption.rect = selectionRect().toRect().adjusted(2, 2, -2, -2); ++ viewItemOption.rect = selectionRect().toRect(); ++ viewItemOption.rect = viewItemOption.rect.adjusted(focusPenWidth, focusPenWidth, -focusPenWidth, -focusPenWidth); + QPainterPath path; +- path.addRoundedRect(viewItemOption.rect, 5, 5); ++ path.addRoundedRect(viewItemOption.rect, roundness, roundness); + QColor accentColor{widget->palette().color(QPalette::Accent)}; + painter->setRenderHint(QPainter::Antialiasing); + bool current = m_current && styleState & QStyle::State_Active; +@@ -621,26 +624,26 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + // Background item + accentColor.setAlphaF(0.0); + if (m_selected && m_hovered) { +- accentColor.setAlphaF(0.5); ++ accentColor.setAlphaF(1.0); + } else if (m_selected) { +- accentColor.setAlphaF(0.4); +- } else if (m_hovered && current) { +- accentColor.setAlphaF(0.3); ++ accentColor.setAlphaF(0.8); + } else if (m_hovered) { +- accentColor.setAlphaF(0.1); ++ accentColor.setAlphaF(0.3); ++ } ++ if (current) { ++ auto currentGap = focusPenWidth; ++ auto currentPathRect = viewItemOption.rect.adjusted(currentGap, currentGap, -currentGap, -currentGap); ++ QPainterPath currentPath; ++ currentPath.addRoundedRect(currentPathRect, roundness, roundness); ++ painter->fillPath(currentPath, accentColor); ++ } else { ++ painter->fillPath(path, accentColor); + } +- painter->fillPath(path, accentColor); + + // Focus decoration +- if (current && m_hovered) { +- accentColor.setAlphaF(1.0); +- } else if (current || m_hovered) { +- accentColor.setAlphaF(0.9); +- } else if (m_current) { +- accentColor.setAlphaF(0.3); +- } + if (m_current || m_hovered) { +- const QPen pen{accentColor, 2}; ++ accentColor.setAlphaF(1.0); ++ const QPen pen{accentColor, focusPenWidth}; + painter->setPen(pen); + painter->drawPath(path); + } +-- +GitLab + + +From da8cbfdd2d72237e2d2a13c88b5a0fafd558ea24 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 14 Apr 2025 15:20:00 +0300 +Subject: [PATCH 03/69] Do not colorize icons + +--- + src/kitemviews/kstandarditemlistwidget.cpp | 11 ----------- + 1 file changed, 11 deletions(-) + +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index c320e375b4..c56c859a71 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -1120,17 +1120,6 @@ void KStandardItemListWidget::updatePixmapCache() + if (m_isHidden) { + KIconEffect::semiTransparent(m_pixmap); + } +- +- if (m_layout == IconsLayout && isSelected()) { +- const QColor color = palette().brush(QPalette::Normal, QPalette::Highlight).color(); +- QImage image = m_pixmap.toImage(); +- if (image.isNull()) { +- m_hoverPixmap = QPixmap(); +- return; +- } +- KIconEffect::colorize(image, color, 0.8f); +- m_pixmap = QPixmap::fromImage(image); +- } + } + + int scaledIconSize = 0; +-- +GitLab + + +From 434aee5f8375f66c41eefc75206a2b2a81849ea9 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 14 Apr 2025 15:58:30 +0300 +Subject: [PATCH 04/69] add highlightedTextColor back + +--- + src/kitemviews/kstandarditemlistwidget.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index c56c859a71..486c909de1 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -721,7 +721,7 @@ QColor KStandardItemListWidget::textColor(const QWidget &widget) const + } + + const QPalette::ColorGroup group = isActiveWindow() && widget.hasFocus() ? QPalette::Active : QPalette::Inactive; +- const QPalette::ColorRole role = /*isSelected() ? QPalette::HighlightedText :*/ normalTextColorRole(); ++ const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : normalTextColorRole(); + return styleOption().palette.color(group, role); + } + +-- +GitLab + + +From fa6ed958b64cf5fd39d3624a661b5984249fce30 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 14 Apr 2025 16:51:26 +0300 +Subject: [PATCH 05/69] Modify padding for iconslayout + +--- + src/kitemviews/kstandarditemlistwidget.cpp | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 486c909de1..2d209ba5bb 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -550,11 +550,11 @@ QRectF KStandardItemListWidget::selectionRect() const + } else { + result.setLeft(size().width() - m_columnWidthSum - rightPadding()); + } +- } +- +- if (m_layout == IconsLayout) { +- const int availableWidth = size().width() - 2 * padding - result.width(); +- result = result.adjusted(-0.5 * availableWidth, 0, 0.5 * availableWidth, 0); ++ } else { ++ // Make sure values are always positive ++ const int availableWidth = qAbs((size().width() - 2 * padding - result.width()) * 0.5); ++ const int availableHeight = m_layout == CompactLayout ? 0 : qAbs((size().height() - 2 * padding - result.height()) * 0.5); ++ result = result.adjusted(-availableWidth, -availableHeight, availableWidth, availableHeight); + } + + return result; +-- +GitLab + + +From 66c8dbf844c81197ec30a90ead4b392b803573ae Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 14 Apr 2025 16:55:17 +0300 +Subject: [PATCH 06/69] Use highlight color + +--- + src/kitemviews/kitemlistwidget.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 1e82c27b1b..8c5b1e6259 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -617,7 +617,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + viewItemOption.rect = viewItemOption.rect.adjusted(focusPenWidth, focusPenWidth, -focusPenWidth, -focusPenWidth); + QPainterPath path; + path.addRoundedRect(viewItemOption.rect, roundness, roundness); +- QColor accentColor{widget->palette().color(QPalette::Accent)}; ++ QColor accentColor{widget->palette().color(QPalette::Highlight)}; + painter->setRenderHint(QPainter::Antialiasing); + bool current = m_current && styleState & QStyle::State_Active; + +@@ -643,7 +643,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + // Focus decoration + if (m_current || m_hovered) { + accentColor.setAlphaF(1.0); +- const QPen pen{accentColor, focusPenWidth}; ++ const QPen pen{accentColor.lighter(120), focusPenWidth}; + painter->setPen(pen); + painter->drawPath(path); + } +-- +GitLab + + +From 49441c8362b56b04ce0ccf25f6f45070a4ca8477 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 14 Apr 2025 17:00:54 +0300 +Subject: [PATCH 07/69] adjust the viewitemoption.rect + +--- + src/kitemviews/kitemlistwidget.cpp | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 8c5b1e6259..9444616f58 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -608,20 +608,23 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + { + QStyleOptionViewItem viewItemOption; + const int focusPenWidth = 2; ++ // Small adjustment due to how QRect coordinates work ++ const int viewItemRectAdjustment = focusPenWidth + 1; + const int roundness = 5; + initStyleOption(&viewItemOption); + viewItemOption.state = styleState; + viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; + viewItemOption.showDecorationSelected = true; + viewItemOption.rect = selectionRect().toRect(); +- viewItemOption.rect = viewItemOption.rect.adjusted(focusPenWidth, focusPenWidth, -focusPenWidth, -focusPenWidth); ++ viewItemOption.rect = viewItemOption.rect.adjusted(viewItemRectAdjustment, viewItemRectAdjustment, -viewItemRectAdjustment, -viewItemRectAdjustment); + QPainterPath path; + path.addRoundedRect(viewItemOption.rect, roundness, roundness); + QColor accentColor{widget->palette().color(QPalette::Highlight)}; + painter->setRenderHint(QPainter::Antialiasing); + bool current = m_current && styleState & QStyle::State_Active; + +- // Background item ++ // Background item, alpha values are from ++ // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg + accentColor.setAlphaF(0.0); + if (m_selected && m_hovered) { + accentColor.setAlphaF(1.0); +@@ -641,7 +644,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + } + + // Focus decoration +- if (m_current || m_hovered) { ++ if (current || m_hovered) { + accentColor.setAlphaF(1.0); + const QPen pen{accentColor.lighter(120), focusPenWidth}; + painter->setPen(pen); +-- +GitLab + + +From 35ffad2d67c6dca2bab0d979b8017a5da377ae05 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Tue, 15 Apr 2025 15:03:01 +0300 +Subject: [PATCH 08/69] Make hovered outline transparent + +--- + src/kitemviews/kitemlistwidget.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 9444616f58..ddf9a4ea1a 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -645,7 +645,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + + // Focus decoration + if (current || m_hovered) { +- accentColor.setAlphaF(1.0); ++ accentColor.setAlphaF(m_hovered ? 0.4 : 1.0); + const QPen pen{accentColor.lighter(120), focusPenWidth}; + painter->setPen(pen); + painter->drawPath(path); +-- +GitLab + + +From 528f25f0c412073a3ae643fb5f9f8d163cc83d21 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Tue, 15 Apr 2025 15:10:27 +0300 +Subject: [PATCH 09/69] Only apply hover effect to icon when its selected + +Better contrast this way +--- + src/kitemviews/kstandarditemlistwidget.cpp | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 2d209ba5bb..b9bbb68b8a 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -1171,7 +1171,9 @@ void KStandardItemListWidget::updatePixmapCache() + // Prepare the pixmap that is used when the item gets hovered + if (isHovered()) { + m_hoverPixmap = m_pixmap; +- KIconEffect::toActive(m_hoverPixmap); ++ if (isSelected()) { ++ KIconEffect::toActive(m_hoverPixmap); ++ } + } else if (hoverOpacity() <= 0.0) { + // No hover animation is ongoing. Clear m_hoverPixmap to save memory. + m_hoverPixmap = QPixmap(); +-- +GitLab + + +From edf7272c9c8245f7297d2bd9738996433fd8bb82 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Tue, 15 Apr 2025 16:53:09 +0300 +Subject: [PATCH 10/69] Use style 2 + +--- + src/kitemviews/kitemlistwidget.cpp | 17 +++++------------ + 1 file changed, 5 insertions(+), 12 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index ddf9a4ea1a..14795af9fa 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -629,23 +629,16 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + if (m_selected && m_hovered) { + accentColor.setAlphaF(1.0); + } else if (m_selected) { +- accentColor.setAlphaF(0.8); ++ accentColor.setAlphaF(0.5); + } else if (m_hovered) { + accentColor.setAlphaF(0.3); + } +- if (current) { +- auto currentGap = focusPenWidth; +- auto currentPathRect = viewItemOption.rect.adjusted(currentGap, currentGap, -currentGap, -currentGap); +- QPainterPath currentPath; +- currentPath.addRoundedRect(currentPathRect, roundness, roundness); +- painter->fillPath(currentPath, accentColor); +- } else { +- painter->fillPath(path, accentColor); +- } ++ ++ painter->fillPath(path, accentColor); + + // Focus decoration +- if (current || m_hovered) { +- accentColor.setAlphaF(m_hovered ? 0.4 : 1.0); ++ if (current) { ++ accentColor.setAlphaF(1.0); + const QPen pen{accentColor.lighter(120), focusPenWidth}; + painter->setPen(pen); + painter->drawPath(path); +-- +GitLab + + +From 9933d7c49a1d0bcf956afe69b347df18fb2f1c70 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Tue, 15 Apr 2025 17:04:08 +0300 +Subject: [PATCH 11/69] Set pen color according to base lightness + +--- + src/kitemviews/kitemlistwidget.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 14795af9fa..64584abce2 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -629,7 +629,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + if (m_selected && m_hovered) { + accentColor.setAlphaF(1.0); + } else if (m_selected) { +- accentColor.setAlphaF(0.5); ++ accentColor.setAlphaF(0.8); + } else if (m_hovered) { + accentColor.setAlphaF(0.3); + } +@@ -639,7 +639,8 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + // Focus decoration + if (current) { + accentColor.setAlphaF(1.0); +- const QPen pen{accentColor.lighter(120), focusPenWidth}; ++ // Set the pen color lighter or darker depending on background color ++ const QPen pen{m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker() : accentColor.lighter(), focusPenWidth}; + painter->setPen(pen); + painter->drawPath(path); + } +-- +GitLab + + +From 0ddc8b6f93bda0afc525e57576ef00ab0ad94697 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Tue, 15 Apr 2025 17:21:11 +0300 +Subject: [PATCH 12/69] Dont show focus before interaction + +--- + src/kitemviews/kitemlistcontroller.cpp | 4 ++++ + src/kitemviews/kitemlistselectionmanager.cpp | 4 +--- + 2 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index cd60c3a41b..f0c6a26878 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -478,6 +478,10 @@ bool KItemListController::keyPressEvent(QKeyEvent *event) + return false; + } + ++ if (index < 0) { ++ index = 0; ++ } ++ + if (m_selectionManager->currentItem() != index) { + switch (m_selectionBehavior) { + case NoSelection: +diff --git a/src/kitemviews/kitemlistselectionmanager.cpp b/src/kitemviews/kitemlistselectionmanager.cpp +index 6f7f0e0776..abf58df240 100644 +--- a/src/kitemviews/kitemlistselectionmanager.cpp ++++ b/src/kitemviews/kitemlistselectionmanager.cpp +@@ -217,9 +217,7 @@ void KItemListSelectionManager::itemsInserted(const KItemRangeList &itemRanges) + const KItemSet previousSelection = selectedItems(); + + // Update the current item +- if (m_currentItem < 0) { +- setCurrentItem(0); +- } else { ++ if (m_currentItem >= 0) { + const int previousCurrent = m_currentItem; + int inc = 0; + for (const KItemRange &itemRange : itemRanges) { +-- +GitLab + + +From 8588d3aa3bb73e7c6f35df8844de0b9ccc335078 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Wed, 16 Apr 2025 15:23:08 +0300 +Subject: [PATCH 13/69] Less intense selection lightening/darkening + +--- + src/kitemviews/kitemlistwidget.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 64584abce2..ebbfb98cc6 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -640,7 +640,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + if (current) { + accentColor.setAlphaF(1.0); + // Set the pen color lighter or darker depending on background color +- const QPen pen{m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker() : accentColor.lighter(), focusPenWidth}; ++ const QPen pen{m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110), focusPenWidth}; + painter->setPen(pen); + painter->drawPath(path); + } +-- +GitLab + + +From cbec8b9acd0aa13ddb984097e9c9ea37baba6a33 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Wed, 16 Apr 2025 15:23:43 +0300 +Subject: [PATCH 14/69] Clean up currentItem when clicking on empty area + +--- + src/kitemviews/kitemlistcontroller.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index f0c6a26878..4f5c8fbb39 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1720,6 +1720,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + + if (!m_pressedIndex.has_value()) { + // We have a right-click in an empty region, don't create rubber band. ++ m_selectionManager->setCurrentItem(-1); + return true; + } + } +@@ -1783,6 +1784,8 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + } + + return !createRubberBand; ++ } else { ++ m_selectionManager->setCurrentItem(-1); + } + + return false; +-- +GitLab + + +From cfe048eabb2e29c8e01f9a0428548f8366078b73 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Wed, 16 Apr 2025 15:52:33 +0300 +Subject: [PATCH 15/69] Clean up the current item after mouse drag if it + selects nothing + +--- + src/kitemviews/kitemlistcontroller.cpp | 16 ++++++++++++++-- + src/kitemviews/kitemlistcontroller.h | 5 +++++ + 2 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 4f5c8fbb39..e8edc33c03 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1720,7 +1720,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + + if (!m_pressedIndex.has_value()) { + // We have a right-click in an empty region, don't create rubber band. +- m_selectionManager->setCurrentItem(-1); ++ cleanUpCurrentItem(); + return true; + } + } +@@ -1785,7 +1785,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + + return !createRubberBand; + } else { +- m_selectionManager->setCurrentItem(-1); ++ cleanUpCurrentItem(); + } + + return false; +@@ -1881,6 +1881,8 @@ bool KItemListController::onRelease(const QPointF &pos, const Qt::KeyboardModifi + m_pressedMouseGlobalPos = QPointF(); + m_pressedIndex = std::nullopt; + m_clearSelectionIfItemsAreNotDragged = false; ++ // Clean up current item if nothing is selected after release from drag operation ++ cleanUpCurrentItem(); + return false; + } + +@@ -1913,4 +1915,14 @@ void KItemListController::slotStateChanged(QScroller::State newState) + } + } + ++void KItemListController::cleanUpCurrentItem() ++{ ++ if (m_selectionManager->currentItem() != -1 && m_selectionManager->selectedItems().count() == 0) { ++ if (m_selectionManager->isAnchoredSelectionActive()) { ++ m_selectionManager->endAnchoredSelection(); ++ } ++ m_selectionManager->setCurrentItem(-1); ++ } ++} ++ + #include "moc_kitemlistcontroller.cpp" +diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h +index 48da07206d..7fcda72795 100644 +--- a/src/kitemviews/kitemlistcontroller.h ++++ b/src/kitemviews/kitemlistcontroller.h +@@ -325,6 +325,11 @@ private: + bool onPress(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons); + bool onRelease(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons, bool touch); + void startRubberBand(); ++ /** ++ * Ends the anchoredSelection and sets the currentItem in selectionManager to -1. ++ * This is used to not draw the focus item when using mouse to operate the view. ++ */ ++ void cleanUpCurrentItem(); + + private: + bool m_singleClickActivationEnforced; +-- +GitLab + + +From d833acb8a5af26fef199e9dd6c1e26416947a0b9 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Wed, 16 Apr 2025 16:10:42 +0300 +Subject: [PATCH 16/69] Fix text colors + +--- + src/kitemviews/kitemlistwidget.cpp | 6 +++--- + src/kitemviews/kstandarditemlistwidget.cpp | 10 ++++------ + 2 files changed, 7 insertions(+), 9 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index ebbfb98cc6..0f85b726a8 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -619,7 +619,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + viewItemOption.rect = viewItemOption.rect.adjusted(viewItemRectAdjustment, viewItemRectAdjustment, -viewItemRectAdjustment, -viewItemRectAdjustment); + QPainterPath path; + path.addRoundedRect(viewItemOption.rect, roundness, roundness); +- QColor accentColor{widget->palette().color(QPalette::Highlight)}; ++ QColor accentColor{widget->palette().color(QPalette::Accent)}; + painter->setRenderHint(QPainter::Antialiasing); + bool current = m_current && styleState & QStyle::State_Active; + +@@ -627,9 +627,9 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg + accentColor.setAlphaF(0.0); + if (m_selected && m_hovered) { +- accentColor.setAlphaF(1.0); ++ accentColor.setAlphaF(0.5); + } else if (m_selected) { +- accentColor.setAlphaF(0.8); ++ accentColor.setAlphaF(0.4); + } else if (m_hovered) { + accentColor.setAlphaF(0.3); + } +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index b9bbb68b8a..b60aeb19ba 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -721,7 +721,7 @@ QColor KStandardItemListWidget::textColor(const QWidget &widget) const + } + + const QPalette::ColorGroup group = isActiveWindow() && widget.hasFocus() ? QPalette::Active : QPalette::Inactive; +- const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : normalTextColorRole(); ++ const QPalette::ColorRole role = normalTextColorRole(); + return styleOption().palette.color(group, role); + } + +@@ -1171,9 +1171,7 @@ void KStandardItemListWidget::updatePixmapCache() + // Prepare the pixmap that is used when the item gets hovered + if (isHovered()) { + m_hoverPixmap = m_pixmap; +- if (isSelected()) { +- KIconEffect::toActive(m_hoverPixmap); +- } ++ KIconEffect::toActive(m_hoverPixmap); + } else if (hoverOpacity() <= 0.0) { + // No hover animation is ongoing. Clear m_hoverPixmap to save memory. + m_hoverPixmap = QPixmap(); +@@ -1532,10 +1530,10 @@ void KStandardItemListWidget::updateAdditionalInfoTextColor() + const bool hasFocus = scene()->views()[0]->parentWidget()->hasFocus(); + if (m_customTextColor.isValid()) { + c1 = m_customTextColor; +- } else if (false && isSelected() && hasFocus && (m_layout != DetailsLayout || m_highlightEntireRow)) { ++ } else if (isSelected() && hasFocus && (m_layout != DetailsLayout || m_highlightEntireRow)) { + // The detail text color needs to match the main text (HighlightedText) for the same level + // of readability. We short circuit early here to avoid interpolating with another color. +- m_additionalInfoTextColor = styleOption().palette.color(QPalette::HighlightedText); ++ m_additionalInfoTextColor = styleOption().palette.color(normalTextColorRole()); + return; + } else { + c1 = styleOption().palette.text().color(); +-- +GitLab + + +From ec725291eac833b8982cda4b1592d54239626b4f Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Wed, 16 Apr 2025 16:32:35 +0300 +Subject: [PATCH 17/69] Add bit more padding around the text to take outline in + account + +--- + src/kitemviews/kstandarditemlistwidget.cpp | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index b60aeb19ba..8e2515c686 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -1171,7 +1171,9 @@ void KStandardItemListWidget::updatePixmapCache() + // Prepare the pixmap that is used when the item gets hovered + if (isHovered()) { + m_hoverPixmap = m_pixmap; +- KIconEffect::toActive(m_hoverPixmap); ++ if (isSelected()) { ++ KIconEffect::toActive(m_hoverPixmap); ++ } + } else if (hoverOpacity() <= 0.0) { + // No hover animation is ongoing. Clear m_hoverPixmap to save memory. + m_hoverPixmap = QPixmap(); +@@ -1300,7 +1302,8 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() + + const KItemListStyleOption &option = styleOption(); + const qreal padding = option.padding; +- const qreal maxWidth = size().width() - 2 * padding; ++ // adjust the max width according to new outline style ++ const qreal maxWidth = size().width() - 2 * padding - 10; + const qreal lineSpacing = m_customizedFontMetrics.lineSpacing(); + + // Initialize properties for the "text" role. It will be used as anchor +-- +GitLab + + +From 230a6221183594954086187553016d577d738a38 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Wed, 16 Apr 2025 16:36:26 +0300 +Subject: [PATCH 18/69] revert padding + +--- + src/kitemviews/kstandarditemlistwidget.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 8e2515c686..0303547b23 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -1303,7 +1303,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() + const KItemListStyleOption &option = styleOption(); + const qreal padding = option.padding; + // adjust the max width according to new outline style +- const qreal maxWidth = size().width() - 2 * padding - 10; ++ const qreal maxWidth = size().width() - 2 * padding; + const qreal lineSpacing = m_customizedFontMetrics.lineSpacing(); + + // Initialize properties for the "text" role. It will be used as anchor +-- +GitLab + + +From 462e3846d8f077f739d7551a0930df53d9c7069e Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 17 Apr 2025 11:41:33 +0300 +Subject: [PATCH 19/69] Use rect instead of selectionRect for the selection + painting + +Selectionrect is for mouse selection things +--- + src/kitemviews/kitemlistwidget.cpp | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 0f85b726a8..92041fc1e7 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -608,15 +608,12 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + { + QStyleOptionViewItem viewItemOption; + const int focusPenWidth = 2; +- // Small adjustment due to how QRect coordinates work +- const int viewItemRectAdjustment = focusPenWidth + 1; + const int roundness = 5; + initStyleOption(&viewItemOption); + viewItemOption.state = styleState; + viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; + viewItemOption.showDecorationSelected = true; +- viewItemOption.rect = selectionRect().toRect(); +- viewItemOption.rect = viewItemOption.rect.adjusted(viewItemRectAdjustment, viewItemRectAdjustment, -viewItemRectAdjustment, -viewItemRectAdjustment); ++ viewItemOption.rect = rect().toRect(); + QPainterPath path; + path.addRoundedRect(viewItemOption.rect, roundness, roundness); + QColor accentColor{widget->palette().color(QPalette::Accent)}; +-- +GitLab + + +From 06dbf47020e8a3bc33f8ae87a451a8418efc3306 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 17 Apr 2025 11:53:15 +0300 +Subject: [PATCH 20/69] Revert currentItem changes + +--- + src/kitemviews/kitemlistcontroller.cpp | 19 ------------------- + src/kitemviews/kitemlistcontroller.h | 5 ----- + src/kitemviews/kitemlistselectionmanager.cpp | 4 +++- + 3 files changed, 3 insertions(+), 25 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index e8edc33c03..cd60c3a41b 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -478,10 +478,6 @@ bool KItemListController::keyPressEvent(QKeyEvent *event) + return false; + } + +- if (index < 0) { +- index = 0; +- } +- + if (m_selectionManager->currentItem() != index) { + switch (m_selectionBehavior) { + case NoSelection: +@@ -1720,7 +1716,6 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + + if (!m_pressedIndex.has_value()) { + // We have a right-click in an empty region, don't create rubber band. +- cleanUpCurrentItem(); + return true; + } + } +@@ -1784,8 +1779,6 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + } + + return !createRubberBand; +- } else { +- cleanUpCurrentItem(); + } + + return false; +@@ -1881,8 +1874,6 @@ bool KItemListController::onRelease(const QPointF &pos, const Qt::KeyboardModifi + m_pressedMouseGlobalPos = QPointF(); + m_pressedIndex = std::nullopt; + m_clearSelectionIfItemsAreNotDragged = false; +- // Clean up current item if nothing is selected after release from drag operation +- cleanUpCurrentItem(); + return false; + } + +@@ -1915,14 +1906,4 @@ void KItemListController::slotStateChanged(QScroller::State newState) + } + } + +-void KItemListController::cleanUpCurrentItem() +-{ +- if (m_selectionManager->currentItem() != -1 && m_selectionManager->selectedItems().count() == 0) { +- if (m_selectionManager->isAnchoredSelectionActive()) { +- m_selectionManager->endAnchoredSelection(); +- } +- m_selectionManager->setCurrentItem(-1); +- } +-} +- + #include "moc_kitemlistcontroller.cpp" +diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h +index 7fcda72795..48da07206d 100644 +--- a/src/kitemviews/kitemlistcontroller.h ++++ b/src/kitemviews/kitemlistcontroller.h +@@ -325,11 +325,6 @@ private: + bool onPress(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons); + bool onRelease(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons, bool touch); + void startRubberBand(); +- /** +- * Ends the anchoredSelection and sets the currentItem in selectionManager to -1. +- * This is used to not draw the focus item when using mouse to operate the view. +- */ +- void cleanUpCurrentItem(); + + private: + bool m_singleClickActivationEnforced; +diff --git a/src/kitemviews/kitemlistselectionmanager.cpp b/src/kitemviews/kitemlistselectionmanager.cpp +index abf58df240..6f7f0e0776 100644 +--- a/src/kitemviews/kitemlistselectionmanager.cpp ++++ b/src/kitemviews/kitemlistselectionmanager.cpp +@@ -217,7 +217,9 @@ void KItemListSelectionManager::itemsInserted(const KItemRangeList &itemRanges) + const KItemSet previousSelection = selectedItems(); + + // Update the current item +- if (m_currentItem >= 0) { ++ if (m_currentItem < 0) { ++ setCurrentItem(0); ++ } else { + const int previousCurrent = m_currentItem; + int inc = 0; + for (const KItemRange &itemRange : itemRanges) { +-- +GitLab + + +From 71ed6a4a0745770410056ad234ee8d7104c10767 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 17 Apr 2025 12:20:14 +0300 +Subject: [PATCH 21/69] Make the focus effect hiding/showing visual only + +--- + src/kitemviews/kitemlistcontroller.cpp | 14 ++++++++++++++ + src/kitemviews/kitemlistcontroller.h | 1 + + src/kitemviews/kitemlistview.cpp | 3 +++ + src/kitemviews/kitemlistwidget.cpp | 8 +++++++- + src/kitemviews/kitemlistwidget.h | 3 +++ + 5 files changed, 28 insertions(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index cd60c3a41b..de8bd26254 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1731,6 +1731,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + if (rightClick && hitTargetIsRowEmptyRegion) { + // We have a right click outside the icon and text rect but within the hover highlight area. + // We don't want items to get selected through this, so we return now. ++ showFocusWidget(false); + return true; + } + +@@ -1779,6 +1780,8 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + } + + return !createRubberBand; ++ } else { ++ showFocusWidget(false); + } + + return false; +@@ -1906,4 +1909,15 @@ void KItemListController::slotStateChanged(QScroller::State newState) + } + } + ++void KItemListController::showFocusWidget(bool show) ++{ ++ const auto widgets = m_view->visibleItemListWidgets(); ++ for (auto widget : widgets) { ++ if (widget->isCurrent()) { ++ widget->showFocusEffect(show); ++ return; ++ } ++ } ++} ++ + #include "moc_kitemlistcontroller.cpp" +diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h +index 48da07206d..d071f20ab0 100644 +--- a/src/kitemviews/kitemlistcontroller.h ++++ b/src/kitemviews/kitemlistcontroller.h +@@ -325,6 +325,7 @@ private: + bool onPress(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons); + bool onRelease(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons, bool touch); + void startRubberBand(); ++ void showFocusWidget(bool show); + + private: + bool m_singleClickActivationEnforced; +diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp +index 265e41e6ca..4db8d4ed0a 100644 +--- a/src/kitemviews/kitemlistview.cpp ++++ b/src/kitemviews/kitemlistview.cpp +@@ -1529,6 +1529,8 @@ void KItemListView::slotCurrentChanged(int current, int previous) + + KItemListWidget *currentWidget = m_visibleItems.value(current, nullptr); + if (currentWidget) { ++ // If previous item was -1, we're setting the first item current, so we can hide focus ++ currentWidget->showFocusEffect(previous >= 0 ? true : false); + currentWidget->setCurrent(true); + } + } +@@ -1548,6 +1550,7 @@ void KItemListView::slotSelectionChanged(const KItemSet ¤t, const KItemSet + KItemListWidget *widget = it.value(); + const bool isSelected(current.contains(index)); + widget->setSelected(isSelected); ++ widget->showFocusEffect(true); + + #ifndef QT_NO_ACCESSIBILITY + if (!QAccessible::isActive()) { +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 92041fc1e7..e41f8a1557 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -37,6 +37,7 @@ KItemListWidget::KItemListWidget(KItemListWidgetInformant *informant, QGraphicsI + , m_expansionAreaHovered(false) + , m_alternateBackground(false) + , m_enabledSelectionToggle(false) ++ , m_showFocusEffect(true) + , m_data() + , m_visibleRoles() + , m_columnWidths() +@@ -634,7 +635,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + painter->fillPath(path, accentColor); + + // Focus decoration +- if (current) { ++ if (current && m_showFocusEffect) { + accentColor.setAlphaF(1.0); + // Set the pen color lighter or darker depending on background color + const QPen pen{m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110), focusPenWidth}; +@@ -643,4 +644,9 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + } + } + ++void KItemListWidget::showFocusEffect(bool show) ++{ ++ m_showFocusEffect = show; ++} ++ + #include "moc_kitemlistwidget.cpp" +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index 0e07d7ab55..06ed511155 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -194,6 +194,8 @@ public: + */ + virtual void startActivateSoonAnimation(int timeUntilActivation); + ++ void showFocusEffect(bool showFocusEffect); ++ + Q_SIGNALS: + void roleEditingCanceled(int index, const QByteArray &role, const QVariant &value); + void roleEditingFinished(int index, const QByteArray &role, const QVariant &value); +@@ -258,6 +260,7 @@ private: + bool m_expansionAreaHovered; + bool m_alternateBackground; + bool m_enabledSelectionToggle; ++ bool m_showFocusEffect; + QHash m_data; + QList m_visibleRoles; + QHash m_columnWidths; +-- +GitLab + + +From e89ce5966ac02f7349922b4a0794d433f705d1dd Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 17 Apr 2025 14:46:51 +0300 +Subject: [PATCH 22/69] Start drag from background area + +Now that we have full size selection item, starting +drag when mouse is in there makes sense. + +Signed-off-by: Akseli Lahtinen +--- + src/kitemviews/kitemlistcontroller.cpp | 14 +------------- + 1 file changed, 1 insertion(+), 13 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index de8bd26254..3757fae1f2 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1721,19 +1721,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + } + + if (m_pressedIndex.has_value()) { +- // The hover highlight area of an item is being pressed. +- const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect +- const bool hitTargetIsRowEmptyRegion = !row->contains(row->mapFromItem(m_view, pos)); +- // again, when this method returns false, a rubberBand selection is created as the event is not consumed; +- // createRubberBand here tells us whether to return true or false. +- bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); +- +- if (rightClick && hitTargetIsRowEmptyRegion) { +- // We have a right click outside the icon and text rect but within the hover highlight area. +- // We don't want items to get selected through this, so we return now. +- showFocusWidget(false); +- return true; +- } ++ bool createRubberBand = false; + + m_selectionManager->setCurrentItem(m_pressedIndex.value()); + +-- +GitLab + + +From d92820622459bf1c15f24cc76747680e7e15fbf0 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 17 Apr 2025 15:39:58 +0300 +Subject: [PATCH 23/69] Show focus effects always on keypress + +--- + src/kitemviews/kitemlistcontroller.cpp | 6 ++---- + src/kitemviews/kitemlistwidget.cpp | 5 ++++- + 2 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 3757fae1f2..190402c705 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -238,6 +238,7 @@ bool KItemListController::isSearchAsYouTypeActive() const + bool KItemListController::keyPressEvent(QKeyEvent *event) + { + int index = m_selectionManager->currentItem(); ++ showFocusWidget(true); + int key = event->key(); + const bool shiftPressed = event->modifiers() & Qt::ShiftModifier; + +@@ -1901,10 +1902,7 @@ void KItemListController::showFocusWidget(bool show) + { + const auto widgets = m_view->visibleItemListWidgets(); + for (auto widget : widgets) { +- if (widget->isCurrent()) { +- widget->showFocusEffect(show); +- return; +- } ++ widget->showFocusEffect(show); + } + } + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index e41f8a1557..174e2feb6a 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -646,7 +646,10 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + + void KItemListWidget::showFocusEffect(bool show) + { +- m_showFocusEffect = show; ++ if (m_showFocusEffect != show) { ++ m_showFocusEffect = show; ++ update(); ++ } + } + + #include "moc_kitemlistwidget.cpp" +-- +GitLab + + +From 39063dd2c47d79a1adadbeefd9c612c03fe8b24c Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 17 Apr 2025 16:20:12 +0300 +Subject: [PATCH 24/69] Rename methods, add method for checking if focus is + shown for widget + +--- + src/kitemviews/kitemlistcontroller.cpp | 8 ++++---- + src/kitemviews/kitemlistcontroller.h | 2 +- + src/kitemviews/kitemlistview.cpp | 3 --- + src/kitemviews/kitemlistwidget.cpp | 15 ++++++++++----- + src/kitemviews/kitemlistwidget.h | 5 +++-- + 5 files changed, 18 insertions(+), 15 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 190402c705..f30453e9cb 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -238,7 +238,7 @@ bool KItemListController::isSearchAsYouTypeActive() const + bool KItemListController::keyPressEvent(QKeyEvent *event) + { + int index = m_selectionManager->currentItem(); +- showFocusWidget(true); ++ showKeyboardFocusEffect(true); + int key = event->key(); + const bool shiftPressed = event->modifiers() & Qt::ShiftModifier; + +@@ -1770,7 +1770,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + + return !createRubberBand; + } else { +- showFocusWidget(false); ++ showKeyboardFocusEffect(false); + } + + return false; +@@ -1898,11 +1898,11 @@ void KItemListController::slotStateChanged(QScroller::State newState) + } + } + +-void KItemListController::showFocusWidget(bool show) ++void KItemListController::showKeyboardFocusEffect(bool show) + { + const auto widgets = m_view->visibleItemListWidgets(); + for (auto widget : widgets) { +- widget->showFocusEffect(show); ++ widget->showKeyboardFocusEffect(show); + } + } + +diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h +index d071f20ab0..d424f92dd0 100644 +--- a/src/kitemviews/kitemlistcontroller.h ++++ b/src/kitemviews/kitemlistcontroller.h +@@ -325,7 +325,7 @@ private: + bool onPress(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons); + bool onRelease(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons, bool touch); + void startRubberBand(); +- void showFocusWidget(bool show); ++ void showKeyboardFocusEffect(bool show); + + private: + bool m_singleClickActivationEnforced; +diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp +index 4db8d4ed0a..265e41e6ca 100644 +--- a/src/kitemviews/kitemlistview.cpp ++++ b/src/kitemviews/kitemlistview.cpp +@@ -1529,8 +1529,6 @@ void KItemListView::slotCurrentChanged(int current, int previous) + + KItemListWidget *currentWidget = m_visibleItems.value(current, nullptr); + if (currentWidget) { +- // If previous item was -1, we're setting the first item current, so we can hide focus +- currentWidget->showFocusEffect(previous >= 0 ? true : false); + currentWidget->setCurrent(true); + } + } +@@ -1550,7 +1548,6 @@ void KItemListView::slotSelectionChanged(const KItemSet ¤t, const KItemSet + KItemListWidget *widget = it.value(); + const bool isSelected(current.contains(index)); + widget->setSelected(isSelected); +- widget->showFocusEffect(true); + + #ifndef QT_NO_ACCESSIBILITY + if (!QAccessible::isActive()) { +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 174e2feb6a..6d1f40a444 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -37,7 +37,7 @@ KItemListWidget::KItemListWidget(KItemListWidgetInformant *informant, QGraphicsI + , m_expansionAreaHovered(false) + , m_alternateBackground(false) + , m_enabledSelectionToggle(false) +- , m_showFocusEffect(true) ++ , m_showKeyboardFocusEffect(false) + , m_data() + , m_visibleRoles() + , m_columnWidths() +@@ -635,7 +635,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + painter->fillPath(path, accentColor); + + // Focus decoration +- if (current && m_showFocusEffect) { ++ if (current && m_showKeyboardFocusEffect) { + accentColor.setAlphaF(1.0); + // Set the pen color lighter or darker depending on background color + const QPen pen{m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110), focusPenWidth}; +@@ -644,12 +644,17 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + } + } + +-void KItemListWidget::showFocusEffect(bool show) ++void KItemListWidget::showKeyboardFocusEffect(bool show) + { +- if (m_showFocusEffect != show) { +- m_showFocusEffect = show; ++ if (m_showKeyboardFocusEffect != show) { ++ m_showKeyboardFocusEffect = show; + update(); + } + } + ++bool KItemListWidget::keyboardFocusEffectShown() ++{ ++ return m_showKeyboardFocusEffect; ++} ++ + #include "moc_kitemlistwidget.cpp" +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index 06ed511155..21e2af4ba1 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -194,7 +194,8 @@ public: + */ + virtual void startActivateSoonAnimation(int timeUntilActivation); + +- void showFocusEffect(bool showFocusEffect); ++ void showKeyboardFocusEffect(bool showFocusEffect); ++ bool keyboardFocusEffectShown(); + + Q_SIGNALS: + void roleEditingCanceled(int index, const QByteArray &role, const QVariant &value); +@@ -260,7 +261,7 @@ private: + bool m_expansionAreaHovered; + bool m_alternateBackground; + bool m_enabledSelectionToggle; +- bool m_showFocusEffect; ++ bool m_showKeyboardFocusEffect; + QHash m_data; + QList m_visibleRoles; + QHash m_columnWidths; +-- +GitLab + + +From 80eaae9049df5806380de6a68f957dc503d8b06a Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 17 Apr 2025 16:50:45 +0300 +Subject: [PATCH 25/69] Show focus when selection mode is toggled or navigation + keys pressed + +--- + src/kitemviews/kitemlistcontroller.cpp | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index f30453e9cb..466bf401ed 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -222,6 +222,9 @@ bool KItemListController::singleClickActivationEnforced() const + + void KItemListController::setSelectionModeEnabled(bool enabled) + { ++ if (enabled) { ++ showKeyboardFocusEffect(true); ++ } + m_selectionMode = enabled; + } + +@@ -238,7 +241,6 @@ bool KItemListController::isSearchAsYouTypeActive() const + bool KItemListController::keyPressEvent(QKeyEvent *event) + { + int index = m_selectionManager->currentItem(); +- showKeyboardFocusEffect(true); + int key = event->key(); + const bool shiftPressed = event->modifiers() & Qt::ShiftModifier; + +@@ -291,6 +293,10 @@ bool KItemListController::keyPressEvent(QKeyEvent *event) + const bool navigationPressed = key == Qt::Key_Home || key == Qt::Key_End || key == Qt::Key_PageUp || key == Qt::Key_PageDown || key == Qt::Key_Up + || key == Qt::Key_Down || key == Qt::Key_Left || key == Qt::Key_Right; + ++ if (navigationPressed) { ++ showKeyboardFocusEffect(true); ++ } ++ + const int itemCount = m_model->count(); + + // For horizontal scroll orientation, transform +-- +GitLab + + +From 0faf1eeabd4f6be73b622b13058c0b56a473be61 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Tue, 22 Apr 2025 16:23:18 +0300 +Subject: [PATCH 26/69] Always show focus, make focus when unselected more + transparent, remove showKeyboardFocusEffect + +--- + src/kitemviews/kitemlistcontroller.cpp | 17 ----------------- + src/kitemviews/kitemlistcontroller.h | 1 - + src/kitemviews/kitemlistwidget.cpp | 23 +++++------------------ + src/kitemviews/kitemlistwidget.h | 4 ---- + 4 files changed, 5 insertions(+), 40 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 466bf401ed..cd19cd7f69 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -222,9 +222,6 @@ bool KItemListController::singleClickActivationEnforced() const + + void KItemListController::setSelectionModeEnabled(bool enabled) + { +- if (enabled) { +- showKeyboardFocusEffect(true); +- } + m_selectionMode = enabled; + } + +@@ -293,10 +290,6 @@ bool KItemListController::keyPressEvent(QKeyEvent *event) + const bool navigationPressed = key == Qt::Key_Home || key == Qt::Key_End || key == Qt::Key_PageUp || key == Qt::Key_PageDown || key == Qt::Key_Up + || key == Qt::Key_Down || key == Qt::Key_Left || key == Qt::Key_Right; + +- if (navigationPressed) { +- showKeyboardFocusEffect(true); +- } +- + const int itemCount = m_model->count(); + + // For horizontal scroll orientation, transform +@@ -1775,8 +1768,6 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + } + + return !createRubberBand; +- } else { +- showKeyboardFocusEffect(false); + } + + return false; +@@ -1904,12 +1895,4 @@ void KItemListController::slotStateChanged(QScroller::State newState) + } + } + +-void KItemListController::showKeyboardFocusEffect(bool show) +-{ +- const auto widgets = m_view->visibleItemListWidgets(); +- for (auto widget : widgets) { +- widget->showKeyboardFocusEffect(show); +- } +-} +- + #include "moc_kitemlistcontroller.cpp" +diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h +index d424f92dd0..48da07206d 100644 +--- a/src/kitemviews/kitemlistcontroller.h ++++ b/src/kitemviews/kitemlistcontroller.h +@@ -325,7 +325,6 @@ private: + bool onPress(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons); + bool onRelease(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons, bool touch); + void startRubberBand(); +- void showKeyboardFocusEffect(bool show); + + private: + bool m_singleClickActivationEnforced; +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 6d1f40a444..a67759d087 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -37,7 +37,6 @@ KItemListWidget::KItemListWidget(KItemListWidgetInformant *informant, QGraphicsI + , m_expansionAreaHovered(false) + , m_alternateBackground(false) + , m_enabledSelectionToggle(false) +- , m_showKeyboardFocusEffect(false) + , m_data() + , m_visibleRoles() + , m_columnWidths() +@@ -608,7 +607,6 @@ void KItemListWidget::clearHoverCache() + void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState) + { + QStyleOptionViewItem viewItemOption; +- const int focusPenWidth = 2; + const int roundness = 5; + initStyleOption(&viewItemOption); + viewItemOption.state = styleState; +@@ -635,26 +633,15 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + painter->fillPath(path, accentColor); + + // Focus decoration +- if (current && m_showKeyboardFocusEffect) { +- accentColor.setAlphaF(1.0); ++ if (current) { ++ accentColor = m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110); ++ accentColor.setAlphaF(m_selected || m_hovered ? 1.0 : 0.5); + // Set the pen color lighter or darker depending on background color +- const QPen pen{m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110), focusPenWidth}; ++ QPen pen{accentColor, 1.5}; ++ pen.setCosmetic(true); + painter->setPen(pen); + painter->drawPath(path); + } + } + +-void KItemListWidget::showKeyboardFocusEffect(bool show) +-{ +- if (m_showKeyboardFocusEffect != show) { +- m_showKeyboardFocusEffect = show; +- update(); +- } +-} +- +-bool KItemListWidget::keyboardFocusEffectShown() +-{ +- return m_showKeyboardFocusEffect; +-} +- + #include "moc_kitemlistwidget.cpp" +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index 21e2af4ba1..0e07d7ab55 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -194,9 +194,6 @@ public: + */ + virtual void startActivateSoonAnimation(int timeUntilActivation); + +- void showKeyboardFocusEffect(bool showFocusEffect); +- bool keyboardFocusEffectShown(); +- + Q_SIGNALS: + void roleEditingCanceled(int index, const QByteArray &role, const QVariant &value); + void roleEditingFinished(int index, const QByteArray &role, const QVariant &value); +@@ -261,7 +258,6 @@ private: + bool m_expansionAreaHovered; + bool m_alternateBackground; + bool m_enabledSelectionToggle; +- bool m_showKeyboardFocusEffect; + QHash m_data; + QList m_visibleRoles; + QHash m_columnWidths; +-- +GitLab + + +From c372ea1e5c1fa65c86f971a20a0cb4ccaf1e3d41 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Tue, 22 Apr 2025 16:59:40 +0300 +Subject: [PATCH 27/69] Fix inconsistent hover area sizing, refactor + selectionRect + +--- + src/kitemviews/kitemlistcontroller.cpp | 9 ++++----- + src/kitemviews/kitemlistview.cpp | 2 +- + src/kitemviews/kitemlistwidget.cpp | 2 +- + src/kitemviews/kitemlistwidget.h | 10 +++++----- + src/kitemviews/kstandarditemlistwidget.cpp | 14 +++++--------- + 5 files changed, 16 insertions(+), 21 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index cd19cd7f69..6ef03dc609 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -990,7 +990,7 @@ bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent *event, const + // we also unhover any old expansion toggle hovers, in case the mouse movement from expansion toggle to icon+text is too fast (i.e. newHoveredWidget is never null between the transition) + unhoverOldExpansionWidget(); + +- const bool isOverIconAndText = newHoveredWidget->iconRect().contains(mappedPos) || newHoveredWidget->textRect().contains(mappedPos); ++ const bool isOverIconAndText = newHoveredWidget->selectionRect().contains(mappedPos); + const bool hasMultipleSelection = m_selectionManager->selectedItems().count() > 1; + + if (hasMultipleSelection && !isOverIconAndText) { +@@ -1366,8 +1366,7 @@ void KItemListController::slotRubberBandChanged() + if (widgetRect.intersects(rubberBandRect)) { + // Select the full row intersecting with the rubberband rectangle + const QRectF selectionRect = widget->selectionRect().translated(widgetRect.topLeft()); +- const QRectF iconRect = widget->iconRect().translated(widgetRect.topLeft()); +- if (selectionRect.intersects(rubberBandRect) || iconRect.intersects(rubberBandRect)) { ++ if (selectionRect.intersects(rubberBandRect)) { + selectedItems.insert(index); + } + } +@@ -1661,7 +1660,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + if (selectedItemsCount > 1 && m_pressedIndex.has_value()) { + const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); + const auto mappedPos = row->mapFromItem(m_view, pos); +- if (pressedItemAlreadySelected || row->iconRect().contains(mappedPos) || row->textRect().contains(mappedPos)) { ++ if (pressedItemAlreadySelected || row->selectionRect().contains(mappedPos)) { + // we are indeed inside the text/icon rect, keep m_pressedIndex what it is + // and short-circuit for single-click activation (it will then propagate to onRelease and activate the item) + // or we just keep going for double-click activation +@@ -1744,7 +1743,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + // We rule out the latter, if the item is not clicked directly and was unselected previously. + const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); + const auto mappedPos = row->mapFromItem(m_view, pos); +- if (!row->iconRect().contains(mappedPos) && !row->textRect().contains(mappedPos) && !pressedItemAlreadySelected) { ++ if (!row->selectionRect().contains(mappedPos) && !pressedItemAlreadySelected) { + createRubberBand = true; + } else { + m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Toggle); +diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp +index 265e41e6ca..9e0a9e0e5c 100644 +--- a/src/kitemviews/kitemlistview.cpp ++++ b/src/kitemviews/kitemlistview.cpp +@@ -542,7 +542,7 @@ QRectF KItemListView::itemContextRect(int index) const + + const KItemListWidget *widget = m_visibleItems.value(index); + if (widget) { +- contextRect = widget->iconRect() | widget->textRect(); ++ contextRect = widget->selectionRect(); + contextRect.translate(itemRect(index).topLeft()); + } + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index a67759d087..8c2432967a 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -612,7 +612,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + viewItemOption.state = styleState; + viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; + viewItemOption.showDecorationSelected = true; +- viewItemOption.rect = rect().toRect(); ++ viewItemOption.rect = selectionRect().toRect(); + QPainterPath path; + path.addRoundedRect(viewItemOption.rect, roundness, roundness); + QColor accentColor{widget->palette().color(QPalette::Accent)}; +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index 0e07d7ab55..4d857c00d7 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -144,11 +144,6 @@ public: + */ + bool contains(const QPointF &point) const override; + +- /** +- * @return Rectangle for the area that shows the icon. +- */ +- virtual QRectF iconRect() const = 0; +- + /** + * @return Rectangle for the area that contains the text-properties. + */ +@@ -245,6 +240,11 @@ private Q_SLOTS: + void slotHoverSequenceTimerTimeout(); + + private: ++ /** ++ * @return Rectangle for the area that shows the icon. ++ */ ++ virtual QRectF iconRect() const = 0; ++ + void initializeSelectionToggle(); + void setHoverOpacity(qreal opacity); + void drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState); +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 0303547b23..4b061c9bb1 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -541,23 +541,19 @@ QRectF KStandardItemListWidget::selectionRect() const + { + const_cast(this)->triggerCacheRefreshing(); + +- const int padding = styleOption().padding; +- QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); +- QRectF result = adjustedIconRect | m_textRect; + if (m_highlightEntireRow) { ++ const int padding = styleOption().padding; ++ QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); ++ QRectF result = adjustedIconRect | m_textRect; + if (layoutDirection() == Qt::LeftToRight) { + result.setRight(leftPadding() + m_columnWidthSum); + } else { + result.setLeft(size().width() - m_columnWidthSum - rightPadding()); + } ++ return result; + } else { +- // Make sure values are always positive +- const int availableWidth = qAbs((size().width() - 2 * padding - result.width()) * 0.5); +- const int availableHeight = m_layout == CompactLayout ? 0 : qAbs((size().height() - 2 * padding - result.height()) * 0.5); +- result = result.adjusted(-availableWidth, -availableHeight, availableWidth, availableHeight); ++ return rect(); + } +- +- return result; + } + + QRectF KStandardItemListWidget::expansionToggleRect() const +-- +GitLab + + +From b09399593c25ab44013cf98afa61813fa628af2a Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Wed, 23 Apr 2025 11:58:20 +0300 +Subject: [PATCH 28/69] Add constexpr for roundness + +--- + src/kitemviews/kitemlistwidget.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 8c2432967a..269c9b9955 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -607,7 +607,7 @@ void KItemListWidget::clearHoverCache() + void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState) + { + QStyleOptionViewItem viewItemOption; +- const int roundness = 5; ++ constexpr int roundness = 5; // From Breeze style. + initStyleOption(&viewItemOption); + viewItemOption.state = styleState; + viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; +-- +GitLab + + +From 688624a1521d8a1d70c37af79920283fda3f8e5f Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Wed, 23 Apr 2025 12:03:58 +0300 +Subject: [PATCH 29/69] Add slight padding to compactlayout selectionRect + +--- + src/kitemviews/kstandarditemlistwidget.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 4b061c9bb1..8024d8cb54 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -541,8 +541,8 @@ QRectF KStandardItemListWidget::selectionRect() const + { + const_cast(this)->triggerCacheRefreshing(); + ++ const int padding = styleOption().padding; + if (m_highlightEntireRow) { +- const int padding = styleOption().padding; + QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); + QRectF result = adjustedIconRect | m_textRect; + if (layoutDirection() == Qt::LeftToRight) { +@@ -552,6 +552,9 @@ QRectF KStandardItemListWidget::selectionRect() const + } + return result; + } else { ++ if (m_layout == CompactLayout) { ++ return rect().adjusted(0, padding, 0, -padding); ++ } + return rect(); + } + } +-- +GitLab + + +From 320e14cc150e90bbd2a9981ac5e48973755e6d02 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Wed, 23 Apr 2025 12:11:04 +0300 +Subject: [PATCH 30/69] Add rubberband start behavior back + +--- + src/kitemviews/kitemlistcontroller.cpp | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 6ef03dc609..fd3feb1a1b 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1720,7 +1720,18 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + } + + if (m_pressedIndex.has_value()) { +- bool createRubberBand = false; ++ // The hover highlight area of an item is being pressed. ++ const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect ++ const bool hitTargetIsRowEmptyRegion = !row->contains(row->mapFromItem(m_view, pos)); ++ // again, when this method returns false, a rubberBand selection is created as the event is not consumed; ++ // createRubberBand here tells us whether to return true or false. ++ bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); ++ ++ if (rightClick && hitTargetIsRowEmptyRegion) { ++ // We have a right click outside the icon and text rect but within the hover highlight area. ++ // We don't want items to get selected through this, so we return now. ++ return true; ++ } + + m_selectionManager->setCurrentItem(m_pressedIndex.value()); + +-- +GitLab + + +From bf66254daea497b588cdaf2578f3990597188f8a Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Fri, 25 Apr 2025 11:06:02 +0300 +Subject: [PATCH 31/69] Remove hover pixmap + +--- + src/kitemviews/kstandarditemlistwidget.cpp | 18 +++--------------- + src/kitemviews/kstandarditemlistwidget.h | 1 - + 2 files changed, 3 insertions(+), 16 deletions(-) + +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 8024d8cb54..da7fd5f4c7 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -271,7 +271,6 @@ KStandardItemListWidget::KStandardItemListWidget(KItemListWidgetInformant *infor + , m_scaledPixmapSize() + , m_columnWidthSum() + , m_iconRect() +- , m_hoverPixmap() + , m_textRect() + , m_sortedVisibleRoles() + , m_expansionArea() +@@ -346,7 +345,7 @@ void KStandardItemListWidget::paint(QPainter *painter, const QStyleOptionGraphic + drawSiblingsInformation(painter); + } + +- auto pixmap = isHovered() ? m_hoverPixmap : m_pixmap; ++ auto pixmap = m_pixmap; + if (!m_overlays.isEmpty()) { + const qreal dpr = KItemViewsUtils::devicePixelRatio(this); + +@@ -388,7 +387,7 @@ void KStandardItemListWidget::paint(QPainter *painter, const QStyleOptionGraphic + { + QPainter p(&pixmap2); + p.setOpacity(hoverOpacity()); +- p.drawPixmap(0, 0, m_hoverPixmap); ++ p.drawPixmap(0, 0, m_pixmap); + } + + // Paint pixmap2 on pixmap1 using CompositionMode_Plus +@@ -1108,7 +1107,7 @@ void KStandardItemListWidget::updatePixmapCache() + } + + if (m_pixmap.isNull()) { +- m_hoverPixmap = QPixmap(); ++ m_pixmap = QPixmap(); + return; + } + +@@ -1166,17 +1165,6 @@ void KStandardItemListWidget::updatePixmapCache() + const QSizeF squareIconSize(widgetIconSize, widgetIconSize); + m_iconRect = QRectF(squareIconPos, squareIconSize); + } +- +- // Prepare the pixmap that is used when the item gets hovered +- if (isHovered()) { +- m_hoverPixmap = m_pixmap; +- if (isSelected()) { +- KIconEffect::toActive(m_hoverPixmap); +- } +- } else if (hoverOpacity() <= 0.0) { +- // No hover animation is ongoing. Clear m_hoverPixmap to save memory. +- m_hoverPixmap = QPixmap(); +- } + } + + void KStandardItemListWidget::updateTextsCache() +diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h +index 594d3e4928..3dbf442913 100644 +--- a/src/kitemviews/kstandarditemlistwidget.h ++++ b/src/kitemviews/kstandarditemlistwidget.h +@@ -280,7 +280,6 @@ private: + + qreal m_columnWidthSum; + QRectF m_iconRect; // Cache for KItemListWidget::iconRect() +- QPixmap m_hoverPixmap; // Cache for modified m_pixmap when hovering the item + + QRectF m_textRect; + +-- +GitLab + + +From f41db3725ad36175721afd430de8ea1b63867803 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Fri, 25 Apr 2025 11:12:33 +0300 +Subject: [PATCH 32/69] Change the alpha values + +--- + src/kitemviews/kitemlistwidget.cpp | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 269c9b9955..b52661e6ee 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -623,11 +623,11 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg + accentColor.setAlphaF(0.0); + if (m_selected && m_hovered) { +- accentColor.setAlphaF(0.5); ++ accentColor.setAlphaF(0.25); + } else if (m_selected) { +- accentColor.setAlphaF(0.4); ++ accentColor.setAlphaF(0.2); + } else if (m_hovered) { +- accentColor.setAlphaF(0.3); ++ accentColor.setAlphaF(0.15); + } + + painter->fillPath(path, accentColor); +@@ -635,7 +635,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + // Focus decoration + if (current) { + accentColor = m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110); +- accentColor.setAlphaF(m_selected || m_hovered ? 1.0 : 0.5); ++ accentColor.setAlphaF(m_selected || m_hovered ? 0.8 : 0.5); + // Set the pen color lighter or darker depending on background color + QPen pen{accentColor, 1.5}; + pen.setCosmetic(true); +-- +GitLab + + +From e299bf436628e58677f06513266811ac4f215f59 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Fri, 25 Apr 2025 12:53:42 +0300 +Subject: [PATCH 33/69] Set hovered effect to widgets when dragging + +--- + src/kitemviews/kitemlistcontroller.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index fd3feb1a1b..66e9ce4884 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -652,6 +652,10 @@ bool KItemListController::mouseMoveEvent(QGraphicsSceneMouseEvent *event, const + m_selectionManager->endAnchoredSelection(); + m_selectionManager->setCurrentItem(newCurrent.value()); + m_selectionManager->beginAnchoredSelection(newCurrent.value()); ++ // Set hovered effect when dragging. ++ for (const auto widget : m_view->visibleItemListWidgets()) { ++ widget->setHovered(widget->isCurrent()); ++ } + } + + if (m_view->scrollOrientation() == Qt::Vertical) { +-- +GitLab + + +From 7a96007a21cc3a844a04992bd4edb764df561039 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Fri, 25 Apr 2025 13:08:52 +0300 +Subject: [PATCH 34/69] Move virtual iconrect back to public + +--- + src/kitemviews/kitemlistwidget.h | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index 4d857c00d7..0e07d7ab55 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -144,6 +144,11 @@ public: + */ + bool contains(const QPointF &point) const override; + ++ /** ++ * @return Rectangle for the area that shows the icon. ++ */ ++ virtual QRectF iconRect() const = 0; ++ + /** + * @return Rectangle for the area that contains the text-properties. + */ +@@ -240,11 +245,6 @@ private Q_SLOTS: + void slotHoverSequenceTimerTimeout(); + + private: +- /** +- * @return Rectangle for the area that shows the icon. +- */ +- virtual QRectF iconRect() const = 0; +- + void initializeSelectionToggle(); + void setHoverOpacity(qreal opacity); + void drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState); +-- +GitLab + + +From 829d721b6ed44202ad91b4ee0ead1b578746d21f Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Fri, 25 Apr 2025 13:11:20 +0300 +Subject: [PATCH 35/69] Remove unecessary assignment + +--- + src/kitemviews/kstandarditemlistwidget.cpp | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index da7fd5f4c7..25dece0f62 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -1107,7 +1107,6 @@ void KStandardItemListWidget::updatePixmapCache() + } + + if (m_pixmap.isNull()) { +- m_pixmap = QPixmap(); + return; + } + +-- +GitLab + + +From d8d4a220cb55e0de7364abd1ebfa4666dbbfa2a8 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 28 Apr 2025 15:56:09 +0300 +Subject: [PATCH 36/69] Better alpha values + +--- + src/kitemviews/kitemlistwidget.cpp | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index b52661e6ee..1b6969130f 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -623,11 +623,11 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg + accentColor.setAlphaF(0.0); + if (m_selected && m_hovered) { +- accentColor.setAlphaF(0.25); ++ accentColor.setAlphaF(0.32); + } else if (m_selected) { +- accentColor.setAlphaF(0.2); ++ accentColor.setAlphaF(0.30); + } else if (m_hovered) { +- accentColor.setAlphaF(0.15); ++ accentColor.setAlphaF(0.20); + } + + painter->fillPath(path, accentColor); +@@ -635,7 +635,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + // Focus decoration + if (current) { + accentColor = m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110); +- accentColor.setAlphaF(m_selected || m_hovered ? 0.8 : 0.5); ++ accentColor.setAlphaF(m_selected || m_hovered ? 0.8 : 0.6); + // Set the pen color lighter or darker depending on background color + QPen pen{accentColor, 1.5}; + pen.setCosmetic(true); +-- +GitLab + + +From c116d53065c1cd71a1f5d924643824145e2e834e Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Tue, 29 Apr 2025 11:35:57 +0300 +Subject: [PATCH 37/69] Use text color as background color, modify alpha values + +--- + src/kitemviews/kitemlistwidget.cpp | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 1b6969130f..0af131c586 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -615,29 +615,31 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + viewItemOption.rect = selectionRect().toRect(); + QPainterPath path; + path.addRoundedRect(viewItemOption.rect, roundness, roundness); +- QColor accentColor{widget->palette().color(QPalette::Accent)}; ++ QColor backgroundColor{widget->palette().color(QPalette::Accent)}; + painter->setRenderHint(QPainter::Antialiasing); + bool current = m_current && styleState & QStyle::State_Active; + + // Background item, alpha values are from + // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg +- accentColor.setAlphaF(0.0); ++ backgroundColor.setAlphaF(0.0); + if (m_selected && m_hovered) { +- accentColor.setAlphaF(0.32); ++ backgroundColor.setAlphaF(0.40); + } else if (m_selected) { +- accentColor.setAlphaF(0.30); ++ backgroundColor.setAlphaF(0.32); + } else if (m_hovered) { +- accentColor.setAlphaF(0.20); ++ backgroundColor = widget->palette().color(QPalette::Text); ++ backgroundColor.setAlphaF(0.06); + } + +- painter->fillPath(path, accentColor); ++ painter->fillPath(path, backgroundColor); + + // Focus decoration + if (current) { +- accentColor = m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110); +- accentColor.setAlphaF(m_selected || m_hovered ? 0.8 : 0.6); ++ QColor focusColor{widget->palette().color(QPalette::Accent)}; ++ focusColor = m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? focusColor.darker(110) : focusColor.lighter(110); ++ focusColor.setAlphaF(m_selected || m_hovered ? 0.8 : 0.6); + // Set the pen color lighter or darker depending on background color +- QPen pen{accentColor, 1.5}; ++ QPen pen{focusColor, 1.5}; + pen.setCosmetic(true); + painter->setPen(pen); + painter->drawPath(path); +-- +GitLab + + +From 66ccf1e63224471fa80ea4d2d868c8dc31697498 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 5 May 2025 14:31:47 +0300 +Subject: [PATCH 38/69] Make sure backgrounds dont overlap at the outline + +--- + src/kitemviews/kitemlistwidget.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 0af131c586..c65c0b2d78 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -608,13 +608,14 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + { + QStyleOptionViewItem viewItemOption; + constexpr int roundness = 5; // From Breeze style. ++ constexpr qreal penWidth = 1.5; + initStyleOption(&viewItemOption); + viewItemOption.state = styleState; + viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; + viewItemOption.showDecorationSelected = true; + viewItemOption.rect = selectionRect().toRect(); + QPainterPath path; +- path.addRoundedRect(viewItemOption.rect, roundness, roundness); ++ path.addRoundedRect(selectionRect().adjusted(penWidth, penWidth, -penWidth, -penWidth), roundness, roundness); + QColor backgroundColor{widget->palette().color(QPalette::Accent)}; + painter->setRenderHint(QPainter::Antialiasing); + bool current = m_current && styleState & QStyle::State_Active; +@@ -639,7 +640,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + focusColor = m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? focusColor.darker(110) : focusColor.lighter(110); + focusColor.setAlphaF(m_selected || m_hovered ? 0.8 : 0.6); + // Set the pen color lighter or darker depending on background color +- QPen pen{focusColor, 1.5}; ++ QPen pen{focusColor, penWidth}; + pen.setCosmetic(true); + painter->setPen(pen); + painter->drawPath(path); +-- +GitLab + + +From 91f8b3123f62db459c970c46190cbf967e1050f9 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Fri, 23 May 2025 14:22:14 +0300 +Subject: [PATCH 39/69] Add horizontal margin according to icon size + +--- + src/views/dolphinitemlistview.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/views/dolphinitemlistview.cpp b/src/views/dolphinitemlistview.cpp +index d31dc11bae..7910080f82 100644 +--- a/src/views/dolphinitemlistview.cpp ++++ b/src/views/dolphinitemlistview.cpp +@@ -194,7 +194,7 @@ void DolphinItemListView::updateGridSize() + + itemHeight = padding * 3 + iconSize + option.fontMetrics.lineSpacing(); + +- horizontalMargin = 4; ++ horizontalMargin = qMax(8.0, ((iconSize + padding) / 4.0)) * qApp->devicePixelRatio(); + verticalMargin = 8; + maxTextLines = IconsModeSettings::maximumTextLines(); + break; +-- +GitLab + + +From 4884701d6f4f4e86bf490c5f5df80289f8b40873 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 26 May 2025 16:21:21 +0300 +Subject: [PATCH 40/69] Use PM_SizeGripSize for horizontal and vertical margins + +--- + src/views/dolphinitemlistview.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/views/dolphinitemlistview.cpp b/src/views/dolphinitemlistview.cpp +index 7910080f82..8529f23a76 100644 +--- a/src/views/dolphinitemlistview.cpp ++++ b/src/views/dolphinitemlistview.cpp +@@ -194,8 +194,9 @@ void DolphinItemListView::updateGridSize() + + itemHeight = padding * 3 + iconSize + option.fontMetrics.lineSpacing(); + +- horizontalMargin = qMax(8.0, ((iconSize + padding) / 4.0)) * qApp->devicePixelRatio(); +- verticalMargin = 8; ++ const auto margin = style()->pixelMetric(QStyle::PM_SizeGripSize); ++ horizontalMargin = margin; ++ verticalMargin = margin; + maxTextLines = IconsModeSettings::maximumTextLines(); + break; + } +-- +GitLab + + +From 452a00a4fe2e1552d9b1e48b4d9ab98b67007072 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 2 Jun 2025 12:34:02 +0300 +Subject: [PATCH 41/69] Refactor selectionRect to + selectionRectCore/extended/visual + +--- + src/kitemviews/kitemlistcontroller.cpp | 10 +++--- + src/kitemviews/kitemlistview.cpp | 4 +-- + src/kitemviews/kitemlistwidget.cpp | 7 ++-- + src/kitemviews/kitemlistwidget.h | 22 ++++++++---- + src/kitemviews/kstandarditemlistwidget.cpp | 41 ++++++++++++---------- + src/kitemviews/kstandarditemlistwidget.h | 5 +-- + 6 files changed, 51 insertions(+), 38 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 66e9ce4884..566f1d6a24 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -994,7 +994,7 @@ bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent *event, const + // we also unhover any old expansion toggle hovers, in case the mouse movement from expansion toggle to icon+text is too fast (i.e. newHoveredWidget is never null between the transition) + unhoverOldExpansionWidget(); + +- const bool isOverIconAndText = newHoveredWidget->selectionRect().contains(mappedPos); ++ const bool isOverIconAndText = newHoveredWidget->selectionRectCore().contains(mappedPos); + const bool hasMultipleSelection = m_selectionManager->selectedItems().count() > 1; + + if (hasMultipleSelection && !isOverIconAndText) { +@@ -1369,7 +1369,7 @@ void KItemListController::slotRubberBandChanged() + const QRectF widgetRect = m_view->itemRect(index); + if (widgetRect.intersects(rubberBandRect)) { + // Select the full row intersecting with the rubberband rectangle +- const QRectF selectionRect = widget->selectionRect().translated(widgetRect.topLeft()); ++ const QRectF selectionRect = widget->visualSelectionRect().translated(widgetRect.topLeft()); + if (selectionRect.intersects(rubberBandRect)) { + selectedItems.insert(index); + } +@@ -1470,7 +1470,7 @@ KItemListWidget *KItemListController::widgetForPos(const QPointF &pos) const + const auto widgets = m_view->visibleItemListWidgets(); + for (KItemListWidget *widget : widgets) { + const QPointF mappedPos = widget->mapFromItem(m_view, pos); +- if (widget->contains(mappedPos) || widget->selectionRect().contains(mappedPos)) { ++ if (widget->contains(mappedPos) || widget->visualSelectionRect().contains(mappedPos)) { + return widget; + } + } +@@ -1664,7 +1664,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + if (selectedItemsCount > 1 && m_pressedIndex.has_value()) { + const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); + const auto mappedPos = row->mapFromItem(m_view, pos); +- if (pressedItemAlreadySelected || row->selectionRect().contains(mappedPos)) { ++ if (pressedItemAlreadySelected || row->selectionRectCore().contains(mappedPos)) { + // we are indeed inside the text/icon rect, keep m_pressedIndex what it is + // and short-circuit for single-click activation (it will then propagate to onRelease and activate the item) + // or we just keep going for double-click activation +@@ -1758,7 +1758,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + // We rule out the latter, if the item is not clicked directly and was unselected previously. + const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); + const auto mappedPos = row->mapFromItem(m_view, pos); +- if (!row->selectionRect().contains(mappedPos) && !pressedItemAlreadySelected) { ++ if (!row->selectionRectCore().contains(mappedPos) && !pressedItemAlreadySelected) { + createRubberBand = true; + } else { + m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Toggle); +diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp +index 9e0a9e0e5c..4146dd8438 100644 +--- a/src/kitemviews/kitemlistview.cpp ++++ b/src/kitemviews/kitemlistview.cpp +@@ -425,7 +425,7 @@ std::optional KItemListView::itemAt(const QPointF &pos) const + + const KItemListWidget *widget = it.value(); + const QPointF mappedPos = widget->mapFromItem(this, pos); +- if (widget->contains(mappedPos) || widget->selectionRect().contains(mappedPos)) { ++ if (widget->contains(mappedPos) || widget->visualSelectionRect().contains(mappedPos)) { + return it.key(); + } + } +@@ -542,7 +542,7 @@ QRectF KItemListView::itemContextRect(int index) const + + const KItemListWidget *widget = m_visibleItems.value(index); + if (widget) { +- contextRect = widget->selectionRect(); ++ contextRect = widget->visualSelectionRect(); + contextRect.translate(itemRect(index).topLeft()); + } + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index c65c0b2d78..18bd4c48b3 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -407,7 +407,7 @@ bool KItemListWidget::contains(const QPointF &point) const + return false; + } + +- return iconRect().contains(point) || textRect().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); ++ return selectionRectCore().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); + } + + QRectF KItemListWidget::textFocusRect() const +@@ -613,9 +613,10 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + viewItemOption.state = styleState; + viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; + viewItemOption.showDecorationSelected = true; +- viewItemOption.rect = selectionRect().toRect(); ++ // TODO: check if we're extended or not ++ viewItemOption.rect = visualSelectionRect().toRect(); + QPainterPath path; +- path.addRoundedRect(selectionRect().adjusted(penWidth, penWidth, -penWidth, -penWidth), roundness, roundness); ++ path.addRoundedRect(visualSelectionRect().adjusted(penWidth, penWidth, -penWidth, -penWidth), roundness, roundness); + QColor backgroundColor{widget->palette().color(QPalette::Accent)}; + painter->setRenderHint(QPainter::Antialiasing); + bool current = m_current && styleState & QStyle::State_Active; +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index 0e07d7ab55..489081b604 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -144,11 +144,6 @@ public: + */ + bool contains(const QPointF &point) const override; + +- /** +- * @return Rectangle for the area that shows the icon. +- */ +- virtual QRectF iconRect() const = 0; +- + /** + * @return Rectangle for the area that contains the text-properties. + */ +@@ -164,9 +159,22 @@ public: + virtual QRectF textFocusRect() const; + + /** +- * @return Rectangle around which a selection box should be drawn if the item is selected. ++ * Used for drawing the visuals, and situations where we want the behavior of the ++ * selection to match the visuals. ++ * ++ * @return The rectangle around selection, depending on if it's full width or not. ++ */ ++ virtual QRectF visualSelectionRect() const = 0; ++ ++ /** ++ * @return Rectangle around icon and it's text: The core area of the item. ++ */ ++ virtual QRectF selectionRectCore() const = 0; ++ ++ /** ++ * @return Same as core, but extended to the full width of the details view. + */ +- virtual QRectF selectionRect() const = 0; ++ virtual QRectF selectionRectExtended() const = 0; + + /** + * @return Rectangle for the selection-toggle that is used to select or deselect an item. +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 25dece0f62..0661a19944 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -483,12 +483,6 @@ void KStandardItemListWidget::paint(QPainter *painter, const QStyleOptionGraphic + #endif + } + +-QRectF KStandardItemListWidget::iconRect() const +-{ +- const_cast(this)->triggerCacheRefreshing(); +- return m_iconRect; +-} +- + QRectF KStandardItemListWidget::textRect() const + { + const_cast(this)->triggerCacheRefreshing(); +@@ -536,28 +530,37 @@ QRectF KStandardItemListWidget::textFocusRect() const + return m_textRect; + } + +-QRectF KStandardItemListWidget::selectionRect() const ++QRectF KStandardItemListWidget::visualSelectionRect() const + { + const_cast(this)->triggerCacheRefreshing(); +- +- const int padding = styleOption().padding; + if (m_highlightEntireRow) { +- QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); +- QRectF result = adjustedIconRect | m_textRect; +- if (layoutDirection() == Qt::LeftToRight) { +- result.setRight(leftPadding() + m_columnWidthSum); +- } else { +- result.setLeft(size().width() - m_columnWidthSum - rightPadding()); +- } +- return result; ++ return selectionRectExtended(); + } else { + if (m_layout == CompactLayout) { +- return rect().adjusted(0, padding, 0, -padding); ++ const int padding = styleOption().padding; ++ return rect().adjusted(-padding, 0, padding, 0); + } + return rect(); + } + } + ++QRectF KStandardItemListWidget::selectionRectCore() const ++{ ++ QRectF result = m_iconRect | m_textRect; ++ return result; ++} ++ ++QRectF KStandardItemListWidget::selectionRectExtended() const ++{ ++ QRectF result = selectionRectCore(); ++ if (layoutDirection() == Qt::LeftToRight) { ++ result.setRight(leftPadding() + m_columnWidthSum); ++ } else { ++ result.setLeft(size().width() - m_columnWidthSum - rightPadding()); ++ } ++ return result; ++} ++ + QRectF KStandardItemListWidget::expansionToggleRect() const + { + const_cast(this)->triggerCacheRefreshing(); +@@ -577,7 +580,7 @@ QRectF KStandardItemListWidget::selectionToggleRect() const + } + + const int padding = styleOption().padding; +- const QRectF selectionRectMinusPadding = selectionRect().adjusted(padding, padding, -padding, -padding); ++ const QRectF selectionRectMinusPadding = selectionRectCore().adjusted(padding, padding, -padding, -padding); + QPointF pos = selectionRectMinusPadding.topLeft(); + if (QApplication::isRightToLeft()) { + pos.setX(selectionRectMinusPadding.right() - (pos.x() + toggleSize - selectionRectMinusPadding.left())); +diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h +index 3dbf442913..c8feed1c9f 100644 +--- a/src/kitemviews/kstandarditemlistwidget.h ++++ b/src/kitemviews/kstandarditemlistwidget.h +@@ -105,10 +105,11 @@ public: + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; + +- QRectF iconRect() const override; + QRectF textRect() const override; + QRectF textFocusRect() const override; +- QRectF selectionRect() const override; ++ QRectF visualSelectionRect() const override; ++ QRectF selectionRectCore() const override; ++ QRectF selectionRectExtended() const override; + QRectF expansionToggleRect() const override; + QRectF selectionToggleRect() const override; + QPixmap createDragPixmap(const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; +-- +GitLab + + +From 6a9f1e168b201d6f6d2edf88d1eb040a208d48f5 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 2 Jun 2025 19:04:47 +0300 +Subject: [PATCH 42/69] fix emblem position + +--- + src/kitemviews/kstandarditemlistwidget.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 0661a19944..58fc9b0415 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -580,7 +580,7 @@ QRectF KStandardItemListWidget::selectionToggleRect() const + } + + const int padding = styleOption().padding; +- const QRectF selectionRectMinusPadding = selectionRectCore().adjusted(padding, padding, -padding, -padding); ++ const QRectF selectionRectMinusPadding = visualSelectionRect().adjusted(padding, padding, -padding, -padding); + QPointF pos = selectionRectMinusPadding.topLeft(); + if (QApplication::isRightToLeft()) { + pos.setX(selectionRectMinusPadding.right() - (pos.x() + toggleSize - selectionRectMinusPadding.left())); +-- +GitLab + + +From f1098aa09599e59fceacc3c90e3daf5b4c177860 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 2 Jun 2025 19:05:01 +0300 +Subject: [PATCH 43/69] fix widget contains + +--- + src/kitemviews/kitemlistwidget.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 18bd4c48b3..ea6b31861e 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -407,7 +407,7 @@ bool KItemListWidget::contains(const QPointF &point) const + return false; + } + +- return selectionRectCore().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); ++ return visualSelectionRect().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); + } + + QRectF KItemListWidget::textFocusRect() const +-- +GitLab + + +From 5e9a5e1a0801a4e9e8b3b72f741cb989e8637e18 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 2 Jun 2025 19:05:11 +0300 +Subject: [PATCH 44/69] remove unnecessary comparisons + +--- + src/kitemviews/kitemlistcontroller.cpp | 2 +- + src/kitemviews/kitemlistview.cpp | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 566f1d6a24..e398985e8a 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1470,7 +1470,7 @@ KItemListWidget *KItemListController::widgetForPos(const QPointF &pos) const + const auto widgets = m_view->visibleItemListWidgets(); + for (KItemListWidget *widget : widgets) { + const QPointF mappedPos = widget->mapFromItem(m_view, pos); +- if (widget->contains(mappedPos) || widget->visualSelectionRect().contains(mappedPos)) { ++ if (widget->contains(mappedPos)) { + return widget; + } + } +diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp +index 4146dd8438..90f2beebb9 100644 +--- a/src/kitemviews/kitemlistview.cpp ++++ b/src/kitemviews/kitemlistview.cpp +@@ -425,7 +425,7 @@ std::optional KItemListView::itemAt(const QPointF &pos) const + + const KItemListWidget *widget = it.value(); + const QPointF mappedPos = widget->mapFromItem(this, pos); +- if (widget->contains(mappedPos) || widget->visualSelectionRect().contains(mappedPos)) { ++ if (widget->contains(mappedPos)) { + return it.key(); + } + } +-- +GitLab + + +From 57d43263cbee51f0f3cb9b0675ffd9fd347791dc Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 2 Jun 2025 19:42:30 +0300 +Subject: [PATCH 45/69] Draw different selection highlights depending on + settings + +--- + src/kitemviews/kstandarditemlistwidget.cpp | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 58fc9b0415..d507d7c0f1 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -533,8 +533,12 @@ QRectF KStandardItemListWidget::textFocusRect() const + QRectF KStandardItemListWidget::visualSelectionRect() const + { + const_cast(this)->triggerCacheRefreshing(); +- if (m_highlightEntireRow) { +- return selectionRectExtended(); ++ if (m_layout == DetailsLayout) { ++ if (m_highlightEntireRow) { ++ return rect(); ++ } else { ++ return selectionRectExtended(); ++ } + } else { + if (m_layout == CompactLayout) { + const int padding = styleOption().padding; +-- +GitLab + + +From 337040cbe81adb6e443fc11045e9e2fd5f800a2b Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 2 Jun 2025 19:44:24 +0300 +Subject: [PATCH 46/69] Make sure we follow details mode selection settings + +--- + src/kitemviews/kitemlistcontroller.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index e398985e8a..45cba1a0db 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1726,7 +1726,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + if (m_pressedIndex.has_value()) { + // The hover highlight area of an item is being pressed. + const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect +- const bool hitTargetIsRowEmptyRegion = !row->contains(row->mapFromItem(m_view, pos)); ++ const bool hitTargetIsRowEmptyRegion = !row->selectionRectCore().contains(row->mapFromItem(m_view, pos)); + // again, when this method returns false, a rubberBand selection is created as the event is not consumed; + // createRubberBand here tells us whether to return true or false. + bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); +-- +GitLab + + +From e212678b7c1972cd28c72d6515ad7e52242e3082 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Tue, 3 Jun 2025 11:46:56 +0300 +Subject: [PATCH 47/69] Fix drawing for details view + +--- + src/kitemviews/kitemlistcontroller.cpp | 2 +- + src/kitemviews/kstandarditemlistwidget.cpp | 8 ++++---- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 45cba1a0db..dfe3fb0eaf 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1726,7 +1726,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + if (m_pressedIndex.has_value()) { + // The hover highlight area of an item is being pressed. + const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect +- const bool hitTargetIsRowEmptyRegion = !row->selectionRectCore().contains(row->mapFromItem(m_view, pos)); ++ const bool hitTargetIsRowEmptyRegion = !row->visualSelectionRect().contains(row->mapFromItem(m_view, pos)); + // again, when this method returns false, a rubberBand selection is created as the event is not consumed; + // createRubberBand here tells us whether to return true or false. + bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index d507d7c0f1..a233472fc6 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -533,15 +533,15 @@ QRectF KStandardItemListWidget::textFocusRect() const + QRectF KStandardItemListWidget::visualSelectionRect() const + { + const_cast(this)->triggerCacheRefreshing(); ++ const int padding = styleOption().padding; + if (m_layout == DetailsLayout) { ++ auto rect = selectionRectCore(); + if (m_highlightEntireRow) { +- return rect(); +- } else { +- return selectionRectExtended(); ++ rect = selectionRectExtended(); + } ++ return rect.adjusted(-padding, 0, padding, 0); + } else { + if (m_layout == CompactLayout) { +- const int padding = styleOption().padding; + return rect().adjusted(-padding, 0, padding, 0); + } + return rect(); +-- +GitLab + + +From 85e7e8eb933448b89138e0ce0b1d23f838711aa3 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Tue, 3 Jun 2025 12:00:17 +0300 +Subject: [PATCH 48/69] cleanup + +--- + src/kitemviews/kstandarditemlistwidget.cpp | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index a233472fc6..ed267bb25d 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -1295,7 +1295,6 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() + + const KItemListStyleOption &option = styleOption(); + const qreal padding = option.padding; +- // adjust the max width according to new outline style + const qreal maxWidth = size().width() - 2 * padding; + const qreal lineSpacing = m_customizedFontMetrics.lineSpacing(); + +-- +GitLab + + +From a22c63ce2472213ca27fe57c4feafde3985a99d7 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Tue, 3 Jun 2025 17:51:51 +0300 +Subject: [PATCH 49/69] remove hover effect when dragging + +--- + src/kitemviews/kitemlistcontroller.cpp | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index dfe3fb0eaf..561917e80e 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -652,10 +652,6 @@ bool KItemListController::mouseMoveEvent(QGraphicsSceneMouseEvent *event, const + m_selectionManager->endAnchoredSelection(); + m_selectionManager->setCurrentItem(newCurrent.value()); + m_selectionManager->beginAnchoredSelection(newCurrent.value()); +- // Set hovered effect when dragging. +- for (const auto widget : m_view->visibleItemListWidgets()) { +- widget->setHovered(widget->isCurrent()); +- } + } + + if (m_view->scrollOrientation() == Qt::Vertical) { +@@ -1363,7 +1359,7 @@ void KItemListController::slotRubberBandChanged() + + // Select all visible items that intersect with the rubberband + const auto widgets = m_view->visibleItemListWidgets(); +- for (const KItemListWidget *widget : widgets) { ++ for (KItemListWidget *widget : widgets) { + const int index = widget->index(); + + const QRectF widgetRect = m_view->itemRect(index); +-- +GitLab + + +From b4937aa0676d84beb41ee4d6750b0cee711a5682 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Wed, 4 Jun 2025 12:31:26 +0300 +Subject: [PATCH 50/69] set a click highlight color + +--- + src/kitemviews/kitemlistcontroller.cpp | 11 ++++++----- + src/kitemviews/kitemlistwidget.cpp | 14 ++++++++++++-- + src/kitemviews/kitemlistwidget.h | 3 +++ + 3 files changed, 21 insertions(+), 7 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 561917e80e..525e8107a4 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1640,6 +1640,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + // simplify the overall logic and possibilities both for users and devs. + const bool leftClick = buttons & Qt::LeftButton; + const bool rightClick = buttons & Qt::RightButton; ++ const bool singleClickActivation = m_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick); + + // The previous selection is cleared if either + // 1. The selection mode is SingleSelection, or +@@ -1664,7 +1665,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + // we are indeed inside the text/icon rect, keep m_pressedIndex what it is + // and short-circuit for single-click activation (it will then propagate to onRelease and activate the item) + // or we just keep going for double-click activation +- if (m_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) || m_singleClickActivationEnforced) { ++ if (singleClickActivation || m_singleClickActivationEnforced) { + if (!pressedItemAlreadySelected) { + // An unselected item was clicked directly while deselecting multiple other items so we mark it "current". + m_selectionManager->setCurrentItem(m_pressedIndex.value()); +@@ -1740,8 +1741,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + break; + + case SingleSelection: +- if (!leftClick || shiftOrControlPressed +- || (!m_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) && !m_singleClickActivationEnforced)) { ++ if (!leftClick || shiftOrControlPressed || (!singleClickActivation && !m_singleClickActivationEnforced)) { + m_selectionManager->setSelected(m_pressedIndex.value()); + } + break; +@@ -1764,9 +1764,10 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + } + } else if (!shiftPressed || !m_selectionManager->isAnchoredSelectionActive()) { + // Select the pressed item and start a new anchored selection +- if (!leftClick || shiftOrControlPressed +- || (!m_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) && !m_singleClickActivationEnforced)) { ++ if (!leftClick || shiftOrControlPressed || (!singleClickActivation && !m_singleClickActivationEnforced)) { + m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Select); ++ } else if (leftClick && (m_singleClickActivationEnforced || singleClickActivation)) { ++ row->setClickHighlight(true); + } + m_selectionManager->beginAnchoredSelection(m_pressedIndex.value()); + } +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index ea6b31861e..22d10d1481 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -37,6 +37,7 @@ KItemListWidget::KItemListWidget(KItemListWidgetInformant *informant, QGraphicsI + , m_expansionAreaHovered(false) + , m_alternateBackground(false) + , m_enabledSelectionToggle(false) ++ , m_clickHighlighted(false) + , m_data() + , m_visibleRoles() + , m_columnWidths() +@@ -281,6 +282,7 @@ void KItemListWidget::setHovered(bool hovered) + + m_hoverSequenceTimer.start(interval); + } else { ++ m_clickHighlighted = false; + setHoverOpacity(0.0); + + if (m_selectionToggle) { +@@ -604,6 +606,14 @@ void KItemListWidget::clearHoverCache() + m_hoverCache = nullptr; + } + ++void KItemListWidget::setClickHighlight(bool enabled) ++{ ++ if (m_clickHighlighted != enabled) { ++ m_clickHighlighted = enabled; ++ update(); ++ } ++} ++ + void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState) + { + QStyleOptionViewItem viewItemOption; +@@ -624,11 +634,11 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + // Background item, alpha values are from + // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg + backgroundColor.setAlphaF(0.0); +- if (m_selected && m_hovered) { ++ if ((m_selected && m_hovered) || m_clickHighlighted) { + backgroundColor.setAlphaF(0.40); + } else if (m_selected) { + backgroundColor.setAlphaF(0.32); +- } else if (m_hovered) { ++ } else if (m_hovered && !m_clickHighlighted) { + backgroundColor = widget->palette().color(QPalette::Text); + backgroundColor.setAlphaF(0.06); + } +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index 489081b604..415bc4b5c7 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -109,6 +109,8 @@ public: + void setEnabledSelectionToggle(bool enabled); + bool enabledSelectionToggle() const; + ++ void setClickHighlight(bool enabled); ++ + /** + * Sets the sibling information for the item and all of its parents. + * The sibling information of the upper most parent is represented by +@@ -266,6 +268,7 @@ private: + bool m_expansionAreaHovered; + bool m_alternateBackground; + bool m_enabledSelectionToggle; ++ bool m_clickHighlighted; + QHash m_data; + QList m_visibleRoles; + QHash m_columnWidths; +-- +GitLab + + +From 9f5e8f169ac98a6d2b23bf850cb6a4470a51b30d Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 5 Jun 2025 12:17:14 +0300 +Subject: [PATCH 51/69] Add hitTargetRect + +--- + src/kitemviews/kitemlistcontroller.cpp | 2 +- + src/kitemviews/kitemlistwidget.h | 11 +++++++++-- + src/kitemviews/kstandarditemlistwidget.cpp | 9 +++++++++ + src/kitemviews/kstandarditemlistwidget.h | 1 + + 4 files changed, 20 insertions(+), 3 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 525e8107a4..d5c72a875b 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1723,7 +1723,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + if (m_pressedIndex.has_value()) { + // The hover highlight area of an item is being pressed. + const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect +- const bool hitTargetIsRowEmptyRegion = !row->visualSelectionRect().contains(row->mapFromItem(m_view, pos)); ++ const bool hitTargetIsRowEmptyRegion = !row->hitTargetRect().contains(row->mapFromItem(m_view, pos)); + // again, when this method returns false, a rubberBand selection is created as the event is not consumed; + // createRubberBand here tells us whether to return true or false. + bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index 415bc4b5c7..ca0dc704b8 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -139,8 +139,8 @@ public: + int iconSize() const; + + /** +- * @return True if \a point is inside KItemListWidget::hoverRect(), +- * KItemListWidget::textRect(), KItemListWidget::selectionToggleRect() ++ * @return True if \a point is inside KItemListWidget::visualSelectionRect(), ++ * KItemListWidget::selectionToggleRect() + * or KItemListWidget::expansionToggleRect(). + * @reimp + */ +@@ -178,6 +178,13 @@ public: + */ + virtual QRectF selectionRectExtended() const = 0; + ++ /** ++ * @return Rectangle where dragging the item is allowed to start. ++ * In compact and icon views, it returns KItemListWidget::visualSelectionRect(). ++ * In details view, it returns KItemListWidget::selectionRectCore(). ++ */ ++ virtual QRectF hitTargetRect() const = 0; ++ + /** + * @return Rectangle for the selection-toggle that is used to select or deselect an item. + * Per default an empty rectangle is returned which means that no selection-toggle +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index ed267bb25d..46374d577b 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -565,6 +565,15 @@ QRectF KStandardItemListWidget::selectionRectExtended() const + return result; + } + ++QRectF KStandardItemListWidget::hitTargetRect() const ++{ ++ if (m_layout == DetailsLayout) { ++ return selectionRectCore(); ++ } else { ++ return visualSelectionRect(); ++ } ++} ++ + QRectF KStandardItemListWidget::expansionToggleRect() const + { + const_cast(this)->triggerCacheRefreshing(); +diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h +index c8feed1c9f..b9deed7454 100644 +--- a/src/kitemviews/kstandarditemlistwidget.h ++++ b/src/kitemviews/kstandarditemlistwidget.h +@@ -110,6 +110,7 @@ public: + QRectF visualSelectionRect() const override; + QRectF selectionRectCore() const override; + QRectF selectionRectExtended() const override; ++ QRectF hitTargetRect() const override; + QRectF expansionToggleRect() const override; + QRectF selectionToggleRect() const override; + QPixmap createDragPixmap(const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; +-- +GitLab + + +From a58b2bcb52433019b1682113ae0feeebf7113b14 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 9 Jun 2025 11:41:46 +0300 +Subject: [PATCH 52/69] Set click highlight work like toolbar click highlight + +--- + src/kitemviews/kitemlistcontroller.cpp | 8 +++++++- + src/kitemviews/kitemlistwidget.cpp | 20 ++++++++++++-------- + 2 files changed, 19 insertions(+), 9 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index d5c72a875b..5201134b9f 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -675,6 +675,10 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, con + return false; + } + ++ for (KItemListWidget *widget : m_view->visibleItemListWidgets()) { ++ widget->setClickHighlight(false); ++ } ++ + if (m_view->m_tapAndHoldIndicator->isActive()) { + m_view->m_tapAndHoldIndicator->setActive(false); + } +@@ -1029,6 +1033,7 @@ bool KItemListController::hoverLeaveEvent(QGraphicsSceneHoverEvent *event, const + + const auto widgets = m_view->visibleItemListWidgets(); + for (KItemListWidget *widget : widgets) { ++ widget->setClickHighlight(false); + if (widget->isHovered()) { + widget->setHovered(false); + Q_EMIT itemUnhovered(widget->index()); +@@ -1766,7 +1771,8 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + // Select the pressed item and start a new anchored selection + if (!leftClick || shiftOrControlPressed || (!singleClickActivation && !m_singleClickActivationEnforced)) { + m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Select); +- } else if (leftClick && (m_singleClickActivationEnforced || singleClickActivation)) { ++ } ++ if (leftClick) { + row->setClickHighlight(true); + } + m_selectionManager->beginAnchoredSelection(m_pressedIndex.value()); +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 22d10d1481..a14d28162a 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -282,7 +282,6 @@ void KItemListWidget::setHovered(bool hovered) + + m_hoverSequenceTimer.start(interval); + } else { +- m_clickHighlighted = false; + setHoverOpacity(0.0); + + if (m_selectionToggle) { +@@ -634,13 +633,18 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + // Background item, alpha values are from + // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg + backgroundColor.setAlphaF(0.0); +- if ((m_selected && m_hovered) || m_clickHighlighted) { +- backgroundColor.setAlphaF(0.40); +- } else if (m_selected) { +- backgroundColor.setAlphaF(0.32); +- } else if (m_hovered && !m_clickHighlighted) { +- backgroundColor = widget->palette().color(QPalette::Text); +- backgroundColor.setAlphaF(0.06); ++ ++ if (m_clickHighlighted) { ++ backgroundColor.setAlphaF(0.5); ++ } else { ++ if (m_selected && m_hovered) { ++ backgroundColor.setAlphaF(0.40); ++ } else if (m_selected) { ++ backgroundColor.setAlphaF(0.32); ++ } else if (m_hovered) { ++ backgroundColor = widget->palette().color(QPalette::Text); ++ backgroundColor.setAlphaF(0.06); ++ } + } + + painter->fillPath(path, backgroundColor); +-- +GitLab + + +From cf5f5e8d2735bef7df60926ccdfc1fae1473de97 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Wed, 11 Jun 2025 13:16:01 +0300 +Subject: [PATCH 53/69] make button click highlight stronger, fix highlight not + clearing + +--- + src/kitemviews/kitemlistcontroller.cpp | 7 ++++--- + src/kitemviews/kitemlistwidget.cpp | 3 ++- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 5201134b9f..5222b9c957 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1733,6 +1733,10 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + // createRubberBand here tells us whether to return true or false. + bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); + ++ if (leftClick) { ++ row->setClickHighlight(true); ++ } ++ + if (rightClick && hitTargetIsRowEmptyRegion) { + // We have a right click outside the icon and text rect but within the hover highlight area. + // We don't want items to get selected through this, so we return now. +@@ -1772,9 +1776,6 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + if (!leftClick || shiftOrControlPressed || (!singleClickActivation && !m_singleClickActivationEnforced)) { + m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Select); + } +- if (leftClick) { +- row->setClickHighlight(true); +- } + m_selectionManager->beginAnchoredSelection(m_pressedIndex.value()); + } + break; +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index a14d28162a..eb24a19dc8 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -609,6 +609,7 @@ void KItemListWidget::setClickHighlight(bool enabled) + { + if (m_clickHighlighted != enabled) { + m_clickHighlighted = enabled; ++ clearHoverCache(); + update(); + } + } +@@ -635,7 +636,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + backgroundColor.setAlphaF(0.0); + + if (m_clickHighlighted) { +- backgroundColor.setAlphaF(0.5); ++ backgroundColor.setAlphaF(1.0); + } else { + if (m_selected && m_hovered) { + backgroundColor.setAlphaF(0.40); +-- +GitLab + + +From 4398a90bfcab35834d0fd84c4e449456509089fb Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Wed, 11 Jun 2025 13:44:04 +0300 +Subject: [PATCH 54/69] Make sure text is readable when clickHighlighted + +--- + src/kitemviews/kitemlistwidget.cpp | 5 +++++ + src/kitemviews/kitemlistwidget.h | 1 + + src/kitemviews/kstandarditemlistwidget.cpp | 6 +++++- + 3 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index eb24a19dc8..0f15aa883b 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -605,6 +605,11 @@ void KItemListWidget::clearHoverCache() + m_hoverCache = nullptr; + } + ++bool KItemListWidget::isClickHighlighted() const ++{ ++ return m_clickHighlighted; ++} ++ + void KItemListWidget::setClickHighlight(bool enabled) + { + if (m_clickHighlighted != enabled) { +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index ca0dc704b8..40b630cc4f 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -109,6 +109,7 @@ public: + void setEnabledSelectionToggle(bool enabled); + bool enabledSelectionToggle() const; + ++ bool isClickHighlighted() const; + void setClickHighlight(bool enabled); + + /** +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 46374d577b..1a2976bfeb 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -712,7 +712,11 @@ QFont KStandardItemListWidget::customizedFont(const QFont &baseFont) const + + QPalette::ColorRole KStandardItemListWidget::normalTextColorRole() const + { +- return QPalette::Text; ++ if (isClickHighlighted()) { ++ return QPalette::HighlightedText; ++ } else { ++ return QPalette::Text; ++ } + } + + void KStandardItemListWidget::setTextColor(const QColor &color) +-- +GitLab + + +From 71bcec57388d613955148b9d590c85ab977f978e Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 12 Jun 2025 18:03:53 +0300 +Subject: [PATCH 55/69] widgetForDropPos uses hitTargetRect instead of contains + +--- + src/kitemviews/kitemlistcontroller.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 5222b9c957..cb97f484d3 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1490,7 +1490,7 @@ KItemListWidget *KItemListController::widgetForDropPos(const QPointF &pos) const + const auto widgets = m_view->visibleItemListWidgets(); + for (KItemListWidget *widget : widgets) { + const QPointF mappedPos = widget->mapFromItem(m_view, pos); +- if (widget->contains(mappedPos)) { ++ if (widget->hitTargetRect().contains(mappedPos)) { + return widget; + } + } +-- +GitLab + + +From 23d522fa8a4726f8b668419fa31fbac04e6e6a84 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 12 Jun 2025 18:03:53 +0300 +Subject: [PATCH 56/69] change hitTargetRect comment + +--- + src/kitemviews/kitemlistwidget.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index 40b630cc4f..6e73bb72d5 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -180,7 +180,7 @@ public: + virtual QRectF selectionRectExtended() const = 0; + + /** +- * @return Rectangle where dragging the item is allowed to start. ++ * @return Returns rectangle where item is considered "hit" during actions, such as drag and drop. + * In compact and icon views, it returns KItemListWidget::visualSelectionRect(). + * In details view, it returns KItemListWidget::selectionRectCore(). + */ +-- +GitLab + + +From 105d70b4d6d5ae02305619cfd4fdb37b6048ddbd Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 12 Jun 2025 18:18:13 +0300 +Subject: [PATCH 57/69] Remove selectionRectExtended + +--- + src/kitemviews/kitemlistwidget.h | 5 ----- + src/kitemviews/kstandarditemlistwidget.cpp | 17 +++++------------ + src/kitemviews/kstandarditemlistwidget.h | 1 - + 3 files changed, 5 insertions(+), 18 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index 6e73bb72d5..2287683570 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -174,11 +174,6 @@ public: + */ + virtual QRectF selectionRectCore() const = 0; + +- /** +- * @return Same as core, but extended to the full width of the details view. +- */ +- virtual QRectF selectionRectExtended() const = 0; +- + /** + * @return Returns rectangle where item is considered "hit" during actions, such as drag and drop. + * In compact and icon views, it returns KItemListWidget::visualSelectionRect(). +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 1a2976bfeb..3530677e83 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -537,7 +537,11 @@ QRectF KStandardItemListWidget::visualSelectionRect() const + if (m_layout == DetailsLayout) { + auto rect = selectionRectCore(); + if (m_highlightEntireRow) { +- rect = selectionRectExtended(); ++ if (layoutDirection() == Qt::LeftToRight) { ++ rect.setRight(leftPadding() + m_columnWidthSum); ++ } else { ++ rect.setLeft(size().width() - m_columnWidthSum - rightPadding()); ++ } + } + return rect.adjusted(-padding, 0, padding, 0); + } else { +@@ -554,17 +558,6 @@ QRectF KStandardItemListWidget::selectionRectCore() const + return result; + } + +-QRectF KStandardItemListWidget::selectionRectExtended() const +-{ +- QRectF result = selectionRectCore(); +- if (layoutDirection() == Qt::LeftToRight) { +- result.setRight(leftPadding() + m_columnWidthSum); +- } else { +- result.setLeft(size().width() - m_columnWidthSum - rightPadding()); +- } +- return result; +-} +- + QRectF KStandardItemListWidget::hitTargetRect() const + { + if (m_layout == DetailsLayout) { +diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h +index b9deed7454..a85e4ee11c 100644 +--- a/src/kitemviews/kstandarditemlistwidget.h ++++ b/src/kitemviews/kstandarditemlistwidget.h +@@ -109,7 +109,6 @@ public: + QRectF textFocusRect() const override; + QRectF visualSelectionRect() const override; + QRectF selectionRectCore() const override; +- QRectF selectionRectExtended() const override; + QRectF hitTargetRect() const override; + QRectF expansionToggleRect() const override; + QRectF selectionToggleRect() const override; +-- +GitLab + + +From 18aec3429bc384e3fe8e80a95fb64e513d8d1442 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 12 Jun 2025 18:21:01 +0300 +Subject: [PATCH 58/69] Rename visualSelectionRect to selectionRectFull + +--- + src/kitemviews/kitemlistcontroller.cpp | 2 +- + src/kitemviews/kitemlistview.cpp | 2 +- + src/kitemviews/kitemlistwidget.cpp | 6 +++--- + src/kitemviews/kitemlistwidget.h | 6 +++--- + src/kitemviews/kstandarditemlistwidget.cpp | 6 +++--- + src/kitemviews/kstandarditemlistwidget.h | 2 +- + 6 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index cb97f484d3..66b5cb9696 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1370,7 +1370,7 @@ void KItemListController::slotRubberBandChanged() + const QRectF widgetRect = m_view->itemRect(index); + if (widgetRect.intersects(rubberBandRect)) { + // Select the full row intersecting with the rubberband rectangle +- const QRectF selectionRect = widget->visualSelectionRect().translated(widgetRect.topLeft()); ++ const QRectF selectionRect = widget->selectionRectFull().translated(widgetRect.topLeft()); + if (selectionRect.intersects(rubberBandRect)) { + selectedItems.insert(index); + } +diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp +index 90f2beebb9..5394e7341e 100644 +--- a/src/kitemviews/kitemlistview.cpp ++++ b/src/kitemviews/kitemlistview.cpp +@@ -542,7 +542,7 @@ QRectF KItemListView::itemContextRect(int index) const + + const KItemListWidget *widget = m_visibleItems.value(index); + if (widget) { +- contextRect = widget->visualSelectionRect(); ++ contextRect = widget->selectionRectFull(); + contextRect.translate(itemRect(index).topLeft()); + } + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 0f15aa883b..2abf9fe067 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -408,7 +408,7 @@ bool KItemListWidget::contains(const QPointF &point) const + return false; + } + +- return visualSelectionRect().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); ++ return selectionRectFull().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); + } + + QRectF KItemListWidget::textFocusRect() const +@@ -629,9 +629,9 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; + viewItemOption.showDecorationSelected = true; + // TODO: check if we're extended or not +- viewItemOption.rect = visualSelectionRect().toRect(); ++ viewItemOption.rect = selectionRectFull().toRect(); + QPainterPath path; +- path.addRoundedRect(visualSelectionRect().adjusted(penWidth, penWidth, -penWidth, -penWidth), roundness, roundness); ++ path.addRoundedRect(selectionRectFull().adjusted(penWidth, penWidth, -penWidth, -penWidth), roundness, roundness); + QColor backgroundColor{widget->palette().color(QPalette::Accent)}; + painter->setRenderHint(QPainter::Antialiasing); + bool current = m_current && styleState & QStyle::State_Active; +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index 2287683570..f277e18a73 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -140,7 +140,7 @@ public: + int iconSize() const; + + /** +- * @return True if \a point is inside KItemListWidget::visualSelectionRect(), ++ * @return True if \a point is inside KItemListWidget::selectionRectFull(), + * KItemListWidget::selectionToggleRect() + * or KItemListWidget::expansionToggleRect(). + * @reimp +@@ -167,7 +167,7 @@ public: + * + * @return The rectangle around selection, depending on if it's full width or not. + */ +- virtual QRectF visualSelectionRect() const = 0; ++ virtual QRectF selectionRectFull() const = 0; + + /** + * @return Rectangle around icon and it's text: The core area of the item. +@@ -176,7 +176,7 @@ public: + + /** + * @return Returns rectangle where item is considered "hit" during actions, such as drag and drop. +- * In compact and icon views, it returns KItemListWidget::visualSelectionRect(). ++ * In compact and icon views, it returns KItemListWidget::selectionRectFull(). + * In details view, it returns KItemListWidget::selectionRectCore(). + */ + virtual QRectF hitTargetRect() const = 0; +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 3530677e83..ba3465c041 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -530,7 +530,7 @@ QRectF KStandardItemListWidget::textFocusRect() const + return m_textRect; + } + +-QRectF KStandardItemListWidget::visualSelectionRect() const ++QRectF KStandardItemListWidget::selectionRectFull() const + { + const_cast(this)->triggerCacheRefreshing(); + const int padding = styleOption().padding; +@@ -563,7 +563,7 @@ QRectF KStandardItemListWidget::hitTargetRect() const + if (m_layout == DetailsLayout) { + return selectionRectCore(); + } else { +- return visualSelectionRect(); ++ return selectionRectFull(); + } + } + +@@ -586,7 +586,7 @@ QRectF KStandardItemListWidget::selectionToggleRect() const + } + + const int padding = styleOption().padding; +- const QRectF selectionRectMinusPadding = visualSelectionRect().adjusted(padding, padding, -padding, -padding); ++ const QRectF selectionRectMinusPadding = selectionRectFull().adjusted(padding, padding, -padding, -padding); + QPointF pos = selectionRectMinusPadding.topLeft(); + if (QApplication::isRightToLeft()) { + pos.setX(selectionRectMinusPadding.right() - (pos.x() + toggleSize - selectionRectMinusPadding.left())); +diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h +index a85e4ee11c..f2b7a49438 100644 +--- a/src/kitemviews/kstandarditemlistwidget.h ++++ b/src/kitemviews/kstandarditemlistwidget.h +@@ -107,7 +107,7 @@ public: + + QRectF textRect() const override; + QRectF textFocusRect() const override; +- QRectF visualSelectionRect() const override; ++ QRectF selectionRectFull() const override; + QRectF selectionRectCore() const override; + QRectF hitTargetRect() const override; + QRectF expansionToggleRect() const override; +-- +GitLab + + +From c1aba1674385f07858c51fc9d16376f4fab10066 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 12 Jun 2025 18:24:44 +0300 +Subject: [PATCH 59/69] rename clickHighlight to isPressed, add comment, move + items + +--- + src/kitemviews/kitemlistcontroller.cpp | 6 +++--- + src/kitemviews/kitemlistwidget.cpp | 4 ++-- + src/kitemviews/kitemlistwidget.h | 7 ++++--- + src/kitemviews/kstandarditemlistwidget.cpp | 2 +- + 4 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 66b5cb9696..1729a65cba 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -676,7 +676,7 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, con + } + + for (KItemListWidget *widget : m_view->visibleItemListWidgets()) { +- widget->setClickHighlight(false); ++ widget->setPressed(false); + } + + if (m_view->m_tapAndHoldIndicator->isActive()) { +@@ -1033,7 +1033,7 @@ bool KItemListController::hoverLeaveEvent(QGraphicsSceneHoverEvent *event, const + + const auto widgets = m_view->visibleItemListWidgets(); + for (KItemListWidget *widget : widgets) { +- widget->setClickHighlight(false); ++ widget->setPressed(false); + if (widget->isHovered()) { + widget->setHovered(false); + Q_EMIT itemUnhovered(widget->index()); +@@ -1734,7 +1734,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); + + if (leftClick) { +- row->setClickHighlight(true); ++ row->setPressed(true); + } + + if (rightClick && hitTargetIsRowEmptyRegion) { +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 2abf9fe067..a47f98ae18 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -605,12 +605,12 @@ void KItemListWidget::clearHoverCache() + m_hoverCache = nullptr; + } + +-bool KItemListWidget::isClickHighlighted() const ++bool KItemListWidget::isPressed() const + { + return m_clickHighlighted; + } + +-void KItemListWidget::setClickHighlight(bool enabled) ++void KItemListWidget::setPressed(bool enabled) + { + if (m_clickHighlighted != enabled) { + m_clickHighlighted = enabled; +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index f277e18a73..7e6b8f9c93 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -98,6 +98,10 @@ public: + void setHovered(bool hovered); + bool isHovered() const; + ++ /** Sets a purely visual pressed highlight effect. */ ++ void setPressed(bool enabled); ++ bool isPressed() const; ++ + void setExpansionAreaHovered(bool hover); + bool expansionAreaHovered() const; + +@@ -109,9 +113,6 @@ public: + void setEnabledSelectionToggle(bool enabled); + bool enabledSelectionToggle() const; + +- bool isClickHighlighted() const; +- void setClickHighlight(bool enabled); +- + /** + * Sets the sibling information for the item and all of its parents. + * The sibling information of the upper most parent is represented by +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index ba3465c041..3511666704 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -705,7 +705,7 @@ QFont KStandardItemListWidget::customizedFont(const QFont &baseFont) const + + QPalette::ColorRole KStandardItemListWidget::normalTextColorRole() const + { +- if (isClickHighlighted()) { ++ if (isPressed()) { + return QPalette::HighlightedText; + } else { + return QPalette::Text; +-- +GitLab + + +From 4af2e8ce7dfe422bfc79073e57aa0774b0bf62c0 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Thu, 12 Jun 2025 18:25:54 +0300 +Subject: [PATCH 60/69] remove todo + +--- + src/kitemviews/kitemlistwidget.cpp | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index a47f98ae18..3eb246e940 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -628,7 +628,6 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS + viewItemOption.state = styleState; + viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; + viewItemOption.showDecorationSelected = true; +- // TODO: check if we're extended or not + viewItemOption.rect = selectionRectFull().toRect(); + QPainterPath path; + path.addRoundedRect(selectionRectFull().adjusted(penWidth, penWidth, -penWidth, -penWidth), roundness, roundness); +-- +GitLab + + +From 6e4705e98dc1f00cbcd6a51d3797a39a8e7bd1c4 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Fri, 13 Jun 2025 11:34:13 +0300 +Subject: [PATCH 61/69] Remove hitTargetRect + +--- + src/kitemviews/kitemlistcontroller.cpp | 7 +++++-- + src/kitemviews/kitemlistwidget.h | 7 ------- + src/kitemviews/kstandarditemlistwidget.cpp | 9 --------- + src/kitemviews/kstandarditemlistwidget.h | 1 - + 4 files changed, 5 insertions(+), 19 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 1729a65cba..1a11d4e882 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1490,7 +1490,7 @@ KItemListWidget *KItemListController::widgetForDropPos(const QPointF &pos) const + const auto widgets = m_view->visibleItemListWidgets(); + for (KItemListWidget *widget : widgets) { + const QPointF mappedPos = widget->mapFromItem(m_view, pos); +- if (widget->hitTargetRect().contains(mappedPos)) { ++ if (widget->selectionRectCore().contains(mappedPos)) { + return widget; + } + } +@@ -1728,7 +1728,10 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + if (m_pressedIndex.has_value()) { + // The hover highlight area of an item is being pressed. + const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect +- const bool hitTargetIsRowEmptyRegion = !row->hitTargetRect().contains(row->mapFromItem(m_view, pos)); ++ ++ // When full row is highlighted, we want to be able to start dragging from anywhere except the core of the item. ++ const auto hitRect = m_view->highlightEntireRow() ? row->selectionRectCore() : row->selectionRectFull(); ++ const bool hitTargetIsRowEmptyRegion = !hitRect.contains(row->mapFromItem(m_view, pos)); + // again, when this method returns false, a rubberBand selection is created as the event is not consumed; + // createRubberBand here tells us whether to return true or false. + bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index 7e6b8f9c93..d75a4db549 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -175,13 +175,6 @@ public: + */ + virtual QRectF selectionRectCore() const = 0; + +- /** +- * @return Returns rectangle where item is considered "hit" during actions, such as drag and drop. +- * In compact and icon views, it returns KItemListWidget::selectionRectFull(). +- * In details view, it returns KItemListWidget::selectionRectCore(). +- */ +- virtual QRectF hitTargetRect() const = 0; +- + /** + * @return Rectangle for the selection-toggle that is used to select or deselect an item. + * Per default an empty rectangle is returned which means that no selection-toggle +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 3511666704..0a2cfb5968 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -558,15 +558,6 @@ QRectF KStandardItemListWidget::selectionRectCore() const + return result; + } + +-QRectF KStandardItemListWidget::hitTargetRect() const +-{ +- if (m_layout == DetailsLayout) { +- return selectionRectCore(); +- } else { +- return selectionRectFull(); +- } +-} +- + QRectF KStandardItemListWidget::expansionToggleRect() const + { + const_cast(this)->triggerCacheRefreshing(); +diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h +index f2b7a49438..cabe3a8c96 100644 +--- a/src/kitemviews/kstandarditemlistwidget.h ++++ b/src/kitemviews/kstandarditemlistwidget.h +@@ -109,7 +109,6 @@ public: + QRectF textFocusRect() const override; + QRectF selectionRectFull() const override; + QRectF selectionRectCore() const override; +- QRectF hitTargetRect() const override; + QRectF expansionToggleRect() const override; + QRectF selectionToggleRect() const override; + QPixmap createDragPixmap(const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; +-- +GitLab + + +From 7e05aa4ccc0121e415ed29dce09cbd116cd186f5 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Fri, 13 Jun 2025 19:17:19 +0300 +Subject: [PATCH 62/69] Modify selectionRectCore to return fullRect unless + dragging in details view + +--- + src/kitemviews/kitemlistcontroller.cpp | 4 +--- + src/kitemviews/kstandarditemlistwidget.cpp | 10 +++++++--- + 2 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 1a11d4e882..2afcf212e6 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1729,9 +1729,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + // The hover highlight area of an item is being pressed. + const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect + +- // When full row is highlighted, we want to be able to start dragging from anywhere except the core of the item. +- const auto hitRect = m_view->highlightEntireRow() ? row->selectionRectCore() : row->selectionRectFull(); +- const bool hitTargetIsRowEmptyRegion = !hitRect.contains(row->mapFromItem(m_view, pos)); ++ const bool hitTargetIsRowEmptyRegion = !row->selectionRectCore().contains(row->mapFromItem(m_view, pos)); + // again, when this method returns false, a rubberBand selection is created as the event is not consumed; + // createRubberBand here tells us whether to return true or false. + bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); +diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp +index 0a2cfb5968..d078b06573 100644 +--- a/src/kitemviews/kstandarditemlistwidget.cpp ++++ b/src/kitemviews/kstandarditemlistwidget.cpp +@@ -535,7 +535,7 @@ QRectF KStandardItemListWidget::selectionRectFull() const + const_cast(this)->triggerCacheRefreshing(); + const int padding = styleOption().padding; + if (m_layout == DetailsLayout) { +- auto rect = selectionRectCore(); ++ auto rect = m_iconRect | m_textRect; + if (m_highlightEntireRow) { + if (layoutDirection() == Qt::LeftToRight) { + rect.setRight(leftPadding() + m_columnWidthSum); +@@ -554,8 +554,12 @@ QRectF KStandardItemListWidget::selectionRectFull() const + + QRectF KStandardItemListWidget::selectionRectCore() const + { +- QRectF result = m_iconRect | m_textRect; +- return result; ++ // Allow dragging from selection area in details view. ++ if (m_layout == DetailsLayout && highlightEntireRow() && !isSelected()) { ++ QRectF result = m_iconRect | m_textRect; ++ return result; ++ } ++ return selectionRectFull(); + } + + QRectF KStandardItemListWidget::expansionToggleRect() const +-- +GitLab + + +From bf8220e6bac6d4f0148c465af012ff98f16ff73e Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 16 Jun 2025 11:07:05 +0300 +Subject: [PATCH 63/69] Remove unneeded check + +--- + src/kitemviews/kitemlistcontroller.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 2afcf212e6..10edf64a66 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1764,7 +1764,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + // We rule out the latter, if the item is not clicked directly and was unselected previously. + const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); + const auto mappedPos = row->mapFromItem(m_view, pos); +- if (!row->selectionRectCore().contains(mappedPos) && !pressedItemAlreadySelected) { ++ if (!row->selectionRectCore().contains(mappedPos)) { + createRubberBand = true; + } else { + m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Toggle); +-- +GitLab + + +From bc5a187f34f1566a7b5f7dacaac851519dfe17c1 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 16 Jun 2025 11:07:48 +0300 +Subject: [PATCH 64/69] add const back + +--- + src/kitemviews/kitemlistcontroller.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 10edf64a66..96f34f1a11 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1364,7 +1364,7 @@ void KItemListController::slotRubberBandChanged() + + // Select all visible items that intersect with the rubberband + const auto widgets = m_view->visibleItemListWidgets(); +- for (KItemListWidget *widget : widgets) { ++ for (const KItemListWidget *widget : widgets) { + const int index = widget->index(); + + const QRectF widgetRect = m_view->itemRect(index); +-- +GitLab + + +From 73977c43f0a6c6d82f5fc8992132138402be8f32 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 16 Jun 2025 11:09:09 +0300 +Subject: [PATCH 65/69] remove selectionToggleRect check + +--- + src/kitemviews/kitemlistwidget.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp +index 3eb246e940..c06e46339f 100644 +--- a/src/kitemviews/kitemlistwidget.cpp ++++ b/src/kitemviews/kitemlistwidget.cpp +@@ -408,7 +408,7 @@ bool KItemListWidget::contains(const QPointF &point) const + return false; + } + +- return selectionRectFull().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); ++ return selectionRectFull().contains(point) || expansionToggleRect().contains(point); + } + + QRectF KItemListWidget::textFocusRect() const +-- +GitLab + + +From 0f477b912347b5661add69dc5a8cf9ee44ecdbfb Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 16 Jun 2025 11:11:24 +0300 +Subject: [PATCH 66/69] remove presseditemalreadyselected check + +--- + src/kitemviews/kitemlistcontroller.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 96f34f1a11..5f668ce3ab 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1666,7 +1666,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + if (selectedItemsCount > 1 && m_pressedIndex.has_value()) { + const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); + const auto mappedPos = row->mapFromItem(m_view, pos); +- if (pressedItemAlreadySelected || row->selectionRectCore().contains(mappedPos)) { ++ if (row->selectionRectCore().contains(mappedPos)) { + // we are indeed inside the text/icon rect, keep m_pressedIndex what it is + // and short-circuit for single-click activation (it will then propagate to onRelease and activate the item) + // or we just keep going for double-click activation +-- +GitLab + + +From 60a92ae27e28c162fd3f4a926b4b00b818134151 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 16 Jun 2025 11:16:09 +0300 +Subject: [PATCH 67/69] add setPressed with more than one selection + +--- + src/kitemviews/kitemlistcontroller.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp +index 5f668ce3ab..fdde48abcd 100644 +--- a/src/kitemviews/kitemlistcontroller.cpp ++++ b/src/kitemviews/kitemlistcontroller.cpp +@@ -1681,6 +1681,9 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier + m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Toggle); + } + } ++ if (leftClick) { ++ row->setPressed(true); ++ } + return true; // event handled, don't create rubber band + } + } else { +-- +GitLab + + +From b3e1a4918e7165c3a19f5a9188e45ec6371fd9fa Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 16 Jun 2025 11:19:48 +0300 +Subject: [PATCH 68/69] set itemContextRect to selectionRectCore + +--- + src/kitemviews/kitemlistview.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp +index 5394e7341e..3ed4df3e7b 100644 +--- a/src/kitemviews/kitemlistview.cpp ++++ b/src/kitemviews/kitemlistview.cpp +@@ -542,7 +542,7 @@ QRectF KItemListView::itemContextRect(int index) const + + const KItemListWidget *widget = m_visibleItems.value(index); + if (widget) { +- contextRect = widget->selectionRectFull(); ++ contextRect = widget->selectionRectCore(); + contextRect.translate(itemRect(index).topLeft()); + } + +-- +GitLab + + +From 65b8c32380f9a7f8a8bf0296adfea9c976682b57 Mon Sep 17 00:00:00 2001 +From: Akseli Lahtinen +Date: Mon, 16 Jun 2025 11:20:34 +0300 +Subject: [PATCH 69/69] fix doc + +--- + src/kitemviews/kitemlistwidget.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h +index d75a4db549..b87a3b34e6 100644 +--- a/src/kitemviews/kitemlistwidget.h ++++ b/src/kitemviews/kitemlistwidget.h +@@ -166,12 +166,12 @@ public: + * Used for drawing the visuals, and situations where we want the behavior of the + * selection to match the visuals. + * +- * @return The rectangle around selection, depending on if it's full width or not. ++ * @return The rectangle around selection. + */ + virtual QRectF selectionRectFull() const = 0; + + /** +- * @return Rectangle around icon and it's text: The core area of the item. ++ * @return The core area of the item. All of it reacts exactly the same way to mouse clicks. + */ + virtual QRectF selectionRectCore() const = 0; + +-- +GitLab + diff --git a/roles/kde/patches/kwin/patches.txt b/roles/kde/patches/kwin/patches.txt new file mode 100644 index 0000000..352c63d --- /dev/null +++ b/roles/kde/patches/kwin/patches.txt @@ -0,0 +1,7 @@ +Plasma 6.5.0: +Pr 3612 https://invent.kde.org/plasma/kwin/-/merge_requests/3612 +Pr 7823 https://invent.kde.org/plasma/kwin/-/merge_requests/7823 + +Plasma 6.4.2: +Pr 7822 https://invent.kde.org/plasma/kwin/-/merge_requests/7822 +Pr 7829 https://invent.kde.org/plasma/kwin/-/merge_requests/7829 diff --git a/roles/kde/patches/kwin/pr3612.patch b/roles/kde/patches/kwin/pr3612.patch new file mode 100644 index 0000000..8a42f11 --- /dev/null +++ b/roles/kde/patches/kwin/pr3612.patch @@ -0,0 +1,2101 @@ +From 677241efbba5f2a725b247baf86a822127571225 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Thu, 16 Feb 2023 10:16:17 +0200 +Subject: [PATCH 1/2] wayland: Implement xx-pip-v1 + +The xx-pip-v1 protocol provides clients a way to create floating windows +with miniature contents, for example a video (a movie or a video call), +a map with directions, a timer countdown, etc. + +These windows are placed in the overlay layer above all windows, including +fullscreen windows. + +This is an experimental version of the protocol. +--- + CMakeLists.txt | 4 + + src/CMakeLists.txt | 2 + + src/placement.cpp | 18 ++ + src/placement.h | 1 + + src/wayland/CMakeLists.txt | 2 + + src/wayland/protocols/xx-pip-v1.xml | 305 +++++++++++++++++++++++++++ + src/wayland/xdgshell.cpp | 2 +- + src/wayland/xdgshell_p.h | 2 + + src/wayland/xxpip_v1.cpp | 312 ++++++++++++++++++++++++++++ + src/wayland/xxpip_v1.h | 159 ++++++++++++++ + src/wayland_server.cpp | 7 + + src/window.cpp | 3 + + src/window.h | 6 + + src/xxpipv1integration.cpp | 43 ++++ + src/xxpipv1integration.h | 28 +++ + src/xxpipv1window.cpp | 179 ++++++++++++++++ + src/xxpipv1window.h | 48 +++++ + tests/CMakeLists.txt | 4 + + tests/pip/CMakeLists.txt | 22 ++ + tests/pip/main.cpp | 19 ++ + tests/pip/pip.cpp | 227 ++++++++++++++++++++ + tests/pip/pip.h | 102 +++++++++ + tests/pip/pipshellsurface.cpp | 156 ++++++++++++++ + tests/pip/pipshellsurface.h | 70 +++++++ + tests/pip/window.cpp | 19 ++ + tests/pip/window.h | 22 ++ + 26 files changed, 1761 insertions(+), 1 deletion(-) + create mode 100644 src/wayland/protocols/xx-pip-v1.xml + create mode 100644 src/wayland/xxpip_v1.cpp + create mode 100644 src/wayland/xxpip_v1.h + create mode 100644 src/xxpipv1integration.cpp + create mode 100644 src/xxpipv1integration.h + create mode 100644 src/xxpipv1window.cpp + create mode 100644 src/xxpipv1window.h + create mode 100644 tests/pip/CMakeLists.txt + create mode 100644 tests/pip/main.cpp + create mode 100644 tests/pip/pip.cpp + create mode 100644 tests/pip/pip.h + create mode 100644 tests/pip/pipshellsurface.cpp + create mode 100644 tests/pip/pipshellsurface.h + create mode 100644 tests/pip/window.cpp + create mode 100644 tests/pip/window.h + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 8d4d03b8459..6ac395557c8 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -84,6 +84,10 @@ endif() + + if (BUILD_TESTING) + find_package(KPipeWire) ++ ++ if (Qt6WaylandClient_VERSION VERSION_GREATER_EQUAL "6.10.0") ++ find_package(Qt6WaylandClientPrivate ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE) ++ endif() + endif() + + # required frameworks by Core +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 48fb847ca7c..978c98f7ff3 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -211,6 +211,8 @@ target_sources(kwin PRIVATE + xdgshellintegration.cpp + xdgshellwindow.cpp + xkb.cpp ++ xxpipv1integration.cpp ++ xxpipv1window.cpp + ) + + target_link_libraries(kwin +diff --git a/src/placement.cpp b/src/placement.cpp +index 6c984282e5e..8890da56159 100644 +--- a/src/placement.cpp ++++ b/src/placement.cpp +@@ -48,6 +48,8 @@ std::optional Placement::place(const Window *c, const QRectF & + return placeOnScreenDisplay(c, area.toRect()); + } else if (c->isTransient() && c->surface()) { + return placeDialog(c, area.toRect(), options->placement()); ++ } else if (c->isPictureInPicture()) { ++ return placePictureInPicture(c, area.toRect()); + } else { + return place(c, area, options->placement()); + } +@@ -403,6 +405,22 @@ std::optional Placement::placeDialog(const Window *c, const QR + return placeOnMainWindow(c, area, nextPlacement); + } + ++std::optional Placement::placePictureInPicture(const Window *c, const QRect &area) ++{ ++ Q_ASSERT(area.isValid()); ++ ++ const QSizeF size = c->size(); ++ if (size.isEmpty()) { ++ return std::nullopt; ++ } ++ ++ const qreal x = area.x() + area.width() - size.width(); ++ const qreal y = area.y() + area.height() - size.height(); ++ ++ return QPointF(x, y); ++} ++ ++ + std::optional Placement::placeUnderMouse(const Window *c, const QRect &area, PlacementPolicy /*next*/) + { + const QSizeF size = c->size(); +diff --git a/src/placement.h b/src/placement.h +index 63be9df117f..e0da0f51ace 100644 +--- a/src/placement.h ++++ b/src/placement.h +@@ -44,6 +44,7 @@ private: + std::optional placeDialog(const Window *c, const QRect &area, PlacementPolicy next = PlacementUnknown); + std::optional placeUtility(const Window *c, const QRect &area, PlacementPolicy next = PlacementUnknown); + std::optional placeOnScreenDisplay(const Window *c, const QRect &area); ++ std::optional placePictureInPicture(const Window *c, const QRect &area); + }; + + } // namespace +diff --git a/src/wayland/CMakeLists.txt b/src/wayland/CMakeLists.txt +index fde7fc50348..7261395ecf9 100644 +--- a/src/wayland/CMakeLists.txt ++++ b/src/wayland/CMakeLists.txt +@@ -38,6 +38,7 @@ ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml + ${PROJECT_SOURCE_DIR}/src/wayland/protocols/drm.xml + ${PROJECT_SOURCE_DIR}/src/wayland/protocols/frog-color-management-v1.xml + ${PROJECT_SOURCE_DIR}/src/wayland/protocols/wlr-layer-shell-unstable-v1.xml ++ ${PROJECT_SOURCE_DIR}/src/wayland/protocols/xx-pip-v1.xml + ${PROJECT_SOURCE_DIR}/src/wayland/protocols/xx-session-management-v1.xml + + ${WaylandProtocols_DATADIR}/stable/presentation-time/presentation-time.xml +@@ -174,6 +175,7 @@ target_sources(kwin PRIVATE + xdgtopleveltag_v1.cpp + xwaylandkeyboardgrab_v1.cpp + xwaylandshell_v1.cpp ++ xxpip_v1.cpp + ) + + install(FILES +diff --git a/src/wayland/protocols/xx-pip-v1.xml b/src/wayland/protocols/xx-pip-v1.xml +new file mode 100644 +index 00000000000..c5eb7636ee9 +--- /dev/null ++++ b/src/wayland/protocols/xx-pip-v1.xml +@@ -0,0 +1,305 @@ ++ ++ ++ ++ Copyright © 2025 Vlad Zahorodnii ++ ++ Permission is hereby granted, free of charge, to any person obtaining a ++ copy of this software and associated documentation files (the "Software"), ++ to deal in the Software without restriction, including without limitation ++ the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ and/or sell copies of the Software, and to permit persons to whom the ++ Software is furnished to do so, subject to the following conditions: ++ ++ The above copyright notice and this permission notice (including the next ++ paragraph) shall be included in all copies or substantial portions of the ++ Software. ++ ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ DEALINGS IN THE SOFTWARE. ++ ++ ++ ++ ++ The xx_pip_shell_v1 interface provides a way to create picture-in-picture ++ windows. ++ ++ Use cases are for example playing a video in a separate floating window. ++ ++ Warning! The protocol described in this file is currently in the testing ++ phase. Backward compatible changes may be added together with the ++ corresponding interface version bump. Backward incompatible changes can ++ only be done by creating a new major version of the extension. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Destroy this xx_pip_shell_v1 object. Objects that have been created ++ through this instance are unaffected. ++ ++ ++ ++ ++ ++ This creates an xx_pip_v1 for the given xdg_surface and gives the ++ associated wl_surface the xx_pip_v1 role. ++ ++ If the wl_surface already has a role assigned, a role protocol error ++ will be raised. ++ ++ Creating a picture-in-picture surface from a wl_surface which has a ++ buffer attached or committed is a client error, and any attempts by ++ a client to attach or manipulate a buffer prior to the first ++ xx_pip_v1.configure event must also be treated as errors. ++ ++ After creating an xx_pip_v1 object and setting it up, the client ++ must perform an initial commit without any buffer attached. ++ The compositor will reply with a xx_pip_v1.configure event. ++ The client must acknowledge it and is then allowed to attach a buffer ++ to map the surface. ++ ++ The compositor may deny showing the picture-in-picture surface, in ++ which case it will send the closed event before the first configure ++ event. ++ ++ See the documentation of xdg_surface for more details about what an ++ xdg_surface is and how it is used. ++ ++ ++ ++ ++ ++ ++ ++ ++ This interface defines an xdg_surface role which represents a floating ++ window with some miniature contents, for example a video. ++ ++ The picture-in-picture window will be placed above all other windows. ++ Compositor-specific policies may override or customize the behavior ++ and the placement of the xx_pip_v1. For example, the compositor may ++ choose to put the xx_pip_v1 in a screen corner, etc. ++ ++ Unmapping an xx_pip_v1 means that the surface cannot be shown ++ by the compositor until it is explicitly mapped again. ++ All active operations (e.g., move, resize) are canceled and all ++ attributes (e.g. title, state, stacking, ...) are discarded for ++ an xx_pip_v1 surface when it is unmapped. The xx_pip_v1 returns to ++ the state it had right after xx_pip_shell_v1.get_pip. The client ++ can re-map the pip by perfoming a commit without any buffer ++ attached, waiting for a configure event and handling it as usual (see ++ xdg_surface description). ++ ++ Attaching a null buffer to a picture-in-picture unmaps the surface. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ This request destroys the role surface and unmaps the surface. ++ ++ ++ ++ ++ ++ Set an application identifier for the surface. ++ ++ The app ID identifies the general class of applications to which ++ the surface belongs. The compositor can use this to group multiple ++ surfaces together, or to determine how to launch a new application. ++ ++ For D-Bus activatable applications, the app ID is used as the D-Bus ++ service name. ++ ++ The compositor shell will try to group application surfaces together ++ by their app ID. As a best practice, it is suggested to select app ++ ID's that match the basename of the application's .desktop file. ++ For example, "org.freedesktop.FooViewer" where the .desktop file is ++ "org.freedesktop.FooViewer.desktop". ++ ++ Like other properties, a set_app_id request can be sent after the ++ xx_pip_v1 has been mapped to update the property. ++ ++ See the desktop-entry specification [0] for more details on ++ application identifiers and how they relate to well-known D-Bus ++ names and .desktop files. ++ ++ [0] http://standards.freedesktop.org/desktop-entry-spec/ ++ ++ ++ ++ ++ ++ ++ Set the origin surface for the picture-in-picture surface. ++ ++ The origin surface is an optional property that specifies a surface ++ from which the picture-in-picture surface has been launched. If set, ++ the compositor may use this hint to play an animation when the ++ picture-in-picture surface is mapped or unmapped. For example, smoothly ++ move the surface from the origin to a screen corner. ++ ++ If the specified origin surface is the same as the picture-in-picture ++ surface, the invalid_origin protocol error will be posted. ++ ++ The origin surface is double-buffered state, see wl_surface.commit. ++ ++ ++ ++ ++ ++ ++ Set the origin rect within the origin surface for the picture-in-picture ++ surface. ++ ++ The origin rect is an optional property that specifies the launch ++ rectangle within the origin surface. The compositor may use this hint ++ to play an animation when the picture-in-picture surface is mapped or ++ unmapped. For example, smoothly move the surface from the origin rect ++ to a screen corner. ++ ++ The origin rect is specified in the surface-local coordinate space. ++ ++ The compositor ignores the parts of the origin rect that fall outside ++ of the origin surface. ++ ++ The origin rect is double-buffered state, see wl_surface.commit. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Start an interactive, user-driven move of the surface. ++ ++ This request must be used in response to some sort of user action ++ like a button press, key press, or touch down event. The passed ++ serial is used to determine the type of interactive move (touch, ++ pointer, etc). ++ ++ The server may ignore move requests depending on the state of ++ the surface, or if the passed serial is no longer valid. ++ ++ If triggered, the surface will lose the focus of the device ++ (wl_pointer, wl_touch, etc) used for the move. It is up to the ++ compositor to visually indicate that the move is taking place, such as ++ updating a pointer cursor, during the move. There is no guarantee ++ that the device focus will return when the move is completed. ++ ++ ++ ++ ++ ++ ++ ++ These values are used to indicate which edge of a surface ++ is being dragged in a resize operation. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Start a user-driven, interactive resize of the surface. ++ ++ This request must be used in response to some sort of user action ++ like a button press, key press, or touch down event. The passed ++ serial is used to determine the type of interactive resize (touch, ++ pointer, etc). ++ ++ The server may ignore resize requests depending on the state of ++ the surface, or if the passed serial is no longer valid. ++ ++ If triggered, the surface also will lose the focus of the device ++ (wl_pointer, wl_touch, etc) used for the resize. It is up to the ++ compositor to visually indicate that the resize is taking place, ++ such as updating a pointer cursor, during the resize. There is no ++ guarantee that the device focus will return when the resize is ++ completed. ++ ++ The edges parameter specifies how the surface should be resized, ++ and is one of the values of the resize_edge enum. The compositor ++ may use this information to update the surface position for ++ example when dragging the top left corner. The compositor may also ++ use this information to adapt its behavior, e.g. choose an ++ appropriate cursor image. ++ ++ ++ ++ ++ ++ ++ ++ ++ The closed event is sent by the compositor when the surface will ++ no longer be shown. Further changes to the surface will be ignored. ++ The client should destroy the resource after receiving this event. ++ ++ ++ ++ ++ ++ The configure_bounds event may be sent prior to a xx_pip_v1.configure ++ event to communicate the bounds a surface size must be constrained to. ++ ++ The passed width and height are in surface coordinate space. ++ ++ If the surface width or the surface height is greater than the specified ++ surface size bounds, an invalid_size protocol error will be posted. ++ ++ The surface bounds subject to compositor policies. ++ ++ The bounds may change at any point, and in such a case, a new ++ xx_pip_v1.configure_bounds will be sent, followed by xx_pip_v1.configure and ++ xdg_surface.configure. ++ ++ ++ ++ ++ ++ ++ ++ This configure event asks the client to resize its pip surface. ++ The configured state should not be applied immediately. See ++ xdg_surface.configure for details. ++ ++ The width and height arguments specify a hint to the window ++ about how its surface should be resized in window geometry ++ coordinates. See set_window_geometry. ++ ++ If the width or height arguments are zero, it means the client ++ should decide its own window dimension. ++ ++ Clients must send an ack_configure in response to this event. See ++ xdg_surface.configure and xdg_surface.ack_configure for details. ++ ++ ++ ++ ++ ++ +diff --git a/src/wayland/xdgshell.cpp b/src/wayland/xdgshell.cpp +index 282678c0938..f1217e9d37a 100644 +--- a/src/wayland/xdgshell.cpp ++++ b/src/wayland/xdgshell.cpp +@@ -186,7 +186,7 @@ void XdgSurfaceInterfacePrivate::xdg_surface_destroy_resource(Resource *resource + + void XdgSurfaceInterfacePrivate::xdg_surface_destroy(Resource *resource) + { +- if (toplevel || popup) { ++ if (!toplevel.isNull() || !popup.isNull() || !pip.isNull()) { + qWarning() << "Tried to destroy xdg_surface before its role object"; + } + wl_resource_destroy(resource->handle); +diff --git a/src/wayland/xdgshell_p.h b/src/wayland/xdgshell_p.h +index 46244b23523..e48dfd8d78d 100644 +--- a/src/wayland/xdgshell_p.h ++++ b/src/wayland/xdgshell_p.h +@@ -16,6 +16,7 @@ + namespace KWin + { + class XdgToplevelDecorationV1Interface; ++class XXPipV1Interface; + + class XdgShellInterfacePrivate : public QtWaylandServer::xdg_wm_base + { +@@ -118,6 +119,7 @@ public: + XdgShellInterface *shell = nullptr; + QPointer toplevel; + QPointer popup; ++ QPointer pip; + QPointer surface; + QRect windowGeometry; + bool firstBufferAttached = false; +diff --git a/src/wayland/xxpip_v1.cpp b/src/wayland/xxpip_v1.cpp +new file mode 100644 +index 00000000000..e0b1f36134f +--- /dev/null ++++ b/src/wayland/xxpip_v1.cpp +@@ -0,0 +1,312 @@ ++/* ++ SPDX-FileCopyrightText: 2023 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL ++*/ ++ ++#include "wayland/xxpip_v1.h" ++#include "utils/resource.h" ++#include "wayland/display.h" ++#include "wayland/seat.h" ++#include "wayland/surface.h" ++#include "wayland/xdgshell_p.h" ++ ++#include "qwayland-server-xx-pip-v1.h" ++ ++namespace KWin ++{ ++ ++static const int s_version = 1; ++ ++class XXPipShellV1InterfacePrivate : public QtWaylandServer::xx_pip_shell_v1 ++{ ++public: ++ explicit XXPipShellV1InterfacePrivate(XXPipShellV1Interface *q, Display *display); ++ ++ XXPipShellV1Interface *q; ++ Display *display; ++ ++protected: ++ void xx_pip_shell_v1_destroy(Resource *resource) override; ++ void xx_pip_shell_v1_get_pip(Resource *resource, uint32_t id, struct ::wl_resource *xdg_surface) override; ++}; ++ ++XXPipShellV1InterfacePrivate::XXPipShellV1InterfacePrivate(XXPipShellV1Interface *q, Display *display) ++ : QtWaylandServer::xx_pip_shell_v1(*display, s_version) ++ , q(q) ++ , display(display) ++{ ++} ++ ++void XXPipShellV1InterfacePrivate::xx_pip_shell_v1_destroy(Resource *resource) ++{ ++ wl_resource_destroy(resource->handle); ++} ++ ++void XXPipShellV1InterfacePrivate::xx_pip_shell_v1_get_pip(Resource *resource, uint32_t id, struct ::wl_resource *xdg_surface) ++{ ++ XdgSurfaceInterface *xdgSurface = XdgSurfaceInterface::get(xdg_surface); ++ ++ if (const SurfaceRole *role = xdgSurface->surface()->role()) { ++ if (role != XXPipV1Interface::role()) { ++ wl_resource_post_error(resource->handle, error_already_constructed, "the surface already has a role assigned %s", role->name().constData()); ++ return; ++ } ++ } else { ++ xdgSurface->surface()->setRole(XXPipV1Interface::role()); ++ } ++ ++ wl_resource *pipResource = wl_resource_create(resource->client(), &xx_pip_v1_interface, resource->version(), id); ++ auto pip = new XXPipV1Interface(q, xdgSurface, pipResource); ++ ++ Q_EMIT q->pipCreated(pip); ++} ++ ++XXPipShellV1Interface::XXPipShellV1Interface(Display *display, QObject *parent) ++ : QObject(parent) ++ , d(std::make_unique(this, display)) ++{ ++} ++ ++XXPipShellV1Interface::~XXPipShellV1Interface() ++{ ++} ++ ++Display *XXPipShellV1Interface::display() const ++{ ++ return d->display; ++} ++ ++class XXPipV1Commit : public SurfaceAttachedState, public XdgSurfaceCommit ++{ ++public: ++ QPointer origin; ++ QRect originRect; ++}; ++ ++class XXPipV1InterfacePrivate : public SurfaceExtension, public QtWaylandServer::xx_pip_v1 ++{ ++public: ++ XXPipV1InterfacePrivate(XXPipV1Interface *q, XXPipShellV1Interface *shell, XdgSurfaceInterface *xdgSurface); ++ ++ void apply(XXPipV1Commit *comit); ++ void reset(); ++ ++ XXPipV1Interface *q; ++ XXPipShellV1Interface *shell; ++ XdgSurfaceInterface *xdgSurface; ++ QString applicationId; ++ QPointer origin; ++ QRect originRect; ++ ++protected: ++ void xx_pip_v1_destroy_resource(Resource *resource) override; ++ void xx_pip_v1_destroy(Resource *resource) override; ++ void xx_pip_v1_set_app_id(Resource *resource, const QString &app_id) override; ++ void xx_pip_v1_set_origin(Resource *resource, struct ::wl_resource *origin) override; ++ void xx_pip_v1_set_origin_rect(Resource *resource, int32_t x, int32_t y, uint32_t width, uint32_t height) override; ++ void xx_pip_v1_move(Resource *resource, struct ::wl_resource *seat, uint32_t serial) override; ++ void xx_pip_v1_resize(Resource *resource, struct ::wl_resource *seat, uint32_t serial, uint32_t edges) override; ++}; ++ ++XXPipV1InterfacePrivate::XXPipV1InterfacePrivate(XXPipV1Interface *q, XXPipShellV1Interface *shell, XdgSurfaceInterface *xdgSurface) ++ : SurfaceExtension(xdgSurface->surface()) ++ , q(q) ++ , shell(shell) ++ , xdgSurface(xdgSurface) ++{ ++} ++ ++void XXPipV1InterfacePrivate::apply(XXPipV1Commit *commit) ++{ ++ auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface); ++ if (xdgSurfacePrivate->firstBufferAttached && !xdgSurfacePrivate->surface->buffer()) { ++ reset(); ++ return; ++ } ++ ++ if (!commit->origin.isNull()) { ++ origin = commit->origin; ++ } ++ if (!commit->originRect.isNull()) { ++ originRect = commit->originRect; ++ } ++ ++ xdgSurfacePrivate->apply(commit); ++ ++ if (!xdgSurfacePrivate->isConfigured) { ++ Q_EMIT q->initializeRequested(); ++ } ++} ++ ++void XXPipV1InterfacePrivate::reset() ++{ ++ auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface); ++ xdgSurfacePrivate->reset(); ++ ++ Q_EMIT q->resetOccurred(); ++} ++ ++void XXPipV1InterfacePrivate::xx_pip_v1_destroy_resource(Resource *resource) ++{ ++ Q_EMIT q->aboutToBeDestroyed(); ++ delete q; ++} ++ ++void XXPipV1InterfacePrivate::xx_pip_v1_destroy(Resource *resource) ++{ ++ wl_resource_destroy(resource->handle); ++} ++ ++void XXPipV1InterfacePrivate::xx_pip_v1_set_app_id(Resource *resource, const QString &app_id) ++{ ++ if (applicationId != app_id) { ++ applicationId = app_id; ++ Q_EMIT q->applicationIdChanged(); ++ } ++} ++ ++void XXPipV1InterfacePrivate::xx_pip_v1_set_origin(Resource *resource, struct ::wl_resource *origin_resource) ++{ ++ SurfaceInterface *origin = SurfaceInterface::get(origin_resource); ++ if (origin == xdgSurface->surface()) { ++ wl_resource_post_error(resource->handle, error_invalid_origin, "pip surface cannot be its own origin"); ++ return; ++ } ++ ++ pending->origin = origin; ++} ++ ++void XXPipV1InterfacePrivate::xx_pip_v1_set_origin_rect(Resource *resource, int32_t x, int32_t y, uint32_t width, uint32_t height) ++{ ++ pending->originRect = QRect(x, y, width, height); ++} ++ ++void XXPipV1InterfacePrivate::xx_pip_v1_move(Resource *resource, struct ::wl_resource *seat_resource, uint32_t serial) ++{ ++ auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface); ++ if (!xdgSurfacePrivate->isConfigured) { ++ wl_resource_post_error(resource->handle, QtWaylandServer::xdg_surface::error_not_constructed, "surface has not been configured yet"); ++ return; ++ } ++ ++ Q_EMIT q->moveRequested(SeatInterface::get(seat_resource), serial); ++} ++ ++void XXPipV1InterfacePrivate::xx_pip_v1_resize(Resource *resource, struct ::wl_resource *seat_resource, uint32_t serial, uint32_t edges) ++{ ++ auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface); ++ if (!xdgSurfacePrivate->isConfigured) { ++ wl_resource_post_error(resource->handle, QtWaylandServer::xdg_surface::error_not_constructed, "surface has not been configured yet"); ++ return; ++ } ++ ++ Gravity gravity; ++ switch (edges) { ++ case resize_edge_none: ++ gravity = Gravity::None; ++ break; ++ case resize_edge_top: ++ gravity = Gravity::Top; ++ break; ++ case resize_edge_bottom: ++ gravity = Gravity::Bottom; ++ break; ++ case resize_edge_left: ++ gravity = Gravity::Left; ++ break; ++ case resize_edge_top_left: ++ gravity = Gravity::TopLeft; ++ break; ++ case resize_edge_bottom_left: ++ gravity = Gravity::BottomLeft; ++ break; ++ case resize_edge_right: ++ gravity = Gravity::Right; ++ break; ++ case resize_edge_top_right: ++ gravity = Gravity::TopRight; ++ break; ++ case resize_edge_bottom_right: ++ gravity = Gravity::BottomRight; ++ break; ++ default: ++ wl_resource_post_error(resource->handle, error_invalid_resize_edge, "invalid resize edge"); ++ return; ++ } ++ ++ Q_EMIT q->resizeRequested(SeatInterface::get(seat_resource), gravity, serial); ++} ++ ++XXPipV1Interface::XXPipV1Interface(XXPipShellV1Interface *shell, XdgSurfaceInterface *xdgSurface, wl_resource *resource) ++ : d(std::make_unique(this, shell, xdgSurface)) ++{ ++ XdgSurfaceInterfacePrivate *surfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface); ++ surfacePrivate->pip = this; ++ surfacePrivate->pending = d->pending; ++ ++ d->init(resource); ++} ++ ++XXPipV1Interface::~XXPipV1Interface() ++{ ++} ++ ++SurfaceRole *XXPipV1Interface::role() ++{ ++ static SurfaceRole role(QByteArrayLiteral("xx_pip_v1")); ++ return &role; ++} ++ ++bool XXPipV1Interface::isConfigured() const ++{ ++ return d->xdgSurface->isConfigured(); ++} ++ ++XdgSurfaceInterface *XXPipV1Interface::xdgSurface() const ++{ ++ return d->xdgSurface; ++} ++ ++SurfaceInterface *XXPipV1Interface::surface() const ++{ ++ return d->xdgSurface->surface(); ++} ++ ++QString XXPipV1Interface::applicationId() const ++{ ++ return d->applicationId; ++} ++ ++quint32 XXPipV1Interface::sendConfigureSize(const QSizeF &size) ++{ ++ const quint32 serial = d->shell->display()->nextSerial(); ++ ++ d->send_configure_size(size.width(), size.height()); ++ ++ auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface()); ++ xdgSurfacePrivate->send_configure(serial); ++ xdgSurfacePrivate->isConfigured = true; ++ ++ return serial; ++} ++ ++void XXPipV1Interface::sendClosed() ++{ ++ d->send_closed(); ++} ++ ++void XXPipV1Interface::sendConfigureBounds(const QSizeF &size) ++{ ++ d->send_configure_bounds(size.width(), size.height()); ++} ++ ++XXPipV1Interface *XXPipV1Interface::get(::wl_resource *resource) ++{ ++ if (auto pipPrivate = resource_cast(resource)) { ++ return pipPrivate->q; ++ } ++ return nullptr; ++} ++ ++} // namespace KWin +diff --git a/src/wayland/xxpip_v1.h b/src/wayland/xxpip_v1.h +new file mode 100644 +index 00000000000..c2737f2ec26 +--- /dev/null ++++ b/src/wayland/xxpip_v1.h +@@ -0,0 +1,159 @@ ++/* ++ SPDX-FileCopyrightText: 2023 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL ++*/ ++ ++#pragma once ++ ++#include "kwin_export.h" ++ ++#include ++ ++#include ++ ++struct wl_resource; ++ ++namespace KWin ++{ ++ ++class Display; ++class SeatInterface; ++class SurfaceInterface; ++class SurfaceRole; ++class XXPipV1Interface; ++class XXPipV1InterfacePrivate; ++class XdgSurfaceInterface; ++class XXPipShellV1InterfacePrivate; ++ ++enum class Gravity; ++ ++/** ++ * The XXPipShellV1Interface extension provides clients a way to create picture-in-picture ++ * surfaces. ++ */ ++class KWIN_EXPORT XXPipShellV1Interface : public QObject ++{ ++ Q_OBJECT ++ ++public: ++ explicit XXPipShellV1Interface(Display *display, QObject *parent = nullptr); ++ ~XXPipShellV1Interface() override; ++ ++ Display *display() const; ++ ++Q_SIGNALS: ++ void pipCreated(XXPipV1Interface *pip); ++ ++private: ++ std::unique_ptr d; ++}; ++ ++/** ++ * The XXPipV1Interface class represents a picture-in-picture surface. ++ * ++ * XXPipV1Interface corresponds to the Wayland interface \c xx_pip_v1. ++ */ ++class KWIN_EXPORT XXPipV1Interface : public QObject ++{ ++ Q_OBJECT ++ ++public: ++ XXPipV1Interface(XXPipShellV1Interface *shell, XdgSurfaceInterface *xdgSurface, wl_resource *resource); ++ ~XXPipV1Interface() override; ++ ++ static SurfaceRole *role(); ++ ++ /** ++ * Returns \c true if the popup has been configured; otherwise returns \c false. ++ */ ++ bool isConfigured() const; ++ ++ /** ++ * Returns the XdgSurfaceInterface associated with the XXPipV1Interface. ++ */ ++ XdgSurfaceInterface *xdgSurface() const; ++ ++ /** ++ * Returns the SurfaceInterface associated with the XXPipV1Interface. ++ */ ++ SurfaceInterface *surface() const; ++ ++ /** ++ * Returns the desktop file name of the pip surface. ++ */ ++ QString applicationId() const; ++ ++ /** ++ * Returns the surface from which the picture-in-picture surface has been launched, or \c null. ++ */ ++ SurfaceInterface *origin() const; ++ ++ /** ++ * Specifies the bounds within the origin surface from which the picture-in-picture surface has ++ * been launched. ++ */ ++ QRect originRect() const; ++ ++ /** ++ * Sends a configure event to the client. \a size specifies the new window geometry size. A size ++ * of zero means the client should decide its own window dimensions. ++ */ ++ quint32 sendConfigureSize(const QSizeF &size); ++ ++ /** ++ * Sends a close event to the client. The client may choose to ignore this request. ++ */ ++ void sendClosed(); ++ ++ /** ++ * Sends an event to the client specifying the maximum bounds for the surface size. Must be ++ * called before sendConfigure(). ++ */ ++ void sendConfigureBounds(const QSizeF &size); ++ ++ /** ++ * Returns the XXPipV1Interface for the specified wayland resource object \a resource. ++ */ ++ static XXPipV1Interface *get(::wl_resource *resource); ++ ++Q_SIGNALS: ++ /** ++ * This signal is emitted when the xx-pip-v1 is about to be destroyed. ++ */ ++ void aboutToBeDestroyed(); ++ ++ /** ++ * This signal is emitted when the xx-pip-v1 has commited the initial state and wants to ++ * be configured. After initializing the pip surface, you must send a configure event. ++ */ ++ void initializeRequested(); ++ ++ /** ++ * This signal is emitted when the pip surface has been unmapped and its state has been reset. ++ */ ++ void resetOccurred(); ++ ++ /** ++ * This signal is emitted when the pip wants to be interactively moved. The \a seat and ++ * the \a serial indicate the user action in response to which this request has been issued. ++ */ ++ void moveRequested(SeatInterface *seat, quint32 serial); ++ ++ /** ++ * This signal is emitted when the pip wants to be interactively resized with ++ * the specified \a gravity. The \a seat and the \a serial indicate the user action ++ * in response to which this request has been issued. ++ */ ++ void resizeRequested(SeatInterface *seat, Gravity anchor, quint32 serial); ++ ++ /** ++ * This signal is emitted when the application id changes. ++ */ ++ void applicationIdChanged(); ++ ++private: ++ std::unique_ptr d; ++}; ++ ++} // namespace KWin +diff --git a/src/wayland_server.cpp b/src/wayland_server.cpp +index 24f7fa71ebe..0d54680313a 100644 +--- a/src/wayland_server.cpp ++++ b/src/wayland_server.cpp +@@ -91,6 +91,7 @@ + #include "xdgactivationv1.h" + #include "xdgshellintegration.h" + #include "xdgshellwindow.h" ++#include "xxpipv1integration.h" + #if KWIN_BUILD_X11 + #include "wayland/xwaylandkeyboardgrab_v1.h" + #include "wayland/xwaylandshell_v1.h" +@@ -581,6 +582,12 @@ void WaylandServer::initWorkspace() + connect(layerShellV1Integration, &LayerShellV1Integration::windowCreated, + this, &WaylandServer::registerWindow); + ++ if (qEnvironmentVariableIntValue("KWIN_WAYLAND_SUPPORT_XX_PIP_V1") == 1) { ++ auto pipV1Integration = new XXPipV1Integration(this); ++ connect(pipV1Integration, &XXPipV1Integration::windowCreated, ++ this, &WaylandServer::registerWindow); ++ } ++ + new KeyStateInterface(m_display, m_display); + + VirtualDesktopManager::self()->setVirtualDesktopManagement(m_virtualDesktopManagement); +diff --git a/src/window.cpp b/src/window.cpp +index 591950ab74a..f5a4be143b8 100644 +--- a/src/window.cpp ++++ b/src/window.cpp +@@ -563,6 +563,9 @@ Layer Window::belongsToLayer() const + if (isUnmanaged() || isInternal()) { + return OverlayLayer; + } ++ if (isPictureInPicture()) { ++ return OverlayLayer; ++ } + if (isLockScreen() && !waylandServer()) { + return OverlayLayer; + } +diff --git a/src/window.h b/src/window.h +index 57be2c6891e..9ae5758de85 100644 +--- a/src/window.h ++++ b/src/window.h +@@ -781,6 +781,7 @@ public: + virtual bool isClient() const; + bool isDeleted() const; + virtual bool isUnmanaged() const; ++ virtual bool isPictureInPicture() const; + + bool isLockScreenOverlay() const; + void setLockScreenOverlay(bool allowed); +@@ -2086,6 +2087,11 @@ inline bool Window::isInternal() const + return false; + } + ++inline bool Window::isPictureInPicture() const ++{ ++ return false; ++} ++ + inline WindowItem *Window::windowItem() const + { + return m_windowItem.get(); +diff --git a/src/xxpipv1integration.cpp b/src/xxpipv1integration.cpp +new file mode 100644 +index 00000000000..b72f2cba140 +--- /dev/null ++++ b/src/xxpipv1integration.cpp +@@ -0,0 +1,43 @@ ++/* ++ SPDX-FileCopyrightText: 2023 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: GPL-2.0-or-later ++*/ ++ ++#include "xxpipv1integration.h" ++#include "wayland/xxpip_v1.h" ++#include "wayland_server.h" ++#include "workspace.h" ++#include "xxpipv1window.h" ++ ++namespace KWin ++{ ++ ++XXPipV1Integration::XXPipV1Integration(QObject *parent) ++ : WaylandShellIntegration(parent) ++{ ++ XXPipShellV1Interface *shell = new XXPipShellV1Interface(waylandServer()->display(), this); ++ connect(shell, &XXPipShellV1Interface::pipCreated, ++ this, &XXPipV1Integration::registerPipV1Surface); ++} ++ ++void XXPipV1Integration::registerPipV1Surface(XXPipV1Interface *pip) ++{ ++ createPipV1Window(pip); ++ connect(pip, &XXPipV1Interface::resetOccurred, this, [this, pip] { ++ createPipV1Window(pip); ++ }); ++} ++ ++void XXPipV1Integration::createPipV1Window(XXPipV1Interface *pip) ++{ ++ if (!workspace()) { ++ qCWarning(KWIN_CORE, "An xx-pip-v1 surface has been created while the compositor " ++ "is still not fully initialized. That is a compositor bug!"); ++ return; ++ } ++ ++ Q_EMIT windowCreated(new XXPipV1Window(pip)); ++} ++ ++} // namespace KWin +diff --git a/src/xxpipv1integration.h b/src/xxpipv1integration.h +new file mode 100644 +index 00000000000..8d2be310fe5 +--- /dev/null ++++ b/src/xxpipv1integration.h +@@ -0,0 +1,28 @@ ++/* ++ SPDX-FileCopyrightText: 2023 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: GPL-2.0-or-later ++*/ ++ ++#pragma once ++ ++#include "waylandshellintegration.h" ++ ++namespace KWin ++{ ++ ++class XXPipV1Interface; ++ ++class XXPipV1Integration : public WaylandShellIntegration ++{ ++ Q_OBJECT ++ ++public: ++ explicit XXPipV1Integration(QObject *parent = nullptr); ++ ++private: ++ void registerPipV1Surface(XXPipV1Interface *pip); ++ void createPipV1Window(XXPipV1Interface *pip); ++}; ++ ++} // namespace KWin +diff --git a/src/xxpipv1window.cpp b/src/xxpipv1window.cpp +new file mode 100644 +index 00000000000..0d6b6bafc8b +--- /dev/null ++++ b/src/xxpipv1window.cpp +@@ -0,0 +1,179 @@ ++/* ++ SPDX-FileCopyrightText: 2023 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: GPL-2.0-or-later ++*/ ++ ++#include "xxpipv1window.h" ++#include "input.h" ++#include "wayland/seat.h" ++#include "wayland/surface.h" ++#include "wayland/tablet_v2.h" ++#include "wayland_server.h" ++#include "workspace.h" ++ ++namespace KWin ++{ ++ ++XXPipV1Window::XXPipV1Window(XXPipV1Interface *shellSurface) ++ : XdgSurfaceWindow(shellSurface->xdgSurface()) ++ , m_shellSurface(shellSurface) ++{ ++ setOutput(workspace()->activeOutput()); ++ setMoveResizeOutput(workspace()->activeOutput()); ++ setOnAllDesktops(true); ++ setOnAllActivities(true); ++ ++ connect(shellSurface, &XXPipV1Interface::initializeRequested, ++ this, &XXPipV1Window::initialize); ++ connect(shellSurface, &XXPipV1Interface::aboutToBeDestroyed, ++ this, &XXPipV1Window::destroyWindow); ++ connect(shellSurface, &XXPipV1Interface::moveRequested, ++ this, &XXPipV1Window::handleMoveRequested); ++ connect(shellSurface, &XXPipV1Interface::resizeRequested, ++ this, &XXPipV1Window::handleResizeRequested); ++ connect(shellSurface, &XXPipV1Interface::applicationIdChanged, ++ this, &XXPipV1Window::handleApplicationIdChanged); ++} ++ ++void XXPipV1Window::initialize() ++{ ++ scheduleConfigure(); ++} ++ ++bool XXPipV1Window::isPictureInPicture() const ++{ ++ return true; ++} ++ ++bool XXPipV1Window::isResizable() const ++{ ++ return true; ++} ++ ++bool XXPipV1Window::isMovable() const ++{ ++ return true; ++} ++ ++bool XXPipV1Window::isMovableAcrossScreens() const ++{ ++ return true; ++} ++ ++bool XXPipV1Window::isCloseable() const ++{ ++ return true; ++} ++ ++void XXPipV1Window::closeWindow() ++{ ++ m_shellSurface->sendClosed(); ++} ++ ++bool XXPipV1Window::wantsInput() const ++{ ++ return false; ++} ++ ++bool XXPipV1Window::takeFocus() ++{ ++ return false; ++} ++ ++bool XXPipV1Window::acceptsFocus() const ++{ ++ return false; ++} ++ ++XdgSurfaceConfigure *XXPipV1Window::sendRoleConfigure() const ++{ ++ surface()->setPreferredBufferScale(nextTargetScale()); ++ surface()->setPreferredBufferTransform(preferredBufferTransform()); ++ surface()->setPreferredColorDescription(preferredColorDescription()); ++ ++ const QRectF geometry = moveResizeGeometry(); ++ if (geometry.isEmpty()) { ++ const QRectF workArea = workspace()->clientArea(PlacementArea, this, moveResizeOutput()); ++ m_shellSurface->sendConfigureBounds(workArea.size() * 0.25); ++ } ++ ++ XdgSurfaceConfigure *configureEvent = new XdgSurfaceConfigure(); ++ configureEvent->bounds = moveResizeGeometry(); ++ configureEvent->serial = m_shellSurface->sendConfigureSize(geometry.size()); ++ ++ return configureEvent; ++} ++ ++void XXPipV1Window::handleRoleDestroyed() ++{ ++ m_shellSurface->disconnect(this); ++ ++ XdgSurfaceWindow::handleRoleDestroyed(); ++} ++ ++void XXPipV1Window::handleApplicationIdChanged() ++{ ++ setResourceClass(resourceName(), m_shellSurface->applicationId()); ++ setDesktopFileName(m_shellSurface->applicationId()); ++} ++ ++void XXPipV1Window::handleMoveRequested(SeatInterface *seat, quint32 serial) ++{ ++ if (const auto anchor = input()->implicitGrabPositionBySerial(seat, serial)) { ++ performMousePressCommand(Options::MouseMove, *anchor); ++ } ++} ++ ++void XXPipV1Window::handleResizeRequested(SeatInterface *seat, Gravity gravity, quint32 serial) ++{ ++ const auto anchor = input()->implicitGrabPositionBySerial(seat, serial); ++ if (!anchor) { ++ return; ++ } ++ if (isInteractiveMoveResize()) { ++ finishInteractiveMoveResize(false); ++ } ++ setInteractiveMoveResizePointerButtonDown(true); ++ setInteractiveMoveResizeAnchor(*anchor); ++ setInteractiveMoveResizeModifiers(Qt::KeyboardModifiers()); ++ setInteractiveMoveOffset(QPointF((anchor->x() - x()) / width(), (anchor->y() - y()) / height())); ++ setUnrestrictedInteractiveMoveResize(false); ++ setInteractiveMoveResizeGravity(gravity); ++ if (!startInteractiveMoveResize()) { ++ setInteractiveMoveResizePointerButtonDown(false); ++ } ++ updateCursor(); ++} ++ ++void XXPipV1Window::doSetNextTargetScale() ++{ ++ if (isDeleted()) { ++ return; ++ } ++ if (m_shellSurface->isConfigured()) { ++ scheduleConfigure(); ++ } ++} ++ ++void XXPipV1Window::doSetPreferredBufferTransform() ++{ ++ if (isDeleted()) { ++ return; ++ } ++ if (m_shellSurface->isConfigured()) { ++ scheduleConfigure(); ++ } ++} ++ ++void XXPipV1Window::doSetPreferredColorDescription() ++{ ++ if (isDeleted()) { ++ return; ++ } ++ if (m_shellSurface->isConfigured()) { ++ scheduleConfigure(); ++ } ++} ++ ++} // namespace KWin +diff --git a/src/xxpipv1window.h b/src/xxpipv1window.h +new file mode 100644 +index 00000000000..15873e3b25f +--- /dev/null ++++ b/src/xxpipv1window.h +@@ -0,0 +1,48 @@ ++/* ++ SPDX-FileCopyrightText: 2023 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: GPL-2.0-or-later ++*/ ++ ++#pragma once ++ ++#include "wayland/xxpip_v1.h" ++#include "xdgshellwindow.h" ++ ++namespace KWin ++{ ++ ++class XXPipV1Window final : public XdgSurfaceWindow ++{ ++ Q_OBJECT ++ ++public: ++ explicit XXPipV1Window(XXPipV1Interface *shellSurface); ++ ++ bool isPictureInPicture() const override; ++ bool isResizable() const override; ++ bool isMovable() const override; ++ bool isMovableAcrossScreens() const override; ++ bool isCloseable() const override; ++ void closeWindow() override; ++ bool wantsInput() const override; ++ bool takeFocus() override; ++ ++protected: ++ bool acceptsFocus() const override; ++ XdgSurfaceConfigure *sendRoleConfigure() const override; ++ void handleRoleDestroyed() override; ++ void doSetNextTargetScale() override; ++ void doSetPreferredBufferTransform() override; ++ void doSetPreferredColorDescription() override; ++ ++private: ++ void initialize(); ++ void handleApplicationIdChanged(); ++ void handleMoveRequested(SeatInterface *seat, quint32 serial); ++ void handleResizeRequested(SeatInterface *seat, Gravity gravity, quint32 serial); ++ ++ XXPipV1Interface *m_shellSurface; ++}; ++ ++} // namespace KWin +diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt +index 134f5416975..824cd67083c 100644 +--- a/tests/CMakeLists.txt ++++ b/tests/CMakeLists.txt +@@ -1,3 +1,7 @@ ++if (Qt6_VERSION VERSION_GREATER_EQUAL "6.9.0") ++ add_subdirectory(pip) ++endif() ++ + if(KWIN_BUILD_X11) + set(normalhintsbasesizetest_SRCS normalhintsbasesizetest.cpp) + add_executable(normalhintsbasesizetest ${normalhintsbasesizetest_SRCS}) +diff --git a/tests/pip/CMakeLists.txt b/tests/pip/CMakeLists.txt +new file mode 100644 +index 00000000000..9135a5ab072 +--- /dev/null ++++ b/tests/pip/CMakeLists.txt +@@ -0,0 +1,22 @@ ++add_executable(piptest) ++ ++target_sources(piptest PRIVATE ++ main.cpp ++ pipshellsurface.cpp ++ pip.cpp ++ window.cpp ++) ++ ++qt6_generate_wayland_protocol_client_sources(piptest ++ PRIVATE_CODE ++ FILES ++ ${PROJECT_SOURCE_DIR}/src/wayland/protocols/xx-pip-v1.xml ++ ${WaylandProtocols_DATADIR}/stable/xdg-shell/xdg-shell.xml ++ ${Wayland_DATADIR}/wayland.xml ++) ++ ++target_link_libraries(piptest PRIVATE ++ Qt::Gui ++ Qt::WaylandClientPrivate ++ Qt::Widgets ++) +diff --git a/tests/pip/main.cpp b/tests/pip/main.cpp +new file mode 100644 +index 00000000000..6d7c4f5b3b4 +--- /dev/null ++++ b/tests/pip/main.cpp +@@ -0,0 +1,19 @@ ++/* ++ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: GPL-2.0-or-later ++*/ ++ ++#include ++ ++#include "window.h" ++ ++int main(int argc, char **argv) ++{ ++ QApplication app(argc, argv); ++ ++ Window w; ++ w.show(); ++ ++ return app.exec(); ++} +diff --git a/tests/pip/pip.cpp b/tests/pip/pip.cpp +new file mode 100644 +index 00000000000..ed14f5f98d4 +--- /dev/null ++++ b/tests/pip/pip.cpp +@@ -0,0 +1,227 @@ ++/* ++ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: GPL-2.0-or-later ++*/ ++ ++#include "pip.h" ++#include "pipshellsurface.h" ++ ++#include ++#include ++ ++PipPin::PipPin(QWidget *parent) ++ : QWidget(parent) ++{ ++ resize(100, 50); ++} ++ ++bool PipPin::isPinned() const ++{ ++ return m_pinned; ++} ++ ++void PipPin::setPinned(bool pinned) ++{ ++ if (m_pinned != pinned) { ++ m_pinned = pinned; ++ update(); ++ } ++} ++ ++void PipPin::paintEvent(QPaintEvent *event) ++{ ++ QPainter painter(this); ++ painter.setClipRegion(event->region()); ++ ++ if (m_hovered) { ++ painter.setOpacity(1.0); ++ } else { ++ painter.setOpacity(0.5); ++ } ++ ++ painter.fillRect(rect(), Qt::black); ++ painter.setPen(Qt::white); ++ painter.drawText(rect(), Qt::AlignCenter, m_pinned ? QStringLiteral("Unpin") : QStringLiteral("Pin")); ++} ++ ++void PipPin::mousePressEvent(QMouseEvent *event) ++{ ++ if (event->button() == Qt::LeftButton) { ++ event->accept(); ++ Q_EMIT clicked(); ++ } ++} ++ ++void PipPin::enterEvent(QEnterEvent *event) ++{ ++ m_hovered = true; ++ update(); ++} ++ ++void PipPin::leaveEvent(QEvent *event) ++{ ++ m_hovered = false; ++ update(); ++} ++ ++Media::Media(QWidget *parent) ++ : QWidget(parent) ++{ ++ m_pip = std::make_unique(); ++ connect(m_pip.get(), &Pip::pinned, this, [this]() { ++ m_pin->setPinned(true); ++ }); ++ connect(m_pip.get(), &Pip::unpinned, this, [this]() { ++ m_pin->setPinned(false); ++ }); ++ ++ m_pin = new PipPin(this); ++ connect(m_pin, &PipPin::clicked, this, [this]() { ++ if (m_pin->isPinned()) { ++ m_pip->show(); ++ } else { ++ m_pip->hide(); ++ } ++ }); ++} ++ ++void Media::paintEvent(QPaintEvent *event) ++{ ++ QPainter painter(this); ++ painter.setClipRegion(event->region()); ++ painter.fillRect(rect(), QColor(0, 0, 0, 128)); ++} ++ ++void Media::resizeEvent(QResizeEvent *event) ++{ ++ m_pin->move(width() - m_pin->width() - 50, height() - m_pin->height() - 50); ++ m_pip->resize(width(), height()); ++} ++ ++PipResizeHandle::PipResizeHandle(Qt::Edges edges, QWidget *parent) ++ : QWidget(parent) ++ , m_edges(edges) ++{ ++ switch (edges) { ++ case Qt::LeftEdge: ++ case Qt::RightEdge: ++ setCursor(Qt::SizeHorCursor); ++ break; ++ case Qt::TopEdge: ++ case Qt::BottomEdge: ++ setCursor(Qt::SizeVerCursor); ++ break; ++ case Qt::TopEdge | Qt::LeftEdge: ++ case Qt::BottomEdge | Qt::RightEdge: ++ setCursor(Qt::SizeFDiagCursor); ++ break; ++ case Qt::TopEdge | Qt::RightEdge: ++ case Qt::BottomEdge | Qt::LeftEdge: ++ setCursor(Qt::SizeBDiagCursor); ++ break; ++ default: ++ Q_UNREACHABLE(); ++ } ++} ++ ++void PipResizeHandle::enterEvent(QEnterEvent *event) ++{ ++ m_hovered = true; ++ update(); ++} ++ ++void PipResizeHandle::leaveEvent(QEvent *event) ++{ ++ m_hovered = false; ++ update(); ++} ++ ++void PipResizeHandle::mousePressEvent(QMouseEvent *event) ++{ ++ if (event->button() == Qt::LeftButton) { ++ event->accept(); ++ window()->windowHandle()->startSystemResize(m_edges); ++ } ++} ++ ++void PipResizeHandle::paintEvent(QPaintEvent *event) ++{ ++ QPainter painter(this); ++ painter.setClipRegion(event->region()); ++ painter.fillRect(rect(), QColor(222, 137, 190, m_hovered ? 128 : 0)); ++} ++ ++Pip::Pip(QWidget *parent) ++ : QWidget(parent) ++{ ++ m_closeButton = new QPushButton(this); ++ m_closeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); ++ m_closeButton->setText(QStringLiteral("Close")); ++ connect(m_closeButton, &QPushButton::clicked, this, &Pip::hide); ++ ++ m_topLeftResizeHandle = new PipResizeHandle(Qt::TopEdge | Qt::LeftEdge, this); ++ m_topResizeHandle = new PipResizeHandle(Qt::TopEdge, this); ++ m_topRightResizeHandle = new PipResizeHandle(Qt::TopEdge | Qt::RightEdge, this); ++ m_rightResizeHandle = new PipResizeHandle(Qt::RightEdge, this); ++ m_bottomRightResizeHandle = new PipResizeHandle(Qt::BottomEdge | Qt::BottomEdge, this); ++ m_bottomResizeHandle = new PipResizeHandle(Qt::BottomEdge, this); ++ m_bottomLeftResizeHandle = new PipResizeHandle(Qt::BottomEdge | Qt::LeftEdge, this); ++ m_leftResizeHandle = new PipResizeHandle(Qt::LeftEdge, this); ++ ++ winId(); ++ PipShellIntegration::assignPipRole(windowHandle()); ++} ++ ++void Pip::layout() ++{ ++ const int gridUnit = 5; ++ const int resizeZone = 2 * gridUnit; ++ ++ m_topLeftResizeHandle->setGeometry(0, 0, resizeZone, resizeZone); ++ m_topResizeHandle->setGeometry(resizeZone, 0, width() - 2 * resizeZone, resizeZone); ++ m_topRightResizeHandle->setGeometry(width() - resizeZone, 0, resizeZone, resizeZone); ++ m_rightResizeHandle->setGeometry(width() - resizeZone, resizeZone, resizeZone, height() - 2 * resizeZone); ++ m_bottomRightResizeHandle->setGeometry(width() - resizeZone, height() - resizeZone, resizeZone, resizeZone); ++ m_bottomResizeHandle->setGeometry(resizeZone, height() - resizeZone, width() - 2 * resizeZone, resizeZone); ++ m_bottomLeftResizeHandle->setGeometry(0, height() - resizeZone, resizeZone, resizeZone); ++ m_leftResizeHandle->setGeometry(0, resizeZone, resizeZone, height() - 2 * resizeZone); ++ ++ m_closeButton->move(width() - resizeZone - gridUnit - m_closeButton->width(), resizeZone + gridUnit); ++} ++ ++void Pip::paintEvent(QPaintEvent *event) ++{ ++ QPainter painter(this); ++ painter.setClipRegion(event->region()); ++ painter.fillRect(rect(), QColor(64, 67, 78)); ++} ++ ++void Pip::resizeEvent(QResizeEvent *event) ++{ ++ layout(); ++} ++ ++void Pip::mousePressEvent(QMouseEvent *event) ++{ ++ switch (event->button()) { ++ case Qt::LeftButton: ++ event->accept(); ++ windowHandle()->startSystemMove(); ++ break; ++ default: ++ break; ++ } ++} ++ ++void Pip::showEvent(QShowEvent *event) ++{ ++ Q_EMIT unpinned(); ++} ++ ++void Pip::hideEvent(QHideEvent *event) ++{ ++ Q_EMIT pinned(); ++} ++ ++#include "moc_pip.cpp" +diff --git a/tests/pip/pip.h b/tests/pip/pip.h +new file mode 100644 +index 00000000000..2f6e4a87d86 +--- /dev/null ++++ b/tests/pip/pip.h +@@ -0,0 +1,102 @@ ++/* ++ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: GPL-2.0-or-later ++*/ ++ ++#pragma once ++ ++#include ++#include ++ ++class PipResizeHandle : public QWidget ++{ ++ Q_OBJECT ++ ++public: ++ explicit PipResizeHandle(Qt::Edges edges, QWidget *parent = nullptr); ++ ++protected: ++ void enterEvent(QEnterEvent *event) override; ++ void leaveEvent(QEvent *event) override; ++ void mousePressEvent(QMouseEvent *event) override; ++ void paintEvent(QPaintEvent *event) override; ++ ++private: ++ Qt::Edges m_edges; ++ bool m_hovered = false; ++}; ++ ++class Pip : public QWidget ++{ ++ Q_OBJECT ++ ++public: ++ explicit Pip(QWidget *parent = nullptr); ++ ++Q_SIGNALS: ++ void pinned(); ++ void unpinned(); ++ ++protected: ++ void paintEvent(QPaintEvent *event) override; ++ void resizeEvent(QResizeEvent *event) override; ++ void mousePressEvent(QMouseEvent *event) override; ++ void showEvent(QShowEvent *event) override; ++ void hideEvent(QHideEvent *event) override; ++ ++private: ++ void layout(); ++ ++ QPushButton *m_closeButton = nullptr; ++ PipResizeHandle *m_topLeftResizeHandle = nullptr; ++ PipResizeHandle *m_topResizeHandle = nullptr; ++ PipResizeHandle *m_topRightResizeHandle = nullptr; ++ PipResizeHandle *m_rightResizeHandle = nullptr; ++ PipResizeHandle *m_bottomRightResizeHandle = nullptr; ++ PipResizeHandle *m_bottomResizeHandle = nullptr; ++ PipResizeHandle *m_bottomLeftResizeHandle = nullptr; ++ PipResizeHandle *m_leftResizeHandle = nullptr; ++}; ++ ++class PipPin : public QWidget ++{ ++ Q_OBJECT ++ ++public: ++ explicit PipPin(QWidget *parent = nullptr); ++ ++ bool isPinned() const; ++ void setPinned(bool pinned); ++ ++Q_SIGNALS: ++ void clicked(); ++ ++protected: ++ void paintEvent(QPaintEvent *event) override; ++ void mousePressEvent(QMouseEvent *event) override; ++ void enterEvent(QEnterEvent *event) override; ++ void leaveEvent(QEvent *event) override; ++ ++private: ++ bool m_pinned = true; ++ bool m_hovered = false; ++}; ++ ++class Media : public QWidget ++{ ++ Q_OBJECT ++ ++public: ++ explicit Media(QWidget *parent = nullptr); ++ ++protected: ++ void paintEvent(QPaintEvent *event) override; ++ void resizeEvent(QResizeEvent *event) override; ++ ++private: ++ void layout(); ++ ++ std::unique_ptr m_pip; ++ PipPin *m_pin = nullptr; ++}; +diff --git a/tests/pip/pipshellsurface.cpp b/tests/pip/pipshellsurface.cpp +new file mode 100644 +index 00000000000..082a51a3c24 +--- /dev/null ++++ b/tests/pip/pipshellsurface.cpp +@@ -0,0 +1,156 @@ ++/* ++ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: GPL-2.0-or-later ++*/ ++ ++#include "pipshellsurface.h" ++ ++#include ++#include ++ ++XdgWmBase::XdgWmBase() ++ : QWaylandClientExtensionTemplate(6) ++{ ++ initialize(); ++ if (!isActive()) { ++ qFatal("The xdg-shell protocol is unsupported by the compositor"); ++ } ++} ++ ++XXPipShell::XXPipShell() ++ : QWaylandClientExtensionTemplate(1) ++{ ++ initialize(); ++ if (!isActive()) { ++ qFatal("The xx-pip-v1 protocol is unsupported by the compositor"); ++ } ++} ++ ++void PipShellIntegration::assignPipRole(QWindow *window) ++{ ++ window->create(); ++ ++ auto waylandWindow = dynamic_cast(window->handle()); ++ if (!waylandWindow) { ++ return; ++ } ++ ++ static PipShellIntegration *shellIntegration = nullptr; ++ if (!shellIntegration) { ++ shellIntegration = new PipShellIntegration(); ++ } ++ ++ waylandWindow->setShellIntegration(shellIntegration); ++} ++ ++PipShellIntegration::PipShellIntegration() ++ : m_xdgWmBase(std::make_unique()) ++ , m_xxPipShell(std::make_unique()) ++{ ++} ++ ++bool PipShellIntegration::initialize(QtWaylandClient::QWaylandDisplay *display) ++{ ++ return m_xdgWmBase->isInitialized() && m_xxPipShell->isInitialized(); ++} ++ ++QtWaylandClient::QWaylandShellSurface *PipShellIntegration::createShellSurface(QtWaylandClient::QWaylandWindow *window) ++{ ++ ::xdg_surface *xdgSurface = m_xdgWmBase->get_xdg_surface(window->wlSurface()); ++ ::xx_pip_v1 *xxPip = m_xxPipShell->get_pip(xdgSurface); ++ return new PipShellSurface(xdgSurface, xxPip, window); ++} ++ ++PipShellSurface::PipShellSurface(::xdg_surface *xdgSurface, ::xx_pip_v1 *xxPip, QtWaylandClient::QWaylandWindow *window) ++ : QWaylandShellSurface(window) ++ , QtWayland::xdg_surface(xdgSurface) ++ , QtWayland::xx_pip_v1(xxPip) ++{ ++} ++ ++PipShellSurface::~PipShellSurface() ++{ ++ xx_pip_v1::destroy(); ++ xdg_surface::destroy(); ++} ++ ++bool PipShellSurface::isExposed() const ++{ ++ return m_configured; ++} ++ ++void PipShellSurface::applyConfigure() ++{ ++ QSize size = window()->windowContentGeometry().size(); ++ if (m_pendingSize.width() > 0) { ++ size.setWidth(m_pendingSize.width()); ++ } ++ if (m_pendingSize.height() > 0) { ++ size.setHeight(m_pendingSize.height()); ++ } ++ ++ window()->resizeFromApplyConfigure(size); ++} ++ ++void PipShellSurface::setWindowGeometry(const QRect &rect) ++{ ++ if (window()->isExposed()) { ++ xdg_surface::set_window_geometry(rect.x(), rect.y(), rect.width(), rect.height()); ++ } ++} ++ ++bool PipShellSurface::move(QtWaylandClient::QWaylandInputDevice *inputDevice) ++{ ++ if (!m_configured) { ++ return false; ++ } ++ xx_pip_v1::move(inputDevice->wl_seat(), inputDevice->serial()); ++ return true; ++} ++ ++bool PipShellSurface::resize(QtWaylandClient::QWaylandInputDevice *inputDevice, Qt::Edges edges) ++{ ++ if (!m_configured) { ++ return false; ++ } ++ ++ const resize_edge edge = static_cast( ++ ((edges & Qt::TopEdge) ? resize_edge_top : 0) ++ | ((edges & Qt::BottomEdge) ? resize_edge_bottom : 0) ++ | ((edges & Qt::LeftEdge) ? resize_edge_left : 0) ++ | ((edges & Qt::RightEdge) ? resize_edge_right : 0)); ++ ++ xx_pip_v1::resize(inputDevice->wl_seat(), inputDevice->serial(), edge); ++ return true; ++} ++ ++void PipShellSurface::xdg_surface_configure(uint32_t serial) ++{ ++ xdg_surface::ack_configure(serial); ++ ++ if (!m_configured) { ++ m_configured = true; ++ applyConfigure(); ++ } else { ++ window()->applyConfigureWhenPossible(); ++ } ++ ++ window()->updateExposure(); ++} ++ ++void PipShellSurface::xx_pip_v1_configure_bounds(int32_t width, int32_t height) ++{ ++} ++ ++void PipShellSurface::xx_pip_v1_configure_size(int32_t width, int32_t height) ++{ ++ m_pendingSize = QSize(width, height); ++} ++ ++void PipShellSurface::xx_pip_v1_closed() ++{ ++ QWindowSystemInterface::handleCloseEvent(window()->window()); ++} ++ ++#include "moc_pipshellsurface.cpp" +diff --git a/tests/pip/pipshellsurface.h b/tests/pip/pipshellsurface.h +new file mode 100644 +index 00000000000..b02e83b3fc9 +--- /dev/null ++++ b/tests/pip/pipshellsurface.h +@@ -0,0 +1,70 @@ ++/* ++ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: GPL-2.0-or-later ++*/ ++ ++#pragma once ++ ++#include ++#include ++#include ++#include ++ ++#include "qwayland-xdg-shell.h" ++#include "qwayland-xx-pip-v1.h" ++ ++class XdgWmBase : public QWaylandClientExtensionTemplate, public QtWayland::xdg_wm_base ++{ ++ Q_OBJECT ++ ++public: ++ XdgWmBase(); ++}; ++ ++class XXPipShell : public QWaylandClientExtensionTemplate, public QtWayland::xx_pip_shell_v1 ++{ ++ Q_OBJECT ++ ++public: ++ XXPipShell(); ++}; ++ ++class PipShellIntegration : public QtWaylandClient::QWaylandShellIntegration ++{ ++public: ++ PipShellIntegration(); ++ ++ bool initialize(QtWaylandClient::QWaylandDisplay *display) override; ++ QtWaylandClient::QWaylandShellSurface *createShellSurface(QtWaylandClient::QWaylandWindow *window) override; ++ ++ static void assignPipRole(QWindow *window); ++ ++private: ++ std::unique_ptr m_xdgWmBase; ++ std::unique_ptr m_xxPipShell; ++}; ++ ++class PipShellSurface : public QtWaylandClient::QWaylandShellSurface, public QtWayland::xdg_surface, public QtWayland::xx_pip_v1 ++{ ++ Q_OBJECT ++ ++public: ++ PipShellSurface(::xdg_surface *xdgSurface, ::xx_pip_v1 *xxPip, QtWaylandClient::QWaylandWindow *window); ++ ~PipShellSurface() override; ++ ++ bool isExposed() const override; ++ void applyConfigure() override; ++ void setWindowGeometry(const QRect &rect) override; ++ bool move(QtWaylandClient::QWaylandInputDevice *inputDevice) override; ++ bool resize(QtWaylandClient::QWaylandInputDevice *inputDevice, Qt::Edges edges) override; ++ ++private: ++ void xdg_surface_configure(uint32_t serial) override; ++ void xx_pip_v1_closed() override; ++ void xx_pip_v1_configure_bounds(int32_t width, int32_t height) override; ++ void xx_pip_v1_configure_size(int32_t width, int32_t height) override; ++ ++ QSize m_pendingSize; ++ bool m_configured = false; ++}; +diff --git a/tests/pip/window.cpp b/tests/pip/window.cpp +new file mode 100644 +index 00000000000..2ac98bde845 +--- /dev/null ++++ b/tests/pip/window.cpp +@@ -0,0 +1,19 @@ ++/* ++ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: GPL-2.0-or-later ++*/ ++ ++#include "window.h" ++#include "pip.h" ++ ++Window::Window(QWidget *parent) ++ : QWidget(parent) ++{ ++ resize(800, 600); ++ ++ m_media = new Media(this); ++ m_media->setGeometry(100, 100, 400, 300); ++} ++ ++#include "moc_window.cpp" +diff --git a/tests/pip/window.h b/tests/pip/window.h +new file mode 100644 +index 00000000000..bfd83e9d467 +--- /dev/null ++++ b/tests/pip/window.h +@@ -0,0 +1,22 @@ ++/* ++ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii ++ ++ SPDX-License-Identifier: GPL-2.0-or-later ++*/ ++ ++#pragma once ++ ++#include ++ ++class Media; ++ ++class Window : public QWidget ++{ ++ Q_OBJECT ++ ++public: ++ explicit Window(QWidget *parent = nullptr); ++ ++private: ++ Media *m_media = nullptr; ++}; +-- +GitLab + + +From cab39d37c8cb7d1c37d04a76cc7fa7af39fb7908 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Thu, 12 Jun 2025 14:22:55 +0000 +Subject: [PATCH 2/2] Apply 2 suggestion(s) to 1 file(s) + +Co-authored-by: Xaver Hugl +--- + src/wayland/xxpip_v1.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/wayland/xxpip_v1.cpp b/src/wayland/xxpip_v1.cpp +index e0b1f36134f..bc1b65d0212 100644 +--- a/src/wayland/xxpip_v1.cpp ++++ b/src/wayland/xxpip_v1.cpp +@@ -282,7 +282,7 @@ quint32 XXPipV1Interface::sendConfigureSize(const QSizeF &size) + { + const quint32 serial = d->shell->display()->nextSerial(); + +- d->send_configure_size(size.width(), size.height()); ++ d->send_configure_size(std::round(size.width()), std::round(size.height())); + + auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface()); + xdgSurfacePrivate->send_configure(serial); +@@ -298,7 +298,7 @@ void XXPipV1Interface::sendClosed() + + void XXPipV1Interface::sendConfigureBounds(const QSizeF &size) + { +- d->send_configure_bounds(size.width(), size.height()); ++ d->send_configure_bounds(std::round(size.width()), std::round(size.height())); + } + + XXPipV1Interface *XXPipV1Interface::get(::wl_resource *resource) +-- +GitLab + diff --git a/roles/kde/patches/kwin/pr7822.patch b/roles/kde/patches/kwin/pr7822.patch new file mode 100644 index 0000000..aca6909 --- /dev/null +++ b/roles/kde/patches/kwin/pr7822.patch @@ -0,0 +1,40 @@ +From 3ac297b99540eae81568edca1e550ca7d1d6c01f Mon Sep 17 00:00:00 2001 +From: Ismael Asensio +Date: Tue, 24 Jun 2025 17:08:00 +0200 +Subject: [PATCH] plugins/fadingpopups: Blacklist spectacle popup menus from + fading effect + +Spectacle can trigger a screenshot from a popup menu. This menu needs +to get hidden immediately with no effects, to avoid appearing on the +screenshot. + +BUG: 505803 +FIXED-IN: 6.4.2 + + +(cherry picked from commit 99f6418e3c2e044eb1f4e8bedcdccac55f1a01d4) + +Co-authored-by: Ismael Asensio +--- + src/plugins/fadingpopups/package/contents/code/main.js | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/plugins/fadingpopups/package/contents/code/main.js b/src/plugins/fadingpopups/package/contents/code/main.js +index f0764b42ac6..7c00640ae8f 100644 +--- a/src/plugins/fadingpopups/package/contents/code/main.js ++++ b/src/plugins/fadingpopups/package/contents/code/main.js +@@ -17,7 +17,10 @@ var blacklist = [ + // The lockscreen isn't a popup window + "kscreenlocker_greet kscreenlocker_greet", + // KDE Plasma splash screen has to be animated only by the login effect. +- "ksplashqml ksplashqml" ++ "ksplashqml ksplashqml", ++ // Spectacle can trigger a screenshot from a popup menu ++ "spectacle org.kde.spectacle", ++ "spectacle spectacle", + ]; + + function isPopupWindow(window) { +-- +GitLab + diff --git a/roles/kde/patches/kwin/pr7823.patch b/roles/kde/patches/kwin/pr7823.patch new file mode 100644 index 0000000..5e54a43 --- /dev/null +++ b/roles/kde/patches/kwin/pr7823.patch @@ -0,0 +1,26 @@ +From a1868942fbc2ad5de4c053dd17335dff34d81779 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 25 Jun 2025 14:10:18 +0300 +Subject: [PATCH] plugins/login: Reduce animation duration + +This makes the startup feel a bit faster. +--- + src/plugins/login/package/contents/code/main.js | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/plugins/login/package/contents/code/main.js b/src/plugins/login/package/contents/code/main.js +index 7f849a6e2e6..e3ad0b76c07 100644 +--- a/src/plugins/login/package/contents/code/main.js ++++ b/src/plugins/login/package/contents/code/main.js +@@ -11,7 +11,7 @@ + "use strict"; + + var loginEffect = { +- duration: animationTime(1000), ++ duration: animationTime(500), + isFadeToBlack: false, + loadConfig: function () { + loginEffect.isFadeToBlack = effect.readConfig("FadeToBlack", false); +-- +GitLab + diff --git a/roles/kde/patches/kwin/pr7829.patch b/roles/kde/patches/kwin/pr7829.patch new file mode 100644 index 0000000..fe92562 --- /dev/null +++ b/roles/kde/patches/kwin/pr7829.patch @@ -0,0 +1,85 @@ +From 4ddb4a23d5f453cf890c9f1b1aa5429150991db3 Mon Sep 17 00:00:00 2001 +From: David Redondo +Date: Thu, 26 Jun 2025 17:00:07 +0200 +Subject: [PATCH] scene: Skip visibility check for the Item itself in + framePainted + +Fixes offscreen rendering and window thumbnails for hidden windows +not udpating. +Co-authored-by: Vlad Zahorodnii +--- + src/scene/item.cpp | 9 +++++---- + src/scene/item.h | 2 +- + src/scene/rootitem.cpp | 9 --------- + src/scene/rootitem.h | 2 -- + 4 files changed, 6 insertions(+), 16 deletions(-) + +diff --git a/src/scene/item.cpp b/src/scene/item.cpp +index 2637a131dbd..eb2b6b46977 100644 +--- a/src/scene/item.cpp ++++ b/src/scene/item.cpp +@@ -648,12 +648,13 @@ void Item::removeEffect() + + void Item::framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp) + { +- if (!isVisible() || workspace()->outputAt(mapToScene(boundingRect()).center()) != output) { +- return; +- } ++ // The visibility of the item itself is not checked here to be able to paint hidden items for ++ // things like screncasts or thumbnails + handleFramePainted(output, frame, timestamp); + for (const auto child : std::as_const(m_childItems)) { +- child->framePainted(output, frame, timestamp); ++ if (child->explicitVisible() && workspace()->outputAt(child->mapToScene(child->boundingRect()).center()) == output) { ++ child->framePainted(output, frame, timestamp); ++ } + } + } + +diff --git a/src/scene/item.h b/src/scene/item.h +index acb29994328..d42b32abf7b 100644 +--- a/src/scene/item.h ++++ b/src/scene/item.h +@@ -144,7 +144,7 @@ public: + void addEffect(); + void removeEffect(); + +- virtual void framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp); ++ void framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp); + + bool isAncestorOf(const Item *item) const; + +diff --git a/src/scene/rootitem.cpp b/src/scene/rootitem.cpp +index fe0cecc76e3..466a25ce828 100644 +--- a/src/scene/rootitem.cpp ++++ b/src/scene/rootitem.cpp +@@ -14,13 +14,4 @@ RootItem::RootItem(Scene *scene) + setScene(scene); + } + +-void RootItem::framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp) +-{ +- handleFramePainted(output, frame, timestamp); +- const auto children = childItems(); +- for (const auto child : children) { +- child->framePainted(output, frame, timestamp); +- } +-} +- + } // namespace KWin +diff --git a/src/scene/rootitem.h b/src/scene/rootitem.h +index 45fa1359c84..43b3cdb90e9 100644 +--- a/src/scene/rootitem.h ++++ b/src/scene/rootitem.h +@@ -20,8 +20,6 @@ class KWIN_EXPORT RootItem : public Item + + public: + explicit RootItem(Scene *scene); +- +- void framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp) override; + }; + + } // namespace KWin +-- +GitLab + diff --git a/roles/kde/patches/plasma-nm/patches.txt b/roles/kde/patches/plasma-nm/patches.txt new file mode 100644 index 0000000..c5e71a7 --- /dev/null +++ b/roles/kde/patches/plasma-nm/patches.txt @@ -0,0 +1,4 @@ +Plasma 6.5.0: + +Pr 439 https://invent.kde.org/plasma/plasma-nm/-/merge_requests/439 +Pr 442 https://invent.kde.org/plasma/plasma-nm/-/merge_requests/442 diff --git a/roles/kde/patches/plasma-nm/pr439.patch b/roles/kde/patches/plasma-nm/pr439.patch new file mode 100644 index 0000000..885e3dd --- /dev/null +++ b/roles/kde/patches/plasma-nm/pr439.patch @@ -0,0 +1,140 @@ +From ac32824009397188131aab4fcc3394fcc4551c5c Mon Sep 17 00:00:00 2001 +From: Nate Graham +Date: Tue, 10 Jun 2025 15:43:13 -0600 +Subject: [PATCH 1/2] applet: handle some more states + +1. Looking for Wi-Fi networks but haven't found any yet +2. NetworkManager isn't running + +FEATURE: 485982 +BUG: 462454 +FIXED-IN: 6.5.0 +--- + applet/contents/ui/ConnectionListPage.qml | 15 ++++++++++++--- + applet/contents/ui/Toolbar.qml | 3 ++- + applet/metadata.json | 1 - + libs/networkstatus.h | 3 +-- + 4 files changed, 15 insertions(+), 7 deletions(-) + +diff --git a/applet/contents/ui/ConnectionListPage.qml b/applet/contents/ui/ConnectionListPage.qml +index b9a949d87..056f52de3 100644 +--- a/applet/contents/ui/ConnectionListPage.qml ++++ b/applet/contents/ui/ConnectionListPage.qml +@@ -101,9 +101,12 @@ ColumnLayout { + if (toolbar.displayplaneModeMessage) { + return "network-flightmode-on" + } +- if (toolbar.displayWifiMessage) { ++ if (toolbar.displayWifiOffMessage) { + return "network-wireless-off" + } ++ if (toolbar.displayWifiConnectingMessage) { ++ return "view-refresh-symbolic" ++ } + if (toolbar.displayWwanMessage) { + return "network-mobile-off" + } +@@ -113,19 +116,25 @@ ColumnLayout { + if (toolbar.displayplaneModeMessage) { + return i18n("Airplane mode is enabled") + } +- if (toolbar.displayWifiMessage) { ++ if (toolbar.displayWifiOffMessage) { + if (toolbar.displayWwanMessage) { + return i18n("Wireless and mobile networks are deactivated") + } + return i18n("Wireless is deactivated") + } ++ if (toolbar.displayWifiConnectingMessage) { ++ return i18n("Looking for wireless networks") ++ } + if (toolbar.displayWwanMessage) { + return i18n("Mobile network is deactivated") + } + if (toolbar.searchTextField.text.length > 0) { + return i18n("No matches") + } +- return i18n("No available connections") ++ if (connectionListPage.nmStatus.connectivity === NMQt.NetworkManager.Full) { ++ return i18n("No available connections") ++ } ++ return nmStatus.checkUnknownReason() + } + } + } +diff --git a/applet/contents/ui/Toolbar.qml b/applet/contents/ui/Toolbar.qml +index 87b3f1654..0d382109b 100644 +--- a/applet/contents/ui/Toolbar.qml ++++ b/applet/contents/ui/Toolbar.qml +@@ -16,7 +16,8 @@ import org.kde.kcmutils as KCMUtils + RowLayout { + id: toolbar + +- readonly property var displayWifiMessage: !wifiSwitchButton.checked && wifiSwitchButton.visible ++ readonly property var displayWifiOffMessage: !wifiSwitchButton.checked && wifiSwitchButton.visible ++ readonly property var displayWifiConnectingMessage: wifiSwitchButton.checked && wifiSwitchButton.visible + readonly property var displayWwanMessage: !wwanSwitchButton.checked && wwanSwitchButton.visible + readonly property var displayplaneModeMessage: planeModeSwitchButton.checked && planeModeSwitchButton.visible + +diff --git a/applet/metadata.json b/applet/metadata.json +index 0ca36a2b7..2f12891b5 100644 +--- a/applet/metadata.json ++++ b/applet/metadata.json +@@ -210,6 +210,5 @@ + "X-KDE-Keywords[zh_CN]": "network,internet,ethernet,wireless,wifi,wlan,vpn,wangluo,hulianwang,yitaiwang,juyuwang,wuxianwangluo,xunizhuanyongwangluo,网络,互联网,以太网,局域网,无线网络,虚拟专用网络", + "X-KDE-Keywords[zh_TW]": "網路,網絡,網際網路,乙太網路,以太網路,無線", + "X-Plasma-API-Minimum-Version": "6.0", +- "X-Plasma-DBusActivationService": "org.freedesktop.NetworkManager", + "X-Plasma-NotificationAreaCategory": "Hardware" + } +diff --git a/libs/networkstatus.h b/libs/networkstatus.h +index aa88bf7c5..a885f04dd 100644 +--- a/libs/networkstatus.h ++++ b/libs/networkstatus.h +@@ -59,6 +59,7 @@ public: + QString activeConnections() const; + QString networkStatus() const; + NetworkManager::Connectivity connectivity() const; ++ Q_INVOKABLE QString checkUnknownReason() const; + + private Q_SLOTS: + void activeConnectionsChanged(); +@@ -75,8 +76,6 @@ private: + QString m_activeConnections; + QString m_networkStatus; + NetworkManager::Connectivity m_connectivity = NetworkManager::UnknownConnectivity; +- +- QString checkUnknownReason() const; + }; + + #endif // PLAMA_NM_NETWORK_STATUS_H +-- +GitLab + + +From a45534cd9c19f267075fe4261087045f1f3a9318 Mon Sep 17 00:00:00 2001 +From: Nate Graham +Date: Wed, 11 Jun 2025 10:14:40 -0600 +Subject: [PATCH 2/2] Rephrase "NetworkManager not running" message to be more + user-friendly + +--- + libs/networkstatus.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libs/networkstatus.cpp b/libs/networkstatus.cpp +index c89ca9fca..b778eedda 100644 +--- a/libs/networkstatus.cpp ++++ b/libs/networkstatus.cpp +@@ -253,7 +253,7 @@ QString NetworkStatus::checkUnknownReason() const + { + // Check if NetworkManager is running. + if (!QDBusConnection::systemBus().interface()->isServiceRegistered(QStringLiteral(NM_DBUS_INTERFACE))) { +- return i18n("NetworkManager not running"); ++ return i18nc("@info:status", "NetworkManager service is not running"); + } + + // Check for compatible NetworkManager version. +-- +GitLab + diff --git a/roles/kde/patches/plasma-nm/pr442.patch b/roles/kde/patches/plasma-nm/pr442.patch new file mode 100644 index 0000000..cd6dda6 --- /dev/null +++ b/roles/kde/patches/plasma-nm/pr442.patch @@ -0,0 +1,168 @@ +From 63a9d544dc4f5160f28e5f3203a2c0a5e639e5ac Mon Sep 17 00:00:00 2001 +From: Nate Graham +Date: Fri, 13 Jun 2025 12:24:22 -0600 +Subject: [PATCH] applet: use standard section headers + +We have them, so we might as well use them. This lets us get rid of a +bunch of complex and fragile code that's responsible for the existing +separator. +--- + applet/contents/ui/ConnectionItem.qml | 14 ----- + applet/contents/ui/ConnectionListPage.qml | 10 ++-- + applet/contents/ui/ListItem.qml | 64 ----------------------- + libs/models/networkmodelitem.cpp | 8 ++- + 4 files changed, 12 insertions(+), 84 deletions(-) + delete mode 100644 applet/contents/ui/ListItem.qml + +diff --git a/applet/contents/ui/ConnectionItem.qml b/applet/contents/ui/ConnectionItem.qml +index ed154e633..5bb5c530c 100644 +--- a/applet/contents/ui/ConnectionItem.qml ++++ b/applet/contents/ui/ConnectionItem.qml +@@ -321,20 +321,6 @@ PlasmaExtras.ExpandableListItem { + } + } + +- onDeactivatedChanged: { +- /* Separator is part of section, which is visible only when available connections exist. Need to determine +- if there is a connection in use, to show Separator. Otherwise need to hide it from the top of the list. +- Connections in use are always on top, only need to check the first one. */ +- if (appletProxyModel.data(appletProxyModel.index(0, 0), PlasmaNM.NetworkModel.SectionRole) !== "Available connections") { +- if (connectionView.showSeparator != true) { +- connectionView.showSeparator = true +- } +- return +- } +- connectionView.showSeparator = false +- return +- } +- + onItemCollapsed: { + connectionItem.customExpandedViewContent = detailsComponent; + setDelayModelUpdates(false); +diff --git a/applet/contents/ui/ConnectionListPage.qml b/applet/contents/ui/ConnectionListPage.qml +index b62da252c..d8ebd2c54 100644 +--- a/applet/contents/ui/ConnectionListPage.qml ++++ b/applet/contents/ui/ConnectionListPage.qml +@@ -8,7 +8,7 @@ import QtQuick 2.15 + import QtQuick.Layouts 1.2 + import org.kde.plasma.components 3.0 as PlasmaComponents3 + import org.kde.kirigami 2.20 as Kirigami +-import org.kde.plasma.extras 2.0 as PlasmaExtras ++import org.kde.plasma.extras as PlasmaExtras + import org.kde.plasma.networkmanagement as PlasmaNM + import org.kde.networkmanager as NMQt + +@@ -55,7 +55,6 @@ ColumnLayout { + id: connectionView + + property int currentVisibleButtonIndex: -1 +- property bool showSeparator: false + + Keys.onDownPressed: event => { + connectionView.incrementCurrentIndex(); +@@ -80,9 +79,10 @@ ColumnLayout { + model: appletProxyModel + currentIndex: -1 + boundsBehavior: Flickable.StopAtBounds +- section.property: showSeparator ? "Section" : "" +- section.delegate: ListItem { +- separator: true ++ section.property: "Section" ++ section.delegate: PlasmaExtras.ListSectionHeader { ++ width: connectionView.width - connectionView.leftMargin - connectionView.rightMargin ++ text: section + } + highlight: PlasmaExtras.Highlight { } + highlightMoveDuration: Kirigami.Units.shortDuration +diff --git a/applet/contents/ui/ListItem.qml b/applet/contents/ui/ListItem.qml +deleted file mode 100644 +index bfe1390d1..000000000 +--- a/applet/contents/ui/ListItem.qml ++++ /dev/null +@@ -1,64 +0,0 @@ +-/* +- SPDX-FileCopyrightText: 2010 Marco Martin +- SPDX-FileCopyrightText: 2016 Jan Grulich +- SPDX-FileCopyrightText: 2020 George Vogiatzis +- +- SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +-*/ +- +-import QtQuick 2.1 +-import org.kde.kirigami 2.20 as Kirigami +-import org.kde.ksvg 1.0 as KSvg +- +-/** +- * Ignores the theme's listItem margins, and uses custom highlight(pressed) area. +- * Could break some themes but the majority look fine. +- * Also includes a separator to be used in sections. +- */ +-MouseArea { +- id: listItem +- +- property bool checked: false +- property bool separator: false +- property rect highlightRect: Qt.rect(0, 0, width, height) +- +- width: parent.width +- +- // Sections have spacing above but not below. Will use 2 of them below. +- height: separator ? separatorLine.height + Kirigami.Units.smallSpacing * 3 : parent.height +- hoverEnabled: true +- +- KSvg.SvgItem { +- id: separatorLine +- anchors { +- horizontalCenter: parent.horizontalCenter +- top: parent.top +- topMargin: Kirigami.Units.smallSpacing +- } +- imagePath: "widgets/line" +- elementId: "horizontal-line" +- width: parent.width - Kirigami.Units.gridUnit * 2 +- visible: listItem.separator +- } +- +- KSvg.FrameSvgItem { +- id: background +- imagePath: "widgets/listitem" +- prefix: "normal" +- anchors.fill: parent +- visible: listItem.separator ? false : true +- } +- +- KSvg.FrameSvgItem { +- id: pressed +- imagePath: "widgets/listitem" +- prefix: "pressed" +- opacity: listItem.checked ? 1 : 0 +- Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } } +- +- x: listItem.highlightRect.x +- y: listItem.highlightRect.y +- height: listItem.highlightRect.height +- width: listItem.highlightRect.width +- } +-} +diff --git a/libs/models/networkmodelitem.cpp b/libs/models/networkmodelitem.cpp +index b92ec0df2..4d7cbd77d 100644 +--- a/libs/models/networkmodelitem.cpp ++++ b/libs/models/networkmodelitem.cpp +@@ -344,7 +344,13 @@ QString NetworkModelItem::originalName() const + QString NetworkModelItem::sectionType() const + { + if (m_connectionState == NetworkManager::ActiveConnection::Deactivated) { +- return QStringLiteral("Available connections"); ++ return i18nc("@title:column header for list of available network connections", "Available"); ++ // clang-format off ++ } else if (m_connectionState == NetworkManager::ActiveConnection::Activating ++ || m_connectionState == NetworkManager::ActiveConnection::Activated ++ || m_connectionState == NetworkManager::ActiveConnection::Deactivating) { ++ // clang-format on ++ return i18nc("@title:column header for list of connected network connections", "Connected"); + } else { + return {}; + } +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/patches.txt b/roles/kde/patches/plasma-workspace/patches.txt new file mode 100644 index 0000000..d704604 --- /dev/null +++ b/roles/kde/patches/plasma-workspace/patches.txt @@ -0,0 +1,6 @@ +Plasma 6.5.0: + +Pr 5589 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5589 +Pr 5626 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5626 +Pr 5627 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5627 +Pr 5628 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5628 diff --git a/roles/kde/patches/plasma-workspace/pr5589.patch b/roles/kde/patches/plasma-workspace/pr5589.patch new file mode 100644 index 0000000..b305b9f --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5589.patch @@ -0,0 +1,37 @@ +From 2278398309c68ce401a8e35b193fca3782391a4a Mon Sep 17 00:00:00 2001 +From: Nate Graham +Date: Thu, 12 Jun 2025 09:15:15 -0600 +Subject: [PATCH] applets/devicenotifier: use standard section header + +No need for a custom header here when we have a standard one. + +CCBUG: 442724 +--- + .../package/contents/ui/FullRepresentation.qml | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/applets/devicenotifier/package/contents/ui/FullRepresentation.qml b/applets/devicenotifier/package/contents/ui/FullRepresentation.qml +index 967223e0a1a..a0c28df45fe 100644 +--- a/applets/devicenotifier/package/contents/ui/FullRepresentation.qml ++++ b/applets/devicenotifier/package/contents/ui/FullRepresentation.qml +@@ -132,15 +132,9 @@ PlasmaExtras.Representation { + + section { + property: "deviceType" +- delegate: Item { +- height: Math.floor(childrenRect.height) ++ delegate: PlasmaExtras.ListSectionHeader { + width: notifierDialog.width - (scrollView.PlasmaComponents3.ScrollBar.vertical.visible ? Kirigami.Units.largeSpacing * 2 : 0) +- Kirigami.Heading { +- level: 3 +- opacity: 0.6 +- text: section +- textFormat: Text.PlainText +- } ++ text: section + } + } + +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/pr5626.patch b/roles/kde/patches/plasma-workspace/pr5626.patch new file mode 100644 index 0000000..6ad487f --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5626.patch @@ -0,0 +1,102 @@ +From 9fabf42c39a25308739dd3483881cc889243bf58 Mon Sep 17 00:00:00 2001 +From: Kristen McWilliam +Date: Tue, 24 Jun 2025 17:44:33 -0400 +Subject: [PATCH] applets/notifications: Add actions to missed notifications + notification + +When a notification is displayed informing the user that notifications were missed while in Do Not +Disturb, now clicking the button or the notification itself will open the notifications applet to +show the missed notifications. + +BUG: 502423 +--- + .../package/contents/ui/main.qml | 10 ++++++ + libnotificationmanager/notifications.cpp | 34 ++++++++++++++----- + libnotificationmanager/notifications.h | 7 ++++ + 3 files changed, 42 insertions(+), 9 deletions(-) + +diff --git a/applets/notifications/package/contents/ui/main.qml b/applets/notifications/package/contents/ui/main.qml +index c96afa0558d..ab66a52f45e 100644 +--- a/applets/notifications/package/contents/ui/main.qml ++++ b/applets/notifications/package/contents/ui/main.qml +@@ -268,4 +268,14 @@ PlasmoidItem { + Component.onDestruction: { + Globals.forget(root); + } ++ ++ Connections { ++ target: Globals.popupNotificationsModel ++ ++ // The user requested to show the notifications popup, probably by ++ // clicking the "Missed Notifications in Do Not Disturb" notification. ++ function onShowNotificationsRequested(): void { ++ root.expanded = true; ++ } ++ } + } +diff --git a/libnotificationmanager/notifications.cpp b/libnotificationmanager/notifications.cpp +index 2cba1360b10..7b5cd9d68c4 100644 +--- a/libnotificationmanager/notifications.cpp ++++ b/libnotificationmanager/notifications.cpp +@@ -903,15 +903,31 @@ void Notifications::showInhibitionSummary(Urgency urgency, const QStringList &bl + return; + } + +- KNotification::event(u"inhibitionSummary"_s, +- i18ncp("@title", "Unread Notification", "Unread Notifications", inhibited), +- i18ncp("@info", +- "%1 notification was received while Do Not Disturb was active.", +- "%1 notifications were received while Do Not Disturb was active.", +- inhibited), +- u"preferences-desktop-notification-bell"_s, +- KNotification::CloseOnTimeout, +- u"libnotificationmanager"_s); ++ KNotification *notification = new KNotification(u"inhibitionSummary"_s); ++ notification->setTitle(i18ncp("@title", "Unread Notification", "Unread Notifications", inhibited)); ++ notification->setText(i18ncp("@info", ++ "%1 notification was received while Do Not Disturb was active.", ++ "%1 notifications were received while Do Not Disturb was active.", ++ inhibited)); ++ notification->setIconName(u"preferences-desktop-notification-bell"_s); ++ notification->setFlags(KNotification::CloseOnTimeout); ++ notification->setComponentName(u"libnotificationmanager"_s); ++ ++ const QString showNotificationsText = i18nc( // ++ "@action:button Show the notifications popup; translate this in as short a form as possible", ++ "Show Notifications"); ++ ++ const KNotificationAction *defaultShowNotificationsAction = notification->addDefaultAction(showNotificationsText); ++ connect(defaultShowNotificationsAction, &KNotificationAction::activated, this, [this]() { ++ Q_EMIT showNotificationsRequested(); ++ }); ++ ++ const KNotificationAction *showNotificationsAction = notification->addAction(showNotificationsText); ++ connect(showNotificationsAction, &KNotificationAction::activated, this, [this]() { ++ Q_EMIT showNotificationsRequested(); ++ }); ++ ++ notification->sendEvent(); + } + + QVariant Notifications::data(const QModelIndex &index, int role) const +diff --git a/libnotificationmanager/notifications.h b/libnotificationmanager/notifications.h +index e927c472c8f..8544b6271ae 100644 +--- a/libnotificationmanager/notifications.h ++++ b/libnotificationmanager/notifications.h +@@ -597,6 +597,13 @@ Q_SIGNALS: + void jobsPercentageChanged(); + void windowChanged(QWindow *window); + ++ /** ++ * Emitted when the user has requested to show the notifications popup. ++ * ++ * This is typically connected to a button in the "Missed Notifications in Do Not Disturb" notification. ++ */ ++ void showNotificationsRequested(); ++ + protected: + void classBegin() override; + void componentComplete() override; +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/pr5627.patch b/roles/kde/patches/plasma-workspace/pr5627.patch new file mode 100644 index 0000000..dc61149 --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5627.patch @@ -0,0 +1,157 @@ +From 1641ea3897d565d672e29a7524ce4171ddbcfd32 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 25 Jun 2025 14:00:05 +0300 +Subject: [PATCH 1/2] shell: Set desktop ksplash stage when all desktop views + are ready + +If there are two outputs and the wallpaper for the first one is ready +but for the second one is not, the ksplash will be notified about the +desktop stage. + +This changes fixes checkAllDesktopsUiReady() so it sets the desktop +stage only if all desktop views are ready. +--- + shell/shellcorona.cpp | 28 +++++++++++++++------------- + shell/shellcorona.h | 2 +- + 2 files changed, 16 insertions(+), 14 deletions(-) + +diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp +index 37d93d05353..65c8ccc272e 100644 +--- a/shell/shellcorona.cpp ++++ b/shell/shellcorona.cpp +@@ -1338,6 +1338,8 @@ void ShellCorona::removeDesktop(DesktopView *desktopView) + + desktopView->destroy(); + desktopView->containment()->reactToScreenChange(); ++ ++ checkAllDesktopsUiReady(); + } + + PanelView *ShellCorona::panelView(Plasma::Containment *containment) const +@@ -1529,22 +1531,22 @@ void ShellCorona::addOutput(QScreen *screen) + #endif + } + +-void ShellCorona::checkAllDesktopsUiReady(bool ready) ++void ShellCorona::checkAllDesktopsUiReady() + { +- if (!ready) ++ const bool ready = std::ranges::all_of(std::as_const(m_desktopViewForScreen), [](const DesktopView *view) { ++ return view->containment()->isUiReady(); ++ }); ++ if (!ready) { + return; +- for (auto v : std::as_const(m_desktopViewForScreen)) { +- if (!v->containment()->isUiReady()) +- return; +- +- qCDebug(PLASMASHELL) << "Plasma Shell startup completed"; +- QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"), +- QStringLiteral("/KSplash"), +- QStringLiteral("org.kde.KSplash"), +- QStringLiteral("setStage")); +- ksplashProgressMessage.setArguments(QList() << QStringLiteral("desktop")); +- QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage); + } ++ ++ qCDebug(PLASMASHELL) << "Plasma Shell startup completed"; ++ QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"), ++ QStringLiteral("/KSplash"), ++ QStringLiteral("org.kde.KSplash"), ++ QStringLiteral("setStage")); ++ ksplashProgressMessage.setArguments(QList() << QStringLiteral("desktop")); ++ QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage); + } + + Plasma::Containment *ShellCorona::createContainmentForActivity(const QString &activity, int screenNum) +diff --git a/shell/shellcorona.h b/shell/shellcorona.h +index 0f544ca266f..7b6c6a559a1 100644 +--- a/shell/shellcorona.h ++++ b/shell/shellcorona.h +@@ -275,7 +275,7 @@ private: + DesktopView *desktopForScreen(QScreen *screen) const; + void setupWaylandIntegration(); + void executeSetupPlasmoidScript(Plasma::Containment *containment, Plasma::Applet *applet); +- void checkAllDesktopsUiReady(bool ready); ++ void checkAllDesktopsUiReady(); + void activateLauncherMenu(const QString &screenName); + void handleColorRequestedFromDBus(const QDBusMessage &msg); + +-- +GitLab + + +From 00bd19ecaccbb10d5cfcc6006b06a9714c615741 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 25 Jun 2025 14:03:28 +0300 +Subject: [PATCH 2/2] shell: Create panel views after desktop views are ready + +With the current code, the splash screen will be hidden as soon as the +wallpapers are loaded. + +However, the splash screnn is actually notified about the desktop stage +about 1-1.5 second later after the wallpaper plugin resets the loading +property. + +The reason for that is that the panel is loaded between +`wallpaper.loading = false` in the wallpaper and ShellCorona::checkAllDesktopsUiReady(). + +This change re-arranges the startup sequence so the panels are loaded +after the desktop views become ready. It reduces plasma startup time a bit. + +In long term, we should look for making panel loading as async as +possible so the main thread doesn't get blocked for too long. +--- + shell/shellcorona.cpp | 15 +++++---------- + 1 file changed, 5 insertions(+), 10 deletions(-) + +diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp +index 65c8ccc272e..6a59683dba7 100644 +--- a/shell/shellcorona.cpp ++++ b/shell/shellcorona.cpp +@@ -868,10 +868,6 @@ void ShellCorona::load() + connect(m_screenPool, &ScreenPool::screenOrderChanged, this, &ShellCorona::handleScreenOrderChanged, Qt::UniqueConnection); + connect(m_screenPool, &ScreenPool::screenRemoved, this, &ShellCorona::handleScreenRemoved, Qt::UniqueConnection); + +- if (!m_waitingPanels.isEmpty()) { +- m_waitingPanelsTimer.start(); +- } +- + if (config()->isImmutable() || !KAuthorized::authorize(QStringLiteral("plasma/plasmashell/unlockedDesktop"))) { + setImmutability(Plasma::Types::SystemImmutable); + } else { +@@ -1517,11 +1513,6 @@ void ShellCorona::addOutput(QScreen *screen) + // in the list. We still don't want to have an invisible view added. + containment->reactToScreenChange(); + +- // were there any panels for this screen before it popped up? +- if (!m_waitingPanels.isEmpty()) { +- m_waitingPanelsTimer.start(); +- } +- + if (!m_screenReorderInProgress) { + Q_EMIT availableScreenRectChanged(m_screenPool->idForScreen(screen)); + } +@@ -1547,6 +1538,10 @@ void ShellCorona::checkAllDesktopsUiReady() + QStringLiteral("setStage")); + ksplashProgressMessage.setArguments(QList() << QStringLiteral("desktop")); + QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage); ++ ++ if (!m_waitingPanels.isEmpty()) { ++ m_waitingPanelsTimer.start(); ++ } + } + + Plasma::Containment *ShellCorona::createContainmentForActivity(const QString &activity, int screenNum) +@@ -1604,7 +1599,7 @@ void ShellCorona::createWaitingPanels() + + QScreen *screen = m_screenPool->screenForId(requestedScreen); + DesktopView *desktopView = desktopForScreen(screen); +- if (!screen || !desktopView) { ++ if (!screen || !desktopView || !desktopView->containment()->isUiReady()) { + stillWaitingPanels << cont; + continue; + } +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/pr5628.patch b/roles/kde/patches/plasma-workspace/pr5628.patch new file mode 100644 index 0000000..aa2a3dd --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5628.patch @@ -0,0 +1,277 @@ +From 9171f24afe6be37e1ac384b8ef03ff89b552be7a Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 25 Jun 2025 17:25:37 +0300 +Subject: [PATCH 1/2] startkde: Remove Before=plasma-ksplash-ready.service + +This line makes ksplash wait for unrelated services such as powerdevil +and baloo. + +This change reduces plasma startup time on my machine to 2-3 seconds. +--- + startkde/systemd/plasma-workspace.target | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/startkde/systemd/plasma-workspace.target b/startkde/systemd/plasma-workspace.target +index a62db5e252a..a9113f49112 100644 +--- a/startkde/systemd/plasma-workspace.target ++++ b/startkde/systemd/plasma-workspace.target +@@ -17,7 +17,6 @@ Wants=xdg-desktop-autostart.target + BindsTo=graphical-session.target + Before=graphical-session.target + Before=xdg-desktop-autostart.target +-Before=plasma-ksplash-ready.service + Before=plasma-restoresession.service + RefuseManualStart=yes + StopWhenUnneeded=true +-- +GitLab + + +From 8202ba92b610c691b8bc6bab8ad5a1c3b9ac73da Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 25 Jun 2025 17:29:19 +0300 +Subject: [PATCH 2/2] startkde: Drop ready stage + +In order to hide the splash screen, it is sufficient just to see the +wallpaper. If more desktop environment components are loaded soon +afterwards, it is okay. + +With systemd boot, the way the ready stage is integrated is also kind +of a hack. +--- + appiumtests/CMakeLists.txt | 1 - + appiumtests/ksplash/CMakeLists.txt | 14 ---- + appiumtests/ksplash/ksplashtest.py | 79 ------------------- + ksplash/ksplashqml/splashapp.cpp | 5 +- + startkde/plasma-session/startup.cpp | 11 --- + startkde/plasma-session/startup.h | 1 - + startkde/systemd/CMakeLists.txt | 3 - + .../systemd/plasma-ksplash-ready.service.in | 10 --- + startkde/systemd/plasma-workspace.target | 1 - + 9 files changed, 2 insertions(+), 123 deletions(-) + delete mode 100644 appiumtests/ksplash/CMakeLists.txt + delete mode 100755 appiumtests/ksplash/ksplashtest.py + delete mode 100644 startkde/systemd/plasma-ksplash-ready.service.in + +diff --git a/appiumtests/CMakeLists.txt b/appiumtests/CMakeLists.txt +index 68d0b6895ba..22234aeb031 100644 +--- a/appiumtests/CMakeLists.txt ++++ b/appiumtests/CMakeLists.txt +@@ -20,5 +20,4 @@ add_subdirectory(applets) + add_subdirectory(components_tests) + add_subdirectory(kcms) + add_subdirectory(krunner) +-add_subdirectory(ksplash) + add_subdirectory(wallpapers) +diff --git a/appiumtests/ksplash/CMakeLists.txt b/appiumtests/ksplash/CMakeLists.txt +deleted file mode 100644 +index 3bea5174f5a..00000000000 +--- a/appiumtests/ksplash/CMakeLists.txt ++++ /dev/null +@@ -1,14 +0,0 @@ +-# SPDX-FileCopyrightText: 2024 Fushan Wen +-# SPDX-License-Identifier: BSD-3-Clause +- +-add_test( +- NAME ksplashtest_wayland +- COMMAND sh -c "mkdir -p /tmp/appium/ksplashtest_wayland;dbus-launch selenium-webdriver-at-spi-run ${CMAKE_CURRENT_SOURCE_DIR}/ksplashtest.py --failfast" +-) +-set_tests_properties(ksplashtest_wayland PROPERTIES TIMEOUT 60 ENVIRONMENT "XDG_RUNTIME_DIR=/tmp/appium/ksplashtest_wayland;FLASK_PORT=5701") +- +-add_test( +- NAME ksplashtest_x11 +- COMMAND sh -c "mkdir -p /tmp/appium/ksplashtest_x11;dbus-launch selenium-webdriver-at-spi-run ${CMAKE_CURRENT_SOURCE_DIR}/ksplashtest.py --failfast" +-) +-set_tests_properties(ksplashtest_x11 PROPERTIES TIMEOUT 60 ENVIRONMENT "XDG_RUNTIME_DIR=/tmp/appium/ksplashtest_x11;FLASK_PORT=5702;TEST_WITH_KWIN_WAYLAND=0") +diff --git a/appiumtests/ksplash/ksplashtest.py b/appiumtests/ksplash/ksplashtest.py +deleted file mode 100755 +index b7ca43c0519..00000000000 +--- a/appiumtests/ksplash/ksplashtest.py ++++ /dev/null +@@ -1,79 +0,0 @@ +-#!/usr/bin/env python3 +- +-# SPDX-FileCopyrightText: 2024 Fushan Wen +-# SPDX-License-Identifier: MIT +- +-# pylint: disable=too-many-arguments +- +-import os +-import subprocess +-import sys +-import time +-import unittest +- +-from appium import webdriver +-from appium.options.common.base import AppiumOptions +-from appium.webdriver.common.appiumby import AppiumBy +-from gi.repository import Gio, GLib +- +- +-class KSplashTest(unittest.TestCase): +- +- driver: webdriver.Remote +- +- @classmethod +- def setUpClass(cls) -> None: +- options = AppiumOptions() +- options.set_capability("app", "ksplashqml --window") +- options.set_capability("environ", { +- "LC_ALL": "en_US.UTF-8", +- "QT_FATAL_WARNINGS": "1", +- "QT_LOGGING_RULES": "qt.accessibility.atspi.warning=false;kf.plasma.core.warning=false;kf.windowsystem.warning=false;kf.kirigami.platform.warning=false;org.kde.plasma.ksplashqml.debug=true", +- }) +- options.set_capability("timeouts", {'implicit': 10000}) +- cls.driver = webdriver.Remote(command_executor=f'http://127.0.0.1:{os.getenv("FLASK_PORT", "4723")}', options=options) +- +- def tearDown(self) -> None: +- """ +- Take screenshot when the current test fails +- """ +- if not self._outcome.result.wasSuccessful(): +- self.driver.get_screenshot_as_file(f"failed_test_shot_ksplash_#{self.id()}.png") +- +- def test_1_bug494840_setStage(self) -> None: +- """ +- Checks if the setStage method is ever called after starting plasma-ksplash-ready.service. +- """ +- if os.getenv("TEST_WITH_KWIN_WAYLAND", "1") == "0": +- stages = ("wm", "kcminit", "ksmserver", "startPlasma", "desktop") +- else: +- stages = ("kcminit", "ksmserver", "startPlasma", "desktop") +- +- session_bus = Gio.bus_get_sync(Gio.BusType.SESSION) +- for stage in stages: +- message: Gio.DBusMessage = Gio.DBusMessage.new_method_call("org.kde.KSplash", "/KSplash", "org.kde.KSplash", "setStage") +- message.set_body(GLib.Variant("(s)", [stage])) +- session_bus.send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE, 3000) +- +- self.driver.find_element(AppiumBy.NAME, "Plasma made by KDE") +- +- with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir, "startkde", "systemd", "plasma-ksplash-ready.service.in"), encoding="utf-8") as handler: +- for line in handler: +- if line.startswith("ExecStart="): +- command = line.removeprefix("ExecStart=").strip().split(" ") +- subprocess.check_call(command, stdout=sys.stderr, stderr=sys.stderr) +- break +- +- success = False +- for _ in range(10): +- try: +- subprocess.check_call(["pidof", "ksplashqml"]) +- except subprocess.CalledProcessError: +- success = True +- break +- time.sleep(1) +- self.assertTrue(success) +- +- +-if __name__ == '__main__': +- unittest.main() +diff --git a/ksplash/ksplashqml/splashapp.cpp b/ksplash/ksplashqml/splashapp.cpp +index b60a58724be..2262503b1c3 100644 +--- a/ksplash/ksplashqml/splashapp.cpp ++++ b/ksplash/ksplashqml/splashapp.cpp +@@ -26,13 +26,12 @@ + #define TEST_STEP_INTERVAL 2000 + + /** +- * There are 7 stages in ksplash ++ * There are 6 stages in ksplash + * - initial (from this class) + * - startPlasma (from startplasma) + * - kcminit + * - ksmserver + * - wm (for X11 from KWin, for Wayland from this class) +- * - ready (from plasma-session startup) + * - desktop (from shellcorona) + */ + +@@ -114,7 +113,7 @@ void SplashApp::setStage(const QString &stage) + void SplashApp::setStage(int stage) + { + m_stage = stage; +- if (m_stage == 7) { ++ if (m_stage == 6) { + QGuiApplication::exit(EXIT_SUCCESS); + } + for (SplashWindow *w : std::as_const(m_windows)) { +diff --git a/startkde/plasma-session/startup.cpp b/startkde/plasma-session/startup.cpp +index a731c7b2791..0567e00881f 100644 +--- a/startkde/plasma-session/startup.cpp ++++ b/startkde/plasma-session/startup.cpp +@@ -206,20 +206,9 @@ Startup::Startup(QObject *parent) + // app will be closed when all KJobs finish thanks to the QEventLoopLocker in each KJob + } + +-void Startup::upAndRunning(const QString &msg) +-{ +- QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"), +- QStringLiteral("/KSplash"), +- QStringLiteral("org.kde.KSplash"), +- QStringLiteral("setStage")); +- ksplashProgressMessage.setArguments(QList() << msg); +- QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage); +-} +- + void Startup::finishStartup() + { + qCDebug(PLASMA_SESSION) << "Finished"; +- upAndRunning(QStringLiteral("ready")); + + playStartupSound(); + new SessionTrack(m_processes); +diff --git a/startkde/plasma-session/startup.h b/startkde/plasma-session/startup.h +index 6ef4fee9bdd..876a1439fce 100644 +--- a/startkde/plasma-session/startup.h ++++ b/startkde/plasma-session/startup.h +@@ -20,7 +20,6 @@ class Startup : public QObject + Q_OBJECT + public: + Startup(QObject *parent); +- void upAndRunning(const QString &msg); + void finishStartup(); + + static Startup *self() +diff --git a/startkde/systemd/CMakeLists.txt b/startkde/systemd/CMakeLists.txt +index 2f5d30e8456..c3455ebae81 100644 +--- a/startkde/systemd/CMakeLists.txt ++++ b/startkde/systemd/CMakeLists.txt +@@ -1,6 +1,3 @@ +-ecm_install_configured_files(INPUT plasma-ksplash-ready.service.in @ONLY +- DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR}) +- + install(FILES plasma-core.target DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR}) + install(FILES plasma-workspace.target DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR}) + install(FILES plasma-workspace-wayland.target DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR}) +diff --git a/startkde/systemd/plasma-ksplash-ready.service.in b/startkde/systemd/plasma-ksplash-ready.service.in +deleted file mode 100644 +index 1e903130a96..00000000000 +--- a/startkde/systemd/plasma-ksplash-ready.service.in ++++ /dev/null +@@ -1,10 +0,0 @@ +-[Unit] +-Description=KSplash "ready" Stage +-Wants=plasma-core.target +-After=plasma-core.target +-PartOf=graphical-session.target +- +-[Service] +-Type=oneshot +-ExecStart=dbus-send --session --reply-timeout=1 --type=method_call --dest=org.kde.KSplash /KSplash org.kde.KSplash.setStage string:ready +-Slice=session.slice +diff --git a/startkde/systemd/plasma-workspace.target b/startkde/systemd/plasma-workspace.target +index a9113f49112..4cc8d9330c3 100644 +--- a/startkde/systemd/plasma-workspace.target ++++ b/startkde/systemd/plasma-workspace.target +@@ -6,7 +6,6 @@ Wants=plasma-restoresession.service + Wants=plasma-xembedsniproxy.service + Wants=plasma-gmenudbusmenuproxy.service + Wants=plasma-powerdevil.service +-Wants=plasma-ksplash-ready.service + Wants=plasma-polkit-agent.service + Wants=kde-baloo.service + Wants=plasma-foreground-booster.service +-- +GitLab + diff --git a/roles/kde/patches/spectacle/patches.txt b/roles/kde/patches/spectacle/patches.txt new file mode 100644 index 0000000..587da02 --- /dev/null +++ b/roles/kde/patches/spectacle/patches.txt @@ -0,0 +1,3 @@ +Plasma 6.5.0: + +Pr 460 https://invent.kde.org/plasma/spectacle/-/merge_requests/460 diff --git a/roles/kde/patches/spectacle/pr460.patch b/roles/kde/patches/spectacle/pr460.patch new file mode 100644 index 0000000..63c6cfa --- /dev/null +++ b/roles/kde/patches/spectacle/pr460.patch @@ -0,0 +1,228 @@ +From 97f209559c00acc1ea6d0736bb318ac0254a3e37 Mon Sep 17 00:00:00 2001 +From: Noah Davis +Date: Wed, 4 Jun 2025 16:06:06 -0400 +Subject: [PATCH 1/2] Say which shortcut can stop recording in recording + notification + +It will say Meta+R by default, but will show the shortcut used to initiate the recording instead if Meta+R isn't assigned to region recording. + +BUG: 505081 +--- + src/Platforms/VideoPlatform.cpp | 16 +++++++++++++++ + src/Platforms/VideoPlatform.h | 4 ++++ + src/Platforms/VideoPlatformWayland.cpp | 6 ++++-- + src/SpectacleCore.cpp | 28 +++++++++++++++++++++++++- + 4 files changed, 51 insertions(+), 3 deletions(-) + +diff --git a/src/Platforms/VideoPlatform.cpp b/src/Platforms/VideoPlatform.cpp +index 592539048..333692326 100644 +--- a/src/Platforms/VideoPlatform.cpp ++++ b/src/Platforms/VideoPlatform.cpp +@@ -69,6 +69,11 @@ VideoPlatform::RecordingState VideoPlatform::recordingState() const + return m_recordingState; + } + ++VideoPlatform::RecordingMode VideoPlatform::recordingMode() const ++{ ++ return m_recordingMode; ++} ++ + void VideoPlatform::setRecordingState(RecordingState state) + { + if (state == m_recordingState) { +@@ -91,9 +96,20 @@ void VideoPlatform::setRecordingState(RecordingState state) + m_elapsedTimer.invalidate(); + m_basicTimer.stop(); + } ++ if (state != RecordingState::Recording) { ++ setRecordingMode(NoRecordingModes); ++ } + m_recordingState = state; + Q_EMIT recordingStateChanged(state); + Q_EMIT recordedTimeChanged(); + } + ++void VideoPlatform::setRecordingMode(RecordingMode mode) ++{ ++ if (m_recordingMode == mode) { ++ return; ++ } ++ m_recordingMode = mode; ++} ++ + #include "moc_VideoPlatform.cpp" +diff --git a/src/Platforms/VideoPlatform.h b/src/Platforms/VideoPlatform.h +index 4f5fba720..eea81e32a 100644 +--- a/src/Platforms/VideoPlatform.h ++++ b/src/Platforms/VideoPlatform.h +@@ -129,8 +129,11 @@ public: + + RecordingState recordingState() const; + ++ RecordingMode recordingMode() const; ++ + protected: + void setRecordingState(RecordingState state); ++ void setRecordingMode(RecordingMode mode); + void timerEvent(QTimerEvent *event) override; + + public Q_SLOTS: +@@ -157,6 +160,7 @@ private: + QBasicTimer m_basicTimer; + qint64 m_recordedTime = 0; + RecordingState m_recordingState = RecordingState::NotRecording; ++ RecordingMode m_recordingMode = RecordingMode::NoRecordingModes; + }; + + Q_DECLARE_OPERATORS_FOR_FLAGS(VideoPlatform::RecordingModes) +diff --git a/src/Platforms/VideoPlatformWayland.cpp b/src/Platforms/VideoPlatformWayland.cpp +index 648f8adbf..984ede0eb 100644 +--- a/src/Platforms/VideoPlatformWayland.cpp ++++ b/src/Platforms/VideoPlatformWayland.cpp +@@ -245,11 +245,12 @@ void VideoPlatformWayland::startRecording(const QUrl &fileUrl, RecordingMode rec + m_recorder->setNodeId(0); + + Q_ASSERT(stream); +- connect(stream, &ScreencastingStream::created, this, [this, stream] { ++ connect(stream, &ScreencastingStream::created, this, [this, stream, recordingMode] { + m_recorder->setNodeId(stream->nodeId()); + if (!m_recorder->output().isEmpty()) { + m_recorder->start(); + } ++ setRecordingMode(recordingMode); + setRecordingState(VideoPlatform::RecordingState::Recording); + }); + connect(stream, &ScreencastingStream::failed, this, [this](const QString &error) { +@@ -302,7 +303,7 @@ void VideoPlatformWayland::startRecording(const QUrl &fileUrl, RecordingMode rec + m_recorder->start(); + } + +- connect(m_recorder.get(), &PipeWireRecord::stateChanged, this, [this] { ++ connect(m_recorder.get(), &PipeWireRecord::stateChanged, this, [this, recordingMode] { + if (m_recorder->state() == PipeWireRecord::Idle) { + m_memoryTimer.stop(); + if (recordingState() != RecordingState::NotRecording && recordingState() != RecordingState::Finished) { +@@ -311,6 +312,7 @@ void VideoPlatformWayland::startRecording(const QUrl &fileUrl, RecordingMode rec + } + } else if (m_recorder->state() == PipeWireRecord::Recording) { + m_memoryTimer.start(5000, Qt::CoarseTimer, this); ++ setRecordingMode(recordingMode); + setRecordingState(VideoPlatform::RecordingState::Recording); + } else if (m_recorder->state() == PipeWireRecord::Rendering) { + m_memoryTimer.stop(); +diff --git a/src/SpectacleCore.cpp b/src/SpectacleCore.cpp +index 8033751c9..aa2e8c6e1 100644 +--- a/src/SpectacleCore.cpp ++++ b/src/SpectacleCore.cpp +@@ -281,7 +281,33 @@ SpectacleCore::SpectacleCore(QObject *parent) + SpectacleCore::instance()->finishRecording(); + }); + const auto messageTitle = i18nc("recording notification title", "Spectacle is Recording"); +- const auto messageBody = i18nc("recording notification message", "Click the system tray icon to finish recording"); ++ auto getSimpleDefaultShortcut = [] { ++ const auto shortcuts = KGlobalAccel::self()->shortcut(ShortcutActions::self()->recordRegionAction()); ++ if (shortcuts.contains(QKeySequence{Qt::META | Qt::Key_R})) { ++ return QKeySequence{Qt::META | Qt::Key_R}; ++ } ++ return QKeySequence{}; ++ }; ++ auto getShortcut = [](const auto &list) { ++ auto it = std::find_if(list.cbegin(), list.cend(), [](const QKeySequence &shortcut) { ++ return !shortcut.isEmpty(); ++ }); ++ return it != list.cend() ? *it : QKeySequence{}; ++ }; ++ QKeySequence stopShortcut = getSimpleDefaultShortcut(); ++ if (stopShortcut.isEmpty()) { ++ auto mode = m_videoPlatform->recordingMode(); ++ if (mode == VideoPlatform::Screen) { ++ stopShortcut = getShortcut(KGlobalAccel::self()->shortcut(ShortcutActions::self()->recordScreenAction())); ++ } else if (mode == VideoPlatform::Window) { ++ stopShortcut = getShortcut(KGlobalAccel::self()->shortcut(ShortcutActions::self()->recordWindowAction())); ++ } else if (mode == VideoPlatform::Region) { ++ stopShortcut = getShortcut(KGlobalAccel::self()->shortcut(ShortcutActions::self()->recordRegionAction())); ++ } ++ } ++ const auto messageBody = stopShortcut.isEmpty() ++ ? i18nc("recording notification message without shortcut", "To finish the recording, click the pulsing red System Tray icon.") ++ : xi18nc("recording notification message with shortcut", "To finish the recording, click the pulsing red System Tray icon or press %1.", stopShortcut.toString(QKeySequence::NativeText)); + auto notification = new KNotification(u"notification"_s, KNotification::CloseOnTimeout | KNotification::DefaultEvent, this); + notification->setTitle(messageTitle); + notification->setText(messageBody); +-- +GitLab + + +From 7fd2fe158408b6285f9855f7fcf34e77d4ecb764 Mon Sep 17 00:00:00 2001 +From: Noah Davis +Date: Thu, 12 Jun 2025 16:12:48 -0400 +Subject: [PATCH 2/2] Rename shortcuts to show that they can start or stop + recording + +BUG: 505081 +--- + desktop/org.kde.spectacle.desktop.cmake | 6 +++--- + src/ShortcutActions.cpp | 6 +++--- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/desktop/org.kde.spectacle.desktop.cmake b/desktop/org.kde.spectacle.desktop.cmake +index 4e36b18e6..800fcb62b 100644 +--- a/desktop/org.kde.spectacle.desktop.cmake ++++ b/desktop/org.kde.spectacle.desktop.cmake +@@ -474,7 +474,7 @@ Exec=${KDE_INSTALL_FULL_BINDIR}/spectacle -u + X-KDE-Shortcuts=Meta+Ctrl+Print + + [Desktop Action RecordRegion] +-Name=Record Rectangular Region ++Name=Start/Stop Region Recording + Name[ar]=يسجل منطقة مستطيلة + Name[az]=Düzbucaqlı sahəni yazmaq + Name[bg]=Заснемане на правоъгълен регион +@@ -522,7 +522,7 @@ Exec=${KDE_INSTALL_FULL_BINDIR}/spectacle -R region + X-KDE-Shortcuts=Meta+Shift+R,Meta+R + + [Desktop Action RecordScreen] +-Name=Record Screen ++Name=Start/Stop Screen Recording + Name[ar]=سجّل الشاشة + Name[az]=Ekranı yazmaq + Name[bg]=Запис на екрана +@@ -570,7 +570,7 @@ Exec=${KDE_INSTALL_FULL_BINDIR}/spectacle -R screen + X-KDE-Shortcuts=Meta+Alt+R + + [Desktop Action RecordWindow] +-Name=Record Window ++Name=Start/Stop Window Recording + Name[ar]=سجل النافذة + Name[az]=Pəncərəni yazmaq + Name[bg]=Запис на прозорец +diff --git a/src/ShortcutActions.cpp b/src/ShortcutActions.cpp +index ee73bcfe5..a1464d06d 100644 +--- a/src/ShortcutActions.cpp ++++ b/src/ShortcutActions.cpp +@@ -73,19 +73,19 @@ ShortcutActions::ShortcutActions() + mActions.addAction(action->objectName(), action); + } + { +- QAction *action = new QAction(i18nc("@action global shortcut", "Record Screen"), &mActions); ++ QAction *action = new QAction(i18nc("@action global shortcut", "Start/Stop Screen Recording"), &mActions); + action->setObjectName(u"RecordScreen"_s); + action->setProperty("isConfigurationAction", true); + mActions.addAction(action->objectName(), action); + } + { +- QAction *action = new QAction(i18nc("@action global shortcut", "Record Window"), &mActions); ++ QAction *action = new QAction(i18nc("@action global shortcut", "Start/Stop Window Recording"), &mActions); + action->setObjectName(u"RecordWindow"_s); + action->setProperty("isConfigurationAction", true); + mActions.addAction(action->objectName(), action); + } + { +- QAction *action = new QAction(i18nc("@action global shortcut", "Record Rectangular Region"), &mActions); ++ QAction *action = new QAction(i18nc("@action global shortcut", "Start/Stop Region Recording"), &mActions); + action->setObjectName(u"RecordRegion"_s); + action->setProperty("isConfigurationAction", true); + mActions.addAction(action->objectName(), action); +-- +GitLab + From 7c242b437d78ed779558ecde6dd3c629ee9508af Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 5 Jul 2025 19:24:24 +0200 Subject: [PATCH 1001/1125] Desktop/discord: use catppuccin vencord module --- roles/desktop/programs/discord.nix | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 7e851c7..2373e40 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -8,6 +8,7 @@ in { nixpkgs.overlays = [discordOverlay]; home-manager.users.toast = { + catppuccin.vesktop.enable = true; programs.vesktop = { enable = true; settings = { @@ -20,7 +21,6 @@ in { }; vencord = { settings = { - enabledThemes = ["catpuccin-mocha.css"]; plugins = { BetterGifPicker.enabled = true; BetterSettings.enabled = true; @@ -52,21 +52,6 @@ in { YoutubeAdblock.enabled = true; }; }; - themes = { - "catpuccin-mocha" = '' - /** - * @name Catppuccin Mocha - * @author winston#0001 - * @authorId 505490445468696576 - * @version 0.2.0 - * @description 🎮 Soothing pastel theme for Discord - * @website https://github.com/catppuccin/discord - * @invite r6Mdz5dpFc - * **/ - - @import url("https://catppuccin.github.io/discord/dist/catppuccin-mocha-mauve.theme.css"); - ''; - }; }; }; }; From a959fb46be3cb8c32fd9c79302ffb66164788026 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 6 Jul 2025 13:15:00 +0200 Subject: [PATCH 1002/1125] Common/atuin: set default filter mode to workspace --- roles/common/programs/atuin.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/programs/atuin.nix b/roles/common/programs/atuin.nix index 71c9c71..ab493cd 100644 --- a/roles/common/programs/atuin.nix +++ b/roles/common/programs/atuin.nix @@ -6,6 +6,7 @@ settings = { enter_accept = true; workspaces = true; + filter_mode = "workspace"; style = "auto"; inline_height = 0; stats = { From 19493e8ef6a2a17291c62c592ad5c999e87170bb Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 9 Jul 2025 13:56:20 +0200 Subject: [PATCH 1003/1125] Kde/patches: update patches --- .../{pr5628.patch => commit8202ba92.patch} | 31 +------------------ .../kde/patches/plasma-workspace/patches.txt | 3 +- 2 files changed, 3 insertions(+), 31 deletions(-) rename roles/kde/patches/plasma-workspace/{pr5628.patch => commit8202ba92.patch} (90%) diff --git a/roles/kde/patches/plasma-workspace/pr5628.patch b/roles/kde/patches/plasma-workspace/commit8202ba92.patch similarity index 90% rename from roles/kde/patches/plasma-workspace/pr5628.patch rename to roles/kde/patches/plasma-workspace/commit8202ba92.patch index aa2a3dd..cb5fb13 100644 --- a/roles/kde/patches/plasma-workspace/pr5628.patch +++ b/roles/kde/patches/plasma-workspace/commit8202ba92.patch @@ -1,36 +1,7 @@ -From 9171f24afe6be37e1ac384b8ef03ff89b552be7a Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Wed, 25 Jun 2025 17:25:37 +0300 -Subject: [PATCH 1/2] startkde: Remove Before=plasma-ksplash-ready.service - -This line makes ksplash wait for unrelated services such as powerdevil -and baloo. - -This change reduces plasma startup time on my machine to 2-3 seconds. ---- - startkde/systemd/plasma-workspace.target | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/startkde/systemd/plasma-workspace.target b/startkde/systemd/plasma-workspace.target -index a62db5e252a..a9113f49112 100644 ---- a/startkde/systemd/plasma-workspace.target -+++ b/startkde/systemd/plasma-workspace.target -@@ -17,7 +17,6 @@ Wants=xdg-desktop-autostart.target - BindsTo=graphical-session.target - Before=graphical-session.target - Before=xdg-desktop-autostart.target --Before=plasma-ksplash-ready.service - Before=plasma-restoresession.service - RefuseManualStart=yes - StopWhenUnneeded=true --- -GitLab - - From 8202ba92b610c691b8bc6bab8ad5a1c3b9ac73da Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 25 Jun 2025 17:29:19 +0300 -Subject: [PATCH 2/2] startkde: Drop ready stage +Subject: [PATCH] startkde: Drop ready stage In order to hide the splash screen, it is sufficient just to see the wallpaper. If more desktop environment components are loaded soon diff --git a/roles/kde/patches/plasma-workspace/patches.txt b/roles/kde/patches/plasma-workspace/patches.txt index d704604..56ecbad 100644 --- a/roles/kde/patches/plasma-workspace/patches.txt +++ b/roles/kde/patches/plasma-workspace/patches.txt @@ -3,4 +3,5 @@ Plasma 6.5.0: Pr 5589 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5589 Pr 5626 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5626 Pr 5627 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5627 -Pr 5628 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5628 +Commit 8202ba92 https://invent.kde.org/plasma/plasma-workspace/-/commit/8202ba92b610c691b8bc6bab8ad5a1c3b9ac73da + Part of https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5628, the other part got cherry picked on 6.4.2 From a82ddf87df25d06816f75cf341f6b5837f07bc0c Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 9 Jul 2025 13:59:32 +0200 Subject: [PATCH 1004/1125] Kde/patches: remove unneeded kwin patches --- roles/kde/patches/kwin/patches.txt | 4 -- roles/kde/patches/kwin/pr7822.patch | 40 -------------- roles/kde/patches/kwin/pr7829.patch | 85 ----------------------------- 3 files changed, 129 deletions(-) delete mode 100644 roles/kde/patches/kwin/pr7822.patch delete mode 100644 roles/kde/patches/kwin/pr7829.patch diff --git a/roles/kde/patches/kwin/patches.txt b/roles/kde/patches/kwin/patches.txt index 352c63d..cf1766b 100644 --- a/roles/kde/patches/kwin/patches.txt +++ b/roles/kde/patches/kwin/patches.txt @@ -1,7 +1,3 @@ Plasma 6.5.0: Pr 3612 https://invent.kde.org/plasma/kwin/-/merge_requests/3612 Pr 7823 https://invent.kde.org/plasma/kwin/-/merge_requests/7823 - -Plasma 6.4.2: -Pr 7822 https://invent.kde.org/plasma/kwin/-/merge_requests/7822 -Pr 7829 https://invent.kde.org/plasma/kwin/-/merge_requests/7829 diff --git a/roles/kde/patches/kwin/pr7822.patch b/roles/kde/patches/kwin/pr7822.patch deleted file mode 100644 index aca6909..0000000 --- a/roles/kde/patches/kwin/pr7822.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 3ac297b99540eae81568edca1e550ca7d1d6c01f Mon Sep 17 00:00:00 2001 -From: Ismael Asensio -Date: Tue, 24 Jun 2025 17:08:00 +0200 -Subject: [PATCH] plugins/fadingpopups: Blacklist spectacle popup menus from - fading effect - -Spectacle can trigger a screenshot from a popup menu. This menu needs -to get hidden immediately with no effects, to avoid appearing on the -screenshot. - -BUG: 505803 -FIXED-IN: 6.4.2 - - -(cherry picked from commit 99f6418e3c2e044eb1f4e8bedcdccac55f1a01d4) - -Co-authored-by: Ismael Asensio ---- - src/plugins/fadingpopups/package/contents/code/main.js | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/plugins/fadingpopups/package/contents/code/main.js b/src/plugins/fadingpopups/package/contents/code/main.js -index f0764b42ac6..7c00640ae8f 100644 ---- a/src/plugins/fadingpopups/package/contents/code/main.js -+++ b/src/plugins/fadingpopups/package/contents/code/main.js -@@ -17,7 +17,10 @@ var blacklist = [ - // The lockscreen isn't a popup window - "kscreenlocker_greet kscreenlocker_greet", - // KDE Plasma splash screen has to be animated only by the login effect. -- "ksplashqml ksplashqml" -+ "ksplashqml ksplashqml", -+ // Spectacle can trigger a screenshot from a popup menu -+ "spectacle org.kde.spectacle", -+ "spectacle spectacle", - ]; - - function isPopupWindow(window) { --- -GitLab - diff --git a/roles/kde/patches/kwin/pr7829.patch b/roles/kde/patches/kwin/pr7829.patch deleted file mode 100644 index fe92562..0000000 --- a/roles/kde/patches/kwin/pr7829.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 4ddb4a23d5f453cf890c9f1b1aa5429150991db3 Mon Sep 17 00:00:00 2001 -From: David Redondo -Date: Thu, 26 Jun 2025 17:00:07 +0200 -Subject: [PATCH] scene: Skip visibility check for the Item itself in - framePainted - -Fixes offscreen rendering and window thumbnails for hidden windows -not udpating. -Co-authored-by: Vlad Zahorodnii ---- - src/scene/item.cpp | 9 +++++---- - src/scene/item.h | 2 +- - src/scene/rootitem.cpp | 9 --------- - src/scene/rootitem.h | 2 -- - 4 files changed, 6 insertions(+), 16 deletions(-) - -diff --git a/src/scene/item.cpp b/src/scene/item.cpp -index 2637a131dbd..eb2b6b46977 100644 ---- a/src/scene/item.cpp -+++ b/src/scene/item.cpp -@@ -648,12 +648,13 @@ void Item::removeEffect() - - void Item::framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp) - { -- if (!isVisible() || workspace()->outputAt(mapToScene(boundingRect()).center()) != output) { -- return; -- } -+ // The visibility of the item itself is not checked here to be able to paint hidden items for -+ // things like screncasts or thumbnails - handleFramePainted(output, frame, timestamp); - for (const auto child : std::as_const(m_childItems)) { -- child->framePainted(output, frame, timestamp); -+ if (child->explicitVisible() && workspace()->outputAt(child->mapToScene(child->boundingRect()).center()) == output) { -+ child->framePainted(output, frame, timestamp); -+ } - } - } - -diff --git a/src/scene/item.h b/src/scene/item.h -index acb29994328..d42b32abf7b 100644 ---- a/src/scene/item.h -+++ b/src/scene/item.h -@@ -144,7 +144,7 @@ public: - void addEffect(); - void removeEffect(); - -- virtual void framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp); -+ void framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp); - - bool isAncestorOf(const Item *item) const; - -diff --git a/src/scene/rootitem.cpp b/src/scene/rootitem.cpp -index fe0cecc76e3..466a25ce828 100644 ---- a/src/scene/rootitem.cpp -+++ b/src/scene/rootitem.cpp -@@ -14,13 +14,4 @@ RootItem::RootItem(Scene *scene) - setScene(scene); - } - --void RootItem::framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp) --{ -- handleFramePainted(output, frame, timestamp); -- const auto children = childItems(); -- for (const auto child : children) { -- child->framePainted(output, frame, timestamp); -- } --} -- - } // namespace KWin -diff --git a/src/scene/rootitem.h b/src/scene/rootitem.h -index 45fa1359c84..43b3cdb90e9 100644 ---- a/src/scene/rootitem.h -+++ b/src/scene/rootitem.h -@@ -20,8 +20,6 @@ class KWIN_EXPORT RootItem : public Item - - public: - explicit RootItem(Scene *scene); -- -- void framePainted(Output *output, OutputFrame *frame, std::chrono::milliseconds timestamp) override; - }; - - } // namespace KWin --- -GitLab - From fe93e06d34d2e872a6193027285f7b398bb4fe85 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 9 Jul 2025 15:15:41 +0200 Subject: [PATCH 1005/1125] Flake: update lock file --- flake.lock | 78 +++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/flake.lock b/flake.lock index 5ba81fe..60574fa 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1751620524, - "narHash": "sha256-zuIiAbZJPaUPzo7nAvN6VpC44rNYju5vNPROvYaEBy4=", + "lastModified": 1751880463, + "narHash": "sha256-aSQllMKqsTYAUp4yhpspZn0Hj5yIj7Mh4UD5iyk5iMM=", "owner": "catppuccin", "repo": "nix", - "rev": "194881dd2ad6303bc2d49f9ce484d127372d7465", + "rev": "9474347c69e93e392f194dda7a57c641ba4b998e", "type": "github" }, "original": { @@ -167,11 +167,11 @@ ] }, "locked": { - "lastModified": 1751589297, - "narHash": "sha256-3q35cq6BPuwIRL3IoVKYPc72r3OleeuRyf4YAPjEqzA=", + "lastModified": 1751990210, + "narHash": "sha256-krWErNDl9ggMLSfK00Q2BcoSk3+IRTSON/DiDgUzzMw=", "owner": "nix-community", "repo": "home-manager", - "rev": "83f978812c37511ef2ffaf75ffa72160483f738a", + "rev": "218da00bfa73f2a61682417efe74549416c16ba6", "type": "github" }, "original": { @@ -187,11 +187,11 @@ ] }, "locked": { - "lastModified": 1751468302, - "narHash": "sha256-tWosziZTT039x6PgEZUhzGlV8oLvdDmIgKTE8ESMaEA=", + "lastModified": 1751810233, + "narHash": "sha256-kllkNbIqQi3VplgTMeGzuh1t8Gk8TauvkTRt93Km+tQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "501cfec8277f931a9c9af9f23d3105c537faeafe", + "rev": "9b0873b46c9f9e4b7aa01eb634952c206af53068", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1751529406, - "narHash": "sha256-jwKDHyUycp678zDYa5Hyfq3msO73YMXdZPxp96dU7po=", + "lastModified": 1752052164, + "narHash": "sha256-rq5aT1acTwLMAds//7WLtZhZGC5Hyr5YQqbiA0kb3yo=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "b2e5ce654e4f5bf8905c2e07a96dcf4966e6277d", + "rev": "f81c48f403c976463fe5812e9e6bca8cf49aebdc", "type": "github" }, "original": { @@ -225,11 +225,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1751575060, - "narHash": "sha256-nDlS4deJqTbLAulAr8bwE5lt/AVnBhVMrFlYZr78ToY=", - "rev": "897f87e76ac051b50b8438d2355463b95f6cd805", + "lastModified": 1751931138, + "narHash": "sha256-Q0pIV16Vx9PZQRVXc1GS/IcKYlmcVMdkSGPdBsiLyKU=", + "rev": "fc3261c3405b122c8c2e5bdc3da6c4fb7ffa80a9", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/897f87e76ac051b50b8438d2355463b95f6cd805.tar.gz?rev=897f87e76ac051b50b8438d2355463b95f6cd805" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/fc3261c3405b122c8c2e5bdc3da6c4fb7ffa80a9.tar.gz?rev=fc3261c3405b122c8c2e5bdc3da6c4fb7ffa80a9" }, "original": { "type": "tarball", @@ -248,11 +248,11 @@ ] }, "locked": { - "lastModified": 1751240140, - "narHash": "sha256-gbFOUtmkzzNAiHoUtySwbi+AVDgWOW8CpWmTmkoaQiI=", - "rev": "ea74d925e650948d296fb85e4671fb0ce944f550", + "lastModified": 1751909859, + "narHash": "sha256-gbpuESxl/An4GTh7QEbQRYJozVIxWkwVGbWK0/0GoRc=", + "rev": "4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/ea74d925e650948d296fb85e4671fb0ce944f550.tar.gz?rev=ea74d925e650948d296fb85e4671fb0ce944f550" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f.tar.gz?rev=4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f" }, "original": { "type": "tarball", @@ -271,11 +271,11 @@ ] }, "locked": { - "lastModified": 1751240140, - "narHash": "sha256-gbFOUtmkzzNAiHoUtySwbi+AVDgWOW8CpWmTmkoaQiI=", - "rev": "ea74d925e650948d296fb85e4671fb0ce944f550", + "lastModified": 1751909859, + "narHash": "sha256-gbpuESxl/An4GTh7QEbQRYJozVIxWkwVGbWK0/0GoRc=", + "rev": "4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/ea74d925e650948d296fb85e4671fb0ce944f550.tar.gz?rev=ea74d925e650948d296fb85e4671fb0ce944f550" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f.tar.gz?rev=4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f" }, "original": { "type": "tarball", @@ -342,11 +342,11 @@ ] }, "locked": { - "lastModified": 1751170039, - "narHash": "sha256-3EKpUmyGmHYA/RuhZjINTZPU+OFWko0eDwazUOW64nw=", + "lastModified": 1751774635, + "narHash": "sha256-DuOznGdgMxeSlPpUu6Wkq0ZD5e2Cfv9XRZeZlHWMd1s=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "9c932ae632d6b5150515e5749b198c175d8565db", + "rev": "85686025ba6d18df31cc651a91d5adef63378978", "type": "github" }, "original": { @@ -362,11 +362,11 @@ ] }, "locked": { - "lastModified": 1751170039, - "narHash": "sha256-3EKpUmyGmHYA/RuhZjINTZPU+OFWko0eDwazUOW64nw=", + "lastModified": 1751774635, + "narHash": "sha256-DuOznGdgMxeSlPpUu6Wkq0ZD5e2Cfv9XRZeZlHWMd1s=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "9c932ae632d6b5150515e5749b198c175d8565db", + "rev": "85686025ba6d18df31cc651a91d5adef63378978", "type": "github" }, "original": { @@ -377,11 +377,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1751432711, - "narHash": "sha256-136MeWtckSHTN9Z2WRNRdZ8oRP3vyx3L8UxeBYE+J9w=", + "lastModified": 1752048960, + "narHash": "sha256-gATnkOe37eeVwKKYCsL+OnS2gU4MmLuZFzzWCtaKLI8=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "497ae1357f1ac97f1aea31a4cb74ad0d534ef41f", + "rev": "7ced9122cff2163c6a0212b8d1ec8c33a1660806", "type": "github" }, "original": { @@ -409,11 +409,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1751479989, - "narHash": "sha256-M5KgdpVBVcW4HRVq9/OSRbrxlwsQ1ogEKqnvzsClDqU=", + "lastModified": 1751943650, + "narHash": "sha256-7orTnNqkGGru8Je6Un6mq1T8YVVU/O5kyW4+f9C1mZQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "34627c90f062da515ea358360f448da57769236e", + "rev": "88983d4b665fb491861005137ce2b11a9f89f203", "type": "github" }, "original": { @@ -424,11 +424,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1751271578, - "narHash": "sha256-P/SQmKDu06x8yv7i0s8bvnnuJYkxVGBWLWHaU+tt4YY=", + "lastModified": 1751792365, + "narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3016b4b15d13f3089db8a41ef937b13a9e33a8df", + "rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb", "type": "github" }, "original": { From 264942168d57e8b78cbcea2064096cd7716145ef Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 21 Jul 2025 13:18:21 +0200 Subject: [PATCH 1006/1125] Machines/Everest: update eno1 prefixLength Forgot to update this when I switched to the isp router. Whoops! --- machines/Everest/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index 9e3c081..f6eb874 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -23,7 +23,7 @@ ipv4.addresses = [ { address = "192.168.1.160"; - prefixLength = 8; + prefixLength = 24; } ]; }; From 820e082f494ef86ad80eba552e8fd6c9152bcfe8 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 19 Jul 2025 02:27:22 +0200 Subject: [PATCH 1007/1125] Kde/plasma: enable i2c --- roles/kde/plasma.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index 467ff8a..ae96ca0 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -49,6 +49,9 @@ in { plasma-vault ]; + # Allows controlling brightness on external monitors + hardware.i2c.enable = true; + # Plasma configs should be on all users home-manager.sharedModules = [ { From 25cad55c78d8de0cd6f049ee8d866d98844947f4 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 19 Jul 2025 03:14:11 +0200 Subject: [PATCH 1008/1125] Gaming/pcsx2: update ps2 bios link --- roles/gaming/programs/pcsx2.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index cb2cda2..a8e5838 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -4,7 +4,7 @@ ... }: let pcsx2-bios = pkgs.fetchzip { - url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202%20-%20BIOS%20Images/ps2-0200a-20040614.zip"; + url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202%20-%20BIOS%20Images%20%28DoM%20Version%29/ps2-0200a-20040614.zip"; hash = "sha256-wMvswgmsKl+cJl49VlVW84tvU5Jzd+2dl07SOiUDtwA="; }; in { From d824d6269c1525d0172db8e9e51ae5fcc284ac9c Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 19 Jul 2025 12:57:05 +0200 Subject: [PATCH 1009/1125] Roles/kde: get rid of kwin-x11 --- roles/kde/programs/kwin.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/kde/programs/kwin.nix b/roles/kde/programs/kwin.nix index 68b9f0a..4094a27 100644 --- a/roles/kde/programs/kwin.nix +++ b/roles/kde/programs/kwin.nix @@ -1,4 +1,5 @@ -{...}: { +{pkgs, ...}: { + environment.plasma6.excludePackages = [pkgs.kdePackages.kwin-x11]; home-manager.users.toast = { programs.plasma = { kwin = { From 283ef9c68025bf3b6f643c75e2af60ebf270dbf6 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 21 Jul 2025 15:25:02 +0200 Subject: [PATCH 1010/1125] Flake: update lock file --- flake.lock | 68 +++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/flake.lock b/flake.lock index 60574fa..1e9e29b 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1751880463, - "narHash": "sha256-aSQllMKqsTYAUp4yhpspZn0Hj5yIj7Mh4UD5iyk5iMM=", + "lastModified": 1752828704, + "narHash": "sha256-I8cCVFZIFcIy+7KBnjCuS/ISTJYeR8mkah1oxA6qBVk=", "owner": "catppuccin", "repo": "nix", - "rev": "9474347c69e93e392f194dda7a57c641ba4b998e", + "rev": "f5d22072074b0bc3c47a3a96a00e4fad263014ff", "type": "github" }, "original": { @@ -167,11 +167,11 @@ ] }, "locked": { - "lastModified": 1751990210, - "narHash": "sha256-krWErNDl9ggMLSfK00Q2BcoSk3+IRTSON/DiDgUzzMw=", + "lastModified": 1753056897, + "narHash": "sha256-AVVMBFcuOXqIgmShvRv9TED3fkiZhQ0ZvlhsPoFfkNE=", "owner": "nix-community", "repo": "home-manager", - "rev": "218da00bfa73f2a61682417efe74549416c16ba6", + "rev": "13a83d1b6545b7f0e8f7689bad62e7a3b1d63771", "type": "github" }, "original": { @@ -187,11 +187,11 @@ ] }, "locked": { - "lastModified": 1751810233, - "narHash": "sha256-kllkNbIqQi3VplgTMeGzuh1t8Gk8TauvkTRt93Km+tQ=", + "lastModified": 1753055804, + "narHash": "sha256-KerePGJYX47ex6OY3CWsid4AltO2gDtQROunYJ0eCEE=", "owner": "nix-community", "repo": "home-manager", - "rev": "9b0873b46c9f9e4b7aa01eb634952c206af53068", + "rev": "adf195f021a8cbb0c317f75b52e96c82616526f9", "type": "github" }, "original": { @@ -209,11 +209,11 @@ ] }, "locked": { - "lastModified": 1752052164, - "narHash": "sha256-rq5aT1acTwLMAds//7WLtZhZGC5Hyr5YQqbiA0kb3yo=", + "lastModified": 1752755091, + "narHash": "sha256-H/k35QJLyQxkFnXR5ckMv/Z+ElNa5f22qNKdyGBMAn4=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "f81c48f403c976463fe5812e9e6bca8cf49aebdc", + "rev": "0d09755fe1df1886e5f07dbb16f7ed373080f86a", "type": "github" }, "original": { @@ -225,11 +225,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1751931138, - "narHash": "sha256-Q0pIV16Vx9PZQRVXc1GS/IcKYlmcVMdkSGPdBsiLyKU=", - "rev": "fc3261c3405b122c8c2e5bdc3da6c4fb7ffa80a9", + "lastModified": 1753028704, + "narHash": "sha256-kKueIZ35JZnEXPkRw/h0xXvZgBLSfFW1J9FfpCIz8WQ=", + "rev": "2fc47b65b848aa1c2752b7b4eeb112c2cf3a240f", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/fc3261c3405b122c8c2e5bdc3da6c4fb7ffa80a9.tar.gz?rev=fc3261c3405b122c8c2e5bdc3da6c4fb7ffa80a9" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/2fc47b65b848aa1c2752b7b4eeb112c2cf3a240f.tar.gz?rev=2fc47b65b848aa1c2752b7b4eeb112c2cf3a240f" }, "original": { "type": "tarball", @@ -342,11 +342,11 @@ ] }, "locked": { - "lastModified": 1751774635, - "narHash": "sha256-DuOznGdgMxeSlPpUu6Wkq0ZD5e2Cfv9XRZeZlHWMd1s=", + "lastModified": 1752985182, + "narHash": "sha256-sX8Neff8lp3TCHai6QmgLr5AD8MdsQQX3b52C1DVXR8=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "85686025ba6d18df31cc651a91d5adef63378978", + "rev": "fafdcb505ba605157ff7a7eeea452bc6d6cbc23c", "type": "github" }, "original": { @@ -362,11 +362,11 @@ ] }, "locked": { - "lastModified": 1751774635, - "narHash": "sha256-DuOznGdgMxeSlPpUu6Wkq0ZD5e2Cfv9XRZeZlHWMd1s=", + "lastModified": 1752985182, + "narHash": "sha256-sX8Neff8lp3TCHai6QmgLr5AD8MdsQQX3b52C1DVXR8=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "85686025ba6d18df31cc651a91d5adef63378978", + "rev": "fafdcb505ba605157ff7a7eeea452bc6d6cbc23c", "type": "github" }, "original": { @@ -377,11 +377,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1752048960, - "narHash": "sha256-gATnkOe37eeVwKKYCsL+OnS2gU4MmLuZFzzWCtaKLI8=", + "lastModified": 1752666637, + "narHash": "sha256-P8J72psdc/rWliIvp8jUpoQ6qRDlVzgSDDlgkaXQ0Fw=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "7ced9122cff2163c6a0212b8d1ec8c33a1660806", + "rev": "d1bfa8f6ccfb5c383e1eba609c1eb67ca24ed153", "type": "github" }, "original": { @@ -393,11 +393,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1750776420, - "narHash": "sha256-/CG+w0o0oJ5itVklOoLbdn2dGB0wbZVOoDm4np6w09A=", + "lastModified": 1752480373, + "narHash": "sha256-JHQbm+OcGp32wAsXTE/FLYGNpb+4GLi5oTvCxwSoBOA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "30a61f056ac492e3b7cdcb69c1e6abdcf00e39cf", + "rev": "62e0f05ede1da0d54515d4ea8ce9c733f12d9f08", "type": "github" }, "original": { @@ -409,11 +409,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1751943650, - "narHash": "sha256-7orTnNqkGGru8Je6Un6mq1T8YVVU/O5kyW4+f9C1mZQ=", + "lastModified": 1752866191, + "narHash": "sha256-NV4S2Lf2hYmZQ3Qf4t/YyyBaJNuxLPyjzvDma0zPp/M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "88983d4b665fb491861005137ce2b11a9f89f203", + "rev": "f01fe91b0108a7aff99c99f2e9abbc45db0adc2a", "type": "github" }, "original": { @@ -424,11 +424,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1751792365, - "narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=", + "lastModified": 1752950548, + "narHash": "sha256-NS6BLD0lxOrnCiEOcvQCDVPXafX1/ek1dfJHX1nUIzc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb", + "rev": "c87b95e25065c028d31a94f06a62927d18763fdf", "type": "github" }, "original": { From 5fc8c72a5138e3e59a7af3a8b8aae9e3bf4eac6b Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 30 Jul 2025 00:18:55 +0200 Subject: [PATCH 1011/1125] Flake: add copyparty flake --- flake.lock | 44 +++++++++++++++++++++++++++++++++++++++++--- flake.nix | 4 ++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 1e9e29b..88f3641 100644 --- a/flake.lock +++ b/flake.lock @@ -57,6 +57,28 @@ "type": "github" } }, + "copyparty": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs-raw" + ] + }, + "locked": { + "lastModified": 1753804059, + "narHash": "sha256-gcjFZpwC4OrwvTXJbBLXhrGqHs3vH8v2UtZ5cR2qbJ4=", + "owner": "toast003", + "repo": "copyparty", + "rev": "7dff81840bf72c2c4983a4b93063032c1f98f2e7", + "type": "github" + }, + "original": { + "owner": "toast003", + "ref": "nix-overhaul", + "repo": "copyparty", + "type": "github" + } + }, "eza-themes": { "flake": false, "locked": { @@ -74,6 +96,21 @@ } }, "flake-utils": { + "locked": { + "lastModified": 1678901627, + "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { "inputs": { "systems": "systems_2" }, @@ -91,7 +128,7 @@ "type": "github" } }, - "flake-utils_2": { + "flake-utils_3": { "inputs": { "systems": "systems_3" }, @@ -238,7 +275,7 @@ }, "lix-module": { "inputs": { - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "flakey-profile": "flakey-profile", "lix": [ "lix" @@ -261,7 +298,7 @@ }, "lix-module-unstable": { "inputs": { - "flake-utils": "flake-utils_2", + "flake-utils": "flake-utils_3", "flakey-profile": "flakey-profile_2", "lix": [ "lix" @@ -465,6 +502,7 @@ "agenix": "agenix", "catppuccin": "catppuccin", "catppuccin-konsole": "catppuccin-konsole", + "copyparty": "copyparty", "eza-themes": "eza-themes", "home-manager": "home-manager_2", "home-manager-unstable": "home-manager-unstable", diff --git a/flake.nix b/flake.nix index 275efa9..c16a70a 100644 --- a/flake.nix +++ b/flake.nix @@ -36,6 +36,9 @@ nix-impermanence.url = "github:nix-community/impermanence"; + copyparty.url = "github:toast003/copyparty/nix-overhaul"; + copyparty.inputs.nixpkgs.follows = "nixpkgs-raw"; + /* These are the same input, just following different nixpkgs versions This avoids some wierdness when using one that follows unstable on a stable nixpkgs @@ -218,6 +221,7 @@ Everest = { stable = true; modules = [ + copyparty.nixosModules.default ./roles/server ]; }; From fb41beb270768b468533418f6972334742c3d81d Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 30 Jul 2025 02:53:52 +0200 Subject: [PATCH 1012/1125] Common/eza: set group option --- roles/common/programs/eza.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/common/programs/eza.nix b/roles/common/programs/eza.nix index e15b9db..90602d6 100644 --- a/roles/common/programs/eza.nix +++ b/roles/common/programs/eza.nix @@ -10,6 +10,9 @@ enableBashIntegration = true; git = true; icons = "auto"; + extraOptions = [ + "--group" + ]; }; xdg.configFile."eza/theme.yml".source = "${flakeSelf.inputs.eza-themes}/themes/catppuccin.yml"; }; From 90028fb7fe7a51baf37990e94d21fde666afddfd Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 30 Jul 2025 03:27:36 +0200 Subject: [PATCH 1013/1125] Roles/server: add copyparty --- roles/server/copyparty.nix | 34 ++++++++++++++++++++++++++++++++++ roles/server/default.nix | 1 + 2 files changed, 35 insertions(+) create mode 100644 roles/server/copyparty.nix diff --git a/roles/server/copyparty.nix b/roles/server/copyparty.nix new file mode 100644 index 0000000..180feec --- /dev/null +++ b/roles/server/copyparty.nix @@ -0,0 +1,34 @@ +{flakeSelf, ...}: { + nixpkgs.overlays = [flakeSelf.inputs.copyparty.overlays.default]; + services.copyparty = { + enable = true; + + settings = { + i = ["unix:770:caddy:/dev/shm/copyparty.socket"]; + }; + + volumes = { + "/Files" = { + path = "/srv/dl"; + access.r = "*"; + }; + }; + }; + + users.users.copyparty.extraGroups = ["caddy"]; + + services.headscale.settings.dns.extra_records = [ + { + name = "files.everest.tailscale"; + type = "A"; + value = "100.100.0.1"; + } + ]; + services.caddy.virtualHosts.copyparty = { + hostName = "files.everest.tailscale"; + extraConfig = '' + import tailscale + reverse_proxy unix//dev/shm/copyparty.socket + ''; + }; +} diff --git a/roles/server/default.nix b/roles/server/default.nix index 5891e05..e77155f 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -18,5 +18,6 @@ ./grafana.nix ./prometheus.nix ./immich.nix + ./copyparty.nix ]; } From 2fea832484bb8bbbebf606dc3d2f510715125351 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 14 Jul 2025 17:38:07 +0200 Subject: [PATCH 1014/1125] Revert "Desktop/NetworkManager: change dhcp implementation" This reverts commit f29d5d4207180facf08776c9e905b1af87659a49. --- roles/desktop/services/networkmanager.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/roles/desktop/services/networkmanager.nix b/roles/desktop/services/networkmanager.nix index 919cd19..c00d3e8 100644 --- a/roles/desktop/services/networkmanager.nix +++ b/roles/desktop/services/networkmanager.nix @@ -10,8 +10,6 @@ in { }; networking.networkmanager = { enable = true; - # Internal dhcp implementation does not like my isp router - dhcp = "dhcpcd"; unmanaged = [ "interface-name:${tailscaleName}" ]; From 2df0370ce05dd49a3d26612235c50dd840eda960 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 16 Jul 2025 01:04:35 +0200 Subject: [PATCH 1015/1125] Machines/WinMax2: switch to limine --- machines/WinMax2/configuration.nix | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 96bad5b..3a3b1b5 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -7,16 +7,15 @@ lib, ... }: { - # Use grub boot loader boot = { loader = { systemd-boot.enable = false; - grub = { + limine = { enable = true; - device = "nodev"; - efiSupport = true; - # No other OS on here :P - useOSProber = false; + enableEditor = true; + style = { + graphicalTerminal.font.scale = "2x2"; + }; }; efi = { efiSysMountPoint = config.fileSystems."efi_boot_partition".mountPoint; @@ -33,6 +32,7 @@ kernelPackages = pkgs.linuxPackages_latest; }; + catppuccin.limine.enable = true; networking.hostName = "WinMax2"; # Define your hostname. From 64d2ca9c23253c82eeba8ea3d619da92df37bc4d Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 16 Jul 2025 17:06:57 +0200 Subject: [PATCH 1016/1125] Machines/WinMax2: reduce limine timeout --- machines/WinMax2/configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 3a3b1b5..d02d33d 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -13,6 +13,9 @@ limine = { enable = true; enableEditor = true; + extraConfig = '' + timeout: 3 + ''; style = { graphicalTerminal.font.scale = "2x2"; }; From 48993bb1e66781826b3d1ae6bb448f4ecfa64cd1 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 16 Jul 2025 17:28:09 +0200 Subject: [PATCH 1017/1125] Machines/WinMax2: disable inputplumber --- machines/WinMax2/configuration.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index d02d33d..c0526ee 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -56,6 +56,8 @@ }; user = "toast"; }; + # Input plumber conflicts with hhd, and it doesn't let me use mouse mode + inputplumber.enable = lib.mkForce false; }; # Allow unfree packages From 91e57025b710c6e1136ca278c431fc82eec21513 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 26 Jul 2025 16:15:04 +0200 Subject: [PATCH 1018/1125] Machines/WinMax2: enable secure boot --- machines/WinMax2/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index c0526ee..0067572 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -13,6 +13,7 @@ limine = { enable = true; enableEditor = true; + secureBoot.enable = true; extraConfig = '' timeout: 3 ''; From 3af90c044f55819e8d637888beb4ef2d93390d60 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 4 Aug 2025 10:45:32 +0200 Subject: [PATCH 1019/1125] Flake: switch to upstream copyparty --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index c16a70a..1f699e7 100644 --- a/flake.nix +++ b/flake.nix @@ -36,7 +36,7 @@ nix-impermanence.url = "github:nix-community/impermanence"; - copyparty.url = "github:toast003/copyparty/nix-overhaul"; + copyparty.url = "github:9001/copyparty"; copyparty.inputs.nixpkgs.follows = "nixpkgs-raw"; /* From cd58dde5fdea54e8978624eb18a8307606685ad0 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 4 Aug 2025 10:45:47 +0200 Subject: [PATCH 1020/1125] Flake: update lock file --- flake.lock | 91 +++++++++++++++++++++++++++--------------------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/flake.lock b/flake.lock index 88f3641..901ec8e 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1752828704, - "narHash": "sha256-I8cCVFZIFcIy+7KBnjCuS/ISTJYeR8mkah1oxA6qBVk=", + "lastModified": 1754271783, + "narHash": "sha256-FknT43lUuVjdOD0kLZUm2jkCS1ld721Sr9vLKi6b1y4=", "owner": "catppuccin", "repo": "nix", - "rev": "f5d22072074b0bc3c47a3a96a00e4fad263014ff", + "rev": "f2a353b8394e9aac739baf2f6bcc972e0a092f75", "type": "github" }, "original": { @@ -65,16 +65,15 @@ ] }, "locked": { - "lastModified": 1753804059, - "narHash": "sha256-gcjFZpwC4OrwvTXJbBLXhrGqHs3vH8v2UtZ5cR2qbJ4=", - "owner": "toast003", + "lastModified": 1754268027, + "narHash": "sha256-E1675V3MGXPPfYplJZ8kAHqxcW/cL0v3MAPR6zvn+1A=", + "owner": "9001", "repo": "copyparty", - "rev": "7dff81840bf72c2c4983a4b93063032c1f98f2e7", + "rev": "8c000fd68353ff087ea2208eb90ba9fb61605eef", "type": "github" }, "original": { - "owner": "toast003", - "ref": "nix-overhaul", + "owner": "9001", "repo": "copyparty", "type": "github" } @@ -82,11 +81,11 @@ "eza-themes": { "flake": false, "locked": { - "lastModified": 1739960775, - "narHash": "sha256-vu6QLz0RvPavpD2VED25D2PJlHgQ8Yis+DnL+BPlvHw=", + "lastModified": 1754231765, + "narHash": "sha256-2WTbCQlhwMo5cOn3KwtNiIst0tNfASfZnPNsNBs+gcU=", "owner": "eza-community", "repo": "eza-themes", - "rev": "57149851f07b3ee6ca94f5fe3d9d552f73f8b8b4", + "rev": "17095bff4792eecd7f4f1ed8301b15000331c906", "type": "github" }, "original": { @@ -204,11 +203,11 @@ ] }, "locked": { - "lastModified": 1753056897, - "narHash": "sha256-AVVMBFcuOXqIgmShvRv9TED3fkiZhQ0ZvlhsPoFfkNE=", + "lastModified": 1754263839, + "narHash": "sha256-ck7lILfCNuunsLvExPI4Pw9OOCJksxXwozum24W8b+8=", "owner": "nix-community", "repo": "home-manager", - "rev": "13a83d1b6545b7f0e8f7689bad62e7a3b1d63771", + "rev": "1d7abbd5454db97e0af51416f4960b3fb64a4773", "type": "github" }, "original": { @@ -224,11 +223,11 @@ ] }, "locked": { - "lastModified": 1753055804, - "narHash": "sha256-KerePGJYX47ex6OY3CWsid4AltO2gDtQROunYJ0eCEE=", + "lastModified": 1753592768, + "narHash": "sha256-oV695RvbAE4+R9pcsT9shmp6zE/+IZe6evHWX63f2Qg=", "owner": "nix-community", "repo": "home-manager", - "rev": "adf195f021a8cbb0c317f75b52e96c82616526f9", + "rev": "fc3add429f21450359369af74c2375cb34a2d204", "type": "github" }, "original": { @@ -246,11 +245,11 @@ ] }, "locked": { - "lastModified": 1752755091, - "narHash": "sha256-H/k35QJLyQxkFnXR5ckMv/Z+ElNa5f22qNKdyGBMAn4=", + "lastModified": 1754110197, + "narHash": "sha256-N7GWK2084EsNdwzwg6FCIgMrSau1WwzxGSNdPHx5Tak=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "0d09755fe1df1886e5f07dbb16f7ed373080f86a", + "rev": "04ce5c103eb621220d69102bc0ee27c3abd89204", "type": "github" }, "original": { @@ -262,11 +261,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1753028704, - "narHash": "sha256-kKueIZ35JZnEXPkRw/h0xXvZgBLSfFW1J9FfpCIz8WQ=", - "rev": "2fc47b65b848aa1c2752b7b4eeb112c2cf3a240f", + "lastModified": 1754137273, + "narHash": "sha256-lyj/k4SU0aHUHnbGu4r67splMWwsC/QLlKo7Mzq0XA4=", + "rev": "cad6118e20a520b7536879d951ab6c3228b3e111", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/2fc47b65b848aa1c2752b7b4eeb112c2cf3a240f.tar.gz?rev=2fc47b65b848aa1c2752b7b4eeb112c2cf3a240f" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/cad6118e20a520b7536879d951ab6c3228b3e111.tar.gz?rev=cad6118e20a520b7536879d951ab6c3228b3e111" }, "original": { "type": "tarball", @@ -379,11 +378,11 @@ ] }, "locked": { - "lastModified": 1752985182, - "narHash": "sha256-sX8Neff8lp3TCHai6QmgLr5AD8MdsQQX3b52C1DVXR8=", + "lastModified": 1754195341, + "narHash": "sha256-YL71IEf2OugH3gmAsxQox6BJI0KOcHKtW2QqT/+s2SA=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "fafdcb505ba605157ff7a7eeea452bc6d6cbc23c", + "rev": "b7fcd4e26d67fca48e77de9b0d0f954b18ae9562", "type": "github" }, "original": { @@ -399,11 +398,11 @@ ] }, "locked": { - "lastModified": 1752985182, - "narHash": "sha256-sX8Neff8lp3TCHai6QmgLr5AD8MdsQQX3b52C1DVXR8=", + "lastModified": 1754195341, + "narHash": "sha256-YL71IEf2OugH3gmAsxQox6BJI0KOcHKtW2QqT/+s2SA=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "fafdcb505ba605157ff7a7eeea452bc6d6cbc23c", + "rev": "b7fcd4e26d67fca48e77de9b0d0f954b18ae9562", "type": "github" }, "original": { @@ -414,11 +413,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1752666637, - "narHash": "sha256-P8J72psdc/rWliIvp8jUpoQ6qRDlVzgSDDlgkaXQ0Fw=", + "lastModified": 1754229794, + "narHash": "sha256-yOl7REX6O/1mh+tpscJPKgjK6nmXSMOB1xhmDNAMUZM=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "d1bfa8f6ccfb5c383e1eba609c1eb67ca24ed153", + "rev": "a872d985392ee5b19d8409bfcc3f106de2070070", "type": "github" }, "original": { @@ -430,11 +429,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1752480373, - "narHash": "sha256-JHQbm+OcGp32wAsXTE/FLYGNpb+4GLi5oTvCxwSoBOA=", + "lastModified": 1753694789, + "narHash": "sha256-cKgvtz6fKuK1Xr5LQW/zOUiAC0oSQoA9nOISB0pJZqM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "62e0f05ede1da0d54515d4ea8ce9c733f12d9f08", + "rev": "dc9637876d0dcc8c9e5e22986b857632effeb727", "type": "github" }, "original": { @@ -446,11 +445,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1752866191, - "narHash": "sha256-NV4S2Lf2hYmZQ3Qf4t/YyyBaJNuxLPyjzvDma0zPp/M=", + "lastModified": 1754028485, + "narHash": "sha256-IiiXB3BDTi6UqzAZcf2S797hWEPCRZOwyNThJIYhUfk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f01fe91b0108a7aff99c99f2e9abbc45db0adc2a", + "rev": "59e69648d345d6e8fef86158c555730fa12af9de", "type": "github" }, "original": { @@ -461,11 +460,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1752950548, - "narHash": "sha256-NS6BLD0lxOrnCiEOcvQCDVPXafX1/ek1dfJHX1nUIzc=", + "lastModified": 1753939845, + "narHash": "sha256-K2ViRJfdVGE8tpJejs8Qpvvejks1+A4GQej/lBk5y7I=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c87b95e25065c028d31a94f06a62927d18763fdf", + "rev": "94def634a20494ee057c76998843c015909d6311", "type": "github" }, "original": { @@ -484,11 +483,11 @@ ] }, "locked": { - "lastModified": 1748196248, - "narHash": "sha256-1iHjsH6/5UOerJEoZKE+Gx1BgAoge/YcnUsOA4wQ/BU=", + "lastModified": 1754241118, + "narHash": "sha256-nsBBqbAFB7lUYIh6S6l7fQ/ALDhCckp7+rqbY2767uE=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "b7697abe89967839b273a863a3805345ea54ab56", + "rev": "968109159b4bbe4386ac281272ddcebeef09ebfc", "type": "github" }, "original": { From 2b4288352319e078a488a082331aa8210225a938 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 4 Aug 2025 15:35:48 +0200 Subject: [PATCH 1021/1125] Machines/WinMax2: use stock mesa and radv --- machines/WinMax2/configuration.nix | 5 ----- 1 file changed, 5 deletions(-) diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 0067572..9a7940f 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -81,11 +81,6 @@ desktopSession = "plasma"; }; hardware.amd.gpu.enableBacklightControl = true; - # Need patched mesa - steamos = { - enableMesaPatches = true; - enableVendorRadv = true; - }; decky-loader = { enable = true; package = pkgs.decky-loader-prerelease; From 190010e31fac072acdfe9ed061a5f8afddf8a0a2 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Aug 2025 04:17:56 +0200 Subject: [PATCH 1022/1125] Desktop/networkmanager: disable wifi mac address randomisation --- roles/desktop/services/networkmanager.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/roles/desktop/services/networkmanager.nix b/roles/desktop/services/networkmanager.nix index c00d3e8..a9917e3 100644 --- a/roles/desktop/services/networkmanager.nix +++ b/roles/desktop/services/networkmanager.nix @@ -13,7 +13,6 @@ in { unmanaged = [ "interface-name:${tailscaleName}" ]; - wifi.macAddress = "random"; ensureProfiles = { environmentFiles = [config.age.secrets.wifiPasswords.path]; profiles = { From 164d6653245c0810c0e94188d8654358c3c51398 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 15 Aug 2025 11:24:49 +0900 Subject: [PATCH 1023/1125] Common: set up timezone automatically --- roles/common/configuration.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index d1441be..f7d502e 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -97,7 +97,8 @@ }; # Set up time zone. - time.timeZone = "Europe/Madrid"; + # time.timeZone = "Europe/Madrid"; + services.automatic-timezoned.enable = true; nixpkgs.overlays = [ ( From f934ff1092fa324989835565a0d0e33e2cc068e5 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 19 Aug 2025 12:12:11 +0900 Subject: [PATCH 1024/1125] Desktop/mpv: enable cdda support --- roles/desktop/programs/mpv.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/roles/desktop/programs/mpv.nix b/roles/desktop/programs/mpv.nix index 81b8392..768dc85 100644 --- a/roles/desktop/programs/mpv.nix +++ b/roles/desktop/programs/mpv.nix @@ -1,4 +1,13 @@ {pkgs, ...}: { + nixpkgs.overlays = [ + ( + final: prev: { + mpv-unwrapped = prev.mpv-unwrapped.override { + cddaSupport = true; + }; + } + ) + ]; home-manager.users.toast = { programs.mpv = { enable = true; From 338714285ed2ae0f99b842a2939b1c6127f4cef0 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 26 Aug 2025 14:57:55 +0900 Subject: [PATCH 1025/1125] Flake: update lock file --- flake.lock | 86 +++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/flake.lock b/flake.lock index 901ec8e..8a84dec 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1750173260, - "narHash": "sha256-9P1FziAwl5+3edkfFcr5HeGtQUtrSdk/MksX39GieoA=", + "lastModified": 1754433428, + "narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=", "owner": "ryantm", "repo": "agenix", - "rev": "531beac616433bac6f9e2a19feb8e99a22a66baf", + "rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d", "type": "github" }, "original": { @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1754271783, - "narHash": "sha256-FknT43lUuVjdOD0kLZUm2jkCS1ld721Sr9vLKi6b1y4=", + "lastModified": 1754950929, + "narHash": "sha256-75hsUMshZ5ZlO/X2JWfZqKHPM66uhUNsDG/Zozwh/xs=", "owner": "catppuccin", "repo": "nix", - "rev": "f2a353b8394e9aac739baf2f6bcc972e0a092f75", + "rev": "45512611f1537c75e439d508409efc6901286645", "type": "github" }, "original": { @@ -65,11 +65,11 @@ ] }, "locked": { - "lastModified": 1754268027, - "narHash": "sha256-E1675V3MGXPPfYplJZ8kAHqxcW/cL0v3MAPR6zvn+1A=", + "lastModified": 1755208437, + "narHash": "sha256-FYKbAR2xHmnvS6GKBRtja28WG0ZDZhWse7N2WL5Sk/E=", "owner": "9001", "repo": "copyparty", - "rev": "8c000fd68353ff087ea2208eb90ba9fb61605eef", + "rev": "f4a3fba29c9e58ca76d92e8e0a70d3083406b048", "type": "github" }, "original": { @@ -203,11 +203,11 @@ ] }, "locked": { - "lastModified": 1754263839, - "narHash": "sha256-ck7lILfCNuunsLvExPI4Pw9OOCJksxXwozum24W8b+8=", + "lastModified": 1755229570, + "narHash": "sha256-soZegto0xXzG2zYlu/zjknDHv0Z7tRS5EQs+Z/VRTBg=", "owner": "nix-community", "repo": "home-manager", - "rev": "1d7abbd5454db97e0af51416f4960b3fb64a4773", + "rev": "11626a4383b458f8dc5ea3237eaa04e8ab1912f3", "type": "github" }, "original": { @@ -245,11 +245,11 @@ ] }, "locked": { - "lastModified": 1754110197, - "narHash": "sha256-N7GWK2084EsNdwzwg6FCIgMrSau1WwzxGSNdPHx5Tak=", + "lastModified": 1755151620, + "narHash": "sha256-fVMalQZ+tRXR8oue2SdWu4CdlsS2NII+++rI40XQ8rU=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "04ce5c103eb621220d69102bc0ee27c3abd89204", + "rev": "16e12d22754d97064867006acae6e16da7a142a6", "type": "github" }, "original": { @@ -261,11 +261,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1754137273, - "narHash": "sha256-lyj/k4SU0aHUHnbGu4r67splMWwsC/QLlKo7Mzq0XA4=", - "rev": "cad6118e20a520b7536879d951ab6c3228b3e111", + "lastModified": 1755216712, + "narHash": "sha256-UEaIcBYAfW9iQoUPYY6oM9ldoEuDzXgI3lTjBEys0L0=", + "rev": "b2e48aac5ccdeea0c44af063feb02000c27abd38", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/cad6118e20a520b7536879d951ab6c3228b3e111.tar.gz?rev=cad6118e20a520b7536879d951ab6c3228b3e111" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/b2e48aac5ccdeea0c44af063feb02000c27abd38.tar.gz?rev=b2e48aac5ccdeea0c44af063feb02000c27abd38" }, "original": { "type": "tarball", @@ -320,11 +320,11 @@ }, "nix-flatpak": { "locked": { - "lastModified": 1751276396, - "narHash": "sha256-oOYrnKStMsOXST+wKnzuSZ49h8Dr1Q3mIn2f5Kb5GAw=", + "lastModified": 1754777568, + "narHash": "sha256-0bBqT+3XncgF8F03RFAamw9vdf0VmaDoIJLTGkjfQZs=", "owner": "gmodena", "repo": "nix-flatpak", - "rev": "59adb9ad1cbd915494fc35cd0e0a9d582ca9de74", + "rev": "62f636b87ef6050760a8cb325cadb90674d1e23e", "type": "github" }, "original": { @@ -378,11 +378,11 @@ ] }, "locked": { - "lastModified": 1754195341, - "narHash": "sha256-YL71IEf2OugH3gmAsxQox6BJI0KOcHKtW2QqT/+s2SA=", + "lastModified": 1754800038, + "narHash": "sha256-UbLO8/0pVBXLJuyRizYOJigtzQAj8Z2bTnbKSec/wN0=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "b7fcd4e26d67fca48e77de9b0d0f954b18ae9562", + "rev": "b65f8d80656f9fcbd1fecc4b7f0730f468333142", "type": "github" }, "original": { @@ -398,11 +398,11 @@ ] }, "locked": { - "lastModified": 1754195341, - "narHash": "sha256-YL71IEf2OugH3gmAsxQox6BJI0KOcHKtW2QqT/+s2SA=", + "lastModified": 1754800038, + "narHash": "sha256-UbLO8/0pVBXLJuyRizYOJigtzQAj8Z2bTnbKSec/wN0=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "b7fcd4e26d67fca48e77de9b0d0f954b18ae9562", + "rev": "b65f8d80656f9fcbd1fecc4b7f0730f468333142", "type": "github" }, "original": { @@ -413,11 +413,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1754229794, - "narHash": "sha256-yOl7REX6O/1mh+tpscJPKgjK6nmXSMOB1xhmDNAMUZM=", + "lastModified": 1754564048, + "narHash": "sha256-dz303vGuzWjzOPOaYkS9xSW+B93PSAJxvBd6CambXVA=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "a872d985392ee5b19d8409bfcc3f106de2070070", + "rev": "26ed7a0d4b8741fe1ef1ee6fa64453ca056ce113", "type": "github" }, "original": { @@ -429,11 +429,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1753694789, - "narHash": "sha256-cKgvtz6fKuK1Xr5LQW/zOUiAC0oSQoA9nOISB0pJZqM=", + "lastModified": 1754498491, + "narHash": "sha256-erbiH2agUTD0Z30xcVSFcDHzkRvkRXOQ3lb887bcVrs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "dc9637876d0dcc8c9e5e22986b857632effeb727", + "rev": "c2ae88e026f9525daf89587f3cbee584b92b6134", "type": "github" }, "original": { @@ -445,11 +445,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1754028485, - "narHash": "sha256-IiiXB3BDTi6UqzAZcf2S797hWEPCRZOwyNThJIYhUfk=", + "lastModified": 1755078291, + "narHash": "sha256-Hu/gTDoi4uy6TAKISPHQusSMy8U6xUbLSDjKBYdhDIY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "59e69648d345d6e8fef86158c555730fa12af9de", + "rev": "3385ca0cd7e14c1a1eb80401fe011705ff012323", "type": "github" }, "original": { @@ -460,11 +460,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1753939845, - "narHash": "sha256-K2ViRJfdVGE8tpJejs8Qpvvejks1+A4GQej/lBk5y7I=", + "lastModified": 1755027561, + "narHash": "sha256-IVft239Bc8p8Dtvf7UAACMG5P3ZV+3/aO28gXpGtMXI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "94def634a20494ee057c76998843c015909d6311", + "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", "type": "github" }, "original": { @@ -483,11 +483,11 @@ ] }, "locked": { - "lastModified": 1754241118, - "narHash": "sha256-nsBBqbAFB7lUYIh6S6l7fQ/ALDhCckp7+rqbY2767uE=", + "lastModified": 1754501628, + "narHash": "sha256-FExJ54tVB5iu7Dh2tLcyCSWpaV+lmUzzWKZUkemwXvo=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "968109159b4bbe4386ac281272ddcebeef09ebfc", + "rev": "cca090f8115c4172b9aef6c5299ae784bdd5e133", "type": "github" }, "original": { From 970da745ad2b16f2b8c1bbefda8f927477bd911c Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 26 Aug 2025 14:58:06 +0900 Subject: [PATCH 1026/1125] Desktop/keepassxc: update configs --- roles/desktop/programs/keepassxc.nix | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/roles/desktop/programs/keepassxc.nix b/roles/desktop/programs/keepassxc.nix index 20c0d9c..a48544a 100644 --- a/roles/desktop/programs/keepassxc.nix +++ b/roles/desktop/programs/keepassxc.nix @@ -3,6 +3,7 @@ users.toast = { programs.keepassxc = { enable = true; + autostart = true; settings = { General = { # Not sure what changing this does, I'll leave it alone @@ -28,9 +29,6 @@ SSHAgent.Enabled = true; }; }; - xdg.autostart.entries = [ - "${pkgs.keepassxc}/share/applications/org.keepassxc.KeePassXC.desktop" - ]; }; }; } From 28245e92f5f2adc4ec8ad56e868cc0fdf2bcdc8a Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 5 Sep 2025 18:45:52 +0200 Subject: [PATCH 1027/1125] Flake: update lock file --- flake.lock | 96 +++++++++++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/flake.lock b/flake.lock index 8a84dec..3b7b3c4 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1754950929, - "narHash": "sha256-75hsUMshZ5ZlO/X2JWfZqKHPM66uhUNsDG/Zozwh/xs=", + "lastModified": 1756741629, + "narHash": "sha256-n+mgH3NoQf8d1jd8cDp/9Mt++hhyuE3LO3ZAxzjWRZw=", "owner": "catppuccin", "repo": "nix", - "rev": "45512611f1537c75e439d508409efc6901286645", + "rev": "cd22197da06df1eb6fabdaa2fc22c170c4f67382", "type": "github" }, "original": { @@ -65,11 +65,11 @@ ] }, "locked": { - "lastModified": 1755208437, - "narHash": "sha256-FYKbAR2xHmnvS6GKBRtja28WG0ZDZhWse7N2WL5Sk/E=", + "lastModified": 1757029702, + "narHash": "sha256-gy2zYv5nHeJ72quyJ1ioe7+Njl2jdq+b3H1QrRr3etA=", "owner": "9001", "repo": "copyparty", - "rev": "f4a3fba29c9e58ca76d92e8e0a70d3083406b048", + "rev": "bd6d1f961de8df47f4d5418f4cf8dd584a98b495", "type": "github" }, "original": { @@ -203,11 +203,11 @@ ] }, "locked": { - "lastModified": 1755229570, - "narHash": "sha256-soZegto0xXzG2zYlu/zjknDHv0Z7tRS5EQs+Z/VRTBg=", + "lastModified": 1756991914, + "narHash": "sha256-4ve/3ah5H/SpL2m3qmZ9GU+VinQYp2MN1G7GamimTds=", "owner": "nix-community", "repo": "home-manager", - "rev": "11626a4383b458f8dc5ea3237eaa04e8ab1912f3", + "rev": "b08f8737776f10920c330657bee8b95834b7a70f", "type": "github" }, "original": { @@ -223,11 +223,11 @@ ] }, "locked": { - "lastModified": 1753592768, - "narHash": "sha256-oV695RvbAE4+R9pcsT9shmp6zE/+IZe6evHWX63f2Qg=", + "lastModified": 1756679287, + "narHash": "sha256-Xd1vOeY9ccDf5VtVK12yM0FS6qqvfUop8UQlxEB+gTQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "fc3add429f21450359369af74c2375cb34a2d204", + "rev": "07fc025fe10487dd80f2ec694f1cd790e752d0e8", "type": "github" }, "original": { @@ -245,11 +245,11 @@ ] }, "locked": { - "lastModified": 1755151620, - "narHash": "sha256-fVMalQZ+tRXR8oue2SdWu4CdlsS2NII+++rI40XQ8rU=", + "lastModified": 1757052778, + "narHash": "sha256-rYszJwY0EArAqK6q0i5bB1zxNCNRk6gVmD9SIvnoXW8=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "16e12d22754d97064867006acae6e16da7a142a6", + "rev": "ceaa413a68f28bbf6731464594fdb2c3513e9110", "type": "github" }, "original": { @@ -261,11 +261,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1755216712, - "narHash": "sha256-UEaIcBYAfW9iQoUPYY6oM9ldoEuDzXgI3lTjBEys0L0=", - "rev": "b2e48aac5ccdeea0c44af063feb02000c27abd38", + "lastModified": 1756426754, + "narHash": "sha256-EVJDo/KjdGtvJKelVPoL92TsPNrqnOJUnaLTIqP+F0o=", + "rev": "f4bdddf0fdaabc68546cf561c5343b83d95d2466", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/b2e48aac5ccdeea0c44af063feb02000c27abd38.tar.gz?rev=b2e48aac5ccdeea0c44af063feb02000c27abd38" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/f4bdddf0fdaabc68546cf561c5343b83d95d2466.tar.gz?rev=f4bdddf0fdaabc68546cf561c5343b83d95d2466" }, "original": { "type": "tarball", @@ -284,11 +284,11 @@ ] }, "locked": { - "lastModified": 1751909859, - "narHash": "sha256-gbpuESxl/An4GTh7QEbQRYJozVIxWkwVGbWK0/0GoRc=", - "rev": "4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f", + "lastModified": 1756511062, + "narHash": "sha256-IgD1JR7scSEwlK/YAbmrcTWpAYT30LPldCUHdzXkaMs=", + "rev": "3f09a5eb772e02d98bb8878ab687d5b721f00d16", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f.tar.gz?rev=4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/3f09a5eb772e02d98bb8878ab687d5b721f00d16.tar.gz?rev=3f09a5eb772e02d98bb8878ab687d5b721f00d16" }, "original": { "type": "tarball", @@ -307,11 +307,11 @@ ] }, "locked": { - "lastModified": 1751909859, - "narHash": "sha256-gbpuESxl/An4GTh7QEbQRYJozVIxWkwVGbWK0/0GoRc=", - "rev": "4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f", + "lastModified": 1756511062, + "narHash": "sha256-IgD1JR7scSEwlK/YAbmrcTWpAYT30LPldCUHdzXkaMs=", + "rev": "3f09a5eb772e02d98bb8878ab687d5b721f00d16", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f.tar.gz?rev=4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/3f09a5eb772e02d98bb8878ab687d5b721f00d16.tar.gz?rev=3f09a5eb772e02d98bb8878ab687d5b721f00d16" }, "original": { "type": "tarball", @@ -378,11 +378,11 @@ ] }, "locked": { - "lastModified": 1754800038, - "narHash": "sha256-UbLO8/0pVBXLJuyRizYOJigtzQAj8Z2bTnbKSec/wN0=", + "lastModified": 1756612744, + "narHash": "sha256-/glV6VAq8Va3ghIbmhET3S1dzkbZqicsk5h+FtvwiPE=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "b65f8d80656f9fcbd1fecc4b7f0730f468333142", + "rev": "3fe768e1f058961095b4a0d7a2ba15dc9736bdc6", "type": "github" }, "original": { @@ -398,11 +398,11 @@ ] }, "locked": { - "lastModified": 1754800038, - "narHash": "sha256-UbLO8/0pVBXLJuyRizYOJigtzQAj8Z2bTnbKSec/wN0=", + "lastModified": 1756612744, + "narHash": "sha256-/glV6VAq8Va3ghIbmhET3S1dzkbZqicsk5h+FtvwiPE=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "b65f8d80656f9fcbd1fecc4b7f0730f468333142", + "rev": "3fe768e1f058961095b4a0d7a2ba15dc9736bdc6", "type": "github" }, "original": { @@ -413,11 +413,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1754564048, - "narHash": "sha256-dz303vGuzWjzOPOaYkS9xSW+B93PSAJxvBd6CambXVA=", + "lastModified": 1756925795, + "narHash": "sha256-kUb5hehaikfUvoJDEc7ngiieX88TwWX/bBRX9Ar6Tac=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "26ed7a0d4b8741fe1ef1ee6fa64453ca056ce113", + "rev": "ba6fab29768007e9f2657014a6e134637100c57d", "type": "github" }, "original": { @@ -429,11 +429,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1754498491, - "narHash": "sha256-erbiH2agUTD0Z30xcVSFcDHzkRvkRXOQ3lb887bcVrs=", + "lastModified": 1756266583, + "narHash": "sha256-cr748nSmpfvnhqSXPiCfUPxRz2FJnvf/RjJGvFfaCsM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c2ae88e026f9525daf89587f3cbee584b92b6134", + "rev": "8a6d5427d99ec71c64f0b93d45778c889005d9c2", "type": "github" }, "original": { @@ -445,11 +445,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1755078291, - "narHash": "sha256-Hu/gTDoi4uy6TAKISPHQusSMy8U6xUbLSDjKBYdhDIY=", + "lastModified": 1756886854, + "narHash": "sha256-6tooT142NLcFjt24Gi4B0G1pgWLvfw7y93sYEfSHlLI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3385ca0cd7e14c1a1eb80401fe011705ff012323", + "rev": "0e6684e6c5755325f801bda1751a8a4038145d7d", "type": "github" }, "original": { @@ -460,11 +460,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1755027561, - "narHash": "sha256-IVft239Bc8p8Dtvf7UAACMG5P3ZV+3/aO28gXpGtMXI=", + "lastModified": 1756787288, + "narHash": "sha256-rw/PHa1cqiePdBxhF66V7R+WAP8WekQ0mCDG4CFqT8Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", + "rev": "d0fc30899600b9b3466ddb260fd83deb486c32f1", "type": "github" }, "original": { @@ -483,11 +483,11 @@ ] }, "locked": { - "lastModified": 1754501628, - "narHash": "sha256-FExJ54tVB5iu7Dh2tLcyCSWpaV+lmUzzWKZUkemwXvo=", + "lastModified": 1756632588, + "narHash": "sha256-ydam6eggXf3ZwRutyCABwSbMAlX+5lW6w1SVZQ+kfSo=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "cca090f8115c4172b9aef6c5299ae784bdd5e133", + "rev": "d47428e5390d6a5a8f764808a4db15929347cd77", "type": "github" }, "original": { From eecbb372cb7e2a248cf92e90ec648b019803abfd Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 5 Sep 2025 18:46:01 +0200 Subject: [PATCH 1028/1125] Kde/patches: remove unneeded dolphin patches --- roles/kde/patches/dolphin/patches.txt | 3 - roles/kde/patches/dolphin/pr946.patch | 3978 ------------------------- 2 files changed, 3981 deletions(-) delete mode 100644 roles/kde/patches/dolphin/patches.txt delete mode 100644 roles/kde/patches/dolphin/pr946.patch diff --git a/roles/kde/patches/dolphin/patches.txt b/roles/kde/patches/dolphin/patches.txt deleted file mode 100644 index a7f0a2a..0000000 --- a/roles/kde/patches/dolphin/patches.txt +++ /dev/null @@ -1,3 +0,0 @@ -Gear 25.08.0: - -Pr 946 https://invent.kde.org/system/dolphin/-/merge_requests/946 diff --git a/roles/kde/patches/dolphin/pr946.patch b/roles/kde/patches/dolphin/pr946.patch deleted file mode 100644 index f01f4bd..0000000 --- a/roles/kde/patches/dolphin/pr946.patch +++ /dev/null @@ -1,3978 +0,0 @@ -From 21990d59c176084af615b97a6e586d32aa47fb66 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Fri, 11 Apr 2025 17:31:12 +0300 -Subject: [PATCH 01/69] WIP: new selection effect stuff - -based on felix branch -https://invent.kde.org/felixernst/dolphin/-/commit/b3fa4479c1c23da08c120e8462bae42c712381d3 ---- - src/kitemviews/kitemlistwidget.cpp | 49 +++++++++++------ - src/kitemviews/kstandarditemlistwidget.cpp | 63 +++++++--------------- - 2 files changed, 52 insertions(+), 60 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index baf2445726..a6fd75a347 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -124,23 +124,11 @@ void KItemListWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *o - painter->fillRect(backgroundRect, backgroundColor); - } - -- if (m_selected && m_editedRole.isEmpty()) { -+ if ((m_selected || m_current) && m_editedRole.isEmpty()) { - const QStyle::State activeState(isActiveWindow() && widget->hasFocus() ? QStyle::State_Active : 0); - drawItemStyleOption(painter, widget, activeState | QStyle::State_Enabled | QStyle::State_Selected | QStyle::State_Item); - } - -- if (m_current && m_editedRole.isEmpty()) { -- QStyleOptionFocusRect focusRectOption; -- initStyleOption(&focusRectOption); -- focusRectOption.rect = textFocusRect().toRect(); -- focusRectOption.state = QStyle::State_Enabled | QStyle::State_Item | QStyle::State_KeyboardFocusChange; -- if (m_selected && widget->hasFocus()) { -- focusRectOption.state |= QStyle::State_Selected; -- } -- -- style()->drawPrimitive(QStyle::PE_FrameFocusRect, &focusRectOption, painter, widget); -- } -- - if (m_hoverOpacity > 0.0) { - if (!m_hoverCache) { - // Initialize the m_hoverCache pixmap to improve the drawing performance -@@ -623,8 +611,39 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - viewItemOption.state = styleState; - viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; - viewItemOption.showDecorationSelected = true; -- viewItemOption.rect = selectionRect().toRect(); -- style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, painter, widget); -+ viewItemOption.rect = selectionRect().toRect().adjusted(2, 2, -2, -2); -+ QPainterPath path; -+ path.addRoundedRect(viewItemOption.rect, 5, 5); -+ QColor accentColor{widget->palette().color(QPalette::Accent)}; -+ painter->setRenderHint(QPainter::Antialiasing); -+ bool current = m_current && styleState & QStyle::State_Active; -+ -+ // Background item -+ accentColor.setAlphaF(0.0); -+ if (m_selected && m_hovered) { -+ accentColor.setAlphaF(0.5); -+ } else if (m_selected) { -+ accentColor.setAlphaF(0.4); -+ } else if (m_hovered && current) { -+ accentColor.setAlphaF(0.3); -+ } else if (m_hovered) { -+ accentColor.setAlphaF(0.1); -+ } -+ painter->fillPath(path, accentColor); -+ -+ // Focus decoration -+ if (current && m_hovered) { -+ accentColor.setAlphaF(1.0); -+ } else if (current || m_hovered) { -+ accentColor.setAlphaF(0.9); -+ } else if (m_current) { -+ accentColor.setAlphaF(0.3); -+ } -+ if (m_current || m_hovered) { -+ const QPen pen{accentColor, 2}; -+ painter->setPen(pen); -+ painter->drawPath(path); -+ } - } - - #include "moc_kitemlistwidget.cpp" -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 49d2f26bfd..c320e375b4 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -541,31 +541,23 @@ QRectF KStandardItemListWidget::selectionRect() const - { - const_cast(this)->triggerCacheRefreshing(); - -- switch (m_layout) { -- case IconsLayout: -- return m_textRect; -- -- case CompactLayout: -- case DetailsLayout: { -- const int padding = styleOption().padding; -- QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); -- QRectF result = adjustedIconRect | m_textRect; -- if (m_highlightEntireRow) { -- if (layoutDirection() == Qt::LeftToRight) { -- result.setRight(leftPadding() + m_columnWidthSum); -- } else { -- result.setLeft(size().width() - m_columnWidthSum - rightPadding()); -- } -+ const int padding = styleOption().padding; -+ QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); -+ QRectF result = adjustedIconRect | m_textRect; -+ if (m_highlightEntireRow) { -+ if (layoutDirection() == Qt::LeftToRight) { -+ result.setRight(leftPadding() + m_columnWidthSum); -+ } else { -+ result.setLeft(size().width() - m_columnWidthSum - rightPadding()); - } -- return result; - } - -- default: -- Q_ASSERT(false); -- break; -+ if (m_layout == IconsLayout) { -+ const int availableWidth = size().width() - 2 * padding - result.width(); -+ result = result.adjusted(-0.5 * availableWidth, 0, 0.5 * availableWidth, 0); - } - -- return m_textRect; -+ return result; - } - - QRectF KStandardItemListWidget::expansionToggleRect() const -@@ -578,7 +570,6 @@ QRectF KStandardItemListWidget::selectionToggleRect() const - { - const_cast(this)->triggerCacheRefreshing(); - -- const QRectF widgetIconRect = iconRect(); - const int widgetIconSize = iconSize(); - int toggleSize = KIconLoader::SizeSmall; - if (widgetIconSize >= KIconLoader::SizeEnormous) { -@@ -587,29 +578,11 @@ QRectF KStandardItemListWidget::selectionToggleRect() const - toggleSize = KIconLoader::SizeSmallMedium; - } - -- QPointF pos = widgetIconRect.topLeft(); -- -- // If the selection toggle has a very small distance to the -- // widget borders, the size of the selection toggle will get -- // increased to prevent an accidental clicking of the item -- // when trying to hit the toggle. -- const int widgetHeight = size().height(); -- const int widgetWidth = size().width(); -- const int minMargin = 2; -- -- if (toggleSize + minMargin * 2 >= widgetHeight) { -- pos.rx() -= (widgetHeight - toggleSize) / 2; -- toggleSize = widgetHeight; -- pos.setY(0); -- } -- if (toggleSize + minMargin * 2 >= widgetWidth) { -- pos.ry() -= (widgetWidth - toggleSize) / 2; -- toggleSize = widgetWidth; -- pos.setX(0); -- } -- -+ const int padding = styleOption().padding; -+ const QRectF selectionRectMinusPadding = selectionRect().adjusted(padding, padding, -padding, -padding); -+ QPointF pos = selectionRectMinusPadding.topLeft(); - if (QApplication::isRightToLeft()) { -- pos.setX(widgetIconRect.right() - (pos.x() + toggleSize - widgetIconRect.left())); -+ pos.setX(selectionRectMinusPadding.right() - (pos.x() + toggleSize - selectionRectMinusPadding.left())); - } - - return QRectF(pos, QSizeF(toggleSize, toggleSize)); -@@ -748,7 +721,7 @@ QColor KStandardItemListWidget::textColor(const QWidget &widget) const - } - - const QPalette::ColorGroup group = isActiveWindow() && widget.hasFocus() ? QPalette::Active : QPalette::Inactive; -- const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : normalTextColorRole(); -+ const QPalette::ColorRole role = /*isSelected() ? QPalette::HighlightedText :*/ normalTextColorRole(); - return styleOption().palette.color(group, role); - } - -@@ -1568,7 +1541,7 @@ void KStandardItemListWidget::updateAdditionalInfoTextColor() - const bool hasFocus = scene()->views()[0]->parentWidget()->hasFocus(); - if (m_customTextColor.isValid()) { - c1 = m_customTextColor; -- } else if (isSelected() && hasFocus && (m_layout != DetailsLayout || m_highlightEntireRow)) { -+ } else if (false && isSelected() && hasFocus && (m_layout != DetailsLayout || m_highlightEntireRow)) { - // The detail text color needs to match the main text (HighlightedText) for the same level - // of readability. We short circuit early here to avoid interpolating with another color. - m_additionalInfoTextColor = styleOption().palette.color(QPalette::HighlightedText); --- -GitLab - - -From 64650add73385948fd76b487a90da2c7635a2b7a Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 14 Apr 2025 14:53:01 +0300 -Subject: [PATCH 02/69] Show a gap between selection and focus - ---- - src/kitemviews/kitemlistwidget.cpp | 35 ++++++++++++++++-------------- - 1 file changed, 19 insertions(+), 16 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index a6fd75a347..1e82c27b1b 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -607,13 +607,16 @@ void KItemListWidget::clearHoverCache() - void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState) - { - QStyleOptionViewItem viewItemOption; -+ const int focusPenWidth = 2; -+ const int roundness = 5; - initStyleOption(&viewItemOption); - viewItemOption.state = styleState; - viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; - viewItemOption.showDecorationSelected = true; -- viewItemOption.rect = selectionRect().toRect().adjusted(2, 2, -2, -2); -+ viewItemOption.rect = selectionRect().toRect(); -+ viewItemOption.rect = viewItemOption.rect.adjusted(focusPenWidth, focusPenWidth, -focusPenWidth, -focusPenWidth); - QPainterPath path; -- path.addRoundedRect(viewItemOption.rect, 5, 5); -+ path.addRoundedRect(viewItemOption.rect, roundness, roundness); - QColor accentColor{widget->palette().color(QPalette::Accent)}; - painter->setRenderHint(QPainter::Antialiasing); - bool current = m_current && styleState & QStyle::State_Active; -@@ -621,26 +624,26 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - // Background item - accentColor.setAlphaF(0.0); - if (m_selected && m_hovered) { -- accentColor.setAlphaF(0.5); -+ accentColor.setAlphaF(1.0); - } else if (m_selected) { -- accentColor.setAlphaF(0.4); -- } else if (m_hovered && current) { -- accentColor.setAlphaF(0.3); -+ accentColor.setAlphaF(0.8); - } else if (m_hovered) { -- accentColor.setAlphaF(0.1); -+ accentColor.setAlphaF(0.3); -+ } -+ if (current) { -+ auto currentGap = focusPenWidth; -+ auto currentPathRect = viewItemOption.rect.adjusted(currentGap, currentGap, -currentGap, -currentGap); -+ QPainterPath currentPath; -+ currentPath.addRoundedRect(currentPathRect, roundness, roundness); -+ painter->fillPath(currentPath, accentColor); -+ } else { -+ painter->fillPath(path, accentColor); - } -- painter->fillPath(path, accentColor); - - // Focus decoration -- if (current && m_hovered) { -- accentColor.setAlphaF(1.0); -- } else if (current || m_hovered) { -- accentColor.setAlphaF(0.9); -- } else if (m_current) { -- accentColor.setAlphaF(0.3); -- } - if (m_current || m_hovered) { -- const QPen pen{accentColor, 2}; -+ accentColor.setAlphaF(1.0); -+ const QPen pen{accentColor, focusPenWidth}; - painter->setPen(pen); - painter->drawPath(path); - } --- -GitLab - - -From da8cbfdd2d72237e2d2a13c88b5a0fafd558ea24 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 14 Apr 2025 15:20:00 +0300 -Subject: [PATCH 03/69] Do not colorize icons - ---- - src/kitemviews/kstandarditemlistwidget.cpp | 11 ----------- - 1 file changed, 11 deletions(-) - -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index c320e375b4..c56c859a71 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -1120,17 +1120,6 @@ void KStandardItemListWidget::updatePixmapCache() - if (m_isHidden) { - KIconEffect::semiTransparent(m_pixmap); - } -- -- if (m_layout == IconsLayout && isSelected()) { -- const QColor color = palette().brush(QPalette::Normal, QPalette::Highlight).color(); -- QImage image = m_pixmap.toImage(); -- if (image.isNull()) { -- m_hoverPixmap = QPixmap(); -- return; -- } -- KIconEffect::colorize(image, color, 0.8f); -- m_pixmap = QPixmap::fromImage(image); -- } - } - - int scaledIconSize = 0; --- -GitLab - - -From 434aee5f8375f66c41eefc75206a2b2a81849ea9 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 14 Apr 2025 15:58:30 +0300 -Subject: [PATCH 04/69] add highlightedTextColor back - ---- - src/kitemviews/kstandarditemlistwidget.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index c56c859a71..486c909de1 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -721,7 +721,7 @@ QColor KStandardItemListWidget::textColor(const QWidget &widget) const - } - - const QPalette::ColorGroup group = isActiveWindow() && widget.hasFocus() ? QPalette::Active : QPalette::Inactive; -- const QPalette::ColorRole role = /*isSelected() ? QPalette::HighlightedText :*/ normalTextColorRole(); -+ const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : normalTextColorRole(); - return styleOption().palette.color(group, role); - } - --- -GitLab - - -From fa6ed958b64cf5fd39d3624a661b5984249fce30 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 14 Apr 2025 16:51:26 +0300 -Subject: [PATCH 05/69] Modify padding for iconslayout - ---- - src/kitemviews/kstandarditemlistwidget.cpp | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 486c909de1..2d209ba5bb 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -550,11 +550,11 @@ QRectF KStandardItemListWidget::selectionRect() const - } else { - result.setLeft(size().width() - m_columnWidthSum - rightPadding()); - } -- } -- -- if (m_layout == IconsLayout) { -- const int availableWidth = size().width() - 2 * padding - result.width(); -- result = result.adjusted(-0.5 * availableWidth, 0, 0.5 * availableWidth, 0); -+ } else { -+ // Make sure values are always positive -+ const int availableWidth = qAbs((size().width() - 2 * padding - result.width()) * 0.5); -+ const int availableHeight = m_layout == CompactLayout ? 0 : qAbs((size().height() - 2 * padding - result.height()) * 0.5); -+ result = result.adjusted(-availableWidth, -availableHeight, availableWidth, availableHeight); - } - - return result; --- -GitLab - - -From 66c8dbf844c81197ec30a90ead4b392b803573ae Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 14 Apr 2025 16:55:17 +0300 -Subject: [PATCH 06/69] Use highlight color - ---- - src/kitemviews/kitemlistwidget.cpp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 1e82c27b1b..8c5b1e6259 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -617,7 +617,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - viewItemOption.rect = viewItemOption.rect.adjusted(focusPenWidth, focusPenWidth, -focusPenWidth, -focusPenWidth); - QPainterPath path; - path.addRoundedRect(viewItemOption.rect, roundness, roundness); -- QColor accentColor{widget->palette().color(QPalette::Accent)}; -+ QColor accentColor{widget->palette().color(QPalette::Highlight)}; - painter->setRenderHint(QPainter::Antialiasing); - bool current = m_current && styleState & QStyle::State_Active; - -@@ -643,7 +643,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - // Focus decoration - if (m_current || m_hovered) { - accentColor.setAlphaF(1.0); -- const QPen pen{accentColor, focusPenWidth}; -+ const QPen pen{accentColor.lighter(120), focusPenWidth}; - painter->setPen(pen); - painter->drawPath(path); - } --- -GitLab - - -From 49441c8362b56b04ce0ccf25f6f45070a4ca8477 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 14 Apr 2025 17:00:54 +0300 -Subject: [PATCH 07/69] adjust the viewitemoption.rect - ---- - src/kitemviews/kitemlistwidget.cpp | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 8c5b1e6259..9444616f58 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -608,20 +608,23 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - { - QStyleOptionViewItem viewItemOption; - const int focusPenWidth = 2; -+ // Small adjustment due to how QRect coordinates work -+ const int viewItemRectAdjustment = focusPenWidth + 1; - const int roundness = 5; - initStyleOption(&viewItemOption); - viewItemOption.state = styleState; - viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; - viewItemOption.showDecorationSelected = true; - viewItemOption.rect = selectionRect().toRect(); -- viewItemOption.rect = viewItemOption.rect.adjusted(focusPenWidth, focusPenWidth, -focusPenWidth, -focusPenWidth); -+ viewItemOption.rect = viewItemOption.rect.adjusted(viewItemRectAdjustment, viewItemRectAdjustment, -viewItemRectAdjustment, -viewItemRectAdjustment); - QPainterPath path; - path.addRoundedRect(viewItemOption.rect, roundness, roundness); - QColor accentColor{widget->palette().color(QPalette::Highlight)}; - painter->setRenderHint(QPainter::Antialiasing); - bool current = m_current && styleState & QStyle::State_Active; - -- // Background item -+ // Background item, alpha values are from -+ // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg - accentColor.setAlphaF(0.0); - if (m_selected && m_hovered) { - accentColor.setAlphaF(1.0); -@@ -641,7 +644,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - } - - // Focus decoration -- if (m_current || m_hovered) { -+ if (current || m_hovered) { - accentColor.setAlphaF(1.0); - const QPen pen{accentColor.lighter(120), focusPenWidth}; - painter->setPen(pen); --- -GitLab - - -From 35ffad2d67c6dca2bab0d979b8017a5da377ae05 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Tue, 15 Apr 2025 15:03:01 +0300 -Subject: [PATCH 08/69] Make hovered outline transparent - ---- - src/kitemviews/kitemlistwidget.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 9444616f58..ddf9a4ea1a 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -645,7 +645,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - - // Focus decoration - if (current || m_hovered) { -- accentColor.setAlphaF(1.0); -+ accentColor.setAlphaF(m_hovered ? 0.4 : 1.0); - const QPen pen{accentColor.lighter(120), focusPenWidth}; - painter->setPen(pen); - painter->drawPath(path); --- -GitLab - - -From 528f25f0c412073a3ae643fb5f9f8d163cc83d21 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Tue, 15 Apr 2025 15:10:27 +0300 -Subject: [PATCH 09/69] Only apply hover effect to icon when its selected - -Better contrast this way ---- - src/kitemviews/kstandarditemlistwidget.cpp | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 2d209ba5bb..b9bbb68b8a 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -1171,7 +1171,9 @@ void KStandardItemListWidget::updatePixmapCache() - // Prepare the pixmap that is used when the item gets hovered - if (isHovered()) { - m_hoverPixmap = m_pixmap; -- KIconEffect::toActive(m_hoverPixmap); -+ if (isSelected()) { -+ KIconEffect::toActive(m_hoverPixmap); -+ } - } else if (hoverOpacity() <= 0.0) { - // No hover animation is ongoing. Clear m_hoverPixmap to save memory. - m_hoverPixmap = QPixmap(); --- -GitLab - - -From edf7272c9c8245f7297d2bd9738996433fd8bb82 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Tue, 15 Apr 2025 16:53:09 +0300 -Subject: [PATCH 10/69] Use style 2 - ---- - src/kitemviews/kitemlistwidget.cpp | 17 +++++------------ - 1 file changed, 5 insertions(+), 12 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index ddf9a4ea1a..14795af9fa 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -629,23 +629,16 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - if (m_selected && m_hovered) { - accentColor.setAlphaF(1.0); - } else if (m_selected) { -- accentColor.setAlphaF(0.8); -+ accentColor.setAlphaF(0.5); - } else if (m_hovered) { - accentColor.setAlphaF(0.3); - } -- if (current) { -- auto currentGap = focusPenWidth; -- auto currentPathRect = viewItemOption.rect.adjusted(currentGap, currentGap, -currentGap, -currentGap); -- QPainterPath currentPath; -- currentPath.addRoundedRect(currentPathRect, roundness, roundness); -- painter->fillPath(currentPath, accentColor); -- } else { -- painter->fillPath(path, accentColor); -- } -+ -+ painter->fillPath(path, accentColor); - - // Focus decoration -- if (current || m_hovered) { -- accentColor.setAlphaF(m_hovered ? 0.4 : 1.0); -+ if (current) { -+ accentColor.setAlphaF(1.0); - const QPen pen{accentColor.lighter(120), focusPenWidth}; - painter->setPen(pen); - painter->drawPath(path); --- -GitLab - - -From 9933d7c49a1d0bcf956afe69b347df18fb2f1c70 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Tue, 15 Apr 2025 17:04:08 +0300 -Subject: [PATCH 11/69] Set pen color according to base lightness - ---- - src/kitemviews/kitemlistwidget.cpp | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 14795af9fa..64584abce2 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -629,7 +629,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - if (m_selected && m_hovered) { - accentColor.setAlphaF(1.0); - } else if (m_selected) { -- accentColor.setAlphaF(0.5); -+ accentColor.setAlphaF(0.8); - } else if (m_hovered) { - accentColor.setAlphaF(0.3); - } -@@ -639,7 +639,8 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - // Focus decoration - if (current) { - accentColor.setAlphaF(1.0); -- const QPen pen{accentColor.lighter(120), focusPenWidth}; -+ // Set the pen color lighter or darker depending on background color -+ const QPen pen{m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker() : accentColor.lighter(), focusPenWidth}; - painter->setPen(pen); - painter->drawPath(path); - } --- -GitLab - - -From 0ddc8b6f93bda0afc525e57576ef00ab0ad94697 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Tue, 15 Apr 2025 17:21:11 +0300 -Subject: [PATCH 12/69] Dont show focus before interaction - ---- - src/kitemviews/kitemlistcontroller.cpp | 4 ++++ - src/kitemviews/kitemlistselectionmanager.cpp | 4 +--- - 2 files changed, 5 insertions(+), 3 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index cd60c3a41b..f0c6a26878 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -478,6 +478,10 @@ bool KItemListController::keyPressEvent(QKeyEvent *event) - return false; - } - -+ if (index < 0) { -+ index = 0; -+ } -+ - if (m_selectionManager->currentItem() != index) { - switch (m_selectionBehavior) { - case NoSelection: -diff --git a/src/kitemviews/kitemlistselectionmanager.cpp b/src/kitemviews/kitemlistselectionmanager.cpp -index 6f7f0e0776..abf58df240 100644 ---- a/src/kitemviews/kitemlistselectionmanager.cpp -+++ b/src/kitemviews/kitemlistselectionmanager.cpp -@@ -217,9 +217,7 @@ void KItemListSelectionManager::itemsInserted(const KItemRangeList &itemRanges) - const KItemSet previousSelection = selectedItems(); - - // Update the current item -- if (m_currentItem < 0) { -- setCurrentItem(0); -- } else { -+ if (m_currentItem >= 0) { - const int previousCurrent = m_currentItem; - int inc = 0; - for (const KItemRange &itemRange : itemRanges) { --- -GitLab - - -From 8588d3aa3bb73e7c6f35df8844de0b9ccc335078 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Wed, 16 Apr 2025 15:23:08 +0300 -Subject: [PATCH 13/69] Less intense selection lightening/darkening - ---- - src/kitemviews/kitemlistwidget.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 64584abce2..ebbfb98cc6 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -640,7 +640,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - if (current) { - accentColor.setAlphaF(1.0); - // Set the pen color lighter or darker depending on background color -- const QPen pen{m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker() : accentColor.lighter(), focusPenWidth}; -+ const QPen pen{m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110), focusPenWidth}; - painter->setPen(pen); - painter->drawPath(path); - } --- -GitLab - - -From cbec8b9acd0aa13ddb984097e9c9ea37baba6a33 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Wed, 16 Apr 2025 15:23:43 +0300 -Subject: [PATCH 14/69] Clean up currentItem when clicking on empty area - ---- - src/kitemviews/kitemlistcontroller.cpp | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index f0c6a26878..4f5c8fbb39 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1720,6 +1720,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - - if (!m_pressedIndex.has_value()) { - // We have a right-click in an empty region, don't create rubber band. -+ m_selectionManager->setCurrentItem(-1); - return true; - } - } -@@ -1783,6 +1784,8 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - } - - return !createRubberBand; -+ } else { -+ m_selectionManager->setCurrentItem(-1); - } - - return false; --- -GitLab - - -From cfe048eabb2e29c8e01f9a0428548f8366078b73 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Wed, 16 Apr 2025 15:52:33 +0300 -Subject: [PATCH 15/69] Clean up the current item after mouse drag if it - selects nothing - ---- - src/kitemviews/kitemlistcontroller.cpp | 16 ++++++++++++++-- - src/kitemviews/kitemlistcontroller.h | 5 +++++ - 2 files changed, 19 insertions(+), 2 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 4f5c8fbb39..e8edc33c03 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1720,7 +1720,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - - if (!m_pressedIndex.has_value()) { - // We have a right-click in an empty region, don't create rubber band. -- m_selectionManager->setCurrentItem(-1); -+ cleanUpCurrentItem(); - return true; - } - } -@@ -1785,7 +1785,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - - return !createRubberBand; - } else { -- m_selectionManager->setCurrentItem(-1); -+ cleanUpCurrentItem(); - } - - return false; -@@ -1881,6 +1881,8 @@ bool KItemListController::onRelease(const QPointF &pos, const Qt::KeyboardModifi - m_pressedMouseGlobalPos = QPointF(); - m_pressedIndex = std::nullopt; - m_clearSelectionIfItemsAreNotDragged = false; -+ // Clean up current item if nothing is selected after release from drag operation -+ cleanUpCurrentItem(); - return false; - } - -@@ -1913,4 +1915,14 @@ void KItemListController::slotStateChanged(QScroller::State newState) - } - } - -+void KItemListController::cleanUpCurrentItem() -+{ -+ if (m_selectionManager->currentItem() != -1 && m_selectionManager->selectedItems().count() == 0) { -+ if (m_selectionManager->isAnchoredSelectionActive()) { -+ m_selectionManager->endAnchoredSelection(); -+ } -+ m_selectionManager->setCurrentItem(-1); -+ } -+} -+ - #include "moc_kitemlistcontroller.cpp" -diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h -index 48da07206d..7fcda72795 100644 ---- a/src/kitemviews/kitemlistcontroller.h -+++ b/src/kitemviews/kitemlistcontroller.h -@@ -325,6 +325,11 @@ private: - bool onPress(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons); - bool onRelease(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons, bool touch); - void startRubberBand(); -+ /** -+ * Ends the anchoredSelection and sets the currentItem in selectionManager to -1. -+ * This is used to not draw the focus item when using mouse to operate the view. -+ */ -+ void cleanUpCurrentItem(); - - private: - bool m_singleClickActivationEnforced; --- -GitLab - - -From d833acb8a5af26fef199e9dd6c1e26416947a0b9 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Wed, 16 Apr 2025 16:10:42 +0300 -Subject: [PATCH 16/69] Fix text colors - ---- - src/kitemviews/kitemlistwidget.cpp | 6 +++--- - src/kitemviews/kstandarditemlistwidget.cpp | 10 ++++------ - 2 files changed, 7 insertions(+), 9 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index ebbfb98cc6..0f85b726a8 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -619,7 +619,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - viewItemOption.rect = viewItemOption.rect.adjusted(viewItemRectAdjustment, viewItemRectAdjustment, -viewItemRectAdjustment, -viewItemRectAdjustment); - QPainterPath path; - path.addRoundedRect(viewItemOption.rect, roundness, roundness); -- QColor accentColor{widget->palette().color(QPalette::Highlight)}; -+ QColor accentColor{widget->palette().color(QPalette::Accent)}; - painter->setRenderHint(QPainter::Antialiasing); - bool current = m_current && styleState & QStyle::State_Active; - -@@ -627,9 +627,9 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg - accentColor.setAlphaF(0.0); - if (m_selected && m_hovered) { -- accentColor.setAlphaF(1.0); -+ accentColor.setAlphaF(0.5); - } else if (m_selected) { -- accentColor.setAlphaF(0.8); -+ accentColor.setAlphaF(0.4); - } else if (m_hovered) { - accentColor.setAlphaF(0.3); - } -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index b9bbb68b8a..b60aeb19ba 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -721,7 +721,7 @@ QColor KStandardItemListWidget::textColor(const QWidget &widget) const - } - - const QPalette::ColorGroup group = isActiveWindow() && widget.hasFocus() ? QPalette::Active : QPalette::Inactive; -- const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : normalTextColorRole(); -+ const QPalette::ColorRole role = normalTextColorRole(); - return styleOption().palette.color(group, role); - } - -@@ -1171,9 +1171,7 @@ void KStandardItemListWidget::updatePixmapCache() - // Prepare the pixmap that is used when the item gets hovered - if (isHovered()) { - m_hoverPixmap = m_pixmap; -- if (isSelected()) { -- KIconEffect::toActive(m_hoverPixmap); -- } -+ KIconEffect::toActive(m_hoverPixmap); - } else if (hoverOpacity() <= 0.0) { - // No hover animation is ongoing. Clear m_hoverPixmap to save memory. - m_hoverPixmap = QPixmap(); -@@ -1532,10 +1530,10 @@ void KStandardItemListWidget::updateAdditionalInfoTextColor() - const bool hasFocus = scene()->views()[0]->parentWidget()->hasFocus(); - if (m_customTextColor.isValid()) { - c1 = m_customTextColor; -- } else if (false && isSelected() && hasFocus && (m_layout != DetailsLayout || m_highlightEntireRow)) { -+ } else if (isSelected() && hasFocus && (m_layout != DetailsLayout || m_highlightEntireRow)) { - // The detail text color needs to match the main text (HighlightedText) for the same level - // of readability. We short circuit early here to avoid interpolating with another color. -- m_additionalInfoTextColor = styleOption().palette.color(QPalette::HighlightedText); -+ m_additionalInfoTextColor = styleOption().palette.color(normalTextColorRole()); - return; - } else { - c1 = styleOption().palette.text().color(); --- -GitLab - - -From ec725291eac833b8982cda4b1592d54239626b4f Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Wed, 16 Apr 2025 16:32:35 +0300 -Subject: [PATCH 17/69] Add bit more padding around the text to take outline in - account - ---- - src/kitemviews/kstandarditemlistwidget.cpp | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index b60aeb19ba..8e2515c686 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -1171,7 +1171,9 @@ void KStandardItemListWidget::updatePixmapCache() - // Prepare the pixmap that is used when the item gets hovered - if (isHovered()) { - m_hoverPixmap = m_pixmap; -- KIconEffect::toActive(m_hoverPixmap); -+ if (isSelected()) { -+ KIconEffect::toActive(m_hoverPixmap); -+ } - } else if (hoverOpacity() <= 0.0) { - // No hover animation is ongoing. Clear m_hoverPixmap to save memory. - m_hoverPixmap = QPixmap(); -@@ -1300,7 +1302,8 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() - - const KItemListStyleOption &option = styleOption(); - const qreal padding = option.padding; -- const qreal maxWidth = size().width() - 2 * padding; -+ // adjust the max width according to new outline style -+ const qreal maxWidth = size().width() - 2 * padding - 10; - const qreal lineSpacing = m_customizedFontMetrics.lineSpacing(); - - // Initialize properties for the "text" role. It will be used as anchor --- -GitLab - - -From 230a6221183594954086187553016d577d738a38 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Wed, 16 Apr 2025 16:36:26 +0300 -Subject: [PATCH 18/69] revert padding - ---- - src/kitemviews/kstandarditemlistwidget.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 8e2515c686..0303547b23 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -1303,7 +1303,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() - const KItemListStyleOption &option = styleOption(); - const qreal padding = option.padding; - // adjust the max width according to new outline style -- const qreal maxWidth = size().width() - 2 * padding - 10; -+ const qreal maxWidth = size().width() - 2 * padding; - const qreal lineSpacing = m_customizedFontMetrics.lineSpacing(); - - // Initialize properties for the "text" role. It will be used as anchor --- -GitLab - - -From 462e3846d8f077f739d7551a0930df53d9c7069e Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 17 Apr 2025 11:41:33 +0300 -Subject: [PATCH 19/69] Use rect instead of selectionRect for the selection - painting - -Selectionrect is for mouse selection things ---- - src/kitemviews/kitemlistwidget.cpp | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 0f85b726a8..92041fc1e7 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -608,15 +608,12 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - { - QStyleOptionViewItem viewItemOption; - const int focusPenWidth = 2; -- // Small adjustment due to how QRect coordinates work -- const int viewItemRectAdjustment = focusPenWidth + 1; - const int roundness = 5; - initStyleOption(&viewItemOption); - viewItemOption.state = styleState; - viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; - viewItemOption.showDecorationSelected = true; -- viewItemOption.rect = selectionRect().toRect(); -- viewItemOption.rect = viewItemOption.rect.adjusted(viewItemRectAdjustment, viewItemRectAdjustment, -viewItemRectAdjustment, -viewItemRectAdjustment); -+ viewItemOption.rect = rect().toRect(); - QPainterPath path; - path.addRoundedRect(viewItemOption.rect, roundness, roundness); - QColor accentColor{widget->palette().color(QPalette::Accent)}; --- -GitLab - - -From 06dbf47020e8a3bc33f8ae87a451a8418efc3306 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 17 Apr 2025 11:53:15 +0300 -Subject: [PATCH 20/69] Revert currentItem changes - ---- - src/kitemviews/kitemlistcontroller.cpp | 19 ------------------- - src/kitemviews/kitemlistcontroller.h | 5 ----- - src/kitemviews/kitemlistselectionmanager.cpp | 4 +++- - 3 files changed, 3 insertions(+), 25 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index e8edc33c03..cd60c3a41b 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -478,10 +478,6 @@ bool KItemListController::keyPressEvent(QKeyEvent *event) - return false; - } - -- if (index < 0) { -- index = 0; -- } -- - if (m_selectionManager->currentItem() != index) { - switch (m_selectionBehavior) { - case NoSelection: -@@ -1720,7 +1716,6 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - - if (!m_pressedIndex.has_value()) { - // We have a right-click in an empty region, don't create rubber band. -- cleanUpCurrentItem(); - return true; - } - } -@@ -1784,8 +1779,6 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - } - - return !createRubberBand; -- } else { -- cleanUpCurrentItem(); - } - - return false; -@@ -1881,8 +1874,6 @@ bool KItemListController::onRelease(const QPointF &pos, const Qt::KeyboardModifi - m_pressedMouseGlobalPos = QPointF(); - m_pressedIndex = std::nullopt; - m_clearSelectionIfItemsAreNotDragged = false; -- // Clean up current item if nothing is selected after release from drag operation -- cleanUpCurrentItem(); - return false; - } - -@@ -1915,14 +1906,4 @@ void KItemListController::slotStateChanged(QScroller::State newState) - } - } - --void KItemListController::cleanUpCurrentItem() --{ -- if (m_selectionManager->currentItem() != -1 && m_selectionManager->selectedItems().count() == 0) { -- if (m_selectionManager->isAnchoredSelectionActive()) { -- m_selectionManager->endAnchoredSelection(); -- } -- m_selectionManager->setCurrentItem(-1); -- } --} -- - #include "moc_kitemlistcontroller.cpp" -diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h -index 7fcda72795..48da07206d 100644 ---- a/src/kitemviews/kitemlistcontroller.h -+++ b/src/kitemviews/kitemlistcontroller.h -@@ -325,11 +325,6 @@ private: - bool onPress(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons); - bool onRelease(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons, bool touch); - void startRubberBand(); -- /** -- * Ends the anchoredSelection and sets the currentItem in selectionManager to -1. -- * This is used to not draw the focus item when using mouse to operate the view. -- */ -- void cleanUpCurrentItem(); - - private: - bool m_singleClickActivationEnforced; -diff --git a/src/kitemviews/kitemlistselectionmanager.cpp b/src/kitemviews/kitemlistselectionmanager.cpp -index abf58df240..6f7f0e0776 100644 ---- a/src/kitemviews/kitemlistselectionmanager.cpp -+++ b/src/kitemviews/kitemlistselectionmanager.cpp -@@ -217,7 +217,9 @@ void KItemListSelectionManager::itemsInserted(const KItemRangeList &itemRanges) - const KItemSet previousSelection = selectedItems(); - - // Update the current item -- if (m_currentItem >= 0) { -+ if (m_currentItem < 0) { -+ setCurrentItem(0); -+ } else { - const int previousCurrent = m_currentItem; - int inc = 0; - for (const KItemRange &itemRange : itemRanges) { --- -GitLab - - -From 71ed6a4a0745770410056ad234ee8d7104c10767 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 17 Apr 2025 12:20:14 +0300 -Subject: [PATCH 21/69] Make the focus effect hiding/showing visual only - ---- - src/kitemviews/kitemlistcontroller.cpp | 14 ++++++++++++++ - src/kitemviews/kitemlistcontroller.h | 1 + - src/kitemviews/kitemlistview.cpp | 3 +++ - src/kitemviews/kitemlistwidget.cpp | 8 +++++++- - src/kitemviews/kitemlistwidget.h | 3 +++ - 5 files changed, 28 insertions(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index cd60c3a41b..de8bd26254 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1731,6 +1731,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - if (rightClick && hitTargetIsRowEmptyRegion) { - // We have a right click outside the icon and text rect but within the hover highlight area. - // We don't want items to get selected through this, so we return now. -+ showFocusWidget(false); - return true; - } - -@@ -1779,6 +1780,8 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - } - - return !createRubberBand; -+ } else { -+ showFocusWidget(false); - } - - return false; -@@ -1906,4 +1909,15 @@ void KItemListController::slotStateChanged(QScroller::State newState) - } - } - -+void KItemListController::showFocusWidget(bool show) -+{ -+ const auto widgets = m_view->visibleItemListWidgets(); -+ for (auto widget : widgets) { -+ if (widget->isCurrent()) { -+ widget->showFocusEffect(show); -+ return; -+ } -+ } -+} -+ - #include "moc_kitemlistcontroller.cpp" -diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h -index 48da07206d..d071f20ab0 100644 ---- a/src/kitemviews/kitemlistcontroller.h -+++ b/src/kitemviews/kitemlistcontroller.h -@@ -325,6 +325,7 @@ private: - bool onPress(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons); - bool onRelease(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons, bool touch); - void startRubberBand(); -+ void showFocusWidget(bool show); - - private: - bool m_singleClickActivationEnforced; -diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp -index 265e41e6ca..4db8d4ed0a 100644 ---- a/src/kitemviews/kitemlistview.cpp -+++ b/src/kitemviews/kitemlistview.cpp -@@ -1529,6 +1529,8 @@ void KItemListView::slotCurrentChanged(int current, int previous) - - KItemListWidget *currentWidget = m_visibleItems.value(current, nullptr); - if (currentWidget) { -+ // If previous item was -1, we're setting the first item current, so we can hide focus -+ currentWidget->showFocusEffect(previous >= 0 ? true : false); - currentWidget->setCurrent(true); - } - } -@@ -1548,6 +1550,7 @@ void KItemListView::slotSelectionChanged(const KItemSet ¤t, const KItemSet - KItemListWidget *widget = it.value(); - const bool isSelected(current.contains(index)); - widget->setSelected(isSelected); -+ widget->showFocusEffect(true); - - #ifndef QT_NO_ACCESSIBILITY - if (!QAccessible::isActive()) { -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 92041fc1e7..e41f8a1557 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -37,6 +37,7 @@ KItemListWidget::KItemListWidget(KItemListWidgetInformant *informant, QGraphicsI - , m_expansionAreaHovered(false) - , m_alternateBackground(false) - , m_enabledSelectionToggle(false) -+ , m_showFocusEffect(true) - , m_data() - , m_visibleRoles() - , m_columnWidths() -@@ -634,7 +635,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - painter->fillPath(path, accentColor); - - // Focus decoration -- if (current) { -+ if (current && m_showFocusEffect) { - accentColor.setAlphaF(1.0); - // Set the pen color lighter or darker depending on background color - const QPen pen{m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110), focusPenWidth}; -@@ -643,4 +644,9 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - } - } - -+void KItemListWidget::showFocusEffect(bool show) -+{ -+ m_showFocusEffect = show; -+} -+ - #include "moc_kitemlistwidget.cpp" -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index 0e07d7ab55..06ed511155 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -194,6 +194,8 @@ public: - */ - virtual void startActivateSoonAnimation(int timeUntilActivation); - -+ void showFocusEffect(bool showFocusEffect); -+ - Q_SIGNALS: - void roleEditingCanceled(int index, const QByteArray &role, const QVariant &value); - void roleEditingFinished(int index, const QByteArray &role, const QVariant &value); -@@ -258,6 +260,7 @@ private: - bool m_expansionAreaHovered; - bool m_alternateBackground; - bool m_enabledSelectionToggle; -+ bool m_showFocusEffect; - QHash m_data; - QList m_visibleRoles; - QHash m_columnWidths; --- -GitLab - - -From e89ce5966ac02f7349922b4a0794d433f705d1dd Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 17 Apr 2025 14:46:51 +0300 -Subject: [PATCH 22/69] Start drag from background area - -Now that we have full size selection item, starting -drag when mouse is in there makes sense. - -Signed-off-by: Akseli Lahtinen ---- - src/kitemviews/kitemlistcontroller.cpp | 14 +------------- - 1 file changed, 1 insertion(+), 13 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index de8bd26254..3757fae1f2 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1721,19 +1721,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - } - - if (m_pressedIndex.has_value()) { -- // The hover highlight area of an item is being pressed. -- const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect -- const bool hitTargetIsRowEmptyRegion = !row->contains(row->mapFromItem(m_view, pos)); -- // again, when this method returns false, a rubberBand selection is created as the event is not consumed; -- // createRubberBand here tells us whether to return true or false. -- bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); -- -- if (rightClick && hitTargetIsRowEmptyRegion) { -- // We have a right click outside the icon and text rect but within the hover highlight area. -- // We don't want items to get selected through this, so we return now. -- showFocusWidget(false); -- return true; -- } -+ bool createRubberBand = false; - - m_selectionManager->setCurrentItem(m_pressedIndex.value()); - --- -GitLab - - -From d92820622459bf1c15f24cc76747680e7e15fbf0 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 17 Apr 2025 15:39:58 +0300 -Subject: [PATCH 23/69] Show focus effects always on keypress - ---- - src/kitemviews/kitemlistcontroller.cpp | 6 ++---- - src/kitemviews/kitemlistwidget.cpp | 5 ++++- - 2 files changed, 6 insertions(+), 5 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 3757fae1f2..190402c705 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -238,6 +238,7 @@ bool KItemListController::isSearchAsYouTypeActive() const - bool KItemListController::keyPressEvent(QKeyEvent *event) - { - int index = m_selectionManager->currentItem(); -+ showFocusWidget(true); - int key = event->key(); - const bool shiftPressed = event->modifiers() & Qt::ShiftModifier; - -@@ -1901,10 +1902,7 @@ void KItemListController::showFocusWidget(bool show) - { - const auto widgets = m_view->visibleItemListWidgets(); - for (auto widget : widgets) { -- if (widget->isCurrent()) { -- widget->showFocusEffect(show); -- return; -- } -+ widget->showFocusEffect(show); - } - } - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index e41f8a1557..174e2feb6a 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -646,7 +646,10 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - - void KItemListWidget::showFocusEffect(bool show) - { -- m_showFocusEffect = show; -+ if (m_showFocusEffect != show) { -+ m_showFocusEffect = show; -+ update(); -+ } - } - - #include "moc_kitemlistwidget.cpp" --- -GitLab - - -From 39063dd2c47d79a1adadbeefd9c612c03fe8b24c Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 17 Apr 2025 16:20:12 +0300 -Subject: [PATCH 24/69] Rename methods, add method for checking if focus is - shown for widget - ---- - src/kitemviews/kitemlistcontroller.cpp | 8 ++++---- - src/kitemviews/kitemlistcontroller.h | 2 +- - src/kitemviews/kitemlistview.cpp | 3 --- - src/kitemviews/kitemlistwidget.cpp | 15 ++++++++++----- - src/kitemviews/kitemlistwidget.h | 5 +++-- - 5 files changed, 18 insertions(+), 15 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 190402c705..f30453e9cb 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -238,7 +238,7 @@ bool KItemListController::isSearchAsYouTypeActive() const - bool KItemListController::keyPressEvent(QKeyEvent *event) - { - int index = m_selectionManager->currentItem(); -- showFocusWidget(true); -+ showKeyboardFocusEffect(true); - int key = event->key(); - const bool shiftPressed = event->modifiers() & Qt::ShiftModifier; - -@@ -1770,7 +1770,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - - return !createRubberBand; - } else { -- showFocusWidget(false); -+ showKeyboardFocusEffect(false); - } - - return false; -@@ -1898,11 +1898,11 @@ void KItemListController::slotStateChanged(QScroller::State newState) - } - } - --void KItemListController::showFocusWidget(bool show) -+void KItemListController::showKeyboardFocusEffect(bool show) - { - const auto widgets = m_view->visibleItemListWidgets(); - for (auto widget : widgets) { -- widget->showFocusEffect(show); -+ widget->showKeyboardFocusEffect(show); - } - } - -diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h -index d071f20ab0..d424f92dd0 100644 ---- a/src/kitemviews/kitemlistcontroller.h -+++ b/src/kitemviews/kitemlistcontroller.h -@@ -325,7 +325,7 @@ private: - bool onPress(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons); - bool onRelease(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons, bool touch); - void startRubberBand(); -- void showFocusWidget(bool show); -+ void showKeyboardFocusEffect(bool show); - - private: - bool m_singleClickActivationEnforced; -diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp -index 4db8d4ed0a..265e41e6ca 100644 ---- a/src/kitemviews/kitemlistview.cpp -+++ b/src/kitemviews/kitemlistview.cpp -@@ -1529,8 +1529,6 @@ void KItemListView::slotCurrentChanged(int current, int previous) - - KItemListWidget *currentWidget = m_visibleItems.value(current, nullptr); - if (currentWidget) { -- // If previous item was -1, we're setting the first item current, so we can hide focus -- currentWidget->showFocusEffect(previous >= 0 ? true : false); - currentWidget->setCurrent(true); - } - } -@@ -1550,7 +1548,6 @@ void KItemListView::slotSelectionChanged(const KItemSet ¤t, const KItemSet - KItemListWidget *widget = it.value(); - const bool isSelected(current.contains(index)); - widget->setSelected(isSelected); -- widget->showFocusEffect(true); - - #ifndef QT_NO_ACCESSIBILITY - if (!QAccessible::isActive()) { -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 174e2feb6a..6d1f40a444 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -37,7 +37,7 @@ KItemListWidget::KItemListWidget(KItemListWidgetInformant *informant, QGraphicsI - , m_expansionAreaHovered(false) - , m_alternateBackground(false) - , m_enabledSelectionToggle(false) -- , m_showFocusEffect(true) -+ , m_showKeyboardFocusEffect(false) - , m_data() - , m_visibleRoles() - , m_columnWidths() -@@ -635,7 +635,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - painter->fillPath(path, accentColor); - - // Focus decoration -- if (current && m_showFocusEffect) { -+ if (current && m_showKeyboardFocusEffect) { - accentColor.setAlphaF(1.0); - // Set the pen color lighter or darker depending on background color - const QPen pen{m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110), focusPenWidth}; -@@ -644,12 +644,17 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - } - } - --void KItemListWidget::showFocusEffect(bool show) -+void KItemListWidget::showKeyboardFocusEffect(bool show) - { -- if (m_showFocusEffect != show) { -- m_showFocusEffect = show; -+ if (m_showKeyboardFocusEffect != show) { -+ m_showKeyboardFocusEffect = show; - update(); - } - } - -+bool KItemListWidget::keyboardFocusEffectShown() -+{ -+ return m_showKeyboardFocusEffect; -+} -+ - #include "moc_kitemlistwidget.cpp" -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index 06ed511155..21e2af4ba1 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -194,7 +194,8 @@ public: - */ - virtual void startActivateSoonAnimation(int timeUntilActivation); - -- void showFocusEffect(bool showFocusEffect); -+ void showKeyboardFocusEffect(bool showFocusEffect); -+ bool keyboardFocusEffectShown(); - - Q_SIGNALS: - void roleEditingCanceled(int index, const QByteArray &role, const QVariant &value); -@@ -260,7 +261,7 @@ private: - bool m_expansionAreaHovered; - bool m_alternateBackground; - bool m_enabledSelectionToggle; -- bool m_showFocusEffect; -+ bool m_showKeyboardFocusEffect; - QHash m_data; - QList m_visibleRoles; - QHash m_columnWidths; --- -GitLab - - -From 80eaae9049df5806380de6a68f957dc503d8b06a Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 17 Apr 2025 16:50:45 +0300 -Subject: [PATCH 25/69] Show focus when selection mode is toggled or navigation - keys pressed - ---- - src/kitemviews/kitemlistcontroller.cpp | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index f30453e9cb..466bf401ed 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -222,6 +222,9 @@ bool KItemListController::singleClickActivationEnforced() const - - void KItemListController::setSelectionModeEnabled(bool enabled) - { -+ if (enabled) { -+ showKeyboardFocusEffect(true); -+ } - m_selectionMode = enabled; - } - -@@ -238,7 +241,6 @@ bool KItemListController::isSearchAsYouTypeActive() const - bool KItemListController::keyPressEvent(QKeyEvent *event) - { - int index = m_selectionManager->currentItem(); -- showKeyboardFocusEffect(true); - int key = event->key(); - const bool shiftPressed = event->modifiers() & Qt::ShiftModifier; - -@@ -291,6 +293,10 @@ bool KItemListController::keyPressEvent(QKeyEvent *event) - const bool navigationPressed = key == Qt::Key_Home || key == Qt::Key_End || key == Qt::Key_PageUp || key == Qt::Key_PageDown || key == Qt::Key_Up - || key == Qt::Key_Down || key == Qt::Key_Left || key == Qt::Key_Right; - -+ if (navigationPressed) { -+ showKeyboardFocusEffect(true); -+ } -+ - const int itemCount = m_model->count(); - - // For horizontal scroll orientation, transform --- -GitLab - - -From 0faf1eeabd4f6be73b622b13058c0b56a473be61 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Tue, 22 Apr 2025 16:23:18 +0300 -Subject: [PATCH 26/69] Always show focus, make focus when unselected more - transparent, remove showKeyboardFocusEffect - ---- - src/kitemviews/kitemlistcontroller.cpp | 17 ----------------- - src/kitemviews/kitemlistcontroller.h | 1 - - src/kitemviews/kitemlistwidget.cpp | 23 +++++------------------ - src/kitemviews/kitemlistwidget.h | 4 ---- - 4 files changed, 5 insertions(+), 40 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 466bf401ed..cd19cd7f69 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -222,9 +222,6 @@ bool KItemListController::singleClickActivationEnforced() const - - void KItemListController::setSelectionModeEnabled(bool enabled) - { -- if (enabled) { -- showKeyboardFocusEffect(true); -- } - m_selectionMode = enabled; - } - -@@ -293,10 +290,6 @@ bool KItemListController::keyPressEvent(QKeyEvent *event) - const bool navigationPressed = key == Qt::Key_Home || key == Qt::Key_End || key == Qt::Key_PageUp || key == Qt::Key_PageDown || key == Qt::Key_Up - || key == Qt::Key_Down || key == Qt::Key_Left || key == Qt::Key_Right; - -- if (navigationPressed) { -- showKeyboardFocusEffect(true); -- } -- - const int itemCount = m_model->count(); - - // For horizontal scroll orientation, transform -@@ -1775,8 +1768,6 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - } - - return !createRubberBand; -- } else { -- showKeyboardFocusEffect(false); - } - - return false; -@@ -1904,12 +1895,4 @@ void KItemListController::slotStateChanged(QScroller::State newState) - } - } - --void KItemListController::showKeyboardFocusEffect(bool show) --{ -- const auto widgets = m_view->visibleItemListWidgets(); -- for (auto widget : widgets) { -- widget->showKeyboardFocusEffect(show); -- } --} -- - #include "moc_kitemlistcontroller.cpp" -diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h -index d424f92dd0..48da07206d 100644 ---- a/src/kitemviews/kitemlistcontroller.h -+++ b/src/kitemviews/kitemlistcontroller.h -@@ -325,7 +325,6 @@ private: - bool onPress(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons); - bool onRelease(const QPointF &pos, const Qt::KeyboardModifiers modifiers, const Qt::MouseButtons buttons, bool touch); - void startRubberBand(); -- void showKeyboardFocusEffect(bool show); - - private: - bool m_singleClickActivationEnforced; -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 6d1f40a444..a67759d087 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -37,7 +37,6 @@ KItemListWidget::KItemListWidget(KItemListWidgetInformant *informant, QGraphicsI - , m_expansionAreaHovered(false) - , m_alternateBackground(false) - , m_enabledSelectionToggle(false) -- , m_showKeyboardFocusEffect(false) - , m_data() - , m_visibleRoles() - , m_columnWidths() -@@ -608,7 +607,6 @@ void KItemListWidget::clearHoverCache() - void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState) - { - QStyleOptionViewItem viewItemOption; -- const int focusPenWidth = 2; - const int roundness = 5; - initStyleOption(&viewItemOption); - viewItemOption.state = styleState; -@@ -635,26 +633,15 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - painter->fillPath(path, accentColor); - - // Focus decoration -- if (current && m_showKeyboardFocusEffect) { -- accentColor.setAlphaF(1.0); -+ if (current) { -+ accentColor = m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110); -+ accentColor.setAlphaF(m_selected || m_hovered ? 1.0 : 0.5); - // Set the pen color lighter or darker depending on background color -- const QPen pen{m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110), focusPenWidth}; -+ QPen pen{accentColor, 1.5}; -+ pen.setCosmetic(true); - painter->setPen(pen); - painter->drawPath(path); - } - } - --void KItemListWidget::showKeyboardFocusEffect(bool show) --{ -- if (m_showKeyboardFocusEffect != show) { -- m_showKeyboardFocusEffect = show; -- update(); -- } --} -- --bool KItemListWidget::keyboardFocusEffectShown() --{ -- return m_showKeyboardFocusEffect; --} -- - #include "moc_kitemlistwidget.cpp" -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index 21e2af4ba1..0e07d7ab55 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -194,9 +194,6 @@ public: - */ - virtual void startActivateSoonAnimation(int timeUntilActivation); - -- void showKeyboardFocusEffect(bool showFocusEffect); -- bool keyboardFocusEffectShown(); -- - Q_SIGNALS: - void roleEditingCanceled(int index, const QByteArray &role, const QVariant &value); - void roleEditingFinished(int index, const QByteArray &role, const QVariant &value); -@@ -261,7 +258,6 @@ private: - bool m_expansionAreaHovered; - bool m_alternateBackground; - bool m_enabledSelectionToggle; -- bool m_showKeyboardFocusEffect; - QHash m_data; - QList m_visibleRoles; - QHash m_columnWidths; --- -GitLab - - -From c372ea1e5c1fa65c86f971a20a0cb4ccaf1e3d41 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Tue, 22 Apr 2025 16:59:40 +0300 -Subject: [PATCH 27/69] Fix inconsistent hover area sizing, refactor - selectionRect - ---- - src/kitemviews/kitemlistcontroller.cpp | 9 ++++----- - src/kitemviews/kitemlistview.cpp | 2 +- - src/kitemviews/kitemlistwidget.cpp | 2 +- - src/kitemviews/kitemlistwidget.h | 10 +++++----- - src/kitemviews/kstandarditemlistwidget.cpp | 14 +++++--------- - 5 files changed, 16 insertions(+), 21 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index cd19cd7f69..6ef03dc609 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -990,7 +990,7 @@ bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent *event, const - // we also unhover any old expansion toggle hovers, in case the mouse movement from expansion toggle to icon+text is too fast (i.e. newHoveredWidget is never null between the transition) - unhoverOldExpansionWidget(); - -- const bool isOverIconAndText = newHoveredWidget->iconRect().contains(mappedPos) || newHoveredWidget->textRect().contains(mappedPos); -+ const bool isOverIconAndText = newHoveredWidget->selectionRect().contains(mappedPos); - const bool hasMultipleSelection = m_selectionManager->selectedItems().count() > 1; - - if (hasMultipleSelection && !isOverIconAndText) { -@@ -1366,8 +1366,7 @@ void KItemListController::slotRubberBandChanged() - if (widgetRect.intersects(rubberBandRect)) { - // Select the full row intersecting with the rubberband rectangle - const QRectF selectionRect = widget->selectionRect().translated(widgetRect.topLeft()); -- const QRectF iconRect = widget->iconRect().translated(widgetRect.topLeft()); -- if (selectionRect.intersects(rubberBandRect) || iconRect.intersects(rubberBandRect)) { -+ if (selectionRect.intersects(rubberBandRect)) { - selectedItems.insert(index); - } - } -@@ -1661,7 +1660,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - if (selectedItemsCount > 1 && m_pressedIndex.has_value()) { - const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); - const auto mappedPos = row->mapFromItem(m_view, pos); -- if (pressedItemAlreadySelected || row->iconRect().contains(mappedPos) || row->textRect().contains(mappedPos)) { -+ if (pressedItemAlreadySelected || row->selectionRect().contains(mappedPos)) { - // we are indeed inside the text/icon rect, keep m_pressedIndex what it is - // and short-circuit for single-click activation (it will then propagate to onRelease and activate the item) - // or we just keep going for double-click activation -@@ -1744,7 +1743,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - // We rule out the latter, if the item is not clicked directly and was unselected previously. - const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); - const auto mappedPos = row->mapFromItem(m_view, pos); -- if (!row->iconRect().contains(mappedPos) && !row->textRect().contains(mappedPos) && !pressedItemAlreadySelected) { -+ if (!row->selectionRect().contains(mappedPos) && !pressedItemAlreadySelected) { - createRubberBand = true; - } else { - m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Toggle); -diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp -index 265e41e6ca..9e0a9e0e5c 100644 ---- a/src/kitemviews/kitemlistview.cpp -+++ b/src/kitemviews/kitemlistview.cpp -@@ -542,7 +542,7 @@ QRectF KItemListView::itemContextRect(int index) const - - const KItemListWidget *widget = m_visibleItems.value(index); - if (widget) { -- contextRect = widget->iconRect() | widget->textRect(); -+ contextRect = widget->selectionRect(); - contextRect.translate(itemRect(index).topLeft()); - } - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index a67759d087..8c2432967a 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -612,7 +612,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - viewItemOption.state = styleState; - viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; - viewItemOption.showDecorationSelected = true; -- viewItemOption.rect = rect().toRect(); -+ viewItemOption.rect = selectionRect().toRect(); - QPainterPath path; - path.addRoundedRect(viewItemOption.rect, roundness, roundness); - QColor accentColor{widget->palette().color(QPalette::Accent)}; -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index 0e07d7ab55..4d857c00d7 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -144,11 +144,6 @@ public: - */ - bool contains(const QPointF &point) const override; - -- /** -- * @return Rectangle for the area that shows the icon. -- */ -- virtual QRectF iconRect() const = 0; -- - /** - * @return Rectangle for the area that contains the text-properties. - */ -@@ -245,6 +240,11 @@ private Q_SLOTS: - void slotHoverSequenceTimerTimeout(); - - private: -+ /** -+ * @return Rectangle for the area that shows the icon. -+ */ -+ virtual QRectF iconRect() const = 0; -+ - void initializeSelectionToggle(); - void setHoverOpacity(qreal opacity); - void drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState); -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 0303547b23..4b061c9bb1 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -541,23 +541,19 @@ QRectF KStandardItemListWidget::selectionRect() const - { - const_cast(this)->triggerCacheRefreshing(); - -- const int padding = styleOption().padding; -- QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); -- QRectF result = adjustedIconRect | m_textRect; - if (m_highlightEntireRow) { -+ const int padding = styleOption().padding; -+ QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); -+ QRectF result = adjustedIconRect | m_textRect; - if (layoutDirection() == Qt::LeftToRight) { - result.setRight(leftPadding() + m_columnWidthSum); - } else { - result.setLeft(size().width() - m_columnWidthSum - rightPadding()); - } -+ return result; - } else { -- // Make sure values are always positive -- const int availableWidth = qAbs((size().width() - 2 * padding - result.width()) * 0.5); -- const int availableHeight = m_layout == CompactLayout ? 0 : qAbs((size().height() - 2 * padding - result.height()) * 0.5); -- result = result.adjusted(-availableWidth, -availableHeight, availableWidth, availableHeight); -+ return rect(); - } -- -- return result; - } - - QRectF KStandardItemListWidget::expansionToggleRect() const --- -GitLab - - -From b09399593c25ab44013cf98afa61813fa628af2a Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Wed, 23 Apr 2025 11:58:20 +0300 -Subject: [PATCH 28/69] Add constexpr for roundness - ---- - src/kitemviews/kitemlistwidget.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 8c2432967a..269c9b9955 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -607,7 +607,7 @@ void KItemListWidget::clearHoverCache() - void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState) - { - QStyleOptionViewItem viewItemOption; -- const int roundness = 5; -+ constexpr int roundness = 5; // From Breeze style. - initStyleOption(&viewItemOption); - viewItemOption.state = styleState; - viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; --- -GitLab - - -From 688624a1521d8a1d70c37af79920283fda3f8e5f Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Wed, 23 Apr 2025 12:03:58 +0300 -Subject: [PATCH 29/69] Add slight padding to compactlayout selectionRect - ---- - src/kitemviews/kstandarditemlistwidget.cpp | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 4b061c9bb1..8024d8cb54 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -541,8 +541,8 @@ QRectF KStandardItemListWidget::selectionRect() const - { - const_cast(this)->triggerCacheRefreshing(); - -+ const int padding = styleOption().padding; - if (m_highlightEntireRow) { -- const int padding = styleOption().padding; - QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); - QRectF result = adjustedIconRect | m_textRect; - if (layoutDirection() == Qt::LeftToRight) { -@@ -552,6 +552,9 @@ QRectF KStandardItemListWidget::selectionRect() const - } - return result; - } else { -+ if (m_layout == CompactLayout) { -+ return rect().adjusted(0, padding, 0, -padding); -+ } - return rect(); - } - } --- -GitLab - - -From 320e14cc150e90bbd2a9981ac5e48973755e6d02 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Wed, 23 Apr 2025 12:11:04 +0300 -Subject: [PATCH 30/69] Add rubberband start behavior back - ---- - src/kitemviews/kitemlistcontroller.cpp | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 6ef03dc609..fd3feb1a1b 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1720,7 +1720,18 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - } - - if (m_pressedIndex.has_value()) { -- bool createRubberBand = false; -+ // The hover highlight area of an item is being pressed. -+ const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect -+ const bool hitTargetIsRowEmptyRegion = !row->contains(row->mapFromItem(m_view, pos)); -+ // again, when this method returns false, a rubberBand selection is created as the event is not consumed; -+ // createRubberBand here tells us whether to return true or false. -+ bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); -+ -+ if (rightClick && hitTargetIsRowEmptyRegion) { -+ // We have a right click outside the icon and text rect but within the hover highlight area. -+ // We don't want items to get selected through this, so we return now. -+ return true; -+ } - - m_selectionManager->setCurrentItem(m_pressedIndex.value()); - --- -GitLab - - -From bf66254daea497b588cdaf2578f3990597188f8a Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Fri, 25 Apr 2025 11:06:02 +0300 -Subject: [PATCH 31/69] Remove hover pixmap - ---- - src/kitemviews/kstandarditemlistwidget.cpp | 18 +++--------------- - src/kitemviews/kstandarditemlistwidget.h | 1 - - 2 files changed, 3 insertions(+), 16 deletions(-) - -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 8024d8cb54..da7fd5f4c7 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -271,7 +271,6 @@ KStandardItemListWidget::KStandardItemListWidget(KItemListWidgetInformant *infor - , m_scaledPixmapSize() - , m_columnWidthSum() - , m_iconRect() -- , m_hoverPixmap() - , m_textRect() - , m_sortedVisibleRoles() - , m_expansionArea() -@@ -346,7 +345,7 @@ void KStandardItemListWidget::paint(QPainter *painter, const QStyleOptionGraphic - drawSiblingsInformation(painter); - } - -- auto pixmap = isHovered() ? m_hoverPixmap : m_pixmap; -+ auto pixmap = m_pixmap; - if (!m_overlays.isEmpty()) { - const qreal dpr = KItemViewsUtils::devicePixelRatio(this); - -@@ -388,7 +387,7 @@ void KStandardItemListWidget::paint(QPainter *painter, const QStyleOptionGraphic - { - QPainter p(&pixmap2); - p.setOpacity(hoverOpacity()); -- p.drawPixmap(0, 0, m_hoverPixmap); -+ p.drawPixmap(0, 0, m_pixmap); - } - - // Paint pixmap2 on pixmap1 using CompositionMode_Plus -@@ -1108,7 +1107,7 @@ void KStandardItemListWidget::updatePixmapCache() - } - - if (m_pixmap.isNull()) { -- m_hoverPixmap = QPixmap(); -+ m_pixmap = QPixmap(); - return; - } - -@@ -1166,17 +1165,6 @@ void KStandardItemListWidget::updatePixmapCache() - const QSizeF squareIconSize(widgetIconSize, widgetIconSize); - m_iconRect = QRectF(squareIconPos, squareIconSize); - } -- -- // Prepare the pixmap that is used when the item gets hovered -- if (isHovered()) { -- m_hoverPixmap = m_pixmap; -- if (isSelected()) { -- KIconEffect::toActive(m_hoverPixmap); -- } -- } else if (hoverOpacity() <= 0.0) { -- // No hover animation is ongoing. Clear m_hoverPixmap to save memory. -- m_hoverPixmap = QPixmap(); -- } - } - - void KStandardItemListWidget::updateTextsCache() -diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h -index 594d3e4928..3dbf442913 100644 ---- a/src/kitemviews/kstandarditemlistwidget.h -+++ b/src/kitemviews/kstandarditemlistwidget.h -@@ -280,7 +280,6 @@ private: - - qreal m_columnWidthSum; - QRectF m_iconRect; // Cache for KItemListWidget::iconRect() -- QPixmap m_hoverPixmap; // Cache for modified m_pixmap when hovering the item - - QRectF m_textRect; - --- -GitLab - - -From f41db3725ad36175721afd430de8ea1b63867803 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Fri, 25 Apr 2025 11:12:33 +0300 -Subject: [PATCH 32/69] Change the alpha values - ---- - src/kitemviews/kitemlistwidget.cpp | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 269c9b9955..b52661e6ee 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -623,11 +623,11 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg - accentColor.setAlphaF(0.0); - if (m_selected && m_hovered) { -- accentColor.setAlphaF(0.5); -+ accentColor.setAlphaF(0.25); - } else if (m_selected) { -- accentColor.setAlphaF(0.4); -+ accentColor.setAlphaF(0.2); - } else if (m_hovered) { -- accentColor.setAlphaF(0.3); -+ accentColor.setAlphaF(0.15); - } - - painter->fillPath(path, accentColor); -@@ -635,7 +635,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - // Focus decoration - if (current) { - accentColor = m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110); -- accentColor.setAlphaF(m_selected || m_hovered ? 1.0 : 0.5); -+ accentColor.setAlphaF(m_selected || m_hovered ? 0.8 : 0.5); - // Set the pen color lighter or darker depending on background color - QPen pen{accentColor, 1.5}; - pen.setCosmetic(true); --- -GitLab - - -From e299bf436628e58677f06513266811ac4f215f59 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Fri, 25 Apr 2025 12:53:42 +0300 -Subject: [PATCH 33/69] Set hovered effect to widgets when dragging - ---- - src/kitemviews/kitemlistcontroller.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index fd3feb1a1b..66e9ce4884 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -652,6 +652,10 @@ bool KItemListController::mouseMoveEvent(QGraphicsSceneMouseEvent *event, const - m_selectionManager->endAnchoredSelection(); - m_selectionManager->setCurrentItem(newCurrent.value()); - m_selectionManager->beginAnchoredSelection(newCurrent.value()); -+ // Set hovered effect when dragging. -+ for (const auto widget : m_view->visibleItemListWidgets()) { -+ widget->setHovered(widget->isCurrent()); -+ } - } - - if (m_view->scrollOrientation() == Qt::Vertical) { --- -GitLab - - -From 7a96007a21cc3a844a04992bd4edb764df561039 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Fri, 25 Apr 2025 13:08:52 +0300 -Subject: [PATCH 34/69] Move virtual iconrect back to public - ---- - src/kitemviews/kitemlistwidget.h | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index 4d857c00d7..0e07d7ab55 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -144,6 +144,11 @@ public: - */ - bool contains(const QPointF &point) const override; - -+ /** -+ * @return Rectangle for the area that shows the icon. -+ */ -+ virtual QRectF iconRect() const = 0; -+ - /** - * @return Rectangle for the area that contains the text-properties. - */ -@@ -240,11 +245,6 @@ private Q_SLOTS: - void slotHoverSequenceTimerTimeout(); - - private: -- /** -- * @return Rectangle for the area that shows the icon. -- */ -- virtual QRectF iconRect() const = 0; -- - void initializeSelectionToggle(); - void setHoverOpacity(qreal opacity); - void drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState); --- -GitLab - - -From 829d721b6ed44202ad91b4ee0ead1b578746d21f Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Fri, 25 Apr 2025 13:11:20 +0300 -Subject: [PATCH 35/69] Remove unecessary assignment - ---- - src/kitemviews/kstandarditemlistwidget.cpp | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index da7fd5f4c7..25dece0f62 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -1107,7 +1107,6 @@ void KStandardItemListWidget::updatePixmapCache() - } - - if (m_pixmap.isNull()) { -- m_pixmap = QPixmap(); - return; - } - --- -GitLab - - -From d8d4a220cb55e0de7364abd1ebfa4666dbbfa2a8 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 28 Apr 2025 15:56:09 +0300 -Subject: [PATCH 36/69] Better alpha values - ---- - src/kitemviews/kitemlistwidget.cpp | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index b52661e6ee..1b6969130f 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -623,11 +623,11 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg - accentColor.setAlphaF(0.0); - if (m_selected && m_hovered) { -- accentColor.setAlphaF(0.25); -+ accentColor.setAlphaF(0.32); - } else if (m_selected) { -- accentColor.setAlphaF(0.2); -+ accentColor.setAlphaF(0.30); - } else if (m_hovered) { -- accentColor.setAlphaF(0.15); -+ accentColor.setAlphaF(0.20); - } - - painter->fillPath(path, accentColor); -@@ -635,7 +635,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - // Focus decoration - if (current) { - accentColor = m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110); -- accentColor.setAlphaF(m_selected || m_hovered ? 0.8 : 0.5); -+ accentColor.setAlphaF(m_selected || m_hovered ? 0.8 : 0.6); - // Set the pen color lighter or darker depending on background color - QPen pen{accentColor, 1.5}; - pen.setCosmetic(true); --- -GitLab - - -From c116d53065c1cd71a1f5d924643824145e2e834e Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Tue, 29 Apr 2025 11:35:57 +0300 -Subject: [PATCH 37/69] Use text color as background color, modify alpha values - ---- - src/kitemviews/kitemlistwidget.cpp | 20 +++++++++++--------- - 1 file changed, 11 insertions(+), 9 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 1b6969130f..0af131c586 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -615,29 +615,31 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - viewItemOption.rect = selectionRect().toRect(); - QPainterPath path; - path.addRoundedRect(viewItemOption.rect, roundness, roundness); -- QColor accentColor{widget->palette().color(QPalette::Accent)}; -+ QColor backgroundColor{widget->palette().color(QPalette::Accent)}; - painter->setRenderHint(QPainter::Antialiasing); - bool current = m_current && styleState & QStyle::State_Active; - - // Background item, alpha values are from - // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg -- accentColor.setAlphaF(0.0); -+ backgroundColor.setAlphaF(0.0); - if (m_selected && m_hovered) { -- accentColor.setAlphaF(0.32); -+ backgroundColor.setAlphaF(0.40); - } else if (m_selected) { -- accentColor.setAlphaF(0.30); -+ backgroundColor.setAlphaF(0.32); - } else if (m_hovered) { -- accentColor.setAlphaF(0.20); -+ backgroundColor = widget->palette().color(QPalette::Text); -+ backgroundColor.setAlphaF(0.06); - } - -- painter->fillPath(path, accentColor); -+ painter->fillPath(path, backgroundColor); - - // Focus decoration - if (current) { -- accentColor = m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? accentColor.darker(110) : accentColor.lighter(110); -- accentColor.setAlphaF(m_selected || m_hovered ? 0.8 : 0.6); -+ QColor focusColor{widget->palette().color(QPalette::Accent)}; -+ focusColor = m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? focusColor.darker(110) : focusColor.lighter(110); -+ focusColor.setAlphaF(m_selected || m_hovered ? 0.8 : 0.6); - // Set the pen color lighter or darker depending on background color -- QPen pen{accentColor, 1.5}; -+ QPen pen{focusColor, 1.5}; - pen.setCosmetic(true); - painter->setPen(pen); - painter->drawPath(path); --- -GitLab - - -From 66ccf1e63224471fa80ea4d2d868c8dc31697498 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 5 May 2025 14:31:47 +0300 -Subject: [PATCH 38/69] Make sure backgrounds dont overlap at the outline - ---- - src/kitemviews/kitemlistwidget.cpp | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 0af131c586..c65c0b2d78 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -608,13 +608,14 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - { - QStyleOptionViewItem viewItemOption; - constexpr int roundness = 5; // From Breeze style. -+ constexpr qreal penWidth = 1.5; - initStyleOption(&viewItemOption); - viewItemOption.state = styleState; - viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; - viewItemOption.showDecorationSelected = true; - viewItemOption.rect = selectionRect().toRect(); - QPainterPath path; -- path.addRoundedRect(viewItemOption.rect, roundness, roundness); -+ path.addRoundedRect(selectionRect().adjusted(penWidth, penWidth, -penWidth, -penWidth), roundness, roundness); - QColor backgroundColor{widget->palette().color(QPalette::Accent)}; - painter->setRenderHint(QPainter::Antialiasing); - bool current = m_current && styleState & QStyle::State_Active; -@@ -639,7 +640,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - focusColor = m_styleOption.palette.color(QPalette::Base).lightnessF() > 0.5 ? focusColor.darker(110) : focusColor.lighter(110); - focusColor.setAlphaF(m_selected || m_hovered ? 0.8 : 0.6); - // Set the pen color lighter or darker depending on background color -- QPen pen{focusColor, 1.5}; -+ QPen pen{focusColor, penWidth}; - pen.setCosmetic(true); - painter->setPen(pen); - painter->drawPath(path); --- -GitLab - - -From 91f8b3123f62db459c970c46190cbf967e1050f9 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Fri, 23 May 2025 14:22:14 +0300 -Subject: [PATCH 39/69] Add horizontal margin according to icon size - ---- - src/views/dolphinitemlistview.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/views/dolphinitemlistview.cpp b/src/views/dolphinitemlistview.cpp -index d31dc11bae..7910080f82 100644 ---- a/src/views/dolphinitemlistview.cpp -+++ b/src/views/dolphinitemlistview.cpp -@@ -194,7 +194,7 @@ void DolphinItemListView::updateGridSize() - - itemHeight = padding * 3 + iconSize + option.fontMetrics.lineSpacing(); - -- horizontalMargin = 4; -+ horizontalMargin = qMax(8.0, ((iconSize + padding) / 4.0)) * qApp->devicePixelRatio(); - verticalMargin = 8; - maxTextLines = IconsModeSettings::maximumTextLines(); - break; --- -GitLab - - -From 4884701d6f4f4e86bf490c5f5df80289f8b40873 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 26 May 2025 16:21:21 +0300 -Subject: [PATCH 40/69] Use PM_SizeGripSize for horizontal and vertical margins - ---- - src/views/dolphinitemlistview.cpp | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/views/dolphinitemlistview.cpp b/src/views/dolphinitemlistview.cpp -index 7910080f82..8529f23a76 100644 ---- a/src/views/dolphinitemlistview.cpp -+++ b/src/views/dolphinitemlistview.cpp -@@ -194,8 +194,9 @@ void DolphinItemListView::updateGridSize() - - itemHeight = padding * 3 + iconSize + option.fontMetrics.lineSpacing(); - -- horizontalMargin = qMax(8.0, ((iconSize + padding) / 4.0)) * qApp->devicePixelRatio(); -- verticalMargin = 8; -+ const auto margin = style()->pixelMetric(QStyle::PM_SizeGripSize); -+ horizontalMargin = margin; -+ verticalMargin = margin; - maxTextLines = IconsModeSettings::maximumTextLines(); - break; - } --- -GitLab - - -From 452a00a4fe2e1552d9b1e48b4d9ab98b67007072 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 2 Jun 2025 12:34:02 +0300 -Subject: [PATCH 41/69] Refactor selectionRect to - selectionRectCore/extended/visual - ---- - src/kitemviews/kitemlistcontroller.cpp | 10 +++--- - src/kitemviews/kitemlistview.cpp | 4 +-- - src/kitemviews/kitemlistwidget.cpp | 7 ++-- - src/kitemviews/kitemlistwidget.h | 22 ++++++++---- - src/kitemviews/kstandarditemlistwidget.cpp | 41 ++++++++++++---------- - src/kitemviews/kstandarditemlistwidget.h | 5 +-- - 6 files changed, 51 insertions(+), 38 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 66e9ce4884..566f1d6a24 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -994,7 +994,7 @@ bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent *event, const - // we also unhover any old expansion toggle hovers, in case the mouse movement from expansion toggle to icon+text is too fast (i.e. newHoveredWidget is never null between the transition) - unhoverOldExpansionWidget(); - -- const bool isOverIconAndText = newHoveredWidget->selectionRect().contains(mappedPos); -+ const bool isOverIconAndText = newHoveredWidget->selectionRectCore().contains(mappedPos); - const bool hasMultipleSelection = m_selectionManager->selectedItems().count() > 1; - - if (hasMultipleSelection && !isOverIconAndText) { -@@ -1369,7 +1369,7 @@ void KItemListController::slotRubberBandChanged() - const QRectF widgetRect = m_view->itemRect(index); - if (widgetRect.intersects(rubberBandRect)) { - // Select the full row intersecting with the rubberband rectangle -- const QRectF selectionRect = widget->selectionRect().translated(widgetRect.topLeft()); -+ const QRectF selectionRect = widget->visualSelectionRect().translated(widgetRect.topLeft()); - if (selectionRect.intersects(rubberBandRect)) { - selectedItems.insert(index); - } -@@ -1470,7 +1470,7 @@ KItemListWidget *KItemListController::widgetForPos(const QPointF &pos) const - const auto widgets = m_view->visibleItemListWidgets(); - for (KItemListWidget *widget : widgets) { - const QPointF mappedPos = widget->mapFromItem(m_view, pos); -- if (widget->contains(mappedPos) || widget->selectionRect().contains(mappedPos)) { -+ if (widget->contains(mappedPos) || widget->visualSelectionRect().contains(mappedPos)) { - return widget; - } - } -@@ -1664,7 +1664,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - if (selectedItemsCount > 1 && m_pressedIndex.has_value()) { - const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); - const auto mappedPos = row->mapFromItem(m_view, pos); -- if (pressedItemAlreadySelected || row->selectionRect().contains(mappedPos)) { -+ if (pressedItemAlreadySelected || row->selectionRectCore().contains(mappedPos)) { - // we are indeed inside the text/icon rect, keep m_pressedIndex what it is - // and short-circuit for single-click activation (it will then propagate to onRelease and activate the item) - // or we just keep going for double-click activation -@@ -1758,7 +1758,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - // We rule out the latter, if the item is not clicked directly and was unselected previously. - const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); - const auto mappedPos = row->mapFromItem(m_view, pos); -- if (!row->selectionRect().contains(mappedPos) && !pressedItemAlreadySelected) { -+ if (!row->selectionRectCore().contains(mappedPos) && !pressedItemAlreadySelected) { - createRubberBand = true; - } else { - m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Toggle); -diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp -index 9e0a9e0e5c..4146dd8438 100644 ---- a/src/kitemviews/kitemlistview.cpp -+++ b/src/kitemviews/kitemlistview.cpp -@@ -425,7 +425,7 @@ std::optional KItemListView::itemAt(const QPointF &pos) const - - const KItemListWidget *widget = it.value(); - const QPointF mappedPos = widget->mapFromItem(this, pos); -- if (widget->contains(mappedPos) || widget->selectionRect().contains(mappedPos)) { -+ if (widget->contains(mappedPos) || widget->visualSelectionRect().contains(mappedPos)) { - return it.key(); - } - } -@@ -542,7 +542,7 @@ QRectF KItemListView::itemContextRect(int index) const - - const KItemListWidget *widget = m_visibleItems.value(index); - if (widget) { -- contextRect = widget->selectionRect(); -+ contextRect = widget->visualSelectionRect(); - contextRect.translate(itemRect(index).topLeft()); - } - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index c65c0b2d78..18bd4c48b3 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -407,7 +407,7 @@ bool KItemListWidget::contains(const QPointF &point) const - return false; - } - -- return iconRect().contains(point) || textRect().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); -+ return selectionRectCore().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); - } - - QRectF KItemListWidget::textFocusRect() const -@@ -613,9 +613,10 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - viewItemOption.state = styleState; - viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; - viewItemOption.showDecorationSelected = true; -- viewItemOption.rect = selectionRect().toRect(); -+ // TODO: check if we're extended or not -+ viewItemOption.rect = visualSelectionRect().toRect(); - QPainterPath path; -- path.addRoundedRect(selectionRect().adjusted(penWidth, penWidth, -penWidth, -penWidth), roundness, roundness); -+ path.addRoundedRect(visualSelectionRect().adjusted(penWidth, penWidth, -penWidth, -penWidth), roundness, roundness); - QColor backgroundColor{widget->palette().color(QPalette::Accent)}; - painter->setRenderHint(QPainter::Antialiasing); - bool current = m_current && styleState & QStyle::State_Active; -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index 0e07d7ab55..489081b604 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -144,11 +144,6 @@ public: - */ - bool contains(const QPointF &point) const override; - -- /** -- * @return Rectangle for the area that shows the icon. -- */ -- virtual QRectF iconRect() const = 0; -- - /** - * @return Rectangle for the area that contains the text-properties. - */ -@@ -164,9 +159,22 @@ public: - virtual QRectF textFocusRect() const; - - /** -- * @return Rectangle around which a selection box should be drawn if the item is selected. -+ * Used for drawing the visuals, and situations where we want the behavior of the -+ * selection to match the visuals. -+ * -+ * @return The rectangle around selection, depending on if it's full width or not. -+ */ -+ virtual QRectF visualSelectionRect() const = 0; -+ -+ /** -+ * @return Rectangle around icon and it's text: The core area of the item. -+ */ -+ virtual QRectF selectionRectCore() const = 0; -+ -+ /** -+ * @return Same as core, but extended to the full width of the details view. - */ -- virtual QRectF selectionRect() const = 0; -+ virtual QRectF selectionRectExtended() const = 0; - - /** - * @return Rectangle for the selection-toggle that is used to select or deselect an item. -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 25dece0f62..0661a19944 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -483,12 +483,6 @@ void KStandardItemListWidget::paint(QPainter *painter, const QStyleOptionGraphic - #endif - } - --QRectF KStandardItemListWidget::iconRect() const --{ -- const_cast(this)->triggerCacheRefreshing(); -- return m_iconRect; --} -- - QRectF KStandardItemListWidget::textRect() const - { - const_cast(this)->triggerCacheRefreshing(); -@@ -536,28 +530,37 @@ QRectF KStandardItemListWidget::textFocusRect() const - return m_textRect; - } - --QRectF KStandardItemListWidget::selectionRect() const -+QRectF KStandardItemListWidget::visualSelectionRect() const - { - const_cast(this)->triggerCacheRefreshing(); -- -- const int padding = styleOption().padding; - if (m_highlightEntireRow) { -- QRectF adjustedIconRect = iconRect().adjusted(-padding, -padding, padding, padding); -- QRectF result = adjustedIconRect | m_textRect; -- if (layoutDirection() == Qt::LeftToRight) { -- result.setRight(leftPadding() + m_columnWidthSum); -- } else { -- result.setLeft(size().width() - m_columnWidthSum - rightPadding()); -- } -- return result; -+ return selectionRectExtended(); - } else { - if (m_layout == CompactLayout) { -- return rect().adjusted(0, padding, 0, -padding); -+ const int padding = styleOption().padding; -+ return rect().adjusted(-padding, 0, padding, 0); - } - return rect(); - } - } - -+QRectF KStandardItemListWidget::selectionRectCore() const -+{ -+ QRectF result = m_iconRect | m_textRect; -+ return result; -+} -+ -+QRectF KStandardItemListWidget::selectionRectExtended() const -+{ -+ QRectF result = selectionRectCore(); -+ if (layoutDirection() == Qt::LeftToRight) { -+ result.setRight(leftPadding() + m_columnWidthSum); -+ } else { -+ result.setLeft(size().width() - m_columnWidthSum - rightPadding()); -+ } -+ return result; -+} -+ - QRectF KStandardItemListWidget::expansionToggleRect() const - { - const_cast(this)->triggerCacheRefreshing(); -@@ -577,7 +580,7 @@ QRectF KStandardItemListWidget::selectionToggleRect() const - } - - const int padding = styleOption().padding; -- const QRectF selectionRectMinusPadding = selectionRect().adjusted(padding, padding, -padding, -padding); -+ const QRectF selectionRectMinusPadding = selectionRectCore().adjusted(padding, padding, -padding, -padding); - QPointF pos = selectionRectMinusPadding.topLeft(); - if (QApplication::isRightToLeft()) { - pos.setX(selectionRectMinusPadding.right() - (pos.x() + toggleSize - selectionRectMinusPadding.left())); -diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h -index 3dbf442913..c8feed1c9f 100644 ---- a/src/kitemviews/kstandarditemlistwidget.h -+++ b/src/kitemviews/kstandarditemlistwidget.h -@@ -105,10 +105,11 @@ public: - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; - -- QRectF iconRect() const override; - QRectF textRect() const override; - QRectF textFocusRect() const override; -- QRectF selectionRect() const override; -+ QRectF visualSelectionRect() const override; -+ QRectF selectionRectCore() const override; -+ QRectF selectionRectExtended() const override; - QRectF expansionToggleRect() const override; - QRectF selectionToggleRect() const override; - QPixmap createDragPixmap(const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; --- -GitLab - - -From 6a9f1e168b201d6f6d2edf88d1eb040a208d48f5 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 2 Jun 2025 19:04:47 +0300 -Subject: [PATCH 42/69] fix emblem position - ---- - src/kitemviews/kstandarditemlistwidget.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 0661a19944..58fc9b0415 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -580,7 +580,7 @@ QRectF KStandardItemListWidget::selectionToggleRect() const - } - - const int padding = styleOption().padding; -- const QRectF selectionRectMinusPadding = selectionRectCore().adjusted(padding, padding, -padding, -padding); -+ const QRectF selectionRectMinusPadding = visualSelectionRect().adjusted(padding, padding, -padding, -padding); - QPointF pos = selectionRectMinusPadding.topLeft(); - if (QApplication::isRightToLeft()) { - pos.setX(selectionRectMinusPadding.right() - (pos.x() + toggleSize - selectionRectMinusPadding.left())); --- -GitLab - - -From f1098aa09599e59fceacc3c90e3daf5b4c177860 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 2 Jun 2025 19:05:01 +0300 -Subject: [PATCH 43/69] fix widget contains - ---- - src/kitemviews/kitemlistwidget.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 18bd4c48b3..ea6b31861e 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -407,7 +407,7 @@ bool KItemListWidget::contains(const QPointF &point) const - return false; - } - -- return selectionRectCore().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); -+ return visualSelectionRect().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); - } - - QRectF KItemListWidget::textFocusRect() const --- -GitLab - - -From 5e9a5e1a0801a4e9e8b3b72f741cb989e8637e18 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 2 Jun 2025 19:05:11 +0300 -Subject: [PATCH 44/69] remove unnecessary comparisons - ---- - src/kitemviews/kitemlistcontroller.cpp | 2 +- - src/kitemviews/kitemlistview.cpp | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 566f1d6a24..e398985e8a 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1470,7 +1470,7 @@ KItemListWidget *KItemListController::widgetForPos(const QPointF &pos) const - const auto widgets = m_view->visibleItemListWidgets(); - for (KItemListWidget *widget : widgets) { - const QPointF mappedPos = widget->mapFromItem(m_view, pos); -- if (widget->contains(mappedPos) || widget->visualSelectionRect().contains(mappedPos)) { -+ if (widget->contains(mappedPos)) { - return widget; - } - } -diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp -index 4146dd8438..90f2beebb9 100644 ---- a/src/kitemviews/kitemlistview.cpp -+++ b/src/kitemviews/kitemlistview.cpp -@@ -425,7 +425,7 @@ std::optional KItemListView::itemAt(const QPointF &pos) const - - const KItemListWidget *widget = it.value(); - const QPointF mappedPos = widget->mapFromItem(this, pos); -- if (widget->contains(mappedPos) || widget->visualSelectionRect().contains(mappedPos)) { -+ if (widget->contains(mappedPos)) { - return it.key(); - } - } --- -GitLab - - -From 57d43263cbee51f0f3cb9b0675ffd9fd347791dc Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 2 Jun 2025 19:42:30 +0300 -Subject: [PATCH 45/69] Draw different selection highlights depending on - settings - ---- - src/kitemviews/kstandarditemlistwidget.cpp | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 58fc9b0415..d507d7c0f1 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -533,8 +533,12 @@ QRectF KStandardItemListWidget::textFocusRect() const - QRectF KStandardItemListWidget::visualSelectionRect() const - { - const_cast(this)->triggerCacheRefreshing(); -- if (m_highlightEntireRow) { -- return selectionRectExtended(); -+ if (m_layout == DetailsLayout) { -+ if (m_highlightEntireRow) { -+ return rect(); -+ } else { -+ return selectionRectExtended(); -+ } - } else { - if (m_layout == CompactLayout) { - const int padding = styleOption().padding; --- -GitLab - - -From 337040cbe81adb6e443fc11045e9e2fd5f800a2b Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 2 Jun 2025 19:44:24 +0300 -Subject: [PATCH 46/69] Make sure we follow details mode selection settings - ---- - src/kitemviews/kitemlistcontroller.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index e398985e8a..45cba1a0db 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1726,7 +1726,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - if (m_pressedIndex.has_value()) { - // The hover highlight area of an item is being pressed. - const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect -- const bool hitTargetIsRowEmptyRegion = !row->contains(row->mapFromItem(m_view, pos)); -+ const bool hitTargetIsRowEmptyRegion = !row->selectionRectCore().contains(row->mapFromItem(m_view, pos)); - // again, when this method returns false, a rubberBand selection is created as the event is not consumed; - // createRubberBand here tells us whether to return true or false. - bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); --- -GitLab - - -From e212678b7c1972cd28c72d6515ad7e52242e3082 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Tue, 3 Jun 2025 11:46:56 +0300 -Subject: [PATCH 47/69] Fix drawing for details view - ---- - src/kitemviews/kitemlistcontroller.cpp | 2 +- - src/kitemviews/kstandarditemlistwidget.cpp | 8 ++++---- - 2 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 45cba1a0db..dfe3fb0eaf 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1726,7 +1726,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - if (m_pressedIndex.has_value()) { - // The hover highlight area of an item is being pressed. - const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect -- const bool hitTargetIsRowEmptyRegion = !row->selectionRectCore().contains(row->mapFromItem(m_view, pos)); -+ const bool hitTargetIsRowEmptyRegion = !row->visualSelectionRect().contains(row->mapFromItem(m_view, pos)); - // again, when this method returns false, a rubberBand selection is created as the event is not consumed; - // createRubberBand here tells us whether to return true or false. - bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index d507d7c0f1..a233472fc6 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -533,15 +533,15 @@ QRectF KStandardItemListWidget::textFocusRect() const - QRectF KStandardItemListWidget::visualSelectionRect() const - { - const_cast(this)->triggerCacheRefreshing(); -+ const int padding = styleOption().padding; - if (m_layout == DetailsLayout) { -+ auto rect = selectionRectCore(); - if (m_highlightEntireRow) { -- return rect(); -- } else { -- return selectionRectExtended(); -+ rect = selectionRectExtended(); - } -+ return rect.adjusted(-padding, 0, padding, 0); - } else { - if (m_layout == CompactLayout) { -- const int padding = styleOption().padding; - return rect().adjusted(-padding, 0, padding, 0); - } - return rect(); --- -GitLab - - -From 85e7e8eb933448b89138e0ce0b1d23f838711aa3 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Tue, 3 Jun 2025 12:00:17 +0300 -Subject: [PATCH 48/69] cleanup - ---- - src/kitemviews/kstandarditemlistwidget.cpp | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index a233472fc6..ed267bb25d 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -1295,7 +1295,6 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() - - const KItemListStyleOption &option = styleOption(); - const qreal padding = option.padding; -- // adjust the max width according to new outline style - const qreal maxWidth = size().width() - 2 * padding; - const qreal lineSpacing = m_customizedFontMetrics.lineSpacing(); - --- -GitLab - - -From a22c63ce2472213ca27fe57c4feafde3985a99d7 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Tue, 3 Jun 2025 17:51:51 +0300 -Subject: [PATCH 49/69] remove hover effect when dragging - ---- - src/kitemviews/kitemlistcontroller.cpp | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index dfe3fb0eaf..561917e80e 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -652,10 +652,6 @@ bool KItemListController::mouseMoveEvent(QGraphicsSceneMouseEvent *event, const - m_selectionManager->endAnchoredSelection(); - m_selectionManager->setCurrentItem(newCurrent.value()); - m_selectionManager->beginAnchoredSelection(newCurrent.value()); -- // Set hovered effect when dragging. -- for (const auto widget : m_view->visibleItemListWidgets()) { -- widget->setHovered(widget->isCurrent()); -- } - } - - if (m_view->scrollOrientation() == Qt::Vertical) { -@@ -1363,7 +1359,7 @@ void KItemListController::slotRubberBandChanged() - - // Select all visible items that intersect with the rubberband - const auto widgets = m_view->visibleItemListWidgets(); -- for (const KItemListWidget *widget : widgets) { -+ for (KItemListWidget *widget : widgets) { - const int index = widget->index(); - - const QRectF widgetRect = m_view->itemRect(index); --- -GitLab - - -From b4937aa0676d84beb41ee4d6750b0cee711a5682 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Wed, 4 Jun 2025 12:31:26 +0300 -Subject: [PATCH 50/69] set a click highlight color - ---- - src/kitemviews/kitemlistcontroller.cpp | 11 ++++++----- - src/kitemviews/kitemlistwidget.cpp | 14 ++++++++++++-- - src/kitemviews/kitemlistwidget.h | 3 +++ - 3 files changed, 21 insertions(+), 7 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 561917e80e..525e8107a4 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1640,6 +1640,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - // simplify the overall logic and possibilities both for users and devs. - const bool leftClick = buttons & Qt::LeftButton; - const bool rightClick = buttons & Qt::RightButton; -+ const bool singleClickActivation = m_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick); - - // The previous selection is cleared if either - // 1. The selection mode is SingleSelection, or -@@ -1664,7 +1665,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - // we are indeed inside the text/icon rect, keep m_pressedIndex what it is - // and short-circuit for single-click activation (it will then propagate to onRelease and activate the item) - // or we just keep going for double-click activation -- if (m_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) || m_singleClickActivationEnforced) { -+ if (singleClickActivation || m_singleClickActivationEnforced) { - if (!pressedItemAlreadySelected) { - // An unselected item was clicked directly while deselecting multiple other items so we mark it "current". - m_selectionManager->setCurrentItem(m_pressedIndex.value()); -@@ -1740,8 +1741,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - break; - - case SingleSelection: -- if (!leftClick || shiftOrControlPressed -- || (!m_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) && !m_singleClickActivationEnforced)) { -+ if (!leftClick || shiftOrControlPressed || (!singleClickActivation && !m_singleClickActivationEnforced)) { - m_selectionManager->setSelected(m_pressedIndex.value()); - } - break; -@@ -1764,9 +1764,10 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - } - } else if (!shiftPressed || !m_selectionManager->isAnchoredSelectionActive()) { - // Select the pressed item and start a new anchored selection -- if (!leftClick || shiftOrControlPressed -- || (!m_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) && !m_singleClickActivationEnforced)) { -+ if (!leftClick || shiftOrControlPressed || (!singleClickActivation && !m_singleClickActivationEnforced)) { - m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Select); -+ } else if (leftClick && (m_singleClickActivationEnforced || singleClickActivation)) { -+ row->setClickHighlight(true); - } - m_selectionManager->beginAnchoredSelection(m_pressedIndex.value()); - } -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index ea6b31861e..22d10d1481 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -37,6 +37,7 @@ KItemListWidget::KItemListWidget(KItemListWidgetInformant *informant, QGraphicsI - , m_expansionAreaHovered(false) - , m_alternateBackground(false) - , m_enabledSelectionToggle(false) -+ , m_clickHighlighted(false) - , m_data() - , m_visibleRoles() - , m_columnWidths() -@@ -281,6 +282,7 @@ void KItemListWidget::setHovered(bool hovered) - - m_hoverSequenceTimer.start(interval); - } else { -+ m_clickHighlighted = false; - setHoverOpacity(0.0); - - if (m_selectionToggle) { -@@ -604,6 +606,14 @@ void KItemListWidget::clearHoverCache() - m_hoverCache = nullptr; - } - -+void KItemListWidget::setClickHighlight(bool enabled) -+{ -+ if (m_clickHighlighted != enabled) { -+ m_clickHighlighted = enabled; -+ update(); -+ } -+} -+ - void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QStyle::State styleState) - { - QStyleOptionViewItem viewItemOption; -@@ -624,11 +634,11 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - // Background item, alpha values are from - // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg - backgroundColor.setAlphaF(0.0); -- if (m_selected && m_hovered) { -+ if ((m_selected && m_hovered) || m_clickHighlighted) { - backgroundColor.setAlphaF(0.40); - } else if (m_selected) { - backgroundColor.setAlphaF(0.32); -- } else if (m_hovered) { -+ } else if (m_hovered && !m_clickHighlighted) { - backgroundColor = widget->palette().color(QPalette::Text); - backgroundColor.setAlphaF(0.06); - } -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index 489081b604..415bc4b5c7 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -109,6 +109,8 @@ public: - void setEnabledSelectionToggle(bool enabled); - bool enabledSelectionToggle() const; - -+ void setClickHighlight(bool enabled); -+ - /** - * Sets the sibling information for the item and all of its parents. - * The sibling information of the upper most parent is represented by -@@ -266,6 +268,7 @@ private: - bool m_expansionAreaHovered; - bool m_alternateBackground; - bool m_enabledSelectionToggle; -+ bool m_clickHighlighted; - QHash m_data; - QList m_visibleRoles; - QHash m_columnWidths; --- -GitLab - - -From 9f5e8f169ac98a6d2b23bf850cb6a4470a51b30d Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 5 Jun 2025 12:17:14 +0300 -Subject: [PATCH 51/69] Add hitTargetRect - ---- - src/kitemviews/kitemlistcontroller.cpp | 2 +- - src/kitemviews/kitemlistwidget.h | 11 +++++++++-- - src/kitemviews/kstandarditemlistwidget.cpp | 9 +++++++++ - src/kitemviews/kstandarditemlistwidget.h | 1 + - 4 files changed, 20 insertions(+), 3 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 525e8107a4..d5c72a875b 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1723,7 +1723,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - if (m_pressedIndex.has_value()) { - // The hover highlight area of an item is being pressed. - const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect -- const bool hitTargetIsRowEmptyRegion = !row->visualSelectionRect().contains(row->mapFromItem(m_view, pos)); -+ const bool hitTargetIsRowEmptyRegion = !row->hitTargetRect().contains(row->mapFromItem(m_view, pos)); - // again, when this method returns false, a rubberBand selection is created as the event is not consumed; - // createRubberBand here tells us whether to return true or false. - bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index 415bc4b5c7..ca0dc704b8 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -139,8 +139,8 @@ public: - int iconSize() const; - - /** -- * @return True if \a point is inside KItemListWidget::hoverRect(), -- * KItemListWidget::textRect(), KItemListWidget::selectionToggleRect() -+ * @return True if \a point is inside KItemListWidget::visualSelectionRect(), -+ * KItemListWidget::selectionToggleRect() - * or KItemListWidget::expansionToggleRect(). - * @reimp - */ -@@ -178,6 +178,13 @@ public: - */ - virtual QRectF selectionRectExtended() const = 0; - -+ /** -+ * @return Rectangle where dragging the item is allowed to start. -+ * In compact and icon views, it returns KItemListWidget::visualSelectionRect(). -+ * In details view, it returns KItemListWidget::selectionRectCore(). -+ */ -+ virtual QRectF hitTargetRect() const = 0; -+ - /** - * @return Rectangle for the selection-toggle that is used to select or deselect an item. - * Per default an empty rectangle is returned which means that no selection-toggle -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index ed267bb25d..46374d577b 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -565,6 +565,15 @@ QRectF KStandardItemListWidget::selectionRectExtended() const - return result; - } - -+QRectF KStandardItemListWidget::hitTargetRect() const -+{ -+ if (m_layout == DetailsLayout) { -+ return selectionRectCore(); -+ } else { -+ return visualSelectionRect(); -+ } -+} -+ - QRectF KStandardItemListWidget::expansionToggleRect() const - { - const_cast(this)->triggerCacheRefreshing(); -diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h -index c8feed1c9f..b9deed7454 100644 ---- a/src/kitemviews/kstandarditemlistwidget.h -+++ b/src/kitemviews/kstandarditemlistwidget.h -@@ -110,6 +110,7 @@ public: - QRectF visualSelectionRect() const override; - QRectF selectionRectCore() const override; - QRectF selectionRectExtended() const override; -+ QRectF hitTargetRect() const override; - QRectF expansionToggleRect() const override; - QRectF selectionToggleRect() const override; - QPixmap createDragPixmap(const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; --- -GitLab - - -From a58b2bcb52433019b1682113ae0feeebf7113b14 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 9 Jun 2025 11:41:46 +0300 -Subject: [PATCH 52/69] Set click highlight work like toolbar click highlight - ---- - src/kitemviews/kitemlistcontroller.cpp | 8 +++++++- - src/kitemviews/kitemlistwidget.cpp | 20 ++++++++++++-------- - 2 files changed, 19 insertions(+), 9 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index d5c72a875b..5201134b9f 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -675,6 +675,10 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, con - return false; - } - -+ for (KItemListWidget *widget : m_view->visibleItemListWidgets()) { -+ widget->setClickHighlight(false); -+ } -+ - if (m_view->m_tapAndHoldIndicator->isActive()) { - m_view->m_tapAndHoldIndicator->setActive(false); - } -@@ -1029,6 +1033,7 @@ bool KItemListController::hoverLeaveEvent(QGraphicsSceneHoverEvent *event, const - - const auto widgets = m_view->visibleItemListWidgets(); - for (KItemListWidget *widget : widgets) { -+ widget->setClickHighlight(false); - if (widget->isHovered()) { - widget->setHovered(false); - Q_EMIT itemUnhovered(widget->index()); -@@ -1766,7 +1771,8 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - // Select the pressed item and start a new anchored selection - if (!leftClick || shiftOrControlPressed || (!singleClickActivation && !m_singleClickActivationEnforced)) { - m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Select); -- } else if (leftClick && (m_singleClickActivationEnforced || singleClickActivation)) { -+ } -+ if (leftClick) { - row->setClickHighlight(true); - } - m_selectionManager->beginAnchoredSelection(m_pressedIndex.value()); -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 22d10d1481..a14d28162a 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -282,7 +282,6 @@ void KItemListWidget::setHovered(bool hovered) - - m_hoverSequenceTimer.start(interval); - } else { -- m_clickHighlighted = false; - setHoverOpacity(0.0); - - if (m_selectionToggle) { -@@ -634,13 +633,18 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - // Background item, alpha values are from - // https://invent.kde.org/plasma/libplasma/-/blob/master/src/desktoptheme/breeze/widgets/viewitem.svg - backgroundColor.setAlphaF(0.0); -- if ((m_selected && m_hovered) || m_clickHighlighted) { -- backgroundColor.setAlphaF(0.40); -- } else if (m_selected) { -- backgroundColor.setAlphaF(0.32); -- } else if (m_hovered && !m_clickHighlighted) { -- backgroundColor = widget->palette().color(QPalette::Text); -- backgroundColor.setAlphaF(0.06); -+ -+ if (m_clickHighlighted) { -+ backgroundColor.setAlphaF(0.5); -+ } else { -+ if (m_selected && m_hovered) { -+ backgroundColor.setAlphaF(0.40); -+ } else if (m_selected) { -+ backgroundColor.setAlphaF(0.32); -+ } else if (m_hovered) { -+ backgroundColor = widget->palette().color(QPalette::Text); -+ backgroundColor.setAlphaF(0.06); -+ } - } - - painter->fillPath(path, backgroundColor); --- -GitLab - - -From cf5f5e8d2735bef7df60926ccdfc1fae1473de97 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Wed, 11 Jun 2025 13:16:01 +0300 -Subject: [PATCH 53/69] make button click highlight stronger, fix highlight not - clearing - ---- - src/kitemviews/kitemlistcontroller.cpp | 7 ++++--- - src/kitemviews/kitemlistwidget.cpp | 3 ++- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 5201134b9f..5222b9c957 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1733,6 +1733,10 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - // createRubberBand here tells us whether to return true or false. - bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); - -+ if (leftClick) { -+ row->setClickHighlight(true); -+ } -+ - if (rightClick && hitTargetIsRowEmptyRegion) { - // We have a right click outside the icon and text rect but within the hover highlight area. - // We don't want items to get selected through this, so we return now. -@@ -1772,9 +1776,6 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - if (!leftClick || shiftOrControlPressed || (!singleClickActivation && !m_singleClickActivationEnforced)) { - m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Select); - } -- if (leftClick) { -- row->setClickHighlight(true); -- } - m_selectionManager->beginAnchoredSelection(m_pressedIndex.value()); - } - break; -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index a14d28162a..eb24a19dc8 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -609,6 +609,7 @@ void KItemListWidget::setClickHighlight(bool enabled) - { - if (m_clickHighlighted != enabled) { - m_clickHighlighted = enabled; -+ clearHoverCache(); - update(); - } - } -@@ -635,7 +636,7 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - backgroundColor.setAlphaF(0.0); - - if (m_clickHighlighted) { -- backgroundColor.setAlphaF(0.5); -+ backgroundColor.setAlphaF(1.0); - } else { - if (m_selected && m_hovered) { - backgroundColor.setAlphaF(0.40); --- -GitLab - - -From 4398a90bfcab35834d0fd84c4e449456509089fb Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Wed, 11 Jun 2025 13:44:04 +0300 -Subject: [PATCH 54/69] Make sure text is readable when clickHighlighted - ---- - src/kitemviews/kitemlistwidget.cpp | 5 +++++ - src/kitemviews/kitemlistwidget.h | 1 + - src/kitemviews/kstandarditemlistwidget.cpp | 6 +++++- - 3 files changed, 11 insertions(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index eb24a19dc8..0f15aa883b 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -605,6 +605,11 @@ void KItemListWidget::clearHoverCache() - m_hoverCache = nullptr; - } - -+bool KItemListWidget::isClickHighlighted() const -+{ -+ return m_clickHighlighted; -+} -+ - void KItemListWidget::setClickHighlight(bool enabled) - { - if (m_clickHighlighted != enabled) { -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index ca0dc704b8..40b630cc4f 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -109,6 +109,7 @@ public: - void setEnabledSelectionToggle(bool enabled); - bool enabledSelectionToggle() const; - -+ bool isClickHighlighted() const; - void setClickHighlight(bool enabled); - - /** -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 46374d577b..1a2976bfeb 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -712,7 +712,11 @@ QFont KStandardItemListWidget::customizedFont(const QFont &baseFont) const - - QPalette::ColorRole KStandardItemListWidget::normalTextColorRole() const - { -- return QPalette::Text; -+ if (isClickHighlighted()) { -+ return QPalette::HighlightedText; -+ } else { -+ return QPalette::Text; -+ } - } - - void KStandardItemListWidget::setTextColor(const QColor &color) --- -GitLab - - -From 71bcec57388d613955148b9d590c85ab977f978e Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 12 Jun 2025 18:03:53 +0300 -Subject: [PATCH 55/69] widgetForDropPos uses hitTargetRect instead of contains - ---- - src/kitemviews/kitemlistcontroller.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 5222b9c957..cb97f484d3 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1490,7 +1490,7 @@ KItemListWidget *KItemListController::widgetForDropPos(const QPointF &pos) const - const auto widgets = m_view->visibleItemListWidgets(); - for (KItemListWidget *widget : widgets) { - const QPointF mappedPos = widget->mapFromItem(m_view, pos); -- if (widget->contains(mappedPos)) { -+ if (widget->hitTargetRect().contains(mappedPos)) { - return widget; - } - } --- -GitLab - - -From 23d522fa8a4726f8b668419fa31fbac04e6e6a84 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 12 Jun 2025 18:03:53 +0300 -Subject: [PATCH 56/69] change hitTargetRect comment - ---- - src/kitemviews/kitemlistwidget.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index 40b630cc4f..6e73bb72d5 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -180,7 +180,7 @@ public: - virtual QRectF selectionRectExtended() const = 0; - - /** -- * @return Rectangle where dragging the item is allowed to start. -+ * @return Returns rectangle where item is considered "hit" during actions, such as drag and drop. - * In compact and icon views, it returns KItemListWidget::visualSelectionRect(). - * In details view, it returns KItemListWidget::selectionRectCore(). - */ --- -GitLab - - -From 105d70b4d6d5ae02305619cfd4fdb37b6048ddbd Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 12 Jun 2025 18:18:13 +0300 -Subject: [PATCH 57/69] Remove selectionRectExtended - ---- - src/kitemviews/kitemlistwidget.h | 5 ----- - src/kitemviews/kstandarditemlistwidget.cpp | 17 +++++------------ - src/kitemviews/kstandarditemlistwidget.h | 1 - - 3 files changed, 5 insertions(+), 18 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index 6e73bb72d5..2287683570 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -174,11 +174,6 @@ public: - */ - virtual QRectF selectionRectCore() const = 0; - -- /** -- * @return Same as core, but extended to the full width of the details view. -- */ -- virtual QRectF selectionRectExtended() const = 0; -- - /** - * @return Returns rectangle where item is considered "hit" during actions, such as drag and drop. - * In compact and icon views, it returns KItemListWidget::visualSelectionRect(). -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 1a2976bfeb..3530677e83 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -537,7 +537,11 @@ QRectF KStandardItemListWidget::visualSelectionRect() const - if (m_layout == DetailsLayout) { - auto rect = selectionRectCore(); - if (m_highlightEntireRow) { -- rect = selectionRectExtended(); -+ if (layoutDirection() == Qt::LeftToRight) { -+ rect.setRight(leftPadding() + m_columnWidthSum); -+ } else { -+ rect.setLeft(size().width() - m_columnWidthSum - rightPadding()); -+ } - } - return rect.adjusted(-padding, 0, padding, 0); - } else { -@@ -554,17 +558,6 @@ QRectF KStandardItemListWidget::selectionRectCore() const - return result; - } - --QRectF KStandardItemListWidget::selectionRectExtended() const --{ -- QRectF result = selectionRectCore(); -- if (layoutDirection() == Qt::LeftToRight) { -- result.setRight(leftPadding() + m_columnWidthSum); -- } else { -- result.setLeft(size().width() - m_columnWidthSum - rightPadding()); -- } -- return result; --} -- - QRectF KStandardItemListWidget::hitTargetRect() const - { - if (m_layout == DetailsLayout) { -diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h -index b9deed7454..a85e4ee11c 100644 ---- a/src/kitemviews/kstandarditemlistwidget.h -+++ b/src/kitemviews/kstandarditemlistwidget.h -@@ -109,7 +109,6 @@ public: - QRectF textFocusRect() const override; - QRectF visualSelectionRect() const override; - QRectF selectionRectCore() const override; -- QRectF selectionRectExtended() const override; - QRectF hitTargetRect() const override; - QRectF expansionToggleRect() const override; - QRectF selectionToggleRect() const override; --- -GitLab - - -From 18aec3429bc384e3fe8e80a95fb64e513d8d1442 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 12 Jun 2025 18:21:01 +0300 -Subject: [PATCH 58/69] Rename visualSelectionRect to selectionRectFull - ---- - src/kitemviews/kitemlistcontroller.cpp | 2 +- - src/kitemviews/kitemlistview.cpp | 2 +- - src/kitemviews/kitemlistwidget.cpp | 6 +++--- - src/kitemviews/kitemlistwidget.h | 6 +++--- - src/kitemviews/kstandarditemlistwidget.cpp | 6 +++--- - src/kitemviews/kstandarditemlistwidget.h | 2 +- - 6 files changed, 12 insertions(+), 12 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index cb97f484d3..66b5cb9696 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1370,7 +1370,7 @@ void KItemListController::slotRubberBandChanged() - const QRectF widgetRect = m_view->itemRect(index); - if (widgetRect.intersects(rubberBandRect)) { - // Select the full row intersecting with the rubberband rectangle -- const QRectF selectionRect = widget->visualSelectionRect().translated(widgetRect.topLeft()); -+ const QRectF selectionRect = widget->selectionRectFull().translated(widgetRect.topLeft()); - if (selectionRect.intersects(rubberBandRect)) { - selectedItems.insert(index); - } -diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp -index 90f2beebb9..5394e7341e 100644 ---- a/src/kitemviews/kitemlistview.cpp -+++ b/src/kitemviews/kitemlistview.cpp -@@ -542,7 +542,7 @@ QRectF KItemListView::itemContextRect(int index) const - - const KItemListWidget *widget = m_visibleItems.value(index); - if (widget) { -- contextRect = widget->visualSelectionRect(); -+ contextRect = widget->selectionRectFull(); - contextRect.translate(itemRect(index).topLeft()); - } - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 0f15aa883b..2abf9fe067 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -408,7 +408,7 @@ bool KItemListWidget::contains(const QPointF &point) const - return false; - } - -- return visualSelectionRect().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); -+ return selectionRectFull().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); - } - - QRectF KItemListWidget::textFocusRect() const -@@ -629,9 +629,9 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; - viewItemOption.showDecorationSelected = true; - // TODO: check if we're extended or not -- viewItemOption.rect = visualSelectionRect().toRect(); -+ viewItemOption.rect = selectionRectFull().toRect(); - QPainterPath path; -- path.addRoundedRect(visualSelectionRect().adjusted(penWidth, penWidth, -penWidth, -penWidth), roundness, roundness); -+ path.addRoundedRect(selectionRectFull().adjusted(penWidth, penWidth, -penWidth, -penWidth), roundness, roundness); - QColor backgroundColor{widget->palette().color(QPalette::Accent)}; - painter->setRenderHint(QPainter::Antialiasing); - bool current = m_current && styleState & QStyle::State_Active; -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index 2287683570..f277e18a73 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -140,7 +140,7 @@ public: - int iconSize() const; - - /** -- * @return True if \a point is inside KItemListWidget::visualSelectionRect(), -+ * @return True if \a point is inside KItemListWidget::selectionRectFull(), - * KItemListWidget::selectionToggleRect() - * or KItemListWidget::expansionToggleRect(). - * @reimp -@@ -167,7 +167,7 @@ public: - * - * @return The rectangle around selection, depending on if it's full width or not. - */ -- virtual QRectF visualSelectionRect() const = 0; -+ virtual QRectF selectionRectFull() const = 0; - - /** - * @return Rectangle around icon and it's text: The core area of the item. -@@ -176,7 +176,7 @@ public: - - /** - * @return Returns rectangle where item is considered "hit" during actions, such as drag and drop. -- * In compact and icon views, it returns KItemListWidget::visualSelectionRect(). -+ * In compact and icon views, it returns KItemListWidget::selectionRectFull(). - * In details view, it returns KItemListWidget::selectionRectCore(). - */ - virtual QRectF hitTargetRect() const = 0; -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 3530677e83..ba3465c041 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -530,7 +530,7 @@ QRectF KStandardItemListWidget::textFocusRect() const - return m_textRect; - } - --QRectF KStandardItemListWidget::visualSelectionRect() const -+QRectF KStandardItemListWidget::selectionRectFull() const - { - const_cast(this)->triggerCacheRefreshing(); - const int padding = styleOption().padding; -@@ -563,7 +563,7 @@ QRectF KStandardItemListWidget::hitTargetRect() const - if (m_layout == DetailsLayout) { - return selectionRectCore(); - } else { -- return visualSelectionRect(); -+ return selectionRectFull(); - } - } - -@@ -586,7 +586,7 @@ QRectF KStandardItemListWidget::selectionToggleRect() const - } - - const int padding = styleOption().padding; -- const QRectF selectionRectMinusPadding = visualSelectionRect().adjusted(padding, padding, -padding, -padding); -+ const QRectF selectionRectMinusPadding = selectionRectFull().adjusted(padding, padding, -padding, -padding); - QPointF pos = selectionRectMinusPadding.topLeft(); - if (QApplication::isRightToLeft()) { - pos.setX(selectionRectMinusPadding.right() - (pos.x() + toggleSize - selectionRectMinusPadding.left())); -diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h -index a85e4ee11c..f2b7a49438 100644 ---- a/src/kitemviews/kstandarditemlistwidget.h -+++ b/src/kitemviews/kstandarditemlistwidget.h -@@ -107,7 +107,7 @@ public: - - QRectF textRect() const override; - QRectF textFocusRect() const override; -- QRectF visualSelectionRect() const override; -+ QRectF selectionRectFull() const override; - QRectF selectionRectCore() const override; - QRectF hitTargetRect() const override; - QRectF expansionToggleRect() const override; --- -GitLab - - -From c1aba1674385f07858c51fc9d16376f4fab10066 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 12 Jun 2025 18:24:44 +0300 -Subject: [PATCH 59/69] rename clickHighlight to isPressed, add comment, move - items - ---- - src/kitemviews/kitemlistcontroller.cpp | 6 +++--- - src/kitemviews/kitemlistwidget.cpp | 4 ++-- - src/kitemviews/kitemlistwidget.h | 7 ++++--- - src/kitemviews/kstandarditemlistwidget.cpp | 2 +- - 4 files changed, 10 insertions(+), 9 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 66b5cb9696..1729a65cba 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -676,7 +676,7 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, con - } - - for (KItemListWidget *widget : m_view->visibleItemListWidgets()) { -- widget->setClickHighlight(false); -+ widget->setPressed(false); - } - - if (m_view->m_tapAndHoldIndicator->isActive()) { -@@ -1033,7 +1033,7 @@ bool KItemListController::hoverLeaveEvent(QGraphicsSceneHoverEvent *event, const - - const auto widgets = m_view->visibleItemListWidgets(); - for (KItemListWidget *widget : widgets) { -- widget->setClickHighlight(false); -+ widget->setPressed(false); - if (widget->isHovered()) { - widget->setHovered(false); - Q_EMIT itemUnhovered(widget->index()); -@@ -1734,7 +1734,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); - - if (leftClick) { -- row->setClickHighlight(true); -+ row->setPressed(true); - } - - if (rightClick && hitTargetIsRowEmptyRegion) { -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 2abf9fe067..a47f98ae18 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -605,12 +605,12 @@ void KItemListWidget::clearHoverCache() - m_hoverCache = nullptr; - } - --bool KItemListWidget::isClickHighlighted() const -+bool KItemListWidget::isPressed() const - { - return m_clickHighlighted; - } - --void KItemListWidget::setClickHighlight(bool enabled) -+void KItemListWidget::setPressed(bool enabled) - { - if (m_clickHighlighted != enabled) { - m_clickHighlighted = enabled; -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index f277e18a73..7e6b8f9c93 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -98,6 +98,10 @@ public: - void setHovered(bool hovered); - bool isHovered() const; - -+ /** Sets a purely visual pressed highlight effect. */ -+ void setPressed(bool enabled); -+ bool isPressed() const; -+ - void setExpansionAreaHovered(bool hover); - bool expansionAreaHovered() const; - -@@ -109,9 +113,6 @@ public: - void setEnabledSelectionToggle(bool enabled); - bool enabledSelectionToggle() const; - -- bool isClickHighlighted() const; -- void setClickHighlight(bool enabled); -- - /** - * Sets the sibling information for the item and all of its parents. - * The sibling information of the upper most parent is represented by -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index ba3465c041..3511666704 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -705,7 +705,7 @@ QFont KStandardItemListWidget::customizedFont(const QFont &baseFont) const - - QPalette::ColorRole KStandardItemListWidget::normalTextColorRole() const - { -- if (isClickHighlighted()) { -+ if (isPressed()) { - return QPalette::HighlightedText; - } else { - return QPalette::Text; --- -GitLab - - -From 4af2e8ce7dfe422bfc79073e57aa0774b0bf62c0 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Thu, 12 Jun 2025 18:25:54 +0300 -Subject: [PATCH 60/69] remove todo - ---- - src/kitemviews/kitemlistwidget.cpp | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index a47f98ae18..3eb246e940 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -628,7 +628,6 @@ void KItemListWidget::drawItemStyleOption(QPainter *painter, QWidget *widget, QS - viewItemOption.state = styleState; - viewItemOption.viewItemPosition = QStyleOptionViewItem::OnlyOne; - viewItemOption.showDecorationSelected = true; -- // TODO: check if we're extended or not - viewItemOption.rect = selectionRectFull().toRect(); - QPainterPath path; - path.addRoundedRect(selectionRectFull().adjusted(penWidth, penWidth, -penWidth, -penWidth), roundness, roundness); --- -GitLab - - -From 6e4705e98dc1f00cbcd6a51d3797a39a8e7bd1c4 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Fri, 13 Jun 2025 11:34:13 +0300 -Subject: [PATCH 61/69] Remove hitTargetRect - ---- - src/kitemviews/kitemlistcontroller.cpp | 7 +++++-- - src/kitemviews/kitemlistwidget.h | 7 ------- - src/kitemviews/kstandarditemlistwidget.cpp | 9 --------- - src/kitemviews/kstandarditemlistwidget.h | 1 - - 4 files changed, 5 insertions(+), 19 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 1729a65cba..1a11d4e882 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1490,7 +1490,7 @@ KItemListWidget *KItemListController::widgetForDropPos(const QPointF &pos) const - const auto widgets = m_view->visibleItemListWidgets(); - for (KItemListWidget *widget : widgets) { - const QPointF mappedPos = widget->mapFromItem(m_view, pos); -- if (widget->hitTargetRect().contains(mappedPos)) { -+ if (widget->selectionRectCore().contains(mappedPos)) { - return widget; - } - } -@@ -1728,7 +1728,10 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - if (m_pressedIndex.has_value()) { - // The hover highlight area of an item is being pressed. - const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect -- const bool hitTargetIsRowEmptyRegion = !row->hitTargetRect().contains(row->mapFromItem(m_view, pos)); -+ -+ // When full row is highlighted, we want to be able to start dragging from anywhere except the core of the item. -+ const auto hitRect = m_view->highlightEntireRow() ? row->selectionRectCore() : row->selectionRectFull(); -+ const bool hitTargetIsRowEmptyRegion = !hitRect.contains(row->mapFromItem(m_view, pos)); - // again, when this method returns false, a rubberBand selection is created as the event is not consumed; - // createRubberBand here tells us whether to return true or false. - bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index 7e6b8f9c93..d75a4db549 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -175,13 +175,6 @@ public: - */ - virtual QRectF selectionRectCore() const = 0; - -- /** -- * @return Returns rectangle where item is considered "hit" during actions, such as drag and drop. -- * In compact and icon views, it returns KItemListWidget::selectionRectFull(). -- * In details view, it returns KItemListWidget::selectionRectCore(). -- */ -- virtual QRectF hitTargetRect() const = 0; -- - /** - * @return Rectangle for the selection-toggle that is used to select or deselect an item. - * Per default an empty rectangle is returned which means that no selection-toggle -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 3511666704..0a2cfb5968 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -558,15 +558,6 @@ QRectF KStandardItemListWidget::selectionRectCore() const - return result; - } - --QRectF KStandardItemListWidget::hitTargetRect() const --{ -- if (m_layout == DetailsLayout) { -- return selectionRectCore(); -- } else { -- return selectionRectFull(); -- } --} -- - QRectF KStandardItemListWidget::expansionToggleRect() const - { - const_cast(this)->triggerCacheRefreshing(); -diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h -index f2b7a49438..cabe3a8c96 100644 ---- a/src/kitemviews/kstandarditemlistwidget.h -+++ b/src/kitemviews/kstandarditemlistwidget.h -@@ -109,7 +109,6 @@ public: - QRectF textFocusRect() const override; - QRectF selectionRectFull() const override; - QRectF selectionRectCore() const override; -- QRectF hitTargetRect() const override; - QRectF expansionToggleRect() const override; - QRectF selectionToggleRect() const override; - QPixmap createDragPixmap(const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; --- -GitLab - - -From 7e05aa4ccc0121e415ed29dce09cbd116cd186f5 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Fri, 13 Jun 2025 19:17:19 +0300 -Subject: [PATCH 62/69] Modify selectionRectCore to return fullRect unless - dragging in details view - ---- - src/kitemviews/kitemlistcontroller.cpp | 4 +--- - src/kitemviews/kstandarditemlistwidget.cpp | 10 +++++++--- - 2 files changed, 8 insertions(+), 6 deletions(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 1a11d4e882..2afcf212e6 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1729,9 +1729,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - // The hover highlight area of an item is being pressed. - const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect - -- // When full row is highlighted, we want to be able to start dragging from anywhere except the core of the item. -- const auto hitRect = m_view->highlightEntireRow() ? row->selectionRectCore() : row->selectionRectFull(); -- const bool hitTargetIsRowEmptyRegion = !hitRect.contains(row->mapFromItem(m_view, pos)); -+ const bool hitTargetIsRowEmptyRegion = !row->selectionRectCore().contains(row->mapFromItem(m_view, pos)); - // again, when this method returns false, a rubberBand selection is created as the event is not consumed; - // createRubberBand here tells us whether to return true or false. - bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty()); -diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp -index 0a2cfb5968..d078b06573 100644 ---- a/src/kitemviews/kstandarditemlistwidget.cpp -+++ b/src/kitemviews/kstandarditemlistwidget.cpp -@@ -535,7 +535,7 @@ QRectF KStandardItemListWidget::selectionRectFull() const - const_cast(this)->triggerCacheRefreshing(); - const int padding = styleOption().padding; - if (m_layout == DetailsLayout) { -- auto rect = selectionRectCore(); -+ auto rect = m_iconRect | m_textRect; - if (m_highlightEntireRow) { - if (layoutDirection() == Qt::LeftToRight) { - rect.setRight(leftPadding() + m_columnWidthSum); -@@ -554,8 +554,12 @@ QRectF KStandardItemListWidget::selectionRectFull() const - - QRectF KStandardItemListWidget::selectionRectCore() const - { -- QRectF result = m_iconRect | m_textRect; -- return result; -+ // Allow dragging from selection area in details view. -+ if (m_layout == DetailsLayout && highlightEntireRow() && !isSelected()) { -+ QRectF result = m_iconRect | m_textRect; -+ return result; -+ } -+ return selectionRectFull(); - } - - QRectF KStandardItemListWidget::expansionToggleRect() const --- -GitLab - - -From bf8220e6bac6d4f0148c465af012ff98f16ff73e Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 16 Jun 2025 11:07:05 +0300 -Subject: [PATCH 63/69] Remove unneeded check - ---- - src/kitemviews/kitemlistcontroller.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 2afcf212e6..10edf64a66 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1764,7 +1764,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - // We rule out the latter, if the item is not clicked directly and was unselected previously. - const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); - const auto mappedPos = row->mapFromItem(m_view, pos); -- if (!row->selectionRectCore().contains(mappedPos) && !pressedItemAlreadySelected) { -+ if (!row->selectionRectCore().contains(mappedPos)) { - createRubberBand = true; - } else { - m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Toggle); --- -GitLab - - -From bc5a187f34f1566a7b5f7dacaac851519dfe17c1 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 16 Jun 2025 11:07:48 +0300 -Subject: [PATCH 64/69] add const back - ---- - src/kitemviews/kitemlistcontroller.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 10edf64a66..96f34f1a11 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1364,7 +1364,7 @@ void KItemListController::slotRubberBandChanged() - - // Select all visible items that intersect with the rubberband - const auto widgets = m_view->visibleItemListWidgets(); -- for (KItemListWidget *widget : widgets) { -+ for (const KItemListWidget *widget : widgets) { - const int index = widget->index(); - - const QRectF widgetRect = m_view->itemRect(index); --- -GitLab - - -From 73977c43f0a6c6d82f5fc8992132138402be8f32 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 16 Jun 2025 11:09:09 +0300 -Subject: [PATCH 65/69] remove selectionToggleRect check - ---- - src/kitemviews/kitemlistwidget.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp -index 3eb246e940..c06e46339f 100644 ---- a/src/kitemviews/kitemlistwidget.cpp -+++ b/src/kitemviews/kitemlistwidget.cpp -@@ -408,7 +408,7 @@ bool KItemListWidget::contains(const QPointF &point) const - return false; - } - -- return selectionRectFull().contains(point) || expansionToggleRect().contains(point) || selectionToggleRect().contains(point); -+ return selectionRectFull().contains(point) || expansionToggleRect().contains(point); - } - - QRectF KItemListWidget::textFocusRect() const --- -GitLab - - -From 0f477b912347b5661add69dc5a8cf9ee44ecdbfb Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 16 Jun 2025 11:11:24 +0300 -Subject: [PATCH 66/69] remove presseditemalreadyselected check - ---- - src/kitemviews/kitemlistcontroller.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 96f34f1a11..5f668ce3ab 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1666,7 +1666,7 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - if (selectedItemsCount > 1 && m_pressedIndex.has_value()) { - const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); - const auto mappedPos = row->mapFromItem(m_view, pos); -- if (pressedItemAlreadySelected || row->selectionRectCore().contains(mappedPos)) { -+ if (row->selectionRectCore().contains(mappedPos)) { - // we are indeed inside the text/icon rect, keep m_pressedIndex what it is - // and short-circuit for single-click activation (it will then propagate to onRelease and activate the item) - // or we just keep going for double-click activation --- -GitLab - - -From 60a92ae27e28c162fd3f4a926b4b00b818134151 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 16 Jun 2025 11:16:09 +0300 -Subject: [PATCH 67/69] add setPressed with more than one selection - ---- - src/kitemviews/kitemlistcontroller.cpp | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp -index 5f668ce3ab..fdde48abcd 100644 ---- a/src/kitemviews/kitemlistcontroller.cpp -+++ b/src/kitemviews/kitemlistcontroller.cpp -@@ -1681,6 +1681,9 @@ bool KItemListController::onPress(const QPointF &pos, const Qt::KeyboardModifier - m_selectionManager->setSelected(m_pressedIndex.value(), 1, KItemListSelectionManager::Toggle); - } - } -+ if (leftClick) { -+ row->setPressed(true); -+ } - return true; // event handled, don't create rubber band - } - } else { --- -GitLab - - -From b3e1a4918e7165c3a19f5a9188e45ec6371fd9fa Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 16 Jun 2025 11:19:48 +0300 -Subject: [PATCH 68/69] set itemContextRect to selectionRectCore - ---- - src/kitemviews/kitemlistview.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp -index 5394e7341e..3ed4df3e7b 100644 ---- a/src/kitemviews/kitemlistview.cpp -+++ b/src/kitemviews/kitemlistview.cpp -@@ -542,7 +542,7 @@ QRectF KItemListView::itemContextRect(int index) const - - const KItemListWidget *widget = m_visibleItems.value(index); - if (widget) { -- contextRect = widget->selectionRectFull(); -+ contextRect = widget->selectionRectCore(); - contextRect.translate(itemRect(index).topLeft()); - } - --- -GitLab - - -From 65b8c32380f9a7f8a8bf0296adfea9c976682b57 Mon Sep 17 00:00:00 2001 -From: Akseli Lahtinen -Date: Mon, 16 Jun 2025 11:20:34 +0300 -Subject: [PATCH 69/69] fix doc - ---- - src/kitemviews/kitemlistwidget.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h -index d75a4db549..b87a3b34e6 100644 ---- a/src/kitemviews/kitemlistwidget.h -+++ b/src/kitemviews/kitemlistwidget.h -@@ -166,12 +166,12 @@ public: - * Used for drawing the visuals, and situations where we want the behavior of the - * selection to match the visuals. - * -- * @return The rectangle around selection, depending on if it's full width or not. -+ * @return The rectangle around selection. - */ - virtual QRectF selectionRectFull() const = 0; - - /** -- * @return Rectangle around icon and it's text: The core area of the item. -+ * @return The core area of the item. All of it reacts exactly the same way to mouse clicks. - */ - virtual QRectF selectionRectCore() const = 0; - --- -GitLab - From 0a00c2b25a386b064b28aebd949cc2c6da21eafb Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 7 Sep 2025 01:08:31 +0200 Subject: [PATCH 1029/1125] Desktop/mpv: set cd speed to 8 --- roles/desktop/programs/mpv.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/programs/mpv.nix b/roles/desktop/programs/mpv.nix index 768dc85..d85b058 100644 --- a/roles/desktop/programs/mpv.nix +++ b/roles/desktop/programs/mpv.nix @@ -17,6 +17,7 @@ config = { hwdec = "auto"; cache = true; + cdda-speed = "8"; }; }; }; From 38df2ff9d6e6c0917fba199b3802067baf61590d Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 7 Sep 2025 01:12:22 +0200 Subject: [PATCH 1030/1125] Kde/plasma: update plasma-manager home manager module name --- roles/kde/plasma.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/kde/plasma.nix b/roles/kde/plasma.nix index ae96ca0..9d4e8b9 100644 --- a/roles/kde/plasma.nix +++ b/roles/kde/plasma.nix @@ -55,7 +55,7 @@ in { # Plasma configs should be on all users home-manager.sharedModules = [ { - imports = [flakeSelf.inputs.plasma-manager.homeManagerModules.plasma-manager]; + imports = [flakeSelf.inputs.plasma-manager.homeModules.plasma-manager]; home.packages = [ ( pkgs.catppuccin-kde.override { From e43910155c560692c77b11fb395277dd13cc2904 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 7 Sep 2025 03:07:50 +0200 Subject: [PATCH 1031/1125] Desktop/ssh: remove default config --- roles/desktop/programs/ssh.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/programs/ssh.nix b/roles/desktop/programs/ssh.nix index 00c4c4d..8aac072 100644 --- a/roles/desktop/programs/ssh.nix +++ b/roles/desktop/programs/ssh.nix @@ -12,6 +12,7 @@ home-manager.users.toast = { programs.ssh = { enable = true; + enableDefaultConfig = false; matchBlocks = { "everest" = { host = "toast003.xyz"; From 2615b290a13e17501ebc28bedf319e12ade68462 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 11 Sep 2025 01:27:25 +0200 Subject: [PATCH 1032/1125] Server/forgejo: use lts --- roles/server/forgejo.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index f4e72df..c7f1780 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -25,7 +25,7 @@ in { specialisation.forgejoEnableRegistration.configuration.services.forgejo.settings.service.DISABLE_REGISTRATION = false; services.forgejo = { enable = true; - package = pkgs.forgejo; + package = pkgs.forgejo-lts; settings = { service = { DISABLE_REGISTRATION = lib.mkDefault true; From fb317980e2ed65119b23ea714770ced355550816 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 11 Sep 2025 01:32:50 +0200 Subject: [PATCH 1033/1125] Machines/Everest: set static time zone --- machines/Everest/configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index f6eb874..b183d34 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -35,6 +35,9 @@ nameservers = ["9.9.9.9"]; }; + time.timeZone = "Europe/Madrid"; + services.automatic-timezoned.enable = lib.mkForce false; + # Define a user account. Don't forget to set a password with ‘passwd’. users.users.toast = { extraGroups = ["networkmanager" "transmission"]; From 69c5e8d9be40a7d406b38ac45b9192e5b962234a Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 11 Sep 2025 01:44:26 +0200 Subject: [PATCH 1034/1125] Server/syncthing: add to rust-motd --- roles/server/syncthing.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 84d20cc..00cbeb4 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -76,4 +76,5 @@ } ''; }; + programs.rust-motd.settings.service_status.Syncthing = "syncthing"; } From cd876e3a17814bbf0ba9124c06ffcdc4eaa455cf Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 14 Sep 2025 02:44:32 +0200 Subject: [PATCH 1035/1125] Machines/Archie: fix headphones not being detected sometimes --- machines/Archie/hardware-configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index da6c290..8ce6999 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -18,6 +18,7 @@ boot.initrd.kernelModules = ["amdgpu"]; boot.kernelModules = ["kvm-amd"]; boot.extraModulePackages = []; + boot.extraModprobeConfig = "options snd_hda_intel power_save=0"; fileSystems."/" = { device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; From ae0393ae37a8c0f956137e0eef9cc22c4322dbd9 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 15 Sep 2025 11:49:26 +0200 Subject: [PATCH 1036/1125] Flake: update lock file --- flake.lock | 62 +++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/flake.lock b/flake.lock index 3b7b3c4..a656b27 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1756741629, - "narHash": "sha256-n+mgH3NoQf8d1jd8cDp/9Mt++hhyuE3LO3ZAxzjWRZw=", + "lastModified": 1757320803, + "narHash": "sha256-7PUIQOMQSJLkNtV42SAYUDw0mRdbBNl6q8pLN8GViwM=", "owner": "catppuccin", "repo": "nix", - "rev": "cd22197da06df1eb6fabdaa2fc22c170c4f67382", + "rev": "d75e3fe67f49728cb5035bc791f4b9065ff3a2c9", "type": "github" }, "original": { @@ -65,11 +65,11 @@ ] }, "locked": { - "lastModified": 1757029702, - "narHash": "sha256-gy2zYv5nHeJ72quyJ1ioe7+Njl2jdq+b3H1QrRr3etA=", + "lastModified": 1757543518, + "narHash": "sha256-6tx7gyQ8uwbTGL4CnAZuov9Xmta38byekiNucz78DIM=", "owner": "9001", "repo": "copyparty", - "rev": "bd6d1f961de8df47f4d5418f4cf8dd584a98b495", + "rev": "5c1a43c71172e115c9cda1f1fe0474a4035b1bb0", "type": "github" }, "original": { @@ -203,11 +203,11 @@ ] }, "locked": { - "lastModified": 1756991914, - "narHash": "sha256-4ve/3ah5H/SpL2m3qmZ9GU+VinQYp2MN1G7GamimTds=", + "lastModified": 1757650187, + "narHash": "sha256-OrythrqccPKtuVt0mj26rr83Qo3Ljb4ZmwLdPGjzjMU=", "owner": "nix-community", "repo": "home-manager", - "rev": "b08f8737776f10920c330657bee8b95834b7a70f", + "rev": "9eab59f3e71ea3a725e4817d8dcf0da0824ad19d", "type": "github" }, "original": { @@ -245,11 +245,11 @@ ] }, "locked": { - "lastModified": 1757052778, - "narHash": "sha256-rYszJwY0EArAqK6q0i5bB1zxNCNRk6gVmD9SIvnoXW8=", + "lastModified": 1757230583, + "narHash": "sha256-4uqu7sFPOaVTCogsxaGMgbzZ2vK40GVGMfUmrvK3/LY=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "ceaa413a68f28bbf6731464594fdb2c3513e9110", + "rev": "fc3960e6c32c9d4f95fff2ef84444284d24d3bea", "type": "github" }, "original": { @@ -261,11 +261,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1756426754, - "narHash": "sha256-EVJDo/KjdGtvJKelVPoL92TsPNrqnOJUnaLTIqP+F0o=", - "rev": "f4bdddf0fdaabc68546cf561c5343b83d95d2466", + "lastModified": 1757670140, + "narHash": "sha256-rJV/kCC6VOCuFHnanXpeqRHwm+xARSfDZg2KTPb4+/g=", + "rev": "138c7161be82d3a240ba3a59cbdd93eef069b448", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/f4bdddf0fdaabc68546cf561c5343b83d95d2466.tar.gz?rev=f4bdddf0fdaabc68546cf561c5343b83d95d2466" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/138c7161be82d3a240ba3a59cbdd93eef069b448.tar.gz?rev=138c7161be82d3a240ba3a59cbdd93eef069b448" }, "original": { "type": "tarball", @@ -378,11 +378,11 @@ ] }, "locked": { - "lastModified": 1756612744, - "narHash": "sha256-/glV6VAq8Va3ghIbmhET3S1dzkbZqicsk5h+FtvwiPE=", + "lastModified": 1757218147, + "narHash": "sha256-IwOwN70HvoBNB2ckaROxcaCvj5NudNc52taPsv5wtLk=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "3fe768e1f058961095b4a0d7a2ba15dc9736bdc6", + "rev": "9b144dc3ef6e42b888c4190e02746aab13b0e97f", "type": "github" }, "original": { @@ -398,11 +398,11 @@ ] }, "locked": { - "lastModified": 1756612744, - "narHash": "sha256-/glV6VAq8Va3ghIbmhET3S1dzkbZqicsk5h+FtvwiPE=", + "lastModified": 1757218147, + "narHash": "sha256-IwOwN70HvoBNB2ckaROxcaCvj5NudNc52taPsv5wtLk=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "3fe768e1f058961095b4a0d7a2ba15dc9736bdc6", + "rev": "9b144dc3ef6e42b888c4190e02746aab13b0e97f", "type": "github" }, "original": { @@ -413,11 +413,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1756925795, - "narHash": "sha256-kUb5hehaikfUvoJDEc7ngiieX88TwWX/bBRX9Ar6Tac=", + "lastModified": 1757103352, + "narHash": "sha256-PtT7ix43ss8PONJ1VJw3f6t2yAoGH+q462Sn8lrmWmk=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "ba6fab29768007e9f2657014a6e134637100c57d", + "rev": "11b2a10c7be726321bb854403fdeec391e798bf0", "type": "github" }, "original": { @@ -445,11 +445,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1756886854, - "narHash": "sha256-6tooT142NLcFjt24Gi4B0G1pgWLvfw7y93sYEfSHlLI=", + "lastModified": 1757545623, + "narHash": "sha256-mCxPABZ6jRjUQx3bPP4vjA68ETbPLNz9V2pk9tO7pRQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0e6684e6c5755325f801bda1751a8a4038145d7d", + "rev": "8cd5ce828d5d1d16feff37340171a98fc3bf6526", "type": "github" }, "original": { @@ -460,11 +460,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1756787288, - "narHash": "sha256-rw/PHa1cqiePdBxhF66V7R+WAP8WekQ0mCDG4CFqT8Y=", + "lastModified": 1757487488, + "narHash": "sha256-zwE/e7CuPJUWKdvvTCB7iunV4E/+G0lKfv4kk/5Izdg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d0fc30899600b9b3466ddb260fd83deb486c32f1", + "rev": "ab0f3607a6c7486ea22229b92ed2d355f1482ee0", "type": "github" }, "original": { From eb2a4ea67ad47ac3c20f40d0f7b25613eb4e5720 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Sep 2025 01:57:22 +0200 Subject: [PATCH 1037/1125] Server: add beets --- roles/server/beets.nix | 44 ++++++++++++++++++++++++++++++++++++++++ roles/server/default.nix | 1 + 2 files changed, 45 insertions(+) create mode 100644 roles/server/beets.nix diff --git a/roles/server/beets.nix b/roles/server/beets.nix new file mode 100644 index 0000000..7532805 --- /dev/null +++ b/roles/server/beets.nix @@ -0,0 +1,44 @@ +{...}: let + musicDir = "/srv/music"; +in { + users = { + users.music = { + isSystemUser = true; + group = "music"; + }; + # Intended for other programs to get write permission + groups.music = { + members = ["toast"]; + }; + }; + systemd.tmpfiles.settings = { + music."${musicDir}" = { + d = { + age = "-"; + user = "music"; + group = "music"; + mode = "2775"; + }; + }; + }; + + home-manager.users.toast = {config, ...}: { + programs.beets = { + enable = true; + settings = { + directory = musicDir; + library = "${config.xdg.dataHome}/beets/library.db"; + + import = { + move = true; + }; + ui.color = true; + + plugins = [ + "unimported" + "fetchart" + ]; + }; + }; + }; +} diff --git a/roles/server/default.nix b/roles/server/default.nix index e77155f..a9b5937 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -19,5 +19,6 @@ ./prometheus.nix ./immich.nix ./copyparty.nix + ./beets.nix ]; } From e1c1ff801db5581ad60201504a9b76d700cd17f8 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Sep 2025 03:27:07 +0200 Subject: [PATCH 1038/1125] Server/copyparty: add to rust_motd --- roles/server/copyparty.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/copyparty.nix b/roles/server/copyparty.nix index 180feec..99822a0 100644 --- a/roles/server/copyparty.nix +++ b/roles/server/copyparty.nix @@ -16,6 +16,7 @@ }; users.users.copyparty.extraGroups = ["caddy"]; + programs.rust-motd.settings.service_status.Copyparty = "copyparty"; services.headscale.settings.dns.extra_records = [ { From 3e291869908d93944d8b16ab2d98d07dde52c992 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Sep 2025 21:27:22 +0200 Subject: [PATCH 1039/1125] Server: add navidrome --- roles/server/default.nix | 1 + roles/server/navidrome.nix | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 roles/server/navidrome.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index a9b5937..44f1b3c 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -20,5 +20,6 @@ ./immich.nix ./copyparty.nix ./beets.nix + ./navidrome.nix ]; } diff --git a/roles/server/navidrome.nix b/roles/server/navidrome.nix new file mode 100644 index 0000000..cab624f --- /dev/null +++ b/roles/server/navidrome.nix @@ -0,0 +1,31 @@ +{lib, ...}: { + services = rec { + navidrome = { + enable = true; + settings = { + BaseUrl = "https://${caddy.virtualHosts.navidrome.hostName}"; + Address = "unix:/run/navidrome/navidrome.socket"; + MusicFolder = "/srv/music"; + EnableStarRating = false; + # Better to download in copyparty / smb + EnableDownloads = false; + }; + }; + caddy.virtualHosts.navidrome = { + hostName = "music.everest.tailscale"; + extraConfig = '' + import tailscale + reverse_proxy ${lib.strings.replaceString ":" "/" navidrome.settings.Address} + ''; + }; + headscale.settings.dns.extra_records = [ + { + name = caddy.virtualHosts.navidrome.hostName; + type = "A"; + value = "100.100.0.1"; + } + ]; + }; + programs.rust-motd.settings.service_status.Navidrome = "navidrome"; + users.users.caddy.extraGroups = ["navidrome"]; +} From b6119bd2ccabf0c0098d84b5181c63cf8f781332 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 13 Sep 2025 00:06:27 +0200 Subject: [PATCH 1040/1125] Server/beets: enable chroma plugin --- roles/server/beets.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/beets.nix b/roles/server/beets.nix index 7532805..c865039 100644 --- a/roles/server/beets.nix +++ b/roles/server/beets.nix @@ -37,6 +37,7 @@ in { plugins = [ "unimported" "fetchart" + "chroma" ]; }; }; From 09d0847ea4358f256948f4ef831c73c90ddea1f7 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Sep 2025 18:00:15 +0200 Subject: [PATCH 1041/1125] Desktop/kde: add patches --- .../patches/frameworkintegration/patches.txt | 2 + .../patches/frameworkintegration/pr54.patch | 50 + roles/kde/patches/kwin/patches.txt | 2 + roles/kde/patches/kwin/pr7927.patch | 669 +++++++++++++ roles/kde/patches/kwin/pr8005.patch | 71 ++ .../kde/patches/plasma-workspace/patches.txt | 9 + .../kde/patches/plasma-workspace/pr5609.patch | 456 +++++++++ .../kde/patches/plasma-workspace/pr5657.patch | 177 ++++ .../kde/patches/plasma-workspace/pr5673.patch | 392 ++++++++ .../patches/plasma-workspace/pr5678.9.patch | 913 ++++++++++++++++++ .../kde/patches/plasma-workspace/pr5734.patch | 133 +++ .../kde/patches/plasma-workspace/pr5746.patch | 33 + .../kde/patches/plasma-workspace/pr5782.patch | 32 + .../kde/patches/plasma-workspace/pr5788.patch | 42 + 14 files changed, 2981 insertions(+) create mode 100644 roles/kde/patches/frameworkintegration/patches.txt create mode 100644 roles/kde/patches/frameworkintegration/pr54.patch create mode 100644 roles/kde/patches/kwin/pr7927.patch create mode 100644 roles/kde/patches/kwin/pr8005.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5609.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5657.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5673.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5678.9.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5734.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5746.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5782.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5788.patch diff --git a/roles/kde/patches/frameworkintegration/patches.txt b/roles/kde/patches/frameworkintegration/patches.txt new file mode 100644 index 0000000..09818df --- /dev/null +++ b/roles/kde/patches/frameworkintegration/patches.txt @@ -0,0 +1,2 @@ +Frameworks 6.18: +Pr 54 https://invent.kde.org/frameworks/frameworkintegration/-/merge_requests/54 diff --git a/roles/kde/patches/frameworkintegration/pr54.patch b/roles/kde/patches/frameworkintegration/pr54.patch new file mode 100644 index 0000000..aee5303 --- /dev/null +++ b/roles/kde/patches/frameworkintegration/pr54.patch @@ -0,0 +1,50 @@ +From 516a3642796563bcc7a13cd02795de3077a861b7 Mon Sep 17 00:00:00 2001 +From: Nate Graham +Date: Tue, 5 Aug 2025 09:27:36 -0600 +Subject: [PATCH] Turn on popups for device notifications + +Part of https://invent.kde.org/plasma/plasma-desktop/-/issues/149 + +These notifications are a useful way to communicate to the user that +their device isn't dead and was actuallt detected. Currently we have +only sounds turned on, and no popups. This problematic for +accessibility because deaf people won't hear the sound. + +For this reason, EU Directive 2019/882 requires that all sound-based +notifications be accompanied by something visual as well. + +Let's turn on popups to comply with that. We did some work to make the +popups not annoying, including: +- Not appearing in the history +- Removing the connection notification when disconnected (and vice + versa) +- Removing the notification when it's for a USB disk and the Disks & + Devices widget appears automatically. +--- + plasma_workspace.notifyrc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/plasma_workspace.notifyrc b/plasma_workspace.notifyrc +index 7b9311d..4394192 100644 +--- a/plasma_workspace.notifyrc ++++ b/plasma_workspace.notifyrc +@@ -2380,7 +2380,7 @@ Comment[uk]=Було з'єднано пристрій + Comment[x-test]=xxA device was plugged inxx + Comment[zh_CN]=已插入一个设备 + Comment[zh_TW]=有裝置剛被插入 +-Action=Sound ++Action=Popup|Sound + Sound=device-added + Urgency=Low + +@@ -2465,6 +2465,6 @@ Comment[uk]=Було від'єднано пристрій + Comment[x-test]=xxA device was unpluggedxx + Comment[zh_CN]=已拔出一个设备 + Comment[zh_TW]=有裝置剛被拔出 +-Action=Sound ++Action=Popup|Sound + Sound=device-removed + Urgency=Low +-- +GitLab + diff --git a/roles/kde/patches/kwin/patches.txt b/roles/kde/patches/kwin/patches.txt index cf1766b..f860b5d 100644 --- a/roles/kde/patches/kwin/patches.txt +++ b/roles/kde/patches/kwin/patches.txt @@ -1,3 +1,5 @@ Plasma 6.5.0: Pr 3612 https://invent.kde.org/plasma/kwin/-/merge_requests/3612 Pr 7823 https://invent.kde.org/plasma/kwin/-/merge_requests/7823 +Pr 8005 https://invent.kde.org/plasma/kwin/-/merge_requests/8005 + Depends on Pr 7927 https://invent.kde.org/plasma/kwin/-/merge_requests/7927 diff --git a/roles/kde/patches/kwin/pr7927.patch b/roles/kde/patches/kwin/pr7927.patch new file mode 100644 index 0000000..d35ef4b --- /dev/null +++ b/roles/kde/patches/kwin/pr7927.patch @@ -0,0 +1,669 @@ +From 9f6c92806490d662117575a766f9fcb01e253344 Mon Sep 17 00:00:00 2001 +From: Xaver Hugl +Date: Tue, 22 Jul 2025 23:24:51 +0200 +Subject: [PATCH 1/4] xdgactivation: move the activation token to workspace + +--- + src/activation.cpp | 14 ++++++++++++ + src/workspace.h | 6 +++++ + src/xdgactivationv1.cpp | 50 +++++++++-------------------------------- + src/xdgactivationv1.h | 14 ++---------- + 4 files changed, 32 insertions(+), 52 deletions(-) + +diff --git a/src/activation.cpp b/src/activation.cpp +index 60b921247ce..9e743b8b098 100644 +--- a/src/activation.cpp ++++ b/src/activation.cpp +@@ -630,4 +630,18 @@ void Workspace::windowAttentionChanged(Window *window, bool set) + } + } + ++void Workspace::setActivationToken(const QString &token, uint32_t serial) ++{ ++ m_activationToken = token; ++ m_activationTokenSerial = serial; ++} ++ ++bool Workspace::mayActivate(const QString &token) const ++{ ++ if (!m_activeWindow) { ++ return true; ++ } ++ return !m_activationToken.isEmpty() && token == m_activationToken && m_activeWindow->lastUsageSerial() <= m_activationTokenSerial; ++} ++ + } // namespace +diff --git a/src/workspace.h b/src/workspace.h +index 2082bbe148d..03c54e06750 100644 +--- a/src/workspace.h ++++ b/src/workspace.h +@@ -436,6 +436,9 @@ public: + OutputConfigurationError applyOutputConfiguration(OutputConfiguration &config, const std::optional> &outputOrder = std::nullopt); + void updateXwaylandScale(); + ++ void setActivationToken(const QString &token, uint32_t serial); ++ bool mayActivate(const QString &token) const; ++ + public Q_SLOTS: + void performWindowOperation(KWin::Window *window, Options::WindowOperation op); + // Keybindings +@@ -729,6 +732,9 @@ private: + std::unique_ptr m_dpmsFilter; + KConfigWatcher::Ptr m_kdeglobalsWatcher; + ++ QString m_activationToken; ++ uint32_t m_activationTokenSerial = 0; ++ + private: + friend bool performTransiencyCheck(); + friend Workspace *workspace(); +diff --git a/src/xdgactivationv1.cpp b/src/xdgactivationv1.cpp +index 39dade95332..a6be350399a 100644 +--- a/src/xdgactivationv1.cpp ++++ b/src/xdgactivationv1.cpp +@@ -33,22 +33,6 @@ static bool isPrivilegedInWindowManagement(const ClientConnection *client) + XdgActivationV1Integration::XdgActivationV1Integration(XdgActivationV1Interface *activation, QObject *parent) + : QObject(parent) + { +- Workspace *ws = Workspace::self(); +- connect(ws, &Workspace::windowActivated, this, [this](Window *window) { +- if (!m_currentActivationToken || !window || window->property("token").toString() == m_currentActivationToken->token) { +- return; +- } +- +- // We check that it's not the app that we are trying to activate +- if (window->desktopFileName() != m_currentActivationToken->applicationId) { +- // But also that the new one has been requested after the token was requested +- if (window->lastUsageSerial() < m_currentActivationToken->serial) { +- return; +- } +- } +- +- clear(); +- }); + activation->setActivationTokenCreator([this](ClientConnection *client, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId) -> QString { + Workspace *ws = Workspace::self(); + Q_ASSERT(client); // Should always be available as it's coming straight from the wayland implementation +@@ -69,9 +53,6 @@ QString XdgActivationV1Integration::requestToken(bool isPrivileged, SurfaceInter + static int i = 0; + const auto newToken = QStringLiteral("kwin-%1").arg(++i); + +- if (m_currentActivationToken) { +- clear(); +- } + bool showNotify = false; + QIcon icon = QIcon::fromTheme(QStringLiteral("system-run")); + if (const QString desktopFilePath = Window::findDesktopFile(appId); !desktopFilePath.isEmpty()) { +@@ -83,13 +64,13 @@ QString XdgActivationV1Integration::requestToken(bool isPrivileged, SurfaceInter + } + icon = QIcon::fromTheme(df.readIcon(), icon); + } +- std::unique_ptr activation; + if (showNotify) { +- activation = waylandServer()->plasmaActivationFeedback()->createActivation(appId); ++ m_lastToken = newToken; ++ m_activation = waylandServer()->plasmaActivationFeedback()->createActivation(appId); + } +- m_currentActivationToken = std::make_unique(ActivationToken{newToken, isPrivileged, surface, serial, seat, appId, showNotify, std::move(activation)}); ++ workspace()->setActivationToken(newToken, serial); + if (showNotify) { +- Q_EMIT effects->startupAdded(m_currentActivationToken->token, icon); ++ Q_EMIT effects->startupAdded(newToken, icon); + } + return newToken; + } +@@ -103,31 +84,20 @@ void XdgActivationV1Integration::activateSurface(SurfaceInterface *surface, cons + return; + } + +- if (!m_currentActivationToken || m_currentActivationToken->token != token) { +- qCDebug(KWIN_CORE) << "Refusing to activate " << window << " (provided token: " << token << ", current token:" << (m_currentActivationToken ? m_currentActivationToken->token : QStringLiteral("null")) << ")"; ++ if (!ws->mayActivate(token)) { + window->demandAttention(); + return; + } +- +- auto ownerWindow = waylandServer()->findWindow(m_currentActivationToken->surface); +- qCDebug(KWIN_CORE) << "activating" << window << surface << "on behalf of" << m_currentActivationToken->surface << "into" << ownerWindow; +- if (!ws->activeWindow() || ws->activeWindow() == ownerWindow || ws->activeWindow()->lastUsageSerial() < m_currentActivationToken->serial || m_currentActivationToken->isPrivileged) { +- ws->activateWindow(window); +- } else { +- qCWarning(KWIN_CORE) << "Activation requested while owner isn't active" << (ownerWindow ? ownerWindow->desktopFileName() : "null") +- << m_currentActivationToken->applicationId; +- window->demandAttention(); +- clear(); +- } ++ ws->activateWindow(window); ++ clear(); + } + + void XdgActivationV1Integration::clear() + { +- Q_ASSERT(m_currentActivationToken); +- if (m_currentActivationToken->showNotify) { +- Q_EMIT effects->startupRemoved(m_currentActivationToken->token); ++ if (m_activation) { ++ Q_EMIT effects->startupRemoved(m_lastToken); ++ m_activation.reset(); + } +- m_currentActivationToken.reset(); + } + + } +diff --git a/src/xdgactivationv1.h b/src/xdgactivationv1.h +index 98835def8aa..77d21856095 100644 +--- a/src/xdgactivationv1.h ++++ b/src/xdgactivationv1.h +@@ -38,18 +38,8 @@ private: + QString requestToken(bool isPrivileged, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId); + void clear(); + +- struct ActivationToken +- { +- QString token; +- bool isPrivileged; +- QPointer surface; +- uint serial; +- SeatInterface *seat; +- QString applicationId; +- bool showNotify; +- std::unique_ptr activation; +- }; +- std::unique_ptr m_currentActivationToken; ++ QString m_lastToken; ++ std::unique_ptr m_activation; + }; + + } +-- +GitLab + + +From 6c673a479412902a14c06046199f976e2192dc65 Mon Sep 17 00:00:00 2001 +From: Xaver Hugl +Date: Tue, 22 Jul 2025 23:43:14 +0200 +Subject: [PATCH 2/4] xdgactivation: also allow using activation tokens before + the window is mapped + +We just store the token in the window, and then Workspace uses it to decide whether +or not to activate the window when it's actually shown. +--- + src/window.cpp | 10 ++++++++++ + src/window.h | 5 +++++ + src/workspace.cpp | 4 ++-- + src/xdgactivationv1.cpp | 6 +++++- + 4 files changed, 22 insertions(+), 3 deletions(-) + +diff --git a/src/window.cpp b/src/window.cpp +index 4a97a54aa74..879147ec673 100644 +--- a/src/window.cpp ++++ b/src/window.cpp +@@ -4675,6 +4675,16 @@ void Window::setDescription(const QString &description) + } + } + ++void Window::setActivationToken(const QString &token) ++{ ++ m_activationToken = token; ++} ++ ++QString Window::activationToken() const ++{ ++ return m_activationToken; ++} ++ + } // namespace KWin + + #include "moc_window.cpp" +diff --git a/src/window.h b/src/window.h +index 1eb371018ca..91addb46819 100644 +--- a/src/window.h ++++ b/src/window.h +@@ -1357,6 +1357,9 @@ public: + QString tag() const; + QString description() const; + ++ void setActivationToken(const QString &token); ++ QString activationToken() const; ++ + public Q_SLOTS: + virtual void closeWindow() = 0; + +@@ -1880,6 +1883,8 @@ protected: + + QString m_tag; + QString m_description; ++ ++ QString m_activationToken; + }; + + inline QRectF Window::bufferGeometry() const +diff --git a/src/workspace.cpp b/src/workspace.cpp +index 3a5cb12677b..866abb8080d 100644 +--- a/src/workspace.cpp ++++ b/src/workspace.cpp +@@ -781,8 +781,8 @@ void Workspace::addWaylandWindow(Window *window) + rearrange(); + } + if (window->wantsInput() && !window->isMinimized()) { +- // Never activate a window on its own in "Extreme" mode. +- if (options->focusStealingPreventionLevel() < 4) { ++ // In "Extreme" mode, require an activation token to activate new windows ++ if (options->focusStealingPreventionLevel() < 4 || (!m_activationToken.isEmpty() && window->activationToken() == m_activationToken)) { + if (!window->isDesktop() + // If there's no active window, make this desktop the active one. + || (activeWindow() == nullptr && should_get_focus.count() == 0)) { +diff --git a/src/xdgactivationv1.cpp b/src/xdgactivationv1.cpp +index a6be350399a..11c95c84b32 100644 +--- a/src/xdgactivationv1.cpp ++++ b/src/xdgactivationv1.cpp +@@ -88,7 +88,11 @@ void XdgActivationV1Integration::activateSurface(SurfaceInterface *surface, cons + window->demandAttention(); + return; + } +- ws->activateWindow(window); ++ if (window->readyForPainting()) { ++ ws->activateWindow(window); ++ } else { ++ window->setActivationToken(token); ++ } + clear(); + } + +-- +GitLab + + +From 2436625a66257f586a0934c3d678c910bbdb3705 Mon Sep 17 00:00:00 2001 +From: Xaver Hugl +Date: Wed, 23 Jul 2025 13:18:39 +0200 +Subject: [PATCH 3/4] xdgactivation: move the "not granted" token to + requestToken + +Having some but not all checks in that method is a bit confusing +--- + src/xdgactivationv1.cpp | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git a/src/xdgactivationv1.cpp b/src/xdgactivationv1.cpp +index 11c95c84b32..e818466f8ad 100644 +--- a/src/xdgactivationv1.cpp ++++ b/src/xdgactivationv1.cpp +@@ -34,15 +34,8 @@ XdgActivationV1Integration::XdgActivationV1Integration(XdgActivationV1Interface + : QObject(parent) + { + activation->setActivationTokenCreator([this](ClientConnection *client, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId) -> QString { +- Workspace *ws = Workspace::self(); + Q_ASSERT(client); // Should always be available as it's coming straight from the wayland implementation +- const bool isPrivileged = isPrivilegedInWindowManagement(client); +- if (!isPrivileged && ws->activeWindow() && ws->activeWindow()->surface() != surface) { +- qCDebug(KWIN_CORE) << "Cannot grant a token to" << client; +- return QStringLiteral("not-granted-666"); +- } +- +- return requestToken(isPrivileged, surface, serial, seat, appId); ++ return requestToken(isPrivilegedInWindowManagement(client), surface, serial, seat, appId); + }); + + connect(activation, &XdgActivationV1Interface::activateRequested, this, &XdgActivationV1Integration::activateSurface); +@@ -50,6 +43,11 @@ XdgActivationV1Integration::XdgActivationV1Integration(XdgActivationV1Interface + + QString XdgActivationV1Integration::requestToken(bool isPrivileged, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId) + { ++ auto window = waylandServer()->findWindow(surface); ++ if (!isPrivileged && workspace()->activeWindow() && workspace()->activeWindow()->surface() != surface) { ++ qCWarning(KWIN_CORE) << "Cannot grant a token to" << window; ++ return QStringLiteral("not-granted-666"); ++ } + static int i = 0; + const auto newToken = QStringLiteral("kwin-%1").arg(++i); + +-- +GitLab + + +From 8508b8060813c07fe035801381bad1f9a375acf0 Mon Sep 17 00:00:00 2001 +From: Xaver Hugl +Date: Thu, 24 Jul 2025 20:43:46 +0200 +Subject: [PATCH 4/4] autotests/integration: add a test case for xdg activation + +--- + autotests/integration/CMakeLists.txt | 3 +- + autotests/integration/activation_test.cpp | 126 +++++++++++++++++++++- + autotests/integration/kwin_wayland_test.h | 31 ++++++ + autotests/integration/test_helpers.cpp | 50 +++++++++ + 4 files changed, 208 insertions(+), 2 deletions(-) + +diff --git a/autotests/integration/CMakeLists.txt b/autotests/integration/CMakeLists.txt +index 13b0cde04f5..408af6ac8b8 100644 +--- a/autotests/integration/CMakeLists.txt ++++ b/autotests/integration/CMakeLists.txt +@@ -16,13 +16,14 @@ qt6_generate_wayland_protocol_client_sources(KWinIntegrationTestFramework + FILES + ${CMAKE_SOURCE_DIR}/src/wayland/protocols/wlr-layer-shell-unstable-v1.xml + ${WaylandProtocols_DATADIR}/stable/presentation-time/presentation-time.xml ++ ${WaylandProtocols_DATADIR}/stable/tablet/tablet-v2.xml + ${WaylandProtocols_DATADIR}/stable/xdg-shell/xdg-shell.xml + ${WaylandProtocols_DATADIR}/staging/color-management/color-management-v1.xml +- ${WaylandProtocols_DATADIR}/stable/tablet/tablet-v2.xml + ${WaylandProtocols_DATADIR}/staging/cursor-shape/cursor-shape-v1.xml + ${WaylandProtocols_DATADIR}/staging/fifo/fifo-v1.xml + ${WaylandProtocols_DATADIR}/staging/fractional-scale/fractional-scale-v1.xml + ${WaylandProtocols_DATADIR}/staging/security-context/security-context-v1.xml ++ ${WaylandProtocols_DATADIR}/staging/xdg-activation/xdg-activation-v1.xml + ${WaylandProtocols_DATADIR}/staging/xdg-dialog/xdg-dialog-v1.xml + ${WaylandProtocols_DATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml + ${WaylandProtocols_DATADIR}/unstable/text-input/text-input-unstable-v3.xml +diff --git a/autotests/integration/activation_test.cpp b/autotests/integration/activation_test.cpp +index 75c9e7e8c7b..30f671d6fe2 100644 +--- a/autotests/integration/activation_test.cpp ++++ b/autotests/integration/activation_test.cpp +@@ -15,6 +15,7 @@ + #include "workspace.h" + #include "x11window.h" + ++#include + #include + #include + #include +@@ -40,6 +41,7 @@ private Q_SLOTS: + void testSwitchToWindowMaximized(); + void testSwitchToWindowFullScreen(); + void testActiveFullscreen(); ++ void testXdgActivation(); + + private: + void stackScreensHorizontally(); +@@ -64,7 +66,7 @@ void ActivationTest::initTestCase() + + void ActivationTest::init() + { +- QVERIFY(Test::setupWaylandConnection()); ++ QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::XdgActivation | Test::AdditionalWaylandInterface::Seat)); + + workspace()->setActiveOutput(QPoint(640, 512)); + input()->pointer()->warp(QPoint(640, 512)); +@@ -592,6 +594,128 @@ void ActivationTest::testActiveFullscreen() + QCOMPARE(workspace()->activeWindow(), waylandWindow); + QCOMPARE(x11Window->layer(), Layer::NormalLayer); + } ++ ++void ActivationTest::testXdgActivation() ++{ ++ Test::setOutputConfig({QRect(0, 0, 1280, 1024)}); ++ ++ uint32_t time = 0; ++ ++ std::vector> surfaces; ++ std::vector> shellSurfaces; ++ std::vector windows; ++ const auto setupWindows = [&]() { ++ windows.clear(); ++ shellSurfaces.clear(); ++ surfaces.clear(); ++ ++ // re-create the same setup every time for reduced confusion ++ for (int i = 0; i < 3; i++) { ++ surfaces.push_back(Test::createSurface()); ++ shellSurfaces.push_back(Test::createXdgToplevelSurface(surfaces.back().get())); ++ windows.push_back(Test::renderAndWaitForShown(surfaces.back().get(), QSize(100, 50), Qt::blue)); ++ windows.back()->move(QPoint(150 * i, 0)); ++ ++ Test::pointerMotion(windows.back()->frameGeometry().center(), time++); ++ Test::pointerButtonPressed(1, time++); ++ Test::pointerButtonReleased(1, time++); ++ } ++ }; ++ setupWindows(); ++ ++ QSignalSpy activationSpy(workspace(), &Workspace::windowActivated); ++ ++ // activating a window without a valid token should fail ++ Test::xdgActivation()->activate(QString(), *surfaces[1]); ++ QVERIFY(!activationSpy.wait(10)); ++ ++ // activating it without a surface should fail as well, even if a serial is present ++ auto token = Test::xdgActivation()->createToken(); ++ token->set_serial(windows.back()->lastUsageSerial(), *Test::waylandSeat()); ++ Test::xdgActivation()->activate(token->commitAndWait(), *surfaces[1]); ++ QVERIFY(!activationSpy.wait(10)); ++ ++ // adding the surface should make it work ++ token = Test::xdgActivation()->createToken(); ++ token->set_surface(*surfaces.back()); ++ token->set_serial(windows.back()->lastUsageSerial(), *Test::waylandSeat()); ++ Test::xdgActivation()->activate(token->commitAndWait(), *surfaces[1]); ++ QVERIFY(activationSpy.wait(10)); ++ QCOMPARE(workspace()->activeWindow(), windows[1]); ++ ++ // activation should still work if the window is closed after creating the token ++ setupWindows(); ++ token = Test::xdgActivation()->createToken(); ++ token->set_surface(*surfaces[2]); ++ token->set_serial(windows[2]->lastUsageSerial(), *Test::waylandSeat()); ++ QString result = token->commitAndWait(); ++ ++ surfaces[2]->attachBuffer((wl_buffer *)nullptr); ++ surfaces[2]->commit(KWayland::Client::Surface::CommitFlag::None); ++ QVERIFY(activationSpy.wait(10)); ++ QCOMPARE(workspace()->activeWindow(), windows[1]); ++ ++ Test::xdgActivation()->activate(result, *surfaces[0]); ++ QVERIFY(activationSpy.wait(10)); ++ QCOMPARE(workspace()->activeWindow(), windows[0]); ++ ++ // ...unless the user interacted with another window in between ++ setupWindows(); ++ token = Test::xdgActivation()->createToken(); ++ token->set_surface(*surfaces[2]); ++ token->set_serial(windows[2]->lastUsageSerial(), *Test::waylandSeat()); ++ result = token->commitAndWait(); ++ ++ surfaces[2]->attachBuffer((wl_buffer *)nullptr); ++ surfaces[2]->commit(KWayland::Client::Surface::CommitFlag::None); ++ QVERIFY(activationSpy.wait(10)); ++ QCOMPARE(workspace()->activeWindow(), windows[1]); ++ ++ Test::pointerMotion(windows[1]->frameGeometry().center(), time++); ++ Test::pointerButtonPressed(1, time++); ++ Test::pointerButtonReleased(1, time++); ++ ++ Test::xdgActivation()->activate(result, *surfaces[0]); ++ QVERIFY(!activationSpy.wait(10)); ++ QCOMPARE(workspace()->activeWindow(), windows[1]); ++ ++ // ensure that windows are only activated on show with a valid activation token ++ options->setFocusStealingPreventionLevel(4); ++ ++ // creating a new window and immediately activating it should work ++ setupWindows(); ++ token = Test::xdgActivation()->createToken(); ++ token->set_surface(*surfaces[2]); ++ token->set_serial(windows[2]->lastUsageSerial(), *Test::waylandSeat()); ++ result = token->commitAndWait(); ++ surfaces.push_back(Test::createSurface()); ++ shellSurfaces.push_back(Test::createXdgToplevelSurface(surfaces.back().get(), [&](Test::XdgToplevel *toplevel) { ++ Test::xdgActivation()->activate(result, *surfaces.back()); ++ })); ++ windows.push_back(Test::renderAndWaitForShown(surfaces.back().get(), QSize(100, 50), Qt::blue)); ++ QCOMPARE(workspace()->activeWindow(), windows.back()); ++ windows.back()->move(QPoint(150 * 3, 0)); ++ ++ // activation should fail if the user clicks on another window in between ++ // creating the activation token and using it ++ setupWindows(); ++ token = Test::xdgActivation()->createToken(); ++ token->set_surface(*surfaces[2]); ++ token->set_serial(windows[2]->lastUsageSerial(), *Test::waylandSeat()); ++ result = token->commitAndWait(); ++ ++ Test::pointerMotion(windows[1]->frameGeometry().center(), time++); ++ Test::pointerButtonPressed(1, time++); ++ Test::pointerButtonReleased(1, time++); ++ ++ surfaces.push_back(Test::createSurface()); ++ shellSurfaces.push_back(Test::createXdgToplevelSurface(surfaces.back().get(), [&](Test::XdgToplevel *toplevel) { ++ Test::xdgActivation()->activate(result, *surfaces.back()); ++ })); ++ windows.push_back(Test::renderAndWaitForShown(surfaces.back().get(), QSize(100, 50), Qt::blue)); ++ QCOMPARE(workspace()->activeWindow(), windows[1]); ++ windows.back()->move(QPoint(150 * 3, 0)); ++} + } + + WAYLANDTEST_MAIN(KWin::ActivationTest) +diff --git a/autotests/integration/kwin_wayland_test.h b/autotests/integration/kwin_wayland_test.h +index b0f63dadbc5..a6616189617 100644 +--- a/autotests/integration/kwin_wayland_test.h ++++ b/autotests/integration/kwin_wayland_test.h +@@ -34,6 +34,7 @@ + #include "qwayland-security-context-v1.h" + #include "qwayland-text-input-unstable-v3.h" + #include "qwayland-wlr-layer-shell-unstable-v1.h" ++#include "qwayland-xdg-activation-v1.h" + #include "qwayland-xdg-decoration-unstable-v1.h" + #include "qwayland-xdg-dialog-v1.h" + #include "qwayland-xdg-shell.h" +@@ -611,6 +612,7 @@ enum class AdditionalWaylandInterface { + ColorManagement = 1 << 22, + FifoV1 = 1 << 23, + PresentationTime = 1 << 24, ++ XdgActivation = 1 << 25, + }; + Q_DECLARE_FLAGS(AdditionalWaylandInterfaces, AdditionalWaylandInterface) + +@@ -717,6 +719,33 @@ private: + void wp_presentation_feedback_discarded() override; + }; + ++class XdgActivationToken : public QObject, public QtWayland::xdg_activation_token_v1 ++{ ++ Q_OBJECT ++public: ++ explicit XdgActivationToken(::xdg_activation_token_v1 *object); ++ ~XdgActivationToken() override; ++ ++ QString commitAndWait(); ++ ++Q_SIGNALS: ++ void tokenReceived(); ++ ++private: ++ void xdg_activation_token_v1_done(const QString &token) override; ++ ++ QString m_token; ++}; ++ ++class XdgActivation : public QtWayland::xdg_activation_v1 ++{ ++public: ++ explicit XdgActivation(::wl_registry *registry, uint32_t id, int version); ++ ~XdgActivation() override; ++ ++ std::unique_ptr createToken(); ++}; ++ + struct Connection + { + static std::unique_ptr setup(AdditionalWaylandInterfaces interfaces = AdditionalWaylandInterfaces()); +@@ -757,6 +786,7 @@ struct Connection + std::unique_ptr colorManager; + std::unique_ptr fifoManager; + std::unique_ptr presentationTime; ++ std::unique_ptr xdgActivation; + }; + + void keyboardKeyPressed(quint32 key, quint32 time); +@@ -821,6 +851,7 @@ SecurityContextManagerV1 *waylandSecurityContextManagerV1(); + ColorManagerV1 *colorManager(); + FifoManagerV1 *fifoManager(); + PresentationTime *presentationTime(); ++XdgActivation *xdgActivation(); + + bool waitForWaylandSurface(Window *window); + +diff --git a/autotests/integration/test_helpers.cpp b/autotests/integration/test_helpers.cpp +index 22380c947d3..e524f10826d 100644 +--- a/autotests/integration/test_helpers.cpp ++++ b/autotests/integration/test_helpers.cpp +@@ -535,6 +535,11 @@ std::unique_ptr Connection::setup(AdditionalWaylandInterfaces flags) + c->presentationTime = std::make_unique(*c->registry, name, version); + } + } ++ if (flags & AdditionalWaylandInterface::XdgActivation) { ++ if (interface == xdg_activation_v1_interface.name) { ++ c->xdgActivation = std::make_unique(*c->registry, name, version); ++ } ++ } + }); + + QSignalSpy allAnnounced(registry, &KWayland::Client::Registry::interfacesAnnounced); +@@ -665,6 +670,7 @@ Connection::~Connection() + colorManager.reset(); + fifoManager.reset(); + presentationTime.reset(); ++ xdgActivation.reset(); + + delete queue; // Must be destroyed last + queue = nullptr; +@@ -796,6 +802,11 @@ PresentationTime *presentationTime() + return s_waylandConnection->presentationTime.get(); + } + ++XdgActivation *xdgActivation() ++{ ++ return s_waylandConnection->xdgActivation.get(); ++} ++ + bool waitForWaylandSurface(Window *window) + { + if (window->surface()) { +@@ -1817,6 +1828,45 @@ void WpPresentationFeedback::wp_presentation_feedback_discarded() + Q_EMIT discarded(); + } + ++XdgActivationToken::XdgActivationToken(::xdg_activation_token_v1 *object) ++ : QtWayland::xdg_activation_token_v1(object) ++{ ++} ++ ++XdgActivationToken::~XdgActivationToken() ++{ ++ destroy(); ++} ++ ++QString XdgActivationToken::commitAndWait() ++{ ++ QSignalSpy received(this, &XdgActivationToken::tokenReceived); ++ commit(); ++ received.wait(); ++ return m_token; ++} ++ ++void XdgActivationToken::xdg_activation_token_v1_done(const QString &token) ++{ ++ m_token = token; ++ Q_EMIT tokenReceived(); ++} ++ ++XdgActivation::XdgActivation(::wl_registry *registry, uint32_t id, int version) ++ : QtWayland::xdg_activation_v1(registry, id, version) ++{ ++} ++ ++XdgActivation::~XdgActivation() ++{ ++ destroy(); ++} ++ ++std::unique_ptr XdgActivation::createToken() ++{ ++ return std::make_unique(get_activation_token()); ++} ++ + void keyboardKeyPressed(quint32 key, quint32 time) + { + auto virtualKeyboard = static_cast(kwinApp())->virtualKeyboard(); +-- +GitLab + diff --git a/roles/kde/patches/kwin/pr8005.patch b/roles/kde/patches/kwin/pr8005.patch new file mode 100644 index 0000000..b95d140 --- /dev/null +++ b/roles/kde/patches/kwin/pr8005.patch @@ -0,0 +1,71 @@ +From dc692e89f101a47b9049b1f6ae4cc3cebef46edb Mon Sep 17 00:00:00 2001 +From: Xaver Hugl +Date: Tue, 12 Aug 2025 15:59:16 +0200 +Subject: [PATCH] xdgactivation: clear activation feedback if no token is + provided too + +If the window is activated, the user expectation is that feedback stops. The underlying +reason for why it's activated doesn't matter. +--- + src/xdgactivationv1.cpp | 12 ++++++++++-- + src/xdgactivationv1.h | 3 ++- + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/src/xdgactivationv1.cpp b/src/xdgactivationv1.cpp +index 360ca9b8743..567b792025f 100644 +--- a/src/xdgactivationv1.cpp ++++ b/src/xdgactivationv1.cpp +@@ -33,6 +33,13 @@ static bool isPrivilegedInWindowManagement(const ClientConnection *client) + XdgActivationV1Integration::XdgActivationV1Integration(XdgActivationV1Interface *activation, QObject *parent) + : QObject(parent) + { ++ connect(Workspace::self(), &Workspace::windowActivated, this, [this](Window *window) { ++ if (!m_activation || !window || m_lastTokenAppId != window->desktopFileName()) { ++ return; ++ } ++ clearFeedback(); ++ }); ++ + activation->setActivationTokenCreator([this](ClientConnection *client, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId) -> QString { + Q_ASSERT(client); // Should always be available as it's coming straight from the wayland implementation + return requestToken(isPrivilegedInWindowManagement(client), surface, serial, seat, appId); +@@ -64,6 +71,7 @@ QString XdgActivationV1Integration::requestToken(bool isPrivileged, SurfaceInter + } + if (showNotify) { + m_lastToken = newToken; ++ m_lastTokenAppId = appId; + m_activation = waylandServer()->plasmaActivationFeedback()->createActivation(appId); + } + if (isPrivileged && workspace()->activeWindow()) { +@@ -95,10 +103,10 @@ void XdgActivationV1Integration::activateSurface(SurfaceInterface *surface, cons + } else { + window->setActivationToken(token); + } +- clear(); ++ clearFeedback(); + } + +-void XdgActivationV1Integration::clear() ++void XdgActivationV1Integration::clearFeedback() + { + if (m_activation) { + Q_EMIT effects->startupRemoved(m_lastToken); +diff --git a/src/xdgactivationv1.h b/src/xdgactivationv1.h +index 77d21856095..ad007c088b6 100644 +--- a/src/xdgactivationv1.h ++++ b/src/xdgactivationv1.h +@@ -36,9 +36,10 @@ public: + + private: + QString requestToken(bool isPrivileged, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId); +- void clear(); ++ void clearFeedback(); + + QString m_lastToken; ++ QString m_lastTokenAppId; + std::unique_ptr m_activation; + }; + +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/patches.txt b/roles/kde/patches/plasma-workspace/patches.txt index 56ecbad..26a8d42 100644 --- a/roles/kde/patches/plasma-workspace/patches.txt +++ b/roles/kde/patches/plasma-workspace/patches.txt @@ -5,3 +5,12 @@ Pr 5626 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5626 Pr 5627 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5627 Commit 8202ba92 https://invent.kde.org/plasma/plasma-workspace/-/commit/8202ba92b610c691b8bc6bab8ad5a1c3b9ac73da Part of https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5628, the other part got cherry picked on 6.4.2 +Pr 5657 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5657 +Pr 5734 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5734 + Depends on Pr 5609 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5609 +Pr 5746 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5746 +Pr 5782 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5782 +Pr 5678 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5678 + Depends on Pr 5673 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5673 +Pr 5788 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5788 + Allows compiling on gcc 14 after applying pr 5678 diff --git a/roles/kde/patches/plasma-workspace/pr5609.patch b/roles/kde/patches/plasma-workspace/pr5609.patch new file mode 100644 index 0000000..74c9d39 --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5609.patch @@ -0,0 +1,456 @@ +From 439b251bcb3ea24f52c052e7244fb7ced04503aa Mon Sep 17 00:00:00 2001 +From: Bohdan Onofriichuk +Date: Thu, 19 Jun 2025 14:51:30 +0000 +Subject: [PATCH] applets/devicenotifier: port to plasma_add_applet + +--- + applets/devicenotifier/CMakeLists.txt | 58 ++++++++++++++++--- + .../{plugin => }/actioninterface.cpp | 0 + .../{plugin => }/actioninterface.h | 0 + .../{plugin => }/actions/defaultaction.cpp | 0 + .../{plugin => }/actions/defaultaction.h | 0 + .../{plugin => }/actions/mountaction.cpp | 0 + .../{plugin => }/actions/mountaction.h | 0 + .../actions/mountandopenaction.cpp | 0 + .../{plugin => }/actions/mountandopenaction.h | 0 + .../actions/openwithfilemanageraction.cpp | 0 + .../actions/openwithfilemanageraction.h | 0 + .../{plugin => }/actions/unmountaction.cpp | 0 + .../{plugin => }/actions/unmountaction.h | 0 + .../{plugin => }/actionscontrol.cpp | 0 + .../{plugin => }/actionscontrol.h | 0 + .../{plugin => }/devicecontrol.cpp | 0 + .../{plugin => }/devicecontrol.h | 0 + .../{plugin => }/deviceerrormonitor_p.cpp | 0 + .../{plugin => }/deviceerrormonitor_p.h | 0 + .../{plugin => }/devicefiltercontrol.cpp | 0 + .../{plugin => }/devicefiltercontrol.h | 0 + .../{plugin => }/devicenotifications.notifyrc | 0 + .../{plugin => }/deviceserviceaction.cpp | 0 + .../{plugin => }/deviceserviceaction.h | 0 + .../{plugin => }/devicestatemonitor_p.cpp | 0 + .../{plugin => }/devicestatemonitor_p.h | 0 + .../{package/contents/config => }/main.xml | 0 + .../{package => }/metadata.json | 1 - + applets/devicenotifier/plugin/CMakeLists.txt | 51 ---------------- + .../{plugin => }/predicatesmonitor_p.cpp | 0 + .../{plugin => }/predicatesmonitor_p.h | 0 + .../contents/ui => qml}/DeviceItem.qml | 22 ++++--- + .../ui => qml}/FullRepresentation.qml | 0 + .../{package/contents/ui => qml}/main.qml | 9 ++- + .../{plugin => }/spacemonitor_p.cpp | 0 + .../{plugin => }/spacemonitor_p.h | 0 + 36 files changed, 65 insertions(+), 76 deletions(-) + rename applets/devicenotifier/{plugin => }/actioninterface.cpp (100%) + rename applets/devicenotifier/{plugin => }/actioninterface.h (100%) + rename applets/devicenotifier/{plugin => }/actions/defaultaction.cpp (100%) + rename applets/devicenotifier/{plugin => }/actions/defaultaction.h (100%) + rename applets/devicenotifier/{plugin => }/actions/mountaction.cpp (100%) + rename applets/devicenotifier/{plugin => }/actions/mountaction.h (100%) + rename applets/devicenotifier/{plugin => }/actions/mountandopenaction.cpp (100%) + rename applets/devicenotifier/{plugin => }/actions/mountandopenaction.h (100%) + rename applets/devicenotifier/{plugin => }/actions/openwithfilemanageraction.cpp (100%) + rename applets/devicenotifier/{plugin => }/actions/openwithfilemanageraction.h (100%) + rename applets/devicenotifier/{plugin => }/actions/unmountaction.cpp (100%) + rename applets/devicenotifier/{plugin => }/actions/unmountaction.h (100%) + rename applets/devicenotifier/{plugin => }/actionscontrol.cpp (100%) + rename applets/devicenotifier/{plugin => }/actionscontrol.h (100%) + rename applets/devicenotifier/{plugin => }/devicecontrol.cpp (100%) + rename applets/devicenotifier/{plugin => }/devicecontrol.h (100%) + rename applets/devicenotifier/{plugin => }/deviceerrormonitor_p.cpp (100%) + rename applets/devicenotifier/{plugin => }/deviceerrormonitor_p.h (100%) + rename applets/devicenotifier/{plugin => }/devicefiltercontrol.cpp (100%) + rename applets/devicenotifier/{plugin => }/devicefiltercontrol.h (100%) + rename applets/devicenotifier/{plugin => }/devicenotifications.notifyrc (100%) + rename applets/devicenotifier/{plugin => }/deviceserviceaction.cpp (100%) + rename applets/devicenotifier/{plugin => }/deviceserviceaction.h (100%) + rename applets/devicenotifier/{plugin => }/devicestatemonitor_p.cpp (100%) + rename applets/devicenotifier/{plugin => }/devicestatemonitor_p.h (100%) + rename applets/devicenotifier/{package/contents/config => }/main.xml (100%) + rename applets/devicenotifier/{package => }/metadata.json (99%) + delete mode 100644 applets/devicenotifier/plugin/CMakeLists.txt + rename applets/devicenotifier/{plugin => }/predicatesmonitor_p.cpp (100%) + rename applets/devicenotifier/{plugin => }/predicatesmonitor_p.h (100%) + rename applets/devicenotifier/{package/contents/ui => qml}/DeviceItem.qml (81%) + rename applets/devicenotifier/{package/contents/ui => qml}/FullRepresentation.qml (100%) + rename applets/devicenotifier/{package/contents/ui => qml}/main.qml (96%) + rename applets/devicenotifier/{plugin => }/spacemonitor_p.cpp (100%) + rename applets/devicenotifier/{plugin => }/spacemonitor_p.h (100%) + +diff --git a/applets/devicenotifier/CMakeLists.txt b/applets/devicenotifier/CMakeLists.txt +index bde4a38dd30..f336db13a69 100644 +--- a/applets/devicenotifier/CMakeLists.txt ++++ b/applets/devicenotifier/CMakeLists.txt +@@ -1,11 +1,55 @@ +-add_subdirectory(plugin) ++# SPDX-FileCopyrightText: 2024 Fushan Wen ++# SPDX-License-Identifier: BSD-3-Clause + +-ecm_qt_install_logging_categories( +- EXPORT APPLETS::DEVICENOTIFIER +- FILE applets/devicenotifier.categories +- DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR} ++add_definitions(-DTRANSLATION_DOMAIN=\"plasma_applet_org.kde.plasma.devicenotifier\") ++ ++plasma_add_applet(org.kde.plasma.devicenotifier ++ QML_SOURCES ++ qml/DeviceItem.qml ++ qml/FullRepresentation.qml ++ qml/main.qml ++ CPP_SOURCES ++ actionscontrol.cpp ++ devicecontrol.cpp ++ spacemonitor_p.cpp ++ devicestatemonitor_p.cpp ++ deviceserviceaction.cpp ++ predicatesmonitor_p.cpp ++ deviceerrormonitor_p.cpp ++ actioninterface.cpp ++ devicefiltercontrol.cpp ++ actions/defaultaction.cpp ++ actions/mountandopenaction.cpp ++ actions/mountaction.cpp ++ actions/unmountaction.cpp ++ actions/openwithfilemanageraction.cpp ++ RESOURCES ++ main.xml ++ GENERATE_APPLET_CLASS ++) ++ ++target_link_libraries(org.kde.plasma.devicenotifier ++ PRIVATE ++ Qt::Qml ++ Plasma::Plasma ++ KF6::Solid ++ KF6::I18n ++ KF6::CoreAddons ++ KF6::Service ++ KF6::KIOCore ++ KF6::KIOGui # KIO::CommandLauncherJob ++ KF6::JobWidgets # KNotificationJobUiDelegate ++ KSysGuard::ProcessCore ++ KF6::Notifications + ) + +-plasma_install_package(package org.kde.plasma.devicenotifier) ++ecm_qt_declare_logging_category(org.kde.plasma.devicenotifier ++ HEADER "devicenotifier_debug.h" ++ IDENTIFIER "APPLETS::DEVICENOTIFIER" ++ CATEGORY_NAME org.kde.applets.devicenotifier ++ DEFAULT_SEVERITY Warning ++ DESCRIPTION "Device Notifier applet" EXPORT "APPLETS::DEVICENOTIFIER" ++) + +-install(FILES openWithFileManager.desktop DESTINATION ${KDE_INSTALL_DATADIR}/solid/actions ) ++install(FILES devicenotifications.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR}) ++install(FILES openWithFileManager.desktop DESTINATION ${KDE_INSTALL_DATADIR}/solid/actions) +diff --git a/applets/devicenotifier/plugin/actioninterface.cpp b/applets/devicenotifier/actioninterface.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/actioninterface.cpp +rename to applets/devicenotifier/actioninterface.cpp +diff --git a/applets/devicenotifier/plugin/actioninterface.h b/applets/devicenotifier/actioninterface.h +similarity index 100% +rename from applets/devicenotifier/plugin/actioninterface.h +rename to applets/devicenotifier/actioninterface.h +diff --git a/applets/devicenotifier/plugin/actions/defaultaction.cpp b/applets/devicenotifier/actions/defaultaction.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/actions/defaultaction.cpp +rename to applets/devicenotifier/actions/defaultaction.cpp +diff --git a/applets/devicenotifier/plugin/actions/defaultaction.h b/applets/devicenotifier/actions/defaultaction.h +similarity index 100% +rename from applets/devicenotifier/plugin/actions/defaultaction.h +rename to applets/devicenotifier/actions/defaultaction.h +diff --git a/applets/devicenotifier/plugin/actions/mountaction.cpp b/applets/devicenotifier/actions/mountaction.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/actions/mountaction.cpp +rename to applets/devicenotifier/actions/mountaction.cpp +diff --git a/applets/devicenotifier/plugin/actions/mountaction.h b/applets/devicenotifier/actions/mountaction.h +similarity index 100% +rename from applets/devicenotifier/plugin/actions/mountaction.h +rename to applets/devicenotifier/actions/mountaction.h +diff --git a/applets/devicenotifier/plugin/actions/mountandopenaction.cpp b/applets/devicenotifier/actions/mountandopenaction.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/actions/mountandopenaction.cpp +rename to applets/devicenotifier/actions/mountandopenaction.cpp +diff --git a/applets/devicenotifier/plugin/actions/mountandopenaction.h b/applets/devicenotifier/actions/mountandopenaction.h +similarity index 100% +rename from applets/devicenotifier/plugin/actions/mountandopenaction.h +rename to applets/devicenotifier/actions/mountandopenaction.h +diff --git a/applets/devicenotifier/plugin/actions/openwithfilemanageraction.cpp b/applets/devicenotifier/actions/openwithfilemanageraction.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/actions/openwithfilemanageraction.cpp +rename to applets/devicenotifier/actions/openwithfilemanageraction.cpp +diff --git a/applets/devicenotifier/plugin/actions/openwithfilemanageraction.h b/applets/devicenotifier/actions/openwithfilemanageraction.h +similarity index 100% +rename from applets/devicenotifier/plugin/actions/openwithfilemanageraction.h +rename to applets/devicenotifier/actions/openwithfilemanageraction.h +diff --git a/applets/devicenotifier/plugin/actions/unmountaction.cpp b/applets/devicenotifier/actions/unmountaction.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/actions/unmountaction.cpp +rename to applets/devicenotifier/actions/unmountaction.cpp +diff --git a/applets/devicenotifier/plugin/actions/unmountaction.h b/applets/devicenotifier/actions/unmountaction.h +similarity index 100% +rename from applets/devicenotifier/plugin/actions/unmountaction.h +rename to applets/devicenotifier/actions/unmountaction.h +diff --git a/applets/devicenotifier/plugin/actionscontrol.cpp b/applets/devicenotifier/actionscontrol.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/actionscontrol.cpp +rename to applets/devicenotifier/actionscontrol.cpp +diff --git a/applets/devicenotifier/plugin/actionscontrol.h b/applets/devicenotifier/actionscontrol.h +similarity index 100% +rename from applets/devicenotifier/plugin/actionscontrol.h +rename to applets/devicenotifier/actionscontrol.h +diff --git a/applets/devicenotifier/plugin/devicecontrol.cpp b/applets/devicenotifier/devicecontrol.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/devicecontrol.cpp +rename to applets/devicenotifier/devicecontrol.cpp +diff --git a/applets/devicenotifier/plugin/devicecontrol.h b/applets/devicenotifier/devicecontrol.h +similarity index 100% +rename from applets/devicenotifier/plugin/devicecontrol.h +rename to applets/devicenotifier/devicecontrol.h +diff --git a/applets/devicenotifier/plugin/deviceerrormonitor_p.cpp b/applets/devicenotifier/deviceerrormonitor_p.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/deviceerrormonitor_p.cpp +rename to applets/devicenotifier/deviceerrormonitor_p.cpp +diff --git a/applets/devicenotifier/plugin/deviceerrormonitor_p.h b/applets/devicenotifier/deviceerrormonitor_p.h +similarity index 100% +rename from applets/devicenotifier/plugin/deviceerrormonitor_p.h +rename to applets/devicenotifier/deviceerrormonitor_p.h +diff --git a/applets/devicenotifier/plugin/devicefiltercontrol.cpp b/applets/devicenotifier/devicefiltercontrol.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/devicefiltercontrol.cpp +rename to applets/devicenotifier/devicefiltercontrol.cpp +diff --git a/applets/devicenotifier/plugin/devicefiltercontrol.h b/applets/devicenotifier/devicefiltercontrol.h +similarity index 100% +rename from applets/devicenotifier/plugin/devicefiltercontrol.h +rename to applets/devicenotifier/devicefiltercontrol.h +diff --git a/applets/devicenotifier/plugin/devicenotifications.notifyrc b/applets/devicenotifier/devicenotifications.notifyrc +similarity index 100% +rename from applets/devicenotifier/plugin/devicenotifications.notifyrc +rename to applets/devicenotifier/devicenotifications.notifyrc +diff --git a/applets/devicenotifier/plugin/deviceserviceaction.cpp b/applets/devicenotifier/deviceserviceaction.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/deviceserviceaction.cpp +rename to applets/devicenotifier/deviceserviceaction.cpp +diff --git a/applets/devicenotifier/plugin/deviceserviceaction.h b/applets/devicenotifier/deviceserviceaction.h +similarity index 100% +rename from applets/devicenotifier/plugin/deviceserviceaction.h +rename to applets/devicenotifier/deviceserviceaction.h +diff --git a/applets/devicenotifier/plugin/devicestatemonitor_p.cpp b/applets/devicenotifier/devicestatemonitor_p.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/devicestatemonitor_p.cpp +rename to applets/devicenotifier/devicestatemonitor_p.cpp +diff --git a/applets/devicenotifier/plugin/devicestatemonitor_p.h b/applets/devicenotifier/devicestatemonitor_p.h +similarity index 100% +rename from applets/devicenotifier/plugin/devicestatemonitor_p.h +rename to applets/devicenotifier/devicestatemonitor_p.h +diff --git a/applets/devicenotifier/package/contents/config/main.xml b/applets/devicenotifier/main.xml +similarity index 100% +rename from applets/devicenotifier/package/contents/config/main.xml +rename to applets/devicenotifier/main.xml +diff --git a/applets/devicenotifier/package/metadata.json b/applets/devicenotifier/metadata.json +similarity index 99% +rename from applets/devicenotifier/package/metadata.json +rename to applets/devicenotifier/metadata.json +index 0a330dfc189..77d7feac1cb 100644 +--- a/applets/devicenotifier/package/metadata.json ++++ b/applets/devicenotifier/metadata.json +@@ -115,7 +115,6 @@ + "desktop" + ], + "Icon": "device-notifier", +- "Id": "org.kde.plasma.devicenotifier", + "License": "GPL-2.0+", + "Name": "Disks & Devices", + "Name[ar]": "الأجهزة والأقراص", +diff --git a/applets/devicenotifier/plugin/CMakeLists.txt b/applets/devicenotifier/plugin/CMakeLists.txt +deleted file mode 100644 +index 34a3456d690..00000000000 +--- a/applets/devicenotifier/plugin/CMakeLists.txt ++++ /dev/null +@@ -1,51 +0,0 @@ +-# SPDX-FileCopyrightText: 2024 Fushan Wen +-# SPDX-License-Identifier: BSD-3-Clause +- +-add_definitions(-DTRANSLATION_DOMAIN=\"plasma_applet_org.kde.plasma.devicenotifier\") +- +-ecm_add_qml_module(devicenotifierplugin URI org.kde.plasma.private.devicenotifier GENERATE_PLUGIN_SOURCE) +- +-target_sources(devicenotifierplugin +- PRIVATE +- actionscontrol.cpp actionscontrol.h +- devicecontrol.cpp devicecontrol.h +- spacemonitor_p.cpp spacemonitor_p.h +- devicestatemonitor_p.cpp devicestatemonitor_p.h +- deviceserviceaction.cpp deviceserviceaction.h +- predicatesmonitor_p.cpp predicatesmonitor_p.h +- deviceerrormonitor_p.cpp deviceerrormonitor_p.h +- actioninterface.cpp actioninterface.h +- devicefiltercontrol.cpp devicefiltercontrol.h +- actions/defaultaction.cpp actions/defaultaction.h +- actions/mountandopenaction.cpp actions/mountandopenaction.h +- actions/mountaction.cpp actions/mountaction.h +- actions/unmountaction.cpp actions/unmountaction.h +- actions/openwithfilemanageraction.cpp actions/openwithfilemanageraction.h +-) +- +-target_link_libraries(devicenotifierplugin +- PRIVATE +- Qt::Qml +- Plasma::Plasma +- KF6::Solid +- KF6::I18n +- KF6::CoreAddons +- KF6::Service +- KF6::KIOCore +- KF6::KIOGui # KIO::CommandLauncherJob +- KF6::JobWidgets # KNotificationJobUiDelegate +- KSysGuard::ProcessCore +- KF6::Notifications +-) +- +-ecm_qt_declare_logging_category(devicenotifierplugin +- HEADER "devicenotifier_debug.h" +- IDENTIFIER "APPLETS::DEVICENOTIFIER" +- CATEGORY_NAME org.kde.applets.devicenotifier +- DEFAULT_SEVERITY Warning +- DESCRIPTION "Device Notifier applet" EXPORT "APPLETS::DEVICENOTIFIER" +-) +- +-ecm_finalize_qml_module(devicenotifierplugin) +- +-install(FILES devicenotifications.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR}) +diff --git a/applets/devicenotifier/plugin/predicatesmonitor_p.cpp b/applets/devicenotifier/predicatesmonitor_p.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/predicatesmonitor_p.cpp +rename to applets/devicenotifier/predicatesmonitor_p.cpp +diff --git a/applets/devicenotifier/plugin/predicatesmonitor_p.h b/applets/devicenotifier/predicatesmonitor_p.h +similarity index 100% +rename from applets/devicenotifier/plugin/predicatesmonitor_p.h +rename to applets/devicenotifier/predicatesmonitor_p.h +diff --git a/applets/devicenotifier/package/contents/ui/DeviceItem.qml b/applets/devicenotifier/qml/DeviceItem.qml +similarity index 81% +rename from applets/devicenotifier/package/contents/ui/DeviceItem.qml +rename to applets/devicenotifier/qml/DeviceItem.qml +index c19c9535b04..861996af45c 100644 +--- a/applets/devicenotifier/package/contents/ui/DeviceItem.qml ++++ b/applets/devicenotifier/qml/DeviceItem.qml +@@ -19,8 +19,6 @@ import org.kde.kirigami as Kirigami + + import org.kde.kquickcontrolsaddons + +-import org.kde.plasma.private.devicenotifier as DN +- + PlasmaExtras.ExpandableListItem { + id: deviceItem + +@@ -41,18 +39,18 @@ PlasmaExtras.ExpandableListItem { + + property bool hasMessage: deviceItem.deviceErrorMessage !== "" + +- property bool isFree: deviceItem.deviceOperationResult !== DN.DevicesStateMonitor.Working && deviceItem.deviceOperationResult !== DN.DevicesStateMonitor.Checking && deviceItem.deviceOperationResult !== DN.DevicesStateMonitor.Repairing && deviceItem.deviceOperationResult !== DN.DevicesStateMonitor.NotPresent && !(deviceItem.deviceMounted === false && deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Successful) ++ property bool isFree: deviceItem.deviceOperationResult !== DevicesStateMonitor.Working && deviceItem.deviceOperationResult !== DevicesStateMonitor.Checking && deviceItem.deviceOperationResult !== DevicesStateMonitor.Repairing && deviceItem.deviceOperationResult !== DevicesStateMonitor.NotPresent && !(deviceItem.deviceMounted === false && deviceItem.deviceOperationResult === DevicesStateMonitor.Successful) + + onDeviceOperationResultChanged: { + if (!popupIconTimer.running) { +- if (deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Working) { ++ if (deviceItem.deviceOperationResult === DevicesStateMonitor.Working) { + if(deviceMounted){ + unmountTimer.restart(); + } +- } else if (deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Successful) { ++ } else if (deviceItem.deviceOperationResult === DevicesStateMonitor.Successful) { + devicenotifier.popupIcon = "dialog-ok" + popupIconTimer.restart() +- } else if (deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Unsuccessful) { ++ } else if (deviceItem.deviceOperationResult === DevicesStateMonitor.Unsuccessful) { + devicenotifier.popupIcon = "dialog-error" + popupIconTimer.restart() + } +@@ -80,7 +78,7 @@ PlasmaExtras.ExpandableListItem { + } else { + return "emblem-error" + } +- } else if (deviceItem.deviceOperationResult !== DN.DevicesStateMonitor.Working && deviceItem.deviceEmblems[0]) { ++ } else if (deviceItem.deviceOperationResult !== DevicesStateMonitor.Working && deviceItem.deviceEmblems[0]) { + return deviceItem.deviceEmblems[0] + } else { + return "" +@@ -93,16 +91,16 @@ PlasmaExtras.ExpandableListItem { + if (deviceItem.hasMessage) { + return deviceItem.deviceErrorMessage + } +- if (deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Checking) { ++ if (deviceItem.deviceOperationResult === DevicesStateMonitor.Checking) { + return i18nc("Accessing is a less technical word for Mounting; translation should be short and mean \'Currently mounting this device\'", "Checking…") +- } else if (deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Repairing) { ++ } else if (deviceItem.deviceOperationResult === DevicesStateMonitor.Repairing) { + return i18nc("Accessing is a less technical word for Mounting; translation should be short and mean \'Currently mounting this device\'", "Repairing…") +- } else if (deviceItem.deviceOperationResult !== DN.DevicesStateMonitor.Working) { ++ } else if (deviceItem.deviceOperationResult !== DevicesStateMonitor.Working) { + if (deviceItem.deviceFreeSpace > 0 && deviceItem.deviceSize > 0) { + return i18nc("@info:status Free disk space", "%1 free of %2", deviceItem.deviceFreeSpaceText, deviceItem.deviceSizeText) + } + return "" +- } else if (!deviceItem.deviceMounted && deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Working) { ++ } else if (!deviceItem.deviceMounted && deviceItem.deviceOperationResult === DevicesStateMonitor.Working) { + return i18nc("Accessing is a less technical word for Mounting; translation should be short and mean \'Currently mounting this device\'", "Accessing…") + } else if (unmountTimer.running) { + // Unmounting; shown if unmount takes less than 1 second +@@ -139,7 +137,7 @@ PlasmaExtras.ExpandableListItem { + } + } + +- isBusy: deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Working || deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Checking || deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Repairing ++ isBusy: deviceItem.deviceOperationResult === DevicesStateMonitor.Working || deviceItem.deviceOperationResult === DevicesStateMonitor.Checking || deviceItem.deviceOperationResult === DevicesStateMonitor.Repairing + + customExpandedViewContent: deviceActions !== undefined && deviceActions.rowCount() !== 0 && isFree ? actionComponent : null + +diff --git a/applets/devicenotifier/package/contents/ui/FullRepresentation.qml b/applets/devicenotifier/qml/FullRepresentation.qml +similarity index 100% +rename from applets/devicenotifier/package/contents/ui/FullRepresentation.qml +rename to applets/devicenotifier/qml/FullRepresentation.qml +diff --git a/applets/devicenotifier/package/contents/ui/main.qml b/applets/devicenotifier/qml/main.qml +similarity index 96% +rename from applets/devicenotifier/package/contents/ui/main.qml +rename to applets/devicenotifier/qml/main.qml +index 4061480becc..7fcd76a6d16 100644 +--- a/applets/devicenotifier/package/contents/ui/main.qml ++++ b/applets/devicenotifier/qml/main.qml +@@ -15,21 +15,20 @@ import org.kde.kirigami as Kirigami + + import org.kde.kcmutils // For KCMLauncher + import org.kde.config // KAuthorized +-import org.kde.plasma.private.devicenotifier as DN + + PlasmoidItem { + id: devicenotifier + +- DN.DeviceFilterControl { ++ DeviceFilterControl { + id: filterModel + + filterType: { + if (Plasmoid.configuration.allDevices) { +- return DN.DeviceFilterControl.All ++ return DeviceFilterControl.All + } else if (Plasmoid.configuration.removableDevices) { +- return DN.DeviceFilterControl.Removable ++ return DeviceFilterControl.Removable + } else { +- return DN.DeviceFilterControl.Unremovable ++ return DeviceFilterControl.Unremovable + } + } + +diff --git a/applets/devicenotifier/plugin/spacemonitor_p.cpp b/applets/devicenotifier/spacemonitor_p.cpp +similarity index 100% +rename from applets/devicenotifier/plugin/spacemonitor_p.cpp +rename to applets/devicenotifier/spacemonitor_p.cpp +diff --git a/applets/devicenotifier/plugin/spacemonitor_p.h b/applets/devicenotifier/spacemonitor_p.h +similarity index 100% +rename from applets/devicenotifier/plugin/spacemonitor_p.h +rename to applets/devicenotifier/spacemonitor_p.h +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/pr5657.patch b/roles/kde/patches/plasma-workspace/pr5657.patch new file mode 100644 index 0000000..71620a0 --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5657.patch @@ -0,0 +1,177 @@ +From aa1e466e5f7684a8b624c34d466dda9d10a331d2 Mon Sep 17 00:00:00 2001 +From: Nate Graham +Date: Sun, 6 Jul 2025 23:20:47 -0400 +Subject: [PATCH 1/2] Improve UX of USB plug/unplug notifications when popup is + shown + +1. When plugged or unplugged, revoke the opposite notification if it's + visible. +2. Set the urgency to low so it won't clutter up the notification + history. +--- + devicenotifications/devicenotifications.cpp | 55 ++++++++++++++++----- + devicenotifications/devicenotifications.h | 5 ++ + 2 files changed, 48 insertions(+), 12 deletions(-) + +diff --git a/devicenotifications/devicenotifications.cpp b/devicenotifications/devicenotifications.cpp +index cc462f58f5..f326691c11 100644 +--- a/devicenotifications/devicenotifications.cpp ++++ b/devicenotifications/devicenotifications.cpp +@@ -15,6 +15,7 @@ + + #include + ++#include + #include + + K_PLUGIN_CLASS_WITH_JSON(KdedDeviceNotifications, "devicenotifications.json") +@@ -375,13 +376,28 @@ void KdedDeviceNotifications::onDeviceAdded(const UdevDevice &device) + return; + } + +- const QString text = !displayName.isEmpty() ? i18n("%1 has been plugged in.", displayName.toHtmlEscaped()) : i18n("A USB device has been plugged in."); ++ // If the user unplugged something and then immediately plugged it in again, ++ // there's no need to keep the unplug notification around. ++ if (m_usbDeviceRemovedNotification) { ++ m_usbDeviceRemovedNotification->close(); ++ } ++ ++ // Only show one of these at a time. We already suppressed creating a bunch ++ // in quick succession for the dock/hub use case, so any that are created ++ // over that time limit anyway are not necessary to stack up. ++ if (m_usbDeviceAddedNotification) { ++ m_usbDeviceAddedNotification->close(); ++ } ++ ++ const QString text = !displayName.isEmpty() ? i18n("%1 has been connected.", displayName.toHtmlEscaped()) : i18n("A USB device has been connected."); ++ ++ m_usbDeviceAddedNotification = new KNotification(QStringLiteral("deviceAdded")); ++ m_usbDeviceAddedNotification->setFlags(KNotification::DefaultEvent); ++ m_usbDeviceAddedNotification->setIconName(QStringLiteral("drive-removable-media-usb")); ++ m_usbDeviceAddedNotification->setTitle(i18nc("@title:notifications", "USB Device Detected")); ++ m_usbDeviceAddedNotification->setText(text); ++ m_usbDeviceAddedNotification->sendEvent(); + +- KNotification::event(QStringLiteral("deviceAdded"), +- i18nc("@title:notifications", "USB Device Detected"), +- text, +- QStringLiteral("drive-removable-media-usb"), +- KNotification::DefaultEvent); + m_deviceAddedTimer.start(); + } + +@@ -401,13 +417,28 @@ void KdedDeviceNotifications::onDeviceRemoved(const UdevDevice &device) + return; + } + +- const QString text = !displayName.isEmpty() ? i18n("%1 has been unplugged.", displayName.toHtmlEscaped()) : i18n("A USB device has been unplugged."); ++ // If the user plugged something in and then immediately unplugged it again, ++ // there's no need to keep the plug notification around. ++ if (m_usbDeviceAddedNotification) { ++ m_usbDeviceAddedNotification->close(); ++ } ++ ++ // Only show one of these at a time. We already suppressed removing a bunch ++ // in quick succession for the dock/hub use case, so any that are removed ++ // over that time limit anyway are not necessary to stack up. ++ if (m_usbDeviceRemovedNotification) { ++ m_usbDeviceRemovedNotification->close(); ++ } ++ ++ const QString text = !displayName.isEmpty() ? i18n("%1 has been disconnected.", displayName.toHtmlEscaped()) : i18n("A USB device has been disconnected."); ++ ++ m_usbDeviceRemovedNotification = new KNotification(QStringLiteral("deviceRemoved")); ++ m_usbDeviceRemovedNotification->setFlags(KNotification::DefaultEvent); ++ m_usbDeviceRemovedNotification->setIconName(QStringLiteral("drive-removable-media-usb")); ++ m_usbDeviceRemovedNotification->setTitle(i18nc("@title:notifications", "USB Device Went Away")); ++ m_usbDeviceRemovedNotification->setText(text); ++ m_usbDeviceRemovedNotification->sendEvent(); + +- KNotification::event(QStringLiteral("deviceRemoved"), +- i18nc("@title:notifications", "USB Device Removed"), +- text, +- QStringLiteral("drive-removable-media-usb"), +- KNotification::DefaultEvent); + m_deviceRemovedTimer.start(); + } + +diff --git a/devicenotifications/devicenotifications.h b/devicenotifications/devicenotifications.h +index 11334008b0..ab7e6b3ff9 100644 +--- a/devicenotifications/devicenotifications.h ++++ b/devicenotifications/devicenotifications.h +@@ -8,11 +8,13 @@ + + #include + #include ++#include + #include + #include + #include + + #include ++#include + + #include + +@@ -98,4 +100,7 @@ private: + + QTimer m_deviceAddedTimer; + QTimer m_deviceRemovedTimer; ++ ++ QPointer m_usbDeviceAddedNotification; ++ QPointer m_usbDeviceRemovedNotification; + }; +-- +2.51.0 + + +From 05f72383fd0b29105f3b5494759500d26b38ffc2 Mon Sep 17 00:00:00 2001 +From: Nate Graham +Date: Fri, 11 Jul 2025 11:25:23 -0600 +Subject: [PATCH 2/2] Delete closed notifications too + +Closing is async; make sure we actually delete them when we want them +gone. +--- + devicenotifications/devicenotifications.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/devicenotifications/devicenotifications.cpp b/devicenotifications/devicenotifications.cpp +index f326691c11..987d65d805 100644 +--- a/devicenotifications/devicenotifications.cpp ++++ b/devicenotifications/devicenotifications.cpp +@@ -380,6 +380,7 @@ void KdedDeviceNotifications::onDeviceAdded(const UdevDevice &device) + // there's no need to keep the unplug notification around. + if (m_usbDeviceRemovedNotification) { + m_usbDeviceRemovedNotification->close(); ++ m_usbDeviceRemovedNotification = nullptr; + } + + // Only show one of these at a time. We already suppressed creating a bunch +@@ -387,6 +388,7 @@ void KdedDeviceNotifications::onDeviceAdded(const UdevDevice &device) + // over that time limit anyway are not necessary to stack up. + if (m_usbDeviceAddedNotification) { + m_usbDeviceAddedNotification->close(); ++ m_usbDeviceAddedNotification = nullptr; + } + + const QString text = !displayName.isEmpty() ? i18n("%1 has been connected.", displayName.toHtmlEscaped()) : i18n("A USB device has been connected."); +@@ -421,6 +423,7 @@ void KdedDeviceNotifications::onDeviceRemoved(const UdevDevice &device) + // there's no need to keep the plug notification around. + if (m_usbDeviceAddedNotification) { + m_usbDeviceAddedNotification->close(); ++ m_usbDeviceAddedNotification = nullptr; + } + + // Only show one of these at a time. We already suppressed removing a bunch +@@ -428,6 +431,7 @@ void KdedDeviceNotifications::onDeviceRemoved(const UdevDevice &device) + // over that time limit anyway are not necessary to stack up. + if (m_usbDeviceRemovedNotification) { + m_usbDeviceRemovedNotification->close(); ++ m_usbDeviceRemovedNotification = nullptr; + } + + const QString text = !displayName.isEmpty() ? i18n("%1 has been disconnected.", displayName.toHtmlEscaped()) : i18n("A USB device has been disconnected."); +-- +2.51.0 + diff --git a/roles/kde/patches/plasma-workspace/pr5673.patch b/roles/kde/patches/plasma-workspace/pr5673.patch new file mode 100644 index 0000000..c78dca1 --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5673.patch @@ -0,0 +1,392 @@ +From 97c77a8e3259d77cb615dadd1c92185545513ebb Mon Sep 17 00:00:00 2001 +From: Harald Sitter +Date: Sun, 13 Jul 2025 16:06:08 +0200 +Subject: [PATCH 1/7] servicerunner: en_US spelling please + +--- + runners/services/servicerunner.cpp | 14 +++++++------- + runners/services/servicerunner.h | 4 ++-- + 2 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp +index 454cf4e99f..357558a77d 100644 +--- a/runners/services/servicerunner.cpp ++++ b/runners/services/servicerunner.cpp +@@ -296,7 +296,7 @@ private: + relevance += .09; + } + +- if (const auto foundIt = m_runner->m_favourites.constFind(service->desktopEntryName()); foundIt != m_runner->m_favourites.cend()) { ++ if (const auto foundIt = m_runner->m_favorites.constFind(service->desktopEntryName()); foundIt != m_runner->m_favorites.cend()) { + if (foundIt->isGlobal || foundIt->linkedActivities.contains(m_currentActivity)) { + qCDebug(RUNNER_SERVICES) << "entry is a favorite" << id << match.subtext() << relevance; + relevance *= 1.25; // Give favorites a relative boost, +@@ -423,7 +423,7 @@ ServiceRunner::ServiceRunner(QObject *parent, const KPluginMetaData &metaData) + }); + + connect(&m_kactivitiesWatcher, &ResultWatcher::resultUnlinked, [this](QString resource) { +- m_favourites.remove(resource.remove(".desktop"_L1)); ++ m_favorites.remove(resource.remove(".desktop"_L1)); + // In case it was only unlinked from one activity + processActivitiesResults(ResultSet(m_kactivitiesQuery | Terms::Url::contains(resource))); + }); +@@ -466,11 +466,11 @@ void ServiceRunner::processActivitiesResults(const ResultSet &results) + const static QLatin1String applicationScheme("applications"); + for (const ResultSet::Result &result : results) { + if (result.url().scheme() == applicationScheme) { +- m_favourites.insert(result.url().path().remove(QLatin1String(".desktop")), +- ActivityFavourite{ +- result.linkedActivities(), +- result.linkedActivities().contains(globalActivity), +- }); ++ m_favorites.insert(result.url().path().remove(QLatin1String(".desktop")), ++ ActivityFavorite{ ++ result.linkedActivities(), ++ result.linkedActivities().contains(globalActivity), ++ }); + } + } + } +diff --git a/runners/services/servicerunner.h b/runners/services/servicerunner.h +index e0507ea459..571d22d90c 100644 +--- a/runners/services/servicerunner.h ++++ b/runners/services/servicerunner.h +@@ -33,11 +33,11 @@ public: + void run(const KRunner::RunnerContext &context, const KRunner::QueryMatch &match) override; + void init() override; + +- struct ActivityFavourite { ++ struct ActivityFavorite { + QStringList linkedActivities; + bool isGlobal; + }; +- QMap m_favourites; ++ QMap m_favorites; + + protected: + void setupMatch(const KService::Ptr &service, KRunner::QueryMatch &action); +-- +2.51.0 + + +From 537d0cf67d600cb40636f9aaef7db6957f002eb2 Mon Sep 17 00:00:00 2001 +From: Harald Sitter +Date: Sun, 13 Jul 2025 16:06:50 +0200 +Subject: [PATCH 2/7] servicerunner: use designated initializers + +makes code easier to read +--- + runners/services/servicerunner.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp +index 357558a77d..2cade45b26 100644 +--- a/runners/services/servicerunner.cpp ++++ b/runners/services/servicerunner.cpp +@@ -468,8 +468,8 @@ void ServiceRunner::processActivitiesResults(const ResultSet &results) + if (result.url().scheme() == applicationScheme) { + m_favorites.insert(result.url().path().remove(QLatin1String(".desktop")), + ActivityFavorite{ +- result.linkedActivities(), +- result.linkedActivities().contains(globalActivity), ++ .linkedActivities = result.linkedActivities(), ++ .isGlobal = result.linkedActivities().contains(globalActivity), + }); + } + } +-- +2.51.0 + + +From 2c5eb156410c022a50a5b6e08a6abc454dd49b83 Mon Sep 17 00:00:00 2001 +From: Harald Sitter +Date: Sun, 13 Jul 2025 16:09:37 +0200 +Subject: [PATCH 3/7] servicerunner: use ranges algorithms + +makes for nicer to read code +--- + runners/services/servicerunner.cpp | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp +index 2cade45b26..87b38a2da3 100644 +--- a/runners/services/servicerunner.cpp ++++ b/runners/services/servicerunner.cpp +@@ -46,15 +46,15 @@ int weightedLength(const QString &query) + + inline bool contains(const QString &result, const QList &queryList) + { +- return std::all_of(queryList.cbegin(), queryList.cend(), [&result](QStringView query) { ++ return std::ranges::all_of(queryList, [&result](QStringView query) { + return result.contains(query, Qt::CaseInsensitive); + }); + } + + inline bool contains(const QStringList &results, const QList &queryList) + { +- return std::all_of(queryList.cbegin(), queryList.cend(), [&results](QStringView query) { +- return std::any_of(results.cbegin(), results.cend(), [&query](QStringView result) { ++ return std::ranges::all_of(queryList, [&results](QStringView query) { ++ return std::ranges::any_of(results, [&query](QStringView result) { + return result.contains(query, Qt::CaseInsensitive); + }); + }); +@@ -327,7 +327,7 @@ private: + setupMatch(service, match); + + qreal relevance = 0.4; +- if (std::any_of(categories.begin(), categories.end(), [this](const QString &category) { ++ if (std::ranges::any_of(categories, [this](const QString &category) { + return category.compare(query, Qt::CaseInsensitive) == 0; + })) { + relevance = 0.6; +@@ -499,7 +499,7 @@ void ServiceRunner::run(const KRunner::RunnerContext & /*context*/, const KRunne + job = new KIO::ApplicationLauncherJob(service); + } else { + const auto actions = service->actions(); +- auto it = std::find_if(actions.begin(), actions.end(), [&actionName](const KServiceAction &action) { ++ auto it = std::ranges::find_if(actions, [&actionName](const KServiceAction &action) { + return action.name() == actionName; + }); + Q_ASSERT(it != actions.end()); +-- +2.51.0 + + +From 0599abb0af9d1da43d8067dd59b8afad7c7be9c6 Mon Sep 17 00:00:00 2001 +From: Harald Sitter +Date: Sun, 13 Jul 2025 16:11:05 +0200 +Subject: [PATCH 4/7] servicerunner: put helper functions into anon namespace + +they are translation unit local after all +--- + runners/services/servicerunner.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp +index 87b38a2da3..baef7ae50f 100644 +--- a/runners/services/servicerunner.cpp ++++ b/runners/services/servicerunner.cpp +@@ -38,6 +38,8 @@ + #include "debug.h" + + using namespace Qt::StringLiterals; ++namespace ++{ + + int weightedLength(const QString &query) + { +@@ -60,6 +62,8 @@ inline bool contains(const QStringList &results, const QList &query + }); + } + ++} // namespace ++ + /** + * @brief Finds all KServices for a given runner query + */ +-- +2.51.0 + + +From 2f81c3ab0520729ed4f97d666b5c74258eed149b Mon Sep 17 00:00:00 2001 +From: Harald Sitter +Date: Sun, 13 Jul 2025 16:12:37 +0200 +Subject: [PATCH 5/7] servicerunner: typos-- + +--- + runners/services/autotests/servicerunnertest.cpp | 4 ++-- + runners/services/servicerunner.cpp | 10 +++++----- + runners/services/servicerunner.h | 2 +- + 3 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/runners/services/autotests/servicerunnertest.cpp b/runners/services/autotests/servicerunnertest.cpp +index ecb8a4816c..fcfd3275ac 100644 +--- a/runners/services/autotests/servicerunnertest.cpp ++++ b/runners/services/autotests/servicerunnertest.cpp +@@ -27,7 +27,7 @@ private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + +- void testExcutableExactMatch(); ++ void testExecutableExactMatch(); + void testKonsoleVsYakuakeComment(); + void testSystemSettings(); + void testSystemSettings2(); +@@ -76,7 +76,7 @@ void ServiceRunnerTest::cleanupTestCase() + { + } + +-void ServiceRunnerTest::testExcutableExactMatch() ++void ServiceRunnerTest::testExecutableExactMatch() + { + const auto matches = launchQuery(QStringLiteral("Virtual Machine Manager ServiceRunnerTest")); // virt-manager.desktop + QVERIFY(std::any_of(matches.cbegin(), matches.cend(), [](const KRunner::QueryMatch &match) { +diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp +index baef7ae50f..ced1b526ce 100644 +--- a/runners/services/servicerunner.cpp ++++ b/runners/services/servicerunner.cpp +@@ -125,7 +125,7 @@ private: + GenericName, + Comment, + }; +- qreal increaseMatchRelavance(const QString &serviceProperty, const QList &strList, Category category) ++ qreal increaseMatchRelevance(const QString &serviceProperty, const QList &strList, Category category) + { + // Increment the relevance based on all the words (other than the first) of the query list + qreal relevanceIncrement = 0; +@@ -273,20 +273,20 @@ private: + categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Highest; + } else if (const int idx = name.indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { + relevance = 0.8; +- relevance += increaseMatchRelavance(name, queryList, Category::Name); ++ relevance += increaseMatchRelevance(name, queryList, Category::Name); + if (idx == 0) { + relevance += 0.1; + categoryRelevance = KRunner::QueryMatch::CategoryRelevance::High; + } + } else if (const int idx = service->genericName().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { + relevance = 0.65; +- relevance += increaseMatchRelavance(service->genericName(), queryList, Category::GenericName); ++ relevance += increaseMatchRelevance(service->genericName(), queryList, Category::GenericName); + if (idx == 0) { + relevance += 0.05; + } + } else if (const int idx = service->comment().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { + relevance = 0.5; +- relevance += increaseMatchRelavance(service->comment(), queryList, Category::Comment); ++ relevance += increaseMatchRelevance(service->comment(), queryList, Category::Comment); + if (idx == 0) { + relevance += 0.05; + } +@@ -481,7 +481,7 @@ void ServiceRunner::processActivitiesResults(const ResultSet &results) + + void ServiceRunner::match(KRunner::RunnerContext &context) + { +- ServiceFinder finder(this, m_services, m_activitiesConsuer.currentActivity()); ++ ServiceFinder finder(this, m_services, m_activitiesConsumer.currentActivity()); + finder.match(context); + } + +diff --git a/runners/services/servicerunner.h b/runners/services/servicerunner.h +index 571d22d90c..96a110789b 100644 +--- a/runners/services/servicerunner.h ++++ b/runners/services/servicerunner.h +@@ -46,7 +46,7 @@ private: + void processActivitiesResults(const ResultSet &results); + const Query m_kactivitiesQuery; + const ResultWatcher m_kactivitiesWatcher; +- const KActivities::Consumer m_activitiesConsuer; ++ const KActivities::Consumer m_activitiesConsumer; + QList m_services; + bool m_matching = false; + }; +-- +2.51.0 + + +From d25a269e9dbf6209ae51f94c298cb1ef640b045c Mon Sep 17 00:00:00 2001 +From: Harald Sitter +Date: Sun, 13 Jul 2025 16:14:53 +0200 +Subject: [PATCH 6/7] servicerunner: don't narrow qsizetype to int + +use auto instead since we don't actually care about their size anyway +since we only perform trivial >=0 checks +--- + runners/services/servicerunner.cpp | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp +index ced1b526ce..551717947f 100644 +--- a/runners/services/servicerunner.cpp ++++ b/runners/services/servicerunner.cpp +@@ -206,7 +206,7 @@ private: + static const auto specialArgs = {QStringLiteral("-qwindowtitle"), QStringLiteral("-qwindowicon"), QStringLiteral("--started-from-file")}; + + for (const auto &specialArg : specialArgs) { +- int index = resultingArgs.indexOf(specialArg); ++ auto index = resultingArgs.indexOf(specialArg); + if (index > -1) { + if (resultingArgs.count() > index) { + resultingArgs.removeAt(index); +@@ -271,20 +271,20 @@ private: + } else if (name.compare(query, Qt::CaseInsensitive) == 0) { + relevance = 1; + categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Highest; +- } else if (const int idx = name.indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { ++ } else if (const auto idx = name.indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { + relevance = 0.8; + relevance += increaseMatchRelevance(name, queryList, Category::Name); + if (idx == 0) { + relevance += 0.1; + categoryRelevance = KRunner::QueryMatch::CategoryRelevance::High; + } +- } else if (const int idx = service->genericName().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { ++ } else if (const auto idx = service->genericName().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { + relevance = 0.65; + relevance += increaseMatchRelevance(service->genericName(), queryList, Category::GenericName); + if (idx == 0) { + relevance += 0.05; + } +- } else if (const int idx = service->comment().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { ++ } else if (const auto idx = service->comment().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { + relevance = 0.5; + relevance += increaseMatchRelevance(service->comment(), queryList, Category::Comment); + if (idx == 0) { +@@ -364,7 +364,7 @@ private: + } + seen(action); + +- const int matchIndex = action.text().indexOf(query, 0, Qt::CaseInsensitive); ++ const auto matchIndex = action.text().indexOf(query, 0, Qt::CaseInsensitive); + if (matchIndex < 0) { + continue; + } +-- +2.51.0 + + +From 1a14af41b78a192d10fb5dcef93bba430872eab4 Mon Sep 17 00:00:00 2001 +From: Harald Sitter +Date: Sun, 13 Jul 2025 16:15:55 +0200 +Subject: [PATCH 7/7] servicerunner: remove inline noise + +functions defined inside a definition are always inline +--- + runners/services/servicerunner.cpp | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp +index 551717947f..eb9f02e74b 100644 +--- a/runners/services/servicerunner.cpp ++++ b/runners/services/servicerunner.cpp +@@ -92,22 +92,22 @@ public: + } + + private: +- inline void seen(const KService::Ptr &service) ++ void seen(const KService::Ptr &service) + { + m_seen.insert(service->exec()); + } + +- inline void seen(const KServiceAction &action) ++ void seen(const KServiceAction &action) + { + m_seen.insert(action.exec()); + } + +- inline bool hasSeen(const KService::Ptr &service) ++ bool hasSeen(const KService::Ptr &service) + { + return m_seen.contains(service->exec()); + } + +- inline bool hasSeen(const KServiceAction &action) ++ bool hasSeen(const KServiceAction &action) + { + return m_seen.contains(action.exec()); + } +-- +2.51.0 + diff --git a/roles/kde/patches/plasma-workspace/pr5678.9.patch b/roles/kde/patches/plasma-workspace/pr5678.9.patch new file mode 100644 index 0000000..1c9421a --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5678.9.patch @@ -0,0 +1,913 @@ +From 312c215e717654e55fa48ec968f412201d2a5544 Mon Sep 17 00:00:00 2001 +From: Harald Sitter +Date: Mon, 14 Jul 2025 17:28:14 +0200 +Subject: [PATCH] servicerunner: fuzzy match + +use a bitap implementation instead of doing awkward contains dances. +this should lead to somewhat more reliable results, which are now more +comprehensively asserted in the unit test + +at the heart of this is a new fuzzyScore function that assigns a score +to a service vis a vis a query. this score is adjusted depending on +which field it is regarding (name > genericname > keywords). +this should hopefully ensure that a match against name outweighs most +other matches. all scores are eventually assembled into a final score +that gets used as match relevance +--- + runners/services/autotests/CMakeLists.txt | 3 + + runners/services/autotests/bitaptest.cpp | 70 +++++ + .../autotests/fixtures/audacity.desktop | 2 +- + .../fixtures/org.kde.discover.desktop | 17 ++ + .../autotests/fixtures/org.kde.kpat.desktop | 2 +- + .../services/autotests/servicerunnertest.cpp | 94 ++++-- + runners/services/bitap.h | 178 +++++++++++ + runners/services/levenshtein.h | 58 ++++ + runners/services/servicerunner.cpp | 286 +++++++++++------- + 9 files changed, 576 insertions(+), 134 deletions(-) + create mode 100644 runners/services/autotests/bitaptest.cpp + create mode 100755 runners/services/autotests/fixtures/org.kde.discover.desktop + create mode 100644 runners/services/bitap.h + create mode 100644 runners/services/levenshtein.h + +diff --git a/runners/services/autotests/CMakeLists.txt b/runners/services/autotests/CMakeLists.txt +index 04849a2928..ff7ec66634 100644 +--- a/runners/services/autotests/CMakeLists.txt ++++ b/runners/services/autotests/CMakeLists.txt +@@ -6,3 +6,6 @@ remove_definitions(-DQT_NO_CAST_FROM_ASCII) + ecm_add_test(servicerunnertest.cpp TEST_NAME servicerunnertest + LINK_LIBRARIES Qt::Test KF6::Service KF6::Runner) + krunner_configure_test(servicerunnertest krunner_services) ++ ++ecm_add_test(bitaptest.cpp TEST_NAME bitaptest ++ LINK_LIBRARIES Qt::Test) +diff --git a/runners/services/autotests/bitaptest.cpp b/runners/services/autotests/bitaptest.cpp +new file mode 100644 +index 0000000000..1a1cb856ec +--- /dev/null ++++ b/runners/services/autotests/bitaptest.cpp +@@ -0,0 +1,70 @@ ++// SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL ++// SPDX-FileCopyrightText: 2025 Harald Sitter ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../bitap.h" ++ ++class BitapTest : public QObject ++{ ++ Q_OBJECT ++private Q_SLOTS: ++ void initTestCase() ++ { ++ } ++ void cleanupTestCase() ++ { ++ } ++ ++ void testBitap() ++ { ++ using namespace Bitap; ++ // The macro has trouble with designated initializers, so we wrap them in (). ++ QCOMPARE(bitap(u"hello world", u"hello", 1), (Match{.end = 4, .distance = 0})); ++ QCOMPARE(bitap(u"wireshark", u"di", 1), (Match{.end = 1, .distance = 1})); ++ QCOMPARE(bitap(u"discover", u"disk", 1), (Match{.end = 2, .distance = 1})); ++ QCOMPARE(bitap(u"discover", u"disc", 1), (Match{.end = 3, .distance = 0})); ++ QCOMPARE(bitap(u"discover", u"scov", 1), (Match{.end = 5, .distance = 0})); ++ QCOMPARE(bitap(u"discover", u"diki", 1), std::nullopt); ++ QCOMPARE(bitap(u"discover", u"obo", 1), std::nullopt); ++ // With a hamming distance of 1 this may match because it is a single transposition. ++ QCOMPARE(bitap(u"discover", u"dicsover", 1), (Match{.end = 7, .distance = 1})); ++ // … but with three characters out of place things should not match. ++ QCOMPARE(bitap(u"discover", u"dicosver", 1), std::nullopt); ++ // pattern too long ++ QCOMPARE(bitap(u"discover", u" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 1), std::nullopt); ++ // This is not a transposition as per Damerau–Levenshtein distance because the characters are not adjacent. ++ QCOMPARE(bitap(u"steam", u"skeap", 1), std::nullopt); ++ // Deletion required ++ QCOMPARE(bitap(u"discover", u"discover", 1), (Match{.end = 7, .distance = 0})); ++ QCOMPARE(bitap(u"discover", u"discovery", 1), (Match{.end = 7, .distance = 1})); ++ // Insertion required ++ QCOMPARE(bitap(u"discover", u"dicover", 1), (Match{.end = 7, .distance = 1})); ++ } ++ ++ void testScore() ++ { ++ using namespace Bitap; ++ // aperfectten has 10 big beautiful indexes. The maximum end is therefore 10. ++ QCOMPARE(score(u"aperfectten", Match{.end = 10, .distance = 0}, 1), 1.0); ++ QCOMPARE(score(u"aperfectten", Match{.end = 4, .distance = 0}, 1), 0.4); ++ QCOMPARE(score(u"aperfectten", Match{.end = 4, .distance = 1}, 1), 0.35); ++ QCOMPARE(score(u"aperfectten", Match{.end = 0, .distance = 0}, 0), 0); ++ QCOMPARE(score(u"aperfectten", Match{.end = 0, .distance = 0}, 1), 0); ++ QCOMPARE(score(u"aperfectten", Match{.end = 1, .distance = 1}, 1), 0.05); ++ ++ QCOMPARE(score(u"abc", Match{.end = 2, .distance = 1}, 1), 0.95); ++ // Ask for distance 0 but it has a distance so this is a super bad match. ++ QCOMPARE(score(u"abc", Match{.end = 2, .distance = 1}, 0), 0); ++ } ++}; ++ ++QTEST_MAIN(BitapTest) ++ ++#include "bitaptest.moc" +diff --git a/runners/services/autotests/fixtures/audacity.desktop b/runners/services/autotests/fixtures/audacity.desktop +index 7613d9f32f..05e1b9d929 100644 +--- a/runners/services/autotests/fixtures/audacity.desktop ++++ b/runners/services/autotests/fixtures/audacity.desktop +@@ -1,5 +1,5 @@ + [Desktop Entry] +-Name=Audacity ++Name=Audacity ServiceRunnerTest + GenericName=Sound Editor + Comment=Record and edit audio files + Keywords=audio;sound;alsa;jack;editor; +diff --git a/runners/services/autotests/fixtures/org.kde.discover.desktop b/runners/services/autotests/fixtures/org.kde.discover.desktop +new file mode 100755 +index 0000000000..978b2b4152 +--- /dev/null ++++ b/runners/services/autotests/fixtures/org.kde.discover.desktop +@@ -0,0 +1,17 @@ ++# SPDX-FileCopyrightText: None ++# SPDX-License-Identifier: CC0-1.0 ++[Desktop Entry] ++Name=Discover ServiceRunnerTest ++Comment=Install and remove apps and add-ons ++MimeType=application/vnd.flatpak;application/vnd.flatpak.repo;application/vnd.flatpak.ref; ++Exec=plasma-discover %F ++Icon=plasmadiscover ++Type=Application ++X-DocPath=plasma-discover/index.html ++InitialPreference=5 ++NoDisplay=false ++Actions=Updates; ++SingleMainWindow=true ++GenericName=Software Center ++Categories=Qt;KDE;System; ++Keywords=program;software;store;repository;package;add;install;uninstall;remove;update;apps;applications;games;flatpak;snap;addons;add-ons;firmware; +diff --git a/runners/services/autotests/fixtures/org.kde.kpat.desktop b/runners/services/autotests/fixtures/org.kde.kpat.desktop +index 71d7fd2a89..3a91d89afe 100644 +--- a/runners/services/autotests/fixtures/org.kde.kpat.desktop ++++ b/runners/services/autotests/fixtures/org.kde.kpat.desktop +@@ -1,7 +1,7 @@ + # SPDX-FileCopyrightText: 2022 Alexander Lohnau + # SPDX-License-Identifier: CC0-1.0 + [Desktop Entry] +-Name=KPatience ++Name=KPatience ServiceRunnerTest + Exec=true -qwindowtitle %c %u + Type=Application + Icon=kpat +diff --git a/runners/services/autotests/servicerunnertest.cpp b/runners/services/autotests/servicerunnertest.cpp +index fcfd3275ac..b911667a3b 100644 +--- a/runners/services/autotests/servicerunnertest.cpp ++++ b/runners/services/autotests/servicerunnertest.cpp +@@ -36,6 +36,10 @@ private Q_SLOTS: + void testINotifyUsage(); + void testSpecialArgs(); + void testEnv(); ++ void testDisassociation(); ++ void testMultipleKeywords(); ++ void testMultipleNameWords(); ++ void testDiscover(); + }; + + void ServiceRunnerTest::initTestCase() +@@ -86,8 +90,8 @@ void ServiceRunnerTest::testExecutableExactMatch() + + void ServiceRunnerTest::testKonsoleVsYakuakeComment() + { +- // Yakuake has konsole mentioned in comment, should be rated lower. +- const auto matches = launchQuery(QStringLiteral("kons")); ++ // Yakuake has konsole mentioned in comment, should not be listed (if it was it should be lower) ++ auto matches = launchQueryAndSort(QStringLiteral("kons")); + + bool konsoleFound = false; + bool yakuakeFound = false; +@@ -97,17 +101,10 @@ void ServiceRunnerTest::testKonsoleVsYakuakeComment() + continue; + } + +- if (match.text() == QLatin1String("Konsole ServiceRunnerTest")) { +- QCOMPARE(match.relevance(), 0.99); +- konsoleFound = true; +- } else if (match.text() == QLatin1String("Yakuake ServiceRunnerTest")) { +- // Rates lower because it doesn't have it in the name. +- QCOMPARE(match.relevance(), 0.59); +- yakuakeFound = true; +- } +- } +- QVERIFY(konsoleFound); +- QVERIFY(yakuakeFound); ++ QCOMPARE(texts, ++ QStringList({ ++ u"Konsole ServiceRunnerTest"_s, ++ })); + } + + void ServiceRunnerTest::testSystemSettings() +@@ -150,8 +147,9 @@ void ServiceRunnerTest::testSystemSettings2() + foreignSystemSettingsFound = true; + } + } +- QVERIFY(systemSettingsFound); +- QVERIFY(!foreignSystemSettingsFound); ++ ++ // The matched texts will contain much more because of the generic search term. Make sure our settings win. ++ QCOMPARE(texts.at(0), u"System Settings ServiceRunnerTest"_s); + } + + void ServiceRunnerTest::testCategories() +@@ -172,10 +170,6 @@ void ServiceRunnerTest::testCategories() + QVERIFY(std::none_of(matches.cbegin(), matches.cend(), [](const KRunner::QueryMatch &match) { + return match.text() == QLatin1String("Konsole ServiceRunnerTest"); + })); +- +- // Query too short to match any category +- matches = launchQuery(QStringLiteral("Dumm")); +- QVERIFY(matches.isEmpty()); + } + + void ServiceRunnerTest::testJumpListActions() +@@ -234,6 +228,68 @@ void ServiceRunnerTest::testEnv() + })); + } + ++void ServiceRunnerTest::testDisassociation() ++{ ++ // This test makes sure that we do not associate a service with a query that is not relevant. ++ auto matches = launchQueryAndSort(u"new laptop com"_s); // particularly notorious because it has two three letter words; 'com' is an incomplete word ++ ++ QStringList texts; ++ for (const auto &match : matches) { ++ texts.push_back(match.text()); ++ } ++ ++ QCOMPARE(texts, QStringList()); ++} ++ ++void ServiceRunnerTest::testMultipleKeywords() ++{ ++ auto matches = launchQueryAndSort(u"text editor programming"_s); ++ ++ QStringList texts; ++ for (const auto &match : matches) { ++ texts.push_back(match.text()); ++ } ++ ++ QCOMPARE(texts, ++ QStringList({ ++ u"Kate ServiceRunnerTest"_s, ++ })); ++} ++ ++void ServiceRunnerTest::testMultipleNameWords() ++{ ++ auto matches = launchQueryAndSort(u"system settings"_s); ++ ++ QStringList texts; ++ for (const auto &match : matches) { ++ if (!match.text().contains("ServiceRunnerTest"_L1)) { ++ continue; ++ } ++ texts.push_back(match.text()); ++ } ++ ++ QCOMPARE(texts, ++ QStringList({ ++ u"System Settings ServiceRunnerTest"_s, ++ })); ++} ++ ++void ServiceRunnerTest::testDiscover() ++{ ++ auto matches = launchQueryAndSort(u"disco"_s); ++ ++ QStringList texts; ++ for (const auto &match : matches) { ++ texts.push_back(match.text()); ++ } ++ ++ qDebug() << texts; ++ QCOMPARE(texts, ++ QStringList({ ++ u"Discover ServiceRunnerTest"_s, ++ })); ++} ++ + QTEST_MAIN(ServiceRunnerTest) + + #include "servicerunnertest.moc" +diff --git a/runners/services/bitap.h b/runners/services/bitap.h +new file mode 100644 +index 0000000000..a6aedb7eaf +--- /dev/null ++++ b/runners/services/bitap.h +@@ -0,0 +1,178 @@ ++// SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL ++// SPDX-FileCopyrightText: 2025 Harald Sitter ++ ++#pragma once ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++namespace Bitap ++{ ++ ++Q_DECLARE_LOGGING_CATEGORY(BITAP) ++Q_LOGGING_CATEGORY(BITAP, "org.kde.plasma.runner.services.bitap", QtWarningMsg) ++ ++struct Match { ++ qsizetype end; ++ qsizetype distance; ++ ++ bool operator==(const Match &other) const = default; ++}; ++ ++inline QDebug operator<<(QDebug dbg, const Bitap::Match &match) ++{ ++ dbg.nospace() << "Bitap::Match(" << match.end << ", " << match.distance << ")"; ++ return dbg; ++} ++ ++// Bitap is a bit of a complicated algorithm thanks to bitwise operations. I've opted to replace them with bitsets for readability. ++// It creates a patternMask based on all characters in the pattern. Basically each character gets assigned a representative bit. ++// e.g. in the pattern 'abc' the character 'a' would be 110, 'b' 101, 'c' 011. ++// This is a bit expensive up front but allows it to carry out everything else using bitwise operations. ++// For each match we set a matching bit in the bits vector. ++// Matching happens within a hamming distance, meaning up to `hammingDistance` characters can be out of place. ++inline std::optional bitap(const QStringView &name, const QStringView &pattern, int hammingDistance) ++{ ++ qCDebug(BITAP) << "Bitap called with name:" << name << "and pattern:" << pattern << "with hamming distance:" << hammingDistance; ++ const auto patternEndIndex = pattern.size() - 1; ++ if (name == pattern) { ++ return Match{.end = patternEndIndex, .distance = 0}; // Perfect match ++ } ++ ++ if (pattern.isEmpty() || name.isEmpty()) { ++ return std::nullopt; ++ } ++ ++ // Being a bitset we could have any number of bits, but practically we probably don't need more than 64, most bitaps I've seen even use 32. ++ constexpr auto maxMaskBits = 64; ++ using Mask = std::bitset; ++ using PatternMask = std::array::max()>; ++ ++ // The way bitap works is that each bit of the Mask represents a character position. Because of this we cannot match ++ // more characters than we have bits for. ++ // -1 because one bit is used for the result (I think) ++ if (pattern.size() >= qsizetype(Mask().size()) - 1) { ++ qCWarning(BITAP) << "Pattern is too long for bitap algorithm, max length is" << Mask().size() - 1; ++ return std::nullopt; ++ } ++ ++ const PatternMask patternMask = [&pattern, &name] { ++ PatternMask patternMask; ++ // The following is an optimized version of patternMask.fill(Mask().set()); to set all **necessary** bits to 1. ++ for (const auto &qchar : pattern) { ++ patternMask.at(qchar.unicode()).set(); ++ } ++ for (const auto &qchar : name) { ++ patternMask.at(qchar.unicode()).set(); ++ } ++ ++ for (int i = 0; i < pattern.size(); ++i) { ++ const auto char_ = pattern.at(i).unicode(); ++ patternMask.at(char_).reset(i); // unset the relevant index bits ++ } ++ ++ if (BITAP().isDebugEnabled()) { ++ for (const auto &i : pattern) { ++ const auto char_ = i.unicode(); ++ qCDebug(BITAP) << "Pattern mask for" << char_ << "is" << patternMask.at(char_).to_string(); ++ } ++ } ++ ++ return patternMask; ++ }(); ++ ++ Match match{ ++ .end = -1, // -1 means no match found for convenience ++ .distance = name.size(), ++ }; ++ ++ std::vector bits((hammingDistance + 1), Mask().set().reset(0)); ++ std::vector transpositions(bits.cbegin(), bits.cend()); ++ for (int i = 0; i < name.size(); ++i) { ++ const auto &char_ = name.at(i); ++ auto previousBit = bits[0]; ++ const auto mask = patternMask.at(char_.unicode()); ++ bits[0] |= mask; ++ bits[0] <<= 1; ++ ++ for (int j = 1; j <= hammingDistance; ++j) { ++ auto bit = bits[j]; ++ auto current = (bit | mask) << 1; ++ // https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance ++ auto substitute = previousBit << 1; ++ auto delete_ = bits[j - 1] << 1; ++ auto insert = previousBit; ++ auto transpose = (transpositions[j - 1] | (mask << 1)) << 1; ++ bits[j] = current & substitute & transpose & delete_ & insert; ++ transpositions[j - 1] = (previousBit << 1) | mask; ++ previousBit = bit; ++ } ++ ++ if (BITAP().isDebugEnabled()) { ++ qCDebug(BITAP) << "After processing character" << char_ << "at index" << i; ++ for (const auto &bit : bits) { ++ qCDebug(BITAP) << "bit" << bit.to_string(); ++ } ++ } ++ ++ for (int k = 0; k <= hammingDistance; ++k) { ++ // If the bit at the end of the mask is 0, it means we have a match. ++ if (0 == (bits[k] & Mask().set(pattern.size()))) { ++ if (k < match.distance && match.end < i) { ++ qCDebug(BITAP) << "Match found at index" << i << "with hamming distance" << k << "better than previous match with distance" ++ << match.distance << "at index" << match.end; ++ match = { ++ .end = i, ++ .distance = k, ++ }; ++ } ++ // We do not return early because we want to find the best match, not just any. ++ // e.g. with a maximum distance of 1 `disc` could match `disc` either at index two with distance one, or at index three with distance zero. ++ } ++ } ++ } ++ ++ // Because we use a complete Damerau–Levenshtein distance the return value is a bit complicated. The trick is that the distance incurs a negative penalty ++ // in relation to the max distance. While an end that is closer to the real end is generally favorably. Combining the two into a single value ++ // would complicate the meaning of the return value to mean "approximate end with random penalty". This is garbage to reason about so instead we return ++ // both values and then assign them meaning in the score function. ++ if (match.end != -1) { ++ return match; ++ } ++ ++ qCDebug(BITAP) << "No match found for pattern" << pattern << "in name" << name; ++ return std::nullopt; ++} ++ ++inline qreal score(const QStringView &name, const auto &match, auto hammingDistance) ++{ ++ // Normalize the score to a value between 0.0 and 1.0 ++ // No distance means the score is directly correlated to the end index. The more characters matched the higher the score. ++ // Any distance will lower the score by a sub 0.1 margin. ++ ++ if (name.size() == 0) { ++ return 0.0; // No name, no score. ++ } ++ ++ const auto maxEnd = name.size() - 1; ++ const auto penalty = [&] { ++ if (hammingDistance <= 0) { ++ return 1.0; // No penalty for no distance ++ } ++ constexpr auto tenth = 10.0; ++ constexpr auto half = 2.0; ++ return qreal(match.distance) / qreal(hammingDistance) / tenth / half; ++ }(); ++ auto score = qreal(match.end) / qreal(maxEnd); ++ // Prevent underflows when the penalty is larger than the score. ++ score = std::max(0.0, score - penalty); ++ ++ Q_ASSERT(score >= 0.0 && score <= 1.0); ++ return score; ++} ++ ++} // namespace Bitap +diff --git a/runners/services/levenshtein.h b/runners/services/levenshtein.h +new file mode 100644 +index 0000000000..0efb960be3 +--- /dev/null ++++ b/runners/services/levenshtein.h +@@ -0,0 +1,58 @@ ++// SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL ++// SPDX-FileCopyrightText: 2025 Harald Sitter ++ ++#pragma ++ ++#include ++#include ++ ++namespace Levenshtein ++{ ++ ++inline int distance(const QStringView &name, const QStringView &query) ++{ ++ if (name == query) { ++ return 0; ++ } ++ ++ std::vector distance0(query.size() + 1, 0); ++ std::vector distance1(query.size() + 1, 0); ++ ++ for (int i = 0; i <= query.size(); ++i) { ++ distance0[i] = i; ++ } ++ ++ for (int i = 0; i < name.size(); ++i) { ++ distance1[0] = i + 1; ++ for (int j = 0; j < query.size(); ++j) { ++ const auto deletionCost = distance0[j + 1] + 1; ++ const auto insertionCost = distance1[j] + 1; ++ const auto substitutionCost = [&] { ++ if (name[i] == query[j]) { ++ return distance0[j]; ++ } ++ return distance0[j] + 1; ++ }(); ++ distance1[j + 1] = std::min({deletionCost, insertionCost, substitutionCost}); ++ } ++ std::swap(distance0, distance1); ++ } ++ return distance0[query.size()]; ++} ++ ++inline qreal score(const QStringView &name, int distance) ++{ ++ // Normalize the distance to a value between 0.0 and 1.0 ++ // The maximum distance is the length of the pattern. ++ // If the distance is 0, it means a perfect match, so we return 1.0. ++ // If the distance is equal to the length of the pattern, we return 0.0. ++ if (distance == 0) { ++ return 1.0; ++ } ++ if (distance >= name.size()) { ++ return 0.0; ++ } ++ return 1.0 - (qreal(distance) / qreal(name.size())); ++} ++ ++} // namespace Levenshtein +diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp +index eb9f02e74b..3d5de8feb2 100644 +--- a/runners/services/servicerunner.cpp ++++ b/runners/services/servicerunner.cpp +@@ -1,7 +1,7 @@ + /* + SPDX-FileCopyrightText: 2006 Aaron Seigo + SPDX-FileCopyrightText: 2014 Vishesh Handa +- SPDX-FileCopyrightText: 2016-2020 Harald Sitter ++ SPDX-FileCopyrightText: 2016-2025 Harald Sitter + SPDX-FileCopyrightText: 2022-2023 Alexander Lohnau + + SPDX-License-Identifier: LGPL-2.0-only +@@ -21,6 +21,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -35,22 +36,130 @@ + #include + #include + ++#include "bitap.h" + #include "debug.h" ++#include "levenshtein.h" + + using namespace Qt::StringLiterals; + namespace + { + +-int weightedLength(const QString &query) ++struct Score { ++ qreal value = 0.0; // The final score, it is the sum of all scores. ++ KRunner::QueryMatch::CategoryRelevance categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Lowest; // The category relevance of the match. ++}; ++ ++struct ScoreCard { ++ Bitap::Match bitap; ++ qreal bitapScore; ++ int levenshtein; ++ qreal levenshteinScore; ++}; ++ ++QDebug operator<<(QDebug dbg, const ScoreCard &card) + { +- return KStringHandler::logicalLength(query); ++ dbg.nospace() << "Scorecard(" << "bitap: " << card.bitap << ", bitapScore: " << card.bitapScore << ", levenshtein: " << card.levenshtein ++ << ", levenshteinScore: " << card.levenshteinScore << ")"; ++ return dbg; + } + +-inline bool contains(const QString &result, const QList &queryList) ++using ScoreCards = std::vector; ++ ++struct WeightedScoreCard { ++ ScoreCards cards; ++ qreal weight; ++}; ++ ++QDebug operator<<(QDebug dbg, const WeightedScoreCard &card) + { +- return std::ranges::all_of(queryList, [&result](QStringView query) { +- return result.contains(query, Qt::CaseInsensitive); +- }); ++ ++ dbg.nospace() << "WeightedCard["; ++ for (const auto &scoreCard : card.cards) { ++ dbg.nospace() << scoreCard; ++ if (&scoreCard != &card.cards.back()) { ++ dbg.nospace() << ", "; ++ } ++ } ++ dbg.nospace() << "]"; ++ return dbg; ++} ++ ++auto makeScores(const auto ¬NormalizedString, const auto &queryList) { ++ if (notNormalizedString.isEmpty()) { ++ return ScoreCards{}; // No string, no score. ++ } ++ ++ const auto string = notNormalizedString.toLower(); ++ ++ ScoreCards cards; ++ for (const auto &queryItem : queryList) { ++ constexpr auto maxDistance = 1; ++ const auto bitap = Bitap::bitap(string, queryItem, maxDistance); ++ if (!bitap) { ++ // One of the query items didn't match. This means the entire query is not a match ++ return ScoreCards{}; ++ } ++ ++ const auto bitapScore = Bitap::score(string, bitap.value(), maxDistance); ++ ++ // Mind that we give different levels of bonus. This is important to imply ordering within competing matches of the same "type". ++ // If we perfectly match that gives a bonus for not requiring any changes. ++ const auto noSubstitionBonus = Bitap::score(string, bitap.value(), 0) == 1.0 ? 4.0 : 1.0; ++ // If we match the entire length of the string that gets a bonus (disregarding distance, that was considered above). ++ const auto completeMatchBonus = bitap->end >= (queryItem.size() - 1) ? 3.0 : 1.0; ++ // If the string starts with the query item that gets a bonus. ++ const auto startsWithBonus = (string.startsWith(queryItem, Qt::CaseInsensitive)) ? 2.0 : 1.0; ++ ++ // Also consider the distance between the input and the query item. ++ // If one is "yolotrollingservice" and the other is "yolo" then we must consider them worse matches than say "yolotroll". ++ const auto levenshtein = Levenshtein::distance(string, queryItem); ++ ++ cards.emplace_back(ScoreCard{ ++ .bitap = *bitap, ++ .bitapScore = bitapScore + completeMatchBonus + noSubstitionBonus + startsWithBonus, ++ .levenshtein = levenshtein, ++ .levenshteinScore = Levenshtein::score(string, levenshtein), ++ }); ++ } ++ ++ return cards; ++}; ++ ++ ++auto makeScoreFromList(const auto &queryList, const QStringList &strings) { ++ // This turns the loop inside out. For every query item we must find a match in our keywords or we discard ++ ScoreCards cards; ++ // e.g. text,editor,programming ++ for (const auto &queryItem : queryList) { ++ // e.g. text;txt;editor;programming;programmer;development;developer;code; ++ auto found = false; ++ ScoreCards queryCards; ++ for (const auto &string : strings) { ++ auto stringCards = makeScores(string, QList{queryItem}); ++ if (stringCards.empty()) { ++ continue; // The combination didn't match. ++ } ++ for (auto &scoreCard : stringCards) { ++ if (scoreCard.levenshteinScore < 0.8) { ++ continue; // Not a good match, skip it. We are very strict with keywords ++ } ++ found = true; ++ queryCards.append_range(stringCards); ++ } ++ // We do not break because other string might also match, improving the score. ++ } ++ if (!found) { ++ // No item in strings matched the query item. This means the entire query is not a match. ++ return ScoreCards{}; ++ } ++ cards.append_range(queryCards); ++ } ++ return cards; ++}; ++ ++int weightedLength(const QString &query) ++{ ++ return KStringHandler::logicalLength(query); + } + + inline bool contains(const QStringList &results, const QList &queryList) +@@ -79,7 +188,7 @@ public: + + void match(KRunner::RunnerContext &context) + { +- query = context.query(); ++ query = context.query().toLower(); + // Splitting the query term to match using subsequences + queryList = QStringView(query).split(QLatin1Char(' ')); + weightedTermLength = weightedLength(query); +@@ -120,36 +229,6 @@ private: + return ret; + } + +- enum class Category { +- Name, +- GenericName, +- Comment, +- }; +- qreal increaseMatchRelevance(const QString &serviceProperty, const QList &strList, Category category) +- { +- // Increment the relevance based on all the words (other than the first) of the query list +- qreal relevanceIncrement = 0; +- +- for (int i = 1; i < strList.size(); ++i) { +- const auto &str = strList.at(i); +- if (category == Category::Name) { +- if (serviceProperty.contains(str, Qt::CaseInsensitive)) { +- relevanceIncrement += 0.01; +- } +- } else if (category == Category::GenericName) { +- if (serviceProperty.contains(str, Qt::CaseInsensitive)) { +- relevanceIncrement += 0.01; +- } +- } else if (category == Category::Comment) { +- if (serviceProperty.contains(str, Qt::CaseInsensitive)) { +- relevanceIncrement += 0.01; +- } +- } +- } +- +- return relevanceIncrement; +- } +- + void setupMatch(const KService::Ptr &service, KRunner::QueryMatch &match) + { + const QString name = service->name(); +@@ -219,96 +298,77 @@ private: + return resultingArgs.join(QLatin1Char(' ')); + } + +- void matchNameKeywordAndGenericName() ++ [[nodiscard]] std::optional fuzzyScore(KService::Ptr service) + { +- const auto nameKeywordAndGenericNameFilter = [this](const KService::Ptr &service) { +- // Name +- if (contains(service->name(), queryList)) { +- return true; +- } +- // If the term length is < 3, no real point searching the untranslated Name, Keywords and GenericName +- if (weightedTermLength < 3) { +- return false; +- } +- if (contains(service->untranslatedName(), queryList)) { +- return true; +- } ++ if (queryList.isEmpty()) { ++ return std::nullopt; // No query, no score. ++ } ++ ++ const auto name = service->name(); ++ if (name.compare(query, Qt::CaseInsensitive) == 0) { ++ // Absolute match. Can't get any better than this. ++ return Score{.value = std::numeric_limits::max(), .categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Highest}; ++ } + +- // Keywords +- if (contains(service->keywords(), queryList)) { +- return true; ++ std::array weightedCards = { ++ WeightedScoreCard{.cards = makeScores(name, queryList), .weight = 1.0}, ++ WeightedScoreCard{.cards = makeScores(service->untranslatedName(), queryList), .weight = 0.8}, ++ WeightedScoreCard{.cards = makeScores(service->genericName(), queryList), .weight = 0.6}, ++ WeightedScoreCard{.cards = makeScoreFromList(queryList, service->keywords()), .weight = 0.1}, ++ }; ++ ++ if (RUNNER_SERVICES().isDebugEnabled()) { ++ qCDebug(RUNNER_SERVICES) << "+++++++ Weighted Cards for" << name; ++ for (const auto &weightedCard : weightedCards) { ++ qCDebug(RUNNER_SERVICES) << weightedCard; + } +- // GenericName +- if (contains(service->genericName(), queryList) || contains(service->untranslatedGenericName(), queryList)) { +- return true; ++ qCDebug(RUNNER_SERVICES) << "-------"; ++ } ++ ++ int scores = 1; // starts at 1 to avoid division by zero ++ qreal finalScore = 0.0; ++ for (const auto &weightedCard : weightedCards) { ++ if (weightedCard.cards.empty()) { ++ continue; // No scores, no match. + } +- // Comment +- if (contains(service->comment(), queryList)) { +- return true; ++ ++ qreal weightedScore = 0.0; ++ for (const auto &scoreCard : weightedCard.cards) { ++ weightedScore += (scoreCard.bitapScore + scoreCard.levenshteinScore) * weightedCard.weight; ++ scores++; + } + +- return false; +- }; ++ finalScore += weightedScore; ++ } ++ finalScore = finalScore / scores; // Average the score for this card + +- for (const KService::Ptr &service : m_services) { +- if (!nameKeywordAndGenericNameFilter(service) || disqualify(service)) { +- continue; +- } ++ qCDebug(RUNNER_SERVICES) << "Final score for" << name << "is" << finalScore; ++ if (finalScore > 0.0) { ++ return Score{.value = finalScore, .categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Moderate}; ++ } + +- const QString id = service->storageId(); +- const QString name = service->name(); ++ return std::nullopt; ++ } + +- KRunner::QueryMatch::CategoryRelevance categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Moderate; +- qreal relevance(0.6); ++ void matchNameKeywordAndGenericName() ++ { ++ static auto isTest = QStandardPaths::isTestModeEnabled(); + +- // If the term was < 3 chars and NOT at the beginning of the App's name, then chances are the user doesn't want that app +- if (weightedTermLength < 3) { +- if (name.startsWith(query, Qt::CaseInsensitive)) { +- relevance = 0.9; +- } else { +- continue; +- } +- } else if (name.compare(query, Qt::CaseInsensitive) == 0) { +- relevance = 1; +- categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Highest; +- } else if (const auto idx = name.indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { +- relevance = 0.8; +- relevance += increaseMatchRelevance(name, queryList, Category::Name); +- if (idx == 0) { +- relevance += 0.1; +- categoryRelevance = KRunner::QueryMatch::CategoryRelevance::High; +- } +- } else if (const auto idx = service->genericName().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { +- relevance = 0.65; +- relevance += increaseMatchRelevance(service->genericName(), queryList, Category::GenericName); +- if (idx == 0) { +- relevance += 0.05; +- } +- } else if (const auto idx = service->comment().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { +- relevance = 0.5; +- relevance += increaseMatchRelevance(service->comment(), queryList, Category::Comment); +- if (idx == 0) { +- relevance += 0.05; +- } ++ for (const KService::Ptr &service : m_services) { ++ if (isTest && !service->name().contains("ServiceRunnerTest"_L1)) { ++ continue; // Skip services that are not part of the test. + } + + KRunner::QueryMatch match(m_runner); +- match.setCategoryRelevance(categoryRelevance); +- setupMatch(service, match); +- if (service->categories().contains(QLatin1String("KDE"))) { +- qCDebug(RUNNER_SERVICES) << "found a kde thing" << id << match.subtext() << relevance; +- relevance += .09; +- } +- +- if (const auto foundIt = m_runner->m_favorites.constFind(service->desktopEntryName()); foundIt != m_runner->m_favorites.cend()) { +- if (foundIt->isGlobal || foundIt->linkedActivities.contains(m_currentActivity)) { +- qCDebug(RUNNER_SERVICES) << "entry is a favorite" << id << match.subtext() << relevance; +- relevance *= 1.25; // Give favorites a relative boost, +- } ++ auto score = fuzzyScore(service); ++ if (!score || disqualify(service)) { ++ continue; + } + +- qCDebug(RUNNER_SERVICES) << name << "is this relevant:" << relevance; +- match.setRelevance(relevance); ++ setupMatch(service, match); ++ match.setCategoryRelevance(score->categoryRelevance); ++ match.setRelevance(score->value); ++ qCDebug(RUNNER_SERVICES) << match.text() << "is this relevant:" << match.relevance() << "category relevance" << match.categoryRelevance(); + + matches << match; + } +-- +2.51.0 + diff --git a/roles/kde/patches/plasma-workspace/pr5734.patch b/roles/kde/patches/plasma-workspace/pr5734.patch new file mode 100644 index 0000000..ffe6605 --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5734.patch @@ -0,0 +1,133 @@ +From 0168ee68b484995ed9398d31004dd80678ac7e37 Mon Sep 17 00:00:00 2001 +From: Kai Uwe Broulik +Date: Tue, 5 Aug 2025 12:57:00 +0200 +Subject: [PATCH] Close USB device added notification when devicenotifier pops + up + +The device notification is supposed to be super quick feedback that +"something" got detected. Once it has been identified as storage +device (disks spun up and what not), devicenotifier will show up +and then you have two popups. +--- + applets/devicenotifier/CMakeLists.txt | 1 + + applets/devicenotifier/devicefiltercontrol.cpp | 14 ++++++++++++++ + applets/devicenotifier/devicefiltercontrol.h | 1 + + applets/devicenotifier/qml/main.qml | 1 + + devicenotifications/devicenotifications.cpp | 8 ++++++++ + devicenotifications/devicenotifications.h | 3 +++ + 6 files changed, 28 insertions(+) + +diff --git a/applets/devicenotifier/CMakeLists.txt b/applets/devicenotifier/CMakeLists.txt +index d87964dc46d..fa415837e68 100644 +--- a/applets/devicenotifier/CMakeLists.txt ++++ b/applets/devicenotifier/CMakeLists.txt +@@ -31,6 +31,7 @@ plasma_add_applet(org.kde.plasma.devicenotifier + + target_link_libraries(org.kde.plasma.devicenotifier + PRIVATE ++ Qt::DBus + Qt::Qml + Plasma::Plasma + KF6::Solid +diff --git a/applets/devicenotifier/devicefiltercontrol.cpp b/applets/devicenotifier/devicefiltercontrol.cpp +index dfdb51a4304..f585eb2f063 100644 +--- a/applets/devicenotifier/devicefiltercontrol.cpp ++++ b/applets/devicenotifier/devicefiltercontrol.cpp +@@ -11,9 +11,14 @@ + #include "devicecontrol.h" + #include "devicestatemonitor_p.h" + ++#include ++#include ++ + #include + #include + ++using namespace Qt::Literals::StringLiterals; ++ + DeviceFilterControl::DeviceFilterControl(QObject *parent) + : QSortFilterProxyModel(parent) + , m_filterType(Removable) +@@ -54,6 +59,15 @@ void DeviceFilterControl::unmountAllRemovables() + qCDebug(APPLETS::DEVICENOTIFIER) << "Device Filter Control: unmount all removables function finished"; + } + ++void DeviceFilterControl::dismissUsbDeviceAddedNotification() ++{ ++ QDBusMessage msg = QDBusMessage::createMethodCall(u"org.kde.kded6"_s, ++ u"/modules/devicenotifications"_s, ++ u"org.kde.plasma.devicenotifications"_s, ++ u"dismissUsbDeviceAdded"_s); ++ QDBusConnection::sessionBus().call(msg, QDBus::NoBlock); ++} ++ + QBindable DeviceFilterControl::bindableLastUdi() + { + return &m_lastUdi; +diff --git a/applets/devicenotifier/devicefiltercontrol.h b/applets/devicenotifier/devicefiltercontrol.h +index e4c0a321657..fa6266fb197 100644 +--- a/applets/devicenotifier/devicefiltercontrol.h ++++ b/applets/devicenotifier/devicefiltercontrol.h +@@ -41,6 +41,7 @@ public: + Q_ENUM(DevicesType) + + Q_INVOKABLE void unmountAllRemovables(); ++ Q_INVOKABLE void dismissUsbDeviceAddedNotification(); + + explicit DeviceFilterControl(QObject *parent = nullptr); + ~DeviceFilterControl() override; +diff --git a/applets/devicenotifier/qml/main.qml b/applets/devicenotifier/qml/main.qml +index 7fcd76a6d16..c7fe6e6197d 100644 +--- a/applets/devicenotifier/qml/main.qml ++++ b/applets/devicenotifier/qml/main.qml +@@ -35,6 +35,7 @@ PlasmoidItem { + onLastUdiChanged: { + if (lastDeviceAdded) { + if (Plasmoid.configuration.popupOnNewDevice) { ++ filterModel.dismissUsbDeviceAddedNotification(); + devicenotifier.expanded = true; + fullRepresentationItem.spontaneousOpen = true; + } +diff --git a/devicenotifications/devicenotifications.cpp b/devicenotifications/devicenotifications.cpp +index 71ae0ff340e..196e28ca948 100644 +--- a/devicenotifications/devicenotifications.cpp ++++ b/devicenotifications/devicenotifications.cpp +@@ -323,6 +323,14 @@ void KdedDeviceNotifications::setupWaylandOutputListener() + wl_callback_add_listener(syncCallback, &syncCallbackListener, this); + } + ++void KdedDeviceNotifications::dismissUsbDeviceAdded() ++{ ++ if (m_usbDeviceAddedNotification) { ++ m_usbDeviceAddedNotification->close(); ++ m_usbDeviceAddedNotification = nullptr; ++ } ++} ++ + void KdedDeviceNotifications::notifyOutputAdded() + { + if (m_deviceAddedTimer.isActive()) { +diff --git a/devicenotifications/devicenotifications.h b/devicenotifications/devicenotifications.h +index ab7e6b3ff9b..75005193287 100644 +--- a/devicenotifications/devicenotifications.h ++++ b/devicenotifications/devicenotifications.h +@@ -77,6 +77,7 @@ private: + class KdedDeviceNotifications : public KDEDModule + { + Q_OBJECT ++ Q_CLASSINFO("D-Bus Interface", "org.kde.plasma.devicenotifications") + + public: + KdedDeviceNotifications(QObject *parent, const QVariantList &args); +@@ -84,6 +85,8 @@ public: + + void setupWaylandOutputListener(); + ++ Q_SCRIPTABLE void dismissUsbDeviceAdded(); ++ + private: + void notifyOutputAdded(); + void notifyOutputRemoved(); +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/pr5746.patch b/roles/kde/patches/plasma-workspace/pr5746.patch new file mode 100644 index 0000000..d4eace1 --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5746.patch @@ -0,0 +1,33 @@ +From f6ec2847358178a5b6ff0497e52d1e2be43d2a48 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Luan=20Vitor=20Simi=C3=A3o=20oliveira?= + +Date: Fri, 8 Aug 2025 14:41:49 -0300 +Subject: [PATCH] kcms/style: add special case for Adwaita gtk theme + +Allows the user to set the GTK theme to the default "Adwaita" +needs to be special cased because the theme is implemented in code. +--- + kcms/style/gtkthemesmodel.cpp | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/kcms/style/gtkthemesmodel.cpp b/kcms/style/gtkthemesmodel.cpp +index 002e87dbd0d..6dcdf4f1a1d 100644 +--- a/kcms/style/gtkthemesmodel.cpp ++++ b/kcms/style/gtkthemesmodel.cpp +@@ -35,7 +35,12 @@ void GtkThemesModel::load() + if (possibleThemeDirectory.dirName() == u"Breeze-Dark") { + continue; + } +- ++ if (possibleThemeDirectory.dirName() == u"Default") { ++ // Adwaita is a special case, since it is implemented inside GTK itself ++ // also setting gtk-theme-name to "Default" breaks dark theme ++ gtk3ThemesNames.insert(QStringLiteral("Adwaita"), possibleThemeDirectory.path()); ++ continue; ++ } + gtk3ThemesNames.insert(possibleThemeDirectory.dirName(), possibleThemeDirectory.path()); + } + } +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/pr5782.patch b/roles/kde/patches/plasma-workspace/pr5782.patch new file mode 100644 index 0000000..a20c5e1 --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5782.patch @@ -0,0 +1,32 @@ +From 4ab3894d75e1f9c6c7738a893a9b707ff0575953 Mon Sep 17 00:00:00 2001 +From: Nate Graham +Date: Thu, 21 Aug 2025 19:37:33 -0600 +Subject: [PATCH] notifications: make "you missed some notifications" + notification transient + +Its purpose is to direct you to the notifications history. If you're +seeing it *in* the notification history, its purpose has been bypassed +because you're already where it wanted to take you. + +Don't show it in the notification history. +--- + libnotificationmanager/notifications.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/libnotificationmanager/notifications.cpp b/libnotificationmanager/notifications.cpp +index f68c342e7e9..128665f4de9 100644 +--- a/libnotificationmanager/notifications.cpp ++++ b/libnotificationmanager/notifications.cpp +@@ -917,6 +917,9 @@ void Notifications::showInhibitionSummary(Urgency urgency, const QStringList &bl + notification->setIconName(u"preferences-desktop-notification-bell"_s); + notification->setFlags(KNotification::CloseOnTimeout); + notification->setComponentName(u"libnotificationmanager"_s); ++ // Don't put it in the history because this doesn't make sense; if you're seeing it ++ // in the history, you're seeing the notifications it was telling you about! ++ notification->setHint(u"transient"_s, true); + + const QString showNotificationsText = i18nc("@action:button Show the notifications popup", "Show Notifications"); + +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/pr5788.patch b/roles/kde/patches/plasma-workspace/pr5788.patch new file mode 100644 index 0000000..96f3980 --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5788.patch @@ -0,0 +1,42 @@ +From f0d2dd20803f2eee364d26656715b89e7c74366c Mon Sep 17 00:00:00 2001 +From: David Redondo +Date: Wed, 27 Aug 2025 09:40:43 +0200 +Subject: [PATCH] servicerunner: use vector::insert on compilers that don't + support append_range yet + +g++ only gained support for it with g++ 15 which was released this month. +--- + runners/services/servicerunner.cpp | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp +index 2ccc9a0af37..9e9d4e70a72 100644 +--- a/runners/services/servicerunner.cpp ++++ b/runners/services/servicerunner.cpp +@@ -142,7 +142,11 @@ auto makeScoreFromList(const auto &queryList, const QStringList &strings) { + continue; // Not a good match, skip it. We are very strict with keywords + } + found = true; ++#ifdef __cpp_lib_containers_ranges + queryCards.append_range(stringCards); ++#else ++ queryCards.insert(queryCards.end(), stringCards.cbegin(), stringCards.cend()); ++#endif + } + // We do not break because other string might also match, improving the score. + } +@@ -150,7 +154,11 @@ auto makeScoreFromList(const auto &queryList, const QStringList &strings) { + // No item in strings matched the query item. This means the entire query is not a match. + return ScoreCards{}; + } ++#ifdef __cpp_lib_containers_ranges + cards.append_range(queryCards); ++#else ++ cards.insert(cards.end(), queryCards.cbegin(), queryCards.cend()); ++#endif + } + return cards; + }; +-- +GitLab + From ccebf381b0817367dfc110aec8cd866ab6be18d0 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Sep 2025 17:02:08 +0200 Subject: [PATCH 1042/1125] Server/beets: configure permissions plugin --- roles/server/beets.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/roles/server/beets.nix b/roles/server/beets.nix index c865039..bb98cfd 100644 --- a/roles/server/beets.nix +++ b/roles/server/beets.nix @@ -38,7 +38,12 @@ in { "unimported" "fetchart" "chroma" + "permissions" ]; + permissions = { + file = "644"; + folder = "755"; + }; }; }; }; From 8fdeb93bc5420333d8984a93c4cb2b4fdab21217 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 22 Sep 2025 17:41:39 +0200 Subject: [PATCH 1043/1125] Server: add minecraft --- roles/server/default.nix | 1 + roles/server/minecraft.nix | 99 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 roles/server/minecraft.nix diff --git a/roles/server/default.nix b/roles/server/default.nix index 44f1b3c..6ffed7e 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -21,5 +21,6 @@ ./copyparty.nix ./beets.nix ./navidrome.nix + ./minecraft.nix ]; } diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix new file mode 100644 index 0000000..138c379 --- /dev/null +++ b/roles/server/minecraft.nix @@ -0,0 +1,99 @@ +{ + pkgs, + config, + ... +}: let + stopScript = pkgs.writeShellScript "minecraft-server-stop" '' + echo stop > ${config.systemd.sockets.minecraft-server-sf5.socketConfig.ListenFIFO} + + # Wait for the PID of the minecraft server to disappear before + # returning, so systemd doesn't attempt to SIGKILL it. + while kill -0 "$1" 2> /dev/null; do + sleep 1s + done + ''; +in { + fileSystems = { + "/var/lib/minecraft" = { + device = "/dev/disk/by-uuid/5322c217-b87b-4150-8b4c-a8fa17a899bf"; + fsType = "btrfs"; + options = ["subvol=@minecraft"]; + }; + }; + users.users.sf5 = { + isSystemUser = true; + group = "sf5"; + }; + users.groups.sf5 = {}; + systemd.tmpfiles.settings = { + music."/var/lib/minecraft/sf5" = { + d = { + age = "-"; + user = "sf5"; + group = "sf5"; + mode = "0755"; + }; + }; + }; + networking.firewall.allowedTCPPorts = [25565]; + systemd.sockets.minecraft-server-sf5 = { + bindsTo = ["minecraft-server-sf5.service"]; + socketConfig = { + ListenFIFO = "/run/minecraft-server-sf5.stdin"; + SocketMode = "0660"; + SocketUser = "sf5"; + SocketGroup = "sf5"; + RemoveOnStop = true; + FlushPending = true; + }; + }; + systemd.services.minecraft-server-sf5 = { + description = "Minecraft Server (Sky Factory 5)"; + wantedBy = ["multi-user.target"]; + requires = ["minecraft-server-sf5.socket"]; + after = [ + "network.target" + "minecraft-server-sf5.socket" + ]; + + path = [pkgs.jdk17 pkgs.bash]; + + serviceConfig = { + ExecStart = "/var/lib/minecraft/sf5/run.sh"; + ExecStop = "${stopScript} $MAINPID"; + Restart = "always"; + User = "sf5"; + WorkingDirectory = "/var/lib/minecraft/sf5"; + + StandardInput = "socket"; + StandardOutput = "journal"; + StandardError = "journal"; + + # Hardening + CapabilityBoundingSet = [""]; + DeviceAllow = [""]; + LockPersonality = true; + PrivateDevices = true; + PrivateTmp = true; + PrivateUsers = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + UMask = "0077"; + }; + }; + programs.rust-motd.settings.service_status."Minecraft (SkyFactory 5)"= "minecraft-server-sf5"; +} From 57125b4bf88ea0b2dbef553b0fd7cf841d41ffc3 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Sep 2025 00:01:11 +0200 Subject: [PATCH 1044/1125] Flake: add nixpkgs patches --- flake.nix | 2 ++ nixpkgs-patches/pr441705.patch | 35 ++++++++++++++++++++++++++++++++++ nixpkgs-patches/pr442482.patch | 35 ++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 nixpkgs-patches/pr441705.patch create mode 100644 nixpkgs-patches/pr442482.patch diff --git a/flake.nix b/flake.nix index 1f699e7..d875ca3 100644 --- a/flake.nix +++ b/flake.nix @@ -101,6 +101,8 @@ src = nixpkgs-unstable-raw; patches = [ ./nixpkgs-patches/plasma-workspace-patch-trimming.patch + ./nixpkgs-patches/pr441705.patch + ./nixpkgs-patches/pr442482.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr441705.patch b/nixpkgs-patches/pr441705.patch new file mode 100644 index 0000000..f9b446d --- /dev/null +++ b/nixpkgs-patches/pr441705.patch @@ -0,0 +1,35 @@ +From 9cde39ee9db16f4b3cb63b4416377277b7c293b6 Mon Sep 17 00:00:00 2001 +From: Robert Helgesson +Date: Wed, 10 Sep 2025 10:11:56 +0200 +Subject: [PATCH] sd-switch: 0.6.0 -> 0.6.1 + +--- + pkgs/by-name/sd/sd-switch/package.nix | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/pkgs/by-name/sd/sd-switch/package.nix b/pkgs/by-name/sd/sd-switch/package.nix +index 72eebfbef61002..f7e4f1a9a01a61 100644 +--- a/pkgs/by-name/sd/sd-switch/package.nix ++++ b/pkgs/by-name/sd/sd-switch/package.nix +@@ -6,7 +6,7 @@ + }: + + let +- version = "0.6.0"; ++ version = "0.6.1"; + in + rustPlatform.buildRustPackage { + pname = "sd-switch"; +@@ -16,10 +16,10 @@ rustPlatform.buildRustPackage { + owner = "~rycee"; + repo = "sd-switch"; + rev = version; +- hash = "sha256-IZ2tyQzWa2Uk002P9jCiaIV3huRiFdTe8eYXVQPBBJI="; ++ hash = "sha256-2Zdgwov+a35OzH6pzXbgxxABI8GDO9z068gLpmE2Jk4="; + }; + +- cargoHash = "sha256-ExQPCA8sAZVE5uB1KUnq6PXGhG1IZjzM9eFwYW3oJtE="; ++ cargoHash = "sha256-At0qo9w+/8sk9BnaZiG870iO8KLkhg2E40VCzQvvPWk="; + + passthru = { + updateScript = nix-update-script { }; diff --git a/nixpkgs-patches/pr442482.patch b/nixpkgs-patches/pr442482.patch new file mode 100644 index 0000000..c6022f9 --- /dev/null +++ b/nixpkgs-patches/pr442482.patch @@ -0,0 +1,35 @@ +From ede83dc17a58d6e846a0125c87dd18dc3abfe2a5 Mon Sep 17 00:00:00 2001 +From: Robert Helgesson +Date: Fri, 12 Sep 2025 23:25:31 +0200 +Subject: [PATCH] sd-switch: 0.6.1 -> 0.6.2 + +--- + pkgs/by-name/sd/sd-switch/package.nix | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/pkgs/by-name/sd/sd-switch/package.nix b/pkgs/by-name/sd/sd-switch/package.nix +index f7e4f1a9a01a61..85ae7e1c0e3552 100644 +--- a/pkgs/by-name/sd/sd-switch/package.nix ++++ b/pkgs/by-name/sd/sd-switch/package.nix +@@ -6,7 +6,7 @@ + }: + + let +- version = "0.6.1"; ++ version = "0.6.2"; + in + rustPlatform.buildRustPackage { + pname = "sd-switch"; +@@ -16,10 +16,10 @@ rustPlatform.buildRustPackage { + owner = "~rycee"; + repo = "sd-switch"; + rev = version; +- hash = "sha256-2Zdgwov+a35OzH6pzXbgxxABI8GDO9z068gLpmE2Jk4="; ++ hash = "sha256-3+FGARca3xcCYKEAxtrhnSnpOP2JZurOPzKvNhAYjkg="; + }; + +- cargoHash = "sha256-At0qo9w+/8sk9BnaZiG870iO8KLkhg2E40VCzQvvPWk="; ++ cargoHash = "sha256-jclRF05eUAW/ggCmfZfWE6c4q25d/WGX0dad4rsP8vk="; + + passthru = { + updateScript = nix-update-script { }; From 86fe2646d12d463e31ad49e53c5d8c73efbc3aa5 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 26 Sep 2025 18:43:27 +0200 Subject: [PATCH 1045/1125] KDE/Patches: don't garbage collect the -patched packages --- roles/kde/patches/default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/kde/patches/default.nix b/roles/kde/patches/default.nix index 86198ed..93ab1cb 100644 --- a/roles/kde/patches/default.nix +++ b/roles/kde/patches/default.nix @@ -38,4 +38,7 @@ in { newDependency = pkgs.kdePackages."${package}-patched"; } ); + system.extraDependencies = lib.lists.forEach programsToPatch ( + package: pkgs.kdePackages."${package}-patched" + ); } From 75312f7622f9c2818e24ddf1c70810af86c527e1 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 22 Sep 2025 18:25:32 +0200 Subject: [PATCH 1046/1125] Server/copyparty: set up db directory, enable rproxy --- roles/server/copyparty.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/server/copyparty.nix b/roles/server/copyparty.nix index 99822a0..1cb52cd 100644 --- a/roles/server/copyparty.nix +++ b/roles/server/copyparty.nix @@ -5,6 +5,8 @@ settings = { i = ["unix:770:caddy:/dev/shm/copyparty.socket"]; + hist = "/var/cache/copyparty"; + rproxy = 1; }; volumes = { From 2fc9fe9e1a2e5f2067bfb4a1e5705a540d5b7807 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 22 Sep 2025 18:26:08 +0200 Subject: [PATCH 1047/1125] Server/beets: make music library accesible with copyparty --- roles/server/beets.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/roles/server/beets.nix b/roles/server/beets.nix index bb98cfd..fc69963 100644 --- a/roles/server/beets.nix +++ b/roles/server/beets.nix @@ -22,6 +22,13 @@ in { }; }; + services.copyparty = { + volumes."/Music" = { + path = "/srv/music"; + access.r = "*"; + }; + }; + home-manager.users.toast = {config, ...}: { programs.beets = { enable = true; From 8597f372c02d09d59860d9af27e92536dfbd2c56 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Sep 2025 19:28:35 +0200 Subject: [PATCH 1048/1125] Flake: remove unneeded patches --- flake.nix | 2 -- nixpkgs-patches/pr441705.patch | 35 ---------------------------------- nixpkgs-patches/pr442482.patch | 35 ---------------------------------- 3 files changed, 72 deletions(-) delete mode 100644 nixpkgs-patches/pr441705.patch delete mode 100644 nixpkgs-patches/pr442482.patch diff --git a/flake.nix b/flake.nix index d875ca3..1f699e7 100644 --- a/flake.nix +++ b/flake.nix @@ -101,8 +101,6 @@ src = nixpkgs-unstable-raw; patches = [ ./nixpkgs-patches/plasma-workspace-patch-trimming.patch - ./nixpkgs-patches/pr441705.patch - ./nixpkgs-patches/pr442482.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr441705.patch b/nixpkgs-patches/pr441705.patch deleted file mode 100644 index f9b446d..0000000 --- a/nixpkgs-patches/pr441705.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 9cde39ee9db16f4b3cb63b4416377277b7c293b6 Mon Sep 17 00:00:00 2001 -From: Robert Helgesson -Date: Wed, 10 Sep 2025 10:11:56 +0200 -Subject: [PATCH] sd-switch: 0.6.0 -> 0.6.1 - ---- - pkgs/by-name/sd/sd-switch/package.nix | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/pkgs/by-name/sd/sd-switch/package.nix b/pkgs/by-name/sd/sd-switch/package.nix -index 72eebfbef61002..f7e4f1a9a01a61 100644 ---- a/pkgs/by-name/sd/sd-switch/package.nix -+++ b/pkgs/by-name/sd/sd-switch/package.nix -@@ -6,7 +6,7 @@ - }: - - let -- version = "0.6.0"; -+ version = "0.6.1"; - in - rustPlatform.buildRustPackage { - pname = "sd-switch"; -@@ -16,10 +16,10 @@ rustPlatform.buildRustPackage { - owner = "~rycee"; - repo = "sd-switch"; - rev = version; -- hash = "sha256-IZ2tyQzWa2Uk002P9jCiaIV3huRiFdTe8eYXVQPBBJI="; -+ hash = "sha256-2Zdgwov+a35OzH6pzXbgxxABI8GDO9z068gLpmE2Jk4="; - }; - -- cargoHash = "sha256-ExQPCA8sAZVE5uB1KUnq6PXGhG1IZjzM9eFwYW3oJtE="; -+ cargoHash = "sha256-At0qo9w+/8sk9BnaZiG870iO8KLkhg2E40VCzQvvPWk="; - - passthru = { - updateScript = nix-update-script { }; diff --git a/nixpkgs-patches/pr442482.patch b/nixpkgs-patches/pr442482.patch deleted file mode 100644 index c6022f9..0000000 --- a/nixpkgs-patches/pr442482.patch +++ /dev/null @@ -1,35 +0,0 @@ -From ede83dc17a58d6e846a0125c87dd18dc3abfe2a5 Mon Sep 17 00:00:00 2001 -From: Robert Helgesson -Date: Fri, 12 Sep 2025 23:25:31 +0200 -Subject: [PATCH] sd-switch: 0.6.1 -> 0.6.2 - ---- - pkgs/by-name/sd/sd-switch/package.nix | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/pkgs/by-name/sd/sd-switch/package.nix b/pkgs/by-name/sd/sd-switch/package.nix -index f7e4f1a9a01a61..85ae7e1c0e3552 100644 ---- a/pkgs/by-name/sd/sd-switch/package.nix -+++ b/pkgs/by-name/sd/sd-switch/package.nix -@@ -6,7 +6,7 @@ - }: - - let -- version = "0.6.1"; -+ version = "0.6.2"; - in - rustPlatform.buildRustPackage { - pname = "sd-switch"; -@@ -16,10 +16,10 @@ rustPlatform.buildRustPackage { - owner = "~rycee"; - repo = "sd-switch"; - rev = version; -- hash = "sha256-2Zdgwov+a35OzH6pzXbgxxABI8GDO9z068gLpmE2Jk4="; -+ hash = "sha256-3+FGARca3xcCYKEAxtrhnSnpOP2JZurOPzKvNhAYjkg="; - }; - -- cargoHash = "sha256-At0qo9w+/8sk9BnaZiG870iO8KLkhg2E40VCzQvvPWk="; -+ cargoHash = "sha256-jclRF05eUAW/ggCmfZfWE6c4q25d/WGX0dad4rsP8vk="; - - passthru = { - updateScript = nix-update-script { }; From 641ebc7ad9c6f93eced9d6b6b13a9f4aeb174d7a Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Sep 2025 19:29:03 +0200 Subject: [PATCH 1049/1125] Flake: update lock file --- flake.lock | 74 +++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/flake.lock b/flake.lock index a656b27..9a4a5f8 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1757320803, - "narHash": "sha256-7PUIQOMQSJLkNtV42SAYUDw0mRdbBNl6q8pLN8GViwM=", + "lastModified": 1758956381, + "narHash": "sha256-ROUw5E8CibG3jEy6oHjrkF6/P60eiaUJmc2s2ecC/LM=", "owner": "catppuccin", "repo": "nix", - "rev": "d75e3fe67f49728cb5035bc791f4b9065ff3a2c9", + "rev": "02dee881c3e644e2b561f407742f1fd927c40b83", "type": "github" }, "original": { @@ -65,11 +65,11 @@ ] }, "locked": { - "lastModified": 1757543518, - "narHash": "sha256-6tx7gyQ8uwbTGL4CnAZuov9Xmta38byekiNucz78DIM=", + "lastModified": 1759098182, + "narHash": "sha256-5+jWxVFWS9i6FQjdmKMWQZqN57W3Tb1cF1IqKqjind4=", "owner": "9001", "repo": "copyparty", - "rev": "5c1a43c71172e115c9cda1f1fe0474a4035b1bb0", + "rev": "d08e872062f0ed2ef28d1e5d3d5a32bac840a723", "type": "github" }, "original": { @@ -203,11 +203,11 @@ ] }, "locked": { - "lastModified": 1757650187, - "narHash": "sha256-OrythrqccPKtuVt0mj26rr83Qo3Ljb4ZmwLdPGjzjMU=", + "lastModified": 1759106866, + "narHash": "sha256-GjLvAl7qxGxKtop6ghasxjQ1biTT7pA+WU45byzMl/4=", "owner": "nix-community", "repo": "home-manager", - "rev": "9eab59f3e71ea3a725e4817d8dcf0da0824ad19d", + "rev": "619ae569293b6427d23cce4854eb4f3c33af3eec", "type": "github" }, "original": { @@ -223,11 +223,11 @@ ] }, "locked": { - "lastModified": 1756679287, - "narHash": "sha256-Xd1vOeY9ccDf5VtVK12yM0FS6qqvfUop8UQlxEB+gTQ=", + "lastModified": 1758463745, + "narHash": "sha256-uhzsV0Q0I9j2y/rfweWeGif5AWe0MGrgZ/3TjpDYdGA=", "owner": "nix-community", "repo": "home-manager", - "rev": "07fc025fe10487dd80f2ec694f1cd790e752d0e8", + "rev": "3b955f5f0a942f9f60cdc9cacb7844335d0f21c3", "type": "github" }, "original": { @@ -261,11 +261,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1757670140, - "narHash": "sha256-rJV/kCC6VOCuFHnanXpeqRHwm+xARSfDZg2KTPb4+/g=", - "rev": "138c7161be82d3a240ba3a59cbdd93eef069b448", + "lastModified": 1759066537, + "narHash": "sha256-9wdZxZqjWCobgQU6TDmdFHm2v8zOKFbg56+iThu63Vc=", + "rev": "f31e8e2b55419c7f250f29ae6fbc59be4a4c259e", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/138c7161be82d3a240ba3a59cbdd93eef069b448.tar.gz?rev=138c7161be82d3a240ba3a59cbdd93eef069b448" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/f31e8e2b55419c7f250f29ae6fbc59be4a4c259e.tar.gz?rev=f31e8e2b55419c7f250f29ae6fbc59be4a4c259e" }, "original": { "type": "tarball", @@ -378,11 +378,11 @@ ] }, "locked": { - "lastModified": 1757218147, - "narHash": "sha256-IwOwN70HvoBNB2ckaROxcaCvj5NudNc52taPsv5wtLk=", + "lastModified": 1759032422, + "narHash": "sha256-WZf+FhebP2/1pK2np5xj/NuDjD6fXK2BHnq/tPUN18o=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "9b144dc3ef6e42b888c4190e02746aab13b0e97f", + "rev": "ec7a78cb0e098832d8acac091a4df393259c4839", "type": "github" }, "original": { @@ -398,11 +398,11 @@ ] }, "locked": { - "lastModified": 1757218147, - "narHash": "sha256-IwOwN70HvoBNB2ckaROxcaCvj5NudNc52taPsv5wtLk=", + "lastModified": 1759032422, + "narHash": "sha256-WZf+FhebP2/1pK2np5xj/NuDjD6fXK2BHnq/tPUN18o=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "9b144dc3ef6e42b888c4190e02746aab13b0e97f", + "rev": "ec7a78cb0e098832d8acac091a4df393259c4839", "type": "github" }, "original": { @@ -413,11 +413,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1757103352, - "narHash": "sha256-PtT7ix43ss8PONJ1VJw3f6t2yAoGH+q462Sn8lrmWmk=", + "lastModified": 1758663926, + "narHash": "sha256-6CFdj7Xs616t1W4jLDH7IohAAvl5Dyib3qEv/Uqw1rk=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "11b2a10c7be726321bb854403fdeec391e798bf0", + "rev": "170ff93c860b2a9868ed1e1102d4e52cb3d934e1", "type": "github" }, "original": { @@ -429,11 +429,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1756266583, - "narHash": "sha256-cr748nSmpfvnhqSXPiCfUPxRz2FJnvf/RjJGvFfaCsM=", + "lastModified": 1758035966, + "narHash": "sha256-qqIJ3yxPiB0ZQTT9//nFGQYn8X/PBoJbofA7hRKZnmE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8a6d5427d99ec71c64f0b93d45778c889005d9c2", + "rev": "8d4ddb19d03c65a36ad8d189d001dc32ffb0306b", "type": "github" }, "original": { @@ -445,11 +445,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1757545623, - "narHash": "sha256-mCxPABZ6jRjUQx3bPP4vjA68ETbPLNz9V2pk9tO7pRQ=", + "lastModified": 1758791193, + "narHash": "sha256-F8WmEwFoHsnix7rt290R0rFXNJiMbClMZyIC/e+HYf0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8cd5ce828d5d1d16feff37340171a98fc3bf6526", + "rev": "25e53aa156d47bad5082ff7618f5feb1f5e02d01", "type": "github" }, "original": { @@ -460,11 +460,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1757487488, - "narHash": "sha256-zwE/e7CuPJUWKdvvTCB7iunV4E/+G0lKfv4kk/5Izdg=", + "lastModified": 1759036355, + "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ab0f3607a6c7486ea22229b92ed2d355f1482ee0", + "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", "type": "github" }, "original": { @@ -483,11 +483,11 @@ ] }, "locked": { - "lastModified": 1756632588, - "narHash": "sha256-ydam6eggXf3ZwRutyCABwSbMAlX+5lW6w1SVZQ+kfSo=", + "lastModified": 1759064045, + "narHash": "sha256-v74j88evVeCK7eqt/wfqe1x3YalwI/uss8TXtiqy5/I=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "d47428e5390d6a5a8f764808a4db15929347cd77", + "rev": "7d7629ba12b2ba7849718f18c1fba6e14708d974", "type": "github" }, "original": { From 68218ec1872ce0f3638bbb06bc858227ea1f9121 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 29 Sep 2025 19:33:04 +0200 Subject: [PATCH 1050/1125] Kde/patches: delete merged patches --- .../patches/frameworkintegration/patches.txt | 2 - .../patches/frameworkintegration/pr54.patch | 50 ------------------- 2 files changed, 52 deletions(-) delete mode 100644 roles/kde/patches/frameworkintegration/patches.txt delete mode 100644 roles/kde/patches/frameworkintegration/pr54.patch diff --git a/roles/kde/patches/frameworkintegration/patches.txt b/roles/kde/patches/frameworkintegration/patches.txt deleted file mode 100644 index 09818df..0000000 --- a/roles/kde/patches/frameworkintegration/patches.txt +++ /dev/null @@ -1,2 +0,0 @@ -Frameworks 6.18: -Pr 54 https://invent.kde.org/frameworks/frameworkintegration/-/merge_requests/54 diff --git a/roles/kde/patches/frameworkintegration/pr54.patch b/roles/kde/patches/frameworkintegration/pr54.patch deleted file mode 100644 index aee5303..0000000 --- a/roles/kde/patches/frameworkintegration/pr54.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 516a3642796563bcc7a13cd02795de3077a861b7 Mon Sep 17 00:00:00 2001 -From: Nate Graham -Date: Tue, 5 Aug 2025 09:27:36 -0600 -Subject: [PATCH] Turn on popups for device notifications - -Part of https://invent.kde.org/plasma/plasma-desktop/-/issues/149 - -These notifications are a useful way to communicate to the user that -their device isn't dead and was actuallt detected. Currently we have -only sounds turned on, and no popups. This problematic for -accessibility because deaf people won't hear the sound. - -For this reason, EU Directive 2019/882 requires that all sound-based -notifications be accompanied by something visual as well. - -Let's turn on popups to comply with that. We did some work to make the -popups not annoying, including: -- Not appearing in the history -- Removing the connection notification when disconnected (and vice - versa) -- Removing the notification when it's for a USB disk and the Disks & - Devices widget appears automatically. ---- - plasma_workspace.notifyrc | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/plasma_workspace.notifyrc b/plasma_workspace.notifyrc -index 7b9311d..4394192 100644 ---- a/plasma_workspace.notifyrc -+++ b/plasma_workspace.notifyrc -@@ -2380,7 +2380,7 @@ Comment[uk]=Було з'єднано пристрій - Comment[x-test]=xxA device was plugged inxx - Comment[zh_CN]=已插入一个设备 - Comment[zh_TW]=有裝置剛被插入 --Action=Sound -+Action=Popup|Sound - Sound=device-added - Urgency=Low - -@@ -2465,6 +2465,6 @@ Comment[uk]=Було від'єднано пристрій - Comment[x-test]=xxA device was unpluggedxx - Comment[zh_CN]=已拔出一个设备 - Comment[zh_TW]=有裝置剛被拔出 --Action=Sound -+Action=Popup|Sound - Sound=device-removed - Urgency=Low --- -GitLab - From a4f27b49af89aa2e88b1483e3ee7fe94a0ce165d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 30 Sep 2025 21:07:03 +0200 Subject: [PATCH 1051/1125] Kde/patches: override packages instead of replacing at runtime This causes A LOT more rebuilds, but it's less hacky --- roles/kde/patches/default.nix | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/roles/kde/patches/default.nix b/roles/kde/patches/default.nix index 93ab1cb..9259279 100644 --- a/roles/kde/patches/default.nix +++ b/roles/kde/patches/default.nix @@ -1,4 +1,4 @@ -{lib, pkgs, ...}: let +{lib, ...}: let rootDirs = builtins.readDir ./.; removeFiles = lib.attrsets.filterAttrs (n: v: v == "directory") rootDirs; programsToPatch = builtins.attrNames removeFiles; @@ -17,7 +17,9 @@ program: let unpatchedProgram = prev."${program}"; in { - "${program}-patched" = unpatchedProgram.overrideAttrs { + "${program}" = unpatchedProgram.overrideAttrs { + version = "${unpatchedProgram.version}-patched"; + __intentionallyOverridingVersion = true; patches = unpatchedProgram.patches ++ getPatches program; }; } @@ -31,14 +33,4 @@ in { } ) ]; - - system.replaceDependencies.replacements = lib.lists.forEach programsToPatch ( - package: { - oldDependency = pkgs.kdePackages.${package}; - newDependency = pkgs.kdePackages."${package}-patched"; - } - ); - system.extraDependencies = lib.lists.forEach programsToPatch ( - package: pkgs.kdePackages."${package}-patched" - ); } From fc803fd67e47538711ce786242085b65c63401d1 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 30 Sep 2025 21:07:54 +0200 Subject: [PATCH 1052/1125] Kde/patches: add more patches --- roles/kde/patches/kwin/patches.txt | 1 + roles/kde/patches/kwin/pr8155.patch | 60 +++ roles/kde/patches/kwindowsystem/1-pr187.patch | 78 ++++ roles/kde/patches/kwindowsystem/patches.txt | 4 + roles/kde/patches/kwindowsystem/pr186.patch | 415 ++++++++++++++++++ .../kde/patches/plasma-workspace/patches.txt | 5 + .../kde/patches/plasma-workspace/pr5816.patch | 349 +++++++++++++++ .../kde/patches/plasma-workspace/pr5818.patch | 76 ++++ 8 files changed, 988 insertions(+) create mode 100644 roles/kde/patches/kwin/pr8155.patch create mode 100644 roles/kde/patches/kwindowsystem/1-pr187.patch create mode 100644 roles/kde/patches/kwindowsystem/patches.txt create mode 100644 roles/kde/patches/kwindowsystem/pr186.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5816.patch create mode 100644 roles/kde/patches/plasma-workspace/pr5818.patch diff --git a/roles/kde/patches/kwin/patches.txt b/roles/kde/patches/kwin/patches.txt index f860b5d..7ac9343 100644 --- a/roles/kde/patches/kwin/patches.txt +++ b/roles/kde/patches/kwin/patches.txt @@ -3,3 +3,4 @@ Pr 3612 https://invent.kde.org/plasma/kwin/-/merge_requests/3612 Pr 7823 https://invent.kde.org/plasma/kwin/-/merge_requests/7823 Pr 8005 https://invent.kde.org/plasma/kwin/-/merge_requests/8005 Depends on Pr 7927 https://invent.kde.org/plasma/kwin/-/merge_requests/7927 +Pr 8155 https://invent.kde.org/plasma/kwin/-/merge_requests/8155 diff --git a/roles/kde/patches/kwin/pr8155.patch b/roles/kde/patches/kwin/pr8155.patch new file mode 100644 index 0000000..ff8eb4b --- /dev/null +++ b/roles/kde/patches/kwin/pr8155.patch @@ -0,0 +1,60 @@ +From bab7c4a4c5e2fb7be83ba94fdd0da7fd196654fa Mon Sep 17 00:00:00 2001 +From: David Redondo +Date: Thu, 25 Sep 2025 12:00:51 +0200 +Subject: [PATCH] Make sure XdgToplevelWindow always has an icon + +If the client never called set_app_id and did not set a custom +icon the window would end up without an icon at all. This ensures +that all windows always have at least the default icon. +--- + autotests/integration/xdgshellwindow_test.cpp | 13 +++++++++++-- + src/xdgshellwindow.cpp | 1 + + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/autotests/integration/xdgshellwindow_test.cpp b/autotests/integration/xdgshellwindow_test.cpp +index 0903043808d..a3658ee62e7 100644 +--- a/autotests/integration/xdgshellwindow_test.cpp ++++ b/autotests/integration/xdgshellwindow_test.cpp +@@ -683,16 +683,25 @@ void TestXdgShellWindow::testDesktopFileName() + std::unique_ptr surface(Test::createSurface()); + // only xdg-shell as ShellSurface misses the setter + std::unique_ptr shellSurface(Test::createXdgToplevelSurface(surface.get())); +- shellSurface->set_app_id(QStringLiteral("org.kde.foo")); + auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); + QVERIFY(window); ++ ++ // A client that never call set_app_id still gets the default icon ++ QCOMPARE(window->desktopFileName(), QString()); ++ QVERIFY(window->resourceClass().startsWith("testXdgShellWindow")); ++ QVERIFY(window->resourceName().startsWith("testXdgShellWindow")); ++ QCOMPARE(window->icon().name(), QStringLiteral("wayland")); ++ ++ QSignalSpy desktopFileNameChangedSpy(window, &Window::desktopFileNameChanged); ++ ++ shellSurface->set_app_id(QStringLiteral("org.kde.foo")); ++ QVERIFY(desktopFileNameChangedSpy.wait()); + QCOMPARE(window->desktopFileName(), QStringLiteral("org.kde.foo")); + QCOMPARE(window->resourceClass(), QStringLiteral("org.kde.foo")); + QVERIFY(window->resourceName().startsWith("testXdgShellWindow")); + // the desktop file does not exist, so icon should be generic Wayland + QCOMPARE(window->icon().name(), QStringLiteral("wayland")); + +- QSignalSpy desktopFileNameChangedSpy(window, &Window::desktopFileNameChanged); + QSignalSpy iconChangedSpy(window, &Window::iconChanged); + shellSurface->set_app_id(QStringLiteral("org.kde.bar")); + QVERIFY(desktopFileNameChangedSpy.wait()); +diff --git a/src/xdgshellwindow.cpp b/src/xdgshellwindow.cpp +index f585d3aef95..092c284b8c2 100644 +--- a/src/xdgshellwindow.cpp ++++ b/src/xdgshellwindow.cpp +@@ -1426,6 +1426,7 @@ void XdgToplevelWindow::initialize() + scheduleConfigure(); + updateColorScheme(); + updateCapabilities(); ++ updateIcon(); + setupWindowManagementInterface(); + + m_isInitialized = true; +-- +GitLab + diff --git a/roles/kde/patches/kwindowsystem/1-pr187.patch b/roles/kde/patches/kwindowsystem/1-pr187.patch new file mode 100644 index 0000000..9021735 --- /dev/null +++ b/roles/kde/patches/kwindowsystem/1-pr187.patch @@ -0,0 +1,78 @@ +From b05d0431d741510c12294c85dc5ce001a8aceca2 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 17 Sep 2025 11:41:15 +0300 +Subject: [PATCH 1/2] wayland: Fix leaking xdg activation objects + +Nobody destroys WaylandXdgActivationV1 objects, we also must call destroy() +manually. +--- + src/platforms/wayland/waylandxdgactivationv1_p.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/platforms/wayland/waylandxdgactivationv1_p.h b/src/platforms/wayland/waylandxdgactivationv1_p.h +index e74c550b..e3b14c27 100644 +--- a/src/platforms/wayland/waylandxdgactivationv1_p.h ++++ b/src/platforms/wayland/waylandxdgactivationv1_p.h +@@ -16,10 +16,18 @@ class QWaylandSurface; + class WaylandXdgActivationTokenV1 : public QObject, public QtWayland::xdg_activation_token_v1 + { + Q_OBJECT ++ + public: ++ ~WaylandXdgActivationTokenV1() override ++ { ++ destroy(); ++ } ++ ++protected: + void xdg_activation_token_v1_done(const QString &token) override + { + Q_EMIT done(token); ++ deleteLater(); + } + + Q_SIGNALS: +-- +GitLab + + +From ac28bf993ba7295faf39607d4b4402f6dce1c36b Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 17 Sep 2025 11:43:16 +0300 +Subject: [PATCH 2/2] wayland: Drop WaylandXdgActivationTokenV1::failed signal + +It's not emitted by anyone. +--- + src/platforms/wayland/waylandxdgactivationv1_p.h | 1 - + src/platforms/wayland/windowsystem.cpp | 3 --- + 2 files changed, 4 deletions(-) + +diff --git a/src/platforms/wayland/waylandxdgactivationv1_p.h b/src/platforms/wayland/waylandxdgactivationv1_p.h +index e3b14c27..077ccd93 100644 +--- a/src/platforms/wayland/waylandxdgactivationv1_p.h ++++ b/src/platforms/wayland/waylandxdgactivationv1_p.h +@@ -31,7 +31,6 @@ protected: + } + + Q_SIGNALS: +- void failed(); + void done(const QString &token); + }; + +diff --git a/src/platforms/wayland/windowsystem.cpp b/src/platforms/wayland/windowsystem.cpp +index 034ffd37..f2d8b4f2 100644 +--- a/src/platforms/wayland/windowsystem.cpp ++++ b/src/platforms/wayland/windowsystem.cpp +@@ -95,9 +95,6 @@ void WindowSystem::requestToken(QWindow *window, uint32_t serial, const QString + auto waylandApp = qGuiApp->nativeInterface(); + auto seat = waylandApp ? waylandApp->lastInputSeat() : nullptr; + auto tokenReq = activation->requestXdgActivationToken(seat, wlSurface, serial, app_id); +- connect(tokenReq, &WaylandXdgActivationTokenV1::failed, KWindowSystem::self(), [serial, app_id]() { +- Q_EMIT KWaylandExtras::self()->xdgActivationTokenArrived(serial, {}); +- }); + connect(tokenReq, &WaylandXdgActivationTokenV1::done, KWindowSystem::self(), [serial](const QString &token) { + Q_EMIT KWaylandExtras::self()->xdgActivationTokenArrived(serial, token); + }); +-- +GitLab + diff --git a/roles/kde/patches/kwindowsystem/patches.txt b/roles/kde/patches/kwindowsystem/patches.txt new file mode 100644 index 0000000..f7b32a9 --- /dev/null +++ b/roles/kde/patches/kwindowsystem/patches.txt @@ -0,0 +1,4 @@ +Plasma 6.6.0: + +Pr 186 https://invent.kde.org/frameworks/kwindowsystem/-/merge_requests/186 +Pr 187 https://invent.kde.org/frameworks/kwindowsystem/-/merge_requests/187 diff --git a/roles/kde/patches/kwindowsystem/pr186.patch b/roles/kde/patches/kwindowsystem/pr186.patch new file mode 100644 index 0000000..c77e64f --- /dev/null +++ b/roles/kde/patches/kwindowsystem/pr186.patch @@ -0,0 +1,415 @@ +From 9d0ffb13d290d76df03d199b50c3b3364d4b93bc Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 17 Sep 2025 10:14:15 +0300 +Subject: [PATCH 1/2] Add QFuture-based xdg-activation token helpers + +QFuture can be used to make the code that needs activation tokens cleaner. +--- + src/kwaylandextras.cpp | 14 +++++++++++ + src/kwaylandextras.h | 21 ++++++++++++++++ + src/kwindowsystem_p.h | 8 ++++++ + .../wayland/waylandxdgactivationv1_p.h | 19 ++++++++++++++ + src/platforms/wayland/windowsystem.cpp | 25 ++++++++++++++++--- + src/platforms/wayland/windowsystem.h | 3 ++- + tests/activationtest.cpp | 13 +++++----- + tests/kwaylandextrastest.cpp | 12 +++------ + 8 files changed, 95 insertions(+), 20 deletions(-) + +diff --git a/src/kwaylandextras.cpp b/src/kwaylandextras.cpp +index 036d57d3..a5f8af8f 100644 +--- a/src/kwaylandextras.cpp ++++ b/src/kwaylandextras.cpp +@@ -63,4 +63,18 @@ void KWaylandExtras::unexportWindow(QWindow *window) + } + } + ++QFuture KWaylandExtras::xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId) ++{ ++ if (auto dv3 = dynamic_cast(KWindowSystem::d_func())) { ++ return dv3->xdgActivationToken(window, serial, appId); ++ } else { ++ return QFuture(); ++ } ++} ++ ++QFuture KWaylandExtras::xdgActivationToken(QWindow *window, const QString &appId) ++{ ++ return xdgActivationToken(window, lastInputSerial(window), appId); ++} ++ + #include "moc_kwaylandextras.cpp" +diff --git a/src/kwaylandextras.h b/src/kwaylandextras.h +index f43135d0..2f763dd5 100644 +--- a/src/kwaylandextras.h ++++ b/src/kwaylandextras.h +@@ -9,6 +9,7 @@ + #ifndef KWAYLANDEXTRAS_H + #define KWAYLANDEXTRAS_H + ++#include + #include + #include + +@@ -61,6 +62,26 @@ public: + */ + Q_INVOKABLE static void unexportWindow(QWindow *window); + ++ /*! ++ * Requests an xdg_activation_v1 token for a specific window \a window with the given \a appId. ++ * The \a serial indicates an event that triggered the request. ++ * ++ * \note No xdgActivationTokenArrived() signal will be emitted for this token. ++ * ++ * \since 6.19 ++ */ ++ static QFuture xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId); ++ ++ /*! ++ * Requests an xdg_activation_v1 token for a specific window \a window with the given \a appId. ++ * The last received input serial will be used to request the token. ++ * ++ * \note No xdgActivationTokenArrived() signal will be emitted for this token. ++ * ++ * \since 6.19 ++ */ ++ static QFuture xdgActivationToken(QWindow *window, const QString &appId); ++ + Q_SIGNALS: + /*! + * Activation \a token to pass to the client. +diff --git a/src/kwindowsystem_p.h b/src/kwindowsystem_p.h +index eb9348ba..e4b51e3e 100644 +--- a/src/kwindowsystem_p.h ++++ b/src/kwindowsystem_p.h +@@ -7,6 +7,8 @@ + #define KWINDOWSYSTEM_P_H + + #include "netwm_def.h" ++ ++#include + #include + #include //For WId + #include +@@ -33,4 +35,10 @@ public: + virtual void unexportWindow(QWindow *window) = 0; + }; + ++class KWINDOWSYSTEM_EXPORT KWindowSystemPrivateV3 : public KWindowSystemPrivateV2 ++{ ++public: ++ virtual QFuture xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId) = 0; ++}; ++ + #endif +diff --git a/src/platforms/wayland/waylandxdgactivationv1_p.h b/src/platforms/wayland/waylandxdgactivationv1_p.h +index 077ccd93..629d45ef 100644 +--- a/src/platforms/wayland/waylandxdgactivationv1_p.h ++++ b/src/platforms/wayland/waylandxdgactivationv1_p.h +@@ -8,7 +8,10 @@ + #define WAYLANDXDGACTIVATIONV1_P_H + + #include "qwayland-xdg-activation-v1.h" ++ ++#include + #include ++#include + #include + + class QWaylandSurface; +@@ -18,20 +21,36 @@ class WaylandXdgActivationTokenV1 : public QObject, public QtWayland::xdg_activa + Q_OBJECT + + public: ++ WaylandXdgActivationTokenV1() ++ { ++ m_promise.start(); ++ } ++ + ~WaylandXdgActivationTokenV1() override + { + destroy(); + } + ++ QFuture future() const ++ { ++ return m_promise.future(); ++ } ++ + protected: + void xdg_activation_token_v1_done(const QString &token) override + { ++ m_promise.addResult(token); ++ m_promise.finish(); ++ + Q_EMIT done(token); + deleteLater(); + } + + Q_SIGNALS: + void done(const QString &token); ++ ++private: ++ QPromise m_promise; + }; + + class WaylandXdgActivationV1 : public QWaylandClientExtensionTemplate, public QtWayland::xdg_activation_v1 +diff --git a/src/platforms/wayland/windowsystem.cpp b/src/platforms/wayland/windowsystem.cpp +index f2d8b4f2..ebb22d78 100644 +--- a/src/platforms/wayland/windowsystem.cpp ++++ b/src/platforms/wayland/windowsystem.cpp +@@ -50,9 +50,7 @@ public: + }; + + WindowSystem::WindowSystem() +- : QObject() +- , KWindowSystemPrivateV2() +- , m_lastToken(qEnvironmentVariable("XDG_ACTIVATION_TOKEN")) ++ : m_lastToken(qEnvironmentVariable("XDG_ACTIVATION_TOKEN")) + { + m_windowManagement = new WindowManagement; + } +@@ -303,4 +301,25 @@ void WindowSystem::doSetMainWindow(QWindow *window, const QString &handle) + } + } + ++QFuture WindowSystem::xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId) ++{ ++ WaylandXdgActivationV1 *activation = WaylandXdgActivationV1::self(); ++ if (!activation->isActive()) { ++ return QFuture(); ++ } ++ ++ auto waylandApp = qGuiApp->nativeInterface(); ++ if (!waylandApp) { ++ return QFuture(); ++ } ++ ++ if (window) { ++ window->create(); ++ } ++ wl_surface *wlSurface = surfaceForWindow(window); ++ ++ auto token = activation->requestXdgActivationToken(waylandApp->lastInputSeat(), wlSurface, serial, appId); ++ return token->future(); ++} ++ + #include "moc_windowsystem.cpp" +diff --git a/src/platforms/wayland/windowsystem.h b/src/platforms/wayland/windowsystem.h +index 87bf23ed..4df82388 100644 +--- a/src/platforms/wayland/windowsystem.h ++++ b/src/platforms/wayland/windowsystem.h +@@ -12,7 +12,7 @@ + + class WindowManagement; + +-class WindowSystem : public QObject, public KWindowSystemPrivateV2 ++class WindowSystem : public QObject, public KWindowSystemPrivateV3 + { + Q_OBJECT + public: +@@ -27,6 +27,7 @@ public: + void exportWindow(QWindow *window) override; + void unexportWindow(QWindow *window) override; + void setMainWindow(QWindow *window, const QString &handle) override; ++ QFuture xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId) override; + + protected: + bool eventFilter(QObject *watched, QEvent *event) override; +diff --git a/tests/activationtest.cpp b/tests/activationtest.cpp +index 306c6048..7aaae4ea 100644 +--- a/tests/activationtest.cpp ++++ b/tests/activationtest.cpp +@@ -28,13 +28,12 @@ public: + pushButton->setText("Raise other"); + layout()->addWidget(pushButton); + +- connect(pushButton, &QPushButton::clicked, this, [this] { +- KWaylandExtras::requestXdgActivationToken(windowHandle(), KWaylandExtras::lastInputSerial(windowHandle()), QString()); +- }); +- +- connect(KWaylandExtras::self(), &KWaylandExtras::xdgActivationTokenArrived, this, [otherWindow](int /*serial*/, const QString &token) { +- KWindowSystem::setCurrentXdgActivationToken(token); +- KWindowSystem::activateWindow(otherWindow->windowHandle()); ++ connect(pushButton, &QPushButton::clicked, this, [this, otherWindow] { ++ KWaylandExtras::xdgActivationToken(windowHandle(), KWaylandExtras::lastInputSerial(windowHandle()), QString()) ++ .then(otherWindow, [otherWindow](const QString &token) { ++ KWindowSystem::setCurrentXdgActivationToken(token); ++ KWindowSystem::activateWindow(otherWindow->windowHandle()); ++ }); + }); + } + }; +diff --git a/tests/kwaylandextrastest.cpp b/tests/kwaylandextrastest.cpp +index 3048cb37..2ee86a82 100644 +--- a/tests/kwaylandextrastest.cpp ++++ b/tests/kwaylandextrastest.cpp +@@ -79,16 +79,10 @@ void Window::updateSerial() + + void Window::requestToken() + { +- connect( +- KWaylandExtras::self(), +- &KWaylandExtras::xdgActivationTokenArrived, +- this, +- [this](int /*serial*/, const QString &token) { ++ KWaylandExtras::xdgActivationToken(windowHandle(), KWaylandExtras::self()->lastInputSerial(windowHandle()), QString()) ++ .then(this, [this](const QString &token) { + m_tokenLabel->setText("XDG actvation token: " + token); +- }, +- Qt::SingleShotConnection); +- +- KWaylandExtras::requestXdgActivationToken(windowHandle(), KWaylandExtras::self()->lastInputSerial(windowHandle()), QString()); ++ }); + } + + void Window::exportWindow() +-- +GitLab + + +From 1b16c417c697b5d30724ce37d0364af894f6680d Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 17 Sep 2025 12:01:53 +0300 +Subject: [PATCH 2/2] Deprecate KWaylandExtras::requestXdgActivationToken() + +KWaylandExtras::xdgActivationToken() provides a more convenient way to +retrieve an xdg activation token. + +Note that the QML side has no corresponding counterpart, however on the +other hand, there is no QML code that uses this function too. If the need +arises, the QML specific API could provide a Promise-like object. +--- + src/CMakeLists.txt | 2 +- + src/kwaylandextras.cpp | 2 ++ + src/kwaylandextras.h | 9 ++++++++- + src/kwindowsystem_p.h | 2 ++ + src/platforms/wayland/windowsystem.cpp | 2 ++ + src/platforms/wayland/windowsystem.h | 2 ++ + 6 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index fd72063b..ba748c2c 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -88,7 +88,7 @@ ecm_generate_export_header(KF6WindowSystem + VERSION ${KF_VERSION} + USE_VERSION_HEADER + DEPRECATED_BASE_VERSION 0 +- DEPRECATION_VERSIONS 6.0 ++ DEPRECATION_VERSIONS 6.0 6.19 + EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} + ) + +diff --git a/src/kwaylandextras.cpp b/src/kwaylandextras.cpp +index a5f8af8f..241f80be 100644 +--- a/src/kwaylandextras.cpp ++++ b/src/kwaylandextras.cpp +@@ -26,6 +26,7 @@ KWaylandExtras *KWaylandExtras::self() + return &instance; + } + ++#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(6, 19) + void KWaylandExtras::requestXdgActivationToken(QWindow *window, uint32_t serial, const QString &app_id) + { + auto dv2 = dynamic_cast(KWindowSystem::d_func()); +@@ -39,6 +40,7 @@ void KWaylandExtras::requestXdgActivationToken(QWindow *window, uint32_t serial, + } + dv2->requestToken(window, serial, app_id); + } ++#endif + + quint32 KWaylandExtras::lastInputSerial(QWindow *window) + { +diff --git a/src/kwaylandextras.h b/src/kwaylandextras.h +index 2f763dd5..56424b89 100644 +--- a/src/kwaylandextras.h ++++ b/src/kwaylandextras.h +@@ -31,14 +31,18 @@ public: + */ + static KWaylandExtras *self(); + ++#if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(6, 19) + /*! + * Requests an xdg_activation_v1 token for a specific window \a win with the given \a app_id. + * + * \a serial Serial of the event that triggered the request. + * + * \sa lastInputSerial ++ * \deprecated [6.19] Use xdgActivationToken() instead. + */ ++ KWINDOWSYSTEM_DEPRECATED_VERSION(6, 19, "Use xdgActivationToken()") + Q_INVOKABLE static void requestXdgActivationToken(QWindow *win, uint32_t serial, const QString &app_id); ++#endif + + /*! + * Offers the seat's current serial for the given \a window. +@@ -83,14 +87,17 @@ public: + static QFuture xdgActivationToken(QWindow *window, const QString &appId); + + Q_SIGNALS: ++#if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(6, 19) + /*! + * Activation \a token to pass to the client. + * + * \a serial Serial of the event that triggered the request + * + * \sa requestXdgActivationToken ++ * \deprecated [6.19] Use xdgActivationToken() instead. + */ +- void xdgActivationTokenArrived(int serial, const QString &token); ++ KWINDOWSYSTEM_DEPRECATED_VERSION(6, 19, "Use xdgActivationToken()") void xdgActivationTokenArrived(int serial, const QString &token); ++#endif + + /*! + * The \a handle of the given \a window to pass to the client. +diff --git a/src/kwindowsystem_p.h b/src/kwindowsystem_p.h +index e4b51e3e..92997120 100644 +--- a/src/kwindowsystem_p.h ++++ b/src/kwindowsystem_p.h +@@ -27,7 +27,9 @@ public: + class KWINDOWSYSTEM_EXPORT KWindowSystemPrivateV2 : public KWindowSystemPrivate + { + public: ++#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(6, 19) + virtual void requestToken(QWindow *win, uint32_t serial, const QString &app_id) = 0; ++#endif + virtual void setCurrentToken(const QString &token) = 0; + virtual quint32 lastInputSerial(QWindow *window) = 0; + virtual void setMainWindow(QWindow *window, const QString &handle) = 0; +diff --git a/src/platforms/wayland/windowsystem.cpp b/src/platforms/wayland/windowsystem.cpp +index ebb22d78..bc803a4f 100644 +--- a/src/platforms/wayland/windowsystem.cpp ++++ b/src/platforms/wayland/windowsystem.cpp +@@ -74,6 +74,7 @@ void WindowSystem::activateWindow(QWindow *win, long int time) + activation->activate(m_lastToken, s); + } + ++#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(6, 19) + void WindowSystem::requestToken(QWindow *window, uint32_t serial, const QString &app_id) + { + if (window) { +@@ -97,6 +98,7 @@ void WindowSystem::requestToken(QWindow *window, uint32_t serial, const QString + Q_EMIT KWaylandExtras::self()->xdgActivationTokenArrived(serial, token); + }); + } ++#endif + + void WindowSystem::setCurrentToken(const QString &token) + { +diff --git a/src/platforms/wayland/windowsystem.h b/src/platforms/wayland/windowsystem.h +index 4df82388..e9dca128 100644 +--- a/src/platforms/wayland/windowsystem.h ++++ b/src/platforms/wayland/windowsystem.h +@@ -19,7 +19,9 @@ public: + WindowSystem(); + ~WindowSystem() override; + void activateWindow(QWindow *win, long time) override; ++#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(6, 19) + void requestToken(QWindow *win, uint32_t serial, const QString &app_id) override; ++#endif + quint32 lastInputSerial(QWindow *window) override; + void setCurrentToken(const QString &token) override; + bool showingDesktop() override; +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/patches.txt b/roles/kde/patches/plasma-workspace/patches.txt index 26a8d42..49de017 100644 --- a/roles/kde/patches/plasma-workspace/patches.txt +++ b/roles/kde/patches/plasma-workspace/patches.txt @@ -14,3 +14,8 @@ Pr 5678 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5678 Depends on Pr 5673 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5673 Pr 5788 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5788 Allows compiling on gcc 14 after applying pr 5678 + +Plasma 6.6.0: + +Pr 5818 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5818 +Pr 5816 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5816 diff --git a/roles/kde/patches/plasma-workspace/pr5816.patch b/roles/kde/patches/plasma-workspace/pr5816.patch new file mode 100644 index 0000000..7a1925a --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5816.patch @@ -0,0 +1,349 @@ +From 77b3ec8cf4fb9414167bb15bcc3c69b1be6c2dbf Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Tue, 16 Sep 2025 15:52:29 +0300 +Subject: [PATCH 1/2] shell: Pass an xdg activation token from DesktopView to + KRunner + +This makes sure that krunner gets focused after starting to type while +a desktop view is focused when using medium or high focus stealing +prevention level. +--- + krunner/dbus/org.kde.krunner.App.xml | 4 ++ + krunner/view.cpp | 14 +++++++ + krunner/view.h | 1 + + shell/desktopview.cpp | 61 ++++++++++++++++++++++++++-- + shell/desktopview.h | 2 + + 5 files changed, 79 insertions(+), 3 deletions(-) + +diff --git a/krunner/dbus/org.kde.krunner.App.xml b/krunner/dbus/org.kde.krunner.App.xml +index 6553e9a1b56..e6926b1b63a 100644 +--- a/krunner/dbus/org.kde.krunner.App.xml ++++ b/krunner/dbus/org.kde.krunner.App.xml +@@ -17,5 +17,9 @@ + + + ++ ++ ++ ++ + + +diff --git a/krunner/view.cpp b/krunner/view.cpp +index afefe9ab486..bb7edd5d654 100644 +--- a/krunner/view.cpp ++++ b/krunner/view.cpp +@@ -263,6 +263,20 @@ void View::querySingleRunner(const QString &runnerName, const QString &term) + m_engine->rootObject()->setProperty("query", term); + } + ++void View::queryWithActivationToken(const QString &term, const QString &activationToken) ++{ ++ qputenv("XDG_ACTIVATION_TOKEN", activationToken.toUtf8()); ++ ++ if (!isVisible()) { ++ display(); ++ } else { ++ requestActivate(); ++ } ++ ++ m_engine->rootObject()->setProperty("singleRunner", QString()); ++ m_engine->rootObject()->setProperty("query", term); ++} ++ + bool View::pinned() const + { + return m_pinned; +diff --git a/krunner/view.h b/krunner/view.h +index 979c6d3b483..af1d477d6f3 100644 +--- a/krunner/view.h ++++ b/krunner/view.h +@@ -93,6 +93,7 @@ public Q_SLOTS: + void displayWithClipboardContents(); + void query(const QString &term); + void querySingleRunner(const QString &runnerName, const QString &term); ++ void queryWithActivationToken(const QString &term, const QString &activationToken); + + protected Q_SLOTS: + void loadConfig(); +diff --git a/shell/desktopview.cpp b/shell/desktopview.cpp +index 36e23149272..744176e6d3e 100644 +--- a/shell/desktopview.cpp ++++ b/shell/desktopview.cpp +@@ -23,6 +23,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -384,11 +385,54 @@ bool DesktopView::event(QEvent *e) + { + if (e->type() == QEvent::FocusOut) { + m_krunnerText.clear(); ++ ++ if (!m_krunnerFuture.isCanceled()) { ++ m_krunnerFuture.cancel(); ++ m_krunnerFuture = {}; ++ } + } + + return PlasmaQuick::ContainmentView::event(e); + } + ++class ActivationTokenRequest : public QObject ++{ ++ Q_OBJECT ++ ++public: ++ explicit ActivationTokenRequest(QWindow *window) ++ : m_serial(KWaylandExtras::lastInputSerial(window)) ++ { ++ m_promise.start(); ++ ++ connect(KWaylandExtras::self(), &KWaylandExtras::xdgActivationTokenArrived, this, [this](int serial, const QString &token) { ++ if (m_serial == serial) { ++ if (!m_promise.isCanceled()) { ++ m_promise.addResult(token); ++ } ++ m_promise.finish(); ++ delete this; ++ } ++ }); ++ KWaylandExtras::requestXdgActivationToken(window, m_serial, QString()); ++ } ++ ++ QFuture future() const ++ { ++ return m_promise.future(); ++ } ++ ++private: ++ QPromise m_promise; ++ int m_serial; ++}; ++ ++static QFuture fetchActivationToken(QWindow *window) ++{ ++ auto request = new ActivationTokenRequest(window); ++ return request->future(); ++} ++ + bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) + { + // allow only Shift and GroupSwitch modifiers +@@ -408,12 +452,22 @@ bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) + krunnerTextChanged = true; + } + if (krunnerTextChanged) { +- const QString interface(QStringLiteral("org.kde.krunner")); + if (!KAuthorized::authorize(QStringLiteral("run_command"))) { + return false; + } +- org::kde::krunner::App krunner(interface, QStringLiteral("/App"), QDBusConnection::sessionBus()); +- krunner.query(m_krunnerText); ++ if (KWindowSystem::isPlatformWayland()) { ++ if (!m_krunnerFuture.isCanceled()) { ++ m_krunnerFuture.cancel(); ++ } ++ m_krunnerFuture = fetchActivationToken(this); ++ m_krunnerFuture.then(this, [this](const QString &token) { ++ org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); ++ krunner.queryWithActivationToken(m_krunnerText, token); ++ }); ++ } else { ++ org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); ++ krunner.query(m_krunnerText); ++ } + return true; + } + return false; +@@ -596,4 +650,5 @@ void DesktopView::setAccentColorFromWallpaper(const QColor &accentColor) + QDBusConnection::sessionBus().send(applyAccentColor); + } + ++#include "desktopview.moc" + #include "moc_desktopview.cpp" +diff --git a/shell/desktopview.h b/shell/desktopview.h +index c2b642d9a15..9e152611a31 100644 +--- a/shell/desktopview.h ++++ b/shell/desktopview.h +@@ -10,6 +10,7 @@ + + #include + #include ++#include + #include + + #include +@@ -127,6 +128,7 @@ private: + QPointer m_screenToFollow; + LayerShellQt::Window *m_layerWindow = nullptr; + QString m_krunnerText; ++ QFuture m_krunnerFuture; + + // KRunner config + KConfigWatcher::Ptr m_configWatcher; +-- +GitLab + + +From b3d97405cb5b0ee9859576309bd826dea6b74274 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 17 Sep 2025 09:59:07 +0300 +Subject: [PATCH 2/2] shell: Use org.freedesktop.Application.ActivateAction to + pass xdg activation token to krunner + +--- + krunner/dbus/org.kde.krunner.App.xml | 4 ---- + krunner/main.cpp | 4 +++- + krunner/view.cpp | 14 ------------ + krunner/view.h | 1 - + shell/CMakeLists.txt | 4 ---- + shell/desktopview.cpp | 32 +++++++++++++++++++++++----- + 6 files changed, 30 insertions(+), 29 deletions(-) + +diff --git a/krunner/dbus/org.kde.krunner.App.xml b/krunner/dbus/org.kde.krunner.App.xml +index e6926b1b63a..6553e9a1b56 100644 +--- a/krunner/dbus/org.kde.krunner.App.xml ++++ b/krunner/dbus/org.kde.krunner.App.xml +@@ -17,9 +17,5 @@ + + + +- +- +- +- + + +diff --git a/krunner/main.cpp b/krunner/main.cpp +index 514c34b032f..02174bb2cda 100644 +--- a/krunner/main.cpp ++++ b/krunner/main.cpp +@@ -136,9 +136,11 @@ int main(int argc, char **argv) + parser.parse(arguments); + updateVisibility(); + }); +- QObject::connect(&service, &KDBusService::activateActionRequested, &view, [&view](const QString &action) { ++ QObject::connect(&service, &KDBusService::activateActionRequested, &view, [&view](const QString &action, const QVariant ¶meter) { + if (action == QLatin1String("RunClipboard")) { + view.displayWithClipboardContents(); ++ } else if (action == QLatin1String("Query")) { ++ view.query(parameter.toString()); + } + }); + +diff --git a/krunner/view.cpp b/krunner/view.cpp +index bb7edd5d654..afefe9ab486 100644 +--- a/krunner/view.cpp ++++ b/krunner/view.cpp +@@ -263,20 +263,6 @@ void View::querySingleRunner(const QString &runnerName, const QString &term) + m_engine->rootObject()->setProperty("query", term); + } + +-void View::queryWithActivationToken(const QString &term, const QString &activationToken) +-{ +- qputenv("XDG_ACTIVATION_TOKEN", activationToken.toUtf8()); +- +- if (!isVisible()) { +- display(); +- } else { +- requestActivate(); +- } +- +- m_engine->rootObject()->setProperty("singleRunner", QString()); +- m_engine->rootObject()->setProperty("query", term); +-} +- + bool View::pinned() const + { + return m_pinned; +diff --git a/krunner/view.h b/krunner/view.h +index af1d477d6f3..979c6d3b483 100644 +--- a/krunner/view.h ++++ b/krunner/view.h +@@ -93,7 +93,6 @@ public Q_SLOTS: + void displayWithClipboardContents(); + void query(const QString &term); + void querySingleRunner(const QString &runnerName, const QString &term); +- void queryWithActivationToken(const QString &term, const QString &activationToken); + + protected Q_SLOTS: + void loadConfig(); +diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt +index 96b91888f1b..814413ac827 100644 +--- a/shell/CMakeLists.txt ++++ b/shell/CMakeLists.txt +@@ -92,10 +92,6 @@ qt6_generate_wayland_protocol_client_sources(plasmashell + ${PLASMA_WAYLAND_PROTOCOLS_DIR}/plasma-shell.xml + ) + +-set(krunner_xml ${plasma-workspace_SOURCE_DIR}/krunner/dbus/org.kde.krunner.App.xml) +-qt_add_dbus_interface(plasma_shell_SRCS ${krunner_xml} krunner_interface) +- +- + target_sources(plasmashell PRIVATE ${plasma_shell_SRCS}) + + target_link_libraries(plasmashell PRIVATE +diff --git a/shell/desktopview.cpp b/shell/desktopview.cpp +index 744176e6d3e..9c3baa84b91 100644 +--- a/shell/desktopview.cpp ++++ b/shell/desktopview.cpp +@@ -6,12 +6,12 @@ + + #include "desktopview.h" + #include "containmentconfigview.h" +-#include "krunner_interface.h" + #include "screenpool.h" + #include "shellcorona.h" + + #include + #include ++#include + #include + #include + #include +@@ -461,12 +461,34 @@ bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) + } + m_krunnerFuture = fetchActivationToken(this); + m_krunnerFuture.then(this, [this](const QString &token) { +- org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); +- krunner.queryWithActivationToken(m_krunnerText, token); ++ auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.krunner"), ++ QStringLiteral("/org/kde/krunner"), ++ QStringLiteral("org.freedesktop.Application"), ++ QStringLiteral("ActivateAction")); ++ message.setArguments({ ++ QStringLiteral("Query"), ++ QVariantList{ ++ m_krunnerText, ++ }, ++ QVariantMap{ ++ {QStringLiteral("activation-token"), token}, ++ }, ++ }); ++ QDBusConnection::sessionBus().asyncCall(message); + }); + } else { +- org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); +- krunner.query(m_krunnerText); ++ auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.krunner"), ++ QStringLiteral("/org/kde/krunner"), ++ QStringLiteral("org.freedesktop.Application"), ++ QStringLiteral("ActivateAction")); ++ message.setArguments({ ++ QStringLiteral("Query"), ++ QVariantList{ ++ m_krunnerText, ++ }, ++ QVariantMap{}, ++ }); ++ QDBusConnection::sessionBus().asyncCall(message); + } + return true; + } +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/pr5818.patch b/roles/kde/patches/plasma-workspace/pr5818.patch new file mode 100644 index 0000000..12417f1 --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5818.patch @@ -0,0 +1,76 @@ +From b29509a32a0aa93555f47bc3d3f04c665c511f30 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 17 Sep 2025 10:27:07 +0300 +Subject: [PATCH] shell: Port to KWaylandExtras::xdgActivationToken() + +--- + shell/desktopview.cpp | 41 +---------------------------------------- + 1 file changed, 1 insertion(+), 40 deletions(-) + +diff --git a/shell/desktopview.cpp b/shell/desktopview.cpp +index 9c3baa84b91..ca48e44e887 100644 +--- a/shell/desktopview.cpp ++++ b/shell/desktopview.cpp +@@ -395,44 +395,6 @@ bool DesktopView::event(QEvent *e) + return PlasmaQuick::ContainmentView::event(e); + } + +-class ActivationTokenRequest : public QObject +-{ +- Q_OBJECT +- +-public: +- explicit ActivationTokenRequest(QWindow *window) +- : m_serial(KWaylandExtras::lastInputSerial(window)) +- { +- m_promise.start(); +- +- connect(KWaylandExtras::self(), &KWaylandExtras::xdgActivationTokenArrived, this, [this](int serial, const QString &token) { +- if (m_serial == serial) { +- if (!m_promise.isCanceled()) { +- m_promise.addResult(token); +- } +- m_promise.finish(); +- delete this; +- } +- }); +- KWaylandExtras::requestXdgActivationToken(window, m_serial, QString()); +- } +- +- QFuture future() const +- { +- return m_promise.future(); +- } +- +-private: +- QPromise m_promise; +- int m_serial; +-}; +- +-static QFuture fetchActivationToken(QWindow *window) +-{ +- auto request = new ActivationTokenRequest(window); +- return request->future(); +-} +- + bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) + { + // allow only Shift and GroupSwitch modifiers +@@ -459,7 +421,7 @@ bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) + if (!m_krunnerFuture.isCanceled()) { + m_krunnerFuture.cancel(); + } +- m_krunnerFuture = fetchActivationToken(this); ++ m_krunnerFuture = KWaylandExtras::xdgActivationToken(this, QString()); + m_krunnerFuture.then(this, [this](const QString &token) { + auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.krunner"), + QStringLiteral("/org/kde/krunner"), +@@ -672,5 +634,4 @@ void DesktopView::setAccentColorFromWallpaper(const QColor &accentColor) + QDBusConnection::sessionBus().send(applyAccentColor); + } + +-#include "desktopview.moc" + #include "moc_desktopview.cpp" +-- +GitLab + From 3fedba90c4fee76c33918f0752914f1f6fa8e340 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 4 Oct 2025 00:17:01 +0200 Subject: [PATCH 1053/1125] Server/beets: enable mbsync and random plugins --- roles/server/beets.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/server/beets.nix b/roles/server/beets.nix index fc69963..67d76c9 100644 --- a/roles/server/beets.nix +++ b/roles/server/beets.nix @@ -46,6 +46,8 @@ in { "fetchart" "chroma" "permissions" + "mbsync" + "random" ]; permissions = { file = "644"; From cf08bc61b21a46e9779550ed7e42c40ae5d188a7 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 4 Oct 2025 17:28:08 +0200 Subject: [PATCH 1054/1125] Flake: use stable catppuccin nix for Everest --- flake.lock | 50 +++++++++++++++++++++++++++++++++++++++++++------- flake.nix | 11 +++++++++-- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 9a4a5f8..db1c629 100644 --- a/flake.lock +++ b/flake.lock @@ -28,15 +28,16 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1758956381, - "narHash": "sha256-ROUw5E8CibG3jEy6oHjrkF6/P60eiaUJmc2s2ecC/LM=", + "lastModified": 1754766435, + "narHash": "sha256-DT8CQoqV2haX+Fo16WXAt9gKCSXOZH9ZfnV++Br+qcM=", "owner": "catppuccin", "repo": "nix", - "rev": "02dee881c3e644e2b561f407742f1fd927c40b83", + "rev": "e339d6d822fa81c39d1ab89694b4ee2cfc830c9a", "type": "github" }, "original": { "owner": "catppuccin", + "ref": "release-25.05", "repo": "nix", "type": "github" } @@ -57,6 +58,24 @@ "type": "github" } }, + "catppuccin-unstable": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1759572023, + "narHash": "sha256-2fzYq/m2PXie5WZO5LhyiZrTIUdUFp1SCLZAwvPL5xo=", + "owner": "catppuccin", + "repo": "nix", + "rev": "eeada12912d80d04733383d231a9d66172858718", + "type": "github" + }, + "original": { + "owner": "catppuccin", + "repo": "nix", + "type": "github" + } + }, "copyparty": { "inputs": { "flake-utils": "flake-utils", @@ -429,16 +448,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1758035966, - "narHash": "sha256-qqIJ3yxPiB0ZQTT9//nFGQYn8X/PBoJbofA7hRKZnmE=", + "lastModified": 1759439645, + "narHash": "sha256-oiAyQaRilPk525Z5aTtTNWNzSrcdJ7IXM0/PL3CGlbI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8d4ddb19d03c65a36ad8d189d001dc32ffb0306b", + "rev": "879bd460b3d3e8571354ce172128fbcbac1ed633", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-unstable", + "ref": "nixos-25.05", "repo": "nixpkgs", "type": "github" } @@ -473,6 +492,22 @@ "type": "indirect" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1759381078, + "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "plasma-manager": { "inputs": { "home-manager": [ @@ -501,6 +536,7 @@ "agenix": "agenix", "catppuccin": "catppuccin", "catppuccin-konsole": "catppuccin-konsole", + "catppuccin-unstable": "catppuccin-unstable", "copyparty": "copyparty", "eza-themes": "eza-themes", "home-manager": "home-manager_2", diff --git a/flake.nix b/flake.nix index 1f699e7..4bc669d 100644 --- a/flake.nix +++ b/flake.nix @@ -61,7 +61,8 @@ nix-flatpak.url = "github:gmodena/nix-flatpak/main"; - catppuccin.url = "github:catppuccin/nix"; + catppuccin-unstable.url = "github:catppuccin/nix"; + catppuccin.url = "github:catppuccin/nix/release-25.05"; lix-module = { url = "https://git.lix.systems/lix-project/nixos-module/archive/main.tar.gz"; @@ -178,7 +179,13 @@ ) .nixosModules .nix-index - catppuccin.nixosModules.catppuccin + ( + if stable + then catppuccin + else catppuccin-unstable + ) + .nixosModules + .catppuccin ( if stable then lix-module From f445891c25ef96a3f3d4617295eccf8913de50a6 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 Oct 2025 00:51:17 +0200 Subject: [PATCH 1055/1125] Kde/patches: delete merged patches --- roles/kde/patches/kwindowsystem/1-pr187.patch | 78 ---- roles/kde/patches/kwindowsystem/patches.txt | 4 - roles/kde/patches/kwindowsystem/pr186.patch | 415 ------------------ 3 files changed, 497 deletions(-) delete mode 100644 roles/kde/patches/kwindowsystem/1-pr187.patch delete mode 100644 roles/kde/patches/kwindowsystem/patches.txt delete mode 100644 roles/kde/patches/kwindowsystem/pr186.patch diff --git a/roles/kde/patches/kwindowsystem/1-pr187.patch b/roles/kde/patches/kwindowsystem/1-pr187.patch deleted file mode 100644 index 9021735..0000000 --- a/roles/kde/patches/kwindowsystem/1-pr187.patch +++ /dev/null @@ -1,78 +0,0 @@ -From b05d0431d741510c12294c85dc5ce001a8aceca2 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Wed, 17 Sep 2025 11:41:15 +0300 -Subject: [PATCH 1/2] wayland: Fix leaking xdg activation objects - -Nobody destroys WaylandXdgActivationV1 objects, we also must call destroy() -manually. ---- - src/platforms/wayland/waylandxdgactivationv1_p.h | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/src/platforms/wayland/waylandxdgactivationv1_p.h b/src/platforms/wayland/waylandxdgactivationv1_p.h -index e74c550b..e3b14c27 100644 ---- a/src/platforms/wayland/waylandxdgactivationv1_p.h -+++ b/src/platforms/wayland/waylandxdgactivationv1_p.h -@@ -16,10 +16,18 @@ class QWaylandSurface; - class WaylandXdgActivationTokenV1 : public QObject, public QtWayland::xdg_activation_token_v1 - { - Q_OBJECT -+ - public: -+ ~WaylandXdgActivationTokenV1() override -+ { -+ destroy(); -+ } -+ -+protected: - void xdg_activation_token_v1_done(const QString &token) override - { - Q_EMIT done(token); -+ deleteLater(); - } - - Q_SIGNALS: --- -GitLab - - -From ac28bf993ba7295faf39607d4b4402f6dce1c36b Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Wed, 17 Sep 2025 11:43:16 +0300 -Subject: [PATCH 2/2] wayland: Drop WaylandXdgActivationTokenV1::failed signal - -It's not emitted by anyone. ---- - src/platforms/wayland/waylandxdgactivationv1_p.h | 1 - - src/platforms/wayland/windowsystem.cpp | 3 --- - 2 files changed, 4 deletions(-) - -diff --git a/src/platforms/wayland/waylandxdgactivationv1_p.h b/src/platforms/wayland/waylandxdgactivationv1_p.h -index e3b14c27..077ccd93 100644 ---- a/src/platforms/wayland/waylandxdgactivationv1_p.h -+++ b/src/platforms/wayland/waylandxdgactivationv1_p.h -@@ -31,7 +31,6 @@ protected: - } - - Q_SIGNALS: -- void failed(); - void done(const QString &token); - }; - -diff --git a/src/platforms/wayland/windowsystem.cpp b/src/platforms/wayland/windowsystem.cpp -index 034ffd37..f2d8b4f2 100644 ---- a/src/platforms/wayland/windowsystem.cpp -+++ b/src/platforms/wayland/windowsystem.cpp -@@ -95,9 +95,6 @@ void WindowSystem::requestToken(QWindow *window, uint32_t serial, const QString - auto waylandApp = qGuiApp->nativeInterface(); - auto seat = waylandApp ? waylandApp->lastInputSeat() : nullptr; - auto tokenReq = activation->requestXdgActivationToken(seat, wlSurface, serial, app_id); -- connect(tokenReq, &WaylandXdgActivationTokenV1::failed, KWindowSystem::self(), [serial, app_id]() { -- Q_EMIT KWaylandExtras::self()->xdgActivationTokenArrived(serial, {}); -- }); - connect(tokenReq, &WaylandXdgActivationTokenV1::done, KWindowSystem::self(), [serial](const QString &token) { - Q_EMIT KWaylandExtras::self()->xdgActivationTokenArrived(serial, token); - }); --- -GitLab - diff --git a/roles/kde/patches/kwindowsystem/patches.txt b/roles/kde/patches/kwindowsystem/patches.txt deleted file mode 100644 index f7b32a9..0000000 --- a/roles/kde/patches/kwindowsystem/patches.txt +++ /dev/null @@ -1,4 +0,0 @@ -Plasma 6.6.0: - -Pr 186 https://invent.kde.org/frameworks/kwindowsystem/-/merge_requests/186 -Pr 187 https://invent.kde.org/frameworks/kwindowsystem/-/merge_requests/187 diff --git a/roles/kde/patches/kwindowsystem/pr186.patch b/roles/kde/patches/kwindowsystem/pr186.patch deleted file mode 100644 index c77e64f..0000000 --- a/roles/kde/patches/kwindowsystem/pr186.patch +++ /dev/null @@ -1,415 +0,0 @@ -From 9d0ffb13d290d76df03d199b50c3b3364d4b93bc Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Wed, 17 Sep 2025 10:14:15 +0300 -Subject: [PATCH 1/2] Add QFuture-based xdg-activation token helpers - -QFuture can be used to make the code that needs activation tokens cleaner. ---- - src/kwaylandextras.cpp | 14 +++++++++++ - src/kwaylandextras.h | 21 ++++++++++++++++ - src/kwindowsystem_p.h | 8 ++++++ - .../wayland/waylandxdgactivationv1_p.h | 19 ++++++++++++++ - src/platforms/wayland/windowsystem.cpp | 25 ++++++++++++++++--- - src/platforms/wayland/windowsystem.h | 3 ++- - tests/activationtest.cpp | 13 +++++----- - tests/kwaylandextrastest.cpp | 12 +++------ - 8 files changed, 95 insertions(+), 20 deletions(-) - -diff --git a/src/kwaylandextras.cpp b/src/kwaylandextras.cpp -index 036d57d3..a5f8af8f 100644 ---- a/src/kwaylandextras.cpp -+++ b/src/kwaylandextras.cpp -@@ -63,4 +63,18 @@ void KWaylandExtras::unexportWindow(QWindow *window) - } - } - -+QFuture KWaylandExtras::xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId) -+{ -+ if (auto dv3 = dynamic_cast(KWindowSystem::d_func())) { -+ return dv3->xdgActivationToken(window, serial, appId); -+ } else { -+ return QFuture(); -+ } -+} -+ -+QFuture KWaylandExtras::xdgActivationToken(QWindow *window, const QString &appId) -+{ -+ return xdgActivationToken(window, lastInputSerial(window), appId); -+} -+ - #include "moc_kwaylandextras.cpp" -diff --git a/src/kwaylandextras.h b/src/kwaylandextras.h -index f43135d0..2f763dd5 100644 ---- a/src/kwaylandextras.h -+++ b/src/kwaylandextras.h -@@ -9,6 +9,7 @@ - #ifndef KWAYLANDEXTRAS_H - #define KWAYLANDEXTRAS_H - -+#include - #include - #include - -@@ -61,6 +62,26 @@ public: - */ - Q_INVOKABLE static void unexportWindow(QWindow *window); - -+ /*! -+ * Requests an xdg_activation_v1 token for a specific window \a window with the given \a appId. -+ * The \a serial indicates an event that triggered the request. -+ * -+ * \note No xdgActivationTokenArrived() signal will be emitted for this token. -+ * -+ * \since 6.19 -+ */ -+ static QFuture xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId); -+ -+ /*! -+ * Requests an xdg_activation_v1 token for a specific window \a window with the given \a appId. -+ * The last received input serial will be used to request the token. -+ * -+ * \note No xdgActivationTokenArrived() signal will be emitted for this token. -+ * -+ * \since 6.19 -+ */ -+ static QFuture xdgActivationToken(QWindow *window, const QString &appId); -+ - Q_SIGNALS: - /*! - * Activation \a token to pass to the client. -diff --git a/src/kwindowsystem_p.h b/src/kwindowsystem_p.h -index eb9348ba..e4b51e3e 100644 ---- a/src/kwindowsystem_p.h -+++ b/src/kwindowsystem_p.h -@@ -7,6 +7,8 @@ - #define KWINDOWSYSTEM_P_H - - #include "netwm_def.h" -+ -+#include - #include - #include //For WId - #include -@@ -33,4 +35,10 @@ public: - virtual void unexportWindow(QWindow *window) = 0; - }; - -+class KWINDOWSYSTEM_EXPORT KWindowSystemPrivateV3 : public KWindowSystemPrivateV2 -+{ -+public: -+ virtual QFuture xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId) = 0; -+}; -+ - #endif -diff --git a/src/platforms/wayland/waylandxdgactivationv1_p.h b/src/platforms/wayland/waylandxdgactivationv1_p.h -index 077ccd93..629d45ef 100644 ---- a/src/platforms/wayland/waylandxdgactivationv1_p.h -+++ b/src/platforms/wayland/waylandxdgactivationv1_p.h -@@ -8,7 +8,10 @@ - #define WAYLANDXDGACTIVATIONV1_P_H - - #include "qwayland-xdg-activation-v1.h" -+ -+#include - #include -+#include - #include - - class QWaylandSurface; -@@ -18,20 +21,36 @@ class WaylandXdgActivationTokenV1 : public QObject, public QtWayland::xdg_activa - Q_OBJECT - - public: -+ WaylandXdgActivationTokenV1() -+ { -+ m_promise.start(); -+ } -+ - ~WaylandXdgActivationTokenV1() override - { - destroy(); - } - -+ QFuture future() const -+ { -+ return m_promise.future(); -+ } -+ - protected: - void xdg_activation_token_v1_done(const QString &token) override - { -+ m_promise.addResult(token); -+ m_promise.finish(); -+ - Q_EMIT done(token); - deleteLater(); - } - - Q_SIGNALS: - void done(const QString &token); -+ -+private: -+ QPromise m_promise; - }; - - class WaylandXdgActivationV1 : public QWaylandClientExtensionTemplate, public QtWayland::xdg_activation_v1 -diff --git a/src/platforms/wayland/windowsystem.cpp b/src/platforms/wayland/windowsystem.cpp -index f2d8b4f2..ebb22d78 100644 ---- a/src/platforms/wayland/windowsystem.cpp -+++ b/src/platforms/wayland/windowsystem.cpp -@@ -50,9 +50,7 @@ public: - }; - - WindowSystem::WindowSystem() -- : QObject() -- , KWindowSystemPrivateV2() -- , m_lastToken(qEnvironmentVariable("XDG_ACTIVATION_TOKEN")) -+ : m_lastToken(qEnvironmentVariable("XDG_ACTIVATION_TOKEN")) - { - m_windowManagement = new WindowManagement; - } -@@ -303,4 +301,25 @@ void WindowSystem::doSetMainWindow(QWindow *window, const QString &handle) - } - } - -+QFuture WindowSystem::xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId) -+{ -+ WaylandXdgActivationV1 *activation = WaylandXdgActivationV1::self(); -+ if (!activation->isActive()) { -+ return QFuture(); -+ } -+ -+ auto waylandApp = qGuiApp->nativeInterface(); -+ if (!waylandApp) { -+ return QFuture(); -+ } -+ -+ if (window) { -+ window->create(); -+ } -+ wl_surface *wlSurface = surfaceForWindow(window); -+ -+ auto token = activation->requestXdgActivationToken(waylandApp->lastInputSeat(), wlSurface, serial, appId); -+ return token->future(); -+} -+ - #include "moc_windowsystem.cpp" -diff --git a/src/platforms/wayland/windowsystem.h b/src/platforms/wayland/windowsystem.h -index 87bf23ed..4df82388 100644 ---- a/src/platforms/wayland/windowsystem.h -+++ b/src/platforms/wayland/windowsystem.h -@@ -12,7 +12,7 @@ - - class WindowManagement; - --class WindowSystem : public QObject, public KWindowSystemPrivateV2 -+class WindowSystem : public QObject, public KWindowSystemPrivateV3 - { - Q_OBJECT - public: -@@ -27,6 +27,7 @@ public: - void exportWindow(QWindow *window) override; - void unexportWindow(QWindow *window) override; - void setMainWindow(QWindow *window, const QString &handle) override; -+ QFuture xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId) override; - - protected: - bool eventFilter(QObject *watched, QEvent *event) override; -diff --git a/tests/activationtest.cpp b/tests/activationtest.cpp -index 306c6048..7aaae4ea 100644 ---- a/tests/activationtest.cpp -+++ b/tests/activationtest.cpp -@@ -28,13 +28,12 @@ public: - pushButton->setText("Raise other"); - layout()->addWidget(pushButton); - -- connect(pushButton, &QPushButton::clicked, this, [this] { -- KWaylandExtras::requestXdgActivationToken(windowHandle(), KWaylandExtras::lastInputSerial(windowHandle()), QString()); -- }); -- -- connect(KWaylandExtras::self(), &KWaylandExtras::xdgActivationTokenArrived, this, [otherWindow](int /*serial*/, const QString &token) { -- KWindowSystem::setCurrentXdgActivationToken(token); -- KWindowSystem::activateWindow(otherWindow->windowHandle()); -+ connect(pushButton, &QPushButton::clicked, this, [this, otherWindow] { -+ KWaylandExtras::xdgActivationToken(windowHandle(), KWaylandExtras::lastInputSerial(windowHandle()), QString()) -+ .then(otherWindow, [otherWindow](const QString &token) { -+ KWindowSystem::setCurrentXdgActivationToken(token); -+ KWindowSystem::activateWindow(otherWindow->windowHandle()); -+ }); - }); - } - }; -diff --git a/tests/kwaylandextrastest.cpp b/tests/kwaylandextrastest.cpp -index 3048cb37..2ee86a82 100644 ---- a/tests/kwaylandextrastest.cpp -+++ b/tests/kwaylandextrastest.cpp -@@ -79,16 +79,10 @@ void Window::updateSerial() - - void Window::requestToken() - { -- connect( -- KWaylandExtras::self(), -- &KWaylandExtras::xdgActivationTokenArrived, -- this, -- [this](int /*serial*/, const QString &token) { -+ KWaylandExtras::xdgActivationToken(windowHandle(), KWaylandExtras::self()->lastInputSerial(windowHandle()), QString()) -+ .then(this, [this](const QString &token) { - m_tokenLabel->setText("XDG actvation token: " + token); -- }, -- Qt::SingleShotConnection); -- -- KWaylandExtras::requestXdgActivationToken(windowHandle(), KWaylandExtras::self()->lastInputSerial(windowHandle()), QString()); -+ }); - } - - void Window::exportWindow() --- -GitLab - - -From 1b16c417c697b5d30724ce37d0364af894f6680d Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Wed, 17 Sep 2025 12:01:53 +0300 -Subject: [PATCH 2/2] Deprecate KWaylandExtras::requestXdgActivationToken() - -KWaylandExtras::xdgActivationToken() provides a more convenient way to -retrieve an xdg activation token. - -Note that the QML side has no corresponding counterpart, however on the -other hand, there is no QML code that uses this function too. If the need -arises, the QML specific API could provide a Promise-like object. ---- - src/CMakeLists.txt | 2 +- - src/kwaylandextras.cpp | 2 ++ - src/kwaylandextras.h | 9 ++++++++- - src/kwindowsystem_p.h | 2 ++ - src/platforms/wayland/windowsystem.cpp | 2 ++ - src/platforms/wayland/windowsystem.h | 2 ++ - 6 files changed, 17 insertions(+), 2 deletions(-) - -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index fd72063b..ba748c2c 100644 ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -88,7 +88,7 @@ ecm_generate_export_header(KF6WindowSystem - VERSION ${KF_VERSION} - USE_VERSION_HEADER - DEPRECATED_BASE_VERSION 0 -- DEPRECATION_VERSIONS 6.0 -+ DEPRECATION_VERSIONS 6.0 6.19 - EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} - ) - -diff --git a/src/kwaylandextras.cpp b/src/kwaylandextras.cpp -index a5f8af8f..241f80be 100644 ---- a/src/kwaylandextras.cpp -+++ b/src/kwaylandextras.cpp -@@ -26,6 +26,7 @@ KWaylandExtras *KWaylandExtras::self() - return &instance; - } - -+#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(6, 19) - void KWaylandExtras::requestXdgActivationToken(QWindow *window, uint32_t serial, const QString &app_id) - { - auto dv2 = dynamic_cast(KWindowSystem::d_func()); -@@ -39,6 +40,7 @@ void KWaylandExtras::requestXdgActivationToken(QWindow *window, uint32_t serial, - } - dv2->requestToken(window, serial, app_id); - } -+#endif - - quint32 KWaylandExtras::lastInputSerial(QWindow *window) - { -diff --git a/src/kwaylandextras.h b/src/kwaylandextras.h -index 2f763dd5..56424b89 100644 ---- a/src/kwaylandextras.h -+++ b/src/kwaylandextras.h -@@ -31,14 +31,18 @@ public: - */ - static KWaylandExtras *self(); - -+#if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(6, 19) - /*! - * Requests an xdg_activation_v1 token for a specific window \a win with the given \a app_id. - * - * \a serial Serial of the event that triggered the request. - * - * \sa lastInputSerial -+ * \deprecated [6.19] Use xdgActivationToken() instead. - */ -+ KWINDOWSYSTEM_DEPRECATED_VERSION(6, 19, "Use xdgActivationToken()") - Q_INVOKABLE static void requestXdgActivationToken(QWindow *win, uint32_t serial, const QString &app_id); -+#endif - - /*! - * Offers the seat's current serial for the given \a window. -@@ -83,14 +87,17 @@ public: - static QFuture xdgActivationToken(QWindow *window, const QString &appId); - - Q_SIGNALS: -+#if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(6, 19) - /*! - * Activation \a token to pass to the client. - * - * \a serial Serial of the event that triggered the request - * - * \sa requestXdgActivationToken -+ * \deprecated [6.19] Use xdgActivationToken() instead. - */ -- void xdgActivationTokenArrived(int serial, const QString &token); -+ KWINDOWSYSTEM_DEPRECATED_VERSION(6, 19, "Use xdgActivationToken()") void xdgActivationTokenArrived(int serial, const QString &token); -+#endif - - /*! - * The \a handle of the given \a window to pass to the client. -diff --git a/src/kwindowsystem_p.h b/src/kwindowsystem_p.h -index e4b51e3e..92997120 100644 ---- a/src/kwindowsystem_p.h -+++ b/src/kwindowsystem_p.h -@@ -27,7 +27,9 @@ public: - class KWINDOWSYSTEM_EXPORT KWindowSystemPrivateV2 : public KWindowSystemPrivate - { - public: -+#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(6, 19) - virtual void requestToken(QWindow *win, uint32_t serial, const QString &app_id) = 0; -+#endif - virtual void setCurrentToken(const QString &token) = 0; - virtual quint32 lastInputSerial(QWindow *window) = 0; - virtual void setMainWindow(QWindow *window, const QString &handle) = 0; -diff --git a/src/platforms/wayland/windowsystem.cpp b/src/platforms/wayland/windowsystem.cpp -index ebb22d78..bc803a4f 100644 ---- a/src/platforms/wayland/windowsystem.cpp -+++ b/src/platforms/wayland/windowsystem.cpp -@@ -74,6 +74,7 @@ void WindowSystem::activateWindow(QWindow *win, long int time) - activation->activate(m_lastToken, s); - } - -+#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(6, 19) - void WindowSystem::requestToken(QWindow *window, uint32_t serial, const QString &app_id) - { - if (window) { -@@ -97,6 +98,7 @@ void WindowSystem::requestToken(QWindow *window, uint32_t serial, const QString - Q_EMIT KWaylandExtras::self()->xdgActivationTokenArrived(serial, token); - }); - } -+#endif - - void WindowSystem::setCurrentToken(const QString &token) - { -diff --git a/src/platforms/wayland/windowsystem.h b/src/platforms/wayland/windowsystem.h -index 4df82388..e9dca128 100644 ---- a/src/platforms/wayland/windowsystem.h -+++ b/src/platforms/wayland/windowsystem.h -@@ -19,7 +19,9 @@ public: - WindowSystem(); - ~WindowSystem() override; - void activateWindow(QWindow *win, long time) override; -+#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(6, 19) - void requestToken(QWindow *win, uint32_t serial, const QString &app_id) override; -+#endif - quint32 lastInputSerial(QWindow *window) override; - void setCurrentToken(const QString &token) override; - bool showingDesktop() override; --- -GitLab - From 3d91ef0932b789fcf342791ac5b71024ee549c3f Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 Oct 2025 00:52:33 +0200 Subject: [PATCH 1056/1125] Desktop/syncthing: add another missing option --- roles/desktop/services/syncthing.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/services/syncthing.nix b/roles/desktop/services/syncthing.nix index dee6a2a..249f49d 100644 --- a/roles/desktop/services/syncthing.nix +++ b/roles/desktop/services/syncthing.nix @@ -38,6 +38,7 @@ "options" "relay" "useInotify" + "guiPasswordFile" ]; removeMissingOptions = rawOptions: ( # lib.attrsets.filterAttrs (n: v: n == "all_proxy") rawOptions From 0af0720268ddebe66aae9e0626a3050a576c01d8 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 Oct 2025 00:52:50 +0200 Subject: [PATCH 1057/1125] Flake: update lock file --- flake.lock | 102 ++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/flake.lock b/flake.lock index db1c629..a2f5ecf 100644 --- a/flake.lock +++ b/flake.lock @@ -63,11 +63,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1759572023, - "narHash": "sha256-2fzYq/m2PXie5WZO5LhyiZrTIUdUFp1SCLZAwvPL5xo=", + "lastModified": 1760692571, + "narHash": "sha256-SgqC+B7F7hHDKug+zRUL83vhibCSknzhRl0+OxUYjn4=", "owner": "catppuccin", "repo": "nix", - "rev": "eeada12912d80d04733383d231a9d66172858718", + "rev": "8a084b86b6a4b2a1575e8cc67e07c4a687fce276", "type": "github" }, "original": { @@ -84,11 +84,11 @@ ] }, "locked": { - "lastModified": 1759098182, - "narHash": "sha256-5+jWxVFWS9i6FQjdmKMWQZqN57W3Tb1cF1IqKqjind4=", + "lastModified": 1760740214, + "narHash": "sha256-pCCcmRzZeGvYeeF87EZOigkYqy2x3oXYWYuHh1DQZL8=", "owner": "9001", "repo": "copyparty", - "rev": "d08e872062f0ed2ef28d1e5d3d5a32bac840a723", + "rev": "51e6099c581ed57ce31f870ba7a10852fc2f09df", "type": "github" }, "original": { @@ -100,11 +100,11 @@ "eza-themes": { "flake": false, "locked": { - "lastModified": 1754231765, - "narHash": "sha256-2WTbCQlhwMo5cOn3KwtNiIst0tNfASfZnPNsNBs+gcU=", + "lastModified": 1760304074, + "narHash": "sha256-qEC7H9/ghnjkwmMZ788TSgS9ysyIfD+3NHCjxq0Dps0=", "owner": "eza-community", "repo": "eza-themes", - "rev": "17095bff4792eecd7f4f1ed8301b15000331c906", + "rev": "c03051f67e84110fbae91ab7cbc377b3460f035c", "type": "github" }, "original": { @@ -222,11 +222,11 @@ ] }, "locked": { - "lastModified": 1759106866, - "narHash": "sha256-GjLvAl7qxGxKtop6ghasxjQ1biTT7pA+WU45byzMl/4=", + "lastModified": 1760662441, + "narHash": "sha256-mlDqR1Ntgs9uYYEAUR1IhamKBO0lxoNS4zGLzEZaY0A=", "owner": "nix-community", "repo": "home-manager", - "rev": "619ae569293b6427d23cce4854eb4f3c33af3eec", + "rev": "722792af097dff5790f1a66d271a47759f477755", "type": "github" }, "original": { @@ -264,11 +264,11 @@ ] }, "locked": { - "lastModified": 1757230583, - "narHash": "sha256-4uqu7sFPOaVTCogsxaGMgbzZ2vK40GVGMfUmrvK3/LY=", + "lastModified": 1760534924, + "narHash": "sha256-OIOCC86DxTxp1VG7xAiM+YABtVqp6vTkYIoAiGQMqso=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "fc3960e6c32c9d4f95fff2ef84444284d24d3bea", + "rev": "100b4e000032b865563a9754e5bca189bc544764", "type": "github" }, "original": { @@ -280,11 +280,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1759066537, - "narHash": "sha256-9wdZxZqjWCobgQU6TDmdFHm2v8zOKFbg56+iThu63Vc=", - "rev": "f31e8e2b55419c7f250f29ae6fbc59be4a4c259e", + "lastModified": 1760728877, + "narHash": "sha256-y3HzKkfXNajVgYSBNUbxiPFcRzt0xpOg8/LLmZX0Kpc=", + "rev": "a55fe35dac3495fc3f9243b5817ce8a5314a8dd5", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/f31e8e2b55419c7f250f29ae6fbc59be4a4c259e.tar.gz?rev=f31e8e2b55419c7f250f29ae6fbc59be4a4c259e" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/a55fe35dac3495fc3f9243b5817ce8a5314a8dd5.tar.gz?rev=a55fe35dac3495fc3f9243b5817ce8a5314a8dd5" }, "original": { "type": "tarball", @@ -303,11 +303,11 @@ ] }, "locked": { - "lastModified": 1756511062, - "narHash": "sha256-IgD1JR7scSEwlK/YAbmrcTWpAYT30LPldCUHdzXkaMs=", - "rev": "3f09a5eb772e02d98bb8878ab687d5b721f00d16", + "lastModified": 1759851320, + "narHash": "sha256-n5dRAIC3/78drQtFxmQRrBLd6TKfotUnX7GWu0mAcSg=", + "rev": "7c31a18259b8358ac196cf803a26967c0fa1d3e4", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/3f09a5eb772e02d98bb8878ab687d5b721f00d16.tar.gz?rev=3f09a5eb772e02d98bb8878ab687d5b721f00d16" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/7c31a18259b8358ac196cf803a26967c0fa1d3e4.tar.gz?rev=7c31a18259b8358ac196cf803a26967c0fa1d3e4" }, "original": { "type": "tarball", @@ -326,11 +326,11 @@ ] }, "locked": { - "lastModified": 1756511062, - "narHash": "sha256-IgD1JR7scSEwlK/YAbmrcTWpAYT30LPldCUHdzXkaMs=", - "rev": "3f09a5eb772e02d98bb8878ab687d5b721f00d16", + "lastModified": 1759851320, + "narHash": "sha256-n5dRAIC3/78drQtFxmQRrBLd6TKfotUnX7GWu0mAcSg=", + "rev": "7c31a18259b8358ac196cf803a26967c0fa1d3e4", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/3f09a5eb772e02d98bb8878ab687d5b721f00d16.tar.gz?rev=3f09a5eb772e02d98bb8878ab687d5b721f00d16" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/7c31a18259b8358ac196cf803a26967c0fa1d3e4.tar.gz?rev=7c31a18259b8358ac196cf803a26967c0fa1d3e4" }, "original": { "type": "tarball", @@ -397,11 +397,11 @@ ] }, "locked": { - "lastModified": 1759032422, - "narHash": "sha256-WZf+FhebP2/1pK2np5xj/NuDjD6fXK2BHnq/tPUN18o=", + "lastModified": 1760241904, + "narHash": "sha256-OD7QnaGEVNdukYEbJbUNWPsvnDrpbZOZxVIk6Pt9Jhw=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "ec7a78cb0e098832d8acac091a4df393259c4839", + "rev": "c9f5ea45f25652ec2f771f9426ccacb21cbbaeaa", "type": "github" }, "original": { @@ -417,11 +417,11 @@ ] }, "locked": { - "lastModified": 1759032422, - "narHash": "sha256-WZf+FhebP2/1pK2np5xj/NuDjD6fXK2BHnq/tPUN18o=", + "lastModified": 1760241904, + "narHash": "sha256-OD7QnaGEVNdukYEbJbUNWPsvnDrpbZOZxVIk6Pt9Jhw=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "ec7a78cb0e098832d8acac091a4df393259c4839", + "rev": "c9f5ea45f25652ec2f771f9426ccacb21cbbaeaa", "type": "github" }, "original": { @@ -432,11 +432,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1758663926, - "narHash": "sha256-6CFdj7Xs616t1W4jLDH7IohAAvl5Dyib3qEv/Uqw1rk=", + "lastModified": 1760106635, + "narHash": "sha256-2GoxVaKWTHBxRoeUYSjv0AfSOx4qw5CWSFz2b+VolKU=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "170ff93c860b2a9868ed1e1102d4e52cb3d934e1", + "rev": "9ed85f8afebf2b7478f25db0a98d0e782c0ed903", "type": "github" }, "original": { @@ -448,11 +448,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1759439645, - "narHash": "sha256-oiAyQaRilPk525Z5aTtTNWNzSrcdJ7IXM0/PL3CGlbI=", + "lastModified": 1753749649, + "narHash": "sha256-+jkEZxs7bfOKfBIk430K+tK9IvXlwzqQQnppC2ZKFj4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "879bd460b3d3e8571354ce172128fbcbac1ed633", + "rev": "1f08a4df998e21f4e8be8fb6fbf61d11a1a5076a", "type": "github" }, "original": { @@ -464,11 +464,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1758791193, - "narHash": "sha256-F8WmEwFoHsnix7rt290R0rFXNJiMbClMZyIC/e+HYf0=", + "lastModified": 1760580664, + "narHash": "sha256-/YdfibIrnqXAL8p5kqCU345mzpHoOtuVIkMiI2pF4Dc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "25e53aa156d47bad5082ff7618f5feb1f5e02d01", + "rev": "98ff3f9af2684f6136c24beef08f5e2033fc5389", "type": "github" }, "original": { @@ -479,11 +479,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1759036355, - "narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", + "lastModified": 1760524057, + "narHash": "sha256-EVAqOteLBFmd7pKkb0+FIUyzTF61VKi7YmvP1tw4nEw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", + "rev": "544961dfcce86422ba200ed9a0b00dd4b1486ec5", "type": "github" }, "original": { @@ -494,11 +494,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1759381078, - "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", + "lastModified": 1760524057, + "narHash": "sha256-EVAqOteLBFmd7pKkb0+FIUyzTF61VKi7YmvP1tw4nEw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", + "rev": "544961dfcce86422ba200ed9a0b00dd4b1486ec5", "type": "github" }, "original": { @@ -518,11 +518,11 @@ ] }, "locked": { - "lastModified": 1759064045, - "narHash": "sha256-v74j88evVeCK7eqt/wfqe1x3YalwI/uss8TXtiqy5/I=", + "lastModified": 1759321049, + "narHash": "sha256-8XkU4gIrLT2DJZWQyvsP5woXGZF5eE/7AnKfwQkiwYU=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "7d7629ba12b2ba7849718f18c1fba6e14708d974", + "rev": "205dcfd4a30d4a5d1b4f28defee69daa7c7252cd", "type": "github" }, "original": { From c777f0e5f18ad30da2b61d4d2c14f4729b57b126 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 18 Oct 2025 11:43:11 +0200 Subject: [PATCH 1058/1125] Common/nix: disable nixos-options --- roles/common/programs/nix.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index 7a96dbf..38fbf21 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -20,6 +20,8 @@ ''; }; + system.tools.nixos-option.enable = false; + nix = { settings = { auto-optimise-store = true; From 93944f1391d97bdca44d235fd6acc38e60b6bc87 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 23 Oct 2025 23:54:16 +0200 Subject: [PATCH 1059/1125] Kde/kwin: enable wayland pip support --- roles/kde/programs/kwin.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/kde/programs/kwin.nix b/roles/kde/programs/kwin.nix index 4094a27..5a3e792 100644 --- a/roles/kde/programs/kwin.nix +++ b/roles/kde/programs/kwin.nix @@ -1,5 +1,8 @@ {pkgs, ...}: { environment.plasma6.excludePackages = [pkgs.kdePackages.kwin-x11]; + environment.variables = { + KWIN_WAYLAND_SUPPORT_XX_PIP_V1 = 1; + }; home-manager.users.toast = { programs.plasma = { kwin = { From 2c49a7318bcfca398bf70258ca8eac1776a32222 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 24 Oct 2025 00:41:26 +0200 Subject: [PATCH 1060/1125] Flake: update lock file --- flake.lock | 74 +++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/flake.lock b/flake.lock index a2f5ecf..ec041d0 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1754433428, - "narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=", + "lastModified": 1760836749, + "narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=", "owner": "ryantm", "repo": "agenix", - "rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d", + "rev": "2f0f812f69f3eb4140157fe15e12739adf82e32a", "type": "github" }, "original": { @@ -63,11 +63,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1760692571, - "narHash": "sha256-SgqC+B7F7hHDKug+zRUL83vhibCSknzhRl0+OxUYjn4=", + "lastModified": 1760953099, + "narHash": "sha256-sOKx2YcHa+lWEvaEOIGqLN2WWk1Wf5z6KM02tdfhMtw=", "owner": "catppuccin", "repo": "nix", - "rev": "8a084b86b6a4b2a1575e8cc67e07c4a687fce276", + "rev": "f5b21876888265d2fee7fb0640d1b66a1c1c6503", "type": "github" }, "original": { @@ -84,11 +84,11 @@ ] }, "locked": { - "lastModified": 1760740214, - "narHash": "sha256-pCCcmRzZeGvYeeF87EZOigkYqy2x3oXYWYuHh1DQZL8=", + "lastModified": 1761171657, + "narHash": "sha256-kLJwQUpOTs/g78o3L0aISoPZ/YvMobh+GiU3j28oBAI=", "owner": "9001", "repo": "copyparty", - "rev": "51e6099c581ed57ce31f870ba7a10852fc2f09df", + "rev": "7f5810f1a7a71f020f50439ad8391bcd92726469", "type": "github" }, "original": { @@ -222,11 +222,11 @@ ] }, "locked": { - "lastModified": 1760662441, - "narHash": "sha256-mlDqR1Ntgs9uYYEAUR1IhamKBO0lxoNS4zGLzEZaY0A=", + "lastModified": 1761191301, + "narHash": "sha256-xsRL2Oyb4YRZZ1Tu4WzR2uFg1n931bH+PfLdFcqtLg8=", "owner": "nix-community", "repo": "home-manager", - "rev": "722792af097dff5790f1a66d271a47759f477755", + "rev": "4958aafe7b237dc1e857fb0c916efff72075048f", "type": "github" }, "original": { @@ -264,11 +264,11 @@ ] }, "locked": { - "lastModified": 1760534924, - "narHash": "sha256-OIOCC86DxTxp1VG7xAiM+YABtVqp6vTkYIoAiGQMqso=", + "lastModified": 1761202163, + "narHash": "sha256-6RySf5VQElrm7RYGWxlIkNttemDp4FF0aH+LX435G2Y=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "100b4e000032b865563a9754e5bca189bc544764", + "rev": "47976126007d9658ca4ac4dd933bea8846170fd9", "type": "github" }, "original": { @@ -280,11 +280,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1760728877, - "narHash": "sha256-y3HzKkfXNajVgYSBNUbxiPFcRzt0xpOg8/LLmZX0Kpc=", - "rev": "a55fe35dac3495fc3f9243b5817ce8a5314a8dd5", + "lastModified": 1761154581, + "narHash": "sha256-/qVkVUpT3MRxsZz9J68hLhli3VMcx8+xAbyYuTXWvfE=", + "rev": "253ed1cc05ff75703e36504244f210bc8af8e560", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/a55fe35dac3495fc3f9243b5817ce8a5314a8dd5.tar.gz?rev=a55fe35dac3495fc3f9243b5817ce8a5314a8dd5" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/253ed1cc05ff75703e36504244f210bc8af8e560.tar.gz?rev=253ed1cc05ff75703e36504244f210bc8af8e560" }, "original": { "type": "tarball", @@ -397,11 +397,11 @@ ] }, "locked": { - "lastModified": 1760241904, - "narHash": "sha256-OD7QnaGEVNdukYEbJbUNWPsvnDrpbZOZxVIk6Pt9Jhw=", + "lastModified": 1760846226, + "narHash": "sha256-xmU8kAsRprJiTGBTaGrwmjBP3AMA9ltlrxHKFuy5JWc=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "c9f5ea45f25652ec2f771f9426ccacb21cbbaeaa", + "rev": "5024e1901239a76b7bf94a4cd27f3507e639d49e", "type": "github" }, "original": { @@ -417,11 +417,11 @@ ] }, "locked": { - "lastModified": 1760241904, - "narHash": "sha256-OD7QnaGEVNdukYEbJbUNWPsvnDrpbZOZxVIk6Pt9Jhw=", + "lastModified": 1760846226, + "narHash": "sha256-xmU8kAsRprJiTGBTaGrwmjBP3AMA9ltlrxHKFuy5JWc=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "c9f5ea45f25652ec2f771f9426ccacb21cbbaeaa", + "rev": "5024e1901239a76b7bf94a4cd27f3507e639d49e", "type": "github" }, "original": { @@ -432,11 +432,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1760106635, - "narHash": "sha256-2GoxVaKWTHBxRoeUYSjv0AfSOx4qw5CWSFz2b+VolKU=", + "lastModified": 1760958188, + "narHash": "sha256-2m1S4jl+GEDtlt2QqeHil8Ny456dcGSKJAM7q3j/BFU=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "9ed85f8afebf2b7478f25db0a98d0e782c0ed903", + "rev": "d6645c340ef7d821602fd2cd199e8d1eed10afbc", "type": "github" }, "original": { @@ -464,11 +464,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1760580664, - "narHash": "sha256-/YdfibIrnqXAL8p5kqCU345mzpHoOtuVIkMiI2pF4Dc=", + "lastModified": 1761016216, + "narHash": "sha256-G/iC4t/9j/52i/nm+0/4ybBmAF4hzR8CNHC75qEhjHo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "98ff3f9af2684f6136c24beef08f5e2033fc5389", + "rev": "481cf557888e05d3128a76f14c76397b7d7cc869", "type": "github" }, "original": { @@ -479,11 +479,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1760524057, - "narHash": "sha256-EVAqOteLBFmd7pKkb0+FIUyzTF61VKi7YmvP1tw4nEw=", + "lastModified": 1761114652, + "narHash": "sha256-f/QCJM/YhrV/lavyCVz8iU3rlZun6d+dAiC3H+CDle4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "544961dfcce86422ba200ed9a0b00dd4b1486ec5", + "rev": "01f116e4df6a15f4ccdffb1bcd41096869fb385c", "type": "github" }, "original": { @@ -518,11 +518,11 @@ ] }, "locked": { - "lastModified": 1759321049, - "narHash": "sha256-8XkU4gIrLT2DJZWQyvsP5woXGZF5eE/7AnKfwQkiwYU=", + "lastModified": 1761078382, + "narHash": "sha256-JNJesbe9MMN1Brq41BHEpuH+Z+Zg74y/nI5AFZX84Vw=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "205dcfd4a30d4a5d1b4f28defee69daa7c7252cd", + "rev": "27dfa61b64d0cdb8e4ba6f3aaa4d4e067d64cb5c", "type": "github" }, "original": { From e15a9c0c0122963d00256a5eac15c03507d99206 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 24 Oct 2025 01:07:37 +0200 Subject: [PATCH 1061/1125] Kde/patches: remove patches that are in plasma 6.5 --- flake.nix | 1 - .../plasma-workspace-patch-trimming.patch | 65 - roles/kde/patches/bluedevil/patches.txt | 2 - roles/kde/patches/bluedevil/pr218.patch | 53 - roles/kde/patches/breeze/patches.txt | 2 - roles/kde/patches/breeze/pr545.patch | 333 --- roles/kde/patches/kwin/patches.txt | 6 - roles/kde/patches/kwin/pr3612.patch | 2101 ----------------- roles/kde/patches/kwin/pr7823.patch | 26 - roles/kde/patches/kwin/pr7927.patch | 669 ------ roles/kde/patches/kwin/pr8005.patch | 71 - roles/kde/patches/kwin/pr8155.patch | 60 - roles/kde/patches/plasma-nm/patches.txt | 4 - roles/kde/patches/plasma-nm/pr439.patch | 140 -- roles/kde/patches/plasma-nm/pr442.patch | 168 -- .../plasma-workspace/commit8202ba92.patch | 248 -- .../kde/patches/plasma-workspace/patches.txt | 18 - .../kde/patches/plasma-workspace/pr5589.patch | 37 - .../kde/patches/plasma-workspace/pr5609.patch | 456 ---- .../kde/patches/plasma-workspace/pr5626.patch | 102 - .../kde/patches/plasma-workspace/pr5627.patch | 157 -- .../kde/patches/plasma-workspace/pr5657.patch | 177 -- .../kde/patches/plasma-workspace/pr5673.patch | 392 --- .../patches/plasma-workspace/pr5678.9.patch | 913 ------- .../kde/patches/plasma-workspace/pr5734.patch | 133 -- .../kde/patches/plasma-workspace/pr5746.patch | 33 - .../kde/patches/plasma-workspace/pr5782.patch | 32 - .../kde/patches/plasma-workspace/pr5788.patch | 42 - .../kde/patches/plasma-workspace/pr5816.patch | 349 --- roles/kde/patches/spectacle/patches.txt | 3 - roles/kde/patches/spectacle/pr460.patch | 228 -- 31 files changed, 7021 deletions(-) delete mode 100644 nixpkgs-patches/plasma-workspace-patch-trimming.patch delete mode 100644 roles/kde/patches/bluedevil/patches.txt delete mode 100644 roles/kde/patches/bluedevil/pr218.patch delete mode 100644 roles/kde/patches/breeze/patches.txt delete mode 100644 roles/kde/patches/breeze/pr545.patch delete mode 100644 roles/kde/patches/kwin/patches.txt delete mode 100644 roles/kde/patches/kwin/pr3612.patch delete mode 100644 roles/kde/patches/kwin/pr7823.patch delete mode 100644 roles/kde/patches/kwin/pr7927.patch delete mode 100644 roles/kde/patches/kwin/pr8005.patch delete mode 100644 roles/kde/patches/kwin/pr8155.patch delete mode 100644 roles/kde/patches/plasma-nm/patches.txt delete mode 100644 roles/kde/patches/plasma-nm/pr439.patch delete mode 100644 roles/kde/patches/plasma-nm/pr442.patch delete mode 100644 roles/kde/patches/plasma-workspace/commit8202ba92.patch delete mode 100644 roles/kde/patches/plasma-workspace/pr5589.patch delete mode 100644 roles/kde/patches/plasma-workspace/pr5609.patch delete mode 100644 roles/kde/patches/plasma-workspace/pr5626.patch delete mode 100644 roles/kde/patches/plasma-workspace/pr5627.patch delete mode 100644 roles/kde/patches/plasma-workspace/pr5657.patch delete mode 100644 roles/kde/patches/plasma-workspace/pr5673.patch delete mode 100644 roles/kde/patches/plasma-workspace/pr5678.9.patch delete mode 100644 roles/kde/patches/plasma-workspace/pr5734.patch delete mode 100644 roles/kde/patches/plasma-workspace/pr5746.patch delete mode 100644 roles/kde/patches/plasma-workspace/pr5782.patch delete mode 100644 roles/kde/patches/plasma-workspace/pr5788.patch delete mode 100644 roles/kde/patches/plasma-workspace/pr5816.patch delete mode 100644 roles/kde/patches/spectacle/patches.txt delete mode 100644 roles/kde/patches/spectacle/pr460.patch diff --git a/flake.nix b/flake.nix index 4bc669d..0392399 100644 --- a/flake.nix +++ b/flake.nix @@ -101,7 +101,6 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/plasma-workspace-patch-trimming.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/plasma-workspace-patch-trimming.patch b/nixpkgs-patches/plasma-workspace-patch-trimming.patch deleted file mode 100644 index bfd45ce..0000000 --- a/nixpkgs-patches/plasma-workspace-patch-trimming.patch +++ /dev/null @@ -1,65 +0,0 @@ -diff --git a/pkgs/kde/plasma/plasma-workspace/dependency-paths.patch b/pkgs/kde/plasma/plasma-workspace/dependency-paths.patch -index b4d46cd869bb..ca5bfd2c4889 100644 ---- a/pkgs/kde/plasma/plasma-workspace/dependency-paths.patch -+++ b/pkgs/kde/plasma/plasma-workspace/dependency-paths.patch -@@ -1,13 +1,14 @@ - diff --git a/applets/devicenotifier/plugin/deviceerrormonitor_p.cpp b/applets/devicenotifier/plugin/deviceerrormonitor_p.cpp --index ba214a555d..421d940738 100644 -+index 183f207946..0f64b068ab 100644 - --- a/applets/devicenotifier/plugin/deviceerrormonitor_p.cpp - +++ b/applets/devicenotifier/plugin/deviceerrormonitor_p.cpp --@@ -155,7 +155,7 @@ void DeviceErrorMonitor::queryBlockingApps(const QString &devicePath) -+@@ -168,7 +168,8 @@ void DeviceErrorMonitor::queryBlockingApps(const QString &devicePath) - Q_EMIT blockingAppsReady(blockApps); - p->deleteLater(); - }); - - p->start(QStringLiteral("lsof"), {QStringLiteral("-t"), devicePath}); - + p->start(QStringLiteral("@lsof@"), {QStringLiteral("-t"), devicePath}); -++ // @dbusSend@ - // p.start(QStringLiteral("fuser"), {QStringLiteral("-m"), devicePath}); - } - -@@ -51,7 +52,7 @@ index e4d1ad4311..d45bdfad98 100644 - - void CFcQuery::procExited() - diff --git a/kcms/krdb/krdb.cpp b/kcms/krdb/krdb.cpp --index f3c9956921..09c818739d 100644 -+index 53f77d0a18..680e81b6e4 100644 - --- a/kcms/krdb/krdb.cpp - +++ b/kcms/krdb/krdb.cpp - @@ -425,7 +425,7 @@ void runRdb(unsigned int flags) -@@ -107,7 +108,7 @@ index 7218628ce9..9126475ea4 100644 - +ExecStart=@qdbus@ org.kde.kcminit /kcminit org.kde.KCMInit.runPhase1 - Slice=session.slice - diff --git a/startkde/startplasma.cpp b/startkde/startplasma.cpp --index 4d31c6f408..17418b1ff7 100644 -+index 02c3f260fb..795244064d 100644 - --- a/startkde/startplasma.cpp - +++ b/startkde/startplasma.cpp - @@ -57,7 +57,7 @@ void sigtermHandler(int signalNumber) -@@ -119,7 +120,7 @@ index 4d31c6f408..17418b1ff7 100644 - } - - QStringList allServices(const QLatin1String &prefix) --@@ -512,7 +512,7 @@ QProcess *setupKSplash() -+@@ -508,7 +508,7 @@ QProcess *setupKSplash() - if (ksplashCfg.readEntry("Engine", QStringLiteral("KSplashQML")) == QLatin1String("KSplashQML")) { - p = new QProcess; - p->setProcessChannelMode(QProcess::ForwardedChannels); -@@ -128,14 +129,4 @@ index 4d31c6f408..17418b1ff7 100644 - } - } - return p; --diff --git a/startkde/systemd/plasma-ksplash-ready.service.in b/startkde/systemd/plasma-ksplash-ready.service.in --index 1e903130a9..0861c3d136 100644 ----- a/startkde/systemd/plasma-ksplash-ready.service.in --+++ b/startkde/systemd/plasma-ksplash-ready.service.in --@@ -6,5 +6,5 @@ PartOf=graphical-session.target -- -- [Service] -- Type=oneshot ---ExecStart=dbus-send --session --reply-timeout=1 --type=method_call --dest=org.kde.KSplash /KSplash org.kde.KSplash.setStage string:ready --+ExecStart=@dbusSend@ --session --reply-timeout=1 --type=method_call --dest=org.kde.KSplash /KSplash org.kde.KSplash.setStage string:ready -- Slice=session.slice -+ - diff --git a/roles/kde/patches/bluedevil/patches.txt b/roles/kde/patches/bluedevil/patches.txt deleted file mode 100644 index f1e689d..0000000 --- a/roles/kde/patches/bluedevil/patches.txt +++ /dev/null @@ -1,2 +0,0 @@ -Plasma 6.5.0: -Pr 218 https://invent.kde.org/plasma/bluedevil/-/merge_requests/218 diff --git a/roles/kde/patches/bluedevil/pr218.patch b/roles/kde/patches/bluedevil/pr218.patch deleted file mode 100644 index c9eca02..0000000 --- a/roles/kde/patches/bluedevil/pr218.patch +++ /dev/null @@ -1,53 +0,0 @@ -From ddbf7452c6f2fe8849de723175710dbf39242422 Mon Sep 17 00:00:00 2001 -From: Nate Graham -Date: Fri, 13 Jun 2025 11:55:47 -0600 -Subject: [PATCH] applet: use standard section headers - -We have them; might as well use them. This lets us get rid of a bunch of -complex and fragile code that's responsible for the existing separator. ---- - .../contents/ui/FullRepresentation.qml | 27 +++---------------- - 1 file changed, 3 insertions(+), 24 deletions(-) - -diff --git a/src/applet/package/contents/ui/FullRepresentation.qml b/src/applet/package/contents/ui/FullRepresentation.qml -index df989267d..27295de21 100644 ---- a/src/applet/package/contents/ui/FullRepresentation.qml -+++ b/src/applet/package/contents/ui/FullRepresentation.qml -@@ -111,31 +111,10 @@ PlasmaExtras.Representation { - bottomMargin: Kirigami.Units.largeSpacing - - section.property: "Section" -- // We want to hide the section delegate for the "Connected" -- // group because it's unnecessary; all we want to do here is -- // separate the connected devices from the available ones -- section.delegate: Loader { -+ section.delegate: PlasmaExtras.ListSectionHeader { - required property string section -- -- active: section !== "Connected" && BluezQt.Manager.connectedDevices.length > 0 -- -- width: ListView.view.width - ListView.view.leftMargin - ListView.view.rightMargin -- // Need to manually set the height or else the loader takes up -- // space after the first time it unloads a previously-loaded item -- height: active ? Kirigami.Units.gridUnit : 0 -- -- // give us 2 frames to try and figure out a layout, this reduces jumpyness quite a bit but doesn't -- // entirely eliminate it https://bugs.kde.org/show_bug.cgi?id=438610 -- Behavior on height { PropertyAnimation { duration: 32 } } -- -- sourceComponent: Item { -- KSvg.SvgItem { -- width: parent.width - Kirigami.Units.gridUnit * 2 -- anchors.centerIn: parent -- imagePath: "widgets/line" -- elementId: "horizontal-line" -- } -- } -+ width: listView.width - listView.leftMargin - listView.rightMargin -+ text: section - } - highlight: PlasmaExtras.Highlight {} - highlightMoveDuration: Kirigami.Units.shortDuration --- -GitLab - diff --git a/roles/kde/patches/breeze/patches.txt b/roles/kde/patches/breeze/patches.txt deleted file mode 100644 index bf22bd1..0000000 --- a/roles/kde/patches/breeze/patches.txt +++ /dev/null @@ -1,2 +0,0 @@ -Plasma 6.5.0: -Pr 545 https://invent.kde.org/plasma/breeze/-/merge_requests/545 diff --git a/roles/kde/patches/breeze/pr545.patch b/roles/kde/patches/breeze/pr545.patch deleted file mode 100644 index 926a40d..0000000 --- a/roles/kde/patches/breeze/pr545.patch +++ /dev/null @@ -1,333 +0,0 @@ -From 38567c2f2d2d0f8524e42224dff53a929cbf086a Mon Sep 17 00:00:00 2001 -From: Kai Uwe Broulik -Date: Sat, 24 May 2025 09:33:44 +0200 -Subject: [PATCH 1/3] kstyle/animations: Use QObject as base type rather than - QWidget - -This prepares for the animation engine being used with Qt Quick Controls. - -In most cases the type is cast to the relevant widget type for checking -anyway, so might as well use the cast object further down but not require -a QWidget at the beginning. ---- - kstyle/animations/breezeanimations.cpp | 48 +++++++++++++------------- - kstyle/animations/breezeanimations.h | 4 +-- - 2 files changed, 26 insertions(+), 26 deletions(-) - -diff --git a/kstyle/animations/breezeanimations.cpp b/kstyle/animations/breezeanimations.cpp -index 12e5107c5..ceab53802 100644 ---- a/kstyle/animations/breezeanimations.cpp -+++ b/kstyle/animations/breezeanimations.cpp -@@ -82,7 +82,7 @@ void Animations::setupEngines() - } - - //____________________________________________________________ --void Animations::registerWidget(QWidget *widget) const -+void Animations::registerWidget(QObject *widget) const - { - if (!widget) { - return; -@@ -101,37 +101,37 @@ void Animations::registerWidget(QWidget *widget) const - // for optimization, one should put with most used widgets here first - - // buttons -- if (qobject_cast(widget)) { -- _toolButtonEngine->registerWidget(widget, AnimationHover | AnimationFocus); -- _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus); -+ if (auto toolButton = qobject_cast(widget)) { -+ _toolButtonEngine->registerWidget(toolButton, AnimationHover | AnimationFocus); -+ _widgetStateEngine->registerWidget(toolButton, AnimationHover | AnimationFocus); - - } else if (qobject_cast(widget) || qobject_cast(widget)) { - _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus | AnimationPressed); - -- } else if (qobject_cast(widget)) { -+ } else if (auto button = qobject_cast(widget)) { - // register to toolbox engine if needed -- if (qobject_cast(widget->parent())) { -- _toolBoxEngine->registerWidget(widget); -+ if (auto toolBox = qobject_cast(widget->parent())) { -+ _toolBoxEngine->registerWidget(toolBox); - } - -- _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus); -+ _widgetStateEngine->registerWidget(button, AnimationHover | AnimationFocus); - - } - - // groupboxes - else if (QGroupBox *groupBox = qobject_cast(widget)) { - if (groupBox->isCheckable()) { -- _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus); -+ _widgetStateEngine->registerWidget(groupBox, AnimationHover | AnimationFocus); - } - } - - // sliders -- else if (qobject_cast(widget)) { -- _scrollBarEngine->registerWidget(widget, AnimationHover | AnimationFocus); -- } else if (qobject_cast(widget)) { -- _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus); -- } else if (qobject_cast(widget)) { -- _dialEngine->registerWidget(widget, AnimationHover | AnimationFocus); -+ else if (auto scrollBar = qobject_cast(widget)) { -+ _scrollBarEngine->registerWidget(scrollBar, AnimationHover | AnimationFocus); -+ } else if (auto slider = qobject_cast(widget)) { -+ _widgetStateEngine->registerWidget(slider, AnimationHover | AnimationFocus); -+ } else if (auto dial = qobject_cast(widget)) { -+ _dialEngine->registerWidget(dial, AnimationHover | AnimationFocus); - } - - // progress bar -@@ -162,24 +162,24 @@ void Animations::registerWidget(QWidget *widget) const - - // header views - // need to come before abstract item view, otherwise is skipped -- else if (qobject_cast(widget)) { -- _headerViewEngine->registerWidget(widget); -+ else if (auto headerView = qobject_cast(widget)) { -+ _headerViewEngine->registerWidget(headerView); - } - - // lists -- else if (qobject_cast(widget)) { -- _inputWidgetEngine->registerWidget(widget, AnimationHover | AnimationFocus); -+ else if (auto itemView = qobject_cast(widget)) { -+ _inputWidgetEngine->registerWidget(itemView, AnimationHover | AnimationFocus); - } - - // tabbar -- else if (qobject_cast(widget)) { -- _tabBarEngine->registerWidget(widget); -+ else if (auto tabBar = qobject_cast(widget)) { -+ _tabBarEngine->registerWidget(tabBar); - } - - // scrollarea - else if (QAbstractScrollArea *scrollArea = qobject_cast(widget)) { -- if (scrollArea->frameShadow() == QFrame::Sunken && (widget->focusPolicy() & Qt::StrongFocus)) { -- _inputWidgetEngine->registerWidget(widget, AnimationHover | AnimationFocus); -+ if (scrollArea->frameShadow() == QFrame::Sunken && (scrollArea->focusPolicy() & Qt::StrongFocus)) { -+ _inputWidgetEngine->registerWidget(scrollArea, AnimationHover | AnimationFocus); - } - } - -@@ -190,7 +190,7 @@ void Animations::registerWidget(QWidget *widget) const - } - - //____________________________________________________________ --void Animations::unregisterWidget(QWidget *widget) const -+void Animations::unregisterWidget(QObject *widget) const - { - if (!widget) { - return; -diff --git a/kstyle/animations/breezeanimations.h b/kstyle/animations/breezeanimations.h -index 6551900a5..3215e8fb9 100644 ---- a/kstyle/animations/breezeanimations.h -+++ b/kstyle/animations/breezeanimations.h -@@ -31,10 +31,10 @@ public: - explicit Animations(); - - //* register animations corresponding to given widget, depending on its type. -- void registerWidget(QWidget *widget) const; -+ void registerWidget(QObject *widget) const; - - /** unregister all animations associated to a widget */ -- void unregisterWidget(QWidget *widget) const; -+ void unregisterWidget(QObject *widget) const; - - //* enability engine - [[nodiscard]] WidgetStateEngine &widgetEnabilityEngine() const --- -GitLab - - -From 75201d1e63d82f7282c8bedcc7cc3d2417b1e123 Mon Sep 17 00:00:00 2001 -From: Kai Uwe Broulik -Date: Sat, 24 May 2025 09:40:01 +0200 -Subject: [PATCH 2/3] kstyle: Use styleObject for widgetStateEngine in - CheckBox/RadioButton - -Prepares it for doing the animation also with Qt Quick Controls -without an actual QWidget. ---- - kstyle/breezestyle.cpp | 44 ++++++++++++++++++++++++++++-------------- - 1 file changed, 29 insertions(+), 15 deletions(-) - -diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp -index 09cee6003..19149c382 100644 ---- a/kstyle/breezestyle.cpp -+++ b/kstyle/breezestyle.cpp -@@ -4738,6 +4738,8 @@ bool Style::drawPanelItemViewItemPrimitive(const QStyleOption *option, QPainter - //___________________________________________________________________________________ - bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const - { -+ const QObject *styleObject = widget ? widget : option->styleObject; -+ - // copy rect and palette - const auto &rect(option->rect); - const auto &palette(option->palette); -@@ -4757,15 +4759,15 @@ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter - } - - // animation state -- _animations->widgetStateEngine().updateState(widget, AnimationHover, mouseOver); -- _animations->widgetStateEngine().updateState(widget, AnimationPressed, checkBoxState != CheckOff); -+ _animations->widgetStateEngine().updateState(styleObject, AnimationHover, mouseOver); -+ _animations->widgetStateEngine().updateState(styleObject, AnimationPressed, checkBoxState != CheckOff); - auto target = checkBoxState; -- if (_animations->widgetStateEngine().isAnimated(widget, AnimationPressed)) { -+ if (_animations->widgetStateEngine().isAnimated(styleObject, AnimationPressed)) { - checkBoxState = CheckAnimated; - } -- const qreal animation(_animations->widgetStateEngine().opacity(widget, AnimationPressed)); -+ const qreal animation(_animations->widgetStateEngine().opacity(styleObject, AnimationPressed)); - -- const qreal opacity(_animations->widgetStateEngine().opacity(widget, AnimationHover)); -+ const qreal opacity(_animations->widgetStateEngine().opacity(styleObject, AnimationHover)); - - // render - _helper->renderCheckBoxBackground(painter, rect, palette, checkBoxState, hasHighlightNeutral(widget, option, mouseOver), sunken, animation); -@@ -4777,6 +4779,8 @@ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter - //___________________________________________________________________________________ - bool Style::drawIndicatorRadioButtonPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const - { -+ const QObject *styleObject = widget ? widget : option->styleObject; -+ - // copy rect and palette - const auto &rect(option->rect); - const auto &palette(option->palette); -@@ -4791,19 +4795,27 @@ bool Style::drawIndicatorRadioButtonPrimitive(const QStyleOption *option, QPaint - RadioButtonState radioButtonState((state & State_On) ? RadioOn : RadioOff); - - // animation state -- _animations->widgetStateEngine().updateState(widget, AnimationHover, mouseOver); -- _animations->widgetStateEngine().updateState(widget, AnimationPressed, radioButtonState != RadioOff); -- if (_animations->widgetStateEngine().isAnimated(widget, AnimationPressed)) { -+ _animations->widgetStateEngine().updateState(styleObject, AnimationHover, mouseOver); -+ _animations->widgetStateEngine().updateState(styleObject, AnimationPressed, radioButtonState != RadioOff); -+ if (_animations->widgetStateEngine().isAnimated(styleObject, AnimationPressed)) { - radioButtonState = RadioAnimated; - } -- const qreal animation(_animations->widgetStateEngine().opacity(widget, AnimationPressed)); -+ const qreal animation(_animations->widgetStateEngine().opacity(styleObject, AnimationPressed)); - - // colors -- const qreal opacity(_animations->widgetStateEngine().opacity(widget, AnimationHover)); -+ const qreal opacity(_animations->widgetStateEngine().opacity(styleObject, AnimationHover)); - - // render -- _helper->renderRadioButtonBackground(painter, rect, palette, radioButtonState, hasHighlightNeutral(widget, option, mouseOver), sunken, animation); -- _helper->renderRadioButton(painter, rect, palette, mouseOver, radioButtonState, hasHighlightNeutral(widget, option, mouseOver), sunken, animation, opacity); -+ _helper->renderRadioButtonBackground(painter, rect, palette, radioButtonState, hasHighlightNeutral(styleObject, option, mouseOver), sunken, animation); -+ _helper->renderRadioButton(painter, -+ rect, -+ palette, -+ mouseOver, -+ radioButtonState, -+ hasHighlightNeutral(styleObject, option, mouseOver), -+ sunken, -+ animation, -+ opacity); - - return true; - } -@@ -5450,6 +5462,8 @@ bool Style::drawCheckBoxLabelControl(const QStyleOption *option, QPainter *paint - return true; - } - -+ const QObject *styleObject = widget ? widget : option->styleObject; -+ - // copy palette and rect - const auto &palette(option->palette); - const auto &rect(option->rect); -@@ -5501,10 +5515,10 @@ bool Style::drawCheckBoxLabelControl(const QStyleOption *option, QPainter *paint - const bool hasFocus(enabled && (state & State_HasFocus)); - - // update animation state -- _animations->widgetStateEngine().updateState(widget, AnimationFocus, hasFocus); -+ _animations->widgetStateEngine().updateState(styleObject, AnimationFocus, hasFocus); - -- const bool isFocusAnimated(_animations->widgetStateEngine().isAnimated(widget, AnimationFocus)); -- const qreal opacity(_animations->widgetStateEngine().opacity(widget, AnimationFocus)); -+ const bool isFocusAnimated(_animations->widgetStateEngine().isAnimated(styleObject, AnimationFocus)); -+ const qreal opacity(_animations->widgetStateEngine().opacity(styleObject, AnimationFocus)); - // focus color - QColor focusColor; - if (isFocusAnimated) { --- -GitLab - - -From a572df8f099969919544dbc2478de6aa2082a705 Mon Sep 17 00:00:00 2001 -From: Kai Uwe Broulik -Date: Sat, 24 May 2025 09:54:44 +0200 -Subject: [PATCH 3/3] kstyle: Register Qt Quick Controls with animations - -Since it's all software-rendered and indirect, only the -CheckBox and RadioButton controls are actually wired up -since the rest of the animations is quite subtle. ---- - kstyle/animations/breezeanimations.cpp | 9 +++++++++ - kstyle/breezestyle.cpp | 4 ++++ - 2 files changed, 13 insertions(+) - -diff --git a/kstyle/animations/breezeanimations.cpp b/kstyle/animations/breezeanimations.cpp -index ceab53802..5285f5daf 100644 ---- a/kstyle/animations/breezeanimations.cpp -+++ b/kstyle/animations/breezeanimations.cpp -@@ -100,6 +100,15 @@ void Animations::registerWidget(QObject *widget) const - // install animation timers - // for optimization, one should put with most used widgets here first - -+ // KQuickStyleItem. -+ const QString elementType = widget->property("elementType").toString(); -+ if (!elementType.isEmpty()) { -+ if (elementType == QLatin1String("checkbox") || elementType == QLatin1String("radiobutton")) { -+ _widgetStateEngine->registerWidget(widget, AnimationHover | AnimationFocus | AnimationPressed); -+ } -+ return; -+ } -+ - // buttons - if (auto toolButton = qobject_cast(widget)) { - _toolButtonEngine->registerWidget(toolButton, AnimationHover | AnimationFocus); -diff --git a/kstyle/breezestyle.cpp b/kstyle/breezestyle.cpp -index 19149c382..e549803f1 100644 ---- a/kstyle/breezestyle.cpp -+++ b/kstyle/breezestyle.cpp -@@ -4739,6 +4739,7 @@ bool Style::drawPanelItemViewItemPrimitive(const QStyleOption *option, QPainter - bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const - { - const QObject *styleObject = widget ? widget : option->styleObject; -+ isQtQuickControl(option, widget); // registers it with widgetStateEngine. - - // copy rect and palette - const auto &rect(option->rect); -@@ -4780,6 +4781,7 @@ bool Style::drawIndicatorCheckBoxPrimitive(const QStyleOption *option, QPainter - bool Style::drawIndicatorRadioButtonPrimitive(const QStyleOption *option, QPainter *painter, const QWidget *widget) const - { - const QObject *styleObject = widget ? widget : option->styleObject; -+ isQtQuickControl(option, widget); // registers it with widgetStateEngine. - - // copy rect and palette - const auto &rect(option->rect); -@@ -5463,6 +5465,7 @@ bool Style::drawCheckBoxLabelControl(const QStyleOption *option, QPainter *paint - } - - const QObject *styleObject = widget ? widget : option->styleObject; -+ isQtQuickControl(option, widget); // registers it with widgetStateEngine. - - // copy palette and rect - const auto &palette(option->palette); -@@ -8460,6 +8463,7 @@ bool Style::isQtQuickControl(const QStyleOption *option, const QWidget *widget) - if (!widget && option) { - if (const auto item = qobject_cast(option->styleObject)) { - _windowManager->registerQuickItem(item); -+ _animations->registerWidget(item); - return true; - } - } --- -GitLab - diff --git a/roles/kde/patches/kwin/patches.txt b/roles/kde/patches/kwin/patches.txt deleted file mode 100644 index 7ac9343..0000000 --- a/roles/kde/patches/kwin/patches.txt +++ /dev/null @@ -1,6 +0,0 @@ -Plasma 6.5.0: -Pr 3612 https://invent.kde.org/plasma/kwin/-/merge_requests/3612 -Pr 7823 https://invent.kde.org/plasma/kwin/-/merge_requests/7823 -Pr 8005 https://invent.kde.org/plasma/kwin/-/merge_requests/8005 - Depends on Pr 7927 https://invent.kde.org/plasma/kwin/-/merge_requests/7927 -Pr 8155 https://invent.kde.org/plasma/kwin/-/merge_requests/8155 diff --git a/roles/kde/patches/kwin/pr3612.patch b/roles/kde/patches/kwin/pr3612.patch deleted file mode 100644 index 8a42f11..0000000 --- a/roles/kde/patches/kwin/pr3612.patch +++ /dev/null @@ -1,2101 +0,0 @@ -From 677241efbba5f2a725b247baf86a822127571225 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Thu, 16 Feb 2023 10:16:17 +0200 -Subject: [PATCH 1/2] wayland: Implement xx-pip-v1 - -The xx-pip-v1 protocol provides clients a way to create floating windows -with miniature contents, for example a video (a movie or a video call), -a map with directions, a timer countdown, etc. - -These windows are placed in the overlay layer above all windows, including -fullscreen windows. - -This is an experimental version of the protocol. ---- - CMakeLists.txt | 4 + - src/CMakeLists.txt | 2 + - src/placement.cpp | 18 ++ - src/placement.h | 1 + - src/wayland/CMakeLists.txt | 2 + - src/wayland/protocols/xx-pip-v1.xml | 305 +++++++++++++++++++++++++++ - src/wayland/xdgshell.cpp | 2 +- - src/wayland/xdgshell_p.h | 2 + - src/wayland/xxpip_v1.cpp | 312 ++++++++++++++++++++++++++++ - src/wayland/xxpip_v1.h | 159 ++++++++++++++ - src/wayland_server.cpp | 7 + - src/window.cpp | 3 + - src/window.h | 6 + - src/xxpipv1integration.cpp | 43 ++++ - src/xxpipv1integration.h | 28 +++ - src/xxpipv1window.cpp | 179 ++++++++++++++++ - src/xxpipv1window.h | 48 +++++ - tests/CMakeLists.txt | 4 + - tests/pip/CMakeLists.txt | 22 ++ - tests/pip/main.cpp | 19 ++ - tests/pip/pip.cpp | 227 ++++++++++++++++++++ - tests/pip/pip.h | 102 +++++++++ - tests/pip/pipshellsurface.cpp | 156 ++++++++++++++ - tests/pip/pipshellsurface.h | 70 +++++++ - tests/pip/window.cpp | 19 ++ - tests/pip/window.h | 22 ++ - 26 files changed, 1761 insertions(+), 1 deletion(-) - create mode 100644 src/wayland/protocols/xx-pip-v1.xml - create mode 100644 src/wayland/xxpip_v1.cpp - create mode 100644 src/wayland/xxpip_v1.h - create mode 100644 src/xxpipv1integration.cpp - create mode 100644 src/xxpipv1integration.h - create mode 100644 src/xxpipv1window.cpp - create mode 100644 src/xxpipv1window.h - create mode 100644 tests/pip/CMakeLists.txt - create mode 100644 tests/pip/main.cpp - create mode 100644 tests/pip/pip.cpp - create mode 100644 tests/pip/pip.h - create mode 100644 tests/pip/pipshellsurface.cpp - create mode 100644 tests/pip/pipshellsurface.h - create mode 100644 tests/pip/window.cpp - create mode 100644 tests/pip/window.h - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 8d4d03b8459..6ac395557c8 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -84,6 +84,10 @@ endif() - - if (BUILD_TESTING) - find_package(KPipeWire) -+ -+ if (Qt6WaylandClient_VERSION VERSION_GREATER_EQUAL "6.10.0") -+ find_package(Qt6WaylandClientPrivate ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE) -+ endif() - endif() - - # required frameworks by Core -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index 48fb847ca7c..978c98f7ff3 100644 ---- a/src/CMakeLists.txt -+++ b/src/CMakeLists.txt -@@ -211,6 +211,8 @@ target_sources(kwin PRIVATE - xdgshellintegration.cpp - xdgshellwindow.cpp - xkb.cpp -+ xxpipv1integration.cpp -+ xxpipv1window.cpp - ) - - target_link_libraries(kwin -diff --git a/src/placement.cpp b/src/placement.cpp -index 6c984282e5e..8890da56159 100644 ---- a/src/placement.cpp -+++ b/src/placement.cpp -@@ -48,6 +48,8 @@ std::optional Placement::place(const Window *c, const QRectF & - return placeOnScreenDisplay(c, area.toRect()); - } else if (c->isTransient() && c->surface()) { - return placeDialog(c, area.toRect(), options->placement()); -+ } else if (c->isPictureInPicture()) { -+ return placePictureInPicture(c, area.toRect()); - } else { - return place(c, area, options->placement()); - } -@@ -403,6 +405,22 @@ std::optional Placement::placeDialog(const Window *c, const QR - return placeOnMainWindow(c, area, nextPlacement); - } - -+std::optional Placement::placePictureInPicture(const Window *c, const QRect &area) -+{ -+ Q_ASSERT(area.isValid()); -+ -+ const QSizeF size = c->size(); -+ if (size.isEmpty()) { -+ return std::nullopt; -+ } -+ -+ const qreal x = area.x() + area.width() - size.width(); -+ const qreal y = area.y() + area.height() - size.height(); -+ -+ return QPointF(x, y); -+} -+ -+ - std::optional Placement::placeUnderMouse(const Window *c, const QRect &area, PlacementPolicy /*next*/) - { - const QSizeF size = c->size(); -diff --git a/src/placement.h b/src/placement.h -index 63be9df117f..e0da0f51ace 100644 ---- a/src/placement.h -+++ b/src/placement.h -@@ -44,6 +44,7 @@ private: - std::optional placeDialog(const Window *c, const QRect &area, PlacementPolicy next = PlacementUnknown); - std::optional placeUtility(const Window *c, const QRect &area, PlacementPolicy next = PlacementUnknown); - std::optional placeOnScreenDisplay(const Window *c, const QRect &area); -+ std::optional placePictureInPicture(const Window *c, const QRect &area); - }; - - } // namespace -diff --git a/src/wayland/CMakeLists.txt b/src/wayland/CMakeLists.txt -index fde7fc50348..7261395ecf9 100644 ---- a/src/wayland/CMakeLists.txt -+++ b/src/wayland/CMakeLists.txt -@@ -38,6 +38,7 @@ ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml - ${PROJECT_SOURCE_DIR}/src/wayland/protocols/drm.xml - ${PROJECT_SOURCE_DIR}/src/wayland/protocols/frog-color-management-v1.xml - ${PROJECT_SOURCE_DIR}/src/wayland/protocols/wlr-layer-shell-unstable-v1.xml -+ ${PROJECT_SOURCE_DIR}/src/wayland/protocols/xx-pip-v1.xml - ${PROJECT_SOURCE_DIR}/src/wayland/protocols/xx-session-management-v1.xml - - ${WaylandProtocols_DATADIR}/stable/presentation-time/presentation-time.xml -@@ -174,6 +175,7 @@ target_sources(kwin PRIVATE - xdgtopleveltag_v1.cpp - xwaylandkeyboardgrab_v1.cpp - xwaylandshell_v1.cpp -+ xxpip_v1.cpp - ) - - install(FILES -diff --git a/src/wayland/protocols/xx-pip-v1.xml b/src/wayland/protocols/xx-pip-v1.xml -new file mode 100644 -index 00000000000..c5eb7636ee9 ---- /dev/null -+++ b/src/wayland/protocols/xx-pip-v1.xml -@@ -0,0 +1,305 @@ -+ -+ -+ -+ Copyright © 2025 Vlad Zahorodnii -+ -+ Permission is hereby granted, free of charge, to any person obtaining a -+ copy of this software and associated documentation files (the "Software"), -+ to deal in the Software without restriction, including without limitation -+ the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ and/or sell copies of the Software, and to permit persons to whom the -+ Software is furnished to do so, subject to the following conditions: -+ -+ The above copyright notice and this permission notice (including the next -+ paragraph) shall be included in all copies or substantial portions of the -+ Software. -+ -+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ DEALINGS IN THE SOFTWARE. -+ -+ -+ -+ -+ The xx_pip_shell_v1 interface provides a way to create picture-in-picture -+ windows. -+ -+ Use cases are for example playing a video in a separate floating window. -+ -+ Warning! The protocol described in this file is currently in the testing -+ phase. Backward compatible changes may be added together with the -+ corresponding interface version bump. Backward incompatible changes can -+ only be done by creating a new major version of the extension. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Destroy this xx_pip_shell_v1 object. Objects that have been created -+ through this instance are unaffected. -+ -+ -+ -+ -+ -+ This creates an xx_pip_v1 for the given xdg_surface and gives the -+ associated wl_surface the xx_pip_v1 role. -+ -+ If the wl_surface already has a role assigned, a role protocol error -+ will be raised. -+ -+ Creating a picture-in-picture surface from a wl_surface which has a -+ buffer attached or committed is a client error, and any attempts by -+ a client to attach or manipulate a buffer prior to the first -+ xx_pip_v1.configure event must also be treated as errors. -+ -+ After creating an xx_pip_v1 object and setting it up, the client -+ must perform an initial commit without any buffer attached. -+ The compositor will reply with a xx_pip_v1.configure event. -+ The client must acknowledge it and is then allowed to attach a buffer -+ to map the surface. -+ -+ The compositor may deny showing the picture-in-picture surface, in -+ which case it will send the closed event before the first configure -+ event. -+ -+ See the documentation of xdg_surface for more details about what an -+ xdg_surface is and how it is used. -+ -+ -+ -+ -+ -+ -+ -+ -+ This interface defines an xdg_surface role which represents a floating -+ window with some miniature contents, for example a video. -+ -+ The picture-in-picture window will be placed above all other windows. -+ Compositor-specific policies may override or customize the behavior -+ and the placement of the xx_pip_v1. For example, the compositor may -+ choose to put the xx_pip_v1 in a screen corner, etc. -+ -+ Unmapping an xx_pip_v1 means that the surface cannot be shown -+ by the compositor until it is explicitly mapped again. -+ All active operations (e.g., move, resize) are canceled and all -+ attributes (e.g. title, state, stacking, ...) are discarded for -+ an xx_pip_v1 surface when it is unmapped. The xx_pip_v1 returns to -+ the state it had right after xx_pip_shell_v1.get_pip. The client -+ can re-map the pip by perfoming a commit without any buffer -+ attached, waiting for a configure event and handling it as usual (see -+ xdg_surface description). -+ -+ Attaching a null buffer to a picture-in-picture unmaps the surface. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ This request destroys the role surface and unmaps the surface. -+ -+ -+ -+ -+ -+ Set an application identifier for the surface. -+ -+ The app ID identifies the general class of applications to which -+ the surface belongs. The compositor can use this to group multiple -+ surfaces together, or to determine how to launch a new application. -+ -+ For D-Bus activatable applications, the app ID is used as the D-Bus -+ service name. -+ -+ The compositor shell will try to group application surfaces together -+ by their app ID. As a best practice, it is suggested to select app -+ ID's that match the basename of the application's .desktop file. -+ For example, "org.freedesktop.FooViewer" where the .desktop file is -+ "org.freedesktop.FooViewer.desktop". -+ -+ Like other properties, a set_app_id request can be sent after the -+ xx_pip_v1 has been mapped to update the property. -+ -+ See the desktop-entry specification [0] for more details on -+ application identifiers and how they relate to well-known D-Bus -+ names and .desktop files. -+ -+ [0] http://standards.freedesktop.org/desktop-entry-spec/ -+ -+ -+ -+ -+ -+ -+ Set the origin surface for the picture-in-picture surface. -+ -+ The origin surface is an optional property that specifies a surface -+ from which the picture-in-picture surface has been launched. If set, -+ the compositor may use this hint to play an animation when the -+ picture-in-picture surface is mapped or unmapped. For example, smoothly -+ move the surface from the origin to a screen corner. -+ -+ If the specified origin surface is the same as the picture-in-picture -+ surface, the invalid_origin protocol error will be posted. -+ -+ The origin surface is double-buffered state, see wl_surface.commit. -+ -+ -+ -+ -+ -+ -+ Set the origin rect within the origin surface for the picture-in-picture -+ surface. -+ -+ The origin rect is an optional property that specifies the launch -+ rectangle within the origin surface. The compositor may use this hint -+ to play an animation when the picture-in-picture surface is mapped or -+ unmapped. For example, smoothly move the surface from the origin rect -+ to a screen corner. -+ -+ The origin rect is specified in the surface-local coordinate space. -+ -+ The compositor ignores the parts of the origin rect that fall outside -+ of the origin surface. -+ -+ The origin rect is double-buffered state, see wl_surface.commit. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Start an interactive, user-driven move of the surface. -+ -+ This request must be used in response to some sort of user action -+ like a button press, key press, or touch down event. The passed -+ serial is used to determine the type of interactive move (touch, -+ pointer, etc). -+ -+ The server may ignore move requests depending on the state of -+ the surface, or if the passed serial is no longer valid. -+ -+ If triggered, the surface will lose the focus of the device -+ (wl_pointer, wl_touch, etc) used for the move. It is up to the -+ compositor to visually indicate that the move is taking place, such as -+ updating a pointer cursor, during the move. There is no guarantee -+ that the device focus will return when the move is completed. -+ -+ -+ -+ -+ -+ -+ -+ These values are used to indicate which edge of a surface -+ is being dragged in a resize operation. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Start a user-driven, interactive resize of the surface. -+ -+ This request must be used in response to some sort of user action -+ like a button press, key press, or touch down event. The passed -+ serial is used to determine the type of interactive resize (touch, -+ pointer, etc). -+ -+ The server may ignore resize requests depending on the state of -+ the surface, or if the passed serial is no longer valid. -+ -+ If triggered, the surface also will lose the focus of the device -+ (wl_pointer, wl_touch, etc) used for the resize. It is up to the -+ compositor to visually indicate that the resize is taking place, -+ such as updating a pointer cursor, during the resize. There is no -+ guarantee that the device focus will return when the resize is -+ completed. -+ -+ The edges parameter specifies how the surface should be resized, -+ and is one of the values of the resize_edge enum. The compositor -+ may use this information to update the surface position for -+ example when dragging the top left corner. The compositor may also -+ use this information to adapt its behavior, e.g. choose an -+ appropriate cursor image. -+ -+ -+ -+ -+ -+ -+ -+ -+ The closed event is sent by the compositor when the surface will -+ no longer be shown. Further changes to the surface will be ignored. -+ The client should destroy the resource after receiving this event. -+ -+ -+ -+ -+ -+ The configure_bounds event may be sent prior to a xx_pip_v1.configure -+ event to communicate the bounds a surface size must be constrained to. -+ -+ The passed width and height are in surface coordinate space. -+ -+ If the surface width or the surface height is greater than the specified -+ surface size bounds, an invalid_size protocol error will be posted. -+ -+ The surface bounds subject to compositor policies. -+ -+ The bounds may change at any point, and in such a case, a new -+ xx_pip_v1.configure_bounds will be sent, followed by xx_pip_v1.configure and -+ xdg_surface.configure. -+ -+ -+ -+ -+ -+ -+ -+ This configure event asks the client to resize its pip surface. -+ The configured state should not be applied immediately. See -+ xdg_surface.configure for details. -+ -+ The width and height arguments specify a hint to the window -+ about how its surface should be resized in window geometry -+ coordinates. See set_window_geometry. -+ -+ If the width or height arguments are zero, it means the client -+ should decide its own window dimension. -+ -+ Clients must send an ack_configure in response to this event. See -+ xdg_surface.configure and xdg_surface.ack_configure for details. -+ -+ -+ -+ -+ -+ -diff --git a/src/wayland/xdgshell.cpp b/src/wayland/xdgshell.cpp -index 282678c0938..f1217e9d37a 100644 ---- a/src/wayland/xdgshell.cpp -+++ b/src/wayland/xdgshell.cpp -@@ -186,7 +186,7 @@ void XdgSurfaceInterfacePrivate::xdg_surface_destroy_resource(Resource *resource - - void XdgSurfaceInterfacePrivate::xdg_surface_destroy(Resource *resource) - { -- if (toplevel || popup) { -+ if (!toplevel.isNull() || !popup.isNull() || !pip.isNull()) { - qWarning() << "Tried to destroy xdg_surface before its role object"; - } - wl_resource_destroy(resource->handle); -diff --git a/src/wayland/xdgshell_p.h b/src/wayland/xdgshell_p.h -index 46244b23523..e48dfd8d78d 100644 ---- a/src/wayland/xdgshell_p.h -+++ b/src/wayland/xdgshell_p.h -@@ -16,6 +16,7 @@ - namespace KWin - { - class XdgToplevelDecorationV1Interface; -+class XXPipV1Interface; - - class XdgShellInterfacePrivate : public QtWaylandServer::xdg_wm_base - { -@@ -118,6 +119,7 @@ public: - XdgShellInterface *shell = nullptr; - QPointer toplevel; - QPointer popup; -+ QPointer pip; - QPointer surface; - QRect windowGeometry; - bool firstBufferAttached = false; -diff --git a/src/wayland/xxpip_v1.cpp b/src/wayland/xxpip_v1.cpp -new file mode 100644 -index 00000000000..e0b1f36134f ---- /dev/null -+++ b/src/wayland/xxpip_v1.cpp -@@ -0,0 +1,312 @@ -+/* -+ SPDX-FileCopyrightText: 2023 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL -+*/ -+ -+#include "wayland/xxpip_v1.h" -+#include "utils/resource.h" -+#include "wayland/display.h" -+#include "wayland/seat.h" -+#include "wayland/surface.h" -+#include "wayland/xdgshell_p.h" -+ -+#include "qwayland-server-xx-pip-v1.h" -+ -+namespace KWin -+{ -+ -+static const int s_version = 1; -+ -+class XXPipShellV1InterfacePrivate : public QtWaylandServer::xx_pip_shell_v1 -+{ -+public: -+ explicit XXPipShellV1InterfacePrivate(XXPipShellV1Interface *q, Display *display); -+ -+ XXPipShellV1Interface *q; -+ Display *display; -+ -+protected: -+ void xx_pip_shell_v1_destroy(Resource *resource) override; -+ void xx_pip_shell_v1_get_pip(Resource *resource, uint32_t id, struct ::wl_resource *xdg_surface) override; -+}; -+ -+XXPipShellV1InterfacePrivate::XXPipShellV1InterfacePrivate(XXPipShellV1Interface *q, Display *display) -+ : QtWaylandServer::xx_pip_shell_v1(*display, s_version) -+ , q(q) -+ , display(display) -+{ -+} -+ -+void XXPipShellV1InterfacePrivate::xx_pip_shell_v1_destroy(Resource *resource) -+{ -+ wl_resource_destroy(resource->handle); -+} -+ -+void XXPipShellV1InterfacePrivate::xx_pip_shell_v1_get_pip(Resource *resource, uint32_t id, struct ::wl_resource *xdg_surface) -+{ -+ XdgSurfaceInterface *xdgSurface = XdgSurfaceInterface::get(xdg_surface); -+ -+ if (const SurfaceRole *role = xdgSurface->surface()->role()) { -+ if (role != XXPipV1Interface::role()) { -+ wl_resource_post_error(resource->handle, error_already_constructed, "the surface already has a role assigned %s", role->name().constData()); -+ return; -+ } -+ } else { -+ xdgSurface->surface()->setRole(XXPipV1Interface::role()); -+ } -+ -+ wl_resource *pipResource = wl_resource_create(resource->client(), &xx_pip_v1_interface, resource->version(), id); -+ auto pip = new XXPipV1Interface(q, xdgSurface, pipResource); -+ -+ Q_EMIT q->pipCreated(pip); -+} -+ -+XXPipShellV1Interface::XXPipShellV1Interface(Display *display, QObject *parent) -+ : QObject(parent) -+ , d(std::make_unique(this, display)) -+{ -+} -+ -+XXPipShellV1Interface::~XXPipShellV1Interface() -+{ -+} -+ -+Display *XXPipShellV1Interface::display() const -+{ -+ return d->display; -+} -+ -+class XXPipV1Commit : public SurfaceAttachedState, public XdgSurfaceCommit -+{ -+public: -+ QPointer origin; -+ QRect originRect; -+}; -+ -+class XXPipV1InterfacePrivate : public SurfaceExtension, public QtWaylandServer::xx_pip_v1 -+{ -+public: -+ XXPipV1InterfacePrivate(XXPipV1Interface *q, XXPipShellV1Interface *shell, XdgSurfaceInterface *xdgSurface); -+ -+ void apply(XXPipV1Commit *comit); -+ void reset(); -+ -+ XXPipV1Interface *q; -+ XXPipShellV1Interface *shell; -+ XdgSurfaceInterface *xdgSurface; -+ QString applicationId; -+ QPointer origin; -+ QRect originRect; -+ -+protected: -+ void xx_pip_v1_destroy_resource(Resource *resource) override; -+ void xx_pip_v1_destroy(Resource *resource) override; -+ void xx_pip_v1_set_app_id(Resource *resource, const QString &app_id) override; -+ void xx_pip_v1_set_origin(Resource *resource, struct ::wl_resource *origin) override; -+ void xx_pip_v1_set_origin_rect(Resource *resource, int32_t x, int32_t y, uint32_t width, uint32_t height) override; -+ void xx_pip_v1_move(Resource *resource, struct ::wl_resource *seat, uint32_t serial) override; -+ void xx_pip_v1_resize(Resource *resource, struct ::wl_resource *seat, uint32_t serial, uint32_t edges) override; -+}; -+ -+XXPipV1InterfacePrivate::XXPipV1InterfacePrivate(XXPipV1Interface *q, XXPipShellV1Interface *shell, XdgSurfaceInterface *xdgSurface) -+ : SurfaceExtension(xdgSurface->surface()) -+ , q(q) -+ , shell(shell) -+ , xdgSurface(xdgSurface) -+{ -+} -+ -+void XXPipV1InterfacePrivate::apply(XXPipV1Commit *commit) -+{ -+ auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface); -+ if (xdgSurfacePrivate->firstBufferAttached && !xdgSurfacePrivate->surface->buffer()) { -+ reset(); -+ return; -+ } -+ -+ if (!commit->origin.isNull()) { -+ origin = commit->origin; -+ } -+ if (!commit->originRect.isNull()) { -+ originRect = commit->originRect; -+ } -+ -+ xdgSurfacePrivate->apply(commit); -+ -+ if (!xdgSurfacePrivate->isConfigured) { -+ Q_EMIT q->initializeRequested(); -+ } -+} -+ -+void XXPipV1InterfacePrivate::reset() -+{ -+ auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface); -+ xdgSurfacePrivate->reset(); -+ -+ Q_EMIT q->resetOccurred(); -+} -+ -+void XXPipV1InterfacePrivate::xx_pip_v1_destroy_resource(Resource *resource) -+{ -+ Q_EMIT q->aboutToBeDestroyed(); -+ delete q; -+} -+ -+void XXPipV1InterfacePrivate::xx_pip_v1_destroy(Resource *resource) -+{ -+ wl_resource_destroy(resource->handle); -+} -+ -+void XXPipV1InterfacePrivate::xx_pip_v1_set_app_id(Resource *resource, const QString &app_id) -+{ -+ if (applicationId != app_id) { -+ applicationId = app_id; -+ Q_EMIT q->applicationIdChanged(); -+ } -+} -+ -+void XXPipV1InterfacePrivate::xx_pip_v1_set_origin(Resource *resource, struct ::wl_resource *origin_resource) -+{ -+ SurfaceInterface *origin = SurfaceInterface::get(origin_resource); -+ if (origin == xdgSurface->surface()) { -+ wl_resource_post_error(resource->handle, error_invalid_origin, "pip surface cannot be its own origin"); -+ return; -+ } -+ -+ pending->origin = origin; -+} -+ -+void XXPipV1InterfacePrivate::xx_pip_v1_set_origin_rect(Resource *resource, int32_t x, int32_t y, uint32_t width, uint32_t height) -+{ -+ pending->originRect = QRect(x, y, width, height); -+} -+ -+void XXPipV1InterfacePrivate::xx_pip_v1_move(Resource *resource, struct ::wl_resource *seat_resource, uint32_t serial) -+{ -+ auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface); -+ if (!xdgSurfacePrivate->isConfigured) { -+ wl_resource_post_error(resource->handle, QtWaylandServer::xdg_surface::error_not_constructed, "surface has not been configured yet"); -+ return; -+ } -+ -+ Q_EMIT q->moveRequested(SeatInterface::get(seat_resource), serial); -+} -+ -+void XXPipV1InterfacePrivate::xx_pip_v1_resize(Resource *resource, struct ::wl_resource *seat_resource, uint32_t serial, uint32_t edges) -+{ -+ auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface); -+ if (!xdgSurfacePrivate->isConfigured) { -+ wl_resource_post_error(resource->handle, QtWaylandServer::xdg_surface::error_not_constructed, "surface has not been configured yet"); -+ return; -+ } -+ -+ Gravity gravity; -+ switch (edges) { -+ case resize_edge_none: -+ gravity = Gravity::None; -+ break; -+ case resize_edge_top: -+ gravity = Gravity::Top; -+ break; -+ case resize_edge_bottom: -+ gravity = Gravity::Bottom; -+ break; -+ case resize_edge_left: -+ gravity = Gravity::Left; -+ break; -+ case resize_edge_top_left: -+ gravity = Gravity::TopLeft; -+ break; -+ case resize_edge_bottom_left: -+ gravity = Gravity::BottomLeft; -+ break; -+ case resize_edge_right: -+ gravity = Gravity::Right; -+ break; -+ case resize_edge_top_right: -+ gravity = Gravity::TopRight; -+ break; -+ case resize_edge_bottom_right: -+ gravity = Gravity::BottomRight; -+ break; -+ default: -+ wl_resource_post_error(resource->handle, error_invalid_resize_edge, "invalid resize edge"); -+ return; -+ } -+ -+ Q_EMIT q->resizeRequested(SeatInterface::get(seat_resource), gravity, serial); -+} -+ -+XXPipV1Interface::XXPipV1Interface(XXPipShellV1Interface *shell, XdgSurfaceInterface *xdgSurface, wl_resource *resource) -+ : d(std::make_unique(this, shell, xdgSurface)) -+{ -+ XdgSurfaceInterfacePrivate *surfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface); -+ surfacePrivate->pip = this; -+ surfacePrivate->pending = d->pending; -+ -+ d->init(resource); -+} -+ -+XXPipV1Interface::~XXPipV1Interface() -+{ -+} -+ -+SurfaceRole *XXPipV1Interface::role() -+{ -+ static SurfaceRole role(QByteArrayLiteral("xx_pip_v1")); -+ return &role; -+} -+ -+bool XXPipV1Interface::isConfigured() const -+{ -+ return d->xdgSurface->isConfigured(); -+} -+ -+XdgSurfaceInterface *XXPipV1Interface::xdgSurface() const -+{ -+ return d->xdgSurface; -+} -+ -+SurfaceInterface *XXPipV1Interface::surface() const -+{ -+ return d->xdgSurface->surface(); -+} -+ -+QString XXPipV1Interface::applicationId() const -+{ -+ return d->applicationId; -+} -+ -+quint32 XXPipV1Interface::sendConfigureSize(const QSizeF &size) -+{ -+ const quint32 serial = d->shell->display()->nextSerial(); -+ -+ d->send_configure_size(size.width(), size.height()); -+ -+ auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface()); -+ xdgSurfacePrivate->send_configure(serial); -+ xdgSurfacePrivate->isConfigured = true; -+ -+ return serial; -+} -+ -+void XXPipV1Interface::sendClosed() -+{ -+ d->send_closed(); -+} -+ -+void XXPipV1Interface::sendConfigureBounds(const QSizeF &size) -+{ -+ d->send_configure_bounds(size.width(), size.height()); -+} -+ -+XXPipV1Interface *XXPipV1Interface::get(::wl_resource *resource) -+{ -+ if (auto pipPrivate = resource_cast(resource)) { -+ return pipPrivate->q; -+ } -+ return nullptr; -+} -+ -+} // namespace KWin -diff --git a/src/wayland/xxpip_v1.h b/src/wayland/xxpip_v1.h -new file mode 100644 -index 00000000000..c2737f2ec26 ---- /dev/null -+++ b/src/wayland/xxpip_v1.h -@@ -0,0 +1,159 @@ -+/* -+ SPDX-FileCopyrightText: 2023 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL -+*/ -+ -+#pragma once -+ -+#include "kwin_export.h" -+ -+#include -+ -+#include -+ -+struct wl_resource; -+ -+namespace KWin -+{ -+ -+class Display; -+class SeatInterface; -+class SurfaceInterface; -+class SurfaceRole; -+class XXPipV1Interface; -+class XXPipV1InterfacePrivate; -+class XdgSurfaceInterface; -+class XXPipShellV1InterfacePrivate; -+ -+enum class Gravity; -+ -+/** -+ * The XXPipShellV1Interface extension provides clients a way to create picture-in-picture -+ * surfaces. -+ */ -+class KWIN_EXPORT XXPipShellV1Interface : public QObject -+{ -+ Q_OBJECT -+ -+public: -+ explicit XXPipShellV1Interface(Display *display, QObject *parent = nullptr); -+ ~XXPipShellV1Interface() override; -+ -+ Display *display() const; -+ -+Q_SIGNALS: -+ void pipCreated(XXPipV1Interface *pip); -+ -+private: -+ std::unique_ptr d; -+}; -+ -+/** -+ * The XXPipV1Interface class represents a picture-in-picture surface. -+ * -+ * XXPipV1Interface corresponds to the Wayland interface \c xx_pip_v1. -+ */ -+class KWIN_EXPORT XXPipV1Interface : public QObject -+{ -+ Q_OBJECT -+ -+public: -+ XXPipV1Interface(XXPipShellV1Interface *shell, XdgSurfaceInterface *xdgSurface, wl_resource *resource); -+ ~XXPipV1Interface() override; -+ -+ static SurfaceRole *role(); -+ -+ /** -+ * Returns \c true if the popup has been configured; otherwise returns \c false. -+ */ -+ bool isConfigured() const; -+ -+ /** -+ * Returns the XdgSurfaceInterface associated with the XXPipV1Interface. -+ */ -+ XdgSurfaceInterface *xdgSurface() const; -+ -+ /** -+ * Returns the SurfaceInterface associated with the XXPipV1Interface. -+ */ -+ SurfaceInterface *surface() const; -+ -+ /** -+ * Returns the desktop file name of the pip surface. -+ */ -+ QString applicationId() const; -+ -+ /** -+ * Returns the surface from which the picture-in-picture surface has been launched, or \c null. -+ */ -+ SurfaceInterface *origin() const; -+ -+ /** -+ * Specifies the bounds within the origin surface from which the picture-in-picture surface has -+ * been launched. -+ */ -+ QRect originRect() const; -+ -+ /** -+ * Sends a configure event to the client. \a size specifies the new window geometry size. A size -+ * of zero means the client should decide its own window dimensions. -+ */ -+ quint32 sendConfigureSize(const QSizeF &size); -+ -+ /** -+ * Sends a close event to the client. The client may choose to ignore this request. -+ */ -+ void sendClosed(); -+ -+ /** -+ * Sends an event to the client specifying the maximum bounds for the surface size. Must be -+ * called before sendConfigure(). -+ */ -+ void sendConfigureBounds(const QSizeF &size); -+ -+ /** -+ * Returns the XXPipV1Interface for the specified wayland resource object \a resource. -+ */ -+ static XXPipV1Interface *get(::wl_resource *resource); -+ -+Q_SIGNALS: -+ /** -+ * This signal is emitted when the xx-pip-v1 is about to be destroyed. -+ */ -+ void aboutToBeDestroyed(); -+ -+ /** -+ * This signal is emitted when the xx-pip-v1 has commited the initial state and wants to -+ * be configured. After initializing the pip surface, you must send a configure event. -+ */ -+ void initializeRequested(); -+ -+ /** -+ * This signal is emitted when the pip surface has been unmapped and its state has been reset. -+ */ -+ void resetOccurred(); -+ -+ /** -+ * This signal is emitted when the pip wants to be interactively moved. The \a seat and -+ * the \a serial indicate the user action in response to which this request has been issued. -+ */ -+ void moveRequested(SeatInterface *seat, quint32 serial); -+ -+ /** -+ * This signal is emitted when the pip wants to be interactively resized with -+ * the specified \a gravity. The \a seat and the \a serial indicate the user action -+ * in response to which this request has been issued. -+ */ -+ void resizeRequested(SeatInterface *seat, Gravity anchor, quint32 serial); -+ -+ /** -+ * This signal is emitted when the application id changes. -+ */ -+ void applicationIdChanged(); -+ -+private: -+ std::unique_ptr d; -+}; -+ -+} // namespace KWin -diff --git a/src/wayland_server.cpp b/src/wayland_server.cpp -index 24f7fa71ebe..0d54680313a 100644 ---- a/src/wayland_server.cpp -+++ b/src/wayland_server.cpp -@@ -91,6 +91,7 @@ - #include "xdgactivationv1.h" - #include "xdgshellintegration.h" - #include "xdgshellwindow.h" -+#include "xxpipv1integration.h" - #if KWIN_BUILD_X11 - #include "wayland/xwaylandkeyboardgrab_v1.h" - #include "wayland/xwaylandshell_v1.h" -@@ -581,6 +582,12 @@ void WaylandServer::initWorkspace() - connect(layerShellV1Integration, &LayerShellV1Integration::windowCreated, - this, &WaylandServer::registerWindow); - -+ if (qEnvironmentVariableIntValue("KWIN_WAYLAND_SUPPORT_XX_PIP_V1") == 1) { -+ auto pipV1Integration = new XXPipV1Integration(this); -+ connect(pipV1Integration, &XXPipV1Integration::windowCreated, -+ this, &WaylandServer::registerWindow); -+ } -+ - new KeyStateInterface(m_display, m_display); - - VirtualDesktopManager::self()->setVirtualDesktopManagement(m_virtualDesktopManagement); -diff --git a/src/window.cpp b/src/window.cpp -index 591950ab74a..f5a4be143b8 100644 ---- a/src/window.cpp -+++ b/src/window.cpp -@@ -563,6 +563,9 @@ Layer Window::belongsToLayer() const - if (isUnmanaged() || isInternal()) { - return OverlayLayer; - } -+ if (isPictureInPicture()) { -+ return OverlayLayer; -+ } - if (isLockScreen() && !waylandServer()) { - return OverlayLayer; - } -diff --git a/src/window.h b/src/window.h -index 57be2c6891e..9ae5758de85 100644 ---- a/src/window.h -+++ b/src/window.h -@@ -781,6 +781,7 @@ public: - virtual bool isClient() const; - bool isDeleted() const; - virtual bool isUnmanaged() const; -+ virtual bool isPictureInPicture() const; - - bool isLockScreenOverlay() const; - void setLockScreenOverlay(bool allowed); -@@ -2086,6 +2087,11 @@ inline bool Window::isInternal() const - return false; - } - -+inline bool Window::isPictureInPicture() const -+{ -+ return false; -+} -+ - inline WindowItem *Window::windowItem() const - { - return m_windowItem.get(); -diff --git a/src/xxpipv1integration.cpp b/src/xxpipv1integration.cpp -new file mode 100644 -index 00000000000..b72f2cba140 ---- /dev/null -+++ b/src/xxpipv1integration.cpp -@@ -0,0 +1,43 @@ -+/* -+ SPDX-FileCopyrightText: 2023 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: GPL-2.0-or-later -+*/ -+ -+#include "xxpipv1integration.h" -+#include "wayland/xxpip_v1.h" -+#include "wayland_server.h" -+#include "workspace.h" -+#include "xxpipv1window.h" -+ -+namespace KWin -+{ -+ -+XXPipV1Integration::XXPipV1Integration(QObject *parent) -+ : WaylandShellIntegration(parent) -+{ -+ XXPipShellV1Interface *shell = new XXPipShellV1Interface(waylandServer()->display(), this); -+ connect(shell, &XXPipShellV1Interface::pipCreated, -+ this, &XXPipV1Integration::registerPipV1Surface); -+} -+ -+void XXPipV1Integration::registerPipV1Surface(XXPipV1Interface *pip) -+{ -+ createPipV1Window(pip); -+ connect(pip, &XXPipV1Interface::resetOccurred, this, [this, pip] { -+ createPipV1Window(pip); -+ }); -+} -+ -+void XXPipV1Integration::createPipV1Window(XXPipV1Interface *pip) -+{ -+ if (!workspace()) { -+ qCWarning(KWIN_CORE, "An xx-pip-v1 surface has been created while the compositor " -+ "is still not fully initialized. That is a compositor bug!"); -+ return; -+ } -+ -+ Q_EMIT windowCreated(new XXPipV1Window(pip)); -+} -+ -+} // namespace KWin -diff --git a/src/xxpipv1integration.h b/src/xxpipv1integration.h -new file mode 100644 -index 00000000000..8d2be310fe5 ---- /dev/null -+++ b/src/xxpipv1integration.h -@@ -0,0 +1,28 @@ -+/* -+ SPDX-FileCopyrightText: 2023 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: GPL-2.0-or-later -+*/ -+ -+#pragma once -+ -+#include "waylandshellintegration.h" -+ -+namespace KWin -+{ -+ -+class XXPipV1Interface; -+ -+class XXPipV1Integration : public WaylandShellIntegration -+{ -+ Q_OBJECT -+ -+public: -+ explicit XXPipV1Integration(QObject *parent = nullptr); -+ -+private: -+ void registerPipV1Surface(XXPipV1Interface *pip); -+ void createPipV1Window(XXPipV1Interface *pip); -+}; -+ -+} // namespace KWin -diff --git a/src/xxpipv1window.cpp b/src/xxpipv1window.cpp -new file mode 100644 -index 00000000000..0d6b6bafc8b ---- /dev/null -+++ b/src/xxpipv1window.cpp -@@ -0,0 +1,179 @@ -+/* -+ SPDX-FileCopyrightText: 2023 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: GPL-2.0-or-later -+*/ -+ -+#include "xxpipv1window.h" -+#include "input.h" -+#include "wayland/seat.h" -+#include "wayland/surface.h" -+#include "wayland/tablet_v2.h" -+#include "wayland_server.h" -+#include "workspace.h" -+ -+namespace KWin -+{ -+ -+XXPipV1Window::XXPipV1Window(XXPipV1Interface *shellSurface) -+ : XdgSurfaceWindow(shellSurface->xdgSurface()) -+ , m_shellSurface(shellSurface) -+{ -+ setOutput(workspace()->activeOutput()); -+ setMoveResizeOutput(workspace()->activeOutput()); -+ setOnAllDesktops(true); -+ setOnAllActivities(true); -+ -+ connect(shellSurface, &XXPipV1Interface::initializeRequested, -+ this, &XXPipV1Window::initialize); -+ connect(shellSurface, &XXPipV1Interface::aboutToBeDestroyed, -+ this, &XXPipV1Window::destroyWindow); -+ connect(shellSurface, &XXPipV1Interface::moveRequested, -+ this, &XXPipV1Window::handleMoveRequested); -+ connect(shellSurface, &XXPipV1Interface::resizeRequested, -+ this, &XXPipV1Window::handleResizeRequested); -+ connect(shellSurface, &XXPipV1Interface::applicationIdChanged, -+ this, &XXPipV1Window::handleApplicationIdChanged); -+} -+ -+void XXPipV1Window::initialize() -+{ -+ scheduleConfigure(); -+} -+ -+bool XXPipV1Window::isPictureInPicture() const -+{ -+ return true; -+} -+ -+bool XXPipV1Window::isResizable() const -+{ -+ return true; -+} -+ -+bool XXPipV1Window::isMovable() const -+{ -+ return true; -+} -+ -+bool XXPipV1Window::isMovableAcrossScreens() const -+{ -+ return true; -+} -+ -+bool XXPipV1Window::isCloseable() const -+{ -+ return true; -+} -+ -+void XXPipV1Window::closeWindow() -+{ -+ m_shellSurface->sendClosed(); -+} -+ -+bool XXPipV1Window::wantsInput() const -+{ -+ return false; -+} -+ -+bool XXPipV1Window::takeFocus() -+{ -+ return false; -+} -+ -+bool XXPipV1Window::acceptsFocus() const -+{ -+ return false; -+} -+ -+XdgSurfaceConfigure *XXPipV1Window::sendRoleConfigure() const -+{ -+ surface()->setPreferredBufferScale(nextTargetScale()); -+ surface()->setPreferredBufferTransform(preferredBufferTransform()); -+ surface()->setPreferredColorDescription(preferredColorDescription()); -+ -+ const QRectF geometry = moveResizeGeometry(); -+ if (geometry.isEmpty()) { -+ const QRectF workArea = workspace()->clientArea(PlacementArea, this, moveResizeOutput()); -+ m_shellSurface->sendConfigureBounds(workArea.size() * 0.25); -+ } -+ -+ XdgSurfaceConfigure *configureEvent = new XdgSurfaceConfigure(); -+ configureEvent->bounds = moveResizeGeometry(); -+ configureEvent->serial = m_shellSurface->sendConfigureSize(geometry.size()); -+ -+ return configureEvent; -+} -+ -+void XXPipV1Window::handleRoleDestroyed() -+{ -+ m_shellSurface->disconnect(this); -+ -+ XdgSurfaceWindow::handleRoleDestroyed(); -+} -+ -+void XXPipV1Window::handleApplicationIdChanged() -+{ -+ setResourceClass(resourceName(), m_shellSurface->applicationId()); -+ setDesktopFileName(m_shellSurface->applicationId()); -+} -+ -+void XXPipV1Window::handleMoveRequested(SeatInterface *seat, quint32 serial) -+{ -+ if (const auto anchor = input()->implicitGrabPositionBySerial(seat, serial)) { -+ performMousePressCommand(Options::MouseMove, *anchor); -+ } -+} -+ -+void XXPipV1Window::handleResizeRequested(SeatInterface *seat, Gravity gravity, quint32 serial) -+{ -+ const auto anchor = input()->implicitGrabPositionBySerial(seat, serial); -+ if (!anchor) { -+ return; -+ } -+ if (isInteractiveMoveResize()) { -+ finishInteractiveMoveResize(false); -+ } -+ setInteractiveMoveResizePointerButtonDown(true); -+ setInteractiveMoveResizeAnchor(*anchor); -+ setInteractiveMoveResizeModifiers(Qt::KeyboardModifiers()); -+ setInteractiveMoveOffset(QPointF((anchor->x() - x()) / width(), (anchor->y() - y()) / height())); -+ setUnrestrictedInteractiveMoveResize(false); -+ setInteractiveMoveResizeGravity(gravity); -+ if (!startInteractiveMoveResize()) { -+ setInteractiveMoveResizePointerButtonDown(false); -+ } -+ updateCursor(); -+} -+ -+void XXPipV1Window::doSetNextTargetScale() -+{ -+ if (isDeleted()) { -+ return; -+ } -+ if (m_shellSurface->isConfigured()) { -+ scheduleConfigure(); -+ } -+} -+ -+void XXPipV1Window::doSetPreferredBufferTransform() -+{ -+ if (isDeleted()) { -+ return; -+ } -+ if (m_shellSurface->isConfigured()) { -+ scheduleConfigure(); -+ } -+} -+ -+void XXPipV1Window::doSetPreferredColorDescription() -+{ -+ if (isDeleted()) { -+ return; -+ } -+ if (m_shellSurface->isConfigured()) { -+ scheduleConfigure(); -+ } -+} -+ -+} // namespace KWin -diff --git a/src/xxpipv1window.h b/src/xxpipv1window.h -new file mode 100644 -index 00000000000..15873e3b25f ---- /dev/null -+++ b/src/xxpipv1window.h -@@ -0,0 +1,48 @@ -+/* -+ SPDX-FileCopyrightText: 2023 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: GPL-2.0-or-later -+*/ -+ -+#pragma once -+ -+#include "wayland/xxpip_v1.h" -+#include "xdgshellwindow.h" -+ -+namespace KWin -+{ -+ -+class XXPipV1Window final : public XdgSurfaceWindow -+{ -+ Q_OBJECT -+ -+public: -+ explicit XXPipV1Window(XXPipV1Interface *shellSurface); -+ -+ bool isPictureInPicture() const override; -+ bool isResizable() const override; -+ bool isMovable() const override; -+ bool isMovableAcrossScreens() const override; -+ bool isCloseable() const override; -+ void closeWindow() override; -+ bool wantsInput() const override; -+ bool takeFocus() override; -+ -+protected: -+ bool acceptsFocus() const override; -+ XdgSurfaceConfigure *sendRoleConfigure() const override; -+ void handleRoleDestroyed() override; -+ void doSetNextTargetScale() override; -+ void doSetPreferredBufferTransform() override; -+ void doSetPreferredColorDescription() override; -+ -+private: -+ void initialize(); -+ void handleApplicationIdChanged(); -+ void handleMoveRequested(SeatInterface *seat, quint32 serial); -+ void handleResizeRequested(SeatInterface *seat, Gravity gravity, quint32 serial); -+ -+ XXPipV1Interface *m_shellSurface; -+}; -+ -+} // namespace KWin -diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt -index 134f5416975..824cd67083c 100644 ---- a/tests/CMakeLists.txt -+++ b/tests/CMakeLists.txt -@@ -1,3 +1,7 @@ -+if (Qt6_VERSION VERSION_GREATER_EQUAL "6.9.0") -+ add_subdirectory(pip) -+endif() -+ - if(KWIN_BUILD_X11) - set(normalhintsbasesizetest_SRCS normalhintsbasesizetest.cpp) - add_executable(normalhintsbasesizetest ${normalhintsbasesizetest_SRCS}) -diff --git a/tests/pip/CMakeLists.txt b/tests/pip/CMakeLists.txt -new file mode 100644 -index 00000000000..9135a5ab072 ---- /dev/null -+++ b/tests/pip/CMakeLists.txt -@@ -0,0 +1,22 @@ -+add_executable(piptest) -+ -+target_sources(piptest PRIVATE -+ main.cpp -+ pipshellsurface.cpp -+ pip.cpp -+ window.cpp -+) -+ -+qt6_generate_wayland_protocol_client_sources(piptest -+ PRIVATE_CODE -+ FILES -+ ${PROJECT_SOURCE_DIR}/src/wayland/protocols/xx-pip-v1.xml -+ ${WaylandProtocols_DATADIR}/stable/xdg-shell/xdg-shell.xml -+ ${Wayland_DATADIR}/wayland.xml -+) -+ -+target_link_libraries(piptest PRIVATE -+ Qt::Gui -+ Qt::WaylandClientPrivate -+ Qt::Widgets -+) -diff --git a/tests/pip/main.cpp b/tests/pip/main.cpp -new file mode 100644 -index 00000000000..6d7c4f5b3b4 ---- /dev/null -+++ b/tests/pip/main.cpp -@@ -0,0 +1,19 @@ -+/* -+ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: GPL-2.0-or-later -+*/ -+ -+#include -+ -+#include "window.h" -+ -+int main(int argc, char **argv) -+{ -+ QApplication app(argc, argv); -+ -+ Window w; -+ w.show(); -+ -+ return app.exec(); -+} -diff --git a/tests/pip/pip.cpp b/tests/pip/pip.cpp -new file mode 100644 -index 00000000000..ed14f5f98d4 ---- /dev/null -+++ b/tests/pip/pip.cpp -@@ -0,0 +1,227 @@ -+/* -+ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: GPL-2.0-or-later -+*/ -+ -+#include "pip.h" -+#include "pipshellsurface.h" -+ -+#include -+#include -+ -+PipPin::PipPin(QWidget *parent) -+ : QWidget(parent) -+{ -+ resize(100, 50); -+} -+ -+bool PipPin::isPinned() const -+{ -+ return m_pinned; -+} -+ -+void PipPin::setPinned(bool pinned) -+{ -+ if (m_pinned != pinned) { -+ m_pinned = pinned; -+ update(); -+ } -+} -+ -+void PipPin::paintEvent(QPaintEvent *event) -+{ -+ QPainter painter(this); -+ painter.setClipRegion(event->region()); -+ -+ if (m_hovered) { -+ painter.setOpacity(1.0); -+ } else { -+ painter.setOpacity(0.5); -+ } -+ -+ painter.fillRect(rect(), Qt::black); -+ painter.setPen(Qt::white); -+ painter.drawText(rect(), Qt::AlignCenter, m_pinned ? QStringLiteral("Unpin") : QStringLiteral("Pin")); -+} -+ -+void PipPin::mousePressEvent(QMouseEvent *event) -+{ -+ if (event->button() == Qt::LeftButton) { -+ event->accept(); -+ Q_EMIT clicked(); -+ } -+} -+ -+void PipPin::enterEvent(QEnterEvent *event) -+{ -+ m_hovered = true; -+ update(); -+} -+ -+void PipPin::leaveEvent(QEvent *event) -+{ -+ m_hovered = false; -+ update(); -+} -+ -+Media::Media(QWidget *parent) -+ : QWidget(parent) -+{ -+ m_pip = std::make_unique(); -+ connect(m_pip.get(), &Pip::pinned, this, [this]() { -+ m_pin->setPinned(true); -+ }); -+ connect(m_pip.get(), &Pip::unpinned, this, [this]() { -+ m_pin->setPinned(false); -+ }); -+ -+ m_pin = new PipPin(this); -+ connect(m_pin, &PipPin::clicked, this, [this]() { -+ if (m_pin->isPinned()) { -+ m_pip->show(); -+ } else { -+ m_pip->hide(); -+ } -+ }); -+} -+ -+void Media::paintEvent(QPaintEvent *event) -+{ -+ QPainter painter(this); -+ painter.setClipRegion(event->region()); -+ painter.fillRect(rect(), QColor(0, 0, 0, 128)); -+} -+ -+void Media::resizeEvent(QResizeEvent *event) -+{ -+ m_pin->move(width() - m_pin->width() - 50, height() - m_pin->height() - 50); -+ m_pip->resize(width(), height()); -+} -+ -+PipResizeHandle::PipResizeHandle(Qt::Edges edges, QWidget *parent) -+ : QWidget(parent) -+ , m_edges(edges) -+{ -+ switch (edges) { -+ case Qt::LeftEdge: -+ case Qt::RightEdge: -+ setCursor(Qt::SizeHorCursor); -+ break; -+ case Qt::TopEdge: -+ case Qt::BottomEdge: -+ setCursor(Qt::SizeVerCursor); -+ break; -+ case Qt::TopEdge | Qt::LeftEdge: -+ case Qt::BottomEdge | Qt::RightEdge: -+ setCursor(Qt::SizeFDiagCursor); -+ break; -+ case Qt::TopEdge | Qt::RightEdge: -+ case Qt::BottomEdge | Qt::LeftEdge: -+ setCursor(Qt::SizeBDiagCursor); -+ break; -+ default: -+ Q_UNREACHABLE(); -+ } -+} -+ -+void PipResizeHandle::enterEvent(QEnterEvent *event) -+{ -+ m_hovered = true; -+ update(); -+} -+ -+void PipResizeHandle::leaveEvent(QEvent *event) -+{ -+ m_hovered = false; -+ update(); -+} -+ -+void PipResizeHandle::mousePressEvent(QMouseEvent *event) -+{ -+ if (event->button() == Qt::LeftButton) { -+ event->accept(); -+ window()->windowHandle()->startSystemResize(m_edges); -+ } -+} -+ -+void PipResizeHandle::paintEvent(QPaintEvent *event) -+{ -+ QPainter painter(this); -+ painter.setClipRegion(event->region()); -+ painter.fillRect(rect(), QColor(222, 137, 190, m_hovered ? 128 : 0)); -+} -+ -+Pip::Pip(QWidget *parent) -+ : QWidget(parent) -+{ -+ m_closeButton = new QPushButton(this); -+ m_closeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); -+ m_closeButton->setText(QStringLiteral("Close")); -+ connect(m_closeButton, &QPushButton::clicked, this, &Pip::hide); -+ -+ m_topLeftResizeHandle = new PipResizeHandle(Qt::TopEdge | Qt::LeftEdge, this); -+ m_topResizeHandle = new PipResizeHandle(Qt::TopEdge, this); -+ m_topRightResizeHandle = new PipResizeHandle(Qt::TopEdge | Qt::RightEdge, this); -+ m_rightResizeHandle = new PipResizeHandle(Qt::RightEdge, this); -+ m_bottomRightResizeHandle = new PipResizeHandle(Qt::BottomEdge | Qt::BottomEdge, this); -+ m_bottomResizeHandle = new PipResizeHandle(Qt::BottomEdge, this); -+ m_bottomLeftResizeHandle = new PipResizeHandle(Qt::BottomEdge | Qt::LeftEdge, this); -+ m_leftResizeHandle = new PipResizeHandle(Qt::LeftEdge, this); -+ -+ winId(); -+ PipShellIntegration::assignPipRole(windowHandle()); -+} -+ -+void Pip::layout() -+{ -+ const int gridUnit = 5; -+ const int resizeZone = 2 * gridUnit; -+ -+ m_topLeftResizeHandle->setGeometry(0, 0, resizeZone, resizeZone); -+ m_topResizeHandle->setGeometry(resizeZone, 0, width() - 2 * resizeZone, resizeZone); -+ m_topRightResizeHandle->setGeometry(width() - resizeZone, 0, resizeZone, resizeZone); -+ m_rightResizeHandle->setGeometry(width() - resizeZone, resizeZone, resizeZone, height() - 2 * resizeZone); -+ m_bottomRightResizeHandle->setGeometry(width() - resizeZone, height() - resizeZone, resizeZone, resizeZone); -+ m_bottomResizeHandle->setGeometry(resizeZone, height() - resizeZone, width() - 2 * resizeZone, resizeZone); -+ m_bottomLeftResizeHandle->setGeometry(0, height() - resizeZone, resizeZone, resizeZone); -+ m_leftResizeHandle->setGeometry(0, resizeZone, resizeZone, height() - 2 * resizeZone); -+ -+ m_closeButton->move(width() - resizeZone - gridUnit - m_closeButton->width(), resizeZone + gridUnit); -+} -+ -+void Pip::paintEvent(QPaintEvent *event) -+{ -+ QPainter painter(this); -+ painter.setClipRegion(event->region()); -+ painter.fillRect(rect(), QColor(64, 67, 78)); -+} -+ -+void Pip::resizeEvent(QResizeEvent *event) -+{ -+ layout(); -+} -+ -+void Pip::mousePressEvent(QMouseEvent *event) -+{ -+ switch (event->button()) { -+ case Qt::LeftButton: -+ event->accept(); -+ windowHandle()->startSystemMove(); -+ break; -+ default: -+ break; -+ } -+} -+ -+void Pip::showEvent(QShowEvent *event) -+{ -+ Q_EMIT unpinned(); -+} -+ -+void Pip::hideEvent(QHideEvent *event) -+{ -+ Q_EMIT pinned(); -+} -+ -+#include "moc_pip.cpp" -diff --git a/tests/pip/pip.h b/tests/pip/pip.h -new file mode 100644 -index 00000000000..2f6e4a87d86 ---- /dev/null -+++ b/tests/pip/pip.h -@@ -0,0 +1,102 @@ -+/* -+ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: GPL-2.0-or-later -+*/ -+ -+#pragma once -+ -+#include -+#include -+ -+class PipResizeHandle : public QWidget -+{ -+ Q_OBJECT -+ -+public: -+ explicit PipResizeHandle(Qt::Edges edges, QWidget *parent = nullptr); -+ -+protected: -+ void enterEvent(QEnterEvent *event) override; -+ void leaveEvent(QEvent *event) override; -+ void mousePressEvent(QMouseEvent *event) override; -+ void paintEvent(QPaintEvent *event) override; -+ -+private: -+ Qt::Edges m_edges; -+ bool m_hovered = false; -+}; -+ -+class Pip : public QWidget -+{ -+ Q_OBJECT -+ -+public: -+ explicit Pip(QWidget *parent = nullptr); -+ -+Q_SIGNALS: -+ void pinned(); -+ void unpinned(); -+ -+protected: -+ void paintEvent(QPaintEvent *event) override; -+ void resizeEvent(QResizeEvent *event) override; -+ void mousePressEvent(QMouseEvent *event) override; -+ void showEvent(QShowEvent *event) override; -+ void hideEvent(QHideEvent *event) override; -+ -+private: -+ void layout(); -+ -+ QPushButton *m_closeButton = nullptr; -+ PipResizeHandle *m_topLeftResizeHandle = nullptr; -+ PipResizeHandle *m_topResizeHandle = nullptr; -+ PipResizeHandle *m_topRightResizeHandle = nullptr; -+ PipResizeHandle *m_rightResizeHandle = nullptr; -+ PipResizeHandle *m_bottomRightResizeHandle = nullptr; -+ PipResizeHandle *m_bottomResizeHandle = nullptr; -+ PipResizeHandle *m_bottomLeftResizeHandle = nullptr; -+ PipResizeHandle *m_leftResizeHandle = nullptr; -+}; -+ -+class PipPin : public QWidget -+{ -+ Q_OBJECT -+ -+public: -+ explicit PipPin(QWidget *parent = nullptr); -+ -+ bool isPinned() const; -+ void setPinned(bool pinned); -+ -+Q_SIGNALS: -+ void clicked(); -+ -+protected: -+ void paintEvent(QPaintEvent *event) override; -+ void mousePressEvent(QMouseEvent *event) override; -+ void enterEvent(QEnterEvent *event) override; -+ void leaveEvent(QEvent *event) override; -+ -+private: -+ bool m_pinned = true; -+ bool m_hovered = false; -+}; -+ -+class Media : public QWidget -+{ -+ Q_OBJECT -+ -+public: -+ explicit Media(QWidget *parent = nullptr); -+ -+protected: -+ void paintEvent(QPaintEvent *event) override; -+ void resizeEvent(QResizeEvent *event) override; -+ -+private: -+ void layout(); -+ -+ std::unique_ptr m_pip; -+ PipPin *m_pin = nullptr; -+}; -diff --git a/tests/pip/pipshellsurface.cpp b/tests/pip/pipshellsurface.cpp -new file mode 100644 -index 00000000000..082a51a3c24 ---- /dev/null -+++ b/tests/pip/pipshellsurface.cpp -@@ -0,0 +1,156 @@ -+/* -+ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: GPL-2.0-or-later -+*/ -+ -+#include "pipshellsurface.h" -+ -+#include -+#include -+ -+XdgWmBase::XdgWmBase() -+ : QWaylandClientExtensionTemplate(6) -+{ -+ initialize(); -+ if (!isActive()) { -+ qFatal("The xdg-shell protocol is unsupported by the compositor"); -+ } -+} -+ -+XXPipShell::XXPipShell() -+ : QWaylandClientExtensionTemplate(1) -+{ -+ initialize(); -+ if (!isActive()) { -+ qFatal("The xx-pip-v1 protocol is unsupported by the compositor"); -+ } -+} -+ -+void PipShellIntegration::assignPipRole(QWindow *window) -+{ -+ window->create(); -+ -+ auto waylandWindow = dynamic_cast(window->handle()); -+ if (!waylandWindow) { -+ return; -+ } -+ -+ static PipShellIntegration *shellIntegration = nullptr; -+ if (!shellIntegration) { -+ shellIntegration = new PipShellIntegration(); -+ } -+ -+ waylandWindow->setShellIntegration(shellIntegration); -+} -+ -+PipShellIntegration::PipShellIntegration() -+ : m_xdgWmBase(std::make_unique()) -+ , m_xxPipShell(std::make_unique()) -+{ -+} -+ -+bool PipShellIntegration::initialize(QtWaylandClient::QWaylandDisplay *display) -+{ -+ return m_xdgWmBase->isInitialized() && m_xxPipShell->isInitialized(); -+} -+ -+QtWaylandClient::QWaylandShellSurface *PipShellIntegration::createShellSurface(QtWaylandClient::QWaylandWindow *window) -+{ -+ ::xdg_surface *xdgSurface = m_xdgWmBase->get_xdg_surface(window->wlSurface()); -+ ::xx_pip_v1 *xxPip = m_xxPipShell->get_pip(xdgSurface); -+ return new PipShellSurface(xdgSurface, xxPip, window); -+} -+ -+PipShellSurface::PipShellSurface(::xdg_surface *xdgSurface, ::xx_pip_v1 *xxPip, QtWaylandClient::QWaylandWindow *window) -+ : QWaylandShellSurface(window) -+ , QtWayland::xdg_surface(xdgSurface) -+ , QtWayland::xx_pip_v1(xxPip) -+{ -+} -+ -+PipShellSurface::~PipShellSurface() -+{ -+ xx_pip_v1::destroy(); -+ xdg_surface::destroy(); -+} -+ -+bool PipShellSurface::isExposed() const -+{ -+ return m_configured; -+} -+ -+void PipShellSurface::applyConfigure() -+{ -+ QSize size = window()->windowContentGeometry().size(); -+ if (m_pendingSize.width() > 0) { -+ size.setWidth(m_pendingSize.width()); -+ } -+ if (m_pendingSize.height() > 0) { -+ size.setHeight(m_pendingSize.height()); -+ } -+ -+ window()->resizeFromApplyConfigure(size); -+} -+ -+void PipShellSurface::setWindowGeometry(const QRect &rect) -+{ -+ if (window()->isExposed()) { -+ xdg_surface::set_window_geometry(rect.x(), rect.y(), rect.width(), rect.height()); -+ } -+} -+ -+bool PipShellSurface::move(QtWaylandClient::QWaylandInputDevice *inputDevice) -+{ -+ if (!m_configured) { -+ return false; -+ } -+ xx_pip_v1::move(inputDevice->wl_seat(), inputDevice->serial()); -+ return true; -+} -+ -+bool PipShellSurface::resize(QtWaylandClient::QWaylandInputDevice *inputDevice, Qt::Edges edges) -+{ -+ if (!m_configured) { -+ return false; -+ } -+ -+ const resize_edge edge = static_cast( -+ ((edges & Qt::TopEdge) ? resize_edge_top : 0) -+ | ((edges & Qt::BottomEdge) ? resize_edge_bottom : 0) -+ | ((edges & Qt::LeftEdge) ? resize_edge_left : 0) -+ | ((edges & Qt::RightEdge) ? resize_edge_right : 0)); -+ -+ xx_pip_v1::resize(inputDevice->wl_seat(), inputDevice->serial(), edge); -+ return true; -+} -+ -+void PipShellSurface::xdg_surface_configure(uint32_t serial) -+{ -+ xdg_surface::ack_configure(serial); -+ -+ if (!m_configured) { -+ m_configured = true; -+ applyConfigure(); -+ } else { -+ window()->applyConfigureWhenPossible(); -+ } -+ -+ window()->updateExposure(); -+} -+ -+void PipShellSurface::xx_pip_v1_configure_bounds(int32_t width, int32_t height) -+{ -+} -+ -+void PipShellSurface::xx_pip_v1_configure_size(int32_t width, int32_t height) -+{ -+ m_pendingSize = QSize(width, height); -+} -+ -+void PipShellSurface::xx_pip_v1_closed() -+{ -+ QWindowSystemInterface::handleCloseEvent(window()->window()); -+} -+ -+#include "moc_pipshellsurface.cpp" -diff --git a/tests/pip/pipshellsurface.h b/tests/pip/pipshellsurface.h -new file mode 100644 -index 00000000000..b02e83b3fc9 ---- /dev/null -+++ b/tests/pip/pipshellsurface.h -@@ -0,0 +1,70 @@ -+/* -+ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: GPL-2.0-or-later -+*/ -+ -+#pragma once -+ -+#include -+#include -+#include -+#include -+ -+#include "qwayland-xdg-shell.h" -+#include "qwayland-xx-pip-v1.h" -+ -+class XdgWmBase : public QWaylandClientExtensionTemplate, public QtWayland::xdg_wm_base -+{ -+ Q_OBJECT -+ -+public: -+ XdgWmBase(); -+}; -+ -+class XXPipShell : public QWaylandClientExtensionTemplate, public QtWayland::xx_pip_shell_v1 -+{ -+ Q_OBJECT -+ -+public: -+ XXPipShell(); -+}; -+ -+class PipShellIntegration : public QtWaylandClient::QWaylandShellIntegration -+{ -+public: -+ PipShellIntegration(); -+ -+ bool initialize(QtWaylandClient::QWaylandDisplay *display) override; -+ QtWaylandClient::QWaylandShellSurface *createShellSurface(QtWaylandClient::QWaylandWindow *window) override; -+ -+ static void assignPipRole(QWindow *window); -+ -+private: -+ std::unique_ptr m_xdgWmBase; -+ std::unique_ptr m_xxPipShell; -+}; -+ -+class PipShellSurface : public QtWaylandClient::QWaylandShellSurface, public QtWayland::xdg_surface, public QtWayland::xx_pip_v1 -+{ -+ Q_OBJECT -+ -+public: -+ PipShellSurface(::xdg_surface *xdgSurface, ::xx_pip_v1 *xxPip, QtWaylandClient::QWaylandWindow *window); -+ ~PipShellSurface() override; -+ -+ bool isExposed() const override; -+ void applyConfigure() override; -+ void setWindowGeometry(const QRect &rect) override; -+ bool move(QtWaylandClient::QWaylandInputDevice *inputDevice) override; -+ bool resize(QtWaylandClient::QWaylandInputDevice *inputDevice, Qt::Edges edges) override; -+ -+private: -+ void xdg_surface_configure(uint32_t serial) override; -+ void xx_pip_v1_closed() override; -+ void xx_pip_v1_configure_bounds(int32_t width, int32_t height) override; -+ void xx_pip_v1_configure_size(int32_t width, int32_t height) override; -+ -+ QSize m_pendingSize; -+ bool m_configured = false; -+}; -diff --git a/tests/pip/window.cpp b/tests/pip/window.cpp -new file mode 100644 -index 00000000000..2ac98bde845 ---- /dev/null -+++ b/tests/pip/window.cpp -@@ -0,0 +1,19 @@ -+/* -+ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: GPL-2.0-or-later -+*/ -+ -+#include "window.h" -+#include "pip.h" -+ -+Window::Window(QWidget *parent) -+ : QWidget(parent) -+{ -+ resize(800, 600); -+ -+ m_media = new Media(this); -+ m_media->setGeometry(100, 100, 400, 300); -+} -+ -+#include "moc_window.cpp" -diff --git a/tests/pip/window.h b/tests/pip/window.h -new file mode 100644 -index 00000000000..bfd83e9d467 ---- /dev/null -+++ b/tests/pip/window.h -@@ -0,0 +1,22 @@ -+/* -+ SPDX-FileCopyrightText: 2025 Vlad Zahorodnii -+ -+ SPDX-License-Identifier: GPL-2.0-or-later -+*/ -+ -+#pragma once -+ -+#include -+ -+class Media; -+ -+class Window : public QWidget -+{ -+ Q_OBJECT -+ -+public: -+ explicit Window(QWidget *parent = nullptr); -+ -+private: -+ Media *m_media = nullptr; -+}; --- -GitLab - - -From cab39d37c8cb7d1c37d04a76cc7fa7af39fb7908 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Thu, 12 Jun 2025 14:22:55 +0000 -Subject: [PATCH 2/2] Apply 2 suggestion(s) to 1 file(s) - -Co-authored-by: Xaver Hugl ---- - src/wayland/xxpip_v1.cpp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/wayland/xxpip_v1.cpp b/src/wayland/xxpip_v1.cpp -index e0b1f36134f..bc1b65d0212 100644 ---- a/src/wayland/xxpip_v1.cpp -+++ b/src/wayland/xxpip_v1.cpp -@@ -282,7 +282,7 @@ quint32 XXPipV1Interface::sendConfigureSize(const QSizeF &size) - { - const quint32 serial = d->shell->display()->nextSerial(); - -- d->send_configure_size(size.width(), size.height()); -+ d->send_configure_size(std::round(size.width()), std::round(size.height())); - - auto xdgSurfacePrivate = XdgSurfaceInterfacePrivate::get(xdgSurface()); - xdgSurfacePrivate->send_configure(serial); -@@ -298,7 +298,7 @@ void XXPipV1Interface::sendClosed() - - void XXPipV1Interface::sendConfigureBounds(const QSizeF &size) - { -- d->send_configure_bounds(size.width(), size.height()); -+ d->send_configure_bounds(std::round(size.width()), std::round(size.height())); - } - - XXPipV1Interface *XXPipV1Interface::get(::wl_resource *resource) --- -GitLab - diff --git a/roles/kde/patches/kwin/pr7823.patch b/roles/kde/patches/kwin/pr7823.patch deleted file mode 100644 index 5e54a43..0000000 --- a/roles/kde/patches/kwin/pr7823.patch +++ /dev/null @@ -1,26 +0,0 @@ -From a1868942fbc2ad5de4c053dd17335dff34d81779 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Wed, 25 Jun 2025 14:10:18 +0300 -Subject: [PATCH] plugins/login: Reduce animation duration - -This makes the startup feel a bit faster. ---- - src/plugins/login/package/contents/code/main.js | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/plugins/login/package/contents/code/main.js b/src/plugins/login/package/contents/code/main.js -index 7f849a6e2e6..e3ad0b76c07 100644 ---- a/src/plugins/login/package/contents/code/main.js -+++ b/src/plugins/login/package/contents/code/main.js -@@ -11,7 +11,7 @@ - "use strict"; - - var loginEffect = { -- duration: animationTime(1000), -+ duration: animationTime(500), - isFadeToBlack: false, - loadConfig: function () { - loginEffect.isFadeToBlack = effect.readConfig("FadeToBlack", false); --- -GitLab - diff --git a/roles/kde/patches/kwin/pr7927.patch b/roles/kde/patches/kwin/pr7927.patch deleted file mode 100644 index d35ef4b..0000000 --- a/roles/kde/patches/kwin/pr7927.patch +++ /dev/null @@ -1,669 +0,0 @@ -From 9f6c92806490d662117575a766f9fcb01e253344 Mon Sep 17 00:00:00 2001 -From: Xaver Hugl -Date: Tue, 22 Jul 2025 23:24:51 +0200 -Subject: [PATCH 1/4] xdgactivation: move the activation token to workspace - ---- - src/activation.cpp | 14 ++++++++++++ - src/workspace.h | 6 +++++ - src/xdgactivationv1.cpp | 50 +++++++++-------------------------------- - src/xdgactivationv1.h | 14 ++---------- - 4 files changed, 32 insertions(+), 52 deletions(-) - -diff --git a/src/activation.cpp b/src/activation.cpp -index 60b921247ce..9e743b8b098 100644 ---- a/src/activation.cpp -+++ b/src/activation.cpp -@@ -630,4 +630,18 @@ void Workspace::windowAttentionChanged(Window *window, bool set) - } - } - -+void Workspace::setActivationToken(const QString &token, uint32_t serial) -+{ -+ m_activationToken = token; -+ m_activationTokenSerial = serial; -+} -+ -+bool Workspace::mayActivate(const QString &token) const -+{ -+ if (!m_activeWindow) { -+ return true; -+ } -+ return !m_activationToken.isEmpty() && token == m_activationToken && m_activeWindow->lastUsageSerial() <= m_activationTokenSerial; -+} -+ - } // namespace -diff --git a/src/workspace.h b/src/workspace.h -index 2082bbe148d..03c54e06750 100644 ---- a/src/workspace.h -+++ b/src/workspace.h -@@ -436,6 +436,9 @@ public: - OutputConfigurationError applyOutputConfiguration(OutputConfiguration &config, const std::optional> &outputOrder = std::nullopt); - void updateXwaylandScale(); - -+ void setActivationToken(const QString &token, uint32_t serial); -+ bool mayActivate(const QString &token) const; -+ - public Q_SLOTS: - void performWindowOperation(KWin::Window *window, Options::WindowOperation op); - // Keybindings -@@ -729,6 +732,9 @@ private: - std::unique_ptr m_dpmsFilter; - KConfigWatcher::Ptr m_kdeglobalsWatcher; - -+ QString m_activationToken; -+ uint32_t m_activationTokenSerial = 0; -+ - private: - friend bool performTransiencyCheck(); - friend Workspace *workspace(); -diff --git a/src/xdgactivationv1.cpp b/src/xdgactivationv1.cpp -index 39dade95332..a6be350399a 100644 ---- a/src/xdgactivationv1.cpp -+++ b/src/xdgactivationv1.cpp -@@ -33,22 +33,6 @@ static bool isPrivilegedInWindowManagement(const ClientConnection *client) - XdgActivationV1Integration::XdgActivationV1Integration(XdgActivationV1Interface *activation, QObject *parent) - : QObject(parent) - { -- Workspace *ws = Workspace::self(); -- connect(ws, &Workspace::windowActivated, this, [this](Window *window) { -- if (!m_currentActivationToken || !window || window->property("token").toString() == m_currentActivationToken->token) { -- return; -- } -- -- // We check that it's not the app that we are trying to activate -- if (window->desktopFileName() != m_currentActivationToken->applicationId) { -- // But also that the new one has been requested after the token was requested -- if (window->lastUsageSerial() < m_currentActivationToken->serial) { -- return; -- } -- } -- -- clear(); -- }); - activation->setActivationTokenCreator([this](ClientConnection *client, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId) -> QString { - Workspace *ws = Workspace::self(); - Q_ASSERT(client); // Should always be available as it's coming straight from the wayland implementation -@@ -69,9 +53,6 @@ QString XdgActivationV1Integration::requestToken(bool isPrivileged, SurfaceInter - static int i = 0; - const auto newToken = QStringLiteral("kwin-%1").arg(++i); - -- if (m_currentActivationToken) { -- clear(); -- } - bool showNotify = false; - QIcon icon = QIcon::fromTheme(QStringLiteral("system-run")); - if (const QString desktopFilePath = Window::findDesktopFile(appId); !desktopFilePath.isEmpty()) { -@@ -83,13 +64,13 @@ QString XdgActivationV1Integration::requestToken(bool isPrivileged, SurfaceInter - } - icon = QIcon::fromTheme(df.readIcon(), icon); - } -- std::unique_ptr activation; - if (showNotify) { -- activation = waylandServer()->plasmaActivationFeedback()->createActivation(appId); -+ m_lastToken = newToken; -+ m_activation = waylandServer()->plasmaActivationFeedback()->createActivation(appId); - } -- m_currentActivationToken = std::make_unique(ActivationToken{newToken, isPrivileged, surface, serial, seat, appId, showNotify, std::move(activation)}); -+ workspace()->setActivationToken(newToken, serial); - if (showNotify) { -- Q_EMIT effects->startupAdded(m_currentActivationToken->token, icon); -+ Q_EMIT effects->startupAdded(newToken, icon); - } - return newToken; - } -@@ -103,31 +84,20 @@ void XdgActivationV1Integration::activateSurface(SurfaceInterface *surface, cons - return; - } - -- if (!m_currentActivationToken || m_currentActivationToken->token != token) { -- qCDebug(KWIN_CORE) << "Refusing to activate " << window << " (provided token: " << token << ", current token:" << (m_currentActivationToken ? m_currentActivationToken->token : QStringLiteral("null")) << ")"; -+ if (!ws->mayActivate(token)) { - window->demandAttention(); - return; - } -- -- auto ownerWindow = waylandServer()->findWindow(m_currentActivationToken->surface); -- qCDebug(KWIN_CORE) << "activating" << window << surface << "on behalf of" << m_currentActivationToken->surface << "into" << ownerWindow; -- if (!ws->activeWindow() || ws->activeWindow() == ownerWindow || ws->activeWindow()->lastUsageSerial() < m_currentActivationToken->serial || m_currentActivationToken->isPrivileged) { -- ws->activateWindow(window); -- } else { -- qCWarning(KWIN_CORE) << "Activation requested while owner isn't active" << (ownerWindow ? ownerWindow->desktopFileName() : "null") -- << m_currentActivationToken->applicationId; -- window->demandAttention(); -- clear(); -- } -+ ws->activateWindow(window); -+ clear(); - } - - void XdgActivationV1Integration::clear() - { -- Q_ASSERT(m_currentActivationToken); -- if (m_currentActivationToken->showNotify) { -- Q_EMIT effects->startupRemoved(m_currentActivationToken->token); -+ if (m_activation) { -+ Q_EMIT effects->startupRemoved(m_lastToken); -+ m_activation.reset(); - } -- m_currentActivationToken.reset(); - } - - } -diff --git a/src/xdgactivationv1.h b/src/xdgactivationv1.h -index 98835def8aa..77d21856095 100644 ---- a/src/xdgactivationv1.h -+++ b/src/xdgactivationv1.h -@@ -38,18 +38,8 @@ private: - QString requestToken(bool isPrivileged, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId); - void clear(); - -- struct ActivationToken -- { -- QString token; -- bool isPrivileged; -- QPointer surface; -- uint serial; -- SeatInterface *seat; -- QString applicationId; -- bool showNotify; -- std::unique_ptr activation; -- }; -- std::unique_ptr m_currentActivationToken; -+ QString m_lastToken; -+ std::unique_ptr m_activation; - }; - - } --- -GitLab - - -From 6c673a479412902a14c06046199f976e2192dc65 Mon Sep 17 00:00:00 2001 -From: Xaver Hugl -Date: Tue, 22 Jul 2025 23:43:14 +0200 -Subject: [PATCH 2/4] xdgactivation: also allow using activation tokens before - the window is mapped - -We just store the token in the window, and then Workspace uses it to decide whether -or not to activate the window when it's actually shown. ---- - src/window.cpp | 10 ++++++++++ - src/window.h | 5 +++++ - src/workspace.cpp | 4 ++-- - src/xdgactivationv1.cpp | 6 +++++- - 4 files changed, 22 insertions(+), 3 deletions(-) - -diff --git a/src/window.cpp b/src/window.cpp -index 4a97a54aa74..879147ec673 100644 ---- a/src/window.cpp -+++ b/src/window.cpp -@@ -4675,6 +4675,16 @@ void Window::setDescription(const QString &description) - } - } - -+void Window::setActivationToken(const QString &token) -+{ -+ m_activationToken = token; -+} -+ -+QString Window::activationToken() const -+{ -+ return m_activationToken; -+} -+ - } // namespace KWin - - #include "moc_window.cpp" -diff --git a/src/window.h b/src/window.h -index 1eb371018ca..91addb46819 100644 ---- a/src/window.h -+++ b/src/window.h -@@ -1357,6 +1357,9 @@ public: - QString tag() const; - QString description() const; - -+ void setActivationToken(const QString &token); -+ QString activationToken() const; -+ - public Q_SLOTS: - virtual void closeWindow() = 0; - -@@ -1880,6 +1883,8 @@ protected: - - QString m_tag; - QString m_description; -+ -+ QString m_activationToken; - }; - - inline QRectF Window::bufferGeometry() const -diff --git a/src/workspace.cpp b/src/workspace.cpp -index 3a5cb12677b..866abb8080d 100644 ---- a/src/workspace.cpp -+++ b/src/workspace.cpp -@@ -781,8 +781,8 @@ void Workspace::addWaylandWindow(Window *window) - rearrange(); - } - if (window->wantsInput() && !window->isMinimized()) { -- // Never activate a window on its own in "Extreme" mode. -- if (options->focusStealingPreventionLevel() < 4) { -+ // In "Extreme" mode, require an activation token to activate new windows -+ if (options->focusStealingPreventionLevel() < 4 || (!m_activationToken.isEmpty() && window->activationToken() == m_activationToken)) { - if (!window->isDesktop() - // If there's no active window, make this desktop the active one. - || (activeWindow() == nullptr && should_get_focus.count() == 0)) { -diff --git a/src/xdgactivationv1.cpp b/src/xdgactivationv1.cpp -index a6be350399a..11c95c84b32 100644 ---- a/src/xdgactivationv1.cpp -+++ b/src/xdgactivationv1.cpp -@@ -88,7 +88,11 @@ void XdgActivationV1Integration::activateSurface(SurfaceInterface *surface, cons - window->demandAttention(); - return; - } -- ws->activateWindow(window); -+ if (window->readyForPainting()) { -+ ws->activateWindow(window); -+ } else { -+ window->setActivationToken(token); -+ } - clear(); - } - --- -GitLab - - -From 2436625a66257f586a0934c3d678c910bbdb3705 Mon Sep 17 00:00:00 2001 -From: Xaver Hugl -Date: Wed, 23 Jul 2025 13:18:39 +0200 -Subject: [PATCH 3/4] xdgactivation: move the "not granted" token to - requestToken - -Having some but not all checks in that method is a bit confusing ---- - src/xdgactivationv1.cpp | 14 ++++++-------- - 1 file changed, 6 insertions(+), 8 deletions(-) - -diff --git a/src/xdgactivationv1.cpp b/src/xdgactivationv1.cpp -index 11c95c84b32..e818466f8ad 100644 ---- a/src/xdgactivationv1.cpp -+++ b/src/xdgactivationv1.cpp -@@ -34,15 +34,8 @@ XdgActivationV1Integration::XdgActivationV1Integration(XdgActivationV1Interface - : QObject(parent) - { - activation->setActivationTokenCreator([this](ClientConnection *client, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId) -> QString { -- Workspace *ws = Workspace::self(); - Q_ASSERT(client); // Should always be available as it's coming straight from the wayland implementation -- const bool isPrivileged = isPrivilegedInWindowManagement(client); -- if (!isPrivileged && ws->activeWindow() && ws->activeWindow()->surface() != surface) { -- qCDebug(KWIN_CORE) << "Cannot grant a token to" << client; -- return QStringLiteral("not-granted-666"); -- } -- -- return requestToken(isPrivileged, surface, serial, seat, appId); -+ return requestToken(isPrivilegedInWindowManagement(client), surface, serial, seat, appId); - }); - - connect(activation, &XdgActivationV1Interface::activateRequested, this, &XdgActivationV1Integration::activateSurface); -@@ -50,6 +43,11 @@ XdgActivationV1Integration::XdgActivationV1Integration(XdgActivationV1Interface - - QString XdgActivationV1Integration::requestToken(bool isPrivileged, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId) - { -+ auto window = waylandServer()->findWindow(surface); -+ if (!isPrivileged && workspace()->activeWindow() && workspace()->activeWindow()->surface() != surface) { -+ qCWarning(KWIN_CORE) << "Cannot grant a token to" << window; -+ return QStringLiteral("not-granted-666"); -+ } - static int i = 0; - const auto newToken = QStringLiteral("kwin-%1").arg(++i); - --- -GitLab - - -From 8508b8060813c07fe035801381bad1f9a375acf0 Mon Sep 17 00:00:00 2001 -From: Xaver Hugl -Date: Thu, 24 Jul 2025 20:43:46 +0200 -Subject: [PATCH 4/4] autotests/integration: add a test case for xdg activation - ---- - autotests/integration/CMakeLists.txt | 3 +- - autotests/integration/activation_test.cpp | 126 +++++++++++++++++++++- - autotests/integration/kwin_wayland_test.h | 31 ++++++ - autotests/integration/test_helpers.cpp | 50 +++++++++ - 4 files changed, 208 insertions(+), 2 deletions(-) - -diff --git a/autotests/integration/CMakeLists.txt b/autotests/integration/CMakeLists.txt -index 13b0cde04f5..408af6ac8b8 100644 ---- a/autotests/integration/CMakeLists.txt -+++ b/autotests/integration/CMakeLists.txt -@@ -16,13 +16,14 @@ qt6_generate_wayland_protocol_client_sources(KWinIntegrationTestFramework - FILES - ${CMAKE_SOURCE_DIR}/src/wayland/protocols/wlr-layer-shell-unstable-v1.xml - ${WaylandProtocols_DATADIR}/stable/presentation-time/presentation-time.xml -+ ${WaylandProtocols_DATADIR}/stable/tablet/tablet-v2.xml - ${WaylandProtocols_DATADIR}/stable/xdg-shell/xdg-shell.xml - ${WaylandProtocols_DATADIR}/staging/color-management/color-management-v1.xml -- ${WaylandProtocols_DATADIR}/stable/tablet/tablet-v2.xml - ${WaylandProtocols_DATADIR}/staging/cursor-shape/cursor-shape-v1.xml - ${WaylandProtocols_DATADIR}/staging/fifo/fifo-v1.xml - ${WaylandProtocols_DATADIR}/staging/fractional-scale/fractional-scale-v1.xml - ${WaylandProtocols_DATADIR}/staging/security-context/security-context-v1.xml -+ ${WaylandProtocols_DATADIR}/staging/xdg-activation/xdg-activation-v1.xml - ${WaylandProtocols_DATADIR}/staging/xdg-dialog/xdg-dialog-v1.xml - ${WaylandProtocols_DATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml - ${WaylandProtocols_DATADIR}/unstable/text-input/text-input-unstable-v3.xml -diff --git a/autotests/integration/activation_test.cpp b/autotests/integration/activation_test.cpp -index 75c9e7e8c7b..30f671d6fe2 100644 ---- a/autotests/integration/activation_test.cpp -+++ b/autotests/integration/activation_test.cpp -@@ -15,6 +15,7 @@ - #include "workspace.h" - #include "x11window.h" - -+#include - #include - #include - #include -@@ -40,6 +41,7 @@ private Q_SLOTS: - void testSwitchToWindowMaximized(); - void testSwitchToWindowFullScreen(); - void testActiveFullscreen(); -+ void testXdgActivation(); - - private: - void stackScreensHorizontally(); -@@ -64,7 +66,7 @@ void ActivationTest::initTestCase() - - void ActivationTest::init() - { -- QVERIFY(Test::setupWaylandConnection()); -+ QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::XdgActivation | Test::AdditionalWaylandInterface::Seat)); - - workspace()->setActiveOutput(QPoint(640, 512)); - input()->pointer()->warp(QPoint(640, 512)); -@@ -592,6 +594,128 @@ void ActivationTest::testActiveFullscreen() - QCOMPARE(workspace()->activeWindow(), waylandWindow); - QCOMPARE(x11Window->layer(), Layer::NormalLayer); - } -+ -+void ActivationTest::testXdgActivation() -+{ -+ Test::setOutputConfig({QRect(0, 0, 1280, 1024)}); -+ -+ uint32_t time = 0; -+ -+ std::vector> surfaces; -+ std::vector> shellSurfaces; -+ std::vector windows; -+ const auto setupWindows = [&]() { -+ windows.clear(); -+ shellSurfaces.clear(); -+ surfaces.clear(); -+ -+ // re-create the same setup every time for reduced confusion -+ for (int i = 0; i < 3; i++) { -+ surfaces.push_back(Test::createSurface()); -+ shellSurfaces.push_back(Test::createXdgToplevelSurface(surfaces.back().get())); -+ windows.push_back(Test::renderAndWaitForShown(surfaces.back().get(), QSize(100, 50), Qt::blue)); -+ windows.back()->move(QPoint(150 * i, 0)); -+ -+ Test::pointerMotion(windows.back()->frameGeometry().center(), time++); -+ Test::pointerButtonPressed(1, time++); -+ Test::pointerButtonReleased(1, time++); -+ } -+ }; -+ setupWindows(); -+ -+ QSignalSpy activationSpy(workspace(), &Workspace::windowActivated); -+ -+ // activating a window without a valid token should fail -+ Test::xdgActivation()->activate(QString(), *surfaces[1]); -+ QVERIFY(!activationSpy.wait(10)); -+ -+ // activating it without a surface should fail as well, even if a serial is present -+ auto token = Test::xdgActivation()->createToken(); -+ token->set_serial(windows.back()->lastUsageSerial(), *Test::waylandSeat()); -+ Test::xdgActivation()->activate(token->commitAndWait(), *surfaces[1]); -+ QVERIFY(!activationSpy.wait(10)); -+ -+ // adding the surface should make it work -+ token = Test::xdgActivation()->createToken(); -+ token->set_surface(*surfaces.back()); -+ token->set_serial(windows.back()->lastUsageSerial(), *Test::waylandSeat()); -+ Test::xdgActivation()->activate(token->commitAndWait(), *surfaces[1]); -+ QVERIFY(activationSpy.wait(10)); -+ QCOMPARE(workspace()->activeWindow(), windows[1]); -+ -+ // activation should still work if the window is closed after creating the token -+ setupWindows(); -+ token = Test::xdgActivation()->createToken(); -+ token->set_surface(*surfaces[2]); -+ token->set_serial(windows[2]->lastUsageSerial(), *Test::waylandSeat()); -+ QString result = token->commitAndWait(); -+ -+ surfaces[2]->attachBuffer((wl_buffer *)nullptr); -+ surfaces[2]->commit(KWayland::Client::Surface::CommitFlag::None); -+ QVERIFY(activationSpy.wait(10)); -+ QCOMPARE(workspace()->activeWindow(), windows[1]); -+ -+ Test::xdgActivation()->activate(result, *surfaces[0]); -+ QVERIFY(activationSpy.wait(10)); -+ QCOMPARE(workspace()->activeWindow(), windows[0]); -+ -+ // ...unless the user interacted with another window in between -+ setupWindows(); -+ token = Test::xdgActivation()->createToken(); -+ token->set_surface(*surfaces[2]); -+ token->set_serial(windows[2]->lastUsageSerial(), *Test::waylandSeat()); -+ result = token->commitAndWait(); -+ -+ surfaces[2]->attachBuffer((wl_buffer *)nullptr); -+ surfaces[2]->commit(KWayland::Client::Surface::CommitFlag::None); -+ QVERIFY(activationSpy.wait(10)); -+ QCOMPARE(workspace()->activeWindow(), windows[1]); -+ -+ Test::pointerMotion(windows[1]->frameGeometry().center(), time++); -+ Test::pointerButtonPressed(1, time++); -+ Test::pointerButtonReleased(1, time++); -+ -+ Test::xdgActivation()->activate(result, *surfaces[0]); -+ QVERIFY(!activationSpy.wait(10)); -+ QCOMPARE(workspace()->activeWindow(), windows[1]); -+ -+ // ensure that windows are only activated on show with a valid activation token -+ options->setFocusStealingPreventionLevel(4); -+ -+ // creating a new window and immediately activating it should work -+ setupWindows(); -+ token = Test::xdgActivation()->createToken(); -+ token->set_surface(*surfaces[2]); -+ token->set_serial(windows[2]->lastUsageSerial(), *Test::waylandSeat()); -+ result = token->commitAndWait(); -+ surfaces.push_back(Test::createSurface()); -+ shellSurfaces.push_back(Test::createXdgToplevelSurface(surfaces.back().get(), [&](Test::XdgToplevel *toplevel) { -+ Test::xdgActivation()->activate(result, *surfaces.back()); -+ })); -+ windows.push_back(Test::renderAndWaitForShown(surfaces.back().get(), QSize(100, 50), Qt::blue)); -+ QCOMPARE(workspace()->activeWindow(), windows.back()); -+ windows.back()->move(QPoint(150 * 3, 0)); -+ -+ // activation should fail if the user clicks on another window in between -+ // creating the activation token and using it -+ setupWindows(); -+ token = Test::xdgActivation()->createToken(); -+ token->set_surface(*surfaces[2]); -+ token->set_serial(windows[2]->lastUsageSerial(), *Test::waylandSeat()); -+ result = token->commitAndWait(); -+ -+ Test::pointerMotion(windows[1]->frameGeometry().center(), time++); -+ Test::pointerButtonPressed(1, time++); -+ Test::pointerButtonReleased(1, time++); -+ -+ surfaces.push_back(Test::createSurface()); -+ shellSurfaces.push_back(Test::createXdgToplevelSurface(surfaces.back().get(), [&](Test::XdgToplevel *toplevel) { -+ Test::xdgActivation()->activate(result, *surfaces.back()); -+ })); -+ windows.push_back(Test::renderAndWaitForShown(surfaces.back().get(), QSize(100, 50), Qt::blue)); -+ QCOMPARE(workspace()->activeWindow(), windows[1]); -+ windows.back()->move(QPoint(150 * 3, 0)); -+} - } - - WAYLANDTEST_MAIN(KWin::ActivationTest) -diff --git a/autotests/integration/kwin_wayland_test.h b/autotests/integration/kwin_wayland_test.h -index b0f63dadbc5..a6616189617 100644 ---- a/autotests/integration/kwin_wayland_test.h -+++ b/autotests/integration/kwin_wayland_test.h -@@ -34,6 +34,7 @@ - #include "qwayland-security-context-v1.h" - #include "qwayland-text-input-unstable-v3.h" - #include "qwayland-wlr-layer-shell-unstable-v1.h" -+#include "qwayland-xdg-activation-v1.h" - #include "qwayland-xdg-decoration-unstable-v1.h" - #include "qwayland-xdg-dialog-v1.h" - #include "qwayland-xdg-shell.h" -@@ -611,6 +612,7 @@ enum class AdditionalWaylandInterface { - ColorManagement = 1 << 22, - FifoV1 = 1 << 23, - PresentationTime = 1 << 24, -+ XdgActivation = 1 << 25, - }; - Q_DECLARE_FLAGS(AdditionalWaylandInterfaces, AdditionalWaylandInterface) - -@@ -717,6 +719,33 @@ private: - void wp_presentation_feedback_discarded() override; - }; - -+class XdgActivationToken : public QObject, public QtWayland::xdg_activation_token_v1 -+{ -+ Q_OBJECT -+public: -+ explicit XdgActivationToken(::xdg_activation_token_v1 *object); -+ ~XdgActivationToken() override; -+ -+ QString commitAndWait(); -+ -+Q_SIGNALS: -+ void tokenReceived(); -+ -+private: -+ void xdg_activation_token_v1_done(const QString &token) override; -+ -+ QString m_token; -+}; -+ -+class XdgActivation : public QtWayland::xdg_activation_v1 -+{ -+public: -+ explicit XdgActivation(::wl_registry *registry, uint32_t id, int version); -+ ~XdgActivation() override; -+ -+ std::unique_ptr createToken(); -+}; -+ - struct Connection - { - static std::unique_ptr setup(AdditionalWaylandInterfaces interfaces = AdditionalWaylandInterfaces()); -@@ -757,6 +786,7 @@ struct Connection - std::unique_ptr colorManager; - std::unique_ptr fifoManager; - std::unique_ptr presentationTime; -+ std::unique_ptr xdgActivation; - }; - - void keyboardKeyPressed(quint32 key, quint32 time); -@@ -821,6 +851,7 @@ SecurityContextManagerV1 *waylandSecurityContextManagerV1(); - ColorManagerV1 *colorManager(); - FifoManagerV1 *fifoManager(); - PresentationTime *presentationTime(); -+XdgActivation *xdgActivation(); - - bool waitForWaylandSurface(Window *window); - -diff --git a/autotests/integration/test_helpers.cpp b/autotests/integration/test_helpers.cpp -index 22380c947d3..e524f10826d 100644 ---- a/autotests/integration/test_helpers.cpp -+++ b/autotests/integration/test_helpers.cpp -@@ -535,6 +535,11 @@ std::unique_ptr Connection::setup(AdditionalWaylandInterfaces flags) - c->presentationTime = std::make_unique(*c->registry, name, version); - } - } -+ if (flags & AdditionalWaylandInterface::XdgActivation) { -+ if (interface == xdg_activation_v1_interface.name) { -+ c->xdgActivation = std::make_unique(*c->registry, name, version); -+ } -+ } - }); - - QSignalSpy allAnnounced(registry, &KWayland::Client::Registry::interfacesAnnounced); -@@ -665,6 +670,7 @@ Connection::~Connection() - colorManager.reset(); - fifoManager.reset(); - presentationTime.reset(); -+ xdgActivation.reset(); - - delete queue; // Must be destroyed last - queue = nullptr; -@@ -796,6 +802,11 @@ PresentationTime *presentationTime() - return s_waylandConnection->presentationTime.get(); - } - -+XdgActivation *xdgActivation() -+{ -+ return s_waylandConnection->xdgActivation.get(); -+} -+ - bool waitForWaylandSurface(Window *window) - { - if (window->surface()) { -@@ -1817,6 +1828,45 @@ void WpPresentationFeedback::wp_presentation_feedback_discarded() - Q_EMIT discarded(); - } - -+XdgActivationToken::XdgActivationToken(::xdg_activation_token_v1 *object) -+ : QtWayland::xdg_activation_token_v1(object) -+{ -+} -+ -+XdgActivationToken::~XdgActivationToken() -+{ -+ destroy(); -+} -+ -+QString XdgActivationToken::commitAndWait() -+{ -+ QSignalSpy received(this, &XdgActivationToken::tokenReceived); -+ commit(); -+ received.wait(); -+ return m_token; -+} -+ -+void XdgActivationToken::xdg_activation_token_v1_done(const QString &token) -+{ -+ m_token = token; -+ Q_EMIT tokenReceived(); -+} -+ -+XdgActivation::XdgActivation(::wl_registry *registry, uint32_t id, int version) -+ : QtWayland::xdg_activation_v1(registry, id, version) -+{ -+} -+ -+XdgActivation::~XdgActivation() -+{ -+ destroy(); -+} -+ -+std::unique_ptr XdgActivation::createToken() -+{ -+ return std::make_unique(get_activation_token()); -+} -+ - void keyboardKeyPressed(quint32 key, quint32 time) - { - auto virtualKeyboard = static_cast(kwinApp())->virtualKeyboard(); --- -GitLab - diff --git a/roles/kde/patches/kwin/pr8005.patch b/roles/kde/patches/kwin/pr8005.patch deleted file mode 100644 index b95d140..0000000 --- a/roles/kde/patches/kwin/pr8005.patch +++ /dev/null @@ -1,71 +0,0 @@ -From dc692e89f101a47b9049b1f6ae4cc3cebef46edb Mon Sep 17 00:00:00 2001 -From: Xaver Hugl -Date: Tue, 12 Aug 2025 15:59:16 +0200 -Subject: [PATCH] xdgactivation: clear activation feedback if no token is - provided too - -If the window is activated, the user expectation is that feedback stops. The underlying -reason for why it's activated doesn't matter. ---- - src/xdgactivationv1.cpp | 12 ++++++++++-- - src/xdgactivationv1.h | 3 ++- - 2 files changed, 12 insertions(+), 3 deletions(-) - -diff --git a/src/xdgactivationv1.cpp b/src/xdgactivationv1.cpp -index 360ca9b8743..567b792025f 100644 ---- a/src/xdgactivationv1.cpp -+++ b/src/xdgactivationv1.cpp -@@ -33,6 +33,13 @@ static bool isPrivilegedInWindowManagement(const ClientConnection *client) - XdgActivationV1Integration::XdgActivationV1Integration(XdgActivationV1Interface *activation, QObject *parent) - : QObject(parent) - { -+ connect(Workspace::self(), &Workspace::windowActivated, this, [this](Window *window) { -+ if (!m_activation || !window || m_lastTokenAppId != window->desktopFileName()) { -+ return; -+ } -+ clearFeedback(); -+ }); -+ - activation->setActivationTokenCreator([this](ClientConnection *client, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId) -> QString { - Q_ASSERT(client); // Should always be available as it's coming straight from the wayland implementation - return requestToken(isPrivilegedInWindowManagement(client), surface, serial, seat, appId); -@@ -64,6 +71,7 @@ QString XdgActivationV1Integration::requestToken(bool isPrivileged, SurfaceInter - } - if (showNotify) { - m_lastToken = newToken; -+ m_lastTokenAppId = appId; - m_activation = waylandServer()->plasmaActivationFeedback()->createActivation(appId); - } - if (isPrivileged && workspace()->activeWindow()) { -@@ -95,10 +103,10 @@ void XdgActivationV1Integration::activateSurface(SurfaceInterface *surface, cons - } else { - window->setActivationToken(token); - } -- clear(); -+ clearFeedback(); - } - --void XdgActivationV1Integration::clear() -+void XdgActivationV1Integration::clearFeedback() - { - if (m_activation) { - Q_EMIT effects->startupRemoved(m_lastToken); -diff --git a/src/xdgactivationv1.h b/src/xdgactivationv1.h -index 77d21856095..ad007c088b6 100644 ---- a/src/xdgactivationv1.h -+++ b/src/xdgactivationv1.h -@@ -36,9 +36,10 @@ public: - - private: - QString requestToken(bool isPrivileged, SurfaceInterface *surface, uint serial, SeatInterface *seat, const QString &appId); -- void clear(); -+ void clearFeedback(); - - QString m_lastToken; -+ QString m_lastTokenAppId; - std::unique_ptr m_activation; - }; - --- -GitLab - diff --git a/roles/kde/patches/kwin/pr8155.patch b/roles/kde/patches/kwin/pr8155.patch deleted file mode 100644 index ff8eb4b..0000000 --- a/roles/kde/patches/kwin/pr8155.patch +++ /dev/null @@ -1,60 +0,0 @@ -From bab7c4a4c5e2fb7be83ba94fdd0da7fd196654fa Mon Sep 17 00:00:00 2001 -From: David Redondo -Date: Thu, 25 Sep 2025 12:00:51 +0200 -Subject: [PATCH] Make sure XdgToplevelWindow always has an icon - -If the client never called set_app_id and did not set a custom -icon the window would end up without an icon at all. This ensures -that all windows always have at least the default icon. ---- - autotests/integration/xdgshellwindow_test.cpp | 13 +++++++++++-- - src/xdgshellwindow.cpp | 1 + - 2 files changed, 12 insertions(+), 2 deletions(-) - -diff --git a/autotests/integration/xdgshellwindow_test.cpp b/autotests/integration/xdgshellwindow_test.cpp -index 0903043808d..a3658ee62e7 100644 ---- a/autotests/integration/xdgshellwindow_test.cpp -+++ b/autotests/integration/xdgshellwindow_test.cpp -@@ -683,16 +683,25 @@ void TestXdgShellWindow::testDesktopFileName() - std::unique_ptr surface(Test::createSurface()); - // only xdg-shell as ShellSurface misses the setter - std::unique_ptr shellSurface(Test::createXdgToplevelSurface(surface.get())); -- shellSurface->set_app_id(QStringLiteral("org.kde.foo")); - auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); - QVERIFY(window); -+ -+ // A client that never call set_app_id still gets the default icon -+ QCOMPARE(window->desktopFileName(), QString()); -+ QVERIFY(window->resourceClass().startsWith("testXdgShellWindow")); -+ QVERIFY(window->resourceName().startsWith("testXdgShellWindow")); -+ QCOMPARE(window->icon().name(), QStringLiteral("wayland")); -+ -+ QSignalSpy desktopFileNameChangedSpy(window, &Window::desktopFileNameChanged); -+ -+ shellSurface->set_app_id(QStringLiteral("org.kde.foo")); -+ QVERIFY(desktopFileNameChangedSpy.wait()); - QCOMPARE(window->desktopFileName(), QStringLiteral("org.kde.foo")); - QCOMPARE(window->resourceClass(), QStringLiteral("org.kde.foo")); - QVERIFY(window->resourceName().startsWith("testXdgShellWindow")); - // the desktop file does not exist, so icon should be generic Wayland - QCOMPARE(window->icon().name(), QStringLiteral("wayland")); - -- QSignalSpy desktopFileNameChangedSpy(window, &Window::desktopFileNameChanged); - QSignalSpy iconChangedSpy(window, &Window::iconChanged); - shellSurface->set_app_id(QStringLiteral("org.kde.bar")); - QVERIFY(desktopFileNameChangedSpy.wait()); -diff --git a/src/xdgshellwindow.cpp b/src/xdgshellwindow.cpp -index f585d3aef95..092c284b8c2 100644 ---- a/src/xdgshellwindow.cpp -+++ b/src/xdgshellwindow.cpp -@@ -1426,6 +1426,7 @@ void XdgToplevelWindow::initialize() - scheduleConfigure(); - updateColorScheme(); - updateCapabilities(); -+ updateIcon(); - setupWindowManagementInterface(); - - m_isInitialized = true; --- -GitLab - diff --git a/roles/kde/patches/plasma-nm/patches.txt b/roles/kde/patches/plasma-nm/patches.txt deleted file mode 100644 index c5e71a7..0000000 --- a/roles/kde/patches/plasma-nm/patches.txt +++ /dev/null @@ -1,4 +0,0 @@ -Plasma 6.5.0: - -Pr 439 https://invent.kde.org/plasma/plasma-nm/-/merge_requests/439 -Pr 442 https://invent.kde.org/plasma/plasma-nm/-/merge_requests/442 diff --git a/roles/kde/patches/plasma-nm/pr439.patch b/roles/kde/patches/plasma-nm/pr439.patch deleted file mode 100644 index 885e3dd..0000000 --- a/roles/kde/patches/plasma-nm/pr439.patch +++ /dev/null @@ -1,140 +0,0 @@ -From ac32824009397188131aab4fcc3394fcc4551c5c Mon Sep 17 00:00:00 2001 -From: Nate Graham -Date: Tue, 10 Jun 2025 15:43:13 -0600 -Subject: [PATCH 1/2] applet: handle some more states - -1. Looking for Wi-Fi networks but haven't found any yet -2. NetworkManager isn't running - -FEATURE: 485982 -BUG: 462454 -FIXED-IN: 6.5.0 ---- - applet/contents/ui/ConnectionListPage.qml | 15 ++++++++++++--- - applet/contents/ui/Toolbar.qml | 3 ++- - applet/metadata.json | 1 - - libs/networkstatus.h | 3 +-- - 4 files changed, 15 insertions(+), 7 deletions(-) - -diff --git a/applet/contents/ui/ConnectionListPage.qml b/applet/contents/ui/ConnectionListPage.qml -index b9a949d87..056f52de3 100644 ---- a/applet/contents/ui/ConnectionListPage.qml -+++ b/applet/contents/ui/ConnectionListPage.qml -@@ -101,9 +101,12 @@ ColumnLayout { - if (toolbar.displayplaneModeMessage) { - return "network-flightmode-on" - } -- if (toolbar.displayWifiMessage) { -+ if (toolbar.displayWifiOffMessage) { - return "network-wireless-off" - } -+ if (toolbar.displayWifiConnectingMessage) { -+ return "view-refresh-symbolic" -+ } - if (toolbar.displayWwanMessage) { - return "network-mobile-off" - } -@@ -113,19 +116,25 @@ ColumnLayout { - if (toolbar.displayplaneModeMessage) { - return i18n("Airplane mode is enabled") - } -- if (toolbar.displayWifiMessage) { -+ if (toolbar.displayWifiOffMessage) { - if (toolbar.displayWwanMessage) { - return i18n("Wireless and mobile networks are deactivated") - } - return i18n("Wireless is deactivated") - } -+ if (toolbar.displayWifiConnectingMessage) { -+ return i18n("Looking for wireless networks") -+ } - if (toolbar.displayWwanMessage) { - return i18n("Mobile network is deactivated") - } - if (toolbar.searchTextField.text.length > 0) { - return i18n("No matches") - } -- return i18n("No available connections") -+ if (connectionListPage.nmStatus.connectivity === NMQt.NetworkManager.Full) { -+ return i18n("No available connections") -+ } -+ return nmStatus.checkUnknownReason() - } - } - } -diff --git a/applet/contents/ui/Toolbar.qml b/applet/contents/ui/Toolbar.qml -index 87b3f1654..0d382109b 100644 ---- a/applet/contents/ui/Toolbar.qml -+++ b/applet/contents/ui/Toolbar.qml -@@ -16,7 +16,8 @@ import org.kde.kcmutils as KCMUtils - RowLayout { - id: toolbar - -- readonly property var displayWifiMessage: !wifiSwitchButton.checked && wifiSwitchButton.visible -+ readonly property var displayWifiOffMessage: !wifiSwitchButton.checked && wifiSwitchButton.visible -+ readonly property var displayWifiConnectingMessage: wifiSwitchButton.checked && wifiSwitchButton.visible - readonly property var displayWwanMessage: !wwanSwitchButton.checked && wwanSwitchButton.visible - readonly property var displayplaneModeMessage: planeModeSwitchButton.checked && planeModeSwitchButton.visible - -diff --git a/applet/metadata.json b/applet/metadata.json -index 0ca36a2b7..2f12891b5 100644 ---- a/applet/metadata.json -+++ b/applet/metadata.json -@@ -210,6 +210,5 @@ - "X-KDE-Keywords[zh_CN]": "network,internet,ethernet,wireless,wifi,wlan,vpn,wangluo,hulianwang,yitaiwang,juyuwang,wuxianwangluo,xunizhuanyongwangluo,网络,互联网,以太网,局域网,无线网络,虚拟专用网络", - "X-KDE-Keywords[zh_TW]": "網路,網絡,網際網路,乙太網路,以太網路,無線", - "X-Plasma-API-Minimum-Version": "6.0", -- "X-Plasma-DBusActivationService": "org.freedesktop.NetworkManager", - "X-Plasma-NotificationAreaCategory": "Hardware" - } -diff --git a/libs/networkstatus.h b/libs/networkstatus.h -index aa88bf7c5..a885f04dd 100644 ---- a/libs/networkstatus.h -+++ b/libs/networkstatus.h -@@ -59,6 +59,7 @@ public: - QString activeConnections() const; - QString networkStatus() const; - NetworkManager::Connectivity connectivity() const; -+ Q_INVOKABLE QString checkUnknownReason() const; - - private Q_SLOTS: - void activeConnectionsChanged(); -@@ -75,8 +76,6 @@ private: - QString m_activeConnections; - QString m_networkStatus; - NetworkManager::Connectivity m_connectivity = NetworkManager::UnknownConnectivity; -- -- QString checkUnknownReason() const; - }; - - #endif // PLAMA_NM_NETWORK_STATUS_H --- -GitLab - - -From a45534cd9c19f267075fe4261087045f1f3a9318 Mon Sep 17 00:00:00 2001 -From: Nate Graham -Date: Wed, 11 Jun 2025 10:14:40 -0600 -Subject: [PATCH 2/2] Rephrase "NetworkManager not running" message to be more - user-friendly - ---- - libs/networkstatus.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libs/networkstatus.cpp b/libs/networkstatus.cpp -index c89ca9fca..b778eedda 100644 ---- a/libs/networkstatus.cpp -+++ b/libs/networkstatus.cpp -@@ -253,7 +253,7 @@ QString NetworkStatus::checkUnknownReason() const - { - // Check if NetworkManager is running. - if (!QDBusConnection::systemBus().interface()->isServiceRegistered(QStringLiteral(NM_DBUS_INTERFACE))) { -- return i18n("NetworkManager not running"); -+ return i18nc("@info:status", "NetworkManager service is not running"); - } - - // Check for compatible NetworkManager version. --- -GitLab - diff --git a/roles/kde/patches/plasma-nm/pr442.patch b/roles/kde/patches/plasma-nm/pr442.patch deleted file mode 100644 index cd6dda6..0000000 --- a/roles/kde/patches/plasma-nm/pr442.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 63a9d544dc4f5160f28e5f3203a2c0a5e639e5ac Mon Sep 17 00:00:00 2001 -From: Nate Graham -Date: Fri, 13 Jun 2025 12:24:22 -0600 -Subject: [PATCH] applet: use standard section headers - -We have them, so we might as well use them. This lets us get rid of a -bunch of complex and fragile code that's responsible for the existing -separator. ---- - applet/contents/ui/ConnectionItem.qml | 14 ----- - applet/contents/ui/ConnectionListPage.qml | 10 ++-- - applet/contents/ui/ListItem.qml | 64 ----------------------- - libs/models/networkmodelitem.cpp | 8 ++- - 4 files changed, 12 insertions(+), 84 deletions(-) - delete mode 100644 applet/contents/ui/ListItem.qml - -diff --git a/applet/contents/ui/ConnectionItem.qml b/applet/contents/ui/ConnectionItem.qml -index ed154e633..5bb5c530c 100644 ---- a/applet/contents/ui/ConnectionItem.qml -+++ b/applet/contents/ui/ConnectionItem.qml -@@ -321,20 +321,6 @@ PlasmaExtras.ExpandableListItem { - } - } - -- onDeactivatedChanged: { -- /* Separator is part of section, which is visible only when available connections exist. Need to determine -- if there is a connection in use, to show Separator. Otherwise need to hide it from the top of the list. -- Connections in use are always on top, only need to check the first one. */ -- if (appletProxyModel.data(appletProxyModel.index(0, 0), PlasmaNM.NetworkModel.SectionRole) !== "Available connections") { -- if (connectionView.showSeparator != true) { -- connectionView.showSeparator = true -- } -- return -- } -- connectionView.showSeparator = false -- return -- } -- - onItemCollapsed: { - connectionItem.customExpandedViewContent = detailsComponent; - setDelayModelUpdates(false); -diff --git a/applet/contents/ui/ConnectionListPage.qml b/applet/contents/ui/ConnectionListPage.qml -index b62da252c..d8ebd2c54 100644 ---- a/applet/contents/ui/ConnectionListPage.qml -+++ b/applet/contents/ui/ConnectionListPage.qml -@@ -8,7 +8,7 @@ import QtQuick 2.15 - import QtQuick.Layouts 1.2 - import org.kde.plasma.components 3.0 as PlasmaComponents3 - import org.kde.kirigami 2.20 as Kirigami --import org.kde.plasma.extras 2.0 as PlasmaExtras -+import org.kde.plasma.extras as PlasmaExtras - import org.kde.plasma.networkmanagement as PlasmaNM - import org.kde.networkmanager as NMQt - -@@ -55,7 +55,6 @@ ColumnLayout { - id: connectionView - - property int currentVisibleButtonIndex: -1 -- property bool showSeparator: false - - Keys.onDownPressed: event => { - connectionView.incrementCurrentIndex(); -@@ -80,9 +79,10 @@ ColumnLayout { - model: appletProxyModel - currentIndex: -1 - boundsBehavior: Flickable.StopAtBounds -- section.property: showSeparator ? "Section" : "" -- section.delegate: ListItem { -- separator: true -+ section.property: "Section" -+ section.delegate: PlasmaExtras.ListSectionHeader { -+ width: connectionView.width - connectionView.leftMargin - connectionView.rightMargin -+ text: section - } - highlight: PlasmaExtras.Highlight { } - highlightMoveDuration: Kirigami.Units.shortDuration -diff --git a/applet/contents/ui/ListItem.qml b/applet/contents/ui/ListItem.qml -deleted file mode 100644 -index bfe1390d1..000000000 ---- a/applet/contents/ui/ListItem.qml -+++ /dev/null -@@ -1,64 +0,0 @@ --/* -- SPDX-FileCopyrightText: 2010 Marco Martin -- SPDX-FileCopyrightText: 2016 Jan Grulich -- SPDX-FileCopyrightText: 2020 George Vogiatzis -- -- SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL --*/ -- --import QtQuick 2.1 --import org.kde.kirigami 2.20 as Kirigami --import org.kde.ksvg 1.0 as KSvg -- --/** -- * Ignores the theme's listItem margins, and uses custom highlight(pressed) area. -- * Could break some themes but the majority look fine. -- * Also includes a separator to be used in sections. -- */ --MouseArea { -- id: listItem -- -- property bool checked: false -- property bool separator: false -- property rect highlightRect: Qt.rect(0, 0, width, height) -- -- width: parent.width -- -- // Sections have spacing above but not below. Will use 2 of them below. -- height: separator ? separatorLine.height + Kirigami.Units.smallSpacing * 3 : parent.height -- hoverEnabled: true -- -- KSvg.SvgItem { -- id: separatorLine -- anchors { -- horizontalCenter: parent.horizontalCenter -- top: parent.top -- topMargin: Kirigami.Units.smallSpacing -- } -- imagePath: "widgets/line" -- elementId: "horizontal-line" -- width: parent.width - Kirigami.Units.gridUnit * 2 -- visible: listItem.separator -- } -- -- KSvg.FrameSvgItem { -- id: background -- imagePath: "widgets/listitem" -- prefix: "normal" -- anchors.fill: parent -- visible: listItem.separator ? false : true -- } -- -- KSvg.FrameSvgItem { -- id: pressed -- imagePath: "widgets/listitem" -- prefix: "pressed" -- opacity: listItem.checked ? 1 : 0 -- Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } } -- -- x: listItem.highlightRect.x -- y: listItem.highlightRect.y -- height: listItem.highlightRect.height -- width: listItem.highlightRect.width -- } --} -diff --git a/libs/models/networkmodelitem.cpp b/libs/models/networkmodelitem.cpp -index b92ec0df2..4d7cbd77d 100644 ---- a/libs/models/networkmodelitem.cpp -+++ b/libs/models/networkmodelitem.cpp -@@ -344,7 +344,13 @@ QString NetworkModelItem::originalName() const - QString NetworkModelItem::sectionType() const - { - if (m_connectionState == NetworkManager::ActiveConnection::Deactivated) { -- return QStringLiteral("Available connections"); -+ return i18nc("@title:column header for list of available network connections", "Available"); -+ // clang-format off -+ } else if (m_connectionState == NetworkManager::ActiveConnection::Activating -+ || m_connectionState == NetworkManager::ActiveConnection::Activated -+ || m_connectionState == NetworkManager::ActiveConnection::Deactivating) { -+ // clang-format on -+ return i18nc("@title:column header for list of connected network connections", "Connected"); - } else { - return {}; - } --- -GitLab - diff --git a/roles/kde/patches/plasma-workspace/commit8202ba92.patch b/roles/kde/patches/plasma-workspace/commit8202ba92.patch deleted file mode 100644 index cb5fb13..0000000 --- a/roles/kde/patches/plasma-workspace/commit8202ba92.patch +++ /dev/null @@ -1,248 +0,0 @@ -From 8202ba92b610c691b8bc6bab8ad5a1c3b9ac73da Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Wed, 25 Jun 2025 17:29:19 +0300 -Subject: [PATCH] startkde: Drop ready stage - -In order to hide the splash screen, it is sufficient just to see the -wallpaper. If more desktop environment components are loaded soon -afterwards, it is okay. - -With systemd boot, the way the ready stage is integrated is also kind -of a hack. ---- - appiumtests/CMakeLists.txt | 1 - - appiumtests/ksplash/CMakeLists.txt | 14 ---- - appiumtests/ksplash/ksplashtest.py | 79 ------------------- - ksplash/ksplashqml/splashapp.cpp | 5 +- - startkde/plasma-session/startup.cpp | 11 --- - startkde/plasma-session/startup.h | 1 - - startkde/systemd/CMakeLists.txt | 3 - - .../systemd/plasma-ksplash-ready.service.in | 10 --- - startkde/systemd/plasma-workspace.target | 1 - - 9 files changed, 2 insertions(+), 123 deletions(-) - delete mode 100644 appiumtests/ksplash/CMakeLists.txt - delete mode 100755 appiumtests/ksplash/ksplashtest.py - delete mode 100644 startkde/systemd/plasma-ksplash-ready.service.in - -diff --git a/appiumtests/CMakeLists.txt b/appiumtests/CMakeLists.txt -index 68d0b6895ba..22234aeb031 100644 ---- a/appiumtests/CMakeLists.txt -+++ b/appiumtests/CMakeLists.txt -@@ -20,5 +20,4 @@ add_subdirectory(applets) - add_subdirectory(components_tests) - add_subdirectory(kcms) - add_subdirectory(krunner) --add_subdirectory(ksplash) - add_subdirectory(wallpapers) -diff --git a/appiumtests/ksplash/CMakeLists.txt b/appiumtests/ksplash/CMakeLists.txt -deleted file mode 100644 -index 3bea5174f5a..00000000000 ---- a/appiumtests/ksplash/CMakeLists.txt -+++ /dev/null -@@ -1,14 +0,0 @@ --# SPDX-FileCopyrightText: 2024 Fushan Wen --# SPDX-License-Identifier: BSD-3-Clause -- --add_test( -- NAME ksplashtest_wayland -- COMMAND sh -c "mkdir -p /tmp/appium/ksplashtest_wayland;dbus-launch selenium-webdriver-at-spi-run ${CMAKE_CURRENT_SOURCE_DIR}/ksplashtest.py --failfast" --) --set_tests_properties(ksplashtest_wayland PROPERTIES TIMEOUT 60 ENVIRONMENT "XDG_RUNTIME_DIR=/tmp/appium/ksplashtest_wayland;FLASK_PORT=5701") -- --add_test( -- NAME ksplashtest_x11 -- COMMAND sh -c "mkdir -p /tmp/appium/ksplashtest_x11;dbus-launch selenium-webdriver-at-spi-run ${CMAKE_CURRENT_SOURCE_DIR}/ksplashtest.py --failfast" --) --set_tests_properties(ksplashtest_x11 PROPERTIES TIMEOUT 60 ENVIRONMENT "XDG_RUNTIME_DIR=/tmp/appium/ksplashtest_x11;FLASK_PORT=5702;TEST_WITH_KWIN_WAYLAND=0") -diff --git a/appiumtests/ksplash/ksplashtest.py b/appiumtests/ksplash/ksplashtest.py -deleted file mode 100755 -index b7ca43c0519..00000000000 ---- a/appiumtests/ksplash/ksplashtest.py -+++ /dev/null -@@ -1,79 +0,0 @@ --#!/usr/bin/env python3 -- --# SPDX-FileCopyrightText: 2024 Fushan Wen --# SPDX-License-Identifier: MIT -- --# pylint: disable=too-many-arguments -- --import os --import subprocess --import sys --import time --import unittest -- --from appium import webdriver --from appium.options.common.base import AppiumOptions --from appium.webdriver.common.appiumby import AppiumBy --from gi.repository import Gio, GLib -- -- --class KSplashTest(unittest.TestCase): -- -- driver: webdriver.Remote -- -- @classmethod -- def setUpClass(cls) -> None: -- options = AppiumOptions() -- options.set_capability("app", "ksplashqml --window") -- options.set_capability("environ", { -- "LC_ALL": "en_US.UTF-8", -- "QT_FATAL_WARNINGS": "1", -- "QT_LOGGING_RULES": "qt.accessibility.atspi.warning=false;kf.plasma.core.warning=false;kf.windowsystem.warning=false;kf.kirigami.platform.warning=false;org.kde.plasma.ksplashqml.debug=true", -- }) -- options.set_capability("timeouts", {'implicit': 10000}) -- cls.driver = webdriver.Remote(command_executor=f'http://127.0.0.1:{os.getenv("FLASK_PORT", "4723")}', options=options) -- -- def tearDown(self) -> None: -- """ -- Take screenshot when the current test fails -- """ -- if not self._outcome.result.wasSuccessful(): -- self.driver.get_screenshot_as_file(f"failed_test_shot_ksplash_#{self.id()}.png") -- -- def test_1_bug494840_setStage(self) -> None: -- """ -- Checks if the setStage method is ever called after starting plasma-ksplash-ready.service. -- """ -- if os.getenv("TEST_WITH_KWIN_WAYLAND", "1") == "0": -- stages = ("wm", "kcminit", "ksmserver", "startPlasma", "desktop") -- else: -- stages = ("kcminit", "ksmserver", "startPlasma", "desktop") -- -- session_bus = Gio.bus_get_sync(Gio.BusType.SESSION) -- for stage in stages: -- message: Gio.DBusMessage = Gio.DBusMessage.new_method_call("org.kde.KSplash", "/KSplash", "org.kde.KSplash", "setStage") -- message.set_body(GLib.Variant("(s)", [stage])) -- session_bus.send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE, 3000) -- -- self.driver.find_element(AppiumBy.NAME, "Plasma made by KDE") -- -- with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir, "startkde", "systemd", "plasma-ksplash-ready.service.in"), encoding="utf-8") as handler: -- for line in handler: -- if line.startswith("ExecStart="): -- command = line.removeprefix("ExecStart=").strip().split(" ") -- subprocess.check_call(command, stdout=sys.stderr, stderr=sys.stderr) -- break -- -- success = False -- for _ in range(10): -- try: -- subprocess.check_call(["pidof", "ksplashqml"]) -- except subprocess.CalledProcessError: -- success = True -- break -- time.sleep(1) -- self.assertTrue(success) -- -- --if __name__ == '__main__': -- unittest.main() -diff --git a/ksplash/ksplashqml/splashapp.cpp b/ksplash/ksplashqml/splashapp.cpp -index b60a58724be..2262503b1c3 100644 ---- a/ksplash/ksplashqml/splashapp.cpp -+++ b/ksplash/ksplashqml/splashapp.cpp -@@ -26,13 +26,12 @@ - #define TEST_STEP_INTERVAL 2000 - - /** -- * There are 7 stages in ksplash -+ * There are 6 stages in ksplash - * - initial (from this class) - * - startPlasma (from startplasma) - * - kcminit - * - ksmserver - * - wm (for X11 from KWin, for Wayland from this class) -- * - ready (from plasma-session startup) - * - desktop (from shellcorona) - */ - -@@ -114,7 +113,7 @@ void SplashApp::setStage(const QString &stage) - void SplashApp::setStage(int stage) - { - m_stage = stage; -- if (m_stage == 7) { -+ if (m_stage == 6) { - QGuiApplication::exit(EXIT_SUCCESS); - } - for (SplashWindow *w : std::as_const(m_windows)) { -diff --git a/startkde/plasma-session/startup.cpp b/startkde/plasma-session/startup.cpp -index a731c7b2791..0567e00881f 100644 ---- a/startkde/plasma-session/startup.cpp -+++ b/startkde/plasma-session/startup.cpp -@@ -206,20 +206,9 @@ Startup::Startup(QObject *parent) - // app will be closed when all KJobs finish thanks to the QEventLoopLocker in each KJob - } - --void Startup::upAndRunning(const QString &msg) --{ -- QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"), -- QStringLiteral("/KSplash"), -- QStringLiteral("org.kde.KSplash"), -- QStringLiteral("setStage")); -- ksplashProgressMessage.setArguments(QList() << msg); -- QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage); --} -- - void Startup::finishStartup() - { - qCDebug(PLASMA_SESSION) << "Finished"; -- upAndRunning(QStringLiteral("ready")); - - playStartupSound(); - new SessionTrack(m_processes); -diff --git a/startkde/plasma-session/startup.h b/startkde/plasma-session/startup.h -index 6ef4fee9bdd..876a1439fce 100644 ---- a/startkde/plasma-session/startup.h -+++ b/startkde/plasma-session/startup.h -@@ -20,7 +20,6 @@ class Startup : public QObject - Q_OBJECT - public: - Startup(QObject *parent); -- void upAndRunning(const QString &msg); - void finishStartup(); - - static Startup *self() -diff --git a/startkde/systemd/CMakeLists.txt b/startkde/systemd/CMakeLists.txt -index 2f5d30e8456..c3455ebae81 100644 ---- a/startkde/systemd/CMakeLists.txt -+++ b/startkde/systemd/CMakeLists.txt -@@ -1,6 +1,3 @@ --ecm_install_configured_files(INPUT plasma-ksplash-ready.service.in @ONLY -- DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR}) -- - install(FILES plasma-core.target DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR}) - install(FILES plasma-workspace.target DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR}) - install(FILES plasma-workspace-wayland.target DESTINATION ${KDE_INSTALL_SYSTEMDUSERUNITDIR}) -diff --git a/startkde/systemd/plasma-ksplash-ready.service.in b/startkde/systemd/plasma-ksplash-ready.service.in -deleted file mode 100644 -index 1e903130a96..00000000000 ---- a/startkde/systemd/plasma-ksplash-ready.service.in -+++ /dev/null -@@ -1,10 +0,0 @@ --[Unit] --Description=KSplash "ready" Stage --Wants=plasma-core.target --After=plasma-core.target --PartOf=graphical-session.target -- --[Service] --Type=oneshot --ExecStart=dbus-send --session --reply-timeout=1 --type=method_call --dest=org.kde.KSplash /KSplash org.kde.KSplash.setStage string:ready --Slice=session.slice -diff --git a/startkde/systemd/plasma-workspace.target b/startkde/systemd/plasma-workspace.target -index a9113f49112..4cc8d9330c3 100644 ---- a/startkde/systemd/plasma-workspace.target -+++ b/startkde/systemd/plasma-workspace.target -@@ -6,7 +6,6 @@ Wants=plasma-restoresession.service - Wants=plasma-xembedsniproxy.service - Wants=plasma-gmenudbusmenuproxy.service - Wants=plasma-powerdevil.service --Wants=plasma-ksplash-ready.service - Wants=plasma-polkit-agent.service - Wants=kde-baloo.service - Wants=plasma-foreground-booster.service --- -GitLab - diff --git a/roles/kde/patches/plasma-workspace/patches.txt b/roles/kde/patches/plasma-workspace/patches.txt index 49de017..3e0146f 100644 --- a/roles/kde/patches/plasma-workspace/patches.txt +++ b/roles/kde/patches/plasma-workspace/patches.txt @@ -1,21 +1,3 @@ -Plasma 6.5.0: - -Pr 5589 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5589 -Pr 5626 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5626 -Pr 5627 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5627 -Commit 8202ba92 https://invent.kde.org/plasma/plasma-workspace/-/commit/8202ba92b610c691b8bc6bab8ad5a1c3b9ac73da - Part of https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5628, the other part got cherry picked on 6.4.2 -Pr 5657 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5657 -Pr 5734 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5734 - Depends on Pr 5609 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5609 -Pr 5746 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5746 -Pr 5782 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5782 -Pr 5678 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5678 - Depends on Pr 5673 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5673 -Pr 5788 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5788 - Allows compiling on gcc 14 after applying pr 5678 - Plasma 6.6.0: -Pr 5818 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5818 Pr 5816 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5816 diff --git a/roles/kde/patches/plasma-workspace/pr5589.patch b/roles/kde/patches/plasma-workspace/pr5589.patch deleted file mode 100644 index b305b9f..0000000 --- a/roles/kde/patches/plasma-workspace/pr5589.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 2278398309c68ce401a8e35b193fca3782391a4a Mon Sep 17 00:00:00 2001 -From: Nate Graham -Date: Thu, 12 Jun 2025 09:15:15 -0600 -Subject: [PATCH] applets/devicenotifier: use standard section header - -No need for a custom header here when we have a standard one. - -CCBUG: 442724 ---- - .../package/contents/ui/FullRepresentation.qml | 10 ++-------- - 1 file changed, 2 insertions(+), 8 deletions(-) - -diff --git a/applets/devicenotifier/package/contents/ui/FullRepresentation.qml b/applets/devicenotifier/package/contents/ui/FullRepresentation.qml -index 967223e0a1a..a0c28df45fe 100644 ---- a/applets/devicenotifier/package/contents/ui/FullRepresentation.qml -+++ b/applets/devicenotifier/package/contents/ui/FullRepresentation.qml -@@ -132,15 +132,9 @@ PlasmaExtras.Representation { - - section { - property: "deviceType" -- delegate: Item { -- height: Math.floor(childrenRect.height) -+ delegate: PlasmaExtras.ListSectionHeader { - width: notifierDialog.width - (scrollView.PlasmaComponents3.ScrollBar.vertical.visible ? Kirigami.Units.largeSpacing * 2 : 0) -- Kirigami.Heading { -- level: 3 -- opacity: 0.6 -- text: section -- textFormat: Text.PlainText -- } -+ text: section - } - } - --- -GitLab - diff --git a/roles/kde/patches/plasma-workspace/pr5609.patch b/roles/kde/patches/plasma-workspace/pr5609.patch deleted file mode 100644 index 74c9d39..0000000 --- a/roles/kde/patches/plasma-workspace/pr5609.patch +++ /dev/null @@ -1,456 +0,0 @@ -From 439b251bcb3ea24f52c052e7244fb7ced04503aa Mon Sep 17 00:00:00 2001 -From: Bohdan Onofriichuk -Date: Thu, 19 Jun 2025 14:51:30 +0000 -Subject: [PATCH] applets/devicenotifier: port to plasma_add_applet - ---- - applets/devicenotifier/CMakeLists.txt | 58 ++++++++++++++++--- - .../{plugin => }/actioninterface.cpp | 0 - .../{plugin => }/actioninterface.h | 0 - .../{plugin => }/actions/defaultaction.cpp | 0 - .../{plugin => }/actions/defaultaction.h | 0 - .../{plugin => }/actions/mountaction.cpp | 0 - .../{plugin => }/actions/mountaction.h | 0 - .../actions/mountandopenaction.cpp | 0 - .../{plugin => }/actions/mountandopenaction.h | 0 - .../actions/openwithfilemanageraction.cpp | 0 - .../actions/openwithfilemanageraction.h | 0 - .../{plugin => }/actions/unmountaction.cpp | 0 - .../{plugin => }/actions/unmountaction.h | 0 - .../{plugin => }/actionscontrol.cpp | 0 - .../{plugin => }/actionscontrol.h | 0 - .../{plugin => }/devicecontrol.cpp | 0 - .../{plugin => }/devicecontrol.h | 0 - .../{plugin => }/deviceerrormonitor_p.cpp | 0 - .../{plugin => }/deviceerrormonitor_p.h | 0 - .../{plugin => }/devicefiltercontrol.cpp | 0 - .../{plugin => }/devicefiltercontrol.h | 0 - .../{plugin => }/devicenotifications.notifyrc | 0 - .../{plugin => }/deviceserviceaction.cpp | 0 - .../{plugin => }/deviceserviceaction.h | 0 - .../{plugin => }/devicestatemonitor_p.cpp | 0 - .../{plugin => }/devicestatemonitor_p.h | 0 - .../{package/contents/config => }/main.xml | 0 - .../{package => }/metadata.json | 1 - - applets/devicenotifier/plugin/CMakeLists.txt | 51 ---------------- - .../{plugin => }/predicatesmonitor_p.cpp | 0 - .../{plugin => }/predicatesmonitor_p.h | 0 - .../contents/ui => qml}/DeviceItem.qml | 22 ++++--- - .../ui => qml}/FullRepresentation.qml | 0 - .../{package/contents/ui => qml}/main.qml | 9 ++- - .../{plugin => }/spacemonitor_p.cpp | 0 - .../{plugin => }/spacemonitor_p.h | 0 - 36 files changed, 65 insertions(+), 76 deletions(-) - rename applets/devicenotifier/{plugin => }/actioninterface.cpp (100%) - rename applets/devicenotifier/{plugin => }/actioninterface.h (100%) - rename applets/devicenotifier/{plugin => }/actions/defaultaction.cpp (100%) - rename applets/devicenotifier/{plugin => }/actions/defaultaction.h (100%) - rename applets/devicenotifier/{plugin => }/actions/mountaction.cpp (100%) - rename applets/devicenotifier/{plugin => }/actions/mountaction.h (100%) - rename applets/devicenotifier/{plugin => }/actions/mountandopenaction.cpp (100%) - rename applets/devicenotifier/{plugin => }/actions/mountandopenaction.h (100%) - rename applets/devicenotifier/{plugin => }/actions/openwithfilemanageraction.cpp (100%) - rename applets/devicenotifier/{plugin => }/actions/openwithfilemanageraction.h (100%) - rename applets/devicenotifier/{plugin => }/actions/unmountaction.cpp (100%) - rename applets/devicenotifier/{plugin => }/actions/unmountaction.h (100%) - rename applets/devicenotifier/{plugin => }/actionscontrol.cpp (100%) - rename applets/devicenotifier/{plugin => }/actionscontrol.h (100%) - rename applets/devicenotifier/{plugin => }/devicecontrol.cpp (100%) - rename applets/devicenotifier/{plugin => }/devicecontrol.h (100%) - rename applets/devicenotifier/{plugin => }/deviceerrormonitor_p.cpp (100%) - rename applets/devicenotifier/{plugin => }/deviceerrormonitor_p.h (100%) - rename applets/devicenotifier/{plugin => }/devicefiltercontrol.cpp (100%) - rename applets/devicenotifier/{plugin => }/devicefiltercontrol.h (100%) - rename applets/devicenotifier/{plugin => }/devicenotifications.notifyrc (100%) - rename applets/devicenotifier/{plugin => }/deviceserviceaction.cpp (100%) - rename applets/devicenotifier/{plugin => }/deviceserviceaction.h (100%) - rename applets/devicenotifier/{plugin => }/devicestatemonitor_p.cpp (100%) - rename applets/devicenotifier/{plugin => }/devicestatemonitor_p.h (100%) - rename applets/devicenotifier/{package/contents/config => }/main.xml (100%) - rename applets/devicenotifier/{package => }/metadata.json (99%) - delete mode 100644 applets/devicenotifier/plugin/CMakeLists.txt - rename applets/devicenotifier/{plugin => }/predicatesmonitor_p.cpp (100%) - rename applets/devicenotifier/{plugin => }/predicatesmonitor_p.h (100%) - rename applets/devicenotifier/{package/contents/ui => qml}/DeviceItem.qml (81%) - rename applets/devicenotifier/{package/contents/ui => qml}/FullRepresentation.qml (100%) - rename applets/devicenotifier/{package/contents/ui => qml}/main.qml (96%) - rename applets/devicenotifier/{plugin => }/spacemonitor_p.cpp (100%) - rename applets/devicenotifier/{plugin => }/spacemonitor_p.h (100%) - -diff --git a/applets/devicenotifier/CMakeLists.txt b/applets/devicenotifier/CMakeLists.txt -index bde4a38dd30..f336db13a69 100644 ---- a/applets/devicenotifier/CMakeLists.txt -+++ b/applets/devicenotifier/CMakeLists.txt -@@ -1,11 +1,55 @@ --add_subdirectory(plugin) -+# SPDX-FileCopyrightText: 2024 Fushan Wen -+# SPDX-License-Identifier: BSD-3-Clause - --ecm_qt_install_logging_categories( -- EXPORT APPLETS::DEVICENOTIFIER -- FILE applets/devicenotifier.categories -- DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR} -+add_definitions(-DTRANSLATION_DOMAIN=\"plasma_applet_org.kde.plasma.devicenotifier\") -+ -+plasma_add_applet(org.kde.plasma.devicenotifier -+ QML_SOURCES -+ qml/DeviceItem.qml -+ qml/FullRepresentation.qml -+ qml/main.qml -+ CPP_SOURCES -+ actionscontrol.cpp -+ devicecontrol.cpp -+ spacemonitor_p.cpp -+ devicestatemonitor_p.cpp -+ deviceserviceaction.cpp -+ predicatesmonitor_p.cpp -+ deviceerrormonitor_p.cpp -+ actioninterface.cpp -+ devicefiltercontrol.cpp -+ actions/defaultaction.cpp -+ actions/mountandopenaction.cpp -+ actions/mountaction.cpp -+ actions/unmountaction.cpp -+ actions/openwithfilemanageraction.cpp -+ RESOURCES -+ main.xml -+ GENERATE_APPLET_CLASS -+) -+ -+target_link_libraries(org.kde.plasma.devicenotifier -+ PRIVATE -+ Qt::Qml -+ Plasma::Plasma -+ KF6::Solid -+ KF6::I18n -+ KF6::CoreAddons -+ KF6::Service -+ KF6::KIOCore -+ KF6::KIOGui # KIO::CommandLauncherJob -+ KF6::JobWidgets # KNotificationJobUiDelegate -+ KSysGuard::ProcessCore -+ KF6::Notifications - ) - --plasma_install_package(package org.kde.plasma.devicenotifier) -+ecm_qt_declare_logging_category(org.kde.plasma.devicenotifier -+ HEADER "devicenotifier_debug.h" -+ IDENTIFIER "APPLETS::DEVICENOTIFIER" -+ CATEGORY_NAME org.kde.applets.devicenotifier -+ DEFAULT_SEVERITY Warning -+ DESCRIPTION "Device Notifier applet" EXPORT "APPLETS::DEVICENOTIFIER" -+) - --install(FILES openWithFileManager.desktop DESTINATION ${KDE_INSTALL_DATADIR}/solid/actions ) -+install(FILES devicenotifications.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR}) -+install(FILES openWithFileManager.desktop DESTINATION ${KDE_INSTALL_DATADIR}/solid/actions) -diff --git a/applets/devicenotifier/plugin/actioninterface.cpp b/applets/devicenotifier/actioninterface.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/actioninterface.cpp -rename to applets/devicenotifier/actioninterface.cpp -diff --git a/applets/devicenotifier/plugin/actioninterface.h b/applets/devicenotifier/actioninterface.h -similarity index 100% -rename from applets/devicenotifier/plugin/actioninterface.h -rename to applets/devicenotifier/actioninterface.h -diff --git a/applets/devicenotifier/plugin/actions/defaultaction.cpp b/applets/devicenotifier/actions/defaultaction.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/actions/defaultaction.cpp -rename to applets/devicenotifier/actions/defaultaction.cpp -diff --git a/applets/devicenotifier/plugin/actions/defaultaction.h b/applets/devicenotifier/actions/defaultaction.h -similarity index 100% -rename from applets/devicenotifier/plugin/actions/defaultaction.h -rename to applets/devicenotifier/actions/defaultaction.h -diff --git a/applets/devicenotifier/plugin/actions/mountaction.cpp b/applets/devicenotifier/actions/mountaction.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/actions/mountaction.cpp -rename to applets/devicenotifier/actions/mountaction.cpp -diff --git a/applets/devicenotifier/plugin/actions/mountaction.h b/applets/devicenotifier/actions/mountaction.h -similarity index 100% -rename from applets/devicenotifier/plugin/actions/mountaction.h -rename to applets/devicenotifier/actions/mountaction.h -diff --git a/applets/devicenotifier/plugin/actions/mountandopenaction.cpp b/applets/devicenotifier/actions/mountandopenaction.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/actions/mountandopenaction.cpp -rename to applets/devicenotifier/actions/mountandopenaction.cpp -diff --git a/applets/devicenotifier/plugin/actions/mountandopenaction.h b/applets/devicenotifier/actions/mountandopenaction.h -similarity index 100% -rename from applets/devicenotifier/plugin/actions/mountandopenaction.h -rename to applets/devicenotifier/actions/mountandopenaction.h -diff --git a/applets/devicenotifier/plugin/actions/openwithfilemanageraction.cpp b/applets/devicenotifier/actions/openwithfilemanageraction.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/actions/openwithfilemanageraction.cpp -rename to applets/devicenotifier/actions/openwithfilemanageraction.cpp -diff --git a/applets/devicenotifier/plugin/actions/openwithfilemanageraction.h b/applets/devicenotifier/actions/openwithfilemanageraction.h -similarity index 100% -rename from applets/devicenotifier/plugin/actions/openwithfilemanageraction.h -rename to applets/devicenotifier/actions/openwithfilemanageraction.h -diff --git a/applets/devicenotifier/plugin/actions/unmountaction.cpp b/applets/devicenotifier/actions/unmountaction.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/actions/unmountaction.cpp -rename to applets/devicenotifier/actions/unmountaction.cpp -diff --git a/applets/devicenotifier/plugin/actions/unmountaction.h b/applets/devicenotifier/actions/unmountaction.h -similarity index 100% -rename from applets/devicenotifier/plugin/actions/unmountaction.h -rename to applets/devicenotifier/actions/unmountaction.h -diff --git a/applets/devicenotifier/plugin/actionscontrol.cpp b/applets/devicenotifier/actionscontrol.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/actionscontrol.cpp -rename to applets/devicenotifier/actionscontrol.cpp -diff --git a/applets/devicenotifier/plugin/actionscontrol.h b/applets/devicenotifier/actionscontrol.h -similarity index 100% -rename from applets/devicenotifier/plugin/actionscontrol.h -rename to applets/devicenotifier/actionscontrol.h -diff --git a/applets/devicenotifier/plugin/devicecontrol.cpp b/applets/devicenotifier/devicecontrol.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/devicecontrol.cpp -rename to applets/devicenotifier/devicecontrol.cpp -diff --git a/applets/devicenotifier/plugin/devicecontrol.h b/applets/devicenotifier/devicecontrol.h -similarity index 100% -rename from applets/devicenotifier/plugin/devicecontrol.h -rename to applets/devicenotifier/devicecontrol.h -diff --git a/applets/devicenotifier/plugin/deviceerrormonitor_p.cpp b/applets/devicenotifier/deviceerrormonitor_p.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/deviceerrormonitor_p.cpp -rename to applets/devicenotifier/deviceerrormonitor_p.cpp -diff --git a/applets/devicenotifier/plugin/deviceerrormonitor_p.h b/applets/devicenotifier/deviceerrormonitor_p.h -similarity index 100% -rename from applets/devicenotifier/plugin/deviceerrormonitor_p.h -rename to applets/devicenotifier/deviceerrormonitor_p.h -diff --git a/applets/devicenotifier/plugin/devicefiltercontrol.cpp b/applets/devicenotifier/devicefiltercontrol.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/devicefiltercontrol.cpp -rename to applets/devicenotifier/devicefiltercontrol.cpp -diff --git a/applets/devicenotifier/plugin/devicefiltercontrol.h b/applets/devicenotifier/devicefiltercontrol.h -similarity index 100% -rename from applets/devicenotifier/plugin/devicefiltercontrol.h -rename to applets/devicenotifier/devicefiltercontrol.h -diff --git a/applets/devicenotifier/plugin/devicenotifications.notifyrc b/applets/devicenotifier/devicenotifications.notifyrc -similarity index 100% -rename from applets/devicenotifier/plugin/devicenotifications.notifyrc -rename to applets/devicenotifier/devicenotifications.notifyrc -diff --git a/applets/devicenotifier/plugin/deviceserviceaction.cpp b/applets/devicenotifier/deviceserviceaction.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/deviceserviceaction.cpp -rename to applets/devicenotifier/deviceserviceaction.cpp -diff --git a/applets/devicenotifier/plugin/deviceserviceaction.h b/applets/devicenotifier/deviceserviceaction.h -similarity index 100% -rename from applets/devicenotifier/plugin/deviceserviceaction.h -rename to applets/devicenotifier/deviceserviceaction.h -diff --git a/applets/devicenotifier/plugin/devicestatemonitor_p.cpp b/applets/devicenotifier/devicestatemonitor_p.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/devicestatemonitor_p.cpp -rename to applets/devicenotifier/devicestatemonitor_p.cpp -diff --git a/applets/devicenotifier/plugin/devicestatemonitor_p.h b/applets/devicenotifier/devicestatemonitor_p.h -similarity index 100% -rename from applets/devicenotifier/plugin/devicestatemonitor_p.h -rename to applets/devicenotifier/devicestatemonitor_p.h -diff --git a/applets/devicenotifier/package/contents/config/main.xml b/applets/devicenotifier/main.xml -similarity index 100% -rename from applets/devicenotifier/package/contents/config/main.xml -rename to applets/devicenotifier/main.xml -diff --git a/applets/devicenotifier/package/metadata.json b/applets/devicenotifier/metadata.json -similarity index 99% -rename from applets/devicenotifier/package/metadata.json -rename to applets/devicenotifier/metadata.json -index 0a330dfc189..77d7feac1cb 100644 ---- a/applets/devicenotifier/package/metadata.json -+++ b/applets/devicenotifier/metadata.json -@@ -115,7 +115,6 @@ - "desktop" - ], - "Icon": "device-notifier", -- "Id": "org.kde.plasma.devicenotifier", - "License": "GPL-2.0+", - "Name": "Disks & Devices", - "Name[ar]": "الأجهزة والأقراص", -diff --git a/applets/devicenotifier/plugin/CMakeLists.txt b/applets/devicenotifier/plugin/CMakeLists.txt -deleted file mode 100644 -index 34a3456d690..00000000000 ---- a/applets/devicenotifier/plugin/CMakeLists.txt -+++ /dev/null -@@ -1,51 +0,0 @@ --# SPDX-FileCopyrightText: 2024 Fushan Wen --# SPDX-License-Identifier: BSD-3-Clause -- --add_definitions(-DTRANSLATION_DOMAIN=\"plasma_applet_org.kde.plasma.devicenotifier\") -- --ecm_add_qml_module(devicenotifierplugin URI org.kde.plasma.private.devicenotifier GENERATE_PLUGIN_SOURCE) -- --target_sources(devicenotifierplugin -- PRIVATE -- actionscontrol.cpp actionscontrol.h -- devicecontrol.cpp devicecontrol.h -- spacemonitor_p.cpp spacemonitor_p.h -- devicestatemonitor_p.cpp devicestatemonitor_p.h -- deviceserviceaction.cpp deviceserviceaction.h -- predicatesmonitor_p.cpp predicatesmonitor_p.h -- deviceerrormonitor_p.cpp deviceerrormonitor_p.h -- actioninterface.cpp actioninterface.h -- devicefiltercontrol.cpp devicefiltercontrol.h -- actions/defaultaction.cpp actions/defaultaction.h -- actions/mountandopenaction.cpp actions/mountandopenaction.h -- actions/mountaction.cpp actions/mountaction.h -- actions/unmountaction.cpp actions/unmountaction.h -- actions/openwithfilemanageraction.cpp actions/openwithfilemanageraction.h --) -- --target_link_libraries(devicenotifierplugin -- PRIVATE -- Qt::Qml -- Plasma::Plasma -- KF6::Solid -- KF6::I18n -- KF6::CoreAddons -- KF6::Service -- KF6::KIOCore -- KF6::KIOGui # KIO::CommandLauncherJob -- KF6::JobWidgets # KNotificationJobUiDelegate -- KSysGuard::ProcessCore -- KF6::Notifications --) -- --ecm_qt_declare_logging_category(devicenotifierplugin -- HEADER "devicenotifier_debug.h" -- IDENTIFIER "APPLETS::DEVICENOTIFIER" -- CATEGORY_NAME org.kde.applets.devicenotifier -- DEFAULT_SEVERITY Warning -- DESCRIPTION "Device Notifier applet" EXPORT "APPLETS::DEVICENOTIFIER" --) -- --ecm_finalize_qml_module(devicenotifierplugin) -- --install(FILES devicenotifications.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR}) -diff --git a/applets/devicenotifier/plugin/predicatesmonitor_p.cpp b/applets/devicenotifier/predicatesmonitor_p.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/predicatesmonitor_p.cpp -rename to applets/devicenotifier/predicatesmonitor_p.cpp -diff --git a/applets/devicenotifier/plugin/predicatesmonitor_p.h b/applets/devicenotifier/predicatesmonitor_p.h -similarity index 100% -rename from applets/devicenotifier/plugin/predicatesmonitor_p.h -rename to applets/devicenotifier/predicatesmonitor_p.h -diff --git a/applets/devicenotifier/package/contents/ui/DeviceItem.qml b/applets/devicenotifier/qml/DeviceItem.qml -similarity index 81% -rename from applets/devicenotifier/package/contents/ui/DeviceItem.qml -rename to applets/devicenotifier/qml/DeviceItem.qml -index c19c9535b04..861996af45c 100644 ---- a/applets/devicenotifier/package/contents/ui/DeviceItem.qml -+++ b/applets/devicenotifier/qml/DeviceItem.qml -@@ -19,8 +19,6 @@ import org.kde.kirigami as Kirigami - - import org.kde.kquickcontrolsaddons - --import org.kde.plasma.private.devicenotifier as DN -- - PlasmaExtras.ExpandableListItem { - id: deviceItem - -@@ -41,18 +39,18 @@ PlasmaExtras.ExpandableListItem { - - property bool hasMessage: deviceItem.deviceErrorMessage !== "" - -- property bool isFree: deviceItem.deviceOperationResult !== DN.DevicesStateMonitor.Working && deviceItem.deviceOperationResult !== DN.DevicesStateMonitor.Checking && deviceItem.deviceOperationResult !== DN.DevicesStateMonitor.Repairing && deviceItem.deviceOperationResult !== DN.DevicesStateMonitor.NotPresent && !(deviceItem.deviceMounted === false && deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Successful) -+ property bool isFree: deviceItem.deviceOperationResult !== DevicesStateMonitor.Working && deviceItem.deviceOperationResult !== DevicesStateMonitor.Checking && deviceItem.deviceOperationResult !== DevicesStateMonitor.Repairing && deviceItem.deviceOperationResult !== DevicesStateMonitor.NotPresent && !(deviceItem.deviceMounted === false && deviceItem.deviceOperationResult === DevicesStateMonitor.Successful) - - onDeviceOperationResultChanged: { - if (!popupIconTimer.running) { -- if (deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Working) { -+ if (deviceItem.deviceOperationResult === DevicesStateMonitor.Working) { - if(deviceMounted){ - unmountTimer.restart(); - } -- } else if (deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Successful) { -+ } else if (deviceItem.deviceOperationResult === DevicesStateMonitor.Successful) { - devicenotifier.popupIcon = "dialog-ok" - popupIconTimer.restart() -- } else if (deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Unsuccessful) { -+ } else if (deviceItem.deviceOperationResult === DevicesStateMonitor.Unsuccessful) { - devicenotifier.popupIcon = "dialog-error" - popupIconTimer.restart() - } -@@ -80,7 +78,7 @@ PlasmaExtras.ExpandableListItem { - } else { - return "emblem-error" - } -- } else if (deviceItem.deviceOperationResult !== DN.DevicesStateMonitor.Working && deviceItem.deviceEmblems[0]) { -+ } else if (deviceItem.deviceOperationResult !== DevicesStateMonitor.Working && deviceItem.deviceEmblems[0]) { - return deviceItem.deviceEmblems[0] - } else { - return "" -@@ -93,16 +91,16 @@ PlasmaExtras.ExpandableListItem { - if (deviceItem.hasMessage) { - return deviceItem.deviceErrorMessage - } -- if (deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Checking) { -+ if (deviceItem.deviceOperationResult === DevicesStateMonitor.Checking) { - return i18nc("Accessing is a less technical word for Mounting; translation should be short and mean \'Currently mounting this device\'", "Checking…") -- } else if (deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Repairing) { -+ } else if (deviceItem.deviceOperationResult === DevicesStateMonitor.Repairing) { - return i18nc("Accessing is a less technical word for Mounting; translation should be short and mean \'Currently mounting this device\'", "Repairing…") -- } else if (deviceItem.deviceOperationResult !== DN.DevicesStateMonitor.Working) { -+ } else if (deviceItem.deviceOperationResult !== DevicesStateMonitor.Working) { - if (deviceItem.deviceFreeSpace > 0 && deviceItem.deviceSize > 0) { - return i18nc("@info:status Free disk space", "%1 free of %2", deviceItem.deviceFreeSpaceText, deviceItem.deviceSizeText) - } - return "" -- } else if (!deviceItem.deviceMounted && deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Working) { -+ } else if (!deviceItem.deviceMounted && deviceItem.deviceOperationResult === DevicesStateMonitor.Working) { - return i18nc("Accessing is a less technical word for Mounting; translation should be short and mean \'Currently mounting this device\'", "Accessing…") - } else if (unmountTimer.running) { - // Unmounting; shown if unmount takes less than 1 second -@@ -139,7 +137,7 @@ PlasmaExtras.ExpandableListItem { - } - } - -- isBusy: deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Working || deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Checking || deviceItem.deviceOperationResult === DN.DevicesStateMonitor.Repairing -+ isBusy: deviceItem.deviceOperationResult === DevicesStateMonitor.Working || deviceItem.deviceOperationResult === DevicesStateMonitor.Checking || deviceItem.deviceOperationResult === DevicesStateMonitor.Repairing - - customExpandedViewContent: deviceActions !== undefined && deviceActions.rowCount() !== 0 && isFree ? actionComponent : null - -diff --git a/applets/devicenotifier/package/contents/ui/FullRepresentation.qml b/applets/devicenotifier/qml/FullRepresentation.qml -similarity index 100% -rename from applets/devicenotifier/package/contents/ui/FullRepresentation.qml -rename to applets/devicenotifier/qml/FullRepresentation.qml -diff --git a/applets/devicenotifier/package/contents/ui/main.qml b/applets/devicenotifier/qml/main.qml -similarity index 96% -rename from applets/devicenotifier/package/contents/ui/main.qml -rename to applets/devicenotifier/qml/main.qml -index 4061480becc..7fcd76a6d16 100644 ---- a/applets/devicenotifier/package/contents/ui/main.qml -+++ b/applets/devicenotifier/qml/main.qml -@@ -15,21 +15,20 @@ import org.kde.kirigami as Kirigami - - import org.kde.kcmutils // For KCMLauncher - import org.kde.config // KAuthorized --import org.kde.plasma.private.devicenotifier as DN - - PlasmoidItem { - id: devicenotifier - -- DN.DeviceFilterControl { -+ DeviceFilterControl { - id: filterModel - - filterType: { - if (Plasmoid.configuration.allDevices) { -- return DN.DeviceFilterControl.All -+ return DeviceFilterControl.All - } else if (Plasmoid.configuration.removableDevices) { -- return DN.DeviceFilterControl.Removable -+ return DeviceFilterControl.Removable - } else { -- return DN.DeviceFilterControl.Unremovable -+ return DeviceFilterControl.Unremovable - } - } - -diff --git a/applets/devicenotifier/plugin/spacemonitor_p.cpp b/applets/devicenotifier/spacemonitor_p.cpp -similarity index 100% -rename from applets/devicenotifier/plugin/spacemonitor_p.cpp -rename to applets/devicenotifier/spacemonitor_p.cpp -diff --git a/applets/devicenotifier/plugin/spacemonitor_p.h b/applets/devicenotifier/spacemonitor_p.h -similarity index 100% -rename from applets/devicenotifier/plugin/spacemonitor_p.h -rename to applets/devicenotifier/spacemonitor_p.h --- -GitLab - diff --git a/roles/kde/patches/plasma-workspace/pr5626.patch b/roles/kde/patches/plasma-workspace/pr5626.patch deleted file mode 100644 index 6ad487f..0000000 --- a/roles/kde/patches/plasma-workspace/pr5626.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 9fabf42c39a25308739dd3483881cc889243bf58 Mon Sep 17 00:00:00 2001 -From: Kristen McWilliam -Date: Tue, 24 Jun 2025 17:44:33 -0400 -Subject: [PATCH] applets/notifications: Add actions to missed notifications - notification - -When a notification is displayed informing the user that notifications were missed while in Do Not -Disturb, now clicking the button or the notification itself will open the notifications applet to -show the missed notifications. - -BUG: 502423 ---- - .../package/contents/ui/main.qml | 10 ++++++ - libnotificationmanager/notifications.cpp | 34 ++++++++++++++----- - libnotificationmanager/notifications.h | 7 ++++ - 3 files changed, 42 insertions(+), 9 deletions(-) - -diff --git a/applets/notifications/package/contents/ui/main.qml b/applets/notifications/package/contents/ui/main.qml -index c96afa0558d..ab66a52f45e 100644 ---- a/applets/notifications/package/contents/ui/main.qml -+++ b/applets/notifications/package/contents/ui/main.qml -@@ -268,4 +268,14 @@ PlasmoidItem { - Component.onDestruction: { - Globals.forget(root); - } -+ -+ Connections { -+ target: Globals.popupNotificationsModel -+ -+ // The user requested to show the notifications popup, probably by -+ // clicking the "Missed Notifications in Do Not Disturb" notification. -+ function onShowNotificationsRequested(): void { -+ root.expanded = true; -+ } -+ } - } -diff --git a/libnotificationmanager/notifications.cpp b/libnotificationmanager/notifications.cpp -index 2cba1360b10..7b5cd9d68c4 100644 ---- a/libnotificationmanager/notifications.cpp -+++ b/libnotificationmanager/notifications.cpp -@@ -903,15 +903,31 @@ void Notifications::showInhibitionSummary(Urgency urgency, const QStringList &bl - return; - } - -- KNotification::event(u"inhibitionSummary"_s, -- i18ncp("@title", "Unread Notification", "Unread Notifications", inhibited), -- i18ncp("@info", -- "%1 notification was received while Do Not Disturb was active.", -- "%1 notifications were received while Do Not Disturb was active.", -- inhibited), -- u"preferences-desktop-notification-bell"_s, -- KNotification::CloseOnTimeout, -- u"libnotificationmanager"_s); -+ KNotification *notification = new KNotification(u"inhibitionSummary"_s); -+ notification->setTitle(i18ncp("@title", "Unread Notification", "Unread Notifications", inhibited)); -+ notification->setText(i18ncp("@info", -+ "%1 notification was received while Do Not Disturb was active.", -+ "%1 notifications were received while Do Not Disturb was active.", -+ inhibited)); -+ notification->setIconName(u"preferences-desktop-notification-bell"_s); -+ notification->setFlags(KNotification::CloseOnTimeout); -+ notification->setComponentName(u"libnotificationmanager"_s); -+ -+ const QString showNotificationsText = i18nc( // -+ "@action:button Show the notifications popup; translate this in as short a form as possible", -+ "Show Notifications"); -+ -+ const KNotificationAction *defaultShowNotificationsAction = notification->addDefaultAction(showNotificationsText); -+ connect(defaultShowNotificationsAction, &KNotificationAction::activated, this, [this]() { -+ Q_EMIT showNotificationsRequested(); -+ }); -+ -+ const KNotificationAction *showNotificationsAction = notification->addAction(showNotificationsText); -+ connect(showNotificationsAction, &KNotificationAction::activated, this, [this]() { -+ Q_EMIT showNotificationsRequested(); -+ }); -+ -+ notification->sendEvent(); - } - - QVariant Notifications::data(const QModelIndex &index, int role) const -diff --git a/libnotificationmanager/notifications.h b/libnotificationmanager/notifications.h -index e927c472c8f..8544b6271ae 100644 ---- a/libnotificationmanager/notifications.h -+++ b/libnotificationmanager/notifications.h -@@ -597,6 +597,13 @@ Q_SIGNALS: - void jobsPercentageChanged(); - void windowChanged(QWindow *window); - -+ /** -+ * Emitted when the user has requested to show the notifications popup. -+ * -+ * This is typically connected to a button in the "Missed Notifications in Do Not Disturb" notification. -+ */ -+ void showNotificationsRequested(); -+ - protected: - void classBegin() override; - void componentComplete() override; --- -GitLab - diff --git a/roles/kde/patches/plasma-workspace/pr5627.patch b/roles/kde/patches/plasma-workspace/pr5627.patch deleted file mode 100644 index dc61149..0000000 --- a/roles/kde/patches/plasma-workspace/pr5627.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 1641ea3897d565d672e29a7524ce4171ddbcfd32 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Wed, 25 Jun 2025 14:00:05 +0300 -Subject: [PATCH 1/2] shell: Set desktop ksplash stage when all desktop views - are ready - -If there are two outputs and the wallpaper for the first one is ready -but for the second one is not, the ksplash will be notified about the -desktop stage. - -This changes fixes checkAllDesktopsUiReady() so it sets the desktop -stage only if all desktop views are ready. ---- - shell/shellcorona.cpp | 28 +++++++++++++++------------- - shell/shellcorona.h | 2 +- - 2 files changed, 16 insertions(+), 14 deletions(-) - -diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp -index 37d93d05353..65c8ccc272e 100644 ---- a/shell/shellcorona.cpp -+++ b/shell/shellcorona.cpp -@@ -1338,6 +1338,8 @@ void ShellCorona::removeDesktop(DesktopView *desktopView) - - desktopView->destroy(); - desktopView->containment()->reactToScreenChange(); -+ -+ checkAllDesktopsUiReady(); - } - - PanelView *ShellCorona::panelView(Plasma::Containment *containment) const -@@ -1529,22 +1531,22 @@ void ShellCorona::addOutput(QScreen *screen) - #endif - } - --void ShellCorona::checkAllDesktopsUiReady(bool ready) -+void ShellCorona::checkAllDesktopsUiReady() - { -- if (!ready) -+ const bool ready = std::ranges::all_of(std::as_const(m_desktopViewForScreen), [](const DesktopView *view) { -+ return view->containment()->isUiReady(); -+ }); -+ if (!ready) { - return; -- for (auto v : std::as_const(m_desktopViewForScreen)) { -- if (!v->containment()->isUiReady()) -- return; -- -- qCDebug(PLASMASHELL) << "Plasma Shell startup completed"; -- QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"), -- QStringLiteral("/KSplash"), -- QStringLiteral("org.kde.KSplash"), -- QStringLiteral("setStage")); -- ksplashProgressMessage.setArguments(QList() << QStringLiteral("desktop")); -- QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage); - } -+ -+ qCDebug(PLASMASHELL) << "Plasma Shell startup completed"; -+ QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"), -+ QStringLiteral("/KSplash"), -+ QStringLiteral("org.kde.KSplash"), -+ QStringLiteral("setStage")); -+ ksplashProgressMessage.setArguments(QList() << QStringLiteral("desktop")); -+ QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage); - } - - Plasma::Containment *ShellCorona::createContainmentForActivity(const QString &activity, int screenNum) -diff --git a/shell/shellcorona.h b/shell/shellcorona.h -index 0f544ca266f..7b6c6a559a1 100644 ---- a/shell/shellcorona.h -+++ b/shell/shellcorona.h -@@ -275,7 +275,7 @@ private: - DesktopView *desktopForScreen(QScreen *screen) const; - void setupWaylandIntegration(); - void executeSetupPlasmoidScript(Plasma::Containment *containment, Plasma::Applet *applet); -- void checkAllDesktopsUiReady(bool ready); -+ void checkAllDesktopsUiReady(); - void activateLauncherMenu(const QString &screenName); - void handleColorRequestedFromDBus(const QDBusMessage &msg); - --- -GitLab - - -From 00bd19ecaccbb10d5cfcc6006b06a9714c615741 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Wed, 25 Jun 2025 14:03:28 +0300 -Subject: [PATCH 2/2] shell: Create panel views after desktop views are ready - -With the current code, the splash screen will be hidden as soon as the -wallpapers are loaded. - -However, the splash screnn is actually notified about the desktop stage -about 1-1.5 second later after the wallpaper plugin resets the loading -property. - -The reason for that is that the panel is loaded between -`wallpaper.loading = false` in the wallpaper and ShellCorona::checkAllDesktopsUiReady(). - -This change re-arranges the startup sequence so the panels are loaded -after the desktop views become ready. It reduces plasma startup time a bit. - -In long term, we should look for making panel loading as async as -possible so the main thread doesn't get blocked for too long. ---- - shell/shellcorona.cpp | 15 +++++---------- - 1 file changed, 5 insertions(+), 10 deletions(-) - -diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp -index 65c8ccc272e..6a59683dba7 100644 ---- a/shell/shellcorona.cpp -+++ b/shell/shellcorona.cpp -@@ -868,10 +868,6 @@ void ShellCorona::load() - connect(m_screenPool, &ScreenPool::screenOrderChanged, this, &ShellCorona::handleScreenOrderChanged, Qt::UniqueConnection); - connect(m_screenPool, &ScreenPool::screenRemoved, this, &ShellCorona::handleScreenRemoved, Qt::UniqueConnection); - -- if (!m_waitingPanels.isEmpty()) { -- m_waitingPanelsTimer.start(); -- } -- - if (config()->isImmutable() || !KAuthorized::authorize(QStringLiteral("plasma/plasmashell/unlockedDesktop"))) { - setImmutability(Plasma::Types::SystemImmutable); - } else { -@@ -1517,11 +1513,6 @@ void ShellCorona::addOutput(QScreen *screen) - // in the list. We still don't want to have an invisible view added. - containment->reactToScreenChange(); - -- // were there any panels for this screen before it popped up? -- if (!m_waitingPanels.isEmpty()) { -- m_waitingPanelsTimer.start(); -- } -- - if (!m_screenReorderInProgress) { - Q_EMIT availableScreenRectChanged(m_screenPool->idForScreen(screen)); - } -@@ -1547,6 +1538,10 @@ void ShellCorona::checkAllDesktopsUiReady() - QStringLiteral("setStage")); - ksplashProgressMessage.setArguments(QList() << QStringLiteral("desktop")); - QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage); -+ -+ if (!m_waitingPanels.isEmpty()) { -+ m_waitingPanelsTimer.start(); -+ } - } - - Plasma::Containment *ShellCorona::createContainmentForActivity(const QString &activity, int screenNum) -@@ -1604,7 +1599,7 @@ void ShellCorona::createWaitingPanels() - - QScreen *screen = m_screenPool->screenForId(requestedScreen); - DesktopView *desktopView = desktopForScreen(screen); -- if (!screen || !desktopView) { -+ if (!screen || !desktopView || !desktopView->containment()->isUiReady()) { - stillWaitingPanels << cont; - continue; - } --- -GitLab - diff --git a/roles/kde/patches/plasma-workspace/pr5657.patch b/roles/kde/patches/plasma-workspace/pr5657.patch deleted file mode 100644 index 71620a0..0000000 --- a/roles/kde/patches/plasma-workspace/pr5657.patch +++ /dev/null @@ -1,177 +0,0 @@ -From aa1e466e5f7684a8b624c34d466dda9d10a331d2 Mon Sep 17 00:00:00 2001 -From: Nate Graham -Date: Sun, 6 Jul 2025 23:20:47 -0400 -Subject: [PATCH 1/2] Improve UX of USB plug/unplug notifications when popup is - shown - -1. When plugged or unplugged, revoke the opposite notification if it's - visible. -2. Set the urgency to low so it won't clutter up the notification - history. ---- - devicenotifications/devicenotifications.cpp | 55 ++++++++++++++++----- - devicenotifications/devicenotifications.h | 5 ++ - 2 files changed, 48 insertions(+), 12 deletions(-) - -diff --git a/devicenotifications/devicenotifications.cpp b/devicenotifications/devicenotifications.cpp -index cc462f58f5..f326691c11 100644 ---- a/devicenotifications/devicenotifications.cpp -+++ b/devicenotifications/devicenotifications.cpp -@@ -15,6 +15,7 @@ - - #include - -+#include - #include - - K_PLUGIN_CLASS_WITH_JSON(KdedDeviceNotifications, "devicenotifications.json") -@@ -375,13 +376,28 @@ void KdedDeviceNotifications::onDeviceAdded(const UdevDevice &device) - return; - } - -- const QString text = !displayName.isEmpty() ? i18n("%1 has been plugged in.", displayName.toHtmlEscaped()) : i18n("A USB device has been plugged in."); -+ // If the user unplugged something and then immediately plugged it in again, -+ // there's no need to keep the unplug notification around. -+ if (m_usbDeviceRemovedNotification) { -+ m_usbDeviceRemovedNotification->close(); -+ } -+ -+ // Only show one of these at a time. We already suppressed creating a bunch -+ // in quick succession for the dock/hub use case, so any that are created -+ // over that time limit anyway are not necessary to stack up. -+ if (m_usbDeviceAddedNotification) { -+ m_usbDeviceAddedNotification->close(); -+ } -+ -+ const QString text = !displayName.isEmpty() ? i18n("%1 has been connected.", displayName.toHtmlEscaped()) : i18n("A USB device has been connected."); -+ -+ m_usbDeviceAddedNotification = new KNotification(QStringLiteral("deviceAdded")); -+ m_usbDeviceAddedNotification->setFlags(KNotification::DefaultEvent); -+ m_usbDeviceAddedNotification->setIconName(QStringLiteral("drive-removable-media-usb")); -+ m_usbDeviceAddedNotification->setTitle(i18nc("@title:notifications", "USB Device Detected")); -+ m_usbDeviceAddedNotification->setText(text); -+ m_usbDeviceAddedNotification->sendEvent(); - -- KNotification::event(QStringLiteral("deviceAdded"), -- i18nc("@title:notifications", "USB Device Detected"), -- text, -- QStringLiteral("drive-removable-media-usb"), -- KNotification::DefaultEvent); - m_deviceAddedTimer.start(); - } - -@@ -401,13 +417,28 @@ void KdedDeviceNotifications::onDeviceRemoved(const UdevDevice &device) - return; - } - -- const QString text = !displayName.isEmpty() ? i18n("%1 has been unplugged.", displayName.toHtmlEscaped()) : i18n("A USB device has been unplugged."); -+ // If the user plugged something in and then immediately unplugged it again, -+ // there's no need to keep the plug notification around. -+ if (m_usbDeviceAddedNotification) { -+ m_usbDeviceAddedNotification->close(); -+ } -+ -+ // Only show one of these at a time. We already suppressed removing a bunch -+ // in quick succession for the dock/hub use case, so any that are removed -+ // over that time limit anyway are not necessary to stack up. -+ if (m_usbDeviceRemovedNotification) { -+ m_usbDeviceRemovedNotification->close(); -+ } -+ -+ const QString text = !displayName.isEmpty() ? i18n("%1 has been disconnected.", displayName.toHtmlEscaped()) : i18n("A USB device has been disconnected."); -+ -+ m_usbDeviceRemovedNotification = new KNotification(QStringLiteral("deviceRemoved")); -+ m_usbDeviceRemovedNotification->setFlags(KNotification::DefaultEvent); -+ m_usbDeviceRemovedNotification->setIconName(QStringLiteral("drive-removable-media-usb")); -+ m_usbDeviceRemovedNotification->setTitle(i18nc("@title:notifications", "USB Device Went Away")); -+ m_usbDeviceRemovedNotification->setText(text); -+ m_usbDeviceRemovedNotification->sendEvent(); - -- KNotification::event(QStringLiteral("deviceRemoved"), -- i18nc("@title:notifications", "USB Device Removed"), -- text, -- QStringLiteral("drive-removable-media-usb"), -- KNotification::DefaultEvent); - m_deviceRemovedTimer.start(); - } - -diff --git a/devicenotifications/devicenotifications.h b/devicenotifications/devicenotifications.h -index 11334008b0..ab7e6b3ff9 100644 ---- a/devicenotifications/devicenotifications.h -+++ b/devicenotifications/devicenotifications.h -@@ -8,11 +8,13 @@ - - #include - #include -+#include - #include - #include - #include - - #include -+#include - - #include - -@@ -98,4 +100,7 @@ private: - - QTimer m_deviceAddedTimer; - QTimer m_deviceRemovedTimer; -+ -+ QPointer m_usbDeviceAddedNotification; -+ QPointer m_usbDeviceRemovedNotification; - }; --- -2.51.0 - - -From 05f72383fd0b29105f3b5494759500d26b38ffc2 Mon Sep 17 00:00:00 2001 -From: Nate Graham -Date: Fri, 11 Jul 2025 11:25:23 -0600 -Subject: [PATCH 2/2] Delete closed notifications too - -Closing is async; make sure we actually delete them when we want them -gone. ---- - devicenotifications/devicenotifications.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/devicenotifications/devicenotifications.cpp b/devicenotifications/devicenotifications.cpp -index f326691c11..987d65d805 100644 ---- a/devicenotifications/devicenotifications.cpp -+++ b/devicenotifications/devicenotifications.cpp -@@ -380,6 +380,7 @@ void KdedDeviceNotifications::onDeviceAdded(const UdevDevice &device) - // there's no need to keep the unplug notification around. - if (m_usbDeviceRemovedNotification) { - m_usbDeviceRemovedNotification->close(); -+ m_usbDeviceRemovedNotification = nullptr; - } - - // Only show one of these at a time. We already suppressed creating a bunch -@@ -387,6 +388,7 @@ void KdedDeviceNotifications::onDeviceAdded(const UdevDevice &device) - // over that time limit anyway are not necessary to stack up. - if (m_usbDeviceAddedNotification) { - m_usbDeviceAddedNotification->close(); -+ m_usbDeviceAddedNotification = nullptr; - } - - const QString text = !displayName.isEmpty() ? i18n("%1 has been connected.", displayName.toHtmlEscaped()) : i18n("A USB device has been connected."); -@@ -421,6 +423,7 @@ void KdedDeviceNotifications::onDeviceRemoved(const UdevDevice &device) - // there's no need to keep the plug notification around. - if (m_usbDeviceAddedNotification) { - m_usbDeviceAddedNotification->close(); -+ m_usbDeviceAddedNotification = nullptr; - } - - // Only show one of these at a time. We already suppressed removing a bunch -@@ -428,6 +431,7 @@ void KdedDeviceNotifications::onDeviceRemoved(const UdevDevice &device) - // over that time limit anyway are not necessary to stack up. - if (m_usbDeviceRemovedNotification) { - m_usbDeviceRemovedNotification->close(); -+ m_usbDeviceRemovedNotification = nullptr; - } - - const QString text = !displayName.isEmpty() ? i18n("%1 has been disconnected.", displayName.toHtmlEscaped()) : i18n("A USB device has been disconnected."); --- -2.51.0 - diff --git a/roles/kde/patches/plasma-workspace/pr5673.patch b/roles/kde/patches/plasma-workspace/pr5673.patch deleted file mode 100644 index c78dca1..0000000 --- a/roles/kde/patches/plasma-workspace/pr5673.patch +++ /dev/null @@ -1,392 +0,0 @@ -From 97c77a8e3259d77cb615dadd1c92185545513ebb Mon Sep 17 00:00:00 2001 -From: Harald Sitter -Date: Sun, 13 Jul 2025 16:06:08 +0200 -Subject: [PATCH 1/7] servicerunner: en_US spelling please - ---- - runners/services/servicerunner.cpp | 14 +++++++------- - runners/services/servicerunner.h | 4 ++-- - 2 files changed, 9 insertions(+), 9 deletions(-) - -diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp -index 454cf4e99f..357558a77d 100644 ---- a/runners/services/servicerunner.cpp -+++ b/runners/services/servicerunner.cpp -@@ -296,7 +296,7 @@ private: - relevance += .09; - } - -- if (const auto foundIt = m_runner->m_favourites.constFind(service->desktopEntryName()); foundIt != m_runner->m_favourites.cend()) { -+ if (const auto foundIt = m_runner->m_favorites.constFind(service->desktopEntryName()); foundIt != m_runner->m_favorites.cend()) { - if (foundIt->isGlobal || foundIt->linkedActivities.contains(m_currentActivity)) { - qCDebug(RUNNER_SERVICES) << "entry is a favorite" << id << match.subtext() << relevance; - relevance *= 1.25; // Give favorites a relative boost, -@@ -423,7 +423,7 @@ ServiceRunner::ServiceRunner(QObject *parent, const KPluginMetaData &metaData) - }); - - connect(&m_kactivitiesWatcher, &ResultWatcher::resultUnlinked, [this](QString resource) { -- m_favourites.remove(resource.remove(".desktop"_L1)); -+ m_favorites.remove(resource.remove(".desktop"_L1)); - // In case it was only unlinked from one activity - processActivitiesResults(ResultSet(m_kactivitiesQuery | Terms::Url::contains(resource))); - }); -@@ -466,11 +466,11 @@ void ServiceRunner::processActivitiesResults(const ResultSet &results) - const static QLatin1String applicationScheme("applications"); - for (const ResultSet::Result &result : results) { - if (result.url().scheme() == applicationScheme) { -- m_favourites.insert(result.url().path().remove(QLatin1String(".desktop")), -- ActivityFavourite{ -- result.linkedActivities(), -- result.linkedActivities().contains(globalActivity), -- }); -+ m_favorites.insert(result.url().path().remove(QLatin1String(".desktop")), -+ ActivityFavorite{ -+ result.linkedActivities(), -+ result.linkedActivities().contains(globalActivity), -+ }); - } - } - } -diff --git a/runners/services/servicerunner.h b/runners/services/servicerunner.h -index e0507ea459..571d22d90c 100644 ---- a/runners/services/servicerunner.h -+++ b/runners/services/servicerunner.h -@@ -33,11 +33,11 @@ public: - void run(const KRunner::RunnerContext &context, const KRunner::QueryMatch &match) override; - void init() override; - -- struct ActivityFavourite { -+ struct ActivityFavorite { - QStringList linkedActivities; - bool isGlobal; - }; -- QMap m_favourites; -+ QMap m_favorites; - - protected: - void setupMatch(const KService::Ptr &service, KRunner::QueryMatch &action); --- -2.51.0 - - -From 537d0cf67d600cb40636f9aaef7db6957f002eb2 Mon Sep 17 00:00:00 2001 -From: Harald Sitter -Date: Sun, 13 Jul 2025 16:06:50 +0200 -Subject: [PATCH 2/7] servicerunner: use designated initializers - -makes code easier to read ---- - runners/services/servicerunner.cpp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp -index 357558a77d..2cade45b26 100644 ---- a/runners/services/servicerunner.cpp -+++ b/runners/services/servicerunner.cpp -@@ -468,8 +468,8 @@ void ServiceRunner::processActivitiesResults(const ResultSet &results) - if (result.url().scheme() == applicationScheme) { - m_favorites.insert(result.url().path().remove(QLatin1String(".desktop")), - ActivityFavorite{ -- result.linkedActivities(), -- result.linkedActivities().contains(globalActivity), -+ .linkedActivities = result.linkedActivities(), -+ .isGlobal = result.linkedActivities().contains(globalActivity), - }); - } - } --- -2.51.0 - - -From 2c5eb156410c022a50a5b6e08a6abc454dd49b83 Mon Sep 17 00:00:00 2001 -From: Harald Sitter -Date: Sun, 13 Jul 2025 16:09:37 +0200 -Subject: [PATCH 3/7] servicerunner: use ranges algorithms - -makes for nicer to read code ---- - runners/services/servicerunner.cpp | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp -index 2cade45b26..87b38a2da3 100644 ---- a/runners/services/servicerunner.cpp -+++ b/runners/services/servicerunner.cpp -@@ -46,15 +46,15 @@ int weightedLength(const QString &query) - - inline bool contains(const QString &result, const QList &queryList) - { -- return std::all_of(queryList.cbegin(), queryList.cend(), [&result](QStringView query) { -+ return std::ranges::all_of(queryList, [&result](QStringView query) { - return result.contains(query, Qt::CaseInsensitive); - }); - } - - inline bool contains(const QStringList &results, const QList &queryList) - { -- return std::all_of(queryList.cbegin(), queryList.cend(), [&results](QStringView query) { -- return std::any_of(results.cbegin(), results.cend(), [&query](QStringView result) { -+ return std::ranges::all_of(queryList, [&results](QStringView query) { -+ return std::ranges::any_of(results, [&query](QStringView result) { - return result.contains(query, Qt::CaseInsensitive); - }); - }); -@@ -327,7 +327,7 @@ private: - setupMatch(service, match); - - qreal relevance = 0.4; -- if (std::any_of(categories.begin(), categories.end(), [this](const QString &category) { -+ if (std::ranges::any_of(categories, [this](const QString &category) { - return category.compare(query, Qt::CaseInsensitive) == 0; - })) { - relevance = 0.6; -@@ -499,7 +499,7 @@ void ServiceRunner::run(const KRunner::RunnerContext & /*context*/, const KRunne - job = new KIO::ApplicationLauncherJob(service); - } else { - const auto actions = service->actions(); -- auto it = std::find_if(actions.begin(), actions.end(), [&actionName](const KServiceAction &action) { -+ auto it = std::ranges::find_if(actions, [&actionName](const KServiceAction &action) { - return action.name() == actionName; - }); - Q_ASSERT(it != actions.end()); --- -2.51.0 - - -From 0599abb0af9d1da43d8067dd59b8afad7c7be9c6 Mon Sep 17 00:00:00 2001 -From: Harald Sitter -Date: Sun, 13 Jul 2025 16:11:05 +0200 -Subject: [PATCH 4/7] servicerunner: put helper functions into anon namespace - -they are translation unit local after all ---- - runners/services/servicerunner.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp -index 87b38a2da3..baef7ae50f 100644 ---- a/runners/services/servicerunner.cpp -+++ b/runners/services/servicerunner.cpp -@@ -38,6 +38,8 @@ - #include "debug.h" - - using namespace Qt::StringLiterals; -+namespace -+{ - - int weightedLength(const QString &query) - { -@@ -60,6 +62,8 @@ inline bool contains(const QStringList &results, const QList &query - }); - } - -+} // namespace -+ - /** - * @brief Finds all KServices for a given runner query - */ --- -2.51.0 - - -From 2f81c3ab0520729ed4f97d666b5c74258eed149b Mon Sep 17 00:00:00 2001 -From: Harald Sitter -Date: Sun, 13 Jul 2025 16:12:37 +0200 -Subject: [PATCH 5/7] servicerunner: typos-- - ---- - runners/services/autotests/servicerunnertest.cpp | 4 ++-- - runners/services/servicerunner.cpp | 10 +++++----- - runners/services/servicerunner.h | 2 +- - 3 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/runners/services/autotests/servicerunnertest.cpp b/runners/services/autotests/servicerunnertest.cpp -index ecb8a4816c..fcfd3275ac 100644 ---- a/runners/services/autotests/servicerunnertest.cpp -+++ b/runners/services/autotests/servicerunnertest.cpp -@@ -27,7 +27,7 @@ private Q_SLOTS: - void initTestCase(); - void cleanupTestCase(); - -- void testExcutableExactMatch(); -+ void testExecutableExactMatch(); - void testKonsoleVsYakuakeComment(); - void testSystemSettings(); - void testSystemSettings2(); -@@ -76,7 +76,7 @@ void ServiceRunnerTest::cleanupTestCase() - { - } - --void ServiceRunnerTest::testExcutableExactMatch() -+void ServiceRunnerTest::testExecutableExactMatch() - { - const auto matches = launchQuery(QStringLiteral("Virtual Machine Manager ServiceRunnerTest")); // virt-manager.desktop - QVERIFY(std::any_of(matches.cbegin(), matches.cend(), [](const KRunner::QueryMatch &match) { -diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp -index baef7ae50f..ced1b526ce 100644 ---- a/runners/services/servicerunner.cpp -+++ b/runners/services/servicerunner.cpp -@@ -125,7 +125,7 @@ private: - GenericName, - Comment, - }; -- qreal increaseMatchRelavance(const QString &serviceProperty, const QList &strList, Category category) -+ qreal increaseMatchRelevance(const QString &serviceProperty, const QList &strList, Category category) - { - // Increment the relevance based on all the words (other than the first) of the query list - qreal relevanceIncrement = 0; -@@ -273,20 +273,20 @@ private: - categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Highest; - } else if (const int idx = name.indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { - relevance = 0.8; -- relevance += increaseMatchRelavance(name, queryList, Category::Name); -+ relevance += increaseMatchRelevance(name, queryList, Category::Name); - if (idx == 0) { - relevance += 0.1; - categoryRelevance = KRunner::QueryMatch::CategoryRelevance::High; - } - } else if (const int idx = service->genericName().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { - relevance = 0.65; -- relevance += increaseMatchRelavance(service->genericName(), queryList, Category::GenericName); -+ relevance += increaseMatchRelevance(service->genericName(), queryList, Category::GenericName); - if (idx == 0) { - relevance += 0.05; - } - } else if (const int idx = service->comment().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { - relevance = 0.5; -- relevance += increaseMatchRelavance(service->comment(), queryList, Category::Comment); -+ relevance += increaseMatchRelevance(service->comment(), queryList, Category::Comment); - if (idx == 0) { - relevance += 0.05; - } -@@ -481,7 +481,7 @@ void ServiceRunner::processActivitiesResults(const ResultSet &results) - - void ServiceRunner::match(KRunner::RunnerContext &context) - { -- ServiceFinder finder(this, m_services, m_activitiesConsuer.currentActivity()); -+ ServiceFinder finder(this, m_services, m_activitiesConsumer.currentActivity()); - finder.match(context); - } - -diff --git a/runners/services/servicerunner.h b/runners/services/servicerunner.h -index 571d22d90c..96a110789b 100644 ---- a/runners/services/servicerunner.h -+++ b/runners/services/servicerunner.h -@@ -46,7 +46,7 @@ private: - void processActivitiesResults(const ResultSet &results); - const Query m_kactivitiesQuery; - const ResultWatcher m_kactivitiesWatcher; -- const KActivities::Consumer m_activitiesConsuer; -+ const KActivities::Consumer m_activitiesConsumer; - QList m_services; - bool m_matching = false; - }; --- -2.51.0 - - -From d25a269e9dbf6209ae51f94c298cb1ef640b045c Mon Sep 17 00:00:00 2001 -From: Harald Sitter -Date: Sun, 13 Jul 2025 16:14:53 +0200 -Subject: [PATCH 6/7] servicerunner: don't narrow qsizetype to int - -use auto instead since we don't actually care about their size anyway -since we only perform trivial >=0 checks ---- - runners/services/servicerunner.cpp | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp -index ced1b526ce..551717947f 100644 ---- a/runners/services/servicerunner.cpp -+++ b/runners/services/servicerunner.cpp -@@ -206,7 +206,7 @@ private: - static const auto specialArgs = {QStringLiteral("-qwindowtitle"), QStringLiteral("-qwindowicon"), QStringLiteral("--started-from-file")}; - - for (const auto &specialArg : specialArgs) { -- int index = resultingArgs.indexOf(specialArg); -+ auto index = resultingArgs.indexOf(specialArg); - if (index > -1) { - if (resultingArgs.count() > index) { - resultingArgs.removeAt(index); -@@ -271,20 +271,20 @@ private: - } else if (name.compare(query, Qt::CaseInsensitive) == 0) { - relevance = 1; - categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Highest; -- } else if (const int idx = name.indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { -+ } else if (const auto idx = name.indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { - relevance = 0.8; - relevance += increaseMatchRelevance(name, queryList, Category::Name); - if (idx == 0) { - relevance += 0.1; - categoryRelevance = KRunner::QueryMatch::CategoryRelevance::High; - } -- } else if (const int idx = service->genericName().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { -+ } else if (const auto idx = service->genericName().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { - relevance = 0.65; - relevance += increaseMatchRelevance(service->genericName(), queryList, Category::GenericName); - if (idx == 0) { - relevance += 0.05; - } -- } else if (const int idx = service->comment().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { -+ } else if (const auto idx = service->comment().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { - relevance = 0.5; - relevance += increaseMatchRelevance(service->comment(), queryList, Category::Comment); - if (idx == 0) { -@@ -364,7 +364,7 @@ private: - } - seen(action); - -- const int matchIndex = action.text().indexOf(query, 0, Qt::CaseInsensitive); -+ const auto matchIndex = action.text().indexOf(query, 0, Qt::CaseInsensitive); - if (matchIndex < 0) { - continue; - } --- -2.51.0 - - -From 1a14af41b78a192d10fb5dcef93bba430872eab4 Mon Sep 17 00:00:00 2001 -From: Harald Sitter -Date: Sun, 13 Jul 2025 16:15:55 +0200 -Subject: [PATCH 7/7] servicerunner: remove inline noise - -functions defined inside a definition are always inline ---- - runners/services/servicerunner.cpp | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp -index 551717947f..eb9f02e74b 100644 ---- a/runners/services/servicerunner.cpp -+++ b/runners/services/servicerunner.cpp -@@ -92,22 +92,22 @@ public: - } - - private: -- inline void seen(const KService::Ptr &service) -+ void seen(const KService::Ptr &service) - { - m_seen.insert(service->exec()); - } - -- inline void seen(const KServiceAction &action) -+ void seen(const KServiceAction &action) - { - m_seen.insert(action.exec()); - } - -- inline bool hasSeen(const KService::Ptr &service) -+ bool hasSeen(const KService::Ptr &service) - { - return m_seen.contains(service->exec()); - } - -- inline bool hasSeen(const KServiceAction &action) -+ bool hasSeen(const KServiceAction &action) - { - return m_seen.contains(action.exec()); - } --- -2.51.0 - diff --git a/roles/kde/patches/plasma-workspace/pr5678.9.patch b/roles/kde/patches/plasma-workspace/pr5678.9.patch deleted file mode 100644 index 1c9421a..0000000 --- a/roles/kde/patches/plasma-workspace/pr5678.9.patch +++ /dev/null @@ -1,913 +0,0 @@ -From 312c215e717654e55fa48ec968f412201d2a5544 Mon Sep 17 00:00:00 2001 -From: Harald Sitter -Date: Mon, 14 Jul 2025 17:28:14 +0200 -Subject: [PATCH] servicerunner: fuzzy match - -use a bitap implementation instead of doing awkward contains dances. -this should lead to somewhat more reliable results, which are now more -comprehensively asserted in the unit test - -at the heart of this is a new fuzzyScore function that assigns a score -to a service vis a vis a query. this score is adjusted depending on -which field it is regarding (name > genericname > keywords). -this should hopefully ensure that a match against name outweighs most -other matches. all scores are eventually assembled into a final score -that gets used as match relevance ---- - runners/services/autotests/CMakeLists.txt | 3 + - runners/services/autotests/bitaptest.cpp | 70 +++++ - .../autotests/fixtures/audacity.desktop | 2 +- - .../fixtures/org.kde.discover.desktop | 17 ++ - .../autotests/fixtures/org.kde.kpat.desktop | 2 +- - .../services/autotests/servicerunnertest.cpp | 94 ++++-- - runners/services/bitap.h | 178 +++++++++++ - runners/services/levenshtein.h | 58 ++++ - runners/services/servicerunner.cpp | 286 +++++++++++------- - 9 files changed, 576 insertions(+), 134 deletions(-) - create mode 100644 runners/services/autotests/bitaptest.cpp - create mode 100755 runners/services/autotests/fixtures/org.kde.discover.desktop - create mode 100644 runners/services/bitap.h - create mode 100644 runners/services/levenshtein.h - -diff --git a/runners/services/autotests/CMakeLists.txt b/runners/services/autotests/CMakeLists.txt -index 04849a2928..ff7ec66634 100644 ---- a/runners/services/autotests/CMakeLists.txt -+++ b/runners/services/autotests/CMakeLists.txt -@@ -6,3 +6,6 @@ remove_definitions(-DQT_NO_CAST_FROM_ASCII) - ecm_add_test(servicerunnertest.cpp TEST_NAME servicerunnertest - LINK_LIBRARIES Qt::Test KF6::Service KF6::Runner) - krunner_configure_test(servicerunnertest krunner_services) -+ -+ecm_add_test(bitaptest.cpp TEST_NAME bitaptest -+ LINK_LIBRARIES Qt::Test) -diff --git a/runners/services/autotests/bitaptest.cpp b/runners/services/autotests/bitaptest.cpp -new file mode 100644 -index 0000000000..1a1cb856ec ---- /dev/null -+++ b/runners/services/autotests/bitaptest.cpp -@@ -0,0 +1,70 @@ -+// SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL -+// SPDX-FileCopyrightText: 2025 Harald Sitter -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "../bitap.h" -+ -+class BitapTest : public QObject -+{ -+ Q_OBJECT -+private Q_SLOTS: -+ void initTestCase() -+ { -+ } -+ void cleanupTestCase() -+ { -+ } -+ -+ void testBitap() -+ { -+ using namespace Bitap; -+ // The macro has trouble with designated initializers, so we wrap them in (). -+ QCOMPARE(bitap(u"hello world", u"hello", 1), (Match{.end = 4, .distance = 0})); -+ QCOMPARE(bitap(u"wireshark", u"di", 1), (Match{.end = 1, .distance = 1})); -+ QCOMPARE(bitap(u"discover", u"disk", 1), (Match{.end = 2, .distance = 1})); -+ QCOMPARE(bitap(u"discover", u"disc", 1), (Match{.end = 3, .distance = 0})); -+ QCOMPARE(bitap(u"discover", u"scov", 1), (Match{.end = 5, .distance = 0})); -+ QCOMPARE(bitap(u"discover", u"diki", 1), std::nullopt); -+ QCOMPARE(bitap(u"discover", u"obo", 1), std::nullopt); -+ // With a hamming distance of 1 this may match because it is a single transposition. -+ QCOMPARE(bitap(u"discover", u"dicsover", 1), (Match{.end = 7, .distance = 1})); -+ // … but with three characters out of place things should not match. -+ QCOMPARE(bitap(u"discover", u"dicosver", 1), std::nullopt); -+ // pattern too long -+ QCOMPARE(bitap(u"discover", u" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 1), std::nullopt); -+ // This is not a transposition as per Damerau–Levenshtein distance because the characters are not adjacent. -+ QCOMPARE(bitap(u"steam", u"skeap", 1), std::nullopt); -+ // Deletion required -+ QCOMPARE(bitap(u"discover", u"discover", 1), (Match{.end = 7, .distance = 0})); -+ QCOMPARE(bitap(u"discover", u"discovery", 1), (Match{.end = 7, .distance = 1})); -+ // Insertion required -+ QCOMPARE(bitap(u"discover", u"dicover", 1), (Match{.end = 7, .distance = 1})); -+ } -+ -+ void testScore() -+ { -+ using namespace Bitap; -+ // aperfectten has 10 big beautiful indexes. The maximum end is therefore 10. -+ QCOMPARE(score(u"aperfectten", Match{.end = 10, .distance = 0}, 1), 1.0); -+ QCOMPARE(score(u"aperfectten", Match{.end = 4, .distance = 0}, 1), 0.4); -+ QCOMPARE(score(u"aperfectten", Match{.end = 4, .distance = 1}, 1), 0.35); -+ QCOMPARE(score(u"aperfectten", Match{.end = 0, .distance = 0}, 0), 0); -+ QCOMPARE(score(u"aperfectten", Match{.end = 0, .distance = 0}, 1), 0); -+ QCOMPARE(score(u"aperfectten", Match{.end = 1, .distance = 1}, 1), 0.05); -+ -+ QCOMPARE(score(u"abc", Match{.end = 2, .distance = 1}, 1), 0.95); -+ // Ask for distance 0 but it has a distance so this is a super bad match. -+ QCOMPARE(score(u"abc", Match{.end = 2, .distance = 1}, 0), 0); -+ } -+}; -+ -+QTEST_MAIN(BitapTest) -+ -+#include "bitaptest.moc" -diff --git a/runners/services/autotests/fixtures/audacity.desktop b/runners/services/autotests/fixtures/audacity.desktop -index 7613d9f32f..05e1b9d929 100644 ---- a/runners/services/autotests/fixtures/audacity.desktop -+++ b/runners/services/autotests/fixtures/audacity.desktop -@@ -1,5 +1,5 @@ - [Desktop Entry] --Name=Audacity -+Name=Audacity ServiceRunnerTest - GenericName=Sound Editor - Comment=Record and edit audio files - Keywords=audio;sound;alsa;jack;editor; -diff --git a/runners/services/autotests/fixtures/org.kde.discover.desktop b/runners/services/autotests/fixtures/org.kde.discover.desktop -new file mode 100755 -index 0000000000..978b2b4152 ---- /dev/null -+++ b/runners/services/autotests/fixtures/org.kde.discover.desktop -@@ -0,0 +1,17 @@ -+# SPDX-FileCopyrightText: None -+# SPDX-License-Identifier: CC0-1.0 -+[Desktop Entry] -+Name=Discover ServiceRunnerTest -+Comment=Install and remove apps and add-ons -+MimeType=application/vnd.flatpak;application/vnd.flatpak.repo;application/vnd.flatpak.ref; -+Exec=plasma-discover %F -+Icon=plasmadiscover -+Type=Application -+X-DocPath=plasma-discover/index.html -+InitialPreference=5 -+NoDisplay=false -+Actions=Updates; -+SingleMainWindow=true -+GenericName=Software Center -+Categories=Qt;KDE;System; -+Keywords=program;software;store;repository;package;add;install;uninstall;remove;update;apps;applications;games;flatpak;snap;addons;add-ons;firmware; -diff --git a/runners/services/autotests/fixtures/org.kde.kpat.desktop b/runners/services/autotests/fixtures/org.kde.kpat.desktop -index 71d7fd2a89..3a91d89afe 100644 ---- a/runners/services/autotests/fixtures/org.kde.kpat.desktop -+++ b/runners/services/autotests/fixtures/org.kde.kpat.desktop -@@ -1,7 +1,7 @@ - # SPDX-FileCopyrightText: 2022 Alexander Lohnau - # SPDX-License-Identifier: CC0-1.0 - [Desktop Entry] --Name=KPatience -+Name=KPatience ServiceRunnerTest - Exec=true -qwindowtitle %c %u - Type=Application - Icon=kpat -diff --git a/runners/services/autotests/servicerunnertest.cpp b/runners/services/autotests/servicerunnertest.cpp -index fcfd3275ac..b911667a3b 100644 ---- a/runners/services/autotests/servicerunnertest.cpp -+++ b/runners/services/autotests/servicerunnertest.cpp -@@ -36,6 +36,10 @@ private Q_SLOTS: - void testINotifyUsage(); - void testSpecialArgs(); - void testEnv(); -+ void testDisassociation(); -+ void testMultipleKeywords(); -+ void testMultipleNameWords(); -+ void testDiscover(); - }; - - void ServiceRunnerTest::initTestCase() -@@ -86,8 +90,8 @@ void ServiceRunnerTest::testExecutableExactMatch() - - void ServiceRunnerTest::testKonsoleVsYakuakeComment() - { -- // Yakuake has konsole mentioned in comment, should be rated lower. -- const auto matches = launchQuery(QStringLiteral("kons")); -+ // Yakuake has konsole mentioned in comment, should not be listed (if it was it should be lower) -+ auto matches = launchQueryAndSort(QStringLiteral("kons")); - - bool konsoleFound = false; - bool yakuakeFound = false; -@@ -97,17 +101,10 @@ void ServiceRunnerTest::testKonsoleVsYakuakeComment() - continue; - } - -- if (match.text() == QLatin1String("Konsole ServiceRunnerTest")) { -- QCOMPARE(match.relevance(), 0.99); -- konsoleFound = true; -- } else if (match.text() == QLatin1String("Yakuake ServiceRunnerTest")) { -- // Rates lower because it doesn't have it in the name. -- QCOMPARE(match.relevance(), 0.59); -- yakuakeFound = true; -- } -- } -- QVERIFY(konsoleFound); -- QVERIFY(yakuakeFound); -+ QCOMPARE(texts, -+ QStringList({ -+ u"Konsole ServiceRunnerTest"_s, -+ })); - } - - void ServiceRunnerTest::testSystemSettings() -@@ -150,8 +147,9 @@ void ServiceRunnerTest::testSystemSettings2() - foreignSystemSettingsFound = true; - } - } -- QVERIFY(systemSettingsFound); -- QVERIFY(!foreignSystemSettingsFound); -+ -+ // The matched texts will contain much more because of the generic search term. Make sure our settings win. -+ QCOMPARE(texts.at(0), u"System Settings ServiceRunnerTest"_s); - } - - void ServiceRunnerTest::testCategories() -@@ -172,10 +170,6 @@ void ServiceRunnerTest::testCategories() - QVERIFY(std::none_of(matches.cbegin(), matches.cend(), [](const KRunner::QueryMatch &match) { - return match.text() == QLatin1String("Konsole ServiceRunnerTest"); - })); -- -- // Query too short to match any category -- matches = launchQuery(QStringLiteral("Dumm")); -- QVERIFY(matches.isEmpty()); - } - - void ServiceRunnerTest::testJumpListActions() -@@ -234,6 +228,68 @@ void ServiceRunnerTest::testEnv() - })); - } - -+void ServiceRunnerTest::testDisassociation() -+{ -+ // This test makes sure that we do not associate a service with a query that is not relevant. -+ auto matches = launchQueryAndSort(u"new laptop com"_s); // particularly notorious because it has two three letter words; 'com' is an incomplete word -+ -+ QStringList texts; -+ for (const auto &match : matches) { -+ texts.push_back(match.text()); -+ } -+ -+ QCOMPARE(texts, QStringList()); -+} -+ -+void ServiceRunnerTest::testMultipleKeywords() -+{ -+ auto matches = launchQueryAndSort(u"text editor programming"_s); -+ -+ QStringList texts; -+ for (const auto &match : matches) { -+ texts.push_back(match.text()); -+ } -+ -+ QCOMPARE(texts, -+ QStringList({ -+ u"Kate ServiceRunnerTest"_s, -+ })); -+} -+ -+void ServiceRunnerTest::testMultipleNameWords() -+{ -+ auto matches = launchQueryAndSort(u"system settings"_s); -+ -+ QStringList texts; -+ for (const auto &match : matches) { -+ if (!match.text().contains("ServiceRunnerTest"_L1)) { -+ continue; -+ } -+ texts.push_back(match.text()); -+ } -+ -+ QCOMPARE(texts, -+ QStringList({ -+ u"System Settings ServiceRunnerTest"_s, -+ })); -+} -+ -+void ServiceRunnerTest::testDiscover() -+{ -+ auto matches = launchQueryAndSort(u"disco"_s); -+ -+ QStringList texts; -+ for (const auto &match : matches) { -+ texts.push_back(match.text()); -+ } -+ -+ qDebug() << texts; -+ QCOMPARE(texts, -+ QStringList({ -+ u"Discover ServiceRunnerTest"_s, -+ })); -+} -+ - QTEST_MAIN(ServiceRunnerTest) - - #include "servicerunnertest.moc" -diff --git a/runners/services/bitap.h b/runners/services/bitap.h -new file mode 100644 -index 0000000000..a6aedb7eaf ---- /dev/null -+++ b/runners/services/bitap.h -@@ -0,0 +1,178 @@ -+// SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL -+// SPDX-FileCopyrightText: 2025 Harald Sitter -+ -+#pragma once -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+namespace Bitap -+{ -+ -+Q_DECLARE_LOGGING_CATEGORY(BITAP) -+Q_LOGGING_CATEGORY(BITAP, "org.kde.plasma.runner.services.bitap", QtWarningMsg) -+ -+struct Match { -+ qsizetype end; -+ qsizetype distance; -+ -+ bool operator==(const Match &other) const = default; -+}; -+ -+inline QDebug operator<<(QDebug dbg, const Bitap::Match &match) -+{ -+ dbg.nospace() << "Bitap::Match(" << match.end << ", " << match.distance << ")"; -+ return dbg; -+} -+ -+// Bitap is a bit of a complicated algorithm thanks to bitwise operations. I've opted to replace them with bitsets for readability. -+// It creates a patternMask based on all characters in the pattern. Basically each character gets assigned a representative bit. -+// e.g. in the pattern 'abc' the character 'a' would be 110, 'b' 101, 'c' 011. -+// This is a bit expensive up front but allows it to carry out everything else using bitwise operations. -+// For each match we set a matching bit in the bits vector. -+// Matching happens within a hamming distance, meaning up to `hammingDistance` characters can be out of place. -+inline std::optional bitap(const QStringView &name, const QStringView &pattern, int hammingDistance) -+{ -+ qCDebug(BITAP) << "Bitap called with name:" << name << "and pattern:" << pattern << "with hamming distance:" << hammingDistance; -+ const auto patternEndIndex = pattern.size() - 1; -+ if (name == pattern) { -+ return Match{.end = patternEndIndex, .distance = 0}; // Perfect match -+ } -+ -+ if (pattern.isEmpty() || name.isEmpty()) { -+ return std::nullopt; -+ } -+ -+ // Being a bitset we could have any number of bits, but practically we probably don't need more than 64, most bitaps I've seen even use 32. -+ constexpr auto maxMaskBits = 64; -+ using Mask = std::bitset; -+ using PatternMask = std::array::max()>; -+ -+ // The way bitap works is that each bit of the Mask represents a character position. Because of this we cannot match -+ // more characters than we have bits for. -+ // -1 because one bit is used for the result (I think) -+ if (pattern.size() >= qsizetype(Mask().size()) - 1) { -+ qCWarning(BITAP) << "Pattern is too long for bitap algorithm, max length is" << Mask().size() - 1; -+ return std::nullopt; -+ } -+ -+ const PatternMask patternMask = [&pattern, &name] { -+ PatternMask patternMask; -+ // The following is an optimized version of patternMask.fill(Mask().set()); to set all **necessary** bits to 1. -+ for (const auto &qchar : pattern) { -+ patternMask.at(qchar.unicode()).set(); -+ } -+ for (const auto &qchar : name) { -+ patternMask.at(qchar.unicode()).set(); -+ } -+ -+ for (int i = 0; i < pattern.size(); ++i) { -+ const auto char_ = pattern.at(i).unicode(); -+ patternMask.at(char_).reset(i); // unset the relevant index bits -+ } -+ -+ if (BITAP().isDebugEnabled()) { -+ for (const auto &i : pattern) { -+ const auto char_ = i.unicode(); -+ qCDebug(BITAP) << "Pattern mask for" << char_ << "is" << patternMask.at(char_).to_string(); -+ } -+ } -+ -+ return patternMask; -+ }(); -+ -+ Match match{ -+ .end = -1, // -1 means no match found for convenience -+ .distance = name.size(), -+ }; -+ -+ std::vector bits((hammingDistance + 1), Mask().set().reset(0)); -+ std::vector transpositions(bits.cbegin(), bits.cend()); -+ for (int i = 0; i < name.size(); ++i) { -+ const auto &char_ = name.at(i); -+ auto previousBit = bits[0]; -+ const auto mask = patternMask.at(char_.unicode()); -+ bits[0] |= mask; -+ bits[0] <<= 1; -+ -+ for (int j = 1; j <= hammingDistance; ++j) { -+ auto bit = bits[j]; -+ auto current = (bit | mask) << 1; -+ // https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance -+ auto substitute = previousBit << 1; -+ auto delete_ = bits[j - 1] << 1; -+ auto insert = previousBit; -+ auto transpose = (transpositions[j - 1] | (mask << 1)) << 1; -+ bits[j] = current & substitute & transpose & delete_ & insert; -+ transpositions[j - 1] = (previousBit << 1) | mask; -+ previousBit = bit; -+ } -+ -+ if (BITAP().isDebugEnabled()) { -+ qCDebug(BITAP) << "After processing character" << char_ << "at index" << i; -+ for (const auto &bit : bits) { -+ qCDebug(BITAP) << "bit" << bit.to_string(); -+ } -+ } -+ -+ for (int k = 0; k <= hammingDistance; ++k) { -+ // If the bit at the end of the mask is 0, it means we have a match. -+ if (0 == (bits[k] & Mask().set(pattern.size()))) { -+ if (k < match.distance && match.end < i) { -+ qCDebug(BITAP) << "Match found at index" << i << "with hamming distance" << k << "better than previous match with distance" -+ << match.distance << "at index" << match.end; -+ match = { -+ .end = i, -+ .distance = k, -+ }; -+ } -+ // We do not return early because we want to find the best match, not just any. -+ // e.g. with a maximum distance of 1 `disc` could match `disc` either at index two with distance one, or at index three with distance zero. -+ } -+ } -+ } -+ -+ // Because we use a complete Damerau–Levenshtein distance the return value is a bit complicated. The trick is that the distance incurs a negative penalty -+ // in relation to the max distance. While an end that is closer to the real end is generally favorably. Combining the two into a single value -+ // would complicate the meaning of the return value to mean "approximate end with random penalty". This is garbage to reason about so instead we return -+ // both values and then assign them meaning in the score function. -+ if (match.end != -1) { -+ return match; -+ } -+ -+ qCDebug(BITAP) << "No match found for pattern" << pattern << "in name" << name; -+ return std::nullopt; -+} -+ -+inline qreal score(const QStringView &name, const auto &match, auto hammingDistance) -+{ -+ // Normalize the score to a value between 0.0 and 1.0 -+ // No distance means the score is directly correlated to the end index. The more characters matched the higher the score. -+ // Any distance will lower the score by a sub 0.1 margin. -+ -+ if (name.size() == 0) { -+ return 0.0; // No name, no score. -+ } -+ -+ const auto maxEnd = name.size() - 1; -+ const auto penalty = [&] { -+ if (hammingDistance <= 0) { -+ return 1.0; // No penalty for no distance -+ } -+ constexpr auto tenth = 10.0; -+ constexpr auto half = 2.0; -+ return qreal(match.distance) / qreal(hammingDistance) / tenth / half; -+ }(); -+ auto score = qreal(match.end) / qreal(maxEnd); -+ // Prevent underflows when the penalty is larger than the score. -+ score = std::max(0.0, score - penalty); -+ -+ Q_ASSERT(score >= 0.0 && score <= 1.0); -+ return score; -+} -+ -+} // namespace Bitap -diff --git a/runners/services/levenshtein.h b/runners/services/levenshtein.h -new file mode 100644 -index 0000000000..0efb960be3 ---- /dev/null -+++ b/runners/services/levenshtein.h -@@ -0,0 +1,58 @@ -+// SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL -+// SPDX-FileCopyrightText: 2025 Harald Sitter -+ -+#pragma -+ -+#include -+#include -+ -+namespace Levenshtein -+{ -+ -+inline int distance(const QStringView &name, const QStringView &query) -+{ -+ if (name == query) { -+ return 0; -+ } -+ -+ std::vector distance0(query.size() + 1, 0); -+ std::vector distance1(query.size() + 1, 0); -+ -+ for (int i = 0; i <= query.size(); ++i) { -+ distance0[i] = i; -+ } -+ -+ for (int i = 0; i < name.size(); ++i) { -+ distance1[0] = i + 1; -+ for (int j = 0; j < query.size(); ++j) { -+ const auto deletionCost = distance0[j + 1] + 1; -+ const auto insertionCost = distance1[j] + 1; -+ const auto substitutionCost = [&] { -+ if (name[i] == query[j]) { -+ return distance0[j]; -+ } -+ return distance0[j] + 1; -+ }(); -+ distance1[j + 1] = std::min({deletionCost, insertionCost, substitutionCost}); -+ } -+ std::swap(distance0, distance1); -+ } -+ return distance0[query.size()]; -+} -+ -+inline qreal score(const QStringView &name, int distance) -+{ -+ // Normalize the distance to a value between 0.0 and 1.0 -+ // The maximum distance is the length of the pattern. -+ // If the distance is 0, it means a perfect match, so we return 1.0. -+ // If the distance is equal to the length of the pattern, we return 0.0. -+ if (distance == 0) { -+ return 1.0; -+ } -+ if (distance >= name.size()) { -+ return 0.0; -+ } -+ return 1.0 - (qreal(distance) / qreal(name.size())); -+} -+ -+} // namespace Levenshtein -diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp -index eb9f02e74b..3d5de8feb2 100644 ---- a/runners/services/servicerunner.cpp -+++ b/runners/services/servicerunner.cpp -@@ -1,7 +1,7 @@ - /* - SPDX-FileCopyrightText: 2006 Aaron Seigo - SPDX-FileCopyrightText: 2014 Vishesh Handa -- SPDX-FileCopyrightText: 2016-2020 Harald Sitter -+ SPDX-FileCopyrightText: 2016-2025 Harald Sitter - SPDX-FileCopyrightText: 2022-2023 Alexander Lohnau - - SPDX-License-Identifier: LGPL-2.0-only -@@ -21,6 +21,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -35,22 +36,130 @@ - #include - #include - -+#include "bitap.h" - #include "debug.h" -+#include "levenshtein.h" - - using namespace Qt::StringLiterals; - namespace - { - --int weightedLength(const QString &query) -+struct Score { -+ qreal value = 0.0; // The final score, it is the sum of all scores. -+ KRunner::QueryMatch::CategoryRelevance categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Lowest; // The category relevance of the match. -+}; -+ -+struct ScoreCard { -+ Bitap::Match bitap; -+ qreal bitapScore; -+ int levenshtein; -+ qreal levenshteinScore; -+}; -+ -+QDebug operator<<(QDebug dbg, const ScoreCard &card) - { -- return KStringHandler::logicalLength(query); -+ dbg.nospace() << "Scorecard(" << "bitap: " << card.bitap << ", bitapScore: " << card.bitapScore << ", levenshtein: " << card.levenshtein -+ << ", levenshteinScore: " << card.levenshteinScore << ")"; -+ return dbg; - } - --inline bool contains(const QString &result, const QList &queryList) -+using ScoreCards = std::vector; -+ -+struct WeightedScoreCard { -+ ScoreCards cards; -+ qreal weight; -+}; -+ -+QDebug operator<<(QDebug dbg, const WeightedScoreCard &card) - { -- return std::ranges::all_of(queryList, [&result](QStringView query) { -- return result.contains(query, Qt::CaseInsensitive); -- }); -+ -+ dbg.nospace() << "WeightedCard["; -+ for (const auto &scoreCard : card.cards) { -+ dbg.nospace() << scoreCard; -+ if (&scoreCard != &card.cards.back()) { -+ dbg.nospace() << ", "; -+ } -+ } -+ dbg.nospace() << "]"; -+ return dbg; -+} -+ -+auto makeScores(const auto ¬NormalizedString, const auto &queryList) { -+ if (notNormalizedString.isEmpty()) { -+ return ScoreCards{}; // No string, no score. -+ } -+ -+ const auto string = notNormalizedString.toLower(); -+ -+ ScoreCards cards; -+ for (const auto &queryItem : queryList) { -+ constexpr auto maxDistance = 1; -+ const auto bitap = Bitap::bitap(string, queryItem, maxDistance); -+ if (!bitap) { -+ // One of the query items didn't match. This means the entire query is not a match -+ return ScoreCards{}; -+ } -+ -+ const auto bitapScore = Bitap::score(string, bitap.value(), maxDistance); -+ -+ // Mind that we give different levels of bonus. This is important to imply ordering within competing matches of the same "type". -+ // If we perfectly match that gives a bonus for not requiring any changes. -+ const auto noSubstitionBonus = Bitap::score(string, bitap.value(), 0) == 1.0 ? 4.0 : 1.0; -+ // If we match the entire length of the string that gets a bonus (disregarding distance, that was considered above). -+ const auto completeMatchBonus = bitap->end >= (queryItem.size() - 1) ? 3.0 : 1.0; -+ // If the string starts with the query item that gets a bonus. -+ const auto startsWithBonus = (string.startsWith(queryItem, Qt::CaseInsensitive)) ? 2.0 : 1.0; -+ -+ // Also consider the distance between the input and the query item. -+ // If one is "yolotrollingservice" and the other is "yolo" then we must consider them worse matches than say "yolotroll". -+ const auto levenshtein = Levenshtein::distance(string, queryItem); -+ -+ cards.emplace_back(ScoreCard{ -+ .bitap = *bitap, -+ .bitapScore = bitapScore + completeMatchBonus + noSubstitionBonus + startsWithBonus, -+ .levenshtein = levenshtein, -+ .levenshteinScore = Levenshtein::score(string, levenshtein), -+ }); -+ } -+ -+ return cards; -+}; -+ -+ -+auto makeScoreFromList(const auto &queryList, const QStringList &strings) { -+ // This turns the loop inside out. For every query item we must find a match in our keywords or we discard -+ ScoreCards cards; -+ // e.g. text,editor,programming -+ for (const auto &queryItem : queryList) { -+ // e.g. text;txt;editor;programming;programmer;development;developer;code; -+ auto found = false; -+ ScoreCards queryCards; -+ for (const auto &string : strings) { -+ auto stringCards = makeScores(string, QList{queryItem}); -+ if (stringCards.empty()) { -+ continue; // The combination didn't match. -+ } -+ for (auto &scoreCard : stringCards) { -+ if (scoreCard.levenshteinScore < 0.8) { -+ continue; // Not a good match, skip it. We are very strict with keywords -+ } -+ found = true; -+ queryCards.append_range(stringCards); -+ } -+ // We do not break because other string might also match, improving the score. -+ } -+ if (!found) { -+ // No item in strings matched the query item. This means the entire query is not a match. -+ return ScoreCards{}; -+ } -+ cards.append_range(queryCards); -+ } -+ return cards; -+}; -+ -+int weightedLength(const QString &query) -+{ -+ return KStringHandler::logicalLength(query); - } - - inline bool contains(const QStringList &results, const QList &queryList) -@@ -79,7 +188,7 @@ public: - - void match(KRunner::RunnerContext &context) - { -- query = context.query(); -+ query = context.query().toLower(); - // Splitting the query term to match using subsequences - queryList = QStringView(query).split(QLatin1Char(' ')); - weightedTermLength = weightedLength(query); -@@ -120,36 +229,6 @@ private: - return ret; - } - -- enum class Category { -- Name, -- GenericName, -- Comment, -- }; -- qreal increaseMatchRelevance(const QString &serviceProperty, const QList &strList, Category category) -- { -- // Increment the relevance based on all the words (other than the first) of the query list -- qreal relevanceIncrement = 0; -- -- for (int i = 1; i < strList.size(); ++i) { -- const auto &str = strList.at(i); -- if (category == Category::Name) { -- if (serviceProperty.contains(str, Qt::CaseInsensitive)) { -- relevanceIncrement += 0.01; -- } -- } else if (category == Category::GenericName) { -- if (serviceProperty.contains(str, Qt::CaseInsensitive)) { -- relevanceIncrement += 0.01; -- } -- } else if (category == Category::Comment) { -- if (serviceProperty.contains(str, Qt::CaseInsensitive)) { -- relevanceIncrement += 0.01; -- } -- } -- } -- -- return relevanceIncrement; -- } -- - void setupMatch(const KService::Ptr &service, KRunner::QueryMatch &match) - { - const QString name = service->name(); -@@ -219,96 +298,77 @@ private: - return resultingArgs.join(QLatin1Char(' ')); - } - -- void matchNameKeywordAndGenericName() -+ [[nodiscard]] std::optional fuzzyScore(KService::Ptr service) - { -- const auto nameKeywordAndGenericNameFilter = [this](const KService::Ptr &service) { -- // Name -- if (contains(service->name(), queryList)) { -- return true; -- } -- // If the term length is < 3, no real point searching the untranslated Name, Keywords and GenericName -- if (weightedTermLength < 3) { -- return false; -- } -- if (contains(service->untranslatedName(), queryList)) { -- return true; -- } -+ if (queryList.isEmpty()) { -+ return std::nullopt; // No query, no score. -+ } -+ -+ const auto name = service->name(); -+ if (name.compare(query, Qt::CaseInsensitive) == 0) { -+ // Absolute match. Can't get any better than this. -+ return Score{.value = std::numeric_limits::max(), .categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Highest}; -+ } - -- // Keywords -- if (contains(service->keywords(), queryList)) { -- return true; -+ std::array weightedCards = { -+ WeightedScoreCard{.cards = makeScores(name, queryList), .weight = 1.0}, -+ WeightedScoreCard{.cards = makeScores(service->untranslatedName(), queryList), .weight = 0.8}, -+ WeightedScoreCard{.cards = makeScores(service->genericName(), queryList), .weight = 0.6}, -+ WeightedScoreCard{.cards = makeScoreFromList(queryList, service->keywords()), .weight = 0.1}, -+ }; -+ -+ if (RUNNER_SERVICES().isDebugEnabled()) { -+ qCDebug(RUNNER_SERVICES) << "+++++++ Weighted Cards for" << name; -+ for (const auto &weightedCard : weightedCards) { -+ qCDebug(RUNNER_SERVICES) << weightedCard; - } -- // GenericName -- if (contains(service->genericName(), queryList) || contains(service->untranslatedGenericName(), queryList)) { -- return true; -+ qCDebug(RUNNER_SERVICES) << "-------"; -+ } -+ -+ int scores = 1; // starts at 1 to avoid division by zero -+ qreal finalScore = 0.0; -+ for (const auto &weightedCard : weightedCards) { -+ if (weightedCard.cards.empty()) { -+ continue; // No scores, no match. - } -- // Comment -- if (contains(service->comment(), queryList)) { -- return true; -+ -+ qreal weightedScore = 0.0; -+ for (const auto &scoreCard : weightedCard.cards) { -+ weightedScore += (scoreCard.bitapScore + scoreCard.levenshteinScore) * weightedCard.weight; -+ scores++; - } - -- return false; -- }; -+ finalScore += weightedScore; -+ } -+ finalScore = finalScore / scores; // Average the score for this card - -- for (const KService::Ptr &service : m_services) { -- if (!nameKeywordAndGenericNameFilter(service) || disqualify(service)) { -- continue; -- } -+ qCDebug(RUNNER_SERVICES) << "Final score for" << name << "is" << finalScore; -+ if (finalScore > 0.0) { -+ return Score{.value = finalScore, .categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Moderate}; -+ } - -- const QString id = service->storageId(); -- const QString name = service->name(); -+ return std::nullopt; -+ } - -- KRunner::QueryMatch::CategoryRelevance categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Moderate; -- qreal relevance(0.6); -+ void matchNameKeywordAndGenericName() -+ { -+ static auto isTest = QStandardPaths::isTestModeEnabled(); - -- // If the term was < 3 chars and NOT at the beginning of the App's name, then chances are the user doesn't want that app -- if (weightedTermLength < 3) { -- if (name.startsWith(query, Qt::CaseInsensitive)) { -- relevance = 0.9; -- } else { -- continue; -- } -- } else if (name.compare(query, Qt::CaseInsensitive) == 0) { -- relevance = 1; -- categoryRelevance = KRunner::QueryMatch::CategoryRelevance::Highest; -- } else if (const auto idx = name.indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { -- relevance = 0.8; -- relevance += increaseMatchRelevance(name, queryList, Category::Name); -- if (idx == 0) { -- relevance += 0.1; -- categoryRelevance = KRunner::QueryMatch::CategoryRelevance::High; -- } -- } else if (const auto idx = service->genericName().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { -- relevance = 0.65; -- relevance += increaseMatchRelevance(service->genericName(), queryList, Category::GenericName); -- if (idx == 0) { -- relevance += 0.05; -- } -- } else if (const auto idx = service->comment().indexOf(queryList[0], 0, Qt::CaseInsensitive); idx != -1) { -- relevance = 0.5; -- relevance += increaseMatchRelevance(service->comment(), queryList, Category::Comment); -- if (idx == 0) { -- relevance += 0.05; -- } -+ for (const KService::Ptr &service : m_services) { -+ if (isTest && !service->name().contains("ServiceRunnerTest"_L1)) { -+ continue; // Skip services that are not part of the test. - } - - KRunner::QueryMatch match(m_runner); -- match.setCategoryRelevance(categoryRelevance); -- setupMatch(service, match); -- if (service->categories().contains(QLatin1String("KDE"))) { -- qCDebug(RUNNER_SERVICES) << "found a kde thing" << id << match.subtext() << relevance; -- relevance += .09; -- } -- -- if (const auto foundIt = m_runner->m_favorites.constFind(service->desktopEntryName()); foundIt != m_runner->m_favorites.cend()) { -- if (foundIt->isGlobal || foundIt->linkedActivities.contains(m_currentActivity)) { -- qCDebug(RUNNER_SERVICES) << "entry is a favorite" << id << match.subtext() << relevance; -- relevance *= 1.25; // Give favorites a relative boost, -- } -+ auto score = fuzzyScore(service); -+ if (!score || disqualify(service)) { -+ continue; - } - -- qCDebug(RUNNER_SERVICES) << name << "is this relevant:" << relevance; -- match.setRelevance(relevance); -+ setupMatch(service, match); -+ match.setCategoryRelevance(score->categoryRelevance); -+ match.setRelevance(score->value); -+ qCDebug(RUNNER_SERVICES) << match.text() << "is this relevant:" << match.relevance() << "category relevance" << match.categoryRelevance(); - - matches << match; - } --- -2.51.0 - diff --git a/roles/kde/patches/plasma-workspace/pr5734.patch b/roles/kde/patches/plasma-workspace/pr5734.patch deleted file mode 100644 index ffe6605..0000000 --- a/roles/kde/patches/plasma-workspace/pr5734.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 0168ee68b484995ed9398d31004dd80678ac7e37 Mon Sep 17 00:00:00 2001 -From: Kai Uwe Broulik -Date: Tue, 5 Aug 2025 12:57:00 +0200 -Subject: [PATCH] Close USB device added notification when devicenotifier pops - up - -The device notification is supposed to be super quick feedback that -"something" got detected. Once it has been identified as storage -device (disks spun up and what not), devicenotifier will show up -and then you have two popups. ---- - applets/devicenotifier/CMakeLists.txt | 1 + - applets/devicenotifier/devicefiltercontrol.cpp | 14 ++++++++++++++ - applets/devicenotifier/devicefiltercontrol.h | 1 + - applets/devicenotifier/qml/main.qml | 1 + - devicenotifications/devicenotifications.cpp | 8 ++++++++ - devicenotifications/devicenotifications.h | 3 +++ - 6 files changed, 28 insertions(+) - -diff --git a/applets/devicenotifier/CMakeLists.txt b/applets/devicenotifier/CMakeLists.txt -index d87964dc46d..fa415837e68 100644 ---- a/applets/devicenotifier/CMakeLists.txt -+++ b/applets/devicenotifier/CMakeLists.txt -@@ -31,6 +31,7 @@ plasma_add_applet(org.kde.plasma.devicenotifier - - target_link_libraries(org.kde.plasma.devicenotifier - PRIVATE -+ Qt::DBus - Qt::Qml - Plasma::Plasma - KF6::Solid -diff --git a/applets/devicenotifier/devicefiltercontrol.cpp b/applets/devicenotifier/devicefiltercontrol.cpp -index dfdb51a4304..f585eb2f063 100644 ---- a/applets/devicenotifier/devicefiltercontrol.cpp -+++ b/applets/devicenotifier/devicefiltercontrol.cpp -@@ -11,9 +11,14 @@ - #include "devicecontrol.h" - #include "devicestatemonitor_p.h" - -+#include -+#include -+ - #include - #include - -+using namespace Qt::Literals::StringLiterals; -+ - DeviceFilterControl::DeviceFilterControl(QObject *parent) - : QSortFilterProxyModel(parent) - , m_filterType(Removable) -@@ -54,6 +59,15 @@ void DeviceFilterControl::unmountAllRemovables() - qCDebug(APPLETS::DEVICENOTIFIER) << "Device Filter Control: unmount all removables function finished"; - } - -+void DeviceFilterControl::dismissUsbDeviceAddedNotification() -+{ -+ QDBusMessage msg = QDBusMessage::createMethodCall(u"org.kde.kded6"_s, -+ u"/modules/devicenotifications"_s, -+ u"org.kde.plasma.devicenotifications"_s, -+ u"dismissUsbDeviceAdded"_s); -+ QDBusConnection::sessionBus().call(msg, QDBus::NoBlock); -+} -+ - QBindable DeviceFilterControl::bindableLastUdi() - { - return &m_lastUdi; -diff --git a/applets/devicenotifier/devicefiltercontrol.h b/applets/devicenotifier/devicefiltercontrol.h -index e4c0a321657..fa6266fb197 100644 ---- a/applets/devicenotifier/devicefiltercontrol.h -+++ b/applets/devicenotifier/devicefiltercontrol.h -@@ -41,6 +41,7 @@ public: - Q_ENUM(DevicesType) - - Q_INVOKABLE void unmountAllRemovables(); -+ Q_INVOKABLE void dismissUsbDeviceAddedNotification(); - - explicit DeviceFilterControl(QObject *parent = nullptr); - ~DeviceFilterControl() override; -diff --git a/applets/devicenotifier/qml/main.qml b/applets/devicenotifier/qml/main.qml -index 7fcd76a6d16..c7fe6e6197d 100644 ---- a/applets/devicenotifier/qml/main.qml -+++ b/applets/devicenotifier/qml/main.qml -@@ -35,6 +35,7 @@ PlasmoidItem { - onLastUdiChanged: { - if (lastDeviceAdded) { - if (Plasmoid.configuration.popupOnNewDevice) { -+ filterModel.dismissUsbDeviceAddedNotification(); - devicenotifier.expanded = true; - fullRepresentationItem.spontaneousOpen = true; - } -diff --git a/devicenotifications/devicenotifications.cpp b/devicenotifications/devicenotifications.cpp -index 71ae0ff340e..196e28ca948 100644 ---- a/devicenotifications/devicenotifications.cpp -+++ b/devicenotifications/devicenotifications.cpp -@@ -323,6 +323,14 @@ void KdedDeviceNotifications::setupWaylandOutputListener() - wl_callback_add_listener(syncCallback, &syncCallbackListener, this); - } - -+void KdedDeviceNotifications::dismissUsbDeviceAdded() -+{ -+ if (m_usbDeviceAddedNotification) { -+ m_usbDeviceAddedNotification->close(); -+ m_usbDeviceAddedNotification = nullptr; -+ } -+} -+ - void KdedDeviceNotifications::notifyOutputAdded() - { - if (m_deviceAddedTimer.isActive()) { -diff --git a/devicenotifications/devicenotifications.h b/devicenotifications/devicenotifications.h -index ab7e6b3ff9b..75005193287 100644 ---- a/devicenotifications/devicenotifications.h -+++ b/devicenotifications/devicenotifications.h -@@ -77,6 +77,7 @@ private: - class KdedDeviceNotifications : public KDEDModule - { - Q_OBJECT -+ Q_CLASSINFO("D-Bus Interface", "org.kde.plasma.devicenotifications") - - public: - KdedDeviceNotifications(QObject *parent, const QVariantList &args); -@@ -84,6 +85,8 @@ public: - - void setupWaylandOutputListener(); - -+ Q_SCRIPTABLE void dismissUsbDeviceAdded(); -+ - private: - void notifyOutputAdded(); - void notifyOutputRemoved(); --- -GitLab - diff --git a/roles/kde/patches/plasma-workspace/pr5746.patch b/roles/kde/patches/plasma-workspace/pr5746.patch deleted file mode 100644 index d4eace1..0000000 --- a/roles/kde/patches/plasma-workspace/pr5746.patch +++ /dev/null @@ -1,33 +0,0 @@ -From f6ec2847358178a5b6ff0497e52d1e2be43d2a48 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Luan=20Vitor=20Simi=C3=A3o=20oliveira?= - -Date: Fri, 8 Aug 2025 14:41:49 -0300 -Subject: [PATCH] kcms/style: add special case for Adwaita gtk theme - -Allows the user to set the GTK theme to the default "Adwaita" -needs to be special cased because the theme is implemented in code. ---- - kcms/style/gtkthemesmodel.cpp | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/kcms/style/gtkthemesmodel.cpp b/kcms/style/gtkthemesmodel.cpp -index 002e87dbd0d..6dcdf4f1a1d 100644 ---- a/kcms/style/gtkthemesmodel.cpp -+++ b/kcms/style/gtkthemesmodel.cpp -@@ -35,7 +35,12 @@ void GtkThemesModel::load() - if (possibleThemeDirectory.dirName() == u"Breeze-Dark") { - continue; - } -- -+ if (possibleThemeDirectory.dirName() == u"Default") { -+ // Adwaita is a special case, since it is implemented inside GTK itself -+ // also setting gtk-theme-name to "Default" breaks dark theme -+ gtk3ThemesNames.insert(QStringLiteral("Adwaita"), possibleThemeDirectory.path()); -+ continue; -+ } - gtk3ThemesNames.insert(possibleThemeDirectory.dirName(), possibleThemeDirectory.path()); - } - } --- -GitLab - diff --git a/roles/kde/patches/plasma-workspace/pr5782.patch b/roles/kde/patches/plasma-workspace/pr5782.patch deleted file mode 100644 index a20c5e1..0000000 --- a/roles/kde/patches/plasma-workspace/pr5782.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 4ab3894d75e1f9c6c7738a893a9b707ff0575953 Mon Sep 17 00:00:00 2001 -From: Nate Graham -Date: Thu, 21 Aug 2025 19:37:33 -0600 -Subject: [PATCH] notifications: make "you missed some notifications" - notification transient - -Its purpose is to direct you to the notifications history. If you're -seeing it *in* the notification history, its purpose has been bypassed -because you're already where it wanted to take you. - -Don't show it in the notification history. ---- - libnotificationmanager/notifications.cpp | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/libnotificationmanager/notifications.cpp b/libnotificationmanager/notifications.cpp -index f68c342e7e9..128665f4de9 100644 ---- a/libnotificationmanager/notifications.cpp -+++ b/libnotificationmanager/notifications.cpp -@@ -917,6 +917,9 @@ void Notifications::showInhibitionSummary(Urgency urgency, const QStringList &bl - notification->setIconName(u"preferences-desktop-notification-bell"_s); - notification->setFlags(KNotification::CloseOnTimeout); - notification->setComponentName(u"libnotificationmanager"_s); -+ // Don't put it in the history because this doesn't make sense; if you're seeing it -+ // in the history, you're seeing the notifications it was telling you about! -+ notification->setHint(u"transient"_s, true); - - const QString showNotificationsText = i18nc("@action:button Show the notifications popup", "Show Notifications"); - --- -GitLab - diff --git a/roles/kde/patches/plasma-workspace/pr5788.patch b/roles/kde/patches/plasma-workspace/pr5788.patch deleted file mode 100644 index 96f3980..0000000 --- a/roles/kde/patches/plasma-workspace/pr5788.patch +++ /dev/null @@ -1,42 +0,0 @@ -From f0d2dd20803f2eee364d26656715b89e7c74366c Mon Sep 17 00:00:00 2001 -From: David Redondo -Date: Wed, 27 Aug 2025 09:40:43 +0200 -Subject: [PATCH] servicerunner: use vector::insert on compilers that don't - support append_range yet - -g++ only gained support for it with g++ 15 which was released this month. ---- - runners/services/servicerunner.cpp | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/runners/services/servicerunner.cpp b/runners/services/servicerunner.cpp -index 2ccc9a0af37..9e9d4e70a72 100644 ---- a/runners/services/servicerunner.cpp -+++ b/runners/services/servicerunner.cpp -@@ -142,7 +142,11 @@ auto makeScoreFromList(const auto &queryList, const QStringList &strings) { - continue; // Not a good match, skip it. We are very strict with keywords - } - found = true; -+#ifdef __cpp_lib_containers_ranges - queryCards.append_range(stringCards); -+#else -+ queryCards.insert(queryCards.end(), stringCards.cbegin(), stringCards.cend()); -+#endif - } - // We do not break because other string might also match, improving the score. - } -@@ -150,7 +154,11 @@ auto makeScoreFromList(const auto &queryList, const QStringList &strings) { - // No item in strings matched the query item. This means the entire query is not a match. - return ScoreCards{}; - } -+#ifdef __cpp_lib_containers_ranges - cards.append_range(queryCards); -+#else -+ cards.insert(cards.end(), queryCards.cbegin(), queryCards.cend()); -+#endif - } - return cards; - }; --- -GitLab - diff --git a/roles/kde/patches/plasma-workspace/pr5816.patch b/roles/kde/patches/plasma-workspace/pr5816.patch deleted file mode 100644 index 7a1925a..0000000 --- a/roles/kde/patches/plasma-workspace/pr5816.patch +++ /dev/null @@ -1,349 +0,0 @@ -From 77b3ec8cf4fb9414167bb15bcc3c69b1be6c2dbf Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Tue, 16 Sep 2025 15:52:29 +0300 -Subject: [PATCH 1/2] shell: Pass an xdg activation token from DesktopView to - KRunner - -This makes sure that krunner gets focused after starting to type while -a desktop view is focused when using medium or high focus stealing -prevention level. ---- - krunner/dbus/org.kde.krunner.App.xml | 4 ++ - krunner/view.cpp | 14 +++++++ - krunner/view.h | 1 + - shell/desktopview.cpp | 61 ++++++++++++++++++++++++++-- - shell/desktopview.h | 2 + - 5 files changed, 79 insertions(+), 3 deletions(-) - -diff --git a/krunner/dbus/org.kde.krunner.App.xml b/krunner/dbus/org.kde.krunner.App.xml -index 6553e9a1b56..e6926b1b63a 100644 ---- a/krunner/dbus/org.kde.krunner.App.xml -+++ b/krunner/dbus/org.kde.krunner.App.xml -@@ -17,5 +17,9 @@ - - - -+ -+ -+ -+ - - -diff --git a/krunner/view.cpp b/krunner/view.cpp -index afefe9ab486..bb7edd5d654 100644 ---- a/krunner/view.cpp -+++ b/krunner/view.cpp -@@ -263,6 +263,20 @@ void View::querySingleRunner(const QString &runnerName, const QString &term) - m_engine->rootObject()->setProperty("query", term); - } - -+void View::queryWithActivationToken(const QString &term, const QString &activationToken) -+{ -+ qputenv("XDG_ACTIVATION_TOKEN", activationToken.toUtf8()); -+ -+ if (!isVisible()) { -+ display(); -+ } else { -+ requestActivate(); -+ } -+ -+ m_engine->rootObject()->setProperty("singleRunner", QString()); -+ m_engine->rootObject()->setProperty("query", term); -+} -+ - bool View::pinned() const - { - return m_pinned; -diff --git a/krunner/view.h b/krunner/view.h -index 979c6d3b483..af1d477d6f3 100644 ---- a/krunner/view.h -+++ b/krunner/view.h -@@ -93,6 +93,7 @@ public Q_SLOTS: - void displayWithClipboardContents(); - void query(const QString &term); - void querySingleRunner(const QString &runnerName, const QString &term); -+ void queryWithActivationToken(const QString &term, const QString &activationToken); - - protected Q_SLOTS: - void loadConfig(); -diff --git a/shell/desktopview.cpp b/shell/desktopview.cpp -index 36e23149272..744176e6d3e 100644 ---- a/shell/desktopview.cpp -+++ b/shell/desktopview.cpp -@@ -23,6 +23,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -384,11 +385,54 @@ bool DesktopView::event(QEvent *e) - { - if (e->type() == QEvent::FocusOut) { - m_krunnerText.clear(); -+ -+ if (!m_krunnerFuture.isCanceled()) { -+ m_krunnerFuture.cancel(); -+ m_krunnerFuture = {}; -+ } - } - - return PlasmaQuick::ContainmentView::event(e); - } - -+class ActivationTokenRequest : public QObject -+{ -+ Q_OBJECT -+ -+public: -+ explicit ActivationTokenRequest(QWindow *window) -+ : m_serial(KWaylandExtras::lastInputSerial(window)) -+ { -+ m_promise.start(); -+ -+ connect(KWaylandExtras::self(), &KWaylandExtras::xdgActivationTokenArrived, this, [this](int serial, const QString &token) { -+ if (m_serial == serial) { -+ if (!m_promise.isCanceled()) { -+ m_promise.addResult(token); -+ } -+ m_promise.finish(); -+ delete this; -+ } -+ }); -+ KWaylandExtras::requestXdgActivationToken(window, m_serial, QString()); -+ } -+ -+ QFuture future() const -+ { -+ return m_promise.future(); -+ } -+ -+private: -+ QPromise m_promise; -+ int m_serial; -+}; -+ -+static QFuture fetchActivationToken(QWindow *window) -+{ -+ auto request = new ActivationTokenRequest(window); -+ return request->future(); -+} -+ - bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) - { - // allow only Shift and GroupSwitch modifiers -@@ -408,12 +452,22 @@ bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) - krunnerTextChanged = true; - } - if (krunnerTextChanged) { -- const QString interface(QStringLiteral("org.kde.krunner")); - if (!KAuthorized::authorize(QStringLiteral("run_command"))) { - return false; - } -- org::kde::krunner::App krunner(interface, QStringLiteral("/App"), QDBusConnection::sessionBus()); -- krunner.query(m_krunnerText); -+ if (KWindowSystem::isPlatformWayland()) { -+ if (!m_krunnerFuture.isCanceled()) { -+ m_krunnerFuture.cancel(); -+ } -+ m_krunnerFuture = fetchActivationToken(this); -+ m_krunnerFuture.then(this, [this](const QString &token) { -+ org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); -+ krunner.queryWithActivationToken(m_krunnerText, token); -+ }); -+ } else { -+ org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); -+ krunner.query(m_krunnerText); -+ } - return true; - } - return false; -@@ -596,4 +650,5 @@ void DesktopView::setAccentColorFromWallpaper(const QColor &accentColor) - QDBusConnection::sessionBus().send(applyAccentColor); - } - -+#include "desktopview.moc" - #include "moc_desktopview.cpp" -diff --git a/shell/desktopview.h b/shell/desktopview.h -index c2b642d9a15..9e152611a31 100644 ---- a/shell/desktopview.h -+++ b/shell/desktopview.h -@@ -10,6 +10,7 @@ - - #include - #include -+#include - #include - - #include -@@ -127,6 +128,7 @@ private: - QPointer m_screenToFollow; - LayerShellQt::Window *m_layerWindow = nullptr; - QString m_krunnerText; -+ QFuture m_krunnerFuture; - - // KRunner config - KConfigWatcher::Ptr m_configWatcher; --- -GitLab - - -From b3d97405cb5b0ee9859576309bd826dea6b74274 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Wed, 17 Sep 2025 09:59:07 +0300 -Subject: [PATCH 2/2] shell: Use org.freedesktop.Application.ActivateAction to - pass xdg activation token to krunner - ---- - krunner/dbus/org.kde.krunner.App.xml | 4 ---- - krunner/main.cpp | 4 +++- - krunner/view.cpp | 14 ------------ - krunner/view.h | 1 - - shell/CMakeLists.txt | 4 ---- - shell/desktopview.cpp | 32 +++++++++++++++++++++++----- - 6 files changed, 30 insertions(+), 29 deletions(-) - -diff --git a/krunner/dbus/org.kde.krunner.App.xml b/krunner/dbus/org.kde.krunner.App.xml -index e6926b1b63a..6553e9a1b56 100644 ---- a/krunner/dbus/org.kde.krunner.App.xml -+++ b/krunner/dbus/org.kde.krunner.App.xml -@@ -17,9 +17,5 @@ - - - -- -- -- -- - - -diff --git a/krunner/main.cpp b/krunner/main.cpp -index 514c34b032f..02174bb2cda 100644 ---- a/krunner/main.cpp -+++ b/krunner/main.cpp -@@ -136,9 +136,11 @@ int main(int argc, char **argv) - parser.parse(arguments); - updateVisibility(); - }); -- QObject::connect(&service, &KDBusService::activateActionRequested, &view, [&view](const QString &action) { -+ QObject::connect(&service, &KDBusService::activateActionRequested, &view, [&view](const QString &action, const QVariant ¶meter) { - if (action == QLatin1String("RunClipboard")) { - view.displayWithClipboardContents(); -+ } else if (action == QLatin1String("Query")) { -+ view.query(parameter.toString()); - } - }); - -diff --git a/krunner/view.cpp b/krunner/view.cpp -index bb7edd5d654..afefe9ab486 100644 ---- a/krunner/view.cpp -+++ b/krunner/view.cpp -@@ -263,20 +263,6 @@ void View::querySingleRunner(const QString &runnerName, const QString &term) - m_engine->rootObject()->setProperty("query", term); - } - --void View::queryWithActivationToken(const QString &term, const QString &activationToken) --{ -- qputenv("XDG_ACTIVATION_TOKEN", activationToken.toUtf8()); -- -- if (!isVisible()) { -- display(); -- } else { -- requestActivate(); -- } -- -- m_engine->rootObject()->setProperty("singleRunner", QString()); -- m_engine->rootObject()->setProperty("query", term); --} -- - bool View::pinned() const - { - return m_pinned; -diff --git a/krunner/view.h b/krunner/view.h -index af1d477d6f3..979c6d3b483 100644 ---- a/krunner/view.h -+++ b/krunner/view.h -@@ -93,7 +93,6 @@ public Q_SLOTS: - void displayWithClipboardContents(); - void query(const QString &term); - void querySingleRunner(const QString &runnerName, const QString &term); -- void queryWithActivationToken(const QString &term, const QString &activationToken); - - protected Q_SLOTS: - void loadConfig(); -diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt -index 96b91888f1b..814413ac827 100644 ---- a/shell/CMakeLists.txt -+++ b/shell/CMakeLists.txt -@@ -92,10 +92,6 @@ qt6_generate_wayland_protocol_client_sources(plasmashell - ${PLASMA_WAYLAND_PROTOCOLS_DIR}/plasma-shell.xml - ) - --set(krunner_xml ${plasma-workspace_SOURCE_DIR}/krunner/dbus/org.kde.krunner.App.xml) --qt_add_dbus_interface(plasma_shell_SRCS ${krunner_xml} krunner_interface) -- -- - target_sources(plasmashell PRIVATE ${plasma_shell_SRCS}) - - target_link_libraries(plasmashell PRIVATE -diff --git a/shell/desktopview.cpp b/shell/desktopview.cpp -index 744176e6d3e..9c3baa84b91 100644 ---- a/shell/desktopview.cpp -+++ b/shell/desktopview.cpp -@@ -6,12 +6,12 @@ - - #include "desktopview.h" - #include "containmentconfigview.h" --#include "krunner_interface.h" - #include "screenpool.h" - #include "shellcorona.h" - - #include - #include -+#include - #include - #include - #include -@@ -461,12 +461,34 @@ bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) - } - m_krunnerFuture = fetchActivationToken(this); - m_krunnerFuture.then(this, [this](const QString &token) { -- org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); -- krunner.queryWithActivationToken(m_krunnerText, token); -+ auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.krunner"), -+ QStringLiteral("/org/kde/krunner"), -+ QStringLiteral("org.freedesktop.Application"), -+ QStringLiteral("ActivateAction")); -+ message.setArguments({ -+ QStringLiteral("Query"), -+ QVariantList{ -+ m_krunnerText, -+ }, -+ QVariantMap{ -+ {QStringLiteral("activation-token"), token}, -+ }, -+ }); -+ QDBusConnection::sessionBus().asyncCall(message); - }); - } else { -- org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); -- krunner.query(m_krunnerText); -+ auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.krunner"), -+ QStringLiteral("/org/kde/krunner"), -+ QStringLiteral("org.freedesktop.Application"), -+ QStringLiteral("ActivateAction")); -+ message.setArguments({ -+ QStringLiteral("Query"), -+ QVariantList{ -+ m_krunnerText, -+ }, -+ QVariantMap{}, -+ }); -+ QDBusConnection::sessionBus().asyncCall(message); - } - return true; - } --- -GitLab - diff --git a/roles/kde/patches/spectacle/patches.txt b/roles/kde/patches/spectacle/patches.txt deleted file mode 100644 index 587da02..0000000 --- a/roles/kde/patches/spectacle/patches.txt +++ /dev/null @@ -1,3 +0,0 @@ -Plasma 6.5.0: - -Pr 460 https://invent.kde.org/plasma/spectacle/-/merge_requests/460 diff --git a/roles/kde/patches/spectacle/pr460.patch b/roles/kde/patches/spectacle/pr460.patch deleted file mode 100644 index 63c6cfa..0000000 --- a/roles/kde/patches/spectacle/pr460.patch +++ /dev/null @@ -1,228 +0,0 @@ -From 97f209559c00acc1ea6d0736bb318ac0254a3e37 Mon Sep 17 00:00:00 2001 -From: Noah Davis -Date: Wed, 4 Jun 2025 16:06:06 -0400 -Subject: [PATCH 1/2] Say which shortcut can stop recording in recording - notification - -It will say Meta+R by default, but will show the shortcut used to initiate the recording instead if Meta+R isn't assigned to region recording. - -BUG: 505081 ---- - src/Platforms/VideoPlatform.cpp | 16 +++++++++++++++ - src/Platforms/VideoPlatform.h | 4 ++++ - src/Platforms/VideoPlatformWayland.cpp | 6 ++++-- - src/SpectacleCore.cpp | 28 +++++++++++++++++++++++++- - 4 files changed, 51 insertions(+), 3 deletions(-) - -diff --git a/src/Platforms/VideoPlatform.cpp b/src/Platforms/VideoPlatform.cpp -index 592539048..333692326 100644 ---- a/src/Platforms/VideoPlatform.cpp -+++ b/src/Platforms/VideoPlatform.cpp -@@ -69,6 +69,11 @@ VideoPlatform::RecordingState VideoPlatform::recordingState() const - return m_recordingState; - } - -+VideoPlatform::RecordingMode VideoPlatform::recordingMode() const -+{ -+ return m_recordingMode; -+} -+ - void VideoPlatform::setRecordingState(RecordingState state) - { - if (state == m_recordingState) { -@@ -91,9 +96,20 @@ void VideoPlatform::setRecordingState(RecordingState state) - m_elapsedTimer.invalidate(); - m_basicTimer.stop(); - } -+ if (state != RecordingState::Recording) { -+ setRecordingMode(NoRecordingModes); -+ } - m_recordingState = state; - Q_EMIT recordingStateChanged(state); - Q_EMIT recordedTimeChanged(); - } - -+void VideoPlatform::setRecordingMode(RecordingMode mode) -+{ -+ if (m_recordingMode == mode) { -+ return; -+ } -+ m_recordingMode = mode; -+} -+ - #include "moc_VideoPlatform.cpp" -diff --git a/src/Platforms/VideoPlatform.h b/src/Platforms/VideoPlatform.h -index 4f5fba720..eea81e32a 100644 ---- a/src/Platforms/VideoPlatform.h -+++ b/src/Platforms/VideoPlatform.h -@@ -129,8 +129,11 @@ public: - - RecordingState recordingState() const; - -+ RecordingMode recordingMode() const; -+ - protected: - void setRecordingState(RecordingState state); -+ void setRecordingMode(RecordingMode mode); - void timerEvent(QTimerEvent *event) override; - - public Q_SLOTS: -@@ -157,6 +160,7 @@ private: - QBasicTimer m_basicTimer; - qint64 m_recordedTime = 0; - RecordingState m_recordingState = RecordingState::NotRecording; -+ RecordingMode m_recordingMode = RecordingMode::NoRecordingModes; - }; - - Q_DECLARE_OPERATORS_FOR_FLAGS(VideoPlatform::RecordingModes) -diff --git a/src/Platforms/VideoPlatformWayland.cpp b/src/Platforms/VideoPlatformWayland.cpp -index 648f8adbf..984ede0eb 100644 ---- a/src/Platforms/VideoPlatformWayland.cpp -+++ b/src/Platforms/VideoPlatformWayland.cpp -@@ -245,11 +245,12 @@ void VideoPlatformWayland::startRecording(const QUrl &fileUrl, RecordingMode rec - m_recorder->setNodeId(0); - - Q_ASSERT(stream); -- connect(stream, &ScreencastingStream::created, this, [this, stream] { -+ connect(stream, &ScreencastingStream::created, this, [this, stream, recordingMode] { - m_recorder->setNodeId(stream->nodeId()); - if (!m_recorder->output().isEmpty()) { - m_recorder->start(); - } -+ setRecordingMode(recordingMode); - setRecordingState(VideoPlatform::RecordingState::Recording); - }); - connect(stream, &ScreencastingStream::failed, this, [this](const QString &error) { -@@ -302,7 +303,7 @@ void VideoPlatformWayland::startRecording(const QUrl &fileUrl, RecordingMode rec - m_recorder->start(); - } - -- connect(m_recorder.get(), &PipeWireRecord::stateChanged, this, [this] { -+ connect(m_recorder.get(), &PipeWireRecord::stateChanged, this, [this, recordingMode] { - if (m_recorder->state() == PipeWireRecord::Idle) { - m_memoryTimer.stop(); - if (recordingState() != RecordingState::NotRecording && recordingState() != RecordingState::Finished) { -@@ -311,6 +312,7 @@ void VideoPlatformWayland::startRecording(const QUrl &fileUrl, RecordingMode rec - } - } else if (m_recorder->state() == PipeWireRecord::Recording) { - m_memoryTimer.start(5000, Qt::CoarseTimer, this); -+ setRecordingMode(recordingMode); - setRecordingState(VideoPlatform::RecordingState::Recording); - } else if (m_recorder->state() == PipeWireRecord::Rendering) { - m_memoryTimer.stop(); -diff --git a/src/SpectacleCore.cpp b/src/SpectacleCore.cpp -index 8033751c9..aa2e8c6e1 100644 ---- a/src/SpectacleCore.cpp -+++ b/src/SpectacleCore.cpp -@@ -281,7 +281,33 @@ SpectacleCore::SpectacleCore(QObject *parent) - SpectacleCore::instance()->finishRecording(); - }); - const auto messageTitle = i18nc("recording notification title", "Spectacle is Recording"); -- const auto messageBody = i18nc("recording notification message", "Click the system tray icon to finish recording"); -+ auto getSimpleDefaultShortcut = [] { -+ const auto shortcuts = KGlobalAccel::self()->shortcut(ShortcutActions::self()->recordRegionAction()); -+ if (shortcuts.contains(QKeySequence{Qt::META | Qt::Key_R})) { -+ return QKeySequence{Qt::META | Qt::Key_R}; -+ } -+ return QKeySequence{}; -+ }; -+ auto getShortcut = [](const auto &list) { -+ auto it = std::find_if(list.cbegin(), list.cend(), [](const QKeySequence &shortcut) { -+ return !shortcut.isEmpty(); -+ }); -+ return it != list.cend() ? *it : QKeySequence{}; -+ }; -+ QKeySequence stopShortcut = getSimpleDefaultShortcut(); -+ if (stopShortcut.isEmpty()) { -+ auto mode = m_videoPlatform->recordingMode(); -+ if (mode == VideoPlatform::Screen) { -+ stopShortcut = getShortcut(KGlobalAccel::self()->shortcut(ShortcutActions::self()->recordScreenAction())); -+ } else if (mode == VideoPlatform::Window) { -+ stopShortcut = getShortcut(KGlobalAccel::self()->shortcut(ShortcutActions::self()->recordWindowAction())); -+ } else if (mode == VideoPlatform::Region) { -+ stopShortcut = getShortcut(KGlobalAccel::self()->shortcut(ShortcutActions::self()->recordRegionAction())); -+ } -+ } -+ const auto messageBody = stopShortcut.isEmpty() -+ ? i18nc("recording notification message without shortcut", "To finish the recording, click the pulsing red System Tray icon.") -+ : xi18nc("recording notification message with shortcut", "To finish the recording, click the pulsing red System Tray icon or press %1.", stopShortcut.toString(QKeySequence::NativeText)); - auto notification = new KNotification(u"notification"_s, KNotification::CloseOnTimeout | KNotification::DefaultEvent, this); - notification->setTitle(messageTitle); - notification->setText(messageBody); --- -GitLab - - -From 7fd2fe158408b6285f9855f7fcf34e77d4ecb764 Mon Sep 17 00:00:00 2001 -From: Noah Davis -Date: Thu, 12 Jun 2025 16:12:48 -0400 -Subject: [PATCH 2/2] Rename shortcuts to show that they can start or stop - recording - -BUG: 505081 ---- - desktop/org.kde.spectacle.desktop.cmake | 6 +++--- - src/ShortcutActions.cpp | 6 +++--- - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/desktop/org.kde.spectacle.desktop.cmake b/desktop/org.kde.spectacle.desktop.cmake -index 4e36b18e6..800fcb62b 100644 ---- a/desktop/org.kde.spectacle.desktop.cmake -+++ b/desktop/org.kde.spectacle.desktop.cmake -@@ -474,7 +474,7 @@ Exec=${KDE_INSTALL_FULL_BINDIR}/spectacle -u - X-KDE-Shortcuts=Meta+Ctrl+Print - - [Desktop Action RecordRegion] --Name=Record Rectangular Region -+Name=Start/Stop Region Recording - Name[ar]=يسجل منطقة مستطيلة - Name[az]=Düzbucaqlı sahəni yazmaq - Name[bg]=Заснемане на правоъгълен регион -@@ -522,7 +522,7 @@ Exec=${KDE_INSTALL_FULL_BINDIR}/spectacle -R region - X-KDE-Shortcuts=Meta+Shift+R,Meta+R - - [Desktop Action RecordScreen] --Name=Record Screen -+Name=Start/Stop Screen Recording - Name[ar]=سجّل الشاشة - Name[az]=Ekranı yazmaq - Name[bg]=Запис на екрана -@@ -570,7 +570,7 @@ Exec=${KDE_INSTALL_FULL_BINDIR}/spectacle -R screen - X-KDE-Shortcuts=Meta+Alt+R - - [Desktop Action RecordWindow] --Name=Record Window -+Name=Start/Stop Window Recording - Name[ar]=سجل النافذة - Name[az]=Pəncərəni yazmaq - Name[bg]=Запис на прозорец -diff --git a/src/ShortcutActions.cpp b/src/ShortcutActions.cpp -index ee73bcfe5..a1464d06d 100644 ---- a/src/ShortcutActions.cpp -+++ b/src/ShortcutActions.cpp -@@ -73,19 +73,19 @@ ShortcutActions::ShortcutActions() - mActions.addAction(action->objectName(), action); - } - { -- QAction *action = new QAction(i18nc("@action global shortcut", "Record Screen"), &mActions); -+ QAction *action = new QAction(i18nc("@action global shortcut", "Start/Stop Screen Recording"), &mActions); - action->setObjectName(u"RecordScreen"_s); - action->setProperty("isConfigurationAction", true); - mActions.addAction(action->objectName(), action); - } - { -- QAction *action = new QAction(i18nc("@action global shortcut", "Record Window"), &mActions); -+ QAction *action = new QAction(i18nc("@action global shortcut", "Start/Stop Window Recording"), &mActions); - action->setObjectName(u"RecordWindow"_s); - action->setProperty("isConfigurationAction", true); - mActions.addAction(action->objectName(), action); - } - { -- QAction *action = new QAction(i18nc("@action global shortcut", "Record Rectangular Region"), &mActions); -+ QAction *action = new QAction(i18nc("@action global shortcut", "Start/Stop Region Recording"), &mActions); - action->setObjectName(u"RecordRegion"_s); - action->setProperty("isConfigurationAction", true); - mActions.addAction(action->objectName(), action); --- -GitLab - From 65eb51865154dfc10dc0602ec2b53ef037e705fa Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 24 Oct 2025 01:08:59 +0200 Subject: [PATCH 1062/1125] Roles/gaming: fix emulator build issues --- flake.nix | 2 ++ nixpkgs-patches/pr454957.patch | 36 ++++++++++++++++++++ nixpkgs-patches/pr454958.patch | 57 ++++++++++++++++++++++++++++++++ roles/gaming/programs/azahar.nix | 28 ++++++++-------- 4 files changed, 110 insertions(+), 13 deletions(-) create mode 100644 nixpkgs-patches/pr454957.patch create mode 100644 nixpkgs-patches/pr454958.patch diff --git a/flake.nix b/flake.nix index 0392399..2ac5d64 100644 --- a/flake.nix +++ b/flake.nix @@ -101,6 +101,8 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ + ./nixpkgs-patches/pr454957.patch + ./nixpkgs-patches/pr454958.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr454957.patch b/nixpkgs-patches/pr454957.patch new file mode 100644 index 0000000..349c4bf --- /dev/null +++ b/nixpkgs-patches/pr454957.patch @@ -0,0 +1,36 @@ +From 75c9e6694415682eea0f73a87a269502bc7a7048 Mon Sep 17 00:00:00 2001 +From: Eric Helgeson +Date: Thu, 23 Oct 2025 11:23:15 -0500 +Subject: [PATCH] rpcs3: Add upstream patch for Qt 6.10+ + +--- + pkgs/by-name/rp/rpcs3/package.nix | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/pkgs/by-name/rp/rpcs3/package.nix b/pkgs/by-name/rp/rpcs3/package.nix +index ed68bcb2ec19c..109f71454fe25 100644 +--- a/pkgs/by-name/rp/rpcs3/package.nix ++++ b/pkgs/by-name/rp/rpcs3/package.nix +@@ -1,6 +1,7 @@ + { + lib, + stdenv, ++ fetchpatch, + fetchFromGitHub, + nix-update-script, + cmake, +@@ -148,6 +149,14 @@ stdenv.mkDerivation (finalAttrs: { + qtwayland + ]; + ++ patches = [ ++ (fetchpatch { ++ name = "fix-build-qt-6.10.patch"; ++ url = "https://github.com/RPCS3/rpcs3/commit/038ee090b731bf63917371a3586c2f7d7cf4e585.patch"; ++ hash = "sha256-jTIxsheG9b9zp0JEeWQ73BunAXmEIg5tj4SrWBfdHy8="; ++ }) ++ ]; ++ + doInstallCheck = true; + + preFixup = '' diff --git a/nixpkgs-patches/pr454958.patch b/nixpkgs-patches/pr454958.patch new file mode 100644 index 0000000..9d7fb04 --- /dev/null +++ b/nixpkgs-patches/pr454958.patch @@ -0,0 +1,57 @@ +From dd207a94bea4679948e37183fb6ad89c40dd79f1 Mon Sep 17 00:00:00 2001 +From: Marcin Serwin +Date: Wed, 15 Oct 2025 15:18:48 +0000 +Subject: [PATCH] pcsx2: fix build with Qt 6.10 + +Signed-off-by: Marcin Serwin +--- + pkgs/by-name/pc/pcsx2/fix-qt-6.10.patch | 25 +++++++++++++++++++++++++ + pkgs/by-name/pc/pcsx2/package.nix | 3 +++ + 2 files changed, 28 insertions(+) + create mode 100644 pkgs/by-name/pc/pcsx2/fix-qt-6.10.patch + +diff --git a/pkgs/by-name/pc/pcsx2/fix-qt-6.10.patch b/pkgs/by-name/pc/pcsx2/fix-qt-6.10.patch +new file mode 100644 +index 0000000000000..06341689c4537 +--- /dev/null ++++ b/pkgs/by-name/pc/pcsx2/fix-qt-6.10.patch +@@ -0,0 +1,25 @@ ++diff --git a/cmake/SearchForStuff.cmake b/cmake/SearchForStuff.cmake ++index 504b7a3..100a024 100644 ++--- a/cmake/SearchForStuff.cmake +++++ b/cmake/SearchForStuff.cmake ++@@ -107,7 +107,7 @@ disable_compiler_warnings_for_target(cubeb) ++ disable_compiler_warnings_for_target(speex) ++ ++ # Find the Qt components that we need. ++-find_package(Qt6 6.7.3 COMPONENTS CoreTools Core GuiTools Gui WidgetsTools Widgets LinguistTools REQUIRED) +++find_package(Qt6 6.7.3 COMPONENTS CoreTools Core CorePrivate GuiTools Gui GuiPrivate WidgetsTools Widgets WidgetsPrivate LinguistTools REQUIRED) ++ ++ if(WIN32) ++ add_subdirectory(3rdparty/rainterface EXCLUDE_FROM_ALL) ++diff --git a/pcsx2-qt/CMakeLists.txt b/pcsx2-qt/CMakeLists.txt ++index a62df95..4883c64 100644 ++--- a/pcsx2-qt/CMakeLists.txt +++++ b/pcsx2-qt/CMakeLists.txt ++@@ -266,6 +266,7 @@ target_link_libraries(pcsx2-qt PRIVATE ++ Qt6::Core ++ Qt6::Gui ++ Qt6::Widgets +++ Qt6::GuiPrivate ++ KDAB::kddockwidgets ++ ) ++ +diff --git a/pkgs/by-name/pc/pcsx2/package.nix b/pkgs/by-name/pc/pcsx2/package.nix +index 16e9aeabf1f69..daddd2f377eb1 100644 +--- a/pkgs/by-name/pc/pcsx2/package.nix ++++ b/pkgs/by-name/pc/pcsx2/package.nix +@@ -63,6 +63,9 @@ llvmPackages.stdenv.mkDerivation (finalAttrs: { + ./0000-define-rev.patch + + ./remove-cubeb-vendor.patch ++ ++ # Based on https://github.com/PCSX2/pcsx2/commit/8dffc857079e942ca77b091486c20c3c6530e4ed which doesn't apply cleanly ++ ./fix-qt-6.10.patch + ]; + + cmakeFlags = [ diff --git a/roles/gaming/programs/azahar.nix b/roles/gaming/programs/azahar.nix index 2b88164..a74b36d 100644 --- a/roles/gaming/programs/azahar.nix +++ b/roles/gaming/programs/azahar.nix @@ -1,17 +1,19 @@ {pkgs, ...}: { - # nixpkgs.overlays = [ - # ( - # final: prev: { - # azahar = prev.azahar.overrideAttrs (old: { - # version = "2120.3"; - # src = final.fetchzip { - # url = "https://github.com/azahar-emu/azahar/releases/download/2120.3/azahar-unified-source-20250414-00e3bbb.tar.xz"; - # hash = "sha256-3QKicmpmWDM7x9GDJ8sxm2Xu+0Yfho4LkSWMp+ixzRk="; - # }; - # }); - # } - # ) - # ]; + nixpkgs.overlays = [ + ( + final: prev: { + azahar = prev.azahar.overrideAttrs (old: { + patches = old.patches ++ [( + final.fetchpatch { + name = "fix-build-qt-6.10.patch"; + url = "https://github.com/azahar-emu/azahar/pull/1441.patch"; + hash = "sha256-PTnhFpuGoF6qPIwupdcRo6s+Tzhj0JR0QwoCgxgGxAw="; + } + )]; + }); + } + ) + ]; home-manager.users.toast = { home.packages = [pkgs.azahar]; }; From 1b620d556b791519da882d9dc8d5db49b4a32a3f Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 25 Oct 2025 00:14:37 +0200 Subject: [PATCH 1063/1125] Kde/kwin: enable overlays --- roles/kde/programs/kwin.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/kde/programs/kwin.nix b/roles/kde/programs/kwin.nix index 5a3e792..1e4f3ae 100644 --- a/roles/kde/programs/kwin.nix +++ b/roles/kde/programs/kwin.nix @@ -2,6 +2,7 @@ environment.plasma6.excludePackages = [pkgs.kdePackages.kwin-x11]; environment.variables = { KWIN_WAYLAND_SUPPORT_XX_PIP_V1 = 1; + KWIN_USE_OVERLAYS = 1; }; home-manager.users.toast = { programs.plasma = { From 91d0d875ea1f04a756623b5f7d5d7e1335f88973 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 25 Oct 2025 00:26:05 +0200 Subject: [PATCH 1064/1125] Desktop/firefox: disable AI features --- roles/desktop/programs/firefox.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index aac3918..1e80585 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -6,6 +6,12 @@ enable = true; policies = { DisableTelemetry = true; + GenerativeAI = { + Chatbot = false; + LinkPreviews = false; + TabGroups = false; + Locked = true; + }; # You need these for Spotify EncryptedMediaExtensions.Enabled = true; ExtensionSettings = { @@ -39,6 +45,10 @@ Value = true; Status = "locked"; }; + "browser.ml.chat.page" = { + Value = false; + Status = "Locked"; + }; }; PromptForDownloadLocation = true; # I use an external password manager, so the built in one just bothers me From 13c1d5864dc944653e9d48130ce9e745ac5bfb90 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 26 Oct 2025 12:47:08 +0100 Subject: [PATCH 1065/1125] Flake: add nixpkgs patch to fix rtkit --- flake.nix | 1 + nixpkgs-patches/pr455128.patch | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 nixpkgs-patches/pr455128.patch diff --git a/flake.nix b/flake.nix index 2ac5d64..3eaf93a 100644 --- a/flake.nix +++ b/flake.nix @@ -103,6 +103,7 @@ patches = [ ./nixpkgs-patches/pr454957.patch ./nixpkgs-patches/pr454958.patch + ./nixpkgs-patches/pr455128.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr455128.patch b/nixpkgs-patches/pr455128.patch new file mode 100644 index 0000000..c44ebb6 --- /dev/null +++ b/nixpkgs-patches/pr455128.patch @@ -0,0 +1,22 @@ +From 2e9d838795edcec2b79dda0284acf27ee34b1ecc Mon Sep 17 00:00:00 2001 +From: h7x4 +Date: Fri, 24 Oct 2025 14:24:14 +0900 +Subject: [PATCH] nixos/rtkit: fix hardening + +--- + nixos/modules/security/rtkit.nix | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/nixos/modules/security/rtkit.nix b/nixos/modules/security/rtkit.nix +index d7c6df17f03b9..f2cd256468da9 100644 +--- a/nixos/modules/security/rtkit.nix ++++ b/nixos/modules/security/rtkit.nix +@@ -64,7 +64,7 @@ in + ]; + + # Needs to verify the user of the processes. +- PrivateUsers = "full"; ++ PrivateUsers = false; + # Needs to access other processes to modify their scheduling modes. + ProcSubset = "all"; + ProtectProc = "default"; From c8d487d374d9eb966a5a5b71d6a0bc67dd10a4ee Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 26 Oct 2025 19:38:06 +0100 Subject: [PATCH 1066/1125] Gaming/steam: install sgdboop, move comment to place --- roles/gaming/programs/steam.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/gaming/programs/steam.nix b/roles/gaming/programs/steam.nix index afbfb67..fc59c63 100644 --- a/roles/gaming/programs/steam.nix +++ b/roles/gaming/programs/steam.nix @@ -19,14 +19,15 @@ then true else false; - # Celeste mod manager home-manager.users.toast = { systemd.user.tmpfiles.rules = [ "r '/%h/.local/share/applications/Steam Linux Runtime *.desktop'" "r '/%h/.local/share/applications/Proton *.desktop'" ]; services.flatpak.packages = [ + # Celeste mod manager "io.github.everestapi.Olympus" ]; + home.packages = [pkgs.sgdboop]; }; } From 74175100c76d83f62edaaec77497b180d755d2d2 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 26 Oct 2025 19:41:18 +0100 Subject: [PATCH 1067/1125] Gaming/steam: open firewall for local network game transfers --- roles/gaming/programs/steam.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/gaming/programs/steam.nix b/roles/gaming/programs/steam.nix index fc59c63..c6e143f 100644 --- a/roles/gaming/programs/steam.nix +++ b/roles/gaming/programs/steam.nix @@ -5,6 +5,7 @@ }: { programs.steam = { enable = true; + localNetworkGameTransfers.openFirewall = true; # Doubt that I'll use it, but I'll enable it anyways remotePlay.openFirewall = true; From 4da3beb168e731cb133d4e85cfb2503b8c93f887 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 28 Oct 2025 19:03:26 +0100 Subject: [PATCH 1068/1125] Desktop: add tailscale system tray --- roles/desktop/services/default.nix | 1 + roles/desktop/services/tailscale.nix | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 roles/desktop/services/tailscale.nix diff --git a/roles/desktop/services/default.nix b/roles/desktop/services/default.nix index f08cc3b..6bc1d0f 100644 --- a/roles/desktop/services/default.nix +++ b/roles/desktop/services/default.nix @@ -6,5 +6,6 @@ ./pipewire.nix ./printing.nix ./networkmanager.nix + ./tailscale.nix ]; } diff --git a/roles/desktop/services/tailscale.nix b/roles/desktop/services/tailscale.nix new file mode 100644 index 0000000..8235ae8 --- /dev/null +++ b/roles/desktop/services/tailscale.nix @@ -0,0 +1,16 @@ +{pkgs, ...}: { + home-manager.users.toast = { + services.tailscale-systray = { + enable = true; + package = pkgs.tailscale.overrideAttrs { + postPatch = '' + substituteInPlace client/systray/logo.go --replace-fail \ + "color.NRGBA{0, 0, 0, 255}" "color.NRGBA{0, 0, 0, 0}" + ''; + # Only use this for the tray, so no testing is needed + # Makes the build last a lot less too + doCheck = false; + }; + }; + }; +} From d3a3617e29a627017624e13d75cbf87fbb676a9d Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 28 Oct 2025 19:13:07 +0100 Subject: [PATCH 1069/1125] Deskop/discord: enable translate plugin --- roles/desktop/programs/discord.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/desktop/programs/discord.nix b/roles/desktop/programs/discord.nix index 2373e40..ca48e5d 100644 --- a/roles/desktop/programs/discord.nix +++ b/roles/desktop/programs/discord.nix @@ -49,6 +49,7 @@ in { ShowHiddenChannels.enabled = true; ShowHiddenThings.enabled = true; SpotifyControls.enabled = true; + Translate.enabled = true; YoutubeAdblock.enabled = true; }; }; From 03b73e7090d8fbb1499b4fe26245c3ae86ace521 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 1 Nov 2025 18:43:19 +0100 Subject: [PATCH 1070/1125] Revert "Roles/gaming: fix emulator build issues" This reverts commit 65eb51865154dfc10dc0602ec2b53ef037e705fa. --- flake.nix | 2 -- nixpkgs-patches/pr454957.patch | 36 -------------------- nixpkgs-patches/pr454958.patch | 57 -------------------------------- roles/gaming/programs/azahar.nix | 28 ++++++++-------- 4 files changed, 13 insertions(+), 110 deletions(-) delete mode 100644 nixpkgs-patches/pr454957.patch delete mode 100644 nixpkgs-patches/pr454958.patch diff --git a/flake.nix b/flake.nix index 3eaf93a..630bad0 100644 --- a/flake.nix +++ b/flake.nix @@ -101,8 +101,6 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/pr454957.patch - ./nixpkgs-patches/pr454958.patch ./nixpkgs-patches/pr455128.patch ]; }; diff --git a/nixpkgs-patches/pr454957.patch b/nixpkgs-patches/pr454957.patch deleted file mode 100644 index 349c4bf..0000000 --- a/nixpkgs-patches/pr454957.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 75c9e6694415682eea0f73a87a269502bc7a7048 Mon Sep 17 00:00:00 2001 -From: Eric Helgeson -Date: Thu, 23 Oct 2025 11:23:15 -0500 -Subject: [PATCH] rpcs3: Add upstream patch for Qt 6.10+ - ---- - pkgs/by-name/rp/rpcs3/package.nix | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/pkgs/by-name/rp/rpcs3/package.nix b/pkgs/by-name/rp/rpcs3/package.nix -index ed68bcb2ec19c..109f71454fe25 100644 ---- a/pkgs/by-name/rp/rpcs3/package.nix -+++ b/pkgs/by-name/rp/rpcs3/package.nix -@@ -1,6 +1,7 @@ - { - lib, - stdenv, -+ fetchpatch, - fetchFromGitHub, - nix-update-script, - cmake, -@@ -148,6 +149,14 @@ stdenv.mkDerivation (finalAttrs: { - qtwayland - ]; - -+ patches = [ -+ (fetchpatch { -+ name = "fix-build-qt-6.10.patch"; -+ url = "https://github.com/RPCS3/rpcs3/commit/038ee090b731bf63917371a3586c2f7d7cf4e585.patch"; -+ hash = "sha256-jTIxsheG9b9zp0JEeWQ73BunAXmEIg5tj4SrWBfdHy8="; -+ }) -+ ]; -+ - doInstallCheck = true; - - preFixup = '' diff --git a/nixpkgs-patches/pr454958.patch b/nixpkgs-patches/pr454958.patch deleted file mode 100644 index 9d7fb04..0000000 --- a/nixpkgs-patches/pr454958.patch +++ /dev/null @@ -1,57 +0,0 @@ -From dd207a94bea4679948e37183fb6ad89c40dd79f1 Mon Sep 17 00:00:00 2001 -From: Marcin Serwin -Date: Wed, 15 Oct 2025 15:18:48 +0000 -Subject: [PATCH] pcsx2: fix build with Qt 6.10 - -Signed-off-by: Marcin Serwin ---- - pkgs/by-name/pc/pcsx2/fix-qt-6.10.patch | 25 +++++++++++++++++++++++++ - pkgs/by-name/pc/pcsx2/package.nix | 3 +++ - 2 files changed, 28 insertions(+) - create mode 100644 pkgs/by-name/pc/pcsx2/fix-qt-6.10.patch - -diff --git a/pkgs/by-name/pc/pcsx2/fix-qt-6.10.patch b/pkgs/by-name/pc/pcsx2/fix-qt-6.10.patch -new file mode 100644 -index 0000000000000..06341689c4537 ---- /dev/null -+++ b/pkgs/by-name/pc/pcsx2/fix-qt-6.10.patch -@@ -0,0 +1,25 @@ -+diff --git a/cmake/SearchForStuff.cmake b/cmake/SearchForStuff.cmake -+index 504b7a3..100a024 100644 -+--- a/cmake/SearchForStuff.cmake -++++ b/cmake/SearchForStuff.cmake -+@@ -107,7 +107,7 @@ disable_compiler_warnings_for_target(cubeb) -+ disable_compiler_warnings_for_target(speex) -+ -+ # Find the Qt components that we need. -+-find_package(Qt6 6.7.3 COMPONENTS CoreTools Core GuiTools Gui WidgetsTools Widgets LinguistTools REQUIRED) -++find_package(Qt6 6.7.3 COMPONENTS CoreTools Core CorePrivate GuiTools Gui GuiPrivate WidgetsTools Widgets WidgetsPrivate LinguistTools REQUIRED) -+ -+ if(WIN32) -+ add_subdirectory(3rdparty/rainterface EXCLUDE_FROM_ALL) -+diff --git a/pcsx2-qt/CMakeLists.txt b/pcsx2-qt/CMakeLists.txt -+index a62df95..4883c64 100644 -+--- a/pcsx2-qt/CMakeLists.txt -++++ b/pcsx2-qt/CMakeLists.txt -+@@ -266,6 +266,7 @@ target_link_libraries(pcsx2-qt PRIVATE -+ Qt6::Core -+ Qt6::Gui -+ Qt6::Widgets -++ Qt6::GuiPrivate -+ KDAB::kddockwidgets -+ ) -+ -diff --git a/pkgs/by-name/pc/pcsx2/package.nix b/pkgs/by-name/pc/pcsx2/package.nix -index 16e9aeabf1f69..daddd2f377eb1 100644 ---- a/pkgs/by-name/pc/pcsx2/package.nix -+++ b/pkgs/by-name/pc/pcsx2/package.nix -@@ -63,6 +63,9 @@ llvmPackages.stdenv.mkDerivation (finalAttrs: { - ./0000-define-rev.patch - - ./remove-cubeb-vendor.patch -+ -+ # Based on https://github.com/PCSX2/pcsx2/commit/8dffc857079e942ca77b091486c20c3c6530e4ed which doesn't apply cleanly -+ ./fix-qt-6.10.patch - ]; - - cmakeFlags = [ diff --git a/roles/gaming/programs/azahar.nix b/roles/gaming/programs/azahar.nix index a74b36d..2b88164 100644 --- a/roles/gaming/programs/azahar.nix +++ b/roles/gaming/programs/azahar.nix @@ -1,19 +1,17 @@ {pkgs, ...}: { - nixpkgs.overlays = [ - ( - final: prev: { - azahar = prev.azahar.overrideAttrs (old: { - patches = old.patches ++ [( - final.fetchpatch { - name = "fix-build-qt-6.10.patch"; - url = "https://github.com/azahar-emu/azahar/pull/1441.patch"; - hash = "sha256-PTnhFpuGoF6qPIwupdcRo6s+Tzhj0JR0QwoCgxgGxAw="; - } - )]; - }); - } - ) - ]; + # nixpkgs.overlays = [ + # ( + # final: prev: { + # azahar = prev.azahar.overrideAttrs (old: { + # version = "2120.3"; + # src = final.fetchzip { + # url = "https://github.com/azahar-emu/azahar/releases/download/2120.3/azahar-unified-source-20250414-00e3bbb.tar.xz"; + # hash = "sha256-3QKicmpmWDM7x9GDJ8sxm2Xu+0Yfho4LkSWMp+ixzRk="; + # }; + # }); + # } + # ) + # ]; home-manager.users.toast = { home.packages = [pkgs.azahar]; }; From d916c8f36a04089e52eb4b28fcee381bbab0aa76 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 1 Nov 2025 18:44:01 +0100 Subject: [PATCH 1071/1125] Revert "Flake: add nixpkgs patch to fix rtkit" This reverts commit 13c1d5864dc944653e9d48130ce9e745ac5bfb90. --- flake.nix | 1 - nixpkgs-patches/pr455128.patch | 22 ---------------------- 2 files changed, 23 deletions(-) delete mode 100644 nixpkgs-patches/pr455128.patch diff --git a/flake.nix b/flake.nix index 630bad0..0392399 100644 --- a/flake.nix +++ b/flake.nix @@ -101,7 +101,6 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ - ./nixpkgs-patches/pr455128.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/pr455128.patch b/nixpkgs-patches/pr455128.patch deleted file mode 100644 index c44ebb6..0000000 --- a/nixpkgs-patches/pr455128.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 2e9d838795edcec2b79dda0284acf27ee34b1ecc Mon Sep 17 00:00:00 2001 -From: h7x4 -Date: Fri, 24 Oct 2025 14:24:14 +0900 -Subject: [PATCH] nixos/rtkit: fix hardening - ---- - nixos/modules/security/rtkit.nix | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/nixos/modules/security/rtkit.nix b/nixos/modules/security/rtkit.nix -index d7c6df17f03b9..f2cd256468da9 100644 ---- a/nixos/modules/security/rtkit.nix -+++ b/nixos/modules/security/rtkit.nix -@@ -64,7 +64,7 @@ in - ]; - - # Needs to verify the user of the processes. -- PrivateUsers = "full"; -+ PrivateUsers = false; - # Needs to access other processes to modify their scheduling modes. - ProcSubset = "all"; - ProtectProc = "default"; From 392df35a1cf7a0249dac7298579c56279f73b57d Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 1 Nov 2025 21:09:14 +0100 Subject: [PATCH 1072/1125] Flake: update lock file --- flake.lock | 90 +++++++++++++++++++++++++++--------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/flake.lock b/flake.lock index ec041d0..afa94eb 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1760836749, - "narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=", + "lastModified": 1761656077, + "narHash": "sha256-lsNWuj4Z+pE7s0bd2OKicOFq9bK86JE0ZGeKJbNqb94=", "owner": "ryantm", "repo": "agenix", - "rev": "2f0f812f69f3eb4140157fe15e12739adf82e32a", + "rev": "9ba0d85de3eaa7afeab493fed622008b6e4924f5", "type": "github" }, "original": { @@ -63,11 +63,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1760953099, - "narHash": "sha256-sOKx2YcHa+lWEvaEOIGqLN2WWk1Wf5z6KM02tdfhMtw=", + "lastModified": 1761906071, + "narHash": "sha256-uq0X0KRzZkKGlkU1ARM+LWCAVvSYJZtTMpuzMO6LXRs=", "owner": "catppuccin", "repo": "nix", - "rev": "f5b21876888265d2fee7fb0640d1b66a1c1c6503", + "rev": "fd1bc7b1af0a576edb13c166c4b1f7b5c7555a73", "type": "github" }, "original": { @@ -84,11 +84,11 @@ ] }, "locked": { - "lastModified": 1761171657, - "narHash": "sha256-kLJwQUpOTs/g78o3L0aISoPZ/YvMobh+GiU3j28oBAI=", + "lastModified": 1761952154, + "narHash": "sha256-VEE54fEp0vxnmmJ5yXxnWVLfc8j5eBmZkC/VDDIGC2w=", "owner": "9001", "repo": "copyparty", - "rev": "7f5810f1a7a71f020f50439ad8391bcd92726469", + "rev": "2cc53ea15181f750b4367e6cd20dfebd0bcb3bee", "type": "github" }, "original": { @@ -222,11 +222,11 @@ ] }, "locked": { - "lastModified": 1761191301, - "narHash": "sha256-xsRL2Oyb4YRZZ1Tu4WzR2uFg1n931bH+PfLdFcqtLg8=", + "lastModified": 1761878381, + "narHash": "sha256-lCRaipHgszaFZ1Cs8fdGJguVycCisBAf2HEFgip5+xU=", "owner": "nix-community", "repo": "home-manager", - "rev": "4958aafe7b237dc1e857fb0c916efff72075048f", + "rev": "4ac96eb21c101a3e5b77ba105febc5641a8959aa", "type": "github" }, "original": { @@ -264,11 +264,11 @@ ] }, "locked": { - "lastModified": 1761202163, - "narHash": "sha256-6RySf5VQElrm7RYGWxlIkNttemDp4FF0aH+LX435G2Y=", + "lastModified": 1761748321, + "narHash": "sha256-hD5mVzmUeyVppjArdy2uVdQe/CQUR9i3WgZB05onE7A=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "47976126007d9658ca4ac4dd933bea8846170fd9", + "rev": "533db5857c9e00ca352558a928417116ee08a824", "type": "github" }, "original": { @@ -280,11 +280,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1761154581, - "narHash": "sha256-/qVkVUpT3MRxsZz9J68hLhli3VMcx8+xAbyYuTXWvfE=", - "rev": "253ed1cc05ff75703e36504244f210bc8af8e560", + "lastModified": 1761937274, + "narHash": "sha256-KlELhsSq3XbemrGyQhmGurFu7m8wOEBw+8M04L7hn7A=", + "rev": "91867941fa73afea7869b7c71ede82e5ef8927da", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/253ed1cc05ff75703e36504244f210bc8af8e560.tar.gz?rev=253ed1cc05ff75703e36504244f210bc8af8e560" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/91867941fa73afea7869b7c71ede82e5ef8927da.tar.gz?rev=91867941fa73afea7869b7c71ede82e5ef8927da" }, "original": { "type": "tarball", @@ -303,11 +303,11 @@ ] }, "locked": { - "lastModified": 1759851320, - "narHash": "sha256-n5dRAIC3/78drQtFxmQRrBLd6TKfotUnX7GWu0mAcSg=", - "rev": "7c31a18259b8358ac196cf803a26967c0fa1d3e4", + "lastModified": 1761960361, + "narHash": "sha256-FvuAw56NIVJpS3Kr8Wv9PpU4eehZMcdIVkxjStuYmqc=", + "rev": "c47f62187601ea2991b79a9bacdbfdf76cd29fbe", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/7c31a18259b8358ac196cf803a26967c0fa1d3e4.tar.gz?rev=7c31a18259b8358ac196cf803a26967c0fa1d3e4" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/c47f62187601ea2991b79a9bacdbfdf76cd29fbe.tar.gz?rev=c47f62187601ea2991b79a9bacdbfdf76cd29fbe" }, "original": { "type": "tarball", @@ -326,11 +326,11 @@ ] }, "locked": { - "lastModified": 1759851320, - "narHash": "sha256-n5dRAIC3/78drQtFxmQRrBLd6TKfotUnX7GWu0mAcSg=", - "rev": "7c31a18259b8358ac196cf803a26967c0fa1d3e4", + "lastModified": 1761960361, + "narHash": "sha256-FvuAw56NIVJpS3Kr8Wv9PpU4eehZMcdIVkxjStuYmqc=", + "rev": "c47f62187601ea2991b79a9bacdbfdf76cd29fbe", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/7c31a18259b8358ac196cf803a26967c0fa1d3e4.tar.gz?rev=7c31a18259b8358ac196cf803a26967c0fa1d3e4" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/c47f62187601ea2991b79a9bacdbfdf76cd29fbe.tar.gz?rev=c47f62187601ea2991b79a9bacdbfdf76cd29fbe" }, "original": { "type": "tarball", @@ -397,11 +397,11 @@ ] }, "locked": { - "lastModified": 1760846226, - "narHash": "sha256-xmU8kAsRprJiTGBTaGrwmjBP3AMA9ltlrxHKFuy5JWc=", + "lastModified": 1761451000, + "narHash": "sha256-qBJL6xEIjqYq9zOcG2vf2nPTeVBppNJzvO0LuQWMwMo=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "5024e1901239a76b7bf94a4cd27f3507e639d49e", + "rev": "ed6b293161b378a7368cda38659eb8d3d9a0dac4", "type": "github" }, "original": { @@ -417,11 +417,11 @@ ] }, "locked": { - "lastModified": 1760846226, - "narHash": "sha256-xmU8kAsRprJiTGBTaGrwmjBP3AMA9ltlrxHKFuy5JWc=", + "lastModified": 1761451000, + "narHash": "sha256-qBJL6xEIjqYq9zOcG2vf2nPTeVBppNJzvO0LuQWMwMo=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "5024e1901239a76b7bf94a4cd27f3507e639d49e", + "rev": "ed6b293161b378a7368cda38659eb8d3d9a0dac4", "type": "github" }, "original": { @@ -432,11 +432,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1760958188, - "narHash": "sha256-2m1S4jl+GEDtlt2QqeHil8Ny456dcGSKJAM7q3j/BFU=", + "lastModified": 1761933221, + "narHash": "sha256-rNHeoG3ZrA94jczyLSjxCtu67YYPYIlXXr0uhG3wNxM=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "d6645c340ef7d821602fd2cd199e8d1eed10afbc", + "rev": "7467f155fcba189eb088a7601f44fbef7688669b", "type": "github" }, "original": { @@ -464,11 +464,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1761016216, - "narHash": "sha256-G/iC4t/9j/52i/nm+0/4ybBmAF4hzR8CNHC75qEhjHo=", + "lastModified": 1761597516, + "narHash": "sha256-wxX7u6D2rpkJLWkZ2E932SIvDJW8+ON/0Yy8+a5vsDU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "481cf557888e05d3128a76f14c76397b7d7cc869", + "rev": "daf6dc47aa4b44791372d6139ab7b25269184d55", "type": "github" }, "original": { @@ -479,11 +479,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1761114652, - "narHash": "sha256-f/QCJM/YhrV/lavyCVz8iU3rlZun6d+dAiC3H+CDle4=", + "lastModified": 1761907660, + "narHash": "sha256-kJ8lIZsiPOmbkJypG+B5sReDXSD1KGu2VEPNqhRa/ew=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "01f116e4df6a15f4ccdffb1bcd41096869fb385c", + "rev": "2fb006b87f04c4d3bdf08cfdbc7fab9c13d94a15", "type": "github" }, "original": { @@ -494,11 +494,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1760524057, - "narHash": "sha256-EVAqOteLBFmd7pKkb0+FIUyzTF61VKi7YmvP1tw4nEw=", + "lastModified": 1761672384, + "narHash": "sha256-o9KF3DJL7g7iYMZq9SWgfS1BFlNbsm6xplRjVlOCkXI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "544961dfcce86422ba200ed9a0b00dd4b1486ec5", + "rev": "08dacfca559e1d7da38f3cf05f1f45ee9bfd213c", "type": "github" }, "original": { From 8f97bc80e3921b0dc0a5beece6990a9fd8d8ba2b Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 2 Nov 2025 00:57:49 +0100 Subject: [PATCH 1073/1125] Common/nix: remove now redundant system nixpkgs flake registry --- flake.nix | 4 ---- roles/common/programs/nix.nix | 7 ------- 2 files changed, 11 deletions(-) diff --git a/flake.nix b/flake.nix index 0392399..cb9ba84 100644 --- a/flake.nix +++ b/flake.nix @@ -155,10 +155,6 @@ pkgs.lib.nixosSystem { system = "x86_64-linux"; specialArgs = { - systemPkgs = - if stable - then nixpkgs-patched - else nixpkgs-unstable-patched; flakeSelf = self; }; modules = diff --git a/roles/common/programs/nix.nix b/roles/common/programs/nix.nix index 38fbf21..a676fbd 100755 --- a/roles/common/programs/nix.nix +++ b/roles/common/programs/nix.nix @@ -1,5 +1,4 @@ { - systemPkgs, config, lib, flakeSelf, @@ -58,12 +57,6 @@ type = "github"; }; }; - # Write the system's nixpkgs into the registry to avoid mixing nixpkgs versions - # https://dataswamp.org/~solene/2022-07-20-nixos-flakes-command-sync-with-system.html - - # Since 24.05 this is already done for nixpkgs, but it doesn't keep the patches - # so I'm keeping this around just in case - system.flake = systemPkgs; }; }; } From 2240c4e256ab3573ddb6fcc6afcb0435917238ee Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 2 Nov 2025 09:59:40 +0100 Subject: [PATCH 1074/1125] Add custom lib --- flake.nix | 1 + lib/default.nix | 8 ++++++++ lib/patches.nix | 13 +++++++++++++ 3 files changed, 22 insertions(+) create mode 100644 lib/default.nix create mode 100644 lib/patches.nix diff --git a/flake.nix b/flake.nix index cb9ba84..2f4f59e 100644 --- a/flake.nix +++ b/flake.nix @@ -157,6 +157,7 @@ specialArgs = { flakeSelf = self; }; + lib = import ./lib {nixpkgs = pkgs;}; modules = [ agenix.nixosModules.default diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..400dc18 --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,8 @@ +{nixpkgs}: +nixpkgs.lib.extend (final: prev: { + toast = let + importLib = file: import file {lib = final;}; + in { + patches = importLib ./patches.nix; + }; +}) diff --git a/lib/patches.nix b/lib/patches.nix new file mode 100644 index 0000000..4f3c1a8 --- /dev/null +++ b/lib/patches.nix @@ -0,0 +1,13 @@ +{lib}: { + /** + Get a list of patches from a path. + */ + patchesInPath = path: let + pathContents = builtins.readDir path; + filter = name: value: + (value == "regular" || value == "symlink") && lib.strings.hasSuffix ".patch" name; + filteredContents = lib.attrsets.filterAttrs filter pathContents; + patchFilenames = builtins.attrNames filteredContents; + in + builtins.map (value: lib.path.append path value) patchFilenames; +} From c914256c9785149244141e63f95f18bf546accb1 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 2 Nov 2025 13:43:13 +0100 Subject: [PATCH 1075/1125] Kde/patches: add plasma-desktop patches --- roles/kde/patches/plasma-desktop/patches.txt | 5 + roles/kde/patches/plasma-desktop/pr3256.patch | 94 +++++++++++++++++++ roles/kde/patches/plasma-desktop/pr3259.patch | 78 +++++++++++++++ roles/kde/patches/plasma-desktop/pr3269.patch | 66 +++++++++++++ 4 files changed, 243 insertions(+) create mode 100644 roles/kde/patches/plasma-desktop/patches.txt create mode 100644 roles/kde/patches/plasma-desktop/pr3256.patch create mode 100644 roles/kde/patches/plasma-desktop/pr3259.patch create mode 100644 roles/kde/patches/plasma-desktop/pr3269.patch diff --git a/roles/kde/patches/plasma-desktop/patches.txt b/roles/kde/patches/plasma-desktop/patches.txt new file mode 100644 index 0000000..50ee310 --- /dev/null +++ b/roles/kde/patches/plasma-desktop/patches.txt @@ -0,0 +1,5 @@ +Plasma 6.6.0: + +Pr 3256 https://invent.kde.org/plasma/plasma-desktop/-/merge_requests/3256 +Pr 3259 https://invent.kde.org/plasma/plasma-desktop/-/merge_requests/3259 +Pr 3269 https://invent.kde.org/plasma/plasma-desktop/-/merge_requests/3269 diff --git a/roles/kde/patches/plasma-desktop/pr3256.patch b/roles/kde/patches/plasma-desktop/pr3256.patch new file mode 100644 index 0000000..61d2a0e --- /dev/null +++ b/roles/kde/patches/plasma-desktop/pr3256.patch @@ -0,0 +1,94 @@ +From 79d010f4bcdb19d5a19d222dd3c3cb581fde891d Mon Sep 17 00:00:00 2001 +From: David Redondo +Date: Fri, 17 Oct 2025 15:15:51 +0200 +Subject: [PATCH] applets/taskmanager: Allow changing a tasks volume by + scrolling + +FEATURE:510668 +FIXED-IN:6.6 +--- + .../package/contents/config/main.xml | 1 + + .../package/contents/ui/ConfigBehavior.qml | 3 ++- + .../package/contents/ui/MouseHandler.qml | 20 +++++++++++++++++++ + 3 files changed, 23 insertions(+), 1 deletion(-) + +diff --git a/applets/taskmanager/package/contents/config/main.xml b/applets/taskmanager/package/contents/config/main.xml +index f71a7a8457..8c3b68785b 100644 +--- a/applets/taskmanager/package/contents/config/main.xml ++++ b/applets/taskmanager/package/contents/config/main.xml +@@ -90,6 +90,7 @@ + + + ++ + + 0 + +diff --git a/applets/taskmanager/package/contents/ui/ConfigBehavior.qml b/applets/taskmanager/package/contents/ui/ConfigBehavior.qml +index 2c0dc19154..73357e9dcd 100644 +--- a/applets/taskmanager/package/contents/ui/ConfigBehavior.qml ++++ b/applets/taskmanager/package/contents/ui/ConfigBehavior.qml +@@ -202,13 +202,14 @@ KCMUtils.SimpleKCM { + + QQC2.ComboBox { + id: wheelEnabled +- Kirigami.FormData.label: i18nc("@label:listbox Part of a sentence: 'Scrolling behavior does nothing/cycles through tasks/cycles through the selected task's windows'", "Scrolling behavior:") ++ Kirigami.FormData.label: i18nc("@label:listbox Part of a sentence: 'Scrolling behavior does nothing/cycles through tasks/cycles through the selected task's windows/adjusts the hovered task’s volume''", "Scrolling behavior:") + Layout.fillWidth: true + Layout.minimumWidth: Kirigami.Units.gridUnit * 14 + model: [ + i18nc("@item:inlistbox Part of a sentence: 'Scrolling behavior does nothing'", "Does nothing"), + i18nc("@item:inlistbox Part of a sentence: 'Scrolling behavior cycles through all tasks'", "Cycles through all tasks"), + i18nc("@item:inlistbox Part of a sentence: 'Scrolling behavior cycles through the hovered task's windows'", "Cycles through the hovered task’s windows"), ++ i18nc("@item:inlistbox Part of a sentence: 'Scrolling behavior adjusts the hovered task’s volume'", "Adjusts the hovered task’s volume"), + ] + } + +diff --git a/applets/taskmanager/package/contents/ui/MouseHandler.qml b/applets/taskmanager/package/contents/ui/MouseHandler.qml +index cf2362835a..3f8d703d73 100644 +--- a/applets/taskmanager/package/contents/ui/MouseHandler.qml ++++ b/applets/taskmanager/package/contents/ui/MouseHandler.qml +@@ -8,6 +8,7 @@ import QtQuick + + import org.kde.taskmanager as TaskManager + import org.kde.plasma.plasmoid ++import org.kde.plasma.private.volume as PlasmaPa + + import "code/tools.js" as TaskTools + +@@ -157,6 +158,10 @@ DropArea { + } + } + ++ PlasmaPa.GlobalConfig { ++ id: plasmaPaConfig ++ } ++ + WheelHandler { + id: wheelHandler + +@@ -179,6 +184,21 @@ DropArea { + increment--; + } + const anchor = dropArea.target.childAt(event.x, event.y); ++ if (Plasmoid.configuration.wheelEnabled === 3) { ++ const loudest = anchor?.audioStreams?.reduce((loudest, stream) => Math.max(loudest, stream.volume), 0) ++ const step = (pulseAudio.item.normalVolume - pulseAudio.item.minimalVolume) * plasmaPaConfig.volumeStep / 100; ++ anchor?.audioStreams?.forEach((stream) => { ++ let delta = step * increment; ++ if (loudest > 0) { ++ delta *= stream.volume / loudest; ++ } ++ const volume = stream.volume + delta; ++ console.log(volume, Math.max(pulseAudio.item.minimalVolume, Math.min(volume, pulseAudio.item.normalVolume))); ++ stream.model.Volume = Math.max(pulseAudio.item.minimalVolume, Math.min(volume, pulseAudio.item.normalVolume)); ++ stream.model.Muted = volume === 0 ++ }) ++ return; ++ } + while (increment !== 0) { + TaskTools.activateNextPrevTask(anchor, increment < 0, Plasmoid.configuration.wheelSkipMinimized, Plasmoid.configuration.wheelEnabled, tasks); + increment += (increment < 0) ? 1 : -1; +-- +GitLab + diff --git a/roles/kde/patches/plasma-desktop/pr3259.patch b/roles/kde/patches/plasma-desktop/pr3259.patch new file mode 100644 index 0000000..8104e45 --- /dev/null +++ b/roles/kde/patches/plasma-desktop/pr3259.patch @@ -0,0 +1,78 @@ +From 57885ba4ec524bdc1c1326228f27c1c3a3561bba Mon Sep 17 00:00:00 2001 +From: Nate Graham +Date: Tue, 21 Oct 2025 13:39:40 -0600 +Subject: [PATCH] applets/kickoff: add spacing between non-switch-on-hover + category items + +Otherwise, their highlight effects touch, and it looks bad. + +To avoid blowing up the layout as a result of this change, slightly +decrease the height of these category list items too, which also reduces +some code complexity. + +BUG: 508985 +FIXED-IN: 6.6.0 +--- + applets/kickoff/ApplicationsPage.qml | 1 + + applets/kickoff/KickoffListDelegate.qml | 9 --------- + applets/kickoff/KickoffListView.qml | 5 +++++ + 3 files changed, 6 insertions(+), 9 deletions(-) + +diff --git a/applets/kickoff/ApplicationsPage.qml b/applets/kickoff/ApplicationsPage.qml +index c2baa75b52..fe8d6eaafb 100644 +--- a/applets/kickoff/ApplicationsPage.qml ++++ b/applets/kickoff/ApplicationsPage.qml +@@ -20,6 +20,7 @@ BasePage { + id: sideBar + focus: true // needed for Loaders + model: kickoff.rootModel ++ showingCategories: true + // needed otherwise app displayed at top-level will show a first character as group. + section.property: "" + delegate: KickoffListDelegate { +diff --git a/applets/kickoff/KickoffListDelegate.qml b/applets/kickoff/KickoffListDelegate.qml +index b1f8afb3ce..02bfcfcacd 100644 +--- a/applets/kickoff/KickoffListDelegate.qml ++++ b/applets/kickoff/KickoffListDelegate.qml +@@ -72,15 +72,6 @@ AbstractKickoffItemDelegate { + id: label + Layout.fillWidth: !descriptionLabel.visible + Layout.maximumWidth: root.width - root.leftPadding - root.rightPadding - icon.width - row.spacing +- Layout.preferredHeight: { +- if (root.isCategoryListItem) { +- return root.compact ? implicitHeight : Math.round(implicitHeight * 1.5); +- } +- if (!root.compact && !descriptionLabel.visible) { +- return implicitHeight + descriptionLabel.implicitHeight +- } +- return implicitHeight; +- } + text: root.text + textFormat: root.isMultilineText ? Text.StyledText : Text.PlainText + elide: Text.ElideRight +diff --git a/applets/kickoff/KickoffListView.qml b/applets/kickoff/KickoffListView.qml +index c7787493e0..382d146428 100644 +--- a/applets/kickoff/KickoffListView.qml ++++ b/applets/kickoff/KickoffListView.qml +@@ -33,6 +33,7 @@ EmptyPage { + property alias section: view.section + property alias highlight: view.highlight + property alias view: view ++ property bool showingCategories: false + + property bool mainContentView: false + property bool hasSectionView: false +@@ -144,6 +145,10 @@ EmptyPage { + width: view.availableWidth + } + ++ // Without switch-on-hover, it's possible for the selected category and the hovered category to be adjacent. ++ // When this happens, their highlights tuoch and look ungly without some artificial spacing added. ++ spacing: root.showingCategories && !Plasmoid.configuration.switchCategoryOnHover ? Kirigami.Units.smallSpacing : 0 ++ + section { + property: "group" + criteria: ViewSection.FullString +-- +GitLab + diff --git a/roles/kde/patches/plasma-desktop/pr3269.patch b/roles/kde/patches/plasma-desktop/pr3269.patch new file mode 100644 index 0000000..3a53322 --- /dev/null +++ b/roles/kde/patches/plasma-desktop/pr3269.patch @@ -0,0 +1,66 @@ +From a63fce38f285b59407c24f44639023d41b5d3ca9 Mon Sep 17 00:00:00 2001 +From: Nate Graham +Date: Thu, 30 Oct 2025 20:01:32 -0600 +Subject: [PATCH] applets/kickoff: add separation between Places page list + items too + +Missed in 57885ba4ec524bdc1c1326228f27c1c3a3561bba + +BUG: 508985 +FIXED-IN: 6.6.0 +--- + applets/kickoff/ApplicationsPage.qml | 2 +- + applets/kickoff/KickoffListView.qml | 4 ++-- + applets/kickoff/PlacesPage.qml | 1 + + 3 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/applets/kickoff/ApplicationsPage.qml b/applets/kickoff/ApplicationsPage.qml +index fe8d6eaafb..206ddd958d 100644 +--- a/applets/kickoff/ApplicationsPage.qml ++++ b/applets/kickoff/ApplicationsPage.qml +@@ -20,7 +20,7 @@ BasePage { + id: sideBar + focus: true // needed for Loaders + model: kickoff.rootModel +- showingCategories: true ++ isSidebar: true + // needed otherwise app displayed at top-level will show a first character as group. + section.property: "" + delegate: KickoffListDelegate { +diff --git a/applets/kickoff/KickoffListView.qml b/applets/kickoff/KickoffListView.qml +index 382d146428..2d67bd59b7 100644 +--- a/applets/kickoff/KickoffListView.qml ++++ b/applets/kickoff/KickoffListView.qml +@@ -33,7 +33,7 @@ EmptyPage { + property alias section: view.section + property alias highlight: view.highlight + property alias view: view +- property bool showingCategories: false ++ property bool isSidebar: false + + property bool mainContentView: false + property bool hasSectionView: false +@@ -147,7 +147,7 @@ EmptyPage { + + // Without switch-on-hover, it's possible for the selected category and the hovered category to be adjacent. + // When this happens, their highlights tuoch and look ungly without some artificial spacing added. +- spacing: root.showingCategories && !Plasmoid.configuration.switchCategoryOnHover ? Kirigami.Units.smallSpacing : 0 ++ spacing: root.isSidebar && !Plasmoid.configuration.switchCategoryOnHover ? Kirigami.Units.smallSpacing : 0 + + section { + property: "group" +diff --git a/applets/kickoff/PlacesPage.qml b/applets/kickoff/PlacesPage.qml +index ff92f535e4..7f81096834 100644 +--- a/applets/kickoff/PlacesPage.qml ++++ b/applets/kickoff/PlacesPage.qml +@@ -19,6 +19,7 @@ BasePage { + id: sideBar + focus: true // needed for Loaders + model: placesCategoryModel ++ isSidebar: true + delegate: KickoffListDelegate { + url: "" + description: "" +-- +GitLab + From 16f79d8a7d9c46bca67dda016625054914b68189 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 2 Nov 2025 13:43:34 +0100 Subject: [PATCH 1076/1125] Kde/patches: remove plasma-workspace patch Lots of packages depend on plasma workspace, so it's not worth building all of them just for a small patch --- .../kde/patches/plasma-workspace/patches.txt | 3 - .../kde/patches/plasma-workspace/pr5818.patch | 76 ------------------- 2 files changed, 79 deletions(-) delete mode 100644 roles/kde/patches/plasma-workspace/patches.txt delete mode 100644 roles/kde/patches/plasma-workspace/pr5818.patch diff --git a/roles/kde/patches/plasma-workspace/patches.txt b/roles/kde/patches/plasma-workspace/patches.txt deleted file mode 100644 index 3e0146f..0000000 --- a/roles/kde/patches/plasma-workspace/patches.txt +++ /dev/null @@ -1,3 +0,0 @@ -Plasma 6.6.0: - -Pr 5816 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5816 diff --git a/roles/kde/patches/plasma-workspace/pr5818.patch b/roles/kde/patches/plasma-workspace/pr5818.patch deleted file mode 100644 index 12417f1..0000000 --- a/roles/kde/patches/plasma-workspace/pr5818.patch +++ /dev/null @@ -1,76 +0,0 @@ -From b29509a32a0aa93555f47bc3d3f04c665c511f30 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Wed, 17 Sep 2025 10:27:07 +0300 -Subject: [PATCH] shell: Port to KWaylandExtras::xdgActivationToken() - ---- - shell/desktopview.cpp | 41 +---------------------------------------- - 1 file changed, 1 insertion(+), 40 deletions(-) - -diff --git a/shell/desktopview.cpp b/shell/desktopview.cpp -index 9c3baa84b91..ca48e44e887 100644 ---- a/shell/desktopview.cpp -+++ b/shell/desktopview.cpp -@@ -395,44 +395,6 @@ bool DesktopView::event(QEvent *e) - return PlasmaQuick::ContainmentView::event(e); - } - --class ActivationTokenRequest : public QObject --{ -- Q_OBJECT -- --public: -- explicit ActivationTokenRequest(QWindow *window) -- : m_serial(KWaylandExtras::lastInputSerial(window)) -- { -- m_promise.start(); -- -- connect(KWaylandExtras::self(), &KWaylandExtras::xdgActivationTokenArrived, this, [this](int serial, const QString &token) { -- if (m_serial == serial) { -- if (!m_promise.isCanceled()) { -- m_promise.addResult(token); -- } -- m_promise.finish(); -- delete this; -- } -- }); -- KWaylandExtras::requestXdgActivationToken(window, m_serial, QString()); -- } -- -- QFuture future() const -- { -- return m_promise.future(); -- } -- --private: -- QPromise m_promise; -- int m_serial; --}; -- --static QFuture fetchActivationToken(QWindow *window) --{ -- auto request = new ActivationTokenRequest(window); -- return request->future(); --} -- - bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) - { - // allow only Shift and GroupSwitch modifiers -@@ -459,7 +421,7 @@ bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) - if (!m_krunnerFuture.isCanceled()) { - m_krunnerFuture.cancel(); - } -- m_krunnerFuture = fetchActivationToken(this); -+ m_krunnerFuture = KWaylandExtras::xdgActivationToken(this, QString()); - m_krunnerFuture.then(this, [this](const QString &token) { - auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.krunner"), - QStringLiteral("/org/kde/krunner"), -@@ -672,5 +634,4 @@ void DesktopView::setAccentColorFromWallpaper(const QColor &accentColor) - QDBusConnection::sessionBus().send(applyAccentColor); - } - --#include "desktopview.moc" - #include "moc_desktopview.cpp" --- -GitLab - From c00ef6ab7c4cf9e5c28aa87631a31289be2a152a Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 2 Nov 2025 13:44:37 +0100 Subject: [PATCH 1077/1125] Kde/patches: get patches with lib.toast.patches.patchesInPath --- roles/kde/patches/default.nix | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/roles/kde/patches/default.nix b/roles/kde/patches/default.nix index 9259279..374881a 100644 --- a/roles/kde/patches/default.nix +++ b/roles/kde/patches/default.nix @@ -3,24 +3,17 @@ removeFiles = lib.attrsets.filterAttrs (n: v: v == "directory") rootDirs; programsToPatch = builtins.attrNames removeFiles; - getPatches = name: - builtins.map (value: ./${name}/${value}) (builtins.attrNames ( - lib.attrsets.filterAttrs ( - n: v: - v == "regular" && lib.strings.hasSuffix ".patch" n - ) (builtins.readDir ./${name}) - )); - bigOverlay = final: prev: lib.attrsets.mergeAttrsList ( lib.lists.forEach programsToPatch ( program: let unpatchedProgram = prev."${program}"; + newPatches = lib.toast.patches.patchesInPath (lib.path.append ./. program); in { "${program}" = unpatchedProgram.overrideAttrs { version = "${unpatchedProgram.version}-patched"; __intentionallyOverridingVersion = true; - patches = unpatchedProgram.patches ++ getPatches program; + patches = unpatchedProgram.patches ++ newPatches; }; } ) From 8b9eae079e136a03bd4b252cbd4adf3472ea3fac Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 5 Nov 2025 10:28:33 +0000 Subject: [PATCH 1078/1125] Desktop/firefox: add control panel for twitter --- roles/desktop/programs/firefox.nix | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/roles/desktop/programs/firefox.nix b/roles/desktop/programs/firefox.nix index 1e80585..538456a 100644 --- a/roles/desktop/programs/firefox.nix +++ b/roles/desktop/programs/firefox.nix @@ -80,6 +80,10 @@ installation_mode = "normal_installed"; install_url = "https://addons.mozilla.org/firefox/downloads/latest/multi-account-containers/latest.xpi"; }; + "{5cce4ab5-3d47-41b9-af5e-8203eea05245}" = { + installation_mode = "normal_installed"; + install_url = "https://addons.mozilla.org/firefox/downloads/latest/control-panel-for-twitter/latest.xpi"; + }; }; Preferences = { "general.smoothScroll.msdPhysics.enabled" = { @@ -126,6 +130,16 @@ identityMacAddonUUID = "b50e5b1e-6f3b-4245-8eac-5654d889156e"; }; }; + # Control panel for twitter + "{5cce4ab5-3d47-41b9-af5e-8203eea05245}".settings = { + hideForYouTimeline = false; + alwaysUseLatestTweets = false; + retweets = "ignore"; + restoreOtherInteractionLinks = true; + navBaseFontSize = false; + followButtonStyle = "themed"; + hideSidebarContent = true; + }; }; }; }; From b8264643e6181f0a792e4c2f3ee7b72e438af405 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 6 Nov 2025 22:40:29 +0100 Subject: [PATCH 1079/1125] Machines: remove iMac --- flake.nix | 4 -- machines/iMac/configuration.nix | 84 ------------------------ machines/iMac/default.nix | 6 -- machines/iMac/hardware-configuration.nix | 69 ------------------- roles/common/services/syncthing.nix | 7 +- roles/server/syncthing.nix | 2 +- 6 files changed, 2 insertions(+), 170 deletions(-) delete mode 100644 machines/iMac/configuration.nix delete mode 100755 machines/iMac/default.nix delete mode 100644 machines/iMac/hardware-configuration.nix diff --git a/flake.nix b/flake.nix index 2f4f59e..96b079b 100644 --- a/flake.nix +++ b/flake.nix @@ -228,10 +228,6 @@ ./roles/server ]; }; - iMac.modules = [ - ./roles/desktop - ./roles/gnome - ]; }; }; } diff --git a/machines/iMac/configuration.nix b/machines/iMac/configuration.nix deleted file mode 100644 index 0d42eb7..0000000 --- a/machines/iMac/configuration.nix +++ /dev/null @@ -1,84 +0,0 @@ -# Edit this configuration file to define what should be installed on -# your system. Help is available in the configuration.nix(5) man page, on -# https://search.nixos.org/options and in the NixOS manual (`nixos-help`). -{ - config, - lib, - pkgs, - ... -}: { - # Use the systemd-boot EFI boot loader. - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; - - nixpkgs.config.allowUnfree = true; - - networking.hostName = "iMac"; # Define your hostname. - - # Set your time zone. - time.timeZone = "Europe/Madrid"; - - # Configure network proxy if necessary - # networking.proxy.default = "http://user:password@proxy:port/"; - # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - - # Select internationalisation properties. - # i18n.defaultLocale = "en_US.UTF-8"; - # console = { - # font = "Lat2-Terminus16"; - # keyMap = "us"; - # useXkbConfig = true; # use xkb.options in tty. - # }; - - # Enable the X11 windowing system. - services.xserver.enable = true; - - # Configure keymap in X11 - services.xserver.xkb.layout = "es"; - # services.xserver.xkb.options = "eurosign:e,caps:escape"; - - # Enable CUPS to print documents. - # services.printing.enable = true; - - # Enable sound. - hardware.pulseaudio.enable = false; - # OR - # services.pipewire = { - # enable = true; - # pulse.enable = true; - # }; - - # Enable touchpad support (enabled default in most desktopManager). - # services.libinput.enable = true; - - # List packages installed in system profile. To search, run: - # $ nix search wget - # environment.systemPackages = with pkgs; [ - # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. - # wget - # ]; - - # Some programs need SUID wrappers, can be configured further or are - # started in user sessions. - # programs.mtr.enable = true; - # programs.gnupg.agent = { - # enable = true; - # enableSSHSupport = true; - # }; - - # List services that you want to enable: - - # Enable the OpenSSH daemon. - # services.openssh.enable = true; - - # Open ports in the firewall. - # networking.firewall.allowedTCPPorts = [ ... ]; - # networking.firewall.allowedUDPPorts = [ ... ]; - # Or disable the firewall altogether. - # networking.firewall.enable = false; - - # Copy the NixOS configuration file and link it from the resulting system - # (/run/current-system/configuration.nix). This is useful in case you - # accidentally delete configuration.nix. - # system.copySystemConfiguration = true; -} diff --git a/machines/iMac/default.nix b/machines/iMac/default.nix deleted file mode 100755 index 187a110..0000000 --- a/machines/iMac/default.nix +++ /dev/null @@ -1,6 +0,0 @@ -{...}: { - imports = [ - ./configuration.nix - ./hardware-configuration.nix - ]; -} diff --git a/machines/iMac/hardware-configuration.nix b/machines/iMac/hardware-configuration.nix deleted file mode 100644 index 89570f6..0000000 --- a/machines/iMac/hardware-configuration.nix +++ /dev/null @@ -1,69 +0,0 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. -{ - config, - lib, - pkgs, - modulesPath, - ... -}: { - imports = [ - (modulesPath + "/installer/scan/not-detected.nix") - ]; - - boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "sdhci_pci"]; - boot.initrd.kernelModules = []; - boot.initrd.systemd.enable = true; - boot.kernelModules = ["kvm-intel" "wl"]; - boot.kernelParams = [ - "acpi_backlight=video" - "nouveau.config=NvClkMode=15" - ]; - boot.extraModulePackages = [config.boot.kernelPackages.broadcom_sta]; - - fileSystems."/" = { - device = "/dev/disk/by-uuid/6062dfe3-6e70-4f30-aa45-e81933f116fb"; - fsType = "btrfs"; - options = ["subvol=@" "compress=zstd"]; - }; - - boot.initrd.luks.devices."SSD".device = "/dev/disk/by-uuid/482cd1b5-2a22-42f3-a497-4b4d7006d2e3"; - - fileSystems."/nix" = { - device = "/dev/disk/by-uuid/6062dfe3-6e70-4f30-aa45-e81933f116fb"; - fsType = "btrfs"; - options = ["subvol=@nix" "compress=zstd"]; - }; - - fileSystems."/home" = { - device = "/dev/disk/by-uuid/6062dfe3-6e70-4f30-aa45-e81933f116fb"; - fsType = "btrfs"; - options = ["subvol=@home" "compress=zstd"]; - }; - - fileSystems."/persist" = { - device = "/dev/disk/by-uuid/6062dfe3-6e70-4f30-aa45-e81933f116fb"; - fsType = "btrfs"; - options = ["subvol=@persist" "compress=zstd"]; - neededForBoot = true; - }; - - fileSystems."/boot" = { - device = "/dev/disk/by-uuid/0D30-3CEE"; - fsType = "vfat"; - options = ["fmask=0022" "dmask=0022"]; - }; - - swapDevices = []; - - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking - # (the default) this is the recommended approach. When using systemd-networkd it's - # still possible to use this option, but it's recommended to use it in conjunction - # with explicit per-interface declarations with `networking.interfaces..useDHCP`. - networking.useDHCP = lib.mkDefault true; - # networking.interfaces.enp4s0f0.useDHCP = lib.mkDefault true; - - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; -} diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index 9f191a1..7403230 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -47,17 +47,12 @@ in { name = "Win Max 2"; id = "X2NILRM-ADRBQ23-AFREAZA-62GVFDF-UVMPR4L-KGHMUNY-BJ2C3CQ-RBT43QS"; }; - "imac" = { - name = "iMac"; - id = "KRHGSJF-64UXAE2-CNSDV6L-QAUV2HU-JTSIEIC-KSHLCBU-IFIQGDX-K5UCSQR"; - compression = "always"; - }; }; folders = { "passwords" = { label = "KeePassXC Passwords"; id = "rdyaq-ex659"; - devices = ["phone" "pc" "steamdeck" "server" "surface" "winmax2" "imac"]; + devices = ["phone" "pc" "steamdeck" "server" "surface" "winmax2"]; }; }; }; diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index 00cbeb4..ad7a1fc 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -35,7 +35,7 @@ "school-things" = { label = "School things"; id = "btsth-vdu9c"; - devices = ["server" "pc" "winmax2" "imac"]; + devices = ["server" "pc" "winmax2"]; path = "${config.services.syncthing.dataDir}/school-things"; }; "project-eden-saves" = { From 9f7cf822ed8c5755c6bb82e0edc64dd4d70c31ea Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 6 Nov 2025 22:41:38 +0100 Subject: [PATCH 1080/1125] Roles: delete gnome Only used it on the iMac --- roles/gnome/default.nix | 6 --- roles/gnome/gnome.nix | 72 ------------------------------- roles/gnome/programs/blackbox.nix | 33 -------------- roles/gnome/programs/default.nix | 11 ----- roles/gnome/programs/firefox.nix | 22 ---------- roles/gnome/programs/nautilus.nix | 15 ------- 6 files changed, 159 deletions(-) delete mode 100755 roles/gnome/default.nix delete mode 100644 roles/gnome/gnome.nix delete mode 100644 roles/gnome/programs/blackbox.nix delete mode 100644 roles/gnome/programs/default.nix delete mode 100644 roles/gnome/programs/firefox.nix delete mode 100644 roles/gnome/programs/nautilus.nix diff --git a/roles/gnome/default.nix b/roles/gnome/default.nix deleted file mode 100755 index 46a06ea..0000000 --- a/roles/gnome/default.nix +++ /dev/null @@ -1,6 +0,0 @@ -{...}: { - imports = [ - ./programs - ./gnome.nix - ]; -} diff --git a/roles/gnome/gnome.nix b/roles/gnome/gnome.nix deleted file mode 100644 index ed86051..0000000 --- a/roles/gnome/gnome.nix +++ /dev/null @@ -1,72 +0,0 @@ -{ - pkgs, - lib, - flakeSelf, - ... -}: { - services = { - xserver = { - displayManager.gdm.enable = true; - desktopManager.gnome.enable = true; - }; - gnome.gnome-browser-connector.enable = true; - }; - - qt = { - enable = true; - platformTheme = "gnome"; - style = "adwaita-dark"; - }; - - # Manage this with home-manager - services.gnome.gnome-keyring.enable = lib.mkForce false; - - home-manager.sharedModules = [ - { - services.gnome-keyring.enable = true; - } - ]; - - # Extensions - environment.systemPackages = with pkgs.gnomeExtensions; [ - appindicator - dash-to-dock - panel-workspace-scroll - ]; - - home-manager.users.toast = { - gtk = { - enable = true; - theme = { - name = "adw-gtk3-dark"; - package = pkgs.adw-gtk3; - }; - cursorTheme = { - name = "Kasane Teto"; - package = flakeSelf.outputs.packages.x86_64-linux.kasane-teto-cursor; - }; - }; - services.gnome-keyring.components = ["pkcs11" "secrets"]; - - dconf.settings = { - "org/gnome/shell" = { - enabled-extensions = [ - "appindicatorsupport@rgcjonas.gmail.com" - "dash-to-dock@micxgx.gmail.com" - "panel-workspace-scroll@polymeilex.github.io" - ]; - favorite-apps = ["firefox.desktop" "com.raggesilver.BlackBox.desktop" "org.gnome.Nautilus.desktop" "android-studio.desktop"]; - }; - "org/gnome/desktop/interface" = { - color-scheme = "prefer-dark"; - }; - "org/gnome/desktop/wm/preferences" = { - resize-with-right-button = true; - }; - "org/gnome/mutter" = { - dynamic-workspaces = true; - edge-tiling = true; - }; - }; - }; -} diff --git a/roles/gnome/programs/blackbox.nix b/roles/gnome/programs/blackbox.nix deleted file mode 100644 index 692aaad..0000000 --- a/roles/gnome/programs/blackbox.nix +++ /dev/null @@ -1,33 +0,0 @@ -{pkgs, ...}: { - programs.gnome-terminal.enable = false; - environment = with pkgs; { - gnome.excludePackages = [gnome-console]; - systemPackages = [ - blackbox-terminal - nautilus-open-in-blackbox - ]; - }; - - home-manager.users.toast = { - lib, - pkgs, - ... - }: { - home.file.".local/share/blackbox/schemes".source = - (pkgs.fetchgit { - url = "https://github.com/catppuccin/tilix.git"; - hash = "sha256-jWnxEtoqqqitHsaDErQNNYjv8DBcrJD0XeIKNopbO3c="; - }) - + /themes; - dconf.settings = with lib.hm.gvariant; { - "com/raggesilver/BlackBox" = { - # Dark mode - style-preference = mkUint32 2; - theme-dark = "Catppuccin Mocha"; - # Default working directory is home folder - working-directory-mode = mkUint32 1; - custom-font = "JetBrainsMono Nerd Font Mono 12"; - }; - }; - }; -} diff --git a/roles/gnome/programs/default.nix b/roles/gnome/programs/default.nix deleted file mode 100644 index 88c2cfb..0000000 --- a/roles/gnome/programs/default.nix +++ /dev/null @@ -1,11 +0,0 @@ -{pkgs, ...}: { - imports = [ - ./blackbox.nix - ./firefox.nix - ./nautilus.nix - ]; - environment.systemPackages = with pkgs; [ - gnome-tweaks - dconf-editor - ]; -} diff --git a/roles/gnome/programs/firefox.nix b/roles/gnome/programs/firefox.nix deleted file mode 100644 index c2460fa..0000000 --- a/roles/gnome/programs/firefox.nix +++ /dev/null @@ -1,22 +0,0 @@ -{pkgs, ...}: let - firefox-gnome-theme = pkgs.fetchFromGitHub { - owner = "rafaelmardojai"; - repo = "firefox-gnome-theme"; - rev = "v129"; - hash = "sha256-MOE9NeU2i6Ws1GhGmppMnjOHkNLl2MQMJmGhaMzdoJM="; - }; - profile-location = ".mozilla/firefox/jdnxpg97.temp"; -in { - home-manager.users.toast = { - programs.firefox = { - enableGnomeExtensions = true; - }; - home.file."${profile-location}/chrome".source = firefox-gnome-theme; - }; - programs.firefox = { - autoConfig = '' - lockPref("toolkit.legacyUserProfileCustomizations.stylesheets",true); - lockPref("svg.context-properties.content.enabled",true); - ''; - }; -} diff --git a/roles/gnome/programs/nautilus.nix b/roles/gnome/programs/nautilus.nix deleted file mode 100644 index d01fd83..0000000 --- a/roles/gnome/programs/nautilus.nix +++ /dev/null @@ -1,15 +0,0 @@ -{pkgs, ...}: { - environment.systemPackages = with pkgs; [ - nautilus-python - ]; - - home-manager.users.toast = { - dconf.settings = { - "org/gnome/preferences" = { - date-time-format = "detailed"; - show-create-link = true; - show-delete-permanently = true; - }; - }; - }; -} From 284bd502f0df6922a817ebc1f6cffe4d4f630ef0 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 6 Nov 2025 23:09:12 +0100 Subject: [PATCH 1081/1125] Server/forgejo: use unix socket --- roles/server/forgejo.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index c7f1780..763cce2 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -32,6 +32,7 @@ in { }; server = { OFFLINE_MODE = false; + PROTOCOL = "http+unix"; ROOT_URL = "https://git.toast003.xyz"; START_SSH_SERVER = true; SSH_PORT = 4222; @@ -61,7 +62,7 @@ in { services.caddy.virtualHosts.forgejo = { hostName = "git.toast003.xyz"; extraConfig = '' - reverse_proxy localhost:${toString config.services.forgejo.settings.server.HTTP_PORT} + reverse_proxy unix/${config.services.forgejo.settings.server.HTTP_ADDR} ''; }; } From afab4c4d0a822e8f849d078454dfb81fef5d7f8f Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 7 Nov 2025 02:16:55 +0100 Subject: [PATCH 1082/1125] Server: remove school.nix Haven't used this in months --- roles/server/school.nix | 138 ---------------------------------------- 1 file changed, 138 deletions(-) delete mode 100644 roles/server/school.nix diff --git a/roles/server/school.nix b/roles/server/school.nix deleted file mode 100644 index e255c1f..0000000 --- a/roles/server/school.nix +++ /dev/null @@ -1,138 +0,0 @@ -{ - flakeSelf, - config, - ... -}: let - hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName + "/"; -in { - networking.nat = { - enable = true; - internalInterfaces = ["ve-+"]; - externalInterface = "eno1"; - }; - - age.secrets.mongodb-uri = { - file = hostSecrets + "mongodb-uri.age"; - }; - - containers.school = { - autoStart = true; - privateNetwork = true; - ephemeral = true; - hostAddress = "192.168.100.10"; - localAddress = "192.168.100.11"; - specialArgs = { - showsApi = flakeSelf.inputs.shows-api; - }; - bindMounts = { - secret = { - mountPoint = "/mongodb.env"; - isReadOnly = true; - hostPath = config.age.secrets.mongodb-uri.path; - }; - }; - config = { - config, - pkgs, - lib, - showsApi, - ... - }: { - environment.systemPackages = [pkgs.htop]; - - users.users.shows = { - name = "shows"; - group = "shows"; - isSystemUser = true; - }; - users.groups.shows = {}; - - systemd.services = let - commonServiceConfig = { - Type = "simple"; - Restart = "on-failure"; - RestartSec = 3; - - # Hardening - CapabilityBoundingSet = ""; - NoNewPrivileges = true; - PrivateUsers = true; - PrivateTmp = true; - PrivateDevices = true; - PrivateMounts = true; - ProtectClock = true; - ProtectControlGroups = true; - ProtectHome = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = true; - ProtectKernelTunables = true; - RestrictAddressFamilies = [ - "AF_INET" - "AF_INET6" - "AF_UNIX" - ]; - RestrictNamespaces = true; - RestrictRealtime = true; - RestrictSUIDSGID = true; - }; - in { - shows-api = { - description = "NestJS API to store info about shows on a MongoDB database"; - after = ["network.target"]; - wantedBy = ["multi-user.target"]; - serviceConfig = - commonServiceConfig - // { - ExecStart = lib.getExe showsApi.packages.x86_64-linux.default; - StateDirectory = ["shows-api"]; - RuntimeDirectory = ["shows-api"]; - User = "shows"; - Group = "shows"; - EnvironmentFile = "/mongodb.env"; - }; - }; - }; - - networking = { - firewall.allowedTCPPorts = [3000]; - - # Use systemd-resolved inside the container - # Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686 - useHostResolvConf = lib.mkForce false; - }; - - services.resolved.enable = true; - - system.stateVersion = "24.11"; - }; - }; - services = { - headscale.settings.dns.extra_records = [ - { - name = "shows.everest.tailscale"; - type = "A"; - value = "100.100.0.1"; - } - ]; - caddy.virtualHosts.shows= { - hostName = "shows.everest.tailscale"; - extraConfig = '' - import tailscale - handle { - respond "Ionic app goes here" - } - - redir /admin /admin/ - handle_path /admin/* { - respond "Angular admin panel goes here" - } - - redir /api /api/ - handle_path /api/* { - reverse_proxy ${config.containers.school.localAddress}:3000 - } - ''; - }; - }; -} From c42c6cd83a87788a247576617e444203a694d9cc Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 7 Nov 2025 02:31:15 +0100 Subject: [PATCH 1083/1125] Flake: remove unused packages --- flake.nix | 2 - pkgs/anything-sync-daemon/default.nix | 57 ------------------- .../disableDaemonStopTargets.patch | 23 -------- pkgs/discord-krisp-fixer | 17 ------ 4 files changed, 99 deletions(-) delete mode 100644 pkgs/anything-sync-daemon/default.nix delete mode 100644 pkgs/anything-sync-daemon/disableDaemonStopTargets.patch delete mode 100644 pkgs/discord-krisp-fixer diff --git a/flake.nix b/flake.nix index 96b079b..74ed969 100644 --- a/flake.nix +++ b/flake.nix @@ -133,8 +133,6 @@ }; packages = { x86_64-linux = with import nixpkgs-unstable-raw {system = "x86_64-linux";}; { - anything-sync-daemon = callPackage ./pkgs/anything-sync-daemon {}; - discord-krisp-fixer = callPackage ./pkgs/discord-krisp-fixer {}; kasane-teto-cursor = callPackage ./pkgs/kasane-teto-cursor {}; }; }; diff --git a/pkgs/anything-sync-daemon/default.nix b/pkgs/anything-sync-daemon/default.nix deleted file mode 100644 index afa5417..0000000 --- a/pkgs/anything-sync-daemon/default.nix +++ /dev/null @@ -1,57 +0,0 @@ -{ - stdenv, - lib, - fetchFromGitHub, - makeWrapper, - rsync, - gawk, - pv, - gnutar, - zstd, - util-linux, - coreutils, - gnugrep, - findutils, -}: -stdenv.mkDerivation rec { - pname = "anything-sync-daemon"; - version = "6.0.0"; - - src = fetchFromGitHub { - owner = "graysky2"; - repo = pname; - rev = "v${version}"; - hash = "sha256-6nfaAMH5YgK6gimuZ8j1zWLTDOi11KIwW7Bf0Iwh7+I="; - }; - - patches = [./disableDaemonStopTargets.patch]; - - nativeBuildInputs = [makeWrapper]; - - postPatch = '' - substituteInPlace init/asd* \ - --replace /usr/bin/anything-sync-daemon $out/bin/anything-sync-daemon - ''; - - enableParallelBuilding = true; - - makeFlags = [ - "DESTDIR=${placeholder "out"}" - "PREFIX=" - "INITDIR_SYSTEMD=/lib/systemd/system" - ]; - - installTargets = ["install-systemd-all"]; - - postInstall = '' - wrapProgram $out/bin/anything-sync-daemon \ - --suffix PATH : ${lib.makeBinPath [rsync gawk pv gnutar zstd util-linux coreutils gnugrep findutils]} - ''; - - meta = with lib; { - description = "Symlinks and syncs user specified dirs to RAM"; - homepage = "https://github.com/graysky2/anything-sync-daemon/"; - license = lib.licenses.mit; - platforms = platforms.linux; - }; -} diff --git a/pkgs/anything-sync-daemon/disableDaemonStopTargets.patch b/pkgs/anything-sync-daemon/disableDaemonStopTargets.patch deleted file mode 100644 index 6dd71bd..0000000 --- a/pkgs/anything-sync-daemon/disableDaemonStopTargets.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff --git a/Makefile b/Makefile -index ddf2d73..827ea8f 100644 ---- a/Makefile -+++ b/Makefile -@@ -31,17 +31,7 @@ common/$(PN): Makefile common/$(PN).in - - help: install - --stop-asd: --ifneq ($(PREFIX), /usr) -- sudo -E asd unsync --endif -- --disable-systemd: --ifeq ($(PREFIX), /usr) -- systemctl stop asd asd-resync || /bin/true --endif -- --install-bin: stop-asd disable-systemd common/$(PN) -+install-bin: common/$(PN) - $(Q)echo -e '\033[1;32mInstalling main script...\033[0m' - $(INSTALL_DIR) "$(DESTDIR)$(BINDIR)" - $(INSTALL_PROGRAM) common/$(PN) "$(DESTDIR)$(BINDIR)/$(PN)" diff --git a/pkgs/discord-krisp-fixer b/pkgs/discord-krisp-fixer deleted file mode 100644 index baa22d2..0000000 --- a/pkgs/discord-krisp-fixer +++ /dev/null @@ -1,17 +0,0 @@ -{ writeShellApplication -, rizin -, discord -}: - -writeShellApplication rec { - name = "discord-krisp-fixer"; - - runtimeInputs = [ rizin ]; - - text = '' - discord_version="${discord.version}" - file="$HOME/.config/discord/$discord_version/modules/discord_krisp/discord_krisp.node" - addr=$(rz-find -x '4881ec00010000' "$file" | head -n1) - rizin -q -w -c "s $addr + 0x30 ; wao nop" "$file" - ''; -} From b1e5e837443a5ab8e00372d7367b4be5fced299b Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 7 Nov 2025 02:39:00 +0100 Subject: [PATCH 1084/1125] Flake: get packages from overlay --- flake.nix | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 74ed969..bcc2a6f 100644 --- a/flake.nix +++ b/flake.nix @@ -131,9 +131,15 @@ export PS1="$PS1(toast-configs)> " ''; }; + overlays.default = final: prev: { + kasane-teto-cursor = final.callPackage ./pkgs/kasane-teto-cursor {}; + }; packages = { - x86_64-linux = with import nixpkgs-unstable-raw {system = "x86_64-linux";}; { - kasane-teto-cursor = callPackage ./pkgs/kasane-teto-cursor {}; + x86_64-linux = with import nixpkgs-unstable-raw { + system = "x86_64-linux"; + overlays = [self.overlays.default]; + }; { + inherit kasane-teto-cursor; }; }; nixosConfigurations = let From 5ddac8b95b767ff2d60c15201416701ab629a03f Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 7 Nov 2025 02:44:39 +0100 Subject: [PATCH 1085/1125] Roles/common: use flake overlay --- roles/common/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index f7d502e..284565f 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -101,6 +101,7 @@ services.automatic-timezoned.enable = true; nixpkgs.overlays = [ + flakeSelf.outputs.overlays.default ( final: prev: { catppuccin = prev.catppuccin.override { From 0bfe20a73696bf0196c62c9c79cd913669d84864 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 11 Nov 2025 02:09:09 +0100 Subject: [PATCH 1086/1125] Packages: add kame-editor and dependencies --- flake.nix | 5 +++- pkgs/kame-editor/default.nix | 53 ++++++++++++++++++++++++++++++++++++ pkgs/kame-tools/default.nix | 29 ++++++++++++++++++++ pkgs/rstmcpp/default.nix | 21 ++++++++++++++ 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 pkgs/kame-editor/default.nix create mode 100644 pkgs/kame-tools/default.nix create mode 100644 pkgs/rstmcpp/default.nix diff --git a/flake.nix b/flake.nix index bcc2a6f..f2971ae 100644 --- a/flake.nix +++ b/flake.nix @@ -133,13 +133,16 @@ }; overlays.default = final: prev: { kasane-teto-cursor = final.callPackage ./pkgs/kasane-teto-cursor {}; + kame-editor = final.callPackage ./pkgs/kame-editor {}; + kame-tools = final.callPackage ./pkgs/kame-tools {}; + rstmcpp = final.callPackage ./pkgs/rstmcpp {}; }; packages = { x86_64-linux = with import nixpkgs-unstable-raw { system = "x86_64-linux"; overlays = [self.overlays.default]; }; { - inherit kasane-teto-cursor; + inherit kasane-teto-cursor kame-editor kame-tools rstmcpp; }; }; nixosConfigurations = let diff --git a/pkgs/kame-editor/default.nix b/pkgs/kame-editor/default.nix new file mode 100644 index 0000000..d974f9c --- /dev/null +++ b/pkgs/kame-editor/default.nix @@ -0,0 +1,53 @@ +{ + stdenv, + fetchFromGitLab, + qt6, + portaudio, + kame-tools, + vgmstream, + rstmcpp, +}: +stdenv.mkDerivation rec { + name = "kame-editor"; + version = "1.4.1"; + + src = fetchFromGitLab { + owner = "beelzy"; + repo = name; + # tag = version; + rev = "82c9c445644b133b6d0ce3529e65b1a3df83c804"; + hash = "sha256-V2nMvVIjFRM8++XQ9tkE2OiZzCvdrg0jK69HM+ZIVyA="; + }; + + postPatch = '' + substituteInPlace kame-editor.pro \ + --replace-fail "/usr/local/bin/" "$out/bin" + ''; + + buildInputs = [ + qt6.qtbase + portaudio + kame-tools + vgmstream + rstmcpp + ]; + + dontStrip = true; + + nativeBuildInputs = [ + qt6.qmake + qt6.wrapQtAppsHook + ]; + + postBuild = '' + bash ./buildicons.sh + ''; + + postInstall = '' + mkdir -p $out/share/icons/hicolor + mkdir -p $out/share/applications + + cp kame-editor.desktop $out/share/applications + cp -r icons/. $out/share/icons/hicolor + ''; +} diff --git a/pkgs/kame-tools/default.nix b/pkgs/kame-tools/default.nix new file mode 100644 index 0000000..fe2b608 --- /dev/null +++ b/pkgs/kame-tools/default.nix @@ -0,0 +1,29 @@ +{ + stdenv, + fetchFromGitLab, + zip, +}: +stdenv.mkDerivation rec { + name = "kame-tools"; + version = "a1fe47cc"; + + src = fetchFromGitLab { + owner = "beelzy"; + repo = name; + rev = version; + fetchSubmodules = true; + hash = "sha256-ETl5f8M4OJPFB7NEq2mVuMm4RhBtAbMzlrvGHD14zXw="; + }; + + postPatch = '' + substituteInPlace buildtools/make_base \ + --replace-fail "/usr/local/bin" "$out/bin" + ''; + + installPhase = '' + mkdir -p $out/bin + cp output/linux-x86_64/* $out/bin/ + ''; + + nativeBuildInputs = [zip]; +} diff --git a/pkgs/rstmcpp/default.nix b/pkgs/rstmcpp/default.nix new file mode 100644 index 0000000..94c51a3 --- /dev/null +++ b/pkgs/rstmcpp/default.nix @@ -0,0 +1,21 @@ +{ + stdenv, + fetchFromGitLab, +}: +stdenv.mkDerivation rec { + name = "rstmcpp"; + version = "fe8bee01"; + + src = fetchFromGitLab { + owner = "beelzy"; + repo = name; + rev = version; + fetchSubmodules = true; + hash = "sha256-T9mxTBj/eykvbBkbmEKTUFldtBp3cJgWAbeu44SwxiM="; + }; + + installPhase = '' + mkdir -p $out/bin + cp rstmcpp $out/bin + ''; +} From 85b1605ea99670e68537576aecfecdd11f7015cc Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 15 Nov 2025 18:56:36 +0100 Subject: [PATCH 1087/1125] Pkgs/kame-editor: add required programs to wrapper path --- pkgs/kame-editor/default.nix | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pkgs/kame-editor/default.nix b/pkgs/kame-editor/default.nix index d974f9c..b3cd0a7 100644 --- a/pkgs/kame-editor/default.nix +++ b/pkgs/kame-editor/default.nix @@ -1,4 +1,5 @@ { + lib, stdenv, fetchFromGitLab, qt6, @@ -27,12 +28,17 @@ stdenv.mkDerivation rec { buildInputs = [ qt6.qtbase portaudio - kame-tools - vgmstream - rstmcpp ]; - dontStrip = true; + qtWrapperArgs = [ + "--prefix PATH : ${ + lib.makeBinPath [ + kame-tools + vgmstream + rstmcpp + ] + }" + ]; nativeBuildInputs = [ qt6.qmake From ce5be49975e6b6abc5ae3b2af38ae71458bc6e65 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 16 Nov 2025 01:41:14 +0100 Subject: [PATCH 1088/1125] Kde/patches: add spectacle patches --- roles/kde/patches/spectacle/patches.txt | 2 + roles/kde/patches/spectacle/pr462.patch | 2844 +++++++++++++++++++++++ roles/kde/patches/spectacle/pr487.patch | 704 ++++++ roles/kde/programs/default.nix | 1 + roles/kde/programs/spectacle.nix | 24 + 5 files changed, 3575 insertions(+) create mode 100644 roles/kde/patches/spectacle/patches.txt create mode 100644 roles/kde/patches/spectacle/pr462.patch create mode 100644 roles/kde/patches/spectacle/pr487.patch create mode 100644 roles/kde/programs/spectacle.nix diff --git a/roles/kde/patches/spectacle/patches.txt b/roles/kde/patches/spectacle/patches.txt new file mode 100644 index 0000000..34909b4 --- /dev/null +++ b/roles/kde/patches/spectacle/patches.txt @@ -0,0 +1,2 @@ +Pr 462 https://invent.kde.org/plasma/spectacle/-/merge_requests/462 +Pr 487 https://invent.kde.org/plasma/spectacle/-/merge_requests/487 diff --git a/roles/kde/patches/spectacle/pr462.patch b/roles/kde/patches/spectacle/pr462.patch new file mode 100644 index 0000000..3db47e0 --- /dev/null +++ b/roles/kde/patches/spectacle/pr462.patch @@ -0,0 +1,2844 @@ +From 9ab7593321d014ff63ef12590a0c2d0e721a90f1 Mon Sep 17 00:00:00 2001 +From: Jhair Paris +Date: Sat, 7 Jun 2025 19:56:28 -0500 +Subject: [PATCH 1/3] Add OCR dependencies and build configuration + +- Add Tesseract and Leptonica dependencies +- Configure OCR support in CMake build system +--- + CMakeLists.txt | 7 +++++++ + src/CMakeLists.txt | 5 ++++- + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index f62a38443..3038f472c 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -89,12 +89,19 @@ find_package(PlasmaWaylandProtocols REQUIRED) + find_package(LayerShellQt REQUIRED) + find_package(KPipeWire) + find_package(OpenCV 4.7 REQUIRED core imgproc) ++find_package(PkgConfig REQUIRED) ++pkg_check_modules(TESSERACT REQUIRED tesseract) + + set_package_properties(KPipeWire PROPERTIES DESCRIPTION + "Used to record pipewire streams into a file" + TYPE REQUIRED + ) + ++set_package_properties(TESSERACT PROPERTIES DESCRIPTION ++ "OCR (Optical Character Recognition) engine for text recognition in images" ++ TYPE REQUIRED ++) ++ + # optional components + find_package(KF6DocTools ${KF6_MIN_VERSION}) + set_package_properties(KF6DocTools PROPERTIES DESCRIPTION +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index d27c2dba4..cb000b35d 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -25,6 +25,7 @@ target_sources(spectacle PRIVATE + CommandLineOptions.cpp + ExportManager.cpp + Geometry.cpp ++ OcrManager.cpp + Gui/Annotations/AnnotationDocument.cpp + Gui/Annotations/AnnotationTool.cpp + Gui/Annotations/AnnotationViewport.cpp +@@ -104,7 +105,7 @@ ki18n_wrap_ui(spectacle + # Needed to compile with OpenCV + target_compile_options (spectacle PRIVATE -fexceptions) + +-target_include_directories(spectacle PUBLIC ${OpenCV_INCLUDE_DIRS}) ++target_include_directories(spectacle PUBLIC ${OpenCV_INCLUDE_DIRS} ${TESSERACT_INCLUDE_DIRS}) + + target_link_libraries(spectacle PRIVATE + Qt::Concurrent +@@ -135,6 +136,7 @@ target_link_libraries(spectacle PRIVATE + Wayland::Client + LayerShellQt::Interface + ${OpenCV_LIBRARIES} ++ ${TESSERACT_LIBRARIES} + ) + + # qt_add_qml_module doesn't know how to deal with headers in subdirectories so +@@ -180,6 +182,7 @@ qt_target_qml_sources(spectacle + Gui/InlineMessageList.qml + Gui/Magnifier.qml + Gui/NewScreenshotToolButton.qml ++ Gui/OcrAction.qml + Gui/OptionsMenuButton.qml + Gui/Outline.qml + Gui/QmlUtils.qml +-- +GitLab + + +From ae7a749c89892c8f0d5494c2d7157970578b8b3f Mon Sep 17 00:00:00 2001 +From: Jhair Paris +Date: Sat, 7 Jun 2025 19:57:10 -0500 +Subject: [PATCH 2/3] Implement OcrManager class for text recognition + +- Add OcrManager class with Tesseract integration +- Provide async OCR processing methods +- Handle OCR initialization and cleanup + +Add OCR language selection to General Options + +- Introduced a new combo box for selecting the OCR language in the settings dialog. +- Implemented methods to populate and refresh the OCR language options based on availability. + +Add OCR action and integrate into UI toolbars + +- Create OcrAction.qml for text recognition functionality +- Add OCR buttons to CaptureOverlay toolbars +- Add OCR button to ViewerPage main toolbar + +Integrate OCR functionality into capture and viewer windows + +Add OCR notifications and core integration + +- Add OCR success/error notification events to notifyrc +- Integrate OCR manager in SpectacleCore + +Remove manual translations + +Implement OCR availability checks + +Enhance OcrManager to load Tesseract library dynamically and check its availability. + +Show info cursor on OCR tooltip icon in settings + +Refactor OCR language name handling using QLocale + +- Replace hardcoded/translatable language name map with dynamic lookup via QLocale and scriptToString. + +Refactor Tesseract initialization to support dynamic language detection + +Detect Tesseract and language packs at configure time; link directly to libtesseract + +- Add tesseract_test.cpp using TessBaseAPI::GetAvailableLanguagesAsVector() +- CMake: pkg_check_modules(TESSERACT) + try_run() to check usable langpacks + - Define HAVE_TESSERACT_OCR when successful; otherwise warn and disable OCR +- OCR: refactor OcrManager to use tesseract::TessBaseAPI (C++ API) + - Remove QLibrary-based dynamic loading and manual symbol resolution + - Wrap OCR code with #ifdef HAVE_TESSERACT_OCR and provide graceful fallbacks + +Refactor OCR text recognition to use ResultIterator for improved accuracy + +Refactor the OCR core: centralize extraction in SpectacleCore, remove direct OCR handling from windows. +--- + CMakeLists.txt | 48 +- + cmake/tesseract_test.cpp | 40 + + desktop/spectacle.notifyrc | 5 + + src/CMakeLists.txt | 9 +- + src/Config.h.in | 3 + + src/Gui/CaptureOverlay.qml | 9 + + src/Gui/CaptureWindow.cpp | 4 +- + src/Gui/OcrAction.qml | 14 + + src/Gui/SettingsDialog/GeneralOptions.ui | 127 ++++ + src/Gui/SettingsDialog/GeneralOptionsPage.cpp | 80 ++ + src/Gui/SettingsDialog/GeneralOptionsPage.h | 4 + + src/Gui/SettingsDialog/SettingsDialog.cpp | 5 + + src/Gui/SettingsDialog/spectacle.kcfg | 4 + + src/Gui/ViewerPage.qml | 5 + + src/Gui/ViewerWindow.cpp | 2 +- + src/OcrManager.cpp | 716 ++++++++++++++++++ + src/OcrManager.h | 175 +++++ + src/SpectacleCore.cpp | 143 ++++ + src/SpectacleCore.h | 9 + + 19 files changed, 1393 insertions(+), 9 deletions(-) + create mode 100644 cmake/tesseract_test.cpp + create mode 100644 src/Gui/OcrAction.qml + create mode 100644 src/OcrManager.cpp + create mode 100644 src/OcrManager.h + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 3038f472c..9b3c47fbe 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -92,16 +92,54 @@ find_package(OpenCV 4.7 REQUIRED core imgproc) + find_package(PkgConfig REQUIRED) + pkg_check_modules(TESSERACT REQUIRED tesseract) + ++# Find Tesseract for OCR functionality ++find_package(PkgConfig QUIET) ++if(PkgConfig_FOUND) ++ pkg_check_modules(TESSERACT tesseract) ++ ++ if(TESSERACT_FOUND) ++ # Test if Tesseract has usable language packs ++ try_run( ++ TESSERACT_TEST_RUN_RESULT ++ TESSERACT_TEST_COMPILE_RESULT ++ ${CMAKE_CURRENT_BINARY_DIR} ++ ${CMAKE_CURRENT_SOURCE_DIR}/cmake/tesseract_test.cpp ++ LINK_LIBRARIES ${TESSERACT_LIBRARIES} ++ CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${TESSERACT_INCLUDE_DIRS}" ++ COMPILE_OUTPUT_VARIABLE TESSERACT_COMPILE_OUTPUT ++ RUN_OUTPUT_VARIABLE TESSERACT_RUN_OUTPUT ++ ) ++ ++ if(TESSERACT_TEST_COMPILE_RESULT AND TESSERACT_TEST_RUN_RESULT EQUAL 0) ++ message(STATUS "Tesseract OCR support enabled") ++ message(STATUS "${TESSERACT_RUN_OUTPUT}") ++ set(HAVE_TESSERACT_OCR TRUE) ++ else() ++ message(WARNING "Tesseract library found but no usable language packs detected") ++ message(WARNING "${TESSERACT_RUN_OUTPUT}") ++ message(WARNING "OCR functionality will be disabled. Install language data packages (e.g., tesseract-ocr-eng)") ++ set(HAVE_TESSERACT_OCR FALSE) ++ endif() ++ else() ++ message(STATUS "Tesseract not found - OCR functionality disabled") ++ set(HAVE_TESSERACT_OCR FALSE) ++ endif() ++ ++ set_package_properties(TESSERACT PROPERTIES ++ DESCRIPTION "OCR engine for text recognition in screenshots" ++ TYPE OPTIONAL ++ PURPOSE "Enables optical character recognition functionality" ++ ) ++else() ++ message(STATUS "PkgConfig not found - Tesseract detection disabled") ++ set(HAVE_TESSERACT_OCR FALSE) ++endif() ++ + set_package_properties(KPipeWire PROPERTIES DESCRIPTION + "Used to record pipewire streams into a file" + TYPE REQUIRED + ) + +-set_package_properties(TESSERACT PROPERTIES DESCRIPTION +- "OCR (Optical Character Recognition) engine for text recognition in images" +- TYPE REQUIRED +-) +- + # optional components + find_package(KF6DocTools ${KF6_MIN_VERSION}) + set_package_properties(KF6DocTools PROPERTIES DESCRIPTION +diff --git a/cmake/tesseract_test.cpp b/cmake/tesseract_test.cpp +new file mode 100644 +index 000000000..4ebae9779 +--- /dev/null ++++ b/cmake/tesseract_test.cpp +@@ -0,0 +1,40 @@ ++#include ++#include ++#include ++#include ++ ++int main() ++{ ++ tesseract::TessBaseAPI api; ++ ++ if (api.Init(nullptr, nullptr) != 0) { ++ std::cerr << "Failed to initialize Tesseract" << std::endl; ++ return 1; ++ } ++ ++ std::vector languages; ++ api.GetAvailableLanguagesAsVector(&languages); ++ ++ // Filter out 'osd' as it's not a usable language for OCR ++ std::vector usableLanguages; ++ for (const auto &lang : languages) { ++ if (lang != "osd") { ++ usableLanguages.push_back(lang); ++ } ++ } ++ ++ if (usableLanguages.empty()) { ++ std::cerr << "No usable Tesseract language packs found. Install language data files (e.g., tesseract-ocr-eng)" << std::endl; ++ return 1; ++ } ++ ++ std::cout << "Found " << usableLanguages.size() << " Tesseract language pack(s): "; ++ for (size_t i = 0; i < usableLanguages.size(); ++i) { ++ std::cout << usableLanguages[i]; ++ if (i < usableLanguages.size() - 1) ++ std::cout << ", "; ++ } ++ std::cout << std::endl; ++ ++ return 0; ++} +diff --git a/desktop/spectacle.notifyrc b/desktop/spectacle.notifyrc +index 5c4166f0b..f3f65f679 100644 +--- a/desktop/spectacle.notifyrc ++++ b/desktop/spectacle.notifyrc +@@ -306,3 +306,8 @@ Comment[uk]=Було створено і збережено новий запи + Comment[zh_CN]=已录制并保存新的屏幕录像 + Comment[zh_TW]=新的螢幕錄製已擷取並儲存 + Action=Popup ++ ++[Event/ocrTextExtracted] ++Name=Text Extracted ++Comment=Text has been extracted from image using OCR ++Action=Popup +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index cb000b35d..c57535e34 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -105,7 +105,7 @@ ki18n_wrap_ui(spectacle + # Needed to compile with OpenCV + target_compile_options (spectacle PRIVATE -fexceptions) + +-target_include_directories(spectacle PUBLIC ${OpenCV_INCLUDE_DIRS} ${TESSERACT_INCLUDE_DIRS}) ++target_include_directories(spectacle PUBLIC ${OpenCV_INCLUDE_DIRS}) + + target_link_libraries(spectacle PRIVATE + Qt::Concurrent +@@ -136,9 +136,14 @@ target_link_libraries(spectacle PRIVATE + Wayland::Client + LayerShellQt::Interface + ${OpenCV_LIBRARIES} +- ${TESSERACT_LIBRARIES} + ) + ++# Link against Tesseract when OCR support is enabled ++if(HAVE_TESSERACT_OCR) ++ target_include_directories(spectacle PRIVATE ${TESSERACT_INCLUDE_DIRS}) ++ target_link_libraries(spectacle PRIVATE ${TESSERACT_LIBRARIES}) ++endif() ++ + # qt_add_qml_module doesn't know how to deal with headers in subdirectories so + # make sure to add those so the headers can be found. + target_include_directories(spectacle PRIVATE +diff --git a/src/Config.h.in b/src/Config.h.in +index 15313542a..aadb22252 100644 +--- a/src/Config.h.in ++++ b/src/Config.h.in +@@ -7,6 +7,9 @@ + /* Define to 1 if we have Purpose */ + #cmakedefine PURPOSE_FOUND 1 + ++/* Define to 1 if we have Tesseract OCR */ ++#cmakedefine HAVE_TESSERACT_OCR 1 ++ + /* Set the Spectacle version from CMake */ + #cmakedefine SPECTACLE_VERSION "@SPECTACLE_VERSION@" + +diff --git a/src/Gui/CaptureOverlay.qml b/src/Gui/CaptureOverlay.qml +index d9ca9a11c..37f3dcf85 100644 +--- a/src/Gui/CaptureOverlay.qml ++++ b/src/Gui/CaptureOverlay.qml +@@ -506,6 +506,11 @@ MouseArea { + visible: action.enabled + action: CopyImageAction {} + } ++ ToolButton { ++ display: TtToolButton.IconOnly ++ visible: action.enabled && !SpectacleCore.videoMode && SpectacleCore.ocrAvailable ++ action: OcrAction {} ++ } + ExportMenuButton { + focusPolicy: Qt.NoFocus + } +@@ -532,6 +537,10 @@ MouseArea { + visible: action.enabled + action: CopyImageAction {} + } ++ ToolButton { ++ visible: action.enabled && !SpectacleCore.videoMode && SpectacleCore.ocrAvailable ++ action: OcrAction {} ++ } + ExportMenuButton { + focusPolicy: Qt.NoFocus + } +diff --git a/src/Gui/CaptureWindow.cpp b/src/Gui/CaptureWindow.cpp +index fc4509cf3..cb8ce97ab 100644 +--- a/src/Gui/CaptureWindow.cpp ++++ b/src/Gui/CaptureWindow.cpp +@@ -8,11 +8,13 @@ + #include "CaptureWindow.h" + + #include "Config.h" +-#include "SpectacleCore.h" + #include "Gui/SelectionEditor.h" ++#include "SpectacleCore.h" + + #include + #include ++#include ++#include + + using namespace Qt::StringLiterals; + +diff --git a/src/Gui/OcrAction.qml b/src/Gui/OcrAction.qml +new file mode 100644 +index 000000000..f887ec0ee +--- /dev/null ++++ b/src/Gui/OcrAction.qml +@@ -0,0 +1,14 @@ ++/* SPDX-FileCopyrightText: 2025 Jhair Paris ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick.Templates as T ++import org.kde.spectacle.private ++ ++T.Action { ++ // OCR is only available for screenshots, not videos, and only when OCR is properly available ++ enabled: !SpectacleCore.videoMode && SpectacleCore.ocrAvailable ++ icon.name: "document-scan" ++ text: i18nc("@action", "Extract Text") ++ onTriggered: contextWindow.extractText() ++} +diff --git a/src/Gui/SettingsDialog/GeneralOptions.ui b/src/Gui/SettingsDialog/GeneralOptions.ui +index 1d99e9a33..ddbbf3e5a 100644 +--- a/src/Gui/SettingsDialog/GeneralOptions.ui ++++ b/src/Gui/SettingsDialog/GeneralOptions.ui +@@ -239,6 +239,132 @@ + + + ++ ++ ++ ++ Qt::Vertical ++ ++ ++ QSizePolicy::Fixed ++ ++ ++ ++ 10 ++ 10 ++ ++ ++ ++ ++ ++ ++ ++ Text Recognition (OCR) ++ ++ ++ ++ ++ ++ ++ Language: ++ ++ ++ ++ ++ ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ currentData ++ ++ ++ ++ ++ ++ ++ false ++ ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ 0 ++ ++ ++ 6 ++ ++ ++ ++ ++ OCR functionality is not available ++ ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ false ++ ++ ++ ++ ++ ++ ++ Please install the required packages: ++• tesseract ++• tesseract language data (e.g., tesseract-ocr-eng for English) ++ ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ Qt::AlignCenter ++ ++ ++ ++ 16 ++ 16 ++ ++ ++ ++ ++ 16 ++ 16 ++ ++ ++ ++ true ++ ++ ++ ++ ++ ++ ++ Qt::Horizontal ++ ++ ++ ++ 40 ++ 20 ++ ++ ++ ++ ++ ++ ++ + + + +@@ -257,6 +383,7 @@ + kcfg_useReleaseToCapture + kcfg_showCaptureInstructions + kcfg_rememberSelectionRect ++ kcfg_ocrLanguage + + + +diff --git a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp +index fcea6f671..5b8a5d9fc 100644 +--- a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp ++++ b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp +@@ -1,4 +1,5 @@ + /* ++ * SPDX-FileCopyrightText: 2025 Jhair Paris + * SPDX-FileCopyrightText: 2019 David Redondo + * SPDX-FileCopyrightText: 2015 Boudhayan Gupta + * +@@ -9,10 +10,13 @@ + + #include "settings.h" + #include "ui_GeneralOptions.h" ++#include "OcrManager.h" + + #include ++#include + + #include ++#include + + GeneralOptionsPage::GeneralOptionsPage(QWidget *parent) + : QWidget(parent) +@@ -20,8 +24,16 @@ GeneralOptionsPage::GeneralOptionsPage(QWidget *parent) + { + m_ui->setupUi(this); + ++ m_ui->ocrInfoIcon->setPixmap(QIcon::fromTheme(QStringLiteral("help-hint")).pixmap(16, 16)); ++ m_ui->ocrInfoIcon->setCursor(Qt::WhatsThisCursor); ++ + m_ui->runningTitle->setLevel(2); + m_ui->regionTitle->setLevel(2); ++ m_ui->ocrTitle->setLevel(2); ++ ++ setupOcrLanguageComboBox(); ++ ++ connect(OcrManager::instance(), &OcrManager::statusChanged, this, &GeneralOptionsPage::refreshOcrLanguageSettings); + + //On Wayland we can't programmatically raise and focus the window so we have to hide the option + if (KWindowSystem::isPlatformWayland() || qstrcmp(qgetenv("XDG_SESSION_TYPE").constData(), "wayland") == 0) { +@@ -31,4 +43,72 @@ GeneralOptionsPage::GeneralOptionsPage(QWidget *parent) + + GeneralOptionsPage::~GeneralOptionsPage() = default; + ++void GeneralOptionsPage::setupOcrLanguageComboBox() ++{ ++ OcrManager *ocrManager = OcrManager::instance(); ++ ++ if (!ocrManager->isAvailable()) { ++ m_ui->kcfg_ocrLanguage->setEnabled(false); ++ m_ui->kcfg_ocrLanguage->addItem(i18n("OCR not available")); ++ m_ui->ocrLanguageLabel->setVisible(false); ++ m_ui->kcfg_ocrLanguage->setVisible(false); ++ m_ui->ocrUnavailableWidget->setVisible(true); ++ return; ++ } ++ ++ const auto availableLanguages = ocrManager->availableLanguagesWithNames(); ++ ++ if (availableLanguages.isEmpty()) { ++ m_ui->kcfg_ocrLanguage->addItem(i18n("No languages found")); ++ m_ui->kcfg_ocrLanguage->setEnabled(false); ++ return; ++ } ++ ++ m_ui->kcfg_ocrLanguage->clear(); ++ m_ui->ocrLanguageLabel->setVisible(true); ++ m_ui->kcfg_ocrLanguage->setVisible(true); ++ m_ui->ocrUnavailableWidget->setVisible(false); ++ ++ for (auto it = availableLanguages.constBegin(); it != availableLanguages.constEnd(); ++it) { ++ m_ui->kcfg_ocrLanguage->addItem(it.value(), it.key()); ++ } ++} ++ ++void GeneralOptionsPage::refreshOcrLanguageSettings() ++{ ++ OcrManager *ocrManager = OcrManager::instance(); ++ ++ if (!ocrManager->isAvailable()) { ++ m_ui->ocrLanguageLabel->setVisible(false); ++ m_ui->kcfg_ocrLanguage->setVisible(false); ++ m_ui->ocrUnavailableWidget->setVisible(true); ++ return; ++ } ++ ++ const auto availableLanguages = ocrManager->availableLanguagesWithNames(); ++ ++ if (availableLanguages.isEmpty()) { ++ return; ++ } ++ ++ m_ui->kcfg_ocrLanguage->clear(); ++ m_ui->kcfg_ocrLanguage->setEnabled(true); ++ m_ui->ocrLanguageLabel->setVisible(true); ++ m_ui->kcfg_ocrLanguage->setVisible(true); ++ m_ui->ocrUnavailableWidget->setVisible(false); ++ ++ for (auto it = availableLanguages.constBegin(); it != availableLanguages.constEnd(); ++it) { ++ m_ui->kcfg_ocrLanguage->addItem(it.value(), it.key()); ++ } ++ ++ const QString currentLanguage = Settings::ocrLanguage(); ++ ++ for (int i = 0; i < m_ui->kcfg_ocrLanguage->count(); ++i) { ++ if (m_ui->kcfg_ocrLanguage->itemData(i).toString() == currentLanguage) { ++ m_ui->kcfg_ocrLanguage->setCurrentIndex(i); ++ break; ++ } ++ } ++} ++ + #include "moc_GeneralOptionsPage.cpp" +diff --git a/src/Gui/SettingsDialog/GeneralOptionsPage.h b/src/Gui/SettingsDialog/GeneralOptionsPage.h +index d8e7c5003..c184d6ba8 100644 +--- a/src/Gui/SettingsDialog/GeneralOptionsPage.h ++++ b/src/Gui/SettingsDialog/GeneralOptionsPage.h +@@ -19,8 +19,12 @@ class GeneralOptionsPage : public QWidget + public: + explicit GeneralOptionsPage(QWidget *parent = nullptr); + ~GeneralOptionsPage() override; ++ ++ void refreshOcrLanguageSettings(); + + private: ++ void setupOcrLanguageComboBox(); ++ + QScopedPointer m_ui; + }; + +diff --git a/src/Gui/SettingsDialog/SettingsDialog.cpp b/src/Gui/SettingsDialog/SettingsDialog.cpp +index a37d8344c..a19a47627 100644 +--- a/src/Gui/SettingsDialog/SettingsDialog.cpp ++++ b/src/Gui/SettingsDialog/SettingsDialog.cpp +@@ -64,6 +64,9 @@ void SettingsDialog::showEvent(QShowEvent *event) + auto parent = parentWidget(); + bool onTop = parent && parent->windowHandle()->flags().testFlag(Qt::WindowStaysOnTopHint); + windowHandle()->setFlag(Qt::WindowStaysOnTopHint, onTop); ++ ++ m_generalPage->refreshOcrLanguageSettings(); ++ + KConfigDialog::showEvent(event); + } + +@@ -87,6 +90,8 @@ void SettingsDialog::updateWidgets() + { + KConfigDialog::updateWidgets(); + m_shortcutsPage->resetChanges(); ++ ++ m_generalPage->refreshOcrLanguageSettings(); + } + + void SettingsDialog::updateWidgetsDefault() +diff --git a/src/Gui/SettingsDialog/spectacle.kcfg b/src/Gui/SettingsDialog/spectacle.kcfg +index e37b9e5b4..4517e2344 100644 +--- a/src/Gui/SettingsDialog/spectacle.kcfg ++++ b/src/Gui/SettingsDialog/spectacle.kcfg +@@ -70,6 +70,10 @@ + + UntilClosed + ++ ++ ++ eng ++ + + + +diff --git a/src/Gui/ViewerPage.qml b/src/Gui/ViewerPage.qml +index 6e77887a8..602e4431b 100644 +--- a/src/Gui/ViewerPage.qml ++++ b/src/Gui/ViewerPage.qml +@@ -61,6 +61,11 @@ EmptyPage { + visible: action.enabled + action: CopyImageAction {} + } ++ TtToolButton { ++ display: TtToolButton.IconOnly ++ visible: action.enabled && SpectacleCore.ocrAvailable ++ action: OcrAction {} ++ } + // We only show this in video mode to save space in screenshot mode + TtToolButton { + visible: SpectacleCore.videoMode +diff --git a/src/Gui/ViewerWindow.cpp b/src/Gui/ViewerWindow.cpp +index 68812495d..8c0d9941f 100644 +--- a/src/Gui/ViewerWindow.cpp ++++ b/src/Gui/ViewerWindow.cpp +@@ -8,9 +8,9 @@ + #include "ViewerWindow.h" + + #include "Config.h" +-#include "SpectacleCore.h" + #include "Gui/ExportMenu.h" + #include "InlineMessageModel.h" ++#include "SpectacleCore.h" + + #include + #include +diff --git a/src/OcrManager.cpp b/src/OcrManager.cpp +new file mode 100644 +index 000000000..1d09db8ef +--- /dev/null ++++ b/src/OcrManager.cpp +@@ -0,0 +1,716 @@ ++/* This file is part of Spectacle, the KDE screenshot utility ++ * SPDX-FileCopyrightText: 2025 Jhair Paris ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++#include "OcrManager.h" ++#include "settings.h" ++#include "spectacle_debug.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++using namespace Qt::StringLiterals; ++ ++OcrManager *OcrManager::s_instance = nullptr; ++ ++OcrManager::OcrManager(QObject *parent) ++ : QObject(parent) ++#ifdef HAVE_TESSERACT_OCR ++ , m_tesseract(nullptr) ++ , m_worker(nullptr) ++#endif ++ , m_workerThread(std::make_unique()) ++ , m_timeoutTimer(new QTimer(this)) ++ , m_status(OcrStatus::Ready) ++ , m_currentLanguageCode() // Current language code ("eng+spa") ++ , m_configuredLanguages() // Languages from Settings (persistent) ++ , m_activeLanguages() ++ , m_shouldRestoreToConfigured(false) // Flag to restore after temp language use ++ , m_initialized(false) ++{ ++#ifdef HAVE_TESSERACT_OCR ++ m_timeoutTimer->setSingleShot(true); ++ m_timeoutTimer->setInterval(30000); ++ ++ connect(m_timeoutTimer, &QTimer::timeout, this, [this]() { ++ qCWarning(SPECTACLE_LOG) << "OCR recognition timed out"; ++ setStatus(OcrStatus::Error); ++ }); ++ ++ m_worker = new OcrWorker(); ++ m_worker->moveToThread(m_workerThread.get()); ++ connect(m_worker, &OcrWorker::imageProcessed, this, &OcrManager::handleRecognitionComplete); ++ m_workerThread->start(); ++ ++ connect(Settings::self(), &Settings::ocrLanguagesChanged, this, [this]() { ++ const QStringList newLanguages = Settings::ocrLanguages(); ++ const QString combinedLanguages = newLanguages.join(u"+"_s); ++ if (combinedLanguages != m_currentLanguageCode) { ++ setLanguagesByCode(newLanguages); ++ } ++ }); ++ ++ QTimer::singleShot(0, this, &OcrManager::initializeTesseract); ++#endif ++} ++ ++OcrManager::~OcrManager() ++{ ++#ifdef HAVE_TESSERACT_OCR ++ if (m_worker) { ++ if (m_workerThread && m_workerThread->isRunning()) { ++ QMetaObject::invokeMethod(m_worker, &QObject::deleteLater, Qt::QueuedConnection); ++ } else { ++ delete m_worker; ++ } ++ m_worker = nullptr; ++ } ++#endif ++ if (m_workerThread && m_workerThread->isRunning()) { ++ m_workerThread->quit(); ++ m_workerThread->wait(3000); ++ } ++#ifdef HAVE_TESSERACT_OCR ++ if (m_tesseract) { ++ m_tesseract->End(); ++ delete m_tesseract; ++ m_tesseract = nullptr; ++ } ++#endif ++} ++ ++OcrManager *OcrManager::instance() ++{ ++ if (!s_instance) { ++ s_instance = new OcrManager(qApp); ++ } ++ return s_instance; ++} ++ ++bool OcrManager::isAvailable() const ++{ ++#ifdef HAVE_TESSERACT_OCR ++ return m_initialized && m_tesseract != nullptr; ++#else ++ return false; ++#endif ++} ++ ++OcrManager::OcrStatus OcrManager::status() const ++{ ++ return m_status; ++} ++ ++QMap OcrManager::availableLanguagesWithNames() const ++{ ++ QMap result; ++ for (const QString &langCode : m_availableLanguages) { ++ result[langCode] = m_languageNames.value(langCode, langCode); ++ } ++ return result; ++} ++ ++void OcrManager::setLanguagesByCode(const QStringList &languageCodes) ++{ ++#ifdef HAVE_TESSERACT_OCR ++ if (languageCodes.isEmpty()) { ++ qCWarning(SPECTACLE_LOG) << "No OCR languages specified"; ++ return; ++ } ++ ++ if (validateAndApplyLanguages(languageCodes)) { ++ m_configuredLanguages = m_activeLanguages; ++ Settings::setOcrLanguages(m_activeLanguages); ++ Settings::self()->save(); ++ qCDebug(SPECTACLE_LOG) << "OCR languages successfully changed to:" << m_currentLanguageCode; ++ } else { ++ qCWarning(SPECTACLE_LOG) << "Failed to set OCR languages"; ++ } ++#else ++ Q_UNUSED(languageCodes); ++ qCWarning(SPECTACLE_LOG) << "OCR not available - Tesseract not compiled in"; ++#endif ++} ++ ++QString OcrManager::currentLanguageCode() const ++{ ++ return m_currentLanguageCode; ++} ++ ++void OcrManager::recognizeText(const QImage &image) ++{ ++#ifdef HAVE_TESSERACT_OCR ++ if (!isAvailable()) { ++ qCWarning(SPECTACLE_LOG) << "Cannot start OCR: engine is not available"; ++ Q_EMIT textRecognized(QString(), false); ++ return; ++ } ++ ++ if (m_status == OcrStatus::Processing) { ++ qCWarning(SPECTACLE_LOG) << "Cannot start OCR: text extraction already running"; ++ Q_EMIT textRecognized(QString(), false); ++ return; ++ } ++ ++ if (image.isNull() || image.size().isEmpty()) { ++ qCWarning(SPECTACLE_LOG) << "Cannot start OCR: invalid image provided"; ++ Q_EMIT textRecognized(QString(), false); ++ return; ++ } ++ ++ // Ensure configured languages are active ++ if (m_configuredLanguages.isEmpty() || m_activeLanguages != m_configuredLanguages) { ++ if (!validateAndApplyLanguages(m_configuredLanguages)) { ++ qCWarning(SPECTACLE_LOG) << "Cannot start OCR: failed to activate configured languages"; ++ Q_EMIT textRecognized(QString(), false); ++ return; ++ } ++ } ++ ++ beginRecognition(image); ++#else ++ Q_UNUSED(image); ++ qCWarning(SPECTACLE_LOG) << "Cannot start OCR: Spectacle built without Tesseract support"; ++ Q_EMIT textRecognized(QString(), false); ++#endif ++} ++ ++void OcrManager::recognizeTextWithLanguage(const QImage &image, const QString &languageCode) ++{ ++#ifdef HAVE_TESSERACT_OCR ++ if (languageCode.isEmpty()) { ++ recognizeText(image); ++ return; ++ } ++ ++ if (!isAvailable()) { ++ qCWarning(SPECTACLE_LOG) << "Cannot start OCR with language" << languageCode << ": engine is not available"; ++ Q_EMIT textRecognized(QString(), false); ++ return; ++ } ++ ++ if (m_status == OcrStatus::Processing) { ++ qCWarning(SPECTACLE_LOG) << "Cannot start OCR with language" << languageCode << ": text extraction already running"; ++ Q_EMIT textRecognized(QString(), false); ++ return; ++ } ++ ++ if (image.isNull() || image.size().isEmpty()) { ++ qCWarning(SPECTACLE_LOG) << "Cannot start OCR with language" << languageCode << ": invalid image provided"; ++ Q_EMIT textRecognized(QString(), false); ++ return; ++ } ++ ++ const QStringList tempLanguages{languageCode}; ++ if (!validateAndApplyLanguages(tempLanguages)) { ++ qCWarning(SPECTACLE_LOG) << "Cannot start OCR with language" << languageCode << ": failed to activate language"; ++ Q_EMIT textRecognized(QString(), false); ++ return; ++ } ++ ++ // Store that we need to restore after recognition ++ m_shouldRestoreToConfigured = (m_activeLanguages != m_configuredLanguages); ++ ++ beginRecognition(image); ++#else ++ Q_UNUSED(image); ++ Q_UNUSED(languageCode); ++ qCWarning(SPECTACLE_LOG) << "Cannot start OCR: Spectacle built without Tesseract support"; ++ Q_EMIT textRecognized(QString(), false); ++#endif ++} ++ ++void OcrManager::handleRecognitionComplete(const QString &text, bool success) ++{ ++ m_timeoutTimer->stop(); ++ ++ if (success) { ++ setStatus(OcrStatus::Ready); ++ ++ if (!text.isEmpty()) { ++ QApplication::clipboard()->setText(text); ++ } ++ ++ Q_EMIT textRecognized(text, true); ++ qCDebug(SPECTACLE_LOG) << "OCR recognition completed successfully"; ++ } else { ++ setStatus(OcrStatus::Error); ++ Q_EMIT textRecognized(QString(), false); ++ qCWarning(SPECTACLE_LOG) << "OCR recognition failed"; ++ } ++ ++ // Restore configured languages if we used temporary ones ++ if (m_shouldRestoreToConfigured && !m_configuredLanguages.isEmpty()) { ++ validateAndApplyLanguages(m_configuredLanguages); ++ m_shouldRestoreToConfigured = false; ++ } ++} ++ ++bool OcrManager::validateAndApplyLanguages(const QStringList &languageCodes) ++{ ++#ifdef HAVE_TESSERACT_OCR ++ if (languageCodes.isEmpty()) { ++ qCWarning(SPECTACLE_LOG) << "No OCR languages provided"; ++ return false; ++ } ++ ++ QStringList validLanguages; ++ for (const QString &lang : languageCodes) { ++ if (lang == u"osd"_s) { ++ qCDebug(SPECTACLE_LOG) << "Skipping 'osd' language"; ++ continue; ++ } ++ ++ if (!isLanguageAvailable(lang)) { ++ qCWarning(SPECTACLE_LOG) << "OCR language not available:" << lang; ++ continue; ++ } ++ ++ if (!validLanguages.contains(lang)) { ++ validLanguages.append(lang); ++ } ++ } ++ ++ if (validLanguages.isEmpty()) { ++ qCWarning(SPECTACLE_LOG) << "No valid OCR languages after filtering"; ++ return false; ++ } ++ ++ if (validLanguages.size() > MAX_OCR_LANGUAGES) { ++ validLanguages = validLanguages.mid(0, MAX_OCR_LANGUAGES); ++ qCInfo(SPECTACLE_LOG) << "Limited to" << MAX_OCR_LANGUAGES << "languages:" << validLanguages; ++ } ++ ++ const QString combinedLanguages = validLanguages.join(u"+"_s); ++ ++ if (m_currentLanguageCode == combinedLanguages && !m_activeLanguages.isEmpty()) { ++ qCDebug(SPECTACLE_LOG) << "Languages already active, no change needed"; ++ return true; ++ } ++ ++ if (!setupTesseractLanguages(validLanguages)) { ++ qCWarning(SPECTACLE_LOG) << "Failed to apply OCR languages:" << combinedLanguages; ++ return false; ++ } ++ ++ m_activeLanguages = validLanguages; ++ m_currentLanguageCode = combinedLanguages; ++ ++ qCDebug(SPECTACLE_LOG) << "OCR languages applied:" << combinedLanguages; ++ return true; ++#else ++ Q_UNUSED(languageCodes); ++ return false; ++#endif ++} ++ ++void OcrManager::beginRecognition(const QImage &image) ++{ ++#ifdef HAVE_TESSERACT_OCR ++ setStatus(OcrStatus::Processing); ++ m_timeoutTimer->start(); ++ ++ QMetaObject::invokeMethod( ++ m_worker, ++ [worker = m_worker, image, tesseract = m_tesseract]() { ++ worker->processImage(image, tesseract); ++ }, ++ Qt::QueuedConnection); ++#else ++ Q_UNUSED(image); ++#endif ++} ++ ++void OcrManager::initializeTesseract() ++{ ++#ifdef HAVE_TESSERACT_OCR ++ try { ++ m_tesseract = new tesseract::TessBaseAPI(); ++ ++ if (m_tesseract->Init(nullptr, nullptr) != 0) { ++ qCWarning(SPECTACLE_LOG) << "Failed to initialize Tesseract OCR engine with auto-detection"; ++ setStatus(OcrStatus::Error); ++ delete m_tesseract; ++ m_tesseract = nullptr; ++ return; ++ } ++ ++ const char *datapath = m_tesseract->GetDatapath(); ++ QString tessdataPath = datapath ? QString::fromUtf8(datapath) : QString(); ++ qCDebug(SPECTACLE_LOG) << "Using tessdata path: " << tessdataPath; ++ ++ setupAvailableLanguages(tessdataPath); ++ ++ if (m_availableLanguages.isEmpty()) { ++ qCWarning(SPECTACLE_LOG) << "No language data files found in tessdata directory"; ++ setStatus(OcrStatus::Error); ++ delete m_tesseract; ++ m_tesseract = nullptr; ++ return; ++ } ++ ++ m_tesseract->End(); ++ ++ QStringList configLanguages = Settings::ocrLanguages(); ++ QStringList initLanguages; ++ ++ // Use configured languages if valid, otherwise fallback to first available ++ for (const QString &lang : configLanguages) { ++ if (!lang.isEmpty() && m_availableLanguages.contains(lang) && lang != u"osd"_s) { ++ initLanguages.append(lang); ++ } ++ } ++ ++ if (initLanguages.isEmpty()) { ++ auto it = std::find_if(m_availableLanguages.begin(), m_availableLanguages.end(), [](const QString &lang) { ++ return lang != u"osd"_s; ++ }); ++ ++ if (it != m_availableLanguages.end()) { ++ initLanguages.append(*it); ++ } else { ++ qCCritical(SPECTACLE_LOG) << "No fallback language available (only osd present)"; ++ setStatus(OcrStatus::Error); ++ delete m_tesseract; ++ m_tesseract = nullptr; ++ return; ++ } ++ } ++ ++ const QString combinedInitLanguages = initLanguages.join(u"+"_s); ++ qCDebug(SPECTACLE_LOG) << "Initializing Tesseract with languages:" << combinedInitLanguages; ++ ++ if (m_tesseract->Init(nullptr, combinedInitLanguages.toUtf8().constData()) != 0) { ++ qCWarning(SPECTACLE_LOG) << "Failed to initialize Tesseract with languages:" << combinedInitLanguages; ++ setStatus(OcrStatus::Error); ++ delete m_tesseract; ++ m_tesseract = nullptr; ++ return; ++ } ++ ++ m_currentLanguageCode = combinedInitLanguages; ++ m_tesseract->SetPageSegMode(tesseract::PSM_AUTO); ++ ++ m_initialized = true; ++ setStatus(OcrStatus::Ready); ++ qCDebug(SPECTACLE_LOG) << "Tesseract OCR engine initialized successfully with languages:" << combinedInitLanguages; ++ ++ loadSavedLanguageSetting(); ++ } catch (const std::exception &e) { ++ qCWarning(SPECTACLE_LOG) << "Exception during Tesseract initialization:" << e.what(); ++ setStatus(OcrStatus::Error); ++ if (m_tesseract) { ++ delete m_tesseract; ++ m_tesseract = nullptr; ++ } ++ } ++#else ++ qCDebug(SPECTACLE_LOG) << "Tesseract OCR not available - compiled out"; ++ setStatus(OcrStatus::Error); ++#endif ++} ++ ++void OcrManager::loadSavedLanguageSetting() ++{ ++ if (!isAvailable()) { ++ qCDebug(SPECTACLE_LOG) << "OCR not available, skipping language loading"; ++ return; ++ } ++ ++ QStringList savedLanguages = Settings::ocrLanguages(); ++ qCDebug(SPECTACLE_LOG) << "Loaded OCR languages setting from config:" << savedLanguages; ++ qCDebug(SPECTACLE_LOG) << "Current OCR language code:" << m_currentLanguageCode; ++ qCDebug(SPECTACLE_LOG) << "Available languages:" << m_availableLanguages; ++ ++ QStringList validLanguages; ++ for (const QString &lang : savedLanguages) { ++ if (lang != u"osd"_s && isLanguageAvailable(lang)) { ++ validLanguages.append(lang); ++ } ++ } ++ ++ if (validLanguages.isEmpty()) { ++ // Find first valid language as fallback ++ auto it = std::find_if(m_availableLanguages.begin(), m_availableLanguages.end(), [](const QString &lang) { ++ return lang != u"osd"_s; ++ }); ++ if (it != m_availableLanguages.end()) { ++ validLanguages.append(*it); ++ } else { ++ qCWarning(SPECTACLE_LOG) << "No usable languages available (only osd present), cannot set default"; ++ return; ++ } ++ qCDebug(SPECTACLE_LOG) << "No valid saved languages, using default:" << validLanguages; ++ Settings::setOcrLanguages(validLanguages); ++ Settings::self()->save(); ++ } ++ ++ m_configuredLanguages = validLanguages; ++ ++ const QString combinedLanguages = validLanguages.join(u"+"_s); ++ if (combinedLanguages != m_currentLanguageCode) { ++ qCDebug(SPECTACLE_LOG) << "Loading OCR languages setting:" << validLanguages; ++ validateAndApplyLanguages(validLanguages); ++ } else { ++ qCDebug(SPECTACLE_LOG) << "OCR languages already set to:" << combinedLanguages; ++ m_activeLanguages = validLanguages; ++ } ++} ++ ++void OcrManager::setStatus(OcrStatus status) ++{ ++ if (m_status == status) { ++ return; ++ } ++ ++ m_status = status; ++ Q_EMIT statusChanged(status); ++} ++ ++bool OcrManager::isLanguageAvailable(const QString &languageCode) const ++{ ++ return m_availableLanguages.contains(languageCode); ++} ++ ++bool OcrManager::setupTesseractLanguages(const QStringList &langCodes) ++{ ++#ifdef HAVE_TESSERACT_OCR ++ if (!m_tesseract || langCodes.isEmpty()) { ++ return false; ++ } ++ ++ const char *datapath = m_tesseract->GetDatapath(); ++ QString tessdataPath = datapath ? QString::fromUtf8(datapath) : QString(); ++ ++ if (tessdataPath.isEmpty()) { ++ qCWarning(SPECTACLE_LOG) << "Tessdata path not found"; ++ return false; ++ } ++ ++ for (const QString &langCode : langCodes) { ++ const QString langFile = QDir(tessdataPath).filePath(langCode + u".traineddata"_s); ++ if (!QFile::exists(langFile)) { ++ qCWarning(SPECTACLE_LOG) << "Language file not found:" << langFile; ++ return false; ++ } ++ } ++ ++ try { ++ m_tesseract->End(); ++ ++ const QString combinedLangs = langCodes.join(u"+"_s); ++ ++ if (m_tesseract->Init(nullptr, combinedLangs.toUtf8().constData()) != 0) { ++ qCWarning(SPECTACLE_LOG) << "Failed to initialize Tesseract with languages:" << combinedLangs; ++ ++ // Fallback to first available language ++ QString fallbackLang; ++ if (!m_availableLanguages.isEmpty()) { ++ auto it = std::find_if(m_availableLanguages.begin(), m_availableLanguages.end(), [](const QString &lang) { ++ return lang != u"osd"_s; ++ }); ++ if (it != m_availableLanguages.end()) { ++ fallbackLang = *it; ++ } ++ } ++ ++ if (!fallbackLang.isEmpty() && m_tesseract->Init(nullptr, fallbackLang.toUtf8().constData()) != 0) { ++ qCCritical(SPECTACLE_LOG) << "Failed to fallback to language:" << fallbackLang; ++ return false; ++ } ++ return false; ++ } ++ ++ m_tesseract->SetPageSegMode(tesseract::PSM_AUTO); ++ return true; ++ } catch (const std::exception &e) { ++ qCWarning(SPECTACLE_LOG) << "Exception while setting up Tesseract languages:" << e.what(); ++ return false; ++ } ++#else ++ Q_UNUSED(langCodes); ++ return false; ++#endif ++} ++ ++void OcrManager::setupAvailableLanguages(const QString &tessdataPath) ++{ ++#ifdef HAVE_TESSERACT_OCR ++ m_availableLanguages.clear(); ++ m_languageNames.clear(); ++ ++ if (!m_tesseract) { ++ qCWarning(SPECTACLE_LOG) << "Cannot enumerate OCR languages: Tesseract not initialized"; ++ return; ++ } ++ ++ QStringList detectedLanguages; ++ ++ try { ++ std::vector available; ++ m_tesseract->GetAvailableLanguagesAsVector(&available); ++ detectedLanguages.reserve(static_cast(available.size())); ++ ++ for (const std::string &language : available) { ++ const QString langCode = QString::fromStdString(language); ++ if (langCode.isEmpty()) { ++ continue; ++ } ++ ++ if (!tessdataPath.isEmpty()) { ++ const QString trainedDataPath = QDir(tessdataPath).filePath(langCode + u".traineddata"_s); ++ if (!QFile::exists(trainedDataPath)) { ++ qCDebug(SPECTACLE_LOG) << "Skipping OCR language" << langCode << "- missing traineddata at" << trainedDataPath; ++ continue; ++ } ++ } ++ ++ if (!detectedLanguages.contains(langCode)) { ++ detectedLanguages.append(langCode); ++ } ++ } ++ } catch (const std::exception &e) { ++ qCWarning(SPECTACLE_LOG) << "Exception while enumerating Tesseract languages:" << e.what(); ++ } ++ ++ std::sort(detectedLanguages.begin(), detectedLanguages.end()); ++ m_availableLanguages = detectedLanguages; ++ ++ for (const QString &langCode : std::as_const(m_availableLanguages)) { ++ if (langCode == u"osd"_s) { ++ m_languageNames.insert(langCode, i18nc("@item:inlistbox", "Orientation and Script Detection")); ++ continue; ++ } ++ ++ const QString displayName = tesseractLangName(langCode); ++ m_languageNames.insert(langCode, displayName); ++ } ++ ++ qCDebug(SPECTACLE_LOG) << "Detected OCR languages:" << m_availableLanguages; ++#else ++ Q_UNUSED(tessdataPath); ++#endif ++} ++ ++QString OcrManager::tesseractLangName(const QString &tesseractCode) const ++{ ++ static const QMap tesseractToIsoMap = { ++ {u"afr"_s, u"af"_s}, {u"ara"_s, u"ar"_s}, {u"aze"_s, u"az"_s}, {u"aze_cyrl"_s, u"az"_s}, {u"bel"_s, u"be"_s}, ++ {u"ben"_s, u"bn"_s}, {u"bul"_s, u"bg"_s}, {u"cat"_s, u"ca"_s}, {u"ces"_s, u"cs"_s}, {u"chi_sim"_s, u"zh_CN"_s}, ++ {u"chi_tra"_s, u"zh_TW"_s}, {u"cym"_s, u"cy"_s}, {u"dan"_s, u"da"_s}, {u"dan_frak"_s, u"da"_s}, {u"deu"_s, u"de"_s}, ++ {u"deu_frak"_s, u"de"_s}, {u"deu_latf"_s, u"de"_s}, {u"ell"_s, u"el"_s}, {u"eng"_s, u"en"_s}, {u"epo"_s, u"eo"_s}, ++ {u"est"_s, u"et"_s}, {u"eus"_s, u"eu"_s}, {u"fas"_s, u"fa"_s}, {u"fin"_s, u"fi"_s}, {u"fra"_s, u"fr"_s}, ++ {u"frk"_s, u"de"_s}, {u"gla"_s, u"gd"_s}, {u"gle"_s, u"ga"_s}, {u"glg"_s, u"gl"_s}, {u"heb"_s, u"he"_s}, ++ {u"hin"_s, u"hi"_s}, {u"hrv"_s, u"hr"_s}, {u"hun"_s, u"hu"_s}, {u"ind"_s, u"id"_s}, {u"isl"_s, u"is"_s}, ++ {u"ita"_s, u"it"_s}, {u"ita_old"_s, u"it"_s}, {u"jpn"_s, u"ja"_s}, {u"kor"_s, u"ko"_s}, {u"kor_vert"_s, u"ko"_s}, ++ {u"lav"_s, u"lv"_s}, {u"lit"_s, u"lt"_s}, {u"nld"_s, u"nl"_s}, {u"nor"_s, u"no"_s}, {u"pol"_s, u"pl"_s}, ++ {u"por"_s, u"pt"_s}, {u"ron"_s, u"ro"_s}, {u"rus"_s, u"ru"_s}, {u"slk"_s, u"sk"_s}, {u"slk_frak"_s, u"sk"_s}, ++ {u"slv"_s, u"sl"_s}, {u"spa"_s, u"es"_s}, {u"spa_old"_s, u"es"_s}, {u"srp"_s, u"sr"_s}, {u"srp_latn"_s, u"sr"_s}, ++ {u"swe"_s, u"sv"_s}, {u"tur"_s, u"tr"_s}, {u"ukr"_s, u"uk"_s}, {u"vie"_s, u"vi"_s}, {u"amh"_s, u"am"_s}, ++ {u"asm"_s, u"as"_s}, {u"bod"_s, u"bo"_s}, {u"dzo"_s, u"dz"_s}, {u"guj"_s, u"gu"_s}, {u"kan"_s, u"kn"_s}, ++ {u"kat"_s, u"ka"_s}, {u"kat_old"_s, u"ka"_s}, {u"kaz"_s, u"kk"_s}, {u"khm"_s, u"km"_s}, {u"kir"_s, u"ky"_s}, ++ {u"lao"_s, u"lo"_s}, {u"mal"_s, u"ml"_s}, {u"mar"_s, u"mr"_s}, {u"mya"_s, u"my"_s}, {u"nep"_s, u"ne"_s}, ++ {u"ori"_s, u"or"_s}, {u"pan"_s, u"pa"_s}, {u"sin"_s, u"si"_s}, {u"tam"_s, u"ta"_s}, {u"tel"_s, u"te"_s}, ++ {u"tha"_s, u"th"_s}, {u"urd"_s, u"ur"_s}, {u"bos"_s, u"bs"_s}, {u"bre"_s, u"br"_s}, {u"cos"_s, u"co"_s}, ++ {u"fao"_s, u"fo"_s}, {u"fil"_s, u"tl"_s}, {u"fry"_s, u"fy"_s}, {u"hat"_s, u"ht"_s}, {u"hye"_s, u"hy"_s}, ++ {u"iku"_s, u"iu"_s}, {u"jav"_s, u"jv"_s}, {u"kmr"_s, u"ku"_s}, {u"kur"_s, u"ku"_s}, {u"lat"_s, u"la"_s}, ++ {u"ltz"_s, u"lb"_s}, {u"mkd"_s, u"mk"_s}, {u"mlt"_s, u"mt"_s}, {u"mon"_s, u"mn"_s}, {u"mri"_s, u"mi"_s}, ++ {u"msa"_s, u"ms"_s}, {u"oci"_s, u"oc"_s}, {u"pus"_s, u"ps"_s}, {u"que"_s, u"qu"_s}, {u"san"_s, u"sa"_s}, ++ {u"snd"_s, u"sd"_s}, {u"sqi"_s, u"sq"_s}, {u"sun"_s, u"su"_s}, {u"swa"_s, u"sw"_s}, {u"tat"_s, u"tt"_s}, ++ {u"tgk"_s, u"tg"_s}, {u"tgl"_s, u"tl"_s}, {u"tir"_s, u"ti"_s}, {u"ton"_s, u"to"_s}, {u"uig"_s, u"ug"_s}, ++ {u"uzb"_s, u"uz"_s}, {u"uzb_cyrl"_s, u"uz"_s}, {u"yid"_s, u"yi"_s}, {u"yor"_s, u"yo"_s}, ++ }; ++ ++ if (tesseractCode == u"equ"_s) { ++ return i18n("Math/Equation Detection"); ++ } ++ if (tesseractCode == u"osd"_s) { ++ return i18n("Orientation and Script Detection"); ++ } ++ ++ const QString isoCode = tesseractToIsoMap.value(tesseractCode); ++ if (!isoCode.isEmpty()) { ++ QLocale locale(isoCode); ++ QString name = locale.nativeLanguageName(); ++ ++ if (!name.isEmpty()) { ++ name[0] = name[0].toUpper(); ++ return name; ++ } ++ ++ QString languageName = QLocale::languageToString(locale.language()); ++ if (!languageName.isEmpty()) { ++ languageName[0] = languageName[0].toUpper(); ++ return languageName; ++ } ++ } ++ ++ return tesseractCode; ++} ++ ++OcrWorker::OcrWorker(QObject *parent) ++ : QObject(parent) ++{ ++} ++ ++void OcrWorker::processImage(const QImage &image, tesseract::TessBaseAPI *tesseract) ++{ ++#ifdef HAVE_TESSERACT_OCR ++ QMutexLocker locker(&m_mutex); ++ ++ if (!tesseract || image.isNull()) { ++ Q_EMIT imageProcessed(QString(), false); ++ return; ++ } ++ ++ try { ++ QImage rgbImage = image.convertToFormat(QImage::Format_RGB888); ++ ++ tesseract->SetImage(rgbImage.bits(), rgbImage.width(), rgbImage.height(), 3, rgbImage.bytesPerLine()); ++ ++ if (tesseract->Recognize(0) != 0) { ++ Q_EMIT imageProcessed(QString(), false); ++ return; ++ } ++ ++ QStringList lines; ++ std::unique_ptr iterator(tesseract->GetIterator()); ++ ++ if (iterator) { ++ do { ++ const char *lineText = iterator->GetUTF8Text(tesseract::RIL_TEXTLINE); ++ if (lineText != nullptr) { ++ QString line = QString::fromUtf8(lineText).trimmed(); ++ if (!line.isEmpty()) { ++ lines.append(line); ++ } ++ delete[] lineText; ++ } ++ } while (iterator->Next(tesseract::RIL_TEXTLINE)); ++ } ++ ++ const QString result = lines.join(QLatin1Char('\n')).trimmed(); ++ Q_EMIT imageProcessed(result, true); ++ } catch (const std::exception &e) { ++ qCWarning(SPECTACLE_LOG) << "Exception in OCR worker:" << e.what(); ++ Q_EMIT imageProcessed(QString(), false); ++ } ++#else ++ Q_UNUSED(image); ++ Q_UNUSED(tesseract); ++ Q_EMIT imageProcessed(QString(), false); ++#endif ++} +diff --git a/src/OcrManager.h b/src/OcrManager.h +new file mode 100644 +index 000000000..c71505b3e +--- /dev/null ++++ b/src/OcrManager.h +@@ -0,0 +1,175 @@ ++/* This file is part of Spectacle, the KDE screenshot utility ++ * SPDX-FileCopyrightText: 2025 Jhair Paris ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++#pragma once ++ ++#include "Config.h" ++ ++#ifdef HAVE_TESSERACT_OCR ++#include ++#else ++namespace tesseract ++{ ++class TessBaseAPI; ++} ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/** ++ * @brief Worker class for OCR processing in background thread ++ */ ++class OcrWorker : public QObject ++{ ++ Q_OBJECT ++ ++public: ++ explicit OcrWorker(QObject *parent = nullptr); ++ ++public Q_SLOTS: ++ void processImage(const QImage &image, tesseract::TessBaseAPI *tesseract); ++ ++Q_SIGNALS: ++ void imageProcessed(const QString &text, bool success); ++ ++private: ++ QMutex m_mutex; ++}; ++ ++/** ++ * This class uses Tesseract OCR engine to extract text from images. ++ * It provides both synchronous and asynchronous text recognition capabilities. ++ */ ++class OcrManager : public QObject ++{ ++ Q_OBJECT ++ ++public: ++ static constexpr int MAX_OCR_LANGUAGES = 4; ++ static constexpr int MIN_OCR_LANGUAGES = 1; ++ enum class OcrStatus { ++ Ready = 0, ++ Processing = 1, ++ Error = 2 ++ }; ++ Q_ENUM(OcrStatus) ++ ++ explicit OcrManager(QObject *parent = nullptr); ++ ~OcrManager() override; ++ ++ static OcrManager *instance(); ++ ++ /** ++ * @brief Check if OCR engine is available and properly initialized ++ * @return true if OCR is available, false otherwise ++ */ ++ bool isAvailable() const; ++ ++ /** ++ * @brief Get the current OCR processing status ++ * @return Current status of the OCR engine ++ */ ++ OcrStatus status() const; ++ ++ /** ++ * @brief Get a map of available languages with human-readable names ++ * @return QMap where key is language code and value is display name ++ */ ++ QMap availableLanguagesWithNames() const; ++ ++ /** ++ * @brief Set multiple languages for OCR processing ++ * @param languageCodes List of language codes to use (e.g., ["eng", "spa", "fra"]) ++ */ ++ void setLanguagesByCode(const QStringList &languageCodes); ++ ++ /** ++ * @brief Get the current language code ++ * @return Current language code (e.g., "eng", "spa") ++ */ ++ QString currentLanguageCode() const; ++ ++public Q_SLOTS: ++ /** ++ * @brief Extract text from an image asynchronously ++ * @param image The image to process ++ * ++ * This method processes the image in a background thread and emits ++ * textRecognized() signal when complete. ++ */ ++ void recognizeText(const QImage &image); ++ ++ /** ++ * @brief Extract text from an image using a temporary language selection ++ * @param image The image to process ++ * @param languageCode The one-off language code to use (e.g. "eng") ++ * ++ * The provided language is applied only for this recognition request and ++ * does not persist the user's saved configuration. ++ */ ++ void recognizeTextWithLanguage(const QImage &image, const QString &languageCode); ++ ++Q_SIGNALS: ++ /** ++ * @brief Emitted when text recognition is complete ++ * @param text The recognized text ++ * @param success true if recognition was successful ++ */ ++ void textRecognized(const QString &text, bool success); ++ ++ /** ++ * @brief Emitted when OCR status changes ++ * @param status New status ++ */ ++ void statusChanged(OcrStatus status); ++ ++private Q_SLOTS: ++ void handleRecognitionComplete(const QString &text, bool success); ++ ++private: ++ void initializeTesseract(); ++ void setStatus(OcrStatus status); ++ bool setupTesseractLanguages(const QStringList &langCodes); ++ void setupAvailableLanguages(const QString &tessdataPath); ++ void loadSavedLanguageSetting(); ++ bool isLanguageAvailable(const QString &languageCode) const; ++ QString tesseractLangName(const QString &tesseractCode) const; ++ ++ /** ++ * @brief Validate, filter, and apply languages to Tesseract ++ * @param languageCodes Languages to validate and apply ++ * @return true if languages were successfully applied ++ */ ++ bool validateAndApplyLanguages(const QStringList &languageCodes); ++ void beginRecognition(const QImage &image); ++ ++ static OcrManager *s_instance; ++ ++#ifdef HAVE_TESSERACT_OCR ++ tesseract::TessBaseAPI *m_tesseract; ++ OcrWorker *m_worker; ++#endif ++ std::unique_ptr m_workerThread; ++ QTimer *m_timeoutTimer; ++ ++ OcrStatus m_status; ++ QString m_currentLanguageCode; ++ QStringList m_configuredLanguages; ++ QStringList m_activeLanguages; ++ bool m_shouldRestoreToConfigured; ++ QStringList m_availableLanguages; ++ QMap m_languageNames; ++ bool m_initialized; ++ ++private: ++}; +\ No newline at end of file +diff --git a/src/SpectacleCore.cpp b/src/SpectacleCore.cpp +index 7371ce768..caada874e 100644 +--- a/src/SpectacleCore.cpp ++++ b/src/SpectacleCore.cpp +@@ -1,6 +1,7 @@ + /* + * SPDX-FileCopyrightText: 2019 David Redondo + * SPDX-FileCopyrightText: 2015 Boudhayan Gupta ++ * SPDX-FileCopyrightText: 2025 Jhair Paris + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ +@@ -20,6 +21,7 @@ + #include "Gui/HelpMenu.h" + #include "Gui/OptionsMenu.h" + #include "Gui/InlineMessageModel.h" ++#include "OcrManager.h" + #include "Platforms/ImagePlatformXcb.h" + #include "Platforms/VideoPlatform.h" + #include "ShortcutActions.h" +@@ -49,6 +51,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -59,6 +62,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -538,6 +543,63 @@ SpectacleCore::SpectacleCore(QObject *parent) + InlineMessageModel::instance()->push(InlineMessageModel::Scanned, text, result); + }; + connect(exportManager, &ExportManager::qrCodeScanned, this, onQRCodeScanned); ++ ++ auto onOcrTextRecognized = [this](const QString &text, bool success) { ++ if (!success) { ++ InlineMessageModel::instance()->push(InlineMessageModel::Error, ++ i18nc("@info", "Text extraction failed")); ++ return; ++ } ++ ++ if (text.isEmpty()) { ++ InlineMessageModel::instance()->push(InlineMessageModel::Copied, ++ i18nc("@info", "No text found in the image")); ++ return; ++ } ++ ++ InlineMessageModel::instance()->push(InlineMessageModel::Copied, ++ i18nc("@info", "Text extraction completed")); ++ ++ auto notification = new KNotification(u"ocrTextExtracted"_s, KNotification::CloseOnTimeout, this); ++ notification->setTitle(i18nc("@info:notification title", "Text Extracted")); ++ ++ notification->setText(i18nc("@info:notification", "Text copied to clipboard")); ++ notification->setIconName(u"document-scan"_s); ++ ++ if (!text.isEmpty()) { ++ auto openEditorAction = notification->addAction(i18nc("@action:button", "Open in Text Editor")); ++ connect(openEditorAction, &KNotificationAction::activated, this, [text]() { ++ // Create temporary file with extracted text ++ auto exportManager = ExportManager::instance(); ++ exportManager->updateTimestamp(); ++ auto timestamp = exportManager->timestamp(); ++ ++ QString filename = QStringLiteral("spectacle_ocr_%1.txt").arg(timestamp.toString(QStringLiteral("yyyyMMdd_HHmmss"))); ++ QString templatePath = QDir::tempPath() + QStringLiteral("/") + filename; ++ ++ QTemporaryFile tempFile; ++ tempFile.setFileTemplate(templatePath); ++ tempFile.setAutoRemove(false); ++ ++ if (tempFile.open()) { ++ QTextStream stream(&tempFile); ++ stream << text; ++ tempFile.close(); ++ ++ auto job = new KIO::OpenUrlJob(QUrl::fromLocalFile(tempFile.fileName())); ++ job->start(); ++ } ++ }); ++ } ++ ++ notification->sendEvent(); ++ }; ++ ++ // Connect to OCR manager ++ connect(OcrManager::instance(), &OcrManager::textRecognized, this, onOcrTextRecognized); ++ connect(OcrManager::instance(), &OcrManager::statusChanged, this, [this](OcrManager::OcrStatus) { ++ Q_EMIT ocrStatusChanged(); ++ }); + + connect(exportManager, &ExportManager::errorMessage, this, &SpectacleCore::showErrorMessage); + +@@ -582,6 +644,87 @@ SpectacleCore::SpectacleCore(QObject *parent) + }); + } + ++bool SpectacleCore::ocrAvailable() const ++{ ++ return OcrManager::instance()->isAvailable(); ++} ++ ++OcrManager::OcrStatus SpectacleCore::ocrStatus() const ++{ ++ return OcrManager::instance()->status(); ++} ++ ++QVariantMap SpectacleCore::ocrAvailableLanguages() const ++{ ++ auto ocrManager = OcrManager::instance(); ++ if (!ocrManager->isAvailable()) { ++ return QVariantMap(); ++ } ++ ++ auto languageMap = ocrManager->availableLanguagesWithNames(); ++ QVariantMap result; ++ for (auto it = languageMap.constBegin(); it != languageMap.constEnd(); ++it) { ++ result[it.key()] = it.value(); ++ } ++ return result; ++} ++ ++bool SpectacleCore::startOcrExtraction(const QString &languageCode) ++{ ++ if (m_videoMode) { ++ return false; ++ } ++ ++ const bool hasCaptureWindows = !CaptureWindow::instances().isEmpty(); ++ ++ if (hasCaptureWindows) { ++ auto selectionEditor = SelectionEditor::instance(); ++ auto inlineMessages = InlineMessageModel::instance(); ++ ++ if (!selectionEditor->acceptSelection(ExportManager::UserAction)) { ++ inlineMessages->push(InlineMessageModel::Error, i18nc("@info", "Please select a region before extracting text")); ++ return false; ++ } ++ ++ QMetaObject::invokeMethod( ++ this, ++ [this, languageCode]() { ++ performOcrExtraction(languageCode); ++ }, ++ Qt::QueuedConnection); ++ return true; ++ } ++ ++ return performOcrExtraction(languageCode); ++} ++ ++bool SpectacleCore::performOcrExtraction(const QString &languageCode) ++{ ++ auto ocrManager = OcrManager::instance(); ++ auto inlineMessages = InlineMessageModel::instance(); ++ ++ if (!ocrManager->isAvailable()) { ++ inlineMessages->push(InlineMessageModel::Error, i18nc("@info", "OCR is not available.")); ++ return false; ++ } ++ ++ const QImage image = m_annotationDocument->renderToImage(); ++ if (image.isNull()) { ++ inlineMessages->push(InlineMessageModel::Error, i18nc("@info", "No screenshot available.")); ++ return false; ++ } ++ ++ inlineMessages->push(InlineMessageModel::Copied, i18nc("@info", "Extracting text from image...")); ++ ++ if (languageCode.isEmpty()) { ++ ocrManager->recognizeText(image); ++ } else { ++ ocrManager->recognizeTextWithLanguage(image, languageCode); ++ } ++ ++ return true; ++} ++ + SpectacleCore::~SpectacleCore() noexcept + { + s_self = nullptr; +diff --git a/src/SpectacleCore.h b/src/SpectacleCore.h +index 23d65ead9..2c87ff8f4 100644 +--- a/src/SpectacleCore.h ++++ b/src/SpectacleCore.h +@@ -17,6 +17,7 @@ + #include "Gui/Annotations/AnnotationDocument.h" + #include "Gui/CaptureWindow.h" + #include "Gui/ViewerWindow.h" ++#include "OcrManager.h" + #include "Platforms/PlatformLoader.h" + #include "RecordingModeModel.h" + #include "VideoFormatModel.h" +@@ -40,6 +41,8 @@ class SpectacleCore : public QObject + Q_PROPERTY(bool videoMode READ videoMode WRITE setVideoMode NOTIFY videoModeChanged) + Q_PROPERTY(QUrl currentVideo READ currentVideo NOTIFY currentVideoChanged) + Q_PROPERTY(AnnotationDocument *annotationDocument READ annotationDocument CONSTANT FINAL) ++ Q_PROPERTY(bool ocrAvailable READ ocrAvailable NOTIFY ocrStatusChanged FINAL) ++ Q_PROPERTY(OcrManager::OcrStatus ocrStatus READ ocrStatus NOTIFY ocrStatusChanged FINAL) + + public: + enum class StartMode { +@@ -74,6 +77,10 @@ public: + + QUrl currentVideo() const; + ++ bool ocrAvailable() const; ++ OcrManager::OcrStatus ocrStatus() const; ++ Q_INVOKABLE QVariantMap ocrAvailableLanguages() const; ++ Q_INVOKABLE bool startOcrExtraction(const QString &languageCode = QString()); + + void initGuiNoScreenshot(); + +@@ -125,6 +132,7 @@ Q_SIGNALS: + void videoModeChanged(bool videoMode); + void currentVideoChanged(const QUrl ¤tVideo); + void recordedTimeChanged(); ++ void ocrStatusChanged(); + + private: + explicit SpectacleCore(QObject *parent = nullptr); +@@ -148,6 +156,7 @@ private: + void unityLauncherUpdate(const QVariantMap &properties) const; + void setCurrentVideo(const QUrl ¤tVideo); + QUrl videoOutputUrl() const; ++ bool performOcrExtraction(const QString &languageCode); + + static SpectacleCore *s_self; + std::unique_ptr m_annotationDocument = nullptr; +-- +GitLab + + +From a1f7ac0b716ea295cfec120bf8691dd86e56413b Mon Sep 17 00:00:00 2001 +From: Jhair Paris +Date: Mon, 13 Oct 2025 22:58:17 -0500 +Subject: [PATCH 3/3] add support for multiple OCR languages in preferences + dialog + +- Switch from single ocrLanguage string to ocrLanguages string list in settings +- Add OcrLanguageSelector widget for multi-language selection +- Integrate new selector into GeneralOptionsPage and SettingsDialog + +add OCR language menu to main interface + +- Introduce OcrLanguageMenu and OcrLanguageMenuButton components +- Expose language selection in ViewerPage and CaptureOverlay +- Move OCR extraction logic to SpectacleCore::startOcrExtraction + +Remove OCR language menu components and references from the project + +Add OCR language submenu to ExportMenu +--- + src/CMakeLists.txt | 1 + + src/Gui/CaptureOverlay.qml | 8 +- + src/Gui/ExportMenu.cpp | 84 ++++++ + src/Gui/ExportMenu.h | 5 + + src/Gui/OcrAction.qml | 7 +- + src/Gui/SettingsDialog/GeneralOptions.ui | 38 ++- + src/Gui/SettingsDialog/GeneralOptionsPage.cpp | 81 ++---- + src/Gui/SettingsDialog/GeneralOptionsPage.h | 16 +- + .../SettingsDialog/OcrLanguageSelector.cpp | 271 ++++++++++++++++++ + src/Gui/SettingsDialog/OcrLanguageSelector.h | 111 +++++++ + src/Gui/SettingsDialog/SettingsDialog.cpp | 17 +- + src/Gui/SettingsDialog/spectacle.kcfg | 4 +- + src/Gui/ViewerPage.qml | 4 +- + 13 files changed, 561 insertions(+), 86 deletions(-) + create mode 100644 src/Gui/SettingsDialog/OcrLanguageSelector.cpp + create mode 100644 src/Gui/SettingsDialog/OcrLanguageSelector.h + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index c57535e34..6efeff637 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -44,6 +44,7 @@ target_sources(spectacle PRIVATE + Gui/SelectionEditor.cpp + Gui/SettingsDialog/GeneralOptionsPage.cpp + Gui/SettingsDialog/ImageSaveOptionsPage.cpp ++ Gui/SettingsDialog/OcrLanguageSelector.cpp + Gui/SettingsDialog/SettingsDialog.cpp + Gui/SettingsDialog/ShortcutsOptionsPage.cpp + Gui/SettingsDialog/VideoFormatComboBox.cpp +diff --git a/src/Gui/CaptureOverlay.qml b/src/Gui/CaptureOverlay.qml +index 37f3dcf85..431d76479 100644 +--- a/src/Gui/CaptureOverlay.qml ++++ b/src/Gui/CaptureOverlay.qml +@@ -506,11 +506,13 @@ MouseArea { + visible: action.enabled + action: CopyImageAction {} + } ++ + ToolButton { + display: TtToolButton.IconOnly +- visible: action.enabled && !SpectacleCore.videoMode && SpectacleCore.ocrAvailable ++ visible: !SpectacleCore.videoMode && SpectacleCore.ocrAvailable + action: OcrAction {} + } ++ + ExportMenuButton { + focusPolicy: Qt.NoFocus + } +@@ -537,10 +539,12 @@ MouseArea { + visible: action.enabled + action: CopyImageAction {} + } ++ + ToolButton { +- visible: action.enabled && !SpectacleCore.videoMode && SpectacleCore.ocrAvailable ++ visible: !SpectacleCore.videoMode && SpectacleCore.ocrAvailable + action: OcrAction {} + } ++ + ExportMenuButton { + focusPolicy: Qt.NoFocus + } +diff --git a/src/Gui/ExportMenu.cpp b/src/Gui/ExportMenu.cpp +index e2c7dd5b6..57e1480fa 100644 +--- a/src/Gui/ExportMenu.cpp ++++ b/src/Gui/ExportMenu.cpp +@@ -6,6 +6,7 @@ + + #include "ExportMenu.h" + #include "CaptureWindow.h" ++#include "OcrManager.h" + #include "SpectacleCore.h" + #include "WidgetWindowUtils.h" + #include "settings.h" +@@ -54,6 +55,8 @@ ExportMenu::ExportMenu(QWidget *parent) + this, &ExportMenu::openScreenshotsFolder); + addAction(KStandardActions::print(this, &ExportMenu::openPrintDialog, this)); + ++ createOcrLanguageSubmenu(); ++ + #ifdef PURPOSE_FOUND + loadPurposeMenu(); + connect(ExportManager::instance(), &ExportManager::imageChanged, this, &ExportMenu::onImageChanged); +@@ -233,4 +236,85 @@ void ExportMenu::openPrintDialog() + dialog->setVisible(true); + } + ++void ExportMenu::createOcrLanguageSubmenu() ++{ ++ Q_ASSERT(!m_ocrLanguageMenu); ++ ++ auto ocrManager = OcrManager::instance(); ++ ++ if (!ocrManager || !ocrManager->isAvailable()) { ++ return; ++ } ++ ++ m_ocrLanguageMenu = addMenu(i18nc("@action:menu", "Extract Text by Language")); ++ m_ocrLanguageMenu->setIcon(QIcon::fromTheme(u"document-scan"_s)); ++ ++ // Keep the submenu in sync with OCR status changes ++ if (ocrManager) { ++ connect(ocrManager, &OcrManager::statusChanged, this, &ExportMenu::buildOcrLanguageSubmenu); ++ } ++ ++ if (auto settings = Settings::self()) { ++ connect(settings, &Settings::ocrLanguagesChanged, this, &ExportMenu::buildOcrLanguageSubmenu); ++ } ++ ++ connect(m_ocrLanguageMenu, &QMenu::aboutToShow, this, &ExportMenu::buildOcrLanguageSubmenu); ++ ++ buildOcrLanguageSubmenu(); ++} ++ ++void ExportMenu::buildOcrLanguageSubmenu() ++{ ++ if (!m_ocrLanguageMenu) { ++ return; ++ } ++ ++ m_ocrLanguageMenu->clear(); ++ ++ auto ocrManager = OcrManager::instance(); ++ ++ if (!ocrManager) { ++ QAction *action = m_ocrLanguageMenu->addAction(i18n("OCR engine is not available.")); ++ action->setEnabled(false); ++ return; ++ } ++ ++ const bool initializationFailed = ocrManager->status() == OcrManager::OcrStatus::Error; ++ if (!ocrManager->isAvailable()) { ++ QAction *action = m_ocrLanguageMenu->addAction(initializationFailed ? i18n("OCR is not available. Please install Tesseract OCR.") ++ : i18n("OCR engine is initializing…")); ++ action->setEnabled(false); ++ return; ++ } ++ ++ const bool busy = ocrManager->status() == OcrManager::OcrStatus::Processing; ++ const QMap languages = ocrManager->availableLanguagesWithNames(); ++ ++ if (languages.isEmpty()) { ++ QAction *action = m_ocrLanguageMenu->addAction(i18n("No OCR language data available.")); ++ action->setEnabled(false); ++ return; ++ } ++ ++ for (auto it = languages.cbegin(); it != languages.cend(); ++it) { ++ const QString &code = it.key(); ++ ++ if (code == u"osd"_s) { ++ continue; ++ } ++ ++ QAction *languageAction = m_ocrLanguageMenu->addAction(it.value()); ++ languageAction->setEnabled(!busy); ++ ++ connect(languageAction, &QAction::triggered, this, [this, code]() { ++ triggerExtraction(code); ++ }); ++ } ++} ++ ++void ExportMenu::triggerExtraction(const QString &languageCode) ++{ ++ SpectacleCore::instance()->startOcrExtraction(languageCode); ++} ++ + #include "moc_ExportMenu.cpp" +diff --git a/src/Gui/ExportMenu.h b/src/Gui/ExportMenu.h +index e0533a708..bfac0b990 100644 +--- a/src/Gui/ExportMenu.h ++++ b/src/Gui/ExportMenu.h +@@ -9,6 +9,7 @@ + + #include "SpectacleMenu.h" + ++#include + #include + + #include "Config.h" +@@ -49,8 +50,11 @@ private: + + Q_SLOT void onImageChanged(); + Q_SLOT void openScreenshotsFolder(); ++ Q_SLOT void buildOcrLanguageSubmenu(); ++ Q_SLOT void triggerExtraction(const QString &languageCode); + + void getKServiceItems(); ++ void createOcrLanguageSubmenu(); + + #ifdef PURPOSE_FOUND + void loadPurposeMenu(); +@@ -59,6 +63,7 @@ private: + bool mUpdatedImageAvailable; + std::unique_ptr mPurposeMenu; + #endif ++ QMenu *m_ocrLanguageMenu = nullptr; + friend class ExportMenuSingleton; + }; + +diff --git a/src/Gui/OcrAction.qml b/src/Gui/OcrAction.qml +index f887ec0ee..a22efec16 100644 +--- a/src/Gui/OcrAction.qml ++++ b/src/Gui/OcrAction.qml +@@ -6,9 +6,10 @@ import QtQuick.Templates as T + import org.kde.spectacle.private + + T.Action { +- // OCR is only available for screenshots, not videos, and only when OCR is properly available +- enabled: !SpectacleCore.videoMode && SpectacleCore.ocrAvailable ++ enabled: !SpectacleCore.videoMode && ++ SpectacleCore.ocrAvailable && ++ SpectacleCore.ocrStatus !== 1 + icon.name: "document-scan" + text: i18nc("@action", "Extract Text") +- onTriggered: contextWindow.extractText() ++ onTriggered: SpectacleCore.startOcrExtraction() + } +diff --git a/src/Gui/SettingsDialog/GeneralOptions.ui b/src/Gui/SettingsDialog/GeneralOptions.ui +index ddbbf3e5a..048639b89 100644 +--- a/src/Gui/SettingsDialog/GeneralOptions.ui ++++ b/src/Gui/SettingsDialog/GeneralOptions.ui +@@ -265,21 +265,39 @@ + + + +- Language: ++ Languages for OCR: + + + + +- +- +- +- 0 +- 0 +- ++ ++ ++ true + +- +- currentData ++ ++ QFrame::StyledPanel + ++ ++ 120 ++ ++ ++ 60 ++ ++ ++ Qt::ScrollBarAlwaysOff ++ ++ ++ ++ ++ 0 ++ 0 ++ 69 ++ 69 ++ ++ ++ ++ ++ + + + +@@ -383,7 +401,7 @@ + kcfg_useReleaseToCapture + kcfg_showCaptureInstructions + kcfg_rememberSelectionRect +- kcfg_ocrLanguage ++ ocrLanguageScrollArea + + + +diff --git a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp +index 5b8a5d9fc..f6be13d56 100644 +--- a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp ++++ b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp +@@ -8,19 +8,22 @@ + + #include "GeneralOptionsPage.h" + ++#include "OcrLanguageSelector.h" ++#include "OcrManager.h" + #include "settings.h" + #include "ui_GeneralOptions.h" +-#include "OcrManager.h" + +-#include + #include ++#include + +-#include + #include + ++using namespace Qt::Literals::StringLiterals; ++ + GeneralOptionsPage::GeneralOptionsPage(QWidget *parent) + : QWidget(parent) + , m_ui(new Ui_GeneralOptions) ++ , m_ocrLanguageSelector(new OcrLanguageSelector(this)) + { + m_ui->setupUi(this); + +@@ -31,9 +34,12 @@ GeneralOptionsPage::GeneralOptionsPage(QWidget *parent) + m_ui->regionTitle->setLevel(2); + m_ui->ocrTitle->setLevel(2); + +- setupOcrLanguageComboBox(); ++ m_ui->ocrLanguageScrollArea->setWidget(m_ocrLanguageSelector); ++ m_ui->ocrLanguageScrollArea->setWidgetResizable(true); ++ ++ connect(m_ocrLanguageSelector, &OcrLanguageSelector::selectedLanguagesChanged, this, &GeneralOptionsPage::ocrLanguageChanged); + +- connect(OcrManager::instance(), &OcrManager::statusChanged, this, &GeneralOptionsPage::refreshOcrLanguageSettings); ++ refreshOcrLanguageSettings(); + + //On Wayland we can't programmatically raise and focus the window so we have to hide the option + if (KWindowSystem::isPlatformWayland() || qstrcmp(qgetenv("XDG_SESSION_TYPE").constData(), "wayland") == 0) { +@@ -43,71 +49,20 @@ GeneralOptionsPage::GeneralOptionsPage(QWidget *parent) + + GeneralOptionsPage::~GeneralOptionsPage() = default; + +-void GeneralOptionsPage::setupOcrLanguageComboBox() +-{ +- OcrManager *ocrManager = OcrManager::instance(); +- +- if (!ocrManager->isAvailable()) { +- m_ui->kcfg_ocrLanguage->setEnabled(false); +- m_ui->kcfg_ocrLanguage->addItem(i18n("OCR not available")); +- m_ui->ocrLanguageLabel->setVisible(false); +- m_ui->kcfg_ocrLanguage->setVisible(false); +- m_ui->ocrUnavailableWidget->setVisible(true); +- return; +- } +- +- const auto availableLanguages = ocrManager->availableLanguagesWithNames(); +- +- if (availableLanguages.isEmpty()) { +- m_ui->kcfg_ocrLanguage->addItem(i18n("No languages found")); +- m_ui->kcfg_ocrLanguage->setEnabled(false); +- return; +- } +- +- m_ui->kcfg_ocrLanguage->clear(); +- m_ui->ocrLanguageLabel->setVisible(true); +- m_ui->kcfg_ocrLanguage->setVisible(true); +- m_ui->ocrUnavailableWidget->setVisible(false); +- +- for (auto it = availableLanguages.constBegin(); it != availableLanguages.constEnd(); ++it) { +- m_ui->kcfg_ocrLanguage->addItem(it.value(), it.key()); +- } +-} +- + void GeneralOptionsPage::refreshOcrLanguageSettings() + { + OcrManager *ocrManager = OcrManager::instance(); + + if (!ocrManager->isAvailable()) { + m_ui->ocrLanguageLabel->setVisible(false); +- m_ui->kcfg_ocrLanguage->setVisible(false); ++ m_ui->ocrLanguageScrollArea->setVisible(false); + m_ui->ocrUnavailableWidget->setVisible(true); +- return; +- } +- +- const auto availableLanguages = ocrManager->availableLanguagesWithNames(); +- +- if (availableLanguages.isEmpty()) { +- return; +- } +- +- m_ui->kcfg_ocrLanguage->clear(); +- m_ui->kcfg_ocrLanguage->setEnabled(true); +- m_ui->ocrLanguageLabel->setVisible(true); +- m_ui->kcfg_ocrLanguage->setVisible(true); +- m_ui->ocrUnavailableWidget->setVisible(false); +- +- for (auto it = availableLanguages.constBegin(); it != availableLanguages.constEnd(); ++it) { +- m_ui->kcfg_ocrLanguage->addItem(it.value(), it.key()); +- } +- +- const QString currentLanguage = Settings::ocrLanguage(); +- +- for (int i = 0; i < m_ui->kcfg_ocrLanguage->count(); ++i) { +- if (m_ui->kcfg_ocrLanguage->itemData(i).toString() == currentLanguage) { +- m_ui->kcfg_ocrLanguage->setCurrentIndex(i); +- break; +- } ++ } else { ++ m_ui->ocrLanguageLabel->setVisible(true); ++ m_ui->ocrLanguageScrollArea->setVisible(true); ++ m_ui->ocrUnavailableWidget->setVisible(false); ++ ++ m_ocrLanguageSelector->refresh(); + } + } + +diff --git a/src/Gui/SettingsDialog/GeneralOptionsPage.h b/src/Gui/SettingsDialog/GeneralOptionsPage.h +index c184d6ba8..a3a5cb17d 100644 +--- a/src/Gui/SettingsDialog/GeneralOptionsPage.h ++++ b/src/Gui/SettingsDialog/GeneralOptionsPage.h +@@ -11,6 +11,7 @@ + #include + + class Ui_GeneralOptions; ++class OcrLanguageSelector; + + class GeneralOptionsPage : public QWidget + { +@@ -22,10 +23,21 @@ public: + + void refreshOcrLanguageSettings(); + ++ /** ++ * @brief Get direct access to the OCR language selector widget ++ * @return Pointer to the OcrLanguageSelector widget for direct manipulation ++ */ ++ OcrLanguageSelector *ocrLanguageSelector() const ++ { ++ return m_ocrLanguageSelector; ++ } ++ ++Q_SIGNALS: ++ void ocrLanguageChanged(); ++ + private: +- void setupOcrLanguageComboBox(); +- + QScopedPointer m_ui; ++ OcrLanguageSelector *m_ocrLanguageSelector; + }; + + #endif // GENERALOPTIONSPAGE_H +diff --git a/src/Gui/SettingsDialog/OcrLanguageSelector.cpp b/src/Gui/SettingsDialog/OcrLanguageSelector.cpp +new file mode 100644 +index 000000000..d1d809323 +--- /dev/null ++++ b/src/Gui/SettingsDialog/OcrLanguageSelector.cpp +@@ -0,0 +1,271 @@ ++/* ++ * SPDX-FileCopyrightText: 2025 Jhair Paris ++ * ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++#include "OcrLanguageSelector.h" ++#include "OcrManager.h" ++#include "settings.h" ++#include "spectacle_debug.h" ++ ++#include ++ ++#include ++#include ++ ++using namespace Qt::Literals::StringLiterals; ++ ++OcrLanguageSelector::OcrLanguageSelector(QWidget *parent) ++ : QWidget(parent) ++ , m_layout(new QVBoxLayout(this)) ++ , m_blockSignals(false) ++ , m_ocrManager(OcrManager::instance()) ++{ ++ m_layout->setContentsMargins(0, 0, 0, 0); ++ m_layout->setSpacing(0); ++ setContentsMargins(0, 0, 0, 0); ++ ++ setupLanguageCheckboxes(); ++ ++ connect(m_ocrManager, &OcrManager::statusChanged, this, &OcrLanguageSelector::onOcrManagerStatusChanged); ++} ++ ++OcrLanguageSelector::~OcrLanguageSelector() = default; ++ ++QStringList OcrLanguageSelector::selectedLanguages() const ++{ ++ QStringList result; ++ for (QCheckBox *checkbox : m_languageCheckboxes) { ++ if (checkbox->isChecked()) { ++ result.append(checkbox->property("languageCode").toString()); ++ } ++ } ++ return result; ++} ++ ++void OcrLanguageSelector::setSelectedLanguages(const QStringList &languages) ++{ ++ m_blockSignals = true; ++ ++ for (QCheckBox *checkbox : m_languageCheckboxes) { ++ const QString langCode = checkbox->property("languageCode").toString(); ++ checkbox->setChecked(languages.contains(langCode)); ++ } ++ ++ m_blockSignals = false; ++ ++ enforceSelectionLimits(); ++} ++ ++bool OcrLanguageSelector::isDefault() const ++{ ++ const QStringList current = selectedLanguages(); ++ ++ // Default state is exactly one language selected ++ if (current.size() != 1) { ++ return false; ++ } ++ ++ // Check if it's English (preferred default) ++ for (const QCheckBox *checkbox : m_languageCheckboxes) { ++ if (checkbox->property("languageCode").toString() == u"eng"_s) { ++ // English is available, so default is English ++ return current.contains(u"eng"_s); ++ } ++ } ++ ++ // English not available, default is the first available language ++ if (!m_languageCheckboxes.isEmpty()) { ++ QString firstLangCode = m_languageCheckboxes.first()->property("languageCode").toString(); ++ return current.contains(firstLangCode); ++ } ++ ++ return false; ++} ++ ++bool OcrLanguageSelector::hasChanges() const ++{ ++ return selectedLanguages() != Settings::ocrLanguages(); ++} ++ ++void OcrLanguageSelector::applyDefaults() ++{ ++ if (!m_languageCheckboxes.isEmpty()) { ++ m_blockSignals = true; ++ ++ for (QCheckBox *checkbox : m_languageCheckboxes) { ++ checkbox->setChecked(false); ++ } ++ ++ // Try to select English first ++ bool foundDefault = false; ++ for (QCheckBox *checkbox : m_languageCheckboxes) { ++ if (checkbox->property("languageCode").toString() == u"eng"_s) { ++ checkbox->setChecked(true); ++ foundDefault = true; ++ break; ++ } ++ } ++ ++ // If English not available, select first language ++ if (!foundDefault) { ++ m_languageCheckboxes.first()->setChecked(true); ++ } ++ ++ m_blockSignals = false; ++ ++ const QStringList selected = selectedLanguages(); ++ Settings::setOcrLanguages(selected); ++ ++ // Emit signal to notify changes ++ Q_EMIT selectedLanguagesChanged(selected); ++ } ++} ++ ++void OcrLanguageSelector::refresh() ++{ ++ setupLanguageCheckboxes(); ++} ++ ++void OcrLanguageSelector::saveSettings() ++{ ++ const QStringList selected = selectedLanguages(); ++ Settings::setOcrLanguages(selected); ++} ++ ++void OcrLanguageSelector::updateWidgets() ++{ ++ const QStringList savedLanguages = Settings::ocrLanguages(); ++ setSelectedLanguages(savedLanguages); ++} ++ ++void OcrLanguageSelector::onLanguageCheckboxChanged() ++{ ++ if (m_blockSignals) { ++ return; ++ } ++ ++ enforceSelectionLimits(); ++ ++ const QStringList selected = selectedLanguages(); ++ Q_EMIT selectedLanguagesChanged(selected); ++} ++ ++void OcrLanguageSelector::onOcrManagerStatusChanged() ++{ ++ refresh(); ++} ++ ++void OcrLanguageSelector::setupLanguageCheckboxes() ++{ ++ while (QLayoutItem *item = m_layout->takeAt(0)) { ++ if (auto widget = item->widget()) { ++ widget->deleteLater(); ++ } ++ delete item; ++ } ++ ++ m_languageCheckboxes.clear(); ++ m_availableLanguages.clear(); ++ ++ if (!m_ocrManager || !m_ocrManager->isAvailable()) { ++ qCWarning(SPECTACLE_LOG) << "OCR is not available; language selector will remain empty."; ++ return; ++ } ++ ++ m_availableLanguages = m_ocrManager->availableLanguagesWithNames(); ++ ++ if (m_availableLanguages.isEmpty()) { ++ qCWarning(SPECTACLE_LOG) << "No OCR language data available."; ++ return; ++ } ++ ++ for (auto it = m_availableLanguages.cbegin(); it != m_availableLanguages.cend(); ++it) { ++ const QString &langCode = it.key(); ++ if (langCode == u"osd"_s) { ++ continue; ++ } ++ ++ QCheckBox *checkbox = new QCheckBox(it.value(), this); ++ checkbox->setProperty("languageCode", langCode); ++ connect(checkbox, &QCheckBox::toggled, this, &OcrLanguageSelector::onLanguageCheckboxChanged); ++ m_layout->addWidget(checkbox); ++ m_languageCheckboxes.append(checkbox); ++ } ++ ++ if (m_layout->count() > 0) { ++ m_layout->addStretch(); ++ } ++ ++ const QStringList savedLanguages = Settings::ocrLanguages(); ++ setSelectedLanguages(savedLanguages); ++ ++ if (savedLanguages.isEmpty() && !m_languageCheckboxes.isEmpty()) { ++ applyDefaults(); ++ } ++} ++ ++void OcrLanguageSelector::enforceSelectionLimits() ++{ ++ const QStringList selected = selectedLanguages(); ++ const int count = selected.size(); ++ ++ if (count > OcrManager::MAX_OCR_LANGUAGES) { // Max languages for performance ++ for (int i = m_languageCheckboxes.size() - 1; i >= 0; --i) { ++ QCheckBox *checkbox = m_languageCheckboxes[i]; ++ if (checkbox->isChecked()) { ++ blockSignalsAndSetChecked(checkbox, false); ++ break; ++ } ++ } ++ } ++ ++ updateCheckboxEnabledStates(); ++ ++ if (selectedLanguages().size() == 0 && !m_languageCheckboxes.isEmpty()) { ++ applyDefaults(); ++ } ++} ++ ++QString OcrLanguageSelector::getDefaultLanguageCode() const ++{ ++ if (m_languageCheckboxes.isEmpty()) { ++ return QString(); ++ } ++ ++ // Try English first ++ for (const QCheckBox *checkbox : m_languageCheckboxes) { ++ if (checkbox->property("languageCode").toString() == u"eng"_s) { ++ return u"eng"_s; ++ } ++ } ++ ++ // Fallback to first available ++ return m_languageCheckboxes.first()->property("languageCode").toString(); ++} ++ ++void OcrLanguageSelector::updateCheckboxEnabledStates() ++{ ++ const QStringList selected = selectedLanguages(); ++ const int count = selected.size(); ++ ++ // If we have max languages selected, disable all unchecked checkboxes ++ // If we have less than max, enable all checkboxes ++ for (QCheckBox *checkbox : m_languageCheckboxes) { ++ if (checkbox->isChecked()) { ++ checkbox->setEnabled(true); ++ } else { ++ checkbox->setEnabled(count < OcrManager::MAX_OCR_LANGUAGES); ++ } ++ } ++} ++ ++void OcrLanguageSelector::blockSignalsAndSetChecked(QCheckBox *checkbox, bool checked) ++{ ++ m_blockSignals = true; ++ checkbox->setChecked(checked); ++ m_blockSignals = false; ++} ++ ++#include "moc_OcrLanguageSelector.cpp" +\ No newline at end of file +diff --git a/src/Gui/SettingsDialog/OcrLanguageSelector.h b/src/Gui/SettingsDialog/OcrLanguageSelector.h +new file mode 100644 +index 000000000..59b1a3d42 +--- /dev/null ++++ b/src/Gui/SettingsDialog/OcrLanguageSelector.h +@@ -0,0 +1,111 @@ ++/* ++ * SPDX-FileCopyrightText: 2025 Jhair Paris ++ * ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++#ifndef OCRLANGUAGESELECTOR_H ++#define OCRLANGUAGESELECTOR_H ++ ++#include ++#include ++#include ++ ++class OcrManager; ++ ++/** ++ * @brief Specialized widget for OCR language selection with multi-language support ++ * ++ * This widget encapsulates all the logic for OCR language selection: ++ * - Displays available languages as checkboxes (excluding 'osd') ++ * - Enforces limits: minimum 1, maximum languages defined by OcrManager ++ * - Handles defaults: English preferred, fallback to first available ++ * - Follows KConfigDialog pattern: no auto-persistence, explicit save/update methods ++ * - Updates dynamically when OCR manager state changes ++ */ ++class OcrLanguageSelector : public QWidget ++{ ++ Q_OBJECT ++ Q_PROPERTY(QStringList selectedLanguages READ selectedLanguages WRITE setSelectedLanguages NOTIFY selectedLanguagesChanged USER true) ++ Q_PROPERTY(bool isDefault READ isDefault NOTIFY selectedLanguagesChanged) ++ Q_PROPERTY(bool hasChanges READ hasChanges NOTIFY selectedLanguagesChanged) ++ ++public: ++ explicit OcrLanguageSelector(QWidget *parent = nullptr); ++ ~OcrLanguageSelector() override; ++ ++ /** ++ * @brief Get currently selected language codes ++ * @return List of selected language codes (e.g., ["eng", "spa"]) ++ */ ++ QStringList selectedLanguages() const; ++ ++ /** ++ * @brief Set selected languages ++ * @param languages List of language codes to select ++ */ ++ void setSelectedLanguages(const QStringList &languages); ++ ++ /** ++ * @brief Check if current selection is the default state ++ * @return true if selection represents default configuration ++ */ ++ bool isDefault() const; ++ ++ /** ++ * @brief Check if there are unsaved changes ++ * @return true if current selection differs from saved configuration ++ */ ++ bool hasChanges() const; ++ ++ /** ++ * @brief Apply default language selection ++ * Selects English if available, otherwise first available language ++ */ ++ void applyDefaults(); ++ ++ /** ++ * @brief Refresh the widget when OCR manager state changes ++ * Rebuilds checkboxes based on current available languages ++ */ ++ void refresh(); ++ ++ /** ++ * @brief Save current selection to settings (called by KConfigDialog) ++ * Follows KConfigDialog pattern for saving changes ++ */ ++ void saveSettings(); ++ ++ /** ++ * @brief Update widget to reflect current settings (called by KConfigDialog) ++ * Reloads settings when user cancels or dialog is reopened ++ */ ++ void updateWidgets(); ++ ++Q_SIGNALS: ++ /** ++ * @brief Emitted when language selection changes ++ * @param languages New list of selected languages ++ */ ++ void selectedLanguagesChanged(const QStringList &languages); ++ ++private Q_SLOTS: ++ void onLanguageCheckboxChanged(); ++ void onOcrManagerStatusChanged(); ++ ++private: ++ void setupLanguageCheckboxes(); ++ void enforceSelectionLimits(); ++ void updateCheckboxEnabledStates(); ++ QString getDefaultLanguageCode() const; ++ void blockSignalsAndSetChecked(QCheckBox *checkbox, bool checked); ++ ++ QVBoxLayout *m_layout; ++ QList m_languageCheckboxes; ++ QMap m_availableLanguages; // code -> display name ++ bool m_blockSignals; ++ ++ OcrManager *m_ocrManager; ++}; ++ ++#endif // OCRLANGUAGESELECTOR_H +\ No newline at end of file +diff --git a/src/Gui/SettingsDialog/SettingsDialog.cpp b/src/Gui/SettingsDialog/SettingsDialog.cpp +index a19a47627..532bfd3c3 100644 +--- a/src/Gui/SettingsDialog/SettingsDialog.cpp ++++ b/src/Gui/SettingsDialog/SettingsDialog.cpp +@@ -1,4 +1,5 @@ + /* ++ * SPDX-FileCopyrightText: 2025 Jhair Paris + * SPDX-FileCopyrightText: 2019 David Redondo + * SPDX-FileCopyrightText: 2015 Boudhayan Gupta + * +@@ -9,8 +10,9 @@ + + #include "GeneralOptionsPage.h" + #include "ImageSaveOptionsPage.h" +-#include "VideoSaveOptionsPage.h" ++#include "OcrLanguageSelector.h" + #include "ShortcutsOptionsPage.h" ++#include "VideoSaveOptionsPage.h" + #include "settings.h" + + #include +@@ -38,6 +40,9 @@ SettingsDialog::SettingsDialog(QWidget *parent) + connect(m_shortcutsPage, &ShortcutsOptionsPage::shortCutsChanged, this, [this] { + updateButtons(); + }); ++ connect(m_generalPage, &GeneralOptionsPage::ocrLanguageChanged, this, [this] { ++ updateButtons(); ++ }); + connect(this, &KConfigDialog::currentPageChanged, this, &SettingsDialog::updateButtons); + } + +@@ -72,18 +77,20 @@ void SettingsDialog::showEvent(QShowEvent *event) + + bool SettingsDialog::hasChanged() + { +- return m_shortcutsPage->isModified() || KConfigDialog::hasChanged(); ++ return m_shortcutsPage->isModified() || m_generalPage->ocrLanguageSelector()->hasChanges() || KConfigDialog::hasChanged(); + } + + bool SettingsDialog::isDefault() + { +- return currentPage()->name() != i18n("Shortcuts") && KConfigDialog::isDefault(); ++ return currentPage()->name() != i18n("Shortcuts") && m_generalPage->ocrLanguageSelector()->isDefault() && KConfigDialog::isDefault(); + } + + void SettingsDialog::updateSettings() + { + KConfigDialog::updateSettings(); + m_shortcutsPage->saveChanges(); ++ ++ m_generalPage->ocrLanguageSelector()->saveSettings(); + } + + void SettingsDialog::updateWidgets() +@@ -91,6 +98,7 @@ void SettingsDialog::updateWidgets() + KConfigDialog::updateWidgets(); + m_shortcutsPage->resetChanges(); + ++ m_generalPage->ocrLanguageSelector()->updateWidgets(); + m_generalPage->refreshOcrLanguageSettings(); + } + +@@ -98,6 +106,9 @@ void SettingsDialog::updateWidgetsDefault() + { + KConfigDialog::updateWidgetsDefault(); + m_shortcutsPage->defaults(); ++ ++ m_generalPage->ocrLanguageSelector()->applyDefaults(); ++ m_generalPage->refreshOcrLanguageSettings(); + } + + #include "moc_SettingsDialog.cpp" +diff --git a/src/Gui/SettingsDialog/spectacle.kcfg b/src/Gui/SettingsDialog/spectacle.kcfg +index 4517e2344..2062f7cc4 100644 +--- a/src/Gui/SettingsDialog/spectacle.kcfg ++++ b/src/Gui/SettingsDialog/spectacle.kcfg +@@ -70,8 +70,8 @@ + + UntilClosed + +- +- ++ ++ + eng + + +diff --git a/src/Gui/ViewerPage.qml b/src/Gui/ViewerPage.qml +index 602e4431b..133793964 100644 +--- a/src/Gui/ViewerPage.qml ++++ b/src/Gui/ViewerPage.qml +@@ -61,11 +61,13 @@ EmptyPage { + visible: action.enabled + action: CopyImageAction {} + } ++ + TtToolButton { + display: TtToolButton.IconOnly +- visible: action.enabled && SpectacleCore.ocrAvailable ++ visible: !SpectacleCore.videoMode && SpectacleCore.ocrAvailable + action: OcrAction {} + } ++ + // We only show this in video mode to save space in screenshot mode + TtToolButton { + visible: SpectacleCore.videoMode +-- +GitLab + diff --git a/roles/kde/patches/spectacle/pr487.patch b/roles/kde/patches/spectacle/pr487.patch new file mode 100644 index 0000000..759e43a --- /dev/null +++ b/roles/kde/patches/spectacle/pr487.patch @@ -0,0 +1,704 @@ +From d72a6fcb76053139ea709d7b1a4f45aa430a066d Mon Sep 17 00:00:00 2001 +From: Jhair Paris +Date: Sat, 8 Nov 2025 17:32:20 -0500 +Subject: [PATCH 1/4] Enhance OCR language settings management and + synchronization + +- Improved signal handling in OcrLanguageSelector to prevent unnecessary updates. +- Added config sync suspension functionality in OcrManager to manage settings changes. +- Adjusted SettingsDialog to ensure proper synchronization of OCR configurations. +--- + src/Gui/SettingsDialog/GeneralOptionsPage.cpp | 7 +- + src/Gui/SettingsDialog/GeneralOptionsPage.h | 4 +- + .../SettingsDialog/OcrLanguageSelector.cpp | 132 ++++++++---------- + src/Gui/SettingsDialog/OcrLanguageSelector.h | 7 +- + src/Gui/SettingsDialog/SettingsDialog.cpp | 25 +++- + src/Gui/SettingsDialog/SettingsDialog.h | 1 + + src/OcrManager.cpp | 25 ++++ + src/OcrManager.h | 3 + + 8 files changed, 117 insertions(+), 87 deletions(-) + +diff --git a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp +index f6be13d56..ae0a997c3 100644 +--- a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp ++++ b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp +@@ -10,7 +10,6 @@ + + #include "OcrLanguageSelector.h" + #include "OcrManager.h" +-#include "settings.h" + #include "ui_GeneralOptions.h" + + #include +@@ -49,7 +48,7 @@ GeneralOptionsPage::GeneralOptionsPage(QWidget *parent) + + GeneralOptionsPage::~GeneralOptionsPage() = default; + +-void GeneralOptionsPage::refreshOcrLanguageSettings() ++void GeneralOptionsPage::refreshOcrLanguageSettings(bool rebuildSelector) + { + OcrManager *ocrManager = OcrManager::instance(); + +@@ -62,7 +61,9 @@ void GeneralOptionsPage::refreshOcrLanguageSettings() + m_ui->ocrLanguageScrollArea->setVisible(true); + m_ui->ocrUnavailableWidget->setVisible(false); + +- m_ocrLanguageSelector->refresh(); ++ if (rebuildSelector) { ++ m_ocrLanguageSelector->refresh(); ++ } + } + } + +diff --git a/src/Gui/SettingsDialog/GeneralOptionsPage.h b/src/Gui/SettingsDialog/GeneralOptionsPage.h +index a3a5cb17d..bbb6d79a8 100644 +--- a/src/Gui/SettingsDialog/GeneralOptionsPage.h ++++ b/src/Gui/SettingsDialog/GeneralOptionsPage.h +@@ -20,8 +20,8 @@ class GeneralOptionsPage : public QWidget + public: + explicit GeneralOptionsPage(QWidget *parent = nullptr); + ~GeneralOptionsPage() override; +- +- void refreshOcrLanguageSettings(); ++ ++ void refreshOcrLanguageSettings(bool rebuildSelector = true); + + /** + * @brief Get direct access to the OCR language selector widget +diff --git a/src/Gui/SettingsDialog/OcrLanguageSelector.cpp b/src/Gui/SettingsDialog/OcrLanguageSelector.cpp +index d1d809323..815b4c707 100644 +--- a/src/Gui/SettingsDialog/OcrLanguageSelector.cpp ++++ b/src/Gui/SettingsDialog/OcrLanguageSelector.cpp +@@ -12,6 +12,7 @@ + #include + + #include ++#include + #include + + using namespace Qt::Literals::StringLiterals; +@@ -19,7 +20,6 @@ using namespace Qt::Literals::StringLiterals; + OcrLanguageSelector::OcrLanguageSelector(QWidget *parent) + : QWidget(parent) + , m_layout(new QVBoxLayout(this)) +- , m_blockSignals(false) + , m_ocrManager(OcrManager::instance()) + { + m_layout->setContentsMargins(0, 0, 0, 0); +@@ -46,15 +46,14 @@ QStringList OcrLanguageSelector::selectedLanguages() const + + void OcrLanguageSelector::setSelectedLanguages(const QStringList &languages) + { +- m_blockSignals = true; ++ QSignalBlocker blocker(this); + + for (QCheckBox *checkbox : m_languageCheckboxes) { + const QString langCode = checkbox->property("languageCode").toString(); ++ QSignalBlocker checkboxBlocker(checkbox); + checkbox->setChecked(languages.contains(langCode)); + } + +- m_blockSignals = false; +- + enforceSelectionLimits(); + } + +@@ -67,18 +66,11 @@ bool OcrLanguageSelector::isDefault() const + return false; + } + +- // Check if it's English (preferred default) +- for (const QCheckBox *checkbox : m_languageCheckboxes) { +- if (checkbox->property("languageCode").toString() == u"eng"_s) { +- // English is available, so default is English +- return current.contains(u"eng"_s); +- } +- } ++ QCheckBox *defaultCheckbox = findDefaultCheckbox(); + +- // English not available, default is the first available language +- if (!m_languageCheckboxes.isEmpty()) { +- QString firstLangCode = m_languageCheckboxes.first()->property("languageCode").toString(); +- return current.contains(firstLangCode); ++ if (defaultCheckbox) { ++ QString defaultLangCode = defaultCheckbox->property("languageCode").toString(); ++ return current.contains(defaultLangCode); + } + + return false; +@@ -91,36 +83,28 @@ bool OcrLanguageSelector::hasChanges() const + + void OcrLanguageSelector::applyDefaults() + { +- if (!m_languageCheckboxes.isEmpty()) { +- m_blockSignals = true; +- +- for (QCheckBox *checkbox : m_languageCheckboxes) { +- checkbox->setChecked(false); +- } ++ if (m_languageCheckboxes.isEmpty()) { ++ return; ++ } + +- // Try to select English first +- bool foundDefault = false; +- for (QCheckBox *checkbox : m_languageCheckboxes) { +- if (checkbox->property("languageCode").toString() == u"eng"_s) { +- checkbox->setChecked(true); +- foundDefault = true; +- break; +- } +- } ++ QSignalBlocker blocker(this); + +- // If English not available, select first language +- if (!foundDefault) { +- m_languageCheckboxes.first()->setChecked(true); +- } ++ QCheckBox *defaultCheckbox = findDefaultCheckbox(); + +- m_blockSignals = false; ++ for (QCheckBox *checkbox : m_languageCheckboxes) { ++ QSignalBlocker checkboxBlocker(checkbox); ++ checkbox->setChecked(checkbox == defaultCheckbox); ++ } + +- const QStringList selected = selectedLanguages(); +- Settings::setOcrLanguages(selected); ++ const int selectedCount = defaultCheckbox ? 1 : 0; ++ updateCheckboxEnabledStates(selectedCount); + +- // Emit signal to notify changes +- Q_EMIT selectedLanguagesChanged(selected); ++ QStringList selected; ++ if (defaultCheckbox) { ++ selected.append(defaultCheckbox->property("languageCode").toString()); + } ++ ++ Q_EMIT selectedLanguagesChanged(selected); + } + + void OcrLanguageSelector::refresh() +@@ -142,13 +126,17 @@ void OcrLanguageSelector::updateWidgets() + + void OcrLanguageSelector::onLanguageCheckboxChanged() + { +- if (m_blockSignals) { +- return; +- } +- + enforceSelectionLimits(); + +- const QStringList selected = selectedLanguages(); ++ QStringList selected; ++ selected.reserve(OcrManager::MAX_OCR_LANGUAGES); ++ ++ for (QCheckBox *checkbox : m_languageCheckboxes) { ++ if (checkbox->isChecked()) { ++ selected.append(checkbox->property("languageCode").toString()); ++ } ++ } ++ + Q_EMIT selectedLanguagesChanged(selected); + } + +@@ -167,21 +155,20 @@ void OcrLanguageSelector::setupLanguageCheckboxes() + } + + m_languageCheckboxes.clear(); +- m_availableLanguages.clear(); + + if (!m_ocrManager || !m_ocrManager->isAvailable()) { + qCWarning(SPECTACLE_LOG) << "OCR is not available; language selector will remain empty."; + return; + } + +- m_availableLanguages = m_ocrManager->availableLanguagesWithNames(); ++ const QMap availableLanguages = m_ocrManager->availableLanguagesWithNames(); + +- if (m_availableLanguages.isEmpty()) { ++ if (availableLanguages.isEmpty()) { + qCWarning(SPECTACLE_LOG) << "No OCR language data available."; + return; + } + +- for (auto it = m_availableLanguages.cbegin(); it != m_availableLanguages.cend(); ++it) { ++ for (auto it = availableLanguages.cbegin(); it != availableLanguages.cend(); ++it) { + const QString &langCode = it.key(); + if (langCode == u"osd"_s) { + continue; +@@ -208,64 +195,57 @@ void OcrLanguageSelector::setupLanguageCheckboxes() + + void OcrLanguageSelector::enforceSelectionLimits() + { +- const QStringList selected = selectedLanguages(); +- const int count = selected.size(); ++ int selectedCount = 0; ++ ++ for (QCheckBox *checkbox : m_languageCheckboxes) { ++ if (checkbox->isChecked()) { ++ ++selectedCount; ++ } ++ } + +- if (count > OcrManager::MAX_OCR_LANGUAGES) { // Max languages for performance ++ if (selectedCount > OcrManager::MAX_OCR_LANGUAGES) { + for (int i = m_languageCheckboxes.size() - 1; i >= 0; --i) { + QCheckBox *checkbox = m_languageCheckboxes[i]; + if (checkbox->isChecked()) { +- blockSignalsAndSetChecked(checkbox, false); ++ QSignalBlocker blocker(checkbox); ++ checkbox->setChecked(false); ++ --selectedCount; + break; + } + } + } + +- updateCheckboxEnabledStates(); ++ updateCheckboxEnabledStates(selectedCount); + +- if (selectedLanguages().size() == 0 && !m_languageCheckboxes.isEmpty()) { ++ if (selectedCount == 0 && !m_languageCheckboxes.isEmpty()) { + applyDefaults(); + } + } + +-QString OcrLanguageSelector::getDefaultLanguageCode() const ++QCheckBox *OcrLanguageSelector::findDefaultCheckbox() const + { + if (m_languageCheckboxes.isEmpty()) { +- return QString(); ++ return nullptr; + } + + // Try English first +- for (const QCheckBox *checkbox : m_languageCheckboxes) { ++ for (QCheckBox *checkbox : m_languageCheckboxes) { + if (checkbox->property("languageCode").toString() == u"eng"_s) { +- return u"eng"_s; ++ return checkbox; + } + } + + // Fallback to first available +- return m_languageCheckboxes.first()->property("languageCode").toString(); ++ return m_languageCheckboxes.first(); + } + +-void OcrLanguageSelector::updateCheckboxEnabledStates() ++void OcrLanguageSelector::updateCheckboxEnabledStates(int selectedCount) + { +- const QStringList selected = selectedLanguages(); +- const int count = selected.size(); ++ const bool enableUnchecked = selectedCount < OcrManager::MAX_OCR_LANGUAGES; + +- // If we have max languages selected, disable all unchecked checkboxes +- // If we have less than max, enable all checkboxes + for (QCheckBox *checkbox : m_languageCheckboxes) { +- if (checkbox->isChecked()) { +- checkbox->setEnabled(true); +- } else { +- checkbox->setEnabled(count < OcrManager::MAX_OCR_LANGUAGES); +- } ++ checkbox->setEnabled(checkbox->isChecked() || enableUnchecked); + } + } + +-void OcrLanguageSelector::blockSignalsAndSetChecked(QCheckBox *checkbox, bool checked) +-{ +- m_blockSignals = true; +- checkbox->setChecked(checked); +- m_blockSignals = false; +-} +- + #include "moc_OcrLanguageSelector.cpp" +\ No newline at end of file +diff --git a/src/Gui/SettingsDialog/OcrLanguageSelector.h b/src/Gui/SettingsDialog/OcrLanguageSelector.h +index 59b1a3d42..e938e06fa 100644 +--- a/src/Gui/SettingsDialog/OcrLanguageSelector.h ++++ b/src/Gui/SettingsDialog/OcrLanguageSelector.h +@@ -96,14 +96,11 @@ private Q_SLOTS: + private: + void setupLanguageCheckboxes(); + void enforceSelectionLimits(); +- void updateCheckboxEnabledStates(); +- QString getDefaultLanguageCode() const; +- void blockSignalsAndSetChecked(QCheckBox *checkbox, bool checked); ++ void updateCheckboxEnabledStates(int selectedCount); ++ QCheckBox *findDefaultCheckbox() const; + + QVBoxLayout *m_layout; + QList m_languageCheckboxes; +- QMap m_availableLanguages; // code -> display name +- bool m_blockSignals; + + OcrManager *m_ocrManager; + }; +diff --git a/src/Gui/SettingsDialog/SettingsDialog.cpp b/src/Gui/SettingsDialog/SettingsDialog.cpp +index 532bfd3c3..696636685 100644 +--- a/src/Gui/SettingsDialog/SettingsDialog.cpp ++++ b/src/Gui/SettingsDialog/SettingsDialog.cpp +@@ -11,6 +11,7 @@ + #include "GeneralOptionsPage.h" + #include "ImageSaveOptionsPage.h" + #include "OcrLanguageSelector.h" ++#include "OcrManager.h" + #include "ShortcutsOptionsPage.h" + #include "VideoSaveOptionsPage.h" + #include "settings.h" +@@ -46,6 +47,16 @@ SettingsDialog::SettingsDialog(QWidget *parent) + connect(this, &KConfigDialog::currentPageChanged, this, &SettingsDialog::updateButtons); + } + ++SettingsDialog::~SettingsDialog() ++{ ++ // Ensure OCR config sync is resumed ++ if (OcrManager *ocrManager = OcrManager::instance()) { ++ if (ocrManager->isConfigSyncSuspended()) { ++ ocrManager->setConfigSyncSuspended(false); ++ } ++ } ++} ++ + QSize SettingsDialog::sizeHint() const + { + // Avoid having pages that need to be scrolled, +@@ -91,6 +102,10 @@ void SettingsDialog::updateSettings() + m_shortcutsPage->saveChanges(); + + m_generalPage->ocrLanguageSelector()->saveSettings(); ++ ++ if (OcrManager *ocrManager = OcrManager::instance()) { ++ ocrManager->setConfigSyncSuspended(false); ++ } + } + + void SettingsDialog::updateWidgets() +@@ -100,15 +115,23 @@ void SettingsDialog::updateWidgets() + + m_generalPage->ocrLanguageSelector()->updateWidgets(); + m_generalPage->refreshOcrLanguageSettings(); ++ ++ if (OcrManager *ocrManager = OcrManager::instance()) { ++ ocrManager->setConfigSyncSuspended(false); ++ } + } + + void SettingsDialog::updateWidgetsDefault() + { ++ if (OcrManager *ocrManager = OcrManager::instance()) { ++ ocrManager->setConfigSyncSuspended(true); ++ } ++ + KConfigDialog::updateWidgetsDefault(); + m_shortcutsPage->defaults(); + + m_generalPage->ocrLanguageSelector()->applyDefaults(); +- m_generalPage->refreshOcrLanguageSettings(); ++ m_generalPage->refreshOcrLanguageSettings(false); + } + + #include "moc_SettingsDialog.cpp" +diff --git a/src/Gui/SettingsDialog/SettingsDialog.h b/src/Gui/SettingsDialog/SettingsDialog.h +index 50f6d85bf..64281dd09 100644 +--- a/src/Gui/SettingsDialog/SettingsDialog.h ++++ b/src/Gui/SettingsDialog/SettingsDialog.h +@@ -20,6 +20,7 @@ class SettingsDialog : public KConfigDialog + + public: + explicit SettingsDialog(QWidget *parent = nullptr); ++ ~SettingsDialog() override; + + protected: + QSize sizeHint() const override; +diff --git a/src/OcrManager.cpp b/src/OcrManager.cpp +index 1d09db8ef..56d467993 100644 +--- a/src/OcrManager.cpp ++++ b/src/OcrManager.cpp +@@ -56,6 +56,9 @@ OcrManager::OcrManager(QObject *parent) + m_workerThread->start(); + + connect(Settings::self(), &Settings::ocrLanguagesChanged, this, [this]() { ++ if (m_configSyncSuspended) { ++ return; ++ } + const QStringList newLanguages = Settings::ocrLanguages(); + const QString combinedLanguages = newLanguages.join(u"+"_s); + if (combinedLanguages != m_currentLanguageCode) { +@@ -150,6 +153,28 @@ QString OcrManager::currentLanguageCode() const + return m_currentLanguageCode; + } + ++void OcrManager::setConfigSyncSuspended(bool suspended) ++{ ++ if (m_configSyncSuspended == suspended) { ++ return; ++ } ++ ++ m_configSyncSuspended = suspended; ++ ++ // On resume, apply any changes made to Settings ++ if (!m_configSyncSuspended) { ++ const QStringList settingsLanguages = Settings::ocrLanguages(); ++ if (settingsLanguages != m_configuredLanguages) { ++ setLanguagesByCode(settingsLanguages); ++ } ++ } ++} ++ ++bool OcrManager::isConfigSyncSuspended() const ++{ ++ return m_configSyncSuspended; ++} ++ + void OcrManager::recognizeText(const QImage &image) + { + #ifdef HAVE_TESSERACT_OCR +diff --git a/src/OcrManager.h b/src/OcrManager.h +index c71505b3e..37f490600 100644 +--- a/src/OcrManager.h ++++ b/src/OcrManager.h +@@ -98,6 +98,8 @@ public: + * @return Current language code (e.g., "eng", "spa") + */ + QString currentLanguageCode() const; ++ void setConfigSyncSuspended(bool suspended); ++ bool isConfigSyncSuspended() const; + + public Q_SLOTS: + /** +@@ -169,6 +171,7 @@ private: + bool m_shouldRestoreToConfigured; + QStringList m_availableLanguages; + QMap m_languageNames; ++ bool m_configSyncSuspended = false; + bool m_initialized; + + private: +-- +GitLab + + +From 642600410714c783515f2416a9be08ef3406b0d9 Mon Sep 17 00:00:00 2001 +From: Jhair Paris +Date: Sat, 8 Nov 2025 21:30:41 -0500 +Subject: [PATCH 2/4] Fix flickering in settings dialog during OCR + initialization + +--- + src/Gui/SettingsDialog/GeneralOptionsPage.cpp | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp +index ae0a997c3..adfc045e6 100644 +--- a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp ++++ b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp +@@ -38,7 +38,7 @@ GeneralOptionsPage::GeneralOptionsPage(QWidget *parent) + + connect(m_ocrLanguageSelector, &OcrLanguageSelector::selectedLanguagesChanged, this, &GeneralOptionsPage::ocrLanguageChanged); + +- refreshOcrLanguageSettings(); ++ refreshOcrLanguageSettings(false); + + //On Wayland we can't programmatically raise and focus the window so we have to hide the option + if (KWindowSystem::isPlatformWayland() || qstrcmp(qgetenv("XDG_SESSION_TYPE").constData(), "wayland") == 0) { +@@ -51,8 +51,9 @@ GeneralOptionsPage::~GeneralOptionsPage() = default; + void GeneralOptionsPage::refreshOcrLanguageSettings(bool rebuildSelector) + { + OcrManager *ocrManager = OcrManager::instance(); +- +- if (!ocrManager->isAvailable()) { ++ const bool ocrAvailable = ocrManager->isAvailable(); ++ ++ if (!ocrAvailable) { + m_ui->ocrLanguageLabel->setVisible(false); + m_ui->ocrLanguageScrollArea->setVisible(false); + m_ui->ocrUnavailableWidget->setVisible(true); +@@ -60,10 +61,10 @@ void GeneralOptionsPage::refreshOcrLanguageSettings(bool rebuildSelector) + m_ui->ocrLanguageLabel->setVisible(true); + m_ui->ocrLanguageScrollArea->setVisible(true); + m_ui->ocrUnavailableWidget->setVisible(false); ++ } + +- if (rebuildSelector) { +- m_ocrLanguageSelector->refresh(); +- } ++ if (ocrAvailable && rebuildSelector) { ++ m_ocrLanguageSelector->refresh(); + } + } + +-- +GitLab + + +From 6c6d95f3fd87ff70f8c1d25786a5a7f047e9d74f Mon Sep 17 00:00:00 2001 +From: Jhair Paris +Date: Sat, 8 Nov 2025 21:51:05 -0500 +Subject: [PATCH 3/4] Improve OCR language handling in settings dialog + +--- + src/Gui/SettingsDialog/SettingsDialog.cpp | 24 ++++++++++++++++++----- + 1 file changed, 19 insertions(+), 5 deletions(-) + +diff --git a/src/Gui/SettingsDialog/SettingsDialog.cpp b/src/Gui/SettingsDialog/SettingsDialog.cpp +index 696636685..0bfab8bb9 100644 +--- a/src/Gui/SettingsDialog/SettingsDialog.cpp ++++ b/src/Gui/SettingsDialog/SettingsDialog.cpp +@@ -88,12 +88,20 @@ void SettingsDialog::showEvent(QShowEvent *event) + + bool SettingsDialog::hasChanged() + { +- return m_shortcutsPage->isModified() || m_generalPage->ocrLanguageSelector()->hasChanges() || KConfigDialog::hasChanged(); ++ bool ocrHasChanges = false; ++ if (OcrManager::instance()->isAvailable()) { ++ ocrHasChanges = m_generalPage->ocrLanguageSelector()->hasChanges(); ++ } ++ return m_shortcutsPage->isModified() || ocrHasChanges || KConfigDialog::hasChanged(); + } + + bool SettingsDialog::isDefault() + { +- return currentPage()->name() != i18n("Shortcuts") && m_generalPage->ocrLanguageSelector()->isDefault() && KConfigDialog::isDefault(); ++ bool ocrIsDefault = true; ++ if (OcrManager::instance()->isAvailable()) { ++ ocrIsDefault = m_generalPage->ocrLanguageSelector()->isDefault(); ++ } ++ return currentPage()->name() != i18n("Shortcuts") && ocrIsDefault && KConfigDialog::isDefault(); + } + + void SettingsDialog::updateSettings() +@@ -101,7 +109,9 @@ void SettingsDialog::updateSettings() + KConfigDialog::updateSettings(); + m_shortcutsPage->saveChanges(); + +- m_generalPage->ocrLanguageSelector()->saveSettings(); ++ if (OcrManager::instance()->isAvailable()) { ++ m_generalPage->ocrLanguageSelector()->saveSettings(); ++ } + + if (OcrManager *ocrManager = OcrManager::instance()) { + ocrManager->setConfigSyncSuspended(false); +@@ -113,7 +123,9 @@ void SettingsDialog::updateWidgets() + KConfigDialog::updateWidgets(); + m_shortcutsPage->resetChanges(); + +- m_generalPage->ocrLanguageSelector()->updateWidgets(); ++ if (OcrManager::instance()->isAvailable()) { ++ m_generalPage->ocrLanguageSelector()->updateWidgets(); ++ } + m_generalPage->refreshOcrLanguageSettings(); + + if (OcrManager *ocrManager = OcrManager::instance()) { +@@ -130,7 +142,9 @@ void SettingsDialog::updateWidgetsDefault() + KConfigDialog::updateWidgetsDefault(); + m_shortcutsPage->defaults(); + +- m_generalPage->ocrLanguageSelector()->applyDefaults(); ++ if (OcrManager::instance()->isAvailable()) { ++ m_generalPage->ocrLanguageSelector()->applyDefaults(); ++ } + m_generalPage->refreshOcrLanguageSettings(false); + } + +-- +GitLab + + +From 174b4a4a10e2c42fa28eb361cd4b6a833af60dc7 Mon Sep 17 00:00:00 2001 +From: Jhair Paris +Date: Mon, 10 Nov 2025 22:10:51 -0500 +Subject: [PATCH 4/4] Remove Tesseract language pack validation test and + simplify OCR support check + +--- + CMakeLists.txt | 24 ++---------------------- + cmake/tesseract_test.cpp | 40 ---------------------------------------- + 2 files changed, 2 insertions(+), 62 deletions(-) + delete mode 100644 cmake/tesseract_test.cpp + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index ea44e71d4..2adf8a9ac 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -96,28 +96,8 @@ if(PkgConfig_FOUND) + pkg_check_modules(TESSERACT tesseract) + + if(TESSERACT_FOUND) +- # Test if Tesseract has usable language packs +- try_run( +- TESSERACT_TEST_RUN_RESULT +- TESSERACT_TEST_COMPILE_RESULT +- ${CMAKE_CURRENT_BINARY_DIR} +- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/tesseract_test.cpp +- LINK_LIBRARIES ${TESSERACT_LIBRARIES} +- CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${TESSERACT_INCLUDE_DIRS}" +- COMPILE_OUTPUT_VARIABLE TESSERACT_COMPILE_OUTPUT +- RUN_OUTPUT_VARIABLE TESSERACT_RUN_OUTPUT +- ) +- +- if(TESSERACT_TEST_COMPILE_RESULT AND TESSERACT_TEST_RUN_RESULT EQUAL 0) +- message(STATUS "Tesseract OCR support enabled") +- message(STATUS "${TESSERACT_RUN_OUTPUT}") +- set(HAVE_TESSERACT_OCR TRUE) +- else() +- message(WARNING "Tesseract library found but no usable language packs detected") +- message(WARNING "${TESSERACT_RUN_OUTPUT}") +- message(WARNING "OCR functionality will be disabled. Install language data packages (e.g., tesseract-ocr-eng)") +- set(HAVE_TESSERACT_OCR FALSE) +- endif() ++ message(STATUS "Tesseract OCR support enabled") ++ set(HAVE_TESSERACT_OCR TRUE) + else() + message(STATUS "Tesseract not found - OCR functionality disabled") + set(HAVE_TESSERACT_OCR FALSE) +diff --git a/cmake/tesseract_test.cpp b/cmake/tesseract_test.cpp +deleted file mode 100644 +index 4ebae9779..000000000 +--- a/cmake/tesseract_test.cpp ++++ /dev/null +@@ -1,40 +0,0 @@ +-#include +-#include +-#include +-#include +- +-int main() +-{ +- tesseract::TessBaseAPI api; +- +- if (api.Init(nullptr, nullptr) != 0) { +- std::cerr << "Failed to initialize Tesseract" << std::endl; +- return 1; +- } +- +- std::vector languages; +- api.GetAvailableLanguagesAsVector(&languages); +- +- // Filter out 'osd' as it's not a usable language for OCR +- std::vector usableLanguages; +- for (const auto &lang : languages) { +- if (lang != "osd") { +- usableLanguages.push_back(lang); +- } +- } +- +- if (usableLanguages.empty()) { +- std::cerr << "No usable Tesseract language packs found. Install language data files (e.g., tesseract-ocr-eng)" << std::endl; +- return 1; +- } +- +- std::cout << "Found " << usableLanguages.size() << " Tesseract language pack(s): "; +- for (size_t i = 0; i < usableLanguages.size(); ++i) { +- std::cout << usableLanguages[i]; +- if (i < usableLanguages.size() - 1) +- std::cout << ", "; +- } +- std::cout << std::endl; +- +- return 0; +-} +-- +GitLab + diff --git a/roles/kde/programs/default.nix b/roles/kde/programs/default.nix index 13dc61a..0ac9c9f 100644 --- a/roles/kde/programs/default.nix +++ b/roles/kde/programs/default.nix @@ -8,6 +8,7 @@ ./konsole.nix ./kwin.nix ./baloo.nix + ./spectacle.nix ]; # Enable the kde partition manager diff --git a/roles/kde/programs/spectacle.nix b/roles/kde/programs/spectacle.nix new file mode 100644 index 0000000..3dfc0e5 --- /dev/null +++ b/roles/kde/programs/spectacle.nix @@ -0,0 +1,24 @@ +{...}: { + nixpkgs.overlays = [ + ( + final: prev: { + kdePackages = prev.kdePackages.overrideScope ( + kFinal: kPrev: { + # Needed for OCR + spectacle = kPrev.spectacle.overrideAttrs (old: { + nativeBuildInputs = old.nativeBuildInputs ++ [final.pkg-config]; + buildInputs = with final; + old.buildInputs + ++ [ + tesseract + leptonica + libarchive + curl + ]; + }); + } + ); + } + ) + ]; +} From 8b86b1ccc04ede56a3b6bfbfe74dc4cbcbc50b5e Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 18 Nov 2025 17:46:17 +0100 Subject: [PATCH 1089/1125] Flake: update lock file --- flake.lock | 102 ++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/flake.lock b/flake.lock index afa94eb..0136977 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1761656077, - "narHash": "sha256-lsNWuj4Z+pE7s0bd2OKicOFq9bK86JE0ZGeKJbNqb94=", + "lastModified": 1762618334, + "narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=", "owner": "ryantm", "repo": "agenix", - "rev": "9ba0d85de3eaa7afeab493fed622008b6e4924f5", + "rev": "fcdea223397448d35d9b31f798479227e80183f6", "type": "github" }, "original": { @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1754766435, - "narHash": "sha256-DT8CQoqV2haX+Fo16WXAt9gKCSXOZH9ZfnV++Br+qcM=", + "lastModified": 1763111355, + "narHash": "sha256-iUTS8wV7tCo7A456Ro6ZOJ6Bbk0V5Is3zPd+BmJHJ/Q=", "owner": "catppuccin", "repo": "nix", - "rev": "e339d6d822fa81c39d1ab89694b4ee2cfc830c9a", + "rev": "5375a9d80c4b2a835c7203920f997f3ea4224423", "type": "github" }, "original": { @@ -63,11 +63,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1761906071, - "narHash": "sha256-uq0X0KRzZkKGlkU1ARM+LWCAVvSYJZtTMpuzMO6LXRs=", + "lastModified": 1763110997, + "narHash": "sha256-S2vF+3D/9vna3/vBV7LHiGUbp+ltPsQhvccIyim6VQg=", "owner": "catppuccin", "repo": "nix", - "rev": "fd1bc7b1af0a576edb13c166c4b1f7b5c7555a73", + "rev": "e6928cdd3dd20636326c2756d2bc8fd1cd825768", "type": "github" }, "original": { @@ -84,11 +84,11 @@ ] }, "locked": { - "lastModified": 1761952154, - "narHash": "sha256-VEE54fEp0vxnmmJ5yXxnWVLfc8j5eBmZkC/VDDIGC2w=", + "lastModified": 1762095388, + "narHash": "sha256-7Q8LtcvKWHbP8znARRTOY2tpU5WoV6FHwp5TZJOI8Us=", "owner": "9001", "repo": "copyparty", - "rev": "2cc53ea15181f750b4367e6cd20dfebd0bcb3bee", + "rev": "ac085b8149ff50e03d260128596dd130ed1c7cae", "type": "github" }, "original": { @@ -222,11 +222,11 @@ ] }, "locked": { - "lastModified": 1761878381, - "narHash": "sha256-lCRaipHgszaFZ1Cs8fdGJguVycCisBAf2HEFgip5+xU=", + "lastModified": 1763416652, + "narHash": "sha256-8EBEEvtzQ11LCxpQHMNEBQAGtQiCu/pqP9zSovDSbNM=", "owner": "nix-community", "repo": "home-manager", - "rev": "4ac96eb21c101a3e5b77ba105febc5641a8959aa", + "rev": "ea164b7c9ccdc2321379c2ff78fd4317b4c41312", "type": "github" }, "original": { @@ -264,11 +264,11 @@ ] }, "locked": { - "lastModified": 1761748321, - "narHash": "sha256-hD5mVzmUeyVppjArdy2uVdQe/CQUR9i3WgZB05onE7A=", + "lastModified": 1763453666, + "narHash": "sha256-Hu8lDUlbMFvcYX30LBXX7Gq5FbU35bERH0pSX5qHf/Q=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "533db5857c9e00ca352558a928417116ee08a824", + "rev": "b843b551415c7aecc97c8b3ab3fff26fd0cd8bbf", "type": "github" }, "original": { @@ -280,11 +280,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1761937274, - "narHash": "sha256-KlELhsSq3XbemrGyQhmGurFu7m8wOEBw+8M04L7hn7A=", - "rev": "91867941fa73afea7869b7c71ede82e5ef8927da", + "lastModified": 1763492483, + "narHash": "sha256-LfrnMNvGkJCRFIDieERBUULmIH+mkFpLNpUJf1a5uiA=", + "rev": "1b7ad3a7ad1eb41e5cf7e4280965037687b4fe09", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/91867941fa73afea7869b7c71ede82e5ef8927da.tar.gz?rev=91867941fa73afea7869b7c71ede82e5ef8927da" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/1b7ad3a7ad1eb41e5cf7e4280965037687b4fe09.tar.gz?rev=1b7ad3a7ad1eb41e5cf7e4280965037687b4fe09" }, "original": { "type": "tarball", @@ -303,11 +303,11 @@ ] }, "locked": { - "lastModified": 1761960361, - "narHash": "sha256-FvuAw56NIVJpS3Kr8Wv9PpU4eehZMcdIVkxjStuYmqc=", - "rev": "c47f62187601ea2991b79a9bacdbfdf76cd29fbe", + "lastModified": 1763435414, + "narHash": "sha256-i2467FddWfd19q5Qoj+1/BAeg6LZmM5m4mYGRSQn/as=", + "rev": "192c92b603731fbc1bade6c1b18c8d8a0086f703", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/c47f62187601ea2991b79a9bacdbfdf76cd29fbe.tar.gz?rev=c47f62187601ea2991b79a9bacdbfdf76cd29fbe" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/192c92b603731fbc1bade6c1b18c8d8a0086f703.tar.gz?rev=192c92b603731fbc1bade6c1b18c8d8a0086f703" }, "original": { "type": "tarball", @@ -326,11 +326,11 @@ ] }, "locked": { - "lastModified": 1761960361, - "narHash": "sha256-FvuAw56NIVJpS3Kr8Wv9PpU4eehZMcdIVkxjStuYmqc=", - "rev": "c47f62187601ea2991b79a9bacdbfdf76cd29fbe", + "lastModified": 1763435414, + "narHash": "sha256-i2467FddWfd19q5Qoj+1/BAeg6LZmM5m4mYGRSQn/as=", + "rev": "192c92b603731fbc1bade6c1b18c8d8a0086f703", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/c47f62187601ea2991b79a9bacdbfdf76cd29fbe.tar.gz?rev=c47f62187601ea2991b79a9bacdbfdf76cd29fbe" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/192c92b603731fbc1bade6c1b18c8d8a0086f703.tar.gz?rev=192c92b603731fbc1bade6c1b18c8d8a0086f703" }, "original": { "type": "tarball", @@ -397,11 +397,11 @@ ] }, "locked": { - "lastModified": 1761451000, - "narHash": "sha256-qBJL6xEIjqYq9zOcG2vf2nPTeVBppNJzvO0LuQWMwMo=", + "lastModified": 1763265660, + "narHash": "sha256-Ad9Rd3ZAidrH01xP73S3CjPiyXo7ywZs3uCESjPwUdc=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "ed6b293161b378a7368cda38659eb8d3d9a0dac4", + "rev": "469ef53571ea80890c9497952787920c79c1ee6e", "type": "github" }, "original": { @@ -417,11 +417,11 @@ ] }, "locked": { - "lastModified": 1761451000, - "narHash": "sha256-qBJL6xEIjqYq9zOcG2vf2nPTeVBppNJzvO0LuQWMwMo=", + "lastModified": 1763265660, + "narHash": "sha256-Ad9Rd3ZAidrH01xP73S3CjPiyXo7ywZs3uCESjPwUdc=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "ed6b293161b378a7368cda38659eb8d3d9a0dac4", + "rev": "469ef53571ea80890c9497952787920c79c1ee6e", "type": "github" }, "original": { @@ -432,11 +432,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1761933221, - "narHash": "sha256-rNHeoG3ZrA94jczyLSjxCtu67YYPYIlXXr0uhG3wNxM=", + "lastModified": 1762847253, + "narHash": "sha256-BWWnUUT01lPwCWUvS0p6Px5UOBFeXJ8jR+ZdLX8IbrU=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "7467f155fcba189eb088a7601f44fbef7688669b", + "rev": "899dc449bc6428b9ee6b3b8f771ca2b0ef945ab9", "type": "github" }, "original": { @@ -464,11 +464,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1761597516, - "narHash": "sha256-wxX7u6D2rpkJLWkZ2E932SIvDJW8+ON/0Yy8+a5vsDU=", + "lastModified": 1763334038, + "narHash": "sha256-LBVOyaH6NFzQ3X/c6vfMZ9k4SV2ofhpxeL9YnhHNJQQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "daf6dc47aa4b44791372d6139ab7b25269184d55", + "rev": "4c8cdd5b1a630e8f72c9dd9bf582b1afb3127d2c", "type": "github" }, "original": { @@ -479,11 +479,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1761907660, - "narHash": "sha256-kJ8lIZsiPOmbkJypG+B5sReDXSD1KGu2VEPNqhRa/ew=", + "lastModified": 1763421233, + "narHash": "sha256-Stk9ZYRkGrnnpyJ4eqt9eQtdFWRRIvMxpNRf4sIegnw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2fb006b87f04c4d3bdf08cfdbc7fab9c13d94a15", + "rev": "89c2b2330e733d6cdb5eae7b899326930c2c0648", "type": "github" }, "original": { @@ -494,11 +494,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1761672384, - "narHash": "sha256-o9KF3DJL7g7iYMZq9SWgfS1BFlNbsm6xplRjVlOCkXI=", + "lastModified": 1762111121, + "narHash": "sha256-4vhDuZ7OZaZmKKrnDpxLZZpGIJvAeMtK6FKLJYUtAdw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "08dacfca559e1d7da38f3cf05f1f45ee9bfd213c", + "rev": "b3d51a0365f6695e7dd5cdf3e180604530ed33b4", "type": "github" }, "original": { @@ -518,11 +518,11 @@ ] }, "locked": { - "lastModified": 1761078382, - "narHash": "sha256-JNJesbe9MMN1Brq41BHEpuH+Z+Zg74y/nI5AFZX84Vw=", + "lastModified": 1762784320, + "narHash": "sha256-odsk96Erywk5hs0dhArF38zb7Oe0q6LZ70gXbxAPKno=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "27dfa61b64d0cdb8e4ba6f3aaa4d4e067d64cb5c", + "rev": "7911a0f8a44c7e8b29d031be3149ee8943144321", "type": "github" }, "original": { From eb5ebb056cebbf19501fd6edf691df9a3e600432 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 5 Dec 2025 23:59:26 +0100 Subject: [PATCH 1090/1125] Gaming: patch sdl to ignore keychron things --- roles/gaming/default.nix | 12 +++++++++++- roles/gaming/sdl-keychron-blacklist.patch | 13 +++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 roles/gaming/sdl-keychron-blacklist.patch diff --git a/roles/gaming/default.nix b/roles/gaming/default.nix index 2d8f4ab..4845419 100644 --- a/roles/gaming/default.nix +++ b/roles/gaming/default.nix @@ -1,6 +1,16 @@ -{...}: { +{pkgs, ...}: { imports = [ ./programs ./services ]; + system.replaceDependencies.replacements = [ + { + oldDependency = pkgs.sdl3; + newDependency = pkgs.sdl3.overrideAttrs { + patches = [ + ./sdl-keychron-blacklist.patch + ]; + }; + } + ]; } diff --git a/roles/gaming/sdl-keychron-blacklist.patch b/roles/gaming/sdl-keychron-blacklist.patch new file mode 100644 index 0000000..ef73b54 --- /dev/null +++ b/roles/gaming/sdl-keychron-blacklist.patch @@ -0,0 +1,13 @@ +diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c +index 5ce36de86..37bf5ca85 100644 +--- a/src/joystick/SDL_joystick.c ++++ b/src/joystick/SDL_joystick.c +@@ -281,6 +281,8 @@ static Uint32 initial_blacklist_devices[] = { + MAKE_VIDPID(0x3297, 0x1969), // Moonlander MK1 Keyboard + MAKE_VIDPID(0x3434, 0x0211), // Keychron K1 Pro System Control + MAKE_VIDPID(0x04f2, 0xa13c), // HP Deluxe Webcam KQ246AA ++ MAKE_VIDPID(0x3434, 0x0353), // Keychron V5 System Control ++ MAKE_VIDPID(0x3434, 0xd030), // Keychron Link + }; + static SDL_vidpid_list blacklist_devices = { + SDL_HINT_JOYSTICK_BLACKLIST_DEVICES, 0, 0, NULL, From ed8a6297b75090004b146b1c0b17f180b5ac3afb Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 6 Dec 2025 00:05:39 +0100 Subject: [PATCH 1091/1125] Gaming/pcsx2: refactor, add game config for burnout 3 --- roles/gaming/programs/pcsx2.nix | 174 +++++++++++++++++--------------- 1 file changed, 91 insertions(+), 83 deletions(-) diff --git a/roles/gaming/programs/pcsx2.nix b/roles/gaming/programs/pcsx2.nix index a8e5838..8cf7898 100644 --- a/roles/gaming/programs/pcsx2.nix +++ b/roles/gaming/programs/pcsx2.nix @@ -7,6 +7,7 @@ url = "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202%20-%20BIOS%20Images%20%28DoM%20Version%29/ps2-0200a-20040614.zip"; hash = "sha256-wMvswgmsKl+cJl49VlVW84tvU5Jzd+2dl07SOiUDtwA="; }; + toPcsx2INI = lib.generators.toINI {listsAsDuplicateKeys = true;}; in { home-manager.users.toast = { home.packages = with pkgs; [ @@ -15,93 +16,100 @@ in { xdg.configFile = { #PCSX2 silently overwrites the symlink so I need to force it's creation "PCSX2/inis/PCSX2.ini".force = true; - "PCSX2/inis/PCSX2.ini".text = - lib.generators.toINI { - listsAsDuplicateKeys = true; - } { - UI = { - SettingsVersion = 1; - # Use the system theme - Theme = ""; - HideMouseCursor = true; - }; - Folders = { - Bios = "/home/toast/.local/share/PCSX2/bios"; - }; - GameList.RecursivePaths = [ - "/home/toast/Games/PS2/" - ]; - "EmuCore/GS" = { - dithering_ps2 = 1; - upscale_multiplier = 2; - }; - EmuCore = { - EnableDiscordPresence = true; - EnableFastBoot = true; - McdFolderAutoManage = false; - }; - - MemoryCards.Slot1_Filename = "MemoryCard1.ps2"; - - # Controller settings - Pad1 = { - Up = "SDL-0/DPadUp"; - Right = "SDL-0/DPadRight"; - Down = "SDL-0/DPadDown"; - Left = "SDL-0/DPadLeft"; - Triangle = "SDL-0/Y"; - Circle = "SDL-0/B"; - Cross = "SDL-0/A"; - Square = "SDL-0/X"; - Select = "SDL-0/Back"; - Start = "SDL-0/Start"; - L1 = "SDL-0/LeftShoulder"; - L2 = "SDL-0/+LeftTrigger"; - R1 = "SDL-0/RightShoulder"; - R2 = "SDL-0/+RightTrigger"; - L3 = "SDL-0/LeftStick"; - R3 = "SDL-0/RightStick"; - Analog = "SDL-0/Guide"; - LUp = "SDL-0/-LeftY"; - LRight = "SDL-0/+LeftX"; - LDown = "SDL-0/+LeftY"; - LLeft = "SDL-0/-LeftX"; - RUp = "SDL-0/-RightY"; - RRight = "SDL-0/+RightX"; - RDown = "SDL-0/+RightY"; - RLeft = "SDL-0/-RightX"; - LargeMotor = "SDL-0/LargeMotor"; - SmallMotor = "SDL-0/SmallMotor"; - }; - # Default hotkeys - Hotkeys = { - ToggleFullscreen = "Keyboard/Alt & Keyboard/Return"; - CycleAspectRatio = "Keyboard/F6"; - CycleInterlaceMode = "Keyboard/F5"; - CycleMipmapMode = "Keyboard/Insert"; - GSDumpMultiFrame = "Keyboard/Control & Keyboard/Shift & Keyboard/F8"; - Screenshot = "Keyboard/F8"; - GSDumpSingleFrame = "Keyboard/Shift & Keyboard/F8"; - ToggleSoftwareRendering = "Keyboard/F9"; - ZoomIn = "Keyboard/Control & Keyboard/Plus"; - ZoomOut = "Keyboard/Control & Keyboard/Minus"; - InputRecToggleMode = "Keyboard/Shift & Keyboard/R"; - LoadStateFromSlot = "Keyboard/F3"; - SaveStateToSlot = "Keyboard/F1"; - NextSaveStateSlot = "Keyboard/F2"; - PreviousSaveStateSlot = "Keyboard/Shift & Keyboard/F2"; - OpenPauseMenu = "Keyboard/Escape"; - ToggleFrameLimit = "Keyboard/F4"; - TogglePause = "Keyboard/Space"; - ToggleSlowMotion = "Keyboard/Shift & Keyboard/Backtab"; - ToggleTurbo = "Keyboard/Tab"; - HoldTurbo = "Keyboard/Period"; - }; + "PCSX2/inis/PCSX2.ini".text = toPcsx2INI { + UI = { + SettingsVersion = 1; + # Use the system theme + Theme = ""; + HideMouseCursor = true; }; + Folders = { + Bios = "/home/toast/.local/share/PCSX2/bios"; + }; + GameList.RecursivePaths = [ + "/home/toast/Games/PS2/" + ]; + "EmuCore/GS" = { + dithering_ps2 = 1; + upscale_multiplier = 2; + }; + EmuCore = { + EnableDiscordPresence = true; + EnableFastBoot = true; + McdFolderAutoManage = false; + }; + + MemoryCards.Slot1_Filename = "MemoryCard1.ps2"; + + # Controller settings + Pad1 = { + Up = "SDL-0/DPadUp"; + Right = "SDL-0/DPadRight"; + Down = "SDL-0/DPadDown"; + Left = "SDL-0/DPadLeft"; + Triangle = "SDL-0/Y"; + Circle = "SDL-0/B"; + Cross = "SDL-0/A"; + Square = "SDL-0/X"; + Select = "SDL-0/Back"; + Start = "SDL-0/Start"; + L1 = "SDL-0/LeftShoulder"; + L2 = "SDL-0/+LeftTrigger"; + R1 = "SDL-0/RightShoulder"; + R2 = "SDL-0/+RightTrigger"; + L3 = "SDL-0/LeftStick"; + R3 = "SDL-0/RightStick"; + Analog = "SDL-0/Guide"; + LUp = "SDL-0/-LeftY"; + LRight = "SDL-0/+LeftX"; + LDown = "SDL-0/+LeftY"; + LLeft = "SDL-0/-LeftX"; + RUp = "SDL-0/-RightY"; + RRight = "SDL-0/+RightX"; + RDown = "SDL-0/+RightY"; + RLeft = "SDL-0/-RightX"; + LargeMotor = "SDL-0/LargeMotor"; + SmallMotor = "SDL-0/SmallMotor"; + }; + # Default hotkeys + Hotkeys = { + ToggleFullscreen = "Keyboard/Alt & Keyboard/Return"; + CycleAspectRatio = "Keyboard/F6"; + CycleInterlaceMode = "Keyboard/F5"; + CycleMipmapMode = "Keyboard/Insert"; + GSDumpMultiFrame = "Keyboard/Control & Keyboard/Shift & Keyboard/F8"; + Screenshot = "Keyboard/F8"; + GSDumpSingleFrame = "Keyboard/Shift & Keyboard/F8"; + ToggleSoftwareRendering = "Keyboard/F9"; + ZoomIn = "Keyboard/Control & Keyboard/Plus"; + ZoomOut = "Keyboard/Control & Keyboard/Minus"; + InputRecToggleMode = "Keyboard/Shift & Keyboard/R"; + LoadStateFromSlot = "Keyboard/F3"; + SaveStateToSlot = "Keyboard/F1"; + NextSaveStateSlot = "Keyboard/F2"; + PreviousSaveStateSlot = "Keyboard/Shift & Keyboard/F2"; + OpenPauseMenu = "Keyboard/Escape"; + ToggleFrameLimit = "Keyboard/F4"; + TogglePause = "Keyboard/Space"; + ToggleSlowMotion = "Keyboard/Shift & Keyboard/Backtab"; + ToggleTurbo = "Keyboard/Tab"; + HoldTurbo = "Keyboard/Period"; + }; + }; # 007 nightfire - "PCSX2/gamesettings/SLUS-20579_5B86BB62.ini".text = lib.generators.toINI {} { + "PCSX2/gamesettings/SLUS-20579_5B86BB62.ini".text = toPcsx2INI { "EmuCore/GS".AspectRatio = "16:9"; }; + "PCSX2/gamesettings/SLUS-21050_BEBF8793.ini".text = toPcsx2INI { + "EmuCore/GS".AspectRatio = "16:9"; + Patches.Enable = [ + "60 FPS for Crashes" + "60 FPS for Menus" + "Progressive Scan" + "MPH to KPH" + "Extra Particles While Driving" + ]; + }; }; xdg.dataFile = { # I would prefer to use symlinkJoin like I do for the ISOs, but From 8331e8c8756803b3e12d88cacc09f62f8e2d07ec Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 5 Dec 2025 15:39:47 +0100 Subject: [PATCH 1092/1125] Flake: update lock file, switch stable to 25.11 --- flake.lock | 100 ++++++++++++++++++++++++++--------------------------- flake.nix | 4 +-- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/flake.lock b/flake.lock index 0136977..013bd7d 100644 --- a/flake.lock +++ b/flake.lock @@ -63,11 +63,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1763110997, - "narHash": "sha256-S2vF+3D/9vna3/vBV7LHiGUbp+ltPsQhvccIyim6VQg=", + "lastModified": 1764885363, + "narHash": "sha256-P6UHmw6enwxmP5wP4Lv722+tgpq1PFDAPAdtj7l/16U=", "owner": "catppuccin", "repo": "nix", - "rev": "e6928cdd3dd20636326c2756d2bc8fd1cd825768", + "rev": "95042630028d613080393e0f03c694b77883c7db", "type": "github" }, "original": { @@ -84,11 +84,11 @@ ] }, "locked": { - "lastModified": 1762095388, - "narHash": "sha256-7Q8LtcvKWHbP8znARRTOY2tpU5WoV6FHwp5TZJOI8Us=", + "lastModified": 1764870617, + "narHash": "sha256-Og3V5eIMzmxOnCoVIJD5Xpz7X9OBevdHBJqSoNwV/Ig=", "owner": "9001", "repo": "copyparty", - "rev": "ac085b8149ff50e03d260128596dd130ed1c7cae", + "rev": "fa918228d56e1384e77adc193c4bd26356f6bd18", "type": "github" }, "original": { @@ -222,11 +222,11 @@ ] }, "locked": { - "lastModified": 1763416652, - "narHash": "sha256-8EBEEvtzQ11LCxpQHMNEBQAGtQiCu/pqP9zSovDSbNM=", + "lastModified": 1764872372, + "narHash": "sha256-uZuXRz9CzeCHsRbc2MQvKomwoX6GcFC5BUMEk3ouSFU=", "owner": "nix-community", "repo": "home-manager", - "rev": "ea164b7c9ccdc2321379c2ff78fd4317b4c41312", + "rev": "05a56dbf24f195c62286e3273a2671d3b4904b00", "type": "github" }, "original": { @@ -242,16 +242,16 @@ ] }, "locked": { - "lastModified": 1758463745, - "narHash": "sha256-uhzsV0Q0I9j2y/rfweWeGif5AWe0MGrgZ/3TjpDYdGA=", + "lastModified": 1764866045, + "narHash": "sha256-0GsEtXV9OquDQ1VclQfP16cU5VZh7NEVIOjSH4UaJuM=", "owner": "nix-community", "repo": "home-manager", - "rev": "3b955f5f0a942f9f60cdc9cacb7844335d0f21c3", + "rev": "f63d0fe9d81d36e5fc95497217a72e02b8b7bcab", "type": "github" }, "original": { "owner": "nix-community", - "ref": "release-25.05", + "ref": "release-25.11", "repo": "home-manager", "type": "github" } @@ -264,11 +264,11 @@ ] }, "locked": { - "lastModified": 1763453666, - "narHash": "sha256-Hu8lDUlbMFvcYX30LBXX7Gq5FbU35bERH0pSX5qHf/Q=", + "lastModified": 1764746434, + "narHash": "sha256-6ymFuw+Z1C90ezf8H0BP3c2JFZhJYwMq31px2StwWHU=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "b843b551415c7aecc97c8b3ab3fff26fd0cd8bbf", + "rev": "b4c0b604148adacf119b89824ed26df8926ce42c", "type": "github" }, "original": { @@ -280,11 +280,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1763492483, - "narHash": "sha256-LfrnMNvGkJCRFIDieERBUULmIH+mkFpLNpUJf1a5uiA=", - "rev": "1b7ad3a7ad1eb41e5cf7e4280965037687b4fe09", + "lastModified": 1764846683, + "narHash": "sha256-wW+hjhr2/rUTVAs8VM5Oq8hkT6HZ4zEnaiwYI1VPGDk=", + "rev": "8f5bf1e90556e0cdbee7899a7bee51b6ef76fc94", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/1b7ad3a7ad1eb41e5cf7e4280965037687b4fe09.tar.gz?rev=1b7ad3a7ad1eb41e5cf7e4280965037687b4fe09" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/8f5bf1e90556e0cdbee7899a7bee51b6ef76fc94.tar.gz?rev=8f5bf1e90556e0cdbee7899a7bee51b6ef76fc94" }, "original": { "type": "tarball", @@ -303,11 +303,11 @@ ] }, "locked": { - "lastModified": 1763435414, - "narHash": "sha256-i2467FddWfd19q5Qoj+1/BAeg6LZmM5m4mYGRSQn/as=", - "rev": "192c92b603731fbc1bade6c1b18c8d8a0086f703", + "lastModified": 1764519849, + "narHash": "sha256-XnNABKfIYKSimQVvKc9FnlC2H0LurOhd9MS6l0Z67lE=", + "rev": "6c95c0b6f73f831226453fc6905c216ab634c30f", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/192c92b603731fbc1bade6c1b18c8d8a0086f703.tar.gz?rev=192c92b603731fbc1bade6c1b18c8d8a0086f703" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/6c95c0b6f73f831226453fc6905c216ab634c30f.tar.gz?rev=6c95c0b6f73f831226453fc6905c216ab634c30f" }, "original": { "type": "tarball", @@ -326,11 +326,11 @@ ] }, "locked": { - "lastModified": 1763435414, - "narHash": "sha256-i2467FddWfd19q5Qoj+1/BAeg6LZmM5m4mYGRSQn/as=", - "rev": "192c92b603731fbc1bade6c1b18c8d8a0086f703", + "lastModified": 1764519849, + "narHash": "sha256-XnNABKfIYKSimQVvKc9FnlC2H0LurOhd9MS6l0Z67lE=", + "rev": "6c95c0b6f73f831226453fc6905c216ab634c30f", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/192c92b603731fbc1bade6c1b18c8d8a0086f703.tar.gz?rev=192c92b603731fbc1bade6c1b18c8d8a0086f703" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/6c95c0b6f73f831226453fc6905c216ab634c30f.tar.gz?rev=6c95c0b6f73f831226453fc6905c216ab634c30f" }, "original": { "type": "tarball", @@ -397,11 +397,11 @@ ] }, "locked": { - "lastModified": 1763265660, - "narHash": "sha256-Ad9Rd3ZAidrH01xP73S3CjPiyXo7ywZs3uCESjPwUdc=", + "lastModified": 1764475780, + "narHash": "sha256-77jL5H5x51ksLiOUDjY0ZK8e2T4ZXLhj3ap8ETvknWI=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "469ef53571ea80890c9497952787920c79c1ee6e", + "rev": "5a3ff8c1a09003f399f43d5742d893c0b1ab8af0", "type": "github" }, "original": { @@ -417,11 +417,11 @@ ] }, "locked": { - "lastModified": 1763265660, - "narHash": "sha256-Ad9Rd3ZAidrH01xP73S3CjPiyXo7ywZs3uCESjPwUdc=", + "lastModified": 1764475780, + "narHash": "sha256-77jL5H5x51ksLiOUDjY0ZK8e2T4ZXLhj3ap8ETvknWI=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "469ef53571ea80890c9497952787920c79c1ee6e", + "rev": "5a3ff8c1a09003f399f43d5742d893c0b1ab8af0", "type": "github" }, "original": { @@ -432,11 +432,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1762847253, - "narHash": "sha256-BWWnUUT01lPwCWUvS0p6Px5UOBFeXJ8jR+ZdLX8IbrU=", + "lastModified": 1764440730, + "narHash": "sha256-ZlJTNLUKQRANlLDomuRWLBCH5792x+6XUJ4YdFRjtO4=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "899dc449bc6428b9ee6b3b8f771ca2b0ef945ab9", + "rev": "9154f4569b6cdfd3c595851a6ba51bfaa472d9f3", "type": "github" }, "original": { @@ -464,26 +464,26 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1763334038, - "narHash": "sha256-LBVOyaH6NFzQ3X/c6vfMZ9k4SV2ofhpxeL9YnhHNJQQ=", + "lastModified": 1764677808, + "narHash": "sha256-H3lC7knbXOBrHI9hITQ7modLuX20mYJVhZORL5ioms0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4c8cdd5b1a630e8f72c9dd9bf582b1afb3127d2c", + "rev": "1aab89277eb2d87823d5b69bae631a2496cff57a", "type": "github" }, "original": { "id": "nixpkgs", - "ref": "nixos-25.05", + "ref": "nixos-25.11", "type": "indirect" } }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1763421233, - "narHash": "sha256-Stk9ZYRkGrnnpyJ4eqt9eQtdFWRRIvMxpNRf4sIegnw=", + "lastModified": 1764667669, + "narHash": "sha256-7WUCZfmqLAssbDqwg9cUDAXrSoXN79eEEq17qhTNM/Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "89c2b2330e733d6cdb5eae7b899326930c2c0648", + "rev": "418468ac9527e799809c900eda37cbff999199b6", "type": "github" }, "original": { @@ -494,11 +494,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1762111121, - "narHash": "sha256-4vhDuZ7OZaZmKKrnDpxLZZpGIJvAeMtK6FKLJYUtAdw=", + "lastModified": 1763966396, + "narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b3d51a0365f6695e7dd5cdf3e180604530ed33b4", + "rev": "5ae3b07d8d6527c42f17c876e404993199144b6a", "type": "github" }, "original": { @@ -518,11 +518,11 @@ ] }, "locked": { - "lastModified": 1762784320, - "narHash": "sha256-odsk96Erywk5hs0dhArF38zb7Oe0q6LZ70gXbxAPKno=", + "lastModified": 1763909441, + "narHash": "sha256-56LwV51TX/FhgX+5LCG6akQ5KrOWuKgcJa+eUsRMxsc=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "7911a0f8a44c7e8b29d031be3149ee8943144321", + "rev": "b24ed4b272256dfc1cc2291f89a9821d5f9e14b4", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index f2971ae..2eeb205 100644 --- a/flake.nix +++ b/flake.nix @@ -6,7 +6,7 @@ url = "git+ssh://forgejo@git.toast003.xyz:4222/Toast/nix-secrets"; flake = false; }; - nixpkgs-raw.url = "nixpkgs/nixos-25.05"; + nixpkgs-raw.url = "nixpkgs/nixos-25.11"; nixpkgs-unstable-raw.url = "nixpkgs/nixos-unstable"; agenix = { @@ -18,7 +18,7 @@ }; home-manager = { - url = "github:nix-community/home-manager/release-25.05"; + url = "github:nix-community/home-manager/release-25.11"; inputs.nixpkgs.follows = "nixpkgs-raw"; }; From e6bdf0f98436d2d32776383b7d88620a31296093 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 5 Dec 2025 15:59:37 +0100 Subject: [PATCH 1093/1125] Common/git: update git and delta settings --- roles/common/programs/git.nix | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/roles/common/programs/git.nix b/roles/common/programs/git.nix index 69866ba..2709d45 100644 --- a/roles/common/programs/git.nix +++ b/roles/common/programs/git.nix @@ -7,15 +7,19 @@ home-manager.users.toast = { programs.git = { enable = true; - userName = "Toast"; - userEmail = "toast003@tutamail.com"; - delta.enable = true; - extraConfig = { + settings = { + user.name = "toast"; + user.email = "toast003@tutamail.com"; init.defaultBranch = "main"; diff.colorMoved = "default"; commit.verbose = "true"; }; }; + + programs.delta = { + enable = true; + enableGitIntegration = true; + }; catppuccin.delta.enable = true; }; } From 4361d6e0a98dee6af0d791532b7fe27f7139c59e Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 5 Dec 2025 16:27:14 +0100 Subject: [PATCH 1094/1125] Flake: remove stable catppuccin --- flake.lock | 50 +++++++------------------------------------------- flake.nix | 11 ++--------- 2 files changed, 9 insertions(+), 52 deletions(-) diff --git a/flake.lock b/flake.lock index 013bd7d..e622e4e 100644 --- a/flake.lock +++ b/flake.lock @@ -28,16 +28,15 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1763111355, - "narHash": "sha256-iUTS8wV7tCo7A456Ro6ZOJ6Bbk0V5Is3zPd+BmJHJ/Q=", + "lastModified": 1764885363, + "narHash": "sha256-P6UHmw6enwxmP5wP4Lv722+tgpq1PFDAPAdtj7l/16U=", "owner": "catppuccin", "repo": "nix", - "rev": "5375a9d80c4b2a835c7203920f997f3ea4224423", + "rev": "95042630028d613080393e0f03c694b77883c7db", "type": "github" }, "original": { "owner": "catppuccin", - "ref": "release-25.05", "repo": "nix", "type": "github" } @@ -58,24 +57,6 @@ "type": "github" } }, - "catppuccin-unstable": { - "inputs": { - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1764885363, - "narHash": "sha256-P6UHmw6enwxmP5wP4Lv722+tgpq1PFDAPAdtj7l/16U=", - "owner": "catppuccin", - "repo": "nix", - "rev": "95042630028d613080393e0f03c694b77883c7db", - "type": "github" - }, - "original": { - "owner": "catppuccin", - "repo": "nix", - "type": "github" - } - }, "copyparty": { "inputs": { "flake-utils": "flake-utils", @@ -448,16 +429,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1753749649, - "narHash": "sha256-+jkEZxs7bfOKfBIk430K+tK9IvXlwzqQQnppC2ZKFj4=", + "lastModified": 1764667669, + "narHash": "sha256-7WUCZfmqLAssbDqwg9cUDAXrSoXN79eEEq17qhTNM/Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1f08a4df998e21f4e8be8fb6fbf61d11a1a5076a", + "rev": "418468ac9527e799809c900eda37cbff999199b6", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-25.05", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } @@ -492,22 +473,6 @@ "type": "indirect" } }, - "nixpkgs_2": { - "locked": { - "lastModified": 1763966396, - "narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "5ae3b07d8d6527c42f17c876e404993199144b6a", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, "plasma-manager": { "inputs": { "home-manager": [ @@ -536,7 +501,6 @@ "agenix": "agenix", "catppuccin": "catppuccin", "catppuccin-konsole": "catppuccin-konsole", - "catppuccin-unstable": "catppuccin-unstable", "copyparty": "copyparty", "eza-themes": "eza-themes", "home-manager": "home-manager_2", diff --git a/flake.nix b/flake.nix index 2eeb205..07875bb 100644 --- a/flake.nix +++ b/flake.nix @@ -61,8 +61,7 @@ nix-flatpak.url = "github:gmodena/nix-flatpak/main"; - catppuccin-unstable.url = "github:catppuccin/nix"; - catppuccin.url = "github:catppuccin/nix/release-25.05"; + catppuccin.url = "github:catppuccin/nix"; lix-module = { url = "https://git.lix.systems/lix-project/nixos-module/archive/main.tar.gz"; @@ -182,13 +181,7 @@ ) .nixosModules .nix-index - ( - if stable - then catppuccin - else catppuccin-unstable - ) - .nixosModules - .catppuccin + catppuccin.nixosModules.catppuccin ( if stable then lix-module From 9ca56553f76c00990647d8d93c2f4c81cfb1fb72 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 6 Dec 2025 02:33:40 +0100 Subject: [PATCH 1095/1125] Justfile: update secrets repo url --- .justfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.justfile b/.justfile index 99e2d75..9b4041a 100644 --- a/.justfile +++ b/.justfile @@ -15,8 +15,8 @@ update: nix flake update @edit-secrets: - git clone ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets.git /tmp/secrets - sed -i 's\git+ssh://forgejo@git.everest.tailscale:4222/Toast/nix-secrets\/tmp/secrets\g' flake.nix + git clone ssh://forgejo@git.toast003.xyz:4222/Toast/nix-secrets.git /tmp/secrets + sed -i 's\git+ssh://forgejo@git.toast003.xyz:4222/Toast/nix-secrets\/tmp/secrets\g' flake.nix nix flake update secrets echo "{{bold}}All done!" echo "{{normal}}Remember to restore flake.nix" From 1d1b76b329eadadb4a70dc5d9f1390d45d2650af Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 6 Dec 2025 03:31:56 +0100 Subject: [PATCH 1096/1125] Flake: add sops-nix --- flake.lock | 23 ++++++++++++++++++++++- flake.nix | 5 +++++ roles/common/configuration.nix | 8 +++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/flake.lock b/flake.lock index e622e4e..b7a234c 100644 --- a/flake.lock +++ b/flake.lock @@ -517,7 +517,8 @@ "nixpkgs-raw": "nixpkgs-raw", "nixpkgs-unstable-raw": "nixpkgs-unstable-raw", "plasma-manager": "plasma-manager", - "secrets": "secrets" + "secrets": "secrets", + "sops-nix": "sops-nix" } }, "secrets": { @@ -536,6 +537,26 @@ "url": "ssh://forgejo@git.toast003.xyz:4222/Toast/nix-secrets" } }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable-raw" + ] + }, + "locked": { + "lastModified": 1764483358, + "narHash": "sha256-EyyvCzXoHrbL467YSsQBTWWg4sR96MH1sPpKoSOelB4=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "5aca6ff67264321d47856a2ed183729271107c9c", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + }, "systems": { "locked": { "lastModified": 1681028828, diff --git a/flake.nix b/flake.nix index 07875bb..b73ccd4 100644 --- a/flake.nix +++ b/flake.nix @@ -16,6 +16,10 @@ darwin.follows = ""; # Not using this on MacOS, so this doesn't pull it's dependencies }; }; + sops-nix = { + url = "github:Mic92/sops-nix"; + inputs.nixpkgs.follows = "nixpkgs-unstable-raw"; + }; home-manager = { url = "github:nix-community/home-manager/release-25.11"; @@ -167,6 +171,7 @@ modules = [ agenix.nixosModules.default + sops-nix.nixosModules.sops ( if stable then home-manager diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 284565f..d26b350 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -129,7 +129,10 @@ backupFileExtension = "hm-backup"; useGlobalPkgs = true; verbose = true; - sharedModules = [flakeSelf.inputs.catppuccin.homeModules.catppuccin]; + sharedModules = with flakeSelf; [ + inputs.catppuccin.homeModules.catppuccin + inputs.sops-nix.homeManagerModules.sops + ]; users.toast = {osConfig, ...}: { catppuccin.flavor = osConfig.catppuccin.flavor; catppuccin.accent = osConfig.catppuccin.accent; @@ -156,6 +159,9 @@ "/persist/id_host" ]; }; + sops = { + age.sshKeyPaths = ["/persist/id_host"]; + }; catppuccin.grub.enable = true; From 8c6fdd5b51184a72605a10de2cd1a42b8a3ca877 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 6 Dec 2025 03:37:06 +0100 Subject: [PATCH 1097/1125] Desktop/NetworkManager: migrate secrets to sops-nix --- flake.lock | 8 ++++---- roles/desktop/services/networkmanager.nix | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/flake.lock b/flake.lock index b7a234c..2ed2be4 100644 --- a/flake.lock +++ b/flake.lock @@ -524,11 +524,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1737970846, - "narHash": "sha256-+b44nvv+rKiRdABSHGaTLbp9ysRaHE+s/CuUsA9zNac=", + "lastModified": 1764987865, + "narHash": "sha256-9gporedK0k0t86x415hVhRdl756RsD9KUinOiuCqK4Y=", "ref": "refs/heads/main", - "rev": "d8262fb108d0810d21c5e098b54a105e867e72ce", - "revCount": 28, + "rev": "e945330fd68c693004ffd107e89b3d8f5d5a662e", + "revCount": 31, "type": "git", "url": "ssh://forgejo@git.toast003.xyz:4222/Toast/nix-secrets" }, diff --git a/roles/desktop/services/networkmanager.nix b/roles/desktop/services/networkmanager.nix index a9917e3..2be85d7 100644 --- a/roles/desktop/services/networkmanager.nix +++ b/roles/desktop/services/networkmanager.nix @@ -5,8 +5,9 @@ }: let tailscaleName = config.services.tailscale.interfaceName; in { - age.secrets = { - wifiPasswords.file = "${flakeSelf.inputs.secrets}/wifi-passwords.age"; + sops.secrets.wifiPasswords = { + sopsFile = "${flakeSelf.inputs.secrets}/wifi-passwords.env"; + format = "dotenv"; }; networking.networkmanager = { enable = true; @@ -14,7 +15,7 @@ in { "interface-name:${tailscaleName}" ]; ensureProfiles = { - environmentFiles = [config.age.secrets.wifiPasswords.path]; + environmentFiles = [config.sops.secrets.wifiPasswords.path]; profiles = { "4g-modem" = { connection = { From 7277135a5bed1698b961a369a710b9fa89505f1c Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 6 Dec 2025 04:16:48 +0100 Subject: [PATCH 1098/1125] Desktop/networkManager: refactor --- lib/default.nix | 1 + lib/networkManager.nix | 18 +++++++++++++ roles/desktop/services/networkmanager.nix | 33 +++++++---------------- 3 files changed, 29 insertions(+), 23 deletions(-) create mode 100644 lib/networkManager.nix diff --git a/lib/default.nix b/lib/default.nix index 400dc18..b3febf7 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -4,5 +4,6 @@ nixpkgs.lib.extend (final: prev: { importLib = file: import file {lib = final;}; in { patches = importLib ./patches.nix; + networkManager = importLib ./networkManager.nix; }; }) diff --git a/lib/networkManager.nix b/lib/networkManager.nix new file mode 100644 index 0000000..183501b --- /dev/null +++ b/lib/networkManager.nix @@ -0,0 +1,18 @@ +{lib}: { + /** + Make a NetworkManager wifi profile, to be used with ensureProfiles + */ + mkWifiProfile = {id, ssid, priority ? 0, wifi-security}: { + connection = { + inherit id; + type = "wifi"; + autoconnect-priority = priority; + }; + ipv4.method = "auto"; + wifi = { + mode = "infrastructure"; + inherit ssid; + }; + inherit wifi-security; + }; +} diff --git a/roles/desktop/services/networkmanager.nix b/roles/desktop/services/networkmanager.nix index 2be85d7..8ba9457 100644 --- a/roles/desktop/services/networkmanager.nix +++ b/roles/desktop/services/networkmanager.nix @@ -1,5 +1,6 @@ { config, + lib, flakeSelf, ... }: let @@ -16,35 +17,21 @@ in { ]; ensureProfiles = { environmentFiles = [config.sops.secrets.wifiPasswords.path]; - profiles = { - "4g-modem" = { - connection = { - id = "4G Modem"; - type = "wifi"; - autoconnect-priority = 5; - }; - ipv4.method = "auto"; - wifi = { - mode = "infrastructure"; - ssid = "TP-Link_CCB4"; - }; + profiles = with lib.toast.networkManager; { + "4g-modem" = mkWifiProfile { + id = "4G Modem"; + priority = 5; + ssid = "TP-Link_CCB4"; wifi-security = { auth-alg = "open"; key-mgmt = "wpa-psk"; psk = "$MODEM"; }; }; - phone = { - connection = { - id = "Phone"; - type = "wifi"; - autoconnect-priority = 5; - }; - ipv4.method = "auto"; - wifi = { - mode = "infrastructure"; - ssid = "Redmi Note 10 Pro_5197"; - }; + phone = mkWifiProfile { + id = "Phone"; + priority = 5; + ssid = "Redmi Note 10 Pro_5197"; wifi-security = { auth-alg = "open"; key-mgmt = "sae"; From 1ea530a2a6e2add56d90a6fb4575f812322e0bbf Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 6 Dec 2025 04:41:12 +0100 Subject: [PATCH 1099/1125] Desktop/networkManager: add home wifi --- flake.lock | 8 ++++---- roles/desktop/services/networkmanager.nix | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 2ed2be4..dcad82e 100644 --- a/flake.lock +++ b/flake.lock @@ -524,11 +524,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1764987865, - "narHash": "sha256-9gporedK0k0t86x415hVhRdl756RsD9KUinOiuCqK4Y=", + "lastModified": 1764992299, + "narHash": "sha256-6vJ4teDUQus5TsOMfJZEfDOslsjvkhHPELZiOAeOX8s=", "ref": "refs/heads/main", - "rev": "e945330fd68c693004ffd107e89b3d8f5d5a662e", - "revCount": 31, + "rev": "5c3122fc8dd5d6fe855d7da42740272cb2c313d4", + "revCount": 32, "type": "git", "url": "ssh://forgejo@git.toast003.xyz:4222/Toast/nix-secrets" }, diff --git a/roles/desktop/services/networkmanager.nix b/roles/desktop/services/networkmanager.nix index 8ba9457..f19610b 100644 --- a/roles/desktop/services/networkmanager.nix +++ b/roles/desktop/services/networkmanager.nix @@ -38,6 +38,14 @@ in { psk = "$PHONE"; }; }; + home = mkWifiProfile { + id = "Home"; + ssid = "MOVISTAR-WIFI6-DC98"; + wifi-security = { + key-mgmt = "sae"; + psk = "$HOME"; + }; + }; }; }; }; From 351bd99fdf9896e8a44c4945ed5acf71896c30c1 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 6 Dec 2025 18:31:24 +0000 Subject: [PATCH 1100/1125] Flake: add nixpkgs patch --- flake.nix | 1 + nixpkgs-patches/revert-mangohud-update.patch | 49 ++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 nixpkgs-patches/revert-mangohud-update.patch diff --git a/flake.nix b/flake.nix index b73ccd4..5a4252c 100644 --- a/flake.nix +++ b/flake.nix @@ -104,6 +104,7 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ + ./nixpkgs-patches/revert-mangohud-update.patch ]; }; nixpkgs-patched = nixpkgs-raw.legacyPackages.x86_64-linux.applyPatches { diff --git a/nixpkgs-patches/revert-mangohud-update.patch b/nixpkgs-patches/revert-mangohud-update.patch new file mode 100644 index 0000000..067618e --- /dev/null +++ b/nixpkgs-patches/revert-mangohud-update.patch @@ -0,0 +1,49 @@ +diff --git a/pkgs/tools/graphics/mangohud/default.nix b/pkgs/tools/graphics/mangohud/default.nix +index cf83d4254baa..992afd60d3cb 100644 +--- a/pkgs/tools/graphics/mangohud/default.nix ++++ b/pkgs/tools/graphics/mangohud/default.nix +@@ -24,8 +24,10 @@ + unzip, + wayland, + libXNVCtrl, ++ nlohmann_json, + spdlog, + libxkbcommon, ++ glew, + glfw, + libXrandr, + x11Support ? true, +@@ -93,14 +95,14 @@ let + in + stdenv.mkDerivation (finalAttrs: { + pname = "mangohud"; +- version = "0.8.2"; ++ version = "0.8.1"; + + src = fetchFromGitHub { + owner = "flightlessmango"; + repo = "MangoHud"; + tag = "v${finalAttrs.version}"; + fetchSubmodules = true; +- hash = "sha256-BZ3R7D2zOlg69rx4y2FzzjpXuPOv913TOz9kSvRN+Wg="; ++ hash = "sha256-FvPhnOvcYE8vVB5R+ZRmuZxrC9U4GA338V7VAuUlHCE="; + }; + + outputs = [ +@@ -188,6 +190,7 @@ stdenv.mkDerivation (finalAttrs: { + + buildInputs = [ + dbus ++ nlohmann_json + spdlog + ] + ++ lib.optional waylandSupport wayland +@@ -195,6 +198,7 @@ stdenv.mkDerivation (finalAttrs: { + ++ lib.optional nvidiaSupport libXNVCtrl + ++ lib.optional (x11Support || waylandSupport) libxkbcommon + ++ lib.optionals mangoappSupport [ ++ glew + glfw + libXrandr + ]; + From 72c8a0e7e251effa30cef1cd76e1473f8026be76 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 7 Dec 2025 23:17:50 +0100 Subject: [PATCH 1101/1125] Server/syncthing: fix id of games folder --- roles/server/syncthing.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index ad7a1fc..b9eaf3d 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -46,7 +46,7 @@ }; "games" = { label = "Games"; - id = "jxuou-2yjnu"; + id = "mwzph-gf2df"; devices = ["steamdeck" "server" "pc" "winmax2"]; path = "${config.services.syncthing.dataDir}/games"; }; From 859a4b20a507453120d51aeae4a037e632911f12 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 8 Dec 2025 01:39:48 +0100 Subject: [PATCH 1102/1125] Common: set up default sops file --- roles/common/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index d26b350..90e4213 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -161,6 +161,7 @@ }; sops = { age.sshKeyPaths = ["/persist/id_host"]; + defaultSopsFile = "${flakeSelf.inputs.secrets}/${config.networking.hostName}.yaml"; }; catppuccin.grub.enable = true; From b668212daf66ed853f0ddef0e0b046c7bac5ae39 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 8 Dec 2025 17:51:55 +0100 Subject: [PATCH 1103/1125] Server: migrate secrets to sops --- flake.lock | 8 ++++---- roles/server/ddclient.nix | 12 +++--------- roles/server/forgejo.nix | 30 +++++++++++++----------------- roles/server/grafana.nix | 27 ++++++++++----------------- roles/server/ssh.nix | 21 +++++---------------- 5 files changed, 35 insertions(+), 63 deletions(-) diff --git a/flake.lock b/flake.lock index dcad82e..33028a8 100644 --- a/flake.lock +++ b/flake.lock @@ -524,11 +524,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1764992299, - "narHash": "sha256-6vJ4teDUQus5TsOMfJZEfDOslsjvkhHPELZiOAeOX8s=", + "lastModified": 1765212399, + "narHash": "sha256-QEjuaK17HddWr0ZBRhsg3nt4QhSxQZ1i9YO2ctV045c=", "ref": "refs/heads/main", - "rev": "5c3122fc8dd5d6fe855d7da42740272cb2c313d4", - "revCount": 32, + "rev": "43c8697580bb389aea565459802c3b9827aa2d3d", + "revCount": 38, "type": "git", "url": "ssh://forgejo@git.toast003.xyz:4222/Toast/nix-secrets" }, diff --git a/roles/server/ddclient.nix b/roles/server/ddclient.nix index d9102f9..a4dfd83 100755 --- a/roles/server/ddclient.nix +++ b/roles/server/ddclient.nix @@ -1,12 +1,6 @@ -{ - config, - flakeSelf, - ... -}: let - hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName; -in { +{config, ...}: { # Set up secrets - age.secrets = {ddclient-passwd.file = hostSecrets + "/ddclient-password.age";}; + sops.secrets.ddclientPassword = {}; services.ddclient = { enable = true; @@ -15,7 +9,7 @@ in { protocol = "namecheap"; server = "dynamicdns.park-your-domain.com"; username = "toast003.xyz"; - passwordFile = config.age.secrets.ddclient-passwd.path; + passwordFile = config.sops.secrets.ddclientPassword.path; domains = ["@"]; }; } diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index 763cce2..22dfa17 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -1,24 +1,20 @@ { config, lib, - flakeSelf, pkgs, ... -}: let - hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName + "/"; -in { - age.secrets = { - forgejo-host-key = { - file = hostSecrets + "forgejoPrivateKey.age"; - mode = "0400"; - owner = "forgejo"; - group = "forgejo"; +}: { + sops.secrets = let + owner = config.services.forgejo.user; + group = config.services.forgejo.group; + in{ + "forgejoHostKey/private" = { + inherit owner group; + name = "id_forgejo"; }; - "forgejo-host-key.pub" = { - file = hostSecrets + "forgejoPublicKey.age"; - mode = "0400"; - owner = "forgejo"; - group = "forgejo"; + "forgejoHostKey/public" = { + inherit owner group; + name = "id_forgejo.pub"; }; }; @@ -36,8 +32,8 @@ in { ROOT_URL = "https://git.toast003.xyz"; START_SSH_SERVER = true; SSH_PORT = 4222; - SSH_SERVER_HOST_KEYS = config.age.secrets.forgejo-host-key.path; - SSH_SERVER_HOST_KEY = "forgejo-host-key"; + SSH_SERVER_HOST_KEYS = config.sops.secrets."forgejoHostKey/private".path; + SSH_SERVER_HOST_KEY = "id_forgejo"; }; repository = { ENABLE_PUSH_CREATE_USER = true; diff --git a/roles/server/grafana.nix b/roles/server/grafana.nix index 957c41b..7563efb 100644 --- a/roles/server/grafana.nix +++ b/roles/server/grafana.nix @@ -1,23 +1,16 @@ -{ - config, - flakeSelf, - ... -}: let +{config, ...}: let domain = "monitoring.everest.tailscale"; in { users.users.caddy.extraGroups = ["grafana"]; - age.secrets = let - hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName + "/"; + sops.secrets = let + owner = "grafana"; + group = "grafana"; in { - grafanaAdminName = { - file = hostSecrets + "grafana/admin_name.age"; - owner = "grafana"; - group = "grafana"; + "grafanaAdmin/username" = { + inherit owner group; }; - grafanaAdminPassword = { - file = hostSecrets + "grafana/admin_password.age"; - owner = "grafana"; - group = "grafana"; + "grafanaAdmin/password" = { + inherit owner group; }; }; services = { @@ -34,8 +27,8 @@ in { settings = { analytics.reporting_enabled = false; security = { - admin_user = "$__file{${config.age.secrets.grafanaAdminName.path}}"; - admin_password = "$__file{${config.age.secrets.grafanaAdminPassword.path}}"; + admin_user = "$__file{${config.sops.secrets."grafanaAdmin/username".path}}"; + admin_password = "$__file{${config.sops.secrets."grafanaAdmin/password".path}}"; cookie_secure = true; strict_transport_security = true; content_security_policy = true; diff --git a/roles/server/ssh.nix b/roles/server/ssh.nix index e4d0da1..7907dee 100755 --- a/roles/server/ssh.nix +++ b/roles/server/ssh.nix @@ -1,11 +1,9 @@ { - flakeSelf, config, pkgs, lib, ... }: let - hostSecrets = "${flakeSelf.inputs.secrets}/" + config.networking.hostName + "/"; hostKeyPath = "/etc/ssh/everest_host_key"; notify = pkgs.writers.writePython3 "send-discord-login-notification" { @@ -16,7 +14,7 @@ if os.environ["PAM_TYPE"] != "open_session": raise SystemExit - secretPath = "${config.age.secrets.discord-webhook.path}" + secretPath = "${config.sops.secrets.discordWebhook.path}" webhookUrl: str @@ -34,19 +32,10 @@ result = requests.post(webhookUrl, json=data) ''; in { - age.secrets = { - everest-host-key = { - file = hostSecrets + "host-private-key.age"; - path = hostKeyPath; - mode = "0400"; - }; - "everest-host-key.pub" = { - file = hostSecrets + "host-public-key.age"; - path = hostKeyPath + ".pub"; - }; - discord-webhook = { - file = hostSecrets + "discord-webhook.age"; - }; + sops.secrets = { + discordWebhook = {}; + "hostKey/private".path = "${hostKeyPath}.pub"; + "hostKey/public".path = hostKeyPath; }; users.users.toast.openssh.authorizedKeys.keys = [ From 4e9a1dae7273394ecd00e8e00dcdc2f549299d68 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 9 Dec 2025 19:17:41 +0100 Subject: [PATCH 1104/1125] Server/ssh: write ssh keys to correct locations --- roles/server/ssh.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/server/ssh.nix b/roles/server/ssh.nix index 7907dee..66e163d 100755 --- a/roles/server/ssh.nix +++ b/roles/server/ssh.nix @@ -34,8 +34,8 @@ in { sops.secrets = { discordWebhook = {}; - "hostKey/private".path = "${hostKeyPath}.pub"; - "hostKey/public".path = hostKeyPath; + "hostKey/public".path = "${hostKeyPath}.pub"; + "hostKey/private".path = hostKeyPath; }; users.users.toast.openssh.authorizedKeys.keys = [ From 03f05703429bc1dde9644e7f2b7d7b8dec16e167 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 4 Oct 2025 22:51:59 +0200 Subject: [PATCH 1105/1125] Machines/WinMax2: remove jovian I basically didn't use it, and it just caused more issues than anything --- flake.nix | 1 - machines/WinMax2/configuration.nix | 17 +---------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/flake.nix b/flake.nix index 5a4252c..0482568 100644 --- a/flake.nix +++ b/flake.nix @@ -221,7 +221,6 @@ ./roles/gaming ]; WinMax2.modules = [ - jovian.nixosModules.default nixos-hardware.nixosModules.gpd-win-max-2-2023 ./roles/desktop ./roles/kde diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index 9a7940f..bdcd084 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -72,22 +72,7 @@ xserver.xkb.layout = lib.mkForce "us"; }; - jovian = { - # Steam Deck UI settings - steam = { - enable = true; - autoStart = false; - user = "toast"; - desktopSession = "plasma"; - }; - hardware.amd.gpu.enableBacklightControl = true; - decky-loader = { - enable = true; - package = pkgs.decky-loader-prerelease; - }; - }; - - # Enable bluetooth + # Enable bluetooth hardware.bluetooth = { enable = true; }; From 76ecdba67e998d9d828987a84a591d035a28814d Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 13 Dec 2025 00:36:30 +0100 Subject: [PATCH 1106/1125] Machines/Everest: wait for DNS to be available --- machines/Everest/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/machines/Everest/configuration.nix b/machines/Everest/configuration.nix index b183d34..4db3273 100755 --- a/machines/Everest/configuration.nix +++ b/machines/Everest/configuration.nix @@ -34,6 +34,7 @@ }; nameservers = ["9.9.9.9"]; }; + systemd.network.wait-online.extraArgs = ["--dns"]; time.timeZone = "Europe/Madrid"; services.automatic-timezoned.enable = lib.mkForce false; From 9be3caddbc5ffbb06240345ce47913d19cd1836f Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 10 Dec 2025 12:30:14 +0100 Subject: [PATCH 1107/1125] Common: set up a default time zone --- roles/common/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 90e4213..833e241 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -97,7 +97,7 @@ }; # Set up time zone. - # time.timeZone = "Europe/Madrid"; + time.timeZone = lib.mkDefault "Europe/Madrid"; services.automatic-timezoned.enable = true; nixpkgs.overlays = [ From 83831f6a755e43e8228eabfaa3a0b704b3a78697 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 10 Dec 2025 20:00:36 +0100 Subject: [PATCH 1108/1125] Common: append -iso to the variant id if building an iso --- roles/common/configuration.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 833e241..f51dacc 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -178,6 +178,9 @@ stateVersion = "25.05"; # Nix on nixos 23.05 does not have dirtyRev configurationRevision = flakeSelf.sourceInfo.rev or flakeSelf.sourceInfo.dirtyRev or "dirty"; - nixos.variant_id = lib.strings.toLower config.networking.hostName; + nixos.variant_id = lib.mkDefault (lib.strings.toLower config.networking.hostName); + }; + image.modules.iso = { + system.nixos.variant_id = "${lib.strings.toLower config.networking.hostName}-iso"; }; } From d7c245ed8ea91b50c9720b6651583f7fa127e2b6 Mon Sep 17 00:00:00 2001 From: Toast Date: Thu, 11 Dec 2025 02:03:09 +0100 Subject: [PATCH 1109/1125] Desktop: install tetrio --- roles/desktop/configuration.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/roles/desktop/configuration.nix b/roles/desktop/configuration.nix index 351893c..048f8e6 100644 --- a/roles/desktop/configuration.nix +++ b/roles/desktop/configuration.nix @@ -23,6 +23,9 @@ pkgs.noto-fonts-cjk-serif ]; + # Already use electron apps (discord) so this only adds 20 mb more + environment.systemPackages = [pkgs.tetrio-desktop]; + hardware.keyboard.qmk.enable = true; home-manager.users.toast.home.packages = [pkgs.qmk]; From 3f0333b4a098ddb882613569999e4366bedf0991 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 12 Dec 2025 05:12:02 +0100 Subject: [PATCH 1110/1125] Kde/patches: add more patches --- roles/kde/patches/plasma-desktop/patches.txt | 1 + roles/kde/patches/plasma-desktop/pr3356.patch | 37 +++++ roles/kde/patches/spectacle/patches.txt | 3 + roles/kde/patches/spectacle/pr493.patch | 129 ++++++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 roles/kde/patches/plasma-desktop/pr3356.patch create mode 100644 roles/kde/patches/spectacle/pr493.patch diff --git a/roles/kde/patches/plasma-desktop/patches.txt b/roles/kde/patches/plasma-desktop/patches.txt index 50ee310..84f4a14 100644 --- a/roles/kde/patches/plasma-desktop/patches.txt +++ b/roles/kde/patches/plasma-desktop/patches.txt @@ -3,3 +3,4 @@ Plasma 6.6.0: Pr 3256 https://invent.kde.org/plasma/plasma-desktop/-/merge_requests/3256 Pr 3259 https://invent.kde.org/plasma/plasma-desktop/-/merge_requests/3259 Pr 3269 https://invent.kde.org/plasma/plasma-desktop/-/merge_requests/3269 +Pr 3356 https://invent.kde.org/plasma/plasma-desktop/-/merge_requests/3356 diff --git a/roles/kde/patches/plasma-desktop/pr3356.patch b/roles/kde/patches/plasma-desktop/pr3356.patch new file mode 100644 index 0000000..3d47aca --- /dev/null +++ b/roles/kde/patches/plasma-desktop/pr3356.patch @@ -0,0 +1,37 @@ +From 04c747a41d8c01248c7baeec5c852c2298f76fc3 Mon Sep 17 00:00:00 2001 +From: Christoph Wolk +Date: Mon, 1 Dec 2025 14:36:09 +0100 +Subject: [PATCH] applets/kickoff: also close when triggering from footer menu + +Kickoff already closes when one of the power/session buttons from the +menu is pressed, but the same does not happen if the same action is +shown in the overflow menu. + +Instead, also close kickoff in that case. + +CCBUG: 508725 +--- + applets/kickoff/LeaveButtons.qml | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/applets/kickoff/LeaveButtons.qml b/applets/kickoff/LeaveButtons.qml +index c9a14dc3254..acf83639341 100644 +--- a/applets/kickoff/LeaveButtons.qml ++++ b/applets/kickoff/LeaveButtons.qml +@@ -214,7 +214,12 @@ RowLayout { + + text: model.display + icon: model.decoration +- onClicked: filteredMenuItemsModel.trigger(index) ++ onClicked: { ++ filteredMenuItemsModel.trigger(index) ++ if (kickoff.hideOnWindowDeactivate) { ++ kickoff.expanded = false; ++ } ++ } + } + onObjectAdded: (index, object) => contextMenu.addMenuItem(object) + onObjectRemoved: (index, object) => contextMenu.removeMenuItem(object) +-- +GitLab + diff --git a/roles/kde/patches/spectacle/patches.txt b/roles/kde/patches/spectacle/patches.txt index 34909b4..e11d502 100644 --- a/roles/kde/patches/spectacle/patches.txt +++ b/roles/kde/patches/spectacle/patches.txt @@ -1,2 +1,5 @@ Pr 462 https://invent.kde.org/plasma/spectacle/-/merge_requests/462 Pr 487 https://invent.kde.org/plasma/spectacle/-/merge_requests/487 + +Plasma 6.6.0: +Pr 493 https://invent.kde.org/plasma/spectacle/-/merge_requests/493 diff --git a/roles/kde/patches/spectacle/pr493.patch b/roles/kde/patches/spectacle/pr493.patch new file mode 100644 index 0000000..d6db2f7 --- /dev/null +++ b/roles/kde/patches/spectacle/pr493.patch @@ -0,0 +1,129 @@ +From 49c615c1989d9fcfce7ed1be805538a9dca6a8a8 Mon Sep 17 00:00:00 2001 +From: Taras Oleksyn +Date: Sat, 29 Nov 2025 10:17:28 +0200 +Subject: [PATCH] Add cancel button to capture window to improve touchscreen + usability + +BUG: 490980 +--- + src/CMakeLists.txt | 1 + + src/Gui/CancelAction.qml | 11 +++++++++++ + src/Gui/CaptureOverlay.qml | 14 ++++++++++++++ + src/Gui/CaptureWindow.cpp | 5 +++++ + src/Gui/CaptureWindow.h | 1 + + src/PlasmaVersion.h | 2 +- + 6 files changed, 33 insertions(+), 1 deletion(-) + create mode 100644 src/Gui/CancelAction.qml + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 23fc4f483..f4957bda7 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -158,6 +158,7 @@ qt_target_qml_sources(spectacle + Gui/AnnotationOptionsToolBarContents.qml + Gui/AnnotationsToolBarContents.qml + Gui/ButtonGrid.qml ++ Gui/CancelAction.qml + Gui/CaptureModeButtonsColumn.qml + Gui/CaptureOptions.qml + Gui/CaptureOverlay.qml +diff --git a/src/Gui/CancelAction.qml b/src/Gui/CancelAction.qml +new file mode 100644 +index 000000000..74bf54816 +--- /dev/null ++++ b/src/Gui/CancelAction.qml +@@ -0,0 +1,11 @@ ++/* SPDX-FileCopyrightText: 2025 Noah Davis ++ * SPDX-License-Identifier: LGPL-2.0-or-later ++ */ ++ ++import QtQuick.Templates as T ++ ++T.Action { ++ icon.name: "dialog-cancel" ++ text: i18nc("@action cancel selection", "Cancel") ++ onTriggered: contextWindow.cancel() ++} +diff --git a/src/Gui/CaptureOverlay.qml b/src/Gui/CaptureOverlay.qml +index e5089934d..5c15d9939 100644 +--- a/src/Gui/CaptureOverlay.qml ++++ b/src/Gui/CaptureOverlay.qml +@@ -491,6 +491,11 @@ MouseArea { + visible: action.enabled + action: AcceptAction {} + } ++ ToolButton { ++ display: TtToolButton.TextBesideIcon ++ visible: action.enabled ++ action: CancelAction {} ++ } + ToolButton { + display: TtToolButton.IconOnly + visible: action.enabled +@@ -527,6 +532,10 @@ MouseArea { + visible: action.enabled + action: AcceptAction {} + } ++ ToolButton { ++ visible: action.enabled ++ action: CancelAction {} ++ } + ToolButton { + visible: action.enabled + action: SaveAction {} +@@ -560,6 +569,11 @@ MouseArea { + visible: action.enabled + action: RecordAction {} + } ++ ToolButton { ++ display: TtToolButton.TextBesideIcon ++ visible: action.enabled ++ action: CancelAction {} ++ } + } + } + +diff --git a/src/Gui/CaptureWindow.cpp b/src/Gui/CaptureWindow.cpp +index cb8ce97ab..c263d1b45 100644 +--- a/src/Gui/CaptureWindow.cpp ++++ b/src/Gui/CaptureWindow.cpp +@@ -129,6 +129,11 @@ bool CaptureWindow::accept() + return SelectionEditor::instance()->acceptSelection(); + } + ++void CaptureWindow::cancel() ++{ ++ SpectacleCore::instance()->cancelScreenshot(); ++} ++ + void CaptureWindow::save() + { + SelectionEditor::instance()->acceptSelection(ExportManager::Save | ExportManager::UserAction); +diff --git a/src/Gui/CaptureWindow.h b/src/Gui/CaptureWindow.h +index b5e87a834..0d50aac90 100644 +--- a/src/Gui/CaptureWindow.h ++++ b/src/Gui/CaptureWindow.h +@@ -34,6 +34,7 @@ public: + + public Q_SLOTS: + bool accept(); ++ void cancel(); + void save() override; + void saveAs() override; + void copyImage() override; +diff --git a/src/PlasmaVersion.h b/src/PlasmaVersion.h +index 08502c895..9518da62b 100644 +--- a/src/PlasmaVersion.h ++++ b/src/PlasmaVersion.h +@@ -15,7 +15,7 @@ public: + static quint32 get(); + + /** +- * Use this for plasama versions the same way you'd use QT_VERSION_CHECK() ++ * Use this for plasma versions the same way you'd use QT_VERSION_CHECK() + */ + static quint32 check(quint8 major, quint8 minor, quint8 patch); + +-- +GitLab + From 04163b2c793de667d6d1487b7b88d2bf1de1967f Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 13 Dec 2025 16:27:24 +0100 Subject: [PATCH 1111/1125] Common/kmscon: enable --- roles/common/services/default.nix | 1 + roles/common/services/kmscon.nix | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 roles/common/services/kmscon.nix diff --git a/roles/common/services/default.nix b/roles/common/services/default.nix index 960410b..6640381 100644 --- a/roles/common/services/default.nix +++ b/roles/common/services/default.nix @@ -3,5 +3,6 @@ ./avahi.nix ./tailscale.nix ./syncthing.nix + ./kmscon.nix ]; } diff --git a/roles/common/services/kmscon.nix b/roles/common/services/kmscon.nix new file mode 100644 index 0000000..dbd31be --- /dev/null +++ b/roles/common/services/kmscon.nix @@ -0,0 +1,29 @@ +{pkgs, ...}: { + services.kmscon = { + enable = true; + useXkbConfig = true; + fonts = [ + { + name = "JetBrains Mono Nerd Font"; + package = pkgs.nerd-fonts.jetbrains-mono; + } + ]; + extraConfig = '' + term=xterm-256color + font-size=10 + ''; + package = pkgs.kmscon.overrideAttrs (old: { + patches = + old.patches + ++ [ + # https://github.com/kmscon/kmscon/issues/133 + ( + pkgs.fetchpatch { + url = "https://github.com/Aetf/kmscon/pull/135.patch"; + hash = "sha256-hJrKkONdQmz9gGMXbk11+4MF8Vn4guE3Bl1Ni6SGDw4="; + } + ) + ]; + }); + }; +} From e863aea052649c39f96d6b9cdec2a60c120bf5d5 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 14 Dec 2025 01:07:21 +0100 Subject: [PATCH 1112/1125] Run formatter --- lib/networkManager.nix | 35 +++++++++++++++++------------- machines/WinMax2/configuration.nix | 2 +- roles/server/endlessh.nix | 2 +- roles/server/forgejo.nix | 2 +- roles/server/minecraft.nix | 2 +- roles/server/prometheus.nix | 12 +++++----- roles/server/transmission.nix | 6 ++++- 7 files changed, 36 insertions(+), 25 deletions(-) diff --git a/lib/networkManager.nix b/lib/networkManager.nix index 183501b..b4bfbfe 100644 --- a/lib/networkManager.nix +++ b/lib/networkManager.nix @@ -1,18 +1,23 @@ {lib}: { - /** + /** Make a NetworkManager wifi profile, to be used with ensureProfiles - */ - mkWifiProfile = {id, ssid, priority ? 0, wifi-security}: { - connection = { - inherit id; - type = "wifi"; - autoconnect-priority = priority; - }; - ipv4.method = "auto"; - wifi = { - mode = "infrastructure"; - inherit ssid; - }; - inherit wifi-security; - }; + */ + mkWifiProfile = { + id, + ssid, + priority ? 0, + wifi-security, + }: { + connection = { + inherit id; + type = "wifi"; + autoconnect-priority = priority; + }; + ipv4.method = "auto"; + wifi = { + mode = "infrastructure"; + inherit ssid; + }; + inherit wifi-security; + }; } diff --git a/machines/WinMax2/configuration.nix b/machines/WinMax2/configuration.nix index bdcd084..81f0f44 100755 --- a/machines/WinMax2/configuration.nix +++ b/machines/WinMax2/configuration.nix @@ -72,7 +72,7 @@ xserver.xkb.layout = lib.mkForce "us"; }; - # Enable bluetooth + # Enable bluetooth hardware.bluetooth = { enable = true; }; diff --git a/roles/server/endlessh.nix b/roles/server/endlessh.nix index 6c56997..b4dcfaa 100755 --- a/roles/server/endlessh.nix +++ b/roles/server/endlessh.nix @@ -1,4 +1,4 @@ -{config,...}: { +{config, ...}: { # I prefer using the go implementation services.endlessh-go = { enable = true; diff --git a/roles/server/forgejo.nix b/roles/server/forgejo.nix index 22dfa17..95210c4 100644 --- a/roles/server/forgejo.nix +++ b/roles/server/forgejo.nix @@ -7,7 +7,7 @@ sops.secrets = let owner = config.services.forgejo.user; group = config.services.forgejo.group; - in{ + in { "forgejoHostKey/private" = { inherit owner group; name = "id_forgejo"; diff --git a/roles/server/minecraft.nix b/roles/server/minecraft.nix index 138c379..9985df0 100644 --- a/roles/server/minecraft.nix +++ b/roles/server/minecraft.nix @@ -95,5 +95,5 @@ in { UMask = "0077"; }; }; - programs.rust-motd.settings.service_status."Minecraft (SkyFactory 5)"= "minecraft-server-sf5"; + programs.rust-motd.settings.service_status."Minecraft (SkyFactory 5)" = "minecraft-server-sf5"; } diff --git a/roles/server/prometheus.nix b/roles/server/prometheus.nix index 999d9c6..fb32f05 100644 --- a/roles/server/prometheus.nix +++ b/roles/server/prometheus.nix @@ -22,10 +22,12 @@ ]; }; services.grafana.provision = { - datasources.settings.datasources = [{ - name = "Prometheus"; - type = "prometheus"; - url = "http://127.0.0.1:${builtins.toString config.services.prometheus.port}"; - }]; + datasources.settings.datasources = [ + { + name = "Prometheus"; + type = "prometheus"; + url = "http://127.0.0.1:${builtins.toString config.services.prometheus.port}"; + } + ]; }; } diff --git a/roles/server/transmission.nix b/roles/server/transmission.nix index a6e7e3c..ce18dbd 100755 --- a/roles/server/transmission.nix +++ b/roles/server/transmission.nix @@ -1,4 +1,8 @@ -{config, pkgs, ...}: let +{ + config, + pkgs, + ... +}: let transmissionUid = toString config.users.users.transmission.uid; transmissionGid = toString config.users.groups.transmission.gid; mountPoint = config.fileSystems."nfs_transmission".mountPoint; From d8f281200351758c62ddff1edc2991d44092d868 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 13 Dec 2025 15:24:18 +0100 Subject: [PATCH 1113/1125] Server/caddy: wait for tailscale ip before starting --- roles/server/caddy.nix | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/roles/server/caddy.nix b/roles/server/caddy.nix index 6542295..14ef62a 100644 --- a/roles/server/caddy.nix +++ b/roles/server/caddy.nix @@ -11,6 +11,19 @@ file_server browse root * /srv/dl/ ''; + script = pkgs.writeShellApplication { + name = "wait-for-tailscale-ip"; + runtimeInputs = [pkgs.iproute2]; + text = '' + # Based on https://github.com/tailscale/tailscale/issues/11504#issuecomment-2113331262 + echo Waiting for tailscale0 to get an IP adress.. + for i in {1..300}; do + if ip addr show dev tailscale0 | grep -q 'inet '; then break; fi + echo "Waiting $i/240 seconds" + sleep 1 + done + ''; + }; in { services.caddy = { enable = true; @@ -71,6 +84,7 @@ in { # in too little time services.caddy.serviceConfig.RestartSec = lib.mkForce "120s"; services.caddy.unitConfig.StartLimitBurst = lib.mkForce "infinity"; + services.caddy.preStart = "${script}/bin/wait-for-tailscale-ip"; }; programs.rust-motd.settings.service_status.Caddy = "caddy"; networking.firewall.allowedTCPPorts = [443 80]; From 2d801ae06a12b83fb9a33bc31baf3324d754c7a1 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 14 Dec 2025 02:16:23 +0100 Subject: [PATCH 1114/1125] Server/ssh: only allow toast user --- roles/server/ssh.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/ssh.nix b/roles/server/ssh.nix index 66e163d..33694c3 100755 --- a/roles/server/ssh.nix +++ b/roles/server/ssh.nix @@ -48,6 +48,7 @@ in { UseDns = true; PermitRootLogin = "no"; PasswordAuthentication = false; + AllowUsers = ["toast"]; }; # The forgejo module is fucky so I can't set this with the nixos option # https://github.com/NixOS/nixpkgs/issues/306205 From 4828dc5a2100dbb685a97220d3b0830e04810b6c Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 14 Dec 2025 02:18:31 +0100 Subject: [PATCH 1115/1125] Server: add borg repos --- roles/server/borg.nix | 18 ++++++++++++++++++ roles/server/default.nix | 1 + 2 files changed, 19 insertions(+) create mode 100644 roles/server/borg.nix diff --git a/roles/server/borg.nix b/roles/server/borg.nix new file mode 100644 index 0000000..1c8817d --- /dev/null +++ b/roles/server/borg.nix @@ -0,0 +1,18 @@ +{...}: { + services.borgbackup = { + repos = { + backups = { + allowSubRepos = true; + authorizedKeys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEMtbHUcYanH/guWaKNjGr/IGa8gvI/xRTcNAI9yXhnK BorgBackup backups key" + ]; + }; + }; + }; + services.openssh.settings = { + AllowUsers = [ + "borg@*.tailscale" + "borg@192.168.1.0/24" + ]; + }; +} diff --git a/roles/server/default.nix b/roles/server/default.nix index 6ffed7e..8bdf5dc 100755 --- a/roles/server/default.nix +++ b/roles/server/default.nix @@ -14,6 +14,7 @@ ./headscale.nix ./caddy.nix ./rust_motd.nix + ./borg.nix ./adguard.nix ./grafana.nix ./prometheus.nix From 9f53c984f4ba97a6442d05abc6f57591c6dd1261 Mon Sep 17 00:00:00 2001 From: Toast Date: Sun, 14 Dec 2025 21:33:40 +0100 Subject: [PATCH 1116/1125] Server/borg: allow connections from localhost --- roles/server/borg.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/server/borg.nix b/roles/server/borg.nix index 1c8817d..d69af2f 100644 --- a/roles/server/borg.nix +++ b/roles/server/borg.nix @@ -13,6 +13,7 @@ AllowUsers = [ "borg@*.tailscale" "borg@192.168.1.0/24" + "borg@localhost" ]; }; } From 15149a7968c314b994b0655fcccadd2839440e40 Mon Sep 17 00:00:00 2001 From: Toast Date: Mon, 15 Dec 2025 09:53:02 +0100 Subject: [PATCH 1117/1125] Server/syncthing: remove school things folder --- roles/server/syncthing.nix | 6 ------ 1 file changed, 6 deletions(-) diff --git a/roles/server/syncthing.nix b/roles/server/syncthing.nix index b9eaf3d..c45a7ae 100755 --- a/roles/server/syncthing.nix +++ b/roles/server/syncthing.nix @@ -32,12 +32,6 @@ devices = ["steamdeck" "server" "pc" "winmax2"]; path = "${config.services.syncthing.dataDir}/pcsx2"; }; - "school-things" = { - label = "School things"; - id = "btsth-vdu9c"; - devices = ["server" "pc" "winmax2"]; - path = "${config.services.syncthing.dataDir}/school-things"; - }; "project-eden-saves" = { label = "Project Eden saves"; id = "xa3qx-3ax5k"; From e8af5123707c749deb80b90825e7b3bdc2dc82fa Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Dec 2025 00:15:17 +0100 Subject: [PATCH 1118/1125] Desktop/distrobox: enable --- roles/desktop/programs/default.nix | 1 + roles/desktop/programs/distrobox.nix | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 roles/desktop/programs/distrobox.nix diff --git a/roles/desktop/programs/default.nix b/roles/desktop/programs/default.nix index 42fe870..1e2eac3 100755 --- a/roles/desktop/programs/default.nix +++ b/roles/desktop/programs/default.nix @@ -10,5 +10,6 @@ ./mpv.nix ./sysdvr-qt.nix ./spotify.nix + ./distrobox.nix ]; } diff --git a/roles/desktop/programs/distrobox.nix b/roles/desktop/programs/distrobox.nix new file mode 100644 index 0000000..4e594a4 --- /dev/null +++ b/roles/desktop/programs/distrobox.nix @@ -0,0 +1,11 @@ +{...}: { + virtualisation.podman = { + # Due to limitations with home-manager, podman has to be available system wide + enable = true; + }; + home-manager.users.toast = { + programs.distrobox = { + enable = true; + }; + }; +} From fa8efef26ac0a400d84c66ff1cc3deda9ed27f87 Mon Sep 17 00:00:00 2001 From: Toast Date: Tue, 16 Dec 2025 23:54:08 +0100 Subject: [PATCH 1119/1125] Programs/distrobox: add container --- roles/desktop/programs/distrobox.nix | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/roles/desktop/programs/distrobox.nix b/roles/desktop/programs/distrobox.nix index 4e594a4..6de5db5 100644 --- a/roles/desktop/programs/distrobox.nix +++ b/roles/desktop/programs/distrobox.nix @@ -6,6 +6,23 @@ home-manager.users.toast = { programs.distrobox = { enable = true; + containers = { + uav = { + image = "quay.io/toolbx/ubuntu-toolbox:24.04"; + # additional_packages = "lsb-release dmidecode git"; + additional_packages = "git"; + init_hooks = [ + "git clone https://github.com/PX4/PX4-Autopilot.git --recursive /tmp/px4" + "cd /tmp/px4/Tools/setup/" + # The install scripts wants to add things to .bashrc, so it errors out + # This removes the line that does that + "sed -i '181d' ubuntu.sh" + "bash ubuntu.sh" + "rm -rf /tmp/px4 --one-file-system" + ]; + entry = true; + }; + }; }; }; } From 0d0d6ebb56c960ea571724e160847015652db0d1 Mon Sep 17 00:00:00 2001 From: Toast Date: Wed, 17 Dec 2025 03:11:42 +0100 Subject: [PATCH 1120/1125] Machines/Archie: mount hard drive --- machines/Archie/hardware-configuration.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/machines/Archie/hardware-configuration.nix b/machines/Archie/hardware-configuration.nix index 8ce6999..cb7bd98 100644 --- a/machines/Archie/hardware-configuration.nix +++ b/machines/Archie/hardware-configuration.nix @@ -54,6 +54,12 @@ fsType = config.fileSystems."/".fsType; options = ["subvolid=5" "ro"]; }; + "/mnt/hdd" = { + # device = "/dev/disk/by-id/ata-SAMSUNG_HD103SI_S1Y5J9CZA19763-part1"; + label = "Archie\\x20HDD"; + fsType = "bcachefs"; + options = ["x-systemd.automount"]; + }; "/mnt/windows" = { device = "/dev/disk/by-uuid/B61AFDAC1AFD6A2F"; fsType = "ntfs3"; From 27babd819ce35e79c2bed2a1c8635d5ec00df935 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Dec 2025 00:51:56 +0100 Subject: [PATCH 1121/1125] Flake: update lock file --- flake.lock | 80 +++++++++++++++++----------------- flake.nix | 1 + nixpkgs-patches/pr471291.patch | 61 ++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 40 deletions(-) create mode 100644 nixpkgs-patches/pr471291.patch diff --git a/flake.lock b/flake.lock index 33028a8..1e733a2 100644 --- a/flake.lock +++ b/flake.lock @@ -28,11 +28,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1764885363, - "narHash": "sha256-P6UHmw6enwxmP5wP4Lv722+tgpq1PFDAPAdtj7l/16U=", + "lastModified": 1765990358, + "narHash": "sha256-l8x0gU8mnYaGMl+gWrsSHKBJlZWD8KXJfHTkRlFiPI0=", "owner": "catppuccin", "repo": "nix", - "rev": "95042630028d613080393e0f03c694b77883c7db", + "rev": "de1b60ca45a578f59f7d84c8d338b346017b2161", "type": "github" }, "original": { @@ -65,11 +65,11 @@ ] }, "locked": { - "lastModified": 1764870617, - "narHash": "sha256-Og3V5eIMzmxOnCoVIJD5Xpz7X9OBevdHBJqSoNwV/Ig=", + "lastModified": 1766045858, + "narHash": "sha256-lsbdHVSc5EB2+XgKDbeG1DjLLY5DnzlKQIPV0uQu/bQ=", "owner": "9001", "repo": "copyparty", - "rev": "fa918228d56e1384e77adc193c4bd26356f6bd18", + "rev": "0e6b167167eaf04036df8576f1ea96bc116ea951", "type": "github" }, "original": { @@ -81,11 +81,11 @@ "eza-themes": { "flake": false, "locked": { - "lastModified": 1760304074, - "narHash": "sha256-qEC7H9/ghnjkwmMZ788TSgS9ysyIfD+3NHCjxq0Dps0=", + "lastModified": 1765813820, + "narHash": "sha256-WcwzKm2mi/tyA+zZCpyvTdrOrZ1R1ENA3t622SGzFas=", "owner": "eza-community", "repo": "eza-themes", - "rev": "c03051f67e84110fbae91ab7cbc377b3460f035c", + "rev": "1239cb1dd23fa8b70865550db77701b164a53cde", "type": "github" }, "original": { @@ -203,11 +203,11 @@ ] }, "locked": { - "lastModified": 1764872372, - "narHash": "sha256-uZuXRz9CzeCHsRbc2MQvKomwoX6GcFC5BUMEk3ouSFU=", + "lastModified": 1765980955, + "narHash": "sha256-rB45jv4uwC90vM9UZ70plfvY/2Kdygs+zlQ07dGQFk4=", "owner": "nix-community", "repo": "home-manager", - "rev": "05a56dbf24f195c62286e3273a2671d3b4904b00", + "rev": "89c9508bbe9b40d36b3dc206c2483ef176f15173", "type": "github" }, "original": { @@ -223,11 +223,11 @@ ] }, "locked": { - "lastModified": 1764866045, - "narHash": "sha256-0GsEtXV9OquDQ1VclQfP16cU5VZh7NEVIOjSH4UaJuM=", + "lastModified": 1765979862, + "narHash": "sha256-/r9/1KamvbHJx6I40H4HsSXnEcBAkj46ZwibhBx9kg0=", "owner": "nix-community", "repo": "home-manager", - "rev": "f63d0fe9d81d36e5fc95497217a72e02b8b7bcab", + "rev": "d3135ab747fd9dac250ffb90b4a7e80634eacbe9", "type": "github" }, "original": { @@ -245,11 +245,11 @@ ] }, "locked": { - "lastModified": 1764746434, - "narHash": "sha256-6ymFuw+Z1C90ezf8H0BP3c2JFZhJYwMq31px2StwWHU=", + "lastModified": 1766067735, + "narHash": "sha256-cRC/rOYRtZNzc5y9nTccozyo/mkI4/1eFE33Aqgs+SQ=", "owner": "Jovian-Experiments", "repo": "Jovian-NixOS", - "rev": "b4c0b604148adacf119b89824ed26df8926ce42c", + "rev": "34a16089be30f77ac9444907ec97c02b4b711896", "type": "github" }, "original": { @@ -261,11 +261,11 @@ "lix": { "flake": false, "locked": { - "lastModified": 1764846683, - "narHash": "sha256-wW+hjhr2/rUTVAs8VM5Oq8hkT6HZ4zEnaiwYI1VPGDk=", - "rev": "8f5bf1e90556e0cdbee7899a7bee51b6ef76fc94", + "lastModified": 1765883751, + "narHash": "sha256-clrWX/t2swPGBVs50Yegq2HK3q5bbwOt3kWMsL7JIZM=", + "rev": "fc0073f54095f15ee272621d4746eb9f40946385", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/8f5bf1e90556e0cdbee7899a7bee51b6ef76fc94.tar.gz?rev=8f5bf1e90556e0cdbee7899a7bee51b6ef76fc94" + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/fc0073f54095f15ee272621d4746eb9f40946385.tar.gz?rev=fc0073f54095f15ee272621d4746eb9f40946385" }, "original": { "type": "tarball", @@ -378,11 +378,11 @@ ] }, "locked": { - "lastModified": 1764475780, - "narHash": "sha256-77jL5H5x51ksLiOUDjY0ZK8e2T4ZXLhj3ap8ETvknWI=", + "lastModified": 1765267181, + "narHash": "sha256-d3NBA9zEtBu2JFMnTBqWj7Tmi7R5OikoU2ycrdhQEws=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "5a3ff8c1a09003f399f43d5742d893c0b1ab8af0", + "rev": "82befcf7dc77c909b0f2a09f5da910ec95c5b78f", "type": "github" }, "original": { @@ -398,11 +398,11 @@ ] }, "locked": { - "lastModified": 1764475780, - "narHash": "sha256-77jL5H5x51ksLiOUDjY0ZK8e2T4ZXLhj3ap8ETvknWI=", + "lastModified": 1765267181, + "narHash": "sha256-d3NBA9zEtBu2JFMnTBqWj7Tmi7R5OikoU2ycrdhQEws=", "owner": "Mic92", "repo": "nix-index-database", - "rev": "5a3ff8c1a09003f399f43d5742d893c0b1ab8af0", + "rev": "82befcf7dc77c909b0f2a09f5da910ec95c5b78f", "type": "github" }, "original": { @@ -429,11 +429,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1764667669, - "narHash": "sha256-7WUCZfmqLAssbDqwg9cUDAXrSoXN79eEEq17qhTNM/Y=", + "lastModified": 1763966396, + "narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "418468ac9527e799809c900eda37cbff999199b6", + "rev": "5ae3b07d8d6527c42f17c876e404993199144b6a", "type": "github" }, "original": { @@ -445,11 +445,11 @@ }, "nixpkgs-raw": { "locked": { - "lastModified": 1764677808, - "narHash": "sha256-H3lC7knbXOBrHI9hITQ7modLuX20mYJVhZORL5ioms0=", + "lastModified": 1765838191, + "narHash": "sha256-m5KWt1nOm76ILk/JSCxBM4MfK3rYY7Wq9/TZIIeGnT8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1aab89277eb2d87823d5b69bae631a2496cff57a", + "rev": "c6f52ebd45e5925c188d1a20119978aa4ffd5ef6", "type": "github" }, "original": { @@ -460,11 +460,11 @@ }, "nixpkgs-unstable-raw": { "locked": { - "lastModified": 1764667669, - "narHash": "sha256-7WUCZfmqLAssbDqwg9cUDAXrSoXN79eEEq17qhTNM/Y=", + "lastModified": 1765779637, + "narHash": "sha256-KJ2wa/BLSrTqDjbfyNx70ov/HdgNBCBBSQP3BIzKnv4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "418468ac9527e799809c900eda37cbff999199b6", + "rev": "1306659b587dc277866c7b69eb97e5f07864d8c4", "type": "github" }, "original": { @@ -544,11 +544,11 @@ ] }, "locked": { - "lastModified": 1764483358, - "narHash": "sha256-EyyvCzXoHrbL467YSsQBTWWg4sR96MH1sPpKoSOelB4=", + "lastModified": 1765836173, + "narHash": "sha256-hWRYfdH2ONI7HXbqZqW8Q1y9IRbnXWvtvt/ONZovSNY=", "owner": "Mic92", "repo": "sops-nix", - "rev": "5aca6ff67264321d47856a2ed183729271107c9c", + "rev": "443a7f2e7e118c4fc63b7fae05ab3080dd0e5c63", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 0482568..8bd2ed9 100644 --- a/flake.nix +++ b/flake.nix @@ -104,6 +104,7 @@ name = "patched-nixpkgs-unstable"; src = nixpkgs-unstable-raw; patches = [ + ./nixpkgs-patches/pr471291.patch ./nixpkgs-patches/revert-mangohud-update.patch ]; }; diff --git a/nixpkgs-patches/pr471291.patch b/nixpkgs-patches/pr471291.patch new file mode 100644 index 0000000..7111330 --- /dev/null +++ b/nixpkgs-patches/pr471291.patch @@ -0,0 +1,61 @@ +From ef52b16862caa43dd4abc0aedf1814796342b664 Mon Sep 17 00:00:00 2001 +From: K900 +Date: Tue, 16 Dec 2025 11:48:37 +0300 +Subject: [PATCH] kdePackages.plasma-vault: refresh patch + +No idea how this happened. +--- + .../plasma/plasma-vault/hardcode-paths.patch | 26 +++++++++---------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +diff --git a/pkgs/kde/plasma/plasma-vault/hardcode-paths.patch b/pkgs/kde/plasma/plasma-vault/hardcode-paths.patch +index d8a5f4a025de3..090df77eb15b0 100644 +--- a/pkgs/kde/plasma/plasma-vault/hardcode-paths.patch ++++ b/pkgs/kde/plasma/plasma-vault/hardcode-paths.patch +@@ -1,5 +1,5 @@ + diff --git a/kded/engine/backends/cryfs/cryfsbackend.cpp b/kded/engine/backends/cryfs/cryfsbackend.cpp +-index f425eb3..5b8cd43 100644 ++index 64138b6..5d249aa 100644 + --- a/kded/engine/backends/cryfs/cryfsbackend.cpp + +++ b/kded/engine/backends/cryfs/cryfsbackend.cpp + @@ -207,7 +207,7 @@ QProcess *CryFsBackend::cryfs(const QStringList &arguments) const +@@ -44,7 +44,7 @@ index b992f6f..eb828dd 100644 + + QString GocryptfsBackend::getConfigFilePath(const Device &device) const + diff --git a/kded/engine/fusebackend_p.cpp b/kded/engine/fusebackend_p.cpp +-index 8763304..e6860d2 100644 ++index 714b660..61d8bf5 100644 + --- a/kded/engine/fusebackend_p.cpp + +++ b/kded/engine/fusebackend_p.cpp + @@ -90,7 +90,7 @@ QProcess *FuseBackend::process(const QString &executable, const QStringList &arg +@@ -57,19 +57,19 @@ index 8763304..e6860d2 100644 + + FutureResult<> FuseBackend::initialize(const QString &name, const Device &device, const MountPoint &mountPoint, const Vault::Payload &payload) + diff --git a/kded/engine/vault.cpp b/kded/engine/vault.cpp +-index c101079..67c8a83 100644 ++index a7a4741..773b671 100644 + --- a/kded/engine/vault.cpp + +++ b/kded/engine/vault.cpp +-@@ -485,7 +485,7 @@ FutureResult<> Vault::close() +- } else { +- // We want to check whether there is an application +- // that is accessing the vault +-- AsynQt::Process::getOutput(QStringLiteral("lsof"), {QStringLiteral("-t"), mountPoint().data()}) | cast() | onError([this] { +-+ AsynQt::Process::getOutput(QStringLiteral("@lsof@"), {QStringLiteral("-t"), mountPoint().data()}) | cast() | onError([this] { +- d->updateMessage(i18n("Unable to lock the vault because an application is using it")); +- }) | onSuccess([this](const QString &result) { +- // based on ksolidnotify.cpp +-@@ -538,7 +538,7 @@ FutureResult<> Vault::forceClose() ++@@ -490,7 +490,7 @@ FutureResult<> Vault::close() ++ } else { ++ // We want to check whether there is an application ++ // that is accessing the vault ++- AsynQt::Process::getOutput(QStringLiteral("lsof"), { QStringLiteral("-t"), mountPoint().data() }) +++ AsynQt::Process::getOutput(QStringLiteral("@lsof@"), { QStringLiteral("-t"), mountPoint().data() }) ++ | cast() ++ | onError([this] { ++ d->updateMessage(i18n("Unable to close the vault because an application is using it")); ++@@ -546,7 +546,7 @@ FutureResult<> Vault::forceClose() + using namespace AsynQt::operators; + + AsynQt::await( From 6365f7b4f3fba169eece5ebf478510db5a31f680 Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Dec 2025 12:14:24 +0100 Subject: [PATCH 1122/1125] Common: set toast password --- flake.lock | 8 ++++---- roles/common/configuration.nix | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 1e733a2..d94d3c9 100644 --- a/flake.lock +++ b/flake.lock @@ -524,11 +524,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1765212399, - "narHash": "sha256-QEjuaK17HddWr0ZBRhsg3nt4QhSxQZ1i9YO2ctV045c=", + "lastModified": 1766142512, + "narHash": "sha256-h/vlxWqgEGbnrTWAFW+TCTJSQ1mAlkWyMM3HyHeqpF4=", "ref": "refs/heads/main", - "rev": "43c8697580bb389aea565459802c3b9827aa2d3d", - "revCount": 38, + "rev": "b87ab22fedeb4187669f1e546f18fb7d781721ba", + "revCount": 40, "type": "git", "url": "ssh://forgejo@git.toast003.xyz:4222/Toast/nix-secrets" }, diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index f51dacc..4862efe 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -94,6 +94,7 @@ isNormalUser = true; description = "Toast"; extraGroups = ["wheel"]; + hashedPasswordFile = config.sops.secrets.toast.path; }; # Set up time zone. @@ -162,6 +163,10 @@ sops = { age.sshKeyPaths = ["/persist/id_host"]; defaultSopsFile = "${flakeSelf.inputs.secrets}/${config.networking.hostName}.yaml"; + secrets.toast = { + sopsFile = "${flakeSelf.inputs.secrets}/passwd.yaml"; + neededForUsers = true; + }; }; catppuccin.grub.enable = true; From b5a8a9a5450c5d5bd69690b93ab3cebc733cc77e Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Dec 2025 12:20:35 +0100 Subject: [PATCH 1123/1125] Common; disable mutable users --- roles/common/configuration.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/common/configuration.nix b/roles/common/configuration.nix index 4862efe..998bbef 100755 --- a/roles/common/configuration.nix +++ b/roles/common/configuration.nix @@ -90,6 +90,7 @@ }; # Set up my user + users.mutableUsers = false; users.users.toast = { isNormalUser = true; description = "Toast"; From beb9705d2f66d663c8b6a5053cc7f29274367f5f Mon Sep 17 00:00:00 2001 From: Toast Date: Fri, 19 Dec 2025 13:21:31 +0100 Subject: [PATCH 1124/1125] Flake: update secrets --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index d94d3c9..8c9a225 100644 --- a/flake.lock +++ b/flake.lock @@ -524,11 +524,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1766142512, - "narHash": "sha256-h/vlxWqgEGbnrTWAFW+TCTJSQ1mAlkWyMM3HyHeqpF4=", + "lastModified": 1766143747, + "narHash": "sha256-bG4QoCZLUDrubYFuRvxiXhycBD3R+UjrzXrNZ+qRnio=", "ref": "refs/heads/main", - "rev": "b87ab22fedeb4187669f1e546f18fb7d781721ba", - "revCount": 40, + "rev": "8921f23861a82f0f8d706c276bc738ca72c053b1", + "revCount": 41, "type": "git", "url": "ssh://forgejo@git.toast003.xyz:4222/Toast/nix-secrets" }, From 924e9b7ab4ee6f990cfe5842702ace45837ce692 Mon Sep 17 00:00:00 2001 From: Toast Date: Sat, 20 Dec 2025 00:59:40 +0100 Subject: [PATCH 1125/1125] Syncthing: move device info to separate file --- lib/default.nix | 1 + lib/syncthing.nix | 5 +++++ roles/common/services/syncthing.nix | 28 ++-------------------------- syncthing.nix | 28 ++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 26 deletions(-) create mode 100644 lib/syncthing.nix create mode 100644 syncthing.nix diff --git a/lib/default.nix b/lib/default.nix index b3febf7..67bfe4e 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -5,5 +5,6 @@ nixpkgs.lib.extend (final: prev: { in { patches = importLib ./patches.nix; networkManager = importLib ./networkManager.nix; + syncthing = importLib ./syncthing.nix; }; }) diff --git a/lib/syncthing.nix b/lib/syncthing.nix new file mode 100644 index 0000000..90553b4 --- /dev/null +++ b/lib/syncthing.nix @@ -0,0 +1,5 @@ +{lib}: let + data = import ./../syncthing.nix; +in { + devices = builtins.getAttr "devices" data; +} diff --git a/roles/common/services/syncthing.nix b/roles/common/services/syncthing.nix index 7403230..820e64f 100755 --- a/roles/common/services/syncthing.nix +++ b/roles/common/services/syncthing.nix @@ -1,5 +1,6 @@ { config, + lib, flakeSelf, ... }: let @@ -22,32 +23,7 @@ in { urAccepted = 3; }; # Set up devices and folders common to every device - devices = { - "phone" = { - name = "Xiaomi Redmi Note 10 Pro"; - id = "K7KNZ5V-XREUADL-CROQXPV-6AA4H65-2VUD34Z-VQWKJ6S-LWWW4EE-XPNEZQ6"; - }; - "pc" = { - name = "Archie"; - id = "NJPX754-64AQNP3-7GZFIRZ-W2EDRJQ-27ORWYM-X5YXEXQ-ERRTRTQ-BSYD4AY"; - }; - "steamdeck" = { - name = "Steam Deck"; - id = "DNFEGEA-PDEVW5A-O5VBVQK-IUXI7J5-MAHCQAG-2JLEFFM-DSXB6AS-TX6ZHAN"; - }; - "server" = { - name = "Everest"; - id = "2GXFZJZ-CF56ER2-SISBGOF-VNXJIG5-GQC6ECA-NHCHAPX-677RSJT-RI5POAZ"; - }; - "surface" = { - name = "Surface Go"; - id = "HTVSF3O-AHY3TNH-BLVSEGK-HRRSMHC-H5LJWVF-NDKGM6O-ATWZALC-YXNV2Q4"; - }; - "winmax2" = { - name = "Win Max 2"; - id = "X2NILRM-ADRBQ23-AFREAZA-62GVFDF-UVMPR4L-KGHMUNY-BJ2C3CQ-RBT43QS"; - }; - }; + devices = lib.toast.syncthing.devices; folders = { "passwords" = { label = "KeePassXC Passwords"; diff --git a/syncthing.nix b/syncthing.nix new file mode 100644 index 0000000..353964a --- /dev/null +++ b/syncthing.nix @@ -0,0 +1,28 @@ +{ + devices = { + "phone" = { + name = "Xiaomi Redmi Note 10 Pro"; + id = "K7KNZ5V-XREUADL-CROQXPV-6AA4H65-2VUD34Z-VQWKJ6S-LWWW4EE-XPNEZQ6"; + }; + "pc" = { + name = "Archie"; + id = "NJPX754-64AQNP3-7GZFIRZ-W2EDRJQ-27ORWYM-X5YXEXQ-ERRTRTQ-BSYD4AY"; + }; + "steamdeck" = { + name = "Steam Deck"; + id = "DNFEGEA-PDEVW5A-O5VBVQK-IUXI7J5-MAHCQAG-2JLEFFM-DSXB6AS-TX6ZHAN"; + }; + "server" = { + name = "Everest"; + id = "2GXFZJZ-CF56ER2-SISBGOF-VNXJIG5-GQC6ECA-NHCHAPX-677RSJT-RI5POAZ"; + }; + "surface" = { + name = "Surface Go"; + id = "HTVSF3O-AHY3TNH-BLVSEGK-HRRSMHC-H5LJWVF-NDKGM6O-ATWZALC-YXNV2Q4"; + }; + "winmax2" = { + name = "Win Max 2"; + id = "X2NILRM-ADRBQ23-AFREAZA-62GVFDF-UVMPR4L-KGHMUNY-BJ2C3CQ-RBT43QS"; + }; + }; +}