1pub extern crate interception_sys;
2
3#[macro_use]
4extern crate bitflags;
5
6pub use interception_sys as raw;
7pub mod scancode;
8
9pub use scancode::ScanCode;
10
11use std::convert::{TryFrom, TryInto};
12use std::default::Default;
13use std::time::Duration;
14use std::vec::Vec;
15
16pub type Device = i32;
17pub type Precedence = i32;
18
19pub enum Filter {
20 MouseFilter(MouseFilter),
21 KeyFilter(KeyFilter),
22}
23
24pub type Predicate = extern "C" fn(device: Device) -> bool;
25
26bitflags! {
27 pub struct MouseState: u16 {
28 const LEFT_BUTTON_DOWN = 1;
29 const LEFT_BUTTON_UP = 2;
30
31 const RIGHT_BUTTON_DOWN = 4;
32 const RIGHT_BUTTON_UP = 8;
33
34 const MIDDLE_BUTTON_DOWN = 16;
35 const MIDDLE_BUTTON_UP = 32;
36
37 const BUTTON_4_DOWN = 64;
38 const BUTTON_4_UP = 128;
39
40 const BUTTON_5_DOWN = 256;
41 const BUTTON_5_UP = 512;
42
43 const WHEEL = 1024;
44 const HWHEEL = 2048;
45
46 const MOVE = 4096;
48 }
49}
50
51pub type MouseFilter = MouseState;
52
53bitflags! {
54 pub struct MouseFlags: u16 {
55 const MOVE_RELATIVE = 0;
56 const MOVE_ABSOLUTE = 1;
57
58 const VIRTUAL_DESKTOP = 2;
59 const ATTRIBUTES_CHANGED = 4;
60
61 const MOVE_NO_COALESCE = 8;
62
63 const TERMSRV_SRC_SHADOW = 256;
64 }
65}
66
67bitflags! {
68 pub struct KeyState: u16 {
69 const DOWN = 0;
70 const UP = 1;
71
72 const E0 = 2;
73 const E1 = 3;
74
75 const TERMSRV_SET_LED = 8;
76 const TERMSRV_SHADOW = 16;
77 const TERMSRV_VKPACKET = 32;
78 }
79}
80
81bitflags! {
82 pub struct KeyFilter: u16 {
83 const DOWN = 1;
84 const UP = 2;
85
86 const E0 = 4;
87 const E1 = 8;
88
89 const TERMSRV_SET_LED = 16;
90 const TERMSRV_SHADOW = 32;
91 const TERMSRV_VKPACKET = 64;
92 }
93}
94
95#[derive(Debug, Copy, Clone)]
96pub enum Stroke {
97 Mouse {
98 state: MouseState,
99 flags: MouseFlags,
100 rolling: i16,
101 x: i32,
102 y: i32,
103 information: u32,
104 },
105
106 Keyboard {
107 code: ScanCode,
108 state: KeyState,
109 information: u32,
110 },
111}
112
113impl TryFrom<raw::InterceptionMouseStroke> for Stroke {
114 type Error = &'static str;
115
116 fn try_from(raw_stroke: raw::InterceptionMouseStroke) -> Result<Self, Self::Error> {
117 let state = match MouseState::from_bits(raw_stroke.state) {
118 Some(state) => state,
119 None => return Err("Extra bits in raw mouse state"),
120 };
121
122 let flags = match MouseFlags::from_bits(raw_stroke.flags) {
123 Some(flags) => flags,
124 None => return Err("Extra bits in raw mouse flags"),
125 };
126
127 Ok(Stroke::Mouse {
128 state: state,
129 flags: flags,
130 rolling: raw_stroke.rolling,
131 x: raw_stroke.x,
132 y: raw_stroke.y,
133 information: raw_stroke.information,
134 })
135 }
136}
137
138impl TryFrom<raw::InterceptionKeyStroke> for Stroke {
139 type Error = &'static str;
140
141 fn try_from(raw_stroke: raw::InterceptionKeyStroke) -> Result<Self, Self::Error> {
142 let state = match KeyState::from_bits(raw_stroke.state) {
143 Some(state) => state,
144 None => return Err("Extra bits in raw keyboard state"),
145 };
146
147 let code = match ScanCode::try_from(raw_stroke.code) {
148 Ok(code) => code,
149 Err(_) => ScanCode::Esc,
150 };
151
152 Ok(Stroke::Keyboard {
153 code: code,
154 state: state,
155 information: raw_stroke.information,
156 })
157 }
158}
159
160impl TryFrom<Stroke> for raw::InterceptionMouseStroke {
161 type Error = &'static str;
162
163 fn try_from(stroke: Stroke) -> Result<Self, Self::Error> {
164 if let Stroke::Mouse {
165 state,
166 flags,
167 rolling,
168 x,
169 y,
170 information,
171 } = stroke
172 {
173 Ok(raw::InterceptionMouseStroke {
174 state: state.bits(),
175 flags: flags.bits(),
176 rolling: rolling,
177 x: x,
178 y: y,
179 information: information,
180 })
181 } else {
182 Err("Stroke must be a mouse stroke")
183 }
184 }
185}
186
187impl TryFrom<Stroke> for raw::InterceptionKeyStroke {
188 type Error = &'static str;
189
190 fn try_from(stroke: Stroke) -> Result<Self, Self::Error> {
191 if let Stroke::Keyboard {
192 code,
193 state,
194 information,
195 } = stroke
196 {
197 Ok(raw::InterceptionKeyStroke {
198 code: code as u16,
199 state: state.bits(),
200 information: information,
201 })
202 } else {
203 Err("Stroke must be a keyboard stroke")
204 }
205 }
206}
207
208pub struct Interception {
209 ctx: raw::InterceptionContext,
210}
211
212impl Interception {
213 pub fn new() -> Option<Self> {
214 let ctx = unsafe { raw::interception_create_context() };
215
216 if ctx == std::ptr::null_mut() {
217 return None;
218 }
219
220 Some(Interception { ctx: ctx })
221 }
222
223 pub fn get_precedence(&self, device: Device) -> Precedence {
224 unsafe { raw::interception_get_precedence(self.ctx, device) }
225 }
226
227 pub fn set_precedence(&self, device: Device, precedence: Precedence) {
228 unsafe { raw::interception_set_precedence(self.ctx, device, precedence) }
229 }
230
231 pub fn get_filter(&self, device: Device) -> Filter {
232 if is_invalid(device) {
233 return Filter::KeyFilter(KeyFilter::empty());
234 }
235
236 let raw_filter = unsafe { raw::interception_get_filter(self.ctx, device) };
237 if is_mouse(device) {
238 let filter = match MouseFilter::from_bits(raw_filter) {
239 Some(filter) => filter,
240 None => MouseFilter::empty(),
241 };
242
243 Filter::MouseFilter(filter)
244 } else {
245 let filter = match KeyFilter::from_bits(raw_filter) {
246 Some(filter) => filter,
247 None => KeyFilter::empty(),
248 };
249
250 Filter::KeyFilter(filter)
251 }
252 }
253
254 pub fn set_filter(&self, predicate: Predicate, filter: Filter) {
255 let filter = match filter {
256 Filter::MouseFilter(filter) => filter.bits(),
257 Filter::KeyFilter(filter) => filter.bits(),
258 };
259
260 unsafe {
261 let predicate = std::mem::transmute(Some(predicate));
262 raw::interception_set_filter(self.ctx, predicate, filter)
263 }
264 }
265
266 pub fn wait(&self) -> Device {
267 unsafe { raw::interception_wait(self.ctx) }
268 }
269
270 pub fn wait_with_timeout(&self, duration: Duration) -> Device {
271 let millis = match u32::try_from(duration.as_millis()) {
272 Ok(m) => m,
273 Err(_) => u32::MAX,
274 };
275
276 unsafe { raw::interception_wait_with_timeout(self.ctx, millis) }
277 }
278
279 pub fn send(&self, device: Device, strokes: &[Stroke]) -> i32 {
280 if is_mouse(device) {
281 self.send_internal::<raw::InterceptionMouseStroke>(device, strokes)
282 } else if is_keyboard(device) {
283 self.send_internal::<raw::InterceptionKeyStroke>(device, strokes)
284 } else {
285 0
286 }
287 }
288
289 fn send_internal<T: TryFrom<Stroke>>(&self, device: Device, strokes: &[Stroke]) -> i32 {
290 let mut raw_strokes = Vec::new();
291
292 for stroke in strokes {
293 if let Ok(raw_stroke) = T::try_from(*stroke) {
294 raw_strokes.push(raw_stroke)
295 }
296 }
297
298 let ptr = raw_strokes.as_ptr();
299 let len = match u32::try_from(raw_strokes.len()) {
300 Ok(l) => l,
301 Err(_) => u32::MAX,
302 };
303
304 unsafe { raw::interception_send(self.ctx, device, std::mem::transmute(ptr), len) }
305 }
306
307 pub fn receive(&self, device: Device, strokes: &mut [Stroke]) -> i32 {
308 if is_mouse(device) {
309 self.receive_internal::<raw::InterceptionMouseStroke>(device, strokes)
310 } else if is_keyboard(device) {
311 self.receive_internal::<raw::InterceptionKeyStroke>(device, strokes)
312 } else {
313 0
314 }
315 }
316
317 fn receive_internal<T: TryInto<Stroke> + Default + Copy>(
318 &self,
319 device: Device,
320 strokes: &mut [Stroke],
321 ) -> i32 {
322 let mut raw_strokes: Vec<T> = Vec::with_capacity(strokes.len());
323 raw_strokes.resize_with(strokes.len(), Default::default);
324
325 let ptr = raw_strokes.as_ptr();
326 let len = match u32::try_from(raw_strokes.len()) {
327 Ok(l) => l,
328 Err(_) => u32::MAX,
329 };
330
331 let num_read =
332 unsafe { raw::interception_receive(self.ctx, device, std::mem::transmute(ptr), len) };
333
334 let mut num_valid: i32 = 0;
335 for i in 0..num_read {
336 if let Ok(stroke) = raw_strokes[i as usize].try_into() {
337 strokes[num_valid as usize] = stroke;
338 num_valid += 1;
339 }
340 }
341
342 num_valid
343 }
344
345 pub fn get_hardware_id(&self, device: Device, buffer: &mut [u8]) -> u32 {
346 let ptr = buffer.as_mut_ptr();
347 let len = match u32::try_from(buffer.len()) {
348 Ok(l) => l,
349 Err(_) => u32::MAX,
350 };
351
352 unsafe {
353 raw::interception_get_hardware_id(self.ctx, device, std::mem::transmute(ptr), len)
354 }
355 }
356}
357
358impl Drop for Interception {
359 fn drop(&mut self) {
360 unsafe { raw::interception_destroy_context(self.ctx) }
361 }
362}
363
364pub extern "C" fn is_invalid(device: Device) -> bool {
365 unsafe { raw::interception_is_invalid(device) != 0 }
366}
367
368pub extern "C" fn is_keyboard(device: Device) -> bool {
369 unsafe { raw::interception_is_keyboard(device) != 0 }
370}
371
372pub extern "C" fn is_mouse(device: Device) -> bool {
373 unsafe { raw::interception_is_mouse(device) != 0 }
374}