@@ -33,6 +33,7 @@ export class CursorOverlay {
3333 private readonly followIntervalMs : number ;
3434 private settings : CursorOverlaySettings ;
3535 private followTimer : NodeJS . Timeout | null = null ;
36+ private dragActive = false ;
3637
3738 constructor ( private readonly options : CursorOverlayOptions ) {
3839 this . idleTimeoutMs = options . idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS ;
@@ -68,7 +69,7 @@ export class CursorOverlay {
6869 setSettings ( settings : CursorOverlaySettings ) : void {
6970 const previous = this . settings ;
7071 this . settings = normalizeCursorOverlaySettings ( settings ) ;
71- if ( ! this . settings . enabled || this . settings . visibility !== 'whileControlling' ) {
72+ if ( ! this . settings . enabled || ! this . shouldFollowCursor ( ) ) {
7273 this . stopFollowing ( ) ;
7374 }
7475 if ( ! this . settings . enabled ) {
@@ -85,13 +86,31 @@ export class CursorOverlay {
8586 }
8687
8788 markControlActive ( ) : void {
88- if ( ! this . settings . enabled || this . settings . visibility !== 'whileControlling' ) return ;
89+ if ( ! this . settings . enabled || ! this . shouldFollowCursor ( ) ) return ;
8990 this . startFollowing ( ) ;
9091 }
9192
93+ setDragActive ( active : boolean ) : void {
94+ if ( this . dragActive === active ) return ;
95+
96+ this . dragActive = active ;
97+ if ( ! this . settings . enabled ) return ;
98+
99+ if ( this . dragActive ) {
100+ this . startFollowing ( ) ;
101+ return ;
102+ }
103+
104+ if ( this . shouldFollowCursor ( ) ) {
105+ this . refreshPersistentOverlay ( ) ;
106+ } else {
107+ this . stopFollowing ( ) ;
108+ }
109+ }
110+
92111 show ( event : CursorOverlayEvent ) : void {
93112 if ( ! this . settings . enabled ) return ;
94- if ( this . settings . visibility === 'whileControlling' ) {
113+ if ( this . shouldFollowCursor ( ) ) {
95114 this . startFollowing ( ) ;
96115 }
97116 this . backend . show ( event , this . renderOptions ( ) ) ;
@@ -103,6 +122,7 @@ export class CursorOverlay {
103122 }
104123
105124 endControlSession ( ) : void {
125+ this . dragActive = false ;
106126 this . hide ( ) ;
107127 }
108128
@@ -112,14 +132,14 @@ export class CursorOverlay {
112132 }
113133
114134 private startFollowing ( ) : void {
115- this . refreshPersistentOverlay ( ) ;
116135 if ( this . followTimer ) return ;
136+ this . refreshPersistentOverlay ( ) ;
117137 this . followTimer = setInterval ( ( ) => {
118- if ( ! this . settings . enabled || this . settings . visibility !== 'whileControlling' ) {
138+ if ( ! this . settings . enabled || ! this . shouldFollowCursor ( ) ) {
119139 this . hide ( ) ;
120140 return ;
121141 }
122- this . backend . show ( 'move' , this . renderOptions ( ) ) ;
142+ this . backend . show ( this . currentPersistentEvent ( ) , this . renderOptions ( ) ) ;
123143 } , this . followIntervalMs ) ;
124144 this . followTimer . unref ?.( ) ;
125145 }
@@ -132,23 +152,31 @@ export class CursorOverlay {
132152 }
133153
134154 private refreshPersistentOverlay ( ) : void {
135- if ( ! this . settings . enabled || this . settings . visibility !== 'whileControlling' ) return ;
136- this . backend . show ( 'move' , this . renderOptions ( ) ) ;
155+ if ( ! this . settings . enabled || ! this . shouldFollowCursor ( ) ) return ;
156+ this . backend . show ( this . currentPersistentEvent ( ) , this . renderOptions ( ) ) ;
137157 }
138158
139159 private renderOptions ( ) : CursorOverlayRenderOptions {
140160 return {
141161 size : this . resolveSizePixels ( ) ,
142162 idleTimeoutMs : this . idleTimeoutMs ,
143163 crosshairs : this . settings . crosshairs ,
144- persistent : this . settings . visibility === 'whileControlling' ,
164+ persistent : this . shouldFollowCursor ( ) ,
145165 colorRgb : resolveCursorOverlayColorRgb ( this . settings . color )
146166 } ;
147167 }
148168
149169 private resolveSizePixels ( ) : number {
150170 return resolveCursorOverlaySizePixels ( this . settings . size ) ;
151171 }
172+
173+ private shouldFollowCursor ( ) : boolean {
174+ return this . settings . visibility === 'whileControlling' || this . dragActive ;
175+ }
176+
177+ private currentPersistentEvent ( ) : CursorOverlayEvent {
178+ return this . dragActive ? 'drag' : 'move' ;
179+ }
152180}
153181
154182type ElectronCursorOverlayBackendOptions = {
@@ -313,7 +341,7 @@ function createOverlayEventScript(
313341 }
314342) : string {
315343 return `
316- document.body.className = ${ JSON . stringify ( event === 'click' ? 'click' : 'move' ) } ;
344+ document.body.className = ${ JSON . stringify ( event ) } ;
317345 document.body.classList.toggle('crosshairs-enabled', ${ JSON . stringify ( options . crosshairs ) } );
318346 document.documentElement.style.setProperty('--overlay-rgb', '${ options . colorRgb . join ( ', ' ) } ');
319347 document.documentElement.style.setProperty('--center-x', '${ Math . round ( options . centerX ) } px');
@@ -405,6 +433,32 @@ function createOverlayHtml(): string {
405433 animation: click-pulse 180ms ease-out;
406434 }
407435
436+ .drag-dot {
437+ position: absolute;
438+ left: var(--center-x, 64px);
439+ top: var(--center-y, 64px);
440+ display: none;
441+ width: calc(var(--ring-size, 72px) * 0.22);
442+ height: calc(var(--ring-size, 72px) * 0.22);
443+ border-radius: 999px;
444+ background: rgba(var(--overlay-rgb, 211, 47, 47), 0.94);
445+ box-shadow:
446+ 0 0 0 4px rgba(var(--overlay-rgb, 211, 47, 47), 0.18),
447+ 0 0 18px rgba(var(--overlay-rgb, 211, 47, 47), 0.45);
448+ transform: translate(-50%, -50%);
449+ }
450+
451+ body.drag .ring {
452+ border-width: calc(var(--ring-stroke, 5px) + 1px);
453+ box-shadow:
454+ 0 0 0 calc(var(--glow-stroke, 24px) * 0.5) rgba(var(--overlay-rgb, 211, 47, 47), 0.26),
455+ 0 0 42px rgba(var(--overlay-rgb, 211, 47, 47), 0.54);
456+ }
457+
458+ body.drag .drag-dot {
459+ display: block;
460+ }
461+
408462 @keyframes click-pulse {
409463 0% {
410464 transform: translate(-50%, -50%) scale(0.82);
@@ -425,6 +479,7 @@ function createOverlayHtml(): string {
425479 <div class="crosshair crosshair-horizontal"></div>
426480 <div class="crosshair crosshair-vertical"></div>
427481 <div class="ring"></div>
482+ <div class="drag-dot"></div>
428483 </body>
429484</html>` ;
430485}
0 commit comments