diff --git a/README.md b/README.md index d8a4539..0cf7bd8 100644 --- a/README.md +++ b/README.md @@ -20,4 +20,8 @@ these are sorted by `theme - de`. ### Catppuccin - Gnome -![](./docs/assets/2024-01-08_14-24.png) \ No newline at end of file +![](./docs/assets/2024-01-08_14-24.png) + +### Catppuccin - Hyprland + +![](./docs/assets/2024-03-17_01-43.png) \ No newline at end of file diff --git a/assets/lockscreen.png b/assets/lockscreen.png new file mode 100644 index 0000000..124dcb4 Binary files /dev/null and b/assets/lockscreen.png differ diff --git a/assets/wallpaper.png b/assets/wallpaper.png new file mode 100644 index 0000000..d23cdaa Binary files /dev/null and b/assets/wallpaper.png differ diff --git a/config/analys.frag b/config/analys.frag new file mode 100644 index 0000000..021f59f --- /dev/null +++ b/config/analys.frag @@ -0,0 +1,223 @@ +precision mediump float; +varying vec2 v_texcoord; +uniform sampler2D tex; +uniform float time; + +// Analys cube +// (c) 2019 FMS_Cat, MIT License + +// == tweak these numbers, yee ===================================================================== +#define SIZE 0.5 +#define FX_NYOOOM 0.0 +#define FX_FORWARD 1.0 +#define FX_KICK (0.1*exp(-3.0*mod(BEAT,4.0))) +#define FX_TWIST (20.0*exp(-3.0*mod(BEAT-2.0,4.0))) +#define FX_SKEW 0.0 +#define FX_DEFORM (0.2*0.0) +#define FX_DEFORM_FREQ 0.1 + +// == raymarch related constants =================================================================== +#define MARCH_ITER 64 +#define MARCH_EPSILON 1E-4 +#define MARCH_NEAR 0.01 +#define MARCH_FAR 40.0 +#define MARCH_MULP 0.6 + +// == common macros ================================================================================ +#define HALF_PI 1.57079632679 +#define PI 3.14159265359 +#define TAU 6.28318530718 +#define BEAT (time*170.0/60.0) +#define saturate(i) clamp(i,0.,1.) +#define linearstep(a,b,t) saturate(((t)-(a))/((b)-(a))) + +// == common functions ============================================================================= +mat2 rotate2D( float t ) { + return mat2( cos( t ), -sin( t ), sin( t ), cos( t ) ); +} + +// == camera ======================================================================================= +struct Camera { + vec3 pos; + vec3 dir; + vec3 up; + float roll; + float fov; +}; + +Camera newCamera( vec3 pos, vec3 dir ) { + Camera camera; + camera.pos = pos; + camera.dir = dir; + camera.up = vec3( 0.0, 1.0, 0.0 ); + camera.roll = 0.0; + camera.fov = 0.5; + return camera; +} + +// == ray ========================================================================================== +struct Ray { + vec3 orig; + vec3 dir; +}; + +Ray newRay( vec3 ori, vec3 dir ) { + Ray ray; + ray.orig = ori; + ray.dir = dir; + return ray; +} + +Ray rayFromCamera( Camera camera, vec2 p ) { + vec3 dirX = normalize( cross( camera.dir, camera.up ) ); + vec3 dirY = cross( dirX, camera.dir ); + vec2 pt = rotate2D( camera.roll ) * p; + return newRay( + camera.pos, + normalize( pt.x * dirX + pt.y * dirY + camera.dir / tan( camera.fov ) ) + ); +} + +vec3 getRayPosition( Ray ray, float len ) { + return ray.orig + ray.dir * len; +} + +// == isect ======================================================================================== +struct Intersection { + Ray ray; + float len; + vec3 pos; +}; + +Intersection newIntersection( Ray ray, float len ) { + Intersection isect; + isect.ray = ray; + isect.len = len; + isect.pos = getRayPosition( ray, len ); + return isect; +} + +// == march result ================================================================================= +struct MarchResult { + float dist; + vec2 uv; +}; + +// == distFuncs ==================================================================================== +float distFuncBox( vec3 p, vec3 b ) { + vec3 d = abs( p ) - b; + return length( max( d, 0.0 ) ) + min( max( d.x, max( d.y, d.z ) ), 0.0 ); +} + +vec3 deform( vec3 p ) { + vec3 pt = p; + pt.xy = rotate2D( FX_SKEW * pt.z ) * pt.xy; + pt.x *= 1.0 - sqrt( FX_NYOOOM ); + pt.yz = rotate2D( FX_NYOOOM * exp( 5.0 * FX_NYOOOM ) * pt.x ) * pt.yz; + pt.y += 2.0 * FX_SKEW * pt.x; + pt += FX_DEFORM * ( + texture2D( tex, FX_DEFORM_FREQ * ( pt.xy ) + 0.5 ).xyz - 0.5 + ); + pt.zx = rotate2D( mod( 2.5 * time + PI, TAU ) + FX_TWIST * pt.y ) * pt.zx; + pt.xy = rotate2D( 0.6 * sin( 0.9 * time ) ) * pt.xy; + pt.yz = rotate2D( 0.6 * sin( 1.4 * time ) ) * pt.yz; + pt -= normalize( pt ) * FX_KICK * sin( 15.0 * length( pt ) - 40.0 * time ); + return pt; +} + +MarchResult distFunc( vec3 p ) { + MarchResult result; + + vec3 pt = p; + pt = deform( pt ); + result.dist = distFuncBox( pt, vec3( SIZE ) ); + + vec3 spt = vec3( 1.0 ); + + if ( FX_FORWARD > 0.0 ) { + vec3 ptIfs = p; + ptIfs.z = mod( ptIfs.z - 16.0 * time + 3.0 * sin( HALF_PI * BEAT + 0.5 ), 6.0 ) - 3.0; + for ( int i = 0; i < 6; i ++ ) { + float fi = float( i ); + spt *= sign( ptIfs ); + ptIfs = abs( ptIfs ) - vec3( 3.2, 4.5, 1.2 ) / max( 1E-2, FX_FORWARD ) * pow( 0.5, fi ); + ptIfs.xy = rotate2D( 1.1 ) * ptIfs.xy; + ptIfs.zx = rotate2D( 2.1 ) * ptIfs.zx; + } + + ptIfs = deform( ptIfs ); + + float distIfs = distFuncBox( ptIfs, vec3( SIZE ) ); + + if ( result.dist < distIfs ) { + spt = vec3( 1.0 ); + } else { + result.dist = distIfs; + pt = ptIfs; + } + } + + vec3 abspt = abs( pt ); + float n = max( abspt.x, max( abspt.y, abspt.z ) ); + + result.uv = 0.5 + ( + ( n == abspt.z ) ? ( pt.xy * vec2( sign( pt.z ), 1.0 ) ) : + ( n == abspt.x ) ? ( pt.zy * vec2( -sign( pt.x ), 1.0 ) ) : + ( pt.xz * vec2( 1.0, -sign( pt.y ) ) ) + ) * spt.x * spt.y * spt.z * 0.5 / SIZE; + + return result; +} + +vec3 normalFunc( vec3 p, float dd ) { + vec2 d = vec2( 0.0, dd ); + return normalize( vec3( + distFunc( p + d.yxx ).dist - distFunc( p - d.yxx ).dist, + distFunc( p + d.xyx ).dist - distFunc( p - d.xyx ).dist, + distFunc( p + d.xxy ).dist - distFunc( p - d.xxy ).dist + ) ); +} + +vec3 normalFunc( vec3 p ) { + return normalFunc( p, MARCH_NEAR ); +} + +// == main procedure =============================================================================== +void main() { + vec2 p = v_texcoord - 0.5; + Camera camera = newCamera( vec3( 0.0, 0.0, 0.0 ), vec3( 0.0, 0.0, -1.0 ) ); + camera.fov = 0.6 + 0.9 * FX_FORWARD * ( 0.5 + 0.5 * sin( HALF_PI * BEAT - 0.5 ) ); + camera.pos.z = 0.5 + 1.5 / camera.fov; + Ray ray = rayFromCamera( camera, p ); + + Intersection isect; + float rayLen = MARCH_NEAR; + vec3 rayPos = getRayPosition( ray, rayLen ); + MarchResult result; + for ( int i = 0; i < MARCH_ITER; i ++ ) { + result = distFunc( rayPos ); + if ( abs( result.dist ) < MARCH_NEAR ) { break; } + rayLen += result.dist * MARCH_MULP; + if ( MARCH_FAR < rayLen ) { break; } + rayPos = getRayPosition( ray, rayLen ); + } + + vec3 bg = vec3( 0.0 ); + + if ( abs( result.dist ) < MARCH_NEAR ) { + vec3 normal = normalFunc( rayPos ); + float edge = linearstep( 0.498, 0.499, abs( result.uv.x - 0.5 ) ); + edge += linearstep( 0.495, 0.497, abs( result.uv.y - 0.5 ) ); + vec2 uv = result.uv; + vec4 tex = texture2D( tex, uv ); + float fog = exp( -0.2 * max( 0.0, rayLen - 3.0 ) ); + gl_FragColor = vec4( fog * mix( + 0.1 + 0.1 * normal + 0.8 * tex.rgb, + 1.0 + 1.0 * sin( vec3( 0.0, 1.0, 2.0 ) + 10.0 * length( result.uv - 0.5 ) - 10.0 * time ), + edge + ), 1.0 ); + } else { + discard; + //gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); + } +} diff --git a/config/dunst.conf b/config/dunst.conf new file mode 100644 index 0000000..b6cb480 --- /dev/null +++ b/config/dunst.conf @@ -0,0 +1,64 @@ +# https://github.com/catppuccin/dunst/blob/main/src/mocha.conf +[global] + frame_color = "#89B4FA" + separator_color= frame + + follow = none + width = 300 + height = 145 + origin = top-right + alignment = "left" + vertical_alignment = "center" + ellipsize = "middle" + offset = "15x15" + padding = 15 + horizontal_padding = 15 + text_icon_padding = 15 + icon_position = "left" + min_icon_size = 48 + max_icon_size = 64 + progress_bar = true + progress_bar_height = 8 + progress_bar_frame_width = 1 + progress_bar_min_width = 150 + progress_bar_max_width = 300 + separator_height = 2 + frame_width = 2 + corner_radius = 8 + transparency = 0 + gap_size = 8 + line_height = 0 + notification_limit = 0 + idle_threshold = 120 + history_length = 20 + show_age_threshold = 60 + markup = "full" + font = "Atkinson Hyperlegible 10" + word_wrap = "yes" + sort = "yes" + shrink = "no" + indicate_hidden = "yes" + sticky_history = "yes" + ignore_newline = "no" + show_indicators = "no" + stack_duplicates = true + always_run_script = true + hide_duplicate_count = false + ignore_dbusclose = false + mouse_left_click = "do_action" + mouse_middle_click = "close_all" + mouse_right_click = "close_current" + +[urgency_low] +background = "#1E1E2E" +foreground = "#CDD6F4" + +[urgency_normal] +background = "#1E1E2E" +foreground = "#CDD6F4" + +[urgency_critical] +background = "#1E1E2E" +foreground = "#CDD6F4" +frame_color = "#FAB387" + diff --git a/config/nwg-drawer.css b/config/nwg-drawer.css new file mode 100644 index 0000000..b1b365c --- /dev/null +++ b/config/nwg-drawer.css @@ -0,0 +1,27 @@ +window { + /*background: @base;*/ + background: alpha(@base, 0.3); + color: @text; + font-family: 'Atkinson Hyperlegible', FontAwesome, Noto Sans CJK; + font-size: 14px; + font-style: normal; +} + +/* search entry */ +entry { + background-color: alpha(@surface0, 0.5); +} + +button, image { + background: none; + border: none +} + +button { + padding: 1em 0.5em; + border-radius: 1em; +} + +button:hover { + background-color: alpha(@surface0, 0.5); +} \ No newline at end of file diff --git a/config/rofi.rasi b/config/rofi.rasi new file mode 100644 index 0000000..a4cad5c --- /dev/null +++ b/config/rofi.rasi @@ -0,0 +1,98 @@ +* { + bg-col: #24273a; + bg-col-light: #313244; + border-col: #363a4f; + selected-col: #45475a; + pink: #f5c2e7; + fg-col: #cdd6f4; + fg-col2: @pink; + grey: #bac2de; + + width: 450px; +} + +element-text, element-icon , mode-switcher { + background-color: inherit; + text-color: inherit; +} + +window { + height: 500px; + border: 2px; + border-radius: 1em; + border-color: @pink; + background-color: @bg-col; +} + +mainbox {background-color: @bg-col;} + +inputbar { + margin: 10px 5px 5px 5px; + children: [prompt, entry]; + background-color: @bg-col; + padding: 1px; +} + +prompt { + background-color: transparent; + padding: 1px; + text-color: @fg-col; + border-radius: 1.5em; +} + +textbox-prompt-colon { + expand: true; + str: ":"; +} + +entry { + padding: 1px; + margin: 0px; + text-color: @fg-col; + background-color: @bg-col; +} + +listview { + border: 0px 0px 0px; + margin: 5px 0px 0px 10px; + columns: 1; + lines: 10; + background-color: @bg-col; +} + +element { + padding: 1px; + background-color: @bg-col; + text-color: @fg-col; +} + +element-icon {size: 12px;} + +element.selected { + background-color: @selected-col; + text-color: @fg-col2; +} + + +scrollbar { + width: 4px ; + border: 0; + handle-color: @fg-col; + handle-width: 8px ; + padding: 0; +} + +mode-switcher {spacing: 0;} + +button { + spacing: 0; + background-color: @bg-col-light; + text-color: @grey; + vertical-align: 0.5; + horizontal-align: 0.5; +} + +button.selected { + background-color: @bg-col; + text-color: @pink; +} \ No newline at end of file diff --git a/config/waybar.css b/config/waybar.css new file mode 100644 index 0000000..ca49431 --- /dev/null +++ b/config/waybar.css @@ -0,0 +1,118 @@ +* { + border: none; + border-radius: 0px; + min-height: 0; +} + +window#waybar { + color: @text; + /*background: alpha(@base, 0.6);*/ + background: @base; + border-radius: 1em; + /*font-family: VictorMono, Iosevka Nerd Font, Noto Sans CJK;*/ + /*font-family: 'Atkinson Hyperlegible', FontAwesome, Noto Sans CJK;*/ + font-family: CozetteVector, FontAwesome, Noto Sans CJK; + font-size: 13px; + font-style: normal; +} + +box.module, .modules-right box { + background-color: @surface0; + margin: 0 0.25em; + padding: 0.15em 0.25em; + border-radius: 1em; +} +.modules-right label.module { + margin: 0 0.5em; +} + +.modules-right box { + padding: 0.15em 0.4em; +} +.modules-left, .modules-right { + margin: 0.4em 0.5em; +} + +#workspaces { + background-color: @surface0; + padding: 0; +} + +#workspaces button { + background-color: transparent; + color: @text; + padding: 0 0.4em; +} + +#workspaces button:nth-child(1) { + border-top-left-radius: 1em; + border-bottom-left-radius: 1em; +} +#workspaces button:nth-last-child(1) { + border-top-right-radius: 1em; + border-bottom-right-radius: 1em; +} + +#workspaces button.visible { + background: @surface1; +} + +#workspaces button.active { + background: @pink; + color: @surface0; +} + +#workspaces button.urgent { + background: @red; + color: @surface0; +} + +#window { + background: transparent; +} + +#clock { + color: @lavender; +} + +#power-profiles-daemon { + color: @teal; +} + +#battery { + color: @green; +} + +#battery.charging { + color: @green; +} + +#battery.warning:not(.charging) { + color: @peach; +} + +#battery.critical:not(.charging) { + color: @maroon; +} + +#network { + color: @sapphire; +} + +#backlight { + color: @yellow; +} + +#pulseaudio { + color: @pink; +} + +#custom-power { + color: @red; +} + +tooltip { + color: @text; + background: @base; + border: 1px solid @pink; +} \ No newline at end of file diff --git a/default.nix b/default.nix index fcac25f..1649857 100644 --- a/default.nix +++ b/default.nix @@ -9,14 +9,24 @@ inherit (lib.modules) mkAliasOptionModule mkDefault mkIf; inherit (lib.my) mapModulesRec'; in { + # disables Nixpkgs Hyprland module to avoid conflicts + #disabledModules = [ "programs/hyprland.nix" ]; + imports = [ inputs.home-manager.nixosModules.home-manager - inputs.nix-colors.homeManagerModules.default (mkAliasOptionModule ["hm"] ["home-manager" "users" config.user.name]) + inputs.nix-colors.homeManagerModules.default + inputs.hyprland.nixosModules.default ] ++ (mapModulesRec' (toString ./modules) import); + hm.imports = [ + inputs.hyprlock.homeManagerModules.hyprlock + inputs.hypridle.homeManagerModules.hypridle + inputs.hyprland.homeManagerModules.default + ]; + # Common config for all nixos machines; environment.variables = { NIXPKGS_ALLOW_UNFREE = "1"; @@ -33,10 +43,11 @@ in { auto-optimise-store = true; keep-outputs = true; keep-derivations = true; - substituters = [ "https://nix-community.cachix.org" "https://nixpkgs-wayland.cachix.org" ]; + substituters = [ "https://nix-community.cachix.org" "https://nixpkgs-wayland.cachix.org" "https://hyprland.cachix.org" ]; trusted-public-keys = [ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" "nixpkgs-wayland.cachix.org-1:3lwxaILxMRkVhehr5StQprHdEo4IrE8sRho9R9HOLYA=" + "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc=" ]; }; }; diff --git a/docs/assets/2024-03-17_01-43.png b/docs/assets/2024-03-17_01-43.png new file mode 100644 index 0000000..245af61 Binary files /dev/null and b/docs/assets/2024-03-17_01-43.png differ diff --git a/flake.lock b/flake.lock index 278ff15..5c8c4aa 100644 --- a/flake.lock +++ b/flake.lock @@ -221,6 +221,227 @@ "type": "github" } }, + "hyprcursor": { + "inputs": { + "hyprlang": "hyprlang_2", + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1710091028, + "narHash": "sha256-yFk2kc8J2kVh0RWlwT+PQf0bpfUNcROOcRYcyQJbpk4=", + "owner": "hyprwm", + "repo": "hyprcursor", + "rev": "05db7dfd7fc261e0195e54f8a6d655d4f370e70f", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprcursor", + "type": "github" + } + }, + "hypridle": { + "inputs": { + "hyprlang": "hyprlang", + "nixpkgs": "nixpkgs_3", + "systems": "systems" + }, + "locked": { + "lastModified": 1710180874, + "narHash": "sha256-ZSn3wXQuRz36Ta/L+UCFKuUVG6QpwK2QmRkPjpQprU4=", + "owner": "hyprwm", + "repo": "hypridle", + "rev": "4395339a2dc410bcf49f3e24f9ed3024fdb25b0a", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hypridle", + "type": "github" + } + }, + "hyprland": { + "inputs": { + "hyprcursor": "hyprcursor", + "hyprland-protocols": "hyprland-protocols", + "hyprlang": "hyprlang_3", + "nixpkgs": "nixpkgs_4", + "systems": "systems_3", + "wlroots": "wlroots", + "xdph": "xdph" + }, + "locked": { + "lastModified": 1710344304, + "narHash": "sha256-jE+/UGqRYkKBBpLTTV5ayCtVmD9N1WsSKpufszUPzcA=", + "owner": "hyprwm", + "repo": "Hyprland", + "rev": "3e67ee0f5f66c74c0a0bd4f797361fd100c2e2d2", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "Hyprland", + "type": "github" + } + }, + "hyprland-catppuccin": { + "flake": false, + "locked": { + "lastModified": 1702668781, + "narHash": "sha256-9BhZq9J1LmHfAPBqOr64chiAEzS+YV6zqe9ma95V3no=", + "owner": "catppuccin", + "repo": "hyprland", + "rev": "fc228737d3d0c12e34a7fa155a0fc3192e5e4017", + "type": "github" + }, + "original": { + "owner": "catppuccin", + "repo": "hyprland", + "type": "github" + } + }, + "hyprland-protocols": { + "inputs": { + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1691753796, + "narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=", + "owner": "hyprwm", + "repo": "hyprland-protocols", + "rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprland-protocols", + "type": "github" + } + }, + "hyprlang": { + "inputs": { + "nixpkgs": [ + "hypridle", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1708212860, + "narHash": "sha256-nW3Zrhh9RJcMTvOcXAaKADnJM/g6tDf3121lJtTHnYo=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "11d5ccda071c153dfdc18ef65338956a51cef96a", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprlang_2": { + "inputs": { + "nixpkgs": [ + "hyprland", + "hyprcursor", + "nixpkgs" + ], + "systems": "systems_2" + }, + "locked": { + "lastModified": 1709914708, + "narHash": "sha256-bR4o3mynoTa1Wi4ZTjbnsZ6iqVcPGriXp56bZh5UFTk=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "a685493fdbeec01ca8ccdf1f3655c044a8ce2fe2", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprlang_3": { + "inputs": { + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1709914708, + "narHash": "sha256-bR4o3mynoTa1Wi4ZTjbnsZ6iqVcPGriXp56bZh5UFTk=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "a685493fdbeec01ca8ccdf1f3655c044a8ce2fe2", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprlang_4": { + "inputs": { + "nixpkgs": [ + "hyprlock", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1708212860, + "narHash": "sha256-nW3Zrhh9RJcMTvOcXAaKADnJM/g6tDf3121lJtTHnYo=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "11d5ccda071c153dfdc18ef65338956a51cef96a", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprlock": { + "inputs": { + "hyprlang": "hyprlang_4", + "nixpkgs": "nixpkgs_5", + "systems": "systems_4" + }, + "locked": { + "lastModified": 1710528547, + "narHash": "sha256-zi2exTT5e3OOK6P7s6IjdiUUIawhqMN4R9RiUJ+T6Fc=", + "owner": "hyprwm", + "repo": "hyprlock", + "rev": "7ee406bf9b11351e3d73e6b6b2aec7de93ba61bf", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlock", + "type": "github" + } + }, "nix-colors": { "inputs": { "base16-schemes": "base16-schemes", @@ -321,6 +542,54 @@ } }, "nixpkgs_3": { + "locked": { + "lastModified": 1708475490, + "narHash": "sha256-g1v0TsWBQPX97ziznfJdWhgMyMGtoBFs102xSYO4syU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0e74ca98a74bc7270d28838369593635a5db3260", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1709961763, + "narHash": "sha256-6H95HGJHhEZtyYA3rIQpvamMKAGoa8Yh2rFV29QnuGw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3030f185ba6a4bf4f18b87f345f104e6a6961f34", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1708475490, + "narHash": "sha256-g1v0TsWBQPX97ziznfJdWhgMyMGtoBFs102xSYO4syU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0e74ca98a74bc7270d28838369593635a5db3260", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { "locked": { "lastModified": 1710162809, "narHash": "sha256-i2R2bcnQp+85de67yjgZVvJhd6rRnJbSYNpGmB6Leb8=", @@ -341,9 +610,142 @@ "crystal-flake": "crystal-flake", "hardware": "hardware", "home-manager": "home-manager", + "hypridle": "hypridle", + "hyprland": "hyprland", + "hyprland-catppuccin": "hyprland-catppuccin", + "hyprlock": "hyprlock", "nix-colors": "nix-colors", - "nixpkgs": "nixpkgs_3", - "nixpkgs-unstable": "nixpkgs-unstable" + "nixpkgs": "nixpkgs_6", + "nixpkgs-unstable": "nixpkgs-unstable", + "waybar-catppuccin": "waybar-catppuccin" + } + }, + "systems": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, + "waybar-catppuccin": { + "flake": false, + "locked": { + "lastModified": 1678438606, + "narHash": "sha256-WLJMA2X20E5PCPg0ZPtSop0bfmu+pLImP9t8A8V4QK8=", + "owner": "catppuccin", + "repo": "waybar", + "rev": "f74ab1eecf2dcaf22569b396eed53b2b2fbe8aff", + "type": "github" + }, + "original": { + "owner": "catppuccin", + "repo": "waybar", + "type": "github" + } + }, + "wlroots": { + "flake": false, + "locked": { + "host": "gitlab.freedesktop.org", + "lastModified": 1709983277, + "narHash": "sha256-wXWIJLd4F2JZeMaihWVDW/yYXCLEC8OpeNJZg9a9ly8=", + "owner": "wlroots", + "repo": "wlroots", + "rev": "50eae512d9cecbf0b3b1898bb1f0b40fa05fe19b", + "type": "gitlab" + }, + "original": { + "host": "gitlab.freedesktop.org", + "owner": "wlroots", + "repo": "wlroots", + "rev": "50eae512d9cecbf0b3b1898bb1f0b40fa05fe19b", + "type": "gitlab" + } + }, + "xdph": { + "inputs": { + "hyprland-protocols": [ + "hyprland", + "hyprland-protocols" + ], + "hyprlang": [ + "hyprland", + "hyprlang" + ], + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1709299639, + "narHash": "sha256-jYqJM5khksLIbqSxCLUUcqEgI+O2LdlSlcMEBs39CAU=", + "owner": "hyprwm", + "repo": "xdg-desktop-portal-hyprland", + "rev": "2d2fb547178ec025da643db57d40a971507b82fe", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "xdg-desktop-portal-hyprland", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index 51bdfa9..f0bfea7 100644 --- a/flake.nix +++ b/flake.nix @@ -14,6 +14,15 @@ catppuccin-vsc.url = "github:catppuccin/vscode"; crystal-flake.url = "github:manveru/crystal-flake"; + + hyprland.url = "github:hyprwm/Hyprland"; + hyprlock.url = "github:hyprwm/hyprlock"; + hypridle.url = "github:hyprwm/hypridle"; + + waybar-catppuccin.url = "github:catppuccin/waybar"; + waybar-catppuccin.flake = false; + hyprland-catppuccin.url = "github:catppuccin/hyprland"; + hyprland-catppuccin.flake = false; }; outputs = inputs @ { diff --git a/hosts/seven-red-suns/default.nix b/hosts/seven-red-suns/default.nix index 1f28c7a..6afe63a 100644 --- a/hosts/seven-red-suns/default.nix +++ b/hosts/seven-red-suns/default.nix @@ -23,6 +23,10 @@ cowsay file which tree gnused yt-dlp prismlauncher ] ++ (with pkgs.my; [ olympus iterator-icons + ]) ++ (with pkgs.gnome; [ + # these are usually defaults, but are missing when non-gnome DEs are used + # however gnome apps are my beloved so i'm just adding them back + nautilus gnome-system-monitor pkgs.loupe gnome-disk-utility pkgs.gedit file-roller ]); # usually you don't need to do this, but this is a workaround for https://github.com/flameshot-org/flameshot/issues/3328 @@ -44,7 +48,8 @@ }; desktop = { envProto = "wayland"; - gnome.enable = true; + + /*gnome.enable = true; gnome.keybinds.shell = { # disable defaults "screenshot" = []; @@ -70,8 +75,21 @@ binding = "Launch1"; command = ''${grabScript}''; }; - }; + };*/ + #xfce.enable = true; + + # in my mind they're a lesbian polycule + hyprland.enable = true; + hyprlock.enable = true; + hyprpaper.enable = true; + hypridle.enable = true; + + dunst.enable = true; + waybar.enable = true; + rofi.enable = true; + nwg-drawer.enable = true; + themes.active = "catppuccin"; }; software = { diff --git a/hosts/seven-red-suns/lenovo-thinkpad-x1-1st-gen.nix b/hosts/seven-red-suns/lenovo-thinkpad-x1-1st-gen.nix index 7d43ed7..26f7996 100644 --- a/hosts/seven-red-suns/lenovo-thinkpad-x1-1st-gen.nix +++ b/hosts/seven-red-suns/lenovo-thinkpad-x1-1st-gen.nix @@ -1,6 +1,6 @@ # Largely based upon https://www.thinkwiki.org/wiki/X1_Linux_Tweaks -{ ... }: +{ pkgs, ... }: { # Laptop-specific battery usage tuning powerManagement.enable = true; @@ -11,8 +11,37 @@ # Use power-profile-daemon for battery saving management services.power-profiles-daemon.enable = true; + # better performance than the actual Intel driver + services.xserver.videoDrivers = ["modesetting"]; + + # OpenCL support and VAAPI + hardware.opengl = { + extraPackages = with pkgs; [ + #intel-compute-runtime + intel-media-driver + intel-vaapi-driver + libvdpau-va-gl + ]; + + extraPackages32 = with pkgs.pkgsi686Linux; [ + #intel-compute-runtime + intel-media-driver + intel-vaapi-driver + libvdpau-va-gl + ]; + }; + + environment.variables = { + LIBVA_DRIVER_NAME = "iHD"; + VDPAU_DRIVER = "va_gl"; + }; + + environment.systemPackages = with pkgs; [ intel-gpu-tools ]; + boot.kernelParams = [ # Enable the i915 Sandybridge Framebuffer Compression (confirmed 475mw savings) "i915.i915_enable_fbc=1" + "i915.fastboot=1" + "enable_gvt=1" ]; } \ No newline at end of file diff --git a/modules/desktop/default.nix b/modules/desktop/default.nix index c104a3a..e21c935 100644 --- a/modules/desktop/default.nix +++ b/modules/desktop/default.nix @@ -42,10 +42,31 @@ in { # https://discourse.nixos.org/t/boot-faster-by-disabling-udev-settle-and-nm-wait-online/6339 systemd.services.systemd-udev-settle.enable = false; systemd.services.NetworkManager-wait-online.enable = false; + + # https://wiki.archlinux.org/title/Systemd/Journal#Persistent_journals + # limit systemd journal size + # journals get big really fasti and on desktops they are not audited often + # on servers, however, they are important for both security and stability + # thus, persisting them as is remains a good idea + services.journald.extraConfig = '' + SystemMaxUse=100M + RuntimeMaxUse=50M + SystemMaxFileSize=50M + ''; } (mkIf (cfg.envProto == "wayland") { - # https://github.com/NixOS/nixpkgs/commit/b2eb5f62a7fd94ab58acafec9f64e54f97c508a6 - environment.sessionVariables.NIXOS_OZONE_WL = "1"; + environment.sessionVariables = { + # https://github.com/NixOS/nixpkgs/commit/b2eb5f62a7fd94ab58acafec9f64e54f97c508a6 + NIXOS_OZONE_WL = "1"; + # the rest are borrowed from https://github.com/NotAShelf/nyx/blob/9fbba55f565c630469a971bc71e5957dc228703b/modules/core/common/system/os/display/wayland/environment.nix#L18 + _JAVA_AWT_WM_NONEREPARENTING = "1"; + GDK_BACKEND = "wayland,x11"; + ANKI_WAYLAND = "1"; + MOZ_ENABLE_WAYLAND = "1"; + XDG_SESSION_TYPE = "wayland"; + SDL_VIDEODRIVER = "wayland"; + CLUTTER_BACKEND = "wayland"; + }; }) (mkIf (cfg.envProto == "x11") { services.xserver.excludePackages = [ pkgs.xterm ]; diff --git a/modules/desktop/dunst.nix b/modules/desktop/dunst.nix new file mode 100644 index 0000000..dabe965 --- /dev/null +++ b/modules/desktop/dunst.nix @@ -0,0 +1,17 @@ +{ lib, config, ... }: + +with lib; +let + cfg = config.modules.desktop.dunst; +in { + options.modules.desktop.dunst = { + enable = mkEnableOption "Enable dunst, a lightweight replacement for the notification daemons provided by most desktop environments"; + }; + + config = mkIf cfg.enable { + hm.services.dunst = { + enable = true; + configFile = ../../config/dunst.conf; + }; + }; +} \ No newline at end of file diff --git a/modules/desktop/fonts.nix b/modules/desktop/fonts.nix index 7cc0d0d..d459064 100644 --- a/modules/desktop/fonts.nix +++ b/modules/desktop/fonts.nix @@ -94,6 +94,7 @@ in { "org/gnome/desktop/interface".monospace-font-name = with cfg.fonts.monospace; "${family} ${toString size}"; }; } // (mkIf cfg.baseFonts { + fonts.enableDefaultPackages = true; fonts.packages = with pkgs; [ fira-code fira-code-symbols @@ -102,6 +103,10 @@ in { proggyfonts atkinson-hyperlegible cozette + twemoji-color-font + noto-fonts-color-emoji + noto-fonts-monochrome-emoji + #font-awesome ]; }); } \ No newline at end of file diff --git a/modules/desktop/hypridle.nix b/modules/desktop/hypridle.nix new file mode 100644 index 0000000..8b9fae3 --- /dev/null +++ b/modules/desktop/hypridle.nix @@ -0,0 +1,40 @@ +{ lib, config, pkgs, ... }: + +with lib; +let + cfg = config.modules.desktop.hypridle; +in { + options.modules.desktop.hypridle = { + enable = mkEnableOption "Enable hypridle, Hyprland's idle daemon"; + }; + + config = mkIf cfg.enable { + hm.services.hypridle = { + enable = true; + + lockCmd = "${lib.getExe config.hm.programs.hyprlock.package}"; + unlockCmd = "pkill -USR1 hyprlock"; + + listeners = [ + { + timeout = 60 * 1; # 1 min + onTimeout = "${lib.getExe pkgs.brightnessctl} -s set 20"; + onResume = "${lib.getExe pkgs.brightnessctl} -r" ; + } + { + timeout = 90; # 1.5 min + onTimeout = "hyprctl dispatch dpms off"; # turn off screen + onResume = "hyprctl dispatch dpms on"; # turn it back on + } + { + timeout = 60 * 2; # 2 min + onTimeout = "loginctl lock-session"; # lock the system + } + { + timeout = 60 * 5; # 5 min + onTimeout = "systemctl suspend"; # suspend + } + ]; + }; + }; +} \ No newline at end of file diff --git a/modules/desktop/hyprland.nix b/modules/desktop/hyprland.nix new file mode 100644 index 0000000..0ba63ec --- /dev/null +++ b/modules/desktop/hyprland.nix @@ -0,0 +1,267 @@ +{ inputs, lib, config, system, pkgs, ... }: + +with lib; +let + cfg = config.modules.desktop.hyprland; +in { + options.modules.desktop.hyprland = { + enable = mkEnableOption "Enable Hyprland, a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks"; + allowTearing = mkEnableOption "Enable tearing, reduces latency in games but unsupported on some GPUs"; + }; + + config = let + hyprpkgs = inputs.hyprland.packages.${system}; + in mkIf cfg.enable { + services.xserver.displayManager.sessionPackages = [ hyprpkgs.hyprland ]; + xdg.portal = { + enable = true; + extraPortals = [ pkgs.xdg-desktop-portal-gtk hyprpkgs.xdg-desktop-portal-hyprland ]; + config = { + common = { + default = [ "hyprland" "gtk" ]; + + # for flameshot to work + # https://github.com/flameshot-org/flameshot/issues/3363#issuecomment-1753771427 + "org.freedesktop.impl.portal.Screencast" = "hyprland"; + "org.freedesktop.impl.portal.Screenshot" = "hyprland"; + }; + }; + }; + hm.wayland.windowManager.hyprland = { + enable = true; + xwayland.enable = true; + package = hyprpkgs.hyprland; + + settings = { + source = []; + + "$mod" = "SUPER"; + bindm = [ + # Move/resize windows with mod + LMB/RMB and dragging + "$mod, mouse:272, movewindow" + "$mod, mouse:273, resizewindow" + ]; + bindel = [ + ", XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 10%+" + ", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 10%-" + ", XF86MonBrightnessUp, exec, ${lib.getExe pkgs.brightnessctl} s +5%" + ", XF86MonBrightnessDown, exec, ${lib.getExe pkgs.brightnessctl} s 5%-" + ]; + bindl = [ + ", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle" + ", XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle" + ]; + bindr = [ + "SUPER, Super_L, exec, ${lib.getExe pkgs.nwg-drawer}" + ]; + bind = + [ + "$mod, R, exec, ${lib.getExe pkgs.rofi-wayland} -show run" + ", Print, exec, ${lib.getExe pkgs.grimblast} copy area" + "$mod, T, exec, ${lib.getExe pkgs.wezterm}" + #"$mod, ;, exec, " + "$mod, Q, killactive, " + #"$mod, M, exit, " + "$mod, V, togglefloating, " + "$mod, P, pseudo, " # dwindle + "$mod, J, togglesplit, " # dwindle + + # Move focus with mod + arrow keys + "$mod, left, movefocus, l" + "$mod, right, movefocus, r" + "$mod, up, movefocus, u" + "$mod, down, movefocus, d" + + # Example special workspace (scratchpad) + "$mod, S, togglespecialworkspace, magic" + "$mod SHIFT, S, movetoworkspace, special:magic" + + # Scroll through existing workspaces with mod + scroll + "$mod, mouse_down, workspace, e+1" + "$mod, mouse_up, workspace, e-1" + ] + ++ ( + # workspaces + # binds $mod + [shift +] {1..10} to [move to] workspace {1..10} + builtins.concatLists (builtins.genList ( + x: let + ws = let + c = (x + 1) / 10; + in + builtins.toString (x + 1 - (c * 10)); + in [ + "$mod, ${ws}, workspace, ${toString (x + 1)}" + "$mod SHIFT, ${ws}, movetoworkspace, ${toString (x + 1)}" + ] + ) + 10) + ); + + input = { + kb_layout = "us,ru"; + kb_variant = "workman,"; + kb_options = "grp:alt_shift_toggle"; + touchpad = { + disable_while_typing = false; + natural_scroll = true; + }; + + follow_mouse = 1; + + sensitivity = 0; # -1.0 - 1.0, 0 means no modification. + }; + + # basically porting the default config for safety + + # See https://wiki.hyprland.org/Configuring/Monitors/ + monitor=",highrr,auto,auto"; + + + # See https://wiki.hyprland.org/Configuring/Keywords/ for more + + # Execute your favorite apps at launch + # exec-once = waybar & hyprpaper & firefox + + exec-once = [ "${lib.getExe pkgs.networkmanagerapplet}" ]; + + # Source a file (multi-file configs) + # source = ~/.config/hypr/myColors.conf + + # Some default env vars. + env = [ + "XCURSOR_THEME,${config.modules.desktop.themes.cursor.name}" + "XCURSOR_SIZE,24" + ]; + + general = { + # See https://wiki.hyprland.org/Configuring/Variables/ for more + + gaps_in = 6; + gaps_out = 6; + border_size = 2; + no_border_on_floating = true; + + layout = "dwindle"; + + resize_on_border = true; + + # https://wiki.hyprland.org/Configuring/Tearing/ + allow_tearing = cfg.allowTearing; + }; + + windowrulev2 = [ + # i think this only applies to proton + "immediate, class:^steam_app_" + "float, class:^steam_app_" + + # common popups + "float, class:file-roller" + "float, class:org.gnome.Loupe" + "float, initialTitle:^Open Folder$" + "float, initialTitle:^Open File$" + + #"float, class:org.gnome.Nautilus" + + # fix focus + "stayfocused, class:^pinentry-" + "stayfocused, class:^rofi" + + # workspace moving + "workspace 1, class:^vivaldi" + "workspace 2, class:code-url-handler" + "workspace 4, class:ArmCord" + ]; + + blurls = [ + "gtk-layer-shell" + "waybar" + ]; + + decoration = { + # See https://wiki.hyprland.org/Configuring/Variables/ for more + + rounding = 10; + + blur = { + enabled = true; + size = 4; + passes = 1; + #popups = true; + }; + + drop_shadow = false; + #shadow_range = 4; + #shadow_render_power = 3; + + # mistake mistake mistkae mistake mistake mistake mistake mistake mistake mistake + #screen_shader = toString ../../config/analys.frag; + }; + + animations = { + enabled = true; + + # https://wiki.hyprland.org/Configuring/Animations/ + + bezier = [ + "outCubic, 0.33, 1, 0.68, 1" + "outExpo, 0.16, 1, 0.3, 1" + ]; + + animation = [ + "windows, 1, 5, outExpo, popin" + "windowsOut, 1, 5, outCubic, popin 80%" + "border, 1, 2, outExpo" + "fade, 1, 3, outCubic" + "workspaces, 1, 6, outExpo" + ]; + }; + + dwindle = { + # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more + pseudotile = "yes"; # master switch for pseudotiling. Enabling is bound to mod + P in the keybinds section below + preserve_split = "yes"; # you probably want this + }; + + master = { + # See https://wiki.hyprland.org/Configuring/Master-Layout/ for more + new_is_master = true; + }; + + gestures = { + # See https://wiki.hyprland.org/Configuring/Variables/ for more + workspace_swipe = true; + }; + + misc = { + # See https://wiki.hyprland.org/Configuring/Variables/ for more + force_default_wallpaper = 0; # Set to 0 to disable the anime mascot wallpapers + disable_splash_rendering = true; + disable_hyprland_logo = true; + vrr = 2; + }; + + # Example windowrule v1 + # windowrule = float, ^(kitty)$ + # Example windowrule v2 + # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ + # See https://wiki.hyprland.org/Configuring/Window-Rules/ for more + }; + # this has to be done this way because source (on my end) is shoved at the bottom + # which means the theme variables aren't loaded in the regular config. + # luckily, extraConfig is always last + extraConfig = '' + general { + col.active_border=$pink + col.inactive_border=$surface0 + } + decoration { + col.shadow=$surface0 + col.shadow_inactive=$surface0 + } + misc { + background_color=$crust + } + ''; + }; + }; +} diff --git a/modules/desktop/hyprlock.nix b/modules/desktop/hyprlock.nix new file mode 100644 index 0000000..ef1e73a --- /dev/null +++ b/modules/desktop/hyprlock.nix @@ -0,0 +1,63 @@ +{ lib, config, pkgs, ... }: + +with lib; +let + cfg = config.modules.desktop.hyprlock; +in { + options.modules.desktop.hyprlock = { + enable = mkEnableOption "Enable hyprlock, a simple, yet fast, multi-threaded and GPU-accelerated screen lock for hyprland"; + }; + + config = mkIf cfg.enable { + security.pam.services.hyprlock.text = "auth include login"; + hm.programs.hyprlock = with config.colorScheme.colors; { + enable = true; + general = { + hide_cursor = false; + no_fade_in = true; + no_fade_out = true; + }; + backgrounds = [ + { + path = toString ../../assets/lockscreen.png; + blur_passes = 3; + blur_size = 6; + } + ]; + labels = [ + { + text = "cmd[update:1000] echo \"$(date +'%H:%M')\""; + font_size = 58; + color = "rgb(${base05})"; + font_family = config.modules.desktop.fonts.fonts.sansSerif.family; + position = { x = 0; y = 30; }; + } + { + text = "cmd[update:1000] echo \"$(date +'%A %B %e')\""; + font_size = 14; + color = "rgb(${base05})"; + font_family = config.modules.desktop.fonts.fonts.sansSerif.family; + position = { x = 0; y = 10; }; + } + ]; + input-fields = [ + { + size = { width = 300; height = 28; }; + outline_thickness = 2; + dots_size = 0.2; + fade_on_empty = false; + placeholder_text = ""; + + outer_color = "rgb(${base0E})"; + inner_color = "rgb(${base00})"; + font_color = "rgb(${base05})"; + check_color = "rgb(${base02})"; + fail_color = "rgb(${base08})"; + capslock_color = "rgb(${base09})"; + + position = { x = 0; y = -30; }; + } + ]; + }; + }; +} \ No newline at end of file diff --git a/modules/desktop/hyprpaper.nix b/modules/desktop/hyprpaper.nix new file mode 100644 index 0000000..cef14bf --- /dev/null +++ b/modules/desktop/hyprpaper.nix @@ -0,0 +1,23 @@ +{ lib, config, pkgs, ... }: + +with lib; +let + cfg = config.modules.desktop.hyprpaper; +in { + options.modules.desktop.hyprpaper = { + enable = mkEnableOption "Enable Hyprpaper, a blazing fast wayland wallpaper utility"; + }; + + config = mkIf cfg.enable { + hm.wayland.windowManager.hyprland.settings.exec-once = [ "${lib.getExe pkgs.hyprpaper}" ]; + hm.xdg.configFile."hypr/hyprpaper.conf" = let + img = ../../assets/wallpaper.png; + in { + text = '' + preload = ${img} + wallpaper = ,${img} + splash = false + ''; + }; + }; +} \ No newline at end of file diff --git a/modules/desktop/nwg-drawer.nix b/modules/desktop/nwg-drawer.nix new file mode 100644 index 0000000..60244d1 --- /dev/null +++ b/modules/desktop/nwg-drawer.nix @@ -0,0 +1,19 @@ +{ lib, config, pkgs, inputs, ... }: + +with lib; +let + cfg = config.modules.desktop.nwg-drawer; +in { + options.modules.desktop.nwg-drawer = { + enable = mkEnableOption "Enable nwg-drawer, a GTK-based application launcher for Wayland"; + }; + + config = mkIf cfg.enable { + hm.wayland.windowManager.hyprland.settings.exec-once = [ "${lib.getExe pkgs.nwg-drawer} -r -nofs -nocats -term wezterm -spacing 15 -fm nautilus" ]; + hm.xdg.configFile."nwg-drawer/drawer.css".text = + builtins.concatStringsSep "\n" [ + "@import \"${inputs.waybar-catppuccin}/themes/mocha.css\";" + (lib.readFile ../../config/nwg-drawer.css) + ]; + }; +} \ No newline at end of file diff --git a/modules/desktop/rofi.nix b/modules/desktop/rofi.nix new file mode 100644 index 0000000..4454266 --- /dev/null +++ b/modules/desktop/rofi.nix @@ -0,0 +1,22 @@ +{ lib, config, pkgs, ... }: + +with lib; +let + cfg = config.modules.desktop.rofi; +in { + options.modules.desktop.rofi = { + enable = mkEnableOption "Enable rofi, a window switcher, run dialog and dmenu replacement"; + }; + + config = mkIf cfg.enable { + hm.programs.rofi = { + enable = true; + package = pkgs.rofi-wayland; + font = with config.modules.desktop.fonts.fonts.monospace; "${family} ${toString size}"; + extraConfig = { + show-icons = true; + }; + theme = ../../config/rofi.rasi; + }; + }; +} \ No newline at end of file diff --git a/modules/desktop/themes/catppuccin/default.nix b/modules/desktop/themes/catppuccin/default.nix index 1edf194..934d9d8 100644 --- a/modules/desktop/themes/catppuccin/default.nix +++ b/modules/desktop/themes/catppuccin/default.nix @@ -3,7 +3,8 @@ with lib; let cfg = config.modules.desktop.themes; - #accent = "pink"; # TODO? + accent = "pink"; + variant = "mocha"; in { config = mkIf (cfg.active == "catppuccin") { colorScheme = inputs.nix-colors.colorSchemes.catppuccin-mocha; @@ -12,10 +13,10 @@ in { dark = true; gtkTheme = { - name = "Catppuccin-Mocha-Compact-Pink-Dark"; + name = "Catppuccin-Mocha-Compact-Pink-Dark"; #todo put accent in here package = pkgs.catppuccin-gtk.override { - variant = "mocha"; - accents = ["pink"]; + variant = variant; + accents = [ accent ]; tweaks = ["rimless"]; size = "compact"; }; @@ -35,7 +36,7 @@ in { vscode = { name = "Catppuccin Mocha"; extension = (pkgs.vscode-extensions.catppuccin.catppuccin-vsc.override { - accent = "pink"; + accent = accent; boldKeywords = false; italicComments = false; italicKeywords = false; @@ -45,6 +46,8 @@ in { }); }; }; + + hyprland = "${inputs.hyprland-catppuccin}/themes/${variant}.conf"; }; }; } \ No newline at end of file diff --git a/modules/desktop/themes/default.nix b/modules/desktop/themes/default.nix index 73de823..a0b1501 100644 --- a/modules/desktop/themes/default.nix +++ b/modules/desktop/themes/default.nix @@ -33,6 +33,8 @@ in { extension = mkPackageOption pkgs "extension" {}; }; }; + + hyprland = mkOpt (nullOr str) null; }; config = mkIf (cfg.active != null) { @@ -55,11 +57,18 @@ in { theme = cfg.gtkTheme; }; + hm.services.dunst.iconTheme = { + name = cfg.iconTheme.name; + package = cfg.iconTheme.package; + }; + hm.programs.vscode = { extensions = [ cfg.editor.vscode.extension ]; userSettings = { "workbench.colorTheme" = cfg.editor.vscode.name; }; }; + + hm.wayland.windowManager.hyprland.settings.source = mkIf (cfg.hyprland != null) [ cfg.hyprland ]; }; } \ No newline at end of file diff --git a/modules/desktop/waybar.nix b/modules/desktop/waybar.nix new file mode 100644 index 0000000..a93f1b0 --- /dev/null +++ b/modules/desktop/waybar.nix @@ -0,0 +1,244 @@ +{ lib, config, pkgs, inputs, ... }: + +with lib; +let + cfg = config.modules.desktop.waybar; +in { + options.modules.desktop.waybar = { + enable = mkEnableOption "Enable Waybar, a lightweight desktop environment based on GTK+"; + }; + + config = mkIf cfg.enable { + hm.wayland.windowManager.hyprland.settings.exec-once = [ "${lib.getExe pkgs.waybar}" ]; + hm.programs.waybar = { + enable = true; + #style = builtins.concatStringsSep "\n" [ + # "@import \"${inputs.waybar-catppuccin}/themes/mocha.css\";" + # (lib.readFile ../../config/waybar.css) + #]; + settings = { + mainBar = { + layer = "top"; + position = "top"; + #spacing = 4; + height = 24; + margin-top = 6; + margin-left = 6; + margin-right = 6; + margin-bottom = 0; + modules-left = [ + "hyprland/workspaces" + "hyprland/window" + ]; + modules-center = [ + "clock" + ]; + modules-right = [ + "group/status" + "tray" + "group/power" + ]; + + "group/status" = { + orientation = "inherit"; + modules = [ + "hyprland/language" + "pulseaudio" + "backlight" + "cpu" + "memory" + "power-profiles-daemon" + "battery" + #"network" + ]; + }; + "group/power" = { + orientation = "inherit"; + drawer = { + transition-duration = 200; + children-class = "not-power"; + transition-left-to-right = false; + }; + modules = [ + "custom/power" + "custom/lock" + "custom/reboot" + "custom/quit" + ]; + }; + "custom/quit" = { + format = ""; + tooltip = true; + tooltip-format = "Exit Hyprland"; + on-click = "hyprctl dispatch exit"; + }; + "custom/lock" = { + format = ""; + tooltip = true; + tooltip-format = "Lock the system"; + on-click = "hyprlock"; + }; + "custom/reboot" = { + format = "↻"; + tooltip = true; + tooltip-format = "Reboot"; + on-click = "reboot"; + }; + "custom/power" = { + format = "⏻"; + tooltip = true; + tooltip-format = "Power off"; + on-click = "shutdown now"; + }; + "hyprland/workspaces" = { + format = "{icon}"; + format-icons = { + "1" = ""; + "2" = ""; + "3" = ""; + "4" = ""; + urgent = ""; + default = "•"; + }; + persistent-workspaces = { + "1" = []; + "2" = []; + "3" = []; + "4" = []; + }; + }; + "hyprland/window" = { + format = "{}"; + icon = true; + icon-size = 16; + rewrite = { + "(.*) - Vivaldi" = "$1"; + "(.*) - Visual Studio Code" = "$1"; + #"(.*\\.nix\\s.*)" = ""; + "(\\S+\\.js\\s.*)" = " $1"; + "(\\S+\\.ts\\s.*)" = " $1"; + "(\\S+\\.go\\s.*)" = " $1"; + "(\\S+\\.lua\\s.*)" = " $1"; + "(\\S+\\.java\\s.*)" = " $1"; + "(\\S+\\.rb\\s.*)" = " $1"; + "(\\S+\\.php\\s.*)" = " $1"; + "(\\S+\\.jsonc?\\s.*)" = " $1"; + "(\\S+\\.md\\s.*)" = " $1"; + "(\\S+\\.txt\\s.*)" = " $1"; + "(\\S+\\.cs\\s.*)" = " $1"; + "(\\S+\\.c\\s.*)" = " $1"; + "(\\S+\\.cpp\\s.*)" = " $1"; + "(\\S+\\.hs\\s.*)" = " $1"; + ".*Discord | (.*) | .*" = "$1 - ArmCord"; + #"(.*) - ArmCord" = "$1"; + }; + separate-outputs = true; + }; + "hyprland/language" = { + format = " {}"; + format-en = "Aa"; + format-ru = "Ру"; + on-click = "hyprctl switchxkblayout at-translated-set-2-keyboard next"; + tooltip = true; + tooltip-format = "{flag} {long}"; + }; + pulseaudio = { + format = "{icon} {volume}%"; + format-bluetooth = "{icon} {volume}%"; + format-muted = "婢 {volume}%"; + format-icons = { + headphone = ""; + hands-free = ""; + headset = ""; + phone = ""; + portable = ""; + car = ""; + default = ["" "" ""]; + }; + scroll-step = 1; + on-click = "${lib.getExe pkgs.pavucontrol}"; + ignored-sinks = ["Easy Effects Sink"]; + }; + backlight = { + format = "{icon} {percent}%"; + format-icons = ["" ""]; + scroll-step = 1; + }; + cpu = { + interval = 4; + format = " {usage}%"; + }; + memory = { + interval = 4; + format = " {percentage}%"; + tooltip-format = "{used:0.1f}GiB/{avail:0.1f}GiB used\n{swapUsed:0.1f}GiB/{swapAvail:0.1f}GiB swap"; + }; + "battery" = { + interval = 30; + states = { + warning = 20; + critical = 10; + }; + full-at = 98; + format = "{icon} {capacity}%"; + format-icons = ["" "" "" "" ""]; + format-critical = " {capacity}%"; + tooltip-format = "{timeTo} ({power}W)"; + format-charging = " {capacity}%"; + }; + "network" = { + format = ""; + format-ethernet = ""; + format-wifi = " {signalStrength}%"; + format-disconnected = ""; + tooltip-format = "{ifname} via {gwaddr}"; + tooltip-format-wifi = "connected to {essid}"; + tooltip-format-ethernet = "{ifname}"; + tooltip-format-disconnected = "Disconnected"; + }; + "clock" = { + format = "{:%H:%M}"; + format-alt = "{:%a %b %d %R}"; + tooltip-format = "{calendar}"; + calendar = { + mode = "year"; + mode-mon-col = 3; + weeks-pos = "right"; + on-scroll = 1; + on-click-right = "mode"; + format = { + months = "{}"; + days = "{}"; + weeks = "W{}"; + weekdays = "{}"; + today = "{}"; + }; + actions = { + on-click-right = "mode"; + on-click-forward = "tz_up"; + on-click-backward = "tz_down"; + on-scroll-up = "shift_up"; + on-scroll-down = "shift_down"; + }; + }; + }; + power-profiles-daemon = { + format = "{icon}"; + tooltip-format = "Power profile: {profile}\nDriver: {driver}"; + tooltip = true; + format-icons = { + default = ""; + performance = " perf"; + balanced = " balance"; + power-saver = " save"; + }; + }; + tray = { + icon-size = 16; + spacing = 4; + }; + }; + }; + }; + }; +} \ No newline at end of file diff --git a/modules/fstrim.nix b/modules/fstrim.nix new file mode 100644 index 0000000..a0e92b1 --- /dev/null +++ b/modules/fstrim.nix @@ -0,0 +1,36 @@ +{ config, lib, ... }: + +with lib; +{ + # if lvm is enabled, then tell it to issue discards + # (this is good for SSDs and has almost no downsides on HDDs, so + # it's a good idea to enable it unconditionally) + environment.etc."lvm/lvm.conf".text = mkIf config.services.lvm.enable '' + devices { + issue_discards = 1 + } + ''; + + # discard blocks that are not in use by the filesystem, good for SSDs + services.fstrim = { + # we may enable this unconditionally across all systems becuase it's performance + # impact is negligible on systems without a SSD - which means it's a no-op with + # almost no downsides aside from the service firing once per week + enable = true; + + # the default value, good enough for average-load systems + interval = "weekly"; + }; + + # tweak fstim service to run only when on AC power + # and to be nice to other processes + # (this is a good idea for any service that runs periodically) + systemd.services.fstrim = { + unitConfig.ConditionACPower = true; + + serviceConfig = { + Nice = 19; + IOSchedulingClass = "idle"; + }; + }; +} \ No newline at end of file diff --git a/modules/lvm.nix b/modules/lvm.nix new file mode 100644 index 0000000..b3b3d32 --- /dev/null +++ b/modules/lvm.nix @@ -0,0 +1,5 @@ +{lib, ...}: +{ + # I don't use lvm, can be disabled + services.lvm.enable = lib.mkDefault false; +} \ No newline at end of file diff --git a/modules/security.nix b/modules/security.nix index 40419f8..b678638 100644 --- a/modules/security.nix +++ b/modules/security.nix @@ -67,6 +67,22 @@ in { }; networking.firewall.enable = false; + + services.usbguard = { + IPCAllowedUsers = [ "root" "${env.mainUser}" ]; + presentDevicePolicy = "allow"; + rules = '' + allow with-interface equals { 08:*:* } + + # Reject devices with suspicious combination of interfaces + reject with-interface all-of { 08:*:* 03:00:* } + reject with-interface all-of { 08:*:* 03:01:* } + reject with-interface all-of { 08:*:* e0:*:* } + reject with-interface all-of { 08:*:* 02:*:* } + ''; + }; + + environment.systemPackages = [ pkgs.usbguard ]; } // (mkIf cfg.useDoas { security.sudo.enable = false; security.doas.enable = true; diff --git a/modules/software/system/alacritty.nix b/modules/software/system/alacritty.nix index ee3f0f1..db37584 100644 --- a/modules/software/system/alacritty.nix +++ b/modules/software/system/alacritty.nix @@ -9,6 +9,7 @@ in { }; config = mkIf cfg.enable { + hm.programs.rofi.terminal = "alacritty"; hm.programs.alacritty = { enable = true; # custom settings diff --git a/modules/software/system/wezterm.nix b/modules/software/system/wezterm.nix index 0e3a2e6..0bc3ac9 100644 --- a/modules/software/system/wezterm.nix +++ b/modules/software/system/wezterm.nix @@ -9,6 +9,7 @@ in { }; config = mkIf cfg.enable { + hm.programs.rofi.terminal = "wezterm"; hm.programs.wezterm = { enable = true; # custom settings @@ -47,4 +48,4 @@ in { ''; }; }; -} \ No newline at end of file +} diff --git a/overlays/waybar.nix b/overlays/waybar.nix new file mode 100644 index 0000000..d865892 --- /dev/null +++ b/overlays/waybar.nix @@ -0,0 +1,31 @@ +final: prev: { + waybar = prev.waybar.overrideAttrs ( old: { + version = "0.10.0"; + + src = prev.fetchFromGitHub { + owner = "Alexays"; + repo = "Waybar"; + rev = "0.10.0"; + hash = "sha256-p1VRrKT2kTDy48gDXPMHlLbfcokAOFeTZXGzTeO1SAE="; + }; + + # fix gtk-layer-shell issue + mesonFlags = builtins.filter (a: !(prev.lib.strings.hasInfix "gtk-layer-shell" a)) old.mesonFlags; + + # fix cava version mismatch issue + postUnpack = let + # Derived from subprojects/cava.wrap + libcava.src = prev.fetchFromGitHub { + owner = "LukashonakV"; + repo = "cava"; + rev = "0.10.1"; + hash = "sha256-iIYKvpOWafPJB5XhDOSIW9Mb4I3A4pcgIIPQdQYEqUw="; + }; + in '' + pushd "$sourceRoot" + cp -R --no-preserve=mode,ownership ${libcava.src} subprojects/cava-0.10.1 + patchShebangs . + popd + ''; + } ); +} \ No newline at end of file