diff --git a/core/internal/config/deployer_test.go b/core/internal/config/deployer_test.go index 79c3178a..e2afe5e5 100644 --- a/core/internal/config/deployer_test.go +++ b/core/internal/config/deployer_test.go @@ -435,7 +435,7 @@ func TestHyprlandConfigDeployment(t *testing.T) { content, err := os.ReadFile(result.Path) require.NoError(t, err) assert.Contains(t, string(content), "# MONITOR CONFIG") - assert.Contains(t, string(content), "bind = $mod, T, exec, ghostty") + assert.Contains(t, string(content), "bind = $mod, T, exec, $TERMINAL") assert.Contains(t, string(content), "exec-once = ") }) @@ -471,7 +471,7 @@ general { require.NoError(t, err) assert.Contains(t, string(newContent), "monitor = DP-1, 1920x1080@144") assert.Contains(t, string(newContent), "monitor = HDMI-A-1, 3840x2160@60") - assert.Contains(t, string(newContent), "bind = $mod, T, exec, kitty") + assert.Contains(t, string(newContent), "bind = $mod, T, exec, $TERMINAL") assert.NotContains(t, string(newContent), "monitor = eDP-2") }) } @@ -487,14 +487,11 @@ func TestNiriConfigStructure(t *testing.T) { func TestHyprlandConfigStructure(t *testing.T) { assert.Contains(t, HyprlandConfig, "# MONITOR CONFIG") - assert.Contains(t, HyprlandConfig, "# ENVIRONMENT VARS") assert.Contains(t, HyprlandConfig, "# STARTUP APPS") assert.Contains(t, HyprlandConfig, "# INPUT CONFIG") assert.Contains(t, HyprlandConfig, "# KEYBINDINGS") assert.Contains(t, HyprlandConfig, "{{POLKIT_AGENT_PATH}}") - assert.Contains(t, HyprlandConfig, "{{TERMINAL_COMMAND}}") - assert.Contains(t, HyprlandConfig, "exec-once = dms run") - assert.Contains(t, HyprlandConfig, "bind = $mod, T, exec,") + assert.Contains(t, HyprlandConfig, "bind = $mod, T, exec, $TERMINAL") assert.Contains(t, HyprlandConfig, "bind = $mod, space, exec, dms ipc call spotlight toggle") assert.Contains(t, HyprlandConfig, "windowrule {") assert.Contains(t, HyprlandConfig, "match:class = ^(com\\.mitchellh\\.ghostty)$") diff --git a/core/internal/config/embedded/hyprland.conf b/core/internal/config/embedded/hyprland.conf index 2927e03b..d2e0d18f 100644 --- a/core/internal/config/embedded/hyprland.conf +++ b/core/internal/config/embedded/hyprland.conf @@ -7,20 +7,10 @@ # monitor = eDP-2, 2560x1600@239.998993, 2560x0, 1, vrr, 1 monitor = , preferred,auto,auto -# ================== -# ENVIRONMENT VARS -# ================== -env = QT_QPA_PLATFORM,wayland -env = ELECTRON_OZONE_PLATFORM_HINT,auto -env = QT_QPA_PLATFORMTHEME,gtk3 -env = QT_QPA_PLATFORMTHEME_QT6,gtk3 -env = TERMINAL,{{TERMINAL_COMMAND}} - # ================== # STARTUP APPS # ================== exec-once = bash -c "wl-paste --watch cliphist store &" -exec-once = dms run exec-once = {{POLKIT_AGENT_PATH}} # ================== @@ -233,7 +223,7 @@ layerrule { $mod = SUPER # === Application Launchers === -bind = $mod, T, exec, {{TERMINAL_COMMAND}} +bind = $mod, T, exec, $TERMINAL bind = $mod, space, exec, dms ipc call spotlight toggle bind = $mod, V, exec, dms ipc call clipboard toggle bind = $mod, M, exec, dms ipc call processlist focusOrToggle diff --git a/core/internal/config/embedded/niri.kdl b/core/internal/config/embedded/niri.kdl index 0cc6e786..b5275596 100644 --- a/core/internal/config/embedded/niri.kdl +++ b/core/internal/config/embedded/niri.kdl @@ -116,15 +116,9 @@ overview { // See the binds section below for more spawn examples. // This line starts waybar, a commonly used bar for Wayland compositors. spawn-at-startup "bash" "-c" "wl-paste --watch cliphist store &" -spawn-at-startup "dms" "run" spawn-at-startup "{{POLKIT_AGENT_PATH}}" environment { XDG_CURRENT_DESKTOP "niri" - QT_QPA_PLATFORM "wayland" - ELECTRON_OZONE_PLATFORM_HINT "auto" - QT_QPA_PLATFORMTHEME "gtk3" - QT_QPA_PLATFORMTHEME_QT6 "gtk3" - TERMINAL "{{TERMINAL_COMMAND}}" } hotkey-overlay { skip-at-startup diff --git a/core/internal/distros/arch.go b/core/internal/distros/arch.go index 6cf17080..8513e0e1 100644 --- a/core/internal/distros/arch.go +++ b/core/internal/distros/arch.go @@ -357,6 +357,15 @@ func (a *ArchDistribution) InstallPackages(ctx context.Context, dependencies []d LogOutput: "Starting post-installation configuration...", } + terminal := a.DetectTerminalFromDeps(dependencies) + if err := a.WriteEnvironmentConfig(terminal); err != nil { + a.log(fmt.Sprintf("Warning: failed to write environment config: %v", err)) + } + + if err := a.EnableDMSService(ctx); err != nil { + a.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err)) + } + // Phase 7: Complete progressChan <- InstallProgressMsg{ Phase: PhaseComplete, diff --git a/core/internal/distros/base.go b/core/internal/distros/base.go index b098fc7a..ee3aa866 100644 --- a/core/internal/distros/base.go +++ b/core/internal/distros/base.go @@ -549,6 +549,68 @@ func (b *BaseDistribution) runWithProgressStepTimeout(cmd *exec.Cmd, progressCha } } +func (b *BaseDistribution) DetectTerminalFromDeps(dependencies []deps.Dependency) deps.Terminal { + for _, dep := range dependencies { + switch dep.Name { + case "ghostty": + return deps.TerminalGhostty + case "kitty": + return deps.TerminalKitty + case "alacritty": + return deps.TerminalAlacritty + } + } + return deps.TerminalGhostty +} + +func (b *BaseDistribution) WriteEnvironmentConfig(terminal deps.Terminal) error { + homeDir, err := os.UserHomeDir() + if err != nil { + return fmt.Errorf("failed to get home directory: %w", err) + } + + envDir := filepath.Join(homeDir, ".config", "environment.d") + if err := os.MkdirAll(envDir, 0755); err != nil { + return fmt.Errorf("failed to create environment.d directory: %w", err) + } + + var terminalCmd string + switch terminal { + case deps.TerminalGhostty: + terminalCmd = "ghostty" + case deps.TerminalKitty: + terminalCmd = "kitty" + case deps.TerminalAlacritty: + terminalCmd = "alacritty" + default: + terminalCmd = "ghostty" + } + + content := fmt.Sprintf(`QT_QPA_PLATFORM=wayland +ELECTRON_OZONE_PLATFORM_HINT=auto +QT_QPA_PLATFORMTHEME=gtk3 +QT_QPA_PLATFORMTHEME_QT6=gtk3 +TERMINAL=%s +`, terminalCmd) + + envFile := filepath.Join(envDir, "90-dms.conf") + if err := os.WriteFile(envFile, []byte(content), 0644); err != nil { + return fmt.Errorf("failed to write environment config: %w", err) + } + + b.log(fmt.Sprintf("Wrote environment config to %s", envFile)) + return nil +} + +func (b *BaseDistribution) EnableDMSService(ctx context.Context) error { + cmd := exec.CommandContext(ctx, "systemctl", "--user", "enable", "--now", "dms") + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to enable dms service: %w", err) + } + b.log("Enabled dms systemd user service") + return nil +} + // installDMSBinary installs the DMS binary from GitHub releases func (b *BaseDistribution) installDMSBinary(ctx context.Context, sudoPassword string, progressChan chan<- InstallProgressMsg) error { b.log("Installing/updating DMS binary...") diff --git a/core/internal/distros/debian.go b/core/internal/distros/debian.go index b927026c..31f00802 100644 --- a/core/internal/distros/debian.go +++ b/core/internal/distros/debian.go @@ -333,6 +333,15 @@ func (d *DebianDistribution) InstallPackages(ctx context.Context, dependencies [ LogOutput: "Starting post-installation configuration...", } + terminal := d.DetectTerminalFromDeps(dependencies) + if err := d.WriteEnvironmentConfig(terminal); err != nil { + d.log(fmt.Sprintf("Warning: failed to write environment config: %v", err)) + } + + if err := d.EnableDMSService(ctx); err != nil { + d.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err)) + } + progressChan <- InstallProgressMsg{ Phase: PhaseComplete, Progress: 1.0, diff --git a/core/internal/distros/fedora.go b/core/internal/distros/fedora.go index 95f0323d..48dfe788 100644 --- a/core/internal/distros/fedora.go +++ b/core/internal/distros/fedora.go @@ -357,6 +357,15 @@ func (f *FedoraDistribution) InstallPackages(ctx context.Context, dependencies [ LogOutput: "Starting post-installation configuration...", } + terminal := f.DetectTerminalFromDeps(dependencies) + if err := f.WriteEnvironmentConfig(terminal); err != nil { + f.log(fmt.Sprintf("Warning: failed to write environment config: %v", err)) + } + + if err := f.EnableDMSService(ctx); err != nil { + f.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err)) + } + // Phase 7: Complete progressChan <- InstallProgressMsg{ Phase: PhaseComplete, diff --git a/core/internal/distros/gentoo.go b/core/internal/distros/gentoo.go index 0e5b12f0..f53dd6aa 100644 --- a/core/internal/distros/gentoo.go +++ b/core/internal/distros/gentoo.go @@ -451,6 +451,15 @@ func (g *GentooDistribution) InstallPackages(ctx context.Context, dependencies [ LogOutput: "Starting post-installation configuration...", } + terminal := g.DetectTerminalFromDeps(dependencies) + if err := g.WriteEnvironmentConfig(terminal); err != nil { + g.log(fmt.Sprintf("Warning: failed to write environment config: %v", err)) + } + + if err := g.EnableDMSService(ctx); err != nil { + g.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err)) + } + progressChan <- InstallProgressMsg{ Phase: PhaseComplete, Progress: 1.0, diff --git a/core/internal/distros/opensuse.go b/core/internal/distros/opensuse.go index efb11bfb..4fc40c15 100644 --- a/core/internal/distros/opensuse.go +++ b/core/internal/distros/opensuse.go @@ -372,6 +372,15 @@ func (o *OpenSUSEDistribution) InstallPackages(ctx context.Context, dependencies LogOutput: "Starting post-installation configuration...", } + terminal := o.DetectTerminalFromDeps(dependencies) + if err := o.WriteEnvironmentConfig(terminal); err != nil { + o.log(fmt.Sprintf("Warning: failed to write environment config: %v", err)) + } + + if err := o.EnableDMSService(ctx); err != nil { + o.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err)) + } + // Complete progressChan <- InstallProgressMsg{ Phase: PhaseComplete, diff --git a/core/internal/distros/ubuntu.go b/core/internal/distros/ubuntu.go index ebc2fcd8..f69e0552 100644 --- a/core/internal/distros/ubuntu.go +++ b/core/internal/distros/ubuntu.go @@ -352,6 +352,15 @@ func (u *UbuntuDistribution) InstallPackages(ctx context.Context, dependencies [ LogOutput: "Starting post-installation configuration...", } + terminal := u.DetectTerminalFromDeps(dependencies) + if err := u.WriteEnvironmentConfig(terminal); err != nil { + u.log(fmt.Sprintf("Warning: failed to write environment config: %v", err)) + } + + if err := u.EnableDMSService(ctx); err != nil { + u.log(fmt.Sprintf("Warning: failed to enable dms service: %v", err)) + } + // Phase 7: Complete progressChan <- InstallProgressMsg{ Phase: PhaseComplete,