Image 1 — Noctalia v5 on NixOS with Hyprland
Image 2 — Noctalia v5 on NixOS with Hyprland
Image 3 — Noctalia v5 on NixOS with Hyprland
Image 4 — Noctalia v5 on NixOS with Hyprland
Image 5 — Noctalia v5 on NixOS with Hyprland
Image 6 — Noctalia v5 on NixOS with Hyprland

Noctalia v5 on NixOS with Hyprland

Hi,

I had been running Arch for a long time with MangoWM + the usual Waybar/Fuzzel/Sww etc stack, I got a new Thinkpad and decided to try NixOS this time.

After much testing, I decided to stabilise on Hyprland with Noctalia v5. I like the various layouts in Hyprland (and eye candy!) and love how much you can customise it in lua - the wiki is very detailed and easy to follow.
I use the master layout for my workspaces but scrolling layout for my scratchpad - I had fun customising all the graphics, beziers, etc, but ironically in the end decided to use plain white borders for selected window and disabled all blur and shadows (I found them distracting!).

Similarly I found Noctalia v5 incredibly easy to configure following their wiki (yes Arch users have a thing for wikis, as any question is guaranteed to get a RTFM response!). Surprisingly I found Noctalia v5 pretty much uses the same RAM as my usual stack of programs (it replaces bar, launcher, notification daemon, wallpaper manager, lock screen, polkit, among others) and it is definitely easier to configure and more cohesive.

I use greetd and trigger noctalia's lock screen on startup to act as a login screen (no real display manager!)

There are so many cool features in NixOS, for instance when making this post, I wanted to screenshot my lockscreen but Noctalia's native screenshot tool didn't allow me to. So I decided to use my trusted grim and thanks to NixOS - I didn't even have to install it! Just did this:

nix-shell -p grim --run "sleep 5 && grim lockscreen.png"

and locked my screen within the 5 seconds to get the screenshot!

I guess the point of this post was that I just wanted to say a big thank you to all the development team for Noctalia and all the other developers out there - your efforts make all this possible - keep up the great work!

If anyone is interested as to what hyprland and noctalia config looks like in NixOS home manager, I typed my hyprland config into a file I created called hyprland.nix, which I then imported into home.nix. For Noctalia I configured everything using the settings UI then read .local/state/noctalia/settings.toml to create my declarative Noctalia NixOS home manager config in a file called noctalia.nix, which I also imported into home.nix (see second code box below).

Hope its of some use to someone.

{ config, pkgs, ... }:

{
  wayland.windowManager.hyprland = {
    enable = true;
    xwayland.enable = true;
    configType = "lua";
    settings = {};
    extraConfig = ''

      hl.config({
        input = {
          kb_layout = "gb",
        },
        xwayland = {
          force_zero_scaling = true,
        },
        general = {
          layout = "master",
          border_size = 2,
          gaps_in = 0,
          gaps_out = 0,
          col = {
            active_border = "rgba(ffffffff)",
            inactive_border = "rgba(1a1a1aff)",
          },
        },
        master = {
          orientation = "left",
          allow_small_split = true,
          mfact = 0.5,
        },
        decoration = {
          rounding = 5,
          rounding_power = 10,
          active_opacity = 1.0,
          inactive_opacity = 1.0,
          dim_special = 0.5,
          blur = {
            enabled = false,
          },
          shadow = {
            enabled = false,
          },
        },
        misc = {
          disable_hyprland_logo = true,
          disable_splash_rendering = true,
          render_unfocused_fps = 1,          
        },
      })

      hl.monitor({ output = "", mode = "preferred", position = "auto", scale = 1 })

      hl.on("hyprland.start", function()
        hl.exec_cmd("noctalia --daemon")
        hl.exec_cmd("sleep 1 && noctalia msg session lock")
      end)

      hl.window_rule({ match = { class = "^(thunar|Thunar)$", title = "Preferences" }, float = true, center = true, size = { 550, 500 } })
      hl.window_rule({ match = { class = "^(thunar|Thunar)$", title = "^(Rename.*)$" }, float = true, move = {"cursor_x-(window_w*0.5)", "cursor_y-(window_h*0.5)"} , size = { 300, 100 } })
      hl.window_rule({ match = { class = "firefox", title = ".*Save.*" }, float = true, center = true })
      hl.window_rule({ match = { class = "firefox", title = ".*Open.*" }, float = true, center = true })
      hl.window_rule({ match = { class = "DesktopEditors", float = true }, float = true, center = true })
      hl.window_rule({ match = { class = "xdg-desktop-portal-gtk", title = ".*Open.*" }, size = {"monitor_w * 0.5", "monitor_h * 0.5"}, float = true, center = true })
      hl.window_rule({ match = { class = "xdg-desktop-portal-gtk", title = ".*Open.*" }, size = {"monitor_w * 0.5", "monitor_h * 0.5"}, float = true, center = true })
      hl.workspace_rule({ workspace = "special:scratchpad", layout = "scrolling", gaps_out = 40, gaps_in = 20})

      hl.curve("fast", { type = "bezier", points = { {0, 1}, {0, 1} } })
      hl.curve("out", { type = "bezier", points = { {1, 1}, {1, 1} } })
      hl.curve("in", { type = "bezier", points = { {0, 1}, {1, 1} } })

      hl.animation({ leaf = "global", enabled = true, speed = 5, bezier = "fast" })
      hl.animation({ leaf = "windows", enabled = true, speed = 5, bezier = "fast", style = "slide" })
      hl.animation({ leaf = "windowsIn", enabled = true, speed = 5, bezier = "fast", style = "slide" })
      hl.animation({ leaf = "windowsOut", enabled = true, speed = 5, bezier = "out", style = "slide" })
      hl.animation({ leaf = "border", enabled = true, speed = 5, bezier = "fast" })
      hl.animation({ leaf = "fade", enabled = false })
      hl.animation({ leaf = "workspaces", enabled = true, speed = 5, bezier = "in", style = "slide" })
      hl.animation({ leaf = "layers", enabled = true, speed = 5, bezier = "fast", style = "slide" })
      hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 5, bezier = "in", style = "slidefadevert 100%"})

      hl.bind("SUPER + RETURN", hl.dsp.exec_cmd("kitty"))
      hl.bind("SUPER + Q", hl.dsp.window.close())
      hl.bind("SUPER + SPACE", hl.dsp.exec_cmd("noctalia msg panel-toggle launcher"))
      hl.bind("ALT + TAB", hl.dsp.exec_cmd("noctalia msg window-switcher"))
      hl.bind("SUPER + E", hl.dsp.exec_cmd("thunar"))
      hl.bind("SUPER + D", hl.dsp.focus({ workspace = "empty" }))
      hl.bind("SUPER + SHIFT + D", hl.dsp.window.move({ workspace = "empty" }))
      hl.bind("SUPER + L", hl.dsp.exec_cmd("noctalia msg session lock"))
      hl.bind("SUPER + V", hl.dsp.exec_cmd("noctalia msg panel-toggle clipboard"))
      hl.bind("SUPER + F", hl.dsp.window.fullscreen({ mode = "maximized", action = "toggle" }))
      hl.bind("SUPER + SHIFT + F", hl.dsp.window.fullscreen({ mode = "fullscreen", action = "toggle" }))
      hl.bind("SUPER + Page_Up", hl.dsp.focus({ workspace = "+1" }))
      hl.bind("SUPER + Page_Down", hl.dsp.focus({ workspace = "-1" }))
      hl.bind("SUPER + SHIFT + Page_Up", hl.dsp.window.move({ workspace = "+1" }))
      hl.bind("SUPER + SHIFT + Page_Down", hl.dsp.window.move({ workspace = "-1" }))
      hl.bind("SUPER + S", hl.dsp.workspace.toggle_special("scratchpad"))
      hl.bind("SUPER + SHIFT +S", hl.dsp.window.move({ workspace = "special:scratchpad" }))

      local function layout_bind(bind_table)
        return function ()
          local workspace = hl.get_active_special_workspace() or
                            hl.get_active_workspace()
          if not workspace then
            return
          end
          local layout = workspace.tiled_layout           
          if bind_table[layout] then
            hl.dispatch(bind_table[layout])
          end
        end
      end

      hl.bind("SUPER + comma", layout_bind({
        master    = hl.dsp.layout("mfact -0.01"),
        scrolling = hl.dsp.layout("colresize -0.01"),    
      }), { repeating = true })

      hl.bind("SUPER + period", layout_bind({
        master    = hl.dsp.layout("mfact +0.01"),
        scrolling = hl.dsp.layout("colresize +0.01"),    
      }), { repeating = true })

      hl.bind("SUPER + SHIFT + comma", layout_bind({
        master    = hl.dsp.layout("orientationprev"),
        scrolling = hl.dsp.layout("swapcol l"),    
      }))

      hl.bind("SUPER + SHIFT + period", layout_bind({
        master    = hl.dsp.layout("orientationnext"),
        scrolling = hl.dsp.layout("swapcol r"),    
      }))

      hl.bind("SUPER + slash", layout_bind({
        master    = hl.dsp.layout("addmaster"),
        scrolling = hl.dsp.layout("consume"),    
      }))

      hl.bind("SUPER + SHIFT + slash", layout_bind({
        master    = hl.dsp.layout("removemaster"),
        scrolling = hl.dsp.layout("expel"),    
      }))

      hl.bind("XF86AudioMute", hl.dsp.exec_cmd("noctalia msg volume-mute"))
      hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("noctalia msg volume-down"))
      hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("noctalia msg volume-up"))
      hl.bind("XF86AudioMicMute", hl.dsp.exec_cmd("noctalia msg mic-mute"))
      hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd("noctalia msg brightness-down"))
      hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd("noctalia msg brightness-up"))
      hl.bind("XF86Display", hl.dsp.exec_cmd("noctalia msg panel-toggle control-center"))
      hl.bind("XF86NotificationCenter", hl.dsp.exec_cmd("noctalia msg power-cycle"))
      hl.bind("XF86PickupPhone", hl.dsp.exec_cmd("noctalia msg bluetooth-toggle"))
      hl.bind("XF86HangupPhone", hl.dsp.exec_cmd("noctalia msg panel-toggle session"))
      hl.bind("XF86Favorites", hl.dsp.exec_cmd("noctalia msg settings-toggle")) 
      hl.bind("Print", hl.dsp.exec_cmd("noctalia msg screenshot-fullscreen"))
      hl.bind("XF86SelectiveScreenshot", hl.dsp.exec_cmd("noctalia msg screenshot-region"))

      hl.bind("SUPER + 1", hl.dsp.focus({ workspace = "1" }))
      hl.bind("SUPER + 2", hl.dsp.focus({ workspace = "2" }))
      hl.bind("SUPER + 3", hl.dsp.focus({ workspace = "3" }))
      hl.bind("SUPER + 4", hl.dsp.focus({ workspace = "4" }))
      hl.bind("SUPER + 5", hl.dsp.focus({ workspace = "5" }))
      hl.bind("SUPER + 6", hl.dsp.focus({ workspace = "6" }))
      hl.bind("SUPER + 7", hl.dsp.focus({ workspace = "7" }))
      hl.bind("SUPER + 8", hl.dsp.focus({ workspace = "8" }))
      hl.bind("SUPER + 9", hl.dsp.focus({ workspace = "9" }))

      hl.bind("SUPER + SHIFT + 1", hl.dsp.window.move({ workspace = "1" }))
      hl.bind("SUPER + SHIFT + 2", hl.dsp.window.move({ workspace = "2" }))
      hl.bind("SUPER + SHIFT + 3", hl.dsp.window.move({ workspace = "3" }))
      hl.bind("SUPER + SHIFT + 4", hl.dsp.window.move({ workspace = "4" }))
      hl.bind("SUPER + SHIFT + 5", hl.dsp.window.move({ workspace = "5" }))
      hl.bind("SUPER + SHIFT + 6", hl.dsp.window.move({ workspace = "6" }))
      hl.bind("SUPER + SHIFT + 7", hl.dsp.window.move({ workspace = "7" }))
      hl.bind("SUPER + SHIFT + 8", hl.dsp.window.move({ workspace = "8" }))
      hl.bind("SUPER + SHIFT + 9", hl.dsp.window.move({ workspace = "9" }))

      hl.bind("SUPER + left", hl.dsp.focus({ direction = "left" }))
      hl.bind("SUPER + right", hl.dsp.focus({ direction = "right" }))
      hl.bind("SUPER + up", hl.dsp.focus({ direction = "up" }))
      hl.bind("SUPER + down", hl.dsp.focus({ direction = "down" }))

      hl.bind("SUPER + SHIFT + left", hl.dsp.window.move({ direction = "left" }))
      hl.bind("SUPER + SHIFT + right", hl.dsp.window.move({ direction = "right" }))
      hl.bind("SUPER + SHIFT + up", hl.dsp.window.move({ direction = "up" }))
      hl.bind("SUPER + SHIFT + down", hl.dsp.window.move({ direction = "down" }))
    '';
  };
}

{ inputs, ... }:
{
  imports = [ inputs.noctalia.homeModules.default ];

  programs.noctalia = {
    enable = true;
    
    settings = {
      config_version = 12;

      bar.default = {
        color = "primary";
        concave_edge_corners = false;
        end = [ "tray" "bluetooth" "network" "volume" "battery" "session" ];
        font_family = "MonaspiceNe Nerd Font";
        icon_color = "primary";
        margin_ends = 0;
        padding = 10;
        radius = 0;
        start = [ "workspaces" ];
        thickness = 20;
        widget_spacing = 10;
      };

      dock.show_dots = true;

      location.auto_locate = true;

      lockscreen = {
        blur_intensity = 0.0;
        wallpaper = "/etc/nixos/Wallpapers/Anime Wisteria.png";
      };

      lockscreen_widgets = {
        enabled = true;
        schema_version = 2;
        widget_order = [
          "lockscreen-login-box@eDP-1"
          "lockscreen-widget-0000000000000001"
          "lockscreen-widget-0000000000000002"
        ];

        grid = {
          cell_size = 24;
          major_interval = 4;
          visible = true;
        };

        widget."lockscreen-login-box@eDP-1" = {
          box_height = 70.0;
          box_width = 336.0;
          cx = 960.0;
          cy = 695.0;
          output = "eDP-1";
          rotation = 0.0;
          type = "login_box";
          settings = {
            background_color = "surface_variant";
            background_opacity = 0.0;
            background_radius = 10.0;
            center_password_text = true;
            input_opacity = 1.0;
            input_radius = 6.0;
            layout = "compact";
            show_caps_lock = true;
            show_keyboard_layout = false;
            show_login_button = false;
            show_media = true;
            show_session_buttons = true;
            show_unlock_hint = true;
            show_weather = true;
          };
        };

        widget."lockscreen-widget-0000000000000001" = {
          box_height = 56.0;
          box_width = 176.0;
          cx = 960.0;
          cy = 444.0;
          output = "eDP-1";
          rotation = 0.0;
          type = "clock";
          settings = {
            background_opacity = 0.0;
            background_padding = 3;
            background_radius = 10;
            clock_style = "digital";
            font_family = "MonaspiceKr Nerd Font";
            format = "{:%-I:%M %p}";
          };
        };

        widget."lockscreen-widget-0000000000000002" = {
          box_height = 64.0;
          box_width = 648.0;
          cx = 960.0;
          cy = 372.0;
          output = "eDP-1";
          rotation = -0.0;
          type = "clock";
          settings = {
            background_opacity = 0.0;
            background_padding = 3;
            background_radius = 10;
            font_family = "MonaspiceKr Nerd Font";
            format = "{:%A %d %B %Y}";
          };
        };
      };

      shell = {
        app_icon_color = "error";
        font_family = "MonaspiceNe NF";
        polkit_agent = true;
        launcher.categories = false;
      };

      theme = {
        mode = "dark";
        source = "wallpaper";
        wallpaper_scheme = "m3-rainbow";
      };

      wallpaper = {
        directory = "/etc/nixos/Wallpapers/";
        fill_mode = "span";
        transition_on_startup = true;
        automation.recursive = false;
        default.path = "/etc/nixos/Wallpapers/Anime Moon.png";
        last.path = "/etc/nixos/Wallpapers/Anime Moon.png";
        monitors."eDP-1".path = "/etc/nixos/Wallpapers/Anime Moon.png";
      };

      widget.clock.format = "{:%A %-e %B %Y %-I:%M %P}";
    };
  };
}
u/Shidenissen — 5 days ago

Hyprland in NixOS with Noctalia v5

Hi,

I had been running Arch for a long time with MangoWM + the usual Waybar/Fuzzel/Sww etc stack, I got a new Thinkpad and decided to try NixOS with Hyprland and Noctalia v5 this time.

Hyprland was easy to set up on NixOS, though integrating Lua config into home manager was a bit of a headache - starting with lots of _args, then Lua helpers and eventually I ditched it all and simply declared everything in Lua via extraconfig '' '' in home manager (see end of post for sample config).

I like the various layouts in Hyprland (and eye candy!) and love how much you can customise it in Lua - the wiki is very detailed and easy to follow.
I use the master layout for my workspaces but scrolling layout for my scratchpad - I had fun customising all the graphics, beziers, etc, but ironically in the end I decided to use plain white borders for selected window and disabled all blur and shadows (I found them distracting!).

Noctalia v5 was also incredibly easy to configure following their wiki (yes Arch users have a thing for wikis, as any question is guaranteed to get a RTFM response!). Surprisingly I found Noctalia v5 pretty much uses the same RAM as my usual stack of programs (it replaces bar, launcher, notification daemon, wallpaper manager, lock screen, polkit, among others) and it is definitely easier to configure and more cohesive. You can also generate palettes from your wallpaper which makes simple "ricing" easier.

There are so many cool features in NixOS, for instance when making this post, I wanted to screenshot my lockscreen but Noctalia's native screenshot tool didn't allow me to. So I decided to use my trusted grim and thanks to NixOS - I didn't even have to install it! Just did this:

nix-shell -p grim --run "sleep 5 && grim lockscreen.png"

and locked my screen within the 5 seconds to get the screenshot!

I guess the point of this post was that I just wanted to say a big thank you to all the development team for Hyprland and all the other developers out there - your efforts make all this possible - keep up the great work!

My NixOS home manager Hyprland config, I typed it all into a file I created called hyprland.nix, which I then imported into home.nix - I used extraconfig as I got fed up with typing _args and then with the complexity added by lua helpers, hope it's of some use to someone:

{ config, pkgs, ... }:

{
  wayland.windowManager.hyprland = {
    enable = true;
    xwayland.enable = true;
    configType = "lua";
    settings = {};
    extraConfig = ''

      hl.config({
        input = {
          kb_layout = "gb",
        },
        xwayland = {
          force_zero_scaling = true,
        },
        general = {
          layout = "master",
          border_size = 2,
          gaps_in = 0,
          gaps_out = 0,
          col = {
            active_border = "rgba(ffffffff)",
            inactive_border = "rgba(1a1a1aff)",
          },
        },
        master = {
          orientation = "left",
          allow_small_split = true,
          mfact = 0.5,
        },
        decoration = {
          rounding = 5,
          rounding_power = 10,
          active_opacity = 1.0,
          inactive_opacity = 1.0,
          dim_special = 0.5,
          blur = {
            enabled = false,
          },
          shadow = {
            enabled = false,
          },
        },
        misc = {
          disable_hyprland_logo = true,
          disable_splash_rendering = true,
          render_unfocused_fps = 1,          
        },
      })

      hl.monitor({ output = "", mode = "preferred", position = "auto", scale = 1 })

      hl.on("hyprland.start", function()
        hl.exec_cmd("noctalia --daemon")
        hl.exec_cmd("sleep 1 && noctalia msg session lock")
      end)

      hl.window_rule({ match = { class = "^(thunar|Thunar)$", title = "Preferences" }, float = true, center = true, size = { 550, 500 } })
      hl.window_rule({ match = { class = "^(thunar|Thunar)$", title = "^(Rename.*)$" }, float = true, move = {"cursor_x-(window_w*0.5)", "cursor_y-(window_h*0.5)"} , size = { 300, 100 } })
      hl.window_rule({ match = { class = "firefox", title = ".*Save.*" }, float = true, center = true })
      hl.window_rule({ match = { class = "firefox", title = ".*Open.*" }, float = true, center = true })
      hl.window_rule({ match = { class = "DesktopEditors", float = true }, float = true, center = true })
      hl.window_rule({ match = { class = "xdg-desktop-portal-gtk", title = ".*Open.*" }, size = {"monitor_w * 0.5", "monitor_h * 0.5"}, float = true, center = true })
      hl.window_rule({ match = { class = "xdg-desktop-portal-gtk", title = ".*Open.*" }, size = {"monitor_w * 0.5", "monitor_h * 0.5"}, float = true, center = true })
      hl.workspace_rule({ workspace = "special:scratchpad", layout = "scrolling", gaps_out = 40, gaps_in = 20})

      hl.curve("fast", { type = "bezier", points = { {0, 1}, {0, 1} } })
      hl.curve("out", { type = "bezier", points = { {1, 1}, {1, 1} } })
      hl.curve("in", { type = "bezier", points = { {0, 1}, {1, 1} } })

      hl.animation({ leaf = "global", enabled = true, speed = 5, bezier = "fast" })
      hl.animation({ leaf = "windows", enabled = true, speed = 5, bezier = "fast", style = "slide" })
      hl.animation({ leaf = "windowsIn", enabled = true, speed = 5, bezier = "fast", style = "slide" })
      hl.animation({ leaf = "windowsOut", enabled = true, speed = 5, bezier = "out", style = "slide" })
      hl.animation({ leaf = "border", enabled = true, speed = 5, bezier = "fast" })
      hl.animation({ leaf = "fade", enabled = false })
      hl.animation({ leaf = "workspaces", enabled = true, speed = 5, bezier = "in", style = "slide" })
      hl.animation({ leaf = "layers", enabled = true, speed = 5, bezier = "fast", style = "slide" })
      hl.animation({ leaf = "specialWorkspace", enabled = true, speed = 5, bezier = "in", style = "slidefadevert 100%"})

      hl.bind("SUPER + RETURN", hl.dsp.exec_cmd("kitty"))
      hl.bind("SUPER + Q", hl.dsp.window.close())
      hl.bind("SUPER + SPACE", hl.dsp.exec_cmd("noctalia msg panel-toggle launcher"))
      hl.bind("ALT + TAB", hl.dsp.exec_cmd("noctalia msg window-switcher"))
      hl.bind("SUPER + E", hl.dsp.exec_cmd("thunar"))
      hl.bind("SUPER + D", hl.dsp.focus({ workspace = "empty" }))
      hl.bind("SUPER + SHIFT + D", hl.dsp.window.move({ workspace = "empty" }))
      hl.bind("SUPER + L", hl.dsp.exec_cmd("noctalia msg session lock"))
      hl.bind("SUPER + V", hl.dsp.exec_cmd("noctalia msg panel-toggle clipboard"))
      hl.bind("SUPER + F", hl.dsp.window.fullscreen({ mode = "maximized", action = "toggle" }))
      hl.bind("SUPER + SHIFT + F", hl.dsp.window.fullscreen({ mode = "fullscreen", action = "toggle" }))
      hl.bind("SUPER + Page_Up", hl.dsp.focus({ workspace = "+1" }))
      hl.bind("SUPER + Page_Down", hl.dsp.focus({ workspace = "-1" }))
      hl.bind("SUPER + SHIFT + Page_Up", hl.dsp.window.move({ workspace = "+1" }))
      hl.bind("SUPER + SHIFT + Page_Down", hl.dsp.window.move({ workspace = "-1" }))
      hl.bind("SUPER + S", hl.dsp.workspace.toggle_special("scratchpad"))
      hl.bind("SUPER + SHIFT +S", hl.dsp.window.move({ workspace = "special:scratchpad" }))

      local function layout_bind(bind_table)
        return function ()
          local workspace = hl.get_active_special_workspace() or
                            hl.get_active_workspace()
          if not workspace then
            return
          end
          local layout = workspace.tiled_layout           
          if bind_table[layout] then
            hl.dispatch(bind_table[layout])
          end
        end
      end

      hl.bind("SUPER + comma", layout_bind({
        master    = hl.dsp.layout("mfact -0.01"),
        scrolling = hl.dsp.layout("colresize -0.01"),    
      }), { repeating = true })

      hl.bind("SUPER + period", layout_bind({
        master    = hl.dsp.layout("mfact +0.01"),
        scrolling = hl.dsp.layout("colresize +0.01"),    
      }), { repeating = true })

      hl.bind("SUPER + SHIFT + comma", layout_bind({
        master    = hl.dsp.layout("orientationprev"),
        scrolling = hl.dsp.layout("swapcol l"),    
      }))

      hl.bind("SUPER + SHIFT + period", layout_bind({
        master    = hl.dsp.layout("orientationnext"),
        scrolling = hl.dsp.layout("swapcol r"),    
      }))

      hl.bind("SUPER + slash", layout_bind({
        master    = hl.dsp.layout("addmaster"),
        scrolling = hl.dsp.layout("consume"),    
      }))

      hl.bind("SUPER + SHIFT + slash", layout_bind({
        master    = hl.dsp.layout("removemaster"),
        scrolling = hl.dsp.layout("expel"),    
      }))

      hl.bind("XF86AudioMute", hl.dsp.exec_cmd("noctalia msg volume-mute"))
      hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("noctalia msg volume-down"))
      hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("noctalia msg volume-up"))
      hl.bind("XF86AudioMicMute", hl.dsp.exec_cmd("noctalia msg mic-mute"))
      hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd("noctalia msg brightness-down"))
      hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd("noctalia msg brightness-up"))
      hl.bind("XF86Display", hl.dsp.exec_cmd("noctalia msg panel-toggle control-center"))
      hl.bind("XF86NotificationCenter", hl.dsp.exec_cmd("noctalia msg power-cycle"))
      hl.bind("XF86PickupPhone", hl.dsp.exec_cmd("noctalia msg bluetooth-toggle"))
      hl.bind("XF86HangupPhone", hl.dsp.exec_cmd("noctalia msg panel-toggle session"))
      hl.bind("XF86Favorites", hl.dsp.exec_cmd("noctalia msg settings-toggle")) 
      hl.bind("Print", hl.dsp.exec_cmd("noctalia msg screenshot-fullscreen"))
      hl.bind("XF86SelectiveScreenshot", hl.dsp.exec_cmd("noctalia msg screenshot-region"))

      hl.bind("SUPER + 1", hl.dsp.focus({ workspace = "1" }))
      hl.bind("SUPER + 2", hl.dsp.focus({ workspace = "2" }))
      hl.bind("SUPER + 3", hl.dsp.focus({ workspace = "3" }))
      hl.bind("SUPER + 4", hl.dsp.focus({ workspace = "4" }))
      hl.bind("SUPER + 5", hl.dsp.focus({ workspace = "5" }))
      hl.bind("SUPER + 6", hl.dsp.focus({ workspace = "6" }))
      hl.bind("SUPER + 7", hl.dsp.focus({ workspace = "7" }))
      hl.bind("SUPER + 8", hl.dsp.focus({ workspace = "8" }))
      hl.bind("SUPER + 9", hl.dsp.focus({ workspace = "9" }))

      hl.bind("SUPER + SHIFT + 1", hl.dsp.window.move({ workspace = "1" }))
      hl.bind("SUPER + SHIFT + 2", hl.dsp.window.move({ workspace = "2" }))
      hl.bind("SUPER + SHIFT + 3", hl.dsp.window.move({ workspace = "3" }))
      hl.bind("SUPER + SHIFT + 4", hl.dsp.window.move({ workspace = "4" }))
      hl.bind("SUPER + SHIFT + 5", hl.dsp.window.move({ workspace = "5" }))
      hl.bind("SUPER + SHIFT + 6", hl.dsp.window.move({ workspace = "6" }))
      hl.bind("SUPER + SHIFT + 7", hl.dsp.window.move({ workspace = "7" }))
      hl.bind("SUPER + SHIFT + 8", hl.dsp.window.move({ workspace = "8" }))
      hl.bind("SUPER + SHIFT + 9", hl.dsp.window.move({ workspace = "9" }))

      hl.bind("SUPER + left", hl.dsp.focus({ direction = "left" }))
      hl.bind("SUPER + right", hl.dsp.focus({ direction = "right" }))
      hl.bind("SUPER + up", hl.dsp.focus({ direction = "up" }))
      hl.bind("SUPER + down", hl.dsp.focus({ direction = "down" }))

      hl.bind("SUPER + SHIFT + left", hl.dsp.window.move({ direction = "left" }))
      hl.bind("SUPER + SHIFT + right", hl.dsp.window.move({ direction = "right" }))
      hl.bind("SUPER + SHIFT + up", hl.dsp.window.move({ direction = "up" }))
      hl.bind("SUPER + SHIFT + down", hl.dsp.window.move({ direction = "down" }))
    '';
  };
}
u/Shidenissen — 5 days ago
▲ 33 r/NixOS

NixOS is a joy to use: (NNH - NixOS, Noctalia v5, Hyprland)

Hi,

I had been running Arch for a long time with MangoWM + the usual Waybar/Fuzzel/Sww etc stack, I got a new Thinkpad and decided to try NixOS this time.

It's been around 3 months since I started with NixOS (using unstable, flakes, home manager) and I spent most of that time experimenting with many different window managers and applications (kde, lxqt, sway, niri, mangowm). I have to say NixOS is an absolute joy to use - it was so easy to change a few lines of configuration to try new combinations.

While my heart still loves MangoWM, I decided to stabilise on Hyprland with Noctalia v5. I like the various layouts in Hyprland (and eye candy!) and love how much you can customise it in lua - the wiki is very detailed and easy to follow.
I use the master layout for my workspaces but scrolling layout for my scratchpad - I had fun customising all the graphics, beziers, etc, but ironically in the end decided to use plain white borders for selected window and disabled all blur and shadows (I found them distracting!).

Similarly I found Noctalia v5 incredibly easy to configure following their wiki (yes Arch users have a thing for wikis, as any question is guaranteed to get a RTFM response!). Surprisingly I found Noctalia v5 pretty much uses the same RAM as my usual stack of programs (it replaces bar, launcher, notification daemon, wallpaper manager, lock screen, polkit, among others) and it is definitely easier to configure and more cohesive.

I use greetd and trigger noctalia's lock screen on startup to act as a login screen (no real display manager!)

I love being able to save all my config to Github easily without playing around with stow/symlinks - I have a few versions of my config with different window managers etc. I also love how easy it is to rollback if things go wrong, though perhaps I could still add btrfs snapshots with snapper or something.

There are so many cool features in NixOS, for instance when making this post, I wanted to screenshot my lockscreen but Noctalia's native screenshot tool didn't allow me to. So I decided to use my trusted grim and thanks to NixOS - I didn't even have to install it! Just did this:

nix-shell -p grim --run "sleep 5 && grim lockscreen.png"

and locked my screen within the 5 seconds to get the screenshot!

My Steam games and Epic games (heroic launcher) also all work flawlessly - I even managed to get Minecraft in Prism Launcher working with 2 players split screen!

I guess the point of this post was that I just wanted to say a big thank you to all the development teams for NixOS, Noctalia, Hyprland, MangoWM and all the other developers out there - your efforts make all this possible - keep up the great work!

I also wanted to say that if you are on the fence about trying NixOS, I would strongly recommend it; try it in a VM or on a second system, perhaps try one of the default desktop environments first (KDE/Gnome), get used to using https://search.nixos.org/packages and https://home-manager-options.extranix.com/ perhaps along with an AI to give you some guidance.

u/Shidenissen — 5 days ago

How to set up Minecraft Splitscreen on PC (2-4 controllers playing on one screen: Java edition - incredibly easy to set up!)

Hi, being unfamiliar with the world of Minecraft I was not aware how easy it was for four children to play together on one screen, using one pc and 4 controllers.

As I did not find an up to date guide I thought I would give a brief overview to help any other people attempting the same.

  1. You must own Minecraft Java on your Microsoft account. (Just need one copy).
  2. Install Prismlauncher: https://prismlauncher.org/ - In Settings -> Java, ensure "Autodetect Java version" and "Auto-download Mojang java" are ticked. - In Settings -> Accounts, "Add Microsoft" in the top right. Then add 4 offline accounts - one for each player.
  3. At the Prismlauncher main screen, click "Add Instance" in the top left. - For Minecraft Version, select 26.1.1 - On the same screen on the right, under "Mod Loader", select "Fabric" and select version 0.19.3. - Press "OK"
  4. Right click the instance that you have just created and in the context menu, select "Edit". Then in the new window select "Mods" in the top left and then "Download Mods" in the top right.
  5. Select Modrinth or CurseForge on the left and in the search box, search for the following mods and for each one click "Select Mod for download": - Fabric API: Select the version at the top which will hopefully be: [26.1.2] Fabric API 0.155.2. - MidnightControls: Select the version at the top which will hopefully be: MidnightControls 1.12.1 + Fabric 26.1. - Splitscreen Support: Select the version at the top which will hopefully be: 1.18.0+26.1.1 (fabric).

Then click "Review and Confirm".

  1. Once all done, still editing your instance, click "Settings" on the left, then the Miscellaneous tab and then tick "Override default account" and select an offline account for your player (this will be your player's in game name).

  2. Launch your instance, wait for it to load.
    Press "F11" on the keyboard to move the window to suit you. Perhaps to the top left corner of the screen to make room for 3 other screens.

At the main menu, click Options -> Controls -> click the Gamepad symbol in the top right.
On the Controller tab, scroll down and set "Unfocused Input" to Yes.
On the Screens tab, scroll down and set "Virtual Mouse" to Yes.

Click Done 3 times to get to the main menu.

  1. Click Singleplayer, create a new world (any settings). Once in the world on your keyboard press: "F3 + P" to disable pause on lost focus.

Exit for now back to Prismlauncher.

  1. Right click on your instance and rename it to your first player's name. Right click on it again and select Copy. In the new window, type in your next player's name and click OK.

  2. Repeat this "copy" step two more times to get a total of 4 instances.

  3. All the settings and even pause on lost focus should have been copied over to each instance, but best to double check: For each of your 3 new instances, follow steps 6, 7, 8 above.

  4. Once all done, launch as many instances as you want 2 to 4.

  5. In one instance, select Singleplayer and Create New World.
    Once in the world access the game menu (start button on the controller) and select "Open to LAN" and then "Start LAN World".

  6. In all the other instances, select "Multiplayer" and wait for your game to appear in the list, select it and click "Join Server".

  7. Everything should work now! Use F11 to shift windows around. If people quit you can even use F11 to split the screen in half vertically or horizontally!

I was worried about performance issues, but I have had no problems on my PC (I7 3770K, 16GB RAM, 1660 Super, SSD).

// If you do experience lag, try adding the following mods: Sodium and Lithium. They greatly improve performance! See Steps 4 and 5 above for how to add mods. You will have to add these two mods to all instances. You can also add other interesting mods in the same way.

// Also, in Minecraft settings you will want to set music volume to 0% for all but one player (otherwise you will have 4 music tracks playing simultaneously!!)

// You may also want to right click on your task bar (start menu bar) and set it to autohide (under taskbar behaviours)!

reddit.com
u/Shidenissen — 21 days ago

How to set up Minecraft Splitscreen on PC (2-4 controllers playing on one screen: Java edition - incredibly easy to set up!)

Hi, being unfamiliar with the world of Minecraft I was not aware how easy it was for four children to play together on one screen, using one pc and 4 controllers.

As I did not find an up to date guide I thought I would give a brief overview to help any other people attempting the same.

  1. You must own Minecraft Java on your Microsoft account. (Just need one copy).
  2. Install Prismlauncher: https://prismlauncher.org/ - In Settings -> Java, ensure "Autodetect Java version" and "Auto-download Mojang java" are ticked. - In Settings -> Accounts, "Add Microsoft" in the top right. Then add 4 offline accounts - one for each player.
  3. At the Prismlauncher main screen, click "Add Instance" in the top left. - For Minecraft Version, select 26.1.1 - On the same screen on the right, under "Mod Loader", select "Fabric" and select version 0.19.3. - Press "OK"
  4. Right click the instance that you have just created and in the context menu, select "Edit". Then in the new window select "Mods" in the top left and then "Download Mods" in the top right.
  5. Select Modrinth or CurseForge on the left and in the search box, search for the following mods and for each one click "Select Mod for download": - Fabric API: Select the version at the top which will hopefully be: [26.1.2] Fabric API 0.155.2. - MidnightControls: Select the version at the top which will hopefully be: MidnightControls 1.12.1 + Fabric 26.1. - Splitscreen Support: Select the version at the top which will hopefully be: 1.18.0+26.1.1 (fabric).

Then click "Review and Confirm".

  1. Once all done, still editing your instance, click "Settings" on the left, then the Miscellaneous tab and then tick "Override default account" and select an offline account for your player (this will be your player's in game name).

  2. Launch your instance, wait for it to load.
    Press "F11" on the keyboard to move the window to suit you. Perhaps to the top left corner of the screen to make room for 3 other screens.

At the main menu, click Options -> Controls -> click the Gamepad symbol in the top right.
On the Controller tab, scroll down and set "Unfocused Input" to Yes.
On the Screens tab, scroll down and set "Virtual Mouse" to Yes.

Click Done 3 times to get to the main menu.

  1. Click Singleplayer, create a new world (any settings). Once in the world on your keyboard press: "F3 + P" to disable pause on lost focus.

Exit for now back to Prismlauncher.

  1. Right click on your instance and rename it to your first player's name. Right click on it again and select Copy. In the new window, type in your next player's name and click OK.

  2. Repeat this "copy" step two more times to get a total of 4 instances.

  3. All the settings and even pause on lost focus should have been copied over to each instance, but best to double check: For each of your 3 new instances, follow steps 6, 7, 8 above.

  4. Once all done, launch as many instances as you want 2 to 4.

  5. In one instance, select Singleplayer and Create New World.
    Once in the world access the game menu (start button on the controller) and select "Open to LAN" and then "Start LAN World".

  6. In all the other instances, select "Multiplayer" and wait for your game to appear in the list, select it and click "Join Server".

  7. Everything should work now! Use F11 to shift windows around. If people quit you can even use F11 to split the screen in half vertically or horizontally!

I was worried about performance issues, but I have had no problems on my PC (I7 3770K, 16GB RAM, 1660 Super, SSD).

// If you do experience lag, try adding the following mods: Sodium and Lithium. They greatly improve performance! See Steps 4 and 5 above for how to add mods. You will have to add these two mods to all instances. You can also add other interesting mods in the same way.

// Also, in Minecraft settings you will want to set music volume to 0% for all but one player (otherwise you will have 4 music tracks playing simultaneously!!)

// You may also want to right click on your task bar (start menu bar) and set it to autohide (under taskbar behaviours)!

reddit.com
u/Shidenissen — 21 days ago

How to set up Minecraft Splitscreen on PC (2-4 controllers playing on one screen: Java edition - incredibly easy to set up!)

Hi, being unfamiliar with the world of Minecraft I was not aware how easy it was for four children to play together on one screen, using one pc and 4 controllers.

As I did not find an up to date guide I thought I would give a brief overview to help any other people attempting the same.

  1. You must own Minecraft Java on your Microsoft account. (Just need one copy).

  2. Install Prismlauncher: https://prismlauncher.org/
    - In Settings -> Java, ensure "Autodetect Java version" and "Auto-download Mojang java" are ticked.
    - In Settings -> Accounts, "Add Microsoft" in the top right. Then add 4 offline accounts - one for each player.

  3. At the Prismlauncher main screen, click "Add Instance" in the top left.
    - For Minecraft Version, select 26.1.1
    - On the same screen on the right, under "Mod Loader", select "Fabric" and select version 0.19.3.
    - Press "OK"

  4. Right click the instance that you have just created and in the context menu, select "Edit". Then in the new window select "Mods" in the top left and then "Download Mods" in the top right.

  5. Select Modrinth or CurseForge on the left and in the search box, search for the following mods and for each one click "Select Mod for download":
    - Fabric API: Select the version at the top which will hopefully be: [26.1.2] Fabric API 0.155.2.
    - MidnightControls: Select the version at the top which will hopefully be: MidnightControls 1.12.1 + Fabric 26.1.
    - Splitscreen Support: Select the version at the top which will hopefully be: 1.18.0+26.1.1 (fabric).

Then click "Review and Confirm".

  1. Once all done, still editing your instance, click "Settings" on the left, then the Miscellaneous tab and then tick "Override default account" and select an offline account for your player (this will be your player's in game name).

  2. Launch your instance, wait for it to load.
    Press "F11" on the keyboard to move the window to suit you. Perhaps to the top left corner of the screen to make room for 3 other screens.

At the main menu, click Options -> Controls -> click the Gamepad symbol in the top right.
On the Controller tab, scroll down and set "Unfocused Input" to Yes.
On the Screens tab, scroll down and set "Virtual Mouse" to Yes.

Click Done 3 times to get to the main menu.

  1. Click Singleplayer, create a new world (any settings). Once in the world on your keyboard press: "F3 + P" to disable pause on lost focus.

Exit for now back to Prismlauncher.

  1. Right click on your instance and rename it to your first player's name. Right click on it again and select Copy. In the new window, type in your next player's name and click OK.

  2. Repeat this "copy" step two more times to get a total of 4 instances.

  3. All the settings and even pause on lost focus should have been copied over to each instance, but best to double check: For each of your 3 new instances, follow steps 6, 7, 8 above.

  4. Once all done, launch as many instances as you want 2 to 4.

  5. In one instance, select Singleplayer and Create New World.
    Once in the world access the game menu (start button on the controller) and select "Open to LAN" and then "Start LAN World".

  6. In all the other instances, select "Multiplayer" and wait for your game to appear in the list, select it and click "Join Server".

  7. Everything should work now! Use F11 to shift windows around. If people quit you can even use F11 to split the screen in half vertically or horizontally!

I was worried about performance issues, but I have had no problems on my PC (I7 3770K, 16GB RAM, 1660 Super, SSD).

reddit.com
u/Shidenissen — 21 days ago
▲ 3 r/NixOS

Nixos (unstable) with home manager. Correct hyprland (lua) configuration?

Hi

Hope you are all well.
I am trying to configure hyprland using home manager on nixos.

I got stuck in several places and used a LLM to work through some errors, but even the LLM seems to be struggling to fix the current issues (binds and exec-once hyprlock not working).

Considering that lua is the recommended configuration language now, how would I go about configuring something like this in home manager:

Thank you!

wayland.windowManager.hyprland = {
    enable = true;
    configType = "lua";

    extraConfig = ''
      local config = {
          autogenerated = 0,

          exec_once = {
              "hyprlock"
          },

          input = {
              kb_layout = "gb"
          },

          bind = {
              "SUPER, Q, exec, kitty",
              "SUPER, R, exec, hyprlauncher",
              "SUPER, M, exit",
          }
      }

      return config
    '';
  };
reddit.com
u/Shidenissen — 1 month ago

Launching TUI applications in floating windows from Waybar on-click events. (MangoWM)

Hi

I am running MangoWM and I love it. It's the best of hyprland and niri merged into one lighter package.

I highly recommend you try it out, I use a keybind to switch between tiling and scrolling variants and have disabled all others and it's amazing.

Anyway back to the topic.. I'm trying to make a system using as many TUI applications as possible. Such as nmtui for WiFi. Alsamixer for sound. Yazi etc.

After much reading of the Mango, Waybar and Foot wikis, I managed to make my own little fix for something that I being a complete arch newbie was quite proud of.

Nmtui when launched with an on-click event from waybar in a floating window (foot) always seemed to get truncated. Adjusting window size via foot flags did not help. However I noticed that if I launched nmtui in an existing foot window, the issue did not occur.

It seemed that if nmtui was loaded too soon into foot, the ncurses interface would get distorted for some reason. So I experimented with a few things and ended up with what is below (waybar on-click event to launch TUI application).

"on-click": "foot -T 'Network Manager TUI' sh -c 'sleep 1 && nmtui; read -t 0'"

Thus nmtui loads with a 1 second delay and this completely fixed the interface distortion issue for all my TUI applications.

Unfortunately when you exit nmtui the terminal window stayed there, which is why I added -t 0 at the end which closes the terminal window the moment the TUI application is closed.

I set a title above because in my mango config I have put:

Windowrule=isfloating:1,title: Network Manager TUI

Which makes the titled foot window float nicely.

Next I just need to figure out how to stop multiple instances of the nmtui when I keep clicking the WiFi icon on waybar. I will update if this noob finds something interesting.

reddit.com
u/Shidenissen — 3 months ago