feat(window): no minimum size
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.
This commit is contained in:
@@ -2376,7 +2376,10 @@ func (a *App) restoreWindowPosition() {
|
||||
applog.Printf("window: maximised with corner 0,0 — nothing to restore")
|
||||
return
|
||||
}
|
||||
if !onSomeMonitor(ws.X, ws.Y, normalMinW, normalMinH) {
|
||||
// The saved size, not the minimum: this asks "is that corner on a
|
||||
// screen", and with no minimum any more the old arguments were a
|
||||
// zero-sized rectangle.
|
||||
if !onSomeMonitor(ws.X, ws.Y, max(ws.Width, windowSaneW), max(ws.Height, windowSaneH)) {
|
||||
applog.Printf("window: saved maximised corner %d,%d is off every monitor — opening where Windows puts it", ws.X, ws.Y)
|
||||
return
|
||||
}
|
||||
@@ -2387,7 +2390,7 @@ func (a *App) restoreWindowPosition() {
|
||||
applog.Printf("window: re-maximised at the saved corner — now at %d,%d", gx, gy)
|
||||
return
|
||||
}
|
||||
if ws.Width < normalMinW || ws.Height < normalMinH || ws.Width > maxW || ws.Height > maxH {
|
||||
if ws.Width < windowSaneW || ws.Height < windowSaneH || ws.Width > maxW || ws.Height > maxH {
|
||||
return // corrupt / absurd — leave the default placement
|
||||
}
|
||||
// The SIZE was sanity-checked above but the POSITION never was, and that is
|
||||
@@ -7671,9 +7674,16 @@ func (a *App) GridSquareChoices() (GridSquareChoices, error) {
|
||||
// Min size must be reduced BEFORE resizing down, otherwise the OS clamps to
|
||||
// the previous (larger) min — and increased BEFORE resizing up.
|
||||
const (
|
||||
compactW, compactH = 1240, 158
|
||||
normalW, normalH = 1400, 900
|
||||
normalMinW, normalMinH = 1100, 700
|
||||
compactW, compactH = 1240, 158
|
||||
normalW, normalH = 1400, 900
|
||||
// No minimum on the normal window: 0 tells Wails not to constrain it at
|
||||
// all, and the operator decides how small is useful. See main.go.
|
||||
normalMinW, normalMinH = 0, 0
|
||||
// windowSaneW/H is not a minimum the operator feels — it is the floor below
|
||||
// which a SAVED geometry is treated as corrupt rather than as a choice. A
|
||||
// window restored at 0x0 cannot be grabbed to fix it, and that is the one
|
||||
// state there is no way back from.
|
||||
windowSaneW, windowSaneH = 200, 150
|
||||
// Large enough to never constrain a maximised window on big displays.
|
||||
maxW, maxH = 8000, 6000
|
||||
)
|
||||
@@ -7693,7 +7703,9 @@ func (a *App) SetCompactMode(on bool) {
|
||||
}
|
||||
a.preCompactW, a.preCompactH = wruntime.WindowGetSize(a.ctx)
|
||||
a.preCompactX, a.preCompactY = wruntime.WindowGetPosition(a.ctx)
|
||||
a.preCompactValid = a.preCompactW >= normalMinW && a.preCompactH >= normalMinH
|
||||
// Against the sane floor, not a minimum — there is no longer one. This
|
||||
// only asks whether the capture is believable enough to restore.
|
||||
a.preCompactValid = a.preCompactW >= windowSaneW && a.preCompactH >= windowSaneH
|
||||
}
|
||||
a.compact = on
|
||||
if on {
|
||||
|
||||
+4
-2
@@ -13,7 +13,8 @@
|
||||
"The satellite ground track no longer draws a straight line across the map when it crosses the antimeridian.",
|
||||
"A correction you make on the transmit VFO is now kept for the whole pass, and remembered for that transponder. Doppler tracking used to undo it a second later.",
|
||||
"The Green Heron RT-21 is named in the rotator list. It speaks the DCU-1 command set OpsLog already drives, over its COM port or straight over TCP with the Ethernet option — set the controller to DCU-1 / Rotor-EZ.",
|
||||
"Retract and Calibrate on a SteppIR now show the elements moving, and inhibit the transmitter while they do. Neither said anything before — the same was missing on an Ultrabeam retract, where the element lengths counting down hid it."
|
||||
"Retract and Calibrate on a SteppIR now show the elements moving, and inhibit the transmitter while they do. Neither said anything before — the same was missing on an Ultrabeam retract, where the element lengths counting down hid it.",
|
||||
"The window can be made as small as you like. The 1100x700 floor is gone — only Windows own limit remains."
|
||||
],
|
||||
"fr": [
|
||||
"Le tracé du ciel et la position passent dans leur propre colonne, à gauche de la carte. Largeur réglable, et la colonne se replie comme celle de droite.",
|
||||
@@ -27,7 +28,8 @@
|
||||
"Le tracé au sol du satellite ne trace plus une ligne droite en travers de la carte lorsqu’il franchit l’antiméridien.",
|
||||
"Une correction faite sur le VFO d’émission est désormais conservée pour toute la passe, et mémorisée pour ce transpondeur. Le suivi Doppler l’effaçait une seconde plus tard.",
|
||||
"Le Green Heron RT-21 est nommé dans la liste des rotators. Il parle le jeu de commandes DCU-1 que OpsLog pilote déjà, via son port COM ou directement en TCP avec l’option Ethernet — régler le contrôleur sur DCU-1 / Rotor-EZ.",
|
||||
"Rétracter et Calibrer sur une SteppIR montrent désormais les éléments en mouvement, et inhibent l’émission pendant ce temps. Ni l’un ni l’autre ne le signalait — même manque sur la rétraction d’une Ultrabeam, où le défilement des longueurs d’éléments le masquait."
|
||||
"Rétracter et Calibrer sur une SteppIR montrent désormais les éléments en mouvement, et inhibent l’émission pendant ce temps. Ni l’un ni l’autre ne le signalait — même manque sur la rétraction d’une Ultrabeam, où le défilement des longueurs d’éléments le masquait.",
|
||||
"La fenêtre peut être réduite autant que vous voulez. Le plancher de 1100x700 disparaît — il ne reste que la limite propre à Windows."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -230,11 +230,21 @@ func main() {
|
||||
bootLog("WebView2 profile: %q", webviewDataPath())
|
||||
bootLog("entering wails.Run (window %dx%d, state %v)", width, height, startState)
|
||||
err := wails.Run(&options.App{
|
||||
Title: "OpsLog",
|
||||
Width: width,
|
||||
Height: height,
|
||||
MinWidth: 1100,
|
||||
MinHeight: 700,
|
||||
Title: "OpsLog",
|
||||
Width: width,
|
||||
Height: height,
|
||||
// No minimum. Wails treats 0 as "no constraint" (winc only fills
|
||||
// PtMinTrackSize when the value is above zero), so Windows applies its
|
||||
// own floor — about the width of the caption buttons — and the operator
|
||||
// decides the rest.
|
||||
//
|
||||
// It was 1100x700, which is a fair guess at where the layout stops being
|
||||
// comfortable and no business of ours to enforce: a second screen used as
|
||||
// a narrow strip, a window parked beside a decoder, a small laptop — all
|
||||
// of them ran into a wall with nothing to show for it. The panels already
|
||||
// scroll and collapse.
|
||||
MinWidth: 0,
|
||||
MinHeight: 0,
|
||||
WindowStartState: startState,
|
||||
// No OS title bar: it was a dead 32-pixel band above a window that already
|
||||
// has its own title strip. The app header takes over — it carries the drag
|
||||
|
||||
@@ -67,3 +67,28 @@ func TestOnSomeMonitorTrustsSavedPositionWhenBoundsUnknown(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user