Files
Endoleap/src/lib/canvas-bindings/pointer-capture.ts
T

15 lines
1.9 KiB
TypeScript

/**
* 浏览器指针捕获的容错边界。这里只处理 DOM 事件传输所有权;手势 token、预览和几何仍归 editor/session。
* DOM 捕获丢失不等于任意事件都能取消当前手势,必须匹配指针与捕获目标。
*/
/** Transport ownership only: document geometry and gesture tokens stay in the editor. */
/** 最小结构化 DOM 端口,让纯测试无需真实 HTMLElement。 */
export type PointerCapturePort={setPointerCapture(id:number):void;hasPointerCapture(id:number):boolean;releasePointerCapture(id:number):void};
/** 普通事件匹配 pointerId 即可;lostpointercapture 还要匹配原捕获目标且确认它已失去捕获。
* 如果同目标已重新捕获该指针,旧 lost 事件不拥有新手势;脱离 DOM 导致查询抛错则允许匹配目标清理。 */
export function ownsPointerCapture(owner:{pointerId:number;capture:unknown}|null|undefined,input:{pointerId:number;type?:string;target?:unknown}){if(!owner||owner.pointerId!==input.pointerId)return false;if(input.type!=='lostpointercapture')return true;if(input.target!==owner.capture)return false;const capture=owner.capture as Partial<PointerCapturePort>|undefined;try{if(capture?.hasPointerCapture?.(owner.pointerId))return false;}catch{/* A detached matching target may still need cancellation. */}return true;}
/** 平台可能因指针失效/节点卸载拒绝捕获,以布尔结果交给宿主决定是否继续手势。 */
export function acquirePointerCapture(target:PointerCapturePort,id:number){try{target.setPointerCapture(id);return true;}catch{return false;}}
/** 尽力释放且吞掉平台清理异常;DOM 释放失败不能取得 editor 的提交或取消权限。 */
export function releasePointerCapture(target:PointerCapturePort,id:number){try{if(target.hasPointerCapture(id))target.releasePointerCapture(id);}catch{/* Detached DOM or an already released platform capture has no editor authority. */}}