node-mac-recorder 1.2.11 → 1.3.0
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 +4 -1
- package/WINDOW_SELECTOR_README.md +396 -0
- package/binding.gyp +2 -1
- package/debug-window-selector.js +178 -0
- package/enhanced-window-selector.js +202 -0
- package/examples/integration-example.js +228 -0
- package/examples/window-selector-example.js +254 -0
- package/index.js +3 -0
- package/package.json +4 -2
- package/simple-test.js +38 -0
- package/src/mac_recorder.mm +6 -0
- package/src/window_selector.mm +482 -0
- package/window-selector-test.js +160 -0
- package/window-selector.js +259 -0
- package/working-example.js +94 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
# Window Selector
|
|
2
|
+
|
|
3
|
+
**macOS Window Selection Tool with Real-time Visual Overlay**
|
|
4
|
+
|
|
5
|
+
Bu modül, macOS'ta sistem imleci ile pencere seçimi yapabilmenizi sağlayan güçlü bir araçtır. İmleç hangi pencerenin üstüne gelirse, o pencereyi mavi kapsayıcı ile highlight eder ve merkeze yerleştirilen "Select Window" butonu ile seçim yapabilirsiniz.
|
|
6
|
+
|
|
7
|
+
## ✨ Özellikler
|
|
8
|
+
|
|
9
|
+
- **Real-time Window Detection**: İmleç hangi pencereye gelirse otomatik olarak tespit eder
|
|
10
|
+
- **Visual Overlay**: Seçilebilir pencereleri mavi transparant kapsayıcı ile highlight eder
|
|
11
|
+
- **Interactive Selection**: Merkeze yerleştirilen "Select Window" butonu ile kolay seçim
|
|
12
|
+
- **Multi-display Support**: Çoklu ekran kurulumlarında çalışır
|
|
13
|
+
- **Detailed Window Info**: Pencere pozisyonu, boyutu ve hangi ekranda olduğunu döndürür
|
|
14
|
+
- **Event-driven API**: Pencere hover, seçim ve hata durumları için event'ler
|
|
15
|
+
- **Permission Management**: macOS izin kontrolü ve yönetimi
|
|
16
|
+
|
|
17
|
+
## 🚀 Kurulum
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Ana proje dizininde
|
|
21
|
+
npm install
|
|
22
|
+
|
|
23
|
+
# Native modülü build edin
|
|
24
|
+
npm run build
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 📋 Sistem Gereksinimleri
|
|
28
|
+
|
|
29
|
+
- **macOS 10.15+** (Catalina veya üzeri)
|
|
30
|
+
- **Node.js 14+**
|
|
31
|
+
- **Xcode Command Line Tools**
|
|
32
|
+
- **System Permissions**:
|
|
33
|
+
- Screen Recording permission
|
|
34
|
+
- Accessibility permission
|
|
35
|
+
|
|
36
|
+
## 🔐 İzinler
|
|
37
|
+
|
|
38
|
+
İlk kullanımda macOS aşağıdaki izinleri isteyecektir:
|
|
39
|
+
|
|
40
|
+
1. **System Preferences > Security & Privacy > Privacy > Screen Recording**
|
|
41
|
+
- Terminal veya kullandığınız IDE'yi (VSCode, WebStorm, vb.) etkinleştirin
|
|
42
|
+
|
|
43
|
+
2. **System Preferences > Security & Privacy > Privacy > Accessibility**
|
|
44
|
+
- Terminal veya kullandığınız IDE'yi etkinleştirin
|
|
45
|
+
|
|
46
|
+
## 🎯 Temel Kullanım
|
|
47
|
+
|
|
48
|
+
### Basit Pencere Seçimi
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
const WindowSelector = require('./window-selector');
|
|
52
|
+
|
|
53
|
+
async function selectWindow() {
|
|
54
|
+
const selector = new WindowSelector();
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
console.log('Bir pencere seçin...');
|
|
58
|
+
const selectedWindow = await selector.selectWindow();
|
|
59
|
+
|
|
60
|
+
console.log('Seçilen pencere:', {
|
|
61
|
+
title: selectedWindow.title,
|
|
62
|
+
app: selectedWindow.appName,
|
|
63
|
+
position: `(${selectedWindow.x}, ${selectedWindow.y})`,
|
|
64
|
+
size: `${selectedWindow.width}x${selectedWindow.height}`,
|
|
65
|
+
screen: selectedWindow.screenId
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return selectedWindow;
|
|
69
|
+
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error('Hata:', error.message);
|
|
72
|
+
} finally {
|
|
73
|
+
await selector.cleanup();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
selectWindow();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Manuel Kontrol
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
const WindowSelector = require('./window-selector');
|
|
84
|
+
|
|
85
|
+
async function manualSelection() {
|
|
86
|
+
const selector = new WindowSelector();
|
|
87
|
+
|
|
88
|
+
// Event listener'lar
|
|
89
|
+
selector.on('windowEntered', (window) => {
|
|
90
|
+
console.log(`Pencere üstünde: ${window.title} (${window.appName})`);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
selector.on('windowSelected', (window) => {
|
|
94
|
+
console.log(`Seçildi: ${window.title}`);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Seçimi başlat
|
|
98
|
+
await selector.startSelection();
|
|
99
|
+
|
|
100
|
+
// Kullanıcı seçim yapana kadar bekle
|
|
101
|
+
// Seçim tamamlandığında 'windowSelected' event'i tetiklenir
|
|
102
|
+
|
|
103
|
+
// Seçimi durdurmak için:
|
|
104
|
+
// await selector.stopSelection();
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## 📚 API Reference
|
|
109
|
+
|
|
110
|
+
### WindowSelector Class
|
|
111
|
+
|
|
112
|
+
#### Constructor
|
|
113
|
+
```javascript
|
|
114
|
+
const selector = new WindowSelector();
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### Methods
|
|
118
|
+
|
|
119
|
+
##### `async selectWindow()`
|
|
120
|
+
Promise tabanlı pencere seçimi. Kullanıcı bir pencere seçene kadar bekler.
|
|
121
|
+
|
|
122
|
+
**Returns:** `Promise<WindowInfo>`
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
const window = await selector.selectWindow();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
##### `async startSelection()`
|
|
129
|
+
Pencere seçim modunu başlatır.
|
|
130
|
+
|
|
131
|
+
**Returns:** `Promise<boolean>`
|
|
132
|
+
|
|
133
|
+
##### `async stopSelection()`
|
|
134
|
+
Pencere seçim modunu durdurur.
|
|
135
|
+
|
|
136
|
+
**Returns:** `Promise<boolean>`
|
|
137
|
+
|
|
138
|
+
##### `getSelectedWindow()`
|
|
139
|
+
Son seçilen pencere bilgisini döndürür.
|
|
140
|
+
|
|
141
|
+
**Returns:** `WindowInfo | null`
|
|
142
|
+
|
|
143
|
+
##### `getStatus()`
|
|
144
|
+
Seçici durumunu döndürür.
|
|
145
|
+
|
|
146
|
+
**Returns:** `SelectionStatus`
|
|
147
|
+
|
|
148
|
+
##### `async checkPermissions()`
|
|
149
|
+
macOS izinlerini kontrol eder.
|
|
150
|
+
|
|
151
|
+
**Returns:** `Promise<PermissionStatus>`
|
|
152
|
+
|
|
153
|
+
##### `async cleanup()`
|
|
154
|
+
Tüm kaynakları temizler ve seçimi durdurur.
|
|
155
|
+
|
|
156
|
+
#### Events
|
|
157
|
+
|
|
158
|
+
##### `selectionStarted`
|
|
159
|
+
Seçim modu başladığında tetiklenir.
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
selector.on('selectionStarted', () => {
|
|
163
|
+
console.log('Seçim başladı');
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
##### `windowEntered`
|
|
168
|
+
İmleç bir pencereye geldiğinde tetiklenir.
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
selector.on('windowEntered', (windowInfo) => {
|
|
172
|
+
console.log(`Pencere: ${windowInfo.title}`);
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
##### `windowLeft`
|
|
177
|
+
İmleç bir pencereden ayrıldığında tetiklenir.
|
|
178
|
+
|
|
179
|
+
```javascript
|
|
180
|
+
selector.on('windowLeft', (windowInfo) => {
|
|
181
|
+
console.log(`Ayrıldı: ${windowInfo.title}`);
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
##### `windowSelected`
|
|
186
|
+
Bir pencere seçildiğinde tetiklenir.
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
selector.on('windowSelected', (windowInfo) => {
|
|
190
|
+
console.log('Seçilen pencere:', windowInfo);
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
##### `selectionStopped`
|
|
195
|
+
Seçim modu durduğunda tetiklenir.
|
|
196
|
+
|
|
197
|
+
##### `error`
|
|
198
|
+
Bir hata oluştuğunda tetiklenir.
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
selector.on('error', (error) => {
|
|
202
|
+
console.error('Hata:', error.message);
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## 📊 Data Types
|
|
207
|
+
|
|
208
|
+
### WindowInfo
|
|
209
|
+
```javascript
|
|
210
|
+
{
|
|
211
|
+
id: number, // Pencere ID'si
|
|
212
|
+
title: string, // Pencere başlığı
|
|
213
|
+
appName: string, // Uygulama adı
|
|
214
|
+
x: number, // Global X pozisyonu
|
|
215
|
+
y: number, // Global Y pozisyonu
|
|
216
|
+
width: number, // Pencere genişliği
|
|
217
|
+
height: number, // Pencere yüksekliği
|
|
218
|
+
screenId: number, // Hangi ekranda olduğu
|
|
219
|
+
screenX: number, // Ekranın X pozisyonu
|
|
220
|
+
screenY: number, // Ekranın Y pozisyonu
|
|
221
|
+
screenWidth: number, // Ekran genişliği
|
|
222
|
+
screenHeight: number // Ekran yüksekliği
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### SelectionStatus
|
|
227
|
+
```javascript
|
|
228
|
+
{
|
|
229
|
+
isSelecting: boolean, // Seçim modunda mı?
|
|
230
|
+
hasSelectedWindow: boolean, // Seçilmiş pencere var mı?
|
|
231
|
+
selectedWindow: WindowInfo | null,
|
|
232
|
+
nativeStatus: object // Native durum bilgisi
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### PermissionStatus
|
|
237
|
+
```javascript
|
|
238
|
+
{
|
|
239
|
+
screenRecording: boolean, // Ekran kaydı izni
|
|
240
|
+
accessibility: boolean, // Erişilebilirlik izni
|
|
241
|
+
microphone: boolean // Mikrofon izni
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 🎮 Test Etme
|
|
246
|
+
|
|
247
|
+
### Test Dosyasını Çalıştır
|
|
248
|
+
```bash
|
|
249
|
+
# Interaktif test
|
|
250
|
+
node window-selector-test.js
|
|
251
|
+
|
|
252
|
+
# API test modu
|
|
253
|
+
node window-selector-test.js --api-test
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Örnekleri Çalıştır
|
|
257
|
+
```bash
|
|
258
|
+
# Basit örnek
|
|
259
|
+
node examples/window-selector-example.js
|
|
260
|
+
|
|
261
|
+
# Gelişmiş örnek (event'lerle)
|
|
262
|
+
node examples/window-selector-example.js --advanced
|
|
263
|
+
|
|
264
|
+
# Çoklu seçim
|
|
265
|
+
node examples/window-selector-example.js --multiple
|
|
266
|
+
|
|
267
|
+
# Detaylı analiz
|
|
268
|
+
node examples/window-selector-example.js --analysis
|
|
269
|
+
|
|
270
|
+
# Yardım
|
|
271
|
+
node examples/window-selector-example.js --help
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## ⚡ Nasıl Çalışır?
|
|
275
|
+
|
|
276
|
+
1. **Window Detection**: macOS `CGWindowListCopyWindowInfo` API'si ile açık pencereleri tespit eder
|
|
277
|
+
2. **Cursor Tracking**: Real-time olarak imleç pozisyonunu takip eder
|
|
278
|
+
3. **Overlay Rendering**: NSWindow ile transparant overlay penceresi oluşturur
|
|
279
|
+
4. **Hit Testing**: İmlecin hangi pencere üstünde olduğunu hesaplar
|
|
280
|
+
5. **Visual Feedback**: Pencereyi highlight eden mavi kapsayıcı çizer
|
|
281
|
+
6. **User Interaction**: Merkeze yerleştirilen button ile seçim yapar
|
|
282
|
+
7. **Data Collection**: Seçilen pencerenin tüm bilgilerini toplar
|
|
283
|
+
|
|
284
|
+
## 🔧 Troubleshooting
|
|
285
|
+
|
|
286
|
+
### Build Hataları
|
|
287
|
+
```bash
|
|
288
|
+
# Xcode Command Line Tools'u yükle
|
|
289
|
+
xcode-select --install
|
|
290
|
+
|
|
291
|
+
# Node-gyp'i yeniden build et
|
|
292
|
+
npm run clean
|
|
293
|
+
npm run build
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### İzin Hataları
|
|
297
|
+
1. **System Preferences > Security & Privacy > Privacy** bölümüne git
|
|
298
|
+
2. **Screen Recording** ve **Accessibility** sekmelerinde Terminal'i etkinleştir
|
|
299
|
+
3. Uygulamayı yeniden başlat
|
|
300
|
+
|
|
301
|
+
### Runtime Hataları
|
|
302
|
+
```javascript
|
|
303
|
+
// İzinleri kontrol et
|
|
304
|
+
const permissions = await selector.checkPermissions();
|
|
305
|
+
if (!permissions.screenRecording) {
|
|
306
|
+
console.log('Screen recording permission required');
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## 🌟 Gelişmiş Örnekler
|
|
311
|
+
|
|
312
|
+
### Otomatik Pencere Kaydı
|
|
313
|
+
```javascript
|
|
314
|
+
const WindowSelector = require('./window-selector');
|
|
315
|
+
const MacRecorder = require('./index');
|
|
316
|
+
|
|
317
|
+
async function recordSelectedWindow() {
|
|
318
|
+
const selector = new WindowSelector();
|
|
319
|
+
const recorder = new MacRecorder();
|
|
320
|
+
|
|
321
|
+
try {
|
|
322
|
+
// Pencere seç
|
|
323
|
+
const window = await selector.selectWindow();
|
|
324
|
+
console.log(`Recording: ${window.title}`);
|
|
325
|
+
|
|
326
|
+
// Seçilen pencereyi kaydet
|
|
327
|
+
const outputPath = `./recordings/${window.appName}-${Date.now()}.mov`;
|
|
328
|
+
await recorder.startRecording(outputPath, {
|
|
329
|
+
windowId: window.id,
|
|
330
|
+
captureCursor: true,
|
|
331
|
+
includeMicrophone: true
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// 10 saniye kaydet
|
|
335
|
+
setTimeout(async () => {
|
|
336
|
+
await recorder.stopRecording();
|
|
337
|
+
console.log(`Recording saved: ${outputPath}`);
|
|
338
|
+
}, 10000);
|
|
339
|
+
|
|
340
|
+
} finally {
|
|
341
|
+
await selector.cleanup();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Pencere Monitoring
|
|
347
|
+
```javascript
|
|
348
|
+
const WindowSelector = require('./window-selector');
|
|
349
|
+
|
|
350
|
+
async function monitorWindowChanges() {
|
|
351
|
+
const selector = new WindowSelector();
|
|
352
|
+
const visitedWindows = new Set();
|
|
353
|
+
|
|
354
|
+
selector.on('windowEntered', (window) => {
|
|
355
|
+
const key = `${window.appName}-${window.title}`;
|
|
356
|
+
if (!visitedWindows.has(key)) {
|
|
357
|
+
visitedWindows.add(key);
|
|
358
|
+
console.log(`Yeni pencere keşfedildi: ${window.title} (${window.appName})`);
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
await selector.startSelection();
|
|
363
|
+
|
|
364
|
+
// İptal etmek için Ctrl+C
|
|
365
|
+
process.on('SIGINT', async () => {
|
|
366
|
+
console.log(`\nToplam keşfedilen pencere: ${visitedWindows.size}`);
|
|
367
|
+
await selector.cleanup();
|
|
368
|
+
process.exit(0);
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## 📄 Lisans
|
|
374
|
+
|
|
375
|
+
Bu modül ana projenin lisansı altındadır.
|
|
376
|
+
|
|
377
|
+
## 🤝 Katkıda Bulunma
|
|
378
|
+
|
|
379
|
+
1. Fork edin
|
|
380
|
+
2. Feature branch oluşturun (`git checkout -b feature/amazing-feature`)
|
|
381
|
+
3. Commit edin (`git commit -m 'Add amazing feature'`)
|
|
382
|
+
4. Push edin (`git push origin feature/amazing-feature`)
|
|
383
|
+
5. Pull Request açın
|
|
384
|
+
|
|
385
|
+
## ⭐ Özellik İstekleri
|
|
386
|
+
|
|
387
|
+
- [ ] Pencere gruplandırma
|
|
388
|
+
- [ ] Hotkey desteği
|
|
389
|
+
- [ ] Pencere filtreleme
|
|
390
|
+
- [ ] Çoklu seçim modu
|
|
391
|
+
- [ ] Screenshot alma
|
|
392
|
+
- [ ] Window history
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
**Not**: Bu modül sadece macOS'ta çalışır ve sistem izinleri gerektirir.
|
package/binding.gyp
CHANGED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const WindowSelector = require('./window-selector');
|
|
4
|
+
|
|
5
|
+
async function debugWindowSelector() {
|
|
6
|
+
console.log('🔍 Window Selector Debug Mode');
|
|
7
|
+
console.log('=============================\n');
|
|
8
|
+
|
|
9
|
+
const selector = new WindowSelector();
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
// 1. İzin kontrolü
|
|
13
|
+
console.log('1️⃣ Checking permissions...');
|
|
14
|
+
const permissions = await selector.checkPermissions();
|
|
15
|
+
console.log('Permissions:', JSON.stringify(permissions, null, 2));
|
|
16
|
+
|
|
17
|
+
if (!permissions.screenRecording || !permissions.accessibility) {
|
|
18
|
+
console.warn('⚠️ Missing permissions detected!');
|
|
19
|
+
console.warn('Go to: System Preferences > Security & Privacy > Privacy');
|
|
20
|
+
console.warn('Enable for Terminal/Node in both:');
|
|
21
|
+
console.warn('- Screen Recording');
|
|
22
|
+
console.warn('- Accessibility');
|
|
23
|
+
console.log();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 2. Native status before start
|
|
27
|
+
console.log('\n2️⃣ Native status before start:');
|
|
28
|
+
const initialStatus = selector.getStatus();
|
|
29
|
+
console.log(JSON.stringify(initialStatus, null, 2));
|
|
30
|
+
|
|
31
|
+
// 3. Start selection with detailed logging
|
|
32
|
+
console.log('\n3️⃣ Starting window selection...');
|
|
33
|
+
|
|
34
|
+
selector.on('selectionStarted', () => {
|
|
35
|
+
console.log('✅ Selection started event received');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
selector.on('windowEntered', (window) => {
|
|
39
|
+
console.log(`🏠 Window entered: "${window.title}" (${window.appName})`);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
selector.on('windowLeft', (window) => {
|
|
43
|
+
console.log(`🚪 Window left: "${window.title}" (${window.appName})`);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
selector.on('windowSelected', (window) => {
|
|
47
|
+
console.log('🎯 Window selected:', window.title);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
selector.on('error', (error) => {
|
|
51
|
+
console.error('❌ Error event:', error);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
await selector.startSelection();
|
|
55
|
+
|
|
56
|
+
// 4. Status after start
|
|
57
|
+
console.log('\n4️⃣ Status after start:');
|
|
58
|
+
const runningStatus = selector.getStatus();
|
|
59
|
+
console.log(JSON.stringify(runningStatus, null, 2));
|
|
60
|
+
|
|
61
|
+
// 5. Detailed native status monitoring
|
|
62
|
+
console.log('\n5️⃣ Monitoring native status (10 seconds)...');
|
|
63
|
+
console.log('Move your cursor over different windows');
|
|
64
|
+
console.log('The overlay should appear over windows\n');
|
|
65
|
+
|
|
66
|
+
for (let i = 0; i < 20; i++) {
|
|
67
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
68
|
+
const status = selector.getStatus();
|
|
69
|
+
|
|
70
|
+
process.stdout.write(`\r[${i+1}/20] `);
|
|
71
|
+
process.stdout.write(`Selecting: ${status.nativeStatus?.isSelecting || false}, `);
|
|
72
|
+
process.stdout.write(`Overlay: ${status.nativeStatus?.hasOverlay || false}, `);
|
|
73
|
+
process.stdout.write(`Windows: ${status.nativeStatus?.windowCount || 0}`);
|
|
74
|
+
|
|
75
|
+
if (status.nativeStatus?.currentWindow) {
|
|
76
|
+
process.stdout.write(`, Current: ${status.nativeStatus.currentWindow.appName}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log('\n\n6️⃣ Final status:');
|
|
81
|
+
const finalStatus = selector.getStatus();
|
|
82
|
+
console.log(JSON.stringify(finalStatus, null, 2));
|
|
83
|
+
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error('\n❌ Debug failed:', error.message);
|
|
86
|
+
console.error('Stack:', error.stack);
|
|
87
|
+
} finally {
|
|
88
|
+
console.log('\n🛑 Stopping selection...');
|
|
89
|
+
await selector.cleanup();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Alternative: Test native functions directly
|
|
94
|
+
async function testNativeFunctions() {
|
|
95
|
+
console.log('🧪 Testing Native Functions Directly');
|
|
96
|
+
console.log('====================================\n');
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
// Try to load native binding directly
|
|
100
|
+
let nativeBinding;
|
|
101
|
+
try {
|
|
102
|
+
nativeBinding = require("./build/Release/mac_recorder.node");
|
|
103
|
+
} catch (error) {
|
|
104
|
+
try {
|
|
105
|
+
nativeBinding = require("./build/Debug/mac_recorder.node");
|
|
106
|
+
} catch (debugError) {
|
|
107
|
+
console.error('❌ Cannot load native module');
|
|
108
|
+
console.error('Release error:', error.message);
|
|
109
|
+
console.error('Debug error:', debugError.message);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.log('✅ Native module loaded successfully');
|
|
115
|
+
|
|
116
|
+
// Test if window selector functions exist
|
|
117
|
+
console.log('\n🔍 Available native functions:');
|
|
118
|
+
const functions = [
|
|
119
|
+
'startWindowSelection',
|
|
120
|
+
'stopWindowSelection',
|
|
121
|
+
'getSelectedWindowInfo',
|
|
122
|
+
'getWindowSelectionStatus'
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
for (const func of functions) {
|
|
126
|
+
if (typeof nativeBinding[func] === 'function') {
|
|
127
|
+
console.log(`✅ ${func} - available`);
|
|
128
|
+
} else {
|
|
129
|
+
console.log(`❌ ${func} - missing`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Test direct native call
|
|
134
|
+
console.log('\n🚀 Testing direct native startWindowSelection...');
|
|
135
|
+
try {
|
|
136
|
+
const result = nativeBinding.startWindowSelection();
|
|
137
|
+
console.log('Native start result:', result);
|
|
138
|
+
|
|
139
|
+
if (result) {
|
|
140
|
+
console.log('✅ Native selection started');
|
|
141
|
+
|
|
142
|
+
// Check status
|
|
143
|
+
const status = nativeBinding.getWindowSelectionStatus();
|
|
144
|
+
console.log('Native status:', JSON.stringify(status, null, 2));
|
|
145
|
+
|
|
146
|
+
// Wait a bit
|
|
147
|
+
console.log('\nWaiting 3 seconds for overlay to appear...');
|
|
148
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
149
|
+
|
|
150
|
+
// Stop
|
|
151
|
+
const stopResult = nativeBinding.stopWindowSelection();
|
|
152
|
+
console.log('Native stop result:', stopResult);
|
|
153
|
+
} else {
|
|
154
|
+
console.log('❌ Native selection failed to start');
|
|
155
|
+
}
|
|
156
|
+
} catch (nativeError) {
|
|
157
|
+
console.error('❌ Native function error:', nativeError.message);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error('❌ Native test failed:', error.message);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Main function
|
|
166
|
+
async function main() {
|
|
167
|
+
const args = process.argv.slice(2);
|
|
168
|
+
|
|
169
|
+
if (args.includes('--native')) {
|
|
170
|
+
await testNativeFunctions();
|
|
171
|
+
} else {
|
|
172
|
+
await debugWindowSelector();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (require.main === module) {
|
|
177
|
+
main().catch(console.error);
|
|
178
|
+
}
|