macOS Window Selection Tool with Real-time Visual Overlay
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.
- Real-time Window Detection: İmleç hangi pencereye gelirse otomatik olarak tespit eder
- Visual Overlay: Seçilebilir pencereleri mavi transparant kapsayıcı ile highlight eder
- Interactive Selection: Merkeze yerleştirilen "Start Record" butonu ile kolay seçim
- Multi-display Support: Çoklu ekran kurulumlarında çalışır
- Detailed Window Info: Pencere pozisyonu, boyutu ve hangi ekranda olduğunu döndürür
- Event-driven API: Pencere hover, seçim ve hata durumları için event'ler
- Window Focus Control: Detect edilen pencereyi otomatik olarak en öne getirir
- Auto Bring-to-Front: Cursor hangi pencereye gelirse otomatik focus yapar
- Recording Preview Overlay: Kayıt alanını görselleştiren tam ekran overlay sistemi
- Screen Selection: Tam ekran overlay ile ekran seçimi (menu bar dahil, ESC ile iptal)
- Screen Recording Preview: Seçilen ekran için kayıt önizleme sistemi
- ESC Key Support: Tüm seçim modlarında ESC tuşu ile iptal
- Permission Management: macOS izin kontrolü ve yönetimi
# Ana proje dizininde
npm install
# Native modülü build edin
npm run build- macOS 10.15+ (Catalina veya üzeri)
- Node.js 14+
- Xcode Command Line Tools
- System Permissions:
- Screen Recording permission
- Accessibility permission
İlk kullanımda macOS aşağıdaki izinleri isteyecektir:
-
System Preferences > Security & Privacy > Privacy > Screen Recording
- Terminal veya kullandığınız IDE'yi (VSCode, WebStorm, vb.) etkinleştirin
-
System Preferences > Security & Privacy > Privacy > Accessibility
- Terminal veya kullandığınız IDE'yi etkinleştirin
const WindowSelector = require('./window-selector');
async function selectWindow() {
const selector = new WindowSelector();
try {
console.log('Bir pencere seçin (ESC ile iptal)...');
const selectedWindow = await selector.selectWindow();
console.log('Seçilen pencere:', {
title: selectedWindow.title,
app: selectedWindow.appName,
position: `(${selectedWindow.x}, ${selectedWindow.y})`,
size: `${selectedWindow.width}x${selectedWindow.height}`,
screen: selectedWindow.screenId
});
return selectedWindow;
} catch (error) {
console.error('Hata:', error.message);
} finally {
await selector.cleanup();
}
}
selectWindow();const WindowSelector = require('./window-selector');
async function manualSelection() {
const selector = new WindowSelector();
// Event listener'lar
selector.on('windowEntered', (window) => {
console.log(`Pencere üstünde: ${window.title} (${window.appName})`);
});
selector.on('windowSelected', (window) => {
console.log(`Seçildi: ${window.title}`);
});
// Seçimi başlat
await selector.startSelection();
// Kullanıcı seçim yapana kadar bekle
// Seçim tamamlandığında 'windowSelected' event'i tetiklenir
// Seçimi durdurmak için:
// await selector.stopSelection();
}const selector = new WindowSelector();Promise tabanlı pencere seçimi. Kullanıcı bir pencere seçene kadar bekler.
Returns: Promise<WindowInfo>
const window = await selector.selectWindow();Pencere seçim modunu başlatır.
Returns: Promise<boolean>
Pencere seçim modunu durdurur.
Returns: Promise<boolean>
Son seçilen pencere bilgisini döndürür.
Returns: WindowInfo | null
Seçici durumunu döndürür.
Returns: SelectionStatus
macOS izinlerini kontrol eder.
Returns: Promise<PermissionStatus>
Belirtilen pencereyi en öne getirir (focus yapar).
Parameters:
windowId(number) - Window ID
Returns: Promise<boolean> - Başarı/başarısızlık
const success = await selector.bringWindowToFront(windowInfo.id);Otomatik pencere en öne getirme özelliğini aktif/pasif yapar.
Parameters:
enabled(boolean) - Enable/disable
selector.setBringToFrontEnabled(true); // Auto mode ON
selector.setBringToFrontEnabled(false); // Auto mode OFFSeçilen pencere için kayıt önizleme overlay'ini gösterir. Tüm ekranı siyah yapar, sadece pencere alanını şeffaf bırakır.
Parameters:
windowInfo(WindowInfo) - Pencere bilgileri
Returns: Promise<boolean> - Başarı/başarısızlık
const success = await selector.showRecordingPreview(selectedWindow);Kayıt önizleme overlay'ini gizler.
Returns: Promise<boolean> - Başarı/başarısızlık
const success = await selector.hideRecordingPreview();Ekran seçim modunu başlatır. Tüm ekranları overlay ile gösterir.
Returns: Promise<boolean> - Başarı/başarısızlık
const success = await selector.startScreenSelection();Ekran seçim modunu durdurur.
Returns: Promise<boolean> - Başarı/başarısızlık
const success = await selector.stopScreenSelection();Son seçilen ekran bilgisini döndürür.
Returns: ScreenInfo | null
const screenInfo = selector.getSelectedScreen();Promise tabanlı ekran seçimi. Kullanıcı bir ekran seçene kadar bekler.
Returns: Promise<ScreenInfo>
const selectedScreen = await selector.selectScreen();Seçilen ekran için kayıt önizleme overlay'ini gösterir. Diğer ekranları siyah yapar, sadece seçili ekranı şeffaf bırakır.
Parameters:
screenInfo(ScreenInfo) - Ekran bilgileri
Returns: Promise<boolean> - Başarı/başarısızlık
const success = await selector.showScreenRecordingPreview(selectedScreen);Ekran kayıt önizleme overlay'ini gizler.
Returns: Promise<boolean> - Başarı/başarısızlık
const success = await selector.hideScreenRecordingPreview();Tüm kaynakları temizler ve seçimi durdurur.
Seçim modu başladığında tetiklenir.
selector.on('selectionStarted', () => {
console.log('Seçim başladı');
});İmleç bir pencereye geldiğinde tetiklenir.
selector.on('windowEntered', (windowInfo) => {
console.log(`Pencere: ${windowInfo.title}`);
});İmleç bir pencereden ayrıldığında tetiklenir.
selector.on('windowLeft', (windowInfo) => {
console.log(`Ayrıldı: ${windowInfo.title}`);
});Bir pencere seçildiğinde tetiklenir.
selector.on('windowSelected', (windowInfo) => {
console.log('Seçilen pencere:', windowInfo);
});Seçim modu durduğunda tetiklenir.
Bir hata oluştuğunda tetiklenir.
selector.on('error', (error) => {
console.error('Hata:', error.message);
});{
id: number, // Pencere ID'si
title: string, // Pencere başlığı
appName: string, // Uygulama adı
x: number, // Global X pozisyonu
y: number, // Global Y pozisyonu
width: number, // Pencere genişliği
height: number, // Pencere yüksekliği
screenId: number, // Hangi ekranda olduğu
screenX: number, // Ekranın X pozisyonu
screenY: number, // Ekranın Y pozisyonu
screenWidth: number, // Ekran genişliği
screenHeight: number // Ekran yüksekliği
}{
isSelecting: boolean, // Seçim modunda mı?
hasSelectedWindow: boolean, // Seçilmiş pencere var mı?
selectedWindow: WindowInfo | null,
nativeStatus: object // Native durum bilgisi
}{
screenRecording: boolean, // Ekran kaydı izni
accessibility: boolean, // Erişilebilirlik izni
microphone: boolean // Mikrofon izni
}{
id: number, // Ekran ID'si (0, 1, 2, ...)
name: string, // Ekran adı ("Display 1", "Display 2", ...)
x: number, // Global X pozisyonu
y: number, // Global Y pozisyonu
width: number, // Ekran genişliği
height: number, // Ekran yüksekliği
resolution: string, // Çözünürlük string'i ("1920x1080")
isPrimary: boolean // Ana ekran mı?
}# Interaktif test
node window-selector-test.js
# API test modu
node window-selector-test.js --api-test# Basit örnek
node examples/window-selector-example.js
# Gelişmiş örnek (event'lerle)
node examples/window-selector-example.js --advanced
# Çoklu seçim
node examples/window-selector-example.js --multiple
# Detaylı analiz
node examples/window-selector-example.js --analysis
# Yardım
node examples/window-selector-example.js --help- Window Detection: macOS
CGWindowListCopyWindowInfoAPI'si ile açık pencereleri tespit eder - Cursor Tracking: Real-time olarak imleç pozisyonunu takip eder
- Overlay Rendering: NSWindow ile transparant overlay penceresi oluşturur
- Hit Testing: İmlecin hangi pencere üstünde olduğunu hesaplar
- Visual Feedback: Pencereyi highlight eden mavi kapsayıcı çizer
- User Interaction: Merkeze yerleştirilen button ile seçim yapar
- Data Collection: Seçilen pencerenin tüm bilgilerini toplar
- Full Screen Overlay: Tüm ekranı kaplayan siyah transparan katman oluşturur
- Window Cutout: Seçilen pencere alanını şeffaf hale getirir (cut-out effect)
- Coordinate Conversion: CGWindow koordinatlarını NSView koordinatlarına dönüştürür
- Multi-Display Support: Çoklu ekran kurulumlarında doğru pozisyonlama yapar
- Non-Interactive: Mouse events'leri geçirir, kullanıcı etkileşimini engellemeZ
- Clean Management: Programatik açma/kapama kontrolü sağlar
- Multi-Screen Detection: NSScreen.screens ile tüm ekranları tespit eder
- Full Screen Coverage: Her ekran için tam kaplama overlay oluşturur (menu bar dahil)
- Interactive Overlays: Her ekranda merkezi "Select Screen" butonu
- Screen Information Display: Ekran adı ve çözünürlük bilgilerini gösterir
- Automatic Assignment: Her overlay'i kendi ekranına otomatik atar
- Selection Feedback: Seçim yapıldığında anında geri bildirim
- Multi-Screen Management: Birden fazla ekranı aynı anda yönetir
- Selective Darkening: Sadece seçilmeyen ekranları siyah overlay ile kaplar
- Recording Area Highlight: Seçilen ekran tamamen şeffaf kalır
- Screen-Specific Overlays: Her ekran için ayrı overlay penceresi
- Coordinate Independence: Her ekranın kendi koordinat sistemini kullanır
# Xcode Command Line Tools'u yükle
xcode-select --install
# Node-gyp'i yeniden build et
npm run clean
npm run build- System Preferences > Security & Privacy > Privacy bölümüne git
- Screen Recording ve Accessibility sekmelerinde Terminal'i etkinleştir
- Uygulamayı yeniden başlat
// İzinleri kontrol et
const permissions = await selector.checkPermissions();
if (!permissions.screenRecording) {
console.log('Screen recording permission required');
}const WindowSelector = require('./window-selector');
async function autoBringToFront() {
const selector = new WindowSelector();
// Auto bring-to-front varsayılan olarak AÇIK
// (Kapatmak için: selector.setBringToFrontEnabled(false))
selector.on('windowEntered', (window) => {
console.log(`🔝 Auto-focused: ${window.appName} - "${window.title}"`);
});
await selector.startSelection();
console.log('🖱️ Move cursor over windows - they will come to front automatically!');
console.log('💡 Only the specific window focuses, not all windows of the app');
}const WindowSelector = require('./window-selector');
async function manualFocus() {
const selector = new WindowSelector();
selector.on('windowEntered', async (window) => {
console.log(`Found: ${window.appName} - "${window.title}"`);
// Manuel olarak pencereyi en öne getir
const success = await selector.bringWindowToFront(window.id);
if (success) {
console.log('✅ Window brought to front!');
}
});
await selector.startSelection();
}const WindowSelector = require('./window-selector');
const MacRecorder = require('./index');
async function recordScreenWithPreview() {
const selector = new WindowSelector();
const recorder = new MacRecorder();
try {
// Ekran seç
const screen = await selector.selectScreen();
console.log(`Selected: ${screen.name} (${screen.resolution})`);
// Kayıt önizlemesi göster (diğer ekranlar siyah, seçili ekran şeffaf)
await selector.showScreenRecordingPreview(screen);
console.log('🎬 Screen recording preview shown');
// 3 saniye bekle
await new Promise(resolve => setTimeout(resolve, 3000));
// Ekran kaydını başlat
const outputPath = `./recordings/screen-${screen.id}-${Date.now()}.mov`;
await recorder.startRecording(outputPath, {
displayId: screen.id,
captureCursor: true,
includeMicrophone: true
});
console.log('🔴 Screen recording started...');
// 10 saniye kaydet
setTimeout(async () => {
await recorder.stopRecording();
// Önizleme overlay'ini gizle
await selector.hideScreenRecordingPreview();
console.log(`✅ Recording saved: ${outputPath}`);
}, 10000);
} finally {
await selector.cleanup();
}
}const WindowSelector = require('./window-selector');
const MacRecorder = require('./index');
async function recordWithPreview() {
const selector = new WindowSelector();
const recorder = new MacRecorder();
try {
// Pencere seç
const window = await selector.selectWindow();
console.log(`Selected: ${window.title}`);
// Kayıt önizlemesi göster (siyah overlay + şeffaf pencere alanı)
await selector.showRecordingPreview(window);
console.log('🎬 Recording preview shown - you can see exact recording area');
// 3 saniye bekle (kullanıcı görebilsin)
await new Promise(resolve => setTimeout(resolve, 3000));
// Kaydı başlat
const outputPath = `./recordings/${window.appName}-${Date.now()}.mov`;
await recorder.startRecording(outputPath, {
windowId: window.id,
captureCursor: true,
includeMicrophone: true
});
console.log('🔴 Recording started...');
// 10 saniye kaydet
setTimeout(async () => {
await recorder.stopRecording();
// Önizleme overlay'ini gizle
await selector.hideRecordingPreview();
console.log(`✅ Recording saved: ${outputPath}`);
}, 10000);
} finally {
await selector.cleanup();
}
}const WindowSelector = require('./window-selector');
async function selectScreen() {
const selector = new WindowSelector();
try {
console.log('Bir ekran seçin (ESC ile iptal)...');
const selectedScreen = await selector.selectScreen();
console.log('Seçilen ekran:', {
name: selectedScreen.name,
resolution: selectedScreen.resolution,
position: `(${selectedScreen.x}, ${selectedScreen.y})`,
isPrimary: selectedScreen.isPrimary
});
return selectedScreen;
} catch (error) {
if (error.message.includes('cancelled')) {
console.log('❌ Seçim iptal edildi');
} else {
console.error('Hata:', error.message);
}
} finally {
await selector.cleanup();
}
}const WindowSelector = require('./window-selector');
async function manualScreenSelection() {
const selector = new WindowSelector();
try {
// Ekran seçimini başlat
await selector.startScreenSelection();
console.log('🖥️ Screen overlays shown - click Start Record button (ESC to cancel)');
// Polling ile seçim bekle
const checkSelection = () => {
const selected = selector.getSelectedScreen();
if (selected) {
console.log(`✅ Screen selected: ${selected.name}`);
return selected;
}
setTimeout(checkSelection, 100);
};
checkSelection();
} catch (error) {
console.error('Hata:', error.message);
}
}const WindowSelector = require('./window-selector');
const MacRecorder = require('./index');
async function recordSelectedWindow() {
const selector = new WindowSelector();
const recorder = new MacRecorder();
try {
// Pencere seç
const window = await selector.selectWindow();
console.log(`Recording: ${window.title}`);
// Seçilen pencereyi kaydet
const outputPath = `./recordings/${window.appName}-${Date.now()}.mov`;
await recorder.startRecording(outputPath, {
windowId: window.id,
captureCursor: true,
includeMicrophone: true
});
// 10 saniye kaydet
setTimeout(async () => {
await recorder.stopRecording();
console.log(`Recording saved: ${outputPath}`);
}, 10000);
} finally {
await selector.cleanup();
}
}const WindowSelector = require('./window-selector');
async function monitorWindowChanges() {
const selector = new WindowSelector();
const visitedWindows = new Set();
selector.on('windowEntered', (window) => {
const key = `${window.appName}-${window.title}`;
if (!visitedWindows.has(key)) {
visitedWindows.add(key);
console.log(`Yeni pencere keşfedildi: ${window.title} (${window.appName})`);
}
});
await selector.startSelection();
// İptal etmek için Ctrl+C
process.on('SIGINT', async () => {
console.log(`\nToplam keşfedilen pencere: ${visitedWindows.size}`);
await selector.cleanup();
process.exit(0);
});
}Bu modül ana projenin lisansı altındadır.
- Fork edin
- Feature branch oluşturun (
git checkout -b feature/amazing-feature) - Commit edin (
git commit -m 'Add amazing feature') - Push edin (
git push origin feature/amazing-feature) - Pull Request açın
- Pencere gruplandırma
- Hotkey desteği
- Pencere filtreleme
- Çoklu seçim modu
- Screenshot alma
- Window history
- Tam ekran overlay (menu bar dahil) ✅
- Multi-display desteği ✅
- Kayıt önizleme sistemi ✅
- Hotkey desteği
- Çoklu ekran seçimi
- Ekran thumbnail'ları
Not: Bu modül sadece macOS'ta çalışır ve sistem izinleri gerektirir.