From 03536fbbb17c407277dfecac9556105f7714bb8e Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Fri, 29 May 2026 23:10:15 -0700 Subject: [PATCH] hyprland: add tasking and dynamic cursor plugins --- dotfiles/config/hypr/hyprland/binds.lua | 16 ++- dotfiles/config/hypr/hyprland/core.lua | 2 +- dotfiles/config/hypr/hyprland/events.lua | 5 +- dotfiles/config/hypr/hyprland/settings.lua | 64 +++++++++++- dotfiles/config/hypr/hyprland/state.lua | 13 +++ dotfiles/config/hypr/hyprland/windows.lua | 108 +++++++++++++++++++ nixos/flake.lock | 116 +++++++++++++++------ nixos/flake.nix | 19 +++- nixos/hyprland.nix | 110 +++++++++++++++++-- 9 files changed, 407 insertions(+), 46 deletions(-) diff --git a/dotfiles/config/hypr/hyprland/binds.lua b/dotfiles/config/hypr/hyprland/binds.lua index b076b011..465c59ee 100644 --- a/dotfiles/config/hypr/hyprland/binds.lua +++ b/dotfiles/config/hypr/hyprland/binds.lua @@ -97,7 +97,19 @@ function M.setup(ctx) default_action = "bring", }), desc("Show all-workspace window overview", overview_bind_opts)) bind(main_mod .. " + SHIFT + slash", hyprwinview({ action = "toggle-filter" }), desc("Toggle window overview filter", overview_bind_opts)) - bind("ALT + Tab", hyprexpo("toggle"), desc("Toggle hyprexpo workspace overview", overview_bind_opts)) + bind("ALT + Tab", function() + if hl.plugin and hl.plugin.hyprtasking and hl.plugin.hyprtasking.toggle then + hl.plugin.hyprtasking.toggle("cursor") + else + hl.notification.create({ + text = "hyprtasking is not loaded", + duration = 1800, + icon = notification_icons.warning, + color = "rgba(edb443ff)", + font_size = 13, + }) + end + end, desc("Toggle hyprtasking workspace overview", overview_bind_opts)) bind("ALT + SHIFT + Tab", hyprexpo("on"), desc("Open hyprexpo workspace overview", overview_bind_opts)) bind(main_mod .. " + G", hyprwinview({ action = "show", @@ -227,6 +239,8 @@ function M.setup(ctx) bind(main_mod .. " + CTRL + Space", gather_workspace_into_tabbed_group, desc("Gather workspace into tabbed group")) bind(main_mod .. " + bracketright", monocle_next, desc("Focus next monocle window")) bind(main_mod .. " + bracketleft", monocle_prev, desc("Focus previous monocle window")) + bind(main_mod .. " + F", toggle_active_window_real_fullscreen, desc("Toggle active window real fullscreen")) + bind(main_mod .. " + SHIFT + F", toggle_active_window_gaming_mode, desc("Toggle active window gaming fullscreen")) bind(main_mod .. " + T", hl.dsp.window.float({ action = "disable" }), desc("Tile active window")) bind(main_mod .. " + O", toggle_pinned_active_window, desc("Toggle pinned active window")) bind(main_mod .. " + M", minimize_active_window, desc("Minimize active window")) diff --git a/dotfiles/config/hypr/hyprland/core.lua b/dotfiles/config/hypr/hyprland/core.lua index 7f0eb243..b9d391b1 100644 --- a/dotfiles/config/hypr/hyprland/core.lua +++ b/dotfiles/config/hypr/hyprland/core.lua @@ -198,7 +198,7 @@ function M.setup(ctx) end local function apply_hyprexpo_config() - if verify_config or not enable_hyprexpo then + if verify_config or not enable_hyprexpo or enable_hyprtasking then return end diff --git a/dotfiles/config/hypr/hyprland/events.lua b/dotfiles/config/hypr/hyprland/events.lua index cea88680..0f774b2c 100644 --- a/dotfiles/config/hypr/hyprland/events.lua +++ b/dotfiles/config/hypr/hyprland/events.lua @@ -26,7 +26,7 @@ function M.setup(ctx) } fullscreen_states[address] = current - if window.floating or current_layout == monocle_layout then + if window.floating or current_layout == monocle_layout or is_game_like_window(window) then return end @@ -41,6 +41,7 @@ function M.setup(ctx) apply_hyprexpo_config() apply_hyprwinview_config() apply_hyprwobbly_config() + apply_dynamic_cursors_config() apply_hyprglass_config() apply_visual_performance_mode() apply_rules() @@ -60,6 +61,7 @@ function M.setup(ctx) hl.on("config.reloaded", apply_hyprexpo_config) hl.on("config.reloaded", apply_hyprwinview_config) hl.on("config.reloaded", apply_hyprwobbly_config) + hl.on("config.reloaded", apply_dynamic_cursors_config) hl.on("config.reloaded", apply_hyprglass_config) hl.on("config.reloaded", apply_visual_performance_mode) hl.on("config.reloaded", apply_rules) @@ -83,7 +85,6 @@ function M.setup(ctx) hl.on("window.move_to_workspace", update_monocle_notice) hl.on("window.fullscreen", reconcile_fullscreen_state) hl.on("window.update_rules", reconcile_fullscreen_state) - hl.on("window.open", adopt_matching_scratchpad_window) hl.on("window.class", adopt_matching_scratchpad_window) hl.on("window.title", adopt_matching_scratchpad_window) diff --git a/dotfiles/config/hypr/hyprland/settings.lua b/dotfiles/config/hypr/hyprland/settings.lua index 920a21ad..4482ac4e 100644 --- a/dotfiles/config/hypr/hyprland/settings.lua +++ b/dotfiles/config/hypr/hyprland/settings.lua @@ -84,18 +84,24 @@ function M.setup(ctx) if enable_nstack and not verify_config then hl.plugin.load("/run/current-system/sw/lib/libhyprNStack.so") end - if enable_hyprexpo and not verify_config then - hl.plugin.load("/run/current-system/sw/lib/libhyprexpo.so") - end if enable_hyprwinview and not verify_config then hl.plugin.load("/run/current-system/sw/lib/libhyprwinview.so") end + if enable_hyprtasking and not verify_config then + hl.plugin.load("/run/current-system/sw/lib/libhyprtasking.so") + end + if enable_hyprexpo and not enable_hyprtasking and not verify_config then + hl.plugin.load("/run/current-system/sw/lib/libhyprexpo.so") + end if enable_workspace_history and not verify_config then hl.plugin.load("/run/current-system/sw/lib/libhypr-workspace-history.so") end if enable_hyprwobbly and not verify_config then hl.plugin.load("/run/current-system/sw/lib/libhyprwobbly.so") end + if enable_dynamic_cursors and not verify_config then + hl.plugin.load("/run/current-system/sw/lib/libhypr-dynamic-cursors.so") + end if enable_hyprglass and not verify_config then hl.plugin.load("/run/current-system/sw/lib/hyprglass.so") end @@ -287,6 +293,45 @@ function M.setup(ctx) }) end + local function apply_dynamic_cursors_config() + if verify_config or not enable_dynamic_cursors then + return + end + + hl.config({ + plugin = { + dynamic_cursors = { + enabled = true, + mode = "tilt", + threshold = 2, + tilt = { + limit = 5000, + activation = "negative_quadratic", + window = 100, + full = 60, + }, + shake = { + enabled = true, + threshold = 6.0, + base = 4.0, + speed = 4.0, + influence = 0.0, + limit = 0.0, + timeout = 2000, + effects = true, + ipc = false, + }, + hyprcursor = { + nearest = 1, + enabled = true, + resolution = -1, + fallback = "clientside", + }, + }, + }, + }) + end + local function apply_visual_performance_mode() if verify_config then return @@ -335,6 +380,18 @@ function M.setup(ctx) hl.workspace_rule({ workspace = "w[tv1]s[false]", gaps_out = 0, gaps_in = 0 }) hl.workspace_rule({ workspace = "f[1]s[false]", gaps_out = 0, gaps_in = 0 }) + hl.window_rule({ + name = "tagged-gaming-window", + match = { tag = gaming_window_tag }, + idle_inhibit = "fullscreen", + opaque = true, + no_blur = true, + no_shadow = true, + no_anim = true, + rounding = 0, + border_size = 0, + }) + hl.window_rule({ match = { class = "^()$", title = "^()$" }, float = true }) hl.window_rule({ match = { title = "^(Picture-in-Picture)$" }, float = true }) hl.window_rule({ @@ -432,6 +489,7 @@ function M.setup(ctx) ctx.apply_rules = apply_rules ctx.apply_hyprglass_config = apply_hyprglass_config ctx.apply_hyprwobbly_config = apply_hyprwobbly_config + ctx.apply_dynamic_cursors_config = apply_dynamic_cursors_config ctx.apply_visual_performance_mode = apply_visual_performance_mode ctx.is_file_chooser_window = is_file_chooser_window ctx.raise_file_chooser_window = raise_file_chooser_window diff --git a/dotfiles/config/hypr/hyprland/state.lua b/dotfiles/config/hypr/hyprland/state.lua index d87ce21d..19f4dcf4 100644 --- a/dotfiles/config/hypr/hyprland/state.lua +++ b/dotfiles/config/hypr/hyprland/state.lua @@ -46,6 +46,18 @@ return { }, minimized_workspace = "special:minimized", inactive_opacity_override_tag = "no-inactive-opacity", + gaming_window_tag = "gaming", + gaming_window_disabled_tag = "no-gaming", + gaming_window_class_patterns = {}, + gaming_window_title_patterns = {}, + gaming_window_excluded_class_patterns = { + "^[Hh]eroic$", + "^[Ss]team$", + }, + gaming_window_excluded_title_patterns = { + "^Heroic Games Launcher$", + "^Steam$", + }, tabbed_group_restore_workspace_prefix = "special:tabbed-monocle-restore-", current_layout = columns_layout, enable_nstack = true, @@ -54,6 +66,7 @@ return { enable_hyprtasking = false, enable_workspace_history = true, enable_hyprwobbly = true, + enable_dynamic_cursors = true, enable_hyprglass = false, hypr_visual_performance_mode = false, configure_nstack_plugin_from_lua = false, diff --git a/dotfiles/config/hypr/hyprland/windows.lua b/dotfiles/config/hypr/hyprland/windows.lua index 93f9c912..e7d3c935 100644 --- a/dotfiles/config/hypr/hyprland/windows.lua +++ b/dotfiles/config/hypr/hyprland/windows.lua @@ -365,6 +365,108 @@ function M.setup(ctx) return false end + local function value_matches_any_pattern(value, patterns) + value = tostring(value or "") + if value == "" then + return false + end + + for _, pattern in ipairs(patterns or {}) do + if value:find(pattern) then + return true + end + end + return false + end + + local function is_game_like_window(window) + if not window then + return false + end + + if window_has_tag(window, gaming_window_disabled_tag) then + return false + end + if + value_matches_any_pattern(window.class, gaming_window_excluded_class_patterns) + or value_matches_any_pattern(window.initial_class, gaming_window_excluded_class_patterns) + or value_matches_any_pattern(window.title, gaming_window_excluded_title_patterns) + or value_matches_any_pattern(window.initial_title, gaming_window_excluded_title_patterns) + then + return false + end + + return tostring(window.content_type or window.content or "") == "game" + or window_has_tag(window, gaming_window_tag) + or value_matches_any_pattern(window.class, gaming_window_class_patterns) + or value_matches_any_pattern(window.initial_class, gaming_window_class_patterns) + or value_matches_any_pattern(window.title, gaming_window_title_patterns) + or value_matches_any_pattern(window.initial_title, gaming_window_title_patterns) + end + + local function set_window_gaming_mode(window, enabled, opts) + local selector = window_selector(window) + if not selector then + return + end + + if enabled then + dispatch(hl.dsp.window.tag({ tag = "-" .. gaming_window_disabled_tag, window = selector })) + dispatch(hl.dsp.window.tag({ tag = "+" .. gaming_window_tag, window = selector })) + dispatch(hl.dsp.window.fullscreen_state({ + internal = 2, + client = 2, + action = "set", + window = selector, + })) + else + dispatch(hl.dsp.window.tag({ tag = "-" .. gaming_window_tag, window = selector })) + dispatch(hl.dsp.window.tag({ tag = "+" .. gaming_window_disabled_tag, window = selector })) + dispatch(hl.dsp.window.fullscreen_state({ + internal = 0, + client = 0, + action = "set", + window = selector, + })) + end + + if not (opts and opts.quiet) then + hl.notification.create({ + text = "Gaming fullscreen: " .. (enabled and "on" or "off"), + duration = 1600, + icon = enabled and notification_icons.ok or notification_icons.info, + color = enabled and "rgba(33ccffee)" or "rgba(edb443ff)", + font_size = 13, + }) + end + end + + local function toggle_active_window_gaming_mode() + local window = hl.get_active_window() + if not window then + return + end + + set_window_gaming_mode(window, not window_has_tag(window, gaming_window_tag)) + end + + local function toggle_active_window_real_fullscreen() + local window = hl.get_active_window() + if not window then + return + end + + local fullscreen = tonumber(window.fullscreen) or 0 + local fullscreen_client = tonumber(window.fullscreen_client) or 0 + local enabling = fullscreen ~= 2 or fullscreen_client ~= 2 + dispatch(hl.dsp.window.fullscreen_state({ + internal = enabling and 2 or 0, + client = enabling and 2 or 0, + action = "set", + window = window_selector(window), + })) + end + local function toggle_inactive_opacity_for_active_window() local window = hl.get_active_window() local selector = window_selector(window) @@ -490,6 +592,12 @@ function M.setup(ctx) ctx.gather_focused_class = gather_focused_class ctx.focus_next_class = focus_next_class ctx.show_active_window_info = show_active_window_info + ctx.window_has_tag = window_has_tag + ctx.value_matches_any_pattern = value_matches_any_pattern + ctx.is_game_like_window = is_game_like_window + ctx.set_window_gaming_mode = set_window_gaming_mode + ctx.toggle_active_window_gaming_mode = toggle_active_window_gaming_mode + ctx.toggle_active_window_real_fullscreen = toggle_active_window_real_fullscreen ctx.toggle_inactive_opacity_for_active_window = toggle_inactive_opacity_for_active_window ctx.raise_or_spawn = raise_or_spawn ctx.minimize_active_window = minimize_active_window diff --git a/nixos/flake.lock b/nixos/flake.lock index fe8d4b07..25c5c6d9 100644 --- a/nixos/flake.lock +++ b/nixos/flake.lock @@ -47,11 +47,11 @@ ] }, "locked": { - "lastModified": 1778620495, - "narHash": "sha256-Gu7UhWjwKCgSiVC3Qz/Rc7cYi9DNuDTBxYzg3kfLvfM=", + "lastModified": 1778857089, + "narHash": "sha256-TclWRW2SdFeETLaiTG4BA8C8C4m/LppQEldncqyTzAQ=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "be35f75ac305f430f5f9d89b5f5a4af59ca7567e", + "rev": "ab2b0af63fbc9fb779d684f19149b790978be8a8", "type": "github" }, "original": { @@ -114,11 +114,11 @@ ] }, "locked": { - "lastModified": 1779413820, - "narHash": "sha256-hydmw2JiC3f211MtY0kvm7uIQnMlHiChC7lisDrwKes=", + "lastModified": 1779510126, + "narHash": "sha256-AN19hN63A3nuuUsOo42dERR/fmMt/rSEqNc1F3xjpAs=", "owner": "sadjow", "repo": "claude-code-nix", - "rev": "7275f14fe05a6001e4832084b8332043d0206e39", + "rev": "304b96c0998c76633bacbb44daa6a5de40f92273", "type": "github" }, "original": { @@ -137,11 +137,11 @@ ] }, "locked": { - "lastModified": 1779385571, - "narHash": "sha256-qvJmkFUHLb0lWUHguEpcFh5sBUSSBzkjGimWkh7RMfQ=", + "lastModified": 1779998039, + "narHash": "sha256-TrNmfalbdX4VOXJyBYDX+jH6Ph7YJbUMAnq6/akCyms=", "owner": "sadjow", "repo": "codex-cli-nix", - "rev": "1b8816f0f793031ee98c928ae7a3bcca2f0b54c0", + "rev": "803b7de2cccae3abbb9d23c10826af087428b06e", "type": "github" }, "original": { @@ -161,11 +161,11 @@ ] }, "locked": { - "lastModified": 1779552492, - "narHash": "sha256-OqhlsHkumu0rcWD3Y+KAawXynOaF4L64L1q55dB9750=", + "lastModified": 1780092586, + "narHash": "sha256-xqFWCCEa8i1zD0NolREtdT8JNDv2pNZ7DQnNvsm0Qas=", "owner": "ilysenko", "repo": "codex-desktop-linux", - "rev": "c4c51883800dbf5fe8010c4a755daf1ca37ce316", + "rev": "defa5d3c027cfcef51e0f4026e3446312cde30b8", "type": "github" }, "original": { @@ -728,11 +728,11 @@ ] }, "locked": { - "lastModified": 1779336838, - "narHash": "sha256-n1+l78hJRABp4cQHKeD0BVByT0vZLPqd09Tvoq8Q+d8=", + "lastModified": 1779726696, + "narHash": "sha256-/p37CB5n6Wpw250b0Lq0CYwNq2D8uGKzDoBulyLcQqA=", "owner": "nix-community", "repo": "home-manager", - "rev": "928d72376949e222ea4f07b44828a55b0136422e", + "rev": "1a95e2efb477959b70b4a14c51035975c0481df6", "type": "github" }, "original": { @@ -742,6 +742,29 @@ "type": "github" } }, + "hypr-dynamic-cursors": { + "inputs": { + "hyprland": [ + "hyprland" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1779380037, + "narHash": "sha256-nWsdcG7kGhBf49VNLfMkaNEPKfT+wBQeIqI1VUgryRY=", + "owner": "VirtCode", + "repo": "hypr-dynamic-cursors", + "rev": "73f97322995e3e5deae6e230129d7aaf3faa853b", + "type": "github" + }, + "original": { + "owner": "VirtCode", + "repo": "hypr-dynamic-cursors", + "type": "github" + } + }, "hypr-workspace-history": { "inputs": { "hyprland": [ @@ -840,11 +863,11 @@ ] }, "locked": { - "lastModified": 1779879328, - "narHash": "sha256-YOnTi54JNKju0wsZ8ckP9IBV3w3fTrdyauWhrCcgjZI=", + "lastModified": 1779455466, + "narHash": "sha256-SBGT6GVkmpX5XoAf+oiVZWlv9xaNSWZeQ33HNIlrz0k=", "owner": "colonelpanic8", "repo": "hyprexpo", - "rev": "3a2f021956809e639e8411e9016c8e637b040c92", + "rev": "8bafe0dbc7c26a3269f7e0fa01e3fa3cf54a3161", "type": "github" }, "original": { @@ -918,11 +941,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1779442755, - "narHash": "sha256-HwUzj6ciD31cPosIQjbiA/eOSeKpuveu/vRdpdywWcA=", + "lastModified": 1779801868, + "narHash": "sha256-qLEUYPaxWezxcRttqLiU1/1YwrAiF0jfVyLePdpOKSs=", "ref": "refs/heads/main", - "rev": "c5154131b13e23af6d39bfa07edbd49ac179036a", - "revCount": 7350, + "rev": "864dc89c9595095b5368a890fb39afbc75f590ca", + "revCount": 7368, "submodules": true, "type": "git", "url": "https://github.com/hyprwm/Hyprland" @@ -1054,6 +1077,33 @@ "type": "github" } }, + "hyprtasking": { + "inputs": { + "hyprland": [ + "hyprland" + ], + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1779035440, + "narHash": "sha256-2+DK+rJ/t1BAAGvQOKTNlwHj3kgfBXgimjlHHpzRuAw=", + "owner": "yerlotic", + "repo": "hyprtasking", + "rev": "3390ce22bdbf2c2f59dad495c218ca3f9e82572e", + "type": "github" + }, + "original": { + "owner": "yerlotic", + "ref": "chase_v55", + "repo": "hyprtasking", + "type": "github" + } + }, "hyprtoolkit": { "inputs": { "aquamarine": [ @@ -1245,6 +1295,8 @@ "flake-utils" ], "nixpkgs": [ + "imalison-taffybar", + "taffybar", "nixpkgs" ], "taffybar": "taffybar", @@ -1401,11 +1453,11 @@ ] }, "locked": { - "lastModified": 1779382658, - "narHash": "sha256-sPYOWKQn/tL1R+ZlXXKOtN5Sql7WqzWCa4nhZeC3FOw=", + "lastModified": 1779813639, + "narHash": "sha256-MaXcIud4ELxIUojrZngqL63rLvJRH3JzjhE6GVeryqk=", "owner": "nixified-ai", "repo": "flake", - "rev": "49c82400f98718f2ddd57c49e03fd4c0e8dde0b3", + "rev": "1490129a551b6209cccf80453d7d03a1b5d62d10", "type": "github" }, "original": { @@ -1503,11 +1555,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1778443072, - "narHash": "sha256-zi7/fsqM/kFdNuED//4WOCUtezGtKKqRNORjMvfwjnA=", + "lastModified": 1779357205, + "narHash": "sha256-cCO8aTqss5x9Ky8GWkpY0Hy5fyTZEbtifSUV8QjSzic=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "da5ad661ba4e5ef59ba743f0d112cbc30e474f32", + "rev": "f83fc3c307e74bc5fd5adb7eb6b8b13ffd2a36e1", "type": "github" }, "original": { @@ -1535,11 +1587,11 @@ }, "nixpkgs_4": { "locked": { - "lastModified": 1778869304, - "narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=", + "lastModified": 1779560665, + "narHash": "sha256-tpyBcxPpcQb8ukyNF7DoCwfSY3VPsxHoYwj00Cayv5o=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "d233902339c02a9c334e7e593de68855ad26c4cb", + "rev": "64c08a7ca051951c8eae34e3e3cb1e202fe36786", "type": "github" }, "original": { @@ -1853,6 +1905,7 @@ "git-sync-rs": "git-sync-rs", "grub2-themes": "grub2-themes", "home-manager": "home-manager", + "hypr-dynamic-cursors": "hypr-dynamic-cursors", "hypr-workspace-history": "hypr-workspace-history", "hyprNStack": "hyprNStack", "hyprcursor": [ @@ -1871,6 +1924,7 @@ "hyprlang" ], "hyprscratch": "hyprscratch", + "hyprtasking": "hyprtasking", "hyprutils": "hyprutils", "hyprwinview": "hyprwinview", "hyprwobbly": "hyprwobbly", diff --git a/nixos/flake.nix b/nixos/flake.nix index b54dbfc5..85d72238 100644 --- a/nixos/flake.nix +++ b/nixos/flake.nix @@ -130,6 +130,16 @@ inputs.hyprland.follows = "hyprland"; }; + hyprtasking = { + # PR #114 tracks Hyprland 0.55 and adds Lua plugin functions. + url = "github:yerlotic/hyprtasking/chase_v55"; + inputs = { + hyprland.follows = "hyprland"; + nixpkgs.follows = "nixpkgs"; + systems.follows = "systems"; + }; + }; + hypr-workspace-history = { url = "github:colonelpanic8/hypr-workspace-history"; inputs.hyprland.follows = "hyprland"; @@ -145,6 +155,14 @@ }; }; + hypr-dynamic-cursors = { + url = "github:VirtCode/hypr-dynamic-cursors"; + inputs = { + hyprland.follows = "hyprland"; + nixpkgs.follows = "nixpkgs"; + }; + }; + hyprglass = { url = "github:colonelpanic8/hyprglass?ref=codex/hyprland-0.55-compat"; flake = false; @@ -197,7 +215,6 @@ imalison-taffybar = { url = "path:../dotfiles/config/taffybar"; inputs = { - nixpkgs.follows = "nixpkgs"; flake-utils.follows = "flake-utils"; xmonad.follows = "xmonad"; }; diff --git a/nixos/hyprland.nix b/nixos/hyprland.nix index 34828071..174a9728 100644 --- a/nixos/hyprland.nix +++ b/nixos/hyprland.nix @@ -8,20 +8,52 @@ }: let system = pkgs.stdenv.hostPlatform.system; hyprlandInput = inputs.hyprland; - avoidHyprlandGccIce = package: - package.override { + hyprlandInputPkgs = import hyprlandInput.inputs.nixpkgs {inherit system;}; + makeHyprlandGlaze = glaze: + (glaze.override { + enableSIMD = false; + }).overrideAttrs (old: { + cmakeFlags = + (old.cmakeFlags or []) + ++ [ + "-Dglaze_DEVELOPER_MODE=OFF" + "-Dglaze_ENABLE_FUZZING=OFF" + "-DBUILD_TESTING=OFF" + ]; + }); + avoidHyprlandGccIce = glaze: package: + (package.override { stdenv = pkgs.clangStdenv; - }; - hyprlandGccIceOverlay = final: prev: { - hyprland = prev.hyprland.override { + }).overrideAttrs (old: { + buildInputs = + map + (input: + if (input.pname or null) == "glaze" + then makeHyprlandGlaze glaze + else input) + (old.buildInputs or []); + }); + avoidOverlayHyprlandGccIce = final: package: + (package.override { stdenv = final.clangStdenv; - }; + }).overrideAttrs (old: { + buildInputs = + map + (input: + if (input.pname or null) == "glaze" + then makeHyprlandGlaze final.glaze + else input) + (old.buildInputs or []); + }); + hyprlandGccIceOverlay = final: prev: { + glaze = makeHyprlandGlaze prev.glaze; + hyprland = avoidOverlayHyprlandGccIce final prev.hyprland; hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;}; hyprland-with-tests = final.hyprland.override {withTests = true;}; }; # GCC 15.2 ICEs while compiling Hyprland 0.55 on this pin. Keep the # Hyprland/plugin pin set intact and build Hyprland itself with Clang. - baseHyprlandPackage = (avoidHyprlandGccIce hyprlandInput.packages.${system}.hyprland).overrideAttrs (_: { + baseHyprlandPackage = (avoidHyprlandGccIce hyprlandInputPkgs.glaze hyprlandInput.packages.${system}.hyprland).overrideAttrs (_: { # Clang 21 can segfault in LLVM's Live DEBUG_VALUE analysis while compiling # ConfigValues.cpp when this build runs in parallel. enableParallelBuilding = false; @@ -65,6 +97,9 @@ name = "${package.name}-lua-config"; inherit (package) version; paths = [package]; + meta = builtins.removeAttrs (package.meta or {}) ["outputsToInstall"] // { + mainProgram = package.meta.mainProgram or "Hyprland"; + }; passthru = (package.passthru or {}) // { @@ -157,6 +192,65 @@ platforms = lib.platforms.linux; }; }; + hyprtasking = pkgs.gcc14Stdenv.mkDerivation { + pname = "hyprtasking"; + version = "0.1.0-unstable-${inputs.hyprtasking.shortRev or "dirty"}"; + src = inputs.hyprtasking; + + strictDeps = true; + nativeBuildInputs = [ + pkgs.pkg-config + pkgs.meson + pkgs.ninja + ] ++ baseHyprlandPackage.nativeBuildInputs; + buildInputs = [baseHyprlandPackage] ++ baseHyprlandPackage.buildInputs; + + meta = { + description = "Powerful workspace management plugin for Hyprland"; + homepage = "https://github.com/raybbian/hyprtasking"; + license = lib.licenses.bsd3; + platforms = lib.platforms.linux; + }; + }; + hyprDynamicCursors = pkgs.gcc14Stdenv.mkDerivation { + pname = "hypr-dynamic-cursors"; + version = "0-unstable-${inputs.hypr-dynamic-cursors.shortRev or "dirty"}"; + src = inputs.hypr-dynamic-cursors; + + strictDeps = true; + nativeBuildInputs = + baseHyprlandPackage.nativeBuildInputs + ++ [ + baseHyprlandPackage + pkgs.pkg-config + ]; + buildInputs = [ (lib.getDev baseHyprlandPackage) ] ++ baseHyprlandPackage.buildInputs; + + dontConfigure = true; + dontUseCmakeConfigure = true; + dontUseMesonConfigure = true; + dontUseNinjaBuild = true; + dontUseNinjaInstall = true; + + buildPhase = '' + runHook preBuild + make + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + install -Dm755 out/dynamic-cursors.so "$out/lib/libhypr-dynamic-cursors.so" + runHook postInstall + ''; + + meta = { + description = "A plugin to make Hyprland cursor movement more realistic"; + homepage = "https://github.com/VirtCode/hypr-dynamic-cursors"; + license = lib.licenses.bsd3; + platforms = lib.platforms.linux; + }; + }; hyprNStack = pkgs.stdenv.mkDerivation { pname = "hyprNStack"; version = "0-unstable-${inputs.hyprNStack.shortRev or "dirty"}"; @@ -194,6 +288,8 @@ hyprexpo hyprwinview hyprWorkspaceHistory + hyprtasking + hyprDynamicCursors hyprwobbly ] ++ lib.optionals enableHyprglass [hyprglass];