summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
l---------config/hypr/hyprland.conf1
-rw-r--r--config/niri/default-config.kdl623
-rw-r--r--config/niri/jonbox.kdl579
-rw-r--r--config/niri/jontop.kdl579
-rw-r--r--config/nvim/lua/lsp.lua293
-rw-r--r--config/waybar/config.jonbox128
-rw-r--r--config/waybar/config.jontop128
-rw-r--r--config/waybar/style.css39
-rw-r--r--default.nix2
-rw-r--r--flake.lock83
-rw-r--r--flake.nix16
-rw-r--r--hosts/jonbox/default.nix92
-rw-r--r--hosts/jontop/default.nix18
-rw-r--r--modules/desktop/apps/browsers/firefox.nix6
-rw-r--r--modules/desktop/apps/editors/neovim.nix48
-rw-r--r--modules/desktop/apps/editors/vscode.nix27
-rw-r--r--modules/desktop/apps/games/lunati.nix24
-rw-r--r--modules/desktop/apps/games/lutris.nix23
-rw-r--r--modules/desktop/apps/games/openttd.nix28
-rw-r--r--modules/desktop/apps/games/prism.nix23
-rw-r--r--modules/desktop/apps/games/steam.nix5
-rw-r--r--modules/desktop/apps/games/vintagestory.nix31
-rw-r--r--modules/desktop/apps/mpd.nix8
-rw-r--r--modules/desktop/apps/mutt-wizard.nix46
-rw-r--r--modules/desktop/apps/virt.nix49
-rw-r--r--modules/desktop/apps/vpn.nix23
-rw-r--r--modules/desktop/greetd.nix1
-rw-r--r--modules/desktop/hyprland.nix67
-rw-r--r--modules/desktop/niri.nix67
-rw-r--r--modules/hardware/audio.nix22
-rw-r--r--modules/hardware/bluetooth.nix2
-rw-r--r--modules/hardware/gpu.nix45
-rw-r--r--modules/options.nix1
-rw-r--r--modules/security.nix28
-rw-r--r--modules/shell/zsh.nix2
-rw-r--r--overlay.nix41
-rw-r--r--packages/aurora4x/default.nix57
-rw-r--r--packages/freeciv/default.nix141
-rw-r--r--packages/freecol/default.nix64
-rw-r--r--packages/vintagestory/default.nix117
40 files changed, 3302 insertions, 275 deletions
diff --git a/config/hypr/hyprland.conf b/config/hypr/hyprland.conf
deleted file mode 120000
index 2cd79a9..0000000
--- a/config/hypr/hyprland.conf
+++ /dev/null
@@ -1 +0,0 @@
-/nix/store/kb2ii1nq7qfbs480iz2a1flb6n3kh1l8-home-manager-files/.config/hypr/hyprland.conf \ No newline at end of file
diff --git a/config/niri/default-config.kdl b/config/niri/default-config.kdl
new file mode 100644
index 0000000..0af16c7
--- /dev/null
+++ b/config/niri/default-config.kdl
@@ -0,0 +1,623 @@
+// This config is in the KDL format: https://kdl.dev
+// "/-" comments out the following node.
+// Check the wiki for a full description of the configuration:
+// https://yalter.github.io/niri/Configuration:-Introduction
+
+// Input device configuration.
+// Find the full list of options on the wiki:
+// https://yalter.github.io/niri/Configuration:-Input
+input {
+ keyboard {
+ xkb {
+ // You can set rules, model, layout, variant and options.
+ // For more information, see xkeyboard-config(7).
+
+ // For example:
+ // layout "us,ru"
+ // options "grp:win_space_toggle,compose:ralt,ctrl:nocaps"
+
+ // If this section is empty, niri will fetch xkb settings
+ // from org.freedesktop.locale1. You can control these using
+ // localectl set-x11-keymap.
+ }
+
+ // Enable numlock on startup, omitting this setting disables it.
+ numlock
+ }
+
+ // Next sections include libinput settings.
+ // Omitting settings disables them, or leaves them at their default values.
+ // All commented-out settings here are examples, not defaults.
+ touchpad {
+ // off
+ tap
+ // dwt
+ // dwtp
+ // drag false
+ // drag-lock
+ natural-scroll
+ // accel-speed 0.2
+ // accel-profile "flat"
+ // scroll-method "two-finger"
+ // disabled-on-external-mouse
+ }
+
+ mouse {
+ // off
+ // natural-scroll
+ // accel-speed 0.2
+ // accel-profile "flat"
+ // scroll-method "no-scroll"
+ }
+
+ trackpoint {
+ // off
+ // natural-scroll
+ // accel-speed 0.2
+ // accel-profile "flat"
+ // scroll-method "on-button-down"
+ // scroll-button 273
+ // scroll-button-lock
+ // middle-emulation
+ }
+
+ // Uncomment this to make the mouse warp to the center of newly focused windows.
+ // warp-mouse-to-focus
+
+ // Focus windows and outputs automatically when moving the mouse into them.
+ // Setting max-scroll-amount="0%" makes it work only on windows already fully on screen.
+ // focus-follows-mouse max-scroll-amount="0%"
+}
+
+// You can configure outputs by their name, which you can find
+// by running `niri msg outputs` while inside a niri instance.
+// The built-in laptop monitor is usually called "eDP-1".
+// Find more information on the wiki:
+// https://yalter.github.io/niri/Configuration:-Outputs
+// Remember to uncomment the node by removing "/-"!
+/-output "eDP-1" {
+ // Uncomment this line to disable this output.
+ // off
+
+ // Resolution and, optionally, refresh rate of the output.
+ // The format is "<width>x<height>" or "<width>x<height>@<refresh rate>".
+ // If the refresh rate is omitted, niri will pick the highest refresh rate
+ // for the resolution.
+ // If the mode is omitted altogether or is invalid, niri will pick one automatically.
+ // Run `niri msg outputs` while inside a niri instance to list all outputs and their modes.
+ mode "1920x1080@120.030"
+
+ // You can use integer or fractional scale, for example use 1.5 for 150% scale.
+ scale 2
+
+ // Transform allows to rotate the output counter-clockwise, valid values are:
+ // normal, 90, 180, 270, flipped, flipped-90, flipped-180 and flipped-270.
+ transform "normal"
+
+ // Position of the output in the global coordinate space.
+ // This affects directional monitor actions like "focus-monitor-left", and cursor movement.
+ // The cursor can only move between directly adjacent outputs.
+ // Output scale and rotation has to be taken into account for positioning:
+ // outputs are sized in logical, or scaled, pixels.
+ // For example, a 3840×2160 output with scale 2.0 will have a logical size of 1920×1080,
+ // so to put another output directly adjacent to it on the right, set its x to 1920.
+ // If the position is unset or results in an overlap, the output is instead placed
+ // automatically.
+ position x=1280 y=0
+}
+
+// Settings that influence how windows are positioned and sized.
+// Find more information on the wiki:
+// https://yalter.github.io/niri/Configuration:-Layout
+layout {
+ // Set gaps around windows in logical pixels.
+ gaps 16
+
+ // When to center a column when changing focus, options are:
+ // - "never", default behavior, focusing an off-screen column will keep at the left
+ // or right edge of the screen.
+ // - "always", the focused column will always be centered.
+ // - "on-overflow", focusing a column will center it if it doesn't fit
+ // together with the previously focused column.
+ center-focused-column "never"
+
+ // You can customize the widths that "switch-preset-column-width" (Mod+R) toggles between.
+ preset-column-widths {
+ // Proportion sets the width as a fraction of the output width, taking gaps into account.
+ // For example, you can perfectly fit four windows sized "proportion 0.25" on an output.
+ // The default preset widths are 1/3, 1/2 and 2/3 of the output.
+ proportion 0.33333
+ proportion 0.5
+ proportion 0.66667
+
+ // Fixed sets the width in logical pixels exactly.
+ // fixed 1920
+ }
+
+ // You can also customize the heights that "switch-preset-window-height" (Mod+Shift+R) toggles between.
+ // preset-window-heights { }
+
+ // You can change the default width of the new windows.
+ default-column-width { proportion 0.5; }
+ // If you leave the brackets empty, the windows themselves will decide their initial width.
+ // default-column-width {}
+
+ // By default focus ring and border are rendered as a solid background rectangle
+ // behind windows. That is, they will show up through semitransparent windows.
+ // This is because windows using client-side decorations can have an arbitrary shape.
+ //
+ // If you don't like that, you should uncomment `prefer-no-csd` below.
+ // Niri will draw focus ring and border *around* windows that agree to omit their
+ // client-side decorations.
+ //
+ // Alternatively, you can override it with a window rule called
+ // `draw-border-with-background`.
+
+ // You can change how the focus ring looks.
+ focus-ring {
+ // Uncomment this line to disable the focus ring.
+ // off
+
+ // How many logical pixels the ring extends out from the windows.
+ width 4
+
+ // Colors can be set in a variety of ways:
+ // - CSS named colors: "red"
+ // - RGB hex: "#rgb", "#rgba", "#rrggbb", "#rrggbbaa"
+ // - CSS-like notation: "rgb(255, 127, 0)", rgba(), hsl() and a few others.
+
+ // Color of the ring on the active monitor.
+ active-color "#7fc8ff"
+
+ // Color of the ring on inactive monitors.
+ //
+ // The focus ring only draws around the active window, so the only place
+ // where you can see its inactive-color is on other monitors.
+ inactive-color "#505050"
+
+ // You can also use gradients. They take precedence over solid colors.
+ // Gradients are rendered the same as CSS linear-gradient(angle, from, to).
+ // The angle is the same as in linear-gradient, and is optional,
+ // defaulting to 180 (top-to-bottom gradient).
+ // You can use any CSS linear-gradient tool on the web to set these up.
+ // Changing the color space is also supported, check the wiki for more info.
+ //
+ // active-gradient from="#80c8ff" to="#c7ff7f" angle=45
+
+ // You can also color the gradient relative to the entire view
+ // of the workspace, rather than relative to just the window itself.
+ // To do that, set relative-to="workspace-view".
+ //
+ // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
+ }
+
+ // You can also add a border. It's similar to the focus ring, but always visible.
+ border {
+ // The settings are the same as for the focus ring.
+ // If you enable the border, you probably want to disable the focus ring.
+ off
+
+ width 4
+ active-color "#ffc87f"
+ inactive-color "#505050"
+
+ // Color of the border around windows that request your attention.
+ urgent-color "#9b0000"
+
+ // Gradients can use a few different interpolation color spaces.
+ // For example, this is a pastel rainbow gradient via in="oklch longer hue".
+ //
+ // active-gradient from="#e5989b" to="#ffb4a2" angle=45 relative-to="workspace-view" in="oklch longer hue"
+
+ // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
+ }
+
+ // You can enable drop shadows for windows.
+ shadow {
+ // Uncomment the next line to enable shadows.
+ // on
+
+ // By default, the shadow draws only around its window, and not behind it.
+ // Uncomment this setting to make the shadow draw behind its window.
+ //
+ // Note that niri has no way of knowing about the CSD window corner
+ // radius. It has to assume that windows have square corners, leading to
+ // shadow artifacts inside the CSD rounded corners. This setting fixes
+ // those artifacts.
+ //
+ // However, instead you may want to set prefer-no-csd and/or
+ // geometry-corner-radius. Then, niri will know the corner radius and
+ // draw the shadow correctly, without having to draw it behind the
+ // window. These will also remove client-side shadows if the window
+ // draws any.
+ //
+ // draw-behind-window true
+
+ // You can change how shadows look. The values below are in logical
+ // pixels and match the CSS box-shadow properties.
+
+ // Softness controls the shadow blur radius.
+ softness 30
+
+ // Spread expands the shadow.
+ spread 5
+
+ // Offset moves the shadow relative to the window.
+ offset x=0 y=5
+
+ // You can also change the shadow color and opacity.
+ color "#0007"
+ }
+
+ // Struts shrink the area occupied by windows, similarly to layer-shell panels.
+ // You can think of them as a kind of outer gaps. They are set in logical pixels.
+ // Left and right struts will cause the next window to the side to always be visible.
+ // Top and bottom struts will simply add outer gaps in addition to the area occupied by
+ // layer-shell panels and regular gaps.
+ struts {
+ // left 64
+ // right 64
+ // top 64
+ // bottom 64
+ }
+}
+
+// Add lines like this to spawn processes at startup.
+// Note that running niri as a session supports xdg-desktop-autostart,
+// which may be more convenient to use.
+// See the binds section below for more spawn examples.
+
+// This line starts waybar, a commonly used bar for Wayland compositors.
+spawn-at-startup "waybar"
+
+// To run a shell command (with variables, pipes, etc.), use spawn-sh-at-startup:
+// spawn-sh-at-startup "qs -c ~/source/qs/MyAwesomeShell"
+
+hotkey-overlay {
+ // Uncomment this line to disable the "Important Hotkeys" pop-up at startup.
+ // skip-at-startup
+}
+
+// Uncomment this line to ask the clients to omit their client-side decorations if possible.
+// If the client will specifically ask for CSD, the request will be honored.
+// Additionally, clients will be informed that they are tiled, removing some client-side rounded corners.
+// This option will also fix border/focus ring drawing behind some semitransparent windows.
+// After enabling or disabling this, you need to restart the apps for this to take effect.
+// prefer-no-csd
+
+// You can change the path where screenshots are saved.
+// A ~ at the front will be expanded to the home directory.
+// The path is formatted with strftime(3) to give you the screenshot date and time.
+screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"
+
+// You can also set this to null to disable saving screenshots to disk.
+// screenshot-path null
+
+// Animation settings.
+// The wiki explains how to configure individual animations:
+// https://yalter.github.io/niri/Configuration:-Animations
+animations {
+ // Uncomment to turn off all animations.
+ // off
+
+ // Slow down all animations by this factor. Values below 1 speed them up instead.
+ // slowdown 3.0
+}
+
+// Window rules let you adjust behavior for individual windows.
+// Find more information on the wiki:
+// https://yalter.github.io/niri/Configuration:-Window-Rules
+
+// Work around WezTerm's initial configure bug
+// by setting an empty default-column-width.
+window-rule {
+ // This regular expression is intentionally made as specific as possible,
+ // since this is the default config, and we want no false positives.
+ // You can get away with just app-id="wezterm" if you want.
+ match app-id=r#"^org\.wezfurlong\.wezterm$"#
+ default-column-width {}
+}
+
+// Open the Firefox picture-in-picture player as floating by default.
+window-rule {
+ // This app-id regular expression will work for both:
+ // - host Firefox (app-id is "firefox")
+ // - Flatpak Firefox (app-id is "org.mozilla.firefox")
+ match app-id=r#"firefox$"# title="^Picture-in-Picture$"
+ open-floating true
+}
+
+// Example: block out two password managers from screen capture.
+// (This example rule is commented out with a "/-" in front.)
+/-window-rule {
+ match app-id=r#"^org\.keepassxc\.KeePassXC$"#
+ match app-id=r#"^org\.gnome\.World\.Secrets$"#
+
+ block-out-from "screen-capture"
+
+ // Use this instead if you want them visible on third-party screenshot tools.
+ // block-out-from "screencast"
+}
+
+// Example: enable rounded corners for all windows.
+// (This example rule is commented out with a "/-" in front.)
+/-window-rule {
+ geometry-corner-radius 12
+ clip-to-geometry true
+}
+
+binds {
+ // Keys consist of modifiers separated by + signs, followed by an XKB key name
+ // in the end. To find an XKB name for a particular key, you may use a program
+ // like wev.
+ //
+ // "Mod" is a special modifier equal to Super when running on a TTY, and to Alt
+ // when running as a winit window.
+ //
+ // Most actions that you can bind here can also be invoked programmatically with
+ // `niri msg action do-something`.
+
+ // Mod-Shift-/, which is usually the same as Mod-?,
+ // shows a list of important hotkeys.
+ Mod+Shift+Slash { show-hotkey-overlay; }
+
+ // Suggested binds for running programs: terminal, app launcher, screen locker.
+ Mod+T hotkey-overlay-title="Open a Terminal: alacritty" { spawn "alacritty"; }
+ Mod+D hotkey-overlay-title="Run an Application: fuzzel" { spawn "fuzzel"; }
+ Super+Alt+L hotkey-overlay-title="Lock the Screen: swaylock" { spawn "swaylock"; }
+
+ // Use spawn-sh to run a shell command. Do this if you need pipes, multiple commands, etc.
+ // Note: the entire command goes as a single argument. It's passed verbatim to `sh -c`.
+ // For example, this is a standard bind to toggle the screen reader (orca).
+ Super+Alt+S allow-when-locked=true hotkey-overlay-title=null { spawn-sh "pkill orca || exec orca"; }
+
+ // Example volume keys mappings for PipeWire & WirePlumber.
+ // The allow-when-locked=true property makes them work even when the session is locked.
+ // Using spawn-sh allows to pass multiple arguments together with the command.
+ // "-l 1.0" limits the volume to 100%.
+ XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1+ -l 1.0"; }
+ XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1-"; }
+ XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; }
+ XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; }
+
+ // Example media keys mapping using playerctl.
+ // This will work with any MPRIS-enabled media player.
+ XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; }
+ XF86AudioStop allow-when-locked=true { spawn-sh "playerctl stop"; }
+ XF86AudioPrev allow-when-locked=true { spawn-sh "playerctl previous"; }
+ XF86AudioNext allow-when-locked=true { spawn-sh "playerctl next"; }
+
+ // Example brightness key mappings for brightnessctl.
+ // You can use regular spawn with multiple arguments too (to avoid going through "sh"),
+ // but you need to manually put each argument in separate "" quotes.
+ XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "+10%"; }
+ XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "10%-"; }
+
+ // Open/close the Overview: a zoomed-out view of workspaces and windows.
+ // You can also move the mouse into the top-left hot corner,
+ // or do a four-finger swipe up on a touchpad.
+ Mod+O repeat=false { toggle-overview; }
+
+ Mod+Q repeat=false { close-window; }
+
+ Mod+Left { focus-column-left; }
+ Mod+Down { focus-window-down; }
+ Mod+Up { focus-window-up; }
+ Mod+Right { focus-column-right; }
+ Mod+H { focus-column-left; }
+ Mod+J { focus-window-down; }
+ Mod+K { focus-window-up; }
+ Mod+L { focus-column-right; }
+
+ Mod+Ctrl+Left { move-column-left; }
+ Mod+Ctrl+Down { move-window-down; }
+ Mod+Ctrl+Up { move-window-up; }
+ Mod+Ctrl+Right { move-column-right; }
+ Mod+Ctrl+H { move-column-left; }
+ Mod+Ctrl+J { move-window-down; }
+ Mod+Ctrl+K { move-window-up; }
+ Mod+Ctrl+L { move-column-right; }
+
+ // Alternative commands that move across workspaces when reaching
+ // the first or last window in a column.
+ // Mod+J { focus-window-or-workspace-down; }
+ // Mod+K { focus-window-or-workspace-up; }
+ // Mod+Ctrl+J { move-window-down-or-to-workspace-down; }
+ // Mod+Ctrl+K { move-window-up-or-to-workspace-up; }
+
+ Mod+Home { focus-column-first; }
+ Mod+End { focus-column-last; }
+ Mod+Ctrl+Home { move-column-to-first; }
+ Mod+Ctrl+End { move-column-to-last; }
+
+ Mod+Shift+Left { focus-monitor-left; }
+ Mod+Shift+Down { focus-monitor-down; }
+ Mod+Shift+Up { focus-monitor-up; }
+ Mod+Shift+Right { focus-monitor-right; }
+ Mod+Shift+H { focus-monitor-left; }
+ Mod+Shift+J { focus-monitor-down; }
+ Mod+Shift+K { focus-monitor-up; }
+ Mod+Shift+L { focus-monitor-right; }
+
+ Mod+Shift+Ctrl+Left { move-column-to-monitor-left; }
+ Mod+Shift+Ctrl+Down { move-column-to-monitor-down; }
+ Mod+Shift+Ctrl+Up { move-column-to-monitor-up; }
+ Mod+Shift+Ctrl+Right { move-column-to-monitor-right; }
+ Mod+Shift+Ctrl+H { move-column-to-monitor-left; }
+ Mod+Shift+Ctrl+J { move-column-to-monitor-down; }
+ Mod+Shift+Ctrl+K { move-column-to-monitor-up; }
+ Mod+Shift+Ctrl+L { move-column-to-monitor-right; }
+
+ // Alternatively, there are commands to move just a single window:
+ // Mod+Shift+Ctrl+Left { move-window-to-monitor-left; }
+ // ...
+
+ // And you can also move a whole workspace to another monitor:
+ // Mod+Shift+Ctrl+Left { move-workspace-to-monitor-left; }
+ // ...
+
+ Mod+Page_Down { focus-workspace-down; }
+ Mod+Page_Up { focus-workspace-up; }
+ Mod+U { focus-workspace-down; }
+ Mod+I { focus-workspace-up; }
+ Mod+Ctrl+Page_Down { move-column-to-workspace-down; }
+ Mod+Ctrl+Page_Up { move-column-to-workspace-up; }
+ Mod+Ctrl+U { move-column-to-workspace-down; }
+ Mod+Ctrl+I { move-column-to-workspace-up; }
+
+ // Alternatively, there are commands to move just a single window:
+ // Mod+Ctrl+Page_Down { move-window-to-workspace-down; }
+ // ...
+
+ Mod+Shift+Page_Down { move-workspace-down; }
+ Mod+Shift+Page_Up { move-workspace-up; }
+ Mod+Shift+U { move-workspace-down; }
+ Mod+Shift+I { move-workspace-up; }
+
+ // You can bind mouse wheel scroll ticks using the following syntax.
+ // These binds will change direction based on the natural-scroll setting.
+ //
+ // To avoid scrolling through workspaces really fast, you can use
+ // the cooldown-ms property. The bind will be rate-limited to this value.
+ // You can set a cooldown on any bind, but it's most useful for the wheel.
+ Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; }
+ Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; }
+ Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; }
+ Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; }
+
+ Mod+WheelScrollRight { focus-column-right; }
+ Mod+WheelScrollLeft { focus-column-left; }
+ Mod+Ctrl+WheelScrollRight { move-column-right; }
+ Mod+Ctrl+WheelScrollLeft { move-column-left; }
+
+ // Usually scrolling up and down with Shift in applications results in
+ // horizontal scrolling; these binds replicate that.
+ Mod+Shift+WheelScrollDown { focus-column-right; }
+ Mod+Shift+WheelScrollUp { focus-column-left; }
+ Mod+Ctrl+Shift+WheelScrollDown { move-column-right; }
+ Mod+Ctrl+Shift+WheelScrollUp { move-column-left; }
+
+ // Similarly, you can bind touchpad scroll "ticks".
+ // Touchpad scrolling is continuous, so for these binds it is split into
+ // discrete intervals.
+ // These binds are also affected by touchpad's natural-scroll, so these
+ // example binds are "inverted", since we have natural-scroll enabled for
+ // touchpads by default.
+ // Mod+TouchpadScrollDown { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.02+"; }
+ // Mod+TouchpadScrollUp { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.02-"; }
+
+ // You can refer to workspaces by index. However, keep in mind that
+ // niri is a dynamic workspace system, so these commands are kind of
+ // "best effort". Trying to refer to a workspace index bigger than
+ // the current workspace count will instead refer to the bottommost
+ // (empty) workspace.
+ //
+ // For example, with 2 workspaces + 1 empty, indices 3, 4, 5 and so on
+ // will all refer to the 3rd workspace.
+ Mod+1 { focus-workspace 1; }
+ Mod+2 { focus-workspace 2; }
+ Mod+3 { focus-workspace 3; }
+ Mod+4 { focus-workspace 4; }
+ Mod+5 { focus-workspace 5; }
+ Mod+6 { focus-workspace 6; }
+ Mod+7 { focus-workspace 7; }
+ Mod+8 { focus-workspace 8; }
+ Mod+9 { focus-workspace 9; }
+ Mod+Ctrl+1 { move-column-to-workspace 1; }
+ Mod+Ctrl+2 { move-column-to-workspace 2; }
+ Mod+Ctrl+3 { move-column-to-workspace 3; }
+ Mod+Ctrl+4 { move-column-to-workspace 4; }
+ Mod+Ctrl+5 { move-column-to-workspace 5; }
+ Mod+Ctrl+6 { move-column-to-workspace 6; }
+ Mod+Ctrl+7 { move-column-to-workspace 7; }
+ Mod+Ctrl+8 { move-column-to-workspace 8; }
+ Mod+Ctrl+9 { move-column-to-workspace 9; }
+
+ // Alternatively, there are commands to move just a single window:
+ // Mod+Ctrl+1 { move-window-to-workspace 1; }
+
+ // Switches focus between the current and the previous workspace.
+ // Mod+Tab { focus-workspace-previous; }
+
+ // The following binds move the focused window in and out of a column.
+ // If the window is alone, they will consume it into the nearby column to the side.
+ // If the window is already in a column, they will expel it out.
+ Mod+BracketLeft { consume-or-expel-window-left; }
+ Mod+BracketRight { consume-or-expel-window-right; }
+
+ // Consume one window from the right to the bottom of the focused column.
+ Mod+Comma { consume-window-into-column; }
+ // Expel the bottom window from the focused column to the right.
+ Mod+Period { expel-window-from-column; }
+
+ Mod+R { switch-preset-column-width; }
+ // Cycling through the presets in reverse order is also possible.
+ // Mod+R { switch-preset-column-width-back; }
+ Mod+Shift+R { switch-preset-window-height; }
+ Mod+Ctrl+R { reset-window-height; }
+ Mod+F { maximize-column; }
+ Mod+Shift+F { fullscreen-window; }
+
+ // Expand the focused column to space not taken up by other fully visible columns.
+ // Makes the column "fill the rest of the space".
+ Mod+Ctrl+F { expand-column-to-available-width; }
+
+ Mod+C { center-column; }
+
+ // Center all fully visible columns on screen.
+ Mod+Ctrl+C { center-visible-columns; }
+
+ // Finer width adjustments.
+ // This command can also:
+ // * set width in pixels: "1000"
+ // * adjust width in pixels: "-5" or "+5"
+ // * set width as a percentage of screen width: "25%"
+ // * adjust width as a percentage of screen width: "-10%" or "+10%"
+ // Pixel sizes use logical, or scaled, pixels. I.e. on an output with scale 2.0,
+ // set-column-width "100" will make the column occupy 200 physical screen pixels.
+ Mod+Minus { set-column-width "-10%"; }
+ Mod+Equal { set-column-width "+10%"; }
+
+ // Finer height adjustments when in column with other windows.
+ Mod+Shift+Minus { set-window-height "-10%"; }
+ Mod+Shift+Equal { set-window-height "+10%"; }
+
+ // Move the focused window between the floating and the tiling layout.
+ Mod+V { toggle-window-floating; }
+ Mod+Shift+V { switch-focus-between-floating-and-tiling; }
+
+ // Toggle tabbed column display mode.
+ // Windows in this column will appear as vertical tabs,
+ // rather than stacked on top of each other.
+ Mod+W { toggle-column-tabbed-display; }
+
+ // Actions to switch layouts.
+ // Note: if you uncomment these, make sure you do NOT have
+ // a matching layout switch hotkey configured in xkb options above.
+ // Having both at once on the same hotkey will break the switching,
+ // since it will switch twice upon pressing the hotkey (once by xkb, once by niri).
+ // Mod+Space { switch-layout "next"; }
+ // Mod+Shift+Space { switch-layout "prev"; }
+
+ Print { screenshot; }
+ Ctrl+Print { screenshot-screen; }
+ Alt+Print { screenshot-window; }
+
+ // Applications such as remote-desktop clients and software KVM switches may
+ // request that niri stops processing the keyboard shortcuts defined here
+ // so they may, for example, forward the key presses as-is to a remote machine.
+ // It's a good idea to bind an escape hatch to toggle the inhibitor,
+ // so a buggy application can't hold your session hostage.
+ //
+ // The allow-inhibiting=false property can be applied to other binds as well,
+ // which ensures niri always processes them, even when an inhibitor is active.
+ Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; }
+
+ // The quit action will show a confirmation dialog to avoid accidental exits.
+ Mod+Shift+E { quit; }
+ Ctrl+Alt+Delete { quit; }
+
+ // Powers off the monitors. To turn them back on, do any input like
+ // moving the mouse or pressing any other key.
+ Mod+Shift+P { power-off-monitors; }
+}
diff --git a/config/niri/jonbox.kdl b/config/niri/jonbox.kdl
new file mode 100644
index 0000000..950e728
--- /dev/null
+++ b/config/niri/jonbox.kdl
@@ -0,0 +1,579 @@
+// This config is in the KDL format: https://kdl.dev
+// "/-" comments out the following node.
+// Check the wiki for a full description of the configuration:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Introduction
+
+// Input device configuration.
+// Find the full list of options on the wiki:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Input
+input {
+ keyboard {
+ xkb {
+ // You can set rules, model, layout, variant and options.
+ // For more information, see xkeyboard-config(7).
+
+ // For example:
+ // layout "us,ru"
+ // options "grp:win_space_toggle,compose:ralt,ctrl:nocaps"
+ }
+
+ // Enable numlock on startup, omitting this setting disables it.
+ numlock
+ }
+
+ // Next sections include libinput settings.
+ // Omitting settings disables them, or leaves them at their default values.
+ touchpad {
+ // off
+ tap
+ // dwt
+ // dwtp
+ // drag false
+ // drag-lock
+ natural-scroll
+ // accel-speed 0.2
+ // accel-profile "flat"
+ // scroll-method "two-finger"
+ // disabled-on-external-mouse
+ }
+
+ mouse {
+ // off
+ // natural-scroll
+ // accel-speed 0.2
+ // accel-profile "flat"
+ // scroll-method "no-scroll"
+ }
+
+ trackpoint {
+ // off
+ // natural-scroll
+ // accel-speed 0.2
+ // accel-profile "flat"
+ // scroll-method "on-button-down"
+ // scroll-button 273
+ // middle-emulation
+ }
+
+ // Uncomment this to make the mouse warp to the center of newly focused windows.
+ // warp-mouse-to-focus
+
+ // Focus windows and outputs automatically when moving the mouse into them.
+ // Setting max-scroll-amount="0%" makes it work only on windows already fully on screen.
+ // focus-follows-mouse max-scroll-amount="0%"
+}
+
+// You can configure outputs by their name, which you can find
+// by running `niri msg outputs` while inside a niri instance.
+// The built-in laptop monitor is usually called "eDP-1".
+// Find more information on the wiki:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Outputs
+// Remember to uncomment the node by removing "/-"!
+/-output "eDP-1" {
+ // Uncomment this line to disable this output.
+ // off
+
+ // Resolution and, optionally, refresh rate of the output.
+ // The format is "<width>x<height>" or "<width>x<height>@<refresh rate>".
+ // If the refresh rate is omitted, niri will pick the highest refresh rate
+ // for the resolution.
+ // If the mode is omitted altogether or is invalid, niri will pick one automatically.
+ // Run `niri msg outputs` while inside a niri instance to list all outputs and their modes.
+ mode "1920x1080@120.030"
+
+ // You can use integer or fractional scale, for example use 1.5 for 150% scale.
+ scale 2
+
+ // Transform allows to rotate the output counter-clockwise, valid values are:
+ // normal, 90, 180, 270, flipped, flipped-90, flipped-180 and flipped-270.
+ transform "normal"
+
+ // Position of the output in the global coordinate space.
+ // This affects directional monitor actions like "focus-monitor-left", and cursor movement.
+ // The cursor can only move between directly adjacent outputs.
+ // Output scale and rotation has to be taken into account for positioning:
+ // outputs are sized in logical, or scaled, pixels.
+ // For example, a 3840×2160 output with scale 2.0 will have a logical size of 1920×1080,
+ // so to put another output directly adjacent to it on the right, set its x to 1920.
+ // If the position is unset or results in an overlap, the output is instead placed
+ // automatically.
+ position x=1280 y=0
+}
+
+// Settings that influence how windows are positioned and sized.
+// Find more information on the wiki:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Layout
+layout {
+ // Set gaps around windows in logical pixels.
+ gaps 16
+
+ // When to center a column when changing focus, options are:
+ // - "never", default behavior, focusing an off-screen column will keep at the left
+ // or right edge of the screen.
+ // - "always", the focused column will always be centered.
+ // - "on-overflow", focusing a column will center it if it doesn't fit
+ // together with the previously focused column.
+ center-focused-column "never"
+
+ // You can customize the widths that "switch-preset-column-width" (Mod+R) toggles between.
+ preset-column-widths {
+ // Proportion sets the width as a fraction of the output width, taking gaps into account.
+ // For example, you can perfectly fit four windows sized "proportion 0.25" on an output.
+ // The default preset widths are 1/3, 1/2 and 2/3 of the output.
+ proportion 0.33333
+ proportion 0.5
+ proportion 0.66667
+
+ // Fixed sets the width in logical pixels exactly.
+ // fixed 1920
+ }
+
+ // You can also customize the heights that "switch-preset-window-height" (Mod+Shift+R) toggles between.
+ // preset-window-heights { }
+
+ // You can change the default width of the new windows.
+ default-column-width { proportion 0.5; }
+ // If you leave the brackets empty, the windows themselves will decide their initial width.
+ // default-column-width {}
+
+ // By default focus ring and border are rendered as a solid background rectangle
+ // behind windows. That is, they will show up through semitransparent windows.
+ // This is because windows using client-side decorations can have an arbitrary shape.
+ //
+ // If you don't like that, you should uncomment `prefer-no-csd` below.
+ // Niri will draw focus ring and border *around* windows that agree to omit their
+ // client-side decorations.
+ //
+ // Alternatively, you can override it with a window rule called
+ // `draw-border-with-background`.
+
+ // You can change how the focus ring looks.
+ focus-ring {
+ // Uncomment this line to disable the focus ring.
+ // off
+
+ // How many logical pixels the ring extends out from the windows.
+ width 4
+
+ // Colors can be set in a variety of ways:
+ // - CSS named colors: "red"
+ // - RGB hex: "#rgb", "#rgba", "#rrggbb", "#rrggbbaa"
+ // - CSS-like notation: "rgb(255, 127, 0)", rgba(), hsl() and a few others.
+
+ // Color of the ring on the active monitor.
+ active-color "#7fc8ff"
+
+ // Color of the ring on inactive monitors.
+ inactive-color "#505050"
+
+ // You can also use gradients. They take precedence over solid colors.
+ // Gradients are rendered the same as CSS linear-gradient(angle, from, to).
+ // The angle is the same as in linear-gradient, and is optional,
+ // defaulting to 180 (top-to-bottom gradient).
+ // You can use any CSS linear-gradient tool on the web to set these up.
+ // Changing the color space is also supported, check the wiki for more info.
+ //
+ // active-gradient from="#80c8ff" to="#bbddff" angle=45
+
+ // You can also color the gradient relative to the entire view
+ // of the workspace, rather than relative to just the window itself.
+ // To do that, set relative-to="workspace-view".
+ //
+ // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
+ }
+
+ // You can also add a border. It's similar to the focus ring, but always visible.
+ border {
+ // The settings are the same as for the focus ring.
+ // If you enable the border, you probably want to disable the focus ring.
+ off
+
+ width 4
+ active-color "#ffc87f"
+ inactive-color "#505050"
+
+ // Color of the border around windows that request your attention.
+ urgent-color "#9b0000"
+
+ // active-gradient from="#ffbb66" to="#ffc880" angle=45 relative-to="workspace-view"
+ // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
+ }
+
+ // You can enable drop shadows for windows.
+ shadow {
+ // Uncomment the next line to enable shadows.
+ // on
+
+ // By default, the shadow draws only around its window, and not behind it.
+ // Uncomment this setting to make the shadow draw behind its window.
+ //
+ // Note that niri has no way of knowing about the CSD window corner
+ // radius. It has to assume that windows have square corners, leading to
+ // shadow artifacts inside the CSD rounded corners. This setting fixes
+ // those artifacts.
+ //
+ // However, instead you may want to set prefer-no-csd and/or
+ // geometry-corner-radius. Then, niri will know the corner radius and
+ // draw the shadow correctly, without having to draw it behind the
+ // window. These will also remove client-side shadows if the window
+ // draws any.
+ //
+ // draw-behind-window true
+
+ // You can change how shadows look. The values below are in logical
+ // pixels and match the CSS box-shadow properties.
+
+ // Softness controls the shadow blur radius.
+ softness 30
+
+ // Spread expands the shadow.
+ spread 5
+
+ // Offset moves the shadow relative to the window.
+ offset x=0 y=5
+
+ // You can also change the shadow color and opacity.
+ color "#0007"
+ }
+
+ // Struts shrink the area occupied by windows, similarly to layer-shell panels.
+ // You can think of them as a kind of outer gaps. They are set in logical pixels.
+ // Left and right struts will cause the next window to the side to always be visible.
+ // Top and bottom struts will simply add outer gaps in addition to the area occupied by
+ // layer-shell panels and regular gaps.
+ struts {
+ // left 64
+ // right 64
+ // top 64
+ // bottom 64
+ }
+}
+
+// Add lines like this to spawn processes at startup.
+// Note that running niri as a session supports xdg-desktop-autostart,
+// which may be more convenient to use.
+// See the binds section below for more spawn examples.
+
+// This line starts waybar, a commonly used bar for Wayland compositors.
+//spawn-at-startup "waybar"
+
+// Uncomment this line to ask the clients to omit their client-side decorations if possible.
+// If the client will specifically ask for CSD, the request will be honored.
+// Additionally, clients will be informed that they are tiled, removing some client-side rounded corners.
+// This option will also fix border/focus ring drawing behind some semitransparent windows.
+// After enabling or disabling this, you need to restart the apps for this to take effect.
+// prefer-no-csd
+
+// You can change the path where screenshots are saved.
+// A ~ at the front will be expanded to the home directory.
+// The path is formatted with strftime(3) to give you the screenshot date and time.
+screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"
+
+// You can also set this to null to disable saving screenshots to disk.
+// screenshot-path null
+
+// Animation settings.
+// The wiki explains how to configure individual animations:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Animations
+animations {
+ // Uncomment to turn off all animations.
+ // off
+
+ // Slow down all animations by this factor. Values below 1 speed them up instead.
+ // slowdown 3.0
+}
+
+// Window rules let you adjust behavior for individual windows.
+// Find more information on the wiki:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Window-Rules
+
+// Work around WezTerm's initial configure bug
+// by setting an empty default-column-width.
+window-rule {
+ // This regular expression is intentionally made as specific as possible,
+ // since this is the default config, and we want no false positives.
+ // You can get away with just app-id="wezterm" if you want.
+ match app-id=r#"^org\.wezfurlong\.wezterm$"#
+ default-column-width {}
+}
+
+// Open the Firefox picture-in-picture player as floating by default.
+window-rule {
+ // This app-id regular expression will work for both:
+ // - host Firefox (app-id is "firefox")
+ // - Flatpak Firefox (app-id is "org.mozilla.firefox")
+ match app-id=r#"firefox$"# title="^Picture-in-Picture$"
+ open-floating true
+}
+
+// Example: block out two password managers from screen capture.
+// (This example rule is commented out with a "/-" in front.)
+/-window-rule {
+ match app-id=r#"^org\.keepassxc\.KeePassXC$"#
+ match app-id=r#"^org\.gnome\.World\.Secrets$"#
+
+ block-out-from "screen-capture"
+
+ // Use this instead if you want them visible on third-party screenshot tools.
+ // block-out-from "screencast"
+}
+
+// Example: enable rounded corners for all windows.
+// (This example rule is commented out with a "/-" in front.)
+/-window-rule {
+ geometry-corner-radius 12
+ clip-to-geometry true
+}
+
+binds {
+ // Keys consist of modifiers separated by + signs, followed by an XKB key name
+ // in the end. To find an XKB name for a particular key, you may use a program
+ // like wev.
+ //
+ // "Mod" is a special modifier equal to Super when running on a TTY, and to Alt
+ // when running as a winit window.
+ //
+ // Most actions that you can bind here can also be invoked programmatically with
+ // `niri msg action do-something`.
+
+ // Mod-Shift-/, which is usually the same as Mod-?,
+ // shows a list of important hotkeys.
+ Mod+Shift+Slash { show-hotkey-overlay; }
+
+ // Suggested binds for running programs: terminal, app launcher, screen locker.
+ Mod+Return hotkey-overlay-title="Open a Terminal: kitty" { spawn "kitty"; }
+ Mod+D hotkey-overlay-title="Run an Application: wofi" { spawn "wofi" "--show" "drun"; }
+ Mod+W hotkey-overlay-title="Open a Web Browser: firefox" { spawn "firefox"; }
+
+ // You can also use a shell. Do this if you need pipes, multiple commands, etc.
+ // Note: the entire command goes as a single argument in the end.
+ // Mod+T { spawn "bash" "-c" "notify-send hello && exec alacritty"; }
+
+ // Example volume keys mappings for PipeWire & WirePlumber.
+ // The allow-when-locked=true property makes them work even when the session is locked.
+ XF86AudioRaiseVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1+"; }
+ XF86AudioLowerVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1-"; }
+ XF86AudioMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; }
+ XF86AudioMicMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; }
+
+ // Open/close the Overview: a zoomed-out view of workspaces and windows.
+ // You can also move the mouse into the top-left hot corner,
+ // or do a four-finger swipe up on a touchpad.
+ Mod+O repeat=false { toggle-overview; }
+
+ Mod+Q { close-window; }
+
+ Mod+Left { focus-column-left; }
+ Mod+Down { focus-window-down; }
+ Mod+Up { focus-window-up; }
+ Mod+Right { focus-column-right; }
+ Mod+H { focus-column-left; }
+ Mod+J { focus-window-down; }
+ Mod+K { focus-window-up; }
+ Mod+L { focus-column-right; }
+
+ Mod+Ctrl+Left { move-column-left; }
+ Mod+Ctrl+Down { move-window-down; }
+ Mod+Ctrl+Up { move-window-up; }
+ Mod+Ctrl+Right { move-column-right; }
+ Mod+Ctrl+H { move-column-left; }
+ Mod+Ctrl+J { move-window-down; }
+ Mod+Ctrl+K { move-window-up; }
+ Mod+Ctrl+L { move-column-right; }
+
+ // Alternative commands that move across workspaces when reaching
+ // the first or last window in a column.
+ // Mod+J { focus-window-or-workspace-down; }
+ // Mod+K { focus-window-or-workspace-up; }
+ // Mod+Ctrl+J { move-window-down-or-to-workspace-down; }
+ // Mod+Ctrl+K { move-window-up-or-to-workspace-up; }
+
+ Mod+Home { focus-column-first; }
+ Mod+End { focus-column-last; }
+ Mod+Ctrl+Home { move-column-to-first; }
+ Mod+Ctrl+End { move-column-to-last; }
+
+ Mod+Shift+Left { focus-monitor-left; }
+ Mod+Shift+Down { focus-monitor-down; }
+ Mod+Shift+Up { focus-monitor-up; }
+ Mod+Shift+Right { focus-monitor-right; }
+ Mod+Shift+H { focus-monitor-left; }
+ Mod+Shift+J { focus-monitor-down; }
+ Mod+Shift+K { focus-monitor-up; }
+ Mod+Shift+L { focus-monitor-right; }
+
+ Mod+Shift+Ctrl+Left { move-column-to-monitor-left; }
+ Mod+Shift+Ctrl+Down { move-column-to-monitor-down; }
+ Mod+Shift+Ctrl+Up { move-column-to-monitor-up; }
+ Mod+Shift+Ctrl+Right { move-column-to-monitor-right; }
+ Mod+Shift+Ctrl+H { move-column-to-monitor-left; }
+ Mod+Shift+Ctrl+J { move-column-to-monitor-down; }
+ Mod+Shift+Ctrl+K { move-column-to-monitor-up; }
+ Mod+Shift+Ctrl+L { move-column-to-monitor-right; }
+
+ // Alternatively, there are commands to move just a single window:
+ // Mod+Shift+Ctrl+Left { move-window-to-monitor-left; }
+ // ...
+
+ // And you can also move a whole workspace to another monitor:
+ // Mod+Shift+Ctrl+Left { move-workspace-to-monitor-left; }
+ // ...
+
+ Mod+Page_Down { focus-workspace-down; }
+ Mod+Page_Up { focus-workspace-up; }
+ Mod+U { focus-workspace-down; }
+ Mod+I { focus-workspace-up; }
+ Mod+Ctrl+Page_Down { move-column-to-workspace-down; }
+ Mod+Ctrl+Page_Up { move-column-to-workspace-up; }
+ Mod+Ctrl+U { move-column-to-workspace-down; }
+ Mod+Ctrl+I { move-column-to-workspace-up; }
+
+ // Alternatively, there are commands to move just a single window:
+ // Mod+Ctrl+Page_Down { move-window-to-workspace-down; }
+ // ...
+
+ Mod+Shift+Page_Down { move-workspace-down; }
+ Mod+Shift+Page_Up { move-workspace-up; }
+ Mod+Shift+U { move-workspace-down; }
+ Mod+Shift+I { move-workspace-up; }
+
+ // You can bind mouse wheel scroll ticks using the following syntax.
+ // These binds will change direction based on the natural-scroll setting.
+ //
+ // To avoid scrolling through workspaces really fast, you can use
+ // the cooldown-ms property. The bind will be rate-limited to this value.
+ // You can set a cooldown on any bind, but it's most useful for the wheel.
+ Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; }
+ Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; }
+ Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; }
+ Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; }
+
+ Mod+WheelScrollRight { focus-column-right; }
+ Mod+WheelScrollLeft { focus-column-left; }
+ Mod+Ctrl+WheelScrollRight { move-column-right; }
+ Mod+Ctrl+WheelScrollLeft { move-column-left; }
+
+ // Usually scrolling up and down with Shift in applications results in
+ // horizontal scrolling; these binds replicate that.
+ Mod+Shift+WheelScrollDown { focus-column-right; }
+ Mod+Shift+WheelScrollUp { focus-column-left; }
+ Mod+Ctrl+Shift+WheelScrollDown { move-column-right; }
+ Mod+Ctrl+Shift+WheelScrollUp { move-column-left; }
+
+ // Similarly, you can bind touchpad scroll "ticks".
+ // Touchpad scrolling is continuous, so for these binds it is split into
+ // discrete intervals.
+ // These binds are also affected by touchpad's natural-scroll, so these
+ // example binds are "inverted", since we have natural-scroll enabled for
+ // touchpads by default.
+ // Mod+TouchpadScrollDown { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02+"; }
+ // Mod+TouchpadScrollUp { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02-"; }
+
+ // You can refer to workspaces by index. However, keep in mind that
+ // niri is a dynamic workspace system, so these commands are kind of
+ // "best effort". Trying to refer to a workspace index bigger than
+ // the current workspace count will instead refer to the bottommost
+ // (empty) workspace.
+ //
+ // For example, with 2 workspaces + 1 empty, indices 3, 4, 5 and so on
+ // will all refer to the 3rd workspace.
+ Mod+1 { focus-workspace 1; }
+ Mod+2 { focus-workspace 2; }
+ Mod+3 { focus-workspace 3; }
+ Mod+4 { focus-workspace 4; }
+ Mod+5 { focus-workspace 5; }
+ Mod+6 { focus-workspace 6; }
+ Mod+7 { focus-workspace 7; }
+ Mod+8 { focus-workspace 8; }
+ Mod+9 { focus-workspace 9; }
+ Mod+Ctrl+1 { move-column-to-workspace 1; }
+ Mod+Ctrl+2 { move-column-to-workspace 2; }
+ Mod+Ctrl+3 { move-column-to-workspace 3; }
+ Mod+Ctrl+4 { move-column-to-workspace 4; }
+ Mod+Ctrl+5 { move-column-to-workspace 5; }
+ Mod+Ctrl+6 { move-column-to-workspace 6; }
+ Mod+Ctrl+7 { move-column-to-workspace 7; }
+ Mod+Ctrl+8 { move-column-to-workspace 8; }
+ Mod+Ctrl+9 { move-column-to-workspace 9; }
+
+ // Alternatively, there are commands to move just a single window:
+ // Mod+Ctrl+1 { move-window-to-workspace 1; }
+
+ // Switches focus between the current and the previous workspace.
+ // Mod+Tab { focus-workspace-previous; }
+
+ // The following binds move the focused window in and out of a column.
+ // If the window is alone, they will consume it into the nearby column to the side.
+ // If the window is already in a column, they will expel it out.
+ Mod+BracketLeft { consume-or-expel-window-left; }
+ Mod+BracketRight { consume-or-expel-window-right; }
+
+ // Consume one window from the right to the bottom of the focused column.
+ Mod+Comma { consume-window-into-column; }
+ // Expel the bottom window from the focused column to the right.
+ Mod+Period { expel-window-from-column; }
+
+ Mod+R { switch-preset-column-width; }
+ Mod+Shift+R { switch-preset-window-height; }
+ Mod+Ctrl+R { reset-window-height; }
+ Mod+F { maximize-column; }
+ Mod+Shift+F { fullscreen-window; }
+
+ // Expand the focused column to space not taken up by other fully visible columns.
+ // Makes the column "fill the rest of the space".
+ Mod+Ctrl+F { expand-column-to-available-width; }
+
+ Mod+C { center-column; }
+
+ // Center all fully visible columns on screen.
+ Mod+Ctrl+C { center-visible-columns; }
+
+ // Finer width adjustments.
+ // This command can also:
+ // * set width in pixels: "1000"
+ // * adjust width in pixels: "-5" or "+5"
+ // * set width as a percentage of screen width: "25%"
+ // * adjust width as a percentage of screen width: "-10%" or "+10%"
+ // Pixel sizes use logical, or scaled, pixels. I.e. on an output with scale 2.0,
+ // set-column-width "100" will make the column occupy 200 physical screen pixels.
+ Mod+Minus { set-column-width "-10%"; }
+ Mod+Equal { set-column-width "+10%"; }
+
+ // Finer height adjustments when in column with other windows.
+ Mod+Shift+Minus { set-window-height "-10%"; }
+ Mod+Shift+Equal { set-window-height "+10%"; }
+
+ // Move the focused window between the floating and the tiling layout.
+ Mod+V { toggle-window-floating; }
+ Mod+Shift+V { switch-focus-between-floating-and-tiling; }
+
+ // Actions to switch layouts.
+ // Note: if you uncomment these, make sure you do NOT have
+ // a matching layout switch hotkey configured in xkb options above.
+ // Having both at once on the same hotkey will break the switching,
+ // since it will switch twice upon pressing the hotkey (once by xkb, once by niri).
+ // Mod+Space { switch-layout "next"; }
+ // Mod+Shift+Space { switch-layout "prev"; }
+
+ Print { screenshot; }
+ Ctrl+Print { screenshot-screen; }
+ Alt+Print { screenshot-window; }
+
+ // Applications such as remote-desktop clients and software KVM switches may
+ // request that niri stops processing the keyboard shortcuts defined here
+ // so they may, for example, forward the key presses as-is to a remote machine.
+ // It's a good idea to bind an escape hatch to toggle the inhibitor,
+ // so a buggy application can't hold your session hostage.
+ //
+ // The allow-inhibiting=false property can be applied to other binds as well,
+ // which ensures niri always processes them, even when an inhibitor is active.
+ Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; }
+
+ // The quit action will show a confirmation dialog to avoid accidental exits.
+ Mod+Shift+E { quit; }
+ Ctrl+Alt+Delete { quit; }
+
+ // Powers off the monitors. To turn them back on, do any input like
+ // moving the mouse or pressing any other key.
+ Mod+Shift+P { power-off-monitors; }
+}
diff --git a/config/niri/jontop.kdl b/config/niri/jontop.kdl
new file mode 100644
index 0000000..950e728
--- /dev/null
+++ b/config/niri/jontop.kdl
@@ -0,0 +1,579 @@
+// This config is in the KDL format: https://kdl.dev
+// "/-" comments out the following node.
+// Check the wiki for a full description of the configuration:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Introduction
+
+// Input device configuration.
+// Find the full list of options on the wiki:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Input
+input {
+ keyboard {
+ xkb {
+ // You can set rules, model, layout, variant and options.
+ // For more information, see xkeyboard-config(7).
+
+ // For example:
+ // layout "us,ru"
+ // options "grp:win_space_toggle,compose:ralt,ctrl:nocaps"
+ }
+
+ // Enable numlock on startup, omitting this setting disables it.
+ numlock
+ }
+
+ // Next sections include libinput settings.
+ // Omitting settings disables them, or leaves them at their default values.
+ touchpad {
+ // off
+ tap
+ // dwt
+ // dwtp
+ // drag false
+ // drag-lock
+ natural-scroll
+ // accel-speed 0.2
+ // accel-profile "flat"
+ // scroll-method "two-finger"
+ // disabled-on-external-mouse
+ }
+
+ mouse {
+ // off
+ // natural-scroll
+ // accel-speed 0.2
+ // accel-profile "flat"
+ // scroll-method "no-scroll"
+ }
+
+ trackpoint {
+ // off
+ // natural-scroll
+ // accel-speed 0.2
+ // accel-profile "flat"
+ // scroll-method "on-button-down"
+ // scroll-button 273
+ // middle-emulation
+ }
+
+ // Uncomment this to make the mouse warp to the center of newly focused windows.
+ // warp-mouse-to-focus
+
+ // Focus windows and outputs automatically when moving the mouse into them.
+ // Setting max-scroll-amount="0%" makes it work only on windows already fully on screen.
+ // focus-follows-mouse max-scroll-amount="0%"
+}
+
+// You can configure outputs by their name, which you can find
+// by running `niri msg outputs` while inside a niri instance.
+// The built-in laptop monitor is usually called "eDP-1".
+// Find more information on the wiki:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Outputs
+// Remember to uncomment the node by removing "/-"!
+/-output "eDP-1" {
+ // Uncomment this line to disable this output.
+ // off
+
+ // Resolution and, optionally, refresh rate of the output.
+ // The format is "<width>x<height>" or "<width>x<height>@<refresh rate>".
+ // If the refresh rate is omitted, niri will pick the highest refresh rate
+ // for the resolution.
+ // If the mode is omitted altogether or is invalid, niri will pick one automatically.
+ // Run `niri msg outputs` while inside a niri instance to list all outputs and their modes.
+ mode "1920x1080@120.030"
+
+ // You can use integer or fractional scale, for example use 1.5 for 150% scale.
+ scale 2
+
+ // Transform allows to rotate the output counter-clockwise, valid values are:
+ // normal, 90, 180, 270, flipped, flipped-90, flipped-180 and flipped-270.
+ transform "normal"
+
+ // Position of the output in the global coordinate space.
+ // This affects directional monitor actions like "focus-monitor-left", and cursor movement.
+ // The cursor can only move between directly adjacent outputs.
+ // Output scale and rotation has to be taken into account for positioning:
+ // outputs are sized in logical, or scaled, pixels.
+ // For example, a 3840×2160 output with scale 2.0 will have a logical size of 1920×1080,
+ // so to put another output directly adjacent to it on the right, set its x to 1920.
+ // If the position is unset or results in an overlap, the output is instead placed
+ // automatically.
+ position x=1280 y=0
+}
+
+// Settings that influence how windows are positioned and sized.
+// Find more information on the wiki:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Layout
+layout {
+ // Set gaps around windows in logical pixels.
+ gaps 16
+
+ // When to center a column when changing focus, options are:
+ // - "never", default behavior, focusing an off-screen column will keep at the left
+ // or right edge of the screen.
+ // - "always", the focused column will always be centered.
+ // - "on-overflow", focusing a column will center it if it doesn't fit
+ // together with the previously focused column.
+ center-focused-column "never"
+
+ // You can customize the widths that "switch-preset-column-width" (Mod+R) toggles between.
+ preset-column-widths {
+ // Proportion sets the width as a fraction of the output width, taking gaps into account.
+ // For example, you can perfectly fit four windows sized "proportion 0.25" on an output.
+ // The default preset widths are 1/3, 1/2 and 2/3 of the output.
+ proportion 0.33333
+ proportion 0.5
+ proportion 0.66667
+
+ // Fixed sets the width in logical pixels exactly.
+ // fixed 1920
+ }
+
+ // You can also customize the heights that "switch-preset-window-height" (Mod+Shift+R) toggles between.
+ // preset-window-heights { }
+
+ // You can change the default width of the new windows.
+ default-column-width { proportion 0.5; }
+ // If you leave the brackets empty, the windows themselves will decide their initial width.
+ // default-column-width {}
+
+ // By default focus ring and border are rendered as a solid background rectangle
+ // behind windows. That is, they will show up through semitransparent windows.
+ // This is because windows using client-side decorations can have an arbitrary shape.
+ //
+ // If you don't like that, you should uncomment `prefer-no-csd` below.
+ // Niri will draw focus ring and border *around* windows that agree to omit their
+ // client-side decorations.
+ //
+ // Alternatively, you can override it with a window rule called
+ // `draw-border-with-background`.
+
+ // You can change how the focus ring looks.
+ focus-ring {
+ // Uncomment this line to disable the focus ring.
+ // off
+
+ // How many logical pixels the ring extends out from the windows.
+ width 4
+
+ // Colors can be set in a variety of ways:
+ // - CSS named colors: "red"
+ // - RGB hex: "#rgb", "#rgba", "#rrggbb", "#rrggbbaa"
+ // - CSS-like notation: "rgb(255, 127, 0)", rgba(), hsl() and a few others.
+
+ // Color of the ring on the active monitor.
+ active-color "#7fc8ff"
+
+ // Color of the ring on inactive monitors.
+ inactive-color "#505050"
+
+ // You can also use gradients. They take precedence over solid colors.
+ // Gradients are rendered the same as CSS linear-gradient(angle, from, to).
+ // The angle is the same as in linear-gradient, and is optional,
+ // defaulting to 180 (top-to-bottom gradient).
+ // You can use any CSS linear-gradient tool on the web to set these up.
+ // Changing the color space is also supported, check the wiki for more info.
+ //
+ // active-gradient from="#80c8ff" to="#bbddff" angle=45
+
+ // You can also color the gradient relative to the entire view
+ // of the workspace, rather than relative to just the window itself.
+ // To do that, set relative-to="workspace-view".
+ //
+ // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
+ }
+
+ // You can also add a border. It's similar to the focus ring, but always visible.
+ border {
+ // The settings are the same as for the focus ring.
+ // If you enable the border, you probably want to disable the focus ring.
+ off
+
+ width 4
+ active-color "#ffc87f"
+ inactive-color "#505050"
+
+ // Color of the border around windows that request your attention.
+ urgent-color "#9b0000"
+
+ // active-gradient from="#ffbb66" to="#ffc880" angle=45 relative-to="workspace-view"
+ // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
+ }
+
+ // You can enable drop shadows for windows.
+ shadow {
+ // Uncomment the next line to enable shadows.
+ // on
+
+ // By default, the shadow draws only around its window, and not behind it.
+ // Uncomment this setting to make the shadow draw behind its window.
+ //
+ // Note that niri has no way of knowing about the CSD window corner
+ // radius. It has to assume that windows have square corners, leading to
+ // shadow artifacts inside the CSD rounded corners. This setting fixes
+ // those artifacts.
+ //
+ // However, instead you may want to set prefer-no-csd and/or
+ // geometry-corner-radius. Then, niri will know the corner radius and
+ // draw the shadow correctly, without having to draw it behind the
+ // window. These will also remove client-side shadows if the window
+ // draws any.
+ //
+ // draw-behind-window true
+
+ // You can change how shadows look. The values below are in logical
+ // pixels and match the CSS box-shadow properties.
+
+ // Softness controls the shadow blur radius.
+ softness 30
+
+ // Spread expands the shadow.
+ spread 5
+
+ // Offset moves the shadow relative to the window.
+ offset x=0 y=5
+
+ // You can also change the shadow color and opacity.
+ color "#0007"
+ }
+
+ // Struts shrink the area occupied by windows, similarly to layer-shell panels.
+ // You can think of them as a kind of outer gaps. They are set in logical pixels.
+ // Left and right struts will cause the next window to the side to always be visible.
+ // Top and bottom struts will simply add outer gaps in addition to the area occupied by
+ // layer-shell panels and regular gaps.
+ struts {
+ // left 64
+ // right 64
+ // top 64
+ // bottom 64
+ }
+}
+
+// Add lines like this to spawn processes at startup.
+// Note that running niri as a session supports xdg-desktop-autostart,
+// which may be more convenient to use.
+// See the binds section below for more spawn examples.
+
+// This line starts waybar, a commonly used bar for Wayland compositors.
+//spawn-at-startup "waybar"
+
+// Uncomment this line to ask the clients to omit their client-side decorations if possible.
+// If the client will specifically ask for CSD, the request will be honored.
+// Additionally, clients will be informed that they are tiled, removing some client-side rounded corners.
+// This option will also fix border/focus ring drawing behind some semitransparent windows.
+// After enabling or disabling this, you need to restart the apps for this to take effect.
+// prefer-no-csd
+
+// You can change the path where screenshots are saved.
+// A ~ at the front will be expanded to the home directory.
+// The path is formatted with strftime(3) to give you the screenshot date and time.
+screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"
+
+// You can also set this to null to disable saving screenshots to disk.
+// screenshot-path null
+
+// Animation settings.
+// The wiki explains how to configure individual animations:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Animations
+animations {
+ // Uncomment to turn off all animations.
+ // off
+
+ // Slow down all animations by this factor. Values below 1 speed them up instead.
+ // slowdown 3.0
+}
+
+// Window rules let you adjust behavior for individual windows.
+// Find more information on the wiki:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Window-Rules
+
+// Work around WezTerm's initial configure bug
+// by setting an empty default-column-width.
+window-rule {
+ // This regular expression is intentionally made as specific as possible,
+ // since this is the default config, and we want no false positives.
+ // You can get away with just app-id="wezterm" if you want.
+ match app-id=r#"^org\.wezfurlong\.wezterm$"#
+ default-column-width {}
+}
+
+// Open the Firefox picture-in-picture player as floating by default.
+window-rule {
+ // This app-id regular expression will work for both:
+ // - host Firefox (app-id is "firefox")
+ // - Flatpak Firefox (app-id is "org.mozilla.firefox")
+ match app-id=r#"firefox$"# title="^Picture-in-Picture$"
+ open-floating true
+}
+
+// Example: block out two password managers from screen capture.
+// (This example rule is commented out with a "/-" in front.)
+/-window-rule {
+ match app-id=r#"^org\.keepassxc\.KeePassXC$"#
+ match app-id=r#"^org\.gnome\.World\.Secrets$"#
+
+ block-out-from "screen-capture"
+
+ // Use this instead if you want them visible on third-party screenshot tools.
+ // block-out-from "screencast"
+}
+
+// Example: enable rounded corners for all windows.
+// (This example rule is commented out with a "/-" in front.)
+/-window-rule {
+ geometry-corner-radius 12
+ clip-to-geometry true
+}
+
+binds {
+ // Keys consist of modifiers separated by + signs, followed by an XKB key name
+ // in the end. To find an XKB name for a particular key, you may use a program
+ // like wev.
+ //
+ // "Mod" is a special modifier equal to Super when running on a TTY, and to Alt
+ // when running as a winit window.
+ //
+ // Most actions that you can bind here can also be invoked programmatically with
+ // `niri msg action do-something`.
+
+ // Mod-Shift-/, which is usually the same as Mod-?,
+ // shows a list of important hotkeys.
+ Mod+Shift+Slash { show-hotkey-overlay; }
+
+ // Suggested binds for running programs: terminal, app launcher, screen locker.
+ Mod+Return hotkey-overlay-title="Open a Terminal: kitty" { spawn "kitty"; }
+ Mod+D hotkey-overlay-title="Run an Application: wofi" { spawn "wofi" "--show" "drun"; }
+ Mod+W hotkey-overlay-title="Open a Web Browser: firefox" { spawn "firefox"; }
+
+ // You can also use a shell. Do this if you need pipes, multiple commands, etc.
+ // Note: the entire command goes as a single argument in the end.
+ // Mod+T { spawn "bash" "-c" "notify-send hello && exec alacritty"; }
+
+ // Example volume keys mappings for PipeWire & WirePlumber.
+ // The allow-when-locked=true property makes them work even when the session is locked.
+ XF86AudioRaiseVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1+"; }
+ XF86AudioLowerVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1-"; }
+ XF86AudioMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; }
+ XF86AudioMicMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; }
+
+ // Open/close the Overview: a zoomed-out view of workspaces and windows.
+ // You can also move the mouse into the top-left hot corner,
+ // or do a four-finger swipe up on a touchpad.
+ Mod+O repeat=false { toggle-overview; }
+
+ Mod+Q { close-window; }
+
+ Mod+Left { focus-column-left; }
+ Mod+Down { focus-window-down; }
+ Mod+Up { focus-window-up; }
+ Mod+Right { focus-column-right; }
+ Mod+H { focus-column-left; }
+ Mod+J { focus-window-down; }
+ Mod+K { focus-window-up; }
+ Mod+L { focus-column-right; }
+
+ Mod+Ctrl+Left { move-column-left; }
+ Mod+Ctrl+Down { move-window-down; }
+ Mod+Ctrl+Up { move-window-up; }
+ Mod+Ctrl+Right { move-column-right; }
+ Mod+Ctrl+H { move-column-left; }
+ Mod+Ctrl+J { move-window-down; }
+ Mod+Ctrl+K { move-window-up; }
+ Mod+Ctrl+L { move-column-right; }
+
+ // Alternative commands that move across workspaces when reaching
+ // the first or last window in a column.
+ // Mod+J { focus-window-or-workspace-down; }
+ // Mod+K { focus-window-or-workspace-up; }
+ // Mod+Ctrl+J { move-window-down-or-to-workspace-down; }
+ // Mod+Ctrl+K { move-window-up-or-to-workspace-up; }
+
+ Mod+Home { focus-column-first; }
+ Mod+End { focus-column-last; }
+ Mod+Ctrl+Home { move-column-to-first; }
+ Mod+Ctrl+End { move-column-to-last; }
+
+ Mod+Shift+Left { focus-monitor-left; }
+ Mod+Shift+Down { focus-monitor-down; }
+ Mod+Shift+Up { focus-monitor-up; }
+ Mod+Shift+Right { focus-monitor-right; }
+ Mod+Shift+H { focus-monitor-left; }
+ Mod+Shift+J { focus-monitor-down; }
+ Mod+Shift+K { focus-monitor-up; }
+ Mod+Shift+L { focus-monitor-right; }
+
+ Mod+Shift+Ctrl+Left { move-column-to-monitor-left; }
+ Mod+Shift+Ctrl+Down { move-column-to-monitor-down; }
+ Mod+Shift+Ctrl+Up { move-column-to-monitor-up; }
+ Mod+Shift+Ctrl+Right { move-column-to-monitor-right; }
+ Mod+Shift+Ctrl+H { move-column-to-monitor-left; }
+ Mod+Shift+Ctrl+J { move-column-to-monitor-down; }
+ Mod+Shift+Ctrl+K { move-column-to-monitor-up; }
+ Mod+Shift+Ctrl+L { move-column-to-monitor-right; }
+
+ // Alternatively, there are commands to move just a single window:
+ // Mod+Shift+Ctrl+Left { move-window-to-monitor-left; }
+ // ...
+
+ // And you can also move a whole workspace to another monitor:
+ // Mod+Shift+Ctrl+Left { move-workspace-to-monitor-left; }
+ // ...
+
+ Mod+Page_Down { focus-workspace-down; }
+ Mod+Page_Up { focus-workspace-up; }
+ Mod+U { focus-workspace-down; }
+ Mod+I { focus-workspace-up; }
+ Mod+Ctrl+Page_Down { move-column-to-workspace-down; }
+ Mod+Ctrl+Page_Up { move-column-to-workspace-up; }
+ Mod+Ctrl+U { move-column-to-workspace-down; }
+ Mod+Ctrl+I { move-column-to-workspace-up; }
+
+ // Alternatively, there are commands to move just a single window:
+ // Mod+Ctrl+Page_Down { move-window-to-workspace-down; }
+ // ...
+
+ Mod+Shift+Page_Down { move-workspace-down; }
+ Mod+Shift+Page_Up { move-workspace-up; }
+ Mod+Shift+U { move-workspace-down; }
+ Mod+Shift+I { move-workspace-up; }
+
+ // You can bind mouse wheel scroll ticks using the following syntax.
+ // These binds will change direction based on the natural-scroll setting.
+ //
+ // To avoid scrolling through workspaces really fast, you can use
+ // the cooldown-ms property. The bind will be rate-limited to this value.
+ // You can set a cooldown on any bind, but it's most useful for the wheel.
+ Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; }
+ Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; }
+ Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; }
+ Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-to-workspace-up; }
+
+ Mod+WheelScrollRight { focus-column-right; }
+ Mod+WheelScrollLeft { focus-column-left; }
+ Mod+Ctrl+WheelScrollRight { move-column-right; }
+ Mod+Ctrl+WheelScrollLeft { move-column-left; }
+
+ // Usually scrolling up and down with Shift in applications results in
+ // horizontal scrolling; these binds replicate that.
+ Mod+Shift+WheelScrollDown { focus-column-right; }
+ Mod+Shift+WheelScrollUp { focus-column-left; }
+ Mod+Ctrl+Shift+WheelScrollDown { move-column-right; }
+ Mod+Ctrl+Shift+WheelScrollUp { move-column-left; }
+
+ // Similarly, you can bind touchpad scroll "ticks".
+ // Touchpad scrolling is continuous, so for these binds it is split into
+ // discrete intervals.
+ // These binds are also affected by touchpad's natural-scroll, so these
+ // example binds are "inverted", since we have natural-scroll enabled for
+ // touchpads by default.
+ // Mod+TouchpadScrollDown { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02+"; }
+ // Mod+TouchpadScrollUp { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02-"; }
+
+ // You can refer to workspaces by index. However, keep in mind that
+ // niri is a dynamic workspace system, so these commands are kind of
+ // "best effort". Trying to refer to a workspace index bigger than
+ // the current workspace count will instead refer to the bottommost
+ // (empty) workspace.
+ //
+ // For example, with 2 workspaces + 1 empty, indices 3, 4, 5 and so on
+ // will all refer to the 3rd workspace.
+ Mod+1 { focus-workspace 1; }
+ Mod+2 { focus-workspace 2; }
+ Mod+3 { focus-workspace 3; }
+ Mod+4 { focus-workspace 4; }
+ Mod+5 { focus-workspace 5; }
+ Mod+6 { focus-workspace 6; }
+ Mod+7 { focus-workspace 7; }
+ Mod+8 { focus-workspace 8; }
+ Mod+9 { focus-workspace 9; }
+ Mod+Ctrl+1 { move-column-to-workspace 1; }
+ Mod+Ctrl+2 { move-column-to-workspace 2; }
+ Mod+Ctrl+3 { move-column-to-workspace 3; }
+ Mod+Ctrl+4 { move-column-to-workspace 4; }
+ Mod+Ctrl+5 { move-column-to-workspace 5; }
+ Mod+Ctrl+6 { move-column-to-workspace 6; }
+ Mod+Ctrl+7 { move-column-to-workspace 7; }
+ Mod+Ctrl+8 { move-column-to-workspace 8; }
+ Mod+Ctrl+9 { move-column-to-workspace 9; }
+
+ // Alternatively, there are commands to move just a single window:
+ // Mod+Ctrl+1 { move-window-to-workspace 1; }
+
+ // Switches focus between the current and the previous workspace.
+ // Mod+Tab { focus-workspace-previous; }
+
+ // The following binds move the focused window in and out of a column.
+ // If the window is alone, they will consume it into the nearby column to the side.
+ // If the window is already in a column, they will expel it out.
+ Mod+BracketLeft { consume-or-expel-window-left; }
+ Mod+BracketRight { consume-or-expel-window-right; }
+
+ // Consume one window from the right to the bottom of the focused column.
+ Mod+Comma { consume-window-into-column; }
+ // Expel the bottom window from the focused column to the right.
+ Mod+Period { expel-window-from-column; }
+
+ Mod+R { switch-preset-column-width; }
+ Mod+Shift+R { switch-preset-window-height; }
+ Mod+Ctrl+R { reset-window-height; }
+ Mod+F { maximize-column; }
+ Mod+Shift+F { fullscreen-window; }
+
+ // Expand the focused column to space not taken up by other fully visible columns.
+ // Makes the column "fill the rest of the space".
+ Mod+Ctrl+F { expand-column-to-available-width; }
+
+ Mod+C { center-column; }
+
+ // Center all fully visible columns on screen.
+ Mod+Ctrl+C { center-visible-columns; }
+
+ // Finer width adjustments.
+ // This command can also:
+ // * set width in pixels: "1000"
+ // * adjust width in pixels: "-5" or "+5"
+ // * set width as a percentage of screen width: "25%"
+ // * adjust width as a percentage of screen width: "-10%" or "+10%"
+ // Pixel sizes use logical, or scaled, pixels. I.e. on an output with scale 2.0,
+ // set-column-width "100" will make the column occupy 200 physical screen pixels.
+ Mod+Minus { set-column-width "-10%"; }
+ Mod+Equal { set-column-width "+10%"; }
+
+ // Finer height adjustments when in column with other windows.
+ Mod+Shift+Minus { set-window-height "-10%"; }
+ Mod+Shift+Equal { set-window-height "+10%"; }
+
+ // Move the focused window between the floating and the tiling layout.
+ Mod+V { toggle-window-floating; }
+ Mod+Shift+V { switch-focus-between-floating-and-tiling; }
+
+ // Actions to switch layouts.
+ // Note: if you uncomment these, make sure you do NOT have
+ // a matching layout switch hotkey configured in xkb options above.
+ // Having both at once on the same hotkey will break the switching,
+ // since it will switch twice upon pressing the hotkey (once by xkb, once by niri).
+ // Mod+Space { switch-layout "next"; }
+ // Mod+Shift+Space { switch-layout "prev"; }
+
+ Print { screenshot; }
+ Ctrl+Print { screenshot-screen; }
+ Alt+Print { screenshot-window; }
+
+ // Applications such as remote-desktop clients and software KVM switches may
+ // request that niri stops processing the keyboard shortcuts defined here
+ // so they may, for example, forward the key presses as-is to a remote machine.
+ // It's a good idea to bind an escape hatch to toggle the inhibitor,
+ // so a buggy application can't hold your session hostage.
+ //
+ // The allow-inhibiting=false property can be applied to other binds as well,
+ // which ensures niri always processes them, even when an inhibitor is active.
+ Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; }
+
+ // The quit action will show a confirmation dialog to avoid accidental exits.
+ Mod+Shift+E { quit; }
+ Ctrl+Alt+Delete { quit; }
+
+ // Powers off the monitors. To turn them back on, do any input like
+ // moving the mouse or pressing any other key.
+ Mod+Shift+P { power-off-monitors; }
+}
diff --git a/config/nvim/lua/lsp.lua b/config/nvim/lua/lsp.lua
index 1056431..5d84e30 100644
--- a/config/nvim/lua/lsp.lua
+++ b/config/nvim/lua/lsp.lua
@@ -1,145 +1,192 @@
-local cmp = require("cmp")
-local nvim_lsp = require("lspconfig")
-local cmp_window = require("cmp.utils.window")
+-- https://raw.githubusercontent.com/neoclide/coc.nvim/master/doc/coc-example-config.lua
-vim.o.completeopt = "menuone,noselect"
-vim.o.shortmess = vim.o.shortmess .. "c"
+-- Some servers have issues with backup files, see #649
+vim.opt.backup = false
+vim.opt.writebackup = false
-local function on_attach(client, bufn)
- local function map(...)
- vim.api.nvim_buf_set_keymap(bufn, ...)
- end
+-- Having longer updatetime (default is 4000 ms = 4s) leads to noticeable
+-- delays and poor user experience
+vim.opt.updatetime = 300
- local function buf_set_option(...)
- vim.api.nvim_buf_set_option(bufn, ...)
- end
+-- Always show the signcolumn, otherwise it would shift the text each time
+-- diagnostics appeared/became resolved
+vim.opt.signcolumn = "yes"
- local opts = { noremap = true, silent = true }
- map("n", "gD", "<Cmd>lua vim.lsp.buf.declaration()<CR>", opts)
- map("n", "gd", "<Cmd>lua vim.lsp.buf.definition()<CR>", opts)
- map("n", "K", "<Cmd>lua vim.lsp.buf.hover()<CR>", opts)
- map("n", "gi", "<Cmd>lua vim.lsp.buf.implementation()<CR>", opts)
- map("n", "<C-k>", "<Cmd>lua vim.lsp.buf.signature_help()<CR>", opts)
- map("n", "<leader>D", "<Cmd>lua vim.lsp.buf.type_definition()<CR>", opts)
- map("n", "gr", "<Cmd>lua vim.lsp.buf.references()<CR>", opts)
- map("n", "<leader>e", "<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>", opts)
- map("n", "[d", "<Cmd>lua vim.lsp.diagnostic.goto_prev()<CR>", opts)
- map("n", "]d", "<Cmd>lua vim.lsp.diagnostic.goto_next()<CR>", opts)
- map("n", "<leader>q", "<Cmd>lua vim.lsp.diagnostic.set_loclist()<CR>", opts)
- map("n", "ga", "<Cmd>lua vim.lsp.buf.code_action()<CR>", opts)
+local keyset = vim.keymap.set
+-- Autocomplete
+function _G.check_back_space()
+ local col = vim.fn.col('.') - 1
+ return col == 0 or vim.fn.getline('.'):sub(col, col):match('%s') ~= nil
end
-local function has_words_before()
- local line, col = unpack(vim.api.nvim_win_get_cursor(0))
- return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
+-- Use Tab for trigger completion with characters ahead and navigate
+-- NOTE: There's always a completion item selected by default, you may want to enable
+-- no select by setting `"suggest.noselect": true` in your configuration file
+-- NOTE: Use command ':verbose imap <tab>' to make sure Tab is not mapped by
+-- other plugins before putting this into your config
+local opts = {silent = true, noremap = true, expr = true, replace_keycodes = false}
+keyset("i", "<TAB>", 'coc#pum#visible() ? coc#pum#next(1) : v:lua.check_back_space() ? "<TAB>" : coc#refresh()', opts)
+keyset("i", "<S-TAB>", [[coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"]], opts)
+
+-- Make <CR> to accept selected completion item or notify coc.nvim to format
+-- <C-g>u breaks current undo, please make your own choice
+keyset("i", "<cr>", [[coc#pum#visible() ? coc#pum#confirm() : "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"]], opts)
+
+-- Use <c-j> to trigger snippets
+keyset("i", "<c-j>", "<Plug>(coc-snippets-expand-jump)")
+-- Use <c-space> to trigger completion
+keyset("i", "<c-space>", "coc#refresh()", {silent = true, expr = true})
+
+-- Use `[g` and `]g` to navigate diagnostics
+-- Use `:CocDiagnostics` to get all diagnostics of current buffer in location list
+keyset("n", "[g", "<Plug>(coc-diagnostic-prev)", {silent = true})
+keyset("n", "]g", "<Plug>(coc-diagnostic-next)", {silent = true})
+
+-- GoTo code navigation
+keyset("n", "gd", "<Plug>(coc-definition)", {silent = true})
+keyset("n", "gy", "<Plug>(coc-type-definition)", {silent = true})
+keyset("n", "gi", "<Plug>(coc-implementation)", {silent = true})
+keyset("n", "gr", "<Plug>(coc-references)", {silent = true})
+
+
+-- Use K to show documentation in preview window
+function _G.show_docs()
+ local cw = vim.fn.expand('<cword>')
+ if vim.fn.index({'vim', 'help'}, vim.bo.filetype) >= 0 then
+ vim.api.nvim_command('h ' .. cw)
+ elseif vim.api.nvim_eval('coc#rpc#ready()') then
+ vim.fn.CocActionAsync('doHover')
+ else
+ vim.api.nvim_command('!' .. vim.o.keywordprg .. ' ' .. cw)
+ end
end
+keyset("n", "K", '<CMD>lua _G.show_docs()<CR>', {silent = true})
-local function feedkey(key, mode)
- vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
-end
-local function border(hl_name)
- return {
- { "╭", hl_name },
- { "─", hl_name },
- { "╮", hl_name },
- { "│", hl_name },
- { "╯", hl_name },
- { "─", hl_name },
- { "╰", hl_name },
- { "│", hl_name },
- }
-end
+-- Highlight the symbol and its references on a CursorHold event(cursor is idle)
+vim.api.nvim_create_augroup("CocGroup", {})
+vim.api.nvim_create_autocmd("CursorHold", {
+ group = "CocGroup",
+ command = "silent call CocActionAsync('highlight')",
+ desc = "Highlight symbol under cursor on CursorHold"
+})
-cmp_window.info_ = cmp_window.info
-cmp_window.info = function(self)
- local info = self:info_()
- info.scrollable = false
- return info
-end
-cmp.setup({
- window = {
- completion = {
- border = border "CmpBorder",
- winhighlight = "Normal:CmpPmenu,CursorLine:PmenuSel,Search:None",
- },
- documentation = {
- border = border "CmpDocBorder"
- },
- },
- snippet = {
- expand = function(args)
- vim.fn["vsnip#anonymous"](args.body)
- end,
- },
- mapping = cmp.mapping.preset.insert({
- ['<C-b>'] = cmp.mapping.scroll_docs(-4),
- ['<C-f>'] = cmp.mapping.scroll_docs(4),
- ['<C-Space>'] = cmp.mapping.complete(),
- ['<C-e>'] = cmp.mapping.abort(),
- ['<CR>'] = cmp.mapping.confirm({select = true}),
- ["<Tab>"] = cmp.mapping(function(fallback)
- if cmp.visible() then
- cmp.select_next_item()
- elseif vim.fn["vsnip#available"](1) == 1 then
- feedkey("<Plug>(vsnip-expand-or-jump)", "")
- elseif has_words_before() then
- cmp.complete()
- else
- fallback()
- end
- end, {"i", "s"}),
-
- ["<S-Tab"] = cmp.mapping(function()
- if cmp.visible() then
- cmp.select_prev_item()
- elseif vim.fn["vsnip#jumpable"](-1) == 1 then
- feedkey("<Plug>(vsnip-jump-prev)", "")
- end
- end, {"i", "s"}),
- }),
- sources = cmp.config.sources({
- { name = "nvim_lsp" },
- { name = "vsnip" },
- { name = "treesitter" },
- { name = "path", option = { trailing_slash = true }},
- { name = "buffer" }
- }),
-})
+-- Symbol renaming
+keyset("n", "<leader>rn", "<Plug>(coc-rename)", {silent = true})
-cmp.setup.cmdline(":", {
- mapping = cmp.mapping.preset.cmdline(),
- sources = cmp.config.sources({
- { name = "path" },
- }, {
- { name = "cmdline" },
- }),
-})
-vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(
- vim.lsp.diagnostic.on_publish_diagnostics, {
- virtual_text = true,
- signs = true,
- update_in_insert = true
- }
-)
+-- Formatting selected code
+keyset("x", "<leader>f", "<Plug>(coc-format-selected)", {silent = true})
+keyset("n", "<leader>f", "<Plug>(coc-format-selected)", {silent = true})
-local capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities())
-local servers = { "ccls", "bashls", "rnix", "texlab", "lua_ls" }
+-- Setup formatexpr specified filetype(s)
+vim.api.nvim_create_autocmd("FileType", {
+ group = "CocGroup",
+ pattern = "typescript,json",
+ command = "setl formatexpr=CocAction('formatSelected')",
+ desc = "Setup formatexpr specified filetype(s)."
+})
-for _, lang in pairs(servers) do
- nvim_lsp[lang].setup({
- root_dir = vim.loop.cwd,
- on_attach = on_attach,
- capabilities = capabilities
- })
-end
+-- Update signature help on jump placeholder
+vim.api.nvim_create_autocmd("User", {
+ group = "CocGroup",
+ pattern = "CocJumpPlaceholder",
+ command = "call CocActionAsync('showSignatureHelp')",
+ desc = "Update signature help on jump placeholder"
+})
+
+-- Apply codeAction to the selected region
+-- Example: `<leader>aap` for current paragraph
+local opts = {silent = true, nowait = true}
+keyset("x", "<leader>a", "<Plug>(coc-codeaction-selected)", opts)
+keyset("n", "<leader>a", "<Plug>(coc-codeaction-selected)", opts)
+
+-- Remap keys for apply code actions at the cursor position.
+keyset("n", "<leader>ac", "<Plug>(coc-codeaction-cursor)", opts)
+-- Remap keys for apply source code actions for current file.
+keyset("n", "<leader>as", "<Plug>(coc-codeaction-source)", opts)
+-- Apply the most preferred quickfix action on the current line.
+keyset("n", "<leader>qf", "<Plug>(coc-fix-current)", opts)
+
+-- Remap keys for apply refactor code actions.
+keyset("n", "<leader>re", "<Plug>(coc-codeaction-refactor)", { silent = true })
+keyset("x", "<leader>r", "<Plug>(coc-codeaction-refactor-selected)", { silent = true })
+keyset("n", "<leader>r", "<Plug>(coc-codeaction-refactor-selected)", { silent = true })
+
+-- Run the Code Lens actions on the current line
+keyset("n", "<leader>cl", "<Plug>(coc-codelens-action)", opts)
+
+
+-- Map function and class text objects
+-- NOTE: Requires 'textDocument.documentSymbol' support from the language server
+keyset("x", "if", "<Plug>(coc-funcobj-i)", opts)
+keyset("o", "if", "<Plug>(coc-funcobj-i)", opts)
+keyset("x", "af", "<Plug>(coc-funcobj-a)", opts)
+keyset("o", "af", "<Plug>(coc-funcobj-a)", opts)
+keyset("x", "ic", "<Plug>(coc-classobj-i)", opts)
+keyset("o", "ic", "<Plug>(coc-classobj-i)", opts)
+keyset("x", "ac", "<Plug>(coc-classobj-a)", opts)
+keyset("o", "ac", "<Plug>(coc-classobj-a)", opts)
+
+
+-- Remap <C-f> and <C-b> to scroll float windows/popups
+---@diagnostic disable-next-line: redefined-local
+local opts = {silent = true, nowait = true, expr = true}
+keyset("n", "<C-f>", 'coc#float#has_scroll() ? coc#float#scroll(1) : "<C-f>"', opts)
+keyset("n", "<C-b>", 'coc#float#has_scroll() ? coc#float#scroll(0) : "<C-b>"', opts)
+keyset("i", "<C-f>",
+ 'coc#float#has_scroll() ? "<c-r>=coc#float#scroll(1)<cr>" : "<Right>"', opts)
+keyset("i", "<C-b>",
+ 'coc#float#has_scroll() ? "<c-r>=coc#float#scroll(0)<cr>" : "<Left>"', opts)
+keyset("v", "<C-f>", 'coc#float#has_scroll() ? coc#float#scroll(1) : "<C-f>"', opts)
+keyset("v", "<C-b>", 'coc#float#has_scroll() ? coc#float#scroll(0) : "<C-b>"', opts)
+
+
+-- Use CTRL-S for selections ranges
+-- Requires 'textDocument/selectionRange' support of language server
+keyset("n", "<C-s>", "<Plug>(coc-range-select)", {silent = true})
+keyset("x", "<C-s>", "<Plug>(coc-range-select)", {silent = true})
+
+
+-- Add `:Format` command to format current buffer
+vim.api.nvim_create_user_command("Format", "call CocAction('format')", {})
+
+-- " Add `:Fold` command to fold current buffer
+vim.api.nvim_create_user_command("Fold", "call CocAction('fold', <f-args>)", {nargs = '?'})
+
+-- Add `:OR` command for organize imports of the current buffer
+vim.api.nvim_create_user_command("OR", "call CocActionAsync('runCommand', 'editor.action.organizeImport')", {})
+
+-- Add (Neo)Vim's native statusline support
+-- NOTE: Please see `:h coc-status` for integrations with external plugins that
+-- provide custom statusline: lightline.vim, vim-airline
+vim.opt.statusline:prepend("%{coc#status()}%{get(b:,'coc_current_function','')}")
+
+-- Mappings for CoCList
+-- code actions and coc stuff
+---@diagnostic disable-next-line: redefined-local
+local opts = {silent = true, nowait = true}
+-- Show all diagnostics
+keyset("n", "<space>a", ":<C-u>CocList diagnostics<cr>", opts)
+-- Manage extensions
+keyset("n", "<space>e", ":<C-u>CocList extensions<cr>", opts)
+-- Show commands
+keyset("n", "<space>c", ":<C-u>CocList commands<cr>", opts)
+-- Find symbol of current document
+keyset("n", "<space>o", ":<C-u>CocList outline<cr>", opts)
+-- Search workspace symbols
+keyset("n", "<space>s", ":<C-u>CocList -I symbols<cr>", opts)
+-- Do default action for next item
+keyset("n", "<space>j", ":<C-u>CocNext<cr>", opts)
+-- Do default action for previous item
+keyset("n", "<space>k", ":<C-u>CocPrev<cr>", opts)
+-- Resume latest coc list
+keyset("n", "<space>p", ":<C-u>CocListResume<cr>", opts)
require("nvim-treesitter.configs").setup({
highlight = { enable = true, },
})
require("gitsigns").setup({})
-
diff --git a/config/waybar/config.jonbox b/config/waybar/config.jonbox
new file mode 100644
index 0000000..c9ad192
--- /dev/null
+++ b/config/waybar/config.jonbox
@@ -0,0 +1,128 @@
+{
+ "layer": "top", // Waybar at top layer
+ "width": 1900, // Waybar width
+ "spacing": 4, // Gaps between modules (4px)
+ // Choose the order of the modules
+ "modules-left": ["hyprland/workspaces"],
+ "modules-center": ["hyprland/window"],
+ "modules-right": ["pulseaudio", "network", "cpu", "memory", "temperature", "clock", "tray"],
+
+ "sway/workspaces": {
+ "disable-scroll": true,
+ "all-outputs": true,
+ "warp-on-scroll": false,
+ "format": "{name}: {icon}",
+ "format-icons": {
+ "urgent": "",
+ "active": "",
+ "default": ""
+ }
+ },
+ "mpd": {
+ "format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ⸨{songPosition}|{queueLength}⸩ {volume}% ",
+ "format-disconnected": "Disconnected ",
+ "format-stopped": "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ",
+ "unknown-tag": "N/A",
+ "interval": 2,
+ "consume-icons": {
+ "on": " "
+ },
+ "random-icons": {
+ "off": "<span color=\"#f53c3c\"></span> ",
+ "on": " "
+ },
+ "repeat-icons": {
+ "on": " "
+ },
+ "single-icons": {
+ "on": "1 "
+ },
+ "state-icons": {
+ "paused": "",
+ "playing": ""
+ },
+ "tooltip-format": "MPD (connected)",
+ "tooltip-format-disconnected": "MPD (disconnected)"
+ },
+ "idle_inhibitor": {
+ "format": "{icon}",
+ "format-icons": {
+ "activated": "",
+ "deactivated": ""
+ }
+ },
+ "tray": {
+ // "icon-size": 21,
+ "spacing": 10
+ },
+ "clock": {
+ // "timezone": "America/New_York",
+ "tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>",
+ "format-alt": "{:%Y-%m-%d}"
+ },
+ "cpu": {
+ "format": "{usage}% ",
+ "tooltip": false
+ },
+ "memory": {
+ "format": "{}% "
+ },
+ "temperature": {
+ // "thermal-zone": 2,
+ // "hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input",
+ "critical-threshold": 80,
+ // "format-critical": "{temperatureC}°C {icon}",
+ "format": "{temperatureC}°C {icon}",
+ "format-icons": ["", "", ""]
+ },
+ "backlight": {
+ // "device": "acpi_video1",
+ "format": "{percent}% {icon}",
+ "format-icons": ["", "", "", "", "", "", "", "", ""]
+ },
+ "battery": {
+ "states": {
+ // "good": 95,
+ "warning": 30,
+ "critical": 15
+ },
+ "format": "{capacity}% {icon}",
+ "format-charging": "{capacity}% ",
+ "format-plugged": "{capacity}% ",
+ "format-alt": "{time} {icon}",
+ // "format-good": "", // An empty format will hide the module
+ // "format-full": "",
+ "format-icons": ["", "", "", "", ""]
+ },
+ "battery#bat2": {
+ "bat": "BAT2"
+ },
+ "network": {
+ // "interface": "wlp2*", // (Optional) To force the use of this interface
+ "format-wifi": "{essid} ({signalStrength}%) ",
+ "format-ethernet": "{ipaddr}/{cidr} ",
+ "tooltip-format": "{ifname} via {gwaddr} ",
+ "format-linked": "{ifname} (No IP) ",
+ "format-disconnected": "Disconnected ⚠",
+ "format-alt": "{ifname}: {ipaddr}/{cidr}"
+ },
+ "pulseaudio": {
+ // "scroll-step": 1, // %, can be a float
+ "format": "{volume}% {icon} {format_source}",
+ "format-bluetooth": "{volume}% {icon} {format_source}",
+ "format-bluetooth-muted": " {icon} {format_source}",
+ "format-muted": " {format_source}",
+ "format-source": "{volume}% ",
+ "format-source-muted": "",
+ "format-icons": {
+ "headphone": "",
+ "hands-free": "",
+ "headset": "",
+ "phone": "",
+ "portable": "",
+ "car": "",
+ "default": ["", "", ""]
+ },
+ "on-click": "pavucontrol"
+ }
+}
diff --git a/config/waybar/config.jontop b/config/waybar/config.jontop
new file mode 100644
index 0000000..b9b9968
--- /dev/null
+++ b/config/waybar/config.jontop
@@ -0,0 +1,128 @@
+{
+ "layer": "top", // Waybar at top layer
+ "width": 1300, // Waybar width
+ "spacing": 4, // Gaps between modules (4px)
+ // Choose the order of the modules
+ "modules-left": ["hyprland/workspaces"],
+ "modules-center": ["hyprland/window"],
+ "modules-right": ["pulseaudio", "network", "cpu", "memory", "temperature", "battery", "clock", "tray"],
+
+ "sway/workspaces": {
+ "disable-scroll": true,
+ "all-outputs": true,
+ "warp-on-scroll": false,
+ "format": "{name}: {icon}",
+ "format-icons": {
+ "urgent": "",
+ "active": "",
+ "default": ""
+ }
+ },
+ "mpd": {
+ "format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ⸨{songPosition}|{queueLength}⸩ {volume}% ",
+ "format-disconnected": "Disconnected ",
+ "format-stopped": "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ",
+ "unknown-tag": "N/A",
+ "interval": 2,
+ "consume-icons": {
+ "on": " "
+ },
+ "random-icons": {
+ "off": "<span color=\"#f53c3c\"></span> ",
+ "on": " "
+ },
+ "repeat-icons": {
+ "on": " "
+ },
+ "single-icons": {
+ "on": "1 "
+ },
+ "state-icons": {
+ "paused": "",
+ "playing": ""
+ },
+ "tooltip-format": "MPD (connected)",
+ "tooltip-format-disconnected": "MPD (disconnected)"
+ },
+ "idle_inhibitor": {
+ "format": "{icon}",
+ "format-icons": {
+ "activated": "",
+ "deactivated": ""
+ }
+ },
+ "tray": {
+ // "icon-size": 21,
+ "spacing": 10
+ },
+ "clock": {
+ // "timezone": "America/New_York",
+ "tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>",
+ "format-alt": "{:%Y-%m-%d}"
+ },
+ "cpu": {
+ "format": "{usage}% ",
+ "tooltip": false
+ },
+ "memory": {
+ "format": "{}% "
+ },
+ "temperature": {
+ // "thermal-zone": 2,
+ // "hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input",
+ "critical-threshold": 80,
+ // "format-critical": "{temperatureC}°C {icon}",
+ "format": "{temperatureC}°C {icon}",
+ "format-icons": ["", "", ""]
+ },
+ "backlight": {
+ // "device": "acpi_video1",
+ "format": "{percent}% {icon}",
+ "format-icons": ["", "", "", "", "", "", "", "", ""]
+ },
+ "battery": {
+ "states": {
+ // "good": 95,
+ "warning": 30,
+ "critical": 15
+ },
+ "format": "{capacity}% {icon}",
+ "format-charging": "{capacity}% ",
+ "format-plugged": "{capacity}% ",
+ "format-alt": "{time} {icon}",
+ // "format-good": "", // An empty format will hide the module
+ // "format-full": "",
+ "format-icons": ["", "", "", "", ""]
+ },
+ "battery#bat2": {
+ "bat": "BAT2"
+ },
+ "network": {
+ // "interface": "wlp2*", // (Optional) To force the use of this interface
+ "format-wifi": "{essid} ({signalStrength}%) ",
+ "format-ethernet": "{ipaddr}/{cidr} ",
+ "tooltip-format": "{ifname} via {gwaddr} ",
+ "format-linked": "{ifname} (No IP) ",
+ "format-disconnected": "Disconnected ⚠",
+ "format-alt": "{ifname}: {ipaddr}/{cidr}"
+ },
+ "pulseaudio": {
+ // "scroll-step": 1, // %, can be a float
+ "format": "{volume}% {icon} {format_source}",
+ "format-bluetooth": "{volume}% {icon} {format_source}",
+ "format-bluetooth-muted": " {icon} {format_source}",
+ "format-muted": " {format_source}",
+ "format-source": "{volume}% ",
+ "format-source-muted": "",
+ "format-icons": {
+ "headphone": "",
+ "hands-free": "",
+ "headset": "",
+ "phone": "",
+ "portable": "",
+ "car": "",
+ "default": ["", "", ""]
+ },
+ "on-click": "pavucontrol"
+ }
+}
diff --git a/config/waybar/style.css b/config/waybar/style.css
index 0a098e4..7b493d6 100644
--- a/config/waybar/style.css
+++ b/config/waybar/style.css
@@ -5,10 +5,10 @@
}
window#waybar {
- background-color: rgba(30, 30, 46, 0.5);
- color: #CDD6F4;
+ background-color: #2B2B30;
+ color: #CDCDDD;
transition-property: background-color;
- transition-duration: .5s;
+ transition-duration: .25s;
}
window#waybar.hidden {
@@ -58,7 +58,7 @@ button:hover {
}
#workspaces button.active {
- background-color: #64727D;
+ background-color: #7B7B90;
box-shadow: inset 0 -3px #ffffff;
}
@@ -94,6 +94,7 @@ button:hover {
#window,
#workspaces {
margin: 0 4px;
+ background-color: #2B2B2B;
}
/* If workspaces is the leftmost module, omit left margin */
@@ -107,7 +108,7 @@ button:hover {
}
#clock {
- background-color: #64727D;
+ background-color: #4b4b5b;
}
#battery {
@@ -142,16 +143,15 @@ label:focus {
}
#cpu {
- background-color: #2ecc71;
- color: #000000;
+ background-color: #4b4b5b;
}
#memory {
- background-color: #9b59b6;
+ background-color: #4b4b5b;
}
#disk {
- background-color: #964B00;
+ background-color: #4b4b5b;
}
#backlight {
@@ -159,7 +159,7 @@ label:focus {
}
#network {
- background-color: #2980b9;
+ background-color: #4b4b5b;
}
#network.disconnected {
@@ -167,22 +167,19 @@ label:focus {
}
#pulseaudio {
- background-color: #f1c40f;
- color: #000000;
+ background-color: #4b4b5b;
}
#pulseaudio.muted {
- background-color: #90b1b1;
- color: #2a5c45;
+ background-color: #4b4b5b;
}
#wireplumber {
- background-color: #fff0f5;
- color: #000000;
+ background-color: #4b4b5b;
}
#wireplumber.muted {
- background-color: #f53c3c;
+ background-color: #4b4b5b;
}
#custom-media {
@@ -200,15 +197,15 @@ label:focus {
}
#temperature {
- background-color: #f0932b;
+ background-color: #4b4b5b;
}
#temperature.critical {
- background-color: #eb4d4b;
+ background-color: #4b4b5b;
}
#tray {
- background-color: #2980b9;
+ background-color: #4b4b5b;
}
#tray > .passive {
@@ -217,7 +214,7 @@ label:focus {
#tray > .needs-attention {
-gtk-icon-effect: highlight;
- background-color: #eb4d4b;
+ background-color: #4b4b5b;
}
#idle_inhibitor {
diff --git a/default.nix b/default.nix
index f223141..f7d4eb1 100644
--- a/default.nix
+++ b/default.nix
@@ -66,5 +66,5 @@
};
};
- system.stateVersion = "23.11";
+ system.stateVersion = "25.05";
}
diff --git a/flake.lock b/flake.lock
index fc94683..cced915 100644
--- a/flake.lock
+++ b/flake.lock
@@ -7,11 +7,11 @@
]
},
"locked": {
- "lastModified": 1704100519,
- "narHash": "sha256-SgZC3cxquvwTN07vrYYT9ZkfvuhS5Y1k1F4+AMsuflc=",
+ "lastModified": 1750713626,
+ "narHash": "sha256-uM+hqdMxp+H53d8R7EHn2yY+nLNGgg59pdipIgCZ5yY=",
"owner": "nix-community",
"repo": "home-manager",
- "rev": "6e91c5df192395753d8e6d55a0352109cb559790",
+ "rev": "86402a17b6c67b07c5536354da5d56c14196de46",
"type": "github"
},
"original": {
@@ -20,13 +20,68 @@
"type": "github"
}
},
+ "lsfg-vk-flake": {
+ "inputs": {
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1753938292,
+ "narHash": "sha256-akeUWgvIIi163s/femzvTOuqqOiOB/8US5ioHsNqhYY=",
+ "owner": "pabloaul",
+ "repo": "lsfg-vk-flake",
+ "rev": "081cd66b1369188777ea146a759d35e99ea6b031",
+ "type": "github"
+ },
+ "original": {
+ "owner": "pabloaul",
+ "ref": "main",
+ "repo": "lsfg-vk-flake",
+ "type": "github"
+ }
+ },
+ "nix-index-database": {
+ "inputs": {
+ "nixpkgs": "nixpkgs"
+ },
+ "locked": {
+ "lastModified": 1728790083,
+ "narHash": "sha256-grMdAd4KSU6uPqsfLzA1B/3pb9GtGI9o8qb0qFzEU/Y=",
+ "owner": "Mic92",
+ "repo": "nix-index-database",
+ "rev": "5c54c33aa04df5dd4b0984b7eb861d1981009b22",
+ "type": "github"
+ },
+ "original": {
+ "owner": "Mic92",
+ "repo": "nix-index-database",
+ "type": "github"
+ }
+ },
"nixpkgs": {
"locked": {
- "lastModified": 1703961334,
- "narHash": "sha256-M1mV/Cq+pgjk0rt6VxoyyD+O8cOUiai8t9Q6Yyq4noY=",
+ "lastModified": 1728492678,
+ "narHash": "sha256-9UTxR8eukdg+XZeHgxW5hQA9fIKHsKCdOIUycTryeVw=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "5633bcff0c6162b9e4b5f1264264611e950c8ec7",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs-unstable": {
+ "locked": {
+ "lastModified": 1758035966,
+ "narHash": "sha256-qqIJ3yxPiB0ZQTT9//nFGQYn8X/PBoJbofA7hRKZnmE=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "b0d36bd0a420ecee3bc916c91886caca87c894e9",
+ "rev": "8d4ddb19d03c65a36ad8d189d001dc32ffb0306b",
"type": "github"
},
"original": {
@@ -36,18 +91,18 @@
"type": "github"
}
},
- "nixpkgs-stable": {
+ "nixpkgs_2": {
"locked": {
- "lastModified": 1703992652,
- "narHash": "sha256-C0o8AUyu8xYgJ36kOxJfXIroy9if/G6aJbNOpA5W0+M=",
+ "lastModified": 1763948260,
+ "narHash": "sha256-dY9qLD0H0zOUgU3vWacPY6Qc421BeQAfm8kBuBtPVE0=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "32f63574c85fbc80e4ba1fbb932cde9619bad25e",
+ "rev": "1c8ba8d3f7634acac4a2094eef7c32ad9106532c",
"type": "github"
},
"original": {
"owner": "nixos",
- "ref": "nixos-23.11",
+ "ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
}
@@ -55,8 +110,10 @@
"root": {
"inputs": {
"home-manager": "home-manager",
- "nixpkgs": "nixpkgs",
- "nixpkgs-stable": "nixpkgs-stable"
+ "lsfg-vk-flake": "lsfg-vk-flake",
+ "nix-index-database": "nix-index-database",
+ "nixpkgs": "nixpkgs_2",
+ "nixpkgs-unstable": "nixpkgs-unstable"
}
}
},
diff --git a/flake.nix b/flake.nix
index 69987c2..e93b180 100644
--- a/flake.nix
+++ b/flake.nix
@@ -2,18 +2,26 @@
description = "Jon's NixOS configuration";
inputs = {
- nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
- nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-23.11";
+ nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
+ nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
+
+ lsfg-vk-flake.url = "github:pabloaul/lsfg-vk-flake/main";
+ lsfg-vk-flake.inputs.nixpkgs.follows = "nixpkgs";
+
+ nix-index-database.url = "github:Mic92/nix-index-database";
};
outputs = inputs @ {
self,
nixpkgs,
+ nixpkgs-unstable,
+ nix-index-database,
+ lsfg-vk-flake,
...
}: let
system = "x86_64-linux";
@@ -41,8 +49,10 @@
mkHost = system: path:
lib.nixosSystem {
inherit system;
- specialArgs = {inherit lib inputs system;};
+ specialArgs = {inherit lib inputs system; rootPath=./.;};
modules = [
+ nix-index-database.nixosModules.nix-index
+ lsfg-vk-flake.nixosModules.default
{
nixpkgs.pkgs = pkgs;
modules.device.name = lib.mkDefault (builtins.baseNameOf path);
diff --git a/hosts/jonbox/default.nix b/hosts/jonbox/default.nix
index 0f525ca..1ed69bf 100644
--- a/hosts/jonbox/default.nix
+++ b/hosts/jonbox/default.nix
@@ -1,9 +1,13 @@
{
+ config,
inputs,
+ options,
lib,
pkgs,
+ rootPath,
...
-}: {
+ }: {
+ hardware.enableAllFirmware = true;
#Filesystems
fileSystems."/" =
{ device = "/dev/disk/by-uuid/83cafaff-8be3-477f-b13c-c47dafdf969d";
@@ -17,17 +21,17 @@
};
fileSystems."/mnt/jonshare" = {
- device = "homenas:/var/data/jon";
+ device = "192.168.0.145:/var/data/jon";
fsType = "nfs";
};
fileSystems."/mnt/plexshare" = {
- device = "homenas:/var/data/plex";
+ device = "192.168.0.145:/var/data/plex";
fsType = "nfs";
};
fileSystems."/mnt/share" = {
- device = "homenas:/var/data/shared";
+ device = "192.168.0.145:/var/data/shared";
fsType = "nfs";
};
@@ -43,9 +47,9 @@
font-awesome
liberation_ttf
noto-fonts
- noto-fonts-cjk
+ noto-fonts-cjk-sans
noto-fonts-emoji
- (nerdfonts.override { fonts = [ "FiraCode" ]; } )
+ nerd-fonts.fira-code
];
modules = {
@@ -61,17 +65,85 @@
browsers.firefox.enable = true;
games = {
enable = true;
+ prism.enable = true;
steam.enable = true;
+ vintagestory.enable = true;
+ openttd.enable = true;
+ luanti.enable = true;
+ };
+ editors = {
+ neovim.enable = true;
+ vscode.enable = true;
};
mpd.enable = true;
flatpak.enable = true;
newsboat.enable = true;
+ virt-manager.enable = true;
+ mutt.enable = true;
};
};
};
- home.manager.wayland.windowManager.hyprland.extraConfig = ''
- monitor=DP-2,1920x1080,0x0,1
- monitor=HDMI-A-2,1920x1080,1920x0,1
- '';
+ services.printing.enable = true;
+ services.mullvad-vpn.enable = true;
+
+ networking.nameservers = [
+ "1.1.1.1"
+ "1.0.0.1"
+ ];
+ services.resolved = {
+ enable = true;
+ dnssec = "true";
+ domains = ["~."];
+ fallbackDns = [
+ "1.1.1.1"
+ "1.0.0.1"
+ ];
+ dnsovertls = "true";
+ };
+
+ services.avahi = {
+ enable = true;
+ nssmdns4 = true;
+ openFirewall = true;
+ };
+
+ environment.systemPackages = [
+ pkgs.wineWowPackages.staging
+ pkgs.winetricks
+ pkgs.wineWowPackages.waylandFull
+
+ pkgs.linuxPackages_latest.perf
+ pkgs.perf-tools
+ pkgs.unstable.yafc-ce
+ ];
+
+ home.packages = with pkgs; [
+ cataclysm-dda
+ cataclysm-tlg
+ (callPackage (rootPath + /packages/freeciv/default.nix) {})
+ unstable.unciv
+ ];
+
+ #services.clamav.daemon.enable = true;
+ #services.clamav.updater.enable = true;
+
+ home.manager.wayland.windowManager.hyprland.settings = {
+ cursor = {
+ no_hardware_cursors = true;
+ };
+ monitor = [
+ "HDMI-A-2,1920x1080,0x0,1"
+ "DP-2,1920x1080,1920x0,1"
+ ];
+ };
+
+ programs.nix-ld.enable = true;
+ programs.nix-index.enableZshIntegration = false;
+ programs.nix-index.enableBashIntegration = false;
+
+ services.lsfg-vk = {
+ enable = false;
+ ui.enable = false;
+ };
}
diff --git a/hosts/jontop/default.nix b/hosts/jontop/default.nix
index b90038b..7b5c6c0 100644
--- a/hosts/jontop/default.nix
+++ b/hosts/jontop/default.nix
@@ -2,6 +2,7 @@
inputs,
lib,
pkgs,
+ rootPath,
...
}: {
#Filesystems
@@ -27,9 +28,10 @@
font-awesome
liberation_ttf
noto-fonts
- noto-fonts-cjk
+ noto-fonts-cjk-sans
noto-fonts-emoji
- (nerdfonts.override { fonts = [ "FiraCode" ]; } )
+ nerd-fonts.fira-code
+ texlive.combined.scheme-full
];
environment.systemPackages = [
@@ -46,12 +48,12 @@
hasBluetooth = true;
};
desktop = {
- hyprland.enable = true;
+ niri.enable = true;
apps = {
browsers.firefox.enable = true;
games = {
- enable = false;
- steam.enable = false;
+ enable = true;
+ steam.enable = true;
};
mpd.enable = false;
flatpak.enable = true;
@@ -59,4 +61,10 @@
};
};
};
+
+ home.packages = with pkgs; [
+ cataclysm-dda
+ (callPackage (rootPath + /packages/freeciv/default.nix) {})
+ unstable.unciv
+ ];
}
diff --git a/modules/desktop/apps/browsers/firefox.nix b/modules/desktop/apps/browsers/firefox.nix
index 3c647f1..2c87bd5 100644
--- a/modules/desktop/apps/browsers/firefox.nix
+++ b/modules/desktop/apps/browsers/firefox.nix
@@ -34,7 +34,7 @@ in
} + "/user.js");
search = {
force = true;
- default = "DuckDuckGo";
+ default = "ddg";
engines = {
"Nix Packages" = {
urls = [{
@@ -47,8 +47,8 @@ in
definedAliases = [ "@np" ];
};
"NixOS Wiki" = {
- urls = [{ template = "https://nixos.wiki/index.php?search={searchTerms}"; }];
- iconUpdateURL = "https://nixos.wiki/favicon.png";
+ urls = [{ template = "https://wiki.nixos.org/index.php?search={searchTerms}"; }];
+ icon = "https://wiki.nixos.org/favicon.png";
updateInterval = 24 * 60 * 60 * 1000;
definedAliases = [ "@nw" ];
};
diff --git a/modules/desktop/apps/editors/neovim.nix b/modules/desktop/apps/editors/neovim.nix
index ee6424b..f0040e0 100644
--- a/modules/desktop/apps/editors/neovim.nix
+++ b/modules/desktop/apps/editors/neovim.nix
@@ -1,12 +1,10 @@
{
config,
- options,
lib,
pkgs,
...
}: let
nvimConf = config.modules.desktop.apps.editors.neovim;
- configDir = config.nixosConfig.configDir;
in {
options.modules.desktop.apps.editors.neovim = {
enable = lib.mkOption {
@@ -24,11 +22,9 @@ in {
};
home.packages = [
- pkgs.rnix-lsp
- pkgs.ccls
- pkgs.nodePackages.bash-language-server
+ pkgs.clang-tools
+ pkgs.nil
pkgs.texlab
- pkgs.sumneko-lua-language-server
];
home.manager.programs.neovim = {
@@ -41,31 +37,37 @@ in {
luafile /etc/nixos/config/nvim/lua/settings.lua
luafile /etc/nixos/config/nvim/lua/lsp.lua
'';
+ coc.enable = true;
+ coc.settings = {
+ "suggest.noselect" = true;
+ "suggest.enablePreview" = true;
+ "suggest.enablePreselect" = false;
+ "suggest.disableKind" = true;
+ "inlayHint.enable" = false;
+
+ "nix.enableLanguageServer" = true;
+ "nix.serverPath" = "nil";
+ };
plugins = with pkgs.vimPlugins; [
nvim-web-devicons
gitsigns-nvim
- nvim-tree-lua
catppuccin-nvim
+ vim-commentary
+ vim-fugitive
+
+ popup-nvim
+ plenary-nvim
+ telescope-nvim
+
nvim-lspconfig
- nvim-cmp
- cmp-cmdline
- cmp-nvim-lsp
- cmp-buffer
- cmp-path
- cmp-vsnip
- cmp-treesitter
-
- vim-nix
- vim-vsnip
- nvim-treesitter.withAllGrammars
- neoformat
+ nvim-treesitter nvim-treesitter.withAllGrammars
- bufferline-nvim
- lualine-nvim
- alpha-nvim
- ];
+ coc-clangd
+ coc-lua
+ coc-spell-checker
+ ];
};
};
}
diff --git a/modules/desktop/apps/editors/vscode.nix b/modules/desktop/apps/editors/vscode.nix
new file mode 100644
index 0000000..a775be8
--- /dev/null
+++ b/modules/desktop/apps/editors/vscode.nix
@@ -0,0 +1,27 @@
+{
+ config,
+ options,
+ lib,
+ pkgs,
+ ...
+}: let
+ codeConf = config.modules.desktop.apps.editors.vscode;
+ configDir = config.nixosConfig.configDir;
+in {
+ options.modules.desktop.apps.editors.vscode = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ };
+
+ config = lib.mkIf (codeConf.enable) {
+ home.manager.programs.vscode = {
+ enable = true;
+ profiles.default.extensions = with pkgs.vscode-extensions; [
+ catppuccin.catppuccin-vsc catppuccin.catppuccin-vsc-icons
+ ms-dotnettools.csharp
+ ];
+ };
+ };
+}
diff --git a/modules/desktop/apps/games/lunati.nix b/modules/desktop/apps/games/lunati.nix
new file mode 100644
index 0000000..1c06b4f
--- /dev/null
+++ b/modules/desktop/apps/games/lunati.nix
@@ -0,0 +1,24 @@
+{
+ config,
+ options,
+ lib,
+ pkgs,
+ rootPath,
+ ...
+}: let
+ luantiConf = config.modules.desktop.apps.games.luanti;
+ configDir = config.nixosConfig.configDir;
+in {
+ options.modules.desktop.apps.games.luanti = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ };
+
+ config = lib.mkIf (luantiConf.enable) {
+ home.packages = with pkgs; [
+ luanti
+ ];
+ };
+}
diff --git a/modules/desktop/apps/games/lutris.nix b/modules/desktop/apps/games/lutris.nix
new file mode 100644
index 0000000..c1c5d31
--- /dev/null
+++ b/modules/desktop/apps/games/lutris.nix
@@ -0,0 +1,23 @@
+{
+ config,
+ options,
+ lib,
+ pkgs,
+ ...
+}: let
+ lutrisConf = config.modules.desktop.apps.games.lutris;
+ configDir = config.nixosConfig.configDir;
+in {
+ options.modules.desktop.apps.games.lutris = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ };
+
+ config = lib.mkIf (lutrisConf.enable) {
+ environment.systemPackages = [
+ pkgs.lutris
+ ];
+ };
+}
diff --git a/modules/desktop/apps/games/openttd.nix b/modules/desktop/apps/games/openttd.nix
new file mode 100644
index 0000000..f66ccc0
--- /dev/null
+++ b/modules/desktop/apps/games/openttd.nix
@@ -0,0 +1,28 @@
+{
+ config,
+ options,
+ lib,
+ pkgs,
+ rootPath,
+ ...
+}: let
+ openttdConf = config.modules.desktop.apps.games.openttd;
+ configDir = config.nixosConfig.configDir;
+in {
+ options.modules.desktop.apps.games.openttd = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ };
+
+ config = lib.mkIf (openttdConf.enable) {
+ home.packages = with pkgs; [
+ openttd
+ ];
+
+ fonts.packages = with pkgs; [
+ openttd-ttf
+ ];
+ };
+}
diff --git a/modules/desktop/apps/games/prism.nix b/modules/desktop/apps/games/prism.nix
new file mode 100644
index 0000000..d3ceee7
--- /dev/null
+++ b/modules/desktop/apps/games/prism.nix
@@ -0,0 +1,23 @@
+{
+ config,
+ options,
+ lib,
+ pkgs,
+ ...
+}: let
+ prismConf = config.modules.desktop.apps.games.prism;
+ configDir = config.nixosConfig.configDir;
+in {
+ options.modules.desktop.apps.games.prism = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ };
+
+ config = lib.mkIf (prismConf.enable) {
+ environment.systemPackages = [
+ pkgs.prismlauncher
+ ];
+ };
+}
diff --git a/modules/desktop/apps/games/steam.nix b/modules/desktop/apps/games/steam.nix
index 50b5c62..51396f1 100644
--- a/modules/desktop/apps/games/steam.nix
+++ b/modules/desktop/apps/games/steam.nix
@@ -29,6 +29,11 @@ in {
remotePlay.openFirewall = true;
dedicatedServer.openFirewall = true;
gamescopeSession.enable = true;
+ protontricks.enable = true;
};
+
+ environment.systemPackages = with pkgs; [
+ protonup-qt
+ ];
};
}
diff --git a/modules/desktop/apps/games/vintagestory.nix b/modules/desktop/apps/games/vintagestory.nix
new file mode 100644
index 0000000..a15935a
--- /dev/null
+++ b/modules/desktop/apps/games/vintagestory.nix
@@ -0,0 +1,31 @@
+{
+ config,
+ options,
+ lib,
+ pkgs,
+ rootPath,
+ ...
+}: let
+ vsConf = config.modules.desktop.apps.games.vintagestory;
+ configDir = config.nixosConfig.configDir;
+in {
+ options.modules.desktop.apps.games.vintagestory = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ };
+
+ config = lib.mkIf (vsConf.enable) {
+ home.manager.xdg.mimeApps = {
+ defaultApplications = {
+ "x-scheme-handler/vintagestoryjoin" = [ "Vintagestory_url_connect.desktop" ];
+ "x-scheme-handler/vintagestorymodinstall" = [ "Vintagestory_url_mod.desktop" ];
+ };
+ };
+
+ home.packages = with pkgs; [
+ (callPackage (rootPath + /packages/vintagestory/default.nix) {})
+ ];
+ };
+}
diff --git a/modules/desktop/apps/mpd.nix b/modules/desktop/apps/mpd.nix
index e7af8c3..17b22ec 100644
--- a/modules/desktop/apps/mpd.nix
+++ b/modules/desktop/apps/mpd.nix
@@ -18,12 +18,11 @@ in
config = lib.mkIf (mpdConfig.enable) {
home.packages = [
pkgs.mpc-cli
- pkgs.ncmpcpp
];
services.mpd = {
enable = true;
- musicDirectory = /home/jon/mus;
+ musicDirectory = "/home/jon/mus";
extraConfig = ''
audio_output {
type "pipewire"
@@ -34,6 +33,11 @@ audio_output {
};
systemd.services.mpd.environment = {
XDG_RUNTIME_DIR = "/run/user/1000";
+ };
+
+ home.manager.programs.ncmpcpp = {
+ enable = true;
+ mpdMusicDir = /home/jon/mus;
};
};
}
diff --git a/modules/desktop/apps/mutt-wizard.nix b/modules/desktop/apps/mutt-wizard.nix
new file mode 100644
index 0000000..da7b779
--- /dev/null
+++ b/modules/desktop/apps/mutt-wizard.nix
@@ -0,0 +1,46 @@
+{
+ config,
+ options,
+ lib,
+ pkgs,
+ ...
+}: let
+ muttConfig = config.modules.desktop.apps.mutt;
+in
+{
+ options.modules.desktop.apps.mutt = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ };
+
+ config = lib.mkIf (muttConfig.enable) {
+ home.packages = [
+ pkgs.neomutt
+ pkgs.isync
+ pkgs.lynx
+ pkgs.mutt-wizard
+ ];
+
+ systemd.timers."auto-mailsync" = {
+ wantedBy = [ "timers.target" ];
+ timerConfig = {
+ OnBootSec = "10m";
+ OnUnitActiveSec = "10m";
+ Unit = "auto-mailsync.service";
+ };
+ };
+
+ systemd.services."auto-mailsync" = {
+ script = ''
+ set -eu
+ /run/current-system/sw/bin/bash -l -c '${pkgs.mutt-wizard}/bin/mailsync -Y'
+ '';
+ serviceConfig = {
+ Type = "oneshot";
+ User = "jon";
+ };
+ };
+ };
+}
diff --git a/modules/desktop/apps/virt.nix b/modules/desktop/apps/virt.nix
new file mode 100644
index 0000000..a9eaef4
--- /dev/null
+++ b/modules/desktop/apps/virt.nix
@@ -0,0 +1,49 @@
+{
+ config,
+ options,
+ lib,
+ pkgs,
+ ...
+}: let
+ virtConfig = config.modules.desktop.apps.virt-manager;
+in
+{
+ options.modules.desktop.apps.virt-manager = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ };
+
+ config = lib.mkIf (virtConfig.enable) {
+ home.packages = [
+ pkgs.virtiofsd
+ ];
+
+ virtualisation.libvirtd = {
+ enable = true;
+ qemu = {
+ package = pkgs.qemu_kvm;
+ runAsRoot = true;
+ swtpm.enable = true;
+ ovmf = {
+ enable = true;
+ packages = [(pkgs.OVMF.override {
+ secureBoot = true;
+ tpmSupport = true;
+ }).fd];
+ };
+ };
+ };
+ programs.virt-manager.enable = true;
+
+ home.manager.dconf.settings = {
+ "org/virt-manager/virt-manager/connections" = {
+ autoconnect = ["qemu:///system"];
+ uris = ["qemu:///system"];
+ };
+ };
+
+ user.extraGroups = ["libvirtd"];
+ };
+}
diff --git a/modules/desktop/apps/vpn.nix b/modules/desktop/apps/vpn.nix
new file mode 100644
index 0000000..8cddb39
--- /dev/null
+++ b/modules/desktop/apps/vpn.nix
@@ -0,0 +1,23 @@
+{
+ config,
+ options,
+ lib,
+ pkgs,
+ ...
+}: let
+ vpnConfig = config.modules.desktop.apps.vpn;
+in
+{
+ options.modules.desktop.apps.vpn = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ };
+
+ config = lib.mkIf (vpnConfig.enable) {
+ home.packages = [
+ pkgs.mullvad-vpn
+ ];
+ };
+}
diff --git a/modules/desktop/greetd.nix b/modules/desktop/greetd.nix
index f9b6f90..0bc5208 100644
--- a/modules/desktop/greetd.nix
+++ b/modules/desktop/greetd.nix
@@ -18,5 +18,6 @@ in {
services.greetd = {
enable = true;
};
+ security.pam.services.greetd.enableGnomeKeyring = true;
};
}
diff --git a/modules/desktop/hyprland.nix b/modules/desktop/hyprland.nix
index 0440453..2839b9a 100644
--- a/modules/desktop/hyprland.nix
+++ b/modules/desktop/hyprland.nix
@@ -10,8 +10,6 @@
defaultApps = config.modules.desktop.defaultApplications.apps;
configDir = config.nixosConfig.configDir;
- screenshotarea = "hyprctl keyword animation 'fadeOut,0,0,default'; grimblast --notify copysave area; hyprctl keyword animation 'fadeOut,1,4,default'";
-
# binds $mod + [shift +] {1..10} to [move to] workspace {1..10}
workspaces = builtins.concatLists (builtins.genList (
x: let
@@ -34,12 +32,6 @@
size = 3;
passes = 1;
};
- drop_shadow = true;
- shadow_ignore_window = true;
- shadow_offset = "0 2";
- shadow_range = 20;
- shadow_render_power = 3;
- "col.shadow" = "rgba(00000055)";
};
animations = {
@@ -85,7 +77,10 @@
"$mod, D, exec, wofi --show drun"
"$mod, Return, exec, ${defaultApps.terminal.cmd}"
"$mod, W, exec, ${defaultApps.browser.cmd}"
- "$mod ALTL, B, exec, killall -SIGUSR2 waybar"
+ "$mod ALT, B, exec, killall -SIGUSR2 waybar"
+
+ #Screenshot
+ "$mod, Print, exec, slurp | grim -g - ~/pic/$(date +%s).png"
]
++ workspaces;
@@ -108,14 +103,16 @@ in {
config = lib.mkIf (hyprlandConf.enable) (lib.mkMerge [
{
- environment.variables.WLR_NO_HARDWARE_CURSORS = "1";
-
home.packages = [
pkgs.killall
pkgs.wl-clipboard
pkgs.wdisplays
pkgs.swaylock
pkgs.swayidle
+ pkgs.slurp
+ pkgs.grim
+ pkgs.mako
+ pkgs.libnotify
pkgs.wofi
pkgs.jq
pkgs.swww
@@ -134,13 +131,18 @@ in {
};
};
};
- extraPortals = [pkgs.xdg-desktop-portal-gtk];
- config.common.default = ["wlr" "gtk"];
+ extraPortals = [
+ pkgs.xdg-desktop-portal-gtk
+ pkgs.xdg-desktop-portal-hyprland
+ ];
+ config.common.default = ["wlr" "gtk" "hyprland" ];
};
+ environment.sessionVariables.NIXOS_OZONE_WL = "1";
home.manager.wayland.windowManager.hyprland = {
enable = true;
xwayland.enable = hyprlandConf.xwayland;
+ systemd.enable = true;
settings = {
"$mod" = "SUPER";
@@ -170,18 +172,35 @@ in {
"swww img ${configDir}/hypr/wallpaper.png"
];
- env = [
+ env = lib.mkMerge [
+ ([
"XDG_CURRENT_DESKTOP,Hyprland"
"XDG_SESSION_TYPE,wayland"
"XDG_SESSION_DESKTOP,Hyprland"
- "GDK_BACKEND,wayland"
+ "GDK_BACKEND,wayland,x11"
+ "SDL_VIDEODRIVER,wayland"
+ "CLUTTER_BACKEND,wayland"
+ "MOZ_ENABLE_WAYLAND,1"
+ "MOZ_DISABLE_RDD_SANDBOX,1"
+ "_JAVA_AWT_WM_NONREPARENTING,1"
+ "QT_AUTO_SCREEN_SCALE_FACTOR,1"
"QT_QPA_PLATFORM,wayland"
"QT_WAYLAND_DISABLE_WINDOWDECORATION,1"
- "QT_AUTO_SCREEN_SCALE_FACTOR,1"
-
- "SDL_VIDEODRIVER,wayland"
- ];
+
+ "disable_hyprland_logo,true"
+ "force_default_wallpaper,0"
+ ])
+ ( lib.mkIf (config.modules.device.gpu == "nvidia")
+ [
+ "GBM_BACKEND,nvidia"
+ "__GLX_VENDOR_LIBRARY_NAME,nvidia"
+ "LIBVA_DRIVER_NAME,nvidia"
+ "NVD_BACKEND,direct"
+ "WLR_DRM_NO_ATOMIC,1"
+ "WLR_USE_LIBINPUT,1"
+ "WLR_RENDERER_ALLOW_SOFTWARE,1"
+ ])];
decoration = decoration;
animations = animations;
@@ -204,16 +223,6 @@ in {
security.pam.services.swaylock = {};
}
- (lib.mkIf (device.gpu == "nvidia") {
- home.manager.wayland.windowManager.hyprland.settings.env = [
- "GBM_BACKEND,nvidia-drm"
- "__GLX_VENDOR_LIBRARY_NAME,nvidia"
- "LIBVA_DRIVER_NAME,nvidia"
- "__GL_GSYNC_ALLOWED"
- "__GL_VRR_ALLOWED"
- "WLR_DRM_NO_ATOMIC,1"
- ];
- })
(lib.mkIf (config.modules.desktop.greetd.enable) {
services.greetd.settings = {
default_session.command = ''
diff --git a/modules/desktop/niri.nix b/modules/desktop/niri.nix
new file mode 100644
index 0000000..1cf80e8
--- /dev/null
+++ b/modules/desktop/niri.nix
@@ -0,0 +1,67 @@
+{
+ config,
+ options,
+ lib,
+ pkgs,
+ ...
+}: let
+ niriConf = config.modules.desktop.niri;
+ device = config.modules.device;
+ defaultApps = config.modules.desktop.defaultApplications.apps;
+ configDir = config.nixosConfig.configDir;
+in {
+ options.modules.desktop.niri = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ };
+ };
+
+ config = lib.mkIf (niriConf.enable) (lib.mkMerge [
+ {
+ programs.niri.enable = true;
+ programs.waybar.enable = true;
+ programs.xwayland.enable = true;
+
+ home.manager.services.polkit-gnome.enable = true;
+
+ home.packages = with pkgs; [
+ libnotify
+ killall
+ wdisplays
+ xwayland-satellite
+ wofi
+ mako
+ jq
+ swww
+ ];
+
+ modules.device.displayProtocol = "wayland";
+
+ environment.sessionVariables.NIXOS_OZONE_WL = "1";
+
+ home.manager.xdg.configFile."niri/config.kdl".source = "${configDir}/niri/${config.networking.hostName}.kdl";
+
+ system.userActivationScripts.linkwaybar.text = ''
+ if [[ ! -h "$HOME/.config/waybar" ]]; then
+ ln -s "${configDir}/waybar" "$HOME/.config/waybar"
+ fi
+ '';
+ }
+ (lib.mkIf (config.modules.desktop.greetd.enable) {
+ services.greetd.settings = {
+ default_session.command = ''
+ ${pkgs.greetd.tuigreet}/bin/tuigreet \
+ --time \
+ --asterisks \
+ --user-menu \
+ --cmd niri-session
+ '';
+ };
+
+ environment.etc."greetd/environments".text = ''
+ Niri
+ '';
+ })
+ ]);
+}
diff --git a/modules/hardware/audio.nix b/modules/hardware/audio.nix
index 3ffa32a..a674597 100644
--- a/modules/hardware/audio.nix
+++ b/modules/hardware/audio.nix
@@ -23,22 +23,18 @@ in {
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
+
+ wireplumber.extraConfig.bluetoothEnhancements = {
+ "monitor.bluez.properties" = {
+ "bluez5.enable-sbc-xq" = true;
+ "bluez5.enable-msbc" = true;
+ "bluez5.enable-hw-volume" = true;
+ };
+ };
};
user.extraGroups = ["audio"];
home.packages = [pkgs.pavucontrol];
- }
- (lib.mkIf (device.hasBluetooth) {
- home.configFile = {
- "wireplumber/bluetooth.lua.d/51-bluez-config.lua".text = ''
- bluez_monitor.properties = {
- ["bluez5.enable-sbc-xq"] = true,
- ["bluez5.enable-msbc"] = true,
- ["bluez5.enable-hw-volume"] = true,
- ["bluez5.headset-roles"] = "[ hsp_hs hsp_ag hfp_hf hfp_ag ]"
- }
- '';
- };
- })
+ }
]);
}
diff --git a/modules/hardware/bluetooth.nix b/modules/hardware/bluetooth.nix
index 7f835bf..c5da0fa 100644
--- a/modules/hardware/bluetooth.nix
+++ b/modules/hardware/bluetooth.nix
@@ -18,9 +18,9 @@ in {
config = lib.mkIf (bluetoothConfig.enable && device.hasBluetooth) {
hardware.bluetooth = {
enable = true;
- package = pkgs.bluez;
powerOnBoot = true;
};
+ services.blueman.enable = true;
user.extraGroups = ["bluetooth"];
};
}
diff --git a/modules/hardware/gpu.nix b/modules/hardware/gpu.nix
index d7dfe17..a71d9d3 100644
--- a/modules/hardware/gpu.nix
+++ b/modules/hardware/gpu.nix
@@ -17,45 +17,42 @@ in {
config = lib.mkIf (gpuConfig.enable) (lib.mkMerge [
{
- hardware.opengl = {
+ hardware.graphics = {
enable = true;
- driSupport = true;
- driSupport32Bit = true;
};
}
(lib.mkIf (device.gpu == "intel") {
boot.initrd.kernelModules = ["i915"];
services.xserver.videoDrivers = ["modesetting"];
- hardware.opengl.extraPackages = [
+ hardware.graphics.extraPackages = [
pkgs.intel-compute-runtime
pkgs.intel-media-driver
- pkgs.vaapiIntel
- pkgs.vaapiVdpau
+ pkgs.intel-vaapi-driver
+ pkgs.libva-vdpau-driver
pkgs.libvdpau-va-gl
];
environment.variables.VDPAU_DRIVER = "va_gl";
})
(lib.mkIf (device.gpu == "nvidia") {
- services.xserver.videoDrivers = ["nvidia"];
- hardware.nvidia = {
- modesetting.enable = true;
- powerManagement.enable = false;
- powerManagement.finegrained = false;
- open = false;
- nvidiaSettings = true;
- package = config.boot.kernelPackages.nvidiaPackages.beta;
- };
- boot.initrd.kernelModules = [
- "nvidia"
- "nvidia_modeset"
- "nvidia_uvm"
- "nvidia_drm"
- ];
- boot.extraModprobeConfig = ''
- options modeset=1 fbdev=1
- '';
+ hardware.graphics.extraPackages = with pkgs; [ nvidia-vaapi-driver ];
+ services.xserver.videoDrivers = ["nvidia"];
+
+ hardware.nvidia = {
+ modesetting.enable = true;
+
+ powerManagement.enable = false;
+ powerManagement.finegrained = false;
+
+ open = true;
+ nvidiaSettings = true;
+ package = config.boot.kernelPackages.nvidiaPackages.latest;
+ };
+
+ environment.systemPackages = with pkgs; [
+ nvtopPackages.nvidia
+ ];
})
]);
}
diff --git a/modules/options.nix b/modules/options.nix
index e429171..c2463b4 100644
--- a/modules/options.nix
+++ b/modules/options.nix
@@ -95,6 +95,7 @@
# home manager configuration
home-manager = {
useUserPackages = true;
+ useGlobalPkgs = true;
users.${config.user.name} = lib.mkAliasDefinitions options.home.manager;
};
diff --git a/modules/security.nix b/modules/security.nix
new file mode 100644
index 0000000..3100f54
--- /dev/null
+++ b/modules/security.nix
@@ -0,0 +1,28 @@
+{
+ config,
+ options,
+ lib,
+ pkgs,
+ ...
+}: let
+
+in {
+ config = {
+ security.polkit.enable = true;
+
+ services.pcscd.enable = true;
+ services.gnome.gnome-keyring.enable = true;
+
+ programs.gnupg.agent = {
+ enable = true;
+ enableSSHSupport = true;
+ };
+
+ home.packages = [
+ (pkgs.pass.withExtensions (exts: [exts.pass-otp ]))
+ pkgs.gcr
+ pkgs.seahorse
+ pkgs.pinentry-qt
+ ];
+ };
+}
diff --git a/modules/shell/zsh.nix b/modules/shell/zsh.nix
index c39ec7a..c844564 100644
--- a/modules/shell/zsh.nix
+++ b/modules/shell/zsh.nix
@@ -39,7 +39,7 @@ in {
};
zsh = {
enable = true;
- enableAutosuggestions = true;
+ autosuggestion.enable = true;
enableCompletion = true;
syntaxHighlighting.enable = true;
autocd = true;
diff --git a/overlay.nix b/overlay.nix
index d79b87c..0f08d5e 100644
--- a/overlay.nix
+++ b/overlay.nix
@@ -2,9 +2,46 @@
inputs,
system,
...
-}: final: prev: {
- stable = import inputs.nixpkgs-stable {
+ }: final: prev: {
+ unstable = import inputs.nixpkgs-unstable {
inherit system;
config.allowUnfree = true;
};
+
+ unciv = prev.unciv.overrideAttrs (old: rec {
+ version = "4.18.14";
+ src = prev.fetchurl {
+ url = "https://github.com/yairm210/Unciv/releases/download/${version}-patch1/Unciv.jar";
+ hash = "sha256-ykyHaIxnahC8D8ZAqzGnwNhc7mUX25uO4hEWKz+7p7o=";
+ };
+ });
+
+ cataclysm-dda = prev.cataclysm-dda.overrideAttrs (old: {
+ version = "0.I";
+ src = prev.fetchFromGitHub {
+ owner = "CleverRaven";
+ repo = "Cataclysm-DDA";
+ tag = "cdda-0.I-2025-10-02-0217";
+ sha256 = "sha256-wD11w1u4hJfvh003ce+7Kq3/OgZDDDDd3VUh7fDgY5Q=";
+ };
+ patches = [];
+ });
+
+ cataclysm-tlg = prev.cataclysm-dda-git.overrideAttrs (old: {
+ meta.mainProgram = "cataclysm-tlg-tiles";
+ pname = "cataclysm-tlg";
+ version = "2025-10-17-1123";
+ src = prev.fetchFromGitHub {
+ owner = "Cataclysm-TLG";
+ repo = "Cataclysm-TLG";
+ tag = "cataclysm-tlg-1.0-${final.cataclysm-tlg.version}";
+ sha256 = "sha256-rpfRBVKyFTLOLl8AOdTueaXI+TozVAEGy5aycoE+ZDs=";
+ };
+ makeFlags = prev.cataclysm-dda-git.makeFlags ++ [ "TESTS=0" ];
+ postInstall = ''
+ substituteInPlace $out/share/applications/com.cataclysm-tlg.cataclysm-tlg.desktop \
+ --replace-fail "Exec=cataclysm-tlg-tiles" "Exec=$out/bin/cataclysm-tlg-tiles"
+ rm $out/bin/zzip
+ '';
+ });
}
diff --git a/packages/aurora4x/default.nix b/packages/aurora4x/default.nix
new file mode 100644
index 0000000..adc1a53
--- /dev/null
+++ b/packages/aurora4x/default.nix
@@ -0,0 +1,57 @@
+{
+ lib,
+ stdenv,
+ fetchurl,
+ makeDesktopItem,
+ copyDesktopItems,
+ mono,
+ unrar
+}:
+
+stdenv.mkDerivation rec {
+ name = "aurora4x-251";
+ version = "251";
+
+ srcs = [
+ (fetchurl {
+ url = "https://www.pentarch.org/steve/Aurora1130Full.rar";
+ hash = "sha256-QaTka9fNXjK/PgiF0S5EX+1dtUGWitcqPQYr54qDYAQ=";
+ })
+ (fetchurl {
+ url = "https://www.pentarch.org/steve/Aurora260.rar";
+ hash = "sha256-AG10u3oVX1rN7FQERVg36l7JBocvpF19/7tvavxH5QQ=";
+ })
+ ];
+
+ nativeBuildInputs = [
+ copyDesktopItems
+ ];
+
+ buildInputs = [
+ unrar
+ ];
+
+ runtimeLibs = lib.makeLibraryPath (
+ [
+ mono
+ ]
+ );
+
+ desktopItems = [
+ (makeDesktopItem {
+ name = "aurora4x";
+ desktopName = "Aurora 4X";
+ exec = "aurora4x";
+ })
+ ];
+
+ unpackCmd = "unrar x -o+ $curSrc";
+
+ installPhase = ''
+ runHook preInstall
+
+ mkdir -p $out/share/aurora4x $out/bin
+
+ runHook postInstall
+ '';
+}
diff --git a/packages/freeciv/default.nix b/packages/freeciv/default.nix
new file mode 100644
index 0000000..5cd37c6
--- /dev/null
+++ b/packages/freeciv/default.nix
@@ -0,0 +1,141 @@
+{
+ lib,
+ stdenv,
+ fetchFromGitHub,
+ autoreconfHook,
+ lua5_3,
+ pkg-config,
+ python3,
+ zlib,
+ bzip2,
+ curl,
+ xz,
+ gettext,
+ libiconv,
+ icu,
+ SDL2,
+ SDL2_mixer,
+ SDL2_image,
+ SDL2_ttf,
+ SDL2_gfx,
+ freetype,
+ fluidsynth,
+ sdl2Client ? false,
+ gtkClient ? true,
+ gtk4,
+ wrapGAppsHook3,
+ qtClient ? false,
+ qt5,
+ server ? true,
+ readline,
+ enableSqlite ? true,
+ sqlite,
+}:
+
+stdenv.mkDerivation (finalAttrs: {
+ pname = "freeciv";
+ version = "3.2.1";
+
+ src = fetchFromGitHub {
+ owner = "freeciv";
+ repo = "freeciv";
+ tag = "R${lib.replaceStrings [ "." ] [ "_" ] finalAttrs.version}";
+ hash = "sha256-Rl/B71pp5PA6mtRaKs8TbOya18cYxlNmMzVJ4ySVmhY=";
+ };
+
+ postPatch = ''
+ for f in {common,utility}/*.py; do
+ substituteInPlace $f \
+ --replace-fail '/usr/bin/env python3' ${python3.interpreter}
+ done
+ for f in bootstrap/*.sh; do
+ patchShebangs $f
+ done
+ '';
+
+ nativeBuildInputs = [
+ autoreconfHook
+ pkg-config
+ ]
+ ++ lib.optionals qtClient [ qt5.wrapQtAppsHook ]
+ ++ lib.optionals gtkClient [ wrapGAppsHook3 ];
+
+ buildInputs = [
+ lua5_3
+ zlib
+ bzip2
+ curl
+ xz
+ gettext
+ libiconv
+ icu
+ SDL2
+ SDL2_mixer
+ fluidsynth
+ ]
+ ++ lib.optionals sdl2Client [
+ SDL2_image
+ SDL2_ttf
+ SDL2_gfx
+ freetype
+ ]
+ ++ lib.optionals gtkClient [ gtk4 ]
+ ++ lib.optionals qtClient [ qt5.qtbase ]
+ ++ lib.optional server readline
+ ++ lib.optional enableSqlite sqlite;
+
+ dontWrapQtApps = true;
+ dontWrapGApps = true;
+
+ # configure is not smart enough to look for SDL2 headers under
+ # .../SDL2, but thankfully $SDL2_PATH is almost exactly what we want
+ preConfigure = ''
+ export CPPFLAGS="$(echo $SDL2_PATH | sed 's#/nix/store/#-I/nix/store/#g')"
+ '';
+ configureFlags = [
+ "--enable-shared"
+ ]
+ ++ lib.optionals sdl2Client [
+ "--enable-client=sdl2"
+ "--enable-sdl-mixer=sdl2"
+ ]
+ ++ lib.optionals qtClient [
+ "--enable-client=qt"
+ "--with-qtver=qt5"
+ "--with-qt5-includes=${qt5.qtbase.dev}/include"
+ ]
+ ++ lib.optionals gtkClient [
+ "--enable-client=gtk4"
+ "--enable-sdl-mixer=sdl2"
+ ]
+ ++ lib.optional enableSqlite "--enable-fcdb=sqlite3"
+ ++ lib.optional (!gtkClient) "--enable-fcmp=cli"
+ ++ lib.optional (!server) "--disable-server";
+
+ postFixup =
+ lib.optionalString qtClient ''
+ wrapQtApp $out/bin/freeciv-qt
+ ''
+ + lib.optionalString gtkClient ''
+ wrapGApp $out/bin/freeciv-gtk4
+ '';
+
+ enableParallelBuilding = true;
+
+ meta = {
+ description = "Multiplayer (or single player), turn-based strategy game";
+ longDescription = ''
+ Freeciv is a Free and Open Source empire-building strategy game
+ inspired by the history of human civilization. The game commences in
+ prehistory and your mission is to lead your tribe from the stone age
+ to the space age...
+ '';
+ homepage = "https://freeciv.org/";
+ license = lib.licenses.gpl2Plus;
+ maintainers = with lib.maintainers; [ pierron ];
+ platforms = lib.platforms.unix;
+ hydraPlatforms = lib.platforms.linux; # sdl-config times out on darwin
+ broken = qtClient && stdenv.hostPlatform.isDarwin; # Missing Qt5 development files
+ };
+})
+
diff --git a/packages/freecol/default.nix b/packages/freecol/default.nix
new file mode 100644
index 0000000..e2562ad
--- /dev/null
+++ b/packages/freecol/default.nix
@@ -0,0 +1,64 @@
+{
+ lib,
+ stdenv,
+ fetchFromGitHub,
+ autoreconfHook,
+ lua5_3,
+ pkg-config,
+ python3,
+ zlib,
+ bzip2,
+ curl,
+ xz,
+ gettext,
+ libiconv,
+ icu,
+ SDL2,
+ SDL2_mixer,
+ SDL2_image,
+ SDL2_ttf,
+ SDL2_gfx,
+ freetype,
+ fluidsynth,
+ sdl2Client ? false,
+ gtkClient ? false,
+ gtk3,
+ wrapGAppsHook3,
+ qtClient ? true,
+ qt5,
+ server ? true,
+ readline,
+ enableSqlite ? true,
+ sqlite,
+}:
+
+stdenv.mkDerivation rec {
+ pname = "freecol";
+ version = "1.2.0";
+
+ src = fetchFromGitHub {
+ owner = "FreeCol";
+ repo = "freecol";
+ rev = "stable";
+ hash = "sha256-+kAV9Jz0aQpzeVUFp3so+rYbWOn52NuxRwE8kP5hzM8=";
+ };
+
+ enableParallelBuilding = true;
+
+ meta = {
+ description = "Multiplayer (or single player), turn-based strategy game";
+ longDescription = ''
+ Freeciv is a Free and Open Source empire-building strategy game
+ inspired by the history of human civilization. The game commences in
+ prehistory and your mission is to lead your tribe from the stone age
+ to the space age...
+ '';
+ homepage = "http://www.freeciv.org"; # http only
+ license = lib.licenses.gpl2Plus;
+ maintainers = with lib.maintainers; [ pierron ];
+ platforms = lib.platforms.unix;
+ hydraPlatforms = lib.platforms.linux; # sdl-config times out on darwin
+ broken = qtClient && stdenv.hostPlatform.isDarwin; # Missing Qt5 development files
+ };
+}
+
diff --git a/packages/vintagestory/default.nix b/packages/vintagestory/default.nix
new file mode 100644
index 0000000..8df3a75
--- /dev/null
+++ b/packages/vintagestory/default.nix
@@ -0,0 +1,117 @@
+{
+ lib,
+ stdenv,
+ fetchurl,
+ makeWrapper,
+ makeDesktopItem,
+ copyDesktopItems,
+ xorg,
+ gtk2,
+ sqlite,
+ openal,
+ cairo,
+ libGLU,
+ SDL2,
+ freealut,
+ libglvnd,
+ pipewire,
+ libpulseaudio,
+ wayland,
+ libxkbcommon,
+ dotnet-runtime_8
+}:
+
+stdenv.mkDerivation rec {
+ name = "vintagestory-${version}";
+ version = "1.21.4";
+
+ src = fetchurl {
+ url = "https://cdn.vintagestory.at/gamefiles/stable/vs_client_linux-x64_${version}.tar.gz";
+ hash = "sha256-npffJgxgUMefX9OiveNk1r4kVqsMaVCC1jcWaibz9l8=";
+ };
+
+ nativeBuildInputs = [
+ makeWrapper
+ copyDesktopItems
+ ];
+
+ buildInputs = [ dotnet-runtime_8 ];
+
+ runtimeLibs = lib.makeLibraryPath (
+ [
+ gtk2
+ sqlite
+ openal
+ cairo
+ libGLU
+ SDL2
+ freealut
+ libglvnd
+ pipewire
+ libpulseaudio
+ wayland
+ libxkbcommon
+ ]
+ ++ (with xorg; [
+ libX11
+ libXi
+ libXcursor
+ ])
+ );
+
+ desktopItems = [
+ (makeDesktopItem {
+ name = "vintagestory";
+ desktopName = "Vintage Story";
+ exec = "vintagestory";
+ icon = "vintagestory";
+ comment = "Innovate and explore in a sandbox world";
+ categories = [ "Game" ];
+ })
+ (makeDesktopItem {
+ name = "Vintagestory_url_connect";
+ desktopName = "Vintage Story URI Connect";
+ type = "Application";
+ noDisplay = true;
+ mimeTypes = [ "x-scheme-handler/vintagestoryjoin" ];
+ exec = "vintagestory -c %U";
+ categories = [ "Game" ];
+ })
+ (makeDesktopItem {
+ name = "Vintagestory_url_mod";
+ desktopName = "Vintage Story URI mod install";
+ type = "Application";
+ noDisplay = true;
+ mimeTypes = [ "x-scheme-handler/vintagestorymodinstall" ];
+ exec = "vintagestory -i %U";
+ categories = [ "Game" ];
+ })
+ ];
+
+ installPhase = ''
+ runHook preInstall
+
+ mkdir -p $out/share/vintagestory $out/bin $out/share/pixmaps $out/share/fonts/truetype
+ cp -r * $out/share/vintagestory
+ cp $out/share/vintagestory/assets/gameicon.xpm $out/share/pixmaps/vintagestory.xpm
+ cp $out/share/vintagestory/assets/game/fonts/*.ttf $out/share/fonts/truetype
+
+ runHook postInstall
+ '';
+
+ preFixup =
+ ''
+ makeWrapper ${dotnet-runtime_8}/bin/dotnet $out/bin/vintagestory \
+ --prefix LD_LIBRARY_PATH : "${runtimeLibs}" \
+ --add-flags $out/share/vintagestory/Vintagestory.dll
+ makeWrapper ${dotnet-runtime_8}/bin/dotnet $out/bin/vintagestory-server \
+ --prefix LD_LIBRARY_PATH : "${runtimeLibs}" \
+ --add-flags $out/share/vintagestory/VintagestoryServer.dll
+ ''
+ + ''
+ find "$out/share/vintagestory/assets/" -not -path "*/fonts/*" -regex ".*/.*[A-Z].*" | while read -r file; do
+ local filename="$(basename -- "$file")"
+ ln -sf "$filename" "''${file%/*}"/"''${filename,,}"
+ done
+ '';
+}