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 +36 -50
- package/package.json +1 -1
- package/src/cursor_tracker.mm +11 -14
- package/test-output/temp_cursor_1758313956591.json +1 -0
- package/test-recording-with-cursor.js +83 -0
- package/test-unified-cursor.js +75 -0
- package/cursor-data-1751364226346.json +0 -1
- package/cursor-data-1751364314136.json +0 -1
- package/cursor-data.json +0 -1
- package/debug-cursor-output.json +0 -1
- package/debug-primary-cursor.js +0 -180
- package/examples/electron-integration-example.js +0 -230
- package/examples/electron-preload.js +0 -46
- package/examples/electron-renderer.html +0 -634
- package/examples/integration-example.js +0 -228
- package/examples/window-selector-example.js +0 -254
- package/quick-cursor-test.json +0 -1
- package/test-both-cursor.json +0 -1
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
|
-
//
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
package/src/cursor_tracker.mm
CHANGED
|
@@ -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"}
|
package/debug-cursor-output.json
DELETED
|
@@ -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"}]
|
package/debug-primary-cursor.js
DELETED
|
@@ -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);
|