diff --git a/package.json b/package.json index 29a0691..2e3aecd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vrclipboard-ime-gui", "private": true, - "version": "1.5.0", + "version": "1.6.0", "type": "module", "scripts": { "dev": "vite", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index c10f5f7..7a52ee2 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3866,7 +3866,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vrclipboard-ime-gui" -version = "1.4.0" +version = "1.6.0" dependencies = [ "anyhow", "calc", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9da6a65..3fcf6a7 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "vrclipboard-ime-gui" -version = "1.4.0" +version = "1.6.0" description = "VRClipboard IME" authors = ["mii"] edition = "2021" diff --git a/src-tauri/src/config.rs b/src-tauri/src/config.rs index cc1dcff..ea3a56f 100644 --- a/src-tauri/src/config.rs +++ b/src-tauri/src/config.rs @@ -21,7 +21,9 @@ pub struct Config { #[serde(default)] pub on_copy_mode: OnCopyMode, #[serde(default = "bool_true")] - pub skip_url: bool + pub skip_url: bool, + #[serde(default = "bool_false")] + pub use_tsf_reconvert: bool } impl Default for Config { @@ -31,8 +33,9 @@ impl Default for Config { split: "/".to_string(), command: ";".to_string(), ignore_prefix: true, - on_copy_mode: OnCopyMode::ReturnToChatbox , - skip_url: true + on_copy_mode: OnCopyMode::ReturnToChatbox, + skip_url: true, + use_tsf_reconvert: false } } } @@ -43,6 +46,8 @@ fn slash() -> String { String::from("/") } fn semicolon() -> String { String::from(";") } #[inline] fn bool_true() -> bool { true } +#[inline] +fn bool_false() -> bool { false } #[derive(Debug, Clone, Deserialize, Serialize)] pub enum OnCopyMode { diff --git a/src-tauri/src/handler.rs b/src-tauri/src/handler.rs index eb92062..8651fa1 100644 --- a/src-tauri/src/handler.rs +++ b/src-tauri/src/handler.rs @@ -6,12 +6,13 @@ use clipboard_master::{ClipboardHandler, CallbackResult}; use regex::Regex; use rosc::{encoder, OscMessage, OscPacket, OscType}; use tauri::{AppHandle, Manager}; -use crate::{config::{Config, OnCopyMode}, conversion::Conversion, Log, STATE}; +use crate::{config::{Config, OnCopyMode}, conversion::Conversion, tsf_conversion::TsfConversion, Log, STATE}; use anyhow::Result; pub struct ConversionHandler { app_handle: AppHandle, conversion: Conversion, + tsf_conversion: Option, clipboard_ctx: ClipboardContext, last_text: String, } @@ -19,9 +20,10 @@ pub struct ConversionHandler { impl ConversionHandler { pub fn new(app_handle: AppHandle) -> Result { let conversion = Conversion::new(); + let tsf_conversion = None; let clipboard_ctx = ClipboardProvider::new().unwrap(); - Ok(Self { app_handle, conversion, clipboard_ctx, last_text: String::new() }) + Ok(Self { app_handle, conversion, tsf_conversion, clipboard_ctx, last_text: String::new() }) } pub fn get_config(&self) -> Config { @@ -29,10 +31,28 @@ impl ConversionHandler { } } +impl ConversionHandler { + fn tsf_conversion(&mut self, contents: &str, config: &Config) -> CallbackResult { + if self.tsf_conversion.is_none() { + self.tsf_conversion = Some(TsfConversion::new()); + + println!("TSF conversion created."); + } + + let tsf_conversion = self.tsf_conversion.as_mut().unwrap(); + + CallbackResult::Next + } +} + impl ClipboardHandler for ConversionHandler { fn on_clipboard_change(&mut self) -> CallbackResult { let config = self.get_config(); if let Ok(mut contents) = self.clipboard_ctx.get_contents() { + if config.use_tsf_reconvert { + return self.tsf_conversion(&contents, &config); + } + if contents != self.last_text { if contents.starts_with(&config.prefix) || config.ignore_prefix { diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 6a0a193..3c99c2f 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -9,6 +9,7 @@ mod config; mod converter; mod transform_rule; mod tsf; +mod tsf_conversion; use std::sync::Mutex; diff --git a/src-tauri/src/tsf/function_provider.rs b/src-tauri/src/tsf/function_provider.rs index defe5f0..c2724a5 100644 --- a/src-tauri/src/tsf/function_provider.rs +++ b/src-tauri/src/tsf/function_provider.rs @@ -1,12 +1,11 @@ use anyhow::Result; use windows::{ core::Interface, - Win32::{ - System::Com::{CoCreateInstance, CoInitialize, CoUninitialize, CLSCTX_INPROC_SERVER}, - UI::{Input::KeyboardAndMouse::HKL, TextServices::{CLSID_TF_InputProcessorProfiles, CLSID_TF_ThreadMgr, ITfFnSearchCandidateProvider, ITfFunctionProvider, ITfInputProcessorProfileMgr, ITfThreadMgr2, GUID_TFCAT_TIP_KEYBOARD, TF_INPUTPROCESSORPROFILE, TF_IPPMF_DONTCARECURRENTINPUTLANGUAGE, TF_PROFILETYPE_INPUTPROCESSOR, TF_TMAE_NOACTIVATEKEYBOARDLAYOUT}, WindowsAndMessaging::{SystemParametersInfoW, SPI_SETTHREADLOCALINPUTSETTINGS, SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS}}, - }, + Win32::UI::TextServices::{ITfFnSearchCandidateProvider, ITfFunctionProvider}, }; +use super::search_candidate_provider::SearchCandidateProvider; + pub struct FunctionProvider { function_provider: ITfFunctionProvider, } diff --git a/src-tauri/src/tsf/mod.rs b/src-tauri/src/tsf/mod.rs index c46f938..01a3a4b 100644 --- a/src-tauri/src/tsf/mod.rs +++ b/src-tauri/src/tsf/mod.rs @@ -2,6 +2,9 @@ use anyhow::Result; use windows::Win32::UI::WindowsAndMessaging::{SystemParametersInfoW, SPI_SETTHREADLOCALINPUTSETTINGS, SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS}; pub mod input_processor_profile_mgr; +pub mod function_provider; +pub mod search_candidate_provider; +pub mod thread_mgr; pub fn set_thread_local_input_settings(thread_local_input_settings: bool) -> Result<()> { let mut result = thread_local_input_settings; diff --git a/src-tauri/src/tsf/search_candidate_provider.rs b/src-tauri/src/tsf/search_candidate_provider.rs index 1c5cd9b..48f5abc 100644 --- a/src-tauri/src/tsf/search_candidate_provider.rs +++ b/src-tauri/src/tsf/search_candidate_provider.rs @@ -1,11 +1,7 @@ use anyhow::Result; -use windows::{ - core::Interface, - Win32::{ - System::Com::{CoCreateInstance, CoInitialize, CoUninitialize, CLSCTX_INPROC_SERVER}, - UI::{Input::KeyboardAndMouse::HKL, TextServices::{CLSID_TF_InputProcessorProfiles, CLSID_TF_ThreadMgr, ITfFnSearchCandidateProvider, ITfFunctionProvider, ITfInputProcessorProfileMgr, ITfThreadMgr2, GUID_TFCAT_TIP_KEYBOARD, TF_INPUTPROCESSORPROFILE, TF_IPPMF_DONTCARECURRENTINPUTLANGUAGE, TF_PROFILETYPE_INPUTPROCESSOR, TF_TMAE_NOACTIVATEKEYBOARDLAYOUT}, WindowsAndMessaging::{SystemParametersInfoW, SPI_SETTHREADLOCALINPUTSETTINGS, SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS}}, - }, -}; +use windows::Win32::UI::TextServices::{ITfFnSearchCandidateProvider, TF_TMAE_NOACTIVATEKEYBOARDLAYOUT}; + +use super::{function_provider::FunctionProvider, input_processor_profile_mgr::InputProcessorProfileMgr, thread_mgr::ThreadMgr}; pub struct SearchCandidateProvider { search_candidate_provider: ITfFnSearchCandidateProvider, diff --git a/src-tauri/src/tsf/thread_mgr.rs b/src-tauri/src/tsf/thread_mgr.rs index a8efd07..6f67d99 100644 --- a/src-tauri/src/tsf/thread_mgr.rs +++ b/src-tauri/src/tsf/thread_mgr.rs @@ -1,11 +1,8 @@ use anyhow::Result; -use windows::{ - core::Interface, - Win32::{ - System::Com::{CoCreateInstance, CoInitialize, CoUninitialize, CLSCTX_INPROC_SERVER}, - UI::{Input::KeyboardAndMouse::HKL, TextServices::{CLSID_TF_InputProcessorProfiles, CLSID_TF_ThreadMgr, ITfFnSearchCandidateProvider, ITfFunctionProvider, ITfInputProcessorProfileMgr, ITfThreadMgr2, GUID_TFCAT_TIP_KEYBOARD, TF_INPUTPROCESSORPROFILE, TF_IPPMF_DONTCARECURRENTINPUTLANGUAGE, TF_PROFILETYPE_INPUTPROCESSOR, TF_TMAE_NOACTIVATEKEYBOARDLAYOUT}, WindowsAndMessaging::{SystemParametersInfoW, SPI_SETTHREADLOCALINPUTSETTINGS, SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS}}, - }, -}; +use windows::Win32::{ + System::Com::{CoCreateInstance, CLSCTX_INPROC_SERVER}, + UI::TextServices::{CLSID_TF_ThreadMgr, ITfFunctionProvider, ITfThreadMgr2}, + }; pub struct ThreadMgr { thread_mgr: ITfThreadMgr2, diff --git a/src-tauri/src/tsf_conversion.rs b/src-tauri/src/tsf_conversion.rs new file mode 100644 index 0000000..124e673 --- /dev/null +++ b/src-tauri/src/tsf_conversion.rs @@ -0,0 +1,28 @@ +use anyhow::Result; +use crate::tsf::{search_candidate_provider::SearchCandidateProvider, set_thread_local_input_settings}; + +pub struct TsfConversion { + pub conversion_history: Vec, + pub clipboard_history: Vec, + pub now_reconvertion: bool, + pub target_text: String, + pub search_candidate_provider: SearchCandidateProvider, +} + +impl TsfConversion { + pub fn new() -> Self { + set_thread_local_input_settings(true).unwrap(); + + Self { + conversion_history: Vec::new(), + clipboard_history: Vec::new(), + now_reconvertion: false, + target_text: String::new(), + search_candidate_provider: SearchCandidateProvider::create().unwrap(), + } + } + + pub fn convert(&self, text: &str) -> Result { + Ok(self.search_candidate_provider.get_candidates(text, 10)?[0].clone()) + } +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index e6f1cdd..24ce042 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -7,7 +7,7 @@ }, "package": { "productName": "vrclipboard-ime-gui", - "version": "1.5.0" + "version": "1.6.0" }, "tauri": { "updater": { diff --git a/src/SettingsComponent.tsx b/src/SettingsComponent.tsx index 9c47070..ea8978c 100644 --- a/src/SettingsComponent.tsx +++ b/src/SettingsComponent.tsx @@ -9,6 +9,7 @@ interface Config { ignore_prefix: boolean; on_copy_mode: OnCopyMode; skip_url: boolean; + use_tsf_reconvert: boolean; } enum OnCopyMode { @@ -24,7 +25,8 @@ const SettingsComponent = () => { command: ';', ignore_prefix: false, on_copy_mode: OnCopyMode.ReturnToChatbox, - skip_url: true + skip_url: true, + use_tsf_reconvert: false }); const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); @@ -179,6 +181,19 @@ const SettingsComponent = () => { )} +
+ + +