====== Vega – Fensterverwaltungssystem ======
Vega ist der Compositor und Window Manager von Lyx OS. Er läuft als privilegierter Ring-3-Prozess und übernimmt alle Aufgaben, die klassisch einem Display-Server zufallen: GOP-Framebuffer beanspruchen, Fenster verwalten, Eingaben (Maus, Tastatur) verarbeiten und jeden Frame kompositionieren.
Lyx OS hat **keinen Display-Server** und kein Socket-Protokoll (kein X11, kein Wayland). Der Kernel stellt den Framebuffer und die Fenstertabelle direkt bereit; Vega liest sie ohne Umweg über IPC.
→ [[lyxos:start|Übersicht]] · [[lyxos:kernel|Kernel-Interna]] · [[lyxos:syscalls|Syscall-ABI]]
----
===== 1. Architektur =====
vega/
├── vega.lyx ← Compositor: Frame-Loop, Fensterzustand, Drag-Logik
└── bsys_vega.lyx ← Bridge-Unit: Syscall-Wrapper, Display-Backend,
VGA-Font, Fenster-Dekoration, Maus-Cursor
''bsys_vega'' muss als erstes Unit importiert werden; ''Init()'' muss vor allen anderen Aufrufen stehen:
import bsys_vega;
fn main(): int64 {
Init(); // r3_sc_block binden + VGA-Font initialisieren
DisplayInit(); // GOP-Framebuffer beanspruchen + Back-Buffer allokieren
SysSetMouseBounds(scrw - 1, scrh - 1);
// ...
}
----
===== 2. Frame-Loop =====
Der Frame-Loop ist der Kern von Vega. Er läuft mit ~100 Hz (PIT-Tick):
while (1 == 1) {
SysVsyncWait(); // auf nächsten PIT-Tick warten (~10 ms)
var mx: int64 := SysGetMouseX();
var my: int64 := SysGetMouseY();
var btn: int64 := SysGetMouseBtn();
handle_drag(mx, my, btn); // Titelleisten-Drag + Z-Order-Änderung
var ch: int64 := KbdPoll(); // non-blocking Tastatureingabe
if (ch != 0) { term_putch(ch); redraw_term_fb(); }
composite_frame(mx, my); // Desktop + Fenster + Cursor rendern
DisplayFlip(); // Back-Buffer → GOP-Framebuffer schreiben
}
----
===== 3. Display-Backend =====
Das Display-Backend abstrahiert den Bildspeicher über einen Double-Buffering-Ansatz: Alle Zeichenoperationen gehen in den **Back-Buffer** (RAM); ''DisplayFlip()'' überträgt ihn dann in den sichtbaren Bildspeicher. Der ist seit 2026-08 nicht mehr zwingend der vom UEFI geerbte GOP-Puffer — Lyx OS übernimmt den Bildschirm nach Möglichkeit selbst (''sys_vbe_takeover'', siehe unten) und fällt nur auf GOP zurück, wenn das scheitert.
==== Initialisierung ====
var ok: int64 := DisplayInit(); // 1 = Erfolg, 0 = kein GOP-Framebuffer
var w: int64 := DisplayGetWidth();
var h: int64 := DisplayGetHeight();
var s: int64 := DisplayGetStride(); // Bytes pro Zeile (kann > w×4 sein)
==== Zeichenoperationen ====
^ Funktion ^ Beschreibung ^
| ''DisplayFill(color)'' | Back-Buffer vollflächig füllen |
| ''DisplayFillRect(x, y, w, h, color)'' | Rechteck im Back-Buffer füllen |
| ''DisplayBlit(src, src_w, src_h, dst_x, dst_y)'' | Pixel-Buffer in Back-Buffer kopieren |
| ''DisplayFlip()'' | Back-Buffer → GOP-Front-Buffer (8-Byte-Chunks, stride-aware) |
==== Farbformat ====
Alle Farben sind 32-Bit **BGRA** (Byte-Reihenfolge im Speicher: B, G, R, A):
con DESK_BG: int64 := 0xFF1A1A2E; // deep navy (Desktop-Hintergrund)
con WIN_BG_TERM: int64 := 0xFF0D1117; // Terminalfenster-Hintergrund
con WIN_FG: int64 := 0xFFCDD6F4; // primärer Text (helles Lavendel)
''DisplayFlip()'' optimiert den Transfer: bei stride = w×4 werden alle Pixel als 8-Byte-Chunks (''poke64'') übertragen, was die MMIO-Transaktionen halbiert im Vergleich zu 4-Byte-Writes.
==== Bildschirm übernehmen statt erben (Bochs-VBE) ====
Bis 2026-08 hing der Compositor an dem Framebuffer, den die Firmware hinterlassen hatte: Adresse, Maße und Zeilenschrittweite kamen aus dem UEFI-GOP, der Bochs-VBE-Treiber war reiner Beobachter. Seit ''sys_vbe_takeover'' setzt Lyx OS den Modus selbst.
^ Schritt ^ Was passiert ^
| Eigener Modus | ''sys_vbe_takeover(w, h, bpp)'' (nr 106) setzt über Bochs-VBE **genau die Maße des Firmware-Modus**. Bewusst keine anderen: ein falscher Modus wäre ein schwarzer Schirm, und der Weg zurück über die Firmware steht dann nicht mehr offen |
| Bildspeicher aus BAR0 | Der Syscall bildet beide Bildhälften (virtuelle Höhe 2×h) in den Adressraum des Aufrufers ab und liefert die Adresse. ''DisplayInit()'' nimmt sie statt der aus ''sys_fb_map'' |
| Seitenwechsel | ''sys_vbe_flip(y)'' (nr 107) setzt den sichtbaren Bereich — ein Registerschreibzugriff statt einer Vollkopie. **Vollkopien** schreiben in die unsichtbare Hälfte und wechseln erst danach; der Betrachter sieht nie ein halb fertiges Bild. **Teilkopien** (Cursor, Damage) gehen weiter in die sichtbare Hälfte, denn sie ergänzen ein bestehendes Bild |
* **EFI bleibt Rückfall.** Scheitert ein Schritt — kein VBE, kein Bildspeicher in BAR0, kein Platz für zwei Bilder —, liefert der Syscall ''-1'' und der GOP-Weg bleibt unverändert in Kraft. ''VBE_UEBERNEHMEN'' in ''vega/bsys_vega.lyx'' schaltet den Versuch mit einer Zeile ganz ab.
* **Der Rückpuffer bleibt im Arbeitsspeicher.** Das ist der Unterschied zum zurückgenommenen Versuch mit direktem Zeichnen (V0.0.2AT): dort lag er im Bildspeicher, und ''DisplayCursorSave'' **las** 560 Punkte je Bild daraus — in VirtualBox je ein Austritt aus dem Gastmodus, ''comp'' stieg auf 115 ms und das Bild flackerte.
* **Der Kernel schweigt danach.** Mit der Übernahme stellt der Kernel seine eigene Bildschirmausgabe ein, sonst stünde Text mitten im Desktop. Die Übernahme meldet er einmal, mit Adresse und virtueller Höhe — ein übernommener Bildschirm sieht sonst genauso aus wie ein geerbter: ''gpu Bildschirm uebernommen: 1920x1080 Bildspeicher 0x80000000 virtuelle Hoehe 2184''.
=== Was es bringt (gemessen, QEMU) ===
Bildschirmfotos der Statuszeile konnten die Frage nicht beantworten — die Streuung zwischen zwei Stichproben desselben Baus war größer als der Unterschied. Deshalb schreibt der Kernel die Verteilung selbst: ''FT_REPORT_EVERY'' in ''kernel/frametl.lyx'' lässt ''FrameTlSubmit'' alle N Bilder eine Zeile auf COM1 legen (Mittel, p50, p90, längstes Bild, verpasste Fristen; p50/p90 aus den letzten 128 Bildern). Last über QMP, feste Bahn, ohne Tastatureingabe, je drei Läufe:
* **~6 % kürzere Bilddauer** und **8 % weniger verpasste Fristen** gegenüber dem EFI-Weg; die Wertebereiche der Läufe überschneiden sich nicht.
* Wichtiger als der Gewinn ist die **Streuung**: VBE schwankt über drei Läufe um 6 %, EFI um 21 %.
* p50 ist mit ~8 ms praktisch gleich — der Unterschied sitzt in den **langen** Bildern, nicht im Normalfall. Genau dort fällt das Kopieren in den Bildspeicher ins Gewicht.
Gilt für QEMU. VirtualBox lässt sich nicht skripten (kein ''mouseputevent''); dort bleibt es beim Boot-Beleg, dass der neue Treiber die Ausgabe führt. ''FT_REPORT_EVERY'' steht im Dauerbau wieder auf ''0'' — der Bericht kostet Laufzeit.
==== Intel-Grafik: erst lesen, dann schreiben ====
Auf echter Intel-Hardware gibt es kein Bochs-VBE — dort bringt erst ein eigener Intel-Pfad denselben Gewinn. Vor dem Treiber steht aber die Diagnose: ''intel_diag()'' in ''kernel/gpu.lyx'' meldet beim Hochfahren je Pipe die **rohen** Werte ''conf''/''srcsz''/''stride''/''surf'', dazu GGC (zugeteilter Grafikspeicher), den GTT-Schlüssel und die Größe des Sichtfensters. **Kein einziger Schreibzugriff.**
Zwei Fragen hängen daran: Stimmt die Deutung (die ''gpu''-Zeile behauptet „Pipe 0, 1920x1080" — auf einer Maschine, die hier nie lief, ist die rohe Zahl die einzige Tatsache)? Und passt ein zweiter Bildpuffer in den bereits zugeteilten Speicher? Dann geht der Seitenwechsel auf Intel wie in den VMs — nur ''PLANE_SURF'' umschalten, ohne Modeset. Sonst muss die GTT-Arbeit davor, denn ''PLANE_SURF'' erwartet eine GTT-Adresse, keine CPU-physische. Ein falsch gesetztes ''PLANE_SURF'' nimmt auf echter Hardware den Bildschirm — deshalb kein ungeprüfter Schreibzugriff.
----
===== 4. Fenster-API =====
Fenster werden vom Kernel in der **Fenstertabelle** (max. 32 Slots) verwaltet. Vega erzeugt Fenster über Syscalls; der physische Framebuffer jedes Fensters liegt im Kernel-Heap.
==== Fenster anlegen und befüllen ====
// Fenster anlegen (Client-Bereich ohne Titelleiste)
var wid: int64 := SysWinCreate(x, y, w, h, 0); // gibt win_id zurück oder -1
if (wid < 0) { return 1; }
// Framebuffer in den User-Adressraum mappen
var wfb: int64 := SysWinGetFb(wid); // user_virt oder -1
// In den Fenster-FB zeichnen (direkt per poke8/poke64)
FillWinFb(wfb, w, h, 0xFF0D1117); // Hintergrund füllen
DrawChar(wfb, w, 4, 4, 65, 0xFFCDD6F4, 0xFF0D1117); // 'A' bei (4,4)
==== Window-Flags (VEGA_WIN_*) ====
^ Konstante ^ Wert ^ Bedeutung ^
| ''VEGA_WIN_NORMAL'' | 0 | Standard-Fenster mit Dekoration |
| ''VEGA_WIN_BORDERLESS'' | 1 | Kein Rahmen, keine Titelleiste |
| ''VEGA_WIN_FULLSCREEN'' | 2 | Vollbild (übernimmt gesamten Screen) |
| ''VEGA_WIN_RESIZABLE'' | 4 | Fenster kann vom User in der Größe geändert werden |
| ''VEGA_WIN_HIDDEN'' | 8 | Fenster existiert, wird aber nicht gerendert |
Flags können kombiniert werden: ''VEGA_WIN_BORDERLESS | VEGA_WIN_RESIZABLE'' ergibt 5.
==== Fenster-Verwaltung ====
^ Funktion ^ Beschreibung ^
| ''SysWinCreate(x, y, w, h, flags)'' | Neues Fenster; ''flags'' aus ''VEGA_WIN_*''-Konstanten |
| ''SysWinDestroy(win_id)'' | Fenster freigeben |
| ''SysWinRaise(win_id)'' | Z-Order auf max+1 (in Vordergrund) |
| ''SysWinMove(win_id, x, y)'' | Position verschieben |
| ''SysWinResize(win_id, new_w, new_h)'' | Fenstergröße ändern |
| ''SysWinGetFb(win_id)'' | Fenster-FB in User-Space mappen → user_virt |
| ''SysWinGetTablePhys()'' | Physische Adresse der Fenstertabelle (Compositor-Direktzugriff) |
| ''SysWinSetTitle(win_id, title_ptr)'' | Fenster-Titel setzen (WP27, nr=148) |
| ''SysWinFindByIdx(idx)'' | win_id des Slots ''idx'' ermitteln (WP27, nr=149) |
| ''SysWinGetTitle(win_id, buf)'' | Fenster-Titel lesen in ''buf'' (WP27, nr=150) |
| ''SysWinGetGeom(win_id, out_buf)'' | Geometrie lesen: x,y,w,h als 4×int64 in ''out_buf'' (WP29, nr=151) |
| ''SysWinGetPid(win_id)'' | PID des Fenster-Besitzers (WP29, nr=152) |
==== Fenstertabelle direkt lesen (Compositor) ====
Vega liest die Fenstertabelle über ihre physische Adresse ohne Syscall-Overhead:
var tbl: int64 := SysWinGetTablePhys();
var i: int64 := 0;
while (i < 32) {
if (WinState(tbl, i) == 1) {
var x: int64 := WinX(tbl, i);
var y: int64 := WinY(tbl, i);
BlitWindow(WinPhys(tbl, i), WinW(tbl, i), WinH(tbl, i), x, y);
}
i := i + 1;
}
^ Hilfsfunktion ^ Rückgabe ^
| ''WinSlot(tbl, idx)'' | Zeiger auf Slot (tbl + idx×104) |
| ''WinId(tbl, idx)'' | win_id des Slots |
| ''WinState(tbl, idx)'' | 0=frei, 1=aktiv |
| ''WinX/Y/W/H/Z(tbl, idx)'' | Position, Größe, Z-Order |
| ''WinPhys(tbl, idx)'' | Physische Adresse des Fenster-FB |
----
===== 5. Fenster-Dekoration =====
''DrawDecoration()'' zeichnet Titelleiste, Rahmen und Schließen-Knopf in den **Back-Buffer** des Compositors (nicht in den Fenster-FB):
// focused: 1 = aktiv (dunkle Titelleiste), 0 = inaktiv (graue Titelleiste)
DrawDecoration(back_buf, display_width, cx, cy, cw, ch, "Terminal", 1);
^ Konstante ^ Wert ^ Bedeutung ^
| ''DECO_TITLE_H'' | 28 | Titelleistenhöhe in Pixeln |
| ''DECO_BAR_FOCUS'' | 0xFF2D3748 | Aktive Titelleiste (dunkles Schiefer) |
| ''DECO_BAR_UNFOCUS'' | 0xFF718096 | Inaktive Titelleiste (grau) |
| ''DECO_CLOSE'' | 0xFFE53E3E | Schließen-Knopf (rot) |
| ''DECO_BORDER'' | 0xFF4A5568 | Fensterrahmen |
Die Titelleiste sitzt **oberhalb** des Client-Bereichs: ''[cy-28 .. cy)''. Für Drag-Hit-Tests ergibt sich daraus:
fn in_titlebar(mx, my, wx, wy, ww): int64 {
if (mx >= wx && mx < wx + ww && my >= wy - 28 && my < wy) { return 1; }
return 0;
}
----
===== 6. VGA-Font =====
Vega enthält einen eingebetteten VGA-8×16-Font für 96 druckbare ASCII-Zeichen (32–127). Der Font wird zur Laufzeit initialisiert (''vga_font_init()'', aufgerufen von ''Init()''), da lyxc keine verketteten String-Literale als Initialisierungswert unterstützt.
// Einzelnes Zeichen an (px, py) in einen Pixel-Buffer zeichnen
DrawChar(buf, buf_w, px, py, ch, fg_color, bg_color);
// Null-terminierten String zeichnen; gibt x-Position nach letztem Zeichen zurück
var x_end: int64 := DrawString(buf, buf_w, px, py, "Hallo", WIN_FG, WIN_BG_TERM);
Jeder Glyph ist 8×16 Pixel; ''DrawChar'' clippt an der rechten Pufferkante. Zeichen außerhalb des druckbaren Bereichs werden als Leerzeichen (ASCII 32) dargestellt.
''DrawCharToPhys'' und ''DrawStringToPhys'' sind Aliases, die explizit deutlich machen, dass der Buffer-Parameter eine physische Adresse ist.
----
===== 7. Maus-Cursor =====
''DrawCursor()'' zeichnet einen 12×20-Pfeil-Sprite mit einfachem Drop-Shadow in den Back-Buffer — immer als letztes, sodass er über allem anderen liegt:
DrawCursor(back_buf, display_width, display_height, mouse_x, mouse_y);
Der Cursor-Sprite ist als Bitmask in ''bsys_vega.lyx'' eingebettet (''arrow_rows'', 40 Bytes für 20 Zeilen × 12 Bit). Der Drop-Shadow wird als schwarzes Pixel (+1,+1) hinter jedem Vordergrundpixel gesetzt, überschreibt aber keine Cursor-Pixel selbst.
----
===== 8. Eingabe =====
==== PS/2-Maus ====
SysSetMouseBounds(scrw - 1, scrh - 1); // Koordinatengrenzen setzen (einmalig)
var mx: int64 := SysGetMouseX(); // X-Koordinate
var my: int64 := SysGetMouseY(); // Y-Koordinate
var btn: int64 := SysGetMouseBtn(); // Tastenbits: VEGA_MBTN_*
^ Konstante ^ Wert ^ Bedeutung ^
| ''VEGA_MBTN_LEFT'' | 1 | Linke Maustaste |
| ''VEGA_MBTN_RIGHT'' | 2 | Rechte Maustaste |
| ''VEGA_MBTN_MIDDLE'' | 4 | Mitteltaste (Rad-Click) |
if (btn & VEGA_MBTN_LEFT != 0) { /* Linksklick */ }
if (btn & VEGA_MBTN_RIGHT != 0) { /* Rechtsklick */ }
==== Tastatur (non-blocking) ====
var ch: int64 := KbdPoll(); // 0 = kein Zeichen; sonst ASCII-Byte
''KbdPoll()'' liest aus dem PS/2-Ringpuffer ohne zu blockieren (Syscall nr=131). Im Gegensatz zu ''sys_read(stdin)'' (nr=0) wartet er nicht auf Eingabe — geeignet für Frame-Loops.
----
===== 9. Ereignis-Ring =====
Prozesse können sich gegenseitig Ereignisse (Typ + 3 Parameter) über einen kernel-seitigen Ringpuffer senden:
// Ereignis an PID 2 senden
SysEventSend(2, EV_KEY_PRESS, 65, 0, 0);
// Eigenes Postfach prüfen (non-blocking)
var ev_buf: int64 := mmap(0, 32, 3, 34, -1, 0); // 4 × int64
var ok: int64 := SysEventRecv(ev_buf);
if (ok == 0) {
var ev_type: int64 := peek64(ev_buf);
var ev_a: int64 := peek64(ev_buf + 8);
}
Der Ring fasst pro PID 16 Ereignisse (32 Bytes/Ereignis). PIDs ≥ 8 werden ignoriert. Ist der Ring voll, gehen neue Ereignisse verloren (kein Backpressure).
----
===== 10. SHM und Console-Routing =====
var shm_id: int64 := SysShmCreate(4096); // SHM-Region anlegen (shm_id oder -1)
var uva: int64 := SysShmMap(shm_id); // in User-Space mappen
SysShmUnmap(shm_id); // Referenzzähler dekrementieren
// PutCh-Ausgabe von PID 3 in SHM-Ringpuffer umleiten
SysSetConsole(3, shm_id);
// Routing abschalten:
SysSetConsole(3, -1);
----
===== 11. std.lyxos.vega — Standardbibliothek für Ring-3-Anwendungen =====
''std.lyxos.vega'' (''src/std/lyxos/vega.lyx'', LX-WP17) ist die öffentliche Standard-Library-Unit für Ring-3-Anwendungen. Sie bietet benannte Konstanten und ''Vega*''-Wrapper um alle Vega-Syscalls — ohne bsys_vega zu importieren.
import std.lyxos.vega;
import std.alloc;
fn main(): int64 {
// Fenster anlegen
var wid: int64 := VegaWinCreate(100, 100, 640, 480, VEGA_WIN_RESIZABLE);
if (wid == 0) { return 1; }
// Framebuffer mappen
var fb: int64 := VegaWinGetFb(wid);
// Mausgrenzen setzen
VegaSetMouseBounds(1919, 1079);
// Frame-Loop
while (1 == 1) {
VegaVsyncWait();
var mx: int64 := VegaGetMouseX();
var my: int64 := VegaGetMouseY();
var ch: int64 := VegaKbdPoll(); // 0 = kein Zeichen
// Ereignisse empfangen
var evBuf: int64 := alloc(32);
var n: int64 := VegaEventRecv(evBuf);
if (n > 0) {
var t: int64 := peek64(evBuf); // VEGA_EVT_*
if (t == VEGA_EVT_WIN_CLOSE) { break; }
}
free(evBuf, 32);
}
VegaWinDestroy(wid);
return 0;
}
==== Konstanten ====
**Window-Flags** (''sys_win_create''):
^ Konstante ^ Wert ^
| ''VEGA_WIN_NORMAL'' | 0 |
| ''VEGA_WIN_BORDERLESS'' | 1 |
| ''VEGA_WIN_FULLSCREEN'' | 2 |
| ''VEGA_WIN_RESIZABLE'' | 4 |
| ''VEGA_WIN_HIDDEN'' | 8 |
**Ereignis-Typen** (''sys_event_send'' / ''sys_event_recv''):
^ Konstante ^ Wert ^ Bedeutung ^
| ''VEGA_EVT_KEY_DOWN'' | 1 | Taste gedrückt |
| ''VEGA_EVT_KEY_UP'' | 2 | Taste losgelassen |
| ''VEGA_EVT_MOUSE_MOVE'' | 3 | Maus bewegt |
| ''VEGA_EVT_MOUSE_BTN'' | 4 | Maustaste gedrückt/losgelassen |
| ''VEGA_EVT_WIN_CLOSE'' | 5 | Schließen-Knopf geklickt |
| ''VEGA_EVT_WIN_RESIZE'' | 6 | Fenster in der Größe geändert |
| ''VEGA_EVT_WIN_FOCUS'' | 7 | Fokus gewonnen / verloren |
**Maustastenbits** (''sys_get_mouse_btn''):
^ Konstante ^ Wert ^
| ''VEGA_MBTN_LEFT'' | 1 |
| ''VEGA_MBTN_RIGHT'' | 2 |
| ''VEGA_MBTN_MIDDLE'' | 4 |
==== Funktionen ====
**Fenster-Verwaltung:**
^ Signatur ^ Beschreibung ^
| ''VegaWinCreate(x, y, w, h, flags): int64'' | Fenster anlegen; gibt win_id zurück (0 = Fehler) |
| ''VegaWinDestroy(winId): int64'' | Fenster freigeben |
| ''VegaWinRaise(winId): int64'' | In Vordergrund bringen |
| ''VegaWinMove(winId, x, y): int64'' | Fenster verschieben |
| ''VegaWinResize(winId, newW, newH): int64'' | Fenstergröße ändern |
| ''VegaWinGetFb(winId): int64'' | Fenster-Framebuffer → UVA (0 = Fehler) |
| ''VegaWinGetTablePhys(): int64'' | Physische Adresse der Fenstertabelle |
| ''VegaWinSetTitle(winId, titlePtr): int64'' | Fenster-Titel setzen (WP27) |
| ''VegaWinFindByIdx(idx): int64'' | win_id für Slot-Index ermitteln (WP27) |
| ''VegaWinGetTitle(winId, buf): int64'' | Fenster-Titel lesen (WP27) |
| ''VegaWinGetGeom(winId, outBuf): int64'' | Geometrie lesen: x,y,w,h in outBuf (4×int64) (WP29) |
| ''VegaWinGetPid(winId): int64'' | PID des Fenster-Besitzers (WP29) |
**Display / Framebuffer:**
^ Signatur ^ Beschreibung ^
| ''VegaVsyncWait(): int64'' | Blockiert bis zum nächsten VSync/PIT-Tick |
| ''VegaFbMapUser(fbPhys, fbW, fbH, stride): int64'' | Physischen Framebuffer in User-Adressraum mappen → UVA |
**Shared Memory:**
^ Signatur ^ Beschreibung ^
| ''VegaShmCreate(size): int64'' | SHM-Region anlegen; gibt shm_id zurück (0 = Fehler) |
| ''VegaShmMap(shmId): int64'' | In User-Space mappen → UVA (0 = Fehler) |
| ''VegaShmUnmap(shmId): int64'' | Referenzzähler dekrementieren |
**Ereignisse:**
^ Signatur ^ Beschreibung ^
| ''VegaEventSend(pid, evtType, a, b): int64'' | Ereignis an PID senden; ''evtType'' aus ''VEGA_EVT_*'' |
| ''VegaEventRecv(outBuf): int64'' | Eigenes Postfach prüfen; gibt Anzahl geschriebener Ereignisse zurück |
| ''VegaSetConsole(pid, shmId): int64'' | PutCh-Ausgabe von PID in SHM-Ringpuffer umleiten (shmId=-1 zum Deaktivieren) |
**PS/2-Maus:**
^ Signatur ^ Beschreibung ^
| ''VegaGetMouseX(): int64'' | X-Koordinate |
| ''VegaGetMouseY(): int64'' | Y-Koordinate |
| ''VegaGetMouseBtn(): int64'' | Tastenbits (''VEGA_MBTN_*'') |
| ''VegaSetMouseBounds(maxX, maxY): int64'' | Koordinatengrenzen setzen |
**Tastatur:**
^ Signatur ^ Beschreibung ^
| ''VegaKbdPoll(): int64'' | Non-blocking; 0 = kein Zeichen, sonst Scancode |
**Zeit:**
^ Signatur ^ Beschreibung ^
| ''VegaTimeNs(): int64'' | Nanosekunden seit Systemstart |
----
===== 12. Quelldateien =====
^ Datei ^ Inhalt ^
| ''vega/vega.lyx'' | Compositor-Hauptprogramm: Frame-Loop, Fenstergeometrie, Drag-Logik, Kompositionierung |
| ''vega/bsys_vega.lyx'' | Bridge-Unit: Syscall-Wrapper (WP17/WP17b), Display-Backend, VGA-Font, Dekoration, Maus-Cursor, Fenster-Tabellenhelfer |
| ''vega/bsys_vega.lyu'' | Vorkompilierte Unit (lyxc-Output) |
| ''vega/vega.elf'' | Fertig gelinktes ELF64-Binary |
| ''src/std/lyxos/vega.lyx'' | Standard-Library-Unit (LX-WP17): öffentliche Vega-API für Ring-3-Anwendungen |
Letzte Aktualisierung: 2026-08-29 — Abschnitt „Bildschirm übernehmen statt erben" ergänzt (Syscalls 106/107, Frametime-Messlauf).
Vorherige Aktualisierung: 2026-06-25