node-mac-recorder 2.19.5 → 2.20.0
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 +4 -1
- package/index.js +158 -22
- package/package.json +1 -1
- package/src/cursor_tracker.mm +101 -17
- package/src/mac_recorder.mm +58 -7
- package/temp_cursor_1758662416766.json +1 -0
- package/temp_cursor_1758662420113.json +1 -0
- package/temp_cursor_1758662423166.json +1 -0
- package/temp_cursor_1758662426222.json +1 -0
package/index.js
CHANGED
|
@@ -87,7 +87,11 @@ class MacRecorder extends EventEmitter {
|
|
|
87
87
|
x: display.x,
|
|
88
88
|
y: display.y,
|
|
89
89
|
isPrimary: display.isPrimary,
|
|
90
|
+
scaleFactor: display.scaleFactor || 1.0,
|
|
91
|
+
physicalWidth: display.physicalWidth || display.width,
|
|
92
|
+
physicalHeight: display.physicalHeight || display.height,
|
|
90
93
|
resolution: `${display.width}x${display.height}`,
|
|
94
|
+
physicalResolution: `${display.physicalWidth || display.width}x${display.physicalHeight || display.height}`,
|
|
91
95
|
}));
|
|
92
96
|
}
|
|
93
97
|
|
|
@@ -771,24 +775,31 @@ class MacRecorder extends EventEmitter {
|
|
|
771
775
|
// JavaScript interval ile polling yap (daha sık - mouse event'leri yakalamak için)
|
|
772
776
|
this.cursorCaptureInterval = setInterval(() => {
|
|
773
777
|
try {
|
|
774
|
-
|
|
778
|
+
// Get cursor position with recording coordinates
|
|
779
|
+
const cursorData = this.getCursorPosition();
|
|
775
780
|
const timestamp = Date.now() - this.cursorCaptureStartTime;
|
|
776
781
|
|
|
777
|
-
//
|
|
778
|
-
let x =
|
|
779
|
-
let y =
|
|
780
|
-
let coordinateSystem = "
|
|
782
|
+
// Use recording coordinates for video overlay alignment
|
|
783
|
+
let x = cursorData.recordingX || cursorData.x;
|
|
784
|
+
let y = cursorData.recordingY || cursorData.y;
|
|
785
|
+
let coordinateSystem = "recording-coordinates";
|
|
781
786
|
|
|
782
|
-
// Apply video-relative transformation for
|
|
787
|
+
// Apply video-relative transformation for window/area recording
|
|
783
788
|
if (this.cursorDisplayInfo && this.cursorDisplayInfo.videoRelative) {
|
|
784
|
-
//
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
789
|
+
// For window/area recording: adjust coordinates relative to capture area
|
|
790
|
+
if (this.cursorDisplayInfo.videoOffsetX || this.cursorDisplayInfo.videoOffsetY) {
|
|
791
|
+
// Convert from full recording resolution to capture area coordinates
|
|
792
|
+
const recordingScaleX = cursorData.scaleX || 1;
|
|
793
|
+
const recordingScaleY = cursorData.scaleY || 1;
|
|
794
|
+
|
|
795
|
+
// Scale offsets to recording resolution
|
|
796
|
+
const scaledOffsetX = this.cursorDisplayInfo.videoOffsetX * recordingScaleX;
|
|
797
|
+
const scaledOffsetY = this.cursorDisplayInfo.videoOffsetY * recordingScaleY;
|
|
798
|
+
|
|
799
|
+
x = x - scaledOffsetX;
|
|
800
|
+
y = y - scaledOffsetY;
|
|
801
|
+
coordinateSystem = "video-relative";
|
|
802
|
+
}
|
|
792
803
|
|
|
793
804
|
// Bounds check for video area (don't skip, just note if outside)
|
|
794
805
|
const outsideVideo = x < 0 || y < 0 ||
|
|
@@ -801,16 +812,30 @@ class MacRecorder extends EventEmitter {
|
|
|
801
812
|
}
|
|
802
813
|
}
|
|
803
814
|
|
|
804
|
-
const
|
|
815
|
+
const captureData = {
|
|
805
816
|
x: x,
|
|
806
817
|
y: y,
|
|
807
818
|
timestamp: timestamp,
|
|
808
819
|
unixTimeMs: Date.now(),
|
|
809
|
-
cursorType:
|
|
810
|
-
type:
|
|
820
|
+
cursorType: cursorData.cursorType,
|
|
821
|
+
type: cursorData.eventType || "move",
|
|
811
822
|
coordinateSystem: coordinateSystem,
|
|
812
|
-
//
|
|
823
|
+
// Recording metadata for video overlay alignment
|
|
813
824
|
recordingType: this.cursorDisplayInfo?.recordingType || "display",
|
|
825
|
+
recordingInfo: {
|
|
826
|
+
// Logical coordinates for backward compatibility
|
|
827
|
+
logicalX: cursorData.x,
|
|
828
|
+
logicalY: cursorData.y,
|
|
829
|
+
// Recording coordinates for video overlay
|
|
830
|
+
recordingX: x,
|
|
831
|
+
recordingY: y,
|
|
832
|
+
// Recording resolution
|
|
833
|
+
recordingWidth: cursorData.recordingWidth,
|
|
834
|
+
recordingHeight: cursorData.recordingHeight,
|
|
835
|
+
// Scale factors
|
|
836
|
+
scaleX: cursorData.scaleX || 1,
|
|
837
|
+
scaleY: cursorData.scaleY || 1
|
|
838
|
+
},
|
|
814
839
|
videoInfo: this.cursorDisplayInfo ? {
|
|
815
840
|
width: this.cursorDisplayInfo.videoWidth,
|
|
816
841
|
height: this.cursorDisplayInfo.videoHeight,
|
|
@@ -825,9 +850,9 @@ class MacRecorder extends EventEmitter {
|
|
|
825
850
|
};
|
|
826
851
|
|
|
827
852
|
// Sadece eventType değiştiğinde veya pozisyon değiştiğinde kaydet
|
|
828
|
-
if (this.shouldCaptureEvent(
|
|
853
|
+
if (this.shouldCaptureEvent(captureData)) {
|
|
829
854
|
// Dosyaya ekle
|
|
830
|
-
const jsonString = JSON.stringify(
|
|
855
|
+
const jsonString = JSON.stringify(captureData);
|
|
831
856
|
|
|
832
857
|
if (this.cursorCaptureFirstWrite) {
|
|
833
858
|
fs.appendFileSync(filepath, jsonString);
|
|
@@ -837,7 +862,7 @@ class MacRecorder extends EventEmitter {
|
|
|
837
862
|
}
|
|
838
863
|
|
|
839
864
|
// Son pozisyonu sakla
|
|
840
|
-
this.lastCapturedData = { ...
|
|
865
|
+
this.lastCapturedData = { ...captureData };
|
|
841
866
|
}
|
|
842
867
|
} catch (error) {
|
|
843
868
|
console.error("Cursor capture error:", error);
|
|
@@ -896,12 +921,123 @@ class MacRecorder extends EventEmitter {
|
|
|
896
921
|
const position = nativeBinding.getCursorPosition();
|
|
897
922
|
|
|
898
923
|
// Cursor hangi display'de ise o display'e relative döndür
|
|
899
|
-
|
|
924
|
+
const displayRelativePosition = this.getDisplayRelativePositionSync(position);
|
|
925
|
+
|
|
926
|
+
// Add recording coordinates for video overlay alignment
|
|
927
|
+
const recordingCoordinates = this.calculateRecordingCoordinates(displayRelativePosition);
|
|
928
|
+
|
|
929
|
+
return {
|
|
930
|
+
...displayRelativePosition,
|
|
931
|
+
// Recording coordinates for video overlay (matches actual video resolution)
|
|
932
|
+
recordingX: recordingCoordinates.x,
|
|
933
|
+
recordingY: recordingCoordinates.y,
|
|
934
|
+
recordingWidth: recordingCoordinates.width,
|
|
935
|
+
recordingHeight: recordingCoordinates.height,
|
|
936
|
+
// Scale factors for reference
|
|
937
|
+
scaleX: recordingCoordinates.scaleX,
|
|
938
|
+
scaleY: recordingCoordinates.scaleY,
|
|
939
|
+
// Original coordinates for backward compatibility
|
|
940
|
+
x: displayRelativePosition.x,
|
|
941
|
+
y: displayRelativePosition.y
|
|
942
|
+
};
|
|
900
943
|
} catch (error) {
|
|
901
944
|
throw new Error("Failed to get cursor position: " + error.message);
|
|
902
945
|
}
|
|
903
946
|
}
|
|
904
947
|
|
|
948
|
+
/**
|
|
949
|
+
* Calculate cursor coordinates for recording video overlay alignment
|
|
950
|
+
* Converts logical display coordinates to actual video recording coordinates
|
|
951
|
+
*/
|
|
952
|
+
calculateRecordingCoordinates(displayPosition) {
|
|
953
|
+
try {
|
|
954
|
+
// Get current display information
|
|
955
|
+
if (!this.cachedDisplays) {
|
|
956
|
+
this.refreshDisplayCache();
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// If still null, use native binding directly
|
|
960
|
+
if (!this.cachedDisplays) {
|
|
961
|
+
try {
|
|
962
|
+
const nativeDisplays = nativeBinding.getDisplays();
|
|
963
|
+
this.cachedDisplays = nativeDisplays.map((display, index) => ({
|
|
964
|
+
id: display.id,
|
|
965
|
+
name: display.name,
|
|
966
|
+
width: display.width,
|
|
967
|
+
height: display.height,
|
|
968
|
+
x: display.x,
|
|
969
|
+
y: display.y,
|
|
970
|
+
isPrimary: display.isPrimary,
|
|
971
|
+
scaleFactor: display.scaleFactor || 1.0,
|
|
972
|
+
physicalWidth: display.physicalWidth || display.width,
|
|
973
|
+
physicalHeight: display.physicalHeight || display.height,
|
|
974
|
+
resolution: `${display.width}x${display.height}`,
|
|
975
|
+
}));
|
|
976
|
+
} catch (e) {
|
|
977
|
+
console.warn('Failed to get displays from native binding:', e.message);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
// Find the target display
|
|
982
|
+
let targetDisplay = null;
|
|
983
|
+
if (displayPosition.displayId) {
|
|
984
|
+
targetDisplay = this.cachedDisplays.find(d => d.id === displayPosition.displayId);
|
|
985
|
+
}
|
|
986
|
+
if (!targetDisplay) {
|
|
987
|
+
targetDisplay = this.cachedDisplays.find(d => d.isPrimary) || this.cachedDisplays[0];
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
if (!targetDisplay) {
|
|
991
|
+
// Fallback: assume 1:1 mapping
|
|
992
|
+
return {
|
|
993
|
+
x: displayPosition.x,
|
|
994
|
+
y: displayPosition.y,
|
|
995
|
+
width: displayPosition.x,
|
|
996
|
+
height: displayPosition.y
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
// Parse display dimensions
|
|
1001
|
+
const logicalWidth = parseInt(targetDisplay.resolution.split("x")[0]);
|
|
1002
|
+
const logicalHeight = parseInt(targetDisplay.resolution.split("x")[1]);
|
|
1003
|
+
|
|
1004
|
+
// Get physical recording dimensions
|
|
1005
|
+
// On Retina displays, recording is done at physical resolution (2x logical)
|
|
1006
|
+
const physicalWidth = targetDisplay.physicalWidth || (logicalWidth * (targetDisplay.scaleFactor || 1));
|
|
1007
|
+
const physicalHeight = targetDisplay.physicalHeight || (logicalHeight * (targetDisplay.scaleFactor || 1));
|
|
1008
|
+
|
|
1009
|
+
// Calculate scale factors for coordinate conversion
|
|
1010
|
+
const scaleX = physicalWidth / logicalWidth;
|
|
1011
|
+
const scaleY = physicalHeight / logicalHeight;
|
|
1012
|
+
|
|
1013
|
+
// Convert logical cursor coordinates to recording coordinates
|
|
1014
|
+
const recordingX = Math.round(displayPosition.x * scaleX);
|
|
1015
|
+
const recordingY = Math.round(displayPosition.y * scaleY);
|
|
1016
|
+
|
|
1017
|
+
return {
|
|
1018
|
+
x: recordingX,
|
|
1019
|
+
y: recordingY,
|
|
1020
|
+
width: physicalWidth,
|
|
1021
|
+
height: physicalHeight,
|
|
1022
|
+
scaleX: scaleX,
|
|
1023
|
+
scaleY: scaleY,
|
|
1024
|
+
logicalWidth: logicalWidth,
|
|
1025
|
+
logicalHeight: logicalHeight
|
|
1026
|
+
};
|
|
1027
|
+
} catch (error) {
|
|
1028
|
+
console.warn('Failed to calculate recording coordinates:', error.message);
|
|
1029
|
+
// Fallback: 1:1 mapping
|
|
1030
|
+
return {
|
|
1031
|
+
x: displayPosition.x,
|
|
1032
|
+
y: displayPosition.y,
|
|
1033
|
+
width: displayPosition.x,
|
|
1034
|
+
height: displayPosition.y,
|
|
1035
|
+
scaleX: 1,
|
|
1036
|
+
scaleY: 1
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
|
|
905
1041
|
/**
|
|
906
1042
|
* Global koordinatları en uygun display'e relative çevirir (sync version)
|
|
907
1043
|
*/
|
package/package.json
CHANGED
package/src/cursor_tracker.mm
CHANGED
|
@@ -58,7 +58,25 @@ NSString* getCursorType() {
|
|
|
58
58
|
// ACCESSIBILITY API BASED CURSOR DETECTION
|
|
59
59
|
// Determine cursor type based on the UI element under the cursor
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
// MACOS 14 FIX: Get cursor position for accessibility API
|
|
62
|
+
CGPoint cursorPos;
|
|
63
|
+
|
|
64
|
+
if (@available(macOS 10.15, *)) {
|
|
65
|
+
// Use NSEvent method for macOS 14 compatibility
|
|
66
|
+
NSPoint mouseLocationInWindow = [NSEvent mouseLocation];
|
|
67
|
+
|
|
68
|
+
// Convert NSEvent bottom-left coordinates to top-left
|
|
69
|
+
CGDirectDisplayID primaryDisplay = CGMainDisplayID();
|
|
70
|
+
CGRect primaryBounds = CGDisplayBounds(primaryDisplay);
|
|
71
|
+
|
|
72
|
+
cursorPos = CGPointMake(
|
|
73
|
+
mouseLocationInWindow.x,
|
|
74
|
+
primaryBounds.size.height - mouseLocationInWindow.y
|
|
75
|
+
);
|
|
76
|
+
} else {
|
|
77
|
+
// Fallback for older macOS versions
|
|
78
|
+
cursorPos = CGEventGetLocation(CGEventCreate(NULL));
|
|
79
|
+
}
|
|
62
80
|
AXUIElementRef systemWide = AXUIElementCreateSystemWide();
|
|
63
81
|
AXUIElementRef elementAtPosition = NULL;
|
|
64
82
|
AXError error = AXUIElementCopyElementAtPosition(systemWide, cursorPos.x, cursorPos.y, &elementAtPosition);
|
|
@@ -345,7 +363,31 @@ CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef eve
|
|
|
345
363
|
return event;
|
|
346
364
|
}
|
|
347
365
|
|
|
348
|
-
|
|
366
|
+
// MACOS 14 FIX: Use alternative coordinate method if available
|
|
367
|
+
CGPoint rawLocation;
|
|
368
|
+
|
|
369
|
+
if (@available(macOS 10.15, *)) {
|
|
370
|
+
// For event callbacks, we can still use CGEventGetLocation
|
|
371
|
+
// but we'll apply coordinate correction if needed
|
|
372
|
+
rawLocation = CGEventGetLocation(event);
|
|
373
|
+
|
|
374
|
+
// Additional validation for macOS 14 scaled displays
|
|
375
|
+
if (rawLocation.x > 5000 || rawLocation.y > 5000) {
|
|
376
|
+
// Coordinates seem unreasonable, try NSEvent method as backup
|
|
377
|
+
NSPoint mouseLocationInWindow = [NSEvent mouseLocation];
|
|
378
|
+
|
|
379
|
+
// Convert NSEvent bottom-left coordinates to top-left
|
|
380
|
+
CGDirectDisplayID primaryDisplay = CGMainDisplayID();
|
|
381
|
+
CGRect primaryBounds = CGDisplayBounds(primaryDisplay);
|
|
382
|
+
|
|
383
|
+
rawLocation = CGPointMake(
|
|
384
|
+
mouseLocationInWindow.x,
|
|
385
|
+
primaryBounds.size.height - mouseLocationInWindow.y
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
} else {
|
|
389
|
+
rawLocation = CGEventGetLocation(event);
|
|
390
|
+
}
|
|
349
391
|
|
|
350
392
|
// Apply DPR scaling correction for Retina displays
|
|
351
393
|
NSDictionary *scalingInfo = getDisplayScalingInfo(rawLocation);
|
|
@@ -413,11 +455,28 @@ void cursorTimerCallback() {
|
|
|
413
455
|
return;
|
|
414
456
|
}
|
|
415
457
|
|
|
416
|
-
// Get cursor position with DPR scaling correction
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
if (
|
|
420
|
-
|
|
458
|
+
// MACOS 14 FIX: Get cursor position with DPR scaling correction
|
|
459
|
+
CGPoint rawLocation;
|
|
460
|
+
|
|
461
|
+
if (@available(macOS 10.15, *)) {
|
|
462
|
+
// Use NSEvent method for better macOS 14 compatibility
|
|
463
|
+
NSPoint mouseLocationInWindow = [NSEvent mouseLocation];
|
|
464
|
+
|
|
465
|
+
// Convert NSEvent bottom-left coordinates to top-left
|
|
466
|
+
CGDirectDisplayID primaryDisplay = CGMainDisplayID();
|
|
467
|
+
CGRect primaryBounds = CGDisplayBounds(primaryDisplay);
|
|
468
|
+
|
|
469
|
+
rawLocation = CGPointMake(
|
|
470
|
+
mouseLocationInWindow.x,
|
|
471
|
+
primaryBounds.size.height - mouseLocationInWindow.y
|
|
472
|
+
);
|
|
473
|
+
} else {
|
|
474
|
+
// Fallback for older macOS versions
|
|
475
|
+
CGEventRef event = CGEventCreate(NULL);
|
|
476
|
+
rawLocation = CGEventGetLocation(event);
|
|
477
|
+
if (event) {
|
|
478
|
+
CFRelease(event);
|
|
479
|
+
}
|
|
421
480
|
}
|
|
422
481
|
|
|
423
482
|
// Apply DPR scaling correction for Retina displays
|
|
@@ -750,23 +809,48 @@ Napi::Value GetCursorPosition(const Napi::CallbackInfo& info) {
|
|
|
750
809
|
Napi::Env env = info.Env();
|
|
751
810
|
|
|
752
811
|
@try {
|
|
753
|
-
//
|
|
754
|
-
|
|
755
|
-
CGPoint rawLocation
|
|
756
|
-
|
|
757
|
-
|
|
812
|
+
// MACOS 14 FIX: Use NSEvent mouseLocation instead of CGEventGetLocation
|
|
813
|
+
// CGEventGetLocation has coordinate system issues on macOS 14 with scaled displays
|
|
814
|
+
CGPoint rawLocation;
|
|
815
|
+
|
|
816
|
+
if (@available(macOS 10.15, *)) {
|
|
817
|
+
// Try NSEvent method first (more reliable on macOS 14)
|
|
818
|
+
NSPoint mouseLocationInWindow = [NSEvent mouseLocation];
|
|
819
|
+
|
|
820
|
+
// NSEvent.mouseLocation returns coordinates in the global coordinate space
|
|
821
|
+
// where (0,0) is at bottom-left of PRIMARY SCREEN
|
|
822
|
+
// CGDisplayBounds uses (0,0) at top-left
|
|
823
|
+
// We need to convert Y coordinate from bottom-left to top-left
|
|
824
|
+
|
|
825
|
+
CGDirectDisplayID primaryDisplay = CGMainDisplayID();
|
|
826
|
+
CGRect primaryBounds = CGDisplayBounds(primaryDisplay);
|
|
827
|
+
|
|
828
|
+
rawLocation = CGPointMake(
|
|
829
|
+
mouseLocationInWindow.x,
|
|
830
|
+
primaryBounds.size.height - mouseLocationInWindow.y
|
|
831
|
+
);
|
|
832
|
+
|
|
833
|
+
NSLog(@"🔧 macOS 14 cursor fix: NSEvent(%.0f,%.0f) -> CGPoint(%.0f,%.0f)",
|
|
834
|
+
mouseLocationInWindow.x, mouseLocationInWindow.y,
|
|
835
|
+
rawLocation.x, rawLocation.y);
|
|
836
|
+
} else {
|
|
837
|
+
// Fallback for older macOS versions
|
|
838
|
+
CGEventRef event = CGEventCreate(NULL);
|
|
839
|
+
rawLocation = CGEventGetLocation(event);
|
|
840
|
+
if (event) {
|
|
841
|
+
CFRelease(event);
|
|
842
|
+
}
|
|
758
843
|
}
|
|
759
|
-
|
|
844
|
+
|
|
760
845
|
// Get display scaling information
|
|
761
846
|
NSDictionary *scalingInfo = getDisplayScalingInfo(rawLocation);
|
|
762
847
|
CGPoint logicalLocation = rawLocation;
|
|
763
|
-
|
|
848
|
+
|
|
764
849
|
if (scalingInfo) {
|
|
765
850
|
CGFloat scaleFactor = [[scalingInfo objectForKey:@"scaleFactor"] doubleValue];
|
|
766
851
|
NSRect displayBounds = [[scalingInfo objectForKey:@"displayBounds"] rectValue];
|
|
767
|
-
|
|
768
|
-
//
|
|
769
|
-
// Keep logical coordinates - transformation happens in JS layer
|
|
852
|
+
|
|
853
|
+
// Use the corrected coordinates
|
|
770
854
|
logicalLocation = rawLocation;
|
|
771
855
|
}
|
|
772
856
|
|
package/src/mac_recorder.mm
CHANGED
|
@@ -577,15 +577,60 @@ Napi::Value GetDisplays(const Napi::CallbackInfo& info) {
|
|
|
577
577
|
CGDirectDisplayID displayID = activeDisplays[i];
|
|
578
578
|
CGRect displayBounds = CGDisplayBounds(displayID);
|
|
579
579
|
bool isPrimary = (displayID == CGMainDisplayID());
|
|
580
|
-
|
|
580
|
+
|
|
581
|
+
// Calculate scale factor and physical dimensions
|
|
582
|
+
CGSize logicalSize = displayBounds.size;
|
|
583
|
+
CGFloat scaleFactor = 1.0;
|
|
584
|
+
CGSize physicalSize = logicalSize;
|
|
585
|
+
CGSize actualPhysicalSize = logicalSize;
|
|
586
|
+
|
|
587
|
+
// Get actual display mode info first (most accurate)
|
|
588
|
+
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayID);
|
|
589
|
+
if (mode) {
|
|
590
|
+
size_t modePixelWidth = CGDisplayModeGetPixelWidth(mode);
|
|
591
|
+
size_t modePixelHeight = CGDisplayModeGetPixelHeight(mode);
|
|
592
|
+
actualPhysicalSize = CGSizeMake(modePixelWidth, modePixelHeight);
|
|
593
|
+
CGDisplayModeRelease(mode);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// Use NSScreen for backing scale factor (this is the UI scaling)
|
|
597
|
+
NSArray *screens = [NSScreen screens];
|
|
598
|
+
for (NSScreen *screen in screens) {
|
|
599
|
+
NSDictionary *screenDescription = [screen deviceDescription];
|
|
600
|
+
NSNumber *screenNumber = [screenDescription objectForKey:@"NSScreenNumber"];
|
|
601
|
+
if (screenNumber && [screenNumber unsignedIntValue] == displayID) {
|
|
602
|
+
scaleFactor = [screen backingScaleFactor];
|
|
603
|
+
|
|
604
|
+
// For cursor tracking, we want to use the logical coordinates that macOS reports
|
|
605
|
+
// Physical size should be what the system actually uses for display output
|
|
606
|
+
physicalSize = actualPhysicalSize;
|
|
607
|
+
|
|
608
|
+
NSLog(@"🔍 Display %u scale analysis:", displayID);
|
|
609
|
+
NSLog(@" Logical bounds: %.0fx%.0f", logicalSize.width, logicalSize.height);
|
|
610
|
+
NSLog(@" NSScreen backing scale: %.1fx", scaleFactor);
|
|
611
|
+
NSLog(@" CGDisplayMode pixels: %.0fx%.0f", actualPhysicalSize.width, actualPhysicalSize.height);
|
|
612
|
+
NSLog(@" Calculated scale: %.2fx", actualPhysicalSize.width / logicalSize.width);
|
|
613
|
+
break;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// Fallback if NSScreen method didn't work
|
|
618
|
+
if (scaleFactor == 1.0 && actualPhysicalSize.width > logicalSize.width) {
|
|
619
|
+
scaleFactor = actualPhysicalSize.width / logicalSize.width;
|
|
620
|
+
physicalSize = actualPhysicalSize;
|
|
621
|
+
}
|
|
622
|
+
|
|
581
623
|
NSDictionary *displayInfo = @{
|
|
582
624
|
@"id": @(displayID), // Direct CGDirectDisplayID
|
|
583
625
|
@"name": [NSString stringWithFormat:@"Display %u", (unsigned int)(i + 1)],
|
|
584
|
-
@"width": @((int)
|
|
585
|
-
@"height": @((int)
|
|
626
|
+
@"width": @((int)logicalSize.width),
|
|
627
|
+
@"height": @((int)logicalSize.height),
|
|
586
628
|
@"x": @((int)displayBounds.origin.x),
|
|
587
629
|
@"y": @((int)displayBounds.origin.y),
|
|
588
|
-
@"isPrimary": @(isPrimary)
|
|
630
|
+
@"isPrimary": @(isPrimary),
|
|
631
|
+
@"scaleFactor": @(scaleFactor),
|
|
632
|
+
@"physicalWidth": @((int)physicalSize.width),
|
|
633
|
+
@"physicalHeight": @((int)physicalSize.height)
|
|
589
634
|
};
|
|
590
635
|
[displays addObject:displayInfo];
|
|
591
636
|
}
|
|
@@ -595,13 +640,16 @@ Napi::Value GetDisplays(const Napi::CallbackInfo& info) {
|
|
|
595
640
|
|
|
596
641
|
for (NSUInteger i = 0; i < displays.count; i++) {
|
|
597
642
|
NSDictionary *display = displays[i];
|
|
598
|
-
NSLog(@"Display %lu: ID=%u, Name=%@,
|
|
643
|
+
NSLog(@"Display %lu: ID=%u, Name=%@, Logical=%@x%@, Physical=%@x%@, Scale=%.1fx",
|
|
599
644
|
(unsigned long)i,
|
|
600
645
|
[display[@"id"] unsignedIntValue],
|
|
601
646
|
display[@"name"],
|
|
602
647
|
display[@"width"],
|
|
603
|
-
display[@"height"]
|
|
604
|
-
|
|
648
|
+
display[@"height"],
|
|
649
|
+
display[@"physicalWidth"],
|
|
650
|
+
display[@"physicalHeight"],
|
|
651
|
+
[display[@"scaleFactor"] doubleValue]);
|
|
652
|
+
|
|
605
653
|
Napi::Object displayObj = Napi::Object::New(env);
|
|
606
654
|
displayObj.Set("id", Napi::Number::New(env, [display[@"id"] unsignedIntValue]));
|
|
607
655
|
displayObj.Set("name", Napi::String::New(env, [display[@"name"] UTF8String]));
|
|
@@ -610,6 +658,9 @@ Napi::Value GetDisplays(const Napi::CallbackInfo& info) {
|
|
|
610
658
|
displayObj.Set("x", Napi::Number::New(env, [display[@"x"] doubleValue]));
|
|
611
659
|
displayObj.Set("y", Napi::Number::New(env, [display[@"y"] doubleValue]));
|
|
612
660
|
displayObj.Set("isPrimary", Napi::Boolean::New(env, [display[@"isPrimary"] boolValue]));
|
|
661
|
+
displayObj.Set("scaleFactor", Napi::Number::New(env, [display[@"scaleFactor"] doubleValue]));
|
|
662
|
+
displayObj.Set("physicalWidth", Napi::Number::New(env, [display[@"physicalWidth"] doubleValue]));
|
|
663
|
+
displayObj.Set("physicalHeight", Napi::Number::New(env, [display[@"physicalHeight"] doubleValue]));
|
|
613
664
|
result[i] = displayObj;
|
|
614
665
|
}
|
|
615
666
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"x":661,"y":888,"timestamp":75,"unixTimeMs":1758662417142,"cursorType":"text","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}}]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"x":661,"y":888,"timestamp":28,"unixTimeMs":1758662420161,"cursorType":"text","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":691,"y":857,"timestamp":468,"unixTimeMs":1758662420601,"cursorType":"text","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":796,"y":749,"timestamp":490,"unixTimeMs":1758662420623,"cursorType":"text","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":971,"y":567,"timestamp":515,"unixTimeMs":1758662420648,"cursorType":"text","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1262,"y":304,"timestamp":525,"unixTimeMs":1758662420658,"cursorType":"text","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1519,"y":95,"timestamp":583,"unixTimeMs":1758662420716,"cursorType":"pointer","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":0,"timestamp":621,"unixTimeMs":1758662420754,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1707,"y":0,"timestamp":1510,"unixTimeMs":1758662421643,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1704,"y":0,"timestamp":1526,"unixTimeMs":1758662421659,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1702,"y":0,"timestamp":1549,"unixTimeMs":1758662421682,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1705,"y":0,"timestamp":1633,"unixTimeMs":1758662421766,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":0,"timestamp":1653,"unixTimeMs":1758662421786,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1707,"y":0,"timestamp":1989,"unixTimeMs":1758662422122,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}}]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"x":1709,"y":0,"timestamp":33,"unixTimeMs":1758662423222,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1707,"y":3,"timestamp":654,"unixTimeMs":1758662423843,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1704,"y":8,"timestamp":677,"unixTimeMs":1758662423866,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1704,"y":10,"timestamp":697,"unixTimeMs":1758662423886,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1703,"y":13,"timestamp":718,"unixTimeMs":1758662423907,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":2,"timestamp":780,"unixTimeMs":1758662423969,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":0,"timestamp":802,"unixTimeMs":1758662423991,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1706,"y":3,"timestamp":968,"unixTimeMs":1758662424157,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1698,"y":15,"timestamp":989,"unixTimeMs":1758662424178,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1691,"y":29,"timestamp":1016,"unixTimeMs":1758662424205,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1688,"y":36,"timestamp":1029,"unixTimeMs":1758662424218,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1687,"y":41,"timestamp":1056,"unixTimeMs":1758662424245,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1687,"y":42,"timestamp":1072,"unixTimeMs":1758662424261,"cursorType":"ns-resize","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1689,"y":38,"timestamp":1094,"unixTimeMs":1758662424283,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1700,"y":23,"timestamp":1116,"unixTimeMs":1758662424305,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":9,"timestamp":1134,"unixTimeMs":1758662424323,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":1,"timestamp":1157,"unixTimeMs":1758662424346,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1707,"y":1,"timestamp":1554,"unixTimeMs":1758662424743,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1702,"y":5,"timestamp":1578,"unixTimeMs":1758662424767,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1694,"y":13,"timestamp":1594,"unixTimeMs":1758662424783,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1690,"y":19,"timestamp":1618,"unixTimeMs":1758662424807,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1685,"y":25,"timestamp":1634,"unixTimeMs":1758662424823,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1684,"y":28,"timestamp":1658,"unixTimeMs":1758662424847,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1686,"y":30,"timestamp":1700,"unixTimeMs":1758662424889,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1691,"y":30,"timestamp":1720,"unixTimeMs":1758662424909,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1699,"y":30,"timestamp":1746,"unixTimeMs":1758662424935,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":25,"timestamp":1764,"unixTimeMs":1758662424953,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":16,"timestamp":1783,"unixTimeMs":1758662424972,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":10,"timestamp":1808,"unixTimeMs":1758662424997,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":0,"timestamp":1825,"unixTimeMs":1758662425014,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1702,"y":0,"timestamp":1890,"unixTimeMs":1758662425079,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1690,"y":1,"timestamp":1919,"unixTimeMs":1758662425108,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1682,"y":4,"timestamp":1930,"unixTimeMs":1758662425119,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1672,"y":12,"timestamp":1949,"unixTimeMs":1758662425138,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1669,"y":16,"timestamp":1976,"unixTimeMs":1758662425165,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1665,"y":22,"timestamp":1991,"unixTimeMs":1758662425180,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}}]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"x":1698,"y":14,"timestamp":31,"unixTimeMs":1758662426275,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1701,"y":11,"timestamp":51,"unixTimeMs":1758662426295,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1705,"y":6,"timestamp":76,"unixTimeMs":1758662426320,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1708,"y":1,"timestamp":95,"unixTimeMs":1758662426339,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1706,"y":8,"timestamp":426,"unixTimeMs":1758662426670,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1703,"y":13,"timestamp":449,"unixTimeMs":1758662426693,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1701,"y":16,"timestamp":467,"unixTimeMs":1758662426711,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1699,"y":19,"timestamp":489,"unixTimeMs":1758662426733,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1701,"y":17,"timestamp":573,"unixTimeMs":1758662426817,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1702,"y":15,"timestamp":595,"unixTimeMs":1758662426839,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1704,"y":12,"timestamp":623,"unixTimeMs":1758662426867,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1705,"y":9,"timestamp":635,"unixTimeMs":1758662426879,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1707,"y":6,"timestamp":660,"unixTimeMs":1758662426904,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1708,"y":4,"timestamp":678,"unixTimeMs":1758662426922,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1708,"y":2,"timestamp":702,"unixTimeMs":1758662426946,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":0,"timestamp":744,"unixTimeMs":1758662426988,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1708,"y":3,"timestamp":890,"unixTimeMs":1758662427134,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1705,"y":8,"timestamp":917,"unixTimeMs":1758662427161,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1702,"y":12,"timestamp":928,"unixTimeMs":1758662427172,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1701,"y":14,"timestamp":951,"unixTimeMs":1758662427195,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1705,"y":10,"timestamp":1036,"unixTimeMs":1758662427280,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":5,"timestamp":1058,"unixTimeMs":1758662427302,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":2,"timestamp":1079,"unixTimeMs":1758662427323,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":0,"timestamp":1100,"unixTimeMs":1758662427344,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1706,"y":5,"timestamp":1222,"unixTimeMs":1758662427466,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1704,"y":8,"timestamp":1244,"unixTimeMs":1758662427488,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1702,"y":13,"timestamp":1266,"unixTimeMs":1758662427510,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1701,"y":16,"timestamp":1288,"unixTimeMs":1758662427532,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1702,"y":14,"timestamp":1371,"unixTimeMs":1758662427615,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1703,"y":12,"timestamp":1395,"unixTimeMs":1758662427639,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1705,"y":9,"timestamp":1432,"unixTimeMs":1758662427676,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1706,"y":6,"timestamp":1454,"unixTimeMs":1758662427698,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1706,"y":4,"timestamp":1494,"unixTimeMs":1758662427738,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1704,"y":7,"timestamp":1561,"unixTimeMs":1758662427805,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1702,"y":10,"timestamp":1578,"unixTimeMs":1758662427822,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1702,"y":12,"timestamp":1617,"unixTimeMs":1758662427861,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1704,"y":12,"timestamp":1661,"unixTimeMs":1758662427905,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1706,"y":12,"timestamp":1685,"unixTimeMs":1758662427929,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1708,"y":11,"timestamp":1726,"unixTimeMs":1758662427970,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":9,"timestamp":1748,"unixTimeMs":1758662427992,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":7,"timestamp":1769,"unixTimeMs":1758662428013,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1709,"y":5,"timestamp":1791,"unixTimeMs":1758662428035,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1707,"y":5,"timestamp":1850,"unixTimeMs":1758662428094,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}},{"x":1708,"y":3,"timestamp":1978,"unixTimeMs":1758662428222,"cursorType":"default","type":"move","coordinateSystem":"video-relative","recordingType":"display","videoInfo":{"width":1710,"height":1112,"offsetX":0,"offsetY":0},"displayInfo":{"displayId":1,"width":1710,"height":1112}}]
|