Volver al inicio

Protección de ventana contra capturas de pantalla: Windows, macOS, Linux

El artículo explica cómo las apps protegen sus ventanas de la captura de pantalla en Windows, macOS y Linux. Analiza la API SetWindowDisplayAffinity, sharingType y funciones del servidor de visualización. Atención especial a las regresiones en macOS 15 Sequoia.

Ventanas ocultas: cómo las apps se protegen de las capturas de pantalla
Advertisement 728x90

# Cómo las aplicaciones protegen las ventanas contra capturas de pantalla: Windows, macOS y Linux en detalle

Cuando intentas hacer una captura de pantalla de Netflix o Spotify, en lugar del vídeo verás un rectángulo negro: no es un error, sino una protección deliberada mediante APIs del sistema. Los desarrolladores usan flags como SetWindowDisplayAffinity en Windows o sharingType en macOS para excluir la ventana de los flujos de captura de pantalla. Pero en macOS 15 Sequoia, Apple rompió la compatibilidad, y en Linux todo depende del servidor de visualización. Vamos a desglosar cómo funciona la protección en cada plataforma, dónde falla y qué soluciones alternativas existen.

Mecanismos de captura de pantalla en Windows: tres APIs principales

Cuando una app como Zoom solicita acceso para compartir pantalla, se suscribe a un flujo de fotogramas del sistema operativo. Windows tiene tres formas principales de obtener este flujo, cada una con sus peculiaridades:

  • GDI BitBlt desde DC del escritorio—el método más antiguo, que funciona desde Windows 2000. Usa la llamada BitBlt desde GetDC(NULL) para copiar píxeles de la superficie DWM (Desktop Window Manager) a cualquier HDC. Lento, sin aceleración por hardware, pero universal. Se usa en apps antiguas y herramientas de monitoreo.
  • Desktop Duplication API (DXGI)—introducida en Windows 8. Mediante IDXGIOutputDuplication::AcquireNextFrame, devuelve una textura GPU con el fotograma completo del escritorio compuesto. Rápida, con aceleración por hardware, pero solo captura el monitor entero. Se usa en versiones clásicas de Zoom, TeamViewer, AnyDesk y Teams.
  • Windows.Graphics.Capture (WGC)—el estándar moderno, introducido en Windows 10 1803. Permite capturar el monitor entero o una ventana específica por HWND. Se usa en versiones actuales de OBS, Microsoft Teams, Chromium, Zoom y la herramienta de recortes integrada.

Los tres métodos leen datos en última instancia de DWM: el único lugar donde se compone la imagen final de pantalla. Ahí es donde entran en juego los mecanismos de protección.

Google AdInline article slot

SetWindowDisplayAffinity: modos y su comportamiento

DWM permite que cada ventana establezca un atributo display affinity mediante la función SetWindowDisplayAffinity. Este atributo determina si la ventana aparece en los flujos de captura. Hay tres valores disponibles:

  • WDA_NONE (0x00)—la ventana es visible en todas las capturas (predeterminado).
  • WDA_MONITOR (0x01)—la ventana se muestra en el monitor, pero se reemplaza por un rectángulo negro en las capturas. Funciona desde Windows Vista. Netflix lo usa para proteger el contenido.
  • WDA_EXCLUDEFROMCAPTURE (0x11)—la ventana se excluye completamente del flujo de captura, como si no existiera. Introducido en Windows 10 May 2020 Update (build 19041). El contenido de las ventanas subyacentes se muestra a través: solución más limpia.

Ejemplo en 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 teper nevidimo for zakhvata. Poprobuy sdelat skrinshot.\n");
    Sleep(60000);
    return 0;
}

Funciona de manera similar en C# mediante P/Invoke, en Electron mediante setContentProtection(true) y en Tauri mediante with_content_protection(true).

Google AdInline article slot

Por debajo, DWM separa los flujos de composición: una ventana con WDA_EXCLUDEFROMCAPTURE solo va al flujo para el monitor físico, no para los clientes de captura. No se puede eludir esto a nivel de lectura de píxeles.

Compatibilidad y limitaciones en Windows

Pruebas en Windows 11 23H2 mostraron que WDA_EXCLUDEFROMCAPTURE funciona correctamente contra todos los métodos de captura principales:

  • GDI BitBlt—la ventana no está presente.
  • Desktop Duplication (DXGI)—la ventana no está presente (en Windows 11 24H2, hay una peculiaridad por la que AcquireNextFrame se activa con actualizaciones de ventanas ocultas, pero no pasa contenido).
  • Windows.Graphics.Capture (WGC)—la ventana no está presente.

La única excepción es PrintWindow. Este método elude DWM y pide a la ventana que renderice directamente en el DC especificado, ignorando el flag. Sin embargo, la mayoría de las apps de compartición de pantalla (Zoom, Teams, Discord, OBS) no usan PrintWindow.

Google AdInline article slot

Limitación clave: WDA_EXCLUDEFROMCAPTURE solo se soporta a partir de Windows 10 20H1 (May 2020 Update). En versiones anteriores, incluidas LTSC, la función devuelve ERROR_INVALID_PARAMETER. En esos casos, recurre a WDA_MONITOR, que muestra un rectángulo negro en las capturas.

También hay un atributo no documentado WCA_EXCLUDED_FROM_DDA mediante SetWindowCompositionAttribute, que excluye la ventana solo de Desktop Duplication API. En la práctica, es innecesario porque WDA_EXCLUDEFROMCAPTURE lo cubre de forma más completa.

macOS hasta 14: sharingType como mecanismo fiable

En macOS hasta la versión 14, se usaba la propiedad sharingType de NSWindow:

window.sharingType = .none

Valores disponibles:

  • .readWrite—la ventana es legible y modificable por otros procesos (rara vez usado).
  • .readOnly—la ventana es capturable (predeterminado).
  • .none—la ventana se excluye de la captura.

Este flag funcionaba a través de WindowServer, que maneja la composición mediante Core Graphics. Hasta e incluyendo macOS 14 Sonoma, sharingType = .none bloqueaba efectivamente la captura tanto por APIs antiguas (CGWindowListCreateImage) como por el nuevo ScreenCaptureKit (introducido en macOS 12.3).

Electron y Tauri usaban este mecanismo por debajo para sus métodos setContentProtection(true).

macOS 15 Sequoia: regresión en ScreenCaptureKit

Con macOS 15 Sequoia, Apple cambió la arquitectura de WindowServer: ahora la composición ensambla todas las ventanas visibles en un único framebuffer, y ScreenCaptureKit lo captura directamente. Como resultado, sharingType = .none ya no afecta a SCStream.

Un representante oficial de Apple lo confirmó en los foros de desarrolladores: “At this time there are no public APIs for preventing screen capture”.

Matiz clave: las APIs antiguas (CGWindowListCreateImage) aún respetan sharingType = .none. Esto crea una división en el comportamiento entre apps:

  • Zoom (actual), Teams, QuickTime, capturas de sistema (Cmd+Shift+3/4/5), versiones nuevas de OBS—usan ScreenCaptureKit → la ventana es visible.
  • Google Chrome (getDisplayMedia), Google Meet en Chrome, versiones antiguas de OBS—usan CoreGraphics → la ventana está oculta.

Esta es una regresión fundamental para productos que necesitan protección contra captura de pantalla. Sin APIs privadas, no hay solución: usarlas garantiza rechazo en la revisión de App Store y roturas en actualizaciones del SO. Alternativas incluyen limitar el soporte a macOS 14 y anteriores, o métodos conductuales: minimizar automáticamente la ventana al inicio de la compartición de pantalla, detectar actividad de SCStream mediante señales del sistema.

Linux: X11 vs Wayland—dos mundos diferentes

En Linux, la situación varía drásticamente según el servidor de visualización.

X11—arquitectónicamente no soporta protección de ventanas contra captura. Cualquier cliente con acceso al display puede llamar a XGetImage o XCompositeNameWindowPixmap para capturar píxeles de cualquier ventana. Las extensiones de composición (Picom, KWin, Mutter) pueden añadir protección parcial, pero no hay solución multiplataforma.

Wayland—basado en principios de aislamiento: los clientes no pueden leer las superficies de otros. La captura de pantalla solo es posible mediante xdg-desktop-portal + PipeWire, y solo con consentimiento explícito del usuario. La protección de ventanas se maneja a nivel de protocolo: si una ventana no concede acceso, no aparece en las capturas. Esto hace que Wayland sea mucho más seguro que X11, pero requiere que las apps implementen los protocolos correctamente.

Puntos clave

  • SetWindowDisplayAffinity con WDA_EXCLUDEFROMCAPTURE—estándar de facto en Windows para excluir completamente una ventana de la captura. Funciona desde Windows 10 May 2020 Update.
  • En macOS 15 Sequoia, sharingType = .none ya no funciona contra ScreenCaptureKit: es un cambio arquitectónico de Apple sin solución pública.
  • En Linux, X11 hace imposible la protección de ventanas por diseño del protocolo; Wayland lo maneja a nivel de protocolo.
  • PrintWindow en Windows elude la protección, pero no se usa en apps populares de compartición de pantalla.
  • Electron y Tauri aprovechan estas APIs por debajo: su comportamiento depende de la plataforma y versión del SO.

— Editorial Team

Advertisement 728x90

Leer después