§
    ¬	Êj§9  ã                  óà   — d Z ddlmZ ddlZddlmZ ddlmZ dZddd	d
dœZ	dd	ddœZ
dgdgdgdgddgdœZdddœdddœdddœdœZ G d„ de¦  «        Zd#d „Z e¦   «         Z G d!„ d"¦  «        ZdS )$u2  The keyboard: from a key name to the four fields Juggler demands.

â›” THIS FILE EXISTS BECAUSE `Page.dispatchKeyEvent` DOES NOT FORGIVE A WRONG
FIELD SILENTLY - IT FORGIVES IT TOO MUCH. It wants `key`, `code`, `keyCode`
and `location` together, and if `code` is empty and `keyCode` is zero the
event still fires: the character shows up in the field, the action succeeds,
the tests pass, and the page reads `event.code === ""` on a key that on every
real Firefox has a physical name. It is a tell that lives in the fields
nobody looks at because the action worked.

The first draft of `_type` in `actions.py` sent exactly that:
`code: ""`, `keyCode: 0`, for every character.

**THREE DETAILS READ IN THE DRIVER'S CODE, not deduced** (`coreBundle.js`,
`RawKeyboardImpl3`), and each one changes the bytes that go out:

1. The `keyCode` field carries **`keyCodeWithoutLocation`**, not `keyCode`.
   They differ exactly on the keys that exist twice: `ShiftLeft` has
   `keyCode` 160 and `keyCodeWithoutLocation` 16, and 16 is what a real
   Firefox puts in the event.
2. For Enter, `text` must be set to an **empty string**, not to `"\r"`:
   Gecko generates the character. Sending it explicitly inserts it twice.
3. `keyup` NEVER carries `text`. With `text` Juggler raises
   `keyup does not support text option` and typing dies halfway through.

**And the layout is not here**: it lives in `keylayout.py`, GENERATED from
the bundle by `scripts/gen_key_layout.py`. Here there is only how a name is
resolved, which is the algorithm of `buildLayoutClosure` read in the driver
and rewritten.
é    )ÚannotationsN)ÚOptionalé   )ÚLAYOUT)ÚAltÚControlÚMetaÚShifté   é   é   )r   r   r
   r	   )r   r   r   r
   r   r   r	   ú
ú)Ú	ShiftLeftÚControlLeftÚAltLeftÚMetaLeftÚEnterÚ
VolumeMuteéµ   )ÚcodeÚkeyCodeWithoutLocationÚ
VolumeDowné¶   ÚVolumeUpé·   )ÚAudioVolumeMuteÚAudioVolumeDownÚAudioVolumeUpc                  ó   — e Zd ZdZdS )Ú
UnknownKeyu�   The name is not in the layout. â›” It is REJECTED instead of inventing
    an empty event: a `keyCode: 0` does not fail, it lies.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© ó    úOC:\Projects\Muse2API\.venv\Lib\site-packages\invisible_core/juggler/keyboard.pyr!   r!   C   s   € € € € € ð>ð >ð >ð >r'   r!   ÚreturnÚdictc            	     óš  — i } t          j        ¦   «         D �]³\  }}|                     d¦  «        pd}||                     d¦  «        pd|                     d¦  «        p|                     d¦  «        pd||                     d¦  «        pd|                     d¦  «        pddœ}t          |¦  «        d	k    r||d<   d
}|                     d¦  «        rEt	          |¦  «        }|d         |d<   |d         |d<   |                     d¦  «        r|d         |d<   t	          ||¬¦  «        | |<   t
                               |g ¦  «        D ]}|| |<   Œ|                     d¦  «        r�ŒQt          |d         ¦  «        d	k    r|                      |d         |¦  «         |r+|                      |d         t	          |d
¬¦  «        ¦  «         �Œµ| S )u}  The name -> description dict, in the same shape as the driver.

    A key is reachable by `code` (`KeyA`), by `key` if it is a single
    character (`a`), by its shifted form (`A`), and by aliases (`Shift`).
    â›” A key with `location` does NOT get entered by `key`: `NumpadEnter`
    must not respond to the name `Enter`, or `press("Enter")` would end up
    on the numpad.
    ÚkeyÚ ÚkeyCoder   r   ÚtextÚlocation)r,   r.   r   r   r/   r0   r   NÚshiftKeyÚshiftKeyCode)Úshifted)r   ÚitemsÚgetÚlenr*   ÚALIASESÚ
setdefault)Úoutr   Údr,   Údescrr3   Úaliass          r(   Ú_build_closurer=   H   sã  € ð €CÝ”<‘>”>ð Hñ H‰ˆˆaØ�eŠe�E‰lŒlÐ ˜bˆàØ—u’u˜YÑ'Ô'Ð,¨1Ø&'§e¢eÐ,DÑ&EÔ&Eð '?Ø)*¯ª¨yÑ)9Ô)9ð'?Ø=>ØØ—E’E˜&‘M”MÐ' RØŸš˜jÑ)Ô)Ð.¨Qð
ð 
ˆõ ˆs‰8Œ8�qŠ=ˆ=ØˆE�&‰MØˆØ�5Š5�ÑÔð 	7Ý˜5‘k”kˆGØ˜zœ]ˆG�E‰NØ 
œmˆG�F‰OØ�uŠu�^Ñ$Ô$ð 7Ø%& ~Ô%6�˜	Ñ"Ý˜¨Ð0Ñ0Ô0ˆˆD‰	Ý—[’[  rÑ*Ô*ð 	ð 	ˆEØˆC�‰JˆJØ�5Š5�ÑÔð 	ÙÝˆu�UŒ|ÑÔ Ò!Ð!Ø�NŠN˜5 œ<¨Ñ/Ô/Ð/Øð 	HØ�NŠN˜7 5œ>­4°ÀÐ+FÑ+FÔ+FÑGÔGÐGùØ€Jr'   c                  óp   — e Zd ZdZddd„Zdd	„Zdd„Zd d„Zd d„Zddœd!d„Z	ddœd"d„Z
d#d„Zd$d„Zd%d„ZdS )&ÚKeyboarda  The state of modifiers and pressed keys, plus the four verbs.

    STATE is the reason this is a class and not three functions:
    `press("Shift+a")` must send `A` and not `a`, and to know that it must
    remember that Shift is down between Shift's keydown and `a`'s.
    NÚsessionÚstrc               óŠ   — || _         || _        t          ¦   «         | _        t          ¦   «         | _        || _        || _        d S ©N)Úcr@   ÚsetÚ	modifiersÚpressedÚpersonaÚacts)ÚselfÚ
connectionr@   rH   rI   s        r(   Ú__init__zKeyboard.__init__}   s<   € ØˆŒØˆŒÝ!™eœeˆŒÝ™EœEˆŒð ˆŒð ˆŒ	ˆ	ˆ	r'   r,   r)   r*   c                óÄ  — |dk    rdn|}t                                |¦  «        }|€t          d|z  ¦  «        ‚d| j        v r|                     d¦  «        r|d         }t	          |¦  «        }t          | j        ¦  «        dk    s!t          | j        ¦  «        dk    rd| j        vrd|d<   |                     t                               |d	         i ¦  «        ¦  «         |S )
NÚControlOrMetar   z�unknown key: %r. Valid names are the layout's `code` values (KeyA, Digit1, Enter), a single character, or an alias (Shift, Control, Alt, Meta).r
   r3   r   r-   r/   r,   )ÚLAYOUT_CLOSUREr5   r!   rF   r*   r6   ÚupdateÚFIREFOX_OVERRIDES)rJ   r,   Únamer:   s       r(   ÚdescribezKeyboard.describeœ   sí   € Ø ?Ò2Ð2ˆyˆy¸ˆÝ×Ò˜tÑ$Ô$ˆØˆ9Ýð5à7:ñ;ñ<ô <ð <ð �d”nÐ$Ð$¨¯ª¨yÑ)9Ô)9Ð$Ø�)”ˆAÝ�‰GŒGˆõ
 ˆtŒ~ÑÔ Ò"Ð"Ý�T”^Ñ$Ô$¨Ò)Ð)¨g¸T¼^Ð.KÐ.KØˆAˆf‰IØ	�ŠÕ"×&Ò& q¨¤x°Ñ4Ô4Ñ5Ô5Ð5Øˆr'   Úintc                óZ   — d}| j         D ] }|t                               |d¦  «        z  }Œ!|S )Nr   )rF   ÚMODIFIER_MASKr5   )rJ   ÚmrR   s      r(   Úmodifier_maskzKeyboard.modifier_mask±   s9   € ØˆØ”Nð 	,ð 	,ˆDØ•×"Ò" 4¨Ñ+Ô+Ñ+ˆAˆAØˆr'   ÚNonec                ó’  — |                       |¦  «        }|d         | j        v }| j                             |d         ¦  «         |d         t          v r | j                             |d         ¦  «         |d         }|dk    rd}| j                             dd|d         |d         |d         |d	         ||d
œ| j        d¬¦  «         d S )Nr   r,   r/   r   r-   úPage.dispatchKeyEventÚkeydownr   r0   )Útyper,   r   r.   r0   Úrepeatr/   é
   ©r@   Útimeout)rS   rG   ÚaddÚ	MODIFIERSrF   rD   Úsendr@   )rJ   r,   r:   r^   r/   s        r(   ÚdownzKeyboard.down¸   sà   € Ø�MŠM˜#ÑÔˆØ�6”˜dœlÐ*ˆØŒ×Ò˜˜6œÑ#Ô#Ð#ØˆUŒ8•yÐ Ð ØŒN×Ò˜q œxÑ(Ô(Ð(Ø�Œyˆð �4Š<ˆ<ØˆDØŒ�ŠÐ+Ø'°°%´À!ÀFÄ)Ø!"Ð#;Ô!<Ø"# J¤-¸6Ø"ð$ð $ð "œ\°2ð 	ñ 	7ô 	7ð 	7ð 	7ð 	7r'   c           
     óR  — |                       |¦  «        }|d         t          v r | j                             |d         ¦  «         | j                             |d         ¦  «         | j                             dd|d         |d         |d         |d         ddœ| j        d	¬
¦  «         d S )Nr,   r   r[   Úkeyupr   r0   F)r]   r,   r   r.   r0   r^   r_   r`   )rS   rc   rF   ÚdiscardrG   rD   rd   r@   )rJ   r,   r:   s      r(   ÚupzKeyboard.upÊ   s¸   € Ø�MŠM˜#ÑÔˆØˆUŒ8•yÐ Ð ØŒN×"Ò" 1 U¤8Ñ,Ô,Ð,ØŒ×Ò˜Q˜vœYÑ'Ô'Ð'ð 	Œ�ŠÐ+Ø%¨a°¬hÀÀ&Ä	Ø!"Ð#;Ô!<Ø"# J¤-¸5ðBð Bð "œ\°2ð	 	ñ 	7ô 	7ð 	7ð 	7ð 	7r'   ©Údwell_msrk   úOptional[float]c               ó  — |                      d¦  «        }|d         |dd…         }}|dk    r|rd|dd…         }}|€|                      ¦   «         }|D ]}|                      |¦  «         Œ	 |                      |¦  «         |dk    rt          j        |dz  ¦  «         |                      |¦  «         t          |¦  «        D ]}|                      |¦  «         ŒdS # t          |¦  «        D ]}|                      |¦  «         Œw xY w)u¶  `press("a")`, `press("Enter")`, `press("Control+Shift+KeyA")`.

        The modifiers are held down for the whole final key and released
        in reverse order, the way a hand would.

        â›” `dwell_ms` IS HOW LONG THE KEY STAYS DOWN, and the unit is in the
        name on purpose: see the note on `type`. Zero was the only value this
        could produce before, which put `keyup` one protocol round trip after
        `keydown` - about 2.4 ms, where a finger takes 60-120.

        It applies to the FINAL key only. A modifier is held across the whole
        press by construction, so giving it a dwell of its own would be a
        second statement about the same duration.
        ú+éÿÿÿÿNr-   ç        ç     @�@)ÚsplitÚ	_dwell_msre   ÚtimeÚsleepri   Úreversed)rJ   r,   rk   ÚpiecesÚfinalÚheldrW   s          r(   ÚpresszKeyboard.press×   s!  € ð —’˜3‘”ˆØ˜R”j &¨¨"¨¤+ˆtˆð
 �BŠ;ˆ;˜4ˆ;Ø˜t C R Cœy�4ˆEð ÐØ—~’~Ñ'Ô'ˆHØð 	ð 	ˆAØ�IŠI�a‰LŒLˆLˆLð	Ø�IŠI�eÑÔÐØ˜#Š~ˆ~Ý”
˜8 fÑ,Ñ-Ô-Ð-Ø�GŠG�E‰NŒNˆNå˜d‘^”^ð ð �Ø—’˜‘
”
�
�
ðð ø•X˜d‘^”^ð ð �Ø—’˜‘
”
�
�
ðøøøs   Á-AC Ã)Drp   )Údelay_msr/   r{   Úfloatc               óP  — |D ]}|t           vrt          d|z  ¦  «        ‚Œ|                      |¦  «        }t          |¦  «        D ]`\  }}||         \  }}|                      ||¬¦  «         |r|n|}|dk    r-|t          |¦  «        dz
  k     rt          j        |dz  ¦  «         ŒadS )uR  One key per character, with the rhythm of a hand.

        â›” This is NOT `insert_text`: a character the layout does not know
        (an ideogram, an emoji) has no key, so here it is REJECTED and
        deferred to `insert_text`. Typing something with no key would mean
        sending `code: ""`, which is exactly the defect this file exists
        to not have.

        â›” THE UNIT IS IN THE NAME, AND IT IS A FIX. The parameter used to be
        called `delay` and was handed straight to `time.sleep`, which takes
        SECONDS, while the public API documents it in MILLISECONDS. On the one
        path that actually forwarded it - the ElementHandle one - `type("abc",
        delay=100)` therefore slept for five minutes instead of 0.3 seconds.
        The six paths that dropped the value were accidentally protected from
        the bug the seventh had.

        â›” AND THE CALLER'S VALUE IS AN OVERRIDE, NOT THE DEFENCE. Without a
        persona this class used to emit keys as fast as the pipe allows, so the
        only thing standing between a caller and an inhuman rhythm was a
        parameter they had to know to pass - and every install that passed
        `delay=100` would have shared one flat rhythm, which is a key that
        links them. The persona is per-session and is what runs when nobody
        asks for anything.
        zu%r has no key on the US layout: use `insert_text`, which goes through `Page.insertText` and does not fake a keypress.rj   rp   r   rq   N)rO   r!   Ú_planÚ	enumeraterz   r6   rt   ru   )	rJ   r/   r{   ÚchÚplanÚirk   Úgap_msÚwait_mss	            r(   r]   zKeyboard.type   sÝ   € ð2 ð 	-ð 	-ˆBØ�Ð'Ð'Ý ð'à)+ñ,ñ-ô -ð -ð (ð �zŠz˜$ÑÔˆÝ˜t‘_”_ð 	-ð 	-‰EˆAˆrØ# AœwÑˆH�fØ�JŠJ�r HˆJÑ-Ô-Ð-Ø"*Ð6�h�h°ˆGØ˜Š}ˆ} ¥S¨¡Y¤Y°¡]Ò!2Ð!2Ý”
˜7 VÑ+Ñ,Ô,Ð,øð	-ð 	-r'   c                óV   — | j         €dS |                      d¦  «        d         d         S )zœHow long ONE key stays down, for a press that is not part of typed
        text. Zero without a persona, which is what turning humanising off
        means.Nrp   Úxr   )rH   r~   )rJ   s    r(   rs   zKeyboard._dwell_ms(  s+   € ð Œ<ÐØ�3Ø�zŠz˜#‰Œ˜qÔ! !Ô$Ð$r'   c                ó˜   — | j         €dgt          |¦  «        z  S ddlm}  ||| j         | j                             d¦  «        ¬¦  «        S )uR  One `(dwell_ms, gap_ms)` per character, from the session's persona.

        â›” Falls back to no rhythm rather than to a made-up one. A default
        constant here would be the shared invariant the persona exists to
        remove, and it would be invisible: every install would type alike and
        nothing would report it.
        N)rp   rp   r   )Úplan_typingÚtyping)Únonce)rH   r6   Ú
_behaviourrˆ   rI   Únext)rJ   r/   rˆ   s      r(   r~   zKeyboard._plan0  sX   € ð Œ<ÐØ�<¥# d¡)¤)Ñ+Ð+Ø+Ð+Ð+Ð+Ð+Ð+Øˆ{˜4 ¤°T´Y·^²^ÀHÑ5MÔ5MÐNÑNÔNÐNr'   c                óP   — | j                              dd|i| j        d¬¦  «         dS )znThe text goes in without key events. This is what is needed for
        a character that is not on the layout.zPage.insertTextr/   r_   r`   N)rD   rd   r@   )rJ   r/   s     r(   Úinsert_textzKeyboard.insert_text=  s;   € ð 	Œ�ŠÐ%¨° ~Ø!œ\°2ð 	ñ 	7ô 	7ð 	7ð 	7ð 	7r'   rC   )r@   rA   )r,   rA   r)   r*   )r)   rT   )r,   rA   r)   rY   )r,   rA   rk   rl   r)   rY   )r/   rA   r{   r|   r)   rY   )r)   r|   )r/   rA   )r/   rA   r)   rY   )r"   r#   r$   r%   rL   rS   rX   re   ri   rz   r]   rs   r~   rŽ   r&   r'   r(   r?   r?   u   s  € € € € € ðð ðð ð ð ð ð>ð ð ð ð*ð ð ð ð7ð 7ð 7ð 7ð$7ð 7ð 7ð 7ð >Bð 'ð 'ð 'ð 'ð 'ð 'ðR 47ð &-ð &-ð &-ð &-ð &-ð &-ðP%ð %ð %ð %ðOð Oð Oð Oð7ð 7ð 7ð 7ð 7ð 7r'   r?   )r)   r*   )r%   Ú
__future__r   rt   r‰   r   Ú	keylayoutr   rc   rV   ÚBUTTON_MASKr7   rQ   Ú
ValueErrorr!   r=   rO   r?   r&   r'   r(   ú<module>r“      s]  ððð ð< #Ð "Ð "Ð "Ð "Ð "à €€€Ø Ð Ð Ð Ð Ð à Ð Ð Ð Ð Ð ð 0€	ð
  a°!¸QÐ?Ð?€ð ˜˜aÐ Ð €ð !˜	°9°+Ø�g¨F¨8¸tÀT¸lðLð L€ð !-ÈÐLÐLØ ,ÈÐLÐLØ(ÀCÐHÐHðð Ð ð>ð >ð >ð >ð >�ñ >ô >ð >ð
'ð 'ð 'ð 'ðT  �Ñ!Ô!€ðL7ð L7ð L7ð L7ð L7ñ L7ô L7ð L7ð L7ð L7r'   