Files
CODE_ASSISTANT/4_rust_tauri/docs-lib/windows-rs.md
T
2026-09-16 17:22:14 +09:00

3.0 KiB

windows 0.61.3 — CodeAssist가 쓰는 Win32 표면

작성: 2026-09-09 근거: 로컬 crate 소스 %USERPROFILE%/.cargo/registry/src/index.crates.io-*/windows-0.61.3/에서 직접 확인함.

Cargo features

windows = { version = "0.61.3", features = [
  "Win32_Foundation",
  "Win32_System_DataExchange",
  "Win32_System_Memory",
  "Win32_System_Threading",
  "Win32_UI_Input_KeyboardAndMouse",
  "Win32_UI_WindowsAndMessaging",
] }

직전 창 스냅샷

GetForegroundWindow() -> HWND
GetWindowTextW(HWND, &mut [u16]) -> i32
GetWindowThreadProcessId(HWND, Option<*mut u32>) -> u32
OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid) -> Result<HANDLE>
QueryFullProcessImageNameW(HANDLE, PROCESS_NAME_FORMAT, PWSTR, *mut u32) -> Result<()>
CloseHandle(HANDLE) -> Result<()>

창 핸들은 앱 상태에서 isize로 보관한다. HWND의 raw pointer를 그대로 앱 상태에 넣으면 Tauri가 요구하는 Send + Sync 경계와 부딪힐 수 있다.

유니코드 텍스트 클립보드

OpenClipboard(None) -> Result<()>
EmptyClipboard() -> Result<()>
GlobalAlloc(GMEM_MOVEABLE, bytes) -> Result<HGLOBAL>
GlobalLock(HGLOBAL) -> *mut c_void
GlobalUnlock(HGLOBAL) -> Result<()>
SetClipboardData(13, Some(HANDLE(hglobal.0))) -> Result<HANDLE> // 13 = CF_UNICODETEXT
CloseClipboard() -> Result<()>

SetClipboardData가 성공하면 메모리 소유권이 Windows로 넘어간다. 성공 뒤 GlobalFree를 부르면 안 된다. 실패한 경우에만 직접 해제한다.

대상 활성화와 Ctrl+V (2026-09-11 갱신)

SetForegroundWindow(HWND) -> BOOL
GetAsyncKeyState(i32) -> i16 // 상위 비트가 1이면 현재 눌린 상태
IsWindow(Option<HWND>) -> BOOL
SendInput(&[INPUT], size_of::<INPUT>() as i32) -> u32 // 실제 전송한 이벤트 수

순서: 클립보드 적재 → 키·마우스 해제 대기(최대 2초, 10ms 간격) → 대상 HWND·PID·thread 재확인 → SetForegroundWindow → 활성화·포커스·키 상태 확인(80ms) → SendInput으로 Ctrl/V 누름·해제 4개 전송 → 성공 때만 창 숨김. 클립보드는 원복하지 않음.

  • SetForegroundWindow 반환 직후에는 대상 활성화가 아직 끝나지 않을 수 있음. 실제 검사에서 약 3ms 뒤 대상이 활성화되는 전환을 관찰함. 첫 활성화 전에는 원래 팔레트나 NULL만 허용하고, 다른 창 또는 활성화 뒤 이탈은 취소함.
  • 이벤트 4개가 전부 전송되지 않으면 오류. 이미 누른 키의 해제만 정리하고 붙여넣기를 재시도하지 않음. 큐 전송 성공과 대상 편집기의 실제 내용 반영은 별개임.
  • paste_codespawn_blocking에서 대기·Win32 작업을 실행하므로 UI 스레드를 막지 않음. 대상 잠금은 스냅샷 복사 때만 사용하며, 진행 중 중복 요청은 바로 거절함.
  • 실패하면 팔레트를 다시 표시하고 오류 안내를 유지. 클립보드 기록 이후 실패에만 원문이 남았다고 안내함.