@@ -55,6 +55,10 @@ export default class TerminalTouchSelection {
5555 this . wasFocusedBeforeSelection = false ;
5656 this . contextMenuShouldStayVisible = false ;
5757
58+ // Selection protection during keyboard events
59+ this . selectionProtected = false ;
60+ this . protectionTimeout = null ;
61+
5862 this . init ( ) ;
5963 }
6064
@@ -460,6 +464,11 @@ export default class TerminalTouchSelection {
460464 onTerminalAreaTouchStart ( event ) {
461465 // Clear selection if touching terminal area while selecting, except on handles or context menu
462466 if ( this . isSelecting ) {
467+ // Don't clear selection if it's protected (during keyboard events)
468+ if ( this . selectionProtected ) {
469+ return ;
470+ }
471+
463472 // Don't interfere with context menu at all
464473 if ( this . contextMenu && this . contextMenu . style . display === "flex" ) {
465474 // Context menu is visible, check if touching it
@@ -515,18 +524,35 @@ export default class TerminalTouchSelection {
515524 setTimeout ( ( ) => {
516525 this . updateCellDimensions ( ) ;
517526 if ( this . isSelecting ) {
518- // Clear selection if it becomes invalid due to resize
527+ // Don't clear selection if it's protected (during keyboard events)
528+ if ( this . selectionProtected ) {
529+ // Just update handle positions during protected period
530+ this . updateHandlePositions ( ) ;
531+ return ;
532+ }
533+
534+ // Only clear selection if it becomes invalid due to actual content resize
535+ // Don't clear selection for keyboard-related resizes
519536 if (
520- this . selectionStart . row >= size . rows ||
521- this . selectionEnd . row >= size . rows
537+ this . selectionStart &&
538+ this . selectionEnd &&
539+ ( this . selectionStart . row >= size . rows ||
540+ this . selectionEnd . row >= size . rows )
522541 ) {
523542 this . clearSelection ( ) ;
524- } else {
543+ } else if ( this . isSelecting ) {
544+ // Maintain selection and update handle positions
525545 this . updateHandlePositions ( ) ;
526- // Hide context menu during resize
546+ // Temporarily hide context menu during resize but keep selection
527547 if ( this . contextMenu && this . contextMenu . style . display === "flex" ) {
528548 this . hideContextMenu ( ) ;
529549 }
550+ // Re-show context menu after resize if selection is still active
551+ setTimeout ( ( ) => {
552+ if ( this . isSelecting && this . options . showContextMenu ) {
553+ this . showContextMenu ( ) ;
554+ }
555+ } , 100 ) ;
530556 }
531557 }
532558 } , 50 ) ;
@@ -539,6 +565,16 @@ export default class TerminalTouchSelection {
539565 // Store initial focus state
540566 this . wasFocusedBeforeSelection = this . isTerminalFocused ( ) ;
541567
568+ // Protect selection from being cancelled by keyboard events
569+ this . selectionProtected = true ;
570+ if ( this . protectionTimeout ) {
571+ clearTimeout ( this . protectionTimeout ) ;
572+ }
573+ // Remove protection after keyboard events have settled
574+ this . protectionTimeout = setTimeout ( ( ) => {
575+ this . selectionProtected = false ;
576+ } , 1000 ) ;
577+
542578 this . isSelecting = true ;
543579
544580 // Try to auto-select word at touch position
@@ -840,25 +876,30 @@ export default class TerminalTouchSelection {
840876 cordova . plugins . clipboard . copy ( selectionText ) ;
841877 }
842878
843- this . clearSelection ( ) ;
879+ this . forceClearSelection ( ) ;
844880 }
845881
846882 pasteFromClipboard ( ) {
847883 if ( cordova ?. plugins ?. clipboard ) {
848884 cordova . plugins . clipboard . paste ( ( text ) => {
849885 this . terminal . paste ( text ) ;
850- this . clearSelection ( ) ;
886+ this . forceClearSelection ( ) ;
851887 } ) ;
852888 }
853889 }
854890
855891 showMoreOptions ( ) {
856892 // Implement additional options if needed
857893 window . toast ( "More options are not implemented yet." ) ;
858- this . clearSelection ( ) ;
894+ this . forceClearSelection ( ) ;
859895 }
860896
861897 clearSelection ( ) {
898+ // Don't clear if selection is protected
899+ if ( this . selectionProtected ) {
900+ return ;
901+ }
902+
862903 // Store focus state before clearing
863904 const shouldRestoreFocus =
864905 this . wasFocusedBeforeSelection && this . isSelecting ;
@@ -879,17 +920,35 @@ export default class TerminalTouchSelection {
879920 this . tapHoldTimeout = null ;
880921 }
881922
882- // Restore focus state if terminal was focused before selection
923+ // Clear protection timeout
924+ if ( this . protectionTimeout ) {
925+ clearTimeout ( this . protectionTimeout ) ;
926+ this . protectionTimeout = null ;
927+ }
928+ this . selectionProtected = false ;
929+
930+ // Only restore focus if explicitly clearing selection (not due to keyboard close)
931+ // and if terminal was focused before selection
883932 if ( shouldRestoreFocus && ! this . isTerminalFocused ( ) ) {
884933 setTimeout ( ( ) => {
885- this . terminal . focus ( ) ;
886- } , 50 ) ;
934+ if ( ! this . isSelecting ) {
935+ this . terminal . focus ( ) ;
936+ }
937+ } , 150 ) ;
887938 }
888939
889940 // Reset focus tracking
890941 this . wasFocusedBeforeSelection = false ;
891942 }
892943
944+ forceClearSelection ( ) {
945+ // Temporarily disable protection to force clear
946+ const wasProtected = this . selectionProtected ;
947+ this . selectionProtected = false ;
948+ this . clearSelection ( ) ;
949+ // Don't restore protection state since we're clearing
950+ }
951+
893952 touchToTerminalCoords ( touch ) {
894953 const rect = this . terminal . element . getBoundingClientRect ( ) ;
895954 const x = touch . clientX - rect . left ;
@@ -1084,7 +1143,7 @@ export default class TerminalTouchSelection {
10841143
10851144 destroy ( ) {
10861145 // Clear selection
1087- this . clearSelection ( ) ;
1146+ this . forceClearSelection ( ) ;
10881147
10891148 // Remove event listeners
10901149 this . terminal . element . removeEventListener (
0 commit comments