gyruby 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/gyruby_ext.c +104 -91
- data/lib/gyruby.rb +2 -0
- metadata +2 -1
data/ext/gyruby_ext.c
CHANGED
@@ -28,20 +28,19 @@
|
|
28
28
|
#define BUFFER_UNIT 1024
|
29
29
|
|
30
30
|
typedef struct {
|
31
|
-
usb_dev_handle *
|
32
|
-
GHashTable *subscriptions;
|
33
|
-
VALUE rb_remote;
|
34
|
-
Display *display;
|
35
|
-
VALUE display_name;
|
36
|
-
|
37
|
-
ID grab_callback;
|
31
|
+
usb_dev_handle *usb_handle; // is NULL if we didnt find the device. will be automatically looked up. will not be looked up again after having been set once
|
32
|
+
GHashTable *subscriptions; // is initialized as a GHashTable, and destroyed on c_remote_free
|
33
|
+
VALUE rb_remote; // the ruby VALUE for this struct
|
34
|
+
Display *display; // is NULL if we havent connected to a display yet. will be looked up on grab and reset to NULL on release
|
35
|
+
VALUE display_name; // is Qnil if we havent connected to a display yet. will be set on grab and reset to Qnil on release
|
36
|
+
ID grab_callback; // is whatever until connect to a display, can be anything, except when display is set - in which case it is set to the ID of the callback for pointer movements
|
38
37
|
} c_remote;
|
39
38
|
|
40
|
-
typedef
|
39
|
+
typedef VALUE
|
41
40
|
(*gyration_data_handler)(gint result, gchar *data, gpointer user_data);
|
42
41
|
|
43
|
-
typedef
|
44
|
-
(*grab_data_handler)(gint x, gint y, gpointer user_data);
|
42
|
+
typedef VALUE
|
43
|
+
(*grab_data_handler)(gint x, gint y, gint maxx, gint maxy, gpointer user_data);
|
45
44
|
|
46
45
|
static VALUE rb_remote;
|
47
46
|
|
@@ -57,8 +56,8 @@ c_remote_inspect(c_remote *remote) {
|
|
57
56
|
static void
|
58
57
|
c_remote_free(c_remote *remote) {
|
59
58
|
g_hash_table_destroy(remote->subscriptions);
|
60
|
-
if (remote->
|
61
|
-
if (usb_close(remote->
|
59
|
+
if (remote->usb_handle != NULL) {
|
60
|
+
if (usb_close(remote->usb_handle) < 0) {
|
62
61
|
gchar *buffer = c_remote_inspect(remote);
|
63
62
|
fprintf(stderr, "Unable to close usb handle! Freeing %s anyway.", buffer);
|
64
63
|
free(buffer);
|
@@ -111,7 +110,7 @@ subscription_equal(gconstpointer a, gconstpointer b) {
|
|
111
110
|
static VALUE
|
112
111
|
rb_remote_alloc(VALUE class) {
|
113
112
|
c_remote *remote = ALLOC(c_remote);
|
114
|
-
remote->
|
113
|
+
remote->usb_handle = NULL;
|
115
114
|
remote->subscriptions = g_hash_table_new_full(subscription_hash, subscription_equal, free, free);
|
116
115
|
remote->display = NULL;
|
117
116
|
remote->display_name = Qnil;
|
@@ -127,13 +126,13 @@ rb_gyruby_set_debug(VALUE self, VALUE arg) {
|
|
127
126
|
|
128
127
|
static void
|
129
128
|
c_remote_fetch_handle(c_remote *remote) {
|
130
|
-
if (remote->
|
129
|
+
if (remote->usb_handle == NULL) {
|
131
130
|
struct usb_bus *busses = usb_get_busses();
|
132
131
|
for (struct usb_bus *bus = busses; bus; bus = bus->next) {
|
133
132
|
for (struct usb_device *dev = bus->devices; dev; dev = dev->next) {
|
134
133
|
if (dev->descriptor.idVendor == 0x0c16 &&
|
135
134
|
dev->descriptor.idProduct == 0x0006) {
|
136
|
-
remote->
|
135
|
+
remote->usb_handle = usb_open(dev);
|
137
136
|
}
|
138
137
|
}
|
139
138
|
}
|
@@ -143,14 +142,14 @@ c_remote_fetch_handle(c_remote *remote) {
|
|
143
142
|
static void
|
144
143
|
c_remote_claim_device(c_remote *remote) {
|
145
144
|
c_remote_fetch_handle(remote);
|
146
|
-
if (remote->
|
147
|
-
if (usb_claim_interface(remote->
|
145
|
+
if (remote->usb_handle) {
|
146
|
+
if (usb_claim_interface(remote->usb_handle, 1) < 0) {
|
148
147
|
char dname[32];
|
149
|
-
if (usb_get_driver_np(remote->
|
150
|
-
if (usb_detach_kernel_driver_np(remote->
|
148
|
+
if (usb_get_driver_np(remote->usb_handle, 1, dname, 31) == 0) {
|
149
|
+
if (usb_detach_kernel_driver_np(remote->usb_handle, 1) < 0) {
|
151
150
|
rb_raise(rb_eRuntimeError, "Failed claiming device. Also failed detaching kernel driver for device.");
|
152
151
|
} else {
|
153
|
-
if (usb_claim_interface(remote->
|
152
|
+
if (usb_claim_interface(remote->usb_handle, 1) < 0) {
|
154
153
|
rb_raise(rb_eRuntimeError, "Failed claiming device. Succeded in detaching kernel driver for device. But still failed claiming device.");
|
155
154
|
}
|
156
155
|
}
|
@@ -161,12 +160,12 @@ c_remote_claim_device(c_remote *remote) {
|
|
161
160
|
}
|
162
161
|
}
|
163
162
|
|
164
|
-
static
|
163
|
+
static VALUE
|
165
164
|
c_remote_handle_usb_data(c_remote *remote, gyration_data_handler handler, gpointer user_data) {
|
166
165
|
char inpacket[PACKET_SIZE];
|
167
166
|
for (gint i = 0; i < PACKET_SIZE; i++)
|
168
167
|
inpacket[i] = 0;
|
169
|
-
gint result = usb_interrupt_read(remote->
|
168
|
+
gint result = usb_interrupt_read(remote->usb_handle,
|
170
169
|
0x82,
|
171
170
|
inpacket,
|
172
171
|
PACKET_SIZE,
|
@@ -182,34 +181,81 @@ true_predicate(Display *display, XEvent *event, XPointer arg) {
|
|
182
181
|
return True;
|
183
182
|
}
|
184
183
|
|
185
|
-
static
|
184
|
+
static VALUE
|
186
185
|
c_remote_handle_grab_data(c_remote *remote, grab_data_handler handler, gpointer user_data) {
|
187
186
|
XEvent event;
|
188
|
-
if (XCheckIfEvent(remote->display, &event, true_predicate, NULL) == True
|
189
|
-
|
190
|
-
|
191
|
-
return
|
187
|
+
if (XCheckIfEvent(remote->display, &event, true_predicate, NULL) == True &&
|
188
|
+
event.xmotion.same_screen == True) {
|
189
|
+
Screen *screen = XDefaultScreenOfDisplay(remote->display);
|
190
|
+
return handler(event.xmotion.x_root, event.xmotion.y_root, WidthOfScreen(screen), HeightOfScreen(screen), user_data);
|
191
|
+
} else {
|
192
|
+
return Qnil;
|
193
|
+
}
|
192
194
|
}
|
193
195
|
|
194
|
-
static
|
195
|
-
|
196
|
-
|
196
|
+
static void
|
197
|
+
c_remote_grab_pointer(c_remote *remote) {
|
198
|
+
if (remote->display_name != Qnil) {
|
199
|
+
remote->display = XOpenDisplay(RSTRING(remote->display_name)->ptr);
|
200
|
+
if (XGrabPointer(remote->display,
|
201
|
+
XDefaultRootWindow(remote->display),
|
202
|
+
False,
|
203
|
+
PointerMotionMask,
|
204
|
+
GrabModeAsync,
|
205
|
+
GrabModeAsync,
|
206
|
+
None,
|
207
|
+
None,
|
208
|
+
CurrentTime) != GrabSuccess) {
|
209
|
+
remote->display = NULL;
|
210
|
+
rb_raise(rb_eRuntimeError, "Failed grabbing the pointer for the root window at %s.", RSTRING(remote->display_name)->ptr);
|
211
|
+
}
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
static VALUE
|
216
|
+
c_remote_handle_data_loop(VALUE arg) {
|
217
|
+
gpointer *args = (gpointer *) GINT_TO_POINTER(arg);
|
218
|
+
c_remote *remote = (c_remote *) args[0];
|
219
|
+
gyration_data_handler gyration_handler = (gyration_data_handler) args[1];
|
220
|
+
grab_data_handler grab_handler = (grab_data_handler) args[2];
|
221
|
+
gpointer user_data = args[3];
|
222
|
+
VALUE rval = Qnil;
|
197
223
|
struct timeval wait_time = { 0, 1 };
|
198
|
-
c_remote_claim_device(remote);
|
199
224
|
while (1) {
|
200
225
|
if (gyration_handler != NULL &&
|
201
|
-
remote->
|
202
|
-
(rval = c_remote_handle_usb_data(remote, gyration_handler, user_data)) !=
|
226
|
+
remote->usb_handle != NULL &&
|
227
|
+
(rval = c_remote_handle_usb_data(remote, gyration_handler, user_data)) != Qnil)
|
203
228
|
return rval;
|
204
229
|
if (grab_handler != NULL &&
|
205
|
-
remote->
|
206
|
-
(rval = c_remote_handle_grab_data(remote, grab_handler, user_data)) !=
|
230
|
+
remote->display_name != Qnil &&
|
231
|
+
(rval = c_remote_handle_grab_data(remote, grab_handler, user_data)) != Qnil)
|
207
232
|
return rval;
|
208
233
|
rb_thread_wait_for(wait_time);
|
209
234
|
}
|
210
235
|
return rval;
|
211
236
|
}
|
212
237
|
|
238
|
+
static VALUE
|
239
|
+
c_remote_release_pointer(VALUE arg) {
|
240
|
+
c_remote *remote = (c_remote *) GINT_TO_POINTER(arg);
|
241
|
+
if (remote->display != NULL) {
|
242
|
+
XUngrabPointer(remote->display, CurrentTime);
|
243
|
+
XCloseDisplay(remote->display);
|
244
|
+
remote->display = NULL;
|
245
|
+
}
|
246
|
+
return Qnil;
|
247
|
+
}
|
248
|
+
|
249
|
+
static VALUE
|
250
|
+
c_remote_handle_data_until(c_remote *remote, gyration_data_handler gyration_handler, grab_data_handler grab_handler, gpointer user_data) {
|
251
|
+
VALUE rval;
|
252
|
+
gpointer loop_args[4] = { remote, gyration_handler, grab_handler, user_data };
|
253
|
+
c_remote_claim_device(remote);
|
254
|
+
c_remote_grab_pointer(remote);
|
255
|
+
rval = rb_ensure(c_remote_handle_data_loop, GPOINTER_TO_INT(loop_args), c_remote_release_pointer, GPOINTER_TO_INT(remote));
|
256
|
+
return rval;
|
257
|
+
}
|
258
|
+
|
213
259
|
static gchar*
|
214
260
|
subscription_from_result_and_packet(gint result, gchar *packet) {
|
215
261
|
gchar *subscription = malloc(sizeof(gint) + (sizeof(gchar) * PACKET_SIZE));
|
@@ -222,71 +268,53 @@ subscription_from_result_and_packet(gint result, gchar *packet) {
|
|
222
268
|
return subscription;
|
223
269
|
}
|
224
270
|
|
225
|
-
static
|
271
|
+
static VALUE
|
226
272
|
c_remote_yield_gyration_data(gint result, gchar *packet, gpointer user_data) {
|
227
273
|
VALUE result_value = INT2NUM(result);
|
228
274
|
VALUE result_string = rb_str_new(packet, PACKET_SIZE);
|
229
|
-
|
230
|
-
if ((rval = rb_yield_values(2, result_value, result_string)) == Qnil)
|
231
|
-
return NULL;
|
232
|
-
else
|
233
|
-
return GINT_TO_POINTER(rval);
|
275
|
+
return rb_yield_values(2, result_value, result_string);
|
234
276
|
}
|
235
277
|
|
236
|
-
static
|
237
|
-
c_remote_call_grab_handler(gint x, gint y, gpointer user_data) {
|
278
|
+
static VALUE
|
279
|
+
c_remote_call_grab_handler(gint x, gint y, gint maxx, gint maxy, gpointer user_data) {
|
238
280
|
c_remote *remote = (c_remote *) user_data;
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
else
|
247
|
-
return GINT_TO_POINTER(rval);
|
281
|
+
return rb_funcall(remote->rb_remote,
|
282
|
+
remote->grab_callback,
|
283
|
+
4,
|
284
|
+
INT2NUM(x),
|
285
|
+
INT2NUM(y),
|
286
|
+
INT2NUM(maxx),
|
287
|
+
INT2NUM(maxy));
|
248
288
|
}
|
249
289
|
|
250
|
-
static
|
290
|
+
static VALUE
|
251
291
|
c_remote_call_subscription(gint result, gchar *packet, gpointer user_data) {
|
252
292
|
gchar *subscription = subscription_from_result_and_packet(result, packet);
|
253
293
|
c_remote *remote = (c_remote *) user_data;
|
254
294
|
ID *callback;
|
255
295
|
if ((callback = g_hash_table_lookup(remote->subscriptions, subscription)) != NULL) {
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
rb_str_new(packet, PACKET_SIZE))) == Qnil)
|
262
|
-
return NULL;
|
263
|
-
else
|
264
|
-
return GINT_TO_POINTER(rval);
|
296
|
+
return rb_funcall(remote->rb_remote,
|
297
|
+
*callback,
|
298
|
+
2,
|
299
|
+
INT2NUM(result),
|
300
|
+
rb_str_new(packet, PACKET_SIZE));
|
265
301
|
} else {
|
266
|
-
return
|
302
|
+
return Qnil;
|
267
303
|
}
|
268
304
|
}
|
269
305
|
|
270
306
|
static VALUE
|
271
307
|
rb_remote_listen(VALUE self) {
|
272
308
|
c_remote *this;
|
273
|
-
gpointer rval;
|
274
309
|
C_REMOTE(self, this);
|
275
|
-
|
276
|
-
return Qnil;
|
277
|
-
else
|
278
|
-
return (VALUE) GPOINTER_TO_INT(rval);
|
310
|
+
return c_remote_handle_data_until(this, c_remote_call_subscription, c_remote_call_grab_handler, this);
|
279
311
|
}
|
280
312
|
|
281
313
|
static VALUE
|
282
314
|
rb_remote_record(VALUE self) {
|
283
315
|
c_remote *this;
|
284
|
-
gpointer rval;
|
285
316
|
C_REMOTE(self, this);
|
286
|
-
|
287
|
-
return Qnil;
|
288
|
-
else
|
289
|
-
return (VALUE) GPOINTER_TO_INT(rval);
|
317
|
+
return c_remote_handle_data_until(this, c_remote_yield_gyration_data, NULL, NULL);
|
290
318
|
}
|
291
319
|
|
292
320
|
static VALUE
|
@@ -348,21 +376,8 @@ static VALUE
|
|
348
376
|
rb_remote_grab(VALUE self, VALUE display_name_value, VALUE callback) {
|
349
377
|
c_remote *this;
|
350
378
|
Check_Type(display_name_value, T_STRING);
|
379
|
+
Check_Type(callback, T_SYMBOL);
|
351
380
|
C_REMOTE(self, this);
|
352
|
-
this->display = XOpenDisplay(RSTRING(display_name_value)->ptr);
|
353
|
-
this->root = XDefaultRootWindow(this->display);
|
354
|
-
if (XGrabPointer(this->display,
|
355
|
-
this->root,
|
356
|
-
False,
|
357
|
-
PointerMotionMask,
|
358
|
-
GrabModeAsync,
|
359
|
-
GrabModeAsync,
|
360
|
-
None,
|
361
|
-
None,
|
362
|
-
CurrentTime) != GrabSuccess) {
|
363
|
-
this->display = NULL;
|
364
|
-
rb_raise(rb_eRuntimeError, "Failed grabbing the pointer for the root window at %s.", RSTRING(display_name_value)->ptr);
|
365
|
-
}
|
366
381
|
this->grab_callback = rb_to_id(callback);
|
367
382
|
this->display_name = display_name_value;
|
368
383
|
return display_name_value;
|
@@ -372,11 +387,9 @@ static VALUE
|
|
372
387
|
rb_remote_release(VALUE self) {
|
373
388
|
c_remote *this;
|
374
389
|
C_REMOTE(self, this);
|
375
|
-
if (this->
|
390
|
+
if (this->display_name == Qnil)
|
376
391
|
rb_raise(rb_eRuntimeError, "You can't release a %s that isn't grabbed.", rb_obj_classname(self));
|
377
|
-
|
378
|
-
XCloseDisplay(this->display);
|
379
|
-
this->display = NULL;
|
392
|
+
this->display_name = Qnil;
|
380
393
|
return self;
|
381
394
|
}
|
382
395
|
|
data/lib/gyruby.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gyruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Kihlgren
|
@@ -22,6 +22,7 @@ extensions:
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
24
|
files:
|
25
|
+
- lib/gyruby.rb
|
25
26
|
- ext/extconf.rb
|
26
27
|
- ext/gyruby_ext.c
|
27
28
|
has_rdoc: true
|