§
    ¬	ÊjãW  ã                  ó0  — d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlmZ ddlmZ dZdZdZ ej        d	¦  «        Zd
ZdZdZdZdZd*d„ZdZd+d„Zd,d„Z G d„ de¦  «        Zd-d!„Z  G d"„ d#¦  «        Z! G d$„ d%¦  «        Z"d&„ Z#d.d)„Z$dS )/aÿ  Invisible-but-headed browser windows.

Playwright's ``headless=True`` flips Firefox onto a different code path -
no widget tree, software-only rendering, distinct timing - and anti-bot
systems can spot the divergence. Running the browser *headed* but hidden
gives us the real rendering pipeline while keeping the windows off screen.

One idea, two mechanisms: the browser is not hidden, the SCREEN it draws on
is one nobody looks at.

- **Windows**: a fresh Win32 desktop object (``CreateDesktop``) that is never
  switched to. The spawner creates the browser process with
  ``STARTUPINFO.lpDesktop`` naming it, so the whole tree - launcher, parent,
  GPU and content processes - is born there and never appears on the
  interactive desktop, in the taskbar or in alt-tab. The binary is stock: no
  window attribute is touched from inside it.

- **Linux**: a private ``Xvfb`` instance, with ``DISPLAY`` pointed at it
  (X11/Wayland have no per-window cloak that keeps the GPU rendering).

Both objects carry the same moves: ``start()`` creates the surface,
``launch_env()`` names the variables the BROWSER's environment must carry
for it - and, with the value ``None``, the ones it must NOT carry -,
``stop()`` releases the surface. The launcher merges ``launch_env()`` into
the one environment it composes for the child (``_session.build_env`` in the
wrapper), so the fact stays with the session: a second session in the same
process never inherits the first one's surface. Neither object touches
``os.environ``. Until 34.25.0 the Linux one wrote ``DISPLAY`` there in
``start()`` and restored it in ``stop()``, so a headed session opened while
an Xvfb session was still alive in the same process was born on the Xvfb
(B221); the ``None`` half of the contract is what moved the five Wayland
removals out of the process too.

The in-binary cloak (``DWMWA_CLOAK`` gated by ``zoom.stealth.cloak_windows``)
that hid the Windows window from 2026-06-11 to 2026-09-20 is gone, and its
pref is no longer emitted: the engine is stock on this surface again.
é    )ÚannotationsN)ÚSet)ÚOptional)ÚWAYLAND_DISPLAYÚXDG_RUNTIME_DIRÚXDG_SESSION_TYPEÚPULSE_SERVERÚWSL2_GUI_APPS_ENABLEDÚINVPW_DESKTOPz/proc/net/unixz@?/tmp/\.X11-unix/X(\d+)éc   i�  é
   s   MIT-MAGIC-COOKIE-1iÿÿ  ÚpathÚstrÚcookieÚbytesÚreturnÚNonec           	     óÖ  — dd„}t                                dd¦  «         |d¦  «        z    |d¦  «        z    |t          ¦  «        z    ||¦  «        z   }t          j        | t          j        t          j        z  t          j        z  t          t          dd	¦  «        z  d
¦  «        }	 t          j	        ||¦  «         t          j
        |¦  «         dS # t          j
        |¦  «         w xY w)aC  Write a one-entry Xauthority file, readable by its owner only.

    The format is libXau's: family, then address, display number, auth name
    and auth data, each a 16-bit big-endian length and its bytes. Written here
    instead of with the ``xauth`` tool, which would be one more package to
    install for nothing.
    Úbr   r   c                óN   — t          | ¦  «                             dd¦  «        | z   S )Né   Úbig)ÚlenÚto_bytes)r   s    úHC:\Projects\Muse2API\.venv\Lib\site-packages\invisible_core/_headless.pyÚfieldz _write_xauthority.<locals>.fielde   s!   € Ý�1‰vŒv�Š˜q %Ñ(Ô(¨1Ñ,Ð,ó    r   r   r   ÚO_BINARYr   i€  N)r   r   r   r   )Ú_FAMILY_WILDr   Ú_COOKIE_NAMEÚosÚopenÚO_WRONLYÚO_CREATÚO_EXCLÚgetattrÚwriteÚclose)r   r   r   ÚrecordÚfds        r   Ú_write_xauthorityr+   ]   sÛ   € ð-ð -ð -ð -õ ×#Ò# A uÑ-Ô-°°°c±
´
Ñ:¸U¸UÀ3¹Z¼ZÑGØ�•lÑ#Ô#ñ$Ø&+ e¨F¡m¤mñ4€Fõ 
Œ�•r”{¥R¤ZÑ/µ"´)Ñ;½gÅbÈ*ÐVWÑ>XÔ>XÑXÐZ_Ñ	`Ô	`€BðÝ
Œ��VÑÔÐå
Œ�‰Œˆˆˆø�Œ�‰Œˆˆøøøs   Â'C ÃC(g      >@c                ó¦   — 	 t          | dd¬¦  «        5 }|                     ¦   «         cd d d ¦  «         S # 1 swxY w Y   d S # t          $ r Y dS w xY w)NÚasciiÚreplace)ÚencodingÚerrorsÚ )r"   ÚreadÚOSError)r   Úfs     r   Ú
_read_procr5   ~   sª   € ðÝ�$ °Ð;Ñ;Ô;ð 	¸qØ—6’6‘8”8ð	ð 	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	øåð ð ð Øˆrˆrðøøøs,   ‚A ”5¨A µ9¹A ¼9½A Á
AÁAÚsetc                 óˆ  — t          ¦   «         } t          t          ¦  «                             ¦   «         dd…         D ]„}|                     dd¦  «        }t          |¦  «        dk    r t                               |d         ¦  «        nd}|r5|                      t          | 
                    d¦  «        ¦  «        ¦  «         Œ…| S )a±  Display numbers this network namespace already has an X server on.

    Any unix socket named for a display in /proc/net/unix, abstract or path,
    in any state, since an accepted connection also carries the name and
    still means a live server. The table lists live sockets only, so a stale
    socket file left in /tmp/.X11-unix does not count, and it covers servers
    whose /tmp is not this one (a container sharing the network namespace
    keeps its lockfile in its own /tmp). A path socket counts although this
    Xvfb opens none: a client of that server asking for :n tries the
    abstract name first, and would reach ours.

    TCP is not read: this Xvfb does not listen on it (see ``_spawn``), so a
    listener on 6000+n is no concern of this display.

    A filter, never the judge: whether a number is free is decided by the
    Xvfb started on it (see ``_spawn``). But it is what keeps sessions of
    this package apart, because an Xvfb started with ``-displayfd`` writes no
    lockfile, so the lockfile check cannot see them. Measured without it:
    with 100 sessions alive, 11 of 51 attempts landed on a taken number, and
    with 250 a start ran out of its ten attempts.
    é   Né   é   )r6   r5   Ú
_PROC_UNIXÚ
splitlinesÚsplitr   Ú	_X_SOCKETÚ	fullmatchÚaddÚintÚgroup)ÚbusyÚlineÚcolsÚms       r   Ú_x_displays_listeningrG   †   s¨   € õ, ‰5Œ5€DÝ�:Ñ&Ô&×1Ò1Ñ3Ô3°A°B°BÔ7ð &ð &ˆð �zŠz˜$ Ñ"Ô"ˆÝ,/°©I¬I¸ªN¨N�I×Ò  Q¤Ñ(Ô(Ð(ÀˆØð 	&Ø�HŠH•S˜Ÿš ™œ‘_”_Ñ%Ô%Ð%øØ€Kr   c                  ó   — e Zd ZdZdS )Ú_XvfbExitedz¸The Xvfb started on a number exited before it was listening: the
    number was taken, by something the filters could not see. Another number
    can succeed, so ``start()`` tries one.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r   r   rI   rI   §   s   € € € € € ð.ð .ð .ð .r   rI   r*   rA   ÚtimeoutÚfloatú
str | Nonec                ó–  — t          j        ¦   «         |z   }d}|                     d¦  «        st|t          j        ¦   «         z
  }|dk    st          j        | gg g |¦  «        d         st          ‚t          j        | d¦  «        }|sdS ||z  }|                     d¦  «        ¯t|                     dd¬¦  «                             ¦   «         S )	zÒThe line Xvfb writes on ``-displayfd`` once its sockets are open, or
    ``None`` at end of file: every copy of the write end is closed, which,
    with ours closed after the spawn, means the server has exited.r   ó   
r   é@   Nr-   r.   )r0   )	ÚtimeÚ	monotonicÚendswithÚselectÚTimeoutErrorr!   r2   ÚdecodeÚstrip)r*   rO   ÚdeadlineÚbufÚleftÚchunks         r   Ú_read_ready_liner`   ­   sÊ   € õ Œ~ÑÔ 'Ñ)€HØ
€CØ�lŠl˜5Ñ!Ô!ð Ø�$œ.Ñ*Ô*Ñ*ˆØ�1Š9ˆ9�FœM¨2¨$°°B¸Ñ=Ô=¸aÔ@ˆ9ÝÐÝ”˜˜B‘”ˆØð 	Ø�4Øˆu‰ˆð �lŠl˜5Ñ!Ô!ð ð �:Š:�g iˆ:Ñ0Ô0×6Ò6Ñ8Ô8Ð8r   c                  óp   — e Zd ZdZddd	„Zdd
„Zdd„Zdd„Zdd„Z e	¦   «         fdd„Z
dd„Zdd„Zdd„ZdS )Ú_LinuxVirtualDisplayzCStandalone Xvfb instance owned by this InvisiblePlaywright session.é€  é8  ÚwidthrA   Úheightr   r   c                óX   — |› d|› d�| _         d | _        d | _        d | _        d | _        d S )NÚxÚx24)Ú	_geometryÚ_procÚ_displayÚ	_auth_dirÚ
_auth_file)Úselfre   rf   s      r   Ú__init__z_LinuxVirtualDisplay.__init__Á   s:   € Ø!Ð/Ð/ FÐ/Ð/Ð/ˆŒØ15ˆŒ
Ø'+ˆŒØ(,ˆŒØ)-ˆŒˆˆr   c                óˆ  — t          d¦  «        st          d¦  «        ‚t          j        d¬¦  «        | _        t
          j                             | j        d¦  «        | _        t          | j        t          j        d¦  «        ¦  «         	 |                      ¦   «          d S # t          $ r |                      ¦   «          ‚ w xY w)NÚXvfbzSinvisible_playwright headless=True requires Xvfb. Install it: sudo apt install xvfbzinvpw-xauth-)ÚprefixÚ
Xauthorityé   )Ú_binary_on_pathÚRuntimeErrorÚtempfileÚmkdtemprm   r!   r   Újoinrn   r+   ÚsecretsÚtoken_bytesÚ_start_serverÚBaseExceptionÚ_remove_auth©ro   s    r   Ústartz_LinuxVirtualDisplay.startÈ   sÃ   € Ý˜vÑ&Ô&ð 	Ýð4ñô ð õ "Ô)°Ð@Ñ@Ô@ˆŒÝœ'Ÿ,š, t¤~°|ÑDÔDˆŒÝ˜$œ/­7Ô+>¸rÑ+BÔ+BÑCÔCÐCð	Ø×ÒÑ Ô Ð Ð Ð øÝð 	ð 	ð 	Ø×ÒÑÔÐØð	øøøs   ÂB! Â! Cc                óF  — d }t          ¦   «         }t          t          ¦  «        D ]c}|                      |¬¦  «        }|                     |¦  «         	 |                      |¦  «        | _         d S # t          $ r}|}Y d }~Œ\d }~ww xY wt          dt          › d|› �¦  «        ‚)N)ÚexcludezXvfb failed to start after z attempts: )	r6   ÚrangeÚ	_ATTEMPTSÚ_pick_displayr@   Ú_spawnrl   rI   rw   )ro   Úlast_errÚtriedÚ_ÚdisplayÚes         r   r}   z"_LinuxVirtualDisplay._start_serverÝ   sÆ   € ð )-ˆÝ™%œ%ˆÝ•yÑ!Ô!ð 	ð 	ˆAØ×(Ò(°Ð(Ñ7Ô7ˆGØ�IŠI�gÑÔÐðØ $§¢¨GÑ 4Ô 4�”Ø��øÝð ð ð Ø������øøøøðøøøåØJ­)ÐJÐJÀÐJÐJñLô Lð 	Ls   ÁA0Á0
BÁ:BÂBr‹   r   c                óª  — t          j        ¦   «         \  }}	 t          j        d|dt	          |¦  «        dd| j        dddddd	dd
d| j        gt          j        t          j        d|f¬¦  «        | _        n## t          $ r t          j
        |¦  «         ‚ w xY w	 t          j
        |¦  «         n# t          j
        |¦  «         w xY w	 t          |t          ¦  «        }n]# t          $ r2 |                      ¦   «          t          d|› dt          d›d�¦  «        d‚t          $ r |                      ¦   «          ‚ w xY w	 t          j
        |¦  «         n# t          j
        |¦  «         w xY w|€'|                      ¦   «          t!          d|› d�¦  «        ‚|                     ¦   «         s*|                      ¦   «          t          d|› d|›d�¦  «        ‚d|› �S )ah  Start Xvfb on ``display`` and return the display it is serving.

        Ready means the SERVER says so: with ``-displayfd`` it writes its
        display number on the pipe after its listening sockets are open and
        its SIGTERM handler is installed, and if it exits first the pipe
        reports end of file. Nothing a third party leaves in /tmp can stand
        in for that. Until this change ready meant "/tmp/.X{n}-lock exists",
        which an Xvfb creates BEFORE opening its sockets: one that then
        failed to open them was taken for a live server, and the loser of a
        race between two sessions read the winner's lockfile as its own -
        both ended on one Xvfb, one of them with a dead one. And a stop()
        right after that kind of ready reached the server before its SIGTERM
        handler, so it died without removing its lockfile.

        The number is passed explicitly: ``-displayfd`` alone makes the
        server scan from :0, which under WSLg takes :0 in front of the
        desktop's own display. Explicit number plus ``-displayfd`` is honoured
        since xorg-server 1.16 (2014). ``-displayfd`` also means the server
        writes no lockfile (``nolock``, in every version), which is why
        _pick_display reads the socket table.

        The one socket it opens is the abstract ``@/tmp/.X11-unix/X{n}``,
        which is what a client asking for ``:n`` reaches first: no socket
        file in /tmp, and no TCP. Until this change it also listened on TCP
        6000+n, on every interface, with access control off (``-ac``): any
        host that could reach the port could read and drive the browser's
        screen, and the browser never used it (measured: Firefox on the
        display holds one unix connection and no TCP one, with TCP on or
        off). It was also one more way to collide: a listener on [::]:6000+n
        made this Xvfb exit.

        Access control is on: ``-auth`` loads the session's cookie (see
        ``start``). Until 37.33.0 it was ``-ac``, so with TCP gone the abstract
        socket was still open, without credentials, to every local process.
        rr   z
-displayfdz-screenÚ0z
+extensionÚGLXÚRENDERz	-nolistenÚunixÚtcpz-authT)ÚstdoutÚstderrÚstart_new_sessionÚpass_fdszXvfb z& neither reported ready nor exited in ÚgÚsNz exited before it was listeningz
 reported z on -displayfdú:)r!   ÚpipeÚ
subprocessÚPopenr   rj   rn   ÚDEVNULLrk   r~   r(   r`   Ú_READY_TIMEOUTrY   Ú_reaprw   rI   Úisdigit)ro   r‹   Úread_endÚ	write_endrD   s        r   r‡   z_LinuxVirtualDisplay._spawnò   s)  € õH !œg™iœiÑˆ�)ð	 Ý#Ô)à˜GØ ¥# i¡.¤.Ø˜s D¤NØ  %Ø  (Ø Ø Ø˜Tœ_ð	õ "Ô)Ý!Ô)Ø"&Ø#˜ðñ ô ˆDŒJˆJøõ  ð 	ð 	ð 	ÝŒH�XÑÔÐØð	øøøð! õ, ŒH�YÑÔÐÐø�BŒH�YÑÔÐÐøøøð	Ý# H­nÑ=Ô=ˆDˆDøÝð 	2ð 	2ð 	2Ø�JŠJ‰LŒLˆLÝð'˜ð 'ð 'Ý!Ð&ð'ð 'ð 'ñ(ô (à-1ð2õ ð 	ð 	ð 	Ø�JŠJ‰LŒLˆLØð	øøøð õ ŒH�XÑÔÐÐø�BŒH�XÑÔÐÐøøøØˆ<Ø�JŠJ‰LŒLˆLÝÐN gÐNÐNÐNÑOÔOÐOØ�|Š|‰~Œ~ð 	RØ�JŠJ‰LŒLˆLÝÐP wÐPÐP¸$ÐPÐPÐPÑQÔQÐQØ�4ˆzˆzÐs=   ˜AA4 Á3B- Á4 BÂB- Â-CÃC ÃE ÃAD7Ä7E ÅE&c                ó¼   — | j         €dS | j                              ¦   «         €| j                              ¦   «          | j                              ¦   «          d| _         dS )z~Kill our Xvfb if it still runs, and wait for it: a child nobody
        waits for stays a zombie for the life of this process.N)rk   ÚpollÚkillÚwaitr€   s    r   rŸ   z_LinuxVirtualDisplay._reapC  sR   € ð Œ:ÐØˆFØŒ:�?Š?ÑÔÐ$ØŒJ�OŠOÑÔÐØŒ
�ŠÑÔÐØˆŒ
ˆ
ˆ
r   rƒ   úAbstractSet[str]c                óæ   ‡‡— t          ¦   «         Šˆˆfd„t          t          t          dz   ¦  «        D ¦   «         }|st	          dt          › dt          › �¦  «        ‚dt          j        |¦  «        › �S )Nc                óp   •— g | ]2}d |› �‰vr)|‰v¯t           j                             d|› d�¦  «        °0|‘Œ3S )r™   z/tmp/.Xz-lock)r!   r   Úexists)Ú.0ÚnrC   rƒ   s     €€r   ú
<listcomp>z6_LinuxVirtualDisplay._pick_display.<locals>.<listcomp>Y  s]   ø€ ð 
ð 
ð 
ØØ�1ˆwˆw˜gÐ%Ð%Ø˜��Ý”G—N’NÐ#5¨QÐ#5Ð#5Ð#5Ñ6Ô6ð ð à��r   r8   zno free X display number in :z-:r™   )rG   r„   Ú_FIRST_DISPLAYÚ_LAST_DISPLAYrw   r{   Úchoice)ro   rƒ   ÚfreerC   s    ` @r   r†   z"_LinuxVirtualDisplay._pick_displayM  s˜   øø€ õ %Ñ&Ô&ˆð
ð 
ð 
ð 
ð 
Ý�^­]¸QÑ->Ñ?Ô?ð
ñ 
ô 
ˆð ð 	SÝØQµÐQÐQÅ-ÐQÐQñSô Sð Sà)•7”> $Ñ'Ô'Ð)Ð)Ð)r   Údictc                óX   — | j         si S | j         | j        dddœ}t          D ]}d||<   Œ|S )a/  What the browser's environment must carry to draw on this Xvfb.

        ``DISPLAY`` names the display, ``XAUTHORITY`` the file holding the
        cookie the server asks for, the two GTK/Firefox switches keep the
        toolkit on X11, and the five Wayland variables are named with ``None``
        so the launcher REMOVES them: inherited from WSLg or GNOME they make
        Firefox prefer the compositor over the display we set, and the window
        leaks onto the real desktop. All of it is this session's, none of it
        is the process's.
        rŽ   Úx11)ÚDISPLAYÚ
XAUTHORITYÚMOZ_ENABLE_WAYLANDÚGDK_BACKENDN)rl   rn   Ú_WAYLAND_LEAK_VARS)ro   ÚenvÚks      r   Ú
launch_envz_LinuxVirtualDisplay.launch_envd  sP   € ð Œ}ð 	ØˆIà”}Øœ/Ø"%Ø ð	
ð 
ˆõ $ð 	ð 	ˆAØˆC�‰FˆFØˆ
r   c                óˆ  — | j         �˜| j                              ¦   «         €| j                              ¦   «          	 | j                              d¬¦  «         nI# t          j        $ r7 | j                              ¦   «          | j                              d¬¦  «         Y nw xY wd | _         d | _        |                      ¦   «          d S )Né   )rO   r   )	rk   r¤   Ú	terminater¦   r›   ÚTimeoutExpiredr¥   rl   r   r€   s    r   Ústopz_LinuxVirtualDisplay.stop{  sÁ   € ØŒ:Ð! d¤j§o¢oÑ&7Ô&7Ð&?ØŒJ× Ò Ñ"Ô"Ð"ð+Ø”
—’¨�Ñ*Ô*Ð*Ð*øÝÔ,ð +ð +ð +Ø”
—’Ñ!Ô!Ð!Ø”
—’¨�Ñ*Ô*Ð*Ð*Ð*ð+øøøð ˆŒ
ØˆŒØ×ÒÑÔÐÐÐs   »A ÁABÂBc                óî   — | j         �2	 t          j        | j         ¦  «         n# t          $ r Y nw xY wd| _         | j        �4	 t          j        | j        ¦  «         n# t          $ r Y nw xY wd| _        dS dS )zhDelete the cookie file and its private directory: the cookie is
        this server's, and dies with it.N)rn   r!   Úremover3   rm   Úrmdirr€   s    r   r   z!_LinuxVirtualDisplay._remove_auth‡  s¢   € ð Œ?Ð&ðÝ”	˜$œ/Ñ*Ô*Ð*Ð*øÝð ð ð Ø�ðøøøà"ˆDŒOØŒ>Ð%ðÝ”˜œÑ(Ô(Ð(Ð(øÝð ð ð Ø�ðøøøà!ˆDŒNˆNˆNð &Ð%s   ‰# £
0¯0ÁA Á
A)Á(A)N)rc   rd   )re   rA   rf   rA   r   r   ©r   r   )r‹   r   r   r   )rƒ   r§   r   r   ©r   r²   )rJ   rK   rL   rM   rp   r�   r}   r‡   rŸ   Ú	frozensetr†   r¼   rÁ   r   rN   r   r   rb   rb   ¾   sí   € € € € € ØMÐMð.ð .ð .ð .ð .ðð ð ð ð*Lð Lð Lð Lð*Oð Oð Oð Oðbð ð ð ð 9B¸	¹¼ð *ð *ð *ð *ð *ð.ð ð ð ð.
ð 
ð 
ð 
ð"ð "ð "ð "ð "ð "r   rb   c                  óJ   — e Zd ZdZdd„Zedd„¦   «         Zdd„Zdd	„Zdd
„Z	dS )Ú_WindowsVirtualDesktopuÍ  A Win32 desktop object nobody switches to, owned by this session.

    Windows has no per-window cloak that leaves a stock binary untouched, but
    it has something Linux lacks: a process is CREATED on a desktop, and every
    process it spawns is born on the same one. Naming a fresh desktop in
    ``STARTUPINFO.lpDesktop`` therefore hides the whole browser tree at once -
    launcher, parent, GPU process, content processes - with no cooperation
    from the binary. The desktop lives on the interactive window station, so
    the GPU is the real one; only ``SwitchDesktop`` would show it, and nothing
    here ever calls that.

    Two facts about that desktop are consequences, not choices, and the prefs
    that follow from them live in ``prefs._WIN_VIRT_DESKTOP_WORKAROUNDS``:
    the GPU process cannot parent its compositor window across desktops under
    the default GPU sandbox, and content processes above sandbox level 4 are
    put on the sandbox's own window station. Both were measured on this exact
    setup in 2026-05 (`22-patch-port-history.md` Â§P16, `71-bug-archive.md`
    #18 Bug A) and are what ``virtual_display=True`` switches on.

    â›” ``SetThreadDesktop`` on the launching thread is NOT enough, and that is
    the mistake this class replaces for the second time: with ``lpDesktop``
    NULL a child inherits the parent PROCESS desktop, not the thread's, so a
    thread-level switch hid nothing (measured 2026-06-11). The name has to
    reach ``CreateProcess`` itself, which is why ``launch_env()`` hands it to
    the environment the spawner reads - the SESSION's, never the process's:
    a headed session opened while a hidden one is still alive must not be
    born on the hidden one's desktop.
    r   r   c                ó"   — d | _         d | _        d S ©N)Ú_handleÚ_namer€   s    r   rp   z_WindowsVirtualDesktop.__init__¶  s   € Ø&*ˆŒØ$(ˆŒ
ˆ
ˆ
r   úOptional[str]c                ó   — | j         S rË   )rÍ   r€   s    r   Únamez_WindowsVirtualDesktop.nameº  s
   € àŒzÐr   c                ó¶  — dd l }ddl m} |                     dd¬¦  «        }|j        |j        _        |j        |j        |j        |j        |j        |j        f|j        _	        dt          j        d¦  «        z   }d}|                     |d d d|d ¦  «        }|s&|                     ¦   «         }t          d	|z  ¦  «        ‚t          |¦  «        | _        || _        d S )
Nr   ©ÚwintypesÚuser32T©Úuse_last_errorÚinvpw_é   i   a  invisible_playwright headless=True could not create a hidden desktop (CreateDesktopW failed, WinError %d). A session with no interactive window station - a service, a scheduled task with no logon - cannot host a headed browser; run from a logged-on session.)ÚctypesrÓ   ÚWinDLLÚHANDLEÚCreateDesktopWÚrestypeÚLPCWSTRÚc_void_pÚDWORDÚargtypesr{   Ú	token_hexÚget_last_errorrw   rA   rÌ   rÍ   )ro   rÙ   rÓ   rÔ   rÐ   Úgeneric_allÚhandleÚerrs           r   r�   z_WindowsVirtualDesktop.start¾  sõ   € ØˆˆˆØ#Ð#Ð#Ð#Ð#Ð#à—’˜x¸�Ñ=Ô=ˆØ(0¬ˆÔÔ%àÔ˜hÔ.°´ØŒN˜HœN¨F¬Oð*=ˆÔÔ&ð �'Ô+¨AÑ.Ô.Ñ.ˆØ ˆØ×&Ò& t¨T°4¸¸KÈÑNÔNˆØð 	,Ø×'Ò'Ñ)Ô)ˆCÝð%ð (+ñ	+ñ,ô ,ð ,õ ˜6‘{”{ˆŒØˆŒ
ˆ
ˆ
r   r²   c                ó0   — | j         rt          | j         ini S )z?The one variable the spawner needs: which desktop to create on.)rÍ   ÚDESKTOP_ENVr€   s    r   r¼   z!_WindowsVirtualDesktop.launch_envØ  s   € à,0¬JÐ>•˜TœZÐ(Ð(¸BÐ>r   c                ó  — | j         �qdd l}ddlm} |                     dd¬¦  «        }|j        f|j        _        |j        |j        _        |                     |                     | j         ¦  «        ¦  «         d | _         d | _	        d S )Nr   rÒ   rÔ   TrÕ   )
rÌ   rÙ   rÓ   rÚ   rÛ   ÚCloseDesktoprá   ÚBOOLrÝ   rÍ   )ro   rÙ   rÓ   rÔ   s       r   rÁ   z_WindowsVirtualDesktop.stopÜ  s�   € ØŒ<Ð#ØˆMˆMˆMØ'Ð'Ð'Ð'Ð'Ð'Ø—]’] 8¸D�]ÑAÔAˆFØ,4¬OÐ+=ˆFÔÔ(Ø*2¬-ˆFÔÔ'ð ×Ò §¢°´Ñ =Ô =Ñ>Ô>Ð>ØˆŒØˆŒ
ˆ
ˆ
r   NrÅ   )r   rÎ   rÆ   )
rJ   rK   rL   rM   rp   ÚpropertyrÐ   r�   r¼   rÁ   rN   r   r   rÉ   rÉ   ˜  sŽ   € € € € € ðð ð:)ð )ð )ð )ð ðð ð ñ „Xððð ð ð ð4?ð ?ð ?ð ?ðð ð ð ð ð r   rÉ   c                 óÒ   — t           j                             d¦  «        rt          ¦   «         S t           j        dk    rt	          ¦   «         S t          dt           j        ›d�¦  «        ‚)zÏReturn a start()/stop()-able hidden surface for this platform.

    - Linux: a fresh ``Xvfb`` (the launcher start()s/stop()s it).
    - Windows: a fresh Win32 desktop the spawner creates the browser on.
    ÚlinuxÚwin32z^invisible_playwright supports Windows and Linux (macOS is no longer a supported platform; got ú))ÚsysÚplatformÚ
startswithrb   rÉ   rw   rN   r   r   Úmake_virtual_displayrô   ê  sp   € õ „|×Ò˜wÑ'Ô'ð &Ý#Ñ%Ô%Ð%Ý
„|�wÒÐÝ%Ñ'Ô'Ð'Ý
ð	KÝ9<¼ð	Kð 	Kð 	Kñô ð r   rÐ   Úboolc                ó8   — dd l }|                     | ¦  «        d uS )Nr   )ÚshutilÚwhich)rÐ   r÷   s     r   rv   rv   ú  s"   € Ø€M€M€MØ�<Š<˜ÑÔ TÐ)Ð)r   )r   r   r   r   r   r   )r   r   r   r   )r   r6   )r*   rA   rO   rP   r   rQ   )rÐ   r   r   rõ   )%rM   Ú
__future__r   r!   Úrer{   rX   r›   rñ   rx   rU   Úcollections.abcr   ÚAbstractSetÚtypingr   r¹   rè   r;   Úcompiler>   r®   r¯   r…   r    r   r+   rž   r5   rG   rw   rI   r`   rb   rÉ   rô   rv   rN   r   r   ú<module>rÿ      së  ðð$ð $ðJ #Ð "Ð "Ð "Ð "Ð "à 	€	€	€	Ø 	€	€	€	Ø €€€Ø €€€Ø Ð Ð Ð Ø 
€
€
€
Ø €€€Ø €€€Ø .Ð .Ð .Ð .Ð .Ð .Ø Ð Ð Ð Ð Ð ðÐ ð €ð €
ØˆBŒJÐ2Ñ3Ô3€	ð €Ø€Ø€	ð %€ð €ðð ð ð ð< €ðð ð ð ðð ð ð ðB.ð .ð .ð .ð .�,ñ .ô .ð .ð9ð 9ð 9ð 9ð"W"ð W"ð W"ð W"ð W"ñ W"ô W"ð W"ðtOð Oð Oð Oð Oñ Oô Oð Oðdð ð ð *ð *ð *ð *ð *ð *r   