node-mac-recorder 2.20.8 → 2.20.10
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 +202 -43
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,67 @@ 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
|
+
// Use more direct cursor detection approach
|
|
648
|
+
NSImage *cursorImage = [currentCursor image];
|
|
649
|
+
NSPoint hotspot = [currentCursor hotSpot];
|
|
650
|
+
NSSize imageSize = [cursorImage size];
|
|
651
|
+
|
|
652
|
+
NSLog(@"🎯 Cursor analysis: size=%.1fx%.1f, hotspot=(%.1f,%.1f)",
|
|
653
|
+
imageSize.width, imageSize.height, hotspot.x, hotspot.y);
|
|
654
|
+
|
|
655
|
+
// Updated pattern recognition based on observed values
|
|
656
|
+
if (imageSize.width >= 8.0 && imageSize.width <= 12.0 &&
|
|
657
|
+
imageSize.height >= 16.0 && imageSize.height <= 20.0 &&
|
|
658
|
+
hotspot.x >= 3.0 && hotspot.x <= 5.0 && hotspot.y >= 8.0 && hotspot.y <= 10.0) {
|
|
659
|
+
// I-beam cursor: narrow and tall, hotspot in middle
|
|
660
|
+
cursorType = @"text";
|
|
661
|
+
NSLog(@"🎯 DETECTED IBEAM CURSOR -> text");
|
|
662
|
+
}
|
|
663
|
+
else if (imageSize.width <= 20.0 && imageSize.height <= 25.0 &&
|
|
664
|
+
hotspot.x <= 5.0 && hotspot.y <= 5.0) {
|
|
665
|
+
// Arrow cursor: small size, hotspot at top-left
|
|
666
|
+
cursorType = @"default";
|
|
667
|
+
NSLog(@"🎯 DETECTED ARROW CURSOR -> default");
|
|
668
|
+
}
|
|
669
|
+
else if (imageSize.width >= 15.0 && imageSize.width <= 25.0 &&
|
|
670
|
+
imageSize.height >= 15.0 && imageSize.height <= 25.0 &&
|
|
671
|
+
hotspot.x >= 5.0 && hotspot.x <= 10.0 && hotspot.y <= 8.0) {
|
|
672
|
+
// Hand cursor: squarish, hotspot at fingertip
|
|
673
|
+
cursorType = @"pointer";
|
|
674
|
+
NSLog(@"🎯 DETECTED HAND CURSOR -> pointer");
|
|
675
|
+
}
|
|
676
|
+
else {
|
|
677
|
+
// Try to use a different approach - cursor name introspection
|
|
678
|
+
NSString *derived = cursorTypeFromNSCursor(currentCursor);
|
|
679
|
+
if (derived && ![derived isEqualToString:@"default"]) {
|
|
680
|
+
cursorType = derived;
|
|
681
|
+
NSLog(@"🎯 DERIVED FROM ANALYSIS: %@", cursorType);
|
|
682
|
+
} else {
|
|
683
|
+
cursorType = @"default";
|
|
684
|
+
NSLog(@"🎯 FALLBACK TO DEFAULT (will check AX)");
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
} else {
|
|
688
|
+
NSLog(@"🖱️ No current cursor found");
|
|
548
689
|
cursorType = @"default";
|
|
549
690
|
}
|
|
550
|
-
|
|
551
|
-
MRLog(@"🎯 SYSTEM CURSOR TYPE: %@", cursorType ? cursorType : @"(nil)");
|
|
552
691
|
};
|
|
553
692
|
|
|
554
693
|
if ([NSThread isMainThread]) {
|
|
@@ -564,7 +703,7 @@ NSString* getCursorType() {
|
|
|
564
703
|
@autoreleasepool {
|
|
565
704
|
g_cursorTypeCounter++;
|
|
566
705
|
|
|
567
|
-
//
|
|
706
|
+
// Get cursor position first
|
|
568
707
|
BOOL hasCursorPosition = NO;
|
|
569
708
|
CGPoint cursorPos = CGPointZero;
|
|
570
709
|
|
|
@@ -589,25 +728,45 @@ NSString* getCursorType() {
|
|
|
589
728
|
}
|
|
590
729
|
}
|
|
591
730
|
|
|
731
|
+
// Try multiple detection methods
|
|
732
|
+
NSString *systemCursorType = detectSystemCursorType();
|
|
592
733
|
NSString *axCursorType = nil;
|
|
734
|
+
|
|
593
735
|
if (hasCursorPosition) {
|
|
594
736
|
axCursorType = detectCursorTypeUsingAccessibility(cursorPos);
|
|
595
737
|
}
|
|
596
738
|
|
|
597
|
-
NSString *
|
|
739
|
+
NSString *finalType = @"default";
|
|
598
740
|
|
|
599
|
-
|
|
600
|
-
|
|
741
|
+
// Smart decision logic: AX for special cases, system for normal cases
|
|
742
|
+
NSLog(@"🎯 CURSOR DECISION: system='%@', ax='%@'", systemCursorType ?: @"nil", axCursorType ?: @"nil");
|
|
743
|
+
|
|
744
|
+
// If system cursor detected something specific (not default), use it
|
|
745
|
+
if (systemCursorType && [systemCursorType length] > 0 && ![systemCursorType isEqualToString:@"default"]) {
|
|
746
|
+
finalType = systemCursorType;
|
|
747
|
+
NSLog(@"🎯 Using SYSTEM cursor (specific): %@", finalType);
|
|
748
|
+
}
|
|
749
|
+
// If AX detected something specific and system is default, use AX
|
|
750
|
+
else if (axCursorType && [axCursorType length] > 0 && ![axCursorType isEqualToString:@"default"] &&
|
|
751
|
+
(!systemCursorType || [systemCursorType isEqualToString:@"default"])) {
|
|
601
752
|
finalType = axCursorType;
|
|
602
|
-
|
|
753
|
+
NSLog(@"🎯 Using AX cursor (specific over default): %@", finalType);
|
|
754
|
+
}
|
|
755
|
+
// Otherwise use system cursor (including default)
|
|
756
|
+
else if (systemCursorType && [systemCursorType length] > 0) {
|
|
603
757
|
finalType = systemCursorType;
|
|
604
|
-
|
|
758
|
+
NSLog(@"🎯 Using SYSTEM cursor: %@", finalType);
|
|
759
|
+
}
|
|
760
|
+
// Final fallback to AX or default
|
|
761
|
+
else if (axCursorType && [axCursorType length] > 0) {
|
|
605
762
|
finalType = axCursorType;
|
|
606
|
-
|
|
607
|
-
|
|
763
|
+
NSLog(@"🎯 Using AX cursor (final fallback): %@", finalType);
|
|
764
|
+
}
|
|
765
|
+
else {
|
|
766
|
+
NSLog(@"🎯 Ultimate fallback to default");
|
|
608
767
|
}
|
|
609
768
|
|
|
610
|
-
|
|
769
|
+
NSLog(@"🎯 FINAL CURSOR TYPE: %@", finalType);
|
|
611
770
|
return finalType;
|
|
612
771
|
}
|
|
613
772
|
}
|