vigilem-evdev 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/ext/Rakefile +31 -0
  4. data/ext/rake_helper.rb +10 -0
  5. data/lib/vigilem/_evdev.rb +24 -0
  6. data/lib/vigilem/evdev.rb +14 -0
  7. data/lib/vigilem/evdev/at_exit.rb +8 -0
  8. data/lib/vigilem/evdev/context_filter.rb +92 -0
  9. data/lib/vigilem/evdev/demultiplexer.rb +26 -0
  10. data/lib/vigilem/evdev/device.rb +182 -0
  11. data/lib/vigilem/evdev/device_capabilities.rb +53 -0
  12. data/lib/vigilem/evdev/dom.rb +8 -0
  13. data/lib/vigilem/evdev/dom/adapter.rb +87 -0
  14. data/lib/vigilem/evdev/dom/code_values_tables.rb +172 -0
  15. data/lib/vigilem/evdev/dom/input_event_converter.rb +329 -0
  16. data/lib/vigilem/evdev/dom/input_event_utils.rb +48 -0
  17. data/lib/vigilem/evdev/dom/key_values_tables.rb +248 -0
  18. data/lib/vigilem/evdev/dom/kp_table.rb +52 -0
  19. data/lib/vigilem/evdev/focus_context_filter.rb +124 -0
  20. data/lib/vigilem/evdev/input_system_handler.rb +69 -0
  21. data/lib/vigilem/evdev/key_map_cache.rb +64 -0
  22. data/lib/vigilem/evdev/multiplexer.rb +73 -0
  23. data/lib/vigilem/evdev/system.rb +17 -0
  24. data/lib/vigilem/evdev/system/input.rb +1053 -0
  25. data/lib/vigilem/evdev/system/input/event.rb +4 -0
  26. data/lib/vigilem/evdev/system/input/input_event.rb +33 -0
  27. data/lib/vigilem/evdev/system/int.rb +9 -0
  28. data/lib/vigilem/evdev/system/ioctl.rb +143 -0
  29. data/lib/vigilem/evdev/system/keymap_loaders.rb +89 -0
  30. data/lib/vigilem/evdev/system/keymap_loaders/dumpkeys_loader.rb +98 -0
  31. data/lib/vigilem/evdev/system/keymap_loaders/kmap_loader.rb +74 -0
  32. data/lib/vigilem/evdev/system/posix_types.rb +5 -0
  33. data/lib/vigilem/evdev/system/time.rb +21 -0
  34. data/lib/vigilem/evdev/transfer_agent.rb +40 -0
  35. data/lib/vigilem/evdev/version.rb +5 -0
  36. data/lib/vigilem/evdev/vty_context_filter.rb +216 -0
  37. data/spec/after_each_example_group.rb +29 -0
  38. data/spec/delete_test_cache_after_group.rb +26 -0
  39. data/spec/spec_helper.rb +30 -0
  40. data/spec/vigilem/_evdev_spec.rb +11 -0
  41. data/spec/vigilem/evdev/context_filter_spec.rb +114 -0
  42. data/spec/vigilem/evdev/demultiplexer_spec.rb +44 -0
  43. data/spec/vigilem/evdev/device_capabilities_spec.rb +0 -0
  44. data/spec/vigilem/evdev/device_spec.rb +97 -0
  45. data/spec/vigilem/evdev/dom/adapter_spec.rb +5 -0
  46. data/spec/vigilem/evdev/dom/input_event_converter_spec.rb +253 -0
  47. data/spec/vigilem/evdev/dom/input_event_utils_spec.rb +23 -0
  48. data/spec/vigilem/evdev/focus_context_filter_spec.rb +112 -0
  49. data/spec/vigilem/evdev/input_system_handler_spec.rb +146 -0
  50. data/spec/vigilem/evdev/key_map_cache_spec.rb +65 -0
  51. data/spec/vigilem/evdev/multiplexer_spec.rb +55 -0
  52. data/spec/vigilem/evdev/system/input/input_event_spec.rb +33 -0
  53. data/spec/vigilem/evdev/system/input_spec.rb +274 -0
  54. data/spec/vigilem/evdev/system/int_spec.rb +30 -0
  55. data/spec/vigilem/evdev/system/ioctl_spec.rb +206 -0
  56. data/spec/vigilem/evdev/system/keymap_loaders/dumpkeys_loader_spec.rb +5 -0
  57. data/spec/vigilem/evdev/system/keymap_loaders/kmap_loader_spec.rb +24 -0
  58. data/spec/vigilem/evdev/system/keymap_loaders_spec.rb +22 -0
  59. data/spec/vigilem/evdev/system/posix_types_spec.rb +15 -0
  60. data/spec/vigilem/evdev/system/time_spec.rb +18 -0
  61. data/spec/vigilem/evdev/transfer_agent_spec.rb +57 -0
  62. data/spec/vigilem/evdev/vty_context_filter_spec.rb +282 -0
  63. metadata +286 -0
@@ -0,0 +1,8 @@
1
+ module Vigilem
2
+ module Evdev
3
+ module DOM
4
+ end
5
+ end
6
+ end
7
+
8
+ require 'vigilem/evdev/dom/adapter'
@@ -0,0 +1,87 @@
1
+ require 'vigilem/core/adapters'
2
+
3
+ require 'vigilem/core/event_handler'
4
+
5
+ require 'vigilem/core/eventable'
6
+
7
+ require 'vigilem/evdev'
8
+
9
+ require 'vigilem/evdev/dom/input_event_converter'
10
+
11
+ module Vigilem
12
+ module Evdev
13
+ class KeyEvent < SimpleDelegator
14
+
15
+ #
16
+ #
17
+ def is_a?
18
+ __getobj__.is_a?
19
+ end
20
+
21
+ #
22
+ #
23
+ def self.cast(event)
24
+ new(event)
25
+ end
26
+ end
27
+ module DOM
28
+ #
29
+ #
30
+ class Adapter
31
+
32
+ include InputEventConverter
33
+
34
+ include Core::Adapters::BufferedAdapter
35
+
36
+ include Core::EventHandler
37
+
38
+ default_handler()
39
+
40
+ #
41
+ # @param devices
42
+ def initialize(*devices)
43
+ initialize_buffered(InputSystemHandler.new(*devices))
44
+ on(KeyEvent) {|event| to_dom_key_event(event) }
45
+ end
46
+
47
+ #
48
+ # @return [Hash]
49
+ def type_hash
50
+ @type_hash ||= { System::Input::EV_KEY => KeyEvent }
51
+ end
52
+
53
+ #
54
+ #
55
+ def to_dom_event(event)
56
+ handle(event)
57
+ end
58
+
59
+ include Core::Eventable
60
+
61
+ #
62
+ # @param [Integer] limit, defaults to 1
63
+ # @return [Array<DOM::Event>]
64
+ def read_many_nonblock(limit=1)
65
+ synchronize {
66
+ buffered!(limit) do |len_remainder|
67
+ dom_src_events = link.read_many_nonblock(len_remainder).map do |event|
68
+ handle(cast(event))
69
+ end.compact.flatten
70
+ # the DOM converter may return more events than called for
71
+ ret, to_buffer = Support::Utils.split_at(dom_src_events, len_remainder)
72
+ buffer.concat([*to_buffer])
73
+ ret
74
+ end
75
+ }
76
+ end
77
+
78
+ #
79
+ # @param event
80
+ def cast(event)
81
+ type_hash[event.type].respond.cast(event)
82
+ end
83
+
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,172 @@
1
+ require 'vigilem/support/key_map'
2
+
3
+ module Vigilem
4
+ module Evdev::DOM
5
+ # @todo there are plenty of mappings missing
6
+ # http://www.w3.org/TR/2014/WD-DOM-Level-3-Events-code-20140612/
7
+ module CodeValuesTables
8
+
9
+ include Evdev::System::Input::KeysAndButtons
10
+
11
+ code_values = Vigilem::DOM::CodeValues
12
+
13
+ WritingSystemKeys = Support::KeyMap.new({
14
+ KEY_GRAVE => 'Backquote',
15
+ KEY_BACKSLASH => 'Backslash',
16
+ KEY_BACKSPACE => 'Backspace',
17
+ KEY_LEFTBRACE => 'BracketLeft',
18
+ KEY_RIGHTBRACE => 'BracketRight',
19
+ KEY_COMMA => 'Comma',
20
+ KEY_EQUAL => 'Equal',
21
+ :'?' => ['IntlBackslash', 'IntlHash'],
22
+ KEY_RO => 'IntlRo',
23
+ KEY_YEN => 'IntlYen',
24
+ KEY_MINUS => 'Minus',
25
+ KEY_DOT => 'Period',
26
+ KEY_APOSTROPHE => 'Quote',
27
+ KEY_SEMICOLON => 'Semicolon',
28
+ KEY_SLASH => 'Slash'
29
+ })
30
+
31
+ FunctionalKeys = Support::KeyMap.new({
32
+ KEY_LEFTALT => 'AltLeft',
33
+ KEY_RIGHTALT => 'AltRight',
34
+ KEY_CAPSLOCK => 'CapsLock',
35
+ KEY_COMPOSE => 'ContextMenu',
36
+ KEY_LEFTCTRL => 'ControlLeft',
37
+ KEY_RIGHTCTRL => 'ControlRight',
38
+ KEY_ENTER => 'Enter',
39
+ KEY_LEFTMETA => 'OSLeft',
40
+ KEY_RIGHTMETA => 'OSRight',
41
+ KEY_LEFTSHIFT => 'ShiftLeft',
42
+ KEY_RIGHTSHIFT => 'ShiftRight',
43
+ KEY_SPACE => 'Space',
44
+ KEY_TAB => 'Tab',
45
+ :'?' => ['Convert', 'KanaMode', 'NonConvert'],
46
+ KEY_HANGEUL => 'Lang1',
47
+ KEY_HANJA => 'Lang2',
48
+ KEY_KATAKANA => 'Lang3',
49
+ KEY_HIRAGANA => 'Lang4',
50
+ KEY_ZENKAKUHANKAKU => 'Lang5'
51
+ })
52
+
53
+
54
+ ControlPadSection = Support::KeyMap.new({
55
+ KEY_DELETE => 'Delete',
56
+ KEY_END => 'End',
57
+ KEY_HELP => 'Help',
58
+ KEY_HOME => 'Home',
59
+ KEY_INSERT => 'Insert',
60
+ KEY_PAGEDOWN => 'Page Down',
61
+ KEY_PAGEUP => 'Page Up'
62
+ })
63
+
64
+ ArrowPadSection = Support::KeyMap[[KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_UP].zip(code_values::ArrowPadSection)]
65
+
66
+ NumpadSection = Support::KeyMap.new({
67
+ KEY_NUMLOCK => 'NumLock',
68
+ KEY_KP0 => 'Numpad0',
69
+ KEY_KP1 => 'Numpad1',
70
+ KEY_KP2 => 'Numpad2',
71
+ KEY_KP3 => 'Numpad3',
72
+ KEY_KP4 => 'Numpad4',
73
+ KEY_KP5 => 'Numpad5',
74
+ KEY_KP6 => 'Numpad6',
75
+ KEY_KP7 => 'Numpad7',
76
+ KEY_KP8 => 'Numpad8',
77
+ KEY_KP9 => 'Numpad9',
78
+ KEY_KPPLUS => 'NumpadAdd',
79
+ KEY_KPDOT => 'NumpadBackspace',
80
+ :'?' => ['NumpadClear', 'NumpadClearEntry', 'NumpadComma',
81
+ 'NumpadEqual', 'NumpadMemoryAdd', 'NumpadMemoryClear',
82
+ 'NumpadMemoryRecall', 'NumpadMemoryStore',
83
+ 'NumpadMemorySubtract', 'NumpadParenLeft',
84
+ 'NumpadParenRight'],
85
+ KEY_KPDOT => 'NumpadDecimal',
86
+ KEY_KPSLASH => 'NumpadDivide',
87
+ KEY_KPENTER => 'NumpadEnter',
88
+ KEY_KPASTERISK => 'NumpadMultiply',
89
+ KEY_KPMINUS => 'NumpadSubtract'
90
+ })
91
+
92
+ FunctionSection = Support::KeyMap.new({
93
+ KEY_ESC => 'Escape',
94
+ KEY_F1 => 'F1',
95
+ KEY_F2 => 'F2',
96
+ KEY_F3 => 'F3',
97
+ KEY_F4 => 'F4',
98
+ KEY_F5 => 'F5',
99
+ KEY_F6 => 'F6',
100
+ KEY_F7 => 'F7',
101
+ KEY_F8 => 'F8',
102
+ KEY_F9 => 'F9',
103
+ KEY_F10 => 'F10',
104
+ KEY_F11 => 'F11',
105
+ KEY_F12 => 'F12',
106
+ KEY_FN => 'Fn',
107
+ :'?' => 'FLock',
108
+ KEY_PRINT => 'PrintScreen',
109
+ KEY_SCROLLLOCK => 'ScrollLock',
110
+ KEY_PAUSE => 'Pause'
111
+ })
112
+
113
+ MediaKeys = Support::KeyMap.new({
114
+ :'?' => ['BrowserBack', 'BrowserFavorites',
115
+ 'BrowserForward', 'BrowserHome',
116
+ 'BrowserRefresh', 'BrowserSearch',
117
+ 'BrowserStop'],
118
+ [KEY_EJECTCD,
119
+ KEY_EJECTCLOSECD] => 'Eject',
120
+ KEY_PROG1 => 'LaunchApp1',
121
+ KEY_PROG1 => 'LaunchApp2',
122
+ KEY_EMAIL => 'LaunchMail',
123
+ KEY_PLAYPAUSE => 'MediaPlayPause',
124
+ KEY_PROGRAM => 'MediaSelect',
125
+ KEY_STOPCD => 'MediaStop',
126
+ KEY_NEXTSONG => 'MediaTrackNext',
127
+ KEY_PREVIOUSSONG => 'MediaTrackPrevious',
128
+ KEY_POWER => 'Power',
129
+ KEY_SLEEP => 'Sleep',
130
+ KEY_VOLUMEDOWN => 'VolumeDown',
131
+ KEY_MUTE => 'VolumeMute',
132
+ KEY_VOLUMEUP => 'VolumeUp',
133
+ KEY_WAKEUP => 'WakeUp'
134
+ })
135
+
136
+ LegacyKeysandNon_StandardKeys = Support::KeyMap.new({
137
+ :'?' => ['Hyper','Super', 'Turbo', 'Abort', 'Resume'],
138
+ KEY_SUSPEND => 'Suspend',
139
+ KEY_AGAIN => 'Again',
140
+ KEY_COPY => 'Copy',
141
+ KEY_CUT => 'Cut',
142
+ KEY_FIND => 'Find',
143
+ KEY_OPEN => 'Open',
144
+ KEY_PASTE => 'Paste',
145
+ KEY_PROPS => 'Props',
146
+ KEY_SELECT => 'Select',
147
+ KEY_UNDO => 'Undo',
148
+ KEY_HIRAGANA => 'Hiragana',
149
+ KEY_KATAKANA => 'Katakana'
150
+ })
151
+
152
+ Sections = [WritingSystemKeys, FunctionalKeys, ControlPadSection,
153
+ ArrowPadSection, NumpadSection, FunctionSection,
154
+ MediaKeys, LegacyKeysandNon_StandardKeys]
155
+
156
+ def self.add_names(key_map)
157
+ key_map.left_side_alias(:keycode)
158
+ key_map.left_side_alias(:keycodes)
159
+ key_map.right_side_alias(:dom_code)
160
+ key_map.right_side_alias(:dom_codes)
161
+ end
162
+
163
+ Sections.each {|sec| add_names(sec) }
164
+ end
165
+
166
+ CodeTable = CodeValuesTables::Sections.each_with_object(Support::KeyMap.new()) do |table, memo|
167
+ memo.merge! table
168
+ end
169
+
170
+ CodeValuesTables.add_names(CodeTable)
171
+ end
172
+ end
@@ -0,0 +1,329 @@
1
+ require 'vigilem/dom'
2
+
3
+ require 'vigilem/core/lockable_pipeline_component'
4
+
5
+ require 'vigilem/_evdev'
6
+
7
+ require 'vigilem/evdev/system'
8
+
9
+ require 'vigilem/evdev/system/input'
10
+
11
+ require 'vigilem/evdev/dom/input_event_utils'
12
+
13
+ require 'vigilem/evdev/system/keymap_loaders'
14
+
15
+ require 'vigilem/evdev/dom/code_values_tables'
16
+ require 'vigilem/evdev/dom/key_values_tables'
17
+ require 'vigilem/evdev/dom/kp_table'
18
+
19
+ module Vigilem
20
+ module Evdev
21
+ module DOM
22
+ # @todo fix charsets, printable characters, etc, split up KeyTables
23
+ # @todo fixme REFACTOR!
24
+ module InputEventConverter
25
+
26
+ KEYCODES = System::Input::KeysAndButtons.constants.each_with_object({}) do |const, hsh|
27
+ hsh[System::Input.const_get(const)] = const
28
+ end
29
+
30
+ PRINTABLE_CHARS = [0x0008..0x000a, 0x0020..0x00ff]
31
+
32
+ UNKNOWN_VAL = 'Unidentified'
33
+
34
+ include CodeValuesTables
35
+ include KeyValuesTables
36
+
37
+ include Core::LockablePipelineComponent
38
+
39
+ include InputEventUtils
40
+
41
+ attr_writer :current_keys, :key_map
42
+
43
+ private :current_keys=
44
+
45
+ KeymapLoaders = System::KeymapLoaders
46
+
47
+ #
48
+ # @return [NilClass]
49
+ def initialize_input_event_converter
50
+ key_map
51
+ nil
52
+ end
53
+
54
+ #
55
+ # @return [KeyMap]
56
+ def key_map
57
+ Evdev.key_map
58
+ end
59
+
60
+ #
61
+ # @return [Array]
62
+ def current_keys
63
+ @current_keys ||= []
64
+ end
65
+
66
+ # gets the current modifier keys
67
+ # @todo capsshift
68
+ # @return [Array<Array<String, String>>] [['ctrl', 'r']]
69
+ def current_mod_keys_w_loc
70
+ current_keys.map do |event|
71
+ if (key = event.key) =~ /c(on)?tro?l|alt|shift/i and
72
+ event.type == 'keydown'
73
+ loc = to_dom_location_common_str(event.location)
74
+ [key.gsub('control', 'ctrl').downcase, loc.downcase]
75
+ end
76
+ end.compact
77
+ end
78
+
79
+ # gets the current modifier keys
80
+ # @return [Array<String>] i.e. ['ctrl']
81
+ def current_mod_keys
82
+ current_mod_keys_w_loc.map(&:first)
83
+ end
84
+
85
+ # grabs the current modifier keys and adds the location
86
+ # to the end
87
+ # @return [Array<String>] i.e. ['ctrlr']
88
+ def current_mod_keys_keymap_fmt
89
+ current_mod_keys_w_loc.map do |mod_w_loc|
90
+ Support::KeyMap.mod_weights.keys & [mod_w_loc.first, mod_w_loc.join]
91
+ end.compact.flatten.uniq.sort {|a,b| Support::KeyMap.mod_weights[a] <=> Support::KeyMap.mod_weights[b] }
92
+ # ruby 2.0.0p384 (2014-01-12) [x86_64-linux-gnu] irb(main):006:0> [1,2,3,4].sort {|a| a } => [4, 3, 1, 2]
93
+ end
94
+
95
+ # gets the keysyms for the given keycode string and current mod keys
96
+ # @param [String] keycode_str, i.e. "keycode30"
97
+ # @return [Array<String> || String] the keysyms and (uni|hex)codes
98
+ def keysyms(keycode_str)
99
+ key_map.keysyms(Support::Utils.unwrap_ary([current_mod_keys_keymap_fmt, keycode_str].flatten))
100
+ end
101
+
102
+ def keysyms!(keycode_str)
103
+ key_map.keysyms(Support::Utils.unwrap_ary(keycode_str))
104
+ end
105
+
106
+ # gets the DOM::KeyEvent#type from InputEvent#value and
107
+ # Dom::KeyEvent#key
108
+ # @param [Integer] event_value, InputEvent#value
109
+ # @param [String] dom_key_value, DOM::KeyEvent#key
110
+ # @return [Array<String> || NilClass] the type of event based on
111
+ # the given args
112
+ def dom_type(event_value, dom_key_value)
113
+ synchronize {
114
+ type = dom_types[event_value]
115
+ if dom_key_value.unpack('U*').size > 1
116
+ type.take(1)
117
+ else
118
+ type
119
+ end
120
+ }
121
+ end
122
+
123
+ #
124
+ # @return [Hash]
125
+ def dom_types
126
+ @dom_types ||= { 0 => ['keyup'], 1 => (down_press = %w(keydown keypress)), 2 => down_press }
127
+ end
128
+
129
+ # takes a code from an input_event and returns a String
130
+ # representing a DOM::KeyEvent#key
131
+ # @todo refactor
132
+ # @param [Integer] event_code, InputEvent#code
133
+ # @return [String] the representing DOM::KeyEvent#key
134
+ def dom_key(event_code, led_names)
135
+ # use infocmp?, terminfo
136
+ synchronize {
137
+ keycode_str = InputEventUtils.event_code_to_keycode_str(event_code)
138
+
139
+ # raise if this is nil?, char_ref will error if char_code.nil?
140
+ code_or_sym = [*keysyms(keycode_str)].last
141
+
142
+ char_code, sym = if char_ref?(code_or_sym)
143
+ [code_or_sym, key_map.info.keysyms[code_or_sym]]
144
+ else
145
+ [key_map.info.char_refs[code_or_sym], code_or_sym]
146
+ end
147
+
148
+ char = char_ref(char_code)
149
+
150
+ white_space_key = (WhitespaceKeys.keysyms.include?(event_code) or
151
+ WhitespaceKeys.keysyms.include?(sym))
152
+
153
+ if char and not white_space_key
154
+ if char.respond_to?(:upcase) and
155
+ led_names.include?(:LED_CAPSL) and
156
+ keysyms.grep(/shift/).empty?
157
+ return char.upcase
158
+ else
159
+ return char
160
+ end
161
+ elsif char_ref?(char_code) and (no_mods = [*keysyms!(keycode_str)].last)
162
+ if char = char_ref(no_mods)
163
+ return char
164
+ end
165
+ end
166
+
167
+ if (not white_space_key) and
168
+ led_names.include?(:LED_NUML) and (kpkey = KPTable.char(sym))
169
+ kpkey
170
+ elsif (key = KeyTable.dom_codes(sym)) and not key.is_a? Array
171
+ key
172
+ elsif keyfrom_event = KeyTable.dom_codes(event_code) and
173
+ not keyfrom_event.is_a? Array
174
+ keyfrom_event
175
+ else
176
+ UNKNOWN_VAL
177
+ end
178
+ }
179
+ end
180
+
181
+ #
182
+ #
183
+ def printable_char?(hex_char)
184
+ Support::Utils.in_ranged_array?(PRINTABLE_CHARS, hex_char)
185
+ end
186
+
187
+ #
188
+ # @return [NilClass || Fixnum]
189
+ def char_ref?(str)
190
+ str =~ /^\+?U\+|0x0[\dA-z]+/i # unicode or hex_string
191
+ end
192
+
193
+ # @todo fixme!
194
+ # @param [String] str
195
+ # @return
196
+ def char_ref(str)
197
+ #"%c" % char
198
+ hex_dec = str.gsub(/\+?U\+/i, '').hex
199
+ if str =~ /^\+?U\+/ # unicode
200
+ hex_dec.chr('UTF-8')
201
+ elsif printable_char?(hex_dec)
202
+ hex_dec.chr('iso-8859-1') # default dumpkeys encoding
203
+ end
204
+ end
205
+
206
+ # gets the DOM::KeyEvent#code fromm a keycode anem and
207
+ # a DOMLLKeyEvent#key
208
+ # @todo needs to be more strict
209
+ # @todo items modified shift still returns the code for
210
+ # the unshifted
211
+ # @param [Fixnum] event_code
212
+ # @param [String] dom_key, DOM::KeyEvent#key
213
+ # @return [String] DOM::KeyEvent#code
214
+ def dom_code(event_code, dom_key_value)
215
+ keycode_name = KEYCODES[event_code]
216
+
217
+ ret_code = if dom_key_value =~ /^[a-z]$/i
218
+ "Key#{dom_key_value.upcase}"
219
+ elsif dom_key_value =~ /^[0-9]$/
220
+ if keycode_name =~ /^KEY_KP/
221
+ "Numpad#{dom_key_value}"
222
+ else
223
+ "Digit#{dom_key_value}"
224
+ end
225
+ elsif not (codes = [*CodeTable.dom_codes(event_code)]).empty?
226
+ Support::Utils.unwrap_ary(codes)
227
+ elsif dom_key_value != UNKNOWN_VAL
228
+ "#{dom_key_value}#{InputEventUtils.location_str_from_keycode_name(keycode_name)}"
229
+ end
230
+
231
+ ret_code ||= UNKNOWN_VAL
232
+ end
233
+
234
+ # gets the DOM_KEY_LOCATION_* of the keycode
235
+ # @param [String || Symbol] keycode_name
236
+ # @return [Integer] dom location, DOM::KeyEvent::KeyLocations
237
+ def dom_location(keycode_name)
238
+ ::VDOM::Utils.common_str_to_dom_location(
239
+ keycode_name.to_s.gsub(/(KEY_)?((KP)|(R)IGHT|(L)EFT)(.*)/, '\3\4\5')
240
+ )
241
+ end
242
+
243
+ # creates a SharedKeyboardAndMouseEventInit from #current_mod_keys
244
+ # and a passed in keycode_name
245
+ # @param [String ||Symbol] keycode_name, KEY_RIGHTCTRL
246
+ # @return [Array<symbol>]
247
+ def dom_modifiers(keycode_name)
248
+ ::VDOM::KeyboardEvent::shared_keyboard_and_mouse_event_init(
249
+ current_mod_keys +
250
+ [keycode_name.to_s.gsub(/(KEY_)?(RIGHT|LEFT)?/i, '').downcase.to_sym]
251
+ )
252
+ end
253
+
254
+ # takes the InputEvent and returns a representing DOM::KeyEvent
255
+ # @todo refactor
256
+ # @param [InputEvent] input_event
257
+ # @return [Array<DOM::KeyEvent>]
258
+ def to_dom_key_event(input_event)
259
+ synchronize {
260
+
261
+ event_code = input_event.code
262
+ keycode_name = KEYCODES[event_code]
263
+
264
+ options = {:location => loc = dom_location(keycode_name),
265
+ :os_specific => os_spec = ::FFIUtils.struct_to_h(input_event),
266
+ :repeat => repeat?(os_spec, loc),
267
+ :modifiers => dom_modifiers(keycode_name),
268
+ }
269
+
270
+ remove_from_current_keys(options[:os_specific], options[:location])
271
+
272
+ options[:key] = key = dom_key(event_code, leds(input_event.leds))
273
+ options[:code] = dom_code(event_code, key)
274
+
275
+ type = dom_type(input_event.value, key)
276
+
277
+ if type.first != 'keyup'
278
+ key_event = ::VDOM::KeyboardEvent.new(type.first, options)
279
+
280
+ key_press = type[1] ? [key_event.copy_to(type[1])] : []
281
+ key_down_events = ([key_event] + key_press)
282
+ current_keys.concat(key_down_events)
283
+ key_down_events
284
+ else
285
+
286
+ key_event = ::VDOM::KeyboardEvent.new(type.first, options)
287
+
288
+ [*key_event].flatten
289
+ end
290
+ }
291
+ end
292
+
293
+ #
294
+ # @param [Hash] os_specific
295
+ # @param [Fixnum] dom_location
296
+ # @return [Array || NilClass]
297
+ def remove_from_current_keys(os_specific, dom_location)
298
+ current_keys.reject! do |current|
299
+ current.os_specific.except(:time, :value) == os_specific.except(:time, :value) and
300
+ current.location == dom_location
301
+ end
302
+ end
303
+
304
+ #
305
+ # @param [Hash] os_specific
306
+ # @param [Fixnum] dom_location
307
+ # @return [TrueClass || FalseClass]
308
+ def repeat?(os_specific, dom_location)
309
+ !!current_keys.find do |current|
310
+ current.os_specific.except(:time) == os_specific.except(:time) and
311
+ current.location == dom_location
312
+ end
313
+ end
314
+
315
+ #
316
+ # @param [String]
317
+ # @return [Array<Symbol> || NilClass]
318
+ def leds(bits_str)
319
+ if bits_str
320
+ System::Input::LEDs.constants.select do |const|
321
+ bits_str[System::Input::LEDs.const_get(const)].to_i > 0
322
+ end
323
+ end
324
+ end
325
+
326
+ end
327
+ end
328
+ end
329
+ end