node-mac-recorder 2.17.14 → 2.17.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.17.14",
3
+ "version": "2.17.15",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -43,9 +43,9 @@ static NSTimeInterval g_lastCursorCheckTime = 0;
43
43
  static int g_sameCursorDetectionCount = 0;
44
44
  static NSString *g_pendingCursorType = nil;
45
45
 
46
- // Cursor stability constants - more responsive
47
- static const NSTimeInterval CURSOR_STABILITY_THRESHOLD = 0.05; // 50ms (faster response)
48
- static const int CURSOR_CONFIRMATION_COUNT = 1; // Need 1 detection (more responsive)
46
+ // Cursor stability constants - minimal stability for real-time response
47
+ static const NSTimeInterval CURSOR_STABILITY_THRESHOLD = 0.02; // 20ms (very fast)
48
+ static const int CURSOR_CONFIRMATION_COUNT = 1; // Immediate response
49
49
 
50
50
  // Mouse button state tracking
51
51
  static bool g_leftMouseDown = false;
@@ -261,9 +261,18 @@ NSString* getCursorType() {
261
261
  else if ([elementRole isEqualToString:@"AXProgressIndicator"]) {
262
262
  contextualCursorType = @"progress";
263
263
  }
264
- // OTHER ELEMENTS - be conservative, don't assume pointer
264
+ // DEFAULT AREAS - explicitly set default for known non-interactive elements
265
+ else if ([elementRole isEqualToString:@"AXApplication"] ||
266
+ [elementRole isEqualToString:@"AXWindow"] ||
267
+ [elementRole isEqualToString:@"AXScrollArea"] ||
268
+ [elementRole isEqualToString:@"AXScrollBar"] ||
269
+ [elementRole isEqualToString:@"AXStaticText"] ||
270
+ [elementRole isEqualToString:@"AXGroup"]) {
271
+ // These are typically non-interactive - should be default cursor
272
+ contextualCursorType = @"default";
273
+ }
274
+ // OTHER ELEMENTS - let NSCursor handle or default
265
275
  else {
266
- // Don't override NSCursor for unknown elements
267
276
  contextualCursorType = nil;
268
277
  }
269
278
  }
@@ -271,59 +280,68 @@ NSString* getCursorType() {
271
280
  }
272
281
  if (systemWide) CFRelease(systemWide);
273
282
 
274
- // Layer 3: Intelligent fusion of NSCursor and contextual results
283
+ // Layer 3: Contextual-first approach (NSCursor is unreliable)
275
284
  NSString *detectedCursorType = @"default";
276
285
 
277
- // Priority logic with better fallback:
278
- // 1. If contextual gives resize cursor, always use it (resize has highest priority)
279
- if (contextualCursorType != nil &&
280
- ([contextualCursorType hasSuffix:@"resize"] ||
281
- [contextualCursorType isEqualToString:@"col-resize"] ||
282
- [contextualCursorType isEqualToString:@"ns-resize"])) {
286
+ // Priority logic - contextual detection first:
287
+ // 1. If contextual gives ANY specific cursor, use it
288
+ if (contextualCursorType != nil) {
283
289
  detectedCursorType = contextualCursorType;
284
290
  }
285
- // 2. If NSCursor gives a definitive answer, use it
286
- else if (nsCursorType != nil) {
291
+ // 2. Fallback to NSCursor only for very specific cases
292
+ else if (nsCursorType != nil &&
293
+ ([nsCursorType isEqualToString:@"text"] ||
294
+ [nsCursorType isEqualToString:@"pointer"])) {
295
+ // Only trust NSCursor for text and pointer (most reliable)
287
296
  detectedCursorType = nsCursorType;
288
297
  }
289
- // 3. If contextual gives specific non-resize cursor, use it
290
- else if (contextualCursorType != nil &&
291
- ![contextualCursorType isEqualToString:@"default"]) {
292
- detectedCursorType = contextualCursorType;
293
- }
294
- // 4. If both are nil or default, use true default
298
+ // 3. Everything else defaults to default
295
299
  else {
296
300
  detectedCursorType = @"default";
297
301
  }
298
302
 
299
- // Layer 4: Stability filtering to prevent oscillation
303
+ // Layer 4: Minimal stability - mostly real-time with quick default fallback
304
+ NSString *finalCursorType = detectedCursorType;
300
305
 
301
- // Time-based stability check
306
+ // Quick validation and immediate response for most cases
302
307
  if (currentTime - g_lastCursorCheckTime > CURSOR_STABILITY_THRESHOLD) {
303
- // Enough time has passed, reset counters
304
- g_sameCursorDetectionCount = 0;
305
- g_pendingCursorType = detectedCursorType;
306
- }
307
-
308
- // Check if detected cursor matches pending cursor
309
- if ([detectedCursorType isEqualToString:g_pendingCursorType]) {
310
- g_sameCursorDetectionCount++;
311
-
312
- // If we have enough confirmations, update stable cursor
313
- if (g_sameCursorDetectionCount >= CURSOR_CONFIRMATION_COUNT) {
308
+ // Update immediately for most cursor types
309
+ if ([detectedCursorType isEqualToString:@"default"] ||
310
+ [detectedCursorType isEqualToString:@"text"] ||
311
+ [detectedCursorType isEqualToString:@"pointer"]) {
312
+ // High-confidence cursor types - update immediately
313
+ g_stableCursorType = detectedCursorType;
314
+ finalCursorType = detectedCursorType;
315
+ }
316
+ // Resize cursors need tiny bit of stability to avoid jitter
317
+ else if ([detectedCursorType hasSuffix:@"resize"]) {
318
+ if ([detectedCursorType isEqualToString:g_pendingCursorType]) {
319
+ g_sameCursorDetectionCount++;
320
+ if (g_sameCursorDetectionCount >= CURSOR_CONFIRMATION_COUNT) {
321
+ g_stableCursorType = detectedCursorType;
322
+ finalCursorType = detectedCursorType;
323
+ } else {
324
+ finalCursorType = g_stableCursorType; // Keep previous
325
+ }
326
+ } else {
327
+ g_pendingCursorType = detectedCursorType;
328
+ g_sameCursorDetectionCount = 1;
329
+ finalCursorType = g_stableCursorType; // Keep previous
330
+ }
331
+ }
332
+ // Everything else - immediate update
333
+ else {
314
334
  g_stableCursorType = detectedCursorType;
315
- g_lastDetectedCursorType = detectedCursorType;
335
+ finalCursorType = detectedCursorType;
316
336
  }
337
+
338
+ g_lastCursorCheckTime = currentTime;
317
339
  } else {
318
- // Different cursor detected, start new pending
319
- g_pendingCursorType = detectedCursorType;
320
- g_sameCursorDetectionCount = 1;
340
+ // Too soon - use stable cursor
341
+ finalCursorType = g_stableCursorType;
321
342
  }
322
343
 
323
- g_lastCursorCheckTime = currentTime;
324
-
325
- // Final validation
326
- NSString *finalCursorType = g_stableCursorType;
344
+ // Final fallback validation
327
345
  if (!finalCursorType || [finalCursorType length] == 0) {
328
346
  finalCursorType = @"default";
329
347
  }