1 /***************************************************************************
2 * Copyright (C) 2009 by Chris Parker *
3 * chrsprkr3@gmail.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the Python License version 2.5 or later. *
8 * This program is distributed in the hope that it will be useful, *
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
11 ***************************************************************************/
23 // --- Published subroutines, functions and structures
26 if (defaults
->display
== NULL
) {
27 fprintf(stderr
, "cleanup: Display is null, no need to release it\n");
29 XFlush(defaults
->display
);
30 XCloseDisplay(defaults
->display
);
31 defaults
->display
= NULL
;
39 void verbose(BOOL verbose
) {
42 defaults
->log_level
|= LOG_LEVEL_VERBOSE
;
44 defaults
->log_level
&= (! LOG_LEVEL_VERBOSE
);
49 void extra_verbose(BOOL extra_verbose
) {
52 defaults
->log_level
|= LOG_LEVEL_EXTRA_VERBOSE
;
54 defaults
->log_level
&= (! LOG_LEVEL_EXTRA_VERBOSE
);
59 void logit(int level
, char *msg
, ...) {
60 if(defaults
->log_level
>= level
) {
63 vfprintf(stderr
, msg
, args
);
70 void _add_code(unsigned short code
, BOOL shifted
) {
71 ascii_codes
[code
].ascii
= (char) code
;
72 ascii_codes
[code
].code
= XKeysymToKeycode(defaults
->display
, code
);
73 ascii_codes
[code
].shifted
= shifted
;
77 if (!defaults
|| !defaults
->dsp_width
) {
83 if (defaults
->dsp_width
) {
86 fprintf(stderr
, "Cannot properly initialize defaults - exiting\n");
93 ascii_codes
= malloc(128 * sizeof(xautpy_ascii_t
));
94 if (ascii_codes
== NULL
) {
95 fprintf(stderr
, "init: Unable to allocate space for ascii codes");
98 memset(ascii_codes
, 0, 128 * sizeof(xautpy_ascii_t
));
100 // These are easy - regular letters are ( lower case == uppercase | 32 )
102 for (i
= 'A'; i
<= 'Z'; i
++) {
103 _add_code(i
, TRUE
); //Upper
104 _add_code((i
| 32), FALSE
); //Lower
108 for (i
= '0'; i
<= '9'; i
++) {
112 // These are arbitrary keys that will just work. They would be too
113 // weird to try to enter in a loop, seeing as how consecutive ascii
114 // codes sometimes require shift, and sometimes do not.
115 // This is just me running my fingers across my QWERTY US keyboard.
116 _add_code(' ', FALSE
); //Space
117 _add_code('\t', FALSE
); //Tab
118 _add_code('`', FALSE
);
119 _add_code('~', TRUE
);
120 _add_code('!', TRUE
);
121 _add_code('@', TRUE
);
122 _add_code('#', TRUE
);
123 _add_code('$', TRUE
);
124 _add_code('%', TRUE
);
125 _add_code('^', TRUE
);
126 _add_code('&', TRUE
);
127 _add_code('*', TRUE
);
128 _add_code('(', TRUE
);
129 _add_code(')', TRUE
);
130 _add_code('-', FALSE
);
131 _add_code('_', TRUE
);
132 _add_code('=', FALSE
);
133 _add_code('+', TRUE
);
134 _add_code('[', FALSE
);
135 _add_code('{', TRUE
);
136 _add_code(']', FALSE
);
137 _add_code('}', TRUE
);
138 _add_code('\\', FALSE
);
139 _add_code('|', TRUE
);
140 _add_code(';', FALSE
);
141 _add_code(':', TRUE
);
142 _add_code('\'', FALSE
);
143 _add_code('"', TRUE
);
144 _add_code(',', FALSE
);
145 _add_code('<', TRUE
); //Strangely, this doesn't appear to work. "+," does though.
146 _add_code('.', FALSE
);
147 _add_code('>', TRUE
);
148 _add_code('/', FALSE
);
149 _add_code('?', TRUE
);
151 SHIFT_L
= XKeysymToKeycode(defaults
->display
, XStringToKeysym("Shift_L"));
152 CONTROL_L
= XKeysymToKeycode(defaults
->display
,
153 XStringToKeysym("Control_L"));
154 ALT_L
= XKeysymToKeycode(defaults
->display
, XStringToKeysym("Alt_L"));
155 META_L
= XKeysymToKeycode(defaults
->display
, XStringToKeysym("Super_L"));
158 //Note that we leave the ascii code and shift alone, so in
159 //essence we are sending +, or shift + comma.
160 ascii_codes
['<'].code
= ascii_codes
[','].code
; //Corrects the "<" problem
161 #endif // LESS_THAN_FIX
166 fprintf( stderr
, "init: No init_ascii function enabled" );
172 if (defaults
&& defaults
->display
) {
175 if (!init_defaults()) {
176 fprintf(stderr
, "Failure initialize defaults\n");
179 if (!_init_ascii()) {
180 fprintf(stderr
, "Failure to initialize ascii keys\n");
185 BOOL
init_defaults() {
186 Display
*display
= XOpenDisplay(NULL
);
187 if (display
== NULL
) {
188 fprintf(stderr
, "init: Unable to get default display\n");
191 defaults
= malloc(sizeof(xautpy_defaults_t
));
192 if (defaults
== NULL
) {
193 fprintf(stderr
, "init: Unable to allocate space for defaults");
196 memset(defaults
, 0, sizeof(xautpy_defaults_t
));
197 defaults
->display
= display
;
198 int defScreen
= XDefaultScreen(defaults
->display
);
199 defaults
->dsp_width
= XDisplayWidth(defaults
->display
, defScreen
);
200 defaults
->dsp_height
= XDisplayHeight(defaults
->display
, defScreen
);
201 defaults
->mouse_move_delay
= 10;
202 defaults
->mouse_down_delay
= 10;
203 defaults
->mouse_click_delay
= 10;
204 defaults
->key_down_delay
= 10;
205 defaults
->key_click_delay
= 5;
206 defaults
->log_level
= LOG_LEVEL_NONE
;
207 defaults
->interpret_meta_symbols
= TRUE
;
211 BOOL
_is_supported_feature(char *feature
) {
213 long item_count
= 0L;
215 Atom
*results
= NULL
;
218 Atom request
= XInternAtom(defaults
->display
, "_NET_SUPPORTED", FALSE
);
219 Atom feature_atom
= XInternAtom(defaults
->display
, feature
, FALSE
);
220 Window root
= RootWindow(defaults
->display
, 0);
222 results
= (Atom
*) _window_property(
223 root
, request
, &item_count
, &type
, &size
);
225 for (i
= 0L; i
< item_count
; i
++) {
226 if (results
[i
] == feature_atom
)
233 char* _stringmid(const char *str
, size_t first
, size_t last
) {
237 size_t len
= strlen(str
);
238 if (len
== 0 || len
< first
|| last
< first
) {
244 size_t count
= last
- first
+ 1;
245 char *ret
= malloc((count
+ 1) * sizeof(char));
247 fprintf(stderr
, "Unable to create string of %d characters\n",
251 memset(ret
, '\0', (count
+ 1) * sizeof(char));
252 ret
= strncpy(ret
, str
+ first
, count
);
256 void _normalize_coords(int *x
, int *y
) {
257 if (!_check_init()) {
262 } else if (*x
> defaults
->dsp_width
) {
263 x
= &defaults
->dsp_width
;
267 } else if (*y
> defaults
->dsp_height
) {
268 y
= &defaults
->dsp_height
;
270 logit(LOG_LEVEL_VERBOSE
, "Final mouse location %d X %d\n", *x
, *y
);
273 BOOL
_normalize_wincoords(int *x
, int *y
, unsigned long win
) {
274 if (!_check_init()) {
277 XWindowAttributes
*attribs
= calloc(1, sizeof(XWindowAttributes
));
278 if(attribs
== NULL
) {
279 fprintf(stderr
, "Unable to allocate space for XWindowAttributes");
282 XSetErrorHandler(_invalid_window_error_handler
);
283 int status
= XGetWindowAttributes(defaults
->display
, win
, attribs
);
284 XSetErrorHandler(NULL
);
287 int winx
= window_x(win
);
288 int winy
= window_y(win
);
291 logit(LOG_LEVEL_VERBOSE
, "Window at %d X %d\n", winx
, winy
);
292 logit(LOG_LEVEL_VERBOSE
, "Relative location %d X %d\n", *x
, *y
);
295 fprintf(stderr
, "Window handle %lu appears to be invalid\n", win
);
296 fprintf(stderr
, "Not moving the mouse\n");
302 //In case the window is partially off the screen
303 _normalize_coords(x
, y
);
307 /* Typically we don't need to do anything other than return
308 * a status of zero. That is sufficient for these functions
310 int _invalid_window_error_handler(Display
*dsp
, XErrorEvent
*err
) {