Skip to content

Commit 069da6d

Browse files
committed
perf: Optimize Windows get selection text
1 parent 1ef997b commit 069da6d

File tree

2 files changed

+60
-4
lines changed

2 files changed

+60
-4
lines changed

src-tauri/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ dirs = "5.0.0"
2727
dunce = "1.0.4"
2828

2929
[target.'cfg(windows)'.dependencies]
30-
windows = {version="0.44.0",features= ["Win32_UI_WindowsAndMessaging", "Win32_Foundation","Win32_System_Threading","Win32_UI_Input_KeyboardAndMouse","Win32_System_DataExchange"] }
30+
windows = {version="0.44.0",features= ["Win32_UI_WindowsAndMessaging", "Win32_Foundation","Win32_System_Threading","Win32_UI_Input_KeyboardAndMouse","Win32_System_DataExchange","Win32_UI_Accessibility","Win32_System_Com"] }
3131
window-shadows = "0.2"
3232
arboard = "3.2.0"
3333

src-tauri/src/selection.rs

+59-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::StringWrapper;
22

33
#[cfg(target_os = "linux")]
4-
pub fn get_selection_text_on_x11() -> Result<String, String> {
4+
fn get_selection_text_on_x11() -> Result<String, String> {
55
use crate::APP;
66
use std::time::Duration;
77
use tauri::Manager;
@@ -48,7 +48,7 @@ pub fn get_selection_text_on_x11() -> Result<String, String> {
4848
}
4949

5050
#[cfg(target_os = "linux")]
51-
pub fn get_selection_text_on_wayland() -> Result<String, String> {
51+
fn get_selection_text_on_wayland() -> Result<String, String> {
5252
use std::io::Read;
5353
use wl_clipboard_rs::paste::{get_contents, ClipboardType, Error, MimeType, Seat};
5454
use wl_clipboard_rs::utils::is_primary_selection_supported;
@@ -107,11 +107,67 @@ pub fn get_selection_text() -> Result<String, String> {
107107
}
108108
}
109109

110+
#[cfg(target_os = "windows")]
111+
fn get_selection_text_by_automation() -> Result<String, String> {
112+
use windows::Win32::System::Com::{CoCreateInstance, CoInitialize, CLSCTX_ALL};
113+
use windows::Win32::UI::Accessibility::{
114+
CUIAutomation, IUIAutomation, IUIAutomationTextPattern, UIA_TextPatternId,
115+
};
116+
// 初始化 COM
117+
match unsafe { CoInitialize(None) } {
118+
Ok(_) => {}
119+
Err(e) => return Err(e.to_string()),
120+
};
121+
// 创建 IUIAutomation 对象
122+
let auto: IUIAutomation = match unsafe { CoCreateInstance(&CUIAutomation, None, CLSCTX_ALL) } {
123+
Ok(v) => v,
124+
Err(e) => return Err(e.to_string()),
125+
};
126+
// 获取焦点元素
127+
let el = match unsafe { auto.GetFocusedElement() } {
128+
Ok(v) => v,
129+
Err(e) => return Err(e.to_string()),
130+
};
131+
// 获取文本对象
132+
let res: IUIAutomationTextPattern = match unsafe { el.GetCurrentPatternAs(UIA_TextPatternId) } {
133+
Ok(v) => v,
134+
Err(e) => return Err(e.to_string()),
135+
};
136+
// 获取文本序列
137+
let text_array = match unsafe { res.GetSelection() } {
138+
Ok(v) => v,
139+
Err(e) => return Err(e.to_string()),
140+
};
141+
let length = unsafe { text_array.Length().unwrap() };
142+
// 遍历文本序列
143+
let mut target = String::new();
144+
for i in 0..length {
145+
let text = match unsafe { text_array.GetElement(i) } {
146+
Ok(v) => v,
147+
Err(e) => return Err(e.to_string()),
148+
};
149+
let str = match unsafe { text.GetText(-1) } {
150+
Ok(v) => v,
151+
Err(e) => return Err(e.to_string()),
152+
};
153+
let str = str.to_string();
154+
target.push_str(&str);
155+
}
156+
Ok(target)
157+
}
158+
110159
// 获取选择的文本(Windows)
111160
#[cfg(target_os = "windows")]
112161
pub fn get_selection_text() -> Result<String, String> {
162+
if let Ok(text) = get_selection_text_by_automation() {
163+
if !text.is_empty() {
164+
println!("get_selection_text_by_automation");
165+
return Ok(text);
166+
}
167+
}
168+
// Automation取词失败后再尝试获取剪切板
113169
use arboard::Clipboard;
114-
170+
println!("get_selection_text_by_clipboard");
115171
// 读取旧的剪切板
116172
let old_clipboard = (
117173
Clipboard::new().unwrap().get_text(),

0 commit comments

Comments
 (0)