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.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/ext/Rakefile +31 -0
- data/ext/rake_helper.rb +10 -0
- data/lib/vigilem/_evdev.rb +24 -0
- data/lib/vigilem/evdev.rb +14 -0
- data/lib/vigilem/evdev/at_exit.rb +8 -0
- data/lib/vigilem/evdev/context_filter.rb +92 -0
- data/lib/vigilem/evdev/demultiplexer.rb +26 -0
- data/lib/vigilem/evdev/device.rb +182 -0
- data/lib/vigilem/evdev/device_capabilities.rb +53 -0
- data/lib/vigilem/evdev/dom.rb +8 -0
- data/lib/vigilem/evdev/dom/adapter.rb +87 -0
- data/lib/vigilem/evdev/dom/code_values_tables.rb +172 -0
- data/lib/vigilem/evdev/dom/input_event_converter.rb +329 -0
- data/lib/vigilem/evdev/dom/input_event_utils.rb +48 -0
- data/lib/vigilem/evdev/dom/key_values_tables.rb +248 -0
- data/lib/vigilem/evdev/dom/kp_table.rb +52 -0
- data/lib/vigilem/evdev/focus_context_filter.rb +124 -0
- data/lib/vigilem/evdev/input_system_handler.rb +69 -0
- data/lib/vigilem/evdev/key_map_cache.rb +64 -0
- data/lib/vigilem/evdev/multiplexer.rb +73 -0
- data/lib/vigilem/evdev/system.rb +17 -0
- data/lib/vigilem/evdev/system/input.rb +1053 -0
- data/lib/vigilem/evdev/system/input/event.rb +4 -0
- data/lib/vigilem/evdev/system/input/input_event.rb +33 -0
- data/lib/vigilem/evdev/system/int.rb +9 -0
- data/lib/vigilem/evdev/system/ioctl.rb +143 -0
- data/lib/vigilem/evdev/system/keymap_loaders.rb +89 -0
- data/lib/vigilem/evdev/system/keymap_loaders/dumpkeys_loader.rb +98 -0
- data/lib/vigilem/evdev/system/keymap_loaders/kmap_loader.rb +74 -0
- data/lib/vigilem/evdev/system/posix_types.rb +5 -0
- data/lib/vigilem/evdev/system/time.rb +21 -0
- data/lib/vigilem/evdev/transfer_agent.rb +40 -0
- data/lib/vigilem/evdev/version.rb +5 -0
- data/lib/vigilem/evdev/vty_context_filter.rb +216 -0
- data/spec/after_each_example_group.rb +29 -0
- data/spec/delete_test_cache_after_group.rb +26 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/vigilem/_evdev_spec.rb +11 -0
- data/spec/vigilem/evdev/context_filter_spec.rb +114 -0
- data/spec/vigilem/evdev/demultiplexer_spec.rb +44 -0
- data/spec/vigilem/evdev/device_capabilities_spec.rb +0 -0
- data/spec/vigilem/evdev/device_spec.rb +97 -0
- data/spec/vigilem/evdev/dom/adapter_spec.rb +5 -0
- data/spec/vigilem/evdev/dom/input_event_converter_spec.rb +253 -0
- data/spec/vigilem/evdev/dom/input_event_utils_spec.rb +23 -0
- data/spec/vigilem/evdev/focus_context_filter_spec.rb +112 -0
- data/spec/vigilem/evdev/input_system_handler_spec.rb +146 -0
- data/spec/vigilem/evdev/key_map_cache_spec.rb +65 -0
- data/spec/vigilem/evdev/multiplexer_spec.rb +55 -0
- data/spec/vigilem/evdev/system/input/input_event_spec.rb +33 -0
- data/spec/vigilem/evdev/system/input_spec.rb +274 -0
- data/spec/vigilem/evdev/system/int_spec.rb +30 -0
- data/spec/vigilem/evdev/system/ioctl_spec.rb +206 -0
- data/spec/vigilem/evdev/system/keymap_loaders/dumpkeys_loader_spec.rb +5 -0
- data/spec/vigilem/evdev/system/keymap_loaders/kmap_loader_spec.rb +24 -0
- data/spec/vigilem/evdev/system/keymap_loaders_spec.rb +22 -0
- data/spec/vigilem/evdev/system/posix_types_spec.rb +15 -0
- data/spec/vigilem/evdev/system/time_spec.rb +18 -0
- data/spec/vigilem/evdev/transfer_agent_spec.rb +57 -0
- data/spec/vigilem/evdev/vty_context_filter_spec.rb +282 -0
- metadata +286 -0
@@ -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
|