refactor(ax): route saved window state via ipc
Some checks failed
Security Scan / security (push) Failing after 29s
Test / test (push) Successful in 1m16s

This commit is contained in:
Virgil 2026-03-31 06:10:54 +00:00
parent f0a1f9027b
commit 552b0751b9
5 changed files with 75 additions and 22 deletions

View file

@ -578,15 +578,6 @@ func (s *Service) persistSection(key string, value map[string]any) {
// --- Service accessors ---
// windowService returns the window service from Core, or nil if not registered.
func (s *Service) windowService() *window.Service {
svc, err := core.ServiceFor[*window.Service](s.Core(), "window")
if err != nil {
return nil
}
return svc
}
// --- Window Management (delegates via IPC) ---
// OpenWindow creates a new window from a declarative Window spec.
@ -726,26 +717,25 @@ func (s *Service) GetWindowTitle(name string) (string, error) {
// ResetWindowState clears saved window positions.
func (s *Service) ResetWindowState() error {
ws := s.windowService()
if ws != nil {
ws.Manager().State().Clear()
}
_, _, _ = s.Core().PERFORM(window.TaskResetWindowState{})
return nil
}
// GetSavedWindowStates returns all saved window states.
func (s *Service) GetSavedWindowStates() map[string]window.WindowState {
ws := s.windowService()
if ws == nil {
result, handled, _ := s.Core().QUERY(window.QuerySavedWindowStates{})
if !handled {
return nil
}
result := make(map[string]window.WindowState)
for _, name := range ws.Manager().State().ListStates() {
if state, ok := ws.Manager().State().GetState(name); ok {
result[name] = state
}
saved, _ := result.(map[string]window.WindowState)
if saved == nil {
return nil
}
return result
out := make(map[string]window.WindowState, len(saved))
for name, state := range saved {
out[name] = state
}
return out
}
// CreateWindow creates a new named window from a declarative Window spec.

View file

@ -393,16 +393,30 @@ func TestResetWindowState_Good(t *testing.T) {
c := newTestConclave(t)
svc := core.MustServiceFor[*Service](c, "display")
err := svc.ResetWindowState()
_ = svc.OpenWindow(window.Window{Name: "reset-win"})
err := svc.SetWindowPosition("reset-win", 42, 84)
require.NoError(t, err)
err = svc.ResetWindowState()
assert.NoError(t, err)
states := svc.GetSavedWindowStates()
assert.Empty(t, states)
}
func TestGetSavedWindowStates_Good(t *testing.T) {
c := newTestConclave(t)
svc := core.MustServiceFor[*Service](c, "display")
_ = svc.OpenWindow(window.Window{Name: "saved-win"})
err := svc.SetWindowPosition("saved-win", 12, 34)
require.NoError(t, err)
states := svc.GetSavedWindowStates()
assert.NotNil(t, states)
require.Contains(t, states, "saved-win")
assert.Equal(t, 12, states["saved-win"].X)
assert.Equal(t, 34, states["saved-win"].Y)
}
func TestHandleIPCEvents_WindowOpened_Good(t *testing.T) {

View file

@ -17,6 +17,8 @@ type QueryWindowByName struct{ Name string }
type QueryConfig struct{}
type QuerySavedWindowStates struct{}
type TaskOpenWindow struct {
Window Window
}
@ -79,6 +81,8 @@ type TaskRestoreLayout struct{ Name string }
type TaskDeleteLayout struct{ Name string }
type TaskResetWindowState struct{}
type TaskTileWindows struct {
Mode string // "left-right", "grid", "left-half", "right-half", etc.
Windows []string // window names; empty = all

View file

@ -59,6 +59,8 @@ func (s *Service) handleQuery(c *core.Core, q core.Query) (any, bool, error) {
return s.queryWindowList(), true, nil
case QueryWindowByName:
return s.queryWindowByName(q.Name), true, nil
case QuerySavedWindowStates:
return s.querySavedWindowStates(), true, nil
case QueryLayoutList:
return s.manager.Layout().ListLayouts(), true, nil
case QueryLayoutGet:
@ -103,6 +105,17 @@ func (s *Service) queryWindowByName(name string) *WindowInfo {
}
}
func (s *Service) querySavedWindowStates() map[string]WindowState {
stateNames := s.manager.State().ListStates()
result := make(map[string]WindowState, len(stateNames))
for _, name := range stateNames {
if state, ok := s.manager.State().GetState(name); ok {
result[name] = state
}
}
return result
}
// --- Task Handlers ---
func (s *Service) handleTask(c *core.Core, t core.Task) (any, bool, error) {
@ -140,6 +153,9 @@ func (s *Service) handleTask(c *core.Core, t core.Task) (any, bool, error) {
case TaskDeleteLayout:
s.manager.Layout().DeleteLayout(t.Name)
return nil, true, nil
case TaskResetWindowState:
s.manager.State().Clear()
return nil, true, nil
case TaskTileWindows:
return nil, true, s.taskTileWindows(t.Mode, t.Windows)
case TaskStackWindows:

View file

@ -89,6 +89,21 @@ func TestQueryWindowByName_Bad(t *testing.T) {
assert.Nil(t, result)
}
func TestQuerySavedWindowStates_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Window: Window{Name: "test"}})
_, _, _ = c.PERFORM(TaskSetPosition{Name: "test", X: 120, Y: 240})
result, handled, err := c.QUERY(QuerySavedWindowStates{})
require.NoError(t, err)
assert.True(t, handled)
states := result.(map[string]WindowState)
require.Contains(t, states, "test")
assert.Equal(t, 120, states["test"].X)
assert.Equal(t, 240, states["test"].Y)
}
func TestTaskCloseWindow_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Window: Window{Name: "test"}})
@ -109,6 +124,20 @@ func TestTaskCloseWindow_Bad(t *testing.T) {
assert.Error(t, err)
}
func TestTaskResetWindowState_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Window: Window{Name: "test"}})
_, _, _ = c.PERFORM(TaskSetPosition{Name: "test", X: 80, Y: 90})
_, handled, err := c.PERFORM(TaskResetWindowState{})
require.NoError(t, err)
assert.True(t, handled)
result, _, err := c.QUERY(QuerySavedWindowStates{})
require.NoError(t, err)
assert.Empty(t, result.(map[string]WindowState))
}
func TestTaskSetPosition_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Window: Window{Name: "test"}})