
    ncP                        d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	 ddl
mZmZmZ ddlmZ 	 eZddlZdd	lmZmZmZmZmZmZmZmZmZmZmZ dd
lm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-  ee$      Z. ee!      Z/ ej`                  dd      Z1e1jd                  Z2e*e2_3        e+ge2_4         ej`                  dd      Z5dZ6dZ7dZ8dZ9dZ:dZ; G d de      Z< G d dej8                        Z= G d dej8                        Z> G d dej8                        Z? G d dej                        ZA G d dej8                        ZB eee'e( ee<            ZCe5j                  ZEeeCe,e!geE_4        e#eE_3        e5j                  ZFeeF_3        e5j                  ZGe#geG_4        e"eG_3        e5j                  ZIe.e-eegeI_4        e"eI_3        e5j                  ZJe.geJ_4        e"eJ_3        e5j                  ZLe.geL_4        edz  ZMe5j                  ZNeMgeN_4        e"eN_3        e5j                  ZPee%egeP_4        eeP_3        e5j                  ZReegeR_4        eeR_3        e5j                  ZSeeeMe%eegeS_4        eeS_3        e5j                  ZTe eeB      egeT_4        eeT_3        dZUdZVdZWdZXdZYe5j                  Z[e&ge[_4        ee[_3        d Z\dZ]d!Z^d"Z_d#Z`e]ee^ee_ee`eiZai dd$d%d&d'd(d)d*d+d,d d-d.d/d0d1d2d3d4d5d6d7d6d8d6d9d:d;d<d=d>d?d>d@i dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbi dcdddedfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzd{d|d}d~ddddddi ddddddddddddddddddddddddddddddddddi ddddddddddddddddddddddddddddddēddƓddȓi ddʓdd̓ddΓddГddғddԓdd֓ddؓddړddܓddޓddddddddddddi dddddddddddddddddddddd ddddddddd	d
ddi dddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.i d/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTd*dUZb e       Zc e	ed      Ze e	ed      Zfi Zgg dVZh ej                  dK      Zj ej                  dK      Zk eM       ZldW ZmdX ZnenZog dYZpdZaqdZardZas etg d[      Zud\ Zvd] Zwd^ Zxd_ Zyd` Zzda Z{db Z|e}dck(  r0 en        ddl~Z~ e~j                  ee        e~j                  ef       yy# e$ r Y w xY w(d  a  
This is the Windows backend for keyboard events, and is implemented by
invoking the Win32 API through the ctypes module. This is error prone
and can introduce very unpythonic failure modes, such as segfaults and
low level memory leaks. But it is also dependency-free, very performant
well documented on Microsoft's website and scattered examples.

# TODO:
- Keypad numbers still print as numbers even when numlock is off.
- No way to specify if user wants a keypad key or not in `map_char`.
    )unicode_literalsN)Lock)defaultdict   )KeyboardEventKEY_DOWNKEY_UP)normalize_name)c_shortc_charc_uint8c_int32c_intc_uintc_uint32c_long	StructureWINFUNCTYPEPOINTER)WORDDWORDBOOLHHOOKMSGLPWSTRWCHARWPARAMLPARAMLONGHMODULELPCWSTR	HINSTANCEHWNDkernel32T)use_last_erroruser32         c                   .    e Zd ZdefdefdefdefdefgZy)KBDLLHOOKSTRUCTvk_code	scan_codeflagstimedwExtraInfoN)__name__
__module____qualname__r   r   	ULONG_PTR_fields_     +E:\Python Projects\keyboard\_winkeyboard.pyr+   r+   7   s0    E"e$% 	*	,Hr7   r+   c                   4    e Zd ZdefdefdefdefdefdeffZy)
MOUSEINPUTdxdy	mouseDatadwFlagsr/   r0   N)r1   r2   r3   r   r   r4   r5   r6   r7   r8   r:   r:   ?   s6    tte$E"	*,Hr7   r:   c                   .    e Zd ZdefdefdefdefdeffZy)
KEYBDINPUTwVkwScanr>   r/   r0   N)r1   r2   r3   r   r   r4   r5   r6   r7   r8   r@   r@   G   s.    $E"	*	,Hr7   r@   c                   "    e Zd ZdefdefdeffZy)HARDWAREINPUTuMsgwParamLwParamHN)r1   r2   r3   r   r   r5   r6   r7   r8   rD   rD   N   s     D!D!#Hr7   rD   c                   "    e Zd ZdefdefdeffZy)_INPUTunionmikihiN)r1   r2   r3   r:   r@   rD   r5   r6   r7   r8   rI   rI   S   s!    z"z"}%'Hr7   rI   c                       e Zd ZdefdeffZy)INPUTtypeunionN)r1   r2   r3   r   rI   r5   r6   r7   r8   rN   rN   X   s    +&(Hr7   rN            i  i  i  )zcontrol-break processingF   )	backspaceF	   )tabF   )clearF   )enterF)shiftF   )ctrlF   )altF   )pauseF   )	caps lockF   )zime kana modeF)zime hanguel modeF)zime hangul modeF   )zime junja modeF   )zime final modeF   )zime hanja modeF)zime kanji modeF   )escF   )zime convertF   )zime nonconvertF   )z
ime acceptF   )zime mode change requestF    )spacebarF!   )zpage upF"   )z	page downF#   )endF$   )homeF%   )leftF&   )upF'   )rightF(   )downF)   )selectF*   )printF+   )executeF,   )zprint screenF-   )insertF.   )deleteF/   )helpF0   )0F1   )1F2   )2F3   )3F4   )4F5   )5F6   )6F7   )7F8   )8F9   )9FA   )aFB   )bFC   )cFD   )dFE   )eFF   )fFG   )gFH   )hFI   )iFJ   )jFK   )kFL   )lFM   )mFN   )nFO   )oFP   )pFQ   )qFR   )rFS   )sFT   )tFU   )uFV   )vFW   )wFX   )xFY   )yFZ   )zF[   )zleft windowsF\   )zright windowsF]   )applicationsF_   )sleepF`   )r   Ta   )r   Tb   )r   Tc   )r   Td   )r   Te   )r   Tf   )r   Tg   )r   Th   )r   Ti   )r   Tj   )*Tk   )+Tl   )	separatorTm   )-Tn   )decimalTo   )/Tp   )f1Fq   )f2Fr   )f3Fs   )f4Ft   )f5Fu   )f6Fv   )f7Fw   )f8Fx   )f9Fy   )f10Fz   )f11F{   )f12F|   )f13F}   )f14F~   )f15F   )f16F   )f17F   )f18F   )f19F   )f20F   )f21F   )f22F   )f23F   )f24F   )num lockF   )scroll lockF   )z
left shiftF   )zright shiftF   )z	left ctrlF   )z
right ctrlF   )z	left menuF   )z
right menuF   )zbrowser backF   )zbrowser forwardF   )zbrowser refreshF   )zbrowser stopF   )zbrowser search keyF   )zbrowser favoritesF   )zbrowser start and homeF   )zvolume muteF   )zvolume downF   )z	volume upF   )z
next trackF   )zprevious trackF   )z
stop mediaF   )zplay/pause mediaF   )z
start mailF   )zselect mediaF   )zstart application 1F   )zstart application 2F   )r   F   ),F   )r   F   ).F   )zime processF   )attnF   )crselF   )exselF   )z	erase eofF)playF)zoomF)z	reserved F)pa1F)               )r6   r\   alt grr!  )r\   r!  rd   )r\   rd   )rT  r!  c           	   #     K   | ||ft         v }|t        v }|r|rt        |   d    dd|v z  t        d<   dd|v z  t        d<   dd|v z  t        d<   dd	|v z  t        d
<   dd|v z  t        d<   dd|v z  t        d<   t        || t        t        t        t              d      }|rGt        j                  r7t        j                   t        || t        t        t        t              d       t        | dz  |dz  z  t        d      }|r"t        j                  rt        j                   t        j                  |t              dz  }|dk7  rt        |       |s|rt        |   d    y y y w)Nr   r  r\   rS   rT  r]   r_   r   rd   rc   r!  r   r#  r"  rg   i      )keypad_keysofficial_virtual_keyskeyboard_state	ToUnicodeunicode_bufferlenvalueGetKeyNameTextname_bufferr&   MapVirtualKeyWMAPVK_VK_TO_CHARchr)	r-   vkis_extended	modifiers	is_keypadis_officialunicode_retname_retchars	            r8   get_event_namesrm  _  sr    B,;I--K[#B'**7i#78N48y#89N48y#89N4;)#;<N4:#:;N4=I#=>N4B	>>3~K^`abK~++"""
 	"i^ATVWXi2or0AA;PTUHK%%  %56=Dqy$i#B'** %9s   E*E,c                     t         5  t        r
	 ddd       yt        d      D  cg c]  } | t        j	                  | t
        d      f! }} t        d      D cg c]  }t        j	                  |t        d      |f! }}||z   D ]  \  }}||dddft        v r|t        vr	|t        |<   dD ]  }t        D ]  }||||f}t        t        |       }|s|D 	cg c]  }	|	j                          }
}	||
z   t        |<   t        t        t        ||
z               D ]  \  }}	t        |	   j!                  ||f       !    dD ]9  }t        D ].  }dgt        dd||f<   t        d   j!                  ddd||ff       0 ; 	 ddd       t#        d	       j%                  ddd
ddd       fd}t        t        j'                               D ]"  \  }	}t)        t+        |      |      t        |	<   $ yc c} w c c}w c c}	w # 1 sw Y   xY w)zX
    Ensures the scan code/virtual key code/name translation tables are
    filled.
    NrQ   r   )r   r   rT    r&  r   c                       y)N
   r6   r6   r7   r8   <lambda>z$_setup_name_tables.<locals>.<lambda>  s    rr7   r(   rR   r)   )r6   rR  rS  )r^   )r`   c                 0    | \  }}|\  }}}}|   ||||fS )Nr6   )liner   entryr-   re  extendedrg  modifiers_preferences          r8   	order_keyz%_setup_name_tables.<locals>.order_key  s0    5-2*	2x#I.8RJJr7   )key)tables_lockto_nameranger&   MapVirtualKeyExWMAPVK_VSC_TO_VK_EXMAPVK_VK_TO_VSC_EXscan_code_to_vkdistinct_modifierslistrm  lower	enumeratemapr
   	from_nameappendr   updateitemssortedset)scall_scan_codesre  all_vksr-   rv  rg  ru  namesnamelowercase_namesr   rx  entriesrw  s                 @r8   _setup_name_tablesr    s   
 
F'Q 'Q
 ^cch]ij]iWY2v66r;MqQR]ij]bch]ij]iWY62227I1MrR]ij+g5MIr2q!Q'72/-/	* #!3I&Hi@E %!89EDI*JED4::<E*J).)@ (1^U_E\1]'^GAt%dO22Au:> (_ "4 # 6: H/	<D:c8Y78(#**AS(I/N+OP 0 I 
R 'z2QAARS_` abK ioo/0g W9=	$ 1U kj" +K/ 
sA   G?G?$G0
G?$G5=AG?G?G:,BG?0G??H)$r     r   r  rk   rZ   r   r  r   r   r   r  r   r   r   r  r   r   r   r  )r   r   r   )r   ru   r   )r   r   r   )r   ry   r   )r   r   r   )r   rq   r   r   r   r   r  )r   r   r   )r   rw   r   )r   r   r   )r   rX   r   )r   r   r   )r   r{   r   r   r   r   r  )r   rs   r   )r   r   r   )r   r}   r   )r   r   r   )r   rr   r   )r   r   r   )r   r   r   )r   r   r   )r   r   r   )r   r   r   F)rS   r$  r%  c                      t                 fdfd}t        d      }t        |      }t        d      }t	        d      }t        ||||      }t        j                  t        |       y)af  
    Registers a Windows low level keyboard hook. The provided callback will
    be invoked for each high-level keyboard event, and is expected to return
    True if the key event should be passed to the next program, or False if
    the event is to be blocked.

    No event is processed until the Windows messages are pumped (see
    start_intercept).
    c                    |dk(  r	t         rda ydt        z  dt        z  z   dt        j	                  d      dz  z  z   d	t        j	                  d
      dz  z  z   dt        j	                  d      dz  z  z   }||||f}|t
        vrt        t        |       t
        |<   t
        |   }|r|d   nd }|t        v r	| t        k(  a|dk(  r|dk(  rda | t        k(  a|||ft        v } 	t        | |xs | ||            S )Nr)  FTrR  rS  rU  r   r   rV  rc   )r#  r"  r   ro  r&  )
event_typer-   r  rh  )ignore_next_right_altshift_is_pressedaltgr_is_pressedr&   GetKeyStater{  r  rm  	shift_vksr   rY  r   )
r  re  r-   rf  rg  ru  r  r  rh  callbacks
            r8   process_keyz&prepare_intercept.<locals>.process_key  s7   
 :/$)! ))**+V//59:; f006:;<  2 24 81 <=	> 	 BY7!/5"9:GEN uQxd ?)X5c	$(!)X5K0K?	yGWUWTW^bnwxyyr7   c                    	 |j                   j                  }t        dz  }|t        k7  rj|j                   j                  |z  |k7  rN|dz  rt
        nt        }|j                   j                  dz  }|j                   j                  } 
||||      }|syt        d | ||      S # t        $ r)}	t        d       t        j                          Y d }	~	;d }	~	ww xY w)Nro   r   zError in keyboard hook:)contentsr,   LLKHF_INJECTED	VK_PACKETr.   r	   r   r-   	Exceptionr   	traceback	print_excCallNextHookEx)nCodewParamlParamre  fake_altr  rf  r-   should_continuer   r  s             r8   low_level_keyboard_handlerz5prepare_intercept.<locals>.low_level_keyboard_handler  s    	"((B&-HY6??#8#88#Cx#O'-}V(
$oo33a7"OO55	"-j"i"U&
 dE66::	  	"+,!!	"s   BB# #	C,CCrZ   Nr   )	r  r   LowLevelKeyboardProcGetModuleHandleWr   SetWindowsHookExatexitregisterUnhookWindowsHookEx)r  r  WH_KEYBOARD_LLkeyboard_callbackhandle	thread_idkeyboard_hookr  s   `      @r8   prepare_interceptr    se     zB;& 2YN,-GHt$FaI$^5FPYZM OO'):;r7   c                     t        |        t               }t        |ddd      s&t        |       t	        |       t        |ddd      s%y y Nr   )r  LPMSG
GetMessageTranslateMessageDispatchMessage)r  msgs     r8   listenr  0  s?    h
'CaA& aA&r7   c              #      K   t                t        j                  |       }|s#t        dj	                  t        |                   |D ]  \  }}|\  }}}}|xs | |f  y w)Nz+Key name {} is not mapped to any known key.)r  r  get
ValueErrorformatrepr)r  r  r   ru  r-   re  rf  rg  s           r8   map_namer  7  sg     mmD!GFMMdSWjYZZ505-	2{IB3	)) s   A"A$c                 
   | dk(  r1t         j                  d| |d       t         j                  d| |d       y | dkD  r/t        j                  | d      }t         j                  || |d       y t         j                  |  d|d       y )Nro  r]   r   r_   )r&   keybd_eventr  r  )coder  re  s      r8   _send_eventr  A  sv    s{4z154z15	  q)2tZ3 	D5!Z3r7   c                     t        | d       y r  r  r  s    r8   pressr  N      ar7   c                     t        | d       y )Nr(   r  r  s    r8   releaser  Q  r  r7   c           	      <   t        | j                  d            }g }g }t        dt        |      d      D ]  }|||dz    \  }}t	        d|dz  |z   t
        dd       }|j                  t        t        t        |                   t	        d|dz  |z   t
        t        z  dd       }|j                  t        t        t        |                    ||z   }t        |      }	t        |	z  }
 |
| }t        t        j                  t                    }t        |	||       y )Nzutf-16ler   r(   rT   )rK   )	bytearrayencoder|  r^  r@   KEYEVENTF_UNICODEr  rN   INPUT_KEYBOARDrI   KEYEVENTF_KEYUPr   ctypessizeof	SendInput)	character
surrogatespressesreleasesr   higherr  	structureinputsnInputsLPINPUTpInputscbSizes                r8   type_unicoder  T  s    9++J78JGH1c*oq)"1QqS)q5A:"79JAtT	u^[I-FGHq5A:"79J_9\^_aef	nkY.GHI * xF&kGgoGvG6=='(Fgw'r7   __main__)__doc__
__future__r   rer  r  	threadingr   collectionsr   _keyboard_eventr   r   r	   _canonical_namesr
   unichrrd  	NameErrorr  r   r   r   r   r   r   r   r   r   r   r   ctypes.wintypesr   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r  r4   WinDLLr$   r  restypeargtypesr&   r  INPUT_MOUSEr  INPUT_HARDWAREr  r  r+   r:   r@   rD   UnionrI   rN   r  SetWindowsHookExWr  r  r  GetMessageWr  r  DispatchMessageAr  keyboard_state_typeGetKeyboardStateGetKeyNameTextWr`  rb  MapVirtualKeyr\  r  rc  MAPVK_VK_TO_VSCMAPVK_VSC_TO_VKr  r~  
VkKeyScanW	VkKeyScanr  
WM_KEYDOWNWM_KEYUPWM_SYSKEYDOWNWM_SYSKEYUPkeyboard_event_typesrZ  rz  r  r{  r  r  r  create_unicode_bufferra  r]  r[  rm  r  initrY  r  r  r  r  r  r  r  r  r  r  r  r  r1   pprintr6   r7   r8   <module>r     sI  
 ( 	    # < < ,	
C  v v v v B  B  B  BEN	6==D9,, "  $I   
x$	7	 ,i ,,!! ,,!! ,#F$$ #
'&,, '
(F ( #5&&'/:RS ++ "$8)eL     && 00  %w  "  
dFF3
 
 ** "G    ))!7  m ** 01    ''!651  %% &)  	f&965&Q	 	 	gene4	 	     	W	 	 
 f8	 `
-`
` 	.` 	
	`
 	
` 	
` 	/` 	.` 	
` 	
` 	
"` 	
%` 	
$` 	
#` 	
#`  	
#!`" 	
##`$ 	.%`& 	
 '`( 	
#)`* 	
+`, 	
,-`. 	
/`0 	
1`2 	
3`4 	.5`6 	/7`8 	/9`: 	-;`< 	
=`> 	/?`@ 	
A`B 	
C`D 	
E`F 	
!G`H 	
I`J 	
K`L 	/M`N 	,O`P 	,Q`R 	,S`T 	,U`V 	,W`X 	,Y`Z 	,[`\ 	,]`^ 	,_`` 	,a`b 	,c`d 	,e`f 	,g`h 	,i`j 	,k`l 	,m`n 	,o`p 	,q`r 	,s`t 	,u`v 	,w`x 	,y`z 	,{`| 	,}`~ 	,`@ 	,A`B 	,C`D 	,E`F 	,G`H 	,I`J 	,K`L 	,M`N 	,O`P 	,Q`R 	,S`T 	,U`V 	
!W`X 	
"Y`Z 	
![`\ 	
]`^ 	+_`` 	+a`b 	+c`d 	+e`f 	+g`h 	+i`j 	+k`l 	+m`n 	+o`p 	+q`r 	+s`t 	+u`v 	
w`x 	+y`z 	
{`| 	+}`~ 	-`@ 	-A`B 	-C`D 	-E`F 	-G`H 	-I`J 	-K`L 	-M`N 	-O`P 	.Q`R 	.S`T 	.U`V 	.W`X 	.Y`Z 	.[`\ 	.]`^ 	._`` 	.a`b 	.c`d 	.e`f 	.g`h 	.i`j 	.k`l 	.m`n 	
o`p 	
 q`r 	
s`t 	
 u`v 	
w`x 	
y`z 	
{`| 	
}`~ 	
!`@ 	
$A`B 	
$C`D 	
!E`F 	
'G`H 	
&I`J 	
+K`L 	
 M`N 	
 O`P 	
Q`R 	
S`T 	
#U`V 	
W`X 	
%Y`Z 	
[`\ 	
!]`^ 	
(_`` 	
(a`b 	,c`d 	,e`f 	,g`h 	,i`l 	
 m`n 	/o`p 	
q`r 	
s`t 	
u`v 



` D f
d
		  +f**2.---b1$&+@5>p &P    "#	H<T*4(& zFMM'FMM)	 ]  		s   V> >WW