{{- $tags := .chezmoi.config.data.tags -}} hl.config({ group = { auto_group = true, insert_after_current = true, focus_removed_window = true, drag_into_group = 1, merge_groups_on_drag = true, merge_groups_on_groupbar = true, merge_floated_into_tiled_on_groupbar = true, group_on_movetoworkspace = false, -- colors to be integrated via theme table groupbar = { enabled = true, height = 16, font_family = "GeistMono Nerd Font", font_size = 8, font_weight_active = "semibold", font_weight_inactive = "normal", stacked = false, gradients = true, gradient_rounding = 6, gradient_rounding_power = 4.0, gradient_round_only_edges = false, indicator_height = 0, rounding = 0, render_titles = true, scrolling = true, text_padding = 4, priority = 3 } } }) -- Permissions (NEW in v0.55) hl.permission({ binary = "/usr/bin/grim", type = "screencopy", mode = "allow" }) hl.permission({ binary = "/usr/bin/grimblast", type = "screencopy", mode = "allow" }) hl.permission({ binary = "/usr/bin/wf-recorder", type = "screencopy", mode = "allow" }) hl.permission({ binary = "/usr/lib/xdg-desktop-portal-hyprland", type = "screencopy", mode = "allow" }) hl.permission({ binary = "/usr/bin/hyprpm", type = "plugin", mode = "allow" }) -- Window Rules hl.window_rule({ match = { class = ".*" }, suppress_event = "maximize" }) -- XWayland fixes hl.window_rule({ match = { class = "^$", title = "^$", xwayland = true, float = true, fullscreen = false, pin = false }, no_focus = true }) hl.window_rule({ match = { xwayland = true }, no_initial_focus = true }) -- Communication hl.window_rule({ match = { class = "^(info\\.mumble\\.Mumble|discord|vesktop|teamspeak-client|TeamSpeak|TeamSpeak 3|teamspeak3)$" }, workspace = "2" }) hl.window_rule({ match = { class = "^(Element)$" }, workspace = "3" }) -- Mail hl.window_rule({ match = { class = "^(org\\.mozilla\\.Thunderbird)$" }, workspace = "1" }) -- Notes hl.window_rule({ match = { class = "^(@joplin/app-desktop)$" }, workspace = "4" }) {{- if index $tags "entertainment" }} -- Multimedia hl.window_rule({ match = { class = "Spotify" }, workspace = "6" }) {{- end }} {{- if index $tags "cs2" }} -- Gaming hl.window_rule({ match = { class = "^(steam)$" }, workspace = "5" }) {{- end }} -- Game Content Bypass (Option A - per-monitor CTM bypass) -- Automatically mark Steam games as "game" content type hl.window_rule({ match = { class = "^steam_app_%d+$" }, content = "game" }) -- Dynamic bypass for custom environment variable NO_BLUELIGHT=1 local function get_process_env(pid, name) if not pid or pid <= 0 then return nil end local f = io.open("/proc/" .. tostring(pid) .. "/environ", "r") if not f then return nil end local content = f:read("*a") f:close() if not content then return nil end for var in content:gmatch("([^%z]+)") do local k, v = var:match("^([^=]+)=(.*)$") if k == name then return v end end return nil end -- Escape regex metacharacters so classes like "org.mozilla.firefox" match literally. local function regex_escape(s) return (s:gsub("([%^%$%.%|%?%*%+%(%)%[%]%{%}\\])", "\\%1")) end -- window_rule registrations persist, so only add one per class (otherwise rules -- accumulate on every matching window.open). local bluelight_bypassed = {} hl.on("window.open", function(w) if not (w.pid and w.pid > 0 and w.class) then return end if bluelight_bypassed[w.class] then return end if get_process_env(w.pid, "NO_BLUELIGHT") == "1" then bluelight_bypassed[w.class] = true hl.window_rule({ match = { class = "^" .. regex_escape(w.class) .. "$" }, content = "game" }) end end) -- System hl.window_rule({ match = { class = "com.saivert.pwvucontrol" }, float = true }) hl.window_rule({ match = { class = "scrrec" }, float = true, pin = true, idle_inhibit = "always", rounding = 10, opacity = 0.6, border_size = 0, size = { 300, 100 }, move = { "1%", "1%" }, monitor = 0, no_initial_focus = true }) hl.window_rule({ match = { class = "com.gabm.satty" }, float = true, min_size = { 700, 400 } }) -- Layer Rules hl.layer_rule({ match = { namespace = "quickshell:.*" }, blur = true, ignore_alpha = 0.79 }) hl.layer_rule({ match = { namespace = "quickshell:popout" }, animation = "bouncy" })