vigilem-evdev 0.1.3

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.
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