
    WCjG                    n   S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSKrSSK	J
r
  SSKJrJr  SSKrSSKr\
 " S S5      5       r\R"                  " \R$                  5      S:X  a  \R&                  O\R(                  r " S	 S
\R,                  5      r " S S\R,                  5      r " S S\R,                  5      r " S S\R4                  5      r " S S\R,                  5      rSrSrSr0 S\R@                  _S\RB                  _S\RD                  _S\RD                  _S\RF                  _S\RF                  _S\RH                  _S\RH                  _S\RJ                  _S\RJ                  _S \RL                  _S!\RL                  _S"\RN                  _S#\RP                  _S$\RR                  _S%\RT                  _S&\RV                  _\RX                  \RZ                  \R\                  \R^                  \R^                  \R`                  \Rb                  \Rd                  \Rd                  \Rf                  \Rh                  \Rj                  \Rl                  \Rn                  \Rp                  S'.Er9\:" SS(5       H  r;\<" \S)\; 3S*\;-   S-
  5      \9S+\; 3'   M     \R^                  \Rb                  \R`                  \Rd                  S,.r=\R|                  \R~                  4\R                  \R                  4\R                  \R                  4S-.rDS.S/S0S.S/S0S.S/S0S1.	rES6S7S2 jjrFS8S3 jrG " S4 S55      rHg)9u  
yjm_remote_control.py

viewer.html에서 들어오는 원격 제어 이벤트를 실제 Windows 입력으로 실행한다.

v2.7 추가:
- 마우스 down/up 기반 드래그 지원
- Ctrl/Shift/Alt + 마우스 클릭/드래그 지원
- Ctrl+A, Ctrl+C, Ctrl+V, Ctrl+X 같은 조합키 안정화
- 중간 버튼, 휠 + modifier 지원
- viewer에서 OSK(Windows 화상 키보드, osk.exe) 실행 요청 지원

보안 원칙:
- 기본값은 차단.
- Python UI의 "원격 제어 허용" 체크가 켜져야만 실행.
- viewer.html에서도 "제어: ON"을 눌러야 이벤트를 보냄.
- 좌표는 현재 캡처 대상 rect 기준으로 변환한다.
    )annotationsN)	dataclass)CallableOptionalc                  8    \ rS rSr% S\S'   S\S'   SrS\S'   S	rg)
ControlResult$   boolokstrmessageNOptional[dict]data )__name__
__module____qualname____firstlineno____annotations__r   __static_attributes__r       ./mnt/data/yjm_in2rtc_mod/yjm_remote_control.pyr   r   $   s    HLD.r   r      c                      \ rS rSrS\R
                  4S\R
                  4S\R                  4S\R                  4S\4/rSr	g)	
KEYBDINPUT/   wVkwScandwFlagstimedwExtraInfor   N)
r   r   r   r   ctypesc_ushortc_ulong	ULONG_PTR_fields_r   r   r   r   r   r   /   sA    	 	&//"	FNN#	 		"Hr   r   c                      \ rS rSrS\R
                  4S\R
                  4S\R                  4S\R                  4S\R                  4S\4/rSr	g	)

MOUSEINPUT9   dxdy	mouseDatar   r    r!   r   N)
r   r   r   r   r"   c_longr$   r%   r&   r   r   r   r   r(   r(   9   sM    	v}}	v}}	fnn%	FNN#	 		"Hr   r(   c                  f    \ rS rSrS\R
                  4S\R                  4S\R                  4/rSrg)HARDWAREINPUTD   uMsgwParamLwParamHr   N)	r   r   r   r   r"   r$   r#   r&   r   r   r   r   r/   r/   D   s,    (9foo*FTZTcTcHdeHr   r/   c                  *    \ rS rSrS\4S\4S\4/rSrg)
INPUTUNIONH   kimihir   N)	r   r   r   r   r   r(   r/   r&   r   r   r   r   r5   r5   H   s    z"T:$6}8MNHr   r5   c                  8    \ rS rSrS\R
                  4S\4/rSrg)INPUTL   typeunionr   N)	r   r   r   r   r"   r$   r5   r&   r   r   r   r   r;   r;   L   s    (7J*?@Hr   r;            	BackspaceTabEnterReturnEscapeEscSpace DeleteDelInsertInsHomeEndPageUpPageDown	ArrowLeft)
ArrowRightArrowUp	ArrowDownControlCtrlShiftAltMetaWinContextMenuPrintScreenPauseCapsLockNumLock
ScrollLock   VK_Fp   Fctrlaltshiftmeta)leftmiddlerightrk   rl   rm   )	r   r?   r@   012rk   rl   rm   c                L    U c  g[        U 5      n[        U5      U:  a  US U nU$ )N )r   len)smax_lentexts      r   
_safe_textrw      s/    yq6D
4y7HW~Kr   c           	         [        U [        5      (       d  SSSSS.$ S Vs0 s H  o[        U R                  U5      5      _M     sn$ s  snf )NFrf   )
isinstancedictr
   get)modsnames     r   
_norm_modsr~      sH    dD!!eeUKK3ST3S4$txx~&&3STTTs   $Ac                  T   \ rS rSr  S     SS jjrSS jrSS jrSS.S S jjrS!S	 jrS"S
 jr	\
S#S j5       r\
S$S j5       r\
S%S j5       rS&S jrS'S jrS(S)S jjrS*S+S jjrS,S-S jjrS.S/S jjr\
S0S j5       rS1S jrS2S jrS.S3S jjr\
S4S5S jj5       rSS jrS'S jrSrg)6RemoteInputController   Nc                    Xl         X l        U=(       d    [        R                  " [        5      U l        U=(       d    S U l        SU l        SU l        SU l	        SU l
        SU l        SU l        / U l        g )Nc                    g Nr   )_texts    r   <lambda>0RemoteInputController.__init__.<locals>.<lambda>   s    r           ~jth?Frk   )source_manageris_enabled_callbacklogging	getLoggerr   loggerstatus_callbacklast_action_atlast_move_status_atlast_coord_ack_atmin_interval_sec_mouse_is_down_mouse_button_mouse_mod_vks)selfr   r   r   r   s        r   __init__RemoteInputController.__init__   sm     -#6 ; 1 1( ;.F3E!#& !$ %##)+r   c                V     [        U R                  5       5      $ ! [         a     gf = f)NF)r
   r   	Exception)r   s    r   
is_enabled RemoteInputController.is_enabled   s-    	00233 		s    
((c                H     U R                  U5        g ! [         a     g f = fr   )r   r   )r   rv   s     r   _statusRemoteInputController._status   s'    	  & 		s    
!!Fforcec                  [         R                  " 5       nU(       d  US;   a  X`R                  -
  S:  a  g X`l        SU[        U5      [        U5      [	        UR                  SS5      5      [	        UR                  SS5      5      [        [	        UR                  SS5      =(       d    S5      5      [        [	        UR                  SS5      =(       d    S5      5      S	.$ )
Nmove	drag_moveg{Gz?control_ackxr   yframe_wframe_h)r=   actionscreen_xscreen_ycanvas_xcanvas_yr   r   )r    perf_counterr   intfloatr{   )r   r   msgr   r   r   nows          r   
_coord_ack RemoteInputController._coord_ack   s    !#88SCYCY=Y\`=`!$!HHcggc1o.cggc1o.5A!6!;!<=5A!6!;!<=	
 		
r   c                X    [         R                  " U5      n[	        U[
        5      (       a  UR                  S5      S:w  a  [        SS5      $ U R                  5       (       d  [        SS5      $ [        R                  " 5       n[        UR                  SS5      5      nUS	;   a.  X0R                  -
  U R                  :  a  [        SS
5      $ X0l         US	;   a  U R                  U5      u  pVU R                  XV5        X0R                  -
  S:  a*  X0l        U R!                  U R"                  (       a  SOS5        [        SU SU SU 3U R%                  XBXV5      5      $ US:X  a  U R                  U5      u  pVU R'                  UR                  SS5      5      n[)        UR                  S5      5      nU R!                  U R+                  USU S35      5        U R-                  XVXx5        [        SSU SU SU 3U R%                  XBXVSS95      $ US:X  a  U R                  U5      u  pVU R'                  UR                  SU R.                  5      5      nU R!                  SU S35        U R1                  XVU5        [        SSU SU SU 3U R%                  XBXVSS95      $ US;   a  U R                  U5      u  pV[)        UR                  S5      5      nUS:X  a  SnSn	S n
O5U R'                  UR                  SS5      5      nUS!:X  a  S"OSn	U	S":X  a  S#OS$n
U R!                  U R+                  USU
 35      5        U R3                  XVXyUS%9  [        SU SU SU SU 3U R%                  XBXVSS95      $ US&:X  a  U R                  U5      u  pV[)        UR                  S5      5      n[5        [7        UR                  S'S5      5      5      nU R!                  U R+                  US(5      5        U R9                  XVXS)9  [        SS*U S+U SU 3U R%                  XBXVSS95      $ US,:X  ag  [;        UR                  S-5      S.S/9nU(       d  [        SS05      $ U R!                  S15        U R=                  U5        [        SS2[?        U5       S335      $ US4:X  aw  [;        UR                  S45      S5S/9n[)        UR                  S5      5      nU R!                  U R+                  US6U 35      5        U RA                  X5        [        SS7U 35      $ US8:X  a]  [;        UR                  S45      S5S/9nU RC                  U5      nUb!  U RE                  US5        [        SS9U 35      $ [        SS:U 35      $ US;:X  a]  [;        UR                  S45      S5S/9nU RC                  U5      nUb!  U RE                  US5        [        SS<U 35      $ [        SS=U 35      $ US>;   a-  U RG                  5         U R!                  S?5        [        SS@5      $ USA:X  a#  U RI                  5         SU l        [        SSB5      $ [        SSCU 35      $ ! [         a    [        SS5      s $ f = f! [         aK  nU RI                  5         U RJ                  RM                  SDU5        [        S[        U5      5      s S nA$ S nAff = f)ENFzinvalid jsonr=   controlignoredzremote control disabledr   rr   r   zrate limitedg      ?u!   원격: 마우스 드래그중...u   원격: 마우스 이동중...TrI   ,
mouse_downbuttonr   r|      원격: u    버튼 누름zmouse_down r   mouse_upu    버튼 놓음z	mouse_up )clickdblclick
rightclickr   rm   r?   u	   우클릭r   r@   u   더블클릭u   클릭)countr|   wheeldeltau   원격: 휠 스크롤)r|   zwheel z at 	type_textrv   i  )ru   z
empty textu   원격: 타이핑중...ztype z charskey(   u   원격: 키 입력 zkey key_downz	key_down zunknown key_down key_upzkey_up zunknown key_up )
launch_oskosku'   원격: 화상 키보드 실행
osk.exezosk launchedrelease_allreleasedzunknown action: zremote control error: %s)'jsonloadsr   r   ry   rz   r{   r   r    r   r   r   r   _map_canvas_to_screen_mover   r   r   r   _button_namer~   
_mod_label_mouse_downr   	_mouse_up_clickr   r   _wheelrw   _type_unicoders   
_press_key
_key_to_vk_keybd_launch_osk_release_mouse_modsr   error)r   rv   r   r   r   r   r   r   r|   r   labelr   
text_valuer   vkexcs                   r   handle_text_message)RemoteInputController.handle_text_message   sk   	8**T"C #t$$9(D 	22   (ABB!SWWXr*+ **(((4+@+@@$UN;;"%]	2..11#6

1 111D8/2,LLH[H[!D  bB  C$TfXQqc1#+>PV]^@bcc%11#6**3778Q+?@!#''&/2T__TXfX^3TUV  v4$T[!AaS+I4??[ahitx?Kyzz#11#6**3778T=O=O+PQxx~>?qV,$TYvhas!A3+GY_fgrvIwxx<<11#6!#''&/2\)$FE'E!..swwx/CDF!':!5A1E.3qjNhET__TXeW3EFGA&DA$TfXQvhas!A3+GY_fgrvIwxx 11#6!#''&/2E#'''1"567T__T3JKLA%3$TVE7$qc1#+FX^efquHvww$'F
!(==67"":.$TU3z?2C6+JKK <!#''&/2T__T5H3NOP*$TT#<88# <__S)>KKD)(3%/@AA$U.?u,EFF! <__S)>KKE*(??$UocU,CDD..  "GH$T>::&((*&+#$T:66 *:6((CDDU  	8 77	8V  	2$$&KK8#> C11		2s   X8 B
Y B/Y BY CY 0B,Y 1Y :Y 
A<Y AY Y *AY >Y 2Y  (Y )Y 8YY
Z)A Z$Z)$Z)c                   U R                   R                  5       nU(       d  [        S5      eUR                  u  p4pV[	        S[        XS-
  5      5      n[	        S[        Xd-
  5      5      n[	        S[        [        UR                  SU5      5      5      5      n	[	        S[        [        UR                  SU5      5      5      5      n
[        UR                  SS5      5      n[        UR                  SS5      5      n[        [        [        U5      [	        S[        U	S-
  U5      5      U-  U	-  -   5      5      n[        [        [        U5      [	        S[        U
S-
  U5      5      U-  U
-  -   5      5      nX4$ )	Nzcapture target not availabler?   r   r   r   r   r   r   )
r   
get_targetRuntimeErrorrectmaxr   r   r{   roundmin)r   r   targetrk   toprm   bottomtarget_wtarget_hr   r   r   r   sxsys                  r   r   +RemoteInputController._map_canvas_to_screenH  s2   $$//1=>>#);; 5q#el+,q#fl+,aU3779h#?@ABaU3779h#?@AB#''#q/"#''#q/"s4y3sC!Q,?#@8#Kg#UUVWs3x#c3w{A+>"?("JW"TTUVvr   c                X    [         R                  " [        U 5      [        U5      45        g r   )win32apiSetCursorPosr   )r   r   s     r   r   RemoteInputController._moveZ  s    s1vs1v./r   c                .    [         R                  U S5      $ )Nrk   )BUTTON_BY_CODEr{   )r   s    r   r   "RemoteInputController._button_name^  s    !!&&11r   c                   / nU R                  S5      (       a  UR                  S5        U R                  S5      (       a  UR                  S5        U R                  S5      (       a  UR                  S5        U R                  S5      (       a  UR                  S5        U(       d  U$ S	S
R                  U5       SUR                  S	S5       3$ )Nrg   rW   ri   rX   rh   rY   rj   r[   r   +
rr   )r{   appendjoinreplace)r|   basenamess      r   r    RemoteInputController._mod_labelb  s    88FLL 88GLL!88E??LL88FLLK#((5/*"T\\*b-I,JKKr   c                   U R                  5         / U l        S Hp  n[        UR                  U5      5      (       d  M$  [        U   nU R                  R                  U5        U R                  US5        [        R                  " S5        Mr     g )Nrf   T{Gzt?)	r   r   r
   r{   MOD_VKr   r   r    sleep)r   r|   r}   r   s       r   _press_mouse_mods'RemoteInputController._press_mouse_modsq  sj      " 4DDHHTN##D\##**2.B%

5! 5r   c                    [        U R                  5       H,  n U R                  US5        [        R                  " S5        M.     / U l        g ! [
         a     ME  f = f)NFr   )reversedr   r   r    r  r   r   r   s     r   r   )RemoteInputController._release_mouse_mods{  sT    4../BB&

5! 0 !  s   (A
AAc                    U R                  X5        U R                  U=(       d    0 5        [        R                  U[        S   5      u  pV[        R
                  " USSSS5        SU l        X0l        g )Nrk   r   T)r   r	  BUTTON_FLAGSr{   r   mouse_eventr   r   )r   r   r   r   r|   down_ups          r   r   !RemoteInputController._mouse_down  s]    

1tzr* $$V\&-AB	T1aA."#r   c                   U R                  X5        [        R                  U[        R                  U R                  [        S   5      5      u  pE[        R
                  " USSSS5        SU l        U R                  5         g )Nrk   r   F)r   r  r{   r   r   r  r   r   )r   r   r   r   _downups         r   r   RemoteInputController._mouse_up  sf    

1 $$V\-=-=d>P>PR^_eRf-gh	RAq!,#  "r   c                   U R                  X5        U R                  U=(       d    0 5        [        R                  U[        S   5      u  pg [	        [        S[        U5      5      5       Hc  n[        R                  " USSSS5        [        R                  " S5        [        R                  " USSSS5        [        R                  " S5        Me     U R                  5         g ! U R                  5         f = f)Nrk   r?   r   gQ?g)\(?)r   r	  r  r{   ranger   r   r   r  r    r  r   )	r   r   r   r   r   r|   r  r  _s	            r   r   RemoteInputController._click  s    

1tzr*##FL,@A	'3q#e*-.$$T1aA6

5!$$RAq!4

5!	 / $$&D$$&s   BC" "C4c                   U R                  X5        US:X  a  g U R                  U=(       d    0 5         US:  a  SOSn[        R                  " [        R
                  SSUS5        U R                  5         g ! U R                  5         f = f)Nr   ix   )r   r	  r   r  win32conMOUSEEVENTF_WHEELr   )r   r   r   r   r|   r   s         r   r   RemoteInputController._wheel  sq    

1A:tzr*	'!AID3E  !;!;Q5!L$$&D$$&s   2A7 7B	c                z    U(       a  SO[         R                  n[        R                  " [	        U 5      SUS5        g )Nr   )r  KEYEVENTF_KEYUPr   keybd_eventr   )r   r  flagss      r   r   RemoteInputController._keybd  s)    x77SWa2r   c                x    U R                  US5        [        R                  " S5        U R                  US5        g )NTgQ?F)r   r    r  r  s     r   	_press_vkRemoteInputController._press_vk  s*    B

5Br   c                    U[         ;   a	  [         U   $ [        U5      S:X  a:  UR                  5       nSUs=::  a  S::  d  O  SUs=::  a  S::  a  O  g [        U5      $ g )Nr?   AZrn   9)VK_MAPrs   upperord)r   r   chs      r   r    RemoteInputController._key_to_vk  sS    &=#;s8q=BbC3"#3#3 2wr   c                6   [        U5      nU R                  U5      nUc  g / nS Hf  n[        UR                  U5      5      (       d  M$  [        U   nUR                  U5        U R                  US5        [        R                  " S5        Mh      U R                  U5        [        U5       H+  nU R                  US5        [        R                  " S5        M-     g ! [        U5       H+  nU R                  US5        [        R                  " S5        M-     f = f)Nrf   Tr  F)r~   r   r
   r{   r  r   r   r    r  r(  r  )r   r   r|   r   	down_modsr}   mvks          r   r    RemoteInputController._press_key  s    $__S!:!	4DDHHTN##Tl  %C&

5! 5	"NN2	*C'

5! +x	*C'

5! +s   C <Dc                    [         U(       a  [        OS-  n[        [        [	        [        SXSS5      S9S9n[        R                  R                  R                  S[        R                  " U5      [        R                  " [        5      5        g )Nr   )r7   )r=   r>   r?   )KEYEVENTF_UNICODEr#  r;   INPUT_KEYBOARDr5   r   r"   windlluser32	SendInputbyrefsizeof)	code_unitkeyupr%  inps       r   _send_unicode_unit(RemoteInputController._send_unicode_unit  s\    !_1EzZ9]^`a=b/cd&&q&,,s*;V]]5=QRr   c                    UR                  SSS9n[        S[        U5      S5       HH  nX#   X#S-      S-  -  nU R                  USS	9  U R                  US
S	9  [        R
                  " S5        MJ     g )Nz	utf-16-lesurrogatepass)errorsr   r@   r?   r   F)r@  Tr   )encoder  rs   rB  r    r  )r   rv   encodediunits        r   r   #RemoteInputController._type_unicode  sv     ++k/+Bq#g,*A:Q1!45D##D#6##D#5JJu	 +r   c                B    [         R                  " S/SS9  g ! [         a&  nU R                  R	                  SU5         S nAOS nAff = f [         R                  " / SQSS9  g ! [         a/  nU R                  R                  SU5        [        SU 35      eS nAff = f)Nosk.exeT)	close_fdszosk direct launch failed: %s)cmdz/cstartrr   rM  zosk launch failed: %su   osk 실행 실패: )
subprocessPopenr   r   debugr   r   )r   	first_exc
second_excs      r   r   !RemoteInputController._launch_osk  s    	Ii[D9 	IKK<iHH	I	CBdS 	CKK5zB!4ZLABB	Cs,    
A	AA	A% %
B/*BB)r   r   r   r   r   r   r   r   r   r   r   )NN)r   zCallable[[], bool]r   zOptional[logging.Logger]r   zOptional[Callable[[str], None]])returnr
   )rv   r   rW  None)r   r   r   rz   r   r   r   r   r   r
   rW  r   )rv   r   rW  r   )r   rz   rW  ztuple[int, int])r   r   r   r   rW  rX  )r   objectrW  r   )r|   dict[str, bool]r  r   rW  r   )r|   rZ  rW  rX  )rW  rX  )rk   N)
r   r   r   r   r   r   r|   dict[str, bool] | NonerW  rX  )rk   )r   r   r   r   r   r   rW  rX  )rk   r?   N)r   r   r   r   r   r   r   r   r|   r[  rW  rX  r   )
r   r   r   r   r   r   r|   r[  rW  rX  )r   r   r  r
   rW  rX  )r   r   rW  rX  )r   r   rW  zOptional[int])r   r   r|   zdict | NonerW  rX  )F)r?  r   r@  r
   rW  rX  )r   r   r   r   r   r   r   r   r   r   staticmethodr   r   r   r	  r   r   r   r   r   r   r(  r   r   rB  r   r   r   r   r   r   r   r      s    
 ,0;?, 0, )	,
 9,& af 
"r2h$ 0 0 2 2 L L"!$#'	' 3 3
"* S S
Cr   r   )   )rt   rY  ru   r   rW  r   )r|   rY  rW  rZ  )I__doc__
__future__r   r"   r   r   osrQ  r    dataclassesr   typingr   r   r   r  r   r>  c_void_pc_ulonglongr$   r%   	Structurer   r(   r/   Unionr5   r;   r9  r#  r8  VK_BACKVK_TAB	VK_RETURN	VK_ESCAPEVK_SPACE	VK_DELETE	VK_INSERTVK_HOMEVK_ENDVK_PRIORVK_NEXTVK_LEFTVK_RIGHTVK_UPVK_DOWN
VK_CONTROLVK_SHIFTVK_MENUVK_LWINVK_APPSVK_SNAPSHOTVK_PAUSE
VK_CAPITAL
VK_NUMLOCK	VK_SCROLLr.  r  rI  getattrr  MOUSEEVENTF_LEFTDOWNMOUSEEVENTF_LEFTUPMOUSEEVENTF_MIDDLEDOWNMOUSEEVENTF_MIDDLEUPMOUSEEVENTF_RIGHTDOWNMOUSEEVENTF_RIGHTUPr  r   rw   r~   r   r   r   r   <module>r     s  & #    	   ! %         #)--"@A"EF6>>	!! !! fF$$ fO OAF A  !
!!!
	8??!
 X!
 h  	!

 h  !
 
8!
 X!
 		!
 h  !
 
8!
 h  !
 
8!
 H!
 
8??!
 h!
    !!
" !!#!
$ ##~~!!""##''##""$$A!
D 
q"Ah$qc
D1HqLAFQqc7O 

 	
 **H,G,GH..0M0MN,,h.J.JK 			
ULC LCr   