Files
rippy/rippy-windows/src/haupt/fensterrand.ts
T
HitonabiandClaude Opus 5 663127f854
Ampel / ampel (push) Successful in 1m35s
feat(v5): Windows-Rand weg, Hardware-Empfehlung sichtbar, Wizard geradegezogen
Vier Punkte des Commanders (01.09.2026):

1. "Ich hab noch den rand ich glaube der kommt aber von windows selbst"
   Stimmt. Ein rahmenloses Fenster behaelt unter Windows 11 den DWM-Rand
   — eine feine Linie, die der Fenstermanager zeichnet, nicht die Seite;
   mit CSS ist da nichts zu holen. Neu fensterrand.ts:
   DwmSetWindowAttribute mit DWMWA_BORDER_COLOR = DWMWA_COLOR_NONE.
   Gemessen: HRESULT 0, Windows nimmt es an. Runde Ecken bleiben (sie
   sind unter Windows 11 das Uebliche); ein Schalter fuer kantig ist da.
   Aeltere Windows antworten mit Fehler — der wird als Wert
   zurueckgegeben und protokolliert, nicht verschluckt (R4); dort gibt es
   den Rand schlicht nicht.

   Das ist der DRITTE erlaubte koffi-Ort. Waechter R1 kennt jetzt drei
   statt zwei Dateien; die Regel selbst ("Win32 nur an benannten Orten")
   bleibt und haelt alles andere weiter dicht.

2. "Die alte Version konnte automatisch anhand der gescannten hardware
   encoder das beste preset waehlen."
   Das KANN diese auch — presetEmpfehlung() waehlt nach den gemessenen
   Backends (VCN -> NVENC -> QSV -> CPU) und laeuft seit dem Kino-Mix.
   Man sah es nur nirgends ausser als Wort "automatisch:" in einem
   Auswahlfeld. Die Erst-Einrichtung zeigt jetzt die gemessenen Encoder
   als Badges und was daraus fuer DVD, Blu-ray und 4K wird — plus eine
   ehrliche Warnung, wenn nur CPU-Encoder da sind.

3. Feld "Update-Adresse" ist raus. Der Schluessel updateUrl gilt
   weiterhin (Datenbank), Paragraph 6.8 prueft ihn wie zuvor.

4. Erst-Einrichtung geprueft. Gefunden und behoben:
   * "Dieses Setup stellt vier Dinge ein" — es stellte ZWEI ein.
   * Der Ablage-Schritt zeigte eine LEERE Zeile, wenn nichts gewaehlt
     war. Es gibt aber eine Vorgabe (Videos\Rippy im Benutzerprofil) —
     die steht jetzt da.
   * Kein Wort zum TMDb-Schluessel, obwohl Schritt 1 "Rippy erkennt, was
     drauf ist" verspricht. Ohne Schluessel heissen Filme wie das
     Disc-Label. Jetzt ein eigener Schritt mit Eingabefeld.
   * Rohe HTML-Checkbox statt des Schalters aus dem Kino-Mix.
   * Kein Hinweis, dass Rippy im Infobereich weiterlebt.
   Neu sechs Schritte, drei Fragen — und die Zahl im Text stimmt.

   Dazu: #einrichtung als Beweis-Anker (RIPPY_START_BEREICH), sonst ist
   der Wizard nach dem ersten Start nicht mehr zu fotografieren und
   damit nicht mehr pruefbar. Beweis: beweise/ui-515-wizard.png

237 Tests gruen, Typpruefung sauber. Version 5.1.5.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 18:43:58 +02:00

79 lines
3.3 KiB
TypeScript

// Den Windows-11-Fensterrand loswerden.
//
// Commander-Fund (01.09.2026): „Ich hab noch den rand ich glaube der kommt
// aber von windows selbst oder?" — Genau so ist es. Ein rahmenloses Fenster
// (`frame: false`) behält unter Windows 11 trotzdem den DWM-Rand: eine
// hauchfeine Linie in der Systemfarbe, gezeichnet vom Fenstermanager, nicht
// von der Seite. Mit CSS ist da nichts zu holen, das liegt außerhalb des
// Fensterinhalts.
//
// DwmSetWindowAttribute kennt dafür zwei Schalter (dwmapi.h, beide erst ab
// Windows 11 Build 22000):
// DWMWA_BORDER_COLOR (34) = DWMWA_COLOR_NONE (0xFFFFFFFE)
// DWMWA_WINDOW_CORNER_PREFERENCE (33) = DWMWCP_DONOTROUND (1)
//
// Ältere Windows antworten mit einem Fehler-HRESULT. Das ist KEIN Problem
// und wird als Wert zurückgegeben, nicht verschluckt (R4): Unter Windows 10
// gibt es diesen Rand schlicht nicht.
//
// Dies ist neben `leine.ts` und `kern/laufwerk/win32.ts` der DRITTE erlaubte
// koffi-Ort; der Wächter-Test R1 kennt genau diese drei. Begründung wie
// dort: ein Win32-Aufruf, der nirgendwo sonst hingehört — und er MUSS im
// Haupt liegen, weil nur dort das Fensterhandle existiert.
import koffi from 'koffi'
const DWMWA_WINDOW_CORNER_PREFERENCE = 33
const DWMWA_BORDER_COLOR = 34
/** „Zeichne gar keinen Rand" — nicht zu verwechseln mit Schwarz. */
const DWMWA_COLOR_NONE = 0xfffffffe
const DWMWCP_DONOTROUND = 1
export interface RandErgebnis {
ok: boolean
/** '' wenn alles saß; sonst der HRESULT-Grund im Klartext. */
fehler: string
}
/**
* Rand entfernen. `eckenKantig` schaltet zusätzlich die runden Ecken ab —
* standardmäßig AUS, weil runde Ecken unter Windows 11 das Übliche sind
* und Rippy sich nicht fremder anfühlen soll, als es muss.
*
* @param handle Das native Fensterhandle (`BrowserWindow.getNativeWindowHandle()`).
*/
export function fensterrandEntfernen(handle: Buffer, eckenKantig = false): RandErgebnis {
if (handle.length < 8) return { ok: false, fehler: 'Fensterhandle unbrauchbar' }
try {
const dwmapi = koffi.load('dwmapi.dll')
// Das Handle steckt als Zeiger IM Puffer. Auf x64 wandert ein Zeiger im
// selben Register wie ein uint64 — deshalb ist das hier gefahrlos.
const DwmSetWindowAttribute = dwmapi.func(
'int32_t __stdcall DwmSetWindowAttribute(uint64_t hwnd, uint32_t dwAttribute, void *pvAttribute, uint32_t cbAttribute)',
)
const hwnd = handle.readBigUInt64LE(0)
const farbe = Buffer.alloc(4)
farbe.writeUInt32LE(DWMWA_COLOR_NONE, 0)
const randErgebnis = DwmSetWindowAttribute(hwnd, DWMWA_BORDER_COLOR, farbe, 4)
let eckenErgebnis = 0
if (eckenKantig) {
const ecken = Buffer.alloc(4)
ecken.writeUInt32LE(DWMWCP_DONOTROUND, 0)
eckenErgebnis = DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, ecken, 4)
}
if (randErgebnis !== 0 || eckenErgebnis !== 0) {
// Ein negatives HRESULT heißt hier fast immer: älteres Windows, das
// diese Schalter nicht kennt. Rippy läuft weiter, nur mit Rand.
return {
ok: false,
fehler: `DwmSetWindowAttribute: HRESULT 0x${(randErgebnis >>> 0).toString(16)} (Rand) / 0x${(eckenErgebnis >>> 0).toString(16)} (Ecken) — vermutlich Windows 10`,
}
}
return { ok: true, fehler: '' }
} catch (fehler) {
return { ok: false, fehler: `koffi/dwmapi nicht verfügbar: ${String(fehler)}` }
}
}