Add engine and connecting between layers
This commit is contained in:
parent
c0cd826b45
commit
0c860c0b5f
|
@ -199,5 +199,30 @@ void send_string(const wchar_t * string) {
|
|||
vec.push_back(input);
|
||||
}
|
||||
|
||||
SendInput(vec.size(), vec.data(), sizeof(INPUT));
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the backspace keypress, *count* times.
|
||||
*/
|
||||
void delete_string(int32_t count) {
|
||||
std::vector<INPUT> vec;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
INPUT input = { 0 };
|
||||
|
||||
input.type = INPUT_KEYBOARD;
|
||||
input.ki.wScan = 0;
|
||||
input.ki.time = 0;
|
||||
input.ki.dwExtraInfo = 0;
|
||||
input.ki.wVk = VK_BACK;
|
||||
input.ki.dwFlags = 0; // 0 for key press
|
||||
vec.push_back(input);
|
||||
|
||||
// Release the "A" key
|
||||
input.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
|
||||
vec.push_back(input);
|
||||
}
|
||||
|
||||
SendInput(vec.size(), vec.data(), sizeof(INPUT));
|
||||
}
|
|
@ -34,4 +34,9 @@ extern "C" void eventloop();
|
|||
*/
|
||||
extern "C" void send_string(const wchar_t * string);
|
||||
|
||||
/*
|
||||
* Send the backspace keypress, *count* times.
|
||||
*/
|
||||
extern "C" void delete_string(int32_t count);
|
||||
|
||||
#endif //ESPANSO_BRIDGE_H
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
use crate::matcher::{Match, MatchReceiver};
|
||||
use crate::keyboard::KeyboardSender;
|
||||
|
||||
pub struct Engine<'a>{
|
||||
sender: &'a KeyboardSender
|
||||
}
|
||||
|
||||
impl <'a> Engine<'a> {
|
||||
pub fn new(sender: &'a KeyboardSender) -> Engine<'a> {
|
||||
Engine{sender}
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a> MatchReceiver for Engine<'a>{
|
||||
fn on_match(&self, m: Match) {
|
||||
self.sender.delete_string(m.trigger.len() as i32);
|
||||
self.sender.send_string(m.result.as_str());
|
||||
}
|
||||
}
|
|
@ -10,9 +10,15 @@ pub trait KeyboardInterceptor {
|
|||
|
||||
pub trait KeyboardSender {
|
||||
fn send_string(&self, s: &str);
|
||||
fn delete_string(&self, count: i32);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn get_backend(sender: mpsc::Sender<char>) -> (impl KeyboardInterceptor, impl KeyboardSender) {
|
||||
(windows::WindowsKeyboardInterceptor {sender}, windows::WindowsKeyboardSender{})
|
||||
pub fn get_interceptor(sender: mpsc::Sender<char>) -> impl KeyboardInterceptor {
|
||||
windows::WindowsKeyboardInterceptor {sender}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn get_sender() -> impl KeyboardSender {
|
||||
windows::WindowsKeyboardSender{}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use std::thread;
|
||||
use std::sync::mpsc;
|
||||
use widestring::{WideString, WideStr};
|
||||
use widestring::{U16CString};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct WindowsKeyboardInterceptor {
|
||||
|
@ -29,9 +29,21 @@ pub struct WindowsKeyboardSender {
|
|||
|
||||
impl super::KeyboardSender for WindowsKeyboardSender {
|
||||
fn send_string(&self, s: &str) {
|
||||
let s = WideString::from(s.to_owned());
|
||||
let res = U16CString::from_str(s);
|
||||
match res {
|
||||
Ok(s) => {
|
||||
unsafe {
|
||||
send_string(s.as_ptr());
|
||||
}
|
||||
}
|
||||
Err(e) => println!("Error while sending string: {}", e.to_string())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn delete_string(&self, count: i32) {
|
||||
unsafe {
|
||||
send_string(s.as_ptr());
|
||||
delete_string(count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,10 +61,12 @@ extern fn keypress_callback(_self: *mut WindowsKeyboardInterceptor, raw_buffer:
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(improper_ctypes)]
|
||||
#[link(name="winbridge", kind="static")]
|
||||
extern {
|
||||
fn register_keypress_callback(s: *const WindowsKeyboardInterceptor, cb: extern fn(_self: *mut WindowsKeyboardInterceptor, *const i32, i32));
|
||||
fn initialize_window();
|
||||
fn eventloop();
|
||||
fn send_string(string: *const u16);
|
||||
fn delete_string(count: i32);
|
||||
}
|
20
src/main.rs
20
src/main.rs
|
@ -1,22 +1,26 @@
|
|||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use std::sync::mpsc;
|
||||
use crate::keyboard::KeyboardInterceptor;
|
||||
use crate::keyboard::KeyboardSender;
|
||||
use crate::matcher::Matcher;
|
||||
use crate::matcher::scrolling::ScrollingMatcher;
|
||||
use crate::engine::Engine;
|
||||
|
||||
mod keyboard;
|
||||
mod matcher;
|
||||
mod engine;
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world from Rust!");
|
||||
println!("espanso is running!");
|
||||
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
let (txc, rxc) = mpsc::channel();
|
||||
|
||||
let (interceptor, sender) = keyboard::get_backend(sender);
|
||||
let interceptor = keyboard::get_interceptor(txc);
|
||||
interceptor.initialize();
|
||||
interceptor.start();
|
||||
|
||||
let matcher = Matcher{receiver};
|
||||
matcher.watch();
|
||||
let sender = keyboard::get_sender();
|
||||
|
||||
let engine = Engine::new(&sender);
|
||||
|
||||
let matcher = ScrollingMatcher::new(&engine);
|
||||
matcher.watch(&rxc);
|
||||
}
|
|
@ -1,24 +1,25 @@
|
|||
use std::sync::mpsc::Receiver;
|
||||
|
||||
pub(crate) mod scrolling;
|
||||
|
||||
pub struct Match {
|
||||
pub trigger: String,
|
||||
pub result: String
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub struct Matcher {
|
||||
pub receiver: Receiver<char>
|
||||
pub trait MatchReceiver {
|
||||
fn on_match(&self, m: Match);
|
||||
}
|
||||
|
||||
impl Matcher {
|
||||
pub fn watch(&self) {
|
||||
pub trait Matcher {
|
||||
fn handle_char(&self, c: char);
|
||||
fn watch(&self, receiver: &Receiver<char>) {
|
||||
loop {
|
||||
match self.receiver.recv() {
|
||||
match receiver.recv() {
|
||||
Ok(c) => {
|
||||
println!("Yeah {}",c);
|
||||
self.handle_char(c);
|
||||
},
|
||||
Err(_) => panic!("Worker threads disconnected before the solution was found!"),
|
||||
Err(_) => panic!("Keyboard interceptor broke receiver stream."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
use crate::matcher::{Match, MatchReceiver};
|
||||
|
||||
pub struct ScrollingMatcher<'a>{
|
||||
receiver: &'a MatchReceiver
|
||||
}
|
||||
|
||||
impl <'a> super::Matcher for ScrollingMatcher<'a> {
|
||||
fn handle_char(&self, c: char) {
|
||||
println!("Scroll {}",c);
|
||||
|
||||
if c == 'a' {
|
||||
self.receiver.on_match(Match{trigger: "a".to_owned(), result: "ciao".to_owned()});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a> ScrollingMatcher<'a> {
|
||||
pub fn new(receiver: &'a MatchReceiver) -> ScrollingMatcher<'a> {
|
||||
ScrollingMatcher{ receiver }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user