feat(gui): bridge arrange-pair and find-space
This commit is contained in:
parent
a07fa49c20
commit
973217ae54
6 changed files with 104 additions and 3 deletions
|
|
@ -615,6 +615,19 @@ func (s *Service) handleWSMessage(msg WSMessage) (any, bool, error) {
|
|||
Workflow: workflow,
|
||||
Windows: names,
|
||||
})
|
||||
case "window:arrange-pair":
|
||||
first, e := wsRequire(msg.Data, "first")
|
||||
if e != nil {
|
||||
return nil, false, e
|
||||
}
|
||||
second, e := wsRequire(msg.Data, "second")
|
||||
if e != nil {
|
||||
return nil, false, e
|
||||
}
|
||||
result, handled, err = s.Core().PERFORM(window.TaskArrangePair{
|
||||
First: first,
|
||||
Second: second,
|
||||
})
|
||||
case "layout:suggest":
|
||||
windowCount := 0
|
||||
if count, ok := msg.Data["windowCount"].(float64); ok {
|
||||
|
|
@ -639,6 +652,19 @@ func (s *Service) handleWSMessage(msg WSMessage) (any, bool, error) {
|
|||
ScreenWidth: screenWidth,
|
||||
ScreenHeight: screenHeight,
|
||||
})
|
||||
case "screen:find-space":
|
||||
width := 0
|
||||
if w, ok := msg.Data["width"].(float64); ok {
|
||||
width = int(w)
|
||||
}
|
||||
height := 0
|
||||
if h, ok := msg.Data["height"].(float64); ok {
|
||||
height = int(h)
|
||||
}
|
||||
result, handled, err = s.Core().QUERY(window.QueryFindSpace{
|
||||
Width: width,
|
||||
Height: height,
|
||||
})
|
||||
case "screen:list":
|
||||
result, handled, err = s.Core().QUERY(screen.QueryAll{})
|
||||
case "screen:get":
|
||||
|
|
@ -1422,6 +1448,32 @@ func (s *Service) ApplyWorkflowLayout(workflow window.WorkflowLayout) error {
|
|||
return ws.Manager().ApplyWorkflow(workflow, ws.Manager().List(), screenWidth, screenHeight)
|
||||
}
|
||||
|
||||
// ArrangeWindowPair places two windows side by side using the window manager's balanced split.
|
||||
func (s *Service) ArrangeWindowPair(first, second string) error {
|
||||
ws := s.windowService()
|
||||
if ws == nil {
|
||||
return fmt.Errorf("window service not available")
|
||||
}
|
||||
screenWidth, screenHeight := s.primaryScreenSize()
|
||||
return ws.Manager().ArrangePair(first, second, screenWidth, screenHeight)
|
||||
}
|
||||
|
||||
// FindSpace returns a free placement suggestion for a new window.
|
||||
func (s *Service) FindSpace(width, height int) (window.SpaceInfo, error) {
|
||||
ws := s.windowService()
|
||||
if ws == nil {
|
||||
return window.SpaceInfo{}, fmt.Errorf("window service not available")
|
||||
}
|
||||
screenWidth, screenHeight := s.primaryScreenSize()
|
||||
if width <= 0 {
|
||||
width = screenWidth / 2
|
||||
}
|
||||
if height <= 0 {
|
||||
height = screenHeight / 2
|
||||
}
|
||||
return ws.Manager().FindSpace(screenWidth, screenHeight, width, height), nil
|
||||
}
|
||||
|
||||
// --- Screen management ---
|
||||
|
||||
// GetScreens returns all known screens.
|
||||
|
|
|
|||
|
|
@ -919,6 +919,36 @@ func TestHandleWSMessage_Extended_Good(t *testing.T) {
|
|||
assert.True(t, handled)
|
||||
})
|
||||
|
||||
t.Run("window arrange pair", func(t *testing.T) {
|
||||
_, handled, err := svc.handleWSMessage(WSMessage{
|
||||
Action: "window:arrange-pair",
|
||||
Data: map[string]any{
|
||||
"first": "editor",
|
||||
"second": "assistant",
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.True(t, handled)
|
||||
})
|
||||
|
||||
t.Run("screen find space", func(t *testing.T) {
|
||||
result, handled, err := svc.handleWSMessage(WSMessage{
|
||||
Action: "screen:find-space",
|
||||
Data: map[string]any{
|
||||
"width": float64(400),
|
||||
"height": float64(300),
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.True(t, handled)
|
||||
space, ok := result.(window.SpaceInfo)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, 2560, space.ScreenWidth)
|
||||
assert.Equal(t, 1440, space.ScreenHeight)
|
||||
assert.Equal(t, 400, space.Width)
|
||||
assert.Equal(t, 300, space.Height)
|
||||
})
|
||||
|
||||
t.Run("clipboard image read", func(t *testing.T) {
|
||||
result, handled, err := svc.handleWSMessage(WSMessage{Action: "clipboard:read-image"})
|
||||
require.NoError(t, err)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ type mockWindow struct {
|
|||
maximised, focused bool
|
||||
visible, alwaysOnTop bool
|
||||
backgroundColor [4]uint8
|
||||
devtoolsOpen bool
|
||||
closed bool
|
||||
eventHandlers []func(WindowEvent)
|
||||
fileDropHandlers []func(paths []string, targetID string)
|
||||
|
|
@ -62,8 +63,8 @@ func (w *mockWindow) Show() { w.visible = true }
|
|||
func (w *mockWindow) Hide() { w.visible = false }
|
||||
func (w *mockWindow) Fullscreen() {}
|
||||
func (w *mockWindow) UnFullscreen() {}
|
||||
func (w *mockWindow) OpenDevTools() {}
|
||||
func (w *mockWindow) CloseDevTools() {}
|
||||
func (w *mockWindow) OpenDevTools() { w.devtoolsOpen = true }
|
||||
func (w *mockWindow) CloseDevTools() { w.devtoolsOpen = false }
|
||||
func (w *mockWindow) OnWindowEvent(handler func(WindowEvent)) {
|
||||
w.eventHandlers = append(w.eventHandlers, handler)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ func (ww *wailsWindow) Hide() { ww.w.Hide() }
|
|||
func (ww *wailsWindow) Fullscreen() { ww.w.Fullscreen() }
|
||||
func (ww *wailsWindow) UnFullscreen() { ww.w.UnFullscreen() }
|
||||
func (ww *wailsWindow) OpenDevTools() { ww.w.OpenDevTools() }
|
||||
func (ww *wailsWindow) CloseDevTools() {}
|
||||
func (ww *wailsWindow) CloseDevTools() { ww.w.CloseDevTools() }
|
||||
|
||||
func (ww *wailsWindow) OnWindowEvent(handler func(event WindowEvent)) {
|
||||
name := ww.w.Name()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
func TestWindowDefaults(t *testing.T) {
|
||||
|
|
@ -162,6 +163,21 @@ func TestManager_Remove_Good(t *testing.T) {
|
|||
assert.False(t, ok)
|
||||
}
|
||||
|
||||
func TestWailsWindow_DevToolsToggle_Good(t *testing.T) {
|
||||
app := application.NewApp()
|
||||
platform := NewWailsPlatform(app)
|
||||
|
||||
pw := platform.CreateWindow(PlatformWindowOptions{Name: "devtools"})
|
||||
ww, ok := pw.(*wailsWindow)
|
||||
require.True(t, ok)
|
||||
|
||||
ww.OpenDevTools()
|
||||
assert.True(t, ww.w.DevToolsOpen())
|
||||
|
||||
ww.CloseDevTools()
|
||||
assert.False(t, ww.w.DevToolsOpen())
|
||||
}
|
||||
|
||||
// --- StateManager Tests ---
|
||||
|
||||
// newTestStateManager creates a clean StateManager with a temp dir for testing.
|
||||
|
|
|
|||
|
|
@ -136,6 +136,8 @@ func (w *WebviewWindow) Hide() { w.visible = false }
|
|||
func (w *WebviewWindow) Fullscreen() { w.fullscreen = true }
|
||||
func (w *WebviewWindow) UnFullscreen() { w.fullscreen = false }
|
||||
func (w *WebviewWindow) OpenDevTools() { w.devtoolsOpen = true }
|
||||
func (w *WebviewWindow) CloseDevTools() { w.devtoolsOpen = false }
|
||||
func (w *WebviewWindow) DevToolsOpen() bool { return w.devtoolsOpen }
|
||||
|
||||
func (w *WebviewWindow) OnWindowEvent(eventType events.WindowEventType, callback func(event *WindowEvent)) func() {
|
||||
w.mu.Lock()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue