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.
Files changed (2) hide show
  1. package/index.js +74 -179
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -283,16 +283,25 @@ class MacRecorder extends EventEmitter {
283
283
  }
284
284
  }
285
285
 
286
- // DisplayId manuel ayarlanmışsa display bilgisini sakla
287
- if (this.options.displayId !== null && !this.recordingDisplayInfo) {
286
+ // Ensure recordingDisplayInfo is always set for cursor tracking
287
+ if (!this.recordingDisplayInfo) {
288
288
  try {
289
289
  const displays = await this.getDisplays();
290
- const targetDisplay = displays.find(d => d.id === this.options.displayId);
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: this.options.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 automatically with recording
360
- let cursorOptions = {};
361
-
362
- // For window recording, use simplified window-relative coordinates
363
- if (this.options.windowId) {
364
- // Use cached window info from the earlier window detection
365
- this.getWindows().then(windows => {
366
- const targetWindow = windows.find(w => w.id === this.options.windowId);
367
- if (targetWindow) {
368
- // Start cursor capture with simplified window-relative tracking
369
- this.startCursorCapture(cursorFilePath, {
370
- windowRelative: true,
371
- windowInfo: {
372
- // Use original global window coordinates for reference
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
- * Cursor capture başlatır - otomatik olarak dosyaya yazmaya başlar
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 {Object} options.windowInfo - Pencere bilgileri (window-relative koordinatlar için)
687
- * @param {boolean} options.windowRelative - Koordinatları pencereye göre relative yap
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
- // Koordinat sistemi belirle: window-relative, display-relative veya global
710
- if (options.windowRelative && options.windowInfo) {
711
- const windowInfo = options.windowInfo;
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 = this.recordingDisplayInfo;
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
- // Transform coordinates based on recording type
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
- if (this.cursorDisplayInfo) {
832
- if (this.cursorDisplayInfo.windowRelative) {
833
- // Window recording: Transform global → window-relative coordinates
834
- x = position.x - this.cursorDisplayInfo.x;
835
- y = position.y - this.cursorDisplayInfo.y;
836
- coordinateSystem = "window-relative";
837
-
838
- // Window bounds check - skip if cursor is outside window
839
- if (x < 0 || y < 0 || x >= this.cursorDisplayInfo.width || y >= this.cursorDisplayInfo.height) {
840
- return; // Skip frame - cursor outside window
841
- }
842
- } else if (this.cursorDisplayInfo.displayRelative) {
843
- // Display recording: Transform global display-relative coordinates
844
- x = position.x - this.cursorDisplayInfo.x;
845
- y = position.y - this.cursorDisplayInfo.y;
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
- // Include recording context for window-relative coordinates
869
- ...(this.cursorDisplayInfo?.windowRelative && {
870
- windowInfo: {
871
- width: this.cursorDisplayInfo.width,
872
- height: this.cursorDisplayInfo.height,
873
- displayId: this.cursorDisplayInfo.displayId
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.18.0",
3
+ "version": "2.18.1",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [