diff --git a/hosts/lambdaos/home.nix b/hosts/lambdaos/home.nix index a54cef1..237678c 100644 --- a/hosts/lambdaos/home.nix +++ b/hosts/lambdaos/home.nix @@ -27,7 +27,29 @@ nixpkgs.config.allowUnfree = true; modules = { - hyprland.enable = true; + hyprland = { + enable = true; + displays = [ + { + name = "DP-3"; + horizontal = 2560; + vertical = 1440; + horizontal-offset = 2560; + vertical-offset = 0; + refresh-rate = 360; + scale = "1"; + } + { + name = "DP-2"; + horizontal = 2560; + vertical = 1440; + horizontal-offset = 0; + vertical-offset = 0; + refresh-rate = 144; + scale = "1"; + } + ]; + }; games.enable = true; apps = { enable = true; diff --git a/hosts/muos/home.nix b/hosts/muos/home.nix index 4d5674b..4f6c9ae 100644 --- a/hosts/muos/home.nix +++ b/hosts/muos/home.nix @@ -29,7 +29,17 @@ modules = { hyprland = { enable = true; - displays = [ "eDP-1, 2256x1504@60, 0x0, 1" ]; + displays = [ + { + name = "eDP-1"; + horizontal = 2256; + vertical = 1504; + horizontal-offset = 0; + vertical-offset = 0; + refresh-rate = 60; + scale = "1"; + } + ]; }; games.enable = true; apps = { diff --git a/modules/automapaper/default.nix b/modules/automapaper/default.nix index 56ecbd6..cbdce38 100644 --- a/modules/automapaper/default.nix +++ b/modules/automapaper/default.nix @@ -6,188 +6,184 @@ in options.modules.automapaper = { enable = lib.mkEnableOption "enable automapaper"; hyprland = lib.mkEnableOption "enable hyprland exec-once integration"; - configurations = lib.mkOption { - description = "automapaper configurations per monitor"; - type = with lib.types; attrsOf (submodule { - options = { - init = lib.mkOption { - type = str; - description = "the shader executed to get the state for the initialisation, and re-initialisation steps"; - }; - state = lib.mkOption { - type = str; - description = "the shader executed to increment the state to the next generation"; - }; - display = lib.mkOption { - type = str; - description = "the shader executed to display the state to the monitor"; - }; - horizontal = lib.mkOption { - type = int; - description = "the amount of horizontal cells in the state"; - }; - vertical = lib.mkOption { - type = int; - description = "the amount of vertical cells in the state"; - }; - tps = lib.mkOption { - type = int; - description = "the target amount of ticks to simulate each second"; - }; - cycles = lib.mkOption { - type = int; - description = "the amount of state increments before the init shader is called again"; - }; - frames_per_tick = lib.mkOption { - type = int; - description = "the amount of times to call the display shader for each iteration of the state shader"; - }; + default-configuration = { + init = lib.mkOption + { + type = lib.types.str; + description = "the shader executed to get the state for the initialisation, and re-initialisation steps"; + default = '' + #version 310 es + precision highp float; + + uniform float time; + uniform vec2 resolution; + + out vec4 stateColor; + + float PHI = 1.61803398874989484820459; // Φ = Golden Ratio + + float gold_noise(in vec2 xy, in float seed){ + return fract(tan(distance(xy*PHI, xy)*seed)*xy.x); + } + + void main( void ) { + + vec2 position = gl_FragCoord.xy; + float color = gold_noise(position.xy, fract(time)); + + + stateColor = vec4(step(0.3, color), 0,0,step(0.3, color)); + }''; }; - }); + state = lib.mkOption { + type = lib.types.str; + description = "the shader executed to increment the state to the next generation"; + default = '' + #version 310 es + precision highp float; + + uniform sampler2D state; + uniform vec2 scale; + + out vec4 stateColor; + + vec4 get(int x, int y) { + return texture(state, (gl_FragCoord.xy + vec2(x, y)) / scale); + } + + void main() { + int sum = int(get(-1, -1).r + + get(-1, 0).r + + get(-1, 1).r + + get( 0, -1).r + + get( 0, 1).r + + get( 1, -1).r + + get( 1, 0).r + + get( 1, 1).r); + vec4 current = get(0,0); + if (sum == 3) { + stateColor.r = 1.0; + stateColor.g = 1.0; + } else if (sum == 2) { + stateColor = current; + if (current.r == 0.0) { + stateColor.g = max(current.g - 0.01, 0.0); + } + } else { + stateColor = vec4(0.0, max(current.g - 0.01, 0.0), 0.0, 1.0); + } + }''; + }; + display = lib.mkOption { + type = lib.types.str; + description = "the shader executed to display the state to the monitor"; + default = '' + #version 310 es + precision + highp + float; + + uniform sampler2D tex2D; + uniform sampler2D old2D; + uniform ivec2 resolution; + uniform float frame_part; + + in highp vec2 texCoords; + out vec4 stateColor; + + const vec4 bgColor = ${nix-colors.lib.conversions.hexToGLSLVec config.colorScheme.palette.base00}; + // #26052e + const vec4 fgColor = ${nix-colors.lib.conversions.hexToGLSLVec config.colorScheme.palette.base01}; + // #950fad + + void main() { + vec2 canvasSize = vec2 (textureSize (tex2D, 0)); + vec4 state = texture (tex2D, texCoords); + vec4 ostate = texture (old2D, texCoords); + + vec2 localCoords = fract (gl_FragCoord.xy / vec2 (resolution) * canvasSize); + localCoords = localCoords - 0.5; + float dist = sqrt (dot (localCoords, localCoords)); + + float size = smoothstep (0.0, 1.0, pow(mix(ostate.g,state.g, frame_part), 3.0)) * 0.35; + float mask = 1.0 - step (size, dist); + + float brightness = mix (ostate.r, state.r, frame_part) + 0.2 * pow(mix(ostate.g,state.g, frame_part), 3.0); + stateColor = mix (bgColor, fgColor, brightness * mask); + } ''; + }; + horizontal = lib.mkOption { + type = lib.types.int; + default = 10; + }; + vertical = lib.mkOption { + type = lib.types.int; + default = 10; + }; + tps = lib.mkOption { + type = lib.types.int; + description = "the target amount of ticks to simulate each second"; + default = 30; + }; + cycles = lib.mkOption { + type = lib.types.int; + description = "the amount of state increments before the init shader is called again"; + default = 2500; + }; + frames_per_tick = lib.mkOption { + type = lib.types.int; + description = "the amount of times to call the display shader for each iteration of the state shader"; + default = 1; + }; }; }; - config = lib.mkIf cfg.enable ( - let - displays = lib.attrsets.mapAttrs - (displayName: displayConfig: - let - init = builtins.toFile "init.frag" displayConfig.init; - state = builtins.toFile "state.frag" displayConfig.state; - display = builtins.toFile "display.frag" displayConfig.display; - in - '' - [display] - name="${displayName}" - horizontal=${builtins.toString displayConfig.horizontal} - vertical=${builtins.toString displayConfig.vertical} - tps=${builtins.toString displayConfig.tps} - state_frag="${state}" - init_frag="${init}" - display_frag="${display}" - cycles=${builtins.toString displayConfig.cycles} - frames_per_tick=${builtins.toString displayConfig.frames_per_tick} - '' - ) - cfg.configurations; - in + config = lib.mkIf cfg.enable { - modules.automapaper.configurations = + wayland.windowManager.hyprland.settings.exec-once = let - conf = { - horizontal = 256; - vertical = 144; - tps = 30; - init = '' - #version 310 es - precision highp float; - - uniform float time; - uniform vec2 resolution; - - out vec4 stateColor; - - float PHI = 1.61803398874989484820459; // Φ = Golden Ratio - - float gold_noise(in vec2 xy, in float seed){ - return fract(tan(distance(xy*PHI, xy)*seed)*xy.x); - } - - void main( void ) { - - vec2 position = gl_FragCoord.xy; - float color = gold_noise(position.xy, fract(time)); - - - stateColor = vec4(step(0.3, color), 0,0,step(0.3, color)); - }''; - state = '' - #version 310 es - precision highp float; - - uniform sampler2D state; - uniform vec2 scale; - - out vec4 stateColor; - - vec4 get(int x, int y) { - return texture(state, (gl_FragCoord.xy + vec2(x, y)) / scale); - } - - void main() { - int sum = int(get(-1, -1).r + - get(-1, 0).r + - get(-1, 1).r + - get( 0, -1).r + - get( 0, 1).r + - get( 1, -1).r + - get( 1, 0).r + - get( 1, 1).r); - vec4 current = get(0,0); - if (sum == 3) { - stateColor.r = 1.0; - stateColor.g = 1.0; - } else if (sum == 2) { - stateColor = current; - if (current.r == 0.0) { - stateColor.g = max(current.g - 0.01, 0.0); - } - } else { - stateColor = vec4(0.0, max(current.g - 0.01, 0.0), 0.0, 1.0); - } - - }''; - display = '' - #version 310 es - precision highp float; - - uniform sampler2D tex2D; - uniform sampler2D old2D; - uniform ivec2 resolution; - uniform float frame_part; - - in highp vec2 texCoords; - out vec4 stateColor; - - const vec4 bgColor = ${nix-colors.lib.conversions.hexToGLSLVec config.colorScheme.palette.base00}; // #26052e - const vec4 fgColor = ${nix-colors.lib.conversions.hexToGLSLVec config.colorScheme.palette.base01}; // #950fad - - void main() { - vec2 canvasSize = vec2(textureSize(tex2D, 0)); - vec4 state = texture(tex2D, texCoords); - vec4 ostate = texture(old2D, texCoords); - - vec2 localCoords = fract(gl_FragCoord.xy / vec2(resolution) * canvasSize); - localCoords = localCoords - 0.5; - float dist = sqrt(dot(localCoords, localCoords)); - - float size = smoothstep(0.0, 1.0, pow(mix(ostate.g,state.g, frame_part), 3.0)) * 0.35; - float mask = 1.0 - step(size, dist); - - float brightness = mix(ostate.r,state.r, frame_part) + 0.2 * pow(mix(ostate.g,state.g, frame_part), 3.0); - stateColor = mix(bgColor, fgColor, brightness * mask); - }''; - cycles = 2500; - frames_per_tick = 1; - }; - - displays_raw = config.modules.hyprland.displays; - displays = builtins.map (display_raw: builtins.head (lib.strings.splitString "," display_raw)) displays_raw; + mkDisplayConfig = conf: + let + init = builtins.toFile "init.frag" conf.init; + state = builtins.toFile "state.frag" conf.state; + display = builtins.toFile "display.frag" conf.display; + in + '' + [display] + name="${conf.name}" + horizontal=${builtins.toString conf.horizontal} + vertical=${builtins.toString conf.vertical} + tps=${builtins.toString conf.tps} + state_frag="${state}" + init_frag="${init}" + display_frag="${display}" + cycles=${builtins.toString conf.cycles} + frames_per_tick=${builtins.toString conf.frames_per_tick} + ''; + confFile = + let + def = config.modules.automapaper.default-configuration; + in + conf: builtins.toFile "${conf.name}.toml" (mkDisplayConfig { + name = conf.name; + horizontal = builtins.div conf.horizontal def.horizontal; + vertical = builtins.div conf.vertical def.vertical; + tps = def.tps; + state = def.state; + init = def.init; + display = def.display; + cycles = def.cycles; + frames_per_tick = def.frames_per_tick; + }); in - - builtins.listToAttrs - (builtins.map - (disp: { - name = disp; - value = conf; - }) - displays); - wayland.windowManager.hyprland.settings.exec-once = lib.mkIf cfg.hyprland ( - lib.mapAttrsToList - (name: config: - "${inputs.automapaper.packages.${pkgs.system}.default}/bin/automapaper -C ${builtins.toFile "${name}.toml" config}") - displays - ); - } - ); + lib.mkIf cfg.hyprland ( + builtins.map + ( + conf: + "${inputs.automapaper.packages.${pkgs.system}.default}/bin/automapaper -c ${confFile conf}" + ) + config.modules.hyprland.displays + ); + }; } + diff --git a/modules/hyprland.nix b/modules/hyprland.nix index a3d1e7f..ce1b72f 100644 --- a/modules/hyprland.nix +++ b/modules/hyprland.nix @@ -23,12 +23,48 @@ in default = pkgs.xdg-desktop-portal-hyprland; }; displays = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ - "DP-3,2560x1440@360,2560x0,1" - "DP-2,2560x1440@144,0x0,1" - "Unknown-1,disable" # NOTE: still borked on 04-06-2024 - ]; + type = lib.types.listOf + (lib.types.submodule { + options = { + name = lib.mkOption + { + type = lib.types.str; + description = "the display identifier"; + example = "DP-2"; + }; + horizontal = lib.mkOption { + type = lib.types.ints.positive; + description = "the horizontal resolution"; + example = 1920; + }; + vertical = lib.mkOption { + type = lib.types.ints.positive; + description = "the vertical resolution"; + example = 1080; + }; + horizontal-offset = lib.mkOption { + type = lib.types.ints.unsigned; + description = "the horizontal resolution"; + example = 1920; + }; + vertical-offset = lib.mkOption { + type = lib.types.ints.unsigned; + description = "the vertical resolution"; + example = 0; + }; + refresh-rate = lib.mkOption { + type = lib.types.ints.unsigned; + description = "the refresh rate of the monitor"; + example = 60; + }; + scale = lib.mkOption { + type = lib.types.str; + description = "the scale of the monitor"; + default = "1"; + example = "1.5"; + }; + }; + }); description = "the display layout to use"; }; }; @@ -89,105 +125,109 @@ in wayland.windowManager.hyprland = { enable = true; package = cfg.package; - settings = { - monitor = cfg.displays; - windowrulev2 = [ - "opacity 1.0 0.6,class:^(kitty)$" - "stayfocused,class:^(wofi)$" - ]; - env = [ - "WLR_NO_HARDWARE_CURSORS,1" - ]; - exec-once = [ - "${pkgs.waybar}/bin/waybar" - "${pkgs.dunst}/bin/dunst" - "${cfg.package}/bin/hyprctl dispatcher focusmonitor 1" - "${pkgs.keepassxc}/bin/keepassxc" - "${pkgs.spotify}/bin/spotify" - ]; - general = { - sensitivity = "1.2"; - gaps_in = "2"; - gaps_out = "3"; - border_size = "3"; - "col.active_border" = "0xff${config.colorScheme.palette.base01}"; - "col.inactive_border" = "0xff${config.colorScheme.palette.base00}"; - }; - input = { - touchpad = { - clickfinger_behavior = 1; - disable_while_typing = 1; - natural_scroll = 1; - tap-to-click = 1; - scroll_factor = 0.3; + settings = + let + make-display-string = display: "${display.name}, ${builtins.toString display.horizontal}x${builtins.toString display.vertical}@${builtins.toString display.refresh-rate}, ${builtins.toString display.horizontal-offset}x${builtins.toString display.vertical-offset}, ${display.scale}"; + in + { + monitor = builtins.map make-display-string cfg.displays; + windowrulev2 = [ + "opacity 1.0 0.6,class:^(kitty)$" + "stayfocused,class:^(wofi)$" + ]; + env = [ + "WLR_NO_HARDWARE_CURSORS,1" + ]; + exec-once = [ + "${pkgs.waybar}/bin/waybar" + "${pkgs.dunst}/bin/dunst" + "${cfg.package}/bin/hyprctl dispatcher focusmonitor 1" + "${pkgs.keepassxc}/bin/keepassxc" + "${pkgs.spotify}/bin/spotify" + ]; + general = { + sensitivity = "1.2"; + gaps_in = "2"; + gaps_out = "3"; + border_size = "3"; + "col.active_border" = "0xff${config.colorScheme.palette.base01}"; + "col.inactive_border" = "0xff${config.colorScheme.palette.base00}"; }; - }; - misc = { - key_press_enables_dpms = true; - }; - decoration = { - rounding = "6"; - active_opacity = "1"; - inactive_opacity = "1"; - }; - animations = { - enabled = "1"; - animation = [ - "windows,1,2,default" - "border,1,10,default" - "fade,0,5,default" - "workspaces,1,4,default" + input = { + touchpad = { + clickfinger_behavior = 1; + disable_while_typing = 1; + natural_scroll = 1; + tap-to-click = 1; + scroll_factor = 0.3; + }; + }; + misc = { + key_press_enables_dpms = true; + }; + decoration = { + rounding = "6"; + active_opacity = "1"; + inactive_opacity = "1"; + }; + animations = { + enabled = "1"; + animation = [ + "windows,1,2,default" + "border,1,10,default" + "fade,0,5,default" + "workspaces,1,4,default" + ]; + }; + "$mod" = "SUPER"; + bind = [ + "$mod,Return,exec,${cfg.terminal}/bin/${cfg.terminal.pname}" + "$mod,tab,cyclenext" + "SUPERSHIFT,Q,killactive" + "$mod,SPACE,exec,wofi-launch" + "$mod,P,exec,wofi-power" + "SUPERSHIFT,m,exit" + "$mod,H,movefocus,l" + "$mod,J,movefocus,u" + "$mod,K,movefocus,d" + "$mod,L,movefocus,r" + "SUPERSHIFT,H,movewindow,l" + "SUPERSHIFT,J,movewindow,u" + "SUPERSHIFT,K,movewindow,d" + "SUPERSHIFT,L,movewindow,r" + "$mod,F,togglefloating" + "$mod,X,togglespecialworkspace" + "SUPERSHIFT,X,movetoworkspace,special" + "SUPERSHIFT,S,exec,${pkgs.hyprshot}/bin/hyprshot -m region --clipboard-only" + "$mod,f11,fullscreen,0" + ",XF86AudioLowerVolume,exec,${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_SINK@ 1%-" + ",XF86AudioRaiseVolume,exec,${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_SINK@ 1%+" + ",XF86AudioMute,exec,${pkgs.wireplumber}/bin/wpctl set-mute @DEFAULT_SINK@ toggle" + ",XF86AudioPlay,exec,${pkgs.playerctl}/bin/playerctl play-pause" + ",XF86AudioPrev,exec,${pkgs.playerctl}/bin/playerctl previous" + ",XF86AudioNext,exec,${pkgs.playerctl}/bin/playerctl next" + "$mod,mouse_up,workspace,r-1" + "$mod,mouse_down,workspace,r+1" + ] + ++ ( + builtins.concatLists (builtins.genList + ( + x: + let + ws = builtins.toString (x); + in + [ + "$mod,${ws},workspace,${ws}" + "ALT,${ws},movetoworkspace,${ws}" + ] + ) + 10) + ); + bindm = [ + "$mod,mouse:272,movewindow" + "$mod,mouse:273,resizewindow" ]; }; - "$mod" = "SUPER"; - bind = [ - "$mod,Return,exec,${cfg.terminal}/bin/${cfg.terminal.pname}" - "$mod,tab,cyclenext" - "SUPERSHIFT,Q,killactive" - "$mod,SPACE,exec,wofi-launch" - "$mod,P,exec,wofi-power" - "SUPERSHIFT,m,exit" - "$mod,H,movefocus,l" - "$mod,J,movefocus,u" - "$mod,K,movefocus,d" - "$mod,L,movefocus,r" - "SUPERSHIFT,H,movewindow,l" - "SUPERSHIFT,J,movewindow,u" - "SUPERSHIFT,K,movewindow,d" - "SUPERSHIFT,L,movewindow,r" - "$mod,F,togglefloating" - "$mod,X,togglespecialworkspace" - "SUPERSHIFT,X,movetoworkspace,special" - "SUPERSHIFT,S,exec,${pkgs.hyprshot}/bin/hyprshot -m region --clipboard-only" - "$mod,f11,fullscreen,0" - ",XF86AudioLowerVolume,exec,${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_SINK@ 1%-" - ",XF86AudioRaiseVolume,exec,${pkgs.wireplumber}/bin/wpctl set-volume @DEFAULT_SINK@ 1%+" - ",XF86AudioMute,exec,${pkgs.wireplumber}/bin/wpctl set-mute @DEFAULT_SINK@ toggle" - ",XF86AudioPlay,exec,${pkgs.playerctl}/bin/playerctl play-pause" - ",XF86AudioPrev,exec,${pkgs.playerctl}/bin/playerctl previous" - ",XF86AudioNext,exec,${pkgs.playerctl}/bin/playerctl next" - "$mod,mouse_up,workspace,r-1" - "$mod,mouse_down,workspace,r+1" - ] - ++ ( - builtins.concatLists (builtins.genList - ( - x: - let - ws = builtins.toString (x); - in - [ - "$mod,${ws},workspace,${ws}" - "ALT,${ws},movetoworkspace,${ws}" - ] - ) - 10) - ); - bindm = [ - "$mod,mouse:272,movewindow" - "$mod,mouse:273,resizewindow" - ]; - }; }; }; } diff --git a/modules/waybar/default.nix b/modules/waybar/default.nix index b325587..1db0a0b 100644 --- a/modules/waybar/default.nix +++ b/modules/waybar/default.nix @@ -42,10 +42,6 @@ in ]; config = - let - displays_raw = config.modules.hyprland.displays; - displays = builtins.map (display_raw: builtins.head (lib.strings.splitString "," display_raw)) displays_raw; - in lib.mkIf cfg.enable { modules.waybar.enabled = ( @@ -75,7 +71,7 @@ in margin-top = 8; margin-left = 10; margin-right = 10; - output = displays; + output = builtins.map (display: display.name) config.modules.hyprland.displays; modules-left = cfg.modules.left; modules-center = cfg.modules.center; modules-right = cfg.modules.right;