From cf8091e7e7f6706588b44e359632938585089aec Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 19:32:00 +0000 Subject: [PATCH] Add display layout helper wrappers --- pkg/display/display.go | 31 +++++++++++++++++++++++++++++++ pkg/display/display_test.go | 22 ++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/pkg/display/display.go b/pkg/display/display.go index e731058..0011817 100644 --- a/pkg/display/display.go +++ b/pkg/display/display.go @@ -35,6 +35,9 @@ type Options struct{} // WindowInfo is an alias for window.WindowInfo (backward compatibility). type WindowInfo = window.WindowInfo +// LayoutSuggestion is an alias for window.LayoutSuggestion (backward compatibility). +type LayoutSuggestion = window.LayoutSuggestion + // Service manages windowing, dialogs, and other visual elements. // It orchestrates sub-services (window, systray, menu) via IPC and bridges // IPC actions to WebSocket events for TypeScript apps. @@ -1501,6 +1504,34 @@ func (s *Service) FindSpace(width, height int) (window.SpaceInfo, error) { return ws.Manager().FindSpace(screenWidth, screenHeight, width, height), nil } +// SuggestLayout returns a recommended arrangement for the current screen. +// Use: suggestion, err := svc.SuggestLayout(3, 1920, 1080) +func (s *Service) SuggestLayout(windowCount, screenWidth, screenHeight int) (window.LayoutSuggestion, error) { + result, handled, err := s.Core().QUERY(window.QueryLayoutSuggestion{ + WindowCount: windowCount, + ScreenWidth: screenWidth, + ScreenHeight: screenHeight, + }) + if err != nil { + return window.LayoutSuggestion{}, err + } + if !handled { + return window.LayoutSuggestion{}, fmt.Errorf("window service not available") + } + suggestion, _ := result.(window.LayoutSuggestion) + return suggestion, nil +} + +// BesideEditor positions a target window beside an editor window. +// Use: _ = svc.BesideEditor("editor", "assistant") +func (s *Service) BesideEditor(editorName, windowName string) error { + _, _, err := s.Core().PERFORM(window.TaskBesideEditor{ + Editor: editorName, + Window: windowName, + }) + return err +} + // --- Screen management --- // GetScreens returns all known screens. diff --git a/pkg/display/display_test.go b/pkg/display/display_test.go index 56490b4..c426add 100644 --- a/pkg/display/display_test.go +++ b/pkg/display/display_test.go @@ -689,6 +689,28 @@ func TestServiceWrappers_Good(t *testing.T) { require.NotNil(t, screenInfo) }) + t.Run("layout helpers", func(t *testing.T) { + suggestion, err := svc.SuggestLayout(2, 2560, 1440) + require.NoError(t, err) + assert.Equal(t, "side-by-side", suggestion.Mode) + + require.NoError(t, svc.OpenWindow(window.WithName("editor-beside"), window.WithSize(800, 600))) + require.NoError(t, svc.OpenWindow(window.WithName("assistant-beside"), window.WithSize(400, 600))) + require.NoError(t, svc.BesideEditor("editor-beside", "assistant-beside")) + + editorInfo, err := svc.GetWindowInfo("editor-beside") + require.NoError(t, err) + require.NotNil(t, editorInfo) + assert.Equal(t, 0, editorInfo.X) + assert.Equal(t, 1792, editorInfo.Width) + + assistantInfo, err := svc.GetWindowInfo("assistant-beside") + require.NoError(t, err) + require.NotNil(t, assistantInfo) + assert.Equal(t, 1792, assistantInfo.X) + assert.Equal(t, 768, assistantInfo.Width) + }) + t.Run("clipboard wrappers", func(t *testing.T) { text, err := svc.ReadClipboard() require.NoError(t, err)