gyruby 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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