dynamic-desktop-manager
Version:
Electron.js uygulamaları için Windows'ta dinamik masaüstü duvar kağıtları (MP4, GIF) ayarlayın. Çoklu monitör, ses ve sığdırma seçeneklerini destekler.
196 lines (171 loc) • 8.42 kB
JavaScript
const { BrowserWindow, screen } = require('electron');
const path = require('path');
const os = require('os');
let ffi;
let ref;
let user32;
// Aktif duvar kağıdı pencerelerini ve ayarlarını saklamak için
// Key: display.id (string), Value: { window: BrowserWindow, filePath: string, type: string, options: WallpaperOptions }
const activeWallpaperWindows = new Map();
function initFFI() {
if (os.platform() !== 'win32' || user32) return;
try {
ffi = require('ffi-napi');
ref = require('ref-napi');
user32 = new ffi.Library('user32', {
'FindWindowW': ['pointer', ['string', 'string']],
'FindWindowExW': ['pointer', ['pointer', 'pointer', 'string', 'string']],
'SendMessageTimeoutW': ['uint32', ['pointer', 'uint32', 'uintptr_t', 'uintptr_t', 'uint32', 'uint32', 'pointer']],
'EnumWindows': ['bool', ['pointer', 'pointer']],
'GetParent': ['pointer', ['pointer']],
'SetParent': ['pointer', ['pointer', 'pointer']],
'GetClassNameW': ['int', ['pointer', 'pointer', 'int']],
});
console.log("dynamic-desktop-manager: FFI başarıyla başlatıldı.");
} catch (e) {
console.error("dynamic-desktop-manager: ffi-napi veya ref-napi yüklenemedi. Windows'ta dinamik duvar kağıdı çalışmayacak.", e);
ffi = null;
user32 = null;
}
}
function attachToDesktop(electronWindow) {
if (os.platform() !== 'win32' || !user32) {
console.warn("dynamic-desktop-manager: attachToDesktop Windows dışı platformda veya FFI başlatılmamışken çağrıldı.");
return;
}
const progman = user32.FindWindowW(ref.allocCString('Progman', 'utf16le'), null);
if (progman.isNull()) {
console.error("dynamic-desktop-manager: Progman penceresi bulunamadı.");
return;
}
let resultPtr = ref.alloc('uint64');
user32.SendMessageTimeoutW(progman, 0x052C, 0, 0, 0x0000, 1000, resultPtr);
let workerW = null;
const enumWindowsProc = ffi.Callback('bool', ['pointer', 'pointer'], (hwnd, lParam) => {
const defView = user32.FindWindowExW(hwnd, null, ref.allocCString('SHELLDLL_DefView', 'utf16le'), null);
if (!defView.isNull()) {
let classNameBuf = Buffer.alloc(256 * 2);
user32.GetClassNameW(hwnd, classNameBuf, 255);
const className = classNameBuf.toString('utf16le').replace(/\0/g, '');
if (className === 'WorkerW') {
const parent = user32.GetParent(hwnd);
if (parent.equals(progman) || parent.isNull()) {
workerW = hwnd;
return false;
}
}
}
return true;
});
user32.EnumWindows(enumWindowsProc, null);
if (!workerW || workerW.isNull()) {
let currentChild = user32.FindWindowExW(progman, null, ref.allocCString('WorkerW', 'utf16le'), null);
while (!currentChild.isNull()) {
const defView = user32.FindWindowExW(currentChild, null, ref.allocCString('SHELLDLL_DefView', 'utf16le'), null);
if (!defView.isNull()) {
workerW = currentChild;
break;
}
currentChild = user32.FindWindowExW(progman, currentChild, ref.allocCString('WorkerW', 'utf16le'), null);
}
}
if (workerW && !workerW.isNull()) {
const electronWinHandle = electronWindow.getNativeWindowHandle();
user32.SetParent(electronWinHandle, workerW);
console.log(`dynamic-desktop-manager: Duvar kağıdı penceresi WorkerW'ye başarıyla eklendi (Ekran: ${electronWindow.displayTargetId}, WorkerW: ${workerW.toString()})`);
} else {
console.error(`dynamic-desktop-manager: Uygun WorkerW penceresi bulunamadı (Ekran: ${electronWindow.displayTargetId}). Duvar kağıdı simgelerin arkasında olmayabilir.`);
}
}
async function createOrUpdateWallpaperWindow(display, filePath, type, options) {
initFFI(); // Her ihtimale karşı FFI'nin başlatıldığından emin ol
const displayIdStr = display.id.toString();
if (activeWallpaperWindows.has(displayIdStr)) {
const existing = activeWallpaperWindows.get(displayIdStr);
// Eğer dosya ve temel ayarlar aynıysa, sadece medyayı güncelle
if (existing.filePath === filePath &&
existing.options.objectFit === options.objectFit &&
existing.options.volume === options.volume &&
existing.options.loop === options.loop) {
existing.window.webContents.send('set-media', { filePath, type, options });
existing.window.showInactive(); // Görünür olduğundan emin ol
console.log(`dynamic-desktop-manager: Mevcut duvar kağıdı penceresi güncellendi (Ekran ID: ${displayIdStr})`);
return existing.window;
}
// Aksi takdirde, eskisini kapat ve yenisini oluştur
await clearWallpaperWindow(displayIdStr);
}
const { x, y, width, height } = display.bounds;
const wallpaperWindow = new BrowserWindow({
x, y, width, height,
frame: false,
transparent: false,
backgroundColor: '#000000',
alwaysOnTop: false,
skipTaskbar: true,
focusable: false,
show: false,
webPreferences: {
preload: path.join(__dirname, '..', 'preload', 'wallpaper-preload.js'),
nodeIntegration: false,
contextIsolation: true,
devTools: process.env.NODE_ENV === 'development',
webSecurity: true, // file:// URL'leri için true kalmalı
},
type: 'toolbar',
});
wallpaperWindow.displayTargetId = displayIdStr; // Hangi ekrana ait olduğunu takip etmek için
const wallpaperHtmlPath = path.join(__dirname, '..', 'renderer', 'wallpaper.html');
await wallpaperWindow.loadFile(wallpaperHtmlPath);
wallpaperWindow.webContents.on('did-finish-load', () => {
wallpaperWindow.webContents.send('set-media', { filePath, type, options });
if (os.platform() === 'win32' && ffi && user32) { // FFI'nin başarılı olup olmadığını kontrol et
attachToDesktop(wallpaperWindow);
}
wallpaperWindow.showInactive();
console.log(`dynamic-desktop-manager: Yeni duvar kağıdı penceresi oluşturuldu ve yüklendi (Ekran ID: ${displayIdStr})`);
});
wallpaperWindow.on('closed', () => {
activeWallpaperWindows.delete(displayIdStr);
console.log(`dynamic-desktop-manager: Duvar kağıdı penceresi kapatıldı (Ekran ID: ${displayIdStr})`);
});
wallpaperWindow.webContents.on('will-navigate', (event) => event.preventDefault());
wallpaperWindow.webContents.setWindowOpenHandler(() => ({ action: 'deny' }));
activeWallpaperWindows.set(displayIdStr, { window: wallpaperWindow, filePath, type, options });
return wallpaperWindow;
}
async function clearWallpaperWindow(displayIdStr) {
if (activeWallpaperWindows.has(displayIdStr)) {
const entry = activeWallpaperWindows.get(displayIdStr);
if (entry.window && !entry.window.isDestroyed()) {
entry.window.close();
}
activeWallpaperWindows.delete(displayIdStr);
console.log(`dynamic-desktop-manager: Duvar kağıdı temizlendi (Ekran ID: ${displayIdStr})`);
}
}
async function clearAllWallpaperWindows() {
for (const displayIdStr of activeWallpaperWindows.keys()) {
await clearWallpaperWindow(displayIdStr);
}
console.log("dynamic-desktop-manager: Tüm aktif duvar kağıtları temizlendi.");
}
function getActiveWallpapers() {
const result = {};
for (const [displayId, data] of activeWallpaperWindows.entries()) {
result[displayId] = {
filePath: data.filePath,
type: data.type,
options: data.options,
displayBounds: screen.getAllDisplays().find(d => d.id.toString() === displayId)?.bounds
};
}
return result;
}
module.exports = {
createOrUpdateWallpaperWindow,
clearWallpaperWindow,
clearAllWallpaperWindows,
getActiveWallpapers,
initFFI // Gerekirse dışarıdan tetiklemek için
};