feat(jade): create modular desktop environment
Rename xmonad/ to jade/ and restructure as a complete desktop environment with hybrid NixOS and home-manager modules. This establishes jade as a self-contained, gruvbox-themed DE that can eventually be extracted as a flake. Changes: - Create jade/ with NixOS module (WM, system packages, GTK theme) - Create jade/home.nix for home-manager services (wezterm, picom, dunst) - Move dmenu with gruvbox patches into jade/dmenu/ - Convert wezterm to pure Lua config with gruvbox-material colors - Move xinitrc into jade/ directory - Remove feh/scrot from global env (now in jade) - Remove dmenu overlay from global overlays - Simplify home-manager desktop features to just user apps This follows the pattern of real DEs (GNOME, KDE) where system and user configs are split across NixOS and home-manager modules.
This commit is contained in:
parent
1a931b76bd
commit
4169045fa4
19 changed files with 310 additions and 200 deletions
|
|
@ -22,9 +22,6 @@
|
|||
# File Management
|
||||
fd ranger tree
|
||||
|
||||
# Graphics & Screenshots
|
||||
feh scrot
|
||||
|
||||
# Networking
|
||||
curl nmap sshfs wget
|
||||
|
||||
|
|
|
|||
88
nixos/common/users/sajenim/jade/default.nix
Normal file
88
nixos/common/users/sajenim/jade/default.nix
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./dmenu
|
||||
];
|
||||
|
||||
# Desktop environment packages and configuration
|
||||
environment = {
|
||||
systemPackages = [
|
||||
# Required for some XFCE/GTK stuff
|
||||
pkgs.dconf
|
||||
# Picture viewer
|
||||
pkgs.xfce.ristretto
|
||||
# Wallpaper setter
|
||||
pkgs.feh
|
||||
# Screenshot tool
|
||||
pkgs.scrot
|
||||
# GTK theme
|
||||
pkgs.unstable.gruvbox-material-gtk-theme
|
||||
# Install our XMonad and Xmobar configuration
|
||||
inputs.xmonad-config.packages.${pkgs.stdenv.hostPlatform.system}.default
|
||||
];
|
||||
|
||||
# Set default terminal for the desktop environment
|
||||
sessionVariables = {
|
||||
TERMINAL = "wezterm";
|
||||
};
|
||||
};
|
||||
|
||||
# Programs and tools for the desktop environment
|
||||
programs = {
|
||||
# File browser
|
||||
thunar.enable = true;
|
||||
# Configuration storage system for xfce
|
||||
xfconf.enable = true;
|
||||
# Enable dconf for GTK applications
|
||||
dconf.enable = true;
|
||||
};
|
||||
|
||||
# System services for the desktop environment
|
||||
services = {
|
||||
# Mount, trash, and other functionalities
|
||||
gvfs.enable = true;
|
||||
# Thumbnail support for images
|
||||
tumbler.enable = true;
|
||||
};
|
||||
|
||||
# XDG desktop portal for file pickers, screen sharing, etc.
|
||||
xdg.portal = {
|
||||
enable = true;
|
||||
config.common.default = ["gtk"];
|
||||
extraPortals = with pkgs; [
|
||||
xdg-desktop-portal-gtk
|
||||
xdg-desktop-portal-wlr
|
||||
];
|
||||
};
|
||||
|
||||
# Install patched fonts for the desktop environment
|
||||
fonts.packages = [
|
||||
(pkgs.stdenv.mkDerivation {
|
||||
name = "jade-fonts";
|
||||
src = "${inputs.self}/pkgs/patched-fonts";
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/fonts
|
||||
cp -r $src/* $out/share/fonts/
|
||||
'';
|
||||
})
|
||||
];
|
||||
|
||||
# Configure GTK theme system-wide
|
||||
environment.etc = {
|
||||
"xdg/gtk-3.0/settings.ini".text = /* ini */ ''
|
||||
[Settings]
|
||||
gtk-theme-name=Gruvbox-Material-Dark
|
||||
gtk-icon-theme-name=Gruvbox-Material-Dark
|
||||
gtk-application-prefer-dark-theme=true
|
||||
'';
|
||||
"xdg/gtk-4.0/settings.ini".text = /* ini */ ''
|
||||
[Settings]
|
||||
gtk-theme-name=Gruvbox-Material-Dark
|
||||
gtk-icon-theme-name=Gruvbox-Material-Dark
|
||||
gtk-application-prefer-dark-theme=true
|
||||
'';
|
||||
};
|
||||
}
|
||||
15
nixos/common/users/sajenim/jade/dmenu/default.nix
Normal file
15
nixos/common/users/sajenim/jade/dmenu/default.nix
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{pkgs, ...}: {
|
||||
# Dynamic menu for X with gruvbox theme and custom bar height
|
||||
nixpkgs.overlays = [
|
||||
(final: prev: {
|
||||
dmenu = prev.dmenu.overrideAttrs (oldAttrs: {
|
||||
patches = [
|
||||
./patches/dmenu-bar-height-5.2.diff
|
||||
./patches/dmenu-gruvbox-20210329-9ae8ea5.diff
|
||||
];
|
||||
});
|
||||
})
|
||||
];
|
||||
|
||||
environment.systemPackages = [pkgs.dmenu];
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
diff --git a/config.def.h b/config.def.h
|
||||
index 1edb647..5c79628 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
|
||||
/* -fn option overrides fonts[0]; default X11 font or font set */
|
||||
+static const int user_bh = 7; /* add an defined amount of pixels to the bar height */
|
||||
+
|
||||
static const char *fonts[] = {
|
||||
"monospace:size=10"
|
||||
};
|
||||
diff --git a/dmenu.c b/dmenu.c
|
||||
index 27b7a30..7be0dc3 100644
|
||||
--- a/dmenu.c
|
||||
+++ b/dmenu.c
|
||||
@@ -629,7 +629,8 @@ setup(void)
|
||||
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
|
||||
|
||||
/* calculate menu geometry */
|
||||
- bh = drw->fonts->h + 2;
|
||||
+ bh = drw->fonts->h;
|
||||
+ bh = user_bh ? bh + user_bh : bh + 2;
|
||||
lines = MAX(lines, 0);
|
||||
mh = (lines + 1) * bh;
|
||||
#ifdef XINERAMA
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
From 9ae8ea55988973aa19f1e069ee24ba7af5a669e0 Mon Sep 17 00:00:00 2001
|
||||
From: Miles Glapa-Grossklag <m.glapa.grossklag@gmail.com>
|
||||
Date: Mon, 29 Mar 2021 18:57:52 -0700
|
||||
Subject: [PATCH] Add gruvbox dark colorscheme
|
||||
|
||||
---
|
||||
config.def.h | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1edb647..36105e5 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -9,9 +9,9 @@ static const char *fonts[] = {
|
||||
static const char *prompt = NULL; /* -p option; prompt to the left of input field */
|
||||
static const char *colors[SchemeLast][2] = {
|
||||
/* fg bg */
|
||||
- [SchemeNorm] = { "#bbbbbb", "#222222" },
|
||||
- [SchemeSel] = { "#eeeeee", "#005577" },
|
||||
- [SchemeOut] = { "#000000", "#00ffff" },
|
||||
+ [SchemeNorm] = { "#a89984", "#282828" },
|
||||
+ [SchemeSel] = { "#32302f", "#a9b665" },
|
||||
+ [SchemeOut] = { "#a89984", "#89b482" },
|
||||
};
|
||||
/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
|
||||
static unsigned int lines = 0;
|
||||
--
|
||||
2.25.1
|
||||
29
nixos/common/users/sajenim/jade/dunst/default.nix
Normal file
29
nixos/common/users/sajenim/jade/dunst/default.nix
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{...}: {
|
||||
# Notification daemon
|
||||
services.dunst = {
|
||||
enable = true;
|
||||
settings = {
|
||||
global = {
|
||||
width = 300;
|
||||
height = 300;
|
||||
origin = "top-right";
|
||||
offset = "20x20";
|
||||
frame_width = 5;
|
||||
frame_color = "#32302f";
|
||||
corner_radius = 10;
|
||||
};
|
||||
urgency_low = {
|
||||
background = "#282828";
|
||||
foreground = "#d4be98";
|
||||
};
|
||||
urgency_normal = {
|
||||
background = "#282828";
|
||||
foreground = "#d4be98";
|
||||
};
|
||||
urgency_critical = {
|
||||
background = "#282828";
|
||||
foreground = "#d4be98";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
24
nixos/common/users/sajenim/jade/home.nix
Normal file
24
nixos/common/users/sajenim/jade/home.nix
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./dunst
|
||||
./picom
|
||||
];
|
||||
|
||||
# Wezterm terminal emulator with jade configuration
|
||||
programs.wezterm = {
|
||||
enable = true;
|
||||
package = pkgs.unstable.wezterm;
|
||||
enableZshIntegration = true;
|
||||
extraConfig = builtins.readFile (
|
||||
"${inputs.self}/nixos/common/users/sajenim/jade/wezterm.lua"
|
||||
);
|
||||
};
|
||||
|
||||
# X session initialization script
|
||||
home.file.".xinitrc".source =
|
||||
"${inputs.self}/nixos/common/users/sajenim/jade/xinitrc";
|
||||
}
|
||||
9
nixos/common/users/sajenim/jade/picom/default.nix
Normal file
9
nixos/common/users/sajenim/jade/picom/default.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{...}: {
|
||||
# X11 compositor for transparency and effects
|
||||
services.picom = {
|
||||
enable = true;
|
||||
shadow = true;
|
||||
shadowExclude = ["class_g = 'dmenu'"];
|
||||
backend = "xrender";
|
||||
};
|
||||
}
|
||||
302
nixos/common/users/sajenim/jade/wezterm.lua
Normal file
302
nixos/common/users/sajenim/jade/wezterm.lua
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
-- Pull in the wezterm API
|
||||
local wezterm = require("wezterm")
|
||||
|
||||
-- Log warnings or generate errors if we define an invalid configuration option
|
||||
local config = wezterm.config_builder()
|
||||
|
||||
-- Format window title to prefer explicit tab titles over process names
|
||||
wezterm.on('format-window-title', function(tab, pane, tabs, panes, config)
|
||||
-- Use explicit tab title if set, otherwise fall back to process name
|
||||
if tab.tab_title and tab.tab_title ~= "" then
|
||||
return tab.tab_title
|
||||
end
|
||||
-- Fallback to active pane's title (process name)
|
||||
return tab.active_pane.title
|
||||
end)
|
||||
|
||||
--
|
||||
-- General configuration options.
|
||||
--
|
||||
|
||||
-- Do not check for or show window with update information
|
||||
config.check_for_updates = false
|
||||
|
||||
-- Improve wezterm graphical performance
|
||||
config.front_end = "OpenGL"
|
||||
config.max_fps = 144
|
||||
config.animation_fps = 144
|
||||
|
||||
-- Font configuration
|
||||
config.font = wezterm.font("Fisa Code")
|
||||
config.font_size = 10.0
|
||||
|
||||
-- Gruvbox Material Dark color scheme
|
||||
config.colors = {
|
||||
foreground = "#D4BE98",
|
||||
background = "#282828",
|
||||
cursor_bg = "#A89984",
|
||||
cursor_fg = "#3C3836",
|
||||
cursor_border = "#A89984",
|
||||
selection_fg = "#A89984",
|
||||
selection_bg = "#3C3836",
|
||||
|
||||
ansi = {
|
||||
"#282828", -- black (bg0)
|
||||
"#EA6962", -- red
|
||||
"#A9B665", -- green
|
||||
"#D8A657", -- yellow
|
||||
"#7DAEA3", -- blue
|
||||
"#D3869B", -- purple
|
||||
"#89B482", -- aqua
|
||||
"#D4BE98", -- white (fg0)
|
||||
},
|
||||
|
||||
brights = {
|
||||
"#7C6F65", -- bright black (grey0)
|
||||
"#EA6962", -- bright red
|
||||
"#A9B665", -- bright green
|
||||
"#D8A657", -- bright yellow
|
||||
"#7DAEA3", -- bright blue
|
||||
"#D3869B", -- bright purple
|
||||
"#89B482", -- bright aqua
|
||||
"#DDC7A1", -- bright white (fg1)
|
||||
},
|
||||
}
|
||||
|
||||
-- Pad window borders
|
||||
config.window_padding = {
|
||||
left = 10,
|
||||
right = 10,
|
||||
top = 10,
|
||||
bottom = 10,
|
||||
}
|
||||
|
||||
--
|
||||
-- Tab bar configuration options.
|
||||
--
|
||||
|
||||
-- Disable modern tab bar
|
||||
config.use_fancy_tab_bar = false
|
||||
config.tab_max_width = 32
|
||||
|
||||
-- Tab bar colors
|
||||
config.colors.tab_bar = {
|
||||
background = "#32302f",
|
||||
active_tab = {
|
||||
bg_color = "#32302f",
|
||||
fg_color = "#7daea3",
|
||||
intensity = "Bold",
|
||||
italic = true,
|
||||
},
|
||||
inactive_tab = {
|
||||
bg_color = "#32302f",
|
||||
fg_color = "#a89984",
|
||||
intensity = "Bold",
|
||||
italic = true,
|
||||
},
|
||||
inactive_tab_hover = {
|
||||
bg_color = "#32302f",
|
||||
fg_color = "#a89984",
|
||||
intensity = "Bold",
|
||||
italic = true,
|
||||
},
|
||||
new_tab = {
|
||||
bg_color = "#32302f",
|
||||
fg_color = "#a89984",
|
||||
intensity = "Bold",
|
||||
italic = true,
|
||||
},
|
||||
new_tab_hover = {
|
||||
bg_color = "#32302f",
|
||||
fg_color = "#a89984",
|
||||
intensity = "Bold",
|
||||
italic = true,
|
||||
},
|
||||
}
|
||||
|
||||
--
|
||||
-- Keymaps configuration.
|
||||
--
|
||||
|
||||
-- Disable the default keybindings
|
||||
config.disable_default_key_bindings = true
|
||||
|
||||
-- Setup leader key
|
||||
config.leader = { key = "a", mods = "ALT", timeout_milliseconds = 2000 }
|
||||
|
||||
-- General keymaps
|
||||
config.keys = {
|
||||
--
|
||||
-- Enter key table modes
|
||||
--
|
||||
|
||||
{ -- Enter tab management mode
|
||||
key = "t",
|
||||
mods = "LEADER",
|
||||
action = wezterm.action.ActivateKeyTable({
|
||||
name = "tab_mode",
|
||||
one_shot = true,
|
||||
}),
|
||||
},
|
||||
|
||||
{ -- Enter pane management mode
|
||||
key = "p",
|
||||
mods = "LEADER",
|
||||
action = wezterm.action.ActivateKeyTable({
|
||||
name = "pane_mode",
|
||||
one_shot = true,
|
||||
}),
|
||||
},
|
||||
|
||||
--
|
||||
-- Navigation
|
||||
--
|
||||
|
||||
{ -- Focus previous tab
|
||||
key = "LeftArrow",
|
||||
mods = "ALT",
|
||||
action = wezterm.action.ActivateTabRelative(-1),
|
||||
},
|
||||
|
||||
{ -- Focus next tab
|
||||
key = "RightArrow",
|
||||
mods = "ALT",
|
||||
action = wezterm.action.ActivateTabRelative(1),
|
||||
},
|
||||
|
||||
{ -- Focus previous pane
|
||||
key = "UpArrow",
|
||||
mods = "ALT",
|
||||
action = wezterm.action.ActivatePaneDirection("Prev"),
|
||||
},
|
||||
|
||||
{ -- Focus next pane
|
||||
key = "DownArrow",
|
||||
mods = "ALT",
|
||||
action = wezterm.action.ActivatePaneDirection("Next"),
|
||||
},
|
||||
|
||||
{ -- Focus largest (master) pane
|
||||
key = "Delete",
|
||||
mods = "ALT",
|
||||
action = wezterm.action_callback(function(window, pane)
|
||||
local tab = window:active_tab()
|
||||
local largest = nil
|
||||
local largest_size = 0
|
||||
|
||||
for _, p in ipairs(tab:panes()) do
|
||||
local dims = p:get_dimensions()
|
||||
local size = dims.pixel_width * dims.pixel_height
|
||||
if size > largest_size then
|
||||
largest_size = size
|
||||
largest = p
|
||||
end
|
||||
end
|
||||
|
||||
if largest and largest:pane_id() ~= pane:pane_id() then
|
||||
largest:activate()
|
||||
end
|
||||
end),
|
||||
},
|
||||
|
||||
--
|
||||
-- Copy / Paste
|
||||
--
|
||||
|
||||
{ -- Enter copy mode
|
||||
key = "Escape",
|
||||
mods = "LEADER",
|
||||
action = wezterm.action.ActivateCopyMode,
|
||||
},
|
||||
|
||||
{ -- Paste from clipboard
|
||||
key = "v",
|
||||
mods = "CTRL|SHIFT",
|
||||
action = wezterm.action.PasteFrom("Clipboard"),
|
||||
},
|
||||
|
||||
--
|
||||
-- Miscellaneous
|
||||
--
|
||||
|
||||
{ -- This lets us unify delete word across programs
|
||||
key = "Backspace",
|
||||
mods = "CTRL",
|
||||
action = wezterm.action.SendKey({ key = "w", mods = "CTRL" }),
|
||||
},
|
||||
}
|
||||
|
||||
--
|
||||
-- Key table definitions for modal keybinding namespaces
|
||||
--
|
||||
|
||||
config.key_tables = {
|
||||
-- Tab management mode (LEADER + t)
|
||||
tab_mode = {
|
||||
{ -- Create new tab
|
||||
key = "n",
|
||||
action = wezterm.action.SpawnCommandInNewTab({
|
||||
cwd = wezterm.home_dir,
|
||||
}),
|
||||
},
|
||||
{ -- Close current tab
|
||||
key = "q",
|
||||
action = wezterm.action.CloseCurrentTab({ confirm = false }),
|
||||
},
|
||||
{ -- Rename current tab
|
||||
key = "r",
|
||||
action = wezterm.action_callback(function(window, pane)
|
||||
local success, stdout, stderr = wezterm.run_child_process({
|
||||
"dmenu",
|
||||
"-fn",
|
||||
"Fisa Code-10",
|
||||
"-p",
|
||||
"Tab name:",
|
||||
})
|
||||
if success and stdout then
|
||||
local name = stdout:gsub("\n", "")
|
||||
if name ~= "" then
|
||||
window:active_tab():set_title(name)
|
||||
end
|
||||
end
|
||||
end),
|
||||
},
|
||||
},
|
||||
|
||||
-- Pane management mode (LEADER + p)
|
||||
pane_mode = {
|
||||
{ -- Split pane vertically (bottom, 30%)
|
||||
key = "s",
|
||||
action = wezterm.action.SplitPane({
|
||||
direction = "Down",
|
||||
size = { Percent = 30 },
|
||||
}),
|
||||
},
|
||||
{ -- Split pane horizontally (left, 28%)
|
||||
key = "v",
|
||||
action = wezterm.action.SplitPane({
|
||||
direction = "Left",
|
||||
size = { Percent = 28 },
|
||||
}),
|
||||
},
|
||||
{ -- Close current pane
|
||||
key = "q",
|
||||
action = wezterm.action.CloseCurrentPane({ confirm = false }),
|
||||
},
|
||||
{ -- Maximize/zoom pane
|
||||
key = "m",
|
||||
action = wezterm.action.TogglePaneZoomState,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
-- Jump to specific tabs by number (ALT + 1-9)
|
||||
for i = 1, 9 do
|
||||
table.insert(config.keys, {
|
||||
key = tostring(i),
|
||||
mods = "ALT",
|
||||
action = wezterm.action.ActivateTab(i - 1),
|
||||
})
|
||||
end
|
||||
|
||||
return config
|
||||
17
nixos/common/users/sajenim/jade/xinitrc
Normal file
17
nixos/common/users/sajenim/jade/xinitrc
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Setup monitors (machine-specific - consider making configurable)
|
||||
xrandr --output HDMI-A-0 --mode 1920x1080 \
|
||||
--output DisplayPort-0 --mode 2560x1440 --right-of HDMI-A-0
|
||||
|
||||
# Apply wallpaper
|
||||
feh --bg-center ~/.repositories/personal/nix-config/assets/chinatown.png
|
||||
|
||||
# Disable screen saver and DPMS features
|
||||
xset s off -dpms
|
||||
|
||||
# Fix for pinentry bug on NixOS
|
||||
gpgconf --reload gpg-agent
|
||||
|
||||
# Launch window manager
|
||||
exec xmonad
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}: {
|
||||
# Unfortunately some of these cannot be managed by
|
||||
# home-manager, so we must install them to the system.
|
||||
|
||||
environment = {
|
||||
systemPackages = [
|
||||
# Required for some XFCE/GTK stuff
|
||||
pkgs.dconf
|
||||
# Dynamic menu for X
|
||||
pkgs.dmenu
|
||||
# Picture viewer
|
||||
pkgs.xfce.ristretto
|
||||
# Install our XMonad and Xmobar configuration
|
||||
inputs.xmonad-config.packages.${pkgs.stdenv.hostPlatform.system}.default
|
||||
];
|
||||
};
|
||||
|
||||
programs = {
|
||||
# File browser
|
||||
thunar.enable = true;
|
||||
# Configuration storage system for xfce
|
||||
xfconf.enable = true;
|
||||
};
|
||||
|
||||
services = {
|
||||
# Mount, trash, and other functionalities
|
||||
gvfs.enable = true;
|
||||
# Thumbnail support for images
|
||||
tumbler.enable = true;
|
||||
};
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
# Our user configuration and optional user units
|
||||
../common/users/sajenim
|
||||
../common/users/sajenim/steam
|
||||
../common/users/sajenim/xmonad
|
||||
../common/users/sajenim/jade
|
||||
|
||||
# Optional components
|
||||
../common/optional/yubikey.nix
|
||||
|
|
|
|||
|
|
@ -1,10 +1,3 @@
|
|||
{pkgs, ...}: {
|
||||
# Required to install flatpak
|
||||
xdg.portal = {
|
||||
enable = true;
|
||||
config.common.default = ["gtk"];
|
||||
extraPortals = [pkgs.xdg-desktop-portal-wlr];
|
||||
};
|
||||
|
||||
{...}: {
|
||||
services.flatpak.enable = true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue