4 Min. LesezeitJonas Höttler

Warum ein Fenster so schwer ein zweites Mal zu erkennen ist

Ein Fenster hat keinen bleibenden Namen. Seine ID stirbt beim Schließen, sein Titel wandert, während du arbeitest, und seine App macht bereitwillig vierzig weitere auf, die genauso aussehen. So findet ein Zettel trotzdem zurück.

Einen Zettel an ein Fenster zu heften klingt nach einer Aufgabe für fünf Minuten. Du hast ein Fenster, das Fenster hat eine Kennung, du schreibst die Kennung neben den Zettel, und morgen schlägst du sie wieder nach.

Die Kennung ist der Teil, der nicht funktioniert. Eine CGWindowID ist auf macOS nur so lange eindeutig, wie das Fenster offen ist, und die Zahl wird danach neu vergeben. Ein HWND verhält sich auf Windows genauso. Speichere eine, beende die App, komm zurück — und die Zahl zeigt entweder auf nichts oder, schlimmer, auf das Fenster von jemand anderem.

Die interessante Frage ist also nicht, wie man einen Zettel zeichnet. Sie lautet: Was ist ein Fenster, so dass man es morgen wiedererkennen kann?

Ein Fenster hat keinen Namen, nur Symptome

Was ein Betriebssystem über ein fremdes Fenster verrät, ist eine kurze Liste:

  • welche App es besitzt, als Bundle-Kennung und als Anzeigename
  • seinen Titel, so wie er gerade lautet
  • wo es steht und wie groß es ist
  • manchmal, wenn die App großzügig ist, den Pfad des Dokuments, das sie zeigt

Das ist die gesamte Beweislage. Es gibt kein Feld namens Identität, und jeder Punkt auf dieser Liste kann sich ändern, ohne dass sich das Fenster ändert.

Der Titel ist der schlimmste Fall, weil er zugleich der nützlichste ist. Er wandert dauernd:

ZeitWas das Fenster meldetWas verglichen wird
09:14importer.dart — cellalertimporter.dart — cellalert
09:31● importer.dart — cellalertimporter.dart — cellalert
10:02● importer.dart — cellalert — Zedimporter.dart — cellalert
10:47importer.dart — cellalertimporter.dart — cellalert
Vier Titel in neunzig Minuten, ein Fenster. Rechts, was nach dem Normalisieren übrig bleibt — und was verglichen wird.

Dasselbe Fenster, neunzig Minuten auseinander, meldet vier verschiedene Zeichenketten. Ein naiver Vergleich würde dreimal entscheiden, dass das ein anderes Fenster ist, und den Zettel fallen lassen.

Erst normalisieren, dann vergleichen

Also wird nichts roh verglichen. Bevor ein Titel als Beweis dient, wird er um das erleichtert, von dem bekannt ist, dass es wandert:

  • die Markierung für ungesicherte Änderungen, die manche Editoren voranstellen (● datei.txt)
  • Zähler für Ungelesenes ((12) Posteingang)
  • ein angehängter App-Name, wo die App einen anhängt
  • Terminal-Fenstergrößen (— 80×24)

Übrig bleibt der Teil, den ein Mensch „den Titel dieses Fensters“ nennen würde. Er ist stabil genug für einen Vergleich — und genau dieses Entfernen ist es, was ein Fenster auffindbar hält, während damit gearbeitet wird, und nicht nur, wenn es ruht.

Es gibt hier eine zweite, feinere Regel. Ein hinteres Stück wie — cellalert benennt meist das Projekt, zu dem eine Datei gehört, und das ist ein wirklich nützliches Signal: Zwei Dateien im selben Repository gehören wahrscheinlich zum selben Arbeitszusammenhang. Manche hinteren Stücke tauchen aber in völlig unverwandten Fenstern auf — bloße Zahlen, Fenstermaße, Shell-Namen. Die werden nie als Projektsignal genommen, denn ein Signal, das auf alles passt, passt auf nichts.

Eine Leiter, keine Regel

Ist normalisiert, ist die eigentliche Zuordnung eine geordnete Liste. Jeder Zettel trägt einen Fingerabdruck — Bundle-Kennung, App-Name, den Titel, wie er beim Anlegen lautete, den Dokumentpfad, falls es einen gab — und bei jeder Änderung werden diese Fingerabdrücke neu auf die gerade offenen Fenster gelegt, das stärkste Signal zuerst.

  1. Dokumentpfad
  2. Fenstertitel
  3. Früherer Titel
  4. Projekt
  5. Ähnlichkeit
  6. Position
  7. Einziges Fenster
Greedy über alle Kandidaten: Das stärkste Signal irgendwo gewinnt zuerst, und eine sichere Zuordnung kann nie von einer schwächeren gestohlen werden.

Die Reihenfolge ist der ganze Entwurf. Ein Dokumentpfad sticht einen Titel, weil eine Datei eine Identität ist und ein Titel nur deren Beschreibung. Ein gemerkter Titel sticht einen Ähnlichkeitswert, weil er etwas ist, das dieses Fenster tatsächlich getragen hat. Die Position sticht nichts außer Verzweiflung.

Und die Zuordnung läuft greedy über alle Kandidaten, nicht Fenster für Fenster. Das ist wichtig: Wenn Zettel A plausibel zu Fenster 1 und 2 passt, Zettel B aber nur zu Fenster 1 und dort sicher, bekommt B zuerst Fenster 1 und A geht an Fenster 2. Jeden Zettel für sich zu betrachten hieße, eine schwache Vermutung dürfe ein Fenster stehlen, das eine sichere Zuordnung gebraucht hätte.

Zwei Regeln über der Leiter

Die Leiter entscheidet zwischen plausiblen Antworten. Zwei Regeln entscheiden, was überhaupt plausibel ist.

Verschiedene Dokumente derselben App passen nie zusammen. Zwei Fenster desselben Editors mit zwei verschiedenen Dateien sind zwei verschiedene Dinge, egal was der Ähnlichkeitswert über ihre Titel sagt. Deinen Zettel über die Migration auf die falsche Quelldatei zu legen ist schlimmer, als gar keinen Zettel zu zeigen — und zwar auf eine Weise, die dir eine Stunde lang nicht auffallen muss.

Die Sicherheit steht auf dem Schirm. Jede Zuordnung meldet, ob sie sicher ist, wahrscheinlich, oder von dir von Hand gesetzt — und eine wahrscheinliche sagt das, in der Oberfläche, direkt neben dem Zettel. Das ist kein Kleingedrucktes. Eine zugegebene Vermutung ist wirklich nützlicher als eine selbstbewusste Falschantwort, weil sie dir sagt, wann du zweimal hinsehen solltest.

Nur Gewissheit darf lehren

Das letzte Stück hat am längsten gebraucht.

Solange eine Bindung sicher ist — exakter Titeltreffer, Dokumentpfad, ein von Hand angehefteter Zettel — sammelt die App jeden Titel, den dieses Fenster danach trägt, bis zu acht davon, und notiert, wo es stand. Nach einem Neustart erkennt jeder dieser gemerkten Titel es wieder. Erst das lässt Terminals überhaupt funktionieren: Der Titel eines Terminals ist, was gerade darin läuft, es kann bis mittags sechs verschiedene Zeichenketten getragen haben — und jede davon ist nun ein Weg zurück.

Die Versuchung ist, auch wahrscheinliche Zuordnungen lehren zu lassen. Das ist genau eine Zeile Code, und es verdoppelt, was die App lernt.

Es ist auch der Fehler, der das Produkt ruiniert. Eine wahrscheinliche Zuordnung ist eine Vermutung. Darf eine Vermutung sich in den Fingerabdruck zurückschreiben, wird aus einer falschen Vermutung dauerhafter Beweis für die nächste falsche Vermutung, und der Zettel wandert zu einem Fenster, zu dem er nie gehörte — still, und endgültig. Also werden wahrscheinliche Zuordnungen angezeigt, und sie lehren nie.

Was das bringt

Das Ergebnis ist undramatisch, und das ist der Punkt. Du schließt ein Fenster, startest am nächsten Morgen den Rechner neu, öffnest dasselbe Projekt — und der Zettel ist da, mit einem kleinen Hinweis, wie sicher die App ist, dass das das richtige Fenster ist.

Der Zettel ist ein Kind des Fensters — nicht des Bildschirms.

Nichts davon ist sichtbar, solange es funktioniert. Alles davon ist sichtbar, sobald es das einmal nicht tut. Genau dafür gibt es den Hinweis.

Fragen, die das aufwirft
Hat ein Fenster eine dauerhafte Kennung?
Nein. Eine CGWindowID ist auf macOS nur eindeutig, solange das Fenster existiert, und wird danach neu vergeben; ein HWND verhält sich auf Windows genauso. Keine von beiden übersteht einen Neustart der App, geschweige denn des Rechners.
Was passiert, wenn zwei Fenster gleich gut passen?
Die Zuordnung läuft greedy über alle Kandidaten: Das stärkste Signal irgendwo wird zuerst gesetzt, und eine sichere Zuordnung kann nie von einer schwächeren verdrängt werden. Wo nichts zwei Kandidaten trennt, wird die Zuordnung als wahrscheinlich ausgewiesen und nicht als sicher.
Warum werden Fenstertitel vor dem Vergleich normalisiert?
Weil sie wandern, während du arbeitest. Markierungen für ungesicherte Änderungen, Zähler für Ungelesenes, angehängte App-Namen und Terminal-Fenstergrößen ändern sich, ohne dass sich das Fenster ändert. Sie zu entfernen ist das, was ein Fenster im Gebrauch auffindbar hält.
Abgelegt unterFensterTechnikmacOS

Die App, neben der das geschrieben wurde

Balane WindowNote heftet einen Zettel an ein Fenster und gibt ihn dir zurück, wenn das Fenster zurückkommt. Kostenlos für zwei Fenster, auf macOS und Windows.

Quellen und Weiterlesen
Mehr aus dem Journal