diff --git a/src/webterm/static/js/terminal.js b/src/webterm/static/js/terminal.js index 788d400..d0a2370 100644 --- a/src/webterm/static/js/terminal.js +++ b/src/webterm/static/js/terminal.js @@ -25,7 +25,7 @@ For tests, pass a Ghostty instance directly: resize: none; font-size: 16px; caret-color: transparent; - `,this.element.style.position="relative",this.element.appendChild(V),this.mobileInput=V,V.addEventListener("beforeinput",(j)=>{let $=null;switch(j.inputType){case"insertLineBreak":$="\r";break;case"deleteContentBackward":$="";break;case"deleteContentForward":$="\x1B[3~";break}if($)j.preventDefault(),this.send(["stdin",$])}),V.addEventListener("input",()=>{let j=V.value;if(j){let $=j;if(this.shiftActive&&j.length===1)$=j.toUpperCase();if(this.ctrlActive&&j.length===1){let P=$.toUpperCase().charCodeAt(0);if(P>=65&&P<=90)$=String.fromCharCode(P-64)}this.send(["stdin",$]),V.value="",this.deactivateModifiers()}}),V.addEventListener("keydown",(j)=>{let $=j.ctrlKey||this.ctrlActive,P=j.shiftKey||this.shiftActive;if(j.ctrlKey&&j.key.length===1&&!j.altKey&&!j.metaKey){let R=j.key.toUpperCase().charCodeAt(0);if(R>=65&&R<=90){j.preventDefault(),this.send(["stdin",String.fromCharCode(R-64)]);return}}let X=null,K=!1;switch(j.key){case"Escape":X="\x1B",K=!0;break;case"ArrowUp":case"ArrowDown":case"ArrowRight":case"ArrowLeft":{let R=j.key==="ArrowUp"?"A":j.key==="ArrowDown"?"B":j.key==="ArrowRight"?"C":"D";if($&&P)X=`\x1B[1;6${R}`;else if($)X=`\x1B[1;5${R}`;else if(P)X=`\x1B[1;2${R}`;else X=`\x1B[${R}`;K=!0;break}case"Tab":if(P)X="\x1B[Z";else X="\t";j.preventDefault(),K=!0;break}if(X){if(j.preventDefault(),this.send(["stdin",X]),K)this.deactivateModifiers()}});let Z=()=>{this.mobileInput?.focus()};this.element.addEventListener("touchend",Z,{passive:!0}),this.element.addEventListener("click",Z)}setupMobileKeybar(){let V=document.createElement("div");V.className="mobile-keybar",V.innerHTML=` + `,this.element.style.position="relative",this.element.appendChild(V),this.mobileInput=V,V.addEventListener("beforeinput",(j)=>{let $=null;switch(j.inputType){case"insertLineBreak":$="\r";break;case"deleteContentBackward":$="";break;case"deleteContentForward":$="\x1B[3~";break}if($)j.preventDefault(),this.send(["stdin",$]),this.deactivateModifiers()}),V.addEventListener("input",()=>{let j=V.value;if(j){let $=j;if(this.shiftActive&&j.length===1)$=j.toUpperCase();if(this.ctrlActive&&j.length===1){let P=$.toUpperCase().charCodeAt(0);if(P>=65&&P<=90)$=String.fromCharCode(P-64)}this.send(["stdin",$]),V.value="",this.deactivateModifiers()}}),V.addEventListener("keydown",(j)=>{let $=j.ctrlKey||this.ctrlActive,P=j.shiftKey||this.shiftActive;if(j.ctrlKey&&j.key.length===1&&!j.altKey&&!j.metaKey){let R=j.key.toUpperCase().charCodeAt(0);if(R>=65&&R<=90){j.preventDefault(),this.send(["stdin",String.fromCharCode(R-64)]);return}}let X=null,K=!1;switch(j.key){case"Escape":X="\x1B",K=!0;break;case"ArrowUp":case"ArrowDown":case"ArrowRight":case"ArrowLeft":{let R=j.key==="ArrowUp"?"A":j.key==="ArrowDown"?"B":j.key==="ArrowRight"?"C":"D";if($&&P)X=`\x1B[1;6${R}`;else if($)X=`\x1B[1;5${R}`;else if(P)X=`\x1B[1;2${R}`;else X=`\x1B[${R}`;K=!0;break}case"Tab":if(P)X="\x1B[Z";else X="\t";j.preventDefault(),K=!0;break}if(X){if(j.preventDefault(),this.send(["stdin",X]),K)this.deactivateModifiers()}});let Z=()=>{this.mobileInput?.focus()};this.element.addEventListener("touchend",Z,{passive:!0}),this.element.addEventListener("click",Z)}setupMobileKeybar(){let V=document.createElement("div");V.className="mobile-keybar",V.innerHTML=` diff --git a/src/webterm/static/js/terminal.ts b/src/webterm/static/js/terminal.ts index 3d17fea..5552939 100644 --- a/src/webterm/static/js/terminal.ts +++ b/src/webterm/static/js/terminal.ts @@ -654,6 +654,8 @@ class WebTerminal { if (seq) { e.preventDefault(); this.send(["stdin", seq]); + // Clear modifiers after sending special keys from soft keyboard + this.deactivateModifiers(); } });