[PR #1877] Exclude software-dimming overlay windows from screen capture #1321

Open
opened 2026-10-02 22:09:46 -06:00 by gitea-mirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/MonitorControl/MonitorControl/pull/1877
Author: @compoundworks
Created: 6/27/2026
Status: 🔄 Open

Base: main ← Head: fix/exclude-dimming-overlay-from-screen-capture


📝 Commits (2)

  • ed07a0c fix: exclude software-dimming overlay windows from screen capture
  • 4d62fa9 Only exclude shade from capture on non-virtual displays

📊 Changes

1 file changed (+9 additions, -0 deletions)

View changed files

📝 MonitorControl/Support/DisplayManager.swift (+9 -0)

📄 Description

Problem

When a display is dimmed using software dimming (the black "shade" overlay), screenshots and screen recordings of that display come out darkened — the capture includes the dimming overlay. This is most visible on displays that have no DDC and no gamma support, such as DisplayLink / virtual displays, where the shade overlay is the only dimming mechanism available.

Reported in:

  • #1453 (Screenshots come up blank/dark when brightness dimmed)
  • #866 (Screenshot from external screen is dimmer with "Avoid gamma table manipulation")
  • #1446

Root cause

DisplayManager.createShadeOnDisplay(...) creates a full‑screen black NSWindow to act as the dimming shade, but never sets its sharingType. The default is .readOnly, so the shade window is visible to the screen‑capture system (CGWindowList / ScreenCaptureKit). Any screenshot or recording taken while a display is dimmed therefore captures the shade and looks dark. The same applies to the 1×1 gammaActivityEnforcer helper window.

Fix

Set sharingType = .none on the shade windows and the gamma activity enforcer. These windows are display‑only chrome; excluding them from capture does not change what the user sees on screen — the display stays visibly dimmed, but captures are taken from the content underneath.

shade.sharingType = .none
self.gammaActivityEnforcer.sharingType = .none

Enumerated MonitorControl's on‑screen windows via CGWindowListCopyWindowInfo and read kCGWindowSharingState:

Window Before (main) After (this PR)
Window Shade for Display (full‑screen) 1 (ReadOnly → captured) 0 (None → excluded)
Gamma Activity Enforcer 1 (captured) 0 (excluded)

With the fix, the dimmed display still looks dimmed to the eye, but screencapture of that display no longer includes the shade — screenshots come out at normal brightness. An isolated test window with sharingType = .none confirmed it is excluded from capture (content behind shows through) rather than rendered black.

No behavior change for users who don't use software dimming.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/MonitorControl/MonitorControl/pull/1877 **Author:** [@compoundworks](https://github.com/compoundworks) **Created:** 6/27/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/exclude-dimming-overlay-from-screen-capture` --- ### 📝 Commits (2) - [`ed07a0c`](https://github.com/MonitorControl/MonitorControl/commit/ed07a0ca532d6d68064b8fa6a92996d2ada731ed) fix: exclude software-dimming overlay windows from screen capture - [`4d62fa9`](https://github.com/MonitorControl/MonitorControl/commit/4d62fa90e0a7289fafa44ac5726f007b50af503c) Only exclude shade from capture on non-virtual displays ### 📊 Changes **1 file changed** (+9 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `MonitorControl/Support/DisplayManager.swift` (+9 -0) </details> ### 📄 Description ## Problem When a display is dimmed using software dimming (the black "shade" overlay), screenshots and screen recordings of that display come out darkened — the capture includes the dimming overlay. This is most visible on displays that have **no DDC and no gamma support**, such as **DisplayLink / virtual displays**, where the shade overlay is the only dimming mechanism available. Reported in: - #1453 (Screenshots come up blank/dark when brightness dimmed) - #866 (Screenshot from external screen is dimmer with "Avoid gamma table manipulation") - #1446 ## Root cause `DisplayManager.createShadeOnDisplay(...)` creates a full‑screen black `NSWindow` to act as the dimming shade, but never sets its `sharingType`. The default is `.readOnly`, so the shade window is visible to the screen‑capture system (`CGWindowList` / ScreenCaptureKit). Any screenshot or recording taken while a display is dimmed therefore captures the shade and looks dark. The same applies to the 1×1 `gammaActivityEnforcer` helper window. ## Fix Set `sharingType = .none` on the shade windows and the gamma activity enforcer. These windows are display‑only chrome; excluding them from capture does not change what the user sees on screen — the display stays visibly dimmed, but captures are taken from the content underneath. ```swift shade.sharingType = .none self.gammaActivityEnforcer.sharingType = .none ``` ## Verification (macOS 15, DisplayLink displays) Enumerated MonitorControl's on‑screen windows via `CGWindowListCopyWindowInfo` and read `kCGWindowSharingState`: | Window | Before (main) | After (this PR) | |---|---|---| | Window Shade for Display (full‑screen) | `1` (ReadOnly → captured) | `0` (None → excluded) | | Gamma Activity Enforcer | `1` (captured) | `0` (excluded) | With the fix, the dimmed display still looks dimmed to the eye, but `screencapture` of that display no longer includes the shade — screenshots come out at normal brightness. An isolated test window with `sharingType = .none` confirmed it is excluded from capture (content behind shows through) rather than rendered black. No behavior change for users who don't use software dimming. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
github-starred/MonitorControl#1321
No description provided.