Skip to content

giacomo/dwm-windows

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

12 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸͺŸ DWM Windows

A modern Node.js/TypeScript library for accessing Windows Desktop Window Manager (DWM) APIs. Get live window thumbnails, icons, and manage virtual desktops with native C++ performance.

✨ Features

Performance and capture notes

  • Default capture prefers classic DWM thumbnail and PrintWindow paths to avoid the flashing yellow border and screen flicker.

  • To opt into Windows Graphics Capture (WGC) for higher fidelity on some apps, set the environment variable DWM_WINDOWS_USE_WGC=1 before running your app. The module will hide the capture border and cursor when supported.

  • Off-screen composition is used to avoid showing the helper window. If you still observe flicker, ensure no antivirus overlays or global screen effects are active.

  • πŸ“ TypeScript-first - Full type definitions and IntelliSense support

  • ⚑ Native performance - C++ bindings for optimal speed

  • 🎯 Window management - Focus, filter, and control windows programmatically

  • πŸ”” Event hooks (no polling) - Created/closed/focused callbacks via native WinEvent hooks

πŸ“¦ Installation

yarn add dwm-windows

πŸš€ Quick Start

import dwmWindows from 'dwm-windows';

// Get all visible windows on current desktop
const windows = dwmWindows.getVisibleWindows();

for (const window of windows) {
  console.log(`${window.title} (${window.executablePath})`);
  console.log(`Icon: ${window.icon.substring(0, 50)}...`);
  console.log(`Thumbnail: ${window.thumbnail.substring(0, 50)}...`);
}

// Focus a specific window
dwmWindows.openWindow(windows[0].id);

πŸ“– API Reference

Core Methods

getVisibleWindows(options?): WindowInfo[]

Returns visible windows. Use { includeAllDesktops: true } to include all virtual desktops.

getWindows(options?): WindowInfo[]

Returns all windows (including hidden ones).

openWindow(windowId: number): boolean

Brings a window to the foreground and focuses it.

updateThumbnail(windowId: number): string

Refreshes and returns the PNG thumbnail as a base64 data URL.

Async API (non-blocking)

Promise-based variants that run work off the main thread and won't block the event loop:

  • getWindowsAsync(options?): Promise<WindowInfo[]>
  • getVisibleWindowsAsync(options?): Promise<WindowInfo[]>
  • openWindowAsync(windowId: number): Promise<boolean>
  • updateThumbnailAsync(windowId: number): Promise<string>

Example:

import dwmWindows from 'dwm-windows';

const all = await dwmWindows.getWindowsAsync({ includeAllDesktops: true });
if (all.length) {
  await dwmWindows.openWindowAsync(all[0].id);
  const freshThumb = await dwmWindows.updateThumbnailAsync(all[0].id);
  console.log('Thumb length:', freshThumb.length);
}

Event Hooks (no polling)

Subscribe to native window events without polling:

  • onWindowCreated(cb: (e) => void)
  • onWindowClosed(cb: (e) => void)
  • onWindowFocused(cb: (e) => void)
  • onWindowChange(cb: (e) => void) // unified: e.type in {created,closed,focused,minimized,restored}
  • stopWindowEvents()

Each event payload contains: { id, hwnd, title, executablePath, isVisible, type }. For closed, title/executablePath may be empty because the window is already gone.

import dwmWindows from 'dwm-windows';

dwmWindows.onWindowCreated(e => console.log('Created:', e));
dwmWindows.onWindowClosed(e => console.log('Closed:', e));
dwmWindows.onWindowFocused(e => console.log('Focused:', e));

// Later, to clean up
dwmWindows.stopWindowEvents();

Filter Methods

getWindowsByTitle(titleFilter: string): WindowInfo[]

Filters windows by title (case-insensitive substring match).

getWindowsByExecutable(executableName: string): WindowInfo[]

Filters windows by executable name (e.g., "notepad.exe").

WindowInfo Interface

interface WindowInfo {
  id: number;                // HWND as number (same as hwnd)
  title: string;             // Window title
  executablePath: string;    // Full path to executable
  isVisible: boolean;        // Visibility state
  hwnd: number;             // Windows handle (same as id)
  thumbnail: string;        // PNG thumbnail (base64 data URL)
  icon: string;             // App icon (base64 data URL)
}

πŸ’‘ Usage Examples

Virtual Desktop Comparison

import dwmWindows from 'dwm-windows';

const currentDesktop = dwmWindows.getVisibleWindows();
const allDesktops = dwmWindows.getVisibleWindows({ includeAllDesktops: true });

// Find windows that exist on other desktops but not current one
// Note: id equals hwnd (native handle), which is stable for the window's lifetime
const currentWindowKeys = new Set(
  currentDesktop.map(w => `${w.title}|${w.executablePath}`)
);
const hiddenWindows = allDesktops.filter(w => 
  !currentWindowKeys.has(`${w.title}|${w.executablePath}`)
);

console.log(`Current desktop: ${currentDesktop.length} windows`);
console.log(`Hidden on other desktops: ${hiddenWindows.length} windows`);

Window Management

// Find all Chrome windows
const chromeWindows = dwmWindows.getWindowsByExecutable('chrome.exe');

// Focus the first Chrome window
if (chromeWindows.length > 0) {
  dwmWindows.openWindow(chromeWindows[0].id);
}

// Find windows by title
const codeWindows = dwmWindows.getWindowsByTitle('Visual Studio Code');

Thumbnail Analysis

const windows = dwmWindows.getVisibleWindows();

const getDataSize = (dataUrl: string) => {
  const base64 = dataUrl.split(',')[1] || '';
  return Math.round(base64.length * 0.75 / 1024); // KB estimate
};

const totalIconSize = windows.reduce((sum, w) => sum + getDataSize(w.icon), 0);
const totalThumbSize = windows.reduce((sum, w) => sum + getDataSize(w.thumbnail), 0);

console.log(`Total payload: ${totalIconSize + totalThumbSize}KB`);
console.log(`Icons: ${totalIconSize}KB, Thumbnails: ${totalThumbSize}KB`);

Live Updates with Events

import dwmWindows from 'dwm-windows';

const windows = new Map<number, { title: string }>();
dwmWindows.getVisibleWindows().forEach(w => windows.set(w.id, { title: w.title }));

dwmWindows.onWindowCreated(e => {
  windows.set(e.id, { title: e.title });
  console.log('Added', e.id, e.title);
});

dwmWindows.onWindowClosed(e => {
  windows.delete(e.id);
  console.log('Removed', e.id);
});

dwmWindows.onWindowFocused(e => {
  console.log('Focused', e.id, e.title);
});

πŸ—οΈ Development

Prerequisites

  • Windows 10/11
  • Node.js β‰₯ 16
  • Visual Studio Build Tools or Visual Studio with C++ workload
  • Python (for node-gyp)

Building

# Install dependencies and build
yarn install

# Rebuild native module only
yarn rebuild

# Build TypeScript and native module
yarn build

# Run example
yarn example

Notes:

  • Windows Graphics Capture is enabled by default for robust, flicker-free captures when supported.
  • Minimized windows use DWM previews; if only a tiny title bar is available, a placeholder thumbnail (centered app icon) is shown instead of a low-quality image.

Project Structure

dwm-windows/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ index.ts      # Main API
β”‚   β”œβ”€β”€ types.d.ts    # Type definitions
β”‚   └── example.ts    # Usage examples
β”œβ”€β”€ dwm_thumbnail.cc  # C++ native bindings
β”œβ”€β”€ binding.gyp       # Node-gyp build configuration
└── build/            # Compiled binaries

πŸ”§ Requirements

  • OS: Windows 10/11 (x64)
  • Node.js: β‰₯ 16.0.0
  • Architecture: x64 only

πŸ“„ License

MIT Β© Giacomo Barbalinardo

🀝 Contributing

Contributions welcome! Please read our contributing guidelines and submit pull requests for any improvements.


Built with ❀️ for Windows and Node devs

About

Windows DWM thumbnail generator for Node.js/Electron

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published