@@ -31,6 +31,14 @@ export default class TerminalTouchSelection {
3131 this . tapHoldTimeout = null ;
3232 this . dragHandle = null ;
3333
34+ // Zoom tracking
35+ this . pinchStartDistance = 0 ;
36+ this . lastPinchDistance = 0 ;
37+ this . isPinching = false ;
38+ this . initialFontSize = 0 ;
39+ this . lastZoomTime = 0 ;
40+ this . zoomThrottle = 50 ; // ms
41+
3442 // DOM elements
3543 this . selectionOverlay = null ;
3644 this . startHandle = null ;
@@ -208,7 +216,14 @@ export default class TerminalTouchSelection {
208216 }
209217
210218 onTerminalTouchStart ( event ) {
211- // Only handle single touch
219+ // Handle pinch zoom
220+ if ( event . touches . length === 2 ) {
221+ event . preventDefault ( ) ;
222+ this . startPinchZoom ( event ) ;
223+ return ;
224+ }
225+
226+ // Only handle single touch for selection
212227 if ( event . touches . length !== 1 ) return ;
213228
214229 const touch = event . touches [ 0 ] ;
@@ -228,15 +243,25 @@ export default class TerminalTouchSelection {
228243
229244 // Start tap-hold timer
230245 this . tapHoldTimeout = setTimeout ( ( ) => {
231- if ( ! this . isSelecting ) {
246+ if ( ! this . isSelecting && ! this . isPinching ) {
232247 this . startSelection ( touch ) ;
233248 }
234249 } , this . options . tapHoldDuration ) ;
235250 }
236251
237252 onTerminalTouchMove ( event ) {
253+ // Handle pinch zoom
254+ if ( event . touches . length === 2 ) {
255+ event . preventDefault ( ) ;
256+ this . handlePinchZoom ( event ) ;
257+ return ;
258+ }
259+
238260 if ( event . touches . length !== 1 ) return ;
239261
262+ // Don't handle single touch if we're pinching
263+ if ( this . isPinching ) return ;
264+
240265 const touch = event . touches [ 0 ] ;
241266 const deltaX = Math . abs ( touch . clientX - this . touchStartPos . x ) ;
242267 const deltaY = Math . abs ( touch . clientY - this . touchStartPos . y ) ;
@@ -260,6 +285,12 @@ export default class TerminalTouchSelection {
260285 }
261286
262287 onTerminalTouchEnd ( event ) {
288+ // Handle end of pinch zoom
289+ if ( this . isPinching ) {
290+ this . endPinchZoom ( ) ;
291+ return ;
292+ }
293+
263294 if ( this . tapHoldTimeout ) {
264295 clearTimeout ( this . tapHoldTimeout ) ;
265296 this . tapHoldTimeout = null ;
@@ -916,6 +947,77 @@ export default class TerminalTouchSelection {
916947 }
917948 }
918949
950+ /**
951+ * Start pinch zoom gesture
952+ */
953+ startPinchZoom ( event ) {
954+ if ( event . touches . length !== 2 ) return ;
955+
956+ this . isPinching = true ;
957+ this . initialFontSize = this . terminal . options . fontSize ;
958+
959+ const touch1 = event . touches [ 0 ] ;
960+ const touch2 = event . touches [ 1 ] ;
961+
962+ this . pinchStartDistance = this . getDistance ( touch1 , touch2 ) ;
963+ this . lastPinchDistance = this . pinchStartDistance ;
964+
965+ // Clear any selection timeouts
966+ if ( this . tapHoldTimeout ) {
967+ clearTimeout ( this . tapHoldTimeout ) ;
968+ this . tapHoldTimeout = null ;
969+ }
970+ }
971+
972+ /**
973+ * Handle pinch zoom gesture
974+ */
975+ handlePinchZoom ( event ) {
976+ if ( ! this . isPinching || event . touches . length !== 2 ) return ;
977+
978+ const now = Date . now ( ) ;
979+ if ( now - this . lastZoomTime < this . zoomThrottle ) return ;
980+ this . lastZoomTime = now ;
981+
982+ const touch1 = event . touches [ 0 ] ;
983+ const touch2 = event . touches [ 1 ] ;
984+ const currentDistance = this . getDistance ( touch1 , touch2 ) ;
985+
986+ const scale = currentDistance / this . pinchStartDistance ;
987+ const newFontSize = Math . round ( this . initialFontSize * scale ) ;
988+
989+ // Clamp font size between reasonable limits
990+ const minFontSize = 8 ;
991+ const maxFontSize = 24 ;
992+ const clampedFontSize = Math . max (
993+ minFontSize ,
994+ Math . min ( maxFontSize , newFontSize ) ,
995+ ) ;
996+
997+ if ( clampedFontSize !== this . terminal . options . fontSize ) {
998+ this . options . onFontSizeChange ( clampedFontSize ) ;
999+ }
1000+ }
1001+
1002+ /**
1003+ * End pinch zoom gesture
1004+ */
1005+ endPinchZoom ( ) {
1006+ this . isPinching = false ;
1007+ this . pinchStartDistance = 0 ;
1008+ this . lastPinchDistance = 0 ;
1009+ this . initialFontSize = 0 ;
1010+ }
1011+
1012+ /**
1013+ * Get distance between two touch points
1014+ */
1015+ getDistance ( touch1 , touch2 ) {
1016+ const dx = touch2 . clientX - touch1 . clientX ;
1017+ const dy = touch2 . clientY - touch1 . clientY ;
1018+ return Math . sqrt ( dx * dx + dy * dy ) ;
1019+ }
1020+
9191021 destroy ( ) {
9201022 // Clear selection
9211023 this . clearSelection ( ) ;
0 commit comments