The window has MoveToActiveSpace so that a first show, or an Open from
the menu bar, puts it on the Space the user is on (a window first shown
while another app was full screen belonged to that Space from then on).
The Dock's reopen also went through openMain's Show and Focus, so with
the window open on another Space a Dock click pulled it over instead of
switching to it, as other Mac apps do.
The window now carries MoveToActiveSpace only while it is shown
(showHere: set, Show, Focus, cleared 500ms later, since clearing it at
once loses the move). The Dock's reopen (reopenMain) activates the app
and leaves an open window where it is, so macOS switches to its Space; a
closed, hidden or minimised window, or one still loading, is shown on the
current Space as before. The menu bar panel and its Open are unchanged.
TestDockReopenKeepsTheWindowsSpace (darwin, cgo) runs a real Wails app:
open, reopen while open (the flag is never set, the window stays open),
hidden then reopened, and minimised then reopened. With the old reopen
it fails ("the shown window stays on its Space").
Tried for real on this Mac (macOS 26.2), on sandbox .app builds of the
old and new code under a sandbox HOME, with a second Space added and
removed afterwards. Old build: window open on Space 1, Dock reopen from
Space 2 left the user on Space 2 and moved the window there. New build:
the same reopen switched to Space 1 and the window stayed there. A
minimised or closed window was shown on Space 2, the current one. The
menu bar panel opened and closed on both Spaces. go test -tags nogui
./internal/gui/... and go test ./internal/gui (cgo) pass under a temp
HOME; go vet, and GOOS=linux / GOOS=windows go vet -tags nogui pass.
Not tried on a full-screen Space or with several displays.
75 lines
2.3 KiB
Go
75 lines
2.3 KiB
Go
//go:build !nogui
|
|
|
|
package gui
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/wailsapp/wails/v3/pkg/application"
|
|
|
|
"github.com/yetone/magpie/internal/settings"
|
|
)
|
|
|
|
// mainMacWindow: the main window's Mac options. A window belongs to the
|
|
// Space it was last shown on, and showing it again takes the user there; one
|
|
// first shown while another app was full screen (a restart to update, with
|
|
// the user in that app) belonged to that app's Space from then on, and every
|
|
// Open went back to it. It moves to the Space the user is on whenever it is
|
|
// shown instead, and can still be made full screen itself. Once shown it
|
|
// stays on its Space (showHere), so a click on the Dock icon goes to it there
|
|
// (reopenMain).
|
|
func mainMacWindow() application.MacWindow {
|
|
return application.MacWindow{
|
|
// no InvisibleTitleBarHeight: that strip drags from anywhere in
|
|
// it, tabs included; the header marks what drags instead
|
|
TitleBar: application.MacTitleBarHiddenInset,
|
|
CollectionBehavior: application.MacWindowCollectionBehaviorMoveToActiveSpace |
|
|
application.MacWindowCollectionBehaviorFullScreenPrimary,
|
|
}
|
|
}
|
|
|
|
type closeAction int
|
|
|
|
const (
|
|
closeHide closeAction = iota // hide the window now
|
|
closeLeaveFullscreen // leave full screen, then hide it
|
|
)
|
|
|
|
// closeStep: what closing the main window does. A full-screen window on the
|
|
// Mac hidden as it is leaves its Space behind, black, with nothing in it; it
|
|
// leaves full screen first and is hidden once it has.
|
|
func closeStep(goos string, fullscreen bool) closeAction {
|
|
if goos == "darwin" && fullscreen {
|
|
return closeLeaveFullscreen
|
|
}
|
|
return closeHide
|
|
}
|
|
|
|
// hideMain hides the main window, and takes magpie out of the Dock if it is
|
|
// there only while the window is shown.
|
|
func (h *host) hideMain() {
|
|
application.InvokeSync(func() {
|
|
if h.main != nil {
|
|
h.main.Hide()
|
|
}
|
|
})
|
|
h.dock(settings.Load(), false)
|
|
}
|
|
|
|
// leaveFullscreenThenHide takes the closed full-screen window out of full
|
|
// screen; WindowDidExitFullScreen hides it. Should that never come (the
|
|
// system refused to leave), it is hidden after a while all the same.
|
|
func (h *host) leaveFullscreenThenHide() {
|
|
h.closing.Store(true)
|
|
application.InvokeSync(func() {
|
|
if h.main != nil {
|
|
h.main.UnFullscreen()
|
|
}
|
|
})
|
|
time.AfterFunc(3*time.Second, func() {
|
|
if h.closing.Swap(false) {
|
|
application.InvokeAsync(h.hideMain)
|
|
}
|
|
})
|
|
}
|