Compare commits

..

12 Commits

Author SHA1 Message Date
569ac528a5 [zix790prors] Add i3 + fixes 2025-10-26 12:00:13 -07:00
6cc8fa4f5d [printing] Ensure network is live 2025-10-25 15:05:19 -07:00
67a82f14fd [nixos] Downgrade from unstable to 25.05 2025-10-25 15:05:08 -07:00
4b68e3f051 [darwin] Configure AutoRaise
Add delays. This works way better with accordion views where the cursor
is often hovering right around window boundaries
2025-10-16 15:29:41 -07:00
81a3657759 [darwin] Add AutoRaise
provides focus-follows-mouse
2025-10-16 10:00:12 -07:00
32e1b81034 [aerospace] Fix fullscreen chord
Cmd-F is too ingrained in muscle memory for Find
2025-10-15 11:14:50 -07:00
6f00c72540 [app-launcher-server] process detection fixes 2025-10-14 18:09:36 -07:00
d26007aa61 [aerospace] More tweaking 2025-10-14 13:43:44 -07:00
1caa8bba3e [aerospace] Further tweaks 2025-10-14 08:26:51 -07:00
d3cb09040a [kodi] Fix autologin for boxy 2025-10-13 14:32:28 -07:00
4bfacffa17 [development] Remove goose 2025-10-13 14:26:08 -07:00
a6961f05ca [app-launcher] Add app-launcher to boxy 2025-10-13 14:25:51 -07:00
15 changed files with 268 additions and 40 deletions

47
flake.lock generated
View File

@@ -23,11 +23,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1752428473, "lastModified": 1761423376,
"narHash": "sha256-IsE7fdAYbRlZuc0H5FtPfhhuHvlxnDGoAxdlnjpVNCU=", "narHash": "sha256-pMy3cnUFfue4vz/y0jx71BfcPGxZf+hk/DtnzWvfU0c=",
"ref": "refs/heads/main", "ref": "refs/heads/main",
"rev": "1fad66b55144ab6beaecd900172a21ac3c34dc52", "rev": "a1f695665771841a988afc965526cbf99160cd77",
"revCount": 10, "revCount": 11,
"type": "git", "type": "git",
"url": "https://git.johnogle.info/johno/google-cookie-retrieval.git" "url": "https://git.johnogle.info/johno/google-cookie-retrieval.git"
}, },
@@ -43,15 +43,16 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759172751, "lastModified": 1758463745,
"narHash": "sha256-E8W8sRXfrvkFW26GuuiWq6QfReU7m5+cngwHuRo/3jc=", "narHash": "sha256-uhzsV0Q0I9j2y/rfweWeGif5AWe0MGrgZ/3TjpDYdGA=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "12fa8548feefa9a10266ba65152fd1a787cdde8f", "rev": "3b955f5f0a942f9f60cdc9cacb7844335d0f21c3",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nix-community", "owner": "nix-community",
"ref": "release-25.05",
"repo": "home-manager", "repo": "home-manager",
"type": "github" "type": "github"
} }
@@ -63,11 +64,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1758805352, "lastModified": 1761339987,
"narHash": "sha256-BHdc43Lkayd+72W/NXRKHzX5AZ+28F3xaUs3a88/Uew=", "narHash": "sha256-IUaawVwItZKi64IA6kF6wQCLCzpXbk2R46dHn8sHkig=",
"owner": "nix-darwin", "owner": "nix-darwin",
"repo": "nix-darwin", "repo": "nix-darwin",
"rev": "c48e963a5558eb1c3827d59d21c5193622a1477c", "rev": "7cd9aac79ee2924a85c211d21fafd394b06a38de",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -82,11 +83,11 @@
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
}, },
"locked": { "locked": {
"lastModified": 1758785683, "lastModified": 1760536587,
"narHash": "sha256-mRn51IeEBXeNh5a6xNLylk4PKBX0s/QQxgkEbYoPq/w=", "narHash": "sha256-wfWqt+igns/VazjPLkyb4Z/wpn4v+XIjUeI3xY/1ENg=",
"owner": "nix-community", "owner": "nix-community",
"repo": "NixOS-WSL", "repo": "NixOS-WSL",
"rev": "1bfb978f2f6261b6086e04af17f9418e1fe36d70", "rev": "f98ee1de1fa36eca63c67b600f5d617e184e82ea",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -98,11 +99,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1758277210, "lastModified": 1759733170,
"narHash": "sha256-iCGWf/LTy+aY0zFu8q12lK8KuZp7yvdhStehhyX1v8w=", "narHash": "sha256-TXnlsVb5Z8HXZ6mZoeOAIwxmvGHp1g4Dw89eLvIwKVI=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "8eaee110344796db060382e15d3af0a9fc396e0e", "rev": "8913c168d1c56dc49a7718685968f38752171c3b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -114,16 +115,16 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1759036355, "lastModified": 1761173472,
"narHash": "sha256-0m27AKv6ka+q270dw48KflE0LwQYrO7Fm4/2//KCVWg=", "narHash": "sha256-m9W0dYXflzeGgKNravKJvTMR4Qqa2MVD11AwlGMufeE=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "e9f00bd893984bc8ce46c895c3bf7cac95331127", "rev": "c8aa8cc00a5cb57fada0851a038d35c08a36a2bb",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "nixos-unstable", "ref": "nixos-25.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@@ -138,11 +139,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1759157415, "lastModified": 1761078382,
"narHash": "sha256-Fg8cOnVoIe0uQ38UpR6XZzRCwDsjjozVwfevW9yCLI0=", "narHash": "sha256-JNJesbe9MMN1Brq41BHEpuH+Z+Zg74y/nI5AFZX84Vw=",
"owner": "nix-community", "owner": "nix-community",
"repo": "plasma-manager", "repo": "plasma-manager",
"rev": "df5b3e6da631f732c26c6044c7cccb8706b4f479", "rev": "27dfa61b64d0cdb8e4ba6f3aaa4d4e067d64cb5c",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -2,7 +2,7 @@
description = "A very basic flake"; description = "A very basic flake";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
nixos-wsl.url = "github:nix-community/NixOS-WSL/main"; nixos-wsl.url = "github:nix-community/NixOS-WSL/main";
nix-darwin = { nix-darwin = {
@@ -11,7 +11,7 @@
}; };
home-manager = { home-manager = {
url = "github:nix-community/home-manager"; url = "github:nix-community/home-manager/release-25.05";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };

View File

@@ -2,6 +2,7 @@
let let
customPkgs = pkgs.callPackage ../packages {}; customPkgs = pkgs.callPackage ../packages {};
leader = "cmd"; # Change this to experiment with different leader keys (e.g., "cmd", "ctrl")
in in
{ {
# Provide arguments to role modules # Provide arguments to role modules
@@ -13,6 +14,26 @@ in
home.homeDirectory = lib.mkForce "/Users/johno"; home.homeDirectory = lib.mkForce "/Users/johno";
home.stateVersion = "24.05"; home.stateVersion = "24.05";
# System packages
home.packages = with pkgs; [
autoraise
];
# Auto-start autoraise on login
launchd.agents.autoraise = {
enable = true;
config = {
ProgramArguments = [
"${pkgs.autoraise}/bin/AutoRaise"
"-pollMillis" "50"
"-delay" "2"
"-focusDelay" "2"
];
RunAtLoad = true;
KeepAlive = true;
};
};
# Override Darwin-incompatible settings from base role # Override Darwin-incompatible settings from base role
programs.rbw.settings.pinentry = lib.mkForce pkgs.pinentry_mac; programs.rbw.settings.pinentry = lib.mkForce pkgs.pinentry_mac;
@@ -43,6 +64,86 @@ in
home.shell.enableShellIntegration = true; home.shell.enableShellIntegration = true;
# TODO: Move this to its own role and/or module
programs.aerospace = {
enable = true;
launchd.enable = true;
userSettings.mode.main.binding = {
"${leader}-slash" = "layout tiles horizontal vertical";
"${leader}-comma" = "layout accordion horizontal vertical";
"${leader}-shift-q" = "close";
"${leader}-shift-f" = "fullscreen";
"${leader}-h" = "focus left";
"${leader}-j" = "focus down";
"${leader}-k" = "focus up";
"${leader}-l" = "focus right";
"${leader}-shift-h" = "move left";
"${leader}-shift-j" = "move down";
"${leader}-shift-k" = "move up";
"${leader}-shift-l" = "move right";
"${leader}-minus" = "resize smart -50";
"${leader}-equal" = "resize smart +50";
"${leader}-1" = "workspace 1";
"${leader}-2" = "workspace 2";
"${leader}-3" = "workspace 3";
"${leader}-4" = "workspace 4";
"${leader}-5" = "workspace 5";
"${leader}-6" = "workspace 6";
"${leader}-7" = "workspace 7";
"${leader}-8" = "workspace 8";
"${leader}-9" = "workspace 9";
"${leader}-0" = "workspace 10";
"${leader}-shift-1" = "move-node-to-workspace 1";
"${leader}-shift-2" = "move-node-to-workspace 2";
"${leader}-shift-3" = "move-node-to-workspace 3";
"${leader}-shift-4" = "move-node-to-workspace 4";
"${leader}-shift-5" = "move-node-to-workspace 5";
"${leader}-shift-6" = "move-node-to-workspace 6";
"${leader}-shift-7" = "move-node-to-workspace 7";
"${leader}-shift-8" = "move-node-to-workspace 8";
"${leader}-shift-9" = "move-node-to-workspace 9";
"${leader}-shift-0" = "move-node-to-workspace 10";
"${leader}-tab" = "workspace-back-and-forth";
"${leader}-shift-tab" = "move-workspace-to-monitor --wrap-around next";
"${leader}-enter" = ''
exec-and-forget osascript <<'APPLESCRIPT'
tell application "Terminal"
set newWindow to make new window
activate
tell newWindow to set index to 1
end tell
APPLESCRIPT
'';
"${leader}-shift-enter" = ''
exec-and-forget osascript <<'APPLESCRIPT'
tell application "Google Chrome"
set newWindow to make new window
activate
tell newWindow to set index to 1
end tell
APPLESCRIPT
'';
"${leader}-shift-e" = "exec-and-forget zsh --login -c \"emacsclient -c -n\"";
"${leader}-i" = "mode service";
};
userSettings.mode.service.binding = {
esc = ["reload-config" "mode main"];
r = ["flatten-workspace-tree" "mode main"]; # reset layout
f = ["layout floating tiling" "mode main"]; # Toggle between floating and tiling layout
backspace = ["close-all-windows-but-current" "mode main"];
"${leader}-shift-h" = ["join-with left" "mode main"];
"${leader}-shift-j" = ["join-with down" "mode main"];
"${leader}-shift-k" = ["join-with up" "mode main"];
"${leader}-shift-l" = ["join-with right" "mode main"];
};
};
home.roles = { home.roles = {
base.enable = true; base.enable = true;
}; };

View File

@@ -11,6 +11,12 @@ let
terminal = "kitty"; terminal = "kitty";
defaultWorkspace = "workspace number 1"; defaultWorkspace = "workspace number 1";
bars = [{
position = "bottom";
statusCommand = "i3status";
trayOutput = "primary"; # Enable system tray on primary output
}];
keybindings = { keybindings = {
"${shared_config.modifier}+Return" = "exec ${terminal}"; "${shared_config.modifier}+Return" = "exec ${terminal}";
"${shared_config.modifier}+Shift+q" = "kill"; "${shared_config.modifier}+Shift+q" = "kill";
@@ -113,6 +119,26 @@ in {
"${shared_config.modifier}+Shift+e" = "${shared_config.modifier}+Shift+e" =
"exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit'"; "exec i3-nagbar -t warning -m 'Do you want to exit i3?' -b 'Yes' 'i3-msg exit'";
}; };
startup = [
# GNOME polkit authentication agent
{
command = "/run/current-system/sw/libexec/polkit-gnome-authentication-agent-1";
always = false;
notification = false;
}
# Picom compositor for smooth rendering and no tearing (important for Nvidia)
{
command = "picom -b";
always = false;
notification = false;
}
# NetworkManager system tray applet
{
command = "nm-applet";
always = false;
notification = false;
}
];
}; };
in { in {
enable = true; enable = true;

View File

@@ -58,11 +58,11 @@ in
programs.ssh = { programs.ssh = {
enable = true; enable = true;
addKeysToAgent = "yes";
matchBlocks = { matchBlocks = {
"nucdeb1" = { "nucdeb1" = {
hostname = "nucdeb1.oglehome"; hostname = "nucdeb1.oglehome";
user = "root"; user = "root";
addKeysToAgent = "yes";
}; };
}; };
}; };

View File

@@ -14,7 +14,7 @@ in
home.packages = [ home.packages = [
# Communication apps # Communication apps
pkgs.element-desktop pkgs.element-desktop
pkgs.fluffychat #pkgs.fluffychat #marked insecure as of nixos 25.05
pkgs.nextcloud-talk-desktop pkgs.nextcloud-talk-desktop
# For logging back into google chat # For logging back into google chat

View File

@@ -14,7 +14,6 @@ in
home.packages = [ home.packages = [
pkgs.claude-code pkgs.claude-code
pkgs.codex pkgs.codex
pkgs.goose-cli
# Custom packages # Custom packages
customPkgs.tea-rbw customPkgs.tea-rbw

View File

@@ -24,7 +24,7 @@ with lib;
}; };
kodi = { kodi = {
enable = true; enable = true;
autologin = false; autologin = true;
wayland = true; wayland = true;
}; };
users.enable = true; users.enable = true;

View File

@@ -24,6 +24,7 @@ with lib;
kde = true; kde = true;
sddm = true; sddm = true;
wayland = true; wayland = true;
x11 = true;
}; };
nfs-mounts.enable = true; nfs-mounts.enable = true;
nvidia.enable = true; nvidia.enable = true;
@@ -51,6 +52,11 @@ with lib;
hardware.graphics.enable = true; hardware.graphics.enable = true;
hardware.graphics.enable32Bit = true; hardware.graphics.enable32Bit = true;
# Set DP-0 as primary display for system tray and multi-monitor setup
services.xserver.displayManager.sessionCommands = ''
${pkgs.xorg.xrandr}/bin/xrandr --output DP-0 --primary
'';
hardware.nvidia = { hardware.nvidia = {
# Modesetting is required. # Modesetting is required.
modesetting.enable = true; modesetting.enable = true;

View File

@@ -7,6 +7,7 @@ import subprocess
import sys import sys
from http.server import BaseHTTPRequestHandler, HTTPServer from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse from urllib.parse import urlparse
import psutil
# Configure logging # Configure logging
logging.basicConfig( logging.basicConfig(
@@ -21,6 +22,60 @@ ALLOWED_APPS = {
'kodi': 'kodi' 'kodi': 'kodi'
} }
def is_app_running(app_name):
"""Check if an application is already running, returns (is_running, pid)"""
command = ALLOWED_APPS.get(app_name)
if not command:
return False, None
logger.debug(f"Looking for processes related to app '{app_name}' (command: '{command}')")
for proc in psutil.process_iter(['name', 'cmdline', 'pid']):
try:
proc_name = proc.info['name']
cmdline = proc.info['cmdline'] or []
logger.debug(f"Checking process PID {proc.info['pid']}: name='{proc_name}', cmdline={cmdline}")
# Check multiple patterns for the application:
# 1. Process name exactly matches command
# 2. Process name contains the command (e.g., "kodi.bin" contains "kodi")
# 3. Command line starts with the command
# 4. Command line contains the wrapped version (e.g., ".kodi-wrapped")
# 5. Any command line argument ends with the command executable
matches = False
match_reason = ""
if proc_name == command:
matches = True
match_reason = f"exact process name match: '{proc_name}'"
elif command in proc_name:
matches = True
match_reason = f"process name contains command: '{proc_name}' contains '{command}'"
elif cmdline and cmdline[0] == command:
matches = True
match_reason = f"exact cmdline match: '{cmdline[0]}'"
elif cmdline and cmdline[0].endswith('/' + command):
matches = True
match_reason = f"cmdline path ends with command: '{cmdline[0]}'"
elif cmdline and any(f'.{command}-wrapped' in arg for arg in cmdline):
matches = True
match_reason = f"wrapped command in cmdline: {cmdline}"
elif cmdline and any(f'{command}.bin' in arg for arg in cmdline):
matches = True
match_reason = f"binary command in cmdline: {cmdline}"
if matches:
logger.info(f"Found running {app_name} process: PID {proc.info['pid']} ({match_reason})")
return True, proc.info['pid']
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
continue
logger.debug(f"No running process found for {app_name}")
return False, None
class AppLauncherHandler(BaseHTTPRequestHandler): class AppLauncherHandler(BaseHTTPRequestHandler):
def log_message(self, format, *args): def log_message(self, format, *args):
logger.info(format % args) logger.info(format % args)
@@ -56,6 +111,22 @@ class AppLauncherHandler(BaseHTTPRequestHandler):
command = ALLOWED_APPS[app_name] command = ALLOWED_APPS[app_name]
# Check if app is already running
is_running, existing_pid = is_app_running(app_name)
if is_running:
logger.info(f"Application {app_name} is already running (PID: {existing_pid}), skipping launch")
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
response = {
'status': 'success',
'message': f'{app_name} is already running',
'pid': existing_pid,
'already_running': True
}
self.wfile.write(json.dumps(response).encode())
return
try: try:
# Launch the application in the background # Launch the application in the background
# Ensure we have the proper environment for GUI apps # Ensure we have the proper environment for GUI apps
@@ -76,7 +147,8 @@ class AppLauncherHandler(BaseHTTPRequestHandler):
response = { response = {
'status': 'success', 'status': 'success',
'message': f'Successfully launched {app_name}', 'message': f'Successfully launched {app_name}',
'pid': process.pid 'pid': process.pid,
'already_running': False
} }
self.wfile.write(json.dumps(response).encode()) self.wfile.write(json.dumps(response).encode())

View File

@@ -1,5 +1,10 @@
{ pkgs }: { pkgs }:
let
python = pkgs.python3.withPackages (ps: with ps; [
psutil
]);
in
pkgs.writeShellScriptBin "app-launcher-server" '' pkgs.writeShellScriptBin "app-launcher-server" ''
exec ${pkgs.python3}/bin/python3 ${./app-launcher-server.py} "$@" exec ${python}/bin/python3 ${./app-launcher-server.py} "$@"
'' ''

View File

@@ -22,6 +22,14 @@ in
ryubing ryubing
dolphin-emu dolphin-emu
]; ];
# TODO: Remove me once dolphin-emu and dolphin-emu-primehack update
# dependencies to mbedtls from mbedtls_2 (which is currently)
# unmaintained
nixpkgs.config.permittedInsecurePackages = [ "mbedtls-2.28.10" ];
warnings = [
"Using insecure mbedtls-2.28.10 for Dolphin Emu - check for updates regularly"
];
}) })
]; ];
} }

View File

@@ -12,7 +12,14 @@ in
windowManager.i3 = { windowManager.i3 = {
enable = true; enable = true;
extraPackages = with pkgs; [ dmenu i3status i3lock ]; extraPackages = with pkgs; [
dmenu
i3status
i3lock
polkit_gnome # GNOME polkit authentication agent (more stable with i3)
picom # Compositor for smooth rendering (important for Nvidia)
networkmanagerapplet # NetworkManager system tray applet
];
}; };
}; };
}; };

View File

@@ -75,13 +75,10 @@ in
}; };
}; };
services = if cfg.autologin then { services.displayManager = mkIf cfg.autologin {
displayManager = {
autoLogin.enable = true; autoLogin.enable = true;
autoLogin.user = "kodi"; autoLogin.user = "kodi";
defaultSession = "kodi"; defaultSession = "plasma";
sessionData.autologinSession = "plasma";
}; };
} else {};
}; };
} }

View File

@@ -26,5 +26,11 @@ in
model = "everywhere"; model = "everywhere";
}]; }];
hardware.printers.ensureDefaultPrinter = "MFC-L8900CDW_series"; hardware.printers.ensureDefaultPrinter = "MFC-L8900CDW_series";
# Fix ensure-printers service to wait for network availability
systemd.services.ensure-printers = {
after = [ "cups.service" "network-online.target" ];
wants = [ "cups.service" "network-online.target" ];
};
}; };
} }