node-mac-recorder 2.18.0 → 2.18.1
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/index.js +74 -179
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -283,16 +283,25 @@ class MacRecorder extends EventEmitter {
|
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
-
//
|
|
287
|
-
if (
|
|
286
|
+
// Ensure recordingDisplayInfo is always set for cursor tracking
|
|
287
|
+
if (!this.recordingDisplayInfo) {
|
|
288
288
|
try {
|
|
289
289
|
const displays = await this.getDisplays();
|
|
290
|
-
|
|
290
|
+
let targetDisplay;
|
|
291
|
+
|
|
292
|
+
if (this.options.displayId !== null) {
|
|
293
|
+
// Manual displayId specified
|
|
294
|
+
targetDisplay = displays.find(d => d.id === this.options.displayId);
|
|
295
|
+
} else {
|
|
296
|
+
// Default to main display
|
|
297
|
+
targetDisplay = displays.find(d => d.isPrimary) || displays[0];
|
|
298
|
+
}
|
|
299
|
+
|
|
291
300
|
if (targetDisplay) {
|
|
292
301
|
this.recordingDisplayInfo = {
|
|
293
|
-
displayId:
|
|
294
|
-
x: targetDisplay.x,
|
|
295
|
-
y: targetDisplay.y,
|
|
302
|
+
displayId: targetDisplay.id,
|
|
303
|
+
x: targetDisplay.x || 0,
|
|
304
|
+
y: targetDisplay.y || 0,
|
|
296
305
|
width: parseInt(targetDisplay.resolution.split("x")[0]),
|
|
297
306
|
height: parseInt(targetDisplay.resolution.split("x")[1]),
|
|
298
307
|
// Add scaling information for cursor coordinate transformation
|
|
@@ -356,56 +365,20 @@ class MacRecorder extends EventEmitter {
|
|
|
356
365
|
this.isRecording = true;
|
|
357
366
|
this.recordingStartTime = Date.now();
|
|
358
367
|
|
|
359
|
-
// Start cursor tracking
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
x: targetWindow.x,
|
|
374
|
-
y: targetWindow.y,
|
|
375
|
-
width: targetWindow.width,
|
|
376
|
-
height: targetWindow.height,
|
|
377
|
-
displayId: this.options.displayId,
|
|
378
|
-
// Persist capture area so we can rebuild global offsets reliably
|
|
379
|
-
captureArea: this.options.captureArea,
|
|
380
|
-
// Keep a snapshot of the window details for debugging/analytics
|
|
381
|
-
originalWindow: targetWindow,
|
|
382
|
-
// Store display info for multi-display coordinate fixes
|
|
383
|
-
targetDisplay: this.recordingDisplayInfo
|
|
384
|
-
}
|
|
385
|
-
}).catch(cursorError => {
|
|
386
|
-
console.warn('Window cursor tracking failed:', cursorError.message);
|
|
387
|
-
// Fallback to display recording
|
|
388
|
-
this.startCursorCapture(cursorFilePath).catch(fallbackError => {
|
|
389
|
-
console.warn('Fallback cursor tracking failed:', fallbackError.message);
|
|
390
|
-
});
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
}).catch(error => {
|
|
394
|
-
console.warn('Could not get window info for cursor tracking:', error.message);
|
|
395
|
-
// Fallback to display cursor tracking
|
|
396
|
-
this.startCursorCapture(cursorFilePath).catch(cursorError => {
|
|
397
|
-
console.warn('Cursor tracking failed to start:', cursorError.message);
|
|
398
|
-
});
|
|
399
|
-
});
|
|
400
|
-
} else {
|
|
401
|
-
// For display recording, use display-relative cursor tracking
|
|
402
|
-
this.startCursorCapture(cursorFilePath, {
|
|
403
|
-
displayRelative: true,
|
|
404
|
-
displayInfo: this.recordingDisplayInfo
|
|
405
|
-
}).catch(cursorError => {
|
|
406
|
-
console.warn('Display cursor tracking failed:', cursorError.message);
|
|
407
|
-
});
|
|
408
|
-
}
|
|
368
|
+
// Start unified cursor tracking for all recording types
|
|
369
|
+
// Use the same standard cursor tracking logic that works best (display-relative)
|
|
370
|
+
const standardCursorOptions = {
|
|
371
|
+
displayRelative: true,
|
|
372
|
+
displayInfo: this.recordingDisplayInfo,
|
|
373
|
+
recordingType: this.options.windowId ? 'window' :
|
|
374
|
+
this.options.captureArea ? 'area' : 'display',
|
|
375
|
+
captureArea: this.options.captureArea,
|
|
376
|
+
windowId: this.options.windowId
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
this.startCursorCapture(cursorFilePath, standardCursorOptions).catch(cursorError => {
|
|
380
|
+
console.warn('Unified cursor tracking failed:', cursorError.message);
|
|
381
|
+
});
|
|
409
382
|
|
|
410
383
|
// Timer başlat (progress tracking için)
|
|
411
384
|
this.recordingTimer = setInterval(() => {
|
|
@@ -679,12 +652,12 @@ class MacRecorder extends EventEmitter {
|
|
|
679
652
|
}
|
|
680
653
|
|
|
681
654
|
/**
|
|
682
|
-
*
|
|
683
|
-
* Recording başlatılmışsa otomatik olarak display-relative koordinatlar kullanır
|
|
655
|
+
* Unified cursor capture for all recording types - uses standardized display-relative coordinates
|
|
684
656
|
* @param {string|number} intervalOrFilepath - Cursor data JSON dosya yolu veya interval
|
|
685
657
|
* @param {Object} options - Cursor capture seçenekleri
|
|
686
|
-
* @param {
|
|
687
|
-
* @param {
|
|
658
|
+
* @param {boolean} options.displayRelative - Use display-relative coordinates (recommended)
|
|
659
|
+
* @param {Object} options.displayInfo - Display information for coordinate transformation
|
|
660
|
+
* @param {string} options.recordingType - Type of recording: 'display', 'window', 'area'
|
|
688
661
|
*/
|
|
689
662
|
async startCursorCapture(intervalOrFilepath = 100, options = {}) {
|
|
690
663
|
let filepath;
|
|
@@ -706,86 +679,28 @@ class MacRecorder extends EventEmitter {
|
|
|
706
679
|
throw new Error("Cursor capture is already running");
|
|
707
680
|
}
|
|
708
681
|
|
|
709
|
-
//
|
|
710
|
-
if (options.
|
|
711
|
-
|
|
712
|
-
const targetDisplay = windowInfo.targetDisplay || this.recordingDisplayInfo || null;
|
|
713
|
-
const captureArea = windowInfo.captureArea || null;
|
|
714
|
-
const hasNumber = (value) => typeof value === "number" && Number.isFinite(value);
|
|
715
|
-
|
|
716
|
-
let globalX = hasNumber(windowInfo.x) ? windowInfo.x : null;
|
|
717
|
-
let globalY = hasNumber(windowInfo.y) ? windowInfo.y : null;
|
|
718
|
-
|
|
719
|
-
if (captureArea && targetDisplay) {
|
|
720
|
-
if (!hasNumber(globalX) && hasNumber(captureArea.x) && hasNumber(targetDisplay.x)) {
|
|
721
|
-
globalX = targetDisplay.x + captureArea.x;
|
|
722
|
-
}
|
|
723
|
-
if (!hasNumber(globalY) && hasNumber(captureArea.y) && hasNumber(targetDisplay.y)) {
|
|
724
|
-
globalY = targetDisplay.y + captureArea.y;
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
if (!hasNumber(globalX)) {
|
|
729
|
-
if (captureArea && hasNumber(captureArea.x) && targetDisplay && hasNumber(targetDisplay.x)) {
|
|
730
|
-
globalX = targetDisplay.x + captureArea.x;
|
|
731
|
-
} else {
|
|
732
|
-
globalX = hasNumber(captureArea?.x) ? captureArea.x : 0;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
if (!hasNumber(globalY)) {
|
|
737
|
-
if (captureArea && hasNumber(captureArea.y) && targetDisplay && hasNumber(targetDisplay.y)) {
|
|
738
|
-
globalY = targetDisplay.y + captureArea.y;
|
|
739
|
-
} else {
|
|
740
|
-
globalY = hasNumber(captureArea?.y) ? captureArea.y : 0;
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
const displayOffsetX = captureArea && hasNumber(captureArea.x)
|
|
745
|
-
? captureArea.x
|
|
746
|
-
: (targetDisplay && hasNumber(globalX) && hasNumber(targetDisplay.x)
|
|
747
|
-
? globalX - targetDisplay.x
|
|
748
|
-
: globalX);
|
|
749
|
-
const displayOffsetY = captureArea && hasNumber(captureArea.y)
|
|
750
|
-
? captureArea.y
|
|
751
|
-
: (targetDisplay && hasNumber(globalY) && hasNumber(targetDisplay.y)
|
|
752
|
-
? globalY - targetDisplay.y
|
|
753
|
-
: globalY);
|
|
754
|
-
|
|
755
|
-
this.cursorDisplayInfo = {
|
|
756
|
-
displayId:
|
|
757
|
-
windowInfo.displayId ??
|
|
758
|
-
targetDisplay?.displayId ??
|
|
759
|
-
targetDisplay?.id ??
|
|
760
|
-
null,
|
|
761
|
-
x: globalX,
|
|
762
|
-
y: globalY,
|
|
763
|
-
width: windowInfo.width,
|
|
764
|
-
height: windowInfo.height,
|
|
765
|
-
windowRelative: true,
|
|
766
|
-
windowInfo: {
|
|
767
|
-
...windowInfo,
|
|
768
|
-
globalX,
|
|
769
|
-
globalY,
|
|
770
|
-
displayOffsetX,
|
|
771
|
-
displayOffsetY
|
|
772
|
-
},
|
|
773
|
-
targetDisplay,
|
|
774
|
-
captureArea
|
|
775
|
-
};
|
|
776
|
-
} else if (options.displayRelative && options.displayInfo) {
|
|
777
|
-
// Display recording: Use display-relative coordinates
|
|
682
|
+
// Use standardized display-relative coordinate system for all recording types
|
|
683
|
+
if (options.displayRelative && options.displayInfo) {
|
|
684
|
+
// Standardized display-relative coordinates for all recording types
|
|
778
685
|
this.cursorDisplayInfo = {
|
|
779
|
-
displayId: options.displayInfo.displayId,
|
|
780
|
-
x: options.displayInfo.x,
|
|
781
|
-
y: options.displayInfo.y,
|
|
782
|
-
width: options.displayInfo.width,
|
|
783
|
-
height: options.displayInfo.height,
|
|
784
|
-
displayRelative: true
|
|
686
|
+
displayId: options.displayInfo.displayId || options.displayInfo.id,
|
|
687
|
+
x: options.displayInfo.x || 0,
|
|
688
|
+
y: options.displayInfo.y || 0,
|
|
689
|
+
width: options.displayInfo.width || options.displayInfo.logicalWidth,
|
|
690
|
+
height: options.displayInfo.height || options.displayInfo.logicalHeight,
|
|
691
|
+
displayRelative: true,
|
|
692
|
+
recordingType: options.recordingType || 'display',
|
|
693
|
+
// Store additional context for debugging
|
|
694
|
+
captureArea: options.captureArea,
|
|
695
|
+
windowId: options.windowId
|
|
785
696
|
};
|
|
786
697
|
} else if (this.recordingDisplayInfo) {
|
|
787
698
|
// Fallback: Use recording display info if available
|
|
788
|
-
this.cursorDisplayInfo =
|
|
699
|
+
this.cursorDisplayInfo = {
|
|
700
|
+
...this.recordingDisplayInfo,
|
|
701
|
+
displayRelative: true,
|
|
702
|
+
recordingType: options.recordingType || 'display'
|
|
703
|
+
};
|
|
789
704
|
} else {
|
|
790
705
|
// Final fallback: Main display global coordinates
|
|
791
706
|
try {
|
|
@@ -823,37 +738,26 @@ class MacRecorder extends EventEmitter {
|
|
|
823
738
|
const position = nativeBinding.getCursorPosition();
|
|
824
739
|
const timestamp = Date.now() - this.cursorCaptureStartTime;
|
|
825
740
|
|
|
826
|
-
//
|
|
741
|
+
// Standardized coordinate transformation for all recording types
|
|
827
742
|
let x = position.x;
|
|
828
743
|
let y = position.y;
|
|
829
744
|
let coordinateSystem = "global";
|
|
830
745
|
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
coordinateSystem = "display-relative";
|
|
847
|
-
|
|
848
|
-
// Display bounds check - skip if cursor is outside display
|
|
849
|
-
if (x < 0 || y < 0 || x >= this.cursorDisplayInfo.width || y >= this.cursorDisplayInfo.height) {
|
|
850
|
-
return; // Skip frame - cursor outside display
|
|
851
|
-
}
|
|
852
|
-
} else {
|
|
853
|
-
// Legacy fallback: Use global coordinates with basic offset
|
|
854
|
-
x = position.x - this.cursorDisplayInfo.x;
|
|
855
|
-
y = position.y - this.cursorDisplayInfo.y;
|
|
856
|
-
coordinateSystem = "display-relative";
|
|
746
|
+
// Apply display-relative transformation for all recording types
|
|
747
|
+
if (this.cursorDisplayInfo && this.cursorDisplayInfo.displayRelative) {
|
|
748
|
+
// Transform global → display-relative coordinates
|
|
749
|
+
x = position.x - this.cursorDisplayInfo.x;
|
|
750
|
+
y = position.y - this.cursorDisplayInfo.y;
|
|
751
|
+
coordinateSystem = "display-relative";
|
|
752
|
+
|
|
753
|
+
// Optional bounds check for display (don't skip, just note if outside)
|
|
754
|
+
const outsideDisplay = x < 0 || y < 0 ||
|
|
755
|
+
x >= this.cursorDisplayInfo.width ||
|
|
756
|
+
y >= this.cursorDisplayInfo.height;
|
|
757
|
+
|
|
758
|
+
// For debugging - add metadata if cursor is outside recording area
|
|
759
|
+
if (outsideDisplay) {
|
|
760
|
+
coordinateSystem = "display-relative-outside";
|
|
857
761
|
}
|
|
858
762
|
}
|
|
859
763
|
|
|
@@ -865,22 +769,13 @@ class MacRecorder extends EventEmitter {
|
|
|
865
769
|
cursorType: position.cursorType,
|
|
866
770
|
type: position.eventType || "move",
|
|
867
771
|
coordinateSystem: coordinateSystem,
|
|
868
|
-
//
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
}),
|
|
876
|
-
// Include display context for display-relative coordinates
|
|
877
|
-
...(this.cursorDisplayInfo?.displayRelative && {
|
|
878
|
-
displayInfo: {
|
|
879
|
-
displayId: this.cursorDisplayInfo.displayId,
|
|
880
|
-
width: this.cursorDisplayInfo.width,
|
|
881
|
-
height: this.cursorDisplayInfo.height
|
|
882
|
-
}
|
|
883
|
-
})
|
|
772
|
+
// Standardized metadata for all recording types
|
|
773
|
+
recordingType: this.cursorDisplayInfo?.recordingType || "display",
|
|
774
|
+
displayInfo: this.cursorDisplayInfo ? {
|
|
775
|
+
displayId: this.cursorDisplayInfo.displayId,
|
|
776
|
+
width: this.cursorDisplayInfo.width,
|
|
777
|
+
height: this.cursorDisplayInfo.height
|
|
778
|
+
} : null
|
|
884
779
|
};
|
|
885
780
|
|
|
886
781
|
// Sadece eventType değiştiğinde veya pozisyon değiştiğinde kaydet
|