fix(vnc): Tastatur ueber echtes RN-TextInput statt WebView-Hidden-Input
Der versteckte WebView-Input oeffnete die Android-Software-Tastatur unzuverlaessig. Jetzt haelt VncTile ein echtes RN-<TextInput> (keyboardType=visible-password), der ⌨-Button fokussiert es. Getippte Zeichen gehen per injectJavaScript an window.ariaVncKey.char/keysym → rfb.sendKey. Prefix-Diff fuer Druckbares, onKeyPress fuer Backspace/Enter. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -77,20 +77,13 @@ export const NOVNC_HTML = `<!doctype html><html><head><meta charset="utf-8">
|
||||
|
||||
var msg=document.getElementById('msg');
|
||||
|
||||
// (Fast) unsichtbares Eingabefeld → Software-Tastatur des Handys tippt in die
|
||||
// VM. WICHTIG: on-screen (nicht off-screen), sonst oeffnet Android die Tastatur
|
||||
// oft nicht bzw. liefert keine Events. opacity:0 + pointer-events:none = sichtbar
|
||||
// fuer den Fokus, aber unsichtbar und klaut keine VM-Touches. font-size:16px
|
||||
// verhindert Auto-Zoom.
|
||||
var kbd=document.createElement('input');
|
||||
kbd.setAttribute('autocomplete','off'); kbd.setAttribute('autocorrect','off');
|
||||
kbd.setAttribute('autocapitalize','off'); kbd.spellcheck=false;
|
||||
kbd.style.cssText='position:fixed;bottom:0;left:0;width:100%;height:1px;opacity:0;'
|
||||
+'border:0;padding:0;margin:0;background:transparent;color:transparent;'
|
||||
+'caret-color:transparent;font-size:16px;pointer-events:none;';
|
||||
document.body.appendChild(kbd);
|
||||
var SPECIAL={Enter:0xff0d,Backspace:0xff08,Tab:0xff09,Escape:0xff1b,Delete:0xffff,
|
||||
ArrowLeft:0xff51,ArrowUp:0xff52,ArrowRight:0xff53,ArrowDown:0xff54,Home:0xff50,End:0xff57};
|
||||
// Tastatur laeuft NICHT mehr ueber ein verstecktes WebView-Feld (Android
|
||||
// oeffnet die Software-Tastatur dafuer unzuverlaessig). Stattdessen haelt die
|
||||
// App ein echtes RN-<TextInput> und ruft window.ariaVncKey.* per
|
||||
// injectJavaScript auf → wird unten (nach RFB-Init) definiert.
|
||||
// cp<0x100 → Keysym == Codepoint (Latin-1)
|
||||
// sonst → X11-Unicode-Keysym 0x01000000+cp
|
||||
function cpToKeysym(cp){ return cp < 0x100 ? cp : 0x01000000 + cp; }
|
||||
|
||||
import('https://cdn.jsdelivr.net/npm/@novnc/novnc@1.4.0/core/rfb.js').then(function(mod){
|
||||
var RFB = mod.default;
|
||||
@@ -105,30 +98,19 @@ export const NOVNC_HTML = `<!doctype html><html><head><meta charset="utf-8">
|
||||
});
|
||||
window.__rfb = rfb;
|
||||
|
||||
// Tasten aus dem versteckten Feld an die VM schicken.
|
||||
// Down+Up einer Taste an die VM schicken.
|
||||
function tap(keysym, code){ try{ rfb.sendKey(keysym, code||null, true); rfb.sendKey(keysym, code||null, false); }catch(_){} }
|
||||
// Sondertasten (feuern zuverlaessig als keydown).
|
||||
kbd.addEventListener('keydown', function(e){
|
||||
if(SPECIAL[e.key]!==undefined){ tap(SPECIAL[e.key], e.code); e.preventDefault(); }
|
||||
});
|
||||
// Druckbare Zeichen + Editieren: beforeinput ist auf Android robuster als
|
||||
// ein input-Diff. preventDefault haelt das Feld leer → kein Doppel-Senden.
|
||||
kbd.addEventListener('beforeinput', function(e){
|
||||
var t=e.inputType||'';
|
||||
if(t==='insertText' && e.data){ for(var i=0;i<e.data.length;i++) tap(e.data.charCodeAt(i)); e.preventDefault(); }
|
||||
else if(t.indexOf('insertLineBreak')>=0 || t.indexOf('insertParagraph')>=0){ tap(0xff0d); e.preventDefault(); }
|
||||
else if(t.indexOf('deleteContentBackward')>=0){ tap(0xff08); e.preventDefault(); }
|
||||
kbd.value='';
|
||||
});
|
||||
// Fallback, falls beforeinput nicht unterstuetzt wird.
|
||||
kbd.addEventListener('input', function(){
|
||||
if(kbd.value){ for(var i=0;i<kbd.value.length;i++){ tap(kbd.value.charCodeAt(i)); } kbd.value=''; }
|
||||
});
|
||||
|
||||
// Empfaenger-API: die App (RN-<TextInput>) ruft das per injectJavaScript.
|
||||
// char(cp) druckbares Zeichen (Codepoint)
|
||||
// keysym(ks) Sondertaste als fertiges X11-Keysym (Backspace/Enter/…)
|
||||
window.ariaVncKey = {
|
||||
char: function(cp){ tap(cpToKeysym(cp)); },
|
||||
keysym: function(ks){ tap(ks); }
|
||||
};
|
||||
|
||||
// Steuerungs-API fuer die App (per injectJavaScript).
|
||||
window.ariaVncCtl = {
|
||||
focusKeyboard: function(){ try{ kbd.value=''; kbd.focus(); }catch(_){} },
|
||||
blurKeyboard: function(){ try{ kbd.blur(); }catch(_){} },
|
||||
cad: function(){ try{ rfb.sendCtrlAltDel(); }catch(_){} },
|
||||
toggleFit: function(){ fit=!fit; rfb.scaleViewport=fit; rfb.clipViewport=!fit; post({event:'vnc_fit', fit:fit}); }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user