feat: size: prefix, external auto-detection, auto-disable stale monitors
- size:WxH and size:WxH@R resolution for config names - auto-detection of external monitors when external list is empty (any non-internal display) - ensureCleanLayout: explicitly disable connected monitors not in target layout - update docs (README, example.yaml) for all three features
This commit is contained in:
@@ -92,6 +92,10 @@ func (h *hyprlandBackend) GetMonitors(ctx context.Context) ([]MonitorInfo, error
|
||||
|
||||
// ApplyLayout writes the monitor configuration file and calls hyprctl reload.
|
||||
// The config is written atomically (temp file + rename) to prevent corruption.
|
||||
//
|
||||
// Any physically connected monitor not mentioned in the desired layout is
|
||||
// explicitly disabled. This prevents external monitors from remaining enabled
|
||||
// when switching to portable mode (where only eDP-* is listed).
|
||||
func (h *hyprlandBackend) ApplyLayout(ctx context.Context, monitors []MonitorConfig) error {
|
||||
var err error
|
||||
monitors, err = resolveMonitorNames(ctx, monitors, h.GetMonitors, h.logger)
|
||||
@@ -99,6 +103,14 @@ func (h *hyprlandBackend) ApplyLayout(ctx context.Context, monitors []MonitorCon
|
||||
return fmt.Errorf("resolve monitor names: %w", err)
|
||||
}
|
||||
|
||||
// Fetch the current set of connected monitors and explicitly disable
|
||||
// any that are not part of the target layout.
|
||||
current, err := h.GetMonitors(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get current monitors for cleanup: %w", err)
|
||||
}
|
||||
monitors = h.ensureCleanLayout(monitors, current)
|
||||
|
||||
content := h.generateConf(monitors)
|
||||
|
||||
destPath, err := h.resolveOutputPath()
|
||||
@@ -282,6 +294,33 @@ func (h *hyprlandBackend) generateConf(monitors []MonitorConfig) string {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// ensureCleanLayout adds disabled entries for any physically connected
|
||||
// monitor that is not present in the target layout. This prevents
|
||||
// monitors from remaining enabled when switching to a mode that only
|
||||
// configures a subset of displays (e.g. portable mode).
|
||||
func (h *hyprlandBackend) ensureCleanLayout(target []MonitorConfig, connected []MonitorInfo) []MonitorConfig {
|
||||
names := make(map[string]bool, len(target))
|
||||
for _, m := range target {
|
||||
names[m.Name] = true
|
||||
}
|
||||
|
||||
var result []MonitorConfig
|
||||
result = append(result, target...)
|
||||
|
||||
for _, mi := range connected {
|
||||
if !names[mi.Name] {
|
||||
h.logger.Debug("explicitly disabling unlisted monitor",
|
||||
"monitor", mi.Name)
|
||||
result = append(result, MonitorConfig{
|
||||
Name: mi.Name,
|
||||
Enabled: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// formatScale formats a scale float: 1 → "1", 1.5 → "1.5"
|
||||
func formatScale(s float64) string {
|
||||
if s == 0 {
|
||||
|
||||
Reference in New Issue
Block a user