
    uj4D                    b   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	m
Z
 ddlmZmZ ddlZddlZe
 G d d             Z ej"                  ej$                        dk(  rej&                  nej(                  Z G d	 d
ej,                        Z G d dej,                        Z G d dej,                        Z G d dej4                        Z G d dej,                        ZdZdZdZi dej@                  dejB                  dejD                  dejD                  dejF                  dejF                  dejH                  dejH                  dejJ                  dejJ                  d ejL                  d!ejL                  d"ejN                  d#ejP                  d$ejR                  d%ejT                  d&ejV                  ejX                  ejZ                  ej\                  ej^                  ej^                  ej`                  ejb                  ejd                  ejd                  ejf                  ejh                  ejj                  ejl                  ejn                  ejp                  d'Z9 e:dd(      D ]  Z; e<ed)e; d*e;z   dz
        e9d+e; <    ej^                  ejb                  ej`                  ejd                  d,Z=ej|                  ej~                  fej                  ej                  fej                  ej                  fd-ZDd.d/d0d.d/d0d.d/d0d1	ZEd6d7d2ZFd8d3ZG G d4 d5      ZHy)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                  "    e Zd ZU ded<   ded<   y)ControlResultboolokstrmessageN)__name__
__module____qualname____annotations__     )D:\_St\RTC8790_8791\yjm_remote_control.pyr   r   $   s    HLr   r      c                  ~    e Zd Zdej                  fdej                  fdej
                  fdej
                  fdefgZy)
KEYBDINPUTwVkwScandwFlagstimedwExtraInfoN)r   r   r   ctypesc_ushortc_ulong	ULONG_PTR_fields_r   r   r   r   r   .   sA    	 	&//"	FNN#	 		"Hr   r   c                      e Zd Zdej                  fdej                  fdej
                  fdej
                  fdej
                  fdefgZy)
MOUSEINPUTdxdy	mouseDatar   r   r   N)r   r   r   r   c_longr   r   r    r   r   r   r"   r"   8   sM    	v}}	v}}	fnn%	FNN#	 		"Hr   r"   c                  ^    e Zd Zdej                  fdej
                  fdej
                  fgZy)HARDWAREINPUTuMsgwParamLwParamHN)r   r   r   r   r   r   r    r   r   r   r(   r(   C   s,    (9foo*FTZTcTcHdeHr   r(   c                  "    e Zd ZdefdefdefgZy)
INPUTUNIONkimihiN)r   r   r   r   r"   r(   r    r   r   r   r-   r-   G   s    z"T:$6}8MNHr   r-   c                  0    e Zd Zdej                  fdefgZy)INPUTtypeunionN)r   r   r   r   r   r-   r    r   r   r   r2   r2   K   s    (7J*?@Hr   r2            	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rightra   rb   rc   )	r   r5   r6   012ra   rb   rc   c                H    | yt        |       }t        |      |kD  r|d | }|S )N )r   len)smax_lentexts      r   
_safe_textrm      s/    yq6D
4y7HW~Kr   c           	         t        | t              sdddddS dD ci c]  }|t        | j                  |             c}S c c}w )NFr\   )
isinstancedictr	   get)modsnames     r   
_norm_modsrt      sG    dD!eeUKK3ST3S4D$txx~&&3STTTs   "Ac                     e Zd Z	 	 d	 	 	 	 	 ddZddZddZddZddZedd       Z	edd       Z
edd	       Zd d
Zd!dZd"d#dZd$d%dZd&d'dZd(d)dZed*d       Zd+dZd,dZd(d-dZed.d/d       ZddZd!dZy)0RemoteInputControllerNc                    || _         || _        |xs t        j                  t              | _        |xs d | _        d| _        d| _        d| _	        d| _
        d| _        g | _        y )Nc                     y Nr   )_texts    r   <lambda>z0RemoteInputController.__init__.<locals>.<lambda>   s    r           ~jth?Fra   )source_manageris_enabled_callbacklogging	getLoggerr   loggerstatus_callbacklast_action_atlast_move_status_atmin_interval_sec_mouse_is_down_mouse_button_mouse_mod_vks)selfr~   r   r   r   s        r   __init__zRemoteInputController.__init__   si     -#6 ; 1 1( ;.F3E!#&  %##)+r   c                T    	 t        | j                               S # t        $ r Y yw xY w)NF)r	   r   	Exception)r   s    r   
is_enabledz RemoteInputController.is_enabled   s-    	00233 		s    	''c                F    	 | j                  |       y # t        $ r Y y w xY wry   )r   r   )r   rl   s     r   _statuszRemoteInputController._status   s'    	  & 		s    	  c           
     ^   	 t        j                  |      }t	        |t
              r|j                  d      dk7  rt        dd      S | j                         st        dd      S t        j                         }t        |j                  dd            }|d	v r/|| j                  z
  | j                  k  rt        dd
      S || _        	 |d	v rr| j                  |      \  }}| j                  ||       || j                  z
  dkD  r&|| _        | j!                  | j"                  rdnd       t        d| d| d|       S |dk(  r| j                  |      \  }}| j%                  |j                  dd            }t'        |j                  d            }| j!                  | j)                  |d| d             | j+                  ||||       t        dd| d| d|       S |dk(  r|| j                  |      \  }}| j%                  |j                  d| j,                              }| j!                  d| d       | j/                  |||       t        dd| d| d|       S |dv r| j                  |      \  }}t'        |j                  d            }|dk(  rd}d}	d}
n3| j%                  |j                  dd            }|d k(  rd!nd}	|	d!k(  rd"nd#}
| j!                  | j)                  |d|
              | j1                  ||||	|$       t        d| d| d| d|       S |d%k(  r| j                  |      \  }}t'        |j                  d            }t3        t5        |j                  d&d                  }| j!                  | j)                  |d'             | j7                  ||||(       t        dd)| d*| d|       S |d+k(  ret9        |j                  d,      d-.      }|st        dd/      S | j!                  d0       | j;                  |       t        dd1t=        |       d2      S |d3k(  r{t9        |j                  d3      d4.      }t'        |j                  d            }| j!                  | j)                  |d5|              | j?                  ||       t        dd6|       S |d7k(  r_t9        |j                  d3      d4.      }| jA                  |      }|!| jC                  |d       t        dd8|       S t        dd9|       S |d:k(  r_t9        |j                  d3      d4.      }| jA                  |      }|!| jC                  |d       t        dd;|       S t        dd<|       S |d=v r-| jE                          | j!                  d>       t        dd?      S |d@k(  r| j"                  rCtF        j                  | j,                  tF        dA         \  }}tI        jJ                  |dddd       | jM                          d| _        | j!                  dB       t        ddC      S t        ddD|       S # t        $ r t        dd      cY S w xY w# t        $ rK}| jM                          | jN                  jQ                  dE|       t        dt        |            cY d }~S d }~ww xY w)FNFzinvalid jsonr3   controlignoredzremote control disabledactionrh   )move	drag_movezrate limitedg      ?u!   원격: 마우스 드래그중...u   원격: 마우스 이동중...Tr?   ,
mouse_downbuttonr   rr      원격: u    버튼 누름zmouse_down mouse_upu    버튼 놓음z	mouse_up )clickdblclick
rightclickr   rc   r5   u	   우클릭r   r6   u   더블클릭u   클릭)countrr   wheeldeltau   원격: 휠 스크롤)rr   zwheel z at 	type_textrl   i  )rk   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_allra   u   원격: 입력 해제releasedzunknown action: zremote control error: %s))jsonloadsr   r   ro   rp   rq   r   r   perf_counterr   r   r   _map_canvas_to_screen_mover   r   r   _button_namert   
_mod_label_mouse_downr   	_mouse_up_clickintfloat_wheelrm   _type_unicoderi   
_press_key
_key_to_vk_keybd_launch_oskBUTTON_FLAGSwin32apimouse_event_release_mouse_modsr   error)r   rl   msgnowr   xyr   rr   r   labelr   
text_valuer   vk_downupexcs                     r   handle_text_messagez)RemoteInputController.handle_text_message   sx   	8**T"C #t$9(D 	22  (ABB!SWWXr*+ **T(((4+@+@@$UN;;"%Da	2..11#61

1a 111D8/2D,LLH[H[!D  bB  C$TfXQqc1#+>??%11#61**3778Q+?@!#''&/2T__TXfX^3TUV  Avt4$T[!AaS+IJJ#11#61**3778T=O=O+PQxx~>?q!V,$TYvhas!A3+GHH<<11#61!#''&/2\)$FE'E!..swwx/CDF!':!5A1E.3qjNhET__TXeW3EFGAq&DA$TfXQvhas!A3+GHH 11#61!#''&/2E#'''1"567T__T3JKLAq%d3$TVE7$qc1#+FGG$'F
!(==67"":.$TU3z?2C6+JKK <!#''&/2T__T5H3NOPT*$TT#<88# <__S)>KKD)(3%/@AA$U.?u,EFF! <__S)>KKE*(??$UocU,CDD..  "GH$T>::&&& , 0 01C1C\RXEY ZIE2((Q1a8((*&+#45$T:66 *:6((CDD]  	8 77	8^  	2$$&KK8#> C11		2s   X= A5Y <B!Y B Y CY !B!Y .Y 2:Y -A?Y -AY Y AY &Y 50Y &BY .Y =YY	Z,!A Z'!Z,'Z,c                   | j                   j                         }|st        d      |j                  \  }}}}t	        dt        ||z
              }t	        dt        ||z
              }t	        dt        t        |j                  d|                        }	t	        dt        t        |j                  d|                        }
t        |j                  dd            }t        |j                  dd            }t        t        t        |      t	        dt        |	dz
  |            |z  |	z  z               }t        t        t        |      t	        dt        |
dz
  |            |z  |
z  z               }||fS )	Nzcapture target not availabler5   frame_wframe_hr   r   r   r|   )
r~   
get_targetRuntimeErrorrectmaxr   r   rq   roundmin)r   r   targetra   toprc   bottomtarget_wtarget_hr   r   r   r   sxsys                  r   r   z+RemoteInputController._map_canvas_to_screen9  s<   $$//1=>>#);; c5&q#edl+,q#fsl+,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2vr   c                V    t        j                  t        |       t        |      f       y ry   )r   SetCursorPosr   )r   r   s     r   r   zRemoteInputController._moveK  s    s1vs1v./r   c                .    t         j                  | d      S )Nra   )BUTTON_BY_CODErq   )r   s    r   r   z"RemoteInputController._button_nameO  s    !!&&11r   c                l   g }| j                  d      r|j                  d       | j                  d      r|j                  d       | j                  d      r|j                  d       | j                  d      r|j                  d       |s|S d	d
j                  |       d|j                  d	d       S )Nr]   rM   r_   rN   r^   rO   r`   rQ   r   +
rh   )rq   appendjoinreplace)rr   basenamess      r   r   z RemoteInputController._mod_labelS  s    88FLL 88GLL!88E?LL88FLLK#((5/*"T\\*b-I,JKKr   c                   | j                          g | _        dD ]h  }t        |j                  |            st        |   }| j                  j                  |       | j                  |d       t        j                  d       j y )Nr\   T{Gzt?)	r   r   r	   rq   MOD_VKr   r   r   sleep)r   rr   rs   r   s       r   _press_mouse_modsz'RemoteInputController._press_mouse_modsb  sg      " 4DDHHTN#D\##**2.B%

5! 5r   c                    t        | j                        D ]*  }	 | j                  |d       t        j                  d       , g | _        y # t
        $ r Y @w xY w)NFr}   )reversedr   r   r   r   r   r   r   s     r   r   z)RemoteInputController._release_mouse_modsl  sT    4../BB&

5! 0 !  s   'A	AAc                    | j                  ||       | j                  |xs i        t        j                  |t        d         \  }}t	        j
                  |dddd       d| _        || _        y )Nra   r   T)r   r   r   rq   r   r   r   r   )r   r   r   r   rr   down_ups          r   r   z!RemoteInputController._mouse_downu  sc    

1atzr* $$V\&-AB	cT1aA."#r   c                   | j                  ||       t        j                  |t        j                  | j                  t        d               \  }}t	        j
                  |dddd       d| _        | j                          y )Nra   r   F)r   r   rq   r   r   r   r   r   )r   r   r   r   r   r   s         r   r   zRemoteInputController._mouse_up}  sj    

1a $$V\-=-=d>P>PR^_eRf-gh	rRAq!,#  "r   c                   | j                  ||       | j                  |xs i        t        j                  |t        d         \  }}	 t	        t        dt        |                  D ]^  }t        j                  |dddd       t        j                  d       t        j                  |dddd       t        j                  d       ` 	 | j                          y # | j                          w xY w)Nra   r5   r   gQ?g)\(?)r   r   r   rq   ranger   r   r   r   r   r   r   )	r   r   r   r   r   rr   r   r   _s	            r   r   zRemoteInputController._click  s    

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

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

5!	 / $$&D$$&s   	A?C C,c                
   | j                  ||       |dk(  ry | j                  |xs i        	 |dkD  rdnd}t        j                  t        j
                  dd|d       | j                          y # | j                          w xY w)Nr   ix   )r   r   r   r   win32conMOUSEEVENTF_WHEELr   )r   r   r   r   rr   r   s         r   r   zRemoteInputController._wheel  ss    

1aA:tzr*	'!AID3E  !;!;Q5!L$$&D$$&s   0A0 0Bc                n    |rdnt         j                  }t        j                  t	        |       d|d       y )Nr   )r   KEYEVENTF_KEYUPr   keybd_eventr   )r   r   flagss      r   r   zRemoteInputController._keybd  s)    x77SWa2r   c                v    | j                  |d       t        j                  d       | j                  |d       y )NTgQ?F)r   r   r   r   s     r   	_press_vkzRemoteInputController._press_vk  s*    B

5Br   c                    |t         v r	t         |   S t        |      dk(  r@|j                         }d|cxk  rdk  sn d|cxk  rdk  rt        |      S  y t        |      S y )Nr5   AZrd   9)VK_MAPri   upperord)r   r   chs      r   r   z RemoteInputController._key_to_vk  sa    &=#;s8q=BbC3"#3#32w $4 2wr   c                   t        |      }| j                  |      }|y g }dD ]^  }t        |j                  |            st        |   }|j                  |       | j                  |d       t        j                  d       ` 	 | j                  |       t        |      D ])  }| j                  |d       t        j                  d       + y # t        |      D ])  }| j                  |d       t        j                  d       + w xY w)Nr\   Tr   F)rt   r   r	   rq   r   r   r   r   r   r  r   )r   r   rr   r   	down_modsrs   mvks          r   r   z RemoteInputController._press_key  s    $__S!:!	4DDHHTN#Tl  %C&

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

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

5! +s   C 9Dc                    t         |rt        ndz  }t        t        t	        t        d| |dd                  }t        j                  j                  j                  dt        j                  |      t        j                  t                     y )Nr   )r.   )r3   r4   r5   )KEYEVENTF_UNICODEr   r2   INPUT_KEYBOARDr-   r   r   windlluser32	SendInputbyrefsizeof)	code_unitkeyupr   inps       r   _send_unicode_unitz(RemoteInputController._send_unicode_unit  s_    !_1EzZ9V[]^`a=b/cd&&q&,,s*;V]]5=QRr   c                    |j                  dd      }t        dt        |      d      D ]N  }||   ||dz      dz  z  }| j                  |d	       | j                  |d
	       t	        j
                  d       P y )Nz	utf-16-lesurrogatepass)errorsr   r6   r5   r   F)r  Tr}   )encoder   ri   r  r   r   )r   rl   encodediunits        r   r   z#RemoteInputController._type_unicode  sz     ++k/+Bq#g,*A1:Q1!45D##D#6##D#5JJu	 +r   c                F   	 t        j                  dgd       y # t        $ r&}| j                  j	                  d|       Y d }~nd }~ww xY w	 t        j                  g dd       y # t        $ r/}| j                  j                  d|       t        d|       d }~ww xY w)Nosk.exeT)	close_fdszosk direct launch failed: %s)cmdz/cstartrh   r!  zosk launch failed: %su   osk 실행 실패: )
subprocessPopenr   r   debugr   r   )r   	first_exc
second_excs      r   r   z!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 1*BB )NN)r   zCallable[[], bool]r   zOptional[logging.Logger]r   zOptional[Callable[[str], None]])returnr	   )rl   r   r*  None)rl   r   r*  r   )r   rp   r*  ztuple[int, int])r   r   r   r   r*  r+  )r   objectr*  r   )rr   dict[str, bool]r   r   r*  r   )rr   r-  r*  r+  )r*  r+  )ra   N)
r   r   r   r   r   r   rr   dict[str, bool] | Noner*  r+  )ra   )r   r   r   r   r   r   r*  r+  )ra   r5   N)r   r   r   r   r   r   r   r   rr   r.  r*  r+  ry   )
r   r   r   r   r   r   rr   r.  r*  r+  )r   r   r   r	   r*  r+  )r   r   r*  r+  )r   r   r*  zOptional[int])r   r   rr   zdict | Noner*  r+  )F)r  r   r  r	   r*  r+  )r   r   r   r   r   r   r   r   staticmethodr   r   r   r   r   r   r   r   r   r   r  r   r   r  r   r   r   r   r   rv   rv      s    
 ,0;?, 0, )	,
 9,$v2p$ 0 0 2 2 L L"!$#'	' 3 3
"* S S
Cr   rv   )   )rj   r,  rk   r   r*  r   )rr   r,  r*  r-  )I__doc__
__future__r   r   r   r   osr%  r   dataclassesr   typingr   r   r   r   r   r  c_void_pc_ulonglongr   r   	Structurer   r"   r(   Unionr-   r2   r  r   r  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   r  getattrr   MOUSEEVENTF_LEFTDOWNMOUSEEVENTF_LEFTUPMOUSEEVENTF_MIDDLEDOWNMOUSEEVENTF_MIDDLEUPMOUSEEVENTF_RIGHTDOWNMOUSEEVENTF_RIGHTUPr   r   rm   rt   rv   r   r   r   <module>rZ     s  & #    	   ! %      #0&--"@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~C ~Cr   