feat(window): expose visibility and minimized state
Some checks failed
Security Scan / security (push) Failing after 31s
Test / test (push) Successful in 1m28s

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-02 14:30:42 +00:00
parent 81b71ff50b
commit 77e03060ac
9 changed files with 78 additions and 13 deletions

View file

@ -426,6 +426,8 @@ func TestGetWindowInfo_Good(t *testing.T) {
assert.Equal(t, 200, info.Y)
assert.Equal(t, 800, info.Width)
assert.Equal(t, 600, info.Height)
assert.True(t, info.Visible)
assert.False(t, info.Minimized)
}
func TestGetWindowInfo_Bad(t *testing.T) {
@ -559,9 +561,15 @@ func TestSetWindowVisibility_Good(t *testing.T) {
err := svc.SetWindowVisibility("vis-win", false)
assert.NoError(t, err)
info, err := svc.GetWindowInfo("vis-win")
require.NoError(t, err)
assert.False(t, info.Visible)
err = svc.SetWindowVisibility("vis-win", true)
assert.NoError(t, err)
info, err = svc.GetWindowInfo("vis-win")
require.NoError(t, err)
assert.True(t, info.Visible)
}
func TestSetWindowAlwaysOnTop_Good(t *testing.T) {

View file

@ -8,6 +8,8 @@ type WindowInfo struct {
Y int `json:"y"`
Width int `json:"width"`
Height int `json:"height"`
Visible bool `json:"visible"`
Minimized bool `json:"minimized"`
Maximized bool `json:"maximized"`
Focused bool `json:"focused"`
}

View file

@ -34,7 +34,8 @@ func (m *MockPlatform) GetWindows() []PlatformWindow {
type MockWindow struct {
name, title, url string
width, height, x, y int
maximised, focused bool
maximised, minimised bool
focused bool
visible, alwaysOnTop bool
backgroundColor [4]uint8
closed bool
@ -46,6 +47,8 @@ func (w *MockWindow) Name() string { return w.name }
func (w *MockWindow) Title() string { return w.title }
func (w *MockWindow) Position() (int, int) { return w.x, w.y }
func (w *MockWindow) Size() (int, int) { return w.width, w.height }
func (w *MockWindow) IsVisible() bool { return w.visible }
func (w *MockWindow) IsMinimised() bool { return w.minimised }
func (w *MockWindow) IsMaximised() bool { return w.maximised }
func (w *MockWindow) IsFocused() bool { return w.focused }
func (w *MockWindow) SetTitle(title string) { w.title = title }
@ -54,9 +57,9 @@ func (w *MockWindow) SetSize(width, height int) { w.width = width; w.
func (w *MockWindow) SetBackgroundColour(r, g, b, a uint8) { w.backgroundColor = [4]uint8{r, g, b, a} }
func (w *MockWindow) SetVisibility(visible bool) { w.visible = visible }
func (w *MockWindow) SetAlwaysOnTop(alwaysOnTop bool) { w.alwaysOnTop = alwaysOnTop }
func (w *MockWindow) Maximise() { w.maximised = true }
func (w *MockWindow) Restore() { w.maximised = false }
func (w *MockWindow) Minimise() {}
func (w *MockWindow) Maximise() { w.maximised = true; w.minimised = false; w.visible = true }
func (w *MockWindow) Restore() { w.maximised = false; w.minimised = false; w.visible = true }
func (w *MockWindow) Minimise() { w.minimised = true; w.maximised = false; w.visible = false }
func (w *MockWindow) Focus() { w.focused = true }
func (w *MockWindow) Close() { w.closed = true }
func (w *MockWindow) Show() { w.visible = true }

View file

@ -33,7 +33,8 @@ func (m *mockPlatform) GetWindows() []PlatformWindow {
type mockWindow struct {
name, title, url string
width, height, x, y int
maximised, focused bool
maximised, minimised bool
focused bool
visible, alwaysOnTop bool
backgroundColor [4]uint8
devtoolsOpen bool
@ -46,6 +47,8 @@ func (w *mockWindow) Name() string { return w.name }
func (w *mockWindow) Title() string { return w.title }
func (w *mockWindow) Position() (int, int) { return w.x, w.y }
func (w *mockWindow) Size() (int, int) { return w.width, w.height }
func (w *mockWindow) IsVisible() bool { return w.visible }
func (w *mockWindow) IsMinimised() bool { return w.minimised }
func (w *mockWindow) IsMaximised() bool { return w.maximised }
func (w *mockWindow) IsFocused() bool { return w.focused }
func (w *mockWindow) SetTitle(title string) { w.title = title }
@ -54,9 +57,9 @@ func (w *mockWindow) SetSize(width, height int) { w.width = width; w.
func (w *mockWindow) SetBackgroundColour(r, g, b, a uint8) { w.backgroundColor = [4]uint8{r, g, b, a} }
func (w *mockWindow) SetVisibility(visible bool) { w.visible = visible }
func (w *mockWindow) SetAlwaysOnTop(alwaysOnTop bool) { w.alwaysOnTop = alwaysOnTop }
func (w *mockWindow) Maximise() { w.maximised = true }
func (w *mockWindow) Restore() { w.maximised = false }
func (w *mockWindow) Minimise() {}
func (w *mockWindow) Maximise() { w.maximised = true; w.minimised = false; w.visible = true }
func (w *mockWindow) Restore() { w.maximised = false; w.minimised = false; w.visible = true }
func (w *mockWindow) Minimise() { w.minimised = true; w.maximised = false; w.visible = false }
func (w *mockWindow) Focus() { w.focused = true }
func (w *mockWindow) Close() { w.closed = true }
func (w *mockWindow) Show() { w.visible = true }

View file

@ -33,6 +33,8 @@ type PlatformWindow interface {
// Queries
Position() (int, int)
Size() (int, int)
IsVisible() bool
IsMinimised() bool
IsMaximised() bool
IsFocused() bool

View file

@ -119,7 +119,14 @@ func (s *Service) queryWindowByName(name string) *WindowInfo {
x, y := pw.Position()
w, h := pw.Size()
return &WindowInfo{
Name: name, Title: pw.Title(), X: x, Y: y, Width: w, Height: h,
Name: name,
Title: pw.Title(),
X: x,
Y: y,
Width: w,
Height: h,
Visible: pw.IsVisible(),
Minimized: pw.IsMinimised(),
Maximized: pw.IsMaximised(),
Focused: pw.IsFocused(),
}
@ -195,7 +202,18 @@ func (s *Service) taskOpenWindow(t TaskOpenWindow) (any, bool, error) {
}
x, y := pw.Position()
w, h := pw.Size()
info := WindowInfo{Name: pw.Name(), Title: pw.Title(), X: x, Y: y, Width: w, Height: h}
info := WindowInfo{
Name: pw.Name(),
Title: pw.Title(),
X: x,
Y: y,
Width: w,
Height: h,
Visible: pw.IsVisible(),
Minimized: pw.IsMinimised(),
Maximized: pw.IsMaximised(),
Focused: pw.IsFocused(),
}
// Attach platform event listeners that convert to IPC actions
s.trackWindow(pw)

View file

@ -95,6 +95,8 @@ func TestQueryWindowByName_Good(t *testing.T) {
assert.True(t, handled)
info := result.(*WindowInfo)
assert.Equal(t, "test", info.Name)
assert.True(t, info.Visible)
assert.False(t, info.Minimized)
}
func TestQueryWindowByName_Bad(t *testing.T) {
@ -153,6 +155,28 @@ func TestTaskSetSize_Good(t *testing.T) {
assert.Equal(t, 600, info.Height)
}
func TestTaskMinimiseAndVisibility_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("test")}})
_, handled, err := c.PERFORM(TaskMinimise{Name: "test"})
require.NoError(t, err)
assert.True(t, handled)
result, _, _ := c.QUERY(QueryWindowByName{Name: "test"})
info := result.(*WindowInfo)
assert.True(t, info.Minimized)
assert.False(t, info.Visible)
_, handled, err = c.PERFORM(TaskSetVisibility{Name: "test", Visible: true})
require.NoError(t, err)
assert.True(t, handled)
result, _, _ = c.QUERY(QueryWindowByName{Name: "test"})
info = result.(*WindowInfo)
assert.True(t, info.Visible)
}
func TestTaskSetAlwaysOnTop_Good(t *testing.T) {
_, c := newTestWindowService(t)
_, _, _ = c.PERFORM(TaskOpenWindow{Opts: []WindowOption{WithName("test")}})

View file

@ -62,6 +62,8 @@ func (ww *wailsWindow) Name() string { return ww.w.Name() }
func (ww *wailsWindow) Title() string { return ww.title }
func (ww *wailsWindow) Position() (int, int) { return ww.w.Position() }
func (ww *wailsWindow) Size() (int, int) { return ww.w.Size() }
func (ww *wailsWindow) IsVisible() bool { return ww.w.IsVisible() }
func (ww *wailsWindow) IsMinimised() bool { return ww.w.IsMinimised() }
func (ww *wailsWindow) IsMaximised() bool { return ww.w.IsMaximised() }
func (ww *wailsWindow) IsFocused() bool { return ww.w.IsFocused() }
func (ww *wailsWindow) SetTitle(title string) { ww.title = title; ww.w.SetTitle(title) }

View file

@ -89,6 +89,7 @@ type WebviewWindow struct {
title string
x, y int
width, height int
minimised bool
maximised bool
focused bool
visible bool
@ -116,6 +117,8 @@ func newWebviewWindow(opts WebviewWindowOptions) *WebviewWindow {
func (w *WebviewWindow) Name() string { return w.opts.Name }
func (w *WebviewWindow) Position() (int, int) { return w.x, w.y }
func (w *WebviewWindow) Size() (int, int) { return w.width, w.height }
func (w *WebviewWindow) IsVisible() bool { return w.visible }
func (w *WebviewWindow) IsMinimised() bool { return w.minimised }
func (w *WebviewWindow) IsMaximised() bool { return w.maximised }
func (w *WebviewWindow) IsFocused() bool { return w.focused }
func (w *WebviewWindow) SetTitle(title string) { w.title = title }
@ -126,9 +129,9 @@ func (w *WebviewWindow) SetSize(width, height int) {
func (w *WebviewWindow) SetBackgroundColour(colour RGBA) {}
func (w *WebviewWindow) SetVisibility(visible bool) { w.visible = visible }
func (w *WebviewWindow) SetAlwaysOnTop(alwaysOnTop bool) { w.alwaysOnTop = alwaysOnTop }
func (w *WebviewWindow) Maximise() { w.maximised = true }
func (w *WebviewWindow) Restore() { w.maximised = false }
func (w *WebviewWindow) Minimise() {}
func (w *WebviewWindow) Maximise() { w.maximised = true; w.minimised = false; w.visible = true }
func (w *WebviewWindow) Restore() { w.maximised = false; w.minimised = false; w.visible = true }
func (w *WebviewWindow) Minimise() { w.minimised = true; w.maximised = false; w.visible = false }
func (w *WebviewWindow) Focus() { w.focused = true }
func (w *WebviewWindow) Close() {}
func (w *WebviewWindow) Show() { w.visible = true }