How Fluxer Handles macOS Dock Badges and Accessibility Permissions in Electron

Fluxer isolates macOS-specific dock badges, bounce notifications, and accessibility permissions in dedicated IPC handlers within the main process, exposing them to the renderer through a typed preload bridge while using platform checks to ensure cross-platform compatibility.

Fluxer is an Electron-based desktop application that provides deep integration with macOS system features. Understanding how Fluxer handles macOS-specific features like dock badge updates and accessibility permissions reveals the architecture patterns used to maintain clean separation between platform-specific code and cross-platform business logic.

Architecture Overview for macOS Features

All macOS-specific functionality in Fluxer is isolated within the main process and exposed to the renderer through a secure preload bridge. The architecture relies on three key components:

  • Main Process Handlers: Located in fluxer_desktop/src/main/IpcHandlers.tsx, these handlers contain the platform-specific implementations using Electron's native APIs.
  • Preload Bridge: Defined in fluxer_desktop/src/preload/index.tsx, this bridge securely exposes IPC methods to the renderer process without exposing the full Node.js API.
  • Platform Guards: All macOS-specific code paths check process.platform === 'darwin' before executing, ensuring the application runs safely on Windows and Linux.

Implementing macOS Dock Badges in Fluxer

The dock badge feature allows Fluxer to display notification counts and attention states on the macOS dock icon. This implementation uses Electron's app.dock API exclusively on macOS while providing fallbacks for other platforms.

Setting the Dock Badge Count

When the renderer needs to update the badge count, it invokes electronApi.setBadgeCount(count) through the preload bridge. The main process handler in fluxer_desktop/src/main/IpcHandlers.tsx processes this request:

// In fluxer_desktop/src/main/IpcHandlers.tsx
ipcMain.on('set-badge-count', (event, payload) => {
  const count = payload?.count ?? 0;
  const label = payload?.text ?? String(count);
  
  if (process.platform === 'darwin' && app.dock) {
    // macOS-specific: Use app.dock.setBadge
    app.dock.setBadge(count > 0 ? label : '');
  } else if (process.platform === 'win32') {
    // Windows fallback: Use overlay icon
    setWindowsBadgeOverlay(count);
  } else {
    // Linux/generic fallback
    app.setBadgeCount(count);
  }
});

The preload bridge in fluxer_desktop/src/preload/index.tsx exposes this functionality:

// In fluxer_desktop/src/preload/index.tsx
setBadgeCount: (count: number, text?: string) => {
  ipcRenderer.send('set-badge-count', { count, text });
}

Bouncing the Dock Icon for Attention

Fluxer implements the macOS dock bounce feature to alert users of critical events. The renderer invokes electronApi.bounceDock(type) where type can be 'informational' or 'critical'.

The main process handler routes this to app.dock.bounce():

// In fluxer_desktop/src/main/IpcHandlers.tsx
ipcMain.handle('bounce-dock', (event, type) => {
  if (process.platform === 'darwin' && app.dock) {
    return app.dock.bounce(type); // Returns bounce ID
  }
  return null;
});

To cancel an active bounce, the renderer calls electronApi.cancelBounceDock(id):

// Cancellation handler
ipcMain.handle('cancel-bounce-dock', (event, id) => {
  if (process.platform === 'darwin' && app.dock && id !== null) {
    app.dock.cancelBounce(id);
  }
});

Managing macOS Accessibility Permissions

Fluxer requires accessibility permissions for certain automation features on macOS. The application uses Electron's systemPreferences module to check and request these permissions without crashing on other platforms.

Checking Trusted Accessibility Client Status

The renderer checks permission status via electronApi.checkAccessibility(prompt). The preload bridge forwards this to the main process:

// In fluxer_desktop/src/preload/index.tsx
checkAccessibility: (prompt: boolean) => 
  ipcRenderer.invoke('check-accessibility', prompt)

The main process handler in fluxer_desktop/src/main/IpcHandlers.tsx implements platform-specific logic:

ipcMain.handle('check-accessibility', (event, prompt) => {
  if (process.platform === 'darwin') {
    // Check if Fluxer is a trusted accessibility client
    return systemPreferences.isTrustedAccessibilityClient(prompt);
  }
  // Always return true on Windows/Linux where this concept doesn't exist
  return true;
});

When prompt is true, macOS displays the system dialog requesting permission if access hasn't been granted.

Opening System Preferences Programmatically

If accessibility permissions are denied, Fluxer guides users to the correct system preferences pane. The renderer invokes electronApi.openAccessibilitySettings():

// Preload exposure
openAccessibilitySettings: () => 
  ipcRenderer.invoke('open-accessibility-settings')

The main process opens the Security & Privacy preferences directly:

ipcMain.handle('open-accessibility-settings', () => {
  if (process.platform === 'darwin') {
    shell.openExternal(
      'x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility'
    );
  }
});

This deep link opens the Accessibility tab within Security & Privacy, eliminating manual navigation for users.

Cross-Platform Safety and Fallbacks

Fluxer's architecture ensures macOS-specific code never executes on incompatible platforms. Every handler checks process.platform === 'darwin' before accessing app.dock or systemPreferences.

For dock badges:

  • macOS: Uses app.dock.setBadge() with string labels
  • Windows: Falls back to setWindowsBadgeOverlay() with overlay icons
  • Linux: Uses generic app.setBadgeCount()

For accessibility:

  • macOS: Checks systemPreferences.isTrustedAccessibilityClient()
  • Other platforms: Returns true immediately, treating the feature as always available

This pattern keeps the renderer code clean—UI components call the same API regardless of platform, while the main process handles platform differentiation.

Summary

  • Fluxer implements macOS dock badges and accessibility permissions through isolated IPC handlers in the main process (fluxer_desktop/src/main/IpcHandlers.tsx).
  • The preload bridge (fluxer_desktop/src/preload/index.tsx) securely exposes these capabilities to the renderer using ipcRenderer and ipcMain.
  • Dock badges use app.dock.setBadge() on macOS, with automatic fallbacks to Windows overlay icons and Linux generic counts.
  • Accessibility permissions rely on systemPreferences.isTrustedAccessibilityClient() to check trusted status and shell.openExternal() to direct users to system preferences.
  • Platform guards (process.platform === 'darwin') ensure macOS-specific APIs never execute on Windows or Linux, maintaining cross-platform stability.

Frequently Asked Questions

How does Fluxer update the macOS dock badge count?

Fluxer updates the dock badge by sending an IPC message from the renderer to the main process via electronApi.setBadgeCount(). The main process handler in fluxer_desktop/src/main/IpcHandlers.tsx checks if process.platform === 'darwin' and calls app.dock.setBadge() with the count or custom text. On other platforms, it falls back to Windows overlay icons or the generic app.setBadgeCount() API.

What Electron API does Fluxer use to check accessibility permissions?

Fluxer uses systemPreferences.isTrustedAccessibilityClient() from Electron's systemPreferences module to check accessibility permissions on macOS. This call is wrapped in an IPC handler in fluxer_desktop/src/main/IpcHandlers.tsx that returns true immediately on Windows and Linux where accessibility permissions don't apply. When called with the prompt parameter set to true, macOS automatically displays the permission dialog if access hasn't been granted.

Can Fluxer bounce the dock icon to notify users of urgent events?

Yes, Fluxer supports dock bouncing through electronApi.bounceDock(type) where type can be 'informational' (bounces once) or 'critical' (bounces until the app is activated). The main process calls app.dock.bounce(type) and returns a bounce ID that can be used with electronApi.cancelBounceDock(id) to programmatically stop the bounce before user interaction.

How does Fluxer handle these macOS features on Windows and Linux?

Fluxer uses platform guards (process.platform === 'darwin') in all IPC handlers to ensure macOS-specific code only executes on macOS. For dock badges, Windows uses overlay icons via setWindowsBadgeOverlay() while Linux uses app.setBadgeCount(). For accessibility, non-macOS platforms immediately return true since the permission concept doesn't exist, allowing the UI to function without platform-specific branching logic in the renderer.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →