VNC-Steuerung verbessern: Low-Latency, Maus, Tastatur, Resize
Die Steuerung ist jetzt auf Minecraft (Menü, Chat, Inventar, AFK-Farmen) optimiert. Für Mouselook/PVP bleibt VNC ungeeignet (Protokollgrenze, dokumentiert). x11vnc (serverseitig, entrypoint.sh): - -threads: parallele I/O-Threads → weniger Eingabe-Lag - -pointer_mode 4: flüssigere Mausübertragung (Default 1 ist träge) - -norepeat: verhindert doppelte Tastaturwiederholungen im Spiel - -nodpms -nofbpm -nowf -nowcr: Energiesparen/Rate-Limiting aus - Über X11VNC_EXTRA env var frei konfigurierbar noVNC-Client (VncViewer.vue): - resize=remote statt scaling: Xvfb folgt Fenstergröße (1:1-Maus-Mapung) - reconnect=1: auto-Reconnect bei Abbruch - clipboard=1: Zwischenablage Browser <-> Container - view_only=0: Eingabe explizit freigeschaltet - Klick ins Bild setzt Tastaturfokus ins iframe - Hinweis auf Mausfreigabe (Strg+Alt+Umschalt), Fokus-Button README: neuer Abschnitt "Steuerung über VNC" mit Grenzerklärung. .env.example + docker-compose.yml: X11VNC_EXTRA durchgereicht.
This commit is contained in:
parent
b8a99e6e9e
commit
af073e77ec
5 changed files with 134 additions and 19 deletions
|
|
@ -16,18 +16,28 @@ const errorMsg = ref<string | null>(null)
|
|||
const iframeEl = ref<HTMLIFrameElement | null>(null)
|
||||
const iframeKey = ref(0)
|
||||
|
||||
// noVNC-URL: autoconnect=1, resize=scaling, Pfad zum websockify.
|
||||
// noVNC-URL mit auf Steuerung/Spiele optimierten Parametern:
|
||||
// resize=remote — passt die Xvfb-Auflösung an die Fenstergröße an
|
||||
// (statt nur zu skalieren). Korrekte 1:1-Maus-Mapung,
|
||||
// keine Unschärfe. Fällt auf 'scale' zurück, falls der
|
||||
// Server kein Resize unterstützt.
|
||||
// reconnect=1 — bei Verbindungsabbruch automatisch neu verbinden.
|
||||
// path=websockify — noVNC spricht den WS-Endpunkt relativ an.
|
||||
// show_dot=1 — lokalen Punkt-Cursor zeigen (Zielhilfe).
|
||||
// view_only=0 — Eingabe explizit freischalten.
|
||||
// clipboard=1 — Zwischenablage zwischen Browser und VM verknüpfen
|
||||
// (wichtig für Login-Codes / Server-IPs kopieren).
|
||||
const novncUrl = computed(() => {
|
||||
const host = window.location.hostname
|
||||
const port = window.location.port || String(window.location.port)
|
||||
const port = window.location.port
|
||||
const params = new URLSearchParams({
|
||||
autoconnect: '1',
|
||||
resize: 'scaling',
|
||||
// noVNC spricht relativ 'websockify' an → nginx mappt /websockify.
|
||||
reconnect: '1',
|
||||
resize: 'remote',
|
||||
path: 'websockify',
|
||||
// show_dot_cursor hilft beim Zielen im VNC-Fenster.
|
||||
show_dot: '1',
|
||||
// host/port für die Anzeige im noVNC-eigenen UI; iframe nutzt aber path.
|
||||
view_only: '0',
|
||||
clipboard: '1',
|
||||
host,
|
||||
port,
|
||||
})
|
||||
|
|
@ -47,6 +57,20 @@ function onIframeLoad() {
|
|||
state.value = 'connected'
|
||||
}
|
||||
|
||||
// Fokus in den iframe setzen, damit Tastatureingaben ans Spiel gehen.
|
||||
// noVNC selbst fängt die Keys im iframe ab; wir müssen nur dorthin fokussieren.
|
||||
function focusFrame() {
|
||||
const el = iframeEl.value
|
||||
if (!el) return
|
||||
// Versuch, das innere Dokument zu fokussieren (gleiche Origin → erlaubt).
|
||||
try {
|
||||
el.contentWindow?.focus()
|
||||
} catch {
|
||||
/* Cross-Origin → iframe focus als Fallback */
|
||||
el.focus()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
state.value = 'connecting'
|
||||
})
|
||||
|
|
@ -54,15 +78,17 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<div class="vnc">
|
||||
<iframe
|
||||
ref="iframeEl"
|
||||
:key="iframeKey"
|
||||
class="vnc__frame"
|
||||
:src="novncUrl"
|
||||
title="Minecraft via noVNC"
|
||||
allow="clipboard-read; clipboard-write; fullscreen"
|
||||
@load="onIframeLoad"
|
||||
></iframe>
|
||||
<div class="vnc__stage" @click="focusFrame">
|
||||
<iframe
|
||||
ref="iframeEl"
|
||||
:key="iframeKey"
|
||||
class="vnc__frame"
|
||||
:src="novncUrl"
|
||||
title="Minecraft via noVNC"
|
||||
allow="clipboard-read; clipboard-write; fullscreen"
|
||||
@load="onIframeLoad"
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
<div v-if="state !== 'connected'" class="vnc__overlay">
|
||||
<div class="vnc__overlay-inner">
|
||||
|
|
@ -91,9 +117,11 @@ onMounted(() => {
|
|||
}}
|
||||
</span>
|
||||
<span class="vnc__hint">
|
||||
Maus im Fenster festhalten? Im noVNC-Seitenmenge „Clip to Window“.
|
||||
Klick ins Bild für Tastatur-Fokus. Maus freigeben:
|
||||
<kbd>Strg</kbd>+<kbd>Alt</kbd>+<kbd>Umschalt</kbd>
|
||||
</span>
|
||||
<button @click="reload">Aktualisieren</button>
|
||||
<button @click="focusFrame" :disabled="state !== 'connected'">Fokus</button>
|
||||
<button @click="reload" :disabled="state === 'connecting'">Aktualisieren</button>
|
||||
<button
|
||||
@click="iframeEl?.requestFullscreen()"
|
||||
:disabled="state !== 'connected'"
|
||||
|
|
@ -113,10 +141,18 @@ onMounted(() => {
|
|||
background: #000;
|
||||
}
|
||||
|
||||
.vnc__frame {
|
||||
.vnc__stage {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vnc__frame {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
background: #000;
|
||||
}
|
||||
|
|
@ -165,6 +201,17 @@ onMounted(() => {
|
|||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.vnc__hint kbd {
|
||||
font-family: var(--mono);
|
||||
background: var(--bg-elev-2);
|
||||
border: 1px solid var(--border);
|
||||
border-bottom-width: 2px;
|
||||
border-radius: 4px;
|
||||
padding: 1px 5px;
|
||||
font-size: 10px;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.vnc__badge.connected {
|
||||
background: var(--accent);
|
||||
color: #0f1115;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue