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);
|
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));
|
SendInput(vec.size(), vec.data(), sizeof(INPUT));
|
||||||
}
|
}
|
|
@ -34,4 +34,9 @@ extern "C" void eventloop();
|
||||||
*/
|
*/
|
||||||
extern "C" void send_string(const wchar_t * string);
|
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
|
#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 {
|
pub trait KeyboardSender {
|
||||||
fn send_string(&self, s: &str);
|
fn send_string(&self, s: &str);
|
||||||
|
fn delete_string(&self, count: i32);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub fn get_backend(sender: mpsc::Sender<char>) -> (impl KeyboardInterceptor, impl KeyboardSender) {
|
pub fn get_interceptor(sender: mpsc::Sender<char>) -> impl KeyboardInterceptor {
|
||||||
(windows::WindowsKeyboardInterceptor {sender}, windows::WindowsKeyboardSender{})
|
windows::WindowsKeyboardInterceptor {sender}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub fn get_sender() -> impl KeyboardSender {
|
||||||
|
windows::WindowsKeyboardSender{}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use widestring::{WideString, WideStr};
|
use widestring::{U16CString};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct WindowsKeyboardInterceptor {
|
pub struct WindowsKeyboardInterceptor {
|
||||||
|
@ -29,9 +29,21 @@ pub struct WindowsKeyboardSender {
|
||||||
|
|
||||||
impl super::KeyboardSender for WindowsKeyboardSender {
|
impl super::KeyboardSender for WindowsKeyboardSender {
|
||||||
fn send_string(&self, s: &str) {
|
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 {
|
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")]
|
#[link(name="winbridge", kind="static")]
|
||||||
extern {
|
extern {
|
||||||
fn register_keypress_callback(s: *const WindowsKeyboardInterceptor, cb: extern fn(_self: *mut WindowsKeyboardInterceptor, *const i32, i32));
|
fn register_keypress_callback(s: *const WindowsKeyboardInterceptor, cb: extern fn(_self: *mut WindowsKeyboardInterceptor, *const i32, i32));
|
||||||
fn initialize_window();
|
fn initialize_window();
|
||||||
fn eventloop();
|
fn eventloop();
|
||||||
fn send_string(string: *const u16);
|
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 std::sync::mpsc;
|
||||||
use crate::keyboard::KeyboardInterceptor;
|
use crate::keyboard::KeyboardInterceptor;
|
||||||
use crate::keyboard::KeyboardSender;
|
|
||||||
use crate::matcher::Matcher;
|
use crate::matcher::Matcher;
|
||||||
|
use crate::matcher::scrolling::ScrollingMatcher;
|
||||||
|
use crate::engine::Engine;
|
||||||
|
|
||||||
mod keyboard;
|
mod keyboard;
|
||||||
mod matcher;
|
mod matcher;
|
||||||
|
mod engine;
|
||||||
|
|
||||||
fn main() {
|
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.initialize();
|
||||||
interceptor.start();
|
interceptor.start();
|
||||||
|
|
||||||
let matcher = Matcher{receiver};
|
let sender = keyboard::get_sender();
|
||||||
matcher.watch();
|
|
||||||
|
let engine = Engine::new(&sender);
|
||||||
|
|
||||||
|
let matcher = ScrollingMatcher::new(&engine);
|
||||||
|
matcher.watch(&rxc);
|
||||||
}
|
}
|
|
@ -1,24 +1,25 @@
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::Receiver;
|
||||||
|
|
||||||
|
pub(crate) mod scrolling;
|
||||||
|
|
||||||
pub struct Match {
|
pub struct Match {
|
||||||
pub trigger: String,
|
pub trigger: String,
|
||||||
pub result: String
|
pub result: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait MatchReceiver {
|
||||||
|
fn on_match(&self, m: Match);
|
||||||
pub struct Matcher {
|
|
||||||
pub receiver: Receiver<char>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Matcher {
|
pub trait Matcher {
|
||||||
pub fn watch(&self) {
|
fn handle_char(&self, c: char);
|
||||||
|
fn watch(&self, receiver: &Receiver<char>) {
|
||||||
loop {
|
loop {
|
||||||
match self.receiver.recv() {
|
match receiver.recv() {
|
||||||
Ok(c) => {
|
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