Merge pull request #121 from Cooper-X-Oak/codex/windows-current-caret-insertion

fix(windows): 粘贴前校验原目标窗口已恢复
This commit is contained in:
TRIP authored and GitHub committed 2026-05-01 19:34:06 +08:00
commit 949c51199f
3 files changed
+55 -12

No files matched your search

@@ -5,6 +5,8 @@ param(
[string]$Phrase = "OpenLess Windows real regression",
[int]$TimeoutSeconds = 120,
[int]$VirtualKey = 0xA3,
[int]$ManualSpeechSeconds = 8,
[switch]$ManualSpeech,
[switch]$DebugHotkeyEvents
)
@@ -356,7 +358,7 @@ try {
$inputTarget = $null
try {
if (-not (Wait-LogPattern $logPath "WH_KEYBOARD_LL installed" 20)) {
if (-not (Wait-LogPattern $logPath "hotkey listener installed|Windows low-level keyboard hook" 20)) {
throw "Windows low-level keyboard hook was not installed."
}
@@ -370,7 +372,12 @@ try {
throw "OpenLess recording session did not start."
}
Speak-TestPhrase $Phrase
if ($ManualSpeech) {
Write-Host "[action] Please speak into the real microphone for $ManualSpeechSeconds seconds."
Start-Sleep -Seconds $ManualSpeechSeconds
} else {
Speak-TestPhrase $Phrase
}
Start-Sleep -Milliseconds 800
Release-Hotkey
@@ -388,8 +395,8 @@ try {
if ([string]::IsNullOrWhiteSpace($latest.rawTranscript) -or [string]::IsNullOrWhiteSpace($latest.finalText)) {
throw "Latest history item is missing rawTranscript or finalText."
}
if (@("copiedFallback", "pasteSent") -notcontains $latest.insertStatus) {
throw "Expected Windows insertStatus copiedFallback or pasteSent, got '$($latest.insertStatus)'."
if ($latest.insertStatus -ne "pasteSent") {
throw "Expected Windows insertStatus pasteSent after guarded foreground restore, got '$($latest.insertStatus)'."
}
Focus-Window $inputTarget.Process | Out-Null
@@ -403,6 +410,9 @@ try {
if ([string]::IsNullOrWhiteSpace($targetText)) {
throw "$Target clipboard readback is empty after Ctrl+A/C."
}
if (-not $targetText.Contains($latest.finalText)) {
throw "$Target readback does not contain latest finalText; insertion was not proven at the target caret."
}
Write-Host "[ok] History updated. raw='$($latest.rawTranscript)'"
Write-Host "[ok] Final text length=$($latest.finalText.Length), insertStatus=$($latest.insertStatus)"
+28 -8
View File
@@ -1276,9 +1276,16 @@ async fn end_session(inner: &Arc<Inner>) -> Result<(), String> {
}
let focus_target = inner.state.lock().focus_target;
restore_focus_target_if_possible(focus_target);
let focus_ready_for_paste = restore_focus_target_if_possible(focus_target);
let restore_clipboard = inner.prefs.get().restore_clipboard_after_paste;
let status = inner.inserter.insert(&polished, restore_clipboard);
let status = if focus_ready_for_paste {
inner.inserter.insert(&polished, restore_clipboard)
} else {
log::warn!(
"[coord] original insertion target is not foreground; copied output without paste"
);
inner.inserter.copy_fallback(&polished)
};
let inserted_chars = polished.chars().count() as u32;
// 累计每条 enabled 词条在最终文本中的命中次数。
@@ -2338,7 +2345,7 @@ fn capture_frontmost_app() -> Option<String> {
}
#[cfg(target_os = "windows")]
fn restore_focus_target_if_possible(target: Option<usize>) {
fn restore_focus_target_if_possible(target: Option<usize>) -> bool {
use std::ffi::c_void;
use std::time::Duration;
use windows::Win32::Foundation::HWND;
@@ -2346,18 +2353,22 @@ fn restore_focus_target_if_possible(target: Option<usize>) {
GetForegroundWindow, IsIconic, IsWindow, SetForegroundWindow, ShowWindow, SW_RESTORE,
};
let Some(raw_target) = target else { return };
let Some(raw_target) = target else {
log::warn!("[coord] no original Windows insertion target captured");
return false;
};
let hwnd = HWND(raw_target as *mut c_void);
if hwnd.0.is_null() {
return;
return false;
}
if !unsafe { IsWindow(hwnd).as_bool() } {
return;
log::warn!("[coord] original Windows insertion target is no longer a valid window");
return false;
}
let foreground = unsafe { GetForegroundWindow() };
if foreground == hwnd {
return;
return true;
}
if unsafe { IsIconic(hwnd).as_bool() } {
@@ -2365,10 +2376,19 @@ fn restore_focus_target_if_possible(target: Option<usize>) {
}
let _ = unsafe { SetForegroundWindow(hwnd) };
std::thread::sleep(Duration::from_millis(60));
let foreground = unsafe { GetForegroundWindow() };
if foreground != hwnd {
log::warn!("[coord] failed to restore original Windows insertion target before paste");
return false;
}
true
}
#[cfg(not(target_os = "windows"))]
fn restore_focus_target_if_possible(_target: Option<usize>) {}
fn restore_focus_target_if_possible(_target: Option<usize>) -> bool {
true
}
#[cfg(target_os = "windows")]
fn show_capsule_window_no_activate() -> bool {
@@ -50,6 +50,19 @@ impl TextInserter {
}
insertion_success_status()
}
/// Copy text without attempting a synthetic paste. Used when the platform cannot
/// prove the original input target is active enough to safely receive Ctrl/Cmd+V.
pub fn copy_fallback(&self, text: &str) -> InsertStatus {
if text.is_empty() {
return InsertStatus::CopiedFallback;
}
if copy_to_clipboard(text) {
InsertStatus::CopiedFallback
} else {
InsertStatus::Failed
}
}
}
impl Default for TextInserter {