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.
Files changed (3) hide show
  1. data/ext/gyruby_ext.c +104 -91
  2. data/lib/gyruby.rb +2 -0
  3. 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 *handle;
32
- GHashTable *subscriptions;
33
- VALUE rb_remote;
34
- Display *display;
35
- VALUE display_name;
36
- Window root;
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 gpointer
39
+ typedef VALUE
41
40
  (*gyration_data_handler)(gint result, gchar *data, gpointer user_data);
42
41
 
43
- typedef gpointer
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->handle != NULL) {
61
- if (usb_close(remote->handle) < 0) {
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->handle = NULL;
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->handle == NULL) {
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->handle = usb_open(dev);
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->handle) {
147
- if (usb_claim_interface(remote->handle, 1) < 0) {
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->handle, 1, dname, 31) == 0) {
150
- if (usb_detach_kernel_driver_np(remote->handle, 1) < 0) {
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->handle, 1) < 0) {
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 gpointer
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->handle,
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 gpointer
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
- return handler(event.xmotion.x_root, event.xmotion.y_root, user_data);
190
- else
191
- return NULL;
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 gpointer
195
- c_remote_handle_data_until(c_remote *remote, gyration_data_handler gyration_handler, grab_data_handler grab_handler, gpointer user_data) {
196
- gpointer rval = NULL;
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->handle != NULL &&
202
- (rval = c_remote_handle_usb_data(remote, gyration_handler, user_data)) != NULL)
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->display != NULL &&
206
- (rval = c_remote_handle_grab_data(remote, grab_handler, user_data)) != NULL)
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 gpointer
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
- VALUE rval;
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 gpointer
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
- VALUE rval;
240
- if ((rval = rb_funcall(remote->rb_remote,
241
- remote->grab_callback,
242
- 2,
243
- INT2NUM(x),
244
- INT2NUM(y))) == Qnil)
245
- return NULL;
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 gpointer
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
- VALUE rval;
257
- if ((rval = rb_funcall(remote->rb_remote,
258
- *callback,
259
- 2,
260
- INT2NUM(result),
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 NULL;
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
- if ((rval = c_remote_handle_data_until(this, c_remote_call_subscription, c_remote_call_grab_handler, this)) == NULL)
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
- if ((rval = c_remote_handle_data_until(this, c_remote_yield_gyration_data, NULL, NULL)) == NULL)
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->display == NULL)
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
- XUngrabPointer(this->display, CurrentTime);
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
@@ -0,0 +1,2 @@
1
+
2
+ require 'gyruby_ext'
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.1
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