node-mac-recorder 2.17.18 → 2.17.20

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 CHANGED
@@ -359,53 +359,10 @@ class MacRecorder extends EventEmitter {
359
359
  // Start cursor tracking automatically with recording
360
360
  let cursorOptions = {};
361
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
- }
362
+ // Hem window hem display recording için aynı native cursor tracking kullan
363
+ this.startCursorCapture(cursorFilePath).catch(cursorError => {
364
+ console.warn('Cursor tracking failed to start:', cursorError.message);
365
+ });
409
366
 
410
367
  // Timer başlat (progress tracking için)
411
368
  this.recordingTimer = setInterval(() => {
@@ -499,9 +456,11 @@ class MacRecorder extends EventEmitter {
499
456
 
500
457
  // Stop cursor tracking automatically
501
458
  if (this.cursorCaptureInterval) {
502
- this.stopCursorCapture().catch(cursorError => {
459
+ try {
460
+ this.stopCursorCapture();
461
+ } catch (cursorError) {
503
462
  console.warn('Cursor tracking failed to stop:', cursorError.message);
504
- });
463
+ }
505
464
  }
506
465
 
507
466
  // Timer durdur
@@ -916,7 +875,34 @@ class MacRecorder extends EventEmitter {
916
875
  /**
917
876
  * Cursor capture durdurur - dosya yazma işlemini sonlandırır
918
877
  */
919
- async stopCursorCapture() {
878
+ stopCursorCapture() {
879
+ if (!this.cursorCaptureInterval) {
880
+ return false;
881
+ }
882
+
883
+ try {
884
+ // Native cursor tracking'i durdur
885
+ const success = nativeBinding.stopCursorTracking();
886
+
887
+ this.cursorCaptureInterval = null;
888
+ this.cursorCaptureFile = null;
889
+ this.cursorCaptureStartTime = null;
890
+
891
+ this.emit("cursorCaptureStopped", {
892
+ timestamp: Date.now()
893
+ });
894
+
895
+ return success;
896
+ } catch (error) {
897
+ console.warn("Error stopping cursor tracking:", error.message);
898
+ return false;
899
+ }
900
+ }
901
+
902
+ /**
903
+ * LEGACY: Eski JS-based cursor capture durdurmak için geriye uyumluluk
904
+ */
905
+ async _legacyStopCursorCapture() {
920
906
  return new Promise((resolve, reject) => {
921
907
  try {
922
908
  if (!this.cursorCaptureInterval) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.17.18",
3
+ "version": "2.17.20",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -601,13 +601,15 @@ CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef eve
601
601
  }
602
602
 
603
603
  // Cursor data oluştur
604
+ // Cursor data oluştur - global koordinat sistemi kullan
604
605
  NSDictionary *cursorInfo = @{
605
606
  @"x": @((int)location.x),
606
607
  @"y": @((int)location.y),
607
608
  @"timestamp": @(timestamp),
608
609
  @"unixTimeMs": @(unixTimeMs),
609
610
  @"cursorType": cursorType,
610
- @"type": eventType
611
+ @"type": eventType,
612
+ @"coordinateSystem": @"global"
611
613
  };
612
614
 
613
615
  // Direkt dosyaya yaz
@@ -636,37 +638,32 @@ void cursorTimerCallback() {
636
638
  // Apply DPR scaling correction for Retina displays
637
639
  NSDictionary *scalingInfo = getDisplayScalingInfo(rawLocation);
638
640
  CGPoint location = rawLocation;
639
-
641
+
640
642
  if (scalingInfo) {
641
643
  CGFloat scaleFactor = [[scalingInfo objectForKey:@"scaleFactor"] doubleValue];
642
644
  NSRect displayBounds = [[scalingInfo objectForKey:@"displayBounds"] rectValue];
643
-
645
+
644
646
  // Keep logical coordinates - no scaling needed here
645
647
  location = rawLocation;
646
648
  }
647
-
649
+
648
650
  NSDate *currentDate = [NSDate date];
649
651
  NSTimeInterval timestamp = [currentDate timeIntervalSinceDate:g_trackingStartTime] * 1000; // milliseconds
650
652
  NSTimeInterval unixTimeMs = [currentDate timeIntervalSince1970] * 1000; // unix timestamp in milliseconds
651
653
  NSString *cursorType = getCursorType();
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
-
654
+
660
655
  // Cursor data oluştur
656
+ // Cursor data oluştur - global koordinat sistemi kullan
661
657
  NSDictionary *cursorInfo = @{
662
658
  @"x": @((int)location.x),
663
659
  @"y": @((int)location.y),
664
660
  @"timestamp": @(timestamp),
665
661
  @"unixTimeMs": @(unixTimeMs),
666
662
  @"cursorType": cursorType,
667
- @"type": @"move"
663
+ @"type": @"move",
664
+ @"coordinateSystem": @"global"
668
665
  };
669
-
666
+
670
667
  // Direkt dosyaya yaz
671
668
  writeToFile(cursorInfo);
672
669
  }
@@ -0,0 +1 @@
1
+ [{"x":609,"y":795,"timestamp":184,"unixTimeMs":1758313956779,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":609,"y":795,"timestamp":205,"unixTimeMs":1758313956800,"cursorType":"default","type":"mousedown","coordinateSystem":"display-relative"},{"x":609,"y":795,"timestamp":224,"unixTimeMs":1758313956819,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":609,"y":795,"timestamp":286,"unixTimeMs":1758313956881,"cursorType":"default","type":"mouseup","coordinateSystem":"display-relative"},{"x":609,"y":795,"timestamp":306,"unixTimeMs":1758313956901,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":609,"y":802,"timestamp":824,"unixTimeMs":1758313957419,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":608,"y":812,"timestamp":842,"unixTimeMs":1758313957437,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":605,"y":828,"timestamp":863,"unixTimeMs":1758313957458,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":601,"y":851,"timestamp":883,"unixTimeMs":1758313957478,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":596,"y":877,"timestamp":905,"unixTimeMs":1758313957500,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":594,"y":887,"timestamp":923,"unixTimeMs":1758313957518,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":591,"y":900,"timestamp":942,"unixTimeMs":1758313957537,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":590,"y":905,"timestamp":965,"unixTimeMs":1758313957560,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":589,"y":908,"timestamp":984,"unixTimeMs":1758313957579,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":588,"y":910,"timestamp":1025,"unixTimeMs":1758313957620,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":588,"y":912,"timestamp":1065,"unixTimeMs":1758313957660,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":588,"y":914,"timestamp":1124,"unixTimeMs":1758313957719,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":587,"y":917,"timestamp":1145,"unixTimeMs":1758313957740,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":586,"y":920,"timestamp":1167,"unixTimeMs":1758313957762,"cursorType":"default","type":"move","coordinateSystem":"display-relative"},{"x":586,"y":922,"timestamp":1186,"unixTimeMs":1758313957781,"cursorType":"default","type":"move","coordinateSystem":"display-relative"}
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+
3
+ const MacRecorder = require('./index.js');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+
7
+ async function testRecordingWithCursor() {
8
+ const recorder = new MacRecorder();
9
+
10
+ console.log('🎯 Testing recording with cursor tracking...');
11
+
12
+ // Create test output directory
13
+ const outputDir = './test-output';
14
+ if (!fs.existsSync(outputDir)) {
15
+ fs.mkdirSync(outputDir);
16
+ }
17
+
18
+ const videoPath = path.join(outputDir, `test-recording-${Date.now()}.mov`);
19
+
20
+ try {
21
+ console.log('Starting recording with auto cursor tracking...');
22
+
23
+ // Start recording (should auto-start cursor tracking)
24
+ await recorder.startRecording(videoPath, {
25
+ captureCursor: true, // This should trigger auto cursor tracking
26
+ quality: 'low',
27
+ frameRate: 10
28
+ });
29
+
30
+ console.log('✅ Recording started successfully');
31
+ console.log('🔥 Recording for 3 seconds...');
32
+
33
+ // Wait 3 seconds
34
+ await new Promise(resolve => setTimeout(resolve, 3000));
35
+
36
+ console.log('Stopping recording...');
37
+ const stopResult = await recorder.stopRecording();
38
+ console.log('✅ Recording stopped:', stopResult);
39
+
40
+ // Wait a bit for file to be written
41
+ await new Promise(resolve => setTimeout(resolve, 1000));
42
+
43
+ // Check if files exist
44
+ if (fs.existsSync(videoPath)) {
45
+ const videoStats = fs.statSync(videoPath);
46
+ console.log('📹 Video file size:', videoStats.size, 'bytes');
47
+ } else {
48
+ console.log('❌ Video file not found:', videoPath);
49
+ }
50
+
51
+ // Check for cursor files
52
+ const cursorFiles = fs.readdirSync(outputDir).filter(f => f.includes('cursor') && f.endsWith('.json'));
53
+ console.log('📊 Cursor files found:', cursorFiles.length);
54
+
55
+ if (cursorFiles.length > 0) {
56
+ const cursorFile = path.join(outputDir, cursorFiles[0]);
57
+ const cursorContent = fs.readFileSync(cursorFile, 'utf8');
58
+ console.log('📁 Cursor file size:', cursorContent.length, 'bytes');
59
+
60
+ if (cursorContent.trim()) {
61
+ try {
62
+ const cursorData = JSON.parse(cursorContent);
63
+ console.log('📍 Cursor data points:', cursorData.length);
64
+ } catch (parseError) {
65
+ console.log('⚠️ Cursor file content preview:', cursorContent.substring(0, 200));
66
+ }
67
+ }
68
+ }
69
+
70
+ } catch (error) {
71
+ console.error('❌ Test failed:', error.message);
72
+ console.error('Stack:', error.stack);
73
+ }
74
+ }
75
+
76
+ // Run test
77
+ testRecordingWithCursor().then(() => {
78
+ console.log('\n✨ Test completed');
79
+ process.exit(0);
80
+ }).catch(error => {
81
+ console.error('💥 Test error:', error);
82
+ process.exit(1);
83
+ });
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+
3
+ const MacRecorder = require('./index.js');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+
7
+ async function testUnifiedCursorTracking() {
8
+ const recorder = new MacRecorder();
9
+
10
+ console.log('🎯 Testing unified cursor tracking...');
11
+
12
+ // Create test output directory
13
+ const outputDir = './test-output';
14
+ if (!fs.existsSync(outputDir)) {
15
+ fs.mkdirSync(outputDir);
16
+ }
17
+
18
+ const cursorFilePath = path.join(outputDir, `unified-cursor-${Date.now()}.json`);
19
+
20
+ try {
21
+ console.log('Starting native cursor tracking...');
22
+
23
+ // Test native cursor tracking
24
+ const result = await recorder.startCursorCapture(cursorFilePath);
25
+ console.log('✅ Cursor tracking started:', result);
26
+
27
+ console.log('\n🔥 Move your mouse around for 5 seconds...');
28
+
29
+ // Wait 5 seconds
30
+ await new Promise(resolve => setTimeout(resolve, 5000));
31
+
32
+ console.log('\nStopping cursor tracking...');
33
+ const stopped = recorder.stopCursorCapture();
34
+ console.log('✅ Cursor tracking stopped:', stopped);
35
+
36
+ // Wait a bit for file to be written
37
+ await new Promise(resolve => setTimeout(resolve, 1000));
38
+
39
+ // Check if file exists and has content
40
+ if (fs.existsSync(cursorFilePath)) {
41
+ const fileContent = fs.readFileSync(cursorFilePath, 'utf8');
42
+ console.log('📁 File size:', fileContent.length, 'bytes');
43
+
44
+ try {
45
+ const cursorData = JSON.parse(fileContent);
46
+ console.log('📊 Cursor data points:', cursorData.length);
47
+
48
+ if (cursorData.length > 0) {
49
+ console.log('📍 First point:', cursorData[0]);
50
+ console.log('📍 Last point:', cursorData[cursorData.length - 1]);
51
+
52
+ // Check coordinate system
53
+ const coordinateSystems = [...new Set(cursorData.map(p => p.coordinateSystem))];
54
+ console.log('🔧 Coordinate systems used:', coordinateSystems);
55
+ }
56
+ } catch (parseError) {
57
+ console.log('⚠️ File content (first 500 chars):', fileContent.substring(0, 500));
58
+ }
59
+ } else {
60
+ console.log('❌ Output file not found:', cursorFilePath);
61
+ }
62
+
63
+ } catch (error) {
64
+ console.error('❌ Test failed:', error.message);
65
+ }
66
+ }
67
+
68
+ // Run test
69
+ testUnifiedCursorTracking().then(() => {
70
+ console.log('\n✨ Test completed');
71
+ process.exit(0);
72
+ }).catch(error => {
73
+ console.error('💥 Test error:', error);
74
+ process.exit(1);
75
+ });
@@ -1 +0,0 @@
1
- []
@@ -1 +0,0 @@
1
- []
package/cursor-data.json DELETED
@@ -1 +0,0 @@
1
- [{"x":1151,"y":726,"timestamp":20,"cursorType":"text","type":"move"}
@@ -1 +0,0 @@
1
- [{"x":48,"y":72,"timestamp":22,"unixTimeMs":1752410259890,"cursorType":"pointer","type":"move"},{"x":47,"y":71,"timestamp":87,"unixTimeMs":1752410259955,"cursorType":"pointer","type":"mousedown"},{"x":47,"y":71,"timestamp":107,"unixTimeMs":1752410259975,"cursorType":"pointer","type":"move"},{"x":47,"y":71,"timestamp":169,"unixTimeMs":1752410260037,"cursorType":"pointer","type":"mouseup"},{"x":47,"y":71,"timestamp":781,"unixTimeMs":1752410260649,"cursorType":"default","type":"move"}]
@@ -1,180 +0,0 @@
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);