vigilem-evdev 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|