add tsf conversion

This commit is contained in:
mii443
2024-09-23 01:33:02 +09:00
parent 1ff9f0ce1b
commit 6afedc2ea8
13 changed files with 92 additions and 28 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "vrclipboard-ime-gui", "name": "vrclipboard-ime-gui",
"private": true, "private": true,
"version": "1.5.0", "version": "1.6.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

2
src-tauri/Cargo.lock generated
View File

@ -3866,7 +3866,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "vrclipboard-ime-gui" name = "vrclipboard-ime-gui"
version = "1.4.0" version = "1.6.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"calc", "calc",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "vrclipboard-ime-gui" name = "vrclipboard-ime-gui"
version = "1.4.0" version = "1.6.0"
description = "VRClipboard IME" description = "VRClipboard IME"
authors = ["mii"] authors = ["mii"]
edition = "2021" edition = "2021"

View File

@ -21,7 +21,9 @@ pub struct Config {
#[serde(default)] #[serde(default)]
pub on_copy_mode: OnCopyMode, pub on_copy_mode: OnCopyMode,
#[serde(default = "bool_true")] #[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 { impl Default for Config {
@ -31,8 +33,9 @@ impl Default for Config {
split: "/".to_string(), split: "/".to_string(),
command: ";".to_string(), command: ";".to_string(),
ignore_prefix: true, ignore_prefix: true,
on_copy_mode: OnCopyMode::ReturnToChatbox , on_copy_mode: OnCopyMode::ReturnToChatbox,
skip_url: true skip_url: true,
use_tsf_reconvert: false
} }
} }
} }
@ -43,6 +46,8 @@ fn slash() -> String { String::from("/") }
fn semicolon() -> String { String::from(";") } fn semicolon() -> String { String::from(";") }
#[inline] #[inline]
fn bool_true() -> bool { true } fn bool_true() -> bool { true }
#[inline]
fn bool_false() -> bool { false }
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub enum OnCopyMode { pub enum OnCopyMode {

View File

@ -6,12 +6,13 @@ use clipboard_master::{ClipboardHandler, CallbackResult};
use regex::Regex; use regex::Regex;
use rosc::{encoder, OscMessage, OscPacket, OscType}; use rosc::{encoder, OscMessage, OscPacket, OscType};
use tauri::{AppHandle, Manager}; 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; use anyhow::Result;
pub struct ConversionHandler { pub struct ConversionHandler {
app_handle: AppHandle, app_handle: AppHandle,
conversion: Conversion, conversion: Conversion,
tsf_conversion: Option<TsfConversion>,
clipboard_ctx: ClipboardContext, clipboard_ctx: ClipboardContext,
last_text: String, last_text: String,
} }
@ -19,9 +20,10 @@ pub struct ConversionHandler {
impl ConversionHandler { impl ConversionHandler {
pub fn new(app_handle: AppHandle) -> Result<Self> { pub fn new(app_handle: AppHandle) -> Result<Self> {
let conversion = Conversion::new(); let conversion = Conversion::new();
let tsf_conversion = None;
let clipboard_ctx = ClipboardProvider::new().unwrap(); 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 { 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 { impl ClipboardHandler for ConversionHandler {
fn on_clipboard_change(&mut self) -> CallbackResult { fn on_clipboard_change(&mut self) -> CallbackResult {
let config = self.get_config(); let config = self.get_config();
if let Ok(mut contents) = self.clipboard_ctx.get_contents() { 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 != self.last_text {
if contents.starts_with(&config.prefix) || config.ignore_prefix { if contents.starts_with(&config.prefix) || config.ignore_prefix {

View File

@ -9,6 +9,7 @@ mod config;
mod converter; mod converter;
mod transform_rule; mod transform_rule;
mod tsf; mod tsf;
mod tsf_conversion;
use std::sync::Mutex; use std::sync::Mutex;

View File

@ -1,12 +1,11 @@
use anyhow::Result; use anyhow::Result;
use windows::{ use windows::{
core::Interface, core::Interface,
Win32::{ Win32::UI::TextServices::{ITfFnSearchCandidateProvider, ITfFunctionProvider},
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 super::search_candidate_provider::SearchCandidateProvider;
pub struct FunctionProvider { pub struct FunctionProvider {
function_provider: ITfFunctionProvider, function_provider: ITfFunctionProvider,
} }

View File

@ -2,6 +2,9 @@ use anyhow::Result;
use windows::Win32::UI::WindowsAndMessaging::{SystemParametersInfoW, SPI_SETTHREADLOCALINPUTSETTINGS, SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS}; use windows::Win32::UI::WindowsAndMessaging::{SystemParametersInfoW, SPI_SETTHREADLOCALINPUTSETTINGS, SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS};
pub mod input_processor_profile_mgr; 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<()> { pub fn set_thread_local_input_settings(thread_local_input_settings: bool) -> Result<()> {
let mut result = thread_local_input_settings; let mut result = thread_local_input_settings;

View File

@ -1,11 +1,7 @@
use anyhow::Result; use anyhow::Result;
use windows::{ use windows::Win32::UI::TextServices::{ITfFnSearchCandidateProvider, TF_TMAE_NOACTIVATEKEYBOARDLAYOUT};
core::Interface,
Win32::{ use super::{function_provider::FunctionProvider, input_processor_profile_mgr::InputProcessorProfileMgr, thread_mgr::ThreadMgr};
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}},
},
};
pub struct SearchCandidateProvider { pub struct SearchCandidateProvider {
search_candidate_provider: ITfFnSearchCandidateProvider, search_candidate_provider: ITfFnSearchCandidateProvider,

View File

@ -1,11 +1,8 @@
use anyhow::Result; use anyhow::Result;
use windows::{ use windows::Win32::{
core::Interface, System::Com::{CoCreateInstance, CLSCTX_INPROC_SERVER},
Win32::{ UI::TextServices::{CLSID_TF_ThreadMgr, ITfFunctionProvider, ITfThreadMgr2},
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}},
},
};
pub struct ThreadMgr { pub struct ThreadMgr {
thread_mgr: ITfThreadMgr2, thread_mgr: ITfThreadMgr2,

View File

@ -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<String>,
pub clipboard_history: Vec<String>,
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<String> {
Ok(self.search_candidate_provider.get_candidates(text, 10)?[0].clone())
}
}

View File

@ -7,7 +7,7 @@
}, },
"package": { "package": {
"productName": "vrclipboard-ime-gui", "productName": "vrclipboard-ime-gui",
"version": "1.5.0" "version": "1.6.0"
}, },
"tauri": { "tauri": {
"updater": { "updater": {

View File

@ -9,6 +9,7 @@ interface Config {
ignore_prefix: boolean; ignore_prefix: boolean;
on_copy_mode: OnCopyMode; on_copy_mode: OnCopyMode;
skip_url: boolean; skip_url: boolean;
use_tsf_reconvert: boolean;
} }
enum OnCopyMode { enum OnCopyMode {
@ -24,7 +25,8 @@ const SettingsComponent = () => {
command: ';', command: ';',
ignore_prefix: false, ignore_prefix: false,
on_copy_mode: OnCopyMode.ReturnToChatbox, on_copy_mode: OnCopyMode.ReturnToChatbox,
skip_url: true skip_url: true,
use_tsf_reconvert: false
}); });
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null); const dropdownRef = useRef<HTMLDivElement>(null);
@ -179,6 +181,19 @@ const SettingsComponent = () => {
</div> </div>
)} )}
</div> </div>
<div className="flex items-center">
<input
type="checkbox"
id="use_tsf_reconvert"
name="use_tsf_reconvert"
checked={settings.use_tsf_reconvert}
onChange={handleChange}
className="mr-2"
/>
<label htmlFor="use_tsf_reconvert" className="text-sm font-medium text-gray-700">
ベータ機能: Text Services Framework 使
</label>
</div>
<button <button
onClick={saveSettings} onClick={saveSettings}
className="bg-blue-500 text-white px-4 py-2 rounded-md hover:bg-blue-600 transition-colors" className="bg-blue-500 text-white px-4 py-2 rounded-md hover:bg-blue-600 transition-colors"