@@ -11,23 +11,54 @@ export function useLaunchHudInteractionState({
1111 isWebcamPreviewDraggingRef : RefObject < boolean > ;
1212 webcamPreviewDragStartRef : RefObject < unknown > ;
1313} ) {
14- const anyPopoverOpenRef = useRef ( false ) ;
1514 const isMouseOverHudRef = useRef ( false ) ;
15+ const timeoutRef = useRef < NodeJS . Timeout | null > ( null ) ;
1616
1717 useEffect ( ( ) => {
18- anyPopoverOpenRef . current = openId !== null ;
1918 if ( openId !== null ) {
2019 window . electronAPI ?. hudOverlaySetIgnoreMouse ?.( false ) ;
2120 } else {
2221 // Proactively check if we should ignore mouse when popover closes
2322 setTimeout ( ( ) => {
24- if ( ! isMouseOverHudRef . current && ! anyPopoverOpenRef . current ) {
23+ if ( ! isMouseOverHudRef . current ) {
2524 window . electronAPI ?. hudOverlaySetIgnoreMouse ?.( true ) ;
2625 }
2726 } , 150 ) ;
2827 }
2928 } , [ openId ] ) ;
3029
30+ useEffect ( ( ) => {
31+ const handleMouseOver = ( e : globalThis . MouseEvent ) => {
32+ const target = e . target as HTMLElement | null ;
33+ if ( ! target ) return ;
34+ const isInteractive = ! ! target . closest (
35+ ".pointer-events-auto, [data-hud-interactive], [data-radix-popper-content-wrapper]"
36+ ) ;
37+
38+ if ( isInteractive ) {
39+ isMouseOverHudRef . current = true ;
40+ if ( timeoutRef . current ) clearTimeout ( timeoutRef . current ) ;
41+ window . electronAPI ?. hudOverlaySetIgnoreMouse ?.( false ) ;
42+ } else {
43+ isMouseOverHudRef . current = false ;
44+ if ( timeoutRef . current ) clearTimeout ( timeoutRef . current ) ;
45+ timeoutRef . current = setTimeout ( ( ) => {
46+ if (
47+ ! isHudDraggingRef . current &&
48+ ! isWebcamPreviewDraggingRef . current &&
49+ ! webcamPreviewDragStartRef . current &&
50+ ! isMouseOverHudRef . current
51+ ) {
52+ window . electronAPI ?. hudOverlaySetIgnoreMouse ?.( true ) ;
53+ }
54+ } , 300 ) ;
55+ }
56+ } ;
57+
58+ window . addEventListener ( "mouseover" , handleMouseOver ) ;
59+ return ( ) => window . removeEventListener ( "mouseover" , handleMouseOver ) ;
60+ } , [ isHudDraggingRef , isWebcamPreviewDraggingRef , webcamPreviewDragStartRef ] ) ;
61+
3162 const beginInteractiveHudAction = useCallback ( ( ) => {
3263 isMouseOverHudRef . current = true ;
3364 window . electronAPI ?. hudOverlaySetIgnoreMouse ?.( false ) ;
@@ -39,8 +70,6 @@ export function useLaunchHudInteractionState({
3970 window . electronAPI ?. hudOverlaySetIgnoreMouse ?.( false ) ;
4071 } , [ ] ) ;
4172
42- const timeoutRef = useRef < NodeJS . Timeout | null > ( null ) ;
43-
4473 const handleHudMouseLeave = useCallback ( ( event : MouseEvent < HTMLDivElement > ) => {
4574 const nextTarget = event . relatedTarget ;
4675 if ( nextTarget instanceof Node && event . currentTarget . contains ( nextTarget ) ) {
@@ -56,11 +85,8 @@ export function useLaunchHudInteractionState({
5685 ! isHudDraggingRef . current &&
5786 ! isWebcamPreviewDraggingRef . current &&
5887 ! webcamPreviewDragStartRef . current &&
59- ! isMouseOverHudRef . current &&
60- ! anyPopoverOpenRef . current
88+ ! isMouseOverHudRef . current
6189 ) {
62- // If a popover is open, we can still ignore mouse if the mouse is truly gone,
63- // but we give a bit more breathing room (the 300ms timeout).
6490 window . electronAPI ?. hudOverlaySetIgnoreMouse ?.( true ) ;
6591 }
6692 } , 300 ) ;
0 commit comments