node-mac-recorder 2.17.17 → 2.17.18

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.
@@ -0,0 +1,180 @@
1
+ const MacRecorder = require('./index.js');
2
+
3
+ async function debugPrimaryCursor() {
4
+ console.log('🔍 Detailed debugging of primary display cursor coordinates...');
5
+
6
+ const recorder = new MacRecorder();
7
+
8
+ try {
9
+ const displays = await recorder.getDisplays();
10
+ const windows = await recorder.getWindows();
11
+
12
+ const primaryDisplay = displays.find(d => d.isPrimary);
13
+ console.log('\n📱 Primary Display:');
14
+ console.log(` Bounds: (${primaryDisplay.x}, ${primaryDisplay.y}) ${primaryDisplay.width}x${primaryDisplay.height}`);
15
+
16
+ // Find a window on primary display
17
+ const primaryWindows = windows.filter(window => {
18
+ const windowCenterX = window.x + window.width / 2;
19
+ const windowCenterY = window.y + window.height / 2;
20
+ return (windowCenterX >= primaryDisplay.x &&
21
+ windowCenterX < primaryDisplay.x + primaryDisplay.width &&
22
+ windowCenterY >= primaryDisplay.y &&
23
+ windowCenterY < primaryDisplay.y + primaryDisplay.height);
24
+ });
25
+
26
+ if (primaryWindows.length === 0) {
27
+ console.log('❌ No windows found on primary display');
28
+ return;
29
+ }
30
+
31
+ const testWindow = primaryWindows[0];
32
+ console.log('\n🪟 Test Window:');
33
+ console.log(` Title: "${testWindow.title}"`);
34
+ console.log(` Global position: (${testWindow.x}, ${testWindow.y})`);
35
+ console.log(` Size: ${testWindow.width}x${testWindow.height}`);
36
+ console.log(` Global bounds: (${testWindow.x}, ${testWindow.y}) to (${testWindow.x + testWindow.width}, ${testWindow.y + testWindow.height})`);
37
+
38
+ // Manual cursor position check
39
+ console.log('\n🖱️ Current cursor position:');
40
+ const currentPos = recorder.getCursorPosition();
41
+ console.log(` Global cursor: (${currentPos.x}, ${currentPos.y})`);
42
+
43
+ // Manual transformation calculation
44
+ console.log('\n🧮 Manual transformation calculation:');
45
+ const manualWindowRelativeX = currentPos.x - testWindow.x;
46
+ const manualWindowRelativeY = currentPos.y - testWindow.y;
47
+ console.log(` Manual window-relative: (${manualWindowRelativeX}, ${manualWindowRelativeY})`);
48
+
49
+ const isInWindow = (manualWindowRelativeX >= 0 && manualWindowRelativeX < testWindow.width &&
50
+ manualWindowRelativeY >= 0 && manualWindowRelativeY < testWindow.height);
51
+ console.log(` Is cursor in window? ${isInWindow ? '✅ YES' : '❌ NO'}`);
52
+
53
+ if (!isInWindow) {
54
+ console.log('\n⚠️ Move cursor to the test window for accurate testing...');
55
+ console.log(' Waiting 3 seconds for you to move cursor to the window...');
56
+ await new Promise(resolve => setTimeout(resolve, 3000));
57
+
58
+ const newPos = recorder.getCursorPosition();
59
+ console.log(`\n🖱️ New cursor position: (${newPos.x}, ${newPos.y})`);
60
+ const newManualX = newPos.x - testWindow.x;
61
+ const newManualY = newPos.y - testWindow.y;
62
+ console.log(` New manual window-relative: (${newManualX}, ${newManualY})`);
63
+
64
+ const newIsInWindow = (newManualX >= 0 && newManualX < testWindow.width &&
65
+ newManualY >= 0 && newManualY < testWindow.height);
66
+ console.log(` Is cursor in window now? ${newIsInWindow ? '✅ YES' : '❌ NO'}`);
67
+ }
68
+
69
+ // Now test with cursor capture to see what actually gets recorded
70
+ console.log('\n🎬 Testing actual cursor capture...');
71
+
72
+ // Create a custom logger to see what coordinates are being processed
73
+ const originalLog = console.log;
74
+ const capturedLogs = [];
75
+
76
+ // Temporarily override console.log to capture coordinate logs
77
+ console.log = (...args) => {
78
+ const message = args.join(' ');
79
+ if (message.includes('cursor') || message.includes('position') || message.includes('coordinate')) {
80
+ capturedLogs.push(message);
81
+ }
82
+ originalLog(...args);
83
+ };
84
+
85
+ const outputFile = `./test-output/debug-primary-${Date.now()}.json`;
86
+
87
+ // Start capture with detailed logging
88
+ await recorder.startCursorCapture(outputFile, {
89
+ windowRelative: true,
90
+ windowInfo: {
91
+ x: testWindow.x,
92
+ y: testWindow.y,
93
+ width: testWindow.width,
94
+ height: testWindow.height,
95
+ displayId: primaryDisplay.id
96
+ }
97
+ });
98
+
99
+ console.log('\n📍 Cursor capture started. Move mouse in the window for 3 seconds...');
100
+ console.log(` Expected window bounds: (0, 0) to (${testWindow.width}, ${testWindow.height})`);
101
+
102
+ // Capture for 3 seconds with manual checking
103
+ for (let i = 0; i < 6; i++) {
104
+ await new Promise(resolve => setTimeout(resolve, 500));
105
+ const pos = recorder.getCursorPosition();
106
+ const windowRelX = pos.x - testWindow.x;
107
+ const windowRelY = pos.y - testWindow.y;
108
+
109
+ console.log(` Sample ${i+1}: Global(${pos.x}, ${pos.y}) → Window-rel(${windowRelX}, ${windowRelY})`);
110
+ }
111
+
112
+ await recorder.stopCursorCapture();
113
+
114
+ // Restore console.log
115
+ console.log = originalLog;
116
+
117
+ // Analyze results
118
+ const fs = require('fs');
119
+ if (fs.existsSync(outputFile)) {
120
+ const cursorData = JSON.parse(fs.readFileSync(outputFile, 'utf8'));
121
+
122
+ console.log('\n📊 Analysis Results:');
123
+ console.log(` Captured events: ${cursorData.length}`);
124
+
125
+ if (cursorData.length > 0) {
126
+ console.log('\n📍 Sample recorded coordinates:');
127
+ cursorData.slice(0, 5).forEach((event, i) => {
128
+ console.log(` Event ${i+1}: (${event.x}, ${event.y}) - ${event.coordinateSystem}`);
129
+ });
130
+
131
+ // Check bounds
132
+ const inBounds = cursorData.filter(event =>
133
+ event.x >= 0 && event.x < testWindow.width &&
134
+ event.y >= 0 && event.y < testWindow.height
135
+ );
136
+
137
+ const outOfBounds = cursorData.filter(event =>
138
+ event.x < 0 || event.x >= testWindow.width ||
139
+ event.y < 0 || event.y >= testWindow.height
140
+ );
141
+
142
+ console.log(`\n✅ Events in bounds: ${inBounds.length}/${cursorData.length} (${Math.round(inBounds.length/cursorData.length*100)}%)`);
143
+
144
+ if (outOfBounds.length > 0) {
145
+ console.log(`❌ Events out of bounds: ${outOfBounds.length}`);
146
+ console.log(' Problem coordinates:');
147
+ outOfBounds.slice(0, 3).forEach(event => {
148
+ console.log(` (${event.x}, ${event.y}) - Expected: 0-${testWindow.width}, 0-${testWindow.height}`);
149
+ });
150
+
151
+ // Calculate offset pattern
152
+ const xOffsets = outOfBounds.map(e => e.x - (e.x >= 0 ? 0 : testWindow.width));
153
+ const yOffsets = outOfBounds.map(e => e.y - (e.y >= 0 ? 0 : testWindow.height));
154
+
155
+ console.log(`\n🔍 Offset analysis:`);
156
+ console.log(` X offset pattern: ${xOffsets.slice(0, 3).join(', ')}`);
157
+ console.log(` Y offset pattern: ${yOffsets.slice(0, 3).join(', ')}`);
158
+ } else {
159
+ console.log('✅ All coordinates are within bounds!');
160
+ }
161
+ } else {
162
+ console.log('❌ No events captured - cursor might not be in window or transformation is dropping events');
163
+ }
164
+ } else {
165
+ console.log('❌ No output file created');
166
+ }
167
+
168
+ console.log('\n🔍 Captured system logs:');
169
+ if (capturedLogs.length > 0) {
170
+ capturedLogs.forEach(log => console.log(` ${log}`));
171
+ } else {
172
+ console.log(' No relevant coordinate logs captured');
173
+ }
174
+
175
+ } catch (error) {
176
+ console.error('❌ Debug failed:', error.message);
177
+ }
178
+ }
179
+
180
+ debugPrimaryCursor().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.17.17",
3
+ "version": "2.17.18",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -636,20 +636,27 @@ void cursorTimerCallback() {
636
636
  // Apply DPR scaling correction for Retina displays
637
637
  NSDictionary *scalingInfo = getDisplayScalingInfo(rawLocation);
638
638
  CGPoint location = rawLocation;
639
-
639
+
640
640
  if (scalingInfo) {
641
641
  CGFloat scaleFactor = [[scalingInfo objectForKey:@"scaleFactor"] doubleValue];
642
642
  NSRect displayBounds = [[scalingInfo objectForKey:@"displayBounds"] rectValue];
643
-
643
+
644
644
  // Keep logical coordinates - no scaling needed here
645
645
  location = rawLocation;
646
646
  }
647
-
647
+
648
648
  NSDate *currentDate = [NSDate date];
649
649
  NSTimeInterval timestamp = [currentDate timeIntervalSinceDate:g_trackingStartTime] * 1000; // milliseconds
650
650
  NSTimeInterval unixTimeMs = [currentDate timeIntervalSince1970] * 1000; // unix timestamp in milliseconds
651
651
  NSString *cursorType = getCursorType();
652
-
652
+
653
+ // CRITICAL: Apply coordinate transformation if needed
654
+ // This should match the transformation logic in index.js cursorTimerCallback
655
+
656
+ // Use transformed coordinates from the JavaScript layer if available
657
+ // The transformation is handled in index.js, so we need to get the transformed position
658
+ // For now, we'll write the raw coordinates and let the JS layer handle transformation
659
+
653
660
  // Cursor data oluştur
654
661
  NSDictionary *cursorInfo = @{
655
662
  @"x": @((int)location.x),
@@ -659,7 +666,7 @@ void cursorTimerCallback() {
659
666
  @"cursorType": cursorType,
660
667
  @"type": @"move"
661
668
  };
662
-
669
+
663
670
  // Direkt dosyaya yaz
664
671
  writeToFile(cursorInfo);
665
672
  }