Fix mobile keyboard: use focusin intercept instead of touchend race

This commit is contained in:
shuki
2026-03-07 07:24:27 +02:00
parent 0fa3d94307
commit a46c902b15

View File

@@ -165,77 +165,57 @@
} }
})(); })();
// Mobile keyboard control: toggle button to show/hide virtual keyboard // Mobile keyboard control: block virtual keyboard unless toggled open
(function() { (function() {
if (!("ontouchstart" in window)) return; if (!("ontouchstart" in window)) return;
var kbOpen = false; var kbAllowed = false;
// Create floating keyboard toggle button // Floating toggle button
var btn = document.createElement("div"); var btn = document.createElement("div");
btn.id = "kb-toggle"; btn.id = "kb-toggle";
btn.textContent = ""; btn.textContent = "\u2328";
btn.style.cssText = "position:fixed;bottom:12px;right:12px;z-index:9999;" + btn.style.cssText = "position:fixed;bottom:12px;right:12px;z-index:9999;" +
"width:44px;height:44px;border-radius:50%;background:rgba(94,11,167,0.85);" + "width:48px;height:48px;border-radius:50%;background:rgba(94,11,167,0.9);" +
"color:#fff;font-size:22px;display:flex;align-items:center;justify-content:center;" + "color:#fff;font-size:24px;display:flex;align-items:center;justify-content:center;" +
"cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,0.4);user-select:none;" + "cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,0.5);user-select:none;" +
"-webkit-tap-highlight-color:transparent;"; "-webkit-tap-highlight-color:transparent;touch-action:manipulation;";
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
document.body.appendChild(btn); document.body.appendChild(btn);
}); });
function getTA() { btn.addEventListener("touchstart", function(e) {
return document.querySelector(".xterm-helper-textarea");
}
function openKeyboard() {
kbOpen = true;
var ta = getTA();
if (ta) {
ta.setAttribute("inputmode", "text");
ta.focus();
}
btn.style.background = "rgba(0,204,0,0.85)";
btn.textContent = "✕";
}
function closeKeyboard() {
kbOpen = false;
var ta = getTA();
if (ta) {
ta.setAttribute("inputmode", "none");
ta.blur();
}
btn.style.background = "rgba(94,11,167,0.85)";
btn.textContent = "⌨";
}
btn.addEventListener("click", function(e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (kbOpen) closeKeyboard(); else openKeyboard(); kbAllowed = !kbAllowed;
}); var ta = document.querySelector(".xterm-helper-textarea");
if (kbAllowed) {
// Prevent keyboard from auto-opening on every tap btn.style.background = "rgba(0,204,0,0.9)";
document.addEventListener("touchend", function(e) { btn.textContent = "\u2715";
if (e.target === btn || btn.contains(e.target)) return; if (ta) { ta.inputMode = "text"; ta.focus(); }
if (kbOpen) return; } else {
setTimeout(function() { btn.style.background = "rgba(94,11,167,0.9)";
var active = document.activeElement; btn.textContent = "\u2328";
if (active && active.classList && active.classList.contains("xterm-helper-textarea")) { if (ta) { ta.inputMode = "none"; ta.blur(); }
active.blur();
} }
}, 30); }, { passive: false });
}, { passive: true });
// Set inputmode=none on xterm textarea once it appears (prevent initial keyboard) // Intercept focus on xterm textarea — set inputmode=none if keyboard not allowed
var checkReady = setInterval(function() { document.addEventListener("focusin", function(e) {
var ta = getTA(); if (kbAllowed) return;
if (e.target && e.target.classList && e.target.classList.contains("xterm-helper-textarea")) {
e.target.inputMode = "none";
}
}, true);
// Set inputmode=none as soon as textarea appears
new MutationObserver(function(mutations, obs) {
var ta = document.querySelector(".xterm-helper-textarea");
if (ta) { if (ta) {
clearInterval(checkReady); ta.inputMode = "none";
ta.setAttribute("inputmode", "none"); obs.disconnect();
} }
}, 200); }).observe(document.body, { childList: true, subtree: true });
})(); })();
// Touch-to-scroll: translate swipe into mouse wheel for Textual scrollable containers // Touch-to-scroll: translate swipe into mouse wheel for Textual scrollable containers