
    uj)                    J   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
mZ ddlmZ ddlmZ ddlZ	 ddlZddlZe
 G d d             Zdd	Zdd
ZddZddZddZddZddZddZddZdddZedk(  r e       Z  e! ee              yy# e$ r dZdZY _w xY w)u  
yjm_monitor_probe.py

Windows 다중 모니터 진단 공통 모듈.

목적:
- mss가 보는 원본 모니터 목록을 그대로 확인한다.
- Win32 EnumDisplayMonitors가 보는 목록을 같이 확인한다.
- DPI awareness 적용 전/후 차이를 줄인다.
- yjm_win2rtc 본 프로그램과 별도 진단 GUI가 같은 함수를 사용하게 한다.

중요 원칙:
- 실제 캡처 기준은 mss.monitors 원본 순서를 우선한다.
- Win32 목록은 진단/비교용이다. mss 목록과 임의 병합하지 않는다.
    )annotationsN)	dataclassasdict)Path)Anyc                      e Zd ZU ded<   ded<   ded<   ded<   ded<   ded<   ded	<   ded
<   dZded<   dZded<   dZded<   dZded<   edd       Z	ddZ
ddZy)MonitorInfostrapiintindexlefttopwidthheightrightbottomFboolprimary devicenameNzdict[str, Any] | Noneextrac                ^    | j                   | j                  | j                  | j                  fS N)r   r   r   r   selfs    (D:\_St\RTC8790_8791\yjm_monitor_probe.pyrectzMonitorInfo.rect7   s!    yy$((DJJ;;    c                    t        |       S r   )r   r   s    r   to_dictzMonitorInfo.to_dict;   s    d|r    c                t   | j                   rdnd}| j                  rd| j                   nd}| j                  rd| j                   nd}| j                   d| j                   d| j
                   d| j                   d| j                   d| j                   d	| j                   d
| j                   | | | S )Nz
 / PRIMARYr    / [] xz @ left=z, top=z, right=z	, bottom=)r   r   r   r   r   r   r   r   r   r   r   )r   r   devr   s       r   labelzMonitorInfo.label>   s    "&,,,B%)[[DKK=!b$(IITYYK 2xxj$**R

|1T[[M Bii[txxjIdkk]iuTF$	
r    )returnztuple[int, int, int, int]r*   dict[str, Any]r*   r
   )__name__
__module____qualname____annotations__r   r   r   r   propertyr   r"   r)    r    r   r	   r	   (   sn    	HJ
I	HJKJKGTFCD#N#'E '< <
r    r	   c                 N   t         j                  dk7  ry	 t        j                  j                  j                  d       y# t        $ r[} 	 t        j                  j                  j                          d|  cY d} ~ S # t        $ r}d|  d| cY d}~cY d} ~ S d}~ww xY wd} ~ ww xY w)	u`   프로세스를 DPI aware로 만든다. 이미 설정되어 있으면 실패해도 무시한다.ntnot-windows   zSetProcessDpiAwareness(2) OKz'SetProcessDPIAware OK / shcore failed: NzDPI awareness failed: shcore=z	, user32=)	osr   ctypeswindllshcoreSetProcessDpiAwareness	Exceptionuser32SetProcessDPIAware)exc1exc2s     r   set_dpi_awarenessrB   I   s    	ww$	I33A6- I	IMM  335<TFCC 	I24&	$HHH	IIsG   )A   	B$
,A<6B$<	BBBBB$BBB$c                 ~   i } t         j                  dk7  rddiS 	 t        j                  j                  j                         | d<   	 t        j                  j                  j                  d      }t        j                  j                  j                  |d      | d<   t        j                  j                  j                  |d	      | d
<   t        j                  j                  j                  d|       | S # t        $ r}t        |      | d<   Y d }~d }~ww xY w# t        $ r}t        |      | d<   Y d }~| S d }~ww xY w)Nr5   platformr6   system_dpi_xsystem_dpi_x_errorr   X   device_caps_logpixelsxZ   device_caps_logpixelsydevice_caps_error)r8   r   r9   r:   r>   GetDpiForSystemr=   r
   GetDCgdi32GetDeviceCaps	ReleaseDC)infoexcdcs      r   get_dpi_inforT   [   s	   D	ww$M**.%}}33CCE^-]]!!''*)/)<)<)J)J2r)R%&)/)<)<)J)J2r)R%&&&q"- K  .%(X!".  -$'H !K-s0   +C6 B-D 6	D?DD	D<#D77D<c                    g } t        j                          5 }t        |j                        D ]  \  }}t        |d         }t        |d         }t        |d         }t        |d         }| j	                  t        d|||||||z   ||z   |dk(  xr |dk(  xr |dk(  |dk(  rdnd	t        |      
              	 ddd       | S # 1 sw Y   | S xY w)uS   mss.monitors 원본 순서 그대로 반환. index 0은 전체 가상 바탕화면.r   r   r   r   mss   r   virtualr   r   r   r   r   r   r   r   r   r   r   r   N)rV   	enumeratemonitorsr   appendr	   dict)resultsctidxmonr   r   r   r   s           r   list_mss_monitorsrb   q   s     "F	c!#,,/HCs6{#Dc%j/CG%EX'FMM!,< AX@$!)@q(+q9bs) 0 
* M+ 
* Ms   B"CCc                     t               dd S )uU   캡처 소스 콤보박스용. mss[1:]만 반환하되 원본 순서를 유지한다.rW   N)rb   r3   r    r   list_mss_physical_displaysrd      s    qr""r    c                    g } t         | S 	 t        j                         }t        |      D ]  \  }}	 |d   }|d   }t        j                  |      }|j                  d|      \  }}}	}
|j                  d      }t        |j                  dd            }t        |j                  dd            }| j                  t        d|t        |      t        |      t        |	|z
        t        |
|z
        t        |	      t        |
      t        |d	z        |||d
              | S # t        $ r | cY S w xY w# t        $ r Y w xY w)Nr   r7   MonitorWorkFlagsDevicer   win32rW   )workflagsrY   )win32apiEnumDisplayMonitorsr=   rZ   GetMonitorInfogetr   r
   r\   r	   r   )r^   r[   r`   itemhmonfallback_rectrQ   r   r   r   r   rk   rl   r   s                 r   list_win32_monitorsrt      sF    "F//1 x(	T	7D GM**40D'+xx	='I$D#uf88F#D!,-E(B/0FMMTCedl+v|,e*v; O!#'%8 )4 M;  6  		s#   D# C-D4#D10D14	E Ec                    g } t         | S 	 d}	 t        j                  d|d      }| j                  |t        |dd      t        |dd      t        |dd      t        |dd      t        |dd      d	       |d
z  }l# t        $ r Y | S w xY w)u7   EnumDisplayDevices 정보. DISPLAY1/2 이름 확인용.Nr   
DeviceNamer   DeviceString
StateFlagsDeviceID	DeviceKey)r   rv   rw   rx   ry   rz   rW   )rm   EnumDisplayDevicesr\   getattrr=   )r^   ir(   s      r   list_display_devicesr~      s    #%F--dAq9CMM")#|R"@$+C$D")#|Q"? 'Z <!(k2!>	 FA   Ms   A/A; ;	BBc                    | s	dddddddS t        d | D              }t        d | D              }t        d | D              }t        d | D              }||||||z
  ||z
  dS )Nr   )r   r   r   r   r   r   c              3  4   K   | ]  }|j                     y wr   )r   .0ms     r   	<genexpr>z3get_virtual_bounds_from_monitors.<locals>.<genexpr>   s     (x!qvvx   c              3  4   K   | ]  }|j                     y wr   )r   r   s     r   r   z3get_virtual_bounds_from_monitors.<locals>.<genexpr>   s     &XaeeXr   c              3  4   K   | ]  }|j                     y wr   )r   r   s     r   r   z3get_virtual_bounds_from_monitors.<locals>.<genexpr>   s     *Ar   c              3  4   K   | ]  }|j                     y wr   )r   r   s     r   r   z3get_virtual_bounds_from_monitors.<locals>.<genexpr>   s     ,8a8r   )minmax)r[   r   r   r   r   s        r    get_virtual_bounds_from_monitorsr      s}    !a1qTUVV(x((D
&X&
&C***E,8,,F3, r    c                    t               } t               }t               }t               }t	        j
                  d      t        j                  t        j                  t        j                         | t               |D cg c]  }|j                          c}t        |dd        |D cg c]  }|j                          c}t        |      |dS c c}w c c}w )Nz%Y-%m-%d %H:%M:%SrW   )	timestamppython
executablerD   
dpi_statusdpi_infomss_monitors mss_virtual_bounds_from_physicalwin32_monitorswin32_virtual_boundsdisplay_devices)rB   rb   rt   r~   timestrftimesysversionr   rD   rT   r"   r   )r   r   r   devicesr   s        r   make_probe_reportr      s    "$J$&L(*N"$G]]#67++nn%%'  N.:;ll;,L\Z[Z\M],^0>?1199;? @ P"  <?s   <C&Cc                
   g }|j                  d       |j                  d| j                  d              |j                  d| j                  d              |j                  d| j                  d              |j                  d| j                  d	              |j                  d
| j                  d              |j                  d| j                  d              |j                  d       |j                  d       |j                  d       | j                  dg       D ]U  }t        |j                  dd      t        |j                  dd            t        |j                  dd            t        |j                  dd            t        |j                  dd            t        |j                  dd            t        |j                  dd            t        |j                  dd            t	        |j                  dd            t        |j                  dd            t        |j                  dd            |j                  d       !      }|j                  d"|j                         z          X |j                  d#| j                  d$              |j                  d       |j                  d%       | j                  d&g       D ]U  }t        |j                  dd'      t        |j                  dd            t        |j                  dd            t        |j                  dd            t        |j                  dd            t        |j                  dd            t        |j                  dd            t        |j                  dd            t	        |j                  dd            t        |j                  dd            t        |j                  dd            |j                  d       !      }|j                  d"|j                         z          X |j                  d(| j                  d)              |j                  d       |j                  d*       | j                  d+g       D ][  }|j                  d,|j                  d       d-|j                  d.       d/|j                  d0       d1|j                  d2              ] |j                  d       d3j                  |      S )4Nz# yjm_monitor_probe reportztimestamp: r   zpython: r   zexecutable: r   z
platform: rD   zdpi_status: r   z
dpi_info: r   r   z## MSS monitorsu`   주의: mss[0]은 전체 가상 바탕화면, mss[1:]가 실제 디스플레이 후보입니다.r   r   rV   r   r   r   r   r   r   r   r   r   Fr   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   z  z"mss_virtual_bounds_from_physical: r   z## Win32 monitorsr   rj   zwin32_virtual_bounds: r   z## Display devicesr   z  [r&   rv   r$   rw   z	 / flags=rx   
)r\   rp   r	   r   r   r
   r)   join)reportlinesr   ra   ds        r   format_report_textr      s    E	LL-.	LL;vzz+6789	LL8FJJx0123	LL<

< 89:;	LL:fjj4567	LL<

< 89:;	LL:fjj4567	LL	LL"#	LLstZZ+eU#aeeGQ'(QUU61%&AEE%O$aeeGQ'(quuXq)*aeeGQ'(quuXq)*y%01quuXr*+QUU62&'%%.
 	TCIIK'( ,  
LL5fjjAc6d5efg	LL	LL$%ZZ("-eW%aeeGQ'(QUU61%&AEE%O$aeeGQ'(quuXq)*aeeGQ'(quuXq)*y%01quuXr*+QUU62&'%%.
 	TCIIK'( .  
LL)&**5K*L)MNO	LL	LL%&ZZ)2.!%%.!AEE,$7#8AEE.<Q;RR[\]\a\abn\o[pq	
 / 
LL99Ur    c                    t        |       }|j                  dd       t               }|dz  }|dz  }|j                  t	        j
                  |dd      d	       |j                  t        |      d	       ||fS )
NT)parentsexist_okzmonitor_report.jsonzmonitor_report.txtFr7   )ensure_asciiindentzutf-8)encoding)r   mkdirr   
write_textjsondumpsr   )out_diroutr   	json_pathtxt_paths        r   save_probe_reportr   4  s~    
w-CIIdTI* F++I))HFqIT[\*62WEhr    __main__r-   r+   )r*   list[MonitorInfo])r*   zlist[dict[str, Any]])r[   r   r*   zdict[str, int])r   r,   r*   r
   )_monitor_probe_output)r   z
str | Pathr*   ztuple[Path, Path])"__doc__
__future__r   r9   r   r8   rD   r   r   dataclassesr   r   pathlibr   typingr   rV   rm   win32guir=   r	   rB   rT   rb   rd   rt   r~   r   r   r   r   r.   r   printr3   r    r   <module>r      s     #   	  
  )   
 
 
 
@I$,6#
$N2"(;| z F	
V
$% y  HHs   B 	B"!B"