Skip to content

Commit 9e85dfd

Browse files
authored
refactor: rdev -> monio (#51)
* refactor: rdev -> monio
1 parent 3c5765b commit 9e85dfd

6 files changed

Lines changed: 59 additions & 71 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.0.1"
44
edition = "2024"
55

66
[dependencies]
7-
rdev = {version = "0.5.3", features = ["unstable_grab"]}
7+
monio = "0.1.1"
88
toml = "1.1.2"
99
serde = { version = "1.0.228", features = ["derive"] }
1010
accessibility = "0.2.0"

src/app_engine/interaction.rs

Lines changed: 30 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,23 @@ use accessibility::{AXUIElement, AXUIElementActions, AXUIElementAttributes};
99
use accessibility_sys::{
1010
kAXErrorAttributeUnsupported, kAXErrorCannotComplete, kAXFocusedAttribute,
1111
};
12-
use core_foundation::{base::TCFType, boolean::CFBoolean, number::CFNumber};
12+
use core_foundation::{base::TCFType, boolean::CFBoolean, number::CFNumber, string::CFString};
1313
use log::Level;
14-
use objc2_app_kit::NSEvent;
15-
use rdev::{Button, EventType, simulate};
16-
use std::time::Duration;
14+
use monio::{Button, Event, ScrollDirection};
1715

1816
impl AppEngine {
19-
pub(super) fn simulate_event(&self, event_type: &EventType) {
20-
match simulate(event_type) {
21-
Ok(()) => (),
22-
Err(e) => {
23-
log::error!("Failed to simulate event {event_type:?}: {e}");
24-
}
25-
}
26-
}
27-
2817
/// Move the mouse to `(end_x, end_y)` with a fading triangle cursor trail animation.
2918
pub(super) fn move_mouse_with_trail(&self, end_x: f64, end_y: f64) {
3019
// Get current mouse position (Cocoa bottom-left origin)
31-
let mouse_loc = NSEvent::mouseLocation();
20+
let mouse_loc = objc2_app_kit::NSEvent::mouseLocation();
3221

3322
if self.config.theme.enable_animation {
3423
self.drawer
3524
.draw_trail(mouse_loc.x, mouse_loc.y, end_x, end_y);
3625
}
37-
self.simulate_event(&EventType::MouseMove { x: end_x, y: end_y });
26+
if let Err(e) = monio::mouse_move(end_x, end_y) {
27+
log::error!("Failed to move mouse to ({end_x}, {end_y}): {e}");
28+
}
3829
}
3930

4031
pub(super) fn simulate_click(&self, x: f64, y: f64, button: Button) {
@@ -53,10 +44,10 @@ impl AppEngine {
5344
let color = frame_colors.get(color_idx).unwrap_or(default_color);
5445
self.drawer.draw_ripple(x, y, color);
5546
}
56-
std::thread::sleep(Duration::from_millis(20));
57-
self.simulate_event(&EventType::ButtonPress(button));
58-
std::thread::sleep(Duration::from_millis(20));
59-
self.simulate_event(&EventType::ButtonRelease(button));
47+
std::thread::sleep(std::time::Duration::from_millis(20));
48+
if let Err(e) = monio::mouse_click(button) {
49+
log::error!("Failed to click mouse button {button:?}: {e}");
50+
}
6051
}
6152

6253
pub(super) fn focus_on_element(&self, element: &AXUIElement) {
@@ -203,6 +194,17 @@ impl AppEngine {
203194
}
204195
}
205196

197+
fn simulate_scroll(delta: f64) {
198+
let direction = if delta > 0.0 {
199+
ScrollDirection::Up
200+
} else {
201+
ScrollDirection::Down
202+
};
203+
if let Err(e) = monio::simulate(&Event::mouse_wheel(0.0, 0.0, direction, delta)) {
204+
log::error!("Failed to simulate scroll {delta}: {e}");
205+
}
206+
}
207+
206208
pub(super) fn perform_scroll_action(&mut self, sa: ScrollAction) {
207209
let Some(selected) = self.selected.as_ref() else {
208210
return;
@@ -248,19 +250,13 @@ impl AppEngine {
248250
}
249251
}
250252
} else {
251-
let distance = (frame.size().1 * self.config.scroll_distance).max(1.0) as i64;
253+
let distance = (frame.size().1 * self.config.scroll_distance).max(1.0);
252254
match sa {
253255
ScrollAction::DownRight => {
254-
self.simulate_event(&EventType::Wheel {
255-
delta_x: 0,
256-
delta_y: -distance,
257-
});
256+
Self::simulate_scroll(-distance);
258257
}
259258
ScrollAction::UpLeft => {
260-
self.simulate_event(&EventType::Wheel {
261-
delta_x: 0,
262-
delta_y: distance,
263-
});
259+
Self::simulate_scroll(distance);
264260
}
265261
ScrollAction::IncreaseDistance => {
266262
self.config.scroll_distance *= 1.5;
@@ -269,17 +265,11 @@ impl AppEngine {
269265
self.config.scroll_distance /= 1.5;
270266
}
271267
ScrollAction::Top => {
272-
self.simulate_event(&EventType::Wheel {
273-
delta_x: 0,
274-
delta_y: 999999,
275-
});
268+
Self::simulate_scroll(999999.0);
276269
self.draw_element_menu("", RoleOfInterest::ScrollBar, false);
277270
}
278271
ScrollAction::Bottom => {
279-
self.simulate_event(&EventType::Wheel {
280-
delta_x: 0,
281-
delta_y: -999999,
282-
});
272+
Self::simulate_scroll(-999999.0);
283273
self.draw_element_menu("", RoleOfInterest::ScrollBar, false);
284274
}
285275
}
@@ -300,14 +290,11 @@ impl AppEngine {
300290
pub(super) fn update_editing_text(&mut self, new_text: String) {
301291
if let Some(selected) = self.editing.as_ref()
302292
&& let Some(ele) = selected.element()
293+
&& let Err(e) = ele.set_value(CFString::new(&new_text).as_CFType())
303294
{
304-
use accessibility::AXUIElementAttributes;
305-
use core_foundation::{base::TCFType, string::CFString};
306-
if let Err(e) = ele.set_value(CFString::new(&new_text).as_CFType()) {
307-
log::warn!("Failed to set the text of focused element: {ele:?}\n Error: {e}");
308-
// Reset editing upon failure
309-
self.editing = None;
310-
}
295+
log::warn!("Failed to set the text of focused element: {ele:?}\n Error: {e}");
296+
// Reset editing upon failure
297+
self.editing = None;
311298
}
312299
}
313300

src/app_engine/workflow.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
config::{RoleOfInterest, WorkFlow, WorkFlowAction},
55
};
66
use log::Level;
7-
use rdev::{Button, EventType};
7+
use monio::Button;
88
use std::time::Duration;
99

1010
impl AppEngine {
@@ -64,11 +64,11 @@ impl AppEngine {
6464
WorkFlowAction::KeyCombo(kb) => {
6565
self.set_simulating_key(true);
6666
for k in kb.keys.iter() {
67-
self.simulate_event(&EventType::KeyPress(*k));
67+
let _ = monio::key_press(*k);
6868
std::thread::sleep(Duration::from_millis(20));
6969
}
7070
for k in kb.keys.iter().rev() {
71-
self.simulate_event(&EventType::KeyRelease(*k));
71+
let _ = monio::key_release(*k);
7272
}
7373
self.set_simulating_key(false);
7474
return false;

src/config.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
use monio::Key;
12
use objc2::rc::Retained;
23
use objc2_app_kit::NSFont;
34
use objc2_core_foundation::CFRetained;
45
use objc2_core_graphics::CGColor;
56
use objc2_foundation::{NSString, ns_string};
6-
use rdev::Key;
77
use serde::{Deserialize, Serialize};
88
use std::fs;
99
use std::path::PathBuf;
@@ -253,16 +253,16 @@ impl AlphabeticKey for Key {
253253
Key::Num9 => '9',
254254
Key::Num0 => '0',
255255
Key::Backspace | Key::Delete => '-',
256-
Key::LeftBracket => '[',
257-
Key::RightBracket => ']',
256+
Key::BracketLeft => '[',
257+
Key::BracketRight => ']',
258258
Key::ShiftLeft | Key::ShiftRight => '󰘶',
259259
_ => ' ',
260260
}
261261
}
262262

263263
fn to_str(&self) -> String {
264264
match self {
265-
Key::Alt | Key::AltGr => "ALT".to_string(),
265+
Key::AltLeft | Key::AltRight => "ALT".to_string(),
266266
Key::ControlLeft | Key::ControlRight => "CTRL".to_string(),
267267
Key::MetaLeft | Key::MetaRight => "META".to_string(),
268268
Key::ShiftLeft | Key::ShiftRight => "SHIFT".to_string(),
@@ -298,7 +298,7 @@ impl AlphabeticKey for Key {
298298
"X" => Some(Key::KeyX),
299299
"Y" => Some(Key::KeyY),
300300
"Z" => Some(Key::KeyZ),
301-
"ALT" => Some(Key::Alt),
301+
"ALT" => Some(Key::AltLeft),
302302
"CTRL" => Some(Key::ControlLeft),
303303
"SHIFT" => Some(Key::ShiftLeft),
304304
"META" => Some(Key::MetaLeft),
@@ -308,7 +308,7 @@ impl AlphabeticKey for Key {
308308

309309
fn right_alternative(&self) -> Option<Key> {
310310
match self {
311-
Key::Alt => Some(Key::AltGr),
311+
Key::AltLeft => Some(Key::AltRight),
312312
Key::ControlLeft => Some(Key::ControlRight),
313313
Key::ShiftLeft => Some(Key::ShiftRight),
314314
Key::ShiftRight => Some(Key::MetaRight),
@@ -417,7 +417,7 @@ impl GlyphlowConfig {
417417

418418
fn default_global_keybinding() -> KeyBinding {
419419
KeyBinding {
420-
keys: vec![Key::Alt, Key::KeyG],
420+
keys: vec![Key::AltLeft, Key::KeyG],
421421
}
422422
}
423423
fn default_text_actions() -> Vec<CommandAction> {

src/key_listener.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{
55
sync::{Mutex, MutexGuard},
66
};
77

8-
use rdev::Key;
8+
use monio::Key;
99
use tokio::sync::mpsc::Sender;
1010

1111
use crate::{
@@ -355,7 +355,7 @@ impl KeyListener {
355355
}
356356
Mode::DashBoard => self.menu_helper(&key, MenuType::Dashboard, state, key_state),
357357
// To act on selected parent node
358-
Mode::Filtering if key == Key::Return => {
358+
Mode::Filtering if key == Key::Enter => {
359359
self.send(AppSignal::ActOnSelected);
360360
self.send(AppSignal::MenuRefresh("".into()));
361361
*state = Mode::DashBoard;
@@ -370,7 +370,7 @@ impl KeyListener {
370370
Mode::WordPicking => {
371371
match key {
372372
Key::Slash => self.send(AppSignal::WordPickerStartSearch),
373-
Key::Return => self.send(AppSignal::WordPickerFinishSearch),
373+
Key::Enter => self.send(AppSignal::WordPickerFinishSearch),
374374
Key::Escape => {
375375
self.send(AppSignal::DeActivate);
376376
*state = Mode::Idle;

src/main.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use glyphlow::{
77
config::{GlyphlowConfig, get_config_path},
88
os_util::check_accessibility_permissions,
99
};
10+
use monio::{EventType, grab};
1011
use notify::RecursiveMode;
1112
use notify_debouncer_mini::{DebounceEventResult, new_debouncer};
12-
use rdev::{EventType, grab};
1313
use std::{
1414
collections::HashSet,
1515
path::PathBuf,
@@ -53,7 +53,7 @@ async fn main() {
5353
let key_listener = KeyListener::new(tx, &config);
5454

5555
let state = Arc::new(Mutex::new(Mode::Idle));
56-
// Need this because rdev::grab takes a Fn not FnMut
56+
// Key state for tracking pressed keys and simulating state
5757
let key_state = Arc::new(Mutex::new(KeyState::default()));
5858

5959
// Listen to temp file updates
@@ -102,23 +102,24 @@ async fn main() {
102102
let state = state.clone();
103103
let _ = grab(move |event| {
104104
let Ok(mut k_s) = key_state.lock() else {
105-
return Some(event);
105+
return Some(event.clone());
106106
};
107107
if k_s.is_simulating {
108-
return Some(event);
108+
return Some(event.clone());
109109
}
110-
let swallow = match event.event_type {
111-
EventType::KeyPress(key) => {
112-
k_s.key_down(&key);
113-
key_listener.key_down(key, &state, &mut k_s)
114-
}
115-
EventType::KeyRelease(key) => {
116-
k_s.key_up(&key);
117-
false
110+
111+
let mut pass_on = true;
112+
if let Some(kb) = &event.keyboard {
113+
match event.event_type {
114+
EventType::KeyPressed => {
115+
k_s.key_down(&kb.key);
116+
pass_on = !key_listener.key_down(kb.key, &state, &mut k_s)
117+
}
118+
EventType::KeyReleased => k_s.key_up(&kb.key),
119+
_ => (),
118120
}
119-
_ => false,
120121
};
121-
(!swallow).then_some(event)
122+
pass_on.then(|| event.clone())
122123
});
123124
});
124125

0 commit comments

Comments
 (0)