imitator_x 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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