# How OpenWhispr Implements Content Protection for the Dictation Window

> Discover how OpenWhispr secures your dictation window by using Electron's setContentProtection API to prevent screen captures and protect sensitive UI elements.

- Repository: [OpenWhispr/openwhispr](https://github.com/OpenWhispr/openwhispr)
- Tags: how-to-guide
- Published: 2026-09-06

---

**OpenWhispr protects sensitive UI elements by dynamically invoking Electron’s native `setContentProtection` API on the main window and floating dictation pill whenever screen captures occur or the Agent Panel opens.**

OpenWhispr is an Electron-based voice dictation application that handles transient transcripts and private assistant conversations. To prevent these elements from appearing in screen recordings or video conferencing streams, the application implements a **content protection** system that leverages native operating-system-level window flags. The implementation centers on two runtime state flags and a central window management class that coordinates protection across multiple BrowserWindow instances.

## Understanding the Content Protection Architecture

The protection mechanism relies on a dual-flag system that monitors UI state and triggers protection accordingly.

### Runtime Privacy Flags

OpenWhispr tracks two boolean state properties that determine when content protection should be active:

- **`_screenContextProtection`** – Enabled when the application captures a screenshot of the current screen to send as context to the voice assistant.
- **`_assistantPanelOpen`** – Set to `true` while the Agent Panel (the LLM response interface) is visible to the user.

When either flag evaluates to `true`, the application assumes sensitive information is on-screen and enables protection.

### The WindowManager Central Controller

All window-related operations reside in [`src/helpers/windowManager.js`](https://github.com/OpenWhispr/openwhispr/blob/main/src/helpers/windowManager.js), which exports a `WindowManager` class. This class owns references to the main application window and the floating "Agent Dictation Pill," exposing methods to synchronize their protection states based on the runtime flags.

## Implementation Details in windowManager.js

The core logic lives in the `WindowManager` class, where Electron’s `setContentProtection` API is called reactively.

### Dynamic Protection Updates

The `_updateMainContentProtection()` method (lines 176–181) evaluates the current privacy flags and applies protection to the main window:

```javascript
_updateMainContentProtection() {
  if (!this.mainWindow) return;
  
  this.mainWindow.setContentProtection(
    Boolean(this._screenContextProtection || this._assistantPanelOpen)
  );
}

```

This method is invoked whenever `_screenContextProtection` or `_assistantPanelOpen` changes value, ensuring the window is hidden from screen capture only when necessary.

### Protecting the Floating Pill Window

When the Agent Panel opens, the application spawns a floating pill window for dictation controls. During initialization (lines 174–176), this window is explicitly marked as protected:

```javascript
pillWindow.setContentProtection(true);

```

Unlike the main window, the pill window remains permanently protected because it may display live transcription text that should never appear in recordings.

## Triggering Protection via IPC

The renderer process communicates state changes to the main process through IPC channels, which ultimately invoke the window manager’s protection methods.

### Screen Context Protection

When the voice assistant captures a screen thumbnail, the renderer enables protection temporarily:

```javascript
// Enable protection while capturing screenshot
ipcRenderer.invoke('set-screen-context-protection', true);

// Disable after capture completes
ipcRenderer.invoke('set-screen-context-protection', false);

```

These IPC calls toggle the `_screenContextProtection` flag and trigger `_updateMainContentProtection()`.

### Assistant Panel State

Opening the Agent Panel implicitly enables protection because `_assistantPanelOpen` becomes `true`:

```javascript
// Show the assistant panel (enables protection)
ipcRenderer.send('toggle-assistant-panel', true);

// Hide the panel (may disable protection if no screenshot active)
ipcRenderer.send('toggle-assistant-panel', false);

```

The IPC handlers (typically defined in [`src/helpers/ipcHandlers.js`](https://github.com/OpenWhispr/openwhispr/blob/main/src/helpers/ipcHandlers.js) or similar) forward these events to the `WindowManager` instance, which updates the protection state accordingly.

## Practical Code Examples

### Query Current Protection State

For debugging or UI indicators, you can check whether the dictation window is currently protected:

```javascript
const isProtected = await ipcRenderer.invoke('is-content-protected');
console.log('Dictation window protected:', isProtected);

```

### Complete Protection Flow

The following pattern demonstrates how a voice-assistant request orchestrates protection:

```javascript
// 1. Prepare to capture screen context
await ipcRenderer.invoke('set-screen-context-protection', true);

// 2. Capture screenshot (window is now hidden from capture APIs)
const screenshot = await captureScreen();

// 3. Open agent panel (forces protection to remain active)
ipcRenderer.send('toggle-assistant-panel', true);

// 4. Send request with context
await sendToAssistant({ image: screenshot });

// 5. Cleanup when done
await ipcRenderer.invoke('set-screen-context-protection', false);
// Protection remains active only if panel is still open

```

## Summary

- **Dual-flag system:** OpenWhispr uses `_screenContextProtection` and `_assistantPanelOpen` to track when sensitive data is visible.
- **Centralized control:** The `WindowManager` class in [`src/helpers/windowManager.js`](https://github.com/OpenWhispr/openwhispr/blob/main/src/helpers/windowManager.js) orchestrates all protection state via `_updateMainContentProtection()`.
- **API usage:** Electron’s `setContentProtection(true)` prevents the OS from including the window in screen recordings or streams.
- **Permanent pill protection:** The floating dictation pill is always protected via `pillWindow.setContentProtection(true)` during creation.
- **IPC integration:** Renderer processes toggle protection via `set-screen-context-protection` and `toggle-assistant-panel` channels.

## Frequently Asked Questions

### What is the `setContentProtection` API in Electron?

`setContentProtection` is a native Electron method available on `BrowserWindow` instances that instructs the operating system to exclude the window from screen captures, screen sharing, and screenshot APIs. When enabled, the window appears as a black rectangle or is omitted entirely from video streams in applications like Zoom, Teams, or OBS.

### Why does OpenWhispr use two separate flags for content protection?

The two-flag design separates transient protection (screenshot capture that lasts seconds) from persistent UI state (Agent Panel visibility). This allows the main window to remain unprotected during normal dictation while ensuring protection during sensitive operations, optimizing usability while maintaining privacy.

### Is the floating dictation pill always protected?

Yes. According to the source code in [`src/helpers/windowManager.js`](https://github.com/OpenWhispr/openwhispr/blob/main/src/helpers/windowManager.js) (lines 174–176), the pill window receives `setContentProtection(true)` immediately upon creation. Since the pill may display live transcription text that could contain sensitive information, it remains hidden from screen capture regardless of other application states.

### How can I verify that content protection is active?

You can invoke the `is-content-protected` IPC channel from the renderer process to query the current state, or check the window behavior by attempting to capture the screen using system tools (the protected window will appear blank or missing in the resulting image).