Compare commits

..

3 Commits

Author SHA1 Message Date
Olivier e68321ac1e Add Virtual-1 display configuration to DMS settings
- Included a new display entry for "Virtual-1" in the DMS settings.json file, enhancing display management capabilities.
2026-07-13 12:39:05 -03:00
Olivier 5357ba307b Fix dms-plugins
- Transitioned to an auto-derived plugin registry from flake inputs, simplifying the addition of new plugins by requiring edits only in `flake.nix`.
- Implemented a camelCase transformation for plugin IDs to align with upstream conventions, with exceptions for specific plugins.
- Enhanced the `shipPlugin` function to route plugin sources correctly, ensuring compatibility with the DMS structure.
- Added assertions to validate Obsidian vault paths at build time, improving error handling and user guidance.
2026-07-13 12:39:05 -03:00
Olivier 9960e874c4 Refactor DMS IPC bindings for Niri and Hyprland
- Updated `binds.nix` files for both Niri and Hyprland to utilize a centralized `dmsIpcBinds` structure, improving maintainability and consistency across keybindings.
- Introduced `dmsIpcBinds` in `default.nix` for both modules to streamline the command definitions for DMS IPC calls.
- Enhanced `dms` module to define shared IPC commands, ensuring uniform command formatting for different compositors.
2026-07-13 12:39:05 -03:00
7 changed files with 127 additions and 51 deletions
+10 -12
View File
@@ -1,6 +1,6 @@
{ ... }: {
flake.lib.hyprlandBinds =
{ lib, dmsEnabled ? false }:
{ lib, dmsEnabled ? false, dmsIpcBinds }:
let
workspaceBinds =
(builtins.map (i: "Super, ${toString i}, workspace, ${toString i}") (builtins.genList (n: n + 1) 9))
@@ -28,17 +28,15 @@
"Super, Equal, splitratio, 0.1"
"AltSuper, Space, togglefloating"
"Super, P, pin"
]
++ lib.optionals dmsEnabled [
"Super, Space, exec, dms ipc call spotlight toggle"
"Super, I, exec, dms ipc call settings focusOrToggle"
"Super, N, exec, dms ipc call notepad toggle"
"ShiftSuper, N, exec, dms ipc call notifications toggle"
"Super, M, exec, dms ipc call processlist focusOrToggle"
"Super, L, exec, dms ipc call lock lock"
"ShiftSuper, V, exec, dms ipc call clipboard toggle"
]
++ [
] ++ lib.optionals dmsEnabled [
"Super, Space, exec, ${dmsIpcBinds.spotlight}"
"Super, I, exec, ${dmsIpcBinds.settingsFocus}"
"Super, N, exec, ${dmsIpcBinds.notepad}"
"ShiftSuper, N, exec, ${dmsIpcBinds.notifications}"
"Super, M, exec, ${dmsIpcBinds.processlistFocus}"
"Super, L, exec, ${dmsIpcBinds.lock}"
"ShiftSuper, V, exec, ${dmsIpcBinds.clipboard}"
] ++ [
"Super, Tab, cyclenext"
"Super, Tab, bringactivetotop"
"Super, left, movefocus, l"
+4 -1
View File
@@ -101,7 +101,10 @@
"sleep 1 && hyprctl reload"
];
}
(self.lib.hyprlandBinds { inherit lib dmsEnabled; })
(self.lib.hyprlandBinds {
inherit lib dmsEnabled;
dmsIpcBinds = self.lib.dmsIpcBinds;
})
{
decoration = {
rounding = 10;
+11 -11
View File
@@ -1,6 +1,6 @@
{ ... }: {
flake.lib.niriBinds =
{ pkgs, dmsEnabled ? false }:
{ pkgs, dmsEnabled ? false, dmsIpcBinds }:
let
lib = pkgs.lib;
in
@@ -12,16 +12,16 @@
"Mod+E"."spawn-sh" = "nemo";
}
// lib.optionalAttrs dmsEnabled {
"Mod+Space"."spawn-sh" = "dms ipc call spotlight toggle";
"Mod+V"."spawn-sh" = "dms ipc call clipboard toggle";
"Mod+N"."spawn-sh" = "dms ipc call notepad toggle";
"Mod+Shift+N"."spawn-sh" = "dms ipc call notifications toggle";
"Mod+M"."spawn-sh" = "dms ipc call processlist toggle";
"Mod+B"."spawn-sh" = ''dms ipc call bar toggle name "Main Bar"; dms ipc call bar toggle name "Bar 2"'';
"Mod+Shift+B"."spawn-sh" = ''dms ipc call bar toggle name "Bar 2"'';
"Mod+A"."spawn-sh" = "dms ipc call ephemera toggle";
"Mod+numbersign"."spawn-sh" = "dms ipc call wallpaperCarousel toggle";
"Mod+L"."spawn-sh" = "dms ipc call lock lock";
"Mod+Space"."spawn-sh" = dmsIpcBinds.spotlight;
"Mod+V"."spawn-sh" = dmsIpcBinds.clipboard;
"Mod+N"."spawn-sh" = dmsIpcBinds.notepad;
"Mod+Shift+N"."spawn-sh" = dmsIpcBinds.notifications;
"Mod+M"."spawn-sh" = dmsIpcBinds.processlist;
"Mod+B"."spawn-sh" = dmsIpcBinds.barToggle;
"Mod+Shift+B"."spawn-sh" = dmsIpcBinds.barToggleBar2;
"Mod+A"."spawn-sh" = dmsIpcBinds.ephemera;
"Mod+numbersign"."spawn-sh" = dmsIpcBinds.wallpaperCarousel;
"Mod+L"."spawn-sh" = dmsIpcBinds.lock;
}
// {
"Mod+Q"."close-window" = _: { };
+4 -1
View File
@@ -21,7 +21,10 @@
niriBaseSettings =
pkgs: dmsEnabled:
self.lib.niriBaseSettings pkgs // {
binds = self.lib.niriBinds { inherit pkgs dmsEnabled; };
binds = self.lib.niriBinds {
inherit pkgs dmsEnabled;
dmsIpcBinds = self.lib.dmsIpcBinds;
};
};
mergeNiriSettings =
+73 -26
View File
@@ -124,33 +124,66 @@ let
;
};
thirdPartyPlugins = {
dankVault = inputs.dms-plugin-dank-vault;
calculator = inputs.dms-plugin-calculator;
homeAssistantMonitor = inputs.dms-plugin-home-assistant;
dropdownMenu = inputs.dms-plugin-dropdown-menu;
ocrScanner = inputs.dms-plugin-ocr-scanner;
unifiedTaskbar = inputs.dms-plugin-unified-taskbar;
widgetGroup = inputs.dms-plugin-widget-group;
nixPackageRunner = inputs.dms-plugin-nix-package-runner;
ambientSound = inputs.dms-plugin-ambient-sound;
cavaVisualizer = inputs.dms-plugin-cava-visualizer;
emojiLauncher = inputs.dms-plugin-emoji-launcher;
dankDesktopWeather = inputs.dms-plugin-official + "/DankDesktopWeather";
webSearch = inputs.dms-plugin-web-search;
wallpaperCarousel = inputs.dms-plugin-wallpaper-carousel;
ephemera = inputs.dms-plugin-ephemera;
appShortcut = inputs.dms-plugin-app-shortcut;
wvkbdToggle = inputs.dms-plugin-wvkbd-toggle;
rbwLockToggle = inputs.dms-plugin-rbw-lock-toggle;
};
# Plugin registry auto-derived from flake inputs matching `dms-plugin-*`.
# Adding a plugin now requires editing only `flake.nix`. The on-disk
# plugin id (= path under ~/.config/DankMaterialShell/plugins/) is camelCase
# per upstream convention; the kebab→camel transform matches it. The
# `idExceptions` map carries the one plugin whose manifest id does not
# follow the default rule.
pluginInputs = lib.filterAttrs (n: _: lib.hasPrefix "dms-plugin-" n) inputs;
shipPlugin =
_id: src:
{
source = src;
onChange = "${dmsRestartOnceScript}";
# `dank-vault` → `dankVault`. `lib.splitString` yields ≥ 1 element so
# `head parts` is safe; `map` runs over the tail only (no-op for
# single-word names like `calculator`). `builtins.substring 1 (-1) p`
# returns the rest of `p` from index 1, dropping the first char
# (Nix treats a negative `len` as "rest of string from `start`").
toCamel = s:
let parts = lib.splitString "-" s; in
builtins.head parts
+ lib.concatStrings (map (
p: if p == "" then ""
else lib.toUpper (builtins.substring 0 1 p)
+ builtins.substring 1 (-1) p
) (builtins.tail parts));
# The `home-assistant` plugin ships its manifest under id
# `homeAssistantMonitor` (not the default kebab→camel result).
idExceptions = { "home-assistant" = "homeAssistantMonitor"; };
# NB: don't rewrite as `idExceptions.${stripped} or toCamel stripped`.
# Nix grammar: `or` binds tighter than function application, so the
# `toCamel` and its arg parse as separate postfix args to the select.
# When the lookup succeeds the resolved string is then applied as a
# function, producing `attempt to call something which is not a function
# but a string: "homeAssistantMonitor"`. Explicit `if/hasAttr` sidesteps
# the parse entirely.
camelMap = lib.mapAttrs' (n: src:
let stripped = lib.removePrefix "dms-plugin-" n; in
lib.nameValuePair
(if builtins.hasAttr stripped idExceptions
then idExceptions.${stripped}
else toCamel stripped)
src
) pluginInputs;
# The official plugin pack bundles multiple QML apps. Ship only the
# DankDesktopWeather subdir (verified by its manifest) to slim closure
# and avoid overlapping with future dedicated `dms-plugin-*` flakes.
thirdPartyPlugins =
builtins.removeAttrs camelMap [ "official" ] // {
dankDesktopWeather = inputs.dms-plugin-official + "/DankDesktopWeather";
};
# DMS reads plugins from ~/.config/DankMaterialShell/plugins/<id>/, so
# we route each plugin source there via HM's `xdg.configFile.target`.
# The attrset name is scoped under `dms-plugin-${id}` (not the bare
# camelCase id) so unrelated HM modules can ship a same-named file
# (e.g. `xdg.configFile.calculator`) without colliding with us.
shipPlugin = id: src: {
source = src;
target = "DankMaterialShell/plugins/${id}";
onChange = "${dmsRestartOnceScript}";
};
in
{
imports = [
@@ -160,7 +193,8 @@ in
config = lib.mkIf dmsEnabled (lib.mkMerge [
(lib.mkIf (dmsOs.bundleThirdPartyPlugins or true) {
xdg.configFile = lib.mapAttrs (_id: src: shipPlugin _id src) thirdPartyPlugins;
xdg.configFile = lib.mapAttrs' (id: src: lib.nameValuePair
"dms-plugin-${id}" (shipPlugin id src)) thirdPartyPlugins;
})
{
programs.nix-monitor = {
@@ -203,10 +237,23 @@ in
enableDynamicTheming = true;
enableAudioWavelength = true;
enableCalendarEvents = false;
# Empty on purpose: DMS owns ~/.config/DankMaterialShell/{settings,session}.json
# at runtime (seeded by `home.activation.dmsSeedConfig`). Setting these
# to non-empty here would clobber the runtime seed on every activation.
settings = { };
session = { };
};
# Surface bad obsidianVaults paths at build time instead of at first matugen run.
# Each entry must point at the `<vault>/.obsidian` dir (matugen writes
# `<vault>/.obsidian/snippets/matugen.css` from there).
assertions = lib.mkIf ((dmsOs.obsidianVaults or [ ]) != [ ]) [
{
assertion = builtins.all (v: lib.hasSuffix "/.obsidian" v) (dmsOs.obsidianVaults or [ ]);
message = "chiasson.desktop.shells.dms.obsidianVaults entries must end in '/.obsidian' (matugen writes <vault>/.obsidian/snippets/matugen.css). Example: /home/olivier/Documents/HomeLab/.obsidian";
}
];
home.activation.dmsSeedConfig = lib.hm.dag.entryAfter [ "writeBoundary" ] "${dmsSeedConfigScript}";
systemd.user.services.dms.serviceConfig.ExecStartPre =
+21
View File
@@ -46,4 +46,25 @@
};
flake.homeManagerModules.desktopShellDms = import ./_private/hm.nix;
# DMS IPC commands shared between Niri and Hyprland keybind tables.
# Defines flake.lib.dmsIpcBinds so each compositor formats the same
# command string in its native shape — Niri attrs vs Hyprland string-list.
# Adding a new DMS keybind requires editing this file plus the
# per-compositor bind layout, not the command string.
flake.lib.dmsIpcBinds = {
spotlight = "dms ipc call spotlight toggle";
clipboard = "dms ipc call clipboard toggle";
notepad = "dms ipc call notepad toggle";
notifications = "dms ipc call notifications toggle";
processlist = "dms ipc call processlist toggle";
# Hyprland prefers focusOrToggle (window-aware); niri subscribes to toggle.
processlistFocus = "dms ipc call processlist focusOrToggle";
settingsFocus = "dms ipc call settings focusOrToggle";
barToggle = ''dms ipc call bar toggle name "Main Bar"; dms ipc call bar toggle name "Bar 2"'';
barToggleBar2 = ''dms ipc call bar toggle name "Bar 2"'';
ephemera = "dms ipc call ephemera toggle";
wallpaperCarousel = "dms ipc call wallpaperCarousel toggle";
lock = "dms ipc call lock lock";
};
}
@@ -486,6 +486,10 @@
{
"name": "DP-3",
"model": "34GL750"
},
{
"name": "Virtual-1",
"model": "Virtual-1"
}
],
"showOnLastDisplay": false,