Skip to content

Commit

Permalink
feat: use get-selected-text (#1507)
Browse files Browse the repository at this point in the history
  • Loading branch information
yetone committed May 4, 2024
1 parent be362ac commit 420b6aa
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 175 deletions.
57 changes: 41 additions & 16 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,16 @@ futures-util = "0.3.29"
tauri-plugin-aptabase = { git = "https://github.com/aptabase/tauri-plugin-aptabase", branch = "v2" }
screenshots = "0.7.2"
image = "0.24.7"
get-selected-text = "0.1.0"

[target.'cfg(target_os = "macos")'.dependencies]
cocoa = "0.24"
objc = "0.2.7"
macos-accessibility-client = "0.0.1"
core-foundation = "0.9.3"
core-graphics = "0.22.3"
accessibility = { git = "https://github.com/yetone/accessibility", branch = "sync" }
accessibility-sys = "0.1.3"
accessibility-ng = "0.1.6"
accessibility-sys-ng = "0.1.3"

[target.'cfg(windows)'.dependencies]
windows = {version="0.54.0",features= ["Win32_UI_WindowsAndMessaging", "Win32_Foundation", "Graphics_Imaging", "Media_Ocr", "Foundation", "Foundation_Collections", "Globalization", "Storage", "Storage_Streams"] }
Expand Down
5 changes: 3 additions & 2 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ mod writing;

use config::get_config;
use debug_print::debug_println;
use get_selected_text::get_selected_text;
use parking_lot::Mutex;
use serde_json::json;
use std::env;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::atomic::AtomicBool;
use sysinfo::{CpuExt, System, SystemExt};
use tauri_plugin_aptabase::EventTracker;
use tauri_plugin_autostart::MacosLauncher;
Expand Down Expand Up @@ -240,7 +241,7 @@ fn bind_mouse_hook() {
}

let _lock = RELEASE_THREAD_ID.lock();
let selected_text = utils::get_selected_text().unwrap_or_default();
let selected_text = get_selected_text().unwrap_or_default();
if !selected_text.is_empty() {
{
*SELECTED_TEXT.lock() = selected_text;
Expand Down
144 changes: 3 additions & 141 deletions src-tauri/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[cfg(target_os = "macos")]
use accessibility_sys::{kAXErrorSuccess, AXError};
use accessibility_sys_ng::{kAXErrorSuccess, AXError};
#[cfg(target_os = "macos")]
use core_graphics::geometry::CGRect;
use enigo::*;
Expand Down Expand Up @@ -273,12 +273,6 @@ pub fn paste(enigo: &mut Enigo) {
enigo.key_up(Key::Control);
}

#[cfg(not(target_os = "macos"))]
pub fn get_selected_text() -> Result<String, Box<dyn std::error::Error>> {
let mut enigo = Enigo::new();
get_selected_text_by_clipboard(&mut enigo, false)
}

pub fn get_selected_text_by_clipboard(
enigo: &mut Enigo,
cancel_select: bool,
Expand Down Expand Up @@ -348,34 +342,6 @@ pub fn get_selected_text_by_clipboard(
}
}

#[cfg(target_os = "macos")]
pub fn get_selected_text() -> Result<String, Box<dyn std::error::Error>> {
use crate::config::get_config;

match get_selected_text_by_ax() {
Ok(text) => Ok(text),
Err(err) => {
println!("get_selected_text_by_ax error: {}", err);
match get_config() {
Ok(config) => {
if config
.allow_using_clipboard_when_selected_text_not_available
.unwrap_or(false)
{
get_selected_text_by_clipboard_using_applescript()
} else {
Ok(String::new())
}
}
Err(err) => {
println!("get_config error: {}", err);
Ok(String::new())
}
}
}
}
}

#[cfg(target_os = "macos")]
unsafe fn ax_call<F, V>(f: F) -> Result<V, AXError>
where
Expand All @@ -393,8 +359,8 @@ where

#[cfg(target_os = "macos")]
unsafe fn get_selected_text_frame_by_ax() -> Result<CGRect, Box<dyn std::error::Error>> {
use accessibility::{AXAttribute, AXUIElement, AXValue};
use accessibility_sys::{
use accessibility_ng::{AXAttribute, AXUIElement, AXValue};
use accessibility_sys_ng::{
kAXBoundsForRangeParameterizedAttribute, kAXFocusedUIElementAttribute,
kAXSelectedTextRangeAttribute,
};
Expand Down Expand Up @@ -481,110 +447,6 @@ pub fn is_valid_selected_frame() -> Result<bool, Box<dyn std::error::Error>> {
}
}

#[cfg(target_os = "macos")]
pub fn get_selected_text_by_ax() -> Result<String, Box<dyn std::error::Error>> {
use accessibility::{AXAttribute, AXUIElement};
use accessibility_sys::{kAXFocusedUIElementAttribute, kAXSelectedTextAttribute};
use core_foundation::string::CFString;

let system_element = AXUIElement::system_wide();
let Some(selected_element) = system_element
.attribute(&AXAttribute::new(&CFString::from_static_string(
kAXFocusedUIElementAttribute,
)))
.map(|element| element.downcast_into::<AXUIElement>())
.ok()
.flatten()
else {
return Err(Box::new(std::io::Error::new(
std::io::ErrorKind::NotFound,
"No selected element",
)));
};
let Some(selected_text) = selected_element
.attribute(&AXAttribute::new(&CFString::from_static_string(
kAXSelectedTextAttribute,
)))
.map(|text| text.downcast_into::<CFString>())
.ok()
.flatten()
else {
return Err(Box::new(std::io::Error::new(
std::io::ErrorKind::NotFound,
"No selected text",
)));
};
Ok(selected_text.to_string())
}

const APPLE_SCRIPT: &str = r#"
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
tell application "System Events"
set frontmostProcess to first process whose frontmost is true
set appName to name of frontmostProcess
end tell
if appName is equal to "OpenAI Translator" then
return
end if
set savedAlertVolume to alert volume of (get volume settings)
-- Back up clipboard contents:
set savedClipboard to the clipboard
set thePasteboard to current application's NSPasteboard's generalPasteboard()
set theCount to thePasteboard's changeCount()
tell application "System Events"
set volume alert volume 0
end tell
-- Copy selected text to clipboard:
tell application "System Events" to keystroke "c" using {command down}
delay 0.1 -- Without this, the clipboard may have stale data.
tell application "System Events"
set volume alert volume savedAlertVolume
end tell
if thePasteboard's changeCount() is theCount then
return ""
end if
set theSelectedText to the clipboard
set the clipboard to savedClipboard
theSelectedText
"#;

#[cfg(target_os = "macos")]
pub fn get_selected_text_by_clipboard_using_applescript(
) -> Result<String, Box<dyn std::error::Error>> {
let output = std::process::Command::new("osascript")
.arg("-e")
.arg(APPLE_SCRIPT)
.output()?;
if output.status.success() {
let content = String::from_utf8(output.stdout)?;
let content = content.trim();
Ok(content.to_string())
} else {
let err = output
.stderr
.into_iter()
.map(|c| c as char)
.collect::<String>()
.into();
Err(err)
}
}

pub fn send_text(text: String) {
match APP_HANDLE.get() {
Some(handle) => handle.emit("change-text", text).unwrap_or_default(),
Expand Down
4 changes: 2 additions & 2 deletions src-tauri/src/windows.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::config;
use crate::config::get_config;
use crate::utils;
use crate::UpdateResult;
use crate::ALWAYS_ON_TOP;
Expand All @@ -8,6 +7,7 @@ use crate::APP_HANDLE;
use cocoa::appkit::NSWindow;
use debug_print::debug_println;
use enigo::*;
use get_selected_text::get_selected_text;
use mouse_position::mouse_position::Mouse;
use serde_json::json;
use std::sync::atomic::Ordering;
Expand Down Expand Up @@ -124,7 +124,7 @@ pub async fn show_translator_window_with_selected_text_command() {
}
};
} else {
selected_text = match utils::get_selected_text() {
selected_text = match get_selected_text() {
Ok(text) => text,
Err(e) => {
eprintln!("Error getting selected text: {}", e);
Expand Down
12 changes: 0 additions & 12 deletions src/common/components/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2718,18 +2718,6 @@ export function InnerSettings({
>
<AlwaysShowIconsCheckbox onBlur={onBlur} />
</FormItem>
<FormItem
style={{
display: isDesktopApp && isMacOS ? 'block' : 'none',
}}
name='allowUsingClipboardWhenSelectedTextNotAvailable'
label={t('Using clipboard')}
caption={t(
'Allow using the clipboard to get the selected text when the selected text is not available'
)}
>
<MyCheckbox onBlur={onBlur} />
</FormItem>
<FormItem name='autoTranslate' label={t('Auto Translate')}>
<AutoTranslateCheckbox onBlur={onBlur} />
</FormItem>
Expand Down

0 comments on commit 420b6aa

Please sign in to comment.