imitator_x 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/ext/keyboard.h ADDED
@@ -0,0 +1,29 @@
1
+ /*********************************************************************************
2
+ Imitator for X is a library allowing you to fake input to systems using X11.
3
+ Copyright � 2010 Marvin G�lker
4
+
5
+ This file is part of Imitator for X.
6
+
7
+ Imitator for X is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU Lesser General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Imitator for X is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public License
18
+ along with Imitator for X. If not, see <http://www.gnu.org/licenses/>.
19
+ *********************************************************************************/
20
+ #ifndef IMITATOR_KEYBOARD_HEADER
21
+ #define IMITATOR_KEYBOARD_HEADER
22
+
23
+ #define RUBY_UTF8_STR(str) rb_enc_str_new(str, strlen(str), rb_utf8_encoding())
24
+
25
+ VALUE Keyboard;
26
+
27
+ void Init_keyboard(void);
28
+
29
+ #endif
data/ext/mouse.c ADDED
@@ -0,0 +1,456 @@
1
+ /*********************************************************************************
2
+ Imitator for X is a library allowing you to fake input to systems using X11.
3
+ Copyright � 2010 Marvin G�lker
4
+
5
+ This file is part of Imitator for X.
6
+
7
+ Imitator for X is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU Lesser General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Imitator for X is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public License
18
+ along with Imitator for X. If not, see <http://www.gnu.org/licenses/>.
19
+ *********************************************************************************/
20
+ #include "x.h"
21
+ #include "mouse.h"
22
+
23
+ /*
24
+ *Document-module: Imitator::X::Mouse
25
+ *This module allows you to interact with the mouse pointer. You can do funny things
26
+ *with this, but make sure, it's *useful* for your users.
27
+ *
28
+ *Every method besides Mouse.move that claims to move the cursor to a specified
29
+ *position uses Mouse.move internally; so make sure you've read Mouse.move's documentation.
30
+ */
31
+
32
+ /*
33
+ *Retrieves the current mouse cursor position.
34
+ *===Return value
35
+ *The cursor position as a 2-element array of form <tt>[x, y]</tt>.
36
+ *===Example
37
+ * p Imitator::X::Mouse.position #=> [464, 620]
38
+ */
39
+ static VALUE m_pos(VALUE self)
40
+ {
41
+ Display * p_display;
42
+ Window root, child_win;
43
+ int rx, ry, wx, wy;
44
+ unsigned int mask;
45
+ VALUE pos = rb_ary_new();
46
+
47
+ p_display = XOpenDisplay(NULL);
48
+ XSetErrorHandler(handle_x_errors);
49
+
50
+ root = XDefaultRootWindow(p_display);
51
+ if (XQueryPointer(p_display, root, &root, &child_win, &rx, &ry, &wx, &wy, &mask) == False)
52
+ rb_raise(XError, "Could not query the pointer's position!");
53
+ rb_ary_push(pos, INT2NUM(rx));
54
+ rb_ary_push(pos, INT2NUM(ry));
55
+
56
+ XSetErrorHandler(NULL);
57
+ XCloseDisplay(p_display);
58
+
59
+ return pos;
60
+ }
61
+
62
+ /*
63
+ *call-seq:
64
+ * Mouse.move(x, y [, step = 1 [, set = false ] ] ) ==> anArray
65
+ *
66
+ *Moves the mouse cursor to the specified position.
67
+ *===Parameters
68
+ *[+x+] The goal X coordinate.
69
+ *[+y+] The goal Y coordinate.
70
+ *[+step+] (1) This specifies the move amount per computation. Higher values make the movement faster, but more inaccurate. Anyway, the cursor will be exactly at your specified position.
71
+ *[+set+] (+false+) If this is +true+, the cursor isn't moved to the goal position, but directly set to it. Ignores +step+ if set to +true+.
72
+ *===Return value
73
+ *The new position.
74
+ *===Raises
75
+ *[ArgumentError] Besides the normal meanings of this error, it may also indicate that the +step+ parameter has to be greater than 0.
76
+ *===Example
77
+ * #Move to (100|100)
78
+ * Imitator::X::Mouse.move(100, 100) #| [100, 100]
79
+ * #Move to (0|0), only executing every 3rd movement;
80
+ * #Altough this would never trigger the origin, the cursor
81
+ * #will be there.
82
+ * Imitator::X::Mouse.move(0, 0, 3) #| [0, 0]
83
+ * #Don't move, directly set the cursor. The step parameter (1 here) is ignored.
84
+ * Imitator::X::Mouse.move(100, 100, 1, true) #| [100, 100]
85
+ * #If you move off the screen, the cursor will stop at the edge.
86
+ * Imitator::X::Mouse.move(-100, 100) #| [0, 100]
87
+ *===Remarks
88
+ *If you specify a +step+ parameter that is greater than the difference of the actual cursor position to
89
+ *the goal position, you'll get an infinite loop here, so be careful. If you're in doubt on how high
90
+ *you should set +step+, just stick to the directly setting variant.
91
+ */
92
+ static VALUE m_move(int argc, VALUE argv[], VALUE self)
93
+ {
94
+ VALUE rx, ry, rstep, rset, temp;
95
+ VALUE args[4];
96
+ Display * p_display;
97
+ int goal_x, goal_y, step, ix, iy, dir;
98
+
99
+ rb_scan_args(argc, argv, "22", &rx, &ry, &rstep, &rset);
100
+
101
+ if (NIL_P(rstep))
102
+ step = 1;
103
+ else
104
+ step = NUM2INT(rstep);
105
+ goal_x = NUM2INT(rx);
106
+ goal_y = NUM2INT(ry);
107
+
108
+ p_display = XOpenDisplay(NULL);
109
+ XSetErrorHandler(handle_x_errors);
110
+
111
+ /*Ignore the rest of the function if we only want to set the cursor*/
112
+ if (RTEST(rset))
113
+ {
114
+ XTestFakeMotionEvent(p_display, 0, goal_x, goal_y, CurrentTime);
115
+ XSetErrorHandler(NULL);
116
+ XCloseDisplay(p_display);
117
+ return m_pos(self);
118
+ }
119
+
120
+ temp = m_pos(self); /*Get actual position, since we don't want to move off (0|0).*/
121
+ ix = NUM2INT(rb_ary_entry(temp, 0));
122
+ iy = NUM2INT(rb_ary_entry(temp, 1));
123
+
124
+ if (step <= 0)
125
+ rb_raise(rb_eArgError, "The step parameter has to be greater than 0!");
126
+
127
+ /*Get the move direction, which indicates wheather we will increment or decrement the X and Y coordinates. */
128
+ if (ix < goal_x)
129
+ {
130
+ if (iy < goal_y)
131
+ dir = 0; /*Right-down*/
132
+ else
133
+ dir = 1; /*Right-up*/
134
+ }
135
+ else
136
+ {
137
+ if (iy < goal_y)
138
+ dir = 2; /*Left-down*/
139
+ else
140
+ dir = 3; /*Left-up*/
141
+ }
142
+
143
+ /*Perform the Y movement*/
144
+ while ((iy < goal_y - step) || (iy > goal_y + step)) /*Got as near as possible to the goal Y*/
145
+ {
146
+ args[0] = INT2NUM(ix);
147
+ args[1] = INT2NUM(iy);
148
+ args[2] = rstep;
149
+ args[3] = Qtrue;
150
+ m_move(4, args, self); /*Needed, since even a sleep() call here doesn't cause X to update the cursor position when trying to use XTestFakeMotionEvent here*/
151
+ if (dir == 0 || dir == 2)
152
+ iy += step;
153
+ else
154
+ iy -= step;
155
+ }
156
+ /*Perform the X movement*/
157
+ while ((ix < goal_x - step) || (ix > goal_x + step)) /*Got as near as possible to the goal X*/
158
+ {
159
+ args[0] = INT2NUM(ix);
160
+ args[1] = INT2NUM(iy);
161
+ args[2] = rstep;
162
+ args[3] = Qtrue;
163
+ m_move(4, args, self); /*Needed, since even a sleep() call here doesn't cause X to update the cursor position when trying to use XTestFakeMotionEvent here*/
164
+ if (dir == 0 || dir == 1)
165
+ ix += step;
166
+ else
167
+ ix -= step;
168
+ }
169
+
170
+ /*Ensure that the cursor is really at the correct position*/
171
+ XTestFakeMotionEvent(p_display, 0, goal_x, goal_y, CurrentTime);
172
+
173
+ XSetErrorHandler(NULL);
174
+ XCloseDisplay(p_display);
175
+ return m_pos(self);
176
+ }
177
+
178
+ /*
179
+ *call-seq:
180
+ * Mouse.click(hsh = {:button => :left}) ==> anArray
181
+ *
182
+ *Executes a mouse click at the current or a given position.
183
+ *===Parameters
184
+ *This method takes a hash as it's only argument. You may pass the following keys and values:
185
+ *[:x] (Current X) The X coordinate where you want to click.
186
+ *[:y] (Current Y) The Y coordinate where you want to click.
187
+ *[:button] (:left) The mouse button you want to click with. One of :left, :right and :middle.
188
+ *[:step] (1) +step+ parameter for Mouse.move.
189
+ *[:set] (false) +set+ parameter for Mouse.move.
190
+ *===Return value
191
+ *The position where the click was executed.
192
+ *===Example
193
+ * #Click at current position
194
+ * Imitator::X::Mouse.click #| [376, 509]
195
+ * #Click at (100|100)
196
+ * Imitator::X::Mouse.click(:x => 100, :y => 100) #| [100, 100]
197
+ * #Click at current position with right mouse button
198
+ * Imitator::X::Mouse.click(:button => :right)
199
+ */
200
+ static VALUE m_click(int argc, VALUE argv[], VALUE self)
201
+ {
202
+ VALUE hsh, rbutton, rbutton2;
203
+ VALUE args[4];
204
+ int button;
205
+ Display * p_display;
206
+
207
+ rb_scan_args(argc, argv, "01", &hsh);
208
+
209
+ if (NIL_P(hsh))
210
+ hsh = rb_hash_new();
211
+
212
+ rbutton = rb_hash_lookup(hsh, ID2SYM(rb_intern("button")));
213
+
214
+ if (NIL_P(rbutton))
215
+ rbutton = ID2SYM(rb_intern("left")); /*No button specified, defaulting to left*/
216
+ rbutton2 = rb_hash_lookup(rb_const_get(Mouse, rb_intern("BUTTONS")), rbutton);
217
+ if (NIL_P(rbutton2))
218
+ rb_raise(rb_eArgError, "Invalid button specified!");
219
+ button = FIX2INT(rbutton2);
220
+
221
+ p_display = XOpenDisplay(NULL);
222
+ XSetErrorHandler(handle_x_errors);
223
+
224
+ /*Move the cursor if wanted before clicking*/
225
+ args[0] = rb_hash_lookup(hsh, ID2SYM(rb_intern("x")));
226
+ args[1] = rb_hash_lookup(hsh, ID2SYM(rb_intern("y")));
227
+ args[2] = rb_hash_lookup(hsh, ID2SYM(rb_intern("step")));
228
+ args[3] = rb_hash_lookup(hsh, ID2SYM(rb_intern("set")));
229
+ if (!NIL_P(args[0]) && !NIL_P(args[1]))
230
+ m_move(4, args, self);
231
+
232
+ XTestFakeButtonEvent(p_display, (unsigned int)button, True, CurrentTime);
233
+ XTestFakeButtonEvent(p_display, (unsigned int)button, False, CurrentTime);
234
+
235
+ XSetErrorHandler(NULL);
236
+ XCloseDisplay(p_display);
237
+ return m_pos(self);
238
+ }
239
+
240
+ /*
241
+ *call-seq:
242
+ * Mouse.down( [ button = :left ] ) ==> nil
243
+ *
244
+ *Holds the given mouse button down. Don't forget to release it sometime.
245
+ *===Parameters
246
+ *[+button+] (:left) The button to hold down.
247
+ *===Return value
248
+ *nil.
249
+ *===Example
250
+ * Imitator::X::Mouse.down
251
+ * Imitator::X::Mouse.up #Never forget to...
252
+ * Imitator::X::Mouse.down(:right)
253
+ * Imitator::X::Mouse.up(:right) #...Release a pressed button.
254
+ */
255
+ static VALUE m_down(int argc, VALUE argv[], VALUE self)
256
+ {
257
+ VALUE rbutton;
258
+ int button;
259
+ Display * p_display;
260
+
261
+ rb_scan_args(argc, argv, "01", &rbutton);
262
+ if (NIL_P(rbutton))
263
+ rbutton = ID2SYM(rb_intern("left"));
264
+ rbutton = rb_hash_lookup(rb_const_get(Mouse, rb_intern("BUTTONS")), rbutton);
265
+ if (NIL_P(rbutton))
266
+ rb_raise(rb_eArgError, "Invalid button specified!");
267
+ button = FIX2INT(rbutton);
268
+
269
+ p_display = XOpenDisplay(NULL);
270
+ XSetErrorHandler(handle_x_errors);
271
+
272
+ XTestFakeButtonEvent(p_display, (unsigned int)button, True, CurrentTime);
273
+
274
+ XSetErrorHandler(NULL);
275
+ XCloseDisplay(p_display);
276
+ return Qnil;
277
+ }
278
+
279
+ /*
280
+ *call-seq:
281
+ * Mouse.up( [ button = :left ] ) ==> nil
282
+ *
283
+ *Releases the given mouse button. This doesn't have any effect if
284
+ *you didn't call Mouse.down before.
285
+ *===Parameters
286
+ *[+button+] (:left) The button to release.
287
+ *===Return value
288
+ *nil.
289
+ *===Example
290
+ * Imitator::X::Mouse.down
291
+ * Imitator::X::Mouse.up
292
+ * Imitator::X::Mouse.down(:right)
293
+ * Imitator::X::Mouse.up(:right)
294
+ */
295
+ static VALUE m_up(int argc, VALUE argv[], VALUE self)
296
+ {
297
+ VALUE rbutton;
298
+ int button;
299
+ Display * p_display;
300
+
301
+ rb_scan_args(argc, argv, "01", &rbutton);
302
+ if (NIL_P(rbutton))
303
+ rbutton = ID2SYM(rb_intern("left"));
304
+ rbutton = rb_hash_lookup(rb_const_get(Mouse, rb_intern("BUTTONS")), rbutton);
305
+ if (NIL_P(rbutton))
306
+ rb_raise(rb_eArgError, "Invalid button specified!");
307
+ button = FIX2INT(rbutton);
308
+
309
+ p_display = XOpenDisplay(NULL);
310
+ XSetErrorHandler(handle_x_errors);
311
+
312
+ XTestFakeButtonEvent(p_display, (unsigned int)button, False, CurrentTime);
313
+
314
+ XSetErrorHandler(NULL);
315
+ XCloseDisplay(p_display);
316
+ return Qnil;
317
+ }
318
+
319
+ /*
320
+ *call-seq:
321
+ * Mouse.drag(hsh) ==> anArray
322
+ *
323
+ *Executes a drag&drop operation.
324
+ *===Parameters
325
+ *This method takes a hash as it's only parameter. You may pass in one of the following keys:
326
+ *[+x1+] (Current X) Start X coordinate.
327
+ *[+y1+] (Current Y) Start Y coordinate.
328
+ *[+x2+] (*Required*) Goal X coordinate.
329
+ *[+y2+] (*Required*) Goal Y coordinate.
330
+ *[+button+] (<tt>:left</tt>) The button to hold down during the movement.
331
+ *[+step+] +step+ parameter to Mouse.move.
332
+ *[+set+] +set+ parameter to Mouse.move. Use not recommanded here.
333
+ *===Return value
334
+ *Returns the new cursor position as a two-element array of form <tt>[x, y]</tt>.
335
+ *===Example
336
+ * #From current to (200|200)
337
+ * Imitator::X::Mouse.drag(:x2 => 200, :y2 => 200)
338
+ * #From current to (200|200), dragging with the right mouse button
339
+ * Imitator::X::Mouse.drag(:x2 => 200, :y2 => 200, :button => :right)
340
+ * #From (300|300) to (200|200)
341
+ * Imitator::X::Mouse.drag(:x1 => 300, :y1 => 300, :x2 => 200, :y2 => 200)
342
+ * #From (CURRENT X|300) to (200|200)
343
+ * Imitator::X::Mouse.drag(:y1 => 300, :x2 => 200, :y2 => 200)
344
+ */
345
+ static VALUE m_drag(VALUE self, VALUE hsh)
346
+ {
347
+ VALUE rx1, ry1, rx2, ry2, rbutton, rstep, rset, temp;
348
+ VALUE args[4];
349
+
350
+ rx1 = rb_hash_lookup(hsh, ID2SYM(rb_intern("x1")));
351
+ ry1 = rb_hash_lookup(hsh, ID2SYM(rb_intern("y1")));
352
+ rx2 = rb_hash_lookup(hsh, ID2SYM(rb_intern("x2")));
353
+ ry2 = rb_hash_lookup(hsh, ID2SYM(rb_intern("y2")));
354
+ rbutton = rb_hash_lookup(hsh, ID2SYM(rb_intern("button")));
355
+ rstep = rb_hash_lookup(hsh, ID2SYM(rb_intern("step")));
356
+ rset = rb_hash_lookup(hsh, ID2SYM(rb_intern("set")));
357
+
358
+ temp = m_pos(self);
359
+ if (NIL_P(rx1))
360
+ rx1 = rb_ary_entry(temp, 0);
361
+ if (NIL_P(ry1))
362
+ ry1 = rb_ary_entry(temp, 1);
363
+ if (NIL_P(rx2))
364
+ rb_raise(rb_eArgError, "No goal X coordinate specified!");
365
+ if (NIL_P(ry2))
366
+ rb_raise(rb_eArgError, "No goal Y coordinate specified!");
367
+ if (NIL_P(rbutton))
368
+ rbutton = ID2SYM(rb_intern("left"));
369
+ /*If rstep or rset is ommited, it's nil, and this is OK*/
370
+
371
+ args[0] = rx1;
372
+ args[1] = ry1;
373
+ args[2] = rstep;
374
+ args[3] = rset;
375
+ m_move(4, args, self);
376
+ args[0] = rbutton;
377
+ args[1] = 0;
378
+ args[2] = 0;
379
+ args[3] = 0;
380
+ m_down(1, args, self);
381
+ args[0] = rx2;
382
+ args[1] = ry2;
383
+ args[2] = rstep;
384
+ args[3] = rset;
385
+ m_move(4, args, self);
386
+ args[0] = rbutton;
387
+ args[1] = 0;
388
+ args[2] = 0;
389
+ args[3] = 0;
390
+ m_up(1, args, self);
391
+
392
+ return m_pos(self);
393
+ }
394
+
395
+ /*
396
+ *call-seq:
397
+ * Mouse.wheel(direction [, amount = 1 ] ) ==> nil
398
+ *
399
+ *Rolls the mouse wheel.
400
+ *===Parameters
401
+ *[+direction+] The direction in which to roll the mouse wheel, either <tt>:up</tt> or <tt>:down</tt>.
402
+ *[+amount+] (1) The amount of roll steps. This <b>does not</b> mean full turns!
403
+ *===Return value
404
+ *nil.
405
+ *===Example
406
+ * #1 roll step up.
407
+ * Imitator::X::Mouse.wheel(:up)
408
+ * #2 roll steps down.
409
+ * Imitator::X::Mouse.wheel(:down, 2)
410
+ */
411
+ static VALUE m_wheel(int argc, VALUE argv[], VALUE self)
412
+ {
413
+ VALUE rdir, ramount;
414
+ VALUE args[1];
415
+ int amount, i;
416
+
417
+ rb_scan_args(argc, argv, "11", &rdir, &ramount);
418
+ if (NIL_P(ramount))
419
+ ramount = INT2FIX(1);
420
+ if ( (SYM2ID(rdir) != rb_intern("up")) && (SYM2ID(rdir) != rb_intern("down")) )
421
+ rb_raise(rb_eArgError, "Invalid wheel direction specified!");
422
+ amount = NUM2INT(ramount);
423
+
424
+ args[0] = rb_hash_new();
425
+ rb_hash_aset(args[0], ID2SYM(rb_intern("button")), rdir);
426
+
427
+ for(i = 0; i < amount; i++)
428
+ m_click(1, args, self);
429
+
430
+ return Qnil;
431
+ }
432
+
433
+ /******************************Init-Function*********************************/
434
+
435
+ void Init_mouse(void)
436
+ {
437
+ VALUE hsh;
438
+ Mouse = rb_define_module_under(X, "Mouse");
439
+ hsh = rb_hash_new();
440
+ rb_hash_aset(hsh, ID2SYM(rb_intern("left")), INT2FIX(1));
441
+ rb_hash_aset(hsh, ID2SYM(rb_intern("middle")), INT2FIX(2));
442
+ rb_hash_aset(hsh, ID2SYM(rb_intern("right")), INT2FIX(3));
443
+ rb_hash_aset(hsh, ID2SYM(rb_intern("up")), INT2FIX(4)); /*Yeah, the two wheel directions... */
444
+ rb_hash_aset(hsh, ID2SYM(rb_intern("down")), INT2FIX(5)); /*...are handled as buttons by X. */
445
+ /*A hash mapping button names to internal numbers. */
446
+ rb_define_const(Mouse, "BUTTONS", hsh);
447
+
448
+ rb_define_module_function(Mouse, "position", m_pos, 0);
449
+ rb_define_module_function(Mouse, "pos", m_pos, 0);
450
+ rb_define_module_function(Mouse, "move", m_move, -1);
451
+ rb_define_module_function(Mouse, "click", m_click, -1);
452
+ rb_define_module_function(Mouse, "down", m_down, -1);
453
+ rb_define_module_function(Mouse, "up", m_up, -1);
454
+ rb_define_module_function(Mouse, "drag", m_drag, 1);
455
+ rb_define_module_function(Mouse, "wheel", m_wheel, -1);
456
+ }
data/ext/mouse.h ADDED
@@ -0,0 +1,28 @@
1
+ /*********************************************************************************
2
+ Imitator for X is a library allowing you to fake input to systems using X11.
3
+ Copyright � 2010 Marvin G�lker
4
+
5
+ This file is part of Imitator for X.
6
+
7
+ Imitator for X is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU Lesser General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Imitator for X is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public License
18
+ along with Imitator for X. If not, see <http://www.gnu.org/licenses/>.
19
+ *********************************************************************************/
20
+ #ifndef IMITATOR_XMOUSE_HEADER
21
+ #define IMITATOR_XMOUSE_HEADER
22
+
23
+ /*Imitator::X::Mouse*/
24
+ VALUE Mouse;
25
+ /*Mouse initialization function*/
26
+ void Init_mouse(void);
27
+
28
+ #endif
data/ext/x.c ADDED
@@ -0,0 +1,84 @@
1
+ /*********************************************************************************
2
+ Imitator for X is a library allowing you to fake input to systems using X11.
3
+ Copyright � 2010 Marvin G�lker
4
+
5
+ This file is part of Imitator for X.
6
+
7
+ Imitator for X is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU Lesser General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Imitator for X is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public License
18
+ along with Imitator for X. If not, see <http://www.gnu.org/licenses/>.
19
+ *********************************************************************************/
20
+ #include "x.h"
21
+ #include "xwindow.h"
22
+ #include "mouse.h"
23
+ #include "keyboard.h"
24
+ #include "clipboard.h"
25
+
26
+ VALUE Imitator;
27
+ VALUE X;
28
+ VALUE ProtocolError;
29
+ VALUE XError;
30
+
31
+ /*
32
+ *Document-module: Imitator
33
+ *Toplevel namespace of the Imitator libraries.
34
+ */
35
+
36
+ /*
37
+ *Document-module: Imitator::X
38
+ *The namespace of this library.
39
+ */
40
+
41
+ /*
42
+ *Document-class: Imitator::X::XProtocolError
43
+ *A Protocol Error as thrown by X. This class uses X's error messages.
44
+ */
45
+
46
+ /*
47
+ *Document-class: Imitator::X::XError
48
+ *Miscellaneous error messages caused by unexpected behaviour of X.
49
+ */
50
+
51
+ /***********************Helper functions***************************/
52
+ /*
53
+ *This function handles X server protocol errors. That allows us to throw Ruby
54
+ *exceptions instead of having X terminate the program and print it's
55
+ *own error message.
56
+ */
57
+ int handle_x_errors(Display *p_display, XErrorEvent *x_errevt)
58
+ {
59
+ char msg[1000];
60
+
61
+ XGetErrorText(p_display, x_errevt->error_code, msg, 1000);
62
+ XCloseDisplay(p_display); /*Ensure the X Server connection is closed*/
63
+ rb_raise(ProtocolError, msg); /*This is OK, I get the error message from X*/
64
+ return 1;
65
+ }
66
+
67
+ /************************Init-Function****************************/
68
+
69
+ void Init_x(void)
70
+ {
71
+ Imitator = rb_define_module("Imitator");
72
+ X = rb_define_module_under(Imitator, "X");
73
+ ProtocolError = rb_define_class_under(X, "XProtocolError", rb_eStandardError);
74
+ XError = rb_define_class_under(X, "XError", rb_eStandardError);
75
+
76
+ /*The version of this library. */
77
+ rb_define_const(X, "VERSION", rb_str_new2("0.0.1"));
78
+
79
+ /*Load the parts of Imitator for X*/
80
+ Init_xwindow();
81
+ Init_mouse();
82
+ Init_keyboard();
83
+ Init_clipboard();
84
+ }
data/ext/x.h ADDED
@@ -0,0 +1,48 @@
1
+ /*********************************************************************************
2
+ Imitator for X is a library allowing you to fake input to systems using X11.
3
+ Copyright � 2010 Marvin G�lker
4
+
5
+ This file is part of Imitator for X.
6
+
7
+ Imitator for X is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU Lesser General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Imitator for X is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public License
18
+ along with Imitator for X. If not, see <http://www.gnu.org/licenses/>.
19
+ *********************************************************************************/
20
+ #include <stdio.h>
21
+ #include <stdlib.h>
22
+ #include <string.h>
23
+ #include <unistd.h>
24
+ #include <signal.h>
25
+ #include <X11/Xlib.h>
26
+ #include <X11/Xutil.h>
27
+ #include <X11/Xatom.h>
28
+ #include <X11/extensions/XTest.h>
29
+ #include "ruby.h"
30
+ #include "ruby/encoding.h"
31
+
32
+ #ifndef IMITATOR_X_HEADER
33
+ #define IMITATOR_X_HEADER
34
+
35
+ /*Maps XProtocolErrors to Ruby errors*/
36
+ int handle_x_errors(Display *p_display, XErrorEvent *x_errevt);
37
+ /*Main initialization function*/
38
+ void Init_x(void);
39
+ /*Imitator module*/
40
+ VALUE Imitator;
41
+ /*Imitator::X*/
42
+ VALUE X;
43
+ /*Imitator::X::XProtocolError*/
44
+ VALUE ProtocolError;
45
+ /*Imitator::X::XError*/
46
+ VALUE XError;
47
+
48
+ #endif