Repository navigation
Zwei Fensterprüfstände: auf Ruhe warten, Grundlage frisch erzwingen - #451
Conversation
`collapsingWidensTheAdjacentPanadapter` fiel am 2026-11-03 und wieder am 2026-11-13 auf dem Linux-Laeufer, beide Male mit DERSELBEN Zahl: 429 statt 420. Der Kommentar im Pruefstand nennt die Ursache schon selbst -- `snapToGridAfterSettle` (WindowPlacement.h) rastet den Rahmen erst 180 ms nach dem Loslassen ein, und wer vorher misst, vergleicht die Breite VOR dem Rasten mit der danach. Die Antwort darauf war bisher eine laengere Wartezeit (kRastFristMs = 400). Das haelt nur, solange der Taktgeber puenktlich drankommt; auf einem ausgelasteten Laeufer tut er das nicht, und eine feste Frist laesst sich nicht so weit hochdrehen, dass sie immer reicht, ohne den Lauf zu bremsen. Jetzt wird an den drei Stellen, die eine Breite ablesen oder vergleichen, nicht mehr auf die Uhr gewartet, sondern auf RUHE: `warteBisDerRahmenSteht` wartet erst die Frist ab (vorher hat das Rasten gar nicht begonnen, und "ruhig" waere eine Luege) und dann, bis sich frameGeometry() drei Messungen lang nicht mehr aendert. Kommt er bis zur Obergrenze nicht zur Ruhe, faellt der Fall mit Begruendung, statt stillschweigend weiterzulaufen. Gegenprobe gefahren: mit einer Ruhepruefung, die nie zutrifft, faellt der Fall mit "der Rahmen kam nach dem Setzen nicht zur Ruhe" -- der Helfer winkt also nicht bloss durch. 2/2 gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
kleinUndWiederGrossGibtDieAlteLage() stellte seine Lage nie her. Der Fall setzt dem schwebenden Fenster eine Untergrenze und erwartet, dass es beim Verkleinern des Hauptfensters an ihr haengenbleibt. Dafuer muessen die ANTEILE, aus denen MainWindow::schwebendeUmrechnen die neue Groesse rechnet, von JETZT stammen. schwebendeMitziehenForTest() setzt aber nur den Hauptrahmen als Basis; die Anteile je Fenster bleiben stehen, solange das Fenster dort steht, wo das Mitziehen es hingesetzt hat -- so ist es gewollt. Steht das Fenster schmaler, als seine Grundlage will (auf macOS: 260 statt 269, weil es im Fall davor an seiner natuerlichen Mindestbreite hing), rechnet der Fall mit 269 weiter und vergleicht gegen 260. Erst auf Linux (drei Faelle), dann auf macOS (Lauf 43497937016, Shard 2/2, ein Fall) -- beide Male dieselbe Ursache. Jetzt zieht der Fall das Fenster vorher um 32 Punkte von Hand: mehr als eine Rasterweite, damit gelten die Anteile als veraltet und werden beim naechsten Umrechnen frisch gemessen. Dazu eine qInfo-Zeile VOR dem Vergleich (ein Fehlschlag in der CI soll die Zahlen zeigen) und eine Vorbedingung, dass das Hauptfenster wirklich schmaler wurde -- es stoesst bei dieser Groesse an seine eigene Mindestbreite. Gegenprobe gefahren: die macOS-Lage lokal hergestellt (Hoechstbreite 200 setzen, Hauptfenster verkleinern, Hoechstbreite loesen) -- ohne die Behebung faellt der Fall mit genau denselben Zahlen wie in der CI (Actual 269, Expected 260), mit ihr ist er gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Zweiter Prüfstand dazu: Ursache ist nicht Flattern, sondern dass der Fall seine Lage nie herstellte: Gegenprobe gefahren: die macOS-Lage lokal hergestellt (Höchstbreite 200 setzen, Hauptfenster verkleinern, Höchstbreite lösen) — ohne die Behebung fällt der Fall mit genau denselben Zahlen wie in der CI, mit ihr ist er grün (10/10, 13,8 s). |
Drei Faelle stellten das Fenster "300 rechts, 520 unter der Oberkante" des Hauptfensters -- eine feste Zahl, die nur hier traegt. Auf macOS wird dasselbe Fenster doppelt so hoch (301 gegen 157 Punkte) und die Bedienleisten fressen 150 Punkte statt weniger: dort ragte es nach dem Verkleinern in die Statusleiste, der Schutzrahmen schob es waehrend der Messung heraus -- und der Pruefstand zaehlte das als "zog mit". Im Protokoll stand es wortwoertlich vor jedem der beiden Fehlschlaege: "Schutzrahmen: 1 schwebende Fenster lagen auf einer Bedienleiste und wurden heruntergeschoben" (Lauf 43523526068, macOS 2/2). Jetzt rechnet tiefAberSicherStellen() die Lage aus der Arbeitsflaeche, der gemessenen Fensterhoehe und dem Platz, den der Fall selbst noch verliert (58 Punkte Hoehe beim Startsprung, 41 beim Zug nach oben, 100 beim Verkleinern) -- und meldet es als fehlenden Platz, wenn der Fall nicht herstellbar ist, statt stumm Falsches zu messen. eigeneBewegung- ZiehtNicht() haengt damit nicht mehr an der Lage seines Vorgaengers. Gegenprobe gefahren: mit erzwungener macOS-Hoehe (setMinimumHeight(310) in initTestCase) fallen mit den alten festen Stellen genau dieselben zwei Faelle, mit denselben Zahlen wie in der CI (Expected QPoint(528,688), "zog mit (0,-224)") und derselben Schutzrahmen-Meldung davor; mit dem Helfer sind alle zehn gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ssen (#453) `beimZiehenWirdDerRahmenSICHTBAR` war auf main rot (Linux-Shard 3/4, 1 von 304 -- derselbe Fall und derselbe Shard wie am 2026-10-20). Das Programm hat dabei vollkommen richtig gearbeitet. Die Ursache stand im VOLLEN Protokoll, eine Zeile vor dem Fehlschlag, und nicht in den FAIL-Zeilen: Schutzrahmen: 1 schwebende Fenster lagen auf einer Bedienleiste und wurden heruntergeschoben Nach dem Aufbau setzt MainWindow zwei Nachlaeufe an (MainWindow.cpp, "Zwei Nachlaeufe"): `singleShot(0)` und `singleShot(500)`, beide rufen `schwebendeAusDemSchutzrahmenHolen()`. Auf dem lastigen Laeufer kam der zweite erst mitten in der Messung -- er holte den eben platzierten Schweber von der Sperrzone weg. Danach beruehrte nichts mehr etwas, also schwieg `meldeZug()` zu Recht, und der Lauf meldete das als „der Rahmen bleibt beim Ziehen unsichtbar". Drei Aenderungen, alle im Pruefstand: * `warteBisDasHauptfensterSteht()` nach dem Muster von `warteBisDerRahmenSteht()` aus tst_side_area_integration.cpp (#451): Mindestfrist ueber die 500 ms des zweiten Nachlaufs, danach auf Ruhe warten -- drei gleiche Messungen der Fenstergeometrie, nicht eine. Auf den ZUSTAND warten, nicht auf die Uhr. * Das `processEvents()` zwischen `move()` und `meldeZug()` ist weg. Genau in dieser Luecke lief der Nachlauf. `meldeZug()` liest `frameGeometry()` direkt und braucht keine Ereignisrunde. * Sprechende Meldungen: faellt der Fall doch, sagt er jetzt, WO das Fenster liegt und dass ein Nachlauf es geholt haben kann. Die alte Meldung („der Rahmen bleibt beim Ziehen unsichtbar") hat mich zuerst auf die falsche Spur gefuehrt. Dazu ein neuer Prueffall, `einePlatzierungLoestDenHinweisNICHTAus`: die Wache `if (s_eigeneBewegungen > 0) { return; }` in `meldeZug()` war NIRGENDS festgenagelt -- in keinem der vier Prueffaelle, die `EigeneBewegung` ueberhaupt nennen. Darum konnte ich sie zuerst fuer die Ursache halten; nichts schloss sie aus. Jetzt tut es etwas, und zwar in beide Richtungen: eine Platzierung loest den Hinweis nicht aus, ein echter Zug danach aber doch. ZWEI GEGENPROBEN gefahren, weil ein lokal gruener Lauf hier nichts beweist: 1. Nachlauf absichtlich mitten in die Messung (`mw.schwebendeAusDemSchutzrahmenHolen()` zwischen `move()` und der Pruefung): rot, mit derselben Protokollzeile wie in der CI und der neuen Meldung „die Lage kam nicht an: 42,100 304x124 trifft die Sperrzone nicht". Damit ist der Fehlschlag des Laeufers gezielt hergestellt, nicht nur vermutet. 2. Die Wache aus `meldeZug()` entfernt: `einePlatzierungLoestDen HinweisNICHTAus` wird rot („der Hinweis blinkt beim PLATZIEREN"). Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Warum
collapsingWidensTheAdjacentPanadapterfiel am 2026-11-03 und wieder am 2026-11-13 auf dem Linux-Läufer — beide Male mit derselben Zahl: 429 statt 420. Am 13.11. hat das einen fertigen PR (#442) blockiert, der den Seitenbereich gar nicht anfasst.Der Kommentar im Prüfstand nennt die Ursache schon selbst:
snapToGridAfterSettle(WindowPlacement.h) rastet den Rahmen erst 180 ms nach dem Loslassen ein. Wer vorher misst, vergleicht die Breite vor dem Rasten mit der danach.Die bisherige Antwort darauf war eine längere Wartezeit (
kRastFristMs = 400). Das hält nur, solange der Taktgeber pünktlich drankommt — auf einem ausgelasteten Läufer tut er das nicht, und eine feste Frist lässt sich nicht so weit hochdrehen, dass sie immer reicht, ohne jeden Lauf zu bremsen.Was sich ändert
An den drei Stellen, die eine Breite ablesen oder vergleichen, wird nicht mehr auf die Uhr gewartet, sondern auf Ruhe:
warteBisDerRahmenSteht()wartet erst die Frist ab — vorher hat das Rasten gar nicht begonnen, und „ruhig" wäre eine Lüge — und dann, bis sichframeGeometry()drei Messungen lang nicht mehr ändert. Kommt der Rahmen bis zur Obergrenze (4 s) nicht zur Ruhe, fällt der Fall mit Begründung, statt stillschweigend weiterzulaufen: ein übergangener Fall sieht aus wie ein Erfolg.Kein Produktivcode berührt, nur der Prüfstand.
Gegenprobe
Mit einer Ruheprüfung, die nie zutrifft (
if (false && jetzt == vorher)), fällt der Fall mitDer Helfer winkt also nicht bloß durch. Zurückgestellt: 2/2 grün.
🤖 Generated with Claude Code