node-mac-recorder 2.17.8 → 2.17.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.
Files changed (2) hide show
  1. package/index.js +137 -110
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -359,60 +359,51 @@ class MacRecorder extends EventEmitter {
359
359
  // Start cursor tracking automatically with recording
360
360
  let cursorOptions = {};
361
361
 
362
- // For window recording, use the original window coordinates (not display-relative captureArea)
362
+ // For window recording, use simplified window-relative coordinates
363
363
  if (this.options.windowId) {
364
364
  // Use cached window info from the earlier window detection
365
365
  this.getWindows().then(windows => {
366
366
  const targetWindow = windows.find(w => w.id === this.options.windowId);
367
367
  if (targetWindow) {
368
- // Restart cursor capture with correct window coordinates
369
- if (this.cursorCaptureInterval) {
370
- this.stopCursorCapture().then(() => {
371
- this.startCursorCapture(cursorFilePath, {
372
- windowRelative: true,
373
- windowInfo: {
374
- x: targetWindow.x, // Global window X coordinate
375
- y: targetWindow.y, // Global window Y coordinate
376
- width: targetWindow.width,
377
- height: targetWindow.height,
378
- displayId: this.options.displayId,
379
- originalWindow: targetWindow,
380
- captureArea: this.options.captureArea
381
- }
382
- }).catch(cursorError => {
383
- console.warn('Cursor tracking failed to restart:', cursorError.message);
384
- });
385
- }).catch(stopError => {
386
- console.warn('Failed to stop cursor capture:', stopError.message);
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);
387
390
  });
388
- } else {
389
- this.startCursorCapture(cursorFilePath, {
390
- windowRelative: true,
391
- windowInfo: {
392
- x: targetWindow.x, // Global window X coordinate
393
- y: targetWindow.y, // Global window Y coordinate
394
- width: targetWindow.width,
395
- height: targetWindow.height,
396
- displayId: this.options.displayId,
397
- originalWindow: targetWindow,
398
- captureArea: this.options.captureArea
399
- }
400
- }).catch(cursorError => {
401
- console.warn('Cursor tracking failed to start:', cursorError.message);
402
- });
403
- }
391
+ });
404
392
  }
405
393
  }).catch(error => {
406
394
  console.warn('Could not get window info for cursor tracking:', error.message);
407
- // Fallback to basic cursor tracking
408
- this.startCursorCapture(cursorFilePath, cursorOptions).catch(cursorError => {
395
+ // Fallback to display cursor tracking
396
+ this.startCursorCapture(cursorFilePath).catch(cursorError => {
409
397
  console.warn('Cursor tracking failed to start:', cursorError.message);
410
398
  });
411
399
  });
412
400
  } else {
413
- // For display recording, use basic cursor tracking
414
- this.startCursorCapture(cursorFilePath, cursorOptions).catch(cursorError => {
415
- console.warn('Cursor tracking failed to start:', cursorError.message);
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);
416
407
  });
417
408
  }
418
409
 
@@ -717,42 +708,92 @@ class MacRecorder extends EventEmitter {
717
708
 
718
709
  // Koordinat sistemi belirle: window-relative, display-relative veya global
719
710
  if (options.windowRelative && options.windowInfo) {
720
- // Window recording için display'e relative captureArea koordinatlarını kullan
721
- const captureArea = options.windowInfo.captureArea;
722
- if (captureArea) {
723
- // captureArea zaten display-relative koordinatlar
724
- this.cursorDisplayInfo = {
725
- displayId: options.windowInfo.displayId || null,
726
- x: captureArea.x, // Display-relative X
727
- y: captureArea.y, // Display-relative Y
728
- width: captureArea.width,
729
- height: captureArea.height,
730
- windowRelative: true,
731
- windowInfo: options.windowInfo
732
- };
733
- } else {
734
- // Fallback: orijinal window koordinatları
735
- this.cursorDisplayInfo = {
736
- displayId: options.windowInfo.displayId || null,
737
- x: options.windowInfo.x || 0,
738
- y: options.windowInfo.y || 0,
739
- width: options.windowInfo.width,
740
- height: options.windowInfo.height,
741
- windowRelative: true,
742
- windowInfo: options.windowInfo
743
- };
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
+ }
744
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
778
+ 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
785
+ };
745
786
  } else if (this.recordingDisplayInfo) {
746
- // Recording başlatılmışsa o display'i kullan
787
+ // Fallback: Use recording display info if available
747
788
  this.cursorDisplayInfo = this.recordingDisplayInfo;
748
789
  } else {
749
- // Main display bilgisini al (her zaman relative koordinatlar için)
790
+ // Final fallback: Main display global coordinates
750
791
  try {
751
792
  const displays = await this.getDisplays();
752
793
  const mainDisplay = displays.find((d) => d.isPrimary) || displays[0];
753
794
  if (mainDisplay) {
754
795
  this.cursorDisplayInfo = {
755
- displayId: 0,
796
+ displayId: mainDisplay.id,
756
797
  x: mainDisplay.x,
757
798
  y: mainDisplay.y,
758
799
  width: parseInt(mainDisplay.resolution.split("x")[0]),
@@ -782,60 +823,37 @@ class MacRecorder extends EventEmitter {
782
823
  const position = nativeBinding.getCursorPosition();
783
824
  const timestamp = Date.now() - this.cursorCaptureStartTime;
784
825
 
785
- // Global koordinatları relative koordinatlara çevir
826
+ // Transform coordinates based on recording type
786
827
  let x = position.x;
787
828
  let y = position.y;
788
829
  let coordinateSystem = "global";
789
830
 
790
831
  if (this.cursorDisplayInfo) {
791
832
  if (this.cursorDisplayInfo.windowRelative) {
792
- // Window recording: cursor'ı önce target display'e relative yap, sonra captureArea'ya relative yap
793
- const targetDisplay = this.recordingDisplayInfo;
794
- if (targetDisplay) {
795
- // 1. Global -> Display-relative
796
- const displayRelativeX = position.x - targetDisplay.x;
797
- const displayRelativeY = position.y - targetDisplay.y;
798
-
799
- // 2. Display-relative -> CaptureArea-relative (window-relative)
800
- x = displayRelativeX - this.cursorDisplayInfo.x;
801
- y = displayRelativeY - this.cursorDisplayInfo.y;
802
- } else {
803
- // Fallback: doğrudan offset çıkar
804
- x = position.x - this.cursorDisplayInfo.x;
805
- y = position.y - this.cursorDisplayInfo.y;
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
806
841
  }
807
- } else {
808
- // Display recording: doğrudan offset çıkar
842
+ } else if (this.cursorDisplayInfo.displayRelative) {
843
+ // Display recording: Transform global → display-relative coordinates
809
844
  x = position.x - this.cursorDisplayInfo.x;
810
845
  y = position.y - this.cursorDisplayInfo.y;
811
- }
846
+ coordinateSystem = "display-relative";
812
847
 
813
- if (this.cursorDisplayInfo.windowRelative) {
814
- // Window-relative koordinatlar
815
- coordinateSystem = "window-relative";
816
-
817
- // Window bounds kontrolü - cursor window dışındaysa kaydetme
818
- if (
819
- x < 0 ||
820
- y < 0 ||
821
- x >= this.cursorDisplayInfo.width ||
822
- y >= this.cursorDisplayInfo.height
823
- ) {
824
- return; // Bu frame'i skip et - cursor pencere dışında
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
825
851
  }
826
852
  } else {
827
- // Display-relative koordinatlar
853
+ // Legacy fallback: Use global coordinates with basic offset
854
+ x = position.x - this.cursorDisplayInfo.x;
855
+ y = position.y - this.cursorDisplayInfo.y;
828
856
  coordinateSystem = "display-relative";
829
-
830
- // Display bounds kontrolü
831
- if (
832
- x < 0 ||
833
- y < 0 ||
834
- x >= this.cursorDisplayInfo.width ||
835
- y >= this.cursorDisplayInfo.height
836
- ) {
837
- return; // Bu frame'i skip et - cursor display dışında
838
- }
839
857
  }
840
858
  }
841
859
 
@@ -847,11 +865,20 @@ class MacRecorder extends EventEmitter {
847
865
  cursorType: position.cursorType,
848
866
  type: position.eventType || "move",
849
867
  coordinateSystem: coordinateSystem,
868
+ // Include recording context for window-relative coordinates
850
869
  ...(this.cursorDisplayInfo?.windowRelative && {
851
870
  windowInfo: {
852
871
  width: this.cursorDisplayInfo.width,
853
872
  height: this.cursorDisplayInfo.height,
854
- originalWindow: this.cursorDisplayInfo.windowInfo
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
855
882
  }
856
883
  })
857
884
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.17.8",
3
+ "version": "2.17.9",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [