Autor Thema: App-/GUI-Server  (Gelesen 25086 mal)

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #60 am: 09. January 2011, 10:20 »
Ich muss nochmal ein paar Sachen nachfragen  :-D

Also nochmal zu den Buffern. Sagen wir mal ich habe keinen VESA Treiber sondern einen "richtigen" Treiber. Schreiben da dann die Programme normalerweise direkt in den Graka-RAM (direkt in den Buffer des Frames) oder schreiben sie direkt in den Graka-RAM (direkt in den Buffer ihres Windows) oder schreiben sie in einen Buffer im normalen RAM und dann holt sich der Graka-Treiber die Daten aus den Buffern bzw. der GUI-Server schickt die Daten aus den Buffern an den Graka-Treiber?

Dann mal zur direkten Implementation.

Ich möchte es jetzt so machen, das der GUI-Server die "Dekoration" (Titelleise + Rahmen eines Fensters) übernimmt und die Anwendung direkt im Fenster alles selber machen muss.
Jedes Ereignis welches innerhalb des Fensters (also der Bereich den die Anwendung bearbeitet) passier (z.B. Maus-Klick, Tastatur-Eingabe, Maus-Bewegung usw.) wird als Nachricht an das Fenster geschickt, aber nicht mit den globalen Koordinaten, sondern mit den Fenster-lokalen Koordinaten. Ist das soweit in Ordnung oder wird es damit Probleme geben (Performance und andere)?

Ich möchte dann ein paar Standard-Bibliotheken schreiben (z.B. wären das bei Haiku die Kits) mit denen es ziemlich einfach werden sollte eine GUI zu schreiben, das ganze in C++, weil sich Objektiorientierung ja praktisch anbietet.
Das Fenster hat eine "Liste" (ich denke man sollte das nicht wortwörtlich nehmen, ansonsten könnte das sehr langsam werden) mit allen Objekten im Fenster (z.B. Buttons, Labels und was es nicht noch alles gibt). Diese "Liste" wird durchgegangen und geschaut, welche Objekte die Nachricht/das Event betrifft.
Von diesen Objekten wird dann jeweils eine "processMsg(msg_t msg)" aufgerufen und bei diesen Objekten kann es dann wieder passieren das diese auch wieder mehrere unter Objekte haben und das selbe durchführen müssen.

Was ist davon zu halten? Zu langsam, zu umständlich?

Was ich auf keinen Fall möchte, ist alles als Fenster betrachten und auch so beim GUI-Server zu registrieren. Denn das würde die ganze komplexität auf den GUI-Server übertragen und das will ich nicht, auch macht es bestimmte Anwendungen schwieriger (ich denke da an Tabs, wo man dann ja bei einem Tab-wechsel alles "Fenster" aus dem alten Tab "löschen" müsste und alle "Fenster" von dem neuem Tab registrieren müsste).

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #61 am: 09. January 2011, 10:42 »
Was ich auf keinen Fall möchte, ist alles als Fenster betrachten und auch so beim GUI-Server zu registrieren. Denn das würde die ganze komplexität auf den GUI-Server übertragen und das will ich nicht, auch macht es bestimmte Anwendungen schwieriger (ich denke da an Tabs, wo man dann ja bei einem Tab-wechsel alles "Fenster" aus dem alten Tab "löschen" müsste und alle "Fenster" von dem neuem Tab registrieren müsste).
Nein, das Fenster des einen Tabs würde in den Hintergrund kommen und dafür das des neuen Tabs in der Vordergrund. Kein Anlass, irgendwas zu löschen oder neu anzulegen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #62 am: 09. January 2011, 10:53 »
Zitat von: taljeth
Nein, das Fenster des einen Tabs würde in den Hintergrund kommen und dafür das des neuen Tabs in der Vordergrund. Kein Anlass, irgendwas zu löschen oder neu anzulegen.
Auch eine Möglichkeit, aber ich will das ja eh nicht so machen ;)
« Letzte Änderung: 09. January 2011, 11:18 von FlashBurn »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #63 am: 09. January 2011, 11:03 »
Naja, ob auf Server- oder auf Clientseite, irgendwo musst du es machen. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #64 am: 09. January 2011, 11:18 »
Zitat von: taljeth
Naja, ob auf Server- oder auf Clientseite, irgendwo musst du es machen.
Lieber auf Clientseite, weil das lässt sich leichter parallelisieren. Denn es ist einfacher gleichzeitig auf mehreren Listen zu arbeiten als gleichzeitig auf einer.

Zumal ich noch andere Gründe habe, warum ich das auf Clientseite haben will (Systemressourcen).

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #65 am: 09. January 2011, 16:34 »
Schreiben da dann die Programme normalerweise direkt in den Graka-RAM (direkt in den Buffer des Frames) oder schreiben sie direkt in den Graka-RAM (direkt in den Buffer ihres Windows) oder schreiben sie in einen Buffer im normalen RAM und dann holt sich der Graka-Treiber die Daten aus den Buffern bzw. der GUI-Server schickt die Daten aus den Buffern an den Graka-Treiber?
Grundsätzlich ein konkretes Implementierungsdetail. ;-) Fenster sollte  allerdings nicht in den Gesamtbildschirm rendern, denn wenn sie im Hintergrund sind (z.B. fürs Vorschaufenster), werden sie ja nicht dargestellt. Das setzt natürlich insgesamt genug Speicher voraus.
Sie rendern also in einen Window-Buffer, der im Grafikspeicher liegen kann (Bedingung für 3D), aber der auch im System-RAM liegen kann (wenn nicht genug Grafikspeicher vorhanden ist, z.B. alte 2D-Grafikkarte; oder für Netzwerktransparenz).

Jedes Ereignis welches innerhalb des Fensters (also der Bereich den die Anwendung bearbeitet) passier (z.B. Maus-Klick, Tastatur-Eingabe, Maus-Bewegung usw.) wird als Nachricht an das Fenster geschickt, aber nicht mit den globalen Koordinaten, sondern mit den Fenster-lokalen Koordinaten. Ist das soweit in Ordnung oder wird es damit Probleme geben (Performance und andere)?
Klingt vernünftig. Beachte, dass du systemweite Shortcuts auch definieren können solltest. Außerdem sinnvoll wäre, dass du vom Fenster eine Rückmeldung bekommst, ob das Ereignis auch verarbeitet werden konnte (bzw. Fenster müssen Ereignisse zum Empfang anmelden).

Grund: Wenn du als Hauptprogramm ein kleines Unterfenster erzeugst, dann möchtest du nicht einen vollständigen Event-Handler da reinbauen, sondern dich nebenbei auch darum kümmern können. Das heißt, dein GUI-Server leitet das an das Fenster weiter, welches das Ereignis möchte. Will es das nicht, geht das Ereignis an das nächsthöhere Fenster, bis du schlussendlich beim Root-Fenster ankommst. Beispiel: Widgets reagieren nicht auf Rechtsklick, da soll dann das System-Kontextmenü kommen. Oder so ähnlich.

Dazu müssen Ereignisse immer auch eine Window-ID haben zu dem Fenster, auf das sie sich beziehen.

Ich möchte dann ein paar Standard-Bibliotheken schreiben (z.B. wären das bei Haiku die Kits) mit denen es ziemlich einfach werden sollte eine GUI zu schreiben, das ganze in C++, weil sich Objektiorientierung ja praktisch anbietet.
Klingt gut.

Das Fenster hat eine "Liste" (ich denke man sollte das nicht wortwörtlich nehmen, ansonsten könnte das sehr langsam werden) mit allen Objekten im Fenster (z.B. Buttons, Labels und was es nicht noch alles gibt). Diese "Liste" wird durchgegangen und geschaut, welche Objekte die Nachricht/das Event betrifft.
Ich denke, das sollte der Anwendung überlassen werden, wie sie darauf reagiert. Grundsätzlich klingt das gut.

Von diesen Objekten wird dann jeweils eine "processMsg(msg_t msg)" aufgerufen und bei diesen Objekten kann es dann wieder passieren das diese auch wieder mehrere unter Objekte haben und das selbe durchführen müssen.
Ja, ist machbar. Manche Steuerelemente haben halt einen Zustandsautomaten (du nanntest Tab-Container) und stellen selbst wieder Fenster dar.

Was ich auf keinen Fall möchte, ist alles als Fenster betrachten und auch so beim GUI-Server zu registrieren. Denn das würde die ganze komplexität auf den GUI-Server übertragen und das will ich nicht, auch macht es bestimmte Anwendungen schwieriger (ich denke da an Tabs, wo man dann ja bei einem Tab-wechsel alles "Fenster" aus dem alten Tab "löschen" müsste und alle "Fenster" von dem neuem Tab registrieren müsste).
Warum nicht?
Dein Tab-Container erstellt für jeden Tab ein "Fenster ohne Dekoration" und macht die halt sichtbar/unsichtbar oder verschiebt sie in seinem lokalen Z-Puffer in den Vorder-/Hintergrund. Das liegt schon nahe.

Außerdem könntest du dann wieder GUI-Server-zentral die Daten cachen, sofern du den Speicher übrig hast. Das ist bei GUI-via-Netzwerk wieder von Vorteil, da du auch Dinge, die nicht dargestellt werden, zwischenspeichern kannst (im Gegensatz zu z.B. VNC). Bei einem lokalen GUI-Server musst du das nicht durchführen, aber ein GUI-Server-Port für X11 könnte/sollte da schon aggressiv cachen. ;-)

Gruß,
Svenska

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #66 am: 09. January 2011, 17:08 »
Um nochmal auf die Buffer zu kommen. Die beiden Varianten Buffer (des Fensters) im Graka oder normalen RAM sind mir klar, aber gibt es auch GUIs die direkt in den Frame-Buffer (damit meine ich direkt den Buffer den die Graka dann als nächsten Frame darstellt) schreiben? Weil ich da dann halt das Problem sehe, das dieser Buffer nicht zusammenhängend sein kann. Dafür gibt es mehrere Gründe z.B. dass das Fenster nicht den ganzen Bildschirm einnimmt oder der Offscreen-Speicher (sprich eine Zeile nimmt mehr Speicher ein als sie eigentlich müsste).

Zitat von: svenska
Beachte, dass du systemweite Shortcuts auch definieren können solltest.
Was genau meinst du damit? Meinst du damit sowas wie STRG+ALT+ENTF, das dann der Taskmanager aufgerufen wird oder das die Windows-Taste das Startmenü öffnet?

Solche Events würde ich gar nicht erst an ein Fenster weitersenden (oder doch?).

Zitat von: svenska
Außerdem sinnvoll wäre, dass du vom Fenster eine Rückmeldung bekommst, ob das Ereignis auch verarbeitet werden konnte (bzw. Fenster müssen Ereignisse zum Empfang anmelden).
Meinst du sowas wie eine Empfangsbestätigung? Wenn ja, das würde den IPC-Overhead ganz schön in die Höhe treiben und man müsste dann festlegen was eine angemessene Zeitspanne (für alle Systeme!) ist um eine Bestätigung zu bekommen.

Welchen Vorteil siehst du darin, wenn Fenster Ereignisse erst zum Empfang anmelden müssen (du meinst ja sicherlich, das sie nur Events bekommen, die sie auch bekommen wollen?)?

Spontan sehe ich nur den Vorteil, das ein wenig IPC wegfällt.

Zitat von: svenska
Wenn du als Hauptprogramm ein kleines Unterfenster erzeugst, dann möchtest du nicht einen vollständigen Event-Handler da reinbauen, sondern dich nebenbei auch darum kümmern können. Das heißt, dein GUI-Server leitet das an das Fenster weiter, welches das Ereignis möchte. Will es das nicht, geht das Ereignis an das nächsthöhere Fenster, bis du schlussendlich beim Root-Fenster ankommst. Beispiel: Widgets reagieren nicht auf Rechtsklick, da soll dann das System-Kontextmenü kommen. Oder so ähnlich.
Also erstmal gutes Bsp. mit den Unterfenstern, daran habe ich noch gar nicht gedacht :( Meine momentane Planung sieht es vor dass das alles vom Clienten gemacht werden muss (warum auch nicht, passiert ja schließlich innerhalb seines Fensters), aber da sehe ich dann jetzt spontan Probleme mit der Konsistenz des Designs.
Wenn ich sowas aber zulassen würde, öffnet das dem Prinzip "alles ist ein Fenster" wieder die Türen und das wollte ich eigentlich vermeiden.

Zitat von: svenska
Ich denke, das sollte der Anwendung überlassen werden, wie sie darauf reagiert. Grundsätzlich klingt das gut.
Ich bin mir nicht sicher ob ich verstanden habe was du meinst, aber ich meinte damit das meine Standard-Bibliotheken das so handhaben sollen. Dem Programmierer steht es frei komplett alles von Hand zu schreiben, aber meine Bibliotheken werden es dann so machen.

Zitat von: svenska
Manche Steuerelemente haben halt einen Zustandsautomaten (du nanntest Tab-Container) und stellen selbst wieder Fenster dar.
Naja, so sehe ich das halt (noch) nicht. Bei mir gibt es per Anwendung nur ein Fenster alles was da drin ist, sind Objekte und interessieren den GUI-Server nicht mehr.

Zitat von: svenska
Warum nicht?
Mein momentanes Problem mit "alles ist ein Fenster" ist, das jedes Fenster einen IPC-Port hat, wo dann Events hingeschickt werden und unter Umständen können das miteinmal verdammt viele Ports werden (was auch Kernel-Speicher kostet, den ich eigentlich nicht auslagern können will) und ich brauche für viele andere Dinge auch noch Ports und wenn ich mir da z.B. so ne Webpage angucke, wo man dann ja auch sagen könnte, ok jeder Button ist ein Fenster, dann jede TextArea usw. Da kommt man schnell auf verdammt viele Ports (vorallem wenn man dann viele Tabs offen hat) und da ich ja meine Ports auch noch beschränke (128k) könnte das problematisch werden.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #67 am: 09. January 2011, 21:08 »
Die beiden Varianten Buffer (des Fensters) im Graka oder normalen RAM sind mir klar, aber gibt es auch GUIs die direkt in den Frame-Buffer (damit meine ich direkt den Buffer den die Graka dann als nächsten Frame darstellt) schreiben?
Ja, siehe DirectFB oder das, was Windows CE macht.

Weil ich da dann halt das Problem sehe, das dieser Buffer nicht zusammenhängend sein kann. Dafür gibt es mehrere Gründe z.B. dass das Fenster nicht den ganzen Bildschirm einnimmt oder der Offscreen-Speicher (sprich eine Zeile nimmt mehr Speicher ein als sie eigentlich müsste).
Richtig. Bei DirectFB/WinCE geht es auch eher um Vollbildanwendungen. Die wichtigen Parameter dafür sind Auflösung (Zahl der Pixel), Farbtiefe (Bit pro Pixel), Zeilen- und Spaltenpitch (Abstand in Bytes von Zeile zu Zeile bzw. Spalte zu Spalte).

Zitat von: svenska
Beachte, dass du systemweite Shortcuts auch definieren können solltest.
Was genau meinst du damit? Meinst du damit sowas wie STRG+ALT+ENTF, das dann der Taskmanager aufgerufen wird oder das die Windows-Taste das Startmenü öffnet?

Solche Events würde ich gar nicht erst an ein Fenster weitersenden (oder doch?).
Genau. Also hast du eine zentrale Instanz in deinem GUI-Server (oder im clientseitigen Root-Window, je nachdem, was du eher magst), wo Events erstmal gefiltert werden, ehe sie dann unter Umständen an Fenster weitergeleitet werden.

Welchen Vorteil siehst du darin, wenn Fenster Ereignisse erst zum Empfang anmelden müssen (du meinst ja sicherlich, das sie nur Events bekommen, die sie auch bekommen wollen?)?
Wenn ich ein kleines Dialogfenster erzeuge, z.B. ein Fenster zur Dateiauswahl, dann möchte ich keinen vollwertigen Eventhandler für dieses Fenster implementieren, sondern ich habe im Hauptprogramm bereits einen, der das mit erledigen kann. Das spart Code und Aufwand in den Anwendungen.

Zweitens kannst du beim Anmelden von Events ja auch mitgeben, dass du für die Maus z.B. absolute Koordinaten möchtest (Standardfall) oder eben relative Events (für Vollbildspiele wichtig). Oder, dass du eine anwendungsseitige Tastaturbelegung haben möchtest und darum die Tastaturevents in "roh" haben möchtest (Bildschirmtastatur für fremde Sprachen).

Viele dieser Flags sind im Normalfall uninteressant, aber für Spiele sehr wichtig.

Wenn ich sowas aber zulassen würde, öffnet das dem Prinzip "alles ist ein Fenster" wieder die Türen und das wollte ich eigentlich vermeiden.
Naja, dieses Prinzip ist für manche Anwendungsfälle aber schon sehr praktisch, darum solltest du es nicht grundsätzlich verbieten.

Und der GUI-Server ist ja eigentlich der Fensterverwalter des Grafiksystems, also sollte er wenigstens das effizient können.

Naja, so sehe ich das halt (noch) nicht. Bei mir gibt es per Anwendung nur ein Fenster alles was da drin ist, sind Objekte und interessieren den GUI-Server nicht mehr.
Was machst du mit GIMP? ;-)

Mein momentanes Problem mit "alles ist ein Fenster" ist, das jedes Fenster einen IPC-Port hat, wo dann Events hingeschickt werden
Aua. Wie wäre es mit einem IPC-Port pro Anwendung, den sie zugeteilt kriegt, wenn sie das erste Fenster erzeugen möchte?

Gruß,
Svenska

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #68 am: 09. January 2011, 22:07 »
Zitat von: svenska
Genau. Also hast du eine zentrale Instanz in deinem GUI-Server (oder im clientseitigen Root-Window, je nachdem, was du eher magst), wo Events erstmal gefiltert werden, ehe sie dann unter Umständen an Fenster weitergeleitet werden.
Naja, dafür ist doch, unter anderem, der GUI-Server da ;)

Zitat von: svenska
Wenn ich ein kleines Dialogfenster erzeuge, z.B. ein Fenster zur Dateiauswahl, dann möchte ich keinen vollwertigen Eventhandler für dieses Fenster implementieren, sondern ich habe im Hauptprogramm bereits einen, der das mit erledigen kann. Das spart Code und Aufwand in den Anwendungen.
Genau dafür ist doch meine Standard-Bibliothek da. Die stellt den ganzen Code bereit und du überlagerst nur den Code/Methoden die du anders haben willst.
So bleibt der Code für jedes Fenster (so lange es sich am Standard orientiert) gleich und ist auch (theoretisch) nur einmal im Speicher, da es ja eine Shared-Library ist.

An was für Events denkst du da eigentlich wenn es welche sein sollen, die auch das Hauptprogramm bearbeiten kann?

Zitat von: svenska
Zweitens kannst du beim Anmelden von Events ja auch mitgeben, dass du für die Maus z.B. absolute Koordinaten möchtest (Standardfall) oder eben relative Events (für Vollbildspiele wichtig). Oder, dass du eine anwendungsseitige Tastaturbelegung haben möchtest und darum die Tastaturevents in "roh" haben möchtest (Bildschirmtastatur für fremde Sprachen).
Ok, sowas könnte man so lösen, das man Events zwar nicht anmelden kann, aber das man bestimmen kann was für Daten die Events enthalten (z.B. relative oder absolute Maus-Koordinaten). Denn ich wüsste auch nicht wo das Problem liegt das man ein Event bekommt, das gerade ein rechts-Klick gemacht wurde und man das nicht wissen will. Dann wird die Nachricht halt einfach verworfen (gut man könnte IPC sparen).

Zitat von: svenska
Was machst du mit GIMP?
Ok, aber das würde sich nicht mit meinem Konzept beißen. Ich hätte mich besser ausdrücken sollen, was ich im Moment noch nicht sehe das es der GUI-Server macht, ist es sowas wie Unter-Fenster (also Fenster die nur innerhalb eines anderen Fensters sind und dieses auch nicht verlassen können) durch den GUI-Server verwalten zu lassen.
Das eigentliche Problem sind halt die Ports, ok ich könnte deren Anzahl erhöhen, aber so ist der GUI-Server einfacher, weil er sich nicht darum kümmern muss ob ein Fenster auch außerhalb eines anderen Fensters darstellbar ist.

Zitat von: svenska
Aua. Wie wäre es mit einem IPC-Port pro Anwendung, den sie zugeteilt kriegt, wenn sie das erste Fenster erzeugen möchte?
Einen pro Anwendung halte ich für zu wenig. Mein Ziel ist es durch meine Standard-Bibliothek den GUI-Code automatisch zu "threaden" (Multithreading) und da macht ein Port pro Fenster einfach mehr Sinn. Das würde dann halt alles in meiner Window-Klasse gemacht werden.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #69 am: 09. January 2011, 22:49 »
An was für Events denkst du da eigentlich wenn es welche sein sollen, die auch das Hauptprogramm bearbeiten kann?
WindowSizeChange, Redraw, KeyPress, LostFocus, GotFocus, ...

Denn ich wüsste auch nicht wo das Problem liegt das man ein Event bekommt, das gerade ein rechts-Klick gemacht wurde und man das nicht wissen will. Dann wird die Nachricht halt einfach verworfen (gut man könnte IPC sparen).
Richtig; bei X11 liegt das daran, dass das IPC mit sehr hoher Latenz verbunden sein kann (Netzwerk).

Einen pro Anwendung halte ich für zu wenig. Mein Ziel ist es durch meine Standard-Bibliothek den GUI-Code automatisch zu "threaden" (Multithreading) und da macht ein Port pro Fenster einfach mehr Sinn. Das würde dann halt alles in meiner Window-Klasse gemacht werden.
Hmm, Geschmackssache. Achte nur darauf, dass du dich nicht zu sehr limitierst.

Gruß

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #70 am: 10. January 2011, 11:15 »
Zitat von: svenska
WindowSizeChange, Redraw, KeyPress, LostFocus, GotFocus, ...
Ok, aber du musst doch die Events auch für nen Öffnen-Dialog implementieren, da doch dort was ganz anderes passieren kann, wenn eine Taste gedrückt wurde.
Hinzu kommt noch, das der Code ja im Endeffekt der gleiche ist, wie gesagt, was man nicht implementiert da wird dann der Standard-Code ausgeführt und der ist eh immer vorhanden. Du hast ja nur ein Objekt und die Variablen haben andere Werte aber der Code der Methoden ist der gleiche (z.B. bei einem Redraw).

Am Bsp. von KeyPress, ich würde dieses Event sogar gar nicht implementieren bzw. dies den Clienten machen lassen. Bei mir würde es dann nur ein Event KeyDown und KeyUp geben und wenn der Client will kann er sich selbst ein Event KeyPress schicken (ohne das IPC dazu genutzt wird), wenn das KeyUp für eine Taste kommt, wo vorher ein KeyDown kam.

Zitat von: svenska
Hmm, Geschmackssache. Achte nur darauf, dass du dich nicht zu sehr limitierst.
Wo limitiere ich mich denn? Meinst du das ich eventuell nicht genügend Ports habe? Dagegen habe ich etwas geplant (eine Idee von erik), so dass weniger Sachen einen Port voraussetzen.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #71 am: 10. January 2011, 13:20 »
Ok, aber du musst doch die Events auch für nen Öffnen-Dialog implementieren, da doch dort was ganz anderes passieren kann, wenn eine Taste gedrückt wurde.
Du schreibst richtig: kann, nicht muss.

 

Einloggen