\chapter{Client}

\section{Verwendete Technologien}
\begin{quotation}\begin{flushright}{\it
Web 2.0 is of course a piece of jargon,\\
nobody even knows what it means.\\
}
Tim Berners-Lee, Begründer des World Wide Webs
\end{flushright}\end{quotation}

\subsection{Sprachen und Werkzeuge}

Um die gewünschte Plattformunabhängigkeit zu erreichen und dabei die
Vorraussetzung zu erfüllen, dass keine Software installiert werden muss um
ajaxWM zu verwenden, fiel die Wahl auf Ajax. Ajax ist ein Akronym aus
{\glqq}Asynchronous Javascript and XML{\grqq} und beschreibt eine Vorgehensweise der
Internetseitengestaltung, bei der der Browser nicht wie bei herkömmlichen
Internetangeboten für jede Anfrage an den Server eine komplette Internetseite
zurück bekommt und diese dann darstellt, sondern dass JavaScript auf die
Interaktion des Benutzers eingeht, Anfragen an den Server im Hintergrund
startet und als Antwort nur die nötigen Informationen bekommt. Diese
Informationen liegen meistens in XML vor, können jedoch auch aus normalem Text
oder HTML-Fragmenten bestehen. JavaScript kann die erhaltenen Informationen zum
Beispiel dadurch darstellen, dass das Design der Seite verändert wird, die
Informationen an einer ausgesuchten Stelle dargestellt werden oder vorhandene
Informationen aktualisiert werden. Ajax erfreut sich im Zeitalter von
{\glqq}Web 2.0{\grqq}\footnote{Schwammige Bezeichnung für die Weiterentwicklung des WWW,
Websites werden interaktiver, sind Nutzerbezogener (z.B. Youtube) es wird
vermehrt {\glqq}soziale Software{\grqq} verwendet, Informationen werden nicht durch
zentrale Organisationen bereitgestellt oder verbreitet sondern z.B. auch über
diverse Weblogs (s.g. Blogs).} immer größerer Beliebtheit. Obwohl JavaScript
durch die Ecma International\footnote{European Computer Manufacturers
Association} standardisiert wurde, ist der Browserkrieg zwischen Netscape und
Microsoft zwar teilweise gelöst, dennoch unterscheiden sich die verschiedenen
Implementationen in manchen Punkten. Vor allem Microsofts Internet Explorer
besitzt bis Version 7 noch keine XMLHttpRequest-API\footnote{Das
XMLHttpRequest-Objekt is das Kernobjekt zur Verwendung von Ajax, es stellt
Funktionen bereit um asynchrone Anfragen abzusetzen, welche normalerweise als
XML beantwortet werden.} sondern benutzt Microsofts hauseigenes ActiveX-Objekt.
Um Anwendungen, die auf Ajax bzw. JavaScript basieren dennoch ohne großen
Aufwand so zu programmieren, dass sie in allen Browsern lauffähig sind, wurden
im Laufe der letzten Jahre mehrere Cross-Browser-Libraries geschaffen, die
dynamisch den Browser ermitteln und plattformunabhängige Schnittstellen
bereitstellen. Solche Libraries sind zum Beispiel Sarissa oder prototype.js,
die auch in ajaxWM verwendet werden\footnote{Prototype.js ist derzeit noch
nicht eingebaut.}.

\subsection{Architekturmodell}

Für den Client wurde ein modifiziertes
MVC-Modell\footnote{Model-View-Controller, Architekturmuster bei dem die
Software in drei Teile aufgeteilt wird. Das Model enthält die Daten, die Views
Präsentieren sie und der Controller regelt den Programmfluss.} verwendet, wobei
das Model den Server darstellt und damit nicht im Client vorhanden ist. Die
Views\footnote{Die Fenster und der Loginbildschirm. Virtuelle Desktops zählen
auch dazu, sind jedoch noch nicht vollständig implementiert.} bekommen ihre
Daten über Controller\footnote{Der Manager, globale Instanz der
Manager-Klasse.}, vom Model und stellen sie dar. Der Controller regelt den
kompletten Programmfluss. Er ist die Schnittstelle zwischen Model und den
Views, fängt Tastendrücke ab, überprüft sie auf Steuerungssequenzen,
kontrolliert die Session, erstellt Views und holt anf Anfrage Daten vom Model
und übergibt sie den Views.

\subsection{Grundlegende Funktionsweise}

Der grundlegende Ablauf des ajaxWM-Clients ist ähnlich anderer
Ajax-Anwendungen. Der Benutzer geht mit dem Browser auf die URL, auf der der
ajaxWM-Server läuft und bekommt als Antwort auf diese Anfrage eine
index.html-Datei die Pfade zu den verschiedenen JavaScript-Dateien enthält. Der
Browser lädt diese Dateien und fährt danach window.onload() aus, welche die
Methode zum Starten des ajaxWM-Clients aufruft. Diese Methode behandelt die
Initialisierung des Window Managers und damit auch die der grafischen
Oberfläche. Danach wird ein Loginbildschirm angezeigt, welcher bestehen bleibt
bis der Login erfolgreich war. Es folgt der Desktopmodus, welcher der Kern von
ajaxWM ist. Hier kann der Benutzer neue Fenster erstellen und mit ihnen und mit
ajaxWM allgemein interagieren. Dieser Desktop-Bildschirm bleibt bis zum Logout
bestehen. Der Logout kann entweder vom Benutzer selbst initiiert werden oder
zwangsweise nach einem bestimmten Zeitintervall erfolgen, in dem der Benutzer
mit keinen Objekten des Clients interagiert hat und auch keine Fenster geöffnet
waren. Nach einem Logout wird wieder der Loginbildschirm
dargestellt\footnote{Der Zwangslogout ist derzeit clientseitig noch nicht
vollständig implementiert, es wird nur die Session und die GUI zerstört.}. Alle
Events, die im Desktopmodus anfallen, werden vom Manager in eine Warteschleife
gesteckt, welche von einer anderen Methode des Managers abgearbeitet wird.
Läuft diese Methode nicht, wird sie direkt nachdem ein Event eingereiht wurde,
gestartet. Die Methode läuft durch, bis die Warteliste komplett leer ist.
Events werden als asynchrone Requests abgesetzt. Typisch für eine ajaxbasierte
Anwendung kommt zu keinem Reload oder Aufruf einer anderen Seite.

\section{Fehlerbehebung}
\begin{quotation}\begin{flushright}{\it
javascript coders always get their punishment\\
}
Zero, \href{http://german-bash.org/12562}{http://german-bash.org/12562} 
\end{flushright}\end{quotation}

Um den ordnungsgemäßen Ablauf des Clients zu überprüfen, wurde ein Debugger
entwickelt. Nachdem dieser initialisiert wurde, kann an jeder Stelle des
Clients ein Aufruf des Debuggers getätigt und ihm dabei Klassen- und
Funktionsname sowie die Nachricht, die angezeigt werden soll, übergeben werden.
Der Debugger zeigt diese Informationen in der rechten oberen Ecke des Fensters
an. Alle Nachrichten werden unten an die Liste angehängt. Würde durch das
Anhängen einer neuen Nachricht das Limit überschritten werden, werden oben am
Anfang der Liste so lange alte Nachrichten entfernt, bis die neue Nachricht
hinzugefügt werden kann ohne dass das Limit dabei überschritten wird. Die
Konfiguration des Debuggers läuft über Variablen des Managers. So können die
Dauer, wie lange die Nachrichtenliste nach dem hinzufügen einer Nachricht
angezeigt werden soll, und die Anzahl der Zeichen, die maximal in der Liste
enthalten sein dürfen, eingestellt werden. Momentan wird ein neuer Debugger
geschrieben, der mit Call-Traces\footnote{Call-Traces verfolgen, welche
Funktion momentan läuft, durch welche Funktion sie aufgerufen wurde, durch
welche Funktion diese wiederum aufgerufen wurde, u.s.w.. Tritt ein Fehler auf,
kann so über die Call-Trace genau erkannt werden, durch welche Funktionen die
Funktion aufgerufen wurde, die den Fehler verursachte. Desweiteren können die
übergebenen Parameter angezeigt werden. So ist der komplette Programmablauf bei
weitem leichter nachvollziehbar und Fehler können leichter gefunden werden.}
funktioniert. Dieser Debugger ersetzt jede Funktion durch einen Wrapper, der,
zusätzlich zu den selben Parametern, wie sie auch die Originalfunktion
erwartet, ein weiteres Objekt - die Call-Trace - erwartet. Wurde kein
Trace-Objekt übergeben, nimmt der Wrapper an, dass die Funktion direkt und
nicht über eine andere, registrierte Funktion aufgerufen wurde und erstellt ein
neues Trace-Objekt. Nach dieser Prüfung liegt immer ein Trace-Objekt vor. Der
Wrapper ruft eine Methode des Trace-Objektes auf, die den jeweiligen Funktions-
und Klassennamen speichert, sodass er später ausgegeben werden kann. Danach
ruft der Wrapper die Funktion auf die er ersetzt hat und übergibt ihr alle
Parameter in der selben Reihenfolge, wie er sie selbst bekommen hat -
ausgenommen vom Trace-Objekt. Da dir Originalfunktion innerhalb der
Wrapperfunktion definiert wird, ist das Trace-Objekt trotzdem verfügbar. Der
Rückgabewert der Originalfunktion wird temporär gespeichert und als
Rückgabewert des Wrappers zurückgegeben, nachdem nach Beendigung der
Originalfunktion das Trace-Objekt aufgefordert wird, den Eintrag dieser
Funktion wieder zu entfernen. Außerdem wird in jeder registrierten Funktion bei
jedem Aufruf einer anderen (oder der selben) registrierten Funktion das
Trace-Objekt als letzter Parameter angehängt. Dies geschieht auch wenn eine
Ausnahme geworfen wird. Der catch-Block, der die Ausnahme auffängt, kann so die
das Trace-Objekt der Ausnahme an den Debugger weitergeben. Dieser kann eine
formatierte Zeichenkette mit der Call-Trace ausgeben.

\lstset{language=Java} 
\begin{lstlisting}[caption=Originalfunktion]{orig}
function toString() {
    return '[object Object]';
}
\end{lstlisting}

\lstset{language=Java} 
\begin{lstlisting}[caption=Modifizierte Funktion{,} die Call-Traces unterstützt]{mod}
function toString(__trace) {
    if (null == __trace) {
        __trace = new Trace();
    }
    __trace.enter(this._CLASS_NAME, 'toString');
    _this = this;
    __trace_toString = function() {
        return '[object Object]';
    }
    var result = __trace_toString();
    __trace.leave();
    return result;
}
\end{lstlisting}

So können Call-Traces in JavaScript verwendet werden, obwohl diese Sprache
dies eigentlich nicht unterstützt.

\section{Startvorgang und Anmeldung}

\begin{quotation}\begin{flushright}{\it
Thunder is good, thunder is impressive;\\
but it is lightning that does the work.\\
}
Mark Twain
\end{flushright}\end{quotation}

\subsection{Grafische Oberfläche}

Bevor die grafische Oberfläche initialisiert wird, wird zuerst der Debugger
initialisiert. Es folgt eine Überprüfung des vom Benutzer ausgewählten
Themes\footnote{Derzeit kann der Benutzer noch kein Theme auswählen.}. Wurde
kein Theme ausgewählt, wird der Standard-Theme\footnote{lim - Less Is More.
Minimalistischer Theme, der nur Fensterinhalt und Titelleiste anzeigt.}
verwendet. Es wird ein Objekt der Klasse, die für die Themes zuständig ist,
erstellt und ihm dabei der Parameter des zu verwendenden Themes übergeben.
Dieses Objekt fügt der dargestellten HTML-Seite im Head-Bereich das
Theme-eigene Stylesheet hinzu, wodurch der Browser automatisch veranlasst wird,
selbstständig diese Datei herunterzuladen. Des weiteren erstellt das
Theme-Objekt eine Anfrage nach der XML-Datei des Themes, in der das Grundgerüst
des Themes beschrieben ist. Ist diese XML-Datei fertig heruntergeladen, wird
sie vom Theme-Objekt unter Berücksichtigung der Attribute, denen besondere
Funktionen zugeordnet sind\footnote{move, resize, position, size, onclick,
onmousedown, content}, in HTML umgesetzt. Am Ende dieser Prozedur ist das
HTML-Grundgerüst und das dazugehörige Stylesheet vorhanden, spezielle Attribute
der XML-Datei wurden in internen Datenstrukturen abgespeichert, sodass die
jeweiligen Elemente, denen besondere Funktionen zugeordnet wurden,
wiedergefunden werden können.

\subsection{Anmeldung}

Nachdem der Benutzer die Seite aufgerufen und der Client die Oberfläche
initialisiert hat, wird der Loginbildschirm angezeigt. Die Arbeit des Managers
ist nun vorerst getan. Jede Interaktion wird nun von der
Loginbildschirm-Klasse behandelt. Wenn der Benutzer sich einloggen möchte,
wird der Loginbildschirm verriegelt und eine Methode Managers aufgerufen,
welche das Login-Event mit den angegebenen Daten absetzt. Der Manager überprüft
ob der Server die Anfrage mit einem Fehlercode beantwortet hat oder ob der
Login erfolgreich war. War der Login erfolgreich wird eine
Session\footnote{Hier nur clientseitig um sich auszuweisen, der Server
überprüft die Gültigkeit der Sessions.} mit der ID, die der Server als Antwort
gesendet hat, erstellt. In beiden Fällen übergibt der Manager dem
Loginbildschirm eine Rückmeldung. Bei einem erfolgreichen Login schließt sich
der Loginbildschirm daraufhin selbst, schlug er fehl wird das eingegebene
Passwort gelöscht und der Loginbildschirm entriegelt. Der Loginbildschirm
bleibt so lange aktiv, bis der Login erfolgreich war.

\subsection{Übergang in den Normalbetrieb}

Nachdem nach einem erfolgreichen Login der Loginbildschirm geschlossen wurde
betritt der Manager den Desktopmodus. Es werden acht virtuelle Desktops
erstellt und zum ersten gewechselt. Der Manager setzt
Keyboardhooks\footnote{Hierbei handelt es sich um lokale Keyboardhooks, das
heißt es werden nur dann Tasten abgefangen, wenn nicht nur das
Browserfenster/-tab aktiv ist und Fokus hat, sondern auch die Seite, die ajaxWM
darstellt, angewählt ist und Tasten direkt an sie geleitet werden.} auf, die
jede gedrückte Taste(nkombination) abfangen und daraufhin überprüfen, ob es
sich um einen Hotkey handelt. Falls es sich um keinen Hotkey handelt und ein
Fenster fokusiert ist werden die gedrückten Tasten UTF-8-kodiert an den Server
gesendet. Hotkeys werden direkt behandelt, ohne dass dem Server irgendeine
Meldung darüber zukommen gelassen wird. Nachdem diese Initialisierungen
abgeschlossen sind, ist es möglich verschiedene Fenster zu erstellen, Befehle
in ihnen einzugeben, sie zu verschieben und ihre Größe zu ändern.

\section{Der Desktop}

\begin{quotation}\begin{flushright}{\it
Very funny, Scotty.\\
Now beam down my clothes!\\
}
Author unbekannt
\end{flushright}\end{quotation}

\subsection{Virtuelle Desktops}

Es sind acht virtuelle Desktops verfügbar, man kann zwischen ihnen mit den
Hotkeys STRG+ALT+1 bis STRG+ALT+8 hin- und herschalten. Alle Fenster, die
erstellt werden, werden - soweit nicht anders angegeben - auf dem virtuellen
Desktop erstellt, der gerade aktiv ist und in allen anderen virtuellen Desktops
nicht angezeigt.

\subsection{Fenster}

\subsubsection{Fenster erstellen}

Das erstellen der Fenster läuft immer über den Manager\footnote{Derzeit können
Fenster nur durch den Hotkey STRG+ALT+W erstellt und durch STRG+ALT+C
geschlossen werden.}. Soll ein neues Fenster erstellt werden, wird zuerst immer
eine Anfrage an den Server gesendet. Wenn kein Fehler beim Server aufgetreten
ist, wird ein neues Fenster-Objekt erstellt und ihm dabei direkt die vom Server
gelieferte ID übergeben. Das Fenster-Objekt bezieht seine HTML-Elemente durch
klonen der Schablone, die das Theme-Objekt aus der XML-Datei erstellt hat. Da
jedoch die Datenstrukturen, die Elemente mit speziellen Funktionen beinhalten
sollen, keine Referenz auf das Element beinhalten können\footnote{Würden die
Datenstrukturen Referenzen auf HTML-Elemente beinhalten, würde das Klonen neue
Elemente erstellen und das Kopieren der Referenzen auf die Elemente der
Schablone verweisen.} wird hier immer nur ein relativer Pfad ausgehend vom
Hauptelement zum gewünschten Element angegeben. So kann, nachdem die Hierarchie
der HTML-Elemente ausgehend vom Hauptelement geklont wurde, jeder Pfad anhand
des geklonten Hauptelementes durch eine Referenz des Elementes, auf das der
Pfad zeigt, ersetzt werden\footnote{Durch dieses Verfahren ist gesichert, dass
es zu keinen überflüssigen Klonungen kommt. Es wird nur das Hauptelement (und
dadurch die ihm untergeordneten Elemente) geklont und alle Pfade durch
Referenzen auf das geklonte Hauptelement oder ihm untergeordnete Elemente
ersetzt. Das Ersetzen der Pfade durch Referenzen beschleunigt den Client enorm,
da bei jedem Zugriff auf ein Element nicht erst das Element in der kompletten
Hierarchie ausgehend vom Hauptelement dieses Fensters gesucht werden muss,
sondern als Referenz direkt vorliegt und dadurch auch kaum zusätzlichen
Arbeitsspeicher verbraucht.}. Elemente, die Event-Handler\footnote{Ein
Event-Handler wird immer dann ausgeführt, wenn ein Ereignis eintritt. Solche
Ereignisse sind in JavaScript zum Beispiel onclick (tritt bei einem Mausklick
auf), onkeydown (tritt auf, wenn eine Taste gedrückt wird) u.a.} zugewiesen
bekommen sollen, werden auf die selbe Art erst durch relative Pfade
dargestellt, die beim Erstellen des Fensters durch Referenzen ersetzt werden.
Obwohl das Fenster-Objekt seine Elemente erstellt und alle Pfade ersetzt hat,
wird es noch nicht angezeigt. Zuerst ruft das Fenster-Objekt noch den Manager
auf, der dem Server ein Synchronisations-Event sendet. Während dieser Event
noch abgearbeitet wird, beginnt das Fenster-Objekt mit der Darstellung des
Fensters. Damit ist die Erstellung des Fensters abgeschlossen und der Manager
schiebt es in den Vordergrund.

\subsubsection{Synchronisation und Tastendruck}

Ajax hat ein so genanntes {\glqq}Polling Problem{\grqq}. Dieses Problem liegt darin, dass
der Server dem Client keine Anfragen senden kann. Jegliche Anfragen können nur
vom Client ausgehen\footnote{Auch bei Ajax handelt es sich nur um das
HTT-Protokoll, welches ein zustandsloses Protokoll ist und nicht für
Anwendungen, bei denen der Server dem Client eigenständig Daten senden kann,
vorgesehen ist.}. Dadurch muss der Client immer wieder beim Server anfragen, ob
neue Informationen vorliegen\footnote{S.g. polling}. Das ist für einen Window
Manager bzw. einen Terminal Emulator ein Problem, da das Terminal in
Wirklichkeit auf dem Server läuft und der Client nicht nur bei einer Änderung
des serverseitigen Terminals aktualisiert werden kann, sondern immer wieder
eine Anfrage an den Server senden muss, welche mit dem Inhalt des Terminals
beantwortet wird, und danach überprüfen muss, ob sich der Inhalt geändert hat.
AjaxWM löst dies im Stil von Ajaxterm: Auf eine Synchronisationsanfrage des
Clients antwortet der Server entweder mit dem Terminalinhalt oder mit
<idem></idem> wenn sich nichts geändert hat. Dies führt dazu, dass im Falle
eines gleichbleibenden Inhaltes einerseits die Übertragung schneller
abgeschlossen ist, andererseits der Client nur bei geändertem Inhalt ein
Fenster aktualisieren muss. Diese Anfrage wird in einem bestimmten
Zeitintervall gesendet, dass sich dynamisch daran anpasst, ob sich der Inhalt
verändert oder nicht. AjaxWM geht aber weiter als Ajaxterm. Bei ajaxWM gibt es
nicht nur ein einziges zentrales Terminal-Objekt, das selbst die Serveranfragen
sendet, sondern einen Window Manager der eine große Anzahl an Terminals
unterstützt. Jedes Terminal ist eigenhändig für seinen Inhalt zuständig und
regelt seine dynamischen Aktualisierungen. Ist der Zeitpunkt einer
Aktualisierung gekommen, wird der Manager aufgerufen, der ein
Synchronisationsevent sendet. Die Antwort des Events wird dem Fenster-Objekt
übergeben. Das Fenster-Objekt überprüft daraufhin, ob sich der Inhalt geändert
hat oder nicht. Bei geändertem Inhalt wird das Fenster aktualisiert und die
Dauer bis zur nächsten Aktualisierung auf das Minimum gesetzt. Hat sich der
Inhalt nicht geändert, wird die Dauer bis zur nächsten Aktualisierung erhöht,
vorrausgesetzt sie hat ein bestimmtes Maxmimum noch nicht überschritten. Ein
Tastendruck läuft ähnlich ab wie die Synchronisation: Der Manager überprüft, ob
die gedrückte Taste kein Hotkey ist und sendet dann dem Server dann ein
Keypress-Event, dass die ID des betroffenen Fensters und das Zeichen
(UTF-8-kodiert) enthält. Dieses Event wird mit dem Terminalinhalt, nachdem das
Zeichen eingegeben wurde, beantwortet. Ab hier läuft es wieder wie bei einer
Synchronisation ab: Der Manager übergibt dem jeweiligen Fenster-Objekt den
Terminalinhalt und das Fenster stellt ihn dar. Dadurch wird bei jedem
Tastendruck, bei dem sich der Inhalt des Terminals ändert, die Dauer bis zur
nächsten Aktualisierung auf das Minimum gesetzt und mögliche weitere
Auswirkungen des Tastendrucks werden innerhalb eines kurzen Intervalles
gepollt. So können Prozessorzeit und Bandbreite bei inaktiven Terminals gespart
und für aktivere Terminals verwendet werden.

\subsubsection{Fenster verschieben und vergrößern}

AjaxWM ist ein Window Manager, der sich in der Handhabung wenig von anderen
Window Managern unterscheidet\footnote{Window Manager haben meist keinen
Taskpanel o.ä., diese Aufgaben erledigen seperate Programme. AjaxWM wird dies
jedoch noch hinzugefügt bekommen. Tiling wird auch noch implementiert.}.
Fenster lassen sich durch klicken und ziehen an der Titelleiste verschieben,
vergrößern oder verkleinern geht durch klicken und ziehen an den
Fensterrahmen\footnote{Da der Standardtheme lim keine Fensterrahmen besitzt -
und auch niemals besitzen wird - ist auch keine Vergrößerung des Fensters
möglich. Daher ist der Vergrößerungsmodus nicht ausführlich getestet und
funktioniert möglicherweise noch nicht.}. Wenn das Fenster verschoben oder
seine Größe verändert wird, wirkt sich jede Änderung sofort auf das Fenster
aus\footnote{Eine Alternative wäre, das echte Fenster unberührt zu lassen, nur
eine Vorschau zu verschieben oder ihre Größe ändern und danach die Größe der
Alternative auf die der Vorschau anzupassen. Wird möglicherweise auch noch
hinzugefügt, aber nicht in der nächsten Zeit.}. Elemente, die beim Verschieben
bzw. beim Vergrößern ihr Aussehen ändern sollen, werden so lange anders
dargestellt, wie das Fenster verschoben oder vergrößert wird. Fenster können
durch jedes Element vergrößert oder verschoben
werden\footnote{onmousedown=``move'' bzw. onmousedown=``resize'' in der Theme-XML
bei jedem Element, das das verschieben oder vergrößern soll.}. Beim gedrückt
halten der Maustaste auf ein solches Element betritt das Fenster den
Verschiebe- bzw. Vergrößerungsmodus, welche Event-Handler aufsetzen, die
ausgeführt werden, wenn der Benutzer die Maustaste loslässt oder die Maus
bewegt. Es wird der Stylesheet-Klassenname eines jeden Elementes, welches beim
Verschieben oder Vergrößern seine Klasse ändern soll\footnote{move=``change''
bzw. reszie=``change'' in ihren XML-Tags in der XML-Datei des Themes.},
geändert\footnote{An den Stylesheet-Klassennamen wird ein \_moving respektive
\_resizing angehängt. Das Aussehen beim Verschieben oder Vergrößern kann so
einfach per CSS definiert werden.}. Beim Bewegen der Maus wird je nach Modus
das Fenster verschoben oder seine Größe geändert. Beim Loslassen werden die
Event-Handler und die Stylesheet-Klassennamen zurückgesetzt und dadurch der
jeweilige Modus verlassen.

\subsubsection{Fenster schließen}

Fenster können entweder durch Klicken auf eine
{\glqq}Schließen{\grqq}-Schaltfläche\footnote{Lim hat keine Schaltflächen und wird auch
keine bekommen. Daher ist noch keine Funktionsweise für Schaltflächen
implementiert.} oder durch das Drücken von STRG+ALT+C geschlossen werden. Wenn
ein Fenster geschlossen werden soll, bereitet es sich erst auf das Schließen
vor\footnote{Derzeit wird nur ein Flag gesetzt, das weitere Synchronisationen
verhindert.} und weist den Manager an, dieses Fenster zu schließen. Der Manager
sendet dem Server die Anfrage, das ausgewählte Fenster serverseitig zu
schließen. Meldet der Server Erfolg, schließt der Manager das Fenster und
zerstört dann das zugehörige Objekt\footnote{Derzeit ist noch keine
Fehlerbehandlung eingebaut, die einen serverseitigen Fehlschlag beim Schließen
behandeln könnte.}. Der Fokus wird dem vorherigen Fenster
übergeben.

