gyruby 0.0.1 → 0.0.2
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/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
|