xinput_wrapper 0.5.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd5d3382f535c9b0cc5fd6def2b5b7bad34237f9eb2e602fef6c9ed21d59e107
4
- data.tar.gz: fe866a13173f38b75027676b7583470c6d350527f1d1fd0eccd978d135fb8e93
3
+ metadata.gz: 8bff9abfb50413d2ef185c472020cd348c53da5512b1f12d92ffbce10b491d2c
4
+ data.tar.gz: 4066ac4f9896ee680bff3a583bc1caf855c5bb17a43e40ff80aeaa4a9c01f263
5
5
  SHA512:
6
- metadata.gz: 4cfc590d0eab22723afe694344a339cf24b7d08989f73c270a6106320806db47442c23607b3f8afd2b1fa63d8a7f79f48fde3c86c4fc6e32cbee60beb06dc4ff
7
- data.tar.gz: 767186f2fde2a191249cea820d6eb6887d32691917b4fe48954be4f3034c56923b5a26a52fe64bb3cc79eeaf30bbeeeaa725d3b88e2bad65fbe57d290633ab22
6
+ metadata.gz: b8cd2b9b6c92418ed1d517d5f201b7e34e8ac7146ba8857d17b94638f4dd05eb626d8c75b1bd7afcc31ca475e7935302db2cb4015a75049a02fc843f3f278a9f
7
+ data.tar.gz: ce4b85f5cab6c0f613d0530c630ce227e15df0432e018b1aae15071484e7c72ef79708a21a771db7f5d50d2770aff051b4778f1d9ea9f4edfabdc4b927431459
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -2,14 +2,44 @@
2
2
 
3
3
  # file: xinput_wrapper.rb
4
4
 
5
+ # Captures keyboard or mouse events using program xinput.
6
+
7
+
8
+ # note: To display a list of xinput devices, run the
9
+ # xinput program without any options.
10
+
5
11
  require 'c32'
6
12
 
7
13
 
14
+ MOTION = 6
15
+ RAWKEY_PRESS = 13
16
+ RAWKEY_RELEASE = 14
17
+ RAWBUTTON_PRESS = 15
18
+ RAWBUTTON_RELEASE = 16
19
+ BUTTONS = %i(left middle right scrollup scrolldown)
20
+
21
+
8
22
  class XInputWrapper
9
23
  using ColouredText
24
+
25
+ attr_accessor :stop
10
26
 
11
- def initialize(device: '3', verbose: true, lookup: {}, debug: false )
27
+ # device list:
28
+ # 3 = Virtual core keyboard
29
+ # 4 = Virtual core XTEST pointer (active when using VNC)
30
+ # 5 = Virtual core XTEST keyboard (active when using VNC)
31
+ # 10 = USB Optical Mouse (locally attached)
32
+ # 11 = Microsoft Wired Keyboard 600 (locally attached)
33
+ #
34
+
35
+ # keys - add the keys you want to be captured. If empty then
36
+ # all keys are captured.
37
+
38
+ def initialize(device: nil, verbose: true, lookup: {}, debug: false,
39
+ callback: nil, keys: [] )
12
40
 
41
+ @callback, @keys = callback, keys
42
+
13
43
  # defaults to QWERTY keyboard layout
14
44
  @modifiers = {
15
45
  62 => :shift, # right control
@@ -29,7 +59,7 @@ class XInputWrapper
29
59
  40=>:d, 41=>:f, 42=>:g, 43=>:h, 44=>:j, 45=>:k, 46=>:l, 47=>:";",
30
60
  48=>:"'", 49=>nil, 52=>:z, 53=>:x, 54=>:c, 55=>:v, 56=>:b, 57=>:n,
31
61
  58=>:m, 59=>:",", 60=>:".", 61=>:/, 65=>:space,
32
- 9 => :escape,
62
+ 9 => :esc,
33
63
  66 => :capslock,
34
64
  67 => :f1,
35
65
  68 => :f2,
@@ -42,18 +72,18 @@ class XInputWrapper
42
72
  75 => :f9,
43
73
  76 => :f10,
44
74
  77 => :numlock,
45
- 78 => :scroll_lock,
75
+ 78 => :scrolllock,
46
76
  95 => :f11,
47
77
  96 => :f12,
48
- 107 => :print_screen,
78
+ 107 => :sysrq, # print_screen
49
79
  110 => :home,
50
- 111 => :up_arrow,
51
- 112 => :pgup,
52
- 113 => :left_arrow,
53
- 114 => :right_arrow,
54
- 115 => :end,
55
- 116 => :down_arrow,
56
- 117 => :pgdown,
80
+ 111 => :up, # arrow keys
81
+ 112 => :pageup,
82
+ 113 => :left, # arrow keys
83
+ 114 => :right, # arrow keys
84
+ 115 => :end,
85
+ 116 => :down, # arrow keys
86
+ 117 => :pagedown,
57
87
  121 => :mute,
58
88
  122 => :vol_down,
59
89
  123 => :vol_up,
@@ -74,31 +104,111 @@ class XInputWrapper
74
104
  }.merge(@modifiers).merge(lookup)
75
105
 
76
106
  @device, @verbose, @debug = device, verbose, debug
107
+ @mouse_pos = [0, 0]
77
108
 
78
109
  end
79
110
 
80
111
  def listen()
81
-
112
+
113
+ @stop = false
114
+
82
115
  command = "xinput test-xi2 --root #{@device}"
83
116
 
84
117
  type = 0
85
118
  raw_keys = []
119
+ t1 = Time.now
120
+ lines = []
86
121
 
87
122
  IO.popen(command).each_line do |x|
88
123
 
124
+ break if @stop
89
125
  #print "GOT ", x
90
- raw_type = x[/EVENT type (\d+)/,1]
126
+ if x[/EVENT type \d \(Motion\)/] and (Time.now > (t1 + 0.06125)) then
91
127
 
92
- type = raw_type.to_i unless raw_type.nil?
93
- next unless type == 13 or type == 14
128
+ type = x[/EVENT type (\d+)/,1].to_i
94
129
 
95
- keycode = x[/detail: (\d+)/,1].to_i
96
- next if keycode == 0
130
+ r = lines.join[/^\s+root: (\d+\.\d{2}\/\d+\.\d{2})/,1]
131
+
132
+ if r then
133
+
134
+ x1, y1 = r.split('/').map(&:to_f)
135
+ puts "x1: %s y1: %s" % [x1, y1] if @debug
136
+ on_mousemove(x1, y1)
137
+ @callback.on_mousemove(x1, y1) if @callback
138
+ @mouse_pos = [x1,y1]
139
+ t1 = Time.now
140
+
141
+ end
142
+
143
+ lines = [x]
144
+
145
+ elsif x[/EVENT type \d+ \(Raw(?:Key|Button)(?:Release|Press)\)/]
146
+
147
+ type = x[/EVENT type (\d+)/,1].to_i
148
+
149
+ lines = [x]
150
+
151
+
152
+ elsif [MOTION, RAWKEY_PRESS, RAWKEY_RELEASE, RAWBUTTON_PRESS,
153
+ RAWBUTTON_RELEASE].include? type
154
+
155
+ lines << x
156
+
157
+ if x == "\n" then
158
+ case lines.first[/(?<=EVENT type )\d+/].to_i
159
+ when RAWKEY_PRESS
160
+
161
+ r = lines.join[/detail: (\d+)/,1]
162
+
163
+ keycode = r.to_i if r
164
+
165
+ type = lines.join[/EVENT type (\d+)/,1] .to_i
166
+
167
+ when RAWKEY_RELEASE
168
+
169
+ r = lines.join[/detail: (\d+)/,1]
170
+
171
+ keycode = r.to_i if r
172
+
173
+ type = lines.join[/EVENT type (\d+)/,1] .to_i
174
+
175
+
176
+ when RAWBUTTON_PRESS
177
+
178
+ r = lines.join[/detail: (\d+)/,1]
179
+
180
+ buttoncode = r.to_i if r
181
+
182
+ type = lines.join[/EVENT type (\d+)/,1] .to_i
183
+
184
+ when RAWBUTTON_RELEASE
185
+
186
+ r = lines.join[/detail: (\d+)/,1]
187
+
188
+ buttoncode = r.to_i if r
189
+
190
+ type = lines.join[/EVENT type (\d+)/,1] .to_i
191
+
192
+ end
193
+
194
+
195
+ else
196
+ next
197
+ end
198
+
199
+ else
200
+ next
201
+ end
202
+
203
+ next unless keycode or buttoncode
204
+ puts 'keycode: ' + keycode.inspect if @debug
205
+ puts 'buttoncode: ' + buttoncode.inspect if @debug
97
206
 
98
207
  # type = 13 means a key has been pressed
99
- if type == 13 then
208
+ if type == RAWKEY_PRESS then
100
209
 
101
- if @modifiers.include? raw_keys.last or @modifiers.include? keycode then
210
+ if @modifiers.include? raw_keys.last or \
211
+ @modifiers.include? keycode then
102
212
  raw_keys << keycode
103
213
  end
104
214
 
@@ -120,10 +230,29 @@ class XInputWrapper
120
230
 
121
231
  puts key.to_s + ' key presssed' if @verbose
122
232
  name = "on_#{key}_key".to_sym
123
- method(name).call if self.protected_methods.include? name
233
+ puts 'name: ' + name.inspect if @debug
234
+
235
+ if private_methods.include? name and (@keys.empty? or \
236
+ @keys.include? key.to_sym) then
237
+ puts 'before method' if @debug
238
+ method(name).call
239
+ end
124
240
 
125
241
  keystring = ((key.length > 1 or key == ' ') ? "{%s}" % key : key)
126
- block_given? ? yield(keystring) : on_key_press(keystring, keycode)
242
+
243
+ if block_given? then
244
+
245
+ yield(keystring)
246
+
247
+ else
248
+
249
+ if @keys.empty? or @keys.include? key.to_sym then
250
+ on_key_press(keystring, keycode)
251
+ end
252
+
253
+ end
254
+
255
+ @callback.on_keypress(keystring, keycode) if @callback
127
256
 
128
257
  end
129
258
 
@@ -135,8 +264,13 @@ class XInputWrapper
135
264
  if block_given? then
136
265
  yield(format_key(keys.last, keys[0..-2]))
137
266
  else
138
- on_key_press(keys.last, keycode, keys[0..-2])
267
+
268
+ if @keys.empty? or (!@keys.empty? and \
269
+ @keys.include? keys.last) then
270
+ on_key_press(keys.last, keycode, keys[0..-2])
271
+ end
139
272
  end
273
+ @callback.on_keypress(keys.last, keycode, keys[0..-2]) if @callback
140
274
 
141
275
  raw_keys = []
142
276
 
@@ -145,7 +279,7 @@ class XInputWrapper
145
279
 
146
280
 
147
281
  # a key has been released
148
- elsif type == 14
282
+ elsif type == RAWKEY_RELEASE
149
283
 
150
284
  # here we are only looking to detect a
151
285
  # single modifier key press and release
@@ -160,51 +294,122 @@ class XInputWrapper
160
294
  yield(format_key(key.to_s))
161
295
 
162
296
  else
163
- name = "on_#{key}_key".to_sym
164
- method(name).call if self.protected_methods.include? name
297
+ name = "on_#{key.to_s}_key".to_sym
298
+ puts 'calling method' if @debug
299
+
300
+ if private_methods.include? name and (@keys.empty? or \
301
+ @keys.include? key.to_sym) then
302
+ method(name).call #if self.methods.include? name
303
+ end
304
+
165
305
  on_key_press(key, keycode)
306
+ @callback.on_keypress(key, keycode) if @callback
166
307
  end
167
308
  end
168
309
 
169
310
  index = raw_keys.rindex(keycode)
170
311
  raw_keys.delete_at index if index
171
-
312
+
313
+ elsif type == RAWBUTTON_PRESS
314
+
315
+ button = BUTTONS[buttoncode-1]
316
+
317
+ case button
318
+ when :scrollup
319
+ on_mouse_scrollup()
320
+ @callback.on_mouse_scrollup() if @callback
321
+ when :scrolldown
322
+ on_mouse_scrolldown()
323
+ @callback.on_mouse_scrolldown() if @callback
324
+ else
325
+ on_mousedown(button, *@mouse_pos)
326
+ @callback.on_mousedown(button, *@mouse_pos) if @callback
327
+ end
328
+
329
+ elsif type == RAWBUTTON_RELEASE
330
+
331
+ button = BUTTONS[buttoncode-1]
332
+ on_mouseup(BUTTONS[buttoncode-1], *@mouse_pos)
333
+
172
334
  end
173
335
 
174
336
  end
175
337
  end
176
338
 
177
- protected
339
+ private
340
+
341
+ def message(s)
342
+ puts 'msg: ' + s
343
+ end
178
344
 
179
- def on_control_key()
180
- puts 'ctrl key pressed'
345
+ def on_ctrl_key()
346
+ message 'ctrl key pressed'
181
347
  end
182
348
 
183
- def on_key_press(key, keycode, modifier)
349
+ def on_key_press(key, keycode, modifier=nil)
184
350
 
185
351
  if @debug then
186
352
  puts ('key: ' + key.inspect).debug
187
353
  end
188
354
 
189
355
  end
356
+
357
+ def on_mousedown(button, x,y)
358
+
359
+ if @debug then
360
+ puts "on_mousedown() %s click x: %s y: %s" % [button, x, y]
361
+ end
362
+
363
+ end
364
+
365
+ def on_mousemove(x,y)
366
+
367
+ if @debug then
368
+ puts "on_mousemove() x: %s y: %s" % [x, y]
369
+ end
370
+
371
+ end
372
+
373
+ def on_mouseup(button, x,y)
374
+
375
+ if @debug then
376
+ puts "on_mousedown() %s click x: %s y: %s" % [button, x, y]
377
+ end
378
+
379
+ end
380
+
381
+ def on_mouse_scrolldown()
382
+
383
+ if @debug then
384
+ puts "on_mouse_scrolldown()"
385
+ end
386
+
387
+ end
388
+
389
+ def on_mouse_scrollup()
390
+
391
+ if @debug then
392
+ puts "on_mouse_scrollup()"
393
+ end
394
+
395
+ end
396
+
190
397
 
191
398
  def on_shift_key() end
192
399
  def on_super_key() end
193
400
 
194
- def on_f1_key() end
195
- def on_f2_key() end
196
- def on_f3_key() end
197
- def on_f4_key() end
198
- def on_f5_key() end
199
- def on_f6_key() end
200
- def on_f7_key() end
201
- def on_f8_key() end
202
- def on_f9_key() end
203
- def on_f10_key() end
204
- def on_f11_key() end
205
- def on_f12_key() end
206
-
207
- private
401
+ def on_f1_key() message 'f1' end
402
+ def on_f2_key() message 'f2' end
403
+ def on_f3_key() message 'f3' end
404
+ def on_f4_key() message 'f4' end
405
+ def on_f5_key() message 'f5' end
406
+ def on_f6_key() message 'f6' end
407
+ def on_f7_key() message 'f7' end
408
+ def on_f8_key() message 'f8' end
409
+ def on_f9_key() message 'f9' end
410
+ def on_f10_key() message 'f10' end
411
+ def on_f11_key() message 'f11' end
412
+ def on_f12_key() message 'f12' end
208
413
 
209
414
  def format_key(key, modifier=[])
210
415
 
@@ -213,6 +418,7 @@ class XInputWrapper
213
418
 
214
419
  end
215
420
 
421
+ def on_alt_key() message 'alt' end
216
422
  def on_leftcontrol_key() on_control_key() end
217
423
  def on_rightcontrol_key() on_control_key() end
218
424
  def on_left_alt_key() on_alt_key() end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xinput_wrapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
@@ -11,52 +11,52 @@ cert_chain:
11
11
  - |
12
12
  -----BEGIN CERTIFICATE-----
13
13
  MIIEXjCCAsagAwIBAgIBATANBgkqhkiG9w0BAQsFADAsMSowKAYDVQQDDCFnZW1t
14
- YXN0ZXIvREM9amFtZXNyb2JlcnRzb24vREM9ZXUwHhcNMTkwMjEwMTU1NTM1WhcN
15
- MjAwMjEwMTU1NTM1WjAsMSowKAYDVQQDDCFnZW1tYXN0ZXIvREM9amFtZXNyb2Jl
16
- cnRzb24vREM9ZXUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQD2pELS
17
- hfHN+He5s77qpnUO4j6GDr1B9PDIKqJDBz+kJCUGXsLzyHnKK8iIblXtETyIJn9F
18
- euzS6ohPh64xfBcKrnF7bSUAXsdC/PZIsNgvSp4Vuguxpe6wDHfaqBhV2KcOjGrP
19
- tnZRvJJHWBczBzMw+BAj0d5Zp5QZaVXDx3mN13t2j6tUncwLF3NYIlaFA7lN4uuV
20
- hiFyqlkk+ELO8eptDF5Wkel5ZjtALo9jOq04KAlImZ7cnFLD1zbAXWiKPyEvSAeL
21
- fGONgtYGEBwIKKeisGTucndYa1iwQOnFLjCixclGH+6+YInlbHUzl/JrFHSEXIYb
22
- 0jU2pHEu+xQlB2xdKiJF6Z/JWWabJ+hyMifxnyPYLW53QGV5fu2uAHDVUCplwhBW
23
- hOBeqmV8SCjX7aYytN7TiqO4Th2kP2tPLQqynFQ3ceNiTcjk1fkliXlv+lc8IFiS
24
- 25oy9Th0M3O7+rs11i1eeaAlvrZ0TWv5qFpJUrMB53UpndLxeroiPw/AzocCAwEA
25
- AaOBijCBhzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUQLWJJ/fU
26
- p6suCssS39/w2O9MQhUwJgYDVR0RBB8wHYEbZ2VtbWFzdGVyQGphbWVzcm9iZXJ0
14
+ YXN0ZXIvREM9amFtZXNyb2JlcnRzb24vREM9ZXUwHhcNMjAwODAzMjEwMTE2WhcN
15
+ MjEwODAzMjEwMTE2WjAsMSowKAYDVQQDDCFnZW1tYXN0ZXIvREM9amFtZXNyb2Jl
16
+ cnRzb24vREM9ZXUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDdnN5k
17
+ jxSdi5vMTqhRRJ8yFAV3MYUs/W6NU+rMUk1uqTC/J+fFox8tg7t4VzQoQq539Onk
18
+ 5iPFJhwo3jAYKIyc+LX4e3CtQMdrheyY/XkaTSu1yPR+c4lT8nhKUf4gI28hNXcx
19
+ lNekrvzzXBVZMGs5F+gKzOYUFS+i0jGPaVaison+iaGVLcjc2/t3AGIQeOHo7QYv
20
+ 6Sswkj9Er4jkwJKHGAvLvh+KTcm/aImIfV4v5FUm6xJMi42lsDWbaRyACtAtNgKF
21
+ cl/pMlb3d5Si3vIcbKlktHR2K5KLtBuFqu/vWdlKygYzpnr3rWjAls8wr2fv6WiS
22
+ BqX3XVtZB4Fh/xriLY3Fj3Qo9RWuGf9S3BIGGxcnsr53bsO1zKXvbNr5UzP9d0+8
23
+ dF5lJ4bu8rw524nYypy39Is9PlHI7L6nxQjy82AmzloxEc31nYM7FF2pjkStv5H5
24
+ zfb4PVsCblnUstufNJWKrg32E2wbzXhzq8+E/U7Y7FM4zABWcyeHtt4Mv0MCAwEA
25
+ AaOBijCBhzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU+hzRpZTx
26
+ g/xK+Tn1+5WHz7CK1y8wJgYDVR0RBB8wHYEbZ2VtbWFzdGVyQGphbWVzcm9iZXJ0
27
27
  c29uLmV1MCYGA1UdEgQfMB2BG2dlbW1hc3RlckBqYW1lc3JvYmVydHNvbi5ldTAN
28
- BgkqhkiG9w0BAQsFAAOCAYEAAuFxNNh+nIt4Ba3bWUilYAVhEYROr32uTWFmyL8w
29
- T4bMAe8OC9PzuIAg3C4jzks008Fbfi7Hcm4Pqc548kbavWtLquzdNwNqasywcweb
30
- FIIGeYpRy2BmHeP8+RK66T+HfdAGGmy60L/q5kTJtV1g9wDTg5glxv7OvlShgKTM
31
- ZgaJi9JerKv6dsB6r1OnnVy73BfQ0eiN2/vwDHCB9Op2E5JKFqUlklGaKvbEsMoV
32
- Ou4ilgqq7OROhrul809YLlc0VHRfAiaOqeO5l1Ccfq9Q2LUZwGhtw+EIKSrgWQZA
33
- 1aSaQX/s+LpAVRGJlWrVa+uQ21aUdItSdkKaRNK4MxQHPu8s/9sgeZRMEO5wJc7i
34
- bvgBqmvgsZwFmSRWE1K/PusL86uaYCw5pTWA+BquQ7taMwhGKqdDlHLp+SQ1Wd82
35
- rryowfoo6nLmegcIZjm+zz/gkT/0udwMMVm2gwo0bIRQuQOLmd7IUNzYQKZQOGMA
36
- g4ETbI8IEC3VCaoECdunsS3t
28
+ BgkqhkiG9w0BAQsFAAOCAYEAXg+9mfaTHPcbez7P0XnwGL0C4zdPwHtBUXioPwjP
29
+ okklRkFzMQnxArm8U9557g8cXY//vKp/cFBdCExE8lLxAOB9gHswJju0g99Yx7gY
30
+ iEV3TWv5qkLQ+n8zdTd8TxEyjWB6ZXOJcE+/cTq9Ly1j4bhf9QTdul02TBukEp6d
31
+ opP5/Yvt1GX0ED98olew/pm+KoKKNkcJzSgEH44O+pCfTi4h2STOFRvXVYaB3AH8
32
+ hpuUFcbxzPhBxOChGPAGZLaf7zurw8B2Q1vP75RV9gJ1M6NKU6Hlb6vMJQ3jz8qv
33
+ GIVFoKMCcJH2EImrG47doRVhQPIlxfz7d3f+FdYgnp7wtuFi/byklu1D2G8ZE8Ax
34
+ 1s9Njv/guBMNkw+RV6IlpMtT0yeVvHeYTt0tPKeyrtBrSfsexA3393T7To6Ms+1s
35
+ B//EUqLB2VKtMmcrYMc2FfbLwllNLY4TRq+/lgVLoDb7oLHsiggYSLZS6lPBIQj/
36
+ YnYsDKwN5siDA79sB0fqq2ml
37
37
  -----END CERTIFICATE-----
38
- date: 2019-04-08 00:00:00.000000000 Z
38
+ date: 2020-08-25 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: c32
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: '0.1'
47
44
  - - ">="
48
45
  - !ruby/object:Gem::Version
49
- version: 0.1.2
46
+ version: 0.2.0
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '0.2'
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
- - - "~>"
55
- - !ruby/object:Gem::Version
56
- version: '0.1'
57
54
  - - ">="
58
55
  - !ruby/object:Gem::Version
59
- version: 0.1.2
56
+ version: 0.2.0
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '0.2'
60
60
  description:
61
61
  email: james@jamesrobertson.eu
62
62
  executables: []
@@ -83,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
83
  - !ruby/object:Gem::Version
84
84
  version: '0'
85
85
  requirements: []
86
- rubygems_version: 3.0.1
86
+ rubygems_version: 3.0.3
87
87
  signing_key:
88
88
  specification_version: 4
89
89
  summary: A wrapper for the Linux utility xinput.
metadata.gz.sig CHANGED
Binary file