diff --git a/core/cmd/dms/commands_setup.go b/core/cmd/dms/commands_setup.go index 71292629..5f390656 100644 --- a/core/cmd/dms/commands_setup.go +++ b/core/cmd/dms/commands_setup.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "os/exec" "path/filepath" "strings" @@ -11,6 +12,7 @@ import ( "github.com/AvengeMedia/DankMaterialShell/core/internal/deps" "github.com/AvengeMedia/DankMaterialShell/core/internal/greeter" "github.com/AvengeMedia/DankMaterialShell/core/internal/log" + "github.com/AvengeMedia/DankMaterialShell/core/internal/privesc" "github.com/AvengeMedia/DankMaterialShell/core/internal/utils" "github.com/spf13/cobra" ) @@ -267,6 +269,8 @@ func runSetupDmsConfig(name string) error { func runSetup() error { fmt.Println("=== DMS Configuration Setup ===") + ensureInputGroup() + wm, wmSelected := promptCompositor() terminal, terminalSelected := promptTerminal() useSystemd := promptSystemd() @@ -340,6 +344,37 @@ func runSetup() error { return nil } +// Add user to the input group for the evdev manager for inut state tracking. +// Caps Lock OSD and the Caps Lock bar indicator. +func ensureInputGroup() { + if !utils.HasGroup("input") { + return + } + currentUser := os.Getenv("USER") + if currentUser == "" { + currentUser = os.Getenv("LOGNAME") + } + if currentUser == "" { + return + } + out, err := execGroups(currentUser) + if err == nil && strings.Contains(out, "input") { + fmt.Printf("✓ %s is already in the input group (Caps Lock OSD enabled)\n", currentUser) + return + } + fmt.Println("Adding user to input group for Caps Lock OSD support...") + if err := privesc.Run(context.Background(), "", "usermod", "-aG", "input", currentUser); err != nil { + fmt.Printf("⚠ Could not add %s to input group (Caps Lock OSD will be unavailable): %v\n", currentUser, err) + } else { + fmt.Printf("✓ Added %s to input group (logout/login required to take effect)\n", currentUser) + } +} + +func execGroups(user string) (string, error) { + out, err := exec.Command("groups", user).Output() + return string(out), err +} + func promptCompositor() (deps.WindowManager, bool) { fmt.Println("Select compositor:") fmt.Println("1) Niri") diff --git a/core/internal/server/evdev/manager.go b/core/internal/server/evdev/manager.go index b5784819..32490723 100644 --- a/core/internal/server/evdev/manager.go +++ b/core/internal/server/evdev/manager.go @@ -391,7 +391,7 @@ func (m *Manager) Close() { func InitializeManager() (*Manager, error) { if os.Getuid() != 0 && !hasInputGroupAccess() { - return nil, fmt.Errorf("insufficient permissions to access input devices") + return nil, fmt.Errorf("insufficient permissions to access input devices. Add your user to the 'input' group: `sudo usermod -a -G input $USER` or run `dms setup`") } return NewManager() diff --git a/core/internal/server/freedesktop/screensaver.go b/core/internal/server/freedesktop/screensaver.go index 095a4c08..320f13e2 100644 --- a/core/internal/server/freedesktop/screensaver.go +++ b/core/internal/server/freedesktop/screensaver.go @@ -104,7 +104,7 @@ func (m *Manager) claimScreensaverName(handler *screensaverHandler, name, iface return false } if reply != dbus.RequestNameReplyPrimaryOwner { - log.Warnf("Screensaver name %s already owned by another process", name) + log.Infof("Screensaver name %s already owned by another process (e.g. hypridle/swayidle)", name) return false } if err := m.exportScreensaverOnPaths(handler, iface, paths...); err != nil { diff --git a/quickshell/DMSShell.qml b/quickshell/DMSShell.qml index 8815e0af..092a8b11 100644 --- a/quickshell/DMSShell.qml +++ b/quickshell/DMSShell.qml @@ -1092,12 +1092,6 @@ Item { } } - Loader { - id: powerProfileWatcherLoader - active: SettingsData.osdPowerProfileEnabled - source: "Services/PowerProfileWatcher.qml" - } - LazyLoader { id: hyprlandOverviewLoader active: CompositorService.isHyprland