node-mac-recorder 2.17.19 → 2.17.21
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/.claude/settings.local.json +3 -1
- package/index.js +21 -200
- package/package.json +1 -1
- package/publish.sh +18 -0
- package/src/cursor_tracker.mm +37 -20
- package/cursor-data-1751364226346.json +0 -1
- package/cursor-data-1751364314136.json +0 -1
- package/cursor-data.json +0 -1
- package/cursor-debug-test.js +0 -60
- package/cursor-dpr-test.js +0 -73
- package/cursor-dpr-test.json +0 -1
- package/cursor-macbook-test.js +0 -63
- package/cursor-permission-test.js +0 -46
- package/cursor-scaling-debug.js +0 -53
- package/cursor-simple-test.js +0 -26
- package/debug-audio.js +0 -79
- package/debug-coordinates.js +0 -69
- package/debug-cursor-output.json +0 -1
- package/debug-macos14.js +0 -110
- package/debug-primary-window.js +0 -84
- package/debug-screen-selection.js +0 -81
- package/debug-window-selector.js +0 -178
- 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/test-cursor-fix.js +0 -105
- package/test-cursor-types.js +0 -117
- package/test-display-coordinates.js +0 -72
- package/test-integrated-recording.js +0 -120
- package/test-menubar-offset.js +0 -110
- package/test-output/primary-fix-test-1758266910543.json +0 -1
- package/test-output/unified-cursor-1758313640878.json +0 -1
- package/test-output/unified-cursor-1758313689471.json +0 -1
- package/test-primary-cursor.js +0 -154
- package/test-primary-fix.js +0 -120
- package/test-unified-cursor.js +0 -75
- package/test-window-recording.js +0 -149
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Window Selector + MacRecorder Integration Example
|
|
5
|
-
* Bu örnek, window selector ile seçilen pencereyi doğrudan kaydetmeyi gösterir
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const MacRecorder = require('../index');
|
|
9
|
-
const path = require('path');
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
|
|
12
|
-
async function recordSelectedWindow() {
|
|
13
|
-
console.log('🎥 Window Selection + Recording Integration');
|
|
14
|
-
console.log('==========================================\n');
|
|
15
|
-
|
|
16
|
-
const recorder = new MacRecorder();
|
|
17
|
-
const selector = new MacRecorder.WindowSelector();
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
// 1. İzinleri kontrol et
|
|
21
|
-
console.log('1️⃣ Checking permissions...');
|
|
22
|
-
const permissions = await recorder.checkPermissions();
|
|
23
|
-
console.log('Permissions:', permissions);
|
|
24
|
-
|
|
25
|
-
if (!permissions.screenRecording) {
|
|
26
|
-
console.warn('⚠️ Screen recording permission required!');
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// 2. Pencere seç
|
|
31
|
-
console.log('\n2️⃣ Select a window to record...');
|
|
32
|
-
console.log('Move cursor over windows and click "Select Window" button\n');
|
|
33
|
-
|
|
34
|
-
const selectedWindow = await selector.selectWindow();
|
|
35
|
-
|
|
36
|
-
console.log('✅ Selected window:', {
|
|
37
|
-
title: selectedWindow.title,
|
|
38
|
-
app: selectedWindow.appName,
|
|
39
|
-
size: `${selectedWindow.width}x${selectedWindow.height}`,
|
|
40
|
-
position: `(${selectedWindow.x}, ${selectedWindow.y})`
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// 3. Çıktı dosyası hazırla
|
|
44
|
-
const outputDir = path.join(__dirname, '..', 'recordings');
|
|
45
|
-
if (!fs.existsSync(outputDir)) {
|
|
46
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
50
|
-
const fileName = `${selectedWindow.appName}-${selectedWindow.title}-${timestamp}.mov`
|
|
51
|
-
.replace(/[^\w\-_.]/g, '_')
|
|
52
|
-
.substring(0, 100);
|
|
53
|
-
const outputPath = path.join(outputDir, fileName);
|
|
54
|
-
|
|
55
|
-
// 4. Kayıt ayarları
|
|
56
|
-
const recordingOptions = {
|
|
57
|
-
windowId: selectedWindow.id,
|
|
58
|
-
captureCursor: true,
|
|
59
|
-
includeMicrophone: false,
|
|
60
|
-
includeSystemAudio: true,
|
|
61
|
-
captureArea: {
|
|
62
|
-
x: selectedWindow.x - selectedWindow.screenX,
|
|
63
|
-
y: selectedWindow.y - selectedWindow.screenY,
|
|
64
|
-
width: selectedWindow.width,
|
|
65
|
-
height: selectedWindow.height
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
console.log('\n3️⃣ Starting recording...');
|
|
70
|
-
console.log(`Output: ${outputPath}`);
|
|
71
|
-
console.log('Recording options:', recordingOptions);
|
|
72
|
-
|
|
73
|
-
// 5. Kayıt başlat
|
|
74
|
-
await recorder.startRecording(outputPath, recordingOptions);
|
|
75
|
-
|
|
76
|
-
console.log('\n🔴 Recording started!');
|
|
77
|
-
console.log('Recording will stop automatically after 10 seconds...');
|
|
78
|
-
console.log('Or press Ctrl+C to stop manually\n');
|
|
79
|
-
|
|
80
|
-
// Progress tracking
|
|
81
|
-
let secondsRecorded = 0;
|
|
82
|
-
const progressInterval = setInterval(() => {
|
|
83
|
-
secondsRecorded++;
|
|
84
|
-
process.stdout.write(`\r⏱️ Recording: ${secondsRecorded}s / 10s`);
|
|
85
|
-
}, 1000);
|
|
86
|
-
|
|
87
|
-
// Ctrl+C handler
|
|
88
|
-
let recordingStopped = false;
|
|
89
|
-
process.on('SIGINT', async () => {
|
|
90
|
-
if (!recordingStopped) {
|
|
91
|
-
recordingStopped = true;
|
|
92
|
-
clearInterval(progressInterval);
|
|
93
|
-
console.log('\n\n🛑 Stopping recording...');
|
|
94
|
-
await recorder.stopRecording();
|
|
95
|
-
console.log(`✅ Recording saved: ${outputPath}`);
|
|
96
|
-
process.exit(0);
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// 6. 10 saniye sonra durdur
|
|
101
|
-
setTimeout(async () => {
|
|
102
|
-
if (!recordingStopped) {
|
|
103
|
-
recordingStopped = true;
|
|
104
|
-
clearInterval(progressInterval);
|
|
105
|
-
console.log('\n\n⏹️ Auto-stopping recording...');
|
|
106
|
-
await recorder.stopRecording();
|
|
107
|
-
|
|
108
|
-
// Dosya oluşup oluşmadığını kontrol et
|
|
109
|
-
setTimeout(() => {
|
|
110
|
-
if (fs.existsSync(outputPath)) {
|
|
111
|
-
const stats = fs.statSync(outputPath);
|
|
112
|
-
console.log(`✅ Recording completed successfully!`);
|
|
113
|
-
console.log(`📁 File: ${outputPath}`);
|
|
114
|
-
console.log(`📊 Size: ${(stats.size / 1024 / 1024).toFixed(2)} MB`);
|
|
115
|
-
console.log('\n🎬 You can now play the video file!');
|
|
116
|
-
} else {
|
|
117
|
-
console.log('⚠️ Recording file not found. Check permissions and try again.');
|
|
118
|
-
}
|
|
119
|
-
process.exit(0);
|
|
120
|
-
}, 2000);
|
|
121
|
-
}
|
|
122
|
-
}, 10000);
|
|
123
|
-
|
|
124
|
-
} catch (error) {
|
|
125
|
-
console.error('\n❌ Error:', error.message);
|
|
126
|
-
console.error(error.stack);
|
|
127
|
-
} finally {
|
|
128
|
-
await selector.cleanup();
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async function selectAndAnalyze() {
|
|
133
|
-
console.log('📊 Window Selection + Analysis Example');
|
|
134
|
-
console.log('======================================\n');
|
|
135
|
-
|
|
136
|
-
const selector = new MacRecorder.WindowSelector();
|
|
137
|
-
|
|
138
|
-
try {
|
|
139
|
-
console.log('Select a window to analyze...\n');
|
|
140
|
-
const window = await selector.selectWindow();
|
|
141
|
-
|
|
142
|
-
console.log('\n🔍 Window Analysis Report');
|
|
143
|
-
console.log('=========================');
|
|
144
|
-
|
|
145
|
-
// Basic info
|
|
146
|
-
console.log(`📱 Application: ${window.appName}`);
|
|
147
|
-
console.log(`🏷️ Title: "${window.title}"`);
|
|
148
|
-
console.log(`🆔 Window ID: ${window.id}`);
|
|
149
|
-
|
|
150
|
-
// Dimensions
|
|
151
|
-
console.log(`\n📐 Dimensions:`);
|
|
152
|
-
console.log(` Size: ${window.width} x ${window.height}`);
|
|
153
|
-
console.log(` Area: ${(window.width * window.height).toLocaleString()} pixels`);
|
|
154
|
-
console.log(` Aspect Ratio: ${(window.width / window.height).toFixed(2)}`);
|
|
155
|
-
|
|
156
|
-
// Position
|
|
157
|
-
console.log(`\n📍 Position:`);
|
|
158
|
-
console.log(` Global: (${window.x}, ${window.y})`);
|
|
159
|
-
console.log(` Screen: ${window.screenId} at (${window.screenX}, ${window.screenY})`);
|
|
160
|
-
console.log(` Relative: (${window.x - window.screenX}, ${window.y - window.screenY})`);
|
|
161
|
-
|
|
162
|
-
// Screen info
|
|
163
|
-
console.log(`\n🖥️ Screen:`);
|
|
164
|
-
console.log(` Size: ${window.screenWidth} x ${window.screenHeight}`);
|
|
165
|
-
console.log(` Coverage: ${((window.width * window.height) / (window.screenWidth * window.screenHeight) * 100).toFixed(1)}%`);
|
|
166
|
-
|
|
167
|
-
// Recording recommendation
|
|
168
|
-
console.log(`\n🎥 Recording Recommendations:`);
|
|
169
|
-
const area = window.width * window.height;
|
|
170
|
-
if (area > 2000000) { // > 2M pixels
|
|
171
|
-
console.log(' 📺 Large window - Good for detailed content recording');
|
|
172
|
-
} else if (area > 500000) { // > 500K pixels
|
|
173
|
-
console.log(' 📄 Medium window - Standard recording quality');
|
|
174
|
-
} else {
|
|
175
|
-
console.log(' 📝 Small window - Consider increasing size for better quality');
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const aspectRatio = window.width / window.height;
|
|
179
|
-
if (Math.abs(aspectRatio - 16/9) < 0.1) {
|
|
180
|
-
console.log(' 🎬 16:9 aspect ratio - Perfect for video content');
|
|
181
|
-
} else if (Math.abs(aspectRatio - 4/3) < 0.1) {
|
|
182
|
-
console.log(' 📺 4:3 aspect ratio - Classic format');
|
|
183
|
-
} else if (aspectRatio > 2) {
|
|
184
|
-
console.log(' 📱 Wide aspect ratio - Good for dashboard/IDE content');
|
|
185
|
-
} else {
|
|
186
|
-
console.log(' 📄 Custom aspect ratio');
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
console.log(`\n✨ Analysis complete!`);
|
|
190
|
-
|
|
191
|
-
} catch (error) {
|
|
192
|
-
console.error('❌ Analysis failed:', error.message);
|
|
193
|
-
} finally {
|
|
194
|
-
await selector.cleanup();
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Main function
|
|
199
|
-
async function main() {
|
|
200
|
-
const args = process.argv.slice(2);
|
|
201
|
-
|
|
202
|
-
if (args.includes('--help')) {
|
|
203
|
-
console.log('Integration Examples:');
|
|
204
|
-
console.log('====================');
|
|
205
|
-
console.log('node examples/integration-example.js [option]');
|
|
206
|
-
console.log('');
|
|
207
|
-
console.log('Options:');
|
|
208
|
-
console.log(' --record Select and record a window (default)');
|
|
209
|
-
console.log(' --analyze Select and analyze a window');
|
|
210
|
-
console.log(' --help Show this help');
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if (args.includes('--analyze')) {
|
|
215
|
-
await selectAndAnalyze();
|
|
216
|
-
} else {
|
|
217
|
-
await recordSelectedWindow();
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (require.main === module) {
|
|
222
|
-
main().catch(console.error);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
module.exports = {
|
|
226
|
-
recordSelectedWindow,
|
|
227
|
-
selectAndAnalyze
|
|
228
|
-
};
|
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const WindowSelector = require('../window-selector');
|
|
4
|
-
|
|
5
|
-
async function simpleExample() {
|
|
6
|
-
console.log('🔍 Simple Window Selection Example');
|
|
7
|
-
console.log('===================================\n');
|
|
8
|
-
|
|
9
|
-
const selector = new WindowSelector();
|
|
10
|
-
|
|
11
|
-
try {
|
|
12
|
-
// Basit pencere seçimi
|
|
13
|
-
console.log('Click on any window to select it...\n');
|
|
14
|
-
const selectedWindow = await selector.selectWindow();
|
|
15
|
-
|
|
16
|
-
console.log('Selected window:', {
|
|
17
|
-
title: selectedWindow.title,
|
|
18
|
-
app: selectedWindow.appName,
|
|
19
|
-
position: `(${selectedWindow.x}, ${selectedWindow.y})`,
|
|
20
|
-
size: `${selectedWindow.width}x${selectedWindow.height}`
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
return selectedWindow;
|
|
24
|
-
|
|
25
|
-
} catch (error) {
|
|
26
|
-
console.error('Error:', error.message);
|
|
27
|
-
throw error;
|
|
28
|
-
} finally {
|
|
29
|
-
await selector.cleanup();
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function advancedExample() {
|
|
34
|
-
console.log('🎯 Advanced Window Selection with Events');
|
|
35
|
-
console.log('=========================================\n');
|
|
36
|
-
|
|
37
|
-
const selector = new WindowSelector();
|
|
38
|
-
|
|
39
|
-
return new Promise(async (resolve, reject) => {
|
|
40
|
-
try {
|
|
41
|
-
// Event listener'ları ayarla
|
|
42
|
-
selector.on('windowEntered', (window) => {
|
|
43
|
-
console.log(`🏠 Hovering over: "${window.title}" (${window.appName})`);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
selector.on('windowLeft', (window) => {
|
|
47
|
-
console.log(`🚪 Left: "${window.title}"`);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
selector.on('windowSelected', (window) => {
|
|
51
|
-
console.log(`\n✅ Selected: "${window.title}" from ${window.appName}`);
|
|
52
|
-
console.log(`📍 Position: (${window.x}, ${window.y})`);
|
|
53
|
-
console.log(`📏 Size: ${window.width} x ${window.height}`);
|
|
54
|
-
console.log(`🖥️ Screen: ${window.screenId} at (${window.screenX}, ${window.screenY})`);
|
|
55
|
-
resolve(window);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
selector.on('error', (error) => {
|
|
59
|
-
console.error('❌ Selection error:', error.message);
|
|
60
|
-
reject(error);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// Cancel handler
|
|
64
|
-
process.on('SIGINT', async () => {
|
|
65
|
-
console.log('\n🛑 Cancelled by user');
|
|
66
|
-
await selector.cleanup();
|
|
67
|
-
process.exit(0);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
console.log('Move cursor over windows to see them highlighted');
|
|
71
|
-
console.log('Click "Select Window" to choose one');
|
|
72
|
-
console.log('Press Ctrl+C to cancel\n');
|
|
73
|
-
|
|
74
|
-
await selector.startSelection();
|
|
75
|
-
|
|
76
|
-
} catch (error) {
|
|
77
|
-
reject(error);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async function multipleSelectionExample() {
|
|
83
|
-
console.log('🔄 Multiple Window Selection Example');
|
|
84
|
-
console.log('=====================================\n');
|
|
85
|
-
|
|
86
|
-
const selector = new WindowSelector();
|
|
87
|
-
const selectedWindows = [];
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
for (let i = 1; i <= 3; i++) {
|
|
91
|
-
console.log(`\n🎯 Selection ${i}/3:`);
|
|
92
|
-
console.log('Select a window...\n');
|
|
93
|
-
|
|
94
|
-
const window = await selector.selectWindow();
|
|
95
|
-
selectedWindows.push({
|
|
96
|
-
selection: i,
|
|
97
|
-
title: window.title,
|
|
98
|
-
app: window.appName,
|
|
99
|
-
position: { x: window.x, y: window.y },
|
|
100
|
-
size: { width: window.width, height: window.height },
|
|
101
|
-
screen: window.screenId
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
console.log(`✅ Selection ${i} complete: "${window.title}"`);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
console.log('\n📋 Summary of selected windows:');
|
|
108
|
-
selectedWindows.forEach((win, index) => {
|
|
109
|
-
console.log(`${index + 1}. "${win.title}" (${win.app}) - ${win.size.width}x${win.size.height}`);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
return selectedWindows;
|
|
113
|
-
|
|
114
|
-
} catch (error) {
|
|
115
|
-
console.error('Error during multiple selection:', error.message);
|
|
116
|
-
throw error;
|
|
117
|
-
} finally {
|
|
118
|
-
await selector.cleanup();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async function windowAnalysisExample() {
|
|
123
|
-
console.log('📊 Window Analysis Example');
|
|
124
|
-
console.log('===========================\n');
|
|
125
|
-
|
|
126
|
-
const selector = new WindowSelector();
|
|
127
|
-
|
|
128
|
-
try {
|
|
129
|
-
const window = await selector.selectWindow();
|
|
130
|
-
|
|
131
|
-
console.log('🔍 Detailed Window Analysis:');
|
|
132
|
-
console.log('============================');
|
|
133
|
-
|
|
134
|
-
// Basic info
|
|
135
|
-
console.log(`📱 Application: ${window.appName}`);
|
|
136
|
-
console.log(`🏷️ Title: "${window.title}"`);
|
|
137
|
-
console.log(`🆔 Window ID: ${window.id}`);
|
|
138
|
-
|
|
139
|
-
// Position & Size
|
|
140
|
-
console.log(`\n📍 Position & Dimensions:`);
|
|
141
|
-
console.log(` Global position: (${window.x}, ${window.y})`);
|
|
142
|
-
console.log(` Size: ${window.width} x ${window.height}`);
|
|
143
|
-
console.log(` Area: ${window.width * window.height} pixels`);
|
|
144
|
-
console.log(` Aspect ratio: ${(window.width / window.height).toFixed(2)}`);
|
|
145
|
-
|
|
146
|
-
// Screen info
|
|
147
|
-
console.log(`\n🖥️ Screen Information:`);
|
|
148
|
-
console.log(` Screen ID: ${window.screenId}`);
|
|
149
|
-
console.log(` Screen origin: (${window.screenX}, ${window.screenY})`);
|
|
150
|
-
console.log(` Screen size: ${window.screenWidth} x ${window.screenHeight}`);
|
|
151
|
-
|
|
152
|
-
// Relative position on screen
|
|
153
|
-
const relativeX = window.x - window.screenX;
|
|
154
|
-
const relativeY = window.y - window.screenY;
|
|
155
|
-
console.log(` Relative position: (${relativeX}, ${relativeY})`);
|
|
156
|
-
|
|
157
|
-
// Window positioning analysis
|
|
158
|
-
console.log(`\n🎯 Position Analysis:`);
|
|
159
|
-
const centerX = relativeX + window.width / 2;
|
|
160
|
-
const centerY = relativeY + window.height / 2;
|
|
161
|
-
const screenCenterX = window.screenWidth / 2;
|
|
162
|
-
const screenCenterY = window.screenHeight / 2;
|
|
163
|
-
|
|
164
|
-
console.log(` Window center: (${centerX.toFixed(0)}, ${centerY.toFixed(0)})`);
|
|
165
|
-
console.log(` Screen center: (${screenCenterX.toFixed(0)}, ${screenCenterY.toFixed(0)})`);
|
|
166
|
-
|
|
167
|
-
if (Math.abs(centerX - screenCenterX) < 50 && Math.abs(centerY - screenCenterY) < 50) {
|
|
168
|
-
console.log(` 🎯 Window is centered on screen`);
|
|
169
|
-
} else {
|
|
170
|
-
const position = [];
|
|
171
|
-
if (centerY < screenCenterY / 2) position.push('top');
|
|
172
|
-
else if (centerY > screenCenterY * 1.5) position.push('bottom');
|
|
173
|
-
else position.push('middle');
|
|
174
|
-
|
|
175
|
-
if (centerX < screenCenterX / 2) position.push('left');
|
|
176
|
-
else if (centerX > screenCenterX * 1.5) position.push('right');
|
|
177
|
-
else position.push('center');
|
|
178
|
-
|
|
179
|
-
console.log(` 📍 Window is positioned at ${position.join('-')} of screen`);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Size classification
|
|
183
|
-
console.log(`\n📏 Size Classification:`);
|
|
184
|
-
const screenArea = window.screenWidth * window.screenHeight;
|
|
185
|
-
const windowArea = window.width * window.height;
|
|
186
|
-
const areaPercentage = (windowArea / screenArea) * 100;
|
|
187
|
-
|
|
188
|
-
console.log(` Occupies ${areaPercentage.toFixed(1)}% of screen area`);
|
|
189
|
-
|
|
190
|
-
if (areaPercentage > 75) {
|
|
191
|
-
console.log(` 📺 Large window (> 75% of screen)`);
|
|
192
|
-
} else if (areaPercentage > 25) {
|
|
193
|
-
console.log(` 📄 Medium window (25-75% of screen)`);
|
|
194
|
-
} else {
|
|
195
|
-
console.log(` 📝 Small window (< 25% of screen)`);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return window;
|
|
199
|
-
|
|
200
|
-
} catch (error) {
|
|
201
|
-
console.error('Error during window analysis:', error.message);
|
|
202
|
-
throw error;
|
|
203
|
-
} finally {
|
|
204
|
-
await selector.cleanup();
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Main function to run examples
|
|
209
|
-
async function main() {
|
|
210
|
-
const args = process.argv.slice(2);
|
|
211
|
-
|
|
212
|
-
if (args.includes('--help')) {
|
|
213
|
-
console.log('Window Selector Examples:');
|
|
214
|
-
console.log('========================');
|
|
215
|
-
console.log('node examples/window-selector-example.js [option]');
|
|
216
|
-
console.log('');
|
|
217
|
-
console.log('Options:');
|
|
218
|
-
console.log(' --simple Simple window selection (default)');
|
|
219
|
-
console.log(' --advanced Advanced example with events');
|
|
220
|
-
console.log(' --multiple Select multiple windows');
|
|
221
|
-
console.log(' --analysis Detailed window analysis');
|
|
222
|
-
console.log(' --help Show this help');
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
try {
|
|
227
|
-
if (args.includes('--advanced')) {
|
|
228
|
-
await advancedExample();
|
|
229
|
-
} else if (args.includes('--multiple')) {
|
|
230
|
-
await multipleSelectionExample();
|
|
231
|
-
} else if (args.includes('--analysis')) {
|
|
232
|
-
await windowAnalysisExample();
|
|
233
|
-
} else {
|
|
234
|
-
await simpleExample();
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
console.log('\n🎉 Example completed successfully!');
|
|
238
|
-
|
|
239
|
-
} catch (error) {
|
|
240
|
-
console.error('\n❌ Example failed:', error.message);
|
|
241
|
-
process.exit(1);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
if (require.main === module) {
|
|
246
|
-
main();
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
module.exports = {
|
|
250
|
-
simpleExample,
|
|
251
|
-
advancedExample,
|
|
252
|
-
multipleSelectionExample,
|
|
253
|
-
windowAnalysisExample
|
|
254
|
-
};
|
package/quick-cursor-test.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[{"x":798,"y":526,"timestamp":20,"unixTimeMs":1752410795804,"cursorType":"text","type":"move"}]
|
package/test-both-cursor.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[{"x":798,"y":526,"timestamp":21,"unixTimeMs":1752410827986,"cursorType":"text","type":"move"}]
|
package/test-cursor-fix.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
const MacRecorder = require('./index.js');
|
|
2
|
-
|
|
3
|
-
async function testCursorCoordinates() {
|
|
4
|
-
console.log('🧪 Testing cursor coordinate fixes for window recording...');
|
|
5
|
-
|
|
6
|
-
const recorder = new MacRecorder();
|
|
7
|
-
|
|
8
|
-
try {
|
|
9
|
-
// Get available windows and displays
|
|
10
|
-
const windows = await recorder.getWindows();
|
|
11
|
-
const displays = await recorder.getDisplays();
|
|
12
|
-
|
|
13
|
-
console.log('\n📱 Available displays:');
|
|
14
|
-
displays.forEach((display, i) => {
|
|
15
|
-
console.log(` ${i + 1}. Display ${display.id}: ${display.resolution} at (${display.x}, ${display.y}) ${display.isPrimary ? '(Primary)' : ''}`);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
console.log('\n🪟 Available windows:');
|
|
19
|
-
windows.slice(0, 5).forEach((window, i) => {
|
|
20
|
-
console.log(` ${i + 1}. ${window.title} (${window.app}) - ${window.width}x${window.height} at (${window.x}, ${window.y})`);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
if (windows.length === 0) {
|
|
24
|
-
console.log('❌ No windows available for testing');
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Pick the first available window for testing
|
|
29
|
-
const testWindow = windows[0];
|
|
30
|
-
console.log(`\n🎯 Testing with window: ${testWindow.title}`);
|
|
31
|
-
console.log(` Window position: (${testWindow.x}, ${testWindow.y})`);
|
|
32
|
-
console.log(` Window size: ${testWindow.width}x${testWindow.height}`);
|
|
33
|
-
|
|
34
|
-
// Check current cursor position before recording
|
|
35
|
-
const cursorPos = recorder.getCursorPosition();
|
|
36
|
-
console.log(`\n🖱️ Current cursor position (global): (${cursorPos.x}, ${cursorPos.y})`);
|
|
37
|
-
|
|
38
|
-
// Setup recording options for window recording
|
|
39
|
-
recorder.options.windowId = testWindow.id;
|
|
40
|
-
recorder.options.captureCursor = true;
|
|
41
|
-
|
|
42
|
-
console.log('\n🔧 Starting cursor capture test for window recording...');
|
|
43
|
-
|
|
44
|
-
// Start cursor capture with window-relative coordinates
|
|
45
|
-
const outputFile = `./test-output/cursor-test-window-${Date.now()}.json`;
|
|
46
|
-
|
|
47
|
-
// Start cursor tracking first to see if coordinate transformation works
|
|
48
|
-
await recorder.startCursorCapture(outputFile, {
|
|
49
|
-
windowRelative: true,
|
|
50
|
-
windowInfo: {
|
|
51
|
-
x: testWindow.x,
|
|
52
|
-
y: testWindow.y,
|
|
53
|
-
width: testWindow.width,
|
|
54
|
-
height: testWindow.height,
|
|
55
|
-
displayId: null // Let it auto-detect
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
console.log('✅ Cursor capture started successfully!');
|
|
60
|
-
console.log('🖱️ Move your mouse around the window for 5 seconds...');
|
|
61
|
-
console.log(` Window bounds: (0, 0) to (${testWindow.width}, ${testWindow.height})`);
|
|
62
|
-
|
|
63
|
-
// Wait for 5 seconds to capture cursor movements
|
|
64
|
-
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
65
|
-
|
|
66
|
-
console.log('\n🛑 Stopping cursor capture...');
|
|
67
|
-
await recorder.stopCursorCapture();
|
|
68
|
-
|
|
69
|
-
console.log(`✅ Test completed! Check cursor data in: ${outputFile}`);
|
|
70
|
-
|
|
71
|
-
// Read and analyze some cursor data
|
|
72
|
-
const fs = require('fs');
|
|
73
|
-
if (fs.existsSync(outputFile)) {
|
|
74
|
-
const cursorData = JSON.parse(fs.readFileSync(outputFile, 'utf8'));
|
|
75
|
-
console.log(`\n📊 Captured ${cursorData.length} cursor events`);
|
|
76
|
-
|
|
77
|
-
if (cursorData.length > 0) {
|
|
78
|
-
const first = cursorData[0];
|
|
79
|
-
const last = cursorData[cursorData.length - 1];
|
|
80
|
-
|
|
81
|
-
console.log(` First event: (${first.x}, ${first.y}) - ${first.coordinateSystem}`);
|
|
82
|
-
console.log(` Last event: (${last.x}, ${last.y}) - ${last.coordinateSystem}`);
|
|
83
|
-
|
|
84
|
-
// Check if coordinates are within window bounds
|
|
85
|
-
const inBounds = cursorData.filter(event =>
|
|
86
|
-
event.x >= 0 && event.x < testWindow.width &&
|
|
87
|
-
event.y >= 0 && event.y < testWindow.height
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
console.log(` Events within window bounds: ${inBounds.length}/${cursorData.length} (${Math.round(inBounds.length/cursorData.length*100)}%)`);
|
|
91
|
-
|
|
92
|
-
if (inBounds.length > 0) {
|
|
93
|
-
console.log('✅ Cursor coordinates appear to be correctly transformed to window-relative!');
|
|
94
|
-
} else {
|
|
95
|
-
console.log('❌ No cursor coordinates are within window bounds - transformation may be incorrect');
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
} catch (error) {
|
|
101
|
-
console.error('❌ Test failed:', error.message);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
testCursorCoordinates().catch(console.error);
|