xinput_wrapper 0.4.1 → 0.7.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a65e18160d628995917a2edbe88191d9af2463d392e323d73be0c9d18125bb1e
4
- data.tar.gz: a64ca44e47e455dc7e164ad3a07a0d45b9f0287ef5edc3d8ea718110af589755
3
+ metadata.gz: af1558bd803a67895343a73b2001a42194b5402bc8998d410d9c388b4836a593
4
+ data.tar.gz: 63e171df3280f2385b404f82673037a2a69e47e758be649253dc6701bc61a089
5
5
  SHA512:
6
- metadata.gz: e5dbaa2fbe33f068c910f5e3b81585541487b0cca4dd8fd84599705754010727c10024e8be94de12694a576e1c794ebd9350336782c404e2f9b9694753ac81ff
7
- data.tar.gz: 3a438de9f271059e494d7d39ffb1d9ed6d51247e7795033be4534aa9596da1f79719c7f92d30a3b4d9fda0bfe38cbd6a0140689b48fdf9828bcd7ddd27496abb
6
+ metadata.gz: 1874c64eed6da4e726bc9e2e8ae755e0e7e3162cce593db5109aa344210b10f414c4917daecd8e188a28287c4a1d13188b23912e42680354adcc114714476e6b
7
+ data.tar.gz: 9af8809d460ff318ff88fc6f49e310bff9ad612f8c800a9aceae0efe55d4a8f70f32cac93e704de837f6683cb09ef8a366b029d78283587bd1af6450b7246b33
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -2,14 +2,40 @@
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
+ def initialize(device: nil, verbose: true, lookup: {}, debug: false,
35
+ callback: nil )
12
36
 
37
+ @callback = callback
38
+
13
39
  # defaults to QWERTY keyboard layout
14
40
  @modifiers = {
15
41
  62 => :shift, # right control
@@ -29,7 +55,7 @@ class XInputWrapper
29
55
  40=>:d, 41=>:f, 42=>:g, 43=>:h, 44=>:j, 45=>:k, 46=>:l, 47=>:";",
30
56
  48=>:"'", 49=>nil, 52=>:z, 53=>:x, 54=>:c, 55=>:v, 56=>:b, 57=>:n,
31
57
  58=>:m, 59=>:",", 60=>:".", 61=>:/, 65=>:space,
32
- 9 => :escape,
58
+ 9 => :esc,
33
59
  66 => :capslock,
34
60
  67 => :f1,
35
61
  68 => :f2,
@@ -42,18 +68,18 @@ class XInputWrapper
42
68
  75 => :f9,
43
69
  76 => :f10,
44
70
  77 => :numlock,
45
- 78 => :scroll_lock,
71
+ 78 => :scrolllock,
46
72
  95 => :f11,
47
73
  96 => :f12,
48
- 107 => :print_screen,
74
+ 107 => :sysrq, # print_screen
49
75
  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,
76
+ 111 => :up, # arrow keys
77
+ 112 => :pageup,
78
+ 113 => :left, # arrow keys
79
+ 114 => :right, # arrow keys
80
+ 115 => :end,
81
+ 116 => :down, # arrow keys
82
+ 117 => :pagedown,
57
83
  121 => :mute,
58
84
  122 => :vol_down,
59
85
  123 => :vol_up,
@@ -78,27 +104,109 @@ class XInputWrapper
78
104
  end
79
105
 
80
106
  def listen()
81
-
107
+
108
+ @stop = false
109
+
82
110
  command = "xinput test-xi2 --root #{@device}"
83
111
 
84
112
  type = 0
85
113
  raw_keys = []
114
+ t1 = Time.now
115
+ lines = []
86
116
 
87
117
  IO.popen(command).each_line do |x|
88
118
 
119
+ break if @stop
89
120
  #print "GOT ", x
90
- raw_type = x[/EVENT type (\d+)/,1]
121
+ if x[/EVENT type \d \(Motion\)/] and (Time.now > (t1 + 0.06125)) then
122
+
123
+ type = x[/EVENT type (\d+)/,1].to_i
124
+
125
+ r = lines.join[/^\s+root: (\d+\.\d{2}\/\d+\.\d{2})/,1]
126
+
127
+ if r then
128
+
129
+ x1, y1 = r.split('/').map(&:to_f)
130
+ puts "x1: %s y1: %s" % [x1, y1] if @debug
131
+ on_mousemove(x1, y1)
132
+ @callback.on_mousemove(x1, y1) if @callback
133
+ @mouse_pos = [x1,y1]
134
+ t1 = Time.now
135
+
136
+ end
137
+
138
+ lines = [x]
139
+
140
+ elsif x[/EVENT type \d+ \(Raw(?:Key|Button)(?:Release|Press)\)/]
141
+
142
+ type = x[/EVENT type (\d+)/,1].to_i
143
+
144
+ lines = [x]
145
+
146
+
147
+ elsif [MOTION, RAWKEY_PRESS, RAWKEY_RELEASE, RAWBUTTON_PRESS,
148
+ RAWBUTTON_RELEASE].include? type
149
+
150
+ lines << x
151
+
152
+ if x == "\n" then
153
+ case lines.first[/(?<=EVENT type )\d+/].to_i
154
+ when RAWKEY_PRESS
155
+
156
+ r = lines.join[/detail: (\d+)/,1]
157
+
158
+ keycode = r.to_i if r
91
159
 
92
- type = raw_type.to_i unless raw_type.nil?
93
- next unless type == 13 or type == 14
160
+ type = lines.join[/EVENT type (\d+)/,1] .to_i
161
+
162
+ when RAWKEY_RELEASE
163
+
164
+ r = lines.join[/detail: (\d+)/,1]
165
+
166
+ keycode = r.to_i if r
167
+
168
+ type = lines.join[/EVENT type (\d+)/,1] .to_i
94
169
 
95
- keycode = x[/detail: (\d+)/,1].to_i
96
- next if keycode == 0
170
+
171
+ when RAWBUTTON_PRESS
172
+
173
+ r = lines.join[/detail: (\d+)/,1]
174
+
175
+ buttoncode = r.to_i if r
176
+
177
+ type = lines.join[/EVENT type (\d+)/,1] .to_i
178
+
179
+ when RAWBUTTON_RELEASE
180
+
181
+ r = lines.join[/detail: (\d+)/,1]
182
+
183
+ buttoncode = r.to_i if r
184
+
185
+ type = lines.join[/EVENT type (\d+)/,1] .to_i
186
+
187
+ end
188
+
189
+
190
+ else
191
+ next
192
+ end
193
+
194
+ else
195
+ next
196
+ end
197
+
198
+ next unless keycode or buttoncode
199
+ puts 'keycode: ' + keycode.inspect if @debug
200
+ puts 'buttoncode: ' + buttoncode.inspect if @debug
97
201
 
98
202
  # type = 13 means a key has been pressed
99
- if type == 13 then
203
+ if type == RAWKEY_PRESS then
100
204
 
101
- raw_keys << keycode
205
+ if @modifiers.include? raw_keys.last or @modifiers.include? keycode then
206
+ raw_keys << keycode
207
+ end
208
+
209
+ next if @modifiers.include? keycode
102
210
 
103
211
  puts 'raw_keys: ' + raw_keys.inspect if @debug
104
212
 
@@ -113,29 +221,82 @@ class XInputWrapper
113
221
  puts ('key: ' + key.inspect).debug if @debug
114
222
 
115
223
  if key then
224
+
116
225
  puts key.to_s + ' key presssed' if @verbose
117
226
  name = "on_#{key}_key".to_sym
118
227
  method(name).call if self.protected_methods.include? name
119
228
 
120
- keystring = ((key.length > 1 or key == ' ') ? "{%s}" % key : key)
121
- on_key_press keystring, keycode
229
+ keystring = ((key.length > 1 or key == ' ') ? "{%s}" % key : key)
230
+ block_given? ? yield(keystring) : on_key_press(keystring, keycode)
231
+ @callback.on_keypress(keystring, keycode) if @callback
232
+
122
233
  end
123
234
 
124
235
  else
125
236
 
126
237
  keys = raw_keys.map {|kc| @lookup[kc] }
127
238
  puts ('keys: ' + keys.inspect) if @debug
128
- on_key_press(keys.last, keycode, keys[0..-2])
239
+
240
+ if block_given? then
241
+ yield(format_key(keys.last, keys[0..-2]))
242
+ else
243
+ on_key_press(keys.last, keycode, keys[0..-2])
244
+ @callback.on_keypress(keys.last, keycode, keys[0..-2]) if @callback
245
+ end
246
+
247
+ raw_keys = []
129
248
 
130
249
  end
131
250
 
132
251
 
133
252
 
134
- elsif type == 14
253
+ # a key has been released
254
+ elsif type == RAWKEY_RELEASE
255
+
256
+ # here we are only looking to detect a
257
+ # single modifier key press and release
258
+
259
+ key = @lookup[keycode]
260
+
261
+ unless raw_keys.empty? then
262
+ puts key.to_s + ' key presssed'
263
+
264
+ if block_given? then
265
+
266
+ yield(format_key(key.to_s))
267
+
268
+ else
269
+ name = "on_#{key}_key".to_sym
270
+ method(name).call if self.protected_methods.include? name
271
+ on_key_press(key, keycode)
272
+ @callback.on_keypress(key, keycode) if @callback
273
+ end
274
+ end
135
275
 
136
276
  index = raw_keys.rindex(keycode)
137
277
  raw_keys.delete_at index if index
138
-
278
+
279
+ elsif type == RAWBUTTON_PRESS
280
+
281
+ button = BUTTONS[buttoncode-1]
282
+
283
+ case button
284
+ when :scrollup
285
+ on_mouse_scrollup()
286
+ @callback.on_mouse_scrollup() if @callback
287
+ when :scrolldown
288
+ on_mouse_scrolldown()
289
+ @callback.on_mouse_scrolldown() if @callback
290
+ else
291
+ on_mousedown(button, *@mouse_pos)
292
+ @callback.on_mousedown(button, *@mouse_pos) if @callback
293
+ end
294
+
295
+ elsif type == RAWBUTTON_RELEASE
296
+
297
+ button = BUTTONS[buttoncode-1]
298
+ on_mouseup(BUTTONS[buttoncode-1], *@mouse_pos)
299
+
139
300
  end
140
301
 
141
302
  end
@@ -147,13 +308,54 @@ class XInputWrapper
147
308
  puts 'ctrl key pressed'
148
309
  end
149
310
 
150
- def on_key_press(key, keycode, modifier)
311
+ def on_key_press(key, keycode, modifier=nil)
151
312
 
152
313
  if @debug then
153
314
  puts ('key: ' + key.inspect).debug
154
315
  end
155
316
 
156
317
  end
318
+
319
+ def on_mousedown(button, x,y)
320
+
321
+ if @debug then
322
+ puts "on_mousedown() %s click x: %s y: %s" % [button, x, y]
323
+ end
324
+
325
+ end
326
+
327
+ def on_mousemove(x,y)
328
+
329
+ if @debug then
330
+ puts "on_mousemove() x: %s y: %s" % [x, y]
331
+ end
332
+
333
+ end
334
+
335
+ def on_mouseup(button, x,y)
336
+
337
+ if @debug then
338
+ puts "on_mousedown() %s click x: %s y: %s" % [button, x, y]
339
+ end
340
+
341
+ end
342
+
343
+ def on_mouse_scrolldown()
344
+
345
+ if @debug then
346
+ puts "on_mouse_scrolldown()"
347
+ end
348
+
349
+ end
350
+
351
+ def on_mouse_scrollup()
352
+
353
+ if @debug then
354
+ puts "on_mouse_scrollup()"
355
+ end
356
+
357
+ end
358
+
157
359
 
158
360
  def on_shift_key() end
159
361
  def on_super_key() end
@@ -173,6 +375,13 @@ class XInputWrapper
173
375
 
174
376
  private
175
377
 
378
+ def format_key(key, modifier=[])
379
+
380
+ modifier.any? ? "{%s}" % (modifier + [key.to_s]).join('+') \
381
+ : key.to_s
382
+
383
+ end
384
+
176
385
  def on_leftcontrol_key() on_control_key() end
177
386
  def on_rightcontrol_key() on_control_key() end
178
387
  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.4.1
4
+ version: 0.7.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-07 00:00:00.000000000 Z
38
+ date: 2020-08-04 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