summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flake.lock2
-rw-r--r--machines/common/default.nix2
-rw-r--r--machines/common/libinputcurve.nix105
-rw-r--r--users/kassouni/desktop/sway/default.nix (renamed from users/kassouni/wayland/default.nix)0
-rw-r--r--users/kassouni/desktop/sway/fuzzel.nix37
-rw-r--r--users/kassouni/desktop/sway/sway.nix (renamed from users/kassouni/wayland/sway.nix)17
-rw-r--r--users/kassouni/desktop/sway/waybar.nix (renamed from users/kassouni/wayland/waybar.nix)32
-rw-r--r--users/kassouni/desktop/xmonad/default.nix7
-rw-r--r--users/kassouni/desktop/xmonad/rofi.nix (renamed from users/kassouni/rofi.nix)0
-rw-r--r--users/kassouni/desktop/xmonad/xbindkeys.nix (renamed from users/kassouni/xbindkeys.nix)0
-rw-r--r--users/kassouni/desktop/xmonad/xmonad.nix9
-rw-r--r--users/kassouni/ghostty.nix4
-rw-r--r--users/kassouni/home.nix15
-rw-r--r--users/kassouni/neovim.nix20
-rw-r--r--users/kassouni/palette/default.nix26
-rw-r--r--users/kassouni/palette/fuzzel-palette.nix27
-rw-r--r--users/kassouni/palette/rofi-palette.nix24
-rw-r--r--users/kassouni/theme.nix19
-rw-r--r--users/kassouni/wayland/fuzzel.nix23
19 files changed, 296 insertions, 73 deletions
diff --git a/flake.lock b/flake.lock
index bfda8af..cd48b89 100644
--- a/flake.lock
+++ b/flake.lock
@@ -332,7 +332,7 @@
"nixpkgs": "nixpkgs_4"
},
"locked": {
- "lastModified": 1788059985,
+ "lastModified": 1788239526,
"narHash": "sha256-wNoWALnRqwCmDFct8ADoNtNsS5ihtobMy2WKVTeZw5A=",
"path": "/home/kassouni/Developer/xmonad-config",
"type": "path"
diff --git a/machines/common/default.nix b/machines/common/default.nix
index df8e60c..9af7dc0 100644
--- a/machines/common/default.nix
+++ b/machines/common/default.nix
@@ -2,11 +2,11 @@
{
imports = [
./base.nix
+ ./libinputcurve.nix
./pipewire.nix
./printer.nix
./rip.nix
./tailscale.nix
./user.nix
- ./x11.nix
];
}
diff --git a/machines/common/libinputcurve.nix b/machines/common/libinputcurve.nix
new file mode 100644
index 0000000..8fefb9e
--- /dev/null
+++ b/machines/common/libinputcurve.nix
@@ -0,0 +1,105 @@
+{ ... }:
+# macOS trackpad pointer-acceleration curve, transplanted onto libinput.
+#
+# WHERE THE CURVE COMES FROM
+#
+# macOS accelerates one pointer report as (IOHIDFamily, IOHIDPointerAccelerator):
+#
+# velocity = floor(hypot(dx, dy)) * rate_multiplier
+# mult = curve(velocity / (resolution / 67)) * (96/67) / velocity
+#
+# where curve() is a quartic up to TangentSpeedLinear, its tangent line up to
+# TangentSpeedParabolicRoot, and the square root of a line beyond that.
+#
+# The coefficients below were recovered by fitting that form to ~2200 pointer
+# reports captured from a real Apple trackpad (see ~/Downloads/code/rev), using
+# the cursor's 1/256-point position deltas as ground truth rather than the
+# integer CGEvent delta, which is rounded and cannot resolve better than +/-1:
+#
+# GainLinear 0.961648 TangentSpeedLinear 7.090
+# GainParabolic 0.829395 TangentSpeedParabolicRoot 17.978
+# GainCubic 0.122907 resolution 400 dpi @ 120 Hz
+# GainQuartic 0 tracking index ~0.6875
+#
+# The fit reproduces every measured velocity bin (v = 1..48 device units per
+# report) to an rms of 2.4e-4 in gain. TangentSpeedParabolicRoot is the one
+# value NOT measured -- the captures top out at 14.4 in/s, well below the
+# roll-off -- so it is taken from the reported 32.2 in/s roll-off. It is
+# corroborated: it puts the factor peak at 38.0 in/s against a reported ~40.
+#
+# TRANSLATION TO LIBINPUT
+#
+# libinput's custom profile has the same shape as Apple's algorithm -- both map
+# an input speed to an output speed and use the ratio as the factor -- so the
+# curve transplants directly. Only the units differ. libinput's x axis is
+# *device units per millisecond* at the touchpad's own resolution (verified:
+# tp_filter_motion passes x through raw, scaling only y for axis aspect), so
+# the points below are specific to a 609.6 dpi (24 units/mm) touchpad.
+#
+# !! These numbers are tied to that resolution. magician's PIXA3854 is
+# !! 609.6 dpi. A touchpad with a different resolution needs the table
+# !! regenerated, or the curve will be wrong by the ratio of resolutions.
+# !! Check with: libinput list-devices, or EVIOCGABS on the event node.
+# !! To scope this to one machine instead, set services.libinput.touchpad.dev.
+#
+# WHAT DOES NOT TRANSFER
+#
+# Apple's floor() on velocity pins the gain flat below one device unit per
+# report (< 0.30 in/s) and then steps it up 12% at exactly |d| = 1. libinput's
+# f() is continuous and its points are uniformly spaced, so that discontinuity
+# cannot be represented. What we get for free: f() runs linearly from the origin
+# to the first knot, so the factor is constant across that first segment. The
+# step below places the first knot at 0.3175 in/s -- essentially exactly Apple's
+# 0.30 in/s plateau edge -- so the plateau's *width* is reproduced. Its value
+# lands ~6% high, because continuity forbids the step.
+#
+# RANGE
+#
+# 64 points is libinput's hard maximum (libinput_config_accel_set_points rejects
+# more), which forces a choice: uniform spacing means covering more speed costs
+# low-speed resolution. 20 in/s is the sweet spot rather than a compromise --
+# past the last knot libinput extrapolates the final segment linearly, and
+# Apple's curve is genuinely a straight line from 12.7 to 32.2 in/s, so the
+# extrapolation is *exact* out to 30 in/s. Error only appears above the
+# roll-off: +2.7% at 40 in/s, +16% at 60 in/s. Those are flick speeds where
+# the pointer is being thrown across the screen anyway.
+#
+# Measured against the capture's own speed distribution: 0.22% weighted rms
+# error, worst case 1.7% below 15 in/s.
+let
+ # Overall speed trim. The curve's shape is independent of this; it scales
+ # cursor travel per finger inch uniformly. 1.0 maps one macOS point to one
+ # X11 pixel. Raise it if the pointer feels sluggish on a HiDPI screen that
+ # X is driving unscaled -- a macOS point is a *logical* unit, so an unscaled
+ # HiDPI X session covers less physical distance per point than macOS does.
+ gain = 1.0;
+
+ # x = 0, step, 2*step, ... in touchpad device units per millisecond.
+ # step = 20 in/s / 63 intervals, at 609.6 dpi.
+ step = 0.193524;
+
+ # f(x), the accelerated speed. libinput uses f(x)/x as the factor.
+ points = [
+ 0.00000 0.03303 0.07349 0.12141 0.17680 0.23966 0.31000 0.38784
+ 0.47319 0.56605 0.66644 0.77437 0.88985 1.01289 1.14350 1.28169
+ 1.42748 1.58086 1.74186 1.91048 2.08674 2.27064 2.46220 2.66142
+ 2.86832 3.08291 3.30520 3.53520 3.77291 4.01836 4.27155 4.53249
+ 4.80119 5.07767 5.36193 5.65398 5.95384 6.26151 6.57702 6.90035
+ 7.23154 7.56666 7.90177 8.23689 8.57201 8.90712 9.24224 9.57736
+ 9.91247 10.24759 10.58270 10.91782 11.25294 11.58805 11.92317 12.25829
+ 12.59340 12.92852 13.26364 13.59875 13.93387 14.26898 14.60410 14.93922
+ ];
+in
+{
+ # services.libinput.enable defaults to services.xserver.enable, so this file
+ # is inert until X is turned on.
+ services.libinput.touchpad = {
+ accelProfile = "custom";
+ accelStepMotion = step;
+ accelPointsMotion = map (p: p * gain) points;
+
+ # Deliberately not setting accelSpeed: libinput ignores the speed setting
+ # entirely under the custom profile (custom_accelerator_set_speed only
+ # range-checks its argument and returns). The curve is the whole story.
+ };
+}
diff --git a/users/kassouni/wayland/default.nix b/users/kassouni/desktop/sway/default.nix
index 947924a..947924a 100644
--- a/users/kassouni/wayland/default.nix
+++ b/users/kassouni/desktop/sway/default.nix
diff --git a/users/kassouni/desktop/sway/fuzzel.nix b/users/kassouni/desktop/sway/fuzzel.nix
new file mode 100644
index 0000000..d6d294b
--- /dev/null
+++ b/users/kassouni/desktop/sway/fuzzel.nix
@@ -0,0 +1,37 @@
+{
+ pkgs,
+ lib,
+ config,
+ ...
+}:
+let
+ inherit (config.colorScheme) ui editor common;
+
+ # fuzzel wants RRGGBBAA with no leading '#'.
+ rgba = c: lib.toLower (lib.removePrefix "#" c) + "ff";
+in
+{
+ programs.fuzzel = {
+ enable = true;
+ settings = {
+ main = {
+ font = lib.mkForce "${config.theme.font.family}:size=${toString config.theme.font.size}";
+ };
+
+ colors = {
+ background = rgba ui.bg;
+ text = rgba editor.fg;
+ match = rgba common.accent.tint;
+ selection = rgba ui.panel.bg;
+ selection-text = rgba editor.fg;
+ selection-match = rgba common.accent.tint;
+ border = rgba ui.line;
+ };
+
+ border = {
+ radius = 0;
+ };
+ };
+ };
+
+}
diff --git a/users/kassouni/wayland/sway.nix b/users/kassouni/desktop/sway/sway.nix
index 0cf97f7..2e73d5f 100644
--- a/users/kassouni/wayland/sway.nix
+++ b/users/kassouni/desktop/sway/sway.nix
@@ -12,16 +12,19 @@
config = {
window.titlebar = false;
menu = "fuzzel";
- gaps = {
- };
modifier = "Mod4";
# Use kitty as default terminal
- terminal = "foot";
+ terminal = "ghostty";
};
- extraConfig = let incr = "5"; in ''
- output * scale 2
- bindsym XF86MonBrightnessDown exec brightnessctl set -e 5%-
- bindsym XF86MonBrightnessUp exec brightnessctl set -e +5%
+ extraConfig = let
+ incr = "5";
+ brightnessctl = "${pkgs.brightnessctl}/bin/brightnessctl";
+ in ''
+ # home-manager inlines these values instead of emitting `set` lines
+ output * scale 1.75
+ output * bg ${config.theme.desktop.wallpaper} fill
+ bindsym XF86MonBrightnessDown exec ${brightnessctl} set -e ${incr}%-
+ bindsym XF86MonBrightnessUp exec ${brightnessctl} set -e +${incr}%
bindsym XF86AudioRaiseVolume exec wpctl set-volume @DEFAULT_SINK@ ${incr}%+
bindsym XF86AudioLowerVolume exec wpctl set-volume @DEFAULT_SINK@ ${incr}%-
input "type:keyboard" {
diff --git a/users/kassouni/wayland/waybar.nix b/users/kassouni/desktop/sway/waybar.nix
index 3026c2f..7cb37a0 100644
--- a/users/kassouni/wayland/waybar.nix
+++ b/users/kassouni/desktop/sway/waybar.nix
@@ -1,4 +1,7 @@
{ pkgs, inputs, config, ... }:
+let
+ inherit (config.colorScheme) ui editor common;
+in
{
programs.waybar = {
enable = true;
@@ -82,27 +85,50 @@
};
};
style = ''
+ * {
+ /* waybar's css font-size is px, but theme.font.size is points like
+ ghostty and fuzzel take. 1pt = 4/3px. */
+ font-family: ${config.theme.font.family};
+ font-size: ${builtins.toString (config.theme.font.size * 4 / 3)}px;
+ }
+
+ window#waybar {
+ background: ${ui.bg};
+ color: ${editor.fg};
+ }
+
.module {
padding: 0px 15px 0px;
}
-
+
#workspaces button {
- font-family: ${config.theme.font.family};
- font-size: ${builtins.toString config.theme.font.size}px;
font-weight: normal;
+ color: ${ui.fg};
+ background: none;
+ border: none;
}
#workspaces button.focused {
+ color: ${common.accent.tint};
+ }
+
+ #workspaces button.urgent {
+ color: ${common.error};
}
#workspaces button:hover {
font-weight: bold;
+ color: ${editor.fg};
box-shadow: none;
text-shadow: inherit;
background: none;
transition: none;
}
+ /* matches the `states.low = 20` threshold on the battery module */
+ #battery.low {
+ color: ${common.error};
+ }
'';
};
diff --git a/users/kassouni/desktop/xmonad/default.nix b/users/kassouni/desktop/xmonad/default.nix
new file mode 100644
index 0000000..d62dbe4
--- /dev/null
+++ b/users/kassouni/desktop/xmonad/default.nix
@@ -0,0 +1,7 @@
+{...}: {
+ imports = [
+ ./xmonad.nix
+ ./rofi.nix
+ ./xbindkeys.nix
+ ];
+}
diff --git a/users/kassouni/rofi.nix b/users/kassouni/desktop/xmonad/rofi.nix
index 740047b..740047b 100644
--- a/users/kassouni/rofi.nix
+++ b/users/kassouni/desktop/xmonad/rofi.nix
diff --git a/users/kassouni/xbindkeys.nix b/users/kassouni/desktop/xmonad/xbindkeys.nix
index 41ef7ed..41ef7ed 100644
--- a/users/kassouni/xbindkeys.nix
+++ b/users/kassouni/desktop/xmonad/xbindkeys.nix
diff --git a/users/kassouni/desktop/xmonad/xmonad.nix b/users/kassouni/desktop/xmonad/xmonad.nix
new file mode 100644
index 0000000..d49dcc1
--- /dev/null
+++ b/users/kassouni/desktop/xmonad/xmonad.nix
@@ -0,0 +1,9 @@
+{pkgs, config, ...}: {
+ xmonad-config = {
+ launcher = "rofi -show drun -show-icons";
+ terminal = "ghostty";
+ wallpaper = config.theme.desktop.wallpaper;
+ xmobar.font = config.theme.font;
+ };
+}
+
diff --git a/users/kassouni/ghostty.nix b/users/kassouni/ghostty.nix
index 8c4aefd..cbfaee1 100644
--- a/users/kassouni/ghostty.nix
+++ b/users/kassouni/ghostty.nix
@@ -3,9 +3,9 @@
programs.ghostty = {
enable = true;
settings = {
- theme = "Ayu Light";
+ theme = "Ayu";
font-family = config.theme.font.family;
- font-size = 24;
+ font-size = config.theme.font.size;
window-decoration = "none";
};
};
diff --git a/users/kassouni/home.nix b/users/kassouni/home.nix
index 9268980..84b69f1 100644
--- a/users/kassouni/home.nix
+++ b/users/kassouni/home.nix
@@ -8,11 +8,12 @@
imports = [
./neovim.nix
./claude.nix
- ./rofi.nix
./music.nix
./fonts.nix
./slippi.nix
./ssh.nix
+ ./desktop/sway
+ ./desktop/xmonad
./rip.nix
./ayu/ayu-dark.nix
./git.nix
@@ -21,23 +22,11 @@
./firefox.nix
./cursor.nix
./bash.nix
- ./xbindkeys.nix
./scripts
./palette
];
home.username = "kassouni";
-
- xmonad-config = {
- launcher = "rofi -show drun -show-icons";
- terminal = "ghostty";
- wallpaper = pkgs.fetchurl {
- url = "https://i.redd.it/p5flk9uzzxxz.jpg";
- sha256 = "1qcl6yh6l24sz3qprj3iyzinj3lyh3c426i6zwambwg816yg3bxs";
- };
- xmobar.font = config.theme.font;
- };
-
home.sessionVariables = {
"TEST_VAR" = "asdf";
};
diff --git a/users/kassouni/neovim.nix b/users/kassouni/neovim.nix
index ec90023..3aac114 100644
--- a/users/kassouni/neovim.nix
+++ b/users/kassouni/neovim.nix
@@ -9,6 +9,11 @@
enable = true;
defaultEditor = true;
+ globals = {
+ mapleader = " ";
+ maplocalleader = " ";
+ };
+
opts = {
number = true;
relativenumber = true;
@@ -19,9 +24,22 @@
plugins = {
# Existing plugins
sleuth.enable = true;
- telescope.enable = true;
+ telescope = {
+ enable = true;
+ keymaps = {
+ "<leader>ff" = {
+ action = "find_files";
+ options.desc = "Telescope find files";
+ };
+ "<leader>fg" = {
+ action = "live_grep";
+ options.desc = "Telescope live grep";
+ };
+ };
+ };
highlight-colors.enable = true;
web-devicons.enable = true;
+ which-key.enable = true;
# LSP
lsp = {
diff --git a/users/kassouni/palette/default.nix b/users/kassouni/palette/default.nix
index 403aa60..0600510 100644
--- a/users/kassouni/palette/default.nix
+++ b/users/kassouni/palette/default.nix
@@ -1,12 +1,4 @@
-{
- config,
- lib,
- pkgs,
- ...
-}:
-let
- cfg = config.kassouni.palette;
-in
+{ lib, ... }:
{
imports = [
./bluetooth.nix
@@ -14,6 +6,8 @@ in
./rebuild.nix
./screenshot.nix
./shutdown.nix
+ ./rofi-palette.nix
+ ./fuzzel-palette.nix
];
options.kassouni.palette.commands = lib.mkOption {
@@ -37,18 +31,8 @@ in
);
default = [ ];
description = ''
- Entries shown in the rofi command palette.
+ Entries shown in the command palette. Rendered by both front ends:
+ `open-palette` (rofi, X11) and `open-palette-fuzzel` (fuzzel, Wayland).
'';
};
-
- config.home.packages = [
- (pkgs.writers.writeBashBin "open-palette" ''
- set -eu
- exes=(${lib.concatMapStringsSep " " (c: "${c.exe}") cfg.commands})
- idx=$(${pkgs.rofi}/bin/rofi -dmenu -i -format i -p palette <<EOF
-${lib.concatMapStrings (c: "${c.icon} ${c.name}\n") cfg.commands}EOF
- )
- exec "''${exes[$idx]}"
- '')
- ];
}
diff --git a/users/kassouni/palette/fuzzel-palette.nix b/users/kassouni/palette/fuzzel-palette.nix
new file mode 100644
index 0000000..d6d4774
--- /dev/null
+++ b/users/kassouni/palette/fuzzel-palette.nix
@@ -0,0 +1,27 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+let
+ cfg = config.kassouni.palette;
+in
+{
+ # Wayland front end for the palette. `--index` is fuzzel's answer to rofi's
+ # `-format i`, so the same index-into-exes trick works. Unlike rofi, fuzzel
+ # will happily accept text that matches no row; it exits non-zero there, but
+ # the numeric guard keeps a surprising build of fuzzel from indexing the
+ # array with garbage.
+ home.packages = [
+ (pkgs.writers.writeBashBin "open-palette-fuzzel" ''
+ set -eu
+ exes=(${lib.concatMapStringsSep " " (c: "${c.exe}") cfg.commands})
+ idx=$(${pkgs.fuzzel}/bin/fuzzel --dmenu --index --prompt "palette " <<EOF
+${lib.concatMapStrings (c: "${c.icon} ${c.name}\n") cfg.commands}EOF
+ )
+ [[ $idx =~ ^[0-9]+$ ]] && [[ $idx -lt ''${#exes[@]} ]] || exit 1
+ exec "''${exes[$idx]}"
+ '')
+ ];
+}
diff --git a/users/kassouni/palette/rofi-palette.nix b/users/kassouni/palette/rofi-palette.nix
new file mode 100644
index 0000000..7418ceb
--- /dev/null
+++ b/users/kassouni/palette/rofi-palette.nix
@@ -0,0 +1,24 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+let
+ cfg = config.kassouni.palette;
+in
+{
+ # X11 front end for the palette. `-format i` makes rofi print the row index,
+ # so the label shown and the executable run stay paired by position rather
+ # than by parsing the label back out.
+ home.packages = [
+ (pkgs.writers.writeBashBin "open-palette" ''
+ set -eu
+ exes=(${lib.concatMapStringsSep " " (c: "${c.exe}") cfg.commands})
+ idx=$(${pkgs.rofi}/bin/rofi -dmenu -i -format i -p palette <<EOF
+${lib.concatMapStrings (c: "${c.icon} ${c.name}\n") cfg.commands}EOF
+ )
+ exec "''${exes[$idx]}"
+ '')
+ ];
+}
diff --git a/users/kassouni/theme.nix b/users/kassouni/theme.nix
index 4c96615..70785ca 100644
--- a/users/kassouni/theme.nix
+++ b/users/kassouni/theme.nix
@@ -6,7 +6,7 @@
font = {
size = lib.mkOption {
type = lib.types.int;
- default = 24;
+ default = 16;
description = "Global font size for all applications";
};
@@ -21,6 +21,23 @@
default = 10;
type = lib.types.int;
};
+
+ wallpaper = lib.mkOption {
+ type = lib.types.path;
+ description = "Wallpaper image used by the window manager";
+ default = pkgs.runCommand "fw-13-pro-wallpaper-6.png" {
+ src = pkgs.fetchurl {
+ url = "https://downloads.frame.work/assets/framework-laptop13pro-wallpaper-pack.zip";
+ sha256 = "0pjmsyfz49r2fwkz0c00rzjhf2rzfxrk72lnqc94z6a8h3rs3v3b";
+ };
+ nativeBuildInputs = [ pkgs.unzip ];
+ } ''
+ unzip -j "$src" "FW 13 Pro Wallpaper 6.png"
+ # unzip restores the archive's own mode bits, which nix rejects on a
+ # store output; install with an explicit mode instead of moving.
+ install -m 0444 "FW 13 Pro Wallpaper 6.png" "$out"
+ '';
+ };
};
};
};
diff --git a/users/kassouni/wayland/fuzzel.nix b/users/kassouni/wayland/fuzzel.nix
deleted file mode 100644
index a716b2b..0000000
--- a/users/kassouni/wayland/fuzzel.nix
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- pkgs,
- lib,
- config,
- ...
-}:
-{
- programs.fuzzel = {
- enable = true;
- settings = {
- main = {
- font = lib.mkForce "${config.theme.font.family}:size=${toString config.theme.font.size}";
- };
-
-
-
- border = {
- radius = 0;
- };
- };
- };
-
-}