diff options
| -rw-r--r-- | flake.lock | 81 | ||||
| -rw-r--r-- | modules/desktop/eww/bar/bar.nix | 18 | ||||
| -rw-r--r-- | modules/desktop/eww/bar/niri-status.lua | 57 |
3 files changed, 97 insertions, 59 deletions
@@ -37,11 +37,11 @@ ] }, "locked": { - "lastModified": 1777487137, - "narHash": "sha256-TuvKVBX60mqyMT6OB5JqVEh1YIWtFMR/igLCaCdC9tw=", + "lastModified": 1788181969, + "narHash": "sha256-OUB6hPlFBB9FRdZgZXSye4lDOg+fbrqKe8ePv2IM7NY=", "owner": "cachix", "repo": "cachix", - "rev": "a66a440c321d35f7193472c317f42a55ccd1cb93", + "rev": "98093e8eea6c1635ef1337a576fa76f3e8bd4f39", "type": "github" }, "original": { @@ -84,11 +84,11 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1788303825, - "narHash": "sha256-R1tqmYSV5yVTqmy+uISsSn+eEiqgW0F49orOHCOBSts=", + "lastModified": 1789152246, + "narHash": "sha256-8ESHEGygXS5lmDepm5cMbmVd8DjcwgwzsmjHc9ffY1c=", "owner": "cachix", "repo": "devenv", - "rev": "df5c75a82c3ac3d70a13c90fb869b7e44470a118", + "rev": "6e323832a55097670dbd8eed04b1e63efc841dfa", "type": "github" }, "original": { @@ -121,11 +121,11 @@ ] }, "locked": { - "lastModified": 1778716662, - "narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=", + "lastModified": 1788306937, + "narHash": "sha256-lbrI1UYVpFgKSsyrU9oeF7FHfnu8nLD9ja0ou9f2rxk=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb", + "rev": "f16b25b8c3d2809b87925d0b76652d7821a75c68", "type": "github" }, "original": { @@ -142,11 +142,11 @@ ] }, "locked": { - "lastModified": 1787559586, - "narHash": "sha256-onL0VLf9vPllmT0H/OlURIU5r5t5WIEl7t4tVNKT0Nw=", + "lastModified": 1788450739, + "narHash": "sha256-glZLQlzIn1fXH6PazR2iUmTo7kzzyYSshrWhLS9TqCU=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "9d0d87172c374f89da73c1cfe6d81ae62feac1f1", + "rev": "31729ca8cbdb4fa927b34e5f4353e6a83f39e993", "type": "github" }, "original": { @@ -174,16 +174,17 @@ "ghostty": { "flake": false, "locked": { - "lastModified": 1784602798, - "narHash": "sha256-298x90knBUWX5GHGXh2SKsAKvStjU2ri9UgOGoF79/8=", + "lastModified": 1786026742, + "narHash": "sha256-tRtgTg/i3w1nFdRHU2IGekfJN8EyP+HARW4MtoUZyqk=", "owner": "ghostty-org", "repo": "ghostty", - "rev": "88b4cd047fa627cdca6781bc7e7dc8b75a2cecb9", + "rev": "22d13172cde98a0a4dda05d3d6a3fcb0dd8ed018", "type": "github" }, "original": { "owner": "ghostty-org", "repo": "ghostty", + "rev": "22d13172cde98a0a4dda05d3d6a3fcb0dd8ed018", "type": "github" } }, @@ -199,11 +200,11 @@ ] }, "locked": { - "lastModified": 1782908218, - "narHash": "sha256-wLMOrPgVyeF3XmP+qfYcLqnVdTxikdcSvbIY7rA9jTA=", + "lastModified": 1788267358, + "narHash": "sha256-nt+lUqYVpc9Y6JeMd2WmXzCDojasdadKo0mWcluvY2Y=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "9f7e99119ece7705299595299f3b031f39356de1", + "rev": "27555e2624241fb116b49095df4caaee85a25691", "type": "github" }, "original": { @@ -219,11 +220,11 @@ ] }, "locked": { - "lastModified": 1788355065, - "narHash": "sha256-gAz5oTI7ur34CfuakQduiQd/2ZhO62Bn2XXg08nZYYQ=", + "lastModified": 1789235087, + "narHash": "sha256-6hZ6Gy8isRQsWdI4l81Egag/PUIh68nSmFr2maInUNg=", "owner": "nix-community", "repo": "home-manager", - "rev": "d9d750e4fc11c10cab2da677bdd31e427f3a3a71", + "rev": "fe48612c5321a2cc09b0f563757a9c9733d641f8", "type": "github" }, "original": { @@ -286,11 +287,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1783935112, - "narHash": "sha256-IAQ14nteIKXAz4cd75UcZrsHGEVJ7QNrkUwX9rmeZ/Y=", + "lastModified": 1788165251, + "narHash": "sha256-ITHt6eU6DuwQqlNV1/wehvKYPE6J8sZIlv75CpDjcHI=", "owner": "nix-community", "repo": "nixd", - "rev": "a64cd33e53b316b6b092ea0a966640cd2309bf3d", + "rev": "e2ca72c353cfbc3d63e942fe9aeae4ec497863bf", "type": "github" }, "original": { @@ -301,11 +302,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1787964612, - "narHash": "sha256-qeiZaY+0tpZXliRA9odCNx+sOfIOhnkcUq9t+ctPrRA=", - "rev": "e8be7818e19ada32105a8af937a6a473b38167ca", + "lastModified": 1789073787, + "narHash": "sha256-vLblJRFZjrSBOyHD4jwBkGJm2iOVk8c9BJnzZTOojSc=", + "rev": "aff8a0b28396750446e5537a96461bc4facdb287", "type": "tarball", - "url": "https://releases.nixos.org/nixpkgs/nixpkgs-26.11pre1063758.e8be7818e19a/nixexprs.tar.xz" + "url": "https://releases.nixos.org/nixpkgs/nixpkgs-26.11pre1071116.aff8a0b28396/nixexprs.tar.xz" }, "original": { "id": "nixpkgs", @@ -314,11 +315,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1787631388, - "narHash": "sha256-vMiXptXarfSdJb1Gkc+FYVOAibuBRj7qxGa8z68q1Uw=", + "lastModified": 1789012029, + "narHash": "sha256-1CBkBf+Nhggykzlx0jvXrj5rk20btl+tK8Fa8Ml/BL4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ac6b2166e7a9375683b8e98f860f273222337b16", + "rev": "d5dfd8e6716dde34398bc14bc87c10dece9c8c68", "type": "github" }, "original": { @@ -335,11 +336,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1788190018, - "narHash": "sha256-59BAfH0txPAZrPBF4QJqwvUWppD+ICrcjA1LZAmPnrQ=", + "lastModified": 1789067777, + "narHash": "sha256-gN3OnYgJwCK0HX01dQGWusnirJuVHE9WigmSqOnyuCE=", "owner": "nix-community", "repo": "nixvim", - "rev": "41844750e55f17b1385d5b09ca7ade5f11f49506", + "rev": "16baff93297c63b6d4c497f00ffcf0b844b06fc6", "type": "github" }, "original": { @@ -365,11 +366,11 @@ ] }, "locked": { - "lastModified": 1782875958, - "narHash": "sha256-5eqDcnBjb1424HRQdnhuhNOBZguq1Z2tqSa2OMF/m2c=", + "lastModified": 1788332415, + "narHash": "sha256-BTFrmyh0oaVDsvA9NNw0YpbbeppTwU0t70iVx672Ew8=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "13139aefa973f3d96c60c0fbab801de058ae25ca", + "rev": "860d7c835ab91bfc8972b67092f5f2db8e9390a0", "type": "github" }, "original": { @@ -404,11 +405,11 @@ ] }, "locked": { - "lastModified": 1780220602, - "narHash": "sha256-eynAfOmbmxJnkp7YewvCEbShNnnYJ9gLLqkzsYtBPeM=", + "lastModified": 1786901030, + "narHash": "sha256-WSFCsDSE5ffgD2MqzkM2CYjeFiKhRF/dJUN8uedb6YE=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "db947814a175b7ca6ded66e21383d938df01c227", + "rev": "27b3b12a8e6375f28ebe122f07d230ca5459bbfa", "type": "github" }, "original": { diff --git a/modules/desktop/eww/bar/bar.nix b/modules/desktop/eww/bar/bar.nix index 0daf7a6..70bfbac 100644 --- a/modules/desktop/eww/bar/bar.nix +++ b/modules/desktop/eww/bar/bar.nix @@ -109,15 +109,15 @@ [ (lib.getExe niri-status) (lib.getExe system-stats) - (toString ../../../../assets/icons/bar/offline.svg) - (toString ../../../../assets/icons/bar/wifi.svg) - (toString ../../../../assets/icons/bar/ethernet.svg) - (toString ../../../../assets/icons/bar/proxy.svg) - (toString ../../../../assets/icons/bar/cpu.svg) - (toString ../../../../assets/icons/bar/ram.svg) - (toString ../../../../assets/icons/bar/audio.svg) - (toString ../../../../assets/icons/bar/calendar.svg) - (toString ../../../../assets/icons/bar/battery.svg) + "${../../../../assets/icons/bar/offline.svg}" + "${../../../../assets/icons/bar/wifi.svg}" + "${../../../../assets/icons/bar/ethernet.svg}" + "${../../../../assets/icons/bar/proxy.svg}" + "${../../../../assets/icons/bar/cpu.svg}" + "${../../../../assets/icons/bar/ram.svg}" + "${../../../../assets/icons/bar/audio.svg}" + "${../../../../assets/icons/bar/calendar.svg}" + "${../../../../assets/icons/bar/battery.svg}" ] (builtins.readFile ./bar.yuck); }; diff --git a/modules/desktop/eww/bar/niri-status.lua b/modules/desktop/eww/bar/niri-status.lua index 6e214c3..e4f21a2 100644 --- a/modules/desktop/eww/bar/niri-status.lua +++ b/modules/desktop/eww/bar/niri-status.lua @@ -89,12 +89,10 @@ local function resolve_icon_path(app_id) if not app_info then local lc = string.lower(app_id) for _, info in ipairs(g_list_to_table(Gio.AppInfo.get_all())) do - if info:is_a(DesktopAppInfo) then - local wm = info:get_startup_wm_class() - if wm and string.lower(wm) == lc then - app_info = info - break - end + local ok_wm, wm = pcall(function() return info:get_startup_wm_class() end) + if ok_wm and wm and string.lower(wm) == lc then + app_info = info + break end end end @@ -129,6 +127,38 @@ local function niri_json(command) return nil end +local function sanitize_utf8(s) + if type(s) ~= "string" or s == "" then return s end + local out = {} + local i, n = 1, #s + while i <= n do + local c = s:byte(i) + local len + if c < 0x80 then len = 1 + elseif c >= 0xC2 and c <= 0xDF then len = 2 + elseif c >= 0xE0 and c <= 0xEF then len = 3 + elseif c >= 0xF0 and c <= 0xF4 then len = 4 + else len = 0 end + + local valid = len > 0 and (i + len - 1 <= n) + if valid then + for k = 1, len - 1 do + local cc = s:byte(i + k) + if not cc or cc < 0x80 or cc > 0xBF then valid = false break end + end + end + + if valid then + out[#out + 1] = s:sub(i, i + len - 1) + i = i + len + else + out[#out + 1] = "\239\191\189" -- U+FFFD + i = i + 1 + end + end + return table.concat(out) +end + local function window_sort_key(w) local layout = w.layout or {} local pos = layout.pos_in_scrolling_layout @@ -180,8 +210,8 @@ local function build_state() for _, w in ipairs(on_active) do active_windows_result[#active_windows_result + 1] = { id = w.id, - title = w.title or "", - app_id = w.app_id or "", + title = sanitize_utf8(w.title or ""), + app_id = sanitize_utf8(w.app_id or ""), is_focused = w.is_focused or false, icon = resolve_icon_path(w.app_id or ""), } @@ -214,7 +244,9 @@ local function build_state() local lines = { ws_name } for idx, w in ipairs(ws_windows) do - lines[#lines + 1] = string.format("%d. %s: %s", idx, (w.app_id and w.app_id ~= "" and w.app_id) or "unknown", (w.title and w.title ~= "" and w.title) or "(untitled)") + local w_app_id = sanitize_utf8(w.app_id or "") + local w_title = sanitize_utf8(w.title or "") + lines[#lines + 1] = string.format("%d. %s: %s", idx, (w_app_id and w_app_id ~= "" and w_app_id) or "unknown", (w_title and w_title ~= "" and w_title) or "(untitled)") end workspaces_result[#workspaces_result + 1] = { @@ -241,7 +273,12 @@ local function emit_state() io.stderr:write(tostring(result) .. "\n") return end - print(cjson.encode(result)) + local ok2, encoded = pcall(cjson.encode, result) + if not ok2 then + io.stderr:write(tostring(encoded) .. "\n") + return + end + print(encoded) io.stdout:flush() end |
