Zpět na domů

Ochrana oken před snímky obrazovky: Windows, macOS, Linux

Článek vysvětluje, jak aplikace chrání svá okna před zachycením obrazovky na Windows, macOS a Linuxu. Jsou rozebrány API SetWindowDisplayAffinity, sharingType a specifika display serverů. Zvláštní pozornost věnována regresi v macOS 15 Sequoia.

Skrytá okna: jak se aplikace chrání před snímky obrazovky
Advertisement 728x90

# Jak aplikace chrání okna před snímky obrazovky: Windows, macOS a Linux v detailech

Při pokusu o snímek obrazovky Netflixu nebo Spotify místo videa uvidíte černý obdélník – to není chyba, ale záměrná ochrana prostřednictvím systémových API. Vývojáři používají příznaky jako SetWindowDisplayAffinity na Windows nebo sharingType na macOS, aby vyloučili okno z proudů zachycení obrazovky. Ale v macOS 15 Sequoia Apple narušila kompatibilitu a na Linuxu to závisí na display serveru. Prozkoumáme, jak ochrana funguje na každé platformě, kde selhává a jaké jsou obchody.

Mechanismy zachycení obrazovky ve Windows: tři hlavní API

Když aplikace jako Zoom požádá o přístup k demonstraci obrazovky, přihlásí se k proudu snímků od operačního systému. Ve Windows existují tři hlavní způsoby, jak získat tento proud, každý se svými vlastnostmi:

  • GDI BitBlt od desktopového DC – nejstarší metoda, fungující od Windows 2000. Používá volání BitBlt z GetDC(NULL), které kopíruje pixely z povrchu DWM (Desktop Window Manager) do libovolného HDC. Pomalá, bez hardwarového zrychlení, ale univerzální. Používá se ve starších aplikacích a monitorovacích nástrojích.
  • Desktop Duplication API (DXGI) – objevila se ve Windows 8. Prostřednictvím IDXGIOutputDuplication::AcquireNextFrame vrací GPU texturu s již složeným snímkem pracovní plochy. Rychlá, hardwarově zrychlená, ale zachycuje pouze celý monitor. Používala se v klasických verzích Zoom, TeamViewer, AnyDesk a Teams.
  • Windows.Graphics.Capture (WGC) – moderní standard, představený ve Windows 10 1803. Podporuje zachycení celého monitoru i konkrétního okna podle HWND. Používá se v aktuálních verzích OBS, Microsoft Teams, Chromium, Zoom a systémovém Snipping Tool.

Všechny tři metody nakonec čtou data z DWM – jediného místa, kde se tvoří finální obraz obrazovky. Právě zde se aplikují mechanismy ochrany.

Google AdInline article slot

SetWindowDisplayAffinity: režimy a jejich chování

DWM umožňuje každému oknu nastavit atribut display affinity prostřednictvím funkce SetWindowDisplayAffinity. Tento atribut určuje, zda se okno dostane do proudů zachycení. K dispozici jsou tři hodnoty:

  • WDA_NONE (0x00) – okno je viditelné ve všech zachyceních (výchozí).
  • WDA_MONITOR (0x01) – okno se zobrazuje na monitoru, ale v zachycení je nahrazeno černým obdélníkem. Funguje od Windows Vista. Právě ho používá Netflix k ochraně obsahu.
  • WDA_EXCLUDEFROMCAPTURE (0x11) – okno je zcela vyloučeno z proudu zachycení, jako by neexistovalo. Objevil se ve Windows 10 May 2020 Update (build 19041). Přes něj je vidět obsah podkladových oken – elegantnější řešení.

Příklad v C++:

#include <windows.h>
#include <cstdio>

int main() {
    HWND hwnd = GetConsoleWindow();
    if (!SetWindowDisplayAffinity(hwnd, WDA_EXCLUDEFROMCAPTURE)) {
        printf("SetWindowDisplayAffinity failed: %lu\n", GetLastError());
        return 1;
    }
    printf("Okno nyní není viditelné pro zachycení. Zkus udělat snímek obrazovky.\n");
    Sleep(60000);
    return 0;
}

Podobně funguje v C# přes P/Invoke, v Electron přes setContentProtection(true), v Tauri přes with_content_protection(true).

Google AdInline article slot

Pod kapotou DWM odděluje kompoziciční potrubí: okno s WDA_EXCLUDEFROMCAPTURE se dostane pouze do potrubí pro fyzický monitor, ale ne do potrubí pro capture klienty. Obtížné to obejít na úrovni čtení pixelů.

Kompatibilita a omezení ve Windows

Test na Windows 11 23H2 ukázal, že WDA_EXCLUDEFROMCAPTURE správně funguje proti všem hlavním metodám zachycení:

  • GDI BitBlt – okno chybí.
  • Desktop Duplication (DXGI) – okno chybí (ve Windows 11 24H2 je zvláštnost s probuzením AcquireNextFrame při aktualizaci skrytého okna, ale obsah se nepřenáší).
  • Windows.Graphics.Capture (WGC) – okno chybí.

Jediné výjimky je PrintWindow. Tato metoda obchází DWM a žádá okno, aby se vykreslilo přímo do uvedeného DC, ignoruje příznak. Nicméně většina aplikací pro demonstraci obrazovky (Zoom, Teams, Discord, OBS) PrintWindow nepoužívá.

Google AdInline article slot

Důležité omezení: WDA_EXCLUDEFROMCAPTURE je podporováno pouze od Windows 10 20H1 (May 2020 Update). Na starších verzích, včetně LTSC, funkce vrátí chybu ERROR_INVALID_PARAMETER. V takových případech lze použít WDA_MONITOR, ale pak bude v zachycení černý obdélník.

Existuje také nedokumentovaný atribut WCA_EXCLUDED_FROM_DDA přes SetWindowCompositionAttribute, který vylučuje okno pouze z Desktop Duplication API. V praxi není potřebný, protože WDA_EXCLUDEFROMCAPTURE řeší úkol úplněji.

macOS do 15: sharingType jako spolehlivý mechanismus

Na macOS do verze 15 se používalo vlastnost sharingType u NSWindow:

window.sharingType = .none

Dostupné hodnoty:

  • .readWrite – okno je dostupné pro čtení a změnu z jiných procesů (málokdy používané).
  • .readOnly – okno je zachytitelné (výchozí).
  • .none – okno je vyloučeno z zachycení.

Tento příznak fungoval přes WindowServer, který řídí kompozici přes Core Graphics. Do macOS 14 Sonoma včetně sharingType = .none efektivně blokoval zachycení jak přes legacy-API (CGWindowListCreateImage), tak přes nový ScreenCaptureKit (zavedený v macOS 12.3).

Electron a Tauri tento mechanismus používaly pod kapotou svých metod setContentProtection(true).

macOS 15 Sequoia: regrese v ScreenCaptureKit

S vydáním macOS 15 Sequoia Apple změnila architekturu WindowServer: nyní kompozice sbírá všechna viditelná okna do jediného framebufferu a ScreenCaptureKit zachycuje právě ten. Výsledkem je, že sharingType = .none přestal ovlivňovat proud SCStream.

Oficiální zástupce Apple potvrdil na Developer Forums: „At this time there are no public APIs for preventing screen capture“.

Důležitý detail: legacy-API (CGWindowListCreateImage) stále respektuje sharingType = .none. To vytváří rozpor v chování různých aplikací:

  • Zoom (aktuální), Teams, QuickTime, systémové snímky (Cmd+Shift+3/4/5), nové verze OBS – používají ScreenCaptureKit → okno je viditelné.
  • Google Chrome (getDisplayMedia), Google Meet v Chrome, staré verze OBS – používají CoreGraphics → okno je skryté.

Jedná se o zásadní regresi pro produkty vyžadující ochranu před zachycením obrazovky. Bez soukromých API není řešení a jejich použití zaručuje odmítnutí v App Store review a riziko poruchy při aktualizacích OS. Alternativy – omezení podpory na macOS 14 a dříve, nebo behaviorální metody: automatické minimalizování okna při zahájení demonstrace, detekce aktivity SCStream přes systémové signály.

Linux: X11 vs Wayland – dva světy

Na Linuxu se situace zásadně liší v závislosti na display serveru.

X11 – architektonicky nepodporuje ochranu oken před zachycením. Jakýkoli klient s přístupem k displeji může volat XGetImage nebo XCompositeNameWindowPixmap a získat pixely jakéhokoli okna. Kompozitní rozšíření (Picom, KWin, Mutter) mohou přidávat částečnou ochranu, ale krosplatformové řešení pro WM neexistuje.

Wayland – postavený na principu izolace: klient nemůže číst cizí surface. Zachycení obrazovky je možné pouze přes xdg-desktop-portal + PipeWire a pouze s explicitním souhlasem uživatele. Ochrana oken se realizuje na úrovni protokolu – pokud okno nepřidělí přístup, nedostane se do zachycení. To činí Wayland výrazně bezpečnější než X11, ale vyžaduje od aplikací správnou implementaci protokolů.

Co je důležité

  • SetWindowDisplayAffinity s WDA_EXCLUDEFROMCAPTURE – de facto standard na Windows pro úplné vyloučení okna z zachycení. Funguje od Windows 10 May 2020 Update.
  • Na macOS 15 Sequoia sharingType = .none už nefunguje proti ScreenCaptureKit – to je architektonická změna Apple bez veřejného obchodu.
  • Na Linuxu na X11 ochrana oken není možná podle designu protokolu; na Wayland je zajištěna na úrovni protokolu.
  • PrintWindow na Windows obchází ochranu, ale nepoužívá se v populárních aplikacích pro demonstraci obrazovky.
  • Electron a Tauri tyto API používají pod kapotou – jejich chování závisí na platformě a verzi OS.

— Editorial Team

Advertisement 728x90

Číst dál