node-mac-recorder 2.20.8 → 2.20.9
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/.claude/settings.local.json +2 -1
- package/package.json +1 -1
- package/src/cursor_tracker.mm +185 -44
package/package.json
CHANGED
package/src/cursor_tracker.mm
CHANGED
|
@@ -392,56 +392,100 @@ static NSString* cursorTypeFromCursorName(NSString *value) {
|
|
|
392
392
|
|
|
393
393
|
NSString *normalized = [[value stringByReplacingOccurrencesOfString:@"_" withString:@"-"] lowercaseString];
|
|
394
394
|
|
|
395
|
-
|
|
395
|
+
// Arrow cursor patterns
|
|
396
|
+
if ([normalized containsString:@"arrow"] || [normalized containsString:@"default"]) {
|
|
396
397
|
return @"default";
|
|
397
398
|
}
|
|
399
|
+
|
|
400
|
+
// Text cursor patterns
|
|
398
401
|
if ([normalized containsString:@"ibeam"] ||
|
|
399
402
|
[normalized containsString:@"insertion"] ||
|
|
400
|
-
[normalized containsString:@"text"]
|
|
403
|
+
[normalized containsString:@"text"] ||
|
|
404
|
+
[normalized containsString:@"edit"]) {
|
|
401
405
|
return @"text";
|
|
402
406
|
}
|
|
403
|
-
|
|
407
|
+
|
|
408
|
+
// Hand cursors
|
|
409
|
+
if ([normalized containsString:@"openhand"] || [normalized containsString:@"open-hand"]) {
|
|
404
410
|
return @"grab";
|
|
405
411
|
}
|
|
406
|
-
if ([normalized containsString:@"closedhand"]) {
|
|
412
|
+
if ([normalized containsString:@"closedhand"] || [normalized containsString:@"closed-hand"]) {
|
|
407
413
|
return @"grabbing";
|
|
408
414
|
}
|
|
415
|
+
|
|
416
|
+
// Pointer cursor patterns
|
|
409
417
|
if ([normalized containsString:@"pointing"] ||
|
|
410
|
-
|
|
418
|
+
[normalized containsString:@"pointinghand"] ||
|
|
419
|
+
([normalized containsString:@"hand"] && ![normalized containsString:@"closed"] && ![normalized containsString:@"open"]) ||
|
|
420
|
+
[normalized containsString:@"link"] ||
|
|
421
|
+
[normalized containsString:@"button"]) {
|
|
411
422
|
return @"pointer";
|
|
412
423
|
}
|
|
413
|
-
|
|
424
|
+
|
|
425
|
+
// Crosshair patterns
|
|
426
|
+
if ([normalized containsString:@"crosshair"] || [normalized containsString:@"cross-hair"]) {
|
|
414
427
|
return @"crosshair";
|
|
415
428
|
}
|
|
429
|
+
|
|
430
|
+
// Not allowed patterns
|
|
416
431
|
if ([normalized containsString:@"not-allowed"] ||
|
|
417
432
|
[normalized containsString:@"notallowed"] ||
|
|
418
|
-
[normalized containsString:@"forbidden"]
|
|
433
|
+
[normalized containsString:@"forbidden"] ||
|
|
434
|
+
[normalized containsString:@"operation-not-allowed"]) {
|
|
419
435
|
return @"not-allowed";
|
|
420
436
|
}
|
|
421
|
-
|
|
437
|
+
|
|
438
|
+
// Copy cursor patterns
|
|
439
|
+
if ([normalized containsString:@"dragcopy"] ||
|
|
440
|
+
[normalized containsString:@"drag-copy"] ||
|
|
441
|
+
[normalized containsString:@"copy"]) {
|
|
422
442
|
return @"copy";
|
|
423
443
|
}
|
|
424
|
-
|
|
444
|
+
|
|
445
|
+
// Alias cursor patterns
|
|
446
|
+
if ([normalized containsString:@"draglink"] ||
|
|
447
|
+
[normalized containsString:@"drag-link"] ||
|
|
448
|
+
[normalized containsString:@"alias"]) {
|
|
425
449
|
return @"alias";
|
|
426
450
|
}
|
|
427
|
-
|
|
451
|
+
|
|
452
|
+
// Context menu patterns
|
|
453
|
+
if (([normalized containsString:@"context"] && [normalized containsString:@"menu"]) ||
|
|
454
|
+
[normalized containsString:@"contextual-menu"]) {
|
|
428
455
|
return @"context-menu";
|
|
429
456
|
}
|
|
457
|
+
|
|
458
|
+
// Zoom patterns
|
|
430
459
|
if ([normalized containsString:@"zoom"]) {
|
|
431
460
|
if ([normalized containsString:@"out"]) {
|
|
432
461
|
return @"zoom-out";
|
|
433
462
|
}
|
|
434
463
|
return @"zoom-in";
|
|
435
464
|
}
|
|
465
|
+
|
|
466
|
+
// Resize cursor patterns - more comprehensive
|
|
436
467
|
if ([normalized containsString:@"resize"] || [normalized containsString:@"size"]) {
|
|
437
|
-
|
|
438
|
-
BOOL
|
|
468
|
+
// Diagonal resize cursors
|
|
469
|
+
BOOL diagonalUp = [normalized containsString:@"diagonalup"] ||
|
|
470
|
+
[normalized containsString:@"diagonal-up"] ||
|
|
471
|
+
[normalized containsString:@"nesw"];
|
|
472
|
+
BOOL diagonalDown = [normalized containsString:@"diagonaldown"] ||
|
|
473
|
+
[normalized containsString:@"diagonal-down"] ||
|
|
474
|
+
[normalized containsString:@"nwse"];
|
|
475
|
+
|
|
476
|
+
// Horizontal and vertical resize
|
|
439
477
|
BOOL horizontal = [normalized containsString:@"leftright"] ||
|
|
478
|
+
[normalized containsString:@"left-right"] ||
|
|
440
479
|
[normalized containsString:@"horizontal"] ||
|
|
441
|
-
([normalized containsString:@"left"] && [normalized containsString:@"right"])
|
|
480
|
+
([normalized containsString:@"left"] && [normalized containsString:@"right"]) ||
|
|
481
|
+
[normalized containsString:@"col"] ||
|
|
482
|
+
[normalized containsString:@"column"];
|
|
483
|
+
|
|
442
484
|
BOOL vertical = [normalized containsString:@"updown"] ||
|
|
485
|
+
[normalized containsString:@"up-down"] ||
|
|
443
486
|
[normalized containsString:@"vertical"] ||
|
|
444
|
-
([normalized containsString:@"up"] && [normalized containsString:@"down"])
|
|
487
|
+
([normalized containsString:@"up"] && [normalized containsString:@"down"]) ||
|
|
488
|
+
[normalized containsString:@"row"];
|
|
445
489
|
|
|
446
490
|
if (diagonalUp) {
|
|
447
491
|
return @"nesw-resize";
|
|
@@ -455,6 +499,22 @@ static NSString* cursorTypeFromCursorName(NSString *value) {
|
|
|
455
499
|
if (horizontal) {
|
|
456
500
|
return @"col-resize";
|
|
457
501
|
}
|
|
502
|
+
|
|
503
|
+
// Generic resize fallback
|
|
504
|
+
return @"default"; // or could be a generic resize
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Additional specific patterns
|
|
508
|
+
if ([normalized containsString:@"wait"] || [normalized containsString:@"busy"]) {
|
|
509
|
+
return @"wait";
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if ([normalized containsString:@"help"] || [normalized containsString:@"question"]) {
|
|
513
|
+
return @"help";
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if ([normalized containsString:@"progress"]) {
|
|
517
|
+
return @"progress";
|
|
458
518
|
}
|
|
459
519
|
|
|
460
520
|
return nil;
|
|
@@ -462,9 +522,10 @@ static NSString* cursorTypeFromCursorName(NSString *value) {
|
|
|
462
522
|
|
|
463
523
|
static NSString* cursorTypeFromNSCursor(NSCursor *cursor) {
|
|
464
524
|
if (!cursor) {
|
|
465
|
-
return
|
|
525
|
+
return @"default";
|
|
466
526
|
}
|
|
467
527
|
|
|
528
|
+
// Standard macOS cursors
|
|
468
529
|
if (cursor == [NSCursor arrowCursor]) {
|
|
469
530
|
return @"default";
|
|
470
531
|
}
|
|
@@ -499,34 +560,66 @@ static NSString* cursorTypeFromNSCursor(NSCursor *cursor) {
|
|
|
499
560
|
if (cursor == [NSCursor contextualMenuCursor]) {
|
|
500
561
|
return @"context-menu";
|
|
501
562
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
563
|
+
|
|
564
|
+
// Resize cursors - improved detection
|
|
565
|
+
if ([NSCursor respondsToSelector:@selector(resizeLeftRightCursor)]) {
|
|
566
|
+
if (cursor == [NSCursor resizeLeftRightCursor]) {
|
|
567
|
+
return @"col-resize";
|
|
568
|
+
}
|
|
507
569
|
}
|
|
508
|
-
if ([NSCursor respondsToSelector:@selector(
|
|
509
|
-
(cursor == [NSCursor
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
570
|
+
if ([NSCursor respondsToSelector:@selector(resizeLeftCursor)]) {
|
|
571
|
+
if (cursor == [NSCursor resizeLeftCursor]) {
|
|
572
|
+
return @"col-resize";
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
if ([NSCursor respondsToSelector:@selector(resizeRightCursor)]) {
|
|
576
|
+
if (cursor == [NSCursor resizeRightCursor]) {
|
|
577
|
+
return @"col-resize";
|
|
578
|
+
}
|
|
513
579
|
}
|
|
580
|
+
if ([NSCursor respondsToSelector:@selector(resizeUpDownCursor)]) {
|
|
581
|
+
if (cursor == [NSCursor resizeUpDownCursor]) {
|
|
582
|
+
return @"ns-resize";
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
if ([NSCursor respondsToSelector:@selector(resizeUpCursor)]) {
|
|
586
|
+
if (cursor == [NSCursor resizeUpCursor]) {
|
|
587
|
+
return @"ns-resize";
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
if ([NSCursor respondsToSelector:@selector(resizeDownCursor)]) {
|
|
591
|
+
if (cursor == [NSCursor resizeDownCursor]) {
|
|
592
|
+
return @"ns-resize";
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
514
596
|
if ([NSCursor respondsToSelector:@selector(disappearingItemCursor)] &&
|
|
515
597
|
cursor == [NSCursor disappearingItemCursor]) {
|
|
516
598
|
return @"default";
|
|
517
599
|
}
|
|
518
600
|
|
|
519
|
-
|
|
601
|
+
// Try to get class name and description for debugging
|
|
602
|
+
NSString *className = NSStringFromClass([cursor class]);
|
|
603
|
+
NSString *description = [cursor description];
|
|
604
|
+
|
|
605
|
+
MRLog(@"🔍 Unknown cursor class: %@, description: %@", className ?: @"nil", description ?: @"nil");
|
|
606
|
+
|
|
607
|
+
// Try name-based detection
|
|
608
|
+
NSString *derived = cursorTypeFromCursorName(className);
|
|
520
609
|
if (derived) {
|
|
610
|
+
MRLog(@"🎯 Cursor type from class name: %@", derived);
|
|
521
611
|
return derived;
|
|
522
612
|
}
|
|
523
613
|
|
|
524
|
-
derived = cursorTypeFromCursorName(
|
|
614
|
+
derived = cursorTypeFromCursorName(description);
|
|
525
615
|
if (derived) {
|
|
616
|
+
MRLog(@"🎯 Cursor type from description: %@", derived);
|
|
526
617
|
return derived;
|
|
527
618
|
}
|
|
528
619
|
|
|
529
|
-
|
|
620
|
+
// Default fallback
|
|
621
|
+
MRLog(@"⚠️ Unknown cursor type, defaulting to 'default'");
|
|
622
|
+
return @"default";
|
|
530
623
|
}
|
|
531
624
|
|
|
532
625
|
static NSString* detectSystemCursorType(void) {
|
|
@@ -534,21 +627,59 @@ static NSString* detectSystemCursorType(void) {
|
|
|
534
627
|
|
|
535
628
|
void (^fetchCursorBlock)(void) = ^{
|
|
536
629
|
NSCursor *currentCursor = nil;
|
|
630
|
+
|
|
631
|
+
// Try different methods to get current cursor
|
|
537
632
|
if ([NSCursor respondsToSelector:@selector(currentSystemCursor)]) {
|
|
538
633
|
currentCursor = [NSCursor currentSystemCursor];
|
|
634
|
+
NSLog(@"🖱️ currentSystemCursor: %@", currentCursor ?: @"nil");
|
|
539
635
|
}
|
|
636
|
+
|
|
540
637
|
if (!currentCursor) {
|
|
541
638
|
currentCursor = [NSCursor currentCursor];
|
|
639
|
+
NSLog(@"🖱️ currentCursor: %@", currentCursor ?: @"nil");
|
|
542
640
|
}
|
|
543
641
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
642
|
+
if (currentCursor) {
|
|
643
|
+
NSString *className = NSStringFromClass([currentCursor class]);
|
|
644
|
+
NSString *description = [currentCursor description];
|
|
645
|
+
NSLog(@"🖱️ Cursor class: %@, description: %@", className ?: @"nil", description ?: @"nil");
|
|
646
|
+
|
|
647
|
+
// Try to identify cursor by hotspot and size (more reliable than pointer equality)
|
|
648
|
+
NSPoint hotspot = [currentCursor hotSpot];
|
|
649
|
+
NSSize cursorSize = [[currentCursor image] size];
|
|
650
|
+
|
|
651
|
+
NSLog(@"🎯 Cursor hotspot: (%.1f, %.1f), size: %.1fx%.1f",
|
|
652
|
+
hotspot.x, hotspot.y, cursorSize.width, cursorSize.height);
|
|
653
|
+
|
|
654
|
+
// Common cursor patterns by hotspot (adjusted for modern macOS cursor sizes)
|
|
655
|
+
if ((hotspot.x >= 0.0 && hotspot.x <= 3.0) && (hotspot.y >= 0.0 && hotspot.y <= 3.0)) {
|
|
656
|
+
// Arrow cursor typically has hotspot at top-left corner
|
|
657
|
+
cursorType = @"default";
|
|
658
|
+
NSLog(@"🎯 ARROW CURSOR (by hotspot) -> default");
|
|
659
|
+
} else if ((hotspot.x >= 12.0 && hotspot.x <= 16.0) && (hotspot.y >= 6.0 && hotspot.y <= 10.0)) {
|
|
660
|
+
// I-beam cursor typically has hotspot around middle
|
|
661
|
+
cursorType = @"text";
|
|
662
|
+
NSLog(@"🎯 IBEAM CURSOR (by hotspot) -> text");
|
|
663
|
+
} else if ((hotspot.x >= 5.0 && hotspot.x <= 10.0) && (hotspot.y >= 0.0 && hotspot.y <= 4.0)) {
|
|
664
|
+
// Pointing hand cursor typically has hotspot at finger tip
|
|
665
|
+
cursorType = @"pointer";
|
|
666
|
+
NSLog(@"🎯 POINTING HAND CURSOR (by hotspot) -> pointer");
|
|
667
|
+
} else {
|
|
668
|
+
// Fallback to more detailed analysis
|
|
669
|
+
NSString *derivedType = cursorTypeFromNSCursor(currentCursor);
|
|
670
|
+
if (derivedType && ![derivedType isEqualToString:@"default"]) {
|
|
671
|
+
cursorType = derivedType;
|
|
672
|
+
NSLog(@"🎯 SYSTEM CURSOR TYPE (derived): %@", cursorType);
|
|
673
|
+
} else {
|
|
674
|
+
// Use accessibility detection if system cursor is generic
|
|
675
|
+
cursorType = @"default";
|
|
676
|
+
NSLog(@"🎯 SYSTEM CURSOR TYPE -> default (will try AX)");
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
} else {
|
|
680
|
+
NSLog(@"🖱️ No current cursor found");
|
|
548
681
|
cursorType = @"default";
|
|
549
682
|
}
|
|
550
|
-
|
|
551
|
-
MRLog(@"🎯 SYSTEM CURSOR TYPE: %@", cursorType ? cursorType : @"(nil)");
|
|
552
683
|
};
|
|
553
684
|
|
|
554
685
|
if ([NSThread isMainThread]) {
|
|
@@ -564,7 +695,7 @@ NSString* getCursorType() {
|
|
|
564
695
|
@autoreleasepool {
|
|
565
696
|
g_cursorTypeCounter++;
|
|
566
697
|
|
|
567
|
-
//
|
|
698
|
+
// Get cursor position first
|
|
568
699
|
BOOL hasCursorPosition = NO;
|
|
569
700
|
CGPoint cursorPos = CGPointZero;
|
|
570
701
|
|
|
@@ -589,25 +720,35 @@ NSString* getCursorType() {
|
|
|
589
720
|
}
|
|
590
721
|
}
|
|
591
722
|
|
|
723
|
+
// Try multiple detection methods
|
|
724
|
+
NSString *systemCursorType = detectSystemCursorType();
|
|
592
725
|
NSString *axCursorType = nil;
|
|
726
|
+
|
|
593
727
|
if (hasCursorPosition) {
|
|
594
728
|
axCursorType = detectCursorTypeUsingAccessibility(cursorPos);
|
|
595
729
|
}
|
|
596
730
|
|
|
597
|
-
NSString *
|
|
731
|
+
NSString *finalType = @"default";
|
|
598
732
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
733
|
+
// System cursor has priority since it's more accurate for visual state
|
|
734
|
+
NSLog(@"🎯 CURSOR DECISION: system='%@', ax='%@'", systemCursorType ?: @"nil", axCursorType ?: @"nil");
|
|
735
|
+
|
|
736
|
+
// Use system cursor if available (it's more accurate for visual appearance)
|
|
737
|
+
if (systemCursorType && [systemCursorType length] > 0) {
|
|
603
738
|
finalType = systemCursorType;
|
|
604
|
-
|
|
739
|
+
NSLog(@"🎯 Using SYSTEM cursor: %@", finalType);
|
|
740
|
+
}
|
|
741
|
+
// Fallback to AX cursor if system cursor is not available
|
|
742
|
+
else if (axCursorType && [axCursorType length] > 0) {
|
|
605
743
|
finalType = axCursorType;
|
|
606
|
-
|
|
607
|
-
|
|
744
|
+
NSLog(@"🎯 Using AX cursor (fallback): %@", finalType);
|
|
745
|
+
}
|
|
746
|
+
// Final fallback
|
|
747
|
+
else {
|
|
748
|
+
NSLog(@"🎯 Fallback to default cursor");
|
|
608
749
|
}
|
|
609
750
|
|
|
610
|
-
|
|
751
|
+
NSLog(@"🎯 FINAL CURSOR TYPE: %@", finalType);
|
|
611
752
|
return finalType;
|
|
612
753
|
}
|
|
613
754
|
}
|