node-mac-recorder 2.20.4 → 2.20.6

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.20.4",
3
+ "version": "2.20.6",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -106,7 +106,7 @@ static BOOL CopyAttributeBoolean(AXUIElementRef element, CFStringRef attribute,
106
106
  return YES;
107
107
  }
108
108
 
109
- static BOOL ElementHasAction(AXUIElementRef element, CFStringRef action) {
109
+ static __attribute__((unused)) BOOL ElementHasAction(AXUIElementRef element, CFStringRef action) {
110
110
  if (!element || !action) {
111
111
  return NO;
112
112
  }
@@ -248,13 +248,7 @@ static NSString* CursorTypeFromAccessibilityElement(AXUIElementRef element, CGPo
248
248
  CFRelease(valueAttribute);
249
249
  }
250
250
 
251
- if (StringEqualsAny(role, @[@"AXProgressIndicator", @"AXBusyIndicator"])) {
252
- return @"progress";
253
- }
254
-
255
- if (StringEqualsAny(role, @[@"AXHelpTag", @"AXTooltip"])) {
256
- return @"help";
257
- }
251
+ // Leave progress/help to system cursor; don't force via AX
258
252
 
259
253
  if ([role isEqualToString:@"AXSplitter"]) {
260
254
  NSString *orientation = CopyAttributeString(element, CFSTR("AXOrientation"));
@@ -273,11 +267,11 @@ static NSString* CursorTypeFromAccessibilityElement(AXUIElementRef element, CGPo
273
267
  }
274
268
  }
275
269
 
276
- if (StringEqualsAny(role, @[@"AXMenuItem", @"AXButton", @"AXLink", @"AXTab", @"AXRadioButton", @"AXCheckBox", @"AXPopUpButton"])) {
270
+ // Pointer (hand) only for actual links; buttons remain default arrow on macOS
271
+ if (StringEqualsAny(role, @[@"AXLink"])) {
277
272
  return @"pointer";
278
273
  }
279
-
280
- if (StringEqualsAny(subrole, @[@"AXLink", @"AXToolbarButton", @"AXFileDrop", @"AXDropTarget"])) {
274
+ if (StringEqualsAny(subrole, @[@"AXLink"])) {
281
275
  return @"pointer";
282
276
  }
283
277
 
@@ -295,11 +289,7 @@ static NSString* CursorTypeFromAccessibilityElement(AXUIElementRef element, CGPo
295
289
  }
296
290
  }
297
291
 
298
- if (ElementHasAction(element, kAXPressAction) ||
299
- ElementHasAction(element, kAXShowMenuAction) ||
300
- ElementHasAction(element, CFSTR("AXConfirm"))) {
301
- return @"pointer";
302
- }
292
+ // Actions alone do not imply pointer hand on macOS; ignore
303
293
 
304
294
  CFTypeRef urlValue = NULL;
305
295
  if (AXUIElementCopyAttributeValue(element, kAXURLAttribute, &urlValue) == kAXErrorSuccess && urlValue) {
@@ -310,23 +300,37 @@ static NSString* CursorTypeFromAccessibilityElement(AXUIElementRef element, CGPo
310
300
  CFRelease(urlValue);
311
301
  }
312
302
 
313
- BOOL isDraggable = NO;
314
- if (CopyAttributeBoolean(element, CFSTR("AXDraggable"), &isDraggable) && isDraggable) {
315
- return @"grab";
316
- }
303
+ // Grab/open-hand often comes from system cursor; avoid forcing via AX
317
304
 
318
- BOOL isMovable = NO;
319
- if (CopyAttributeBoolean(element, CFSTR("AXMovable"), &isMovable) && isMovable) {
320
- return @"grab";
321
- }
305
+ // Zoom is rare; prefer system cursor unless explicitly needed
306
+
307
+ return nil;
308
+ }
322
309
 
323
- if (subrole && [subrole isEqualToString:@"AXZoomIn"]) {
324
- return @"zoom-in";
325
- }
326
- if (subrole && [subrole isEqualToString:@"AXZoomOut"]) {
327
- return @"zoom-out";
310
+ static AXUIElementRef CopyParent(AXUIElementRef element) {
311
+ if (!element) return NULL;
312
+ AXUIElementRef parent = NULL;
313
+ if (AXUIElementCopyAttributeValue(element, kAXParentAttribute, (CFTypeRef *)&parent) == kAXErrorSuccess && parent) {
314
+ return parent; // retained
328
315
  }
316
+ if (parent) CFRelease(parent);
317
+ return NULL;
318
+ }
329
319
 
320
+ static NSString* CursorTypeFromElementOrAncestors(AXUIElementRef element, CGPoint cursorPos, int maxDepth) {
321
+ AXUIElementRef current = element;
322
+ int depth = 0;
323
+ while (current && depth < maxDepth) {
324
+ NSString *t = CursorTypeFromAccessibilityElement(current, cursorPos);
325
+ if (t && [t length] > 0) {
326
+ return t;
327
+ }
328
+ AXUIElementRef parent = CopyParent(current);
329
+ if (current != element) CFRelease(current);
330
+ current = parent;
331
+ depth++;
332
+ }
333
+ if (current && current != element) CFRelease(current);
330
334
  return nil;
331
335
  }
332
336
 
@@ -348,7 +352,7 @@ static NSString* detectCursorTypeUsingAccessibility(CGPoint cursorPos) {
348
352
  AXUIElementRef elementAtPosition = NULL;
349
353
  AXError error = AXUIElementCopyElementAtPosition(systemWide, cursorPos.x, cursorPos.y, &elementAtPosition);
350
354
  if (error == kAXErrorSuccess && elementAtPosition) {
351
- cursorType = CursorTypeFromAccessibilityElement(elementAtPosition, cursorPos);
355
+ cursorType = CursorTypeFromElementOrAncestors(elementAtPosition, cursorPos, 6);
352
356
  CFRelease(elementAtPosition);
353
357
  }
354
358
 
@@ -359,7 +363,7 @@ static NSString* detectCursorTypeUsingAccessibility(CGPoint cursorPos) {
359
363
  AXError hitError = AXUIElementCopyParameterizedAttributeValue(systemWide, kAXHitTestParameterizedAttribute, pointValue, (CFTypeRef *)&hitElement);
360
364
  CFRelease(pointValue);
361
365
  if (hitError == kAXErrorSuccess && hitElement) {
362
- cursorType = CursorTypeFromAccessibilityElement(hitElement, cursorPos);
366
+ cursorType = CursorTypeFromElementOrAncestors(hitElement, cursorPos, 6);
363
367
  CFRelease(hitElement);
364
368
  }
365
369
  }
@@ -559,51 +563,13 @@ NSString* getCursorType() {
559
563
  @autoreleasepool {
560
564
  g_cursorTypeCounter++;
561
565
 
566
+ // Use only the system cursor type for live detection.
562
567
  NSString *systemCursorType = detectSystemCursorType();
563
-
564
- NSString *axCursorType = nil;
565
- BOOL hasCursorPosition = NO;
566
- CGPoint cursorPos = CGPointZero;
567
-
568
- CGEventRef event = CGEventCreate(NULL);
569
- if (event) {
570
- cursorPos = CGEventGetLocation(event);
571
- hasCursorPosition = YES;
572
- CFRelease(event);
568
+ if (systemCursorType && [systemCursorType length] > 0) {
569
+ NSLog(@"🎯 FINAL CURSOR TYPE (System): %@", systemCursorType);
570
+ return systemCursorType;
573
571
  }
574
-
575
- if (!hasCursorPosition) {
576
- if ([NSThread isMainThread]) {
577
- cursorPos = [NSEvent mouseLocation];
578
- hasCursorPosition = YES;
579
- } else {
580
- __block CGPoint fallbackPos = CGPointZero;
581
- dispatch_sync(dispatch_get_main_queue(), ^{
582
- fallbackPos = [NSEvent mouseLocation];
583
- });
584
- cursorPos = fallbackPos;
585
- hasCursorPosition = YES;
586
- }
587
- }
588
-
589
- if (hasCursorPosition) {
590
- axCursorType = detectCursorTypeUsingAccessibility(cursorPos);
591
- }
592
-
593
- NSString *finalType = nil;
594
- if (axCursorType && ![axCursorType isEqualToString:@"default"]) {
595
- finalType = axCursorType;
596
- } else if (systemCursorType && [systemCursorType length] > 0) {
597
- // Prefer the system cursor when accessibility reports a generic value.
598
- finalType = systemCursorType;
599
- } else if (axCursorType && [axCursorType length] > 0) {
600
- finalType = axCursorType;
601
- } else {
602
- finalType = @"default";
603
- }
604
-
605
- NSLog(@"🎯 FINAL CURSOR TYPE: %@", finalType);
606
- return finalType;
572
+ return @"default";
607
573
  }
608
574
  }
609
575
 
@@ -658,6 +624,7 @@ CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef eve
658
624
  NSTimeInterval timestamp = [currentDate timeIntervalSinceDate:g_trackingStartTime] * 1000; // milliseconds
659
625
  NSTimeInterval unixTimeMs = [currentDate timeIntervalSince1970] * 1000; // unix timestamp in milliseconds
660
626
  NSString *cursorType = getCursorType();
627
+ // (already captured above)
661
628
  NSString *eventType = @"move";
662
629
 
663
630
  // Event tipini belirle