From 37663be91b7b28bf1340887ed75166500fc4208c Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 16 Jun 2026 01:59:25 +0000 Subject: [PATCH] fix: add PointerEvent fallback for swipe detection touchstart/touchend never fire on this device (confirmed by zero [TOUCH] log entries). The activity tracker already uses pointerdown/pointerup and works fine, proving PointerEvents reach the preload. Added pointer event handlers that mirror the touch handlers for all gestures (2-finger swipe, 3-finger toggle, 1-finger arrow keys). A 500ms debounce on the IPC send prevents double-firing on devices where both event types fire. https://claude.ai/code/session_01EyjEQLWbTXcZgbMDarf7NU --- ubuntu-based-kiosk-v1.0.2.sh | 132 +++++++++++++++++++++++++++++------ 1 file changed, 111 insertions(+), 21 deletions(-) diff --git a/ubuntu-based-kiosk-v1.0.2.sh b/ubuntu-based-kiosk-v1.0.2.sh index 09c33bd..2aa4bf0 100644 --- a/ubuntu-based-kiosk-v1.0.2.sh +++ b/ubuntu-based-kiosk-v1.0.2.sh @@ -7165,6 +7165,15 @@ window.addEventListener('DOMContentLoaded',()=>{ } },true); + // Shared debounce prevents double-firing when both touch and pointer events fire + let lastSwipeSent=0; + function sendSwipeIPC(direction){ + const now=Date.now(); + if(now-lastSwipeSent<500)return; + lastSwipeSent=now; + ipcRenderer.send(direction); + } + document.addEventListener('touchstart',e=>{ if(e.touches.length>=1){ touchStartX=e.touches[0].clientX; @@ -7187,18 +7196,13 @@ window.addEventListener('DOMContentLoaded',()=>{ const absX=Math.abs(deltaX); const absY=Math.abs(deltaY); - // 3-finger DOWN = toggle hidden tabs (show/hide) if(fingerCount===3&&absY>SWIPE_THRESHOLD&&absX0){ console.log('[TOUCH] 3-finger DOWN - toggle hidden tabs'); ipcRenderer.send('toggle-hidden'); - } - // 2-finger HORIZONTAL = change tabs - else if(fingerCount===2&&absX>SWIPE_THRESHOLD&&absYSWIPE_THRESHOLD&&absY0?'swipe-right':'swipe-left'); - } - // 1-finger HORIZONTAL = arrow keys - else if(fingerCount===1&&absX>SWIPE_THRESHOLD&&absY0?'swipe-right':'swipe-left'); + }else if(fingerCount===1&&absX>SWIPE_THRESHOLD&&absY0?'ArrowRight':'ArrowLeft'; const keyCode=deltaX>0?39:37; ['keydown','keyup'].forEach(eventType=>{ @@ -7210,6 +7214,47 @@ window.addEventListener('DOMContentLoaded',()=>{ } },{passive:true}); + // Pointer event fallback — handles devices/drivers where touchstart/touchend don't fire + // (e.g. Electron 42 on some Linux touchscreen drivers that only generate PointerEvents) + let ptrIds=new Set(); + let ptrPeak=0; + let ptrStartX=0,ptrStartY=0,ptrStartTime=0; + + document.addEventListener('pointerdown',e=>{ + if(e.pointerType!=='touch')return; + ptrIds.add(e.pointerId); + if(ptrIds.size===1){ptrStartX=e.clientX;ptrStartY=e.clientY;ptrStartTime=Date.now();ptrPeak=1;} + else{ptrPeak=Math.max(ptrPeak,ptrIds.size);} + },{passive:true}); + + document.addEventListener('pointerup',e=>{ + if(e.pointerType!=='touch')return; + ptrIds.delete(e.pointerId); + if(ptrIds.size!==0)return; + const deltaTime=Date.now()-ptrStartTime; + if(deltaTime>SWIPE_MAX_TIME){ptrPeak=0;return;} + const deltaX=e.clientX-ptrStartX; + const deltaY=e.clientY-ptrStartY; + const absX=Math.abs(deltaX); + const absY=Math.abs(deltaY); + if(ptrPeak===3&&absY>SWIPE_THRESHOLD&&absX0){ + console.log('[TOUCH] 3-finger DOWN (ptr) - toggle hidden tabs'); + ipcRenderer.send('toggle-hidden'); + }else if(ptrPeak===2&&absX>SWIPE_THRESHOLD&&absY0?'swipe-right':'swipe-left'); + }else if(ptrPeak===1&&absX>SWIPE_THRESHOLD&&absY0?'ArrowRight':'ArrowLeft'; + const keyCode=deltaX>0?39:37; + ['keydown','keyup'].forEach(eventType=>{ + document.dispatchEvent(new KeyboardEvent(eventType,{ + key:key,code:key,keyCode:keyCode,which:keyCode,bubbles:true,cancelable:true + })); + }); + } + ptrPeak=0; + },{passive:true}); + // Show pause button on user interaction (for rotation sites only) let lastUserInteraction=0; const USER_INTERACTION_THROTTLE=500; @@ -9182,6 +9227,15 @@ window.addEventListener('DOMContentLoaded',()=>{ console.log(`[KEYBOARD] State: ${visible ? 'visible' : 'hidden'}`); }); + // Shared debounce prevents double-firing when both touch and pointer events fire + let lastSwipeSent=0; + function sendSwipeIPC(direction){ + const now=Date.now(); + if(now-lastSwipeSent<500)return; + lastSwipeSent=now; + ipcRenderer.send(direction); + } + document.addEventListener('touchstart',e=>{ if(e.touches.length>=1){ touchStartX=e.touches[0].clientX; @@ -9204,25 +9258,17 @@ window.addEventListener('DOMContentLoaded',()=>{ const absX=Math.abs(deltaX); const absY=Math.abs(deltaY); - // 3-finger DOWN = toggle hidden tabs (show/hide) if(fingerCount===3 && absY>SWIPE_THRESHOLD && absX0){ console.log('[TOUCH] 3-finger DOWN - toggle hidden tabs'); ipcRenderer.send('toggle-hidden'); - } - // 2-finger vertical DOWN = keyboard (ALWAYS works, no throttling) - else if(fingerCount===2 && absY>SWIPE_THRESHOLD && absX0){ - const now = Date.now(); + }else if(fingerCount===2 && absY>SWIPE_THRESHOLD && absX0){ console.log('[TOUCH] 2-finger DOWN - toggle keyboard'); ipcRenderer.send('show-keyboard'); - lastKeyboardRequest = now; - } - // 2-finger HORIZONTAL = change tabs - else if(fingerCount===2 && absX>SWIPE_THRESHOLD && absYSWIPE_THRESHOLD && absY0?'swipe-right':'swipe-left'); - } - // 1-finger HORIZONTAL = arrow keys - else if(fingerCount===1 && absX>SWIPE_THRESHOLD && absY0?'swipe-right':'swipe-left'); + }else if(fingerCount===1 && absX>SWIPE_THRESHOLD && absY0?'ArrowRight':'ArrowLeft'; const keyCode=deltaX>0?39:37; ['keydown','keyup'].forEach(eventType=>{ @@ -9233,6 +9279,50 @@ window.addEventListener('DOMContentLoaded',()=>{ } } },{passive:true}); + + // Pointer event fallback — handles devices/drivers where touchstart/touchend don't fire + let ptrIds=new Set(); + let ptrPeak=0; + let ptrStartX=0,ptrStartY=0,ptrStartTime=0; + + document.addEventListener('pointerdown',e=>{ + if(e.pointerType!=='touch')return; + ptrIds.add(e.pointerId); + if(ptrIds.size===1){ptrStartX=e.clientX;ptrStartY=e.clientY;ptrStartTime=Date.now();ptrPeak=1;} + else{ptrPeak=Math.max(ptrPeak,ptrIds.size);} + },{passive:true}); + + document.addEventListener('pointerup',e=>{ + if(e.pointerType!=='touch')return; + ptrIds.delete(e.pointerId); + if(ptrIds.size!==0)return; + const deltaTime=Date.now()-ptrStartTime; + if(deltaTime>SWIPE_MAX_TIME){ptrPeak=0;return;} + const deltaX=e.clientX-ptrStartX; + const deltaY=e.clientY-ptrStartY; + const absX=Math.abs(deltaX); + const absY=Math.abs(deltaY); + if(ptrPeak===3&&absY>SWIPE_THRESHOLD&&absX0){ + console.log('[TOUCH] 3-finger DOWN (ptr) - toggle hidden tabs'); + ipcRenderer.send('toggle-hidden'); + }else if(ptrPeak===2&&absY>SWIPE_THRESHOLD&&absX0){ + console.log('[TOUCH] 2-finger DOWN (ptr) - toggle keyboard'); + ipcRenderer.send('show-keyboard'); + lastKeyboardRequest=Date.now(); + }else if(ptrPeak===2&&absX>SWIPE_THRESHOLD&&absY0?'swipe-right':'swipe-left'); + }else if(ptrPeak===1&&absX>SWIPE_THRESHOLD&&absY0?'ArrowRight':'ArrowLeft'; + const keyCode=deltaX>0?39:37; + ['keydown','keyup'].forEach(eventType=>{ + document.dispatchEvent(new KeyboardEvent(eventType,{ + key:key,code:key,keyCode:keyCode,which:keyCode,bubbles:true,cancelable:true + })); + }); + } + ptrPeak=0; + },{passive:true}); // Optional: Auto-show on text field focus (can be disabled) let autoShowEnabled = true; // Set to false to disable auto-show