1#![warn(missing_docs)]
4
5extern crate libxdo_sys as sys;
6
7use std::ffi::{CString, NulError};
8use std::convert::From;
9use std::error::Error;
10use std::fmt;
11
12pub struct XDo {
14 handle: *mut sys::xdo_t,
15}
16
17#[derive(Debug)]
19pub enum CreationError {
20 Nul(NulError),
22 Ffi,
24}
25
26impl fmt::Display for CreationError {
27 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28 match *self {
29 CreationError::Nul(ref err) => {
30 write!(f,
31 "Failed to create XDo instance: Nul byte in argument: {}",
32 err)
33 }
34 CreationError::Ffi => write!(f, "Libxdo failed to create an instance."),
35 }
36 }
37}
38
39impl Error for CreationError {
40 fn description(&self) -> &str {
41 match *self {
42 CreationError::Nul(_) => "libxdo creation error: Nul byte in argument",
43 CreationError::Ffi => "libxdo creation error: Ffi error",
44 }
45 }
46 fn cause(&self) -> Option<&Error> {
47 match *self {
48 CreationError::Nul(ref err) => Some(err),
49 CreationError::Ffi => None,
50 }
51 }
52}
53
54impl From<NulError> for CreationError {
55 fn from(err: NulError) -> CreationError {
56 CreationError::Nul(err)
57 }
58}
59
60#[derive(Debug)]
62pub enum OpError {
63 Nul(NulError),
65 Ffi(i32),
67}
68
69impl fmt::Display for OpError {
70 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71 match *self {
72 OpError::Nul(ref err) => {
73 write!(f, "Xdo operation failed: Nul byte in argument: {}", err)
74 }
75 OpError::Ffi(code) => write!(f, "Xdo operation failed. Error code {}.", code),
76 }
77 }
78}
79
80impl Error for OpError {
81 fn description(&self) -> &str {
82 match *self {
83 OpError::Nul(_) => "xdo operation failure: Nul byte in argument",
84 OpError::Ffi(_) => "xdo operation failure: Ffi error",
85 }
86 }
87 fn cause(&self) -> Option<&Error> {
88 match *self {
89 OpError::Nul(ref err) => Some(err),
90 OpError::Ffi(_) => None,
91 }
92 }
93}
94
95impl From<NulError> for OpError {
96 fn from(err: NulError) -> Self {
97 OpError::Nul(err)
98 }
99}
100
101pub type OpResult = Result<(), OpError>;
103
104macro_rules! xdo (
105 ($fncall: expr) => {
106 unsafe {
107 match $fncall {
108 0 => Ok(()),
109 code => Err(OpError::Ffi(code))
110 }
111 }
112 }
113);
114
115impl XDo {
116 pub fn new(display: Option<&str>) -> Result<XDo, CreationError> {
126 let c_string;
127 let display = match display {
128 Some(display) => {
129 c_string = CString::new(display)?;
130 c_string.as_ptr()
131 }
132 None => ::std::ptr::null(),
133 };
134 let handle = unsafe { sys::xdo_new(display) };
135 if handle.is_null() {
136 return Err(CreationError::Ffi);
137 }
138 Ok(XDo { handle: handle })
139 }
140 pub fn move_mouse(&self, x: i32, y: i32, screen: i32) -> OpResult {
142 xdo!(sys::xdo_move_mouse(self.handle, x, y, screen))
143 }
144 pub fn move_mouse_relative(&self, x: i32, y: i32) -> OpResult {
146 xdo!(sys::xdo_move_mouse_relative(self.handle, x, y))
147 }
148 pub fn click(&self, button: i32) -> OpResult {
150 xdo!(sys::xdo_click_window(self.handle, sys::CURRENTWINDOW, button))
151 }
152 pub fn mouse_down(&self, button: i32) -> OpResult {
154 xdo!(sys::xdo_mouse_down(self.handle, sys::CURRENTWINDOW, button))
155 }
156 pub fn mouse_up(&self, button: i32) -> OpResult {
158 xdo!(sys::xdo_mouse_up(self.handle, sys::CURRENTWINDOW, button))
159 }
160 pub fn enter_text(&self, text: &str, delay_microsecs: u32) -> OpResult {
162 let string = CString::new(text)?;
163 xdo!(sys::xdo_enter_text_window(self.handle,
164 sys::CURRENTWINDOW,
165 string.as_ptr(),
166 delay_microsecs))
167 }
168 pub fn send_keysequence(&self, sequence: &str, delay_microsecs: u32) -> OpResult {
170 let string = CString::new(sequence)?;
171 xdo!(sys::xdo_send_keysequence_window(self.handle,
172 sys::CURRENTWINDOW,
173 string.as_ptr(),
174 delay_microsecs))
175 }
176 pub fn send_keysequence_up(&self, sequence: &str, delay_microsecs: u32) -> OpResult {
178 let string = CString::new(sequence)?;
179 xdo!(sys::xdo_send_keysequence_window_up(self.handle,
180 sys::CURRENTWINDOW,
181 string.as_ptr(),
182 delay_microsecs))
183 }
184 pub fn send_keysequence_down(&self, sequence: &str, delay_microsecs: u32) -> OpResult {
186 let string = CString::new(sequence)?;
187 xdo!(sys::xdo_send_keysequence_window_down(self.handle,
188 sys::CURRENTWINDOW,
189 string.as_ptr(),
190 delay_microsecs))
191 }
192}
193
194impl Drop for XDo {
195 fn drop(&mut self) {
196 unsafe {
197 sys::xdo_free(self.handle);
198 }
199 }
200}