xinput_wrapper 0.4.1 → 0.7.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: 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