The window would not go below 1100x700. That was a fair guess at where the layout stops being comfortable and no business of ours to enforce: an operator wanting OpsLog as a narrow strip beside a decoder, parked on a second screen, or on a small laptop, hit a wall with nothing to show for it. The panels already scroll and collapse. Zero is how Wails says "do not constrain" — winc fills PtMinTrackSize only when the value is above zero, checked in the library rather than assumed — so Windows applies its own floor, about the width of the caption buttons, and nothing here adds to it. Removing the constant meant three other users of it had to be sorted out, since each wanted something different from "the minimum": - The saved-geometry sanity check now has its own floor, 200x150. That is not a minimum the operator feels; it decides when a stored size is corrupt rather than chosen. A window restored at 0x0 cannot be grabbed to fix it, and that is the one state there is no way back from. - The maximised-corner monitor check was passing the minimum AS a size, which would now be a zero-sized rectangle. It uses the saved size. - Leaving compact mode validated its captured geometry against the minimum; it uses the sane floor. SetCompactHeight keeps its 900 minimum: it returns early unless compact is on, and leaving compact resets the minimum to none.
95 lines
4.0 KiB
Go
95 lines
4.0 KiB
Go
package main
|
|
|
|
import "testing"
|
|
|
|
// A window restored onto a monitor that is no longer attached opens invisibly
|
|
// and stays that way — there is no way back short of deleting window.json, which
|
|
// no operator knows to do. These cases decide whether the saved position is
|
|
// honoured or quietly dropped for the default placement.
|
|
func TestOverlapsEnough(t *testing.T) {
|
|
// Two 1920x1080 monitors, the SECOND one to the LEFT of the primary: the
|
|
// virtual desktop then starts at a negative x. This is the layout that
|
|
// produces lost windows, and where a sign error would go unnoticed.
|
|
const vx, vy, vw, vh = -1920, 0, 3840, 1080
|
|
|
|
cases := []struct {
|
|
name string
|
|
x, y, w, h int
|
|
wantRestorabl bool
|
|
}{
|
|
{"centred on the primary monitor", 300, 200, 1400, 900, true},
|
|
{"on the left-hand monitor (negative x)", -1500, 100, 1400, 900, true},
|
|
{"just inside the far left edge", -1900, 0, 1400, 900, true},
|
|
{"hard against the right edge, title bar still grabbable", 1920 - 200, 100, 1400, 900, true},
|
|
|
|
// The failures this exists to catch.
|
|
{"entirely past the left edge", -3400, 100, 1400, 900, false},
|
|
{"below every monitor", 300, 2000, 1400, 900, false},
|
|
{"barely clipping the right edge (10 px)", 1910, 100, 1400, 900, false},
|
|
{"only a sliver of height on screen (8 px)", 300, 1072, 1400, 900, false},
|
|
{"absurd coordinates from a corrupt file", 999999, 999999, 1400, 900, false},
|
|
}
|
|
for _, c := range cases {
|
|
if got := overlapsEnough(c.x, c.y, c.w, c.h, vx, vy, vw, vh); got != c.wantRestorabl {
|
|
t.Errorf("%s: overlapsEnough(%d,%d,%dx%d) = %v, want %v",
|
|
c.name, c.x, c.y, c.w, c.h, got, c.wantRestorabl)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The actual field scenario: OpsLog was closed on a second monitor, that monitor
|
|
// is gone, and the desktop is now the primary screen alone. The saved position
|
|
// must be dropped — this is the case that leaves the window invisible.
|
|
func TestOverlapsEnoughAfterMonitorUnplugged(t *testing.T) {
|
|
// Single 1920x1080 primary; the left-hand monitor no longer exists.
|
|
const vx, vy, vw, vh = 0, 0, 1920, 1080
|
|
for _, c := range []struct {
|
|
name string
|
|
x, y, w, h int
|
|
want bool
|
|
}{
|
|
{"saved on the monitor that is now gone", -1500, 100, 1400, 900, false},
|
|
{"saved just off the left edge", -1400, 100, 1400, 900, false},
|
|
{"saved on the surviving monitor", 200, 100, 1400, 900, true},
|
|
} {
|
|
if got := overlapsEnough(c.x, c.y, c.w, c.h, vx, vy, vw, vh); got != c.want {
|
|
t.Errorf("%s: got %v, want %v", c.name, got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// With the desktop bounds unavailable (non-Windows, or the call failing) the
|
|
// saved position must be honoured rather than second-guessed.
|
|
func TestOnSomeMonitorTrustsSavedPositionWhenBoundsUnknown(t *testing.T) {
|
|
if _, _, _, _, ok := virtualScreenBounds(); !ok {
|
|
if !onSomeMonitor(999999, 999999, 1400, 900) {
|
|
t.Error("with unknown desktop bounds the saved position must be kept")
|
|
}
|
|
}
|
|
}
|
|
|
|
// The window has no minimum size: an operator who wants OpsLog as a narrow
|
|
// strip beside a decoder gets to have one. Zero is how Wails says "do not
|
|
// constrain" — winc only fills PtMinTrackSize when the value is above zero — so
|
|
// Windows applies its own floor and nothing here adds to it.
|
|
func TestTheWindowHasNoMinimumSize(t *testing.T) {
|
|
if normalMinW != 0 || normalMinH != 0 {
|
|
t.Errorf("normalMin is %dx%d — anything but 0x0 is a wall the operator hits", normalMinW, normalMinH)
|
|
}
|
|
}
|
|
|
|
// The sane floor is a different thing from a minimum: it decides when a SAVED
|
|
// geometry is corrupt rather than chosen. It has to stay small enough not to
|
|
// second-guess a deliberately tiny window, and large enough that what is
|
|
// restored can be grabbed and resized — a window reopened at 0x0 is the one
|
|
// state there is no way back from.
|
|
func TestSavedGeometryFloorIsSmallButGrabbable(t *testing.T) {
|
|
if windowSaneW <= 0 || windowSaneH <= 0 {
|
|
t.Fatal("a zero floor would restore a window that cannot be grabbed")
|
|
}
|
|
if windowSaneW > 400 || windowSaneH > 300 {
|
|
t.Errorf("the floor is %dx%d — big enough to reject a window somebody chose",
|
|
windowSaneW, windowSaneH)
|
|
}
|
|
}
|