vigilem-win32_api 0.0.10

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 (46) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/lib/vigilem/win32_api/console_input_events.rb +78 -0
  4. data/lib/vigilem/win32_api/constants.rb +97 -0
  5. data/lib/vigilem/win32_api/dom/adapter.rb +59 -0
  6. data/lib/vigilem/win32_api/dom/code_values_tables.rb +136 -0
  7. data/lib/vigilem/win32_api/dom/input_record_utils.rb +259 -0
  8. data/lib/vigilem/win32_api/dom/key_values_tables.rb +123 -0
  9. data/lib/vigilem/win32_api/dom.rb +5 -0
  10. data/lib/vigilem/win32_api/eventable.rb +41 -0
  11. data/lib/vigilem/win32_api/input__record.rb +53 -0
  12. data/lib/vigilem/win32_api/input_system_handler.rb +124 -0
  13. data/lib/vigilem/win32_api/p_input__record.rb +55 -0
  14. data/lib/vigilem/win32_api/rubyized.rb +114 -0
  15. data/lib/vigilem/win32_api/types.rb +153 -0
  16. data/lib/vigilem/win32_api/utils/keyboard.rb +120 -0
  17. data/lib/vigilem/win32_api/version.rb +5 -0
  18. data/lib/vigilem/win32_api/virtual_keys/map.rb +211 -0
  19. data/lib/vigilem/win32_api/virtual_keys.rb +9 -0
  20. data/lib/vigilem/win32_api.rb +61 -0
  21. data/spec/acceptance/custom_input_system.feature +3 -0
  22. data/spec/acceptance/dom_adapter.feature +7 -0
  23. data/spec/acceptance/rubyized.feature +6 -0
  24. data/spec/acceptance/steps/custom_input_system_steps.rb +37 -0
  25. data/spec/acceptance/steps/dom_adapter_steps.rb +7 -0
  26. data/spec/acceptance/steps/rubyized_steps.rb +20 -0
  27. data/spec/attributes_and_size_test.rb +10 -0
  28. data/spec/input_helper.rb +41 -0
  29. data/spec/spec_helper.rb +28 -0
  30. data/spec/turnip_helper.rb +1 -0
  31. data/spec/vigilem/api_spec.rb +139 -0
  32. data/spec/vigilem/win32_api/console_input_events_spec.rb +67 -0
  33. data/spec/vigilem/win32_api/dom/adapter_spec.rb +164 -0
  34. data/spec/vigilem/win32_api/dom/code_values_tables_spec.rb +5 -0
  35. data/spec/vigilem/win32_api/dom/input_record_utils_spec.rb +255 -0
  36. data/spec/vigilem/win32_api/dom/key_values_tables_spec.rb +5 -0
  37. data/spec/vigilem/win32_api/eventable_spec.rb +96 -0
  38. data/spec/vigilem/win32_api/input__record_spec.rb +113 -0
  39. data/spec/vigilem/win32_api/input_system_handler_spec.rb +164 -0
  40. data/spec/vigilem/win32_api/p_input__record_spec.rb +43 -0
  41. data/spec/vigilem/win32_api/rubyized_spec.rb +134 -0
  42. data/spec/vigilem/win32_api/types_spec.rb +139 -0
  43. data/spec/vigilem/win32_api/utils/keyboard_spec.rb +126 -0
  44. data/spec/vigilem/win32_api/virtual_keys/map_spec.rb +10 -0
  45. data/spec/vigilem/win32_api/virtual_keys_spec.rb +28 -0
  46. metadata +225 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bbde09d132a14953b05aeb4838acc918ab48c878
4
+ data.tar.gz: 8a9eb4816a5a373fedd2838ce1fb05eba9305d90
5
+ SHA512:
6
+ metadata.gz: 1cbfeaef82619e2b953cf1dc4da2c01756aebb4b32d41c869226e19090db8bca0af9dc8c6da2daa62bc61568bf127977efcb7fd0e889e2c79ec9a014d850c6ce
7
+ data.tar.gz: 8d93eaf3ee72ae910bf61d06e33ff9f69e335167c34c4d939818d59130af29f64d9bf0a09b547b624ca68cc02b121c738f8f1fcb9b99cbc29a20125e09557af8
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 jtzero
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,78 @@
1
+ module Vigilem
2
+ module Win32API
3
+ #
4
+ # group of all the console input events listed by MSoft
5
+ module ConsoleInputEvents
6
+
7
+
8
+ #
9
+ class MOUSE_EVENT_RECORD < ::VFFIStruct
10
+ layout_with_methods :dwMousePosition, Win32API::COORD,
11
+ :dwButtonState, :DWORD,
12
+ :dwControlKeyState, :DWORD,
13
+ :dwEventFlags, :DWORD
14
+ end
15
+
16
+
17
+ #
18
+ class WINDOW_BUFFER_SIZE_RECORD < ::VFFIStruct
19
+ layout_with_methods :dwSize, Win32API::COORD
20
+ end
21
+
22
+
23
+ # "These events are used internally and should be ignored."
24
+ class MENU_EVENT_RECORD < ::VFFIStruct
25
+ layout_with_methods :dwCommandId, :uint
26
+ end
27
+
28
+
29
+ # "These events are used internally and should be ignored."
30
+ class FOCUS_EVENT_RECORD < ::VFFIStruct
31
+ layout_with_methods :bSetFocus, :BOOL
32
+ end
33
+
34
+
35
+ #
36
+ class KEY_EVENT_RECORD < ::VFFIStruct
37
+ layout_with_methods :bKeyDown, :BOOL,
38
+ :wRepeatCount, :WORD,
39
+ :wVirtualKeyCode, :WORD,
40
+ :wVirtualScanCode, :WORD,
41
+ *union(:uChar,
42
+ [:UnicodeChar, :unicode_char], :WCHAR,
43
+ [:AsciiChar, :ascii_char], :CHAR
44
+ ),
45
+ :dwControlKeyState, :uint
46
+
47
+ alias_method :b_key_down, :bKeyDown
48
+ alias_method :w_repeat_count, :wRepeatCount
49
+ alias_method :w_virtual_key_code, :wVirtualKeyCode
50
+ alias_method :w_virtual_scan_code, :wVirtualScanCode
51
+ alias_method :u_char, :uChar
52
+ alias_method :dw_control_key_state, :dwControlKeyState
53
+ end
54
+
55
+ @events = Win32API::Constants::Events
56
+
57
+ #
58
+ # @return [Array<Symbol>]
59
+ def self.vk_names
60
+ @_console_input_events_ ||= @events.constants.grep(/^(?!CTRL).*/)
61
+ end
62
+
63
+ #
64
+ # @return [TransmutableHash<Integer, Symbol>]
65
+ def self.vk_hash
66
+ @_console_input_event_hash_ ||= vk_names.map.with_object(Support::TransmutableHash.new()) {|event_name, hsh| hsh[@events.const_get(event_name)] = event_name }
67
+ end
68
+
69
+ #
70
+ # @return [Array<VFFIStruct>]
71
+ def self.structs
72
+ @_structs_ ||= constants.map {|const| const_get(const) }
73
+ end
74
+ end
75
+
76
+ include ConsoleInputEvents
77
+ end
78
+ end
@@ -0,0 +1,97 @@
1
+ module Vigilem
2
+ module Win32API
3
+
4
+ # @note the colors may be removed in future releases
5
+ module Constants
6
+
7
+ STD_INPUT_HANDLE = 0xFFFFFFF6
8
+ STD_OUTPUT_HANDLE = 0xFFFFFFF5
9
+ STD_ERROR_HANDLE = 0xFFFFFFF4
10
+ INVALID_HANDLE_VALUE = 0xFFFFFFFF
11
+ GENERIC_READ = 0x80000000
12
+ GENERIC_WRITE = 0x40000000
13
+ FILE_SHARE_READ = 0x00000001
14
+ FILE_SHARE_WRITE = 0x00000002
15
+ CONSOLE_TEXTMODE_BUFFER = 0x00000001
16
+ FOREGROUND_BLUE = 0x0001
17
+ FOREGROUND_GREEN = 0x0002
18
+ FOREGROUND_RED = 0x0004
19
+ FOREGROUND_INTENSITY = 0x0008
20
+ BACKGROUND_BLUE = 0x0010
21
+ BACKGROUND_GREEN = 0x0020
22
+ BACKGROUND_RED = 0x0040
23
+ BACKGROUND_INTENSITY = 0x0080
24
+ ENABLE_PROCESSED_INPUT = 0x0001
25
+ ENABLE_LINE_INPUT = 0x0002
26
+ ENABLE_ECHO_INPUT = 0x0004
27
+ ENABLE_WINDOW_INPUT = 0x0008
28
+ ENABLE_MOUSE_INPUT = 0x0010
29
+ ENABLE_PROCESSED_OUTPUT = 0x0001
30
+ ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
31
+
32
+ MOUSE_WHEELED = 0x0004
33
+ DOUBLE_CLICK = 0x0002
34
+ MOUSE_MOVED = 0x0001
35
+ FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001
36
+ FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004
37
+ FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008
38
+ FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010
39
+ RIGHTMOST_BUTTON_PRESSED = 0x0002
40
+
41
+ module Events
42
+ CTRL_C_EVENT = 0x0000
43
+ CTRL_BREAK_EVENT = 0x0001
44
+ CTRL_CLOSE_EVENT = 0x0002
45
+ CTRL_LOGOFF_EVENT = 0x0005
46
+ CTRL_SHUTDOWN_EVENT = 0x0006
47
+ end
48
+
49
+ # @see ReadConsoleInput
50
+ module DWControlKeys
51
+ CAPSLOCK_ON = 0x0080 # The CAPS LOCK light is on.
52
+ ENHANCED_KEY = 0x0100 # The key is enhanced.
53
+ LEFT_ALT_PRESSED = 0x0002 # The left ALT key is pressed.
54
+ LEFT_CTRL_PRESSED = 0x0008 # The left CTRL key is pressed.
55
+ NUMLOCK_ON = 0x0020 # The NUM LOCK light is on.
56
+ RIGHT_ALT_PRESSED = 0x0001 # The right ALT key is pressed.
57
+ RIGHT_CTRL_PRESSED = 0x0004 # The right CTRL key is pressed.
58
+ SCROLLLOCK_ON = 0x0040 # The SCROLL LOCK light is on.
59
+ SHIFT_PRESSED = 0x0010 # The SHIFT key is pressed.
60
+ end
61
+
62
+ include DWControlKeys
63
+
64
+ module Events
65
+ KEY_EVENT = 0x0001
66
+ MOUSE_EVENT = 0x0002
67
+ WINDOW_BUFFER_SIZE_EVENT = 0x0004
68
+ MENU_EVENT = 0x0008
69
+ FOCUS_EVENT = 0x0010
70
+ end
71
+
72
+ include Events
73
+
74
+ module MapType
75
+ MAPVK_VK_TO_VSC = 0
76
+ MAPVK_VSC_TO_VK = 1
77
+ MAPVK_VK_TO_CHAR = 2
78
+ MAPVK_VSC_TO_VK_EX = 3
79
+ end
80
+
81
+ include MapType
82
+
83
+ module MAPVK
84
+ VK_TO_VSC = MapType::MAPVK_VK_TO_VSC
85
+ VSC_TO_VK = MapType::MAPVK_VSC_TO_VK
86
+ VK_TO_CHAR = MapType::MAPVK_VK_TO_CHAR
87
+ VSC_TO_VK_EX = MapType::MAPVK_VSC_TO_VK_EX
88
+ end
89
+ MapVK = MAPVK
90
+
91
+ MapType::MAPVK = MapType::MapVK = MAPVK
92
+
93
+ end
94
+ include Constants
95
+
96
+ end
97
+ end
@@ -0,0 +1,59 @@
1
+ require 'vigilem./core/adapters/buffered_adapter'
2
+
3
+ require 'vigilem/core/eventable'
4
+
5
+ require 'vigilem/core/event_handler'
6
+
7
+ require 'vigilem/win32_api/input_system_handler'
8
+
9
+ module Vigilem
10
+ module Win32API
11
+ module DOM
12
+ #
13
+ #
14
+ class Adapter
15
+
16
+ require 'vigilem/win32_api/dom/input_record_utils'
17
+
18
+ include InputRecordUtils
19
+
20
+ include Core::Adapters::BufferedAdapter
21
+
22
+ include Core::EventHandler
23
+
24
+ default_handler()
25
+
26
+ #
27
+ # @param link
28
+ def initialize(link=InputSystemHandler.new)
29
+ initialize_buffered(link)
30
+ self.dom_ir_utils_source = link
31
+ on(Win32API::KEY_EVENT_RECORD) {|event| to_dom_key_event(event) }
32
+ end
33
+
34
+ include Core::Eventable
35
+
36
+ #
37
+ # @param [Integer] limit
38
+ # @return
39
+ def read_many_nonblock(limit=1)
40
+ buffered!(limit) do |len_remainder|
41
+ dom_src_events = link.read_many_nonblock(len_remainder).map do |event|
42
+ handle(event.event_record)
43
+ end.compact.flatten
44
+ ret, to_buffer = Support::Utils.split_at(dom_src_events, len_remainder)
45
+ buffer.concat([*to_buffer])
46
+ ret
47
+ end
48
+ end
49
+
50
+ #
51
+ # @return [TrueClass || FalseClass]
52
+ def has_any?
53
+ not buffer.empty? || link.has_any?
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,136 @@
1
+ module Vigilem
2
+ module Win32API::DOM
3
+ # http://www.w3.org/TR/2014/WD-DOM-Level-3-Events-code-20140612/
4
+ module CodeValuesTables
5
+
6
+ code_values = Vigilem::DOM::CodeValues
7
+
8
+ WritingSystemKeys = Support::KeyMap.new({
9
+ :VK_OEM_3 => 'Backquote',
10
+ :VK_OEM_5 => 'Backslash',
11
+ :VK_BACK => 'Backspace',
12
+ :VK_OEM_4 => 'BracketLeft',
13
+ :VK_OEM_6 => 'BracketRight',
14
+ :VK_OEM_COMMA => 'Comma',
15
+ :VK_OEM_PLUS => 'Equal',
16
+ #'IntlBackslash', 'IntlHash', 'IntlRo', 'IntlYen',
17
+ :VK_OEM_MINUS => 'Minus',
18
+ :VK_OEM_PERIOD => 'Period',
19
+ :VK_OEM_7 => 'Quote',
20
+ :VK_OEM_1 => 'Semicolon',
21
+ :VK_OEM_2 => 'Slash'})
22
+
23
+ FunctionalKeys = Support::KeyMap.new({
24
+ :VK_MENU => %w(AltLeft AltRight),
25
+ :VK_LMEMU => 'AltLeft',
26
+ :VK_RMEMU => 'AltRight',
27
+ :VK_CAPITAL => 'CapsLock',
28
+ :VK_APPS => 'ContextMenu',
29
+ :VK_CONTROL => %w(ControlLeft ControlRight'),
30
+ :VK_LCONTROL => 'ControlLeft',
31
+ :VK_RCONTROL => 'ControlRight',
32
+ :VK_RETURN => 'Enter',
33
+ :VK_LWIN => 'OSLeft',
34
+ :VK_RWIN => 'OSRight',
35
+ :VK_SHIFT => %w(ShiftLeft ShiftRight),
36
+ :VK_LSHIFT => 'ShiftLeft',
37
+ :VK_RSHIFT => 'ShiftRight',
38
+ :VK_KANA => 'KanaMode',
39
+ :VK_NONCONVERT => 'NonConvert' })
40
+ #'Lang1', 'Lang2', 'Lang3', 'Lang4', 'Lang5' eh?
41
+
42
+ ControlPadSection = Support::KeyMap.new({
43
+ [:ENHANCED_KEY, :VK_DELETE] => 'Delete',
44
+ [:ENHANCED_KEY, :VK_END] => 'End',
45
+ :VK_HELP => 'Help',
46
+ [:ENHANCED_KEY, :VK_HOME] => 'Home',
47
+ [:ENHANCED_KEY, :VK_INSERT] => 'Insert',
48
+ [:ENHANCED_KEY, :VK_NEXT] => 'PageDown',
49
+ [:ENHANCED_KEY, :VK_PRIOR] => 'PageUp'
50
+ })
51
+
52
+ ArrowPadSection = Support::KeyMap[[
53
+ [:ENHANCED_KEY, :VK_DOWN],
54
+ [:ENHANCED_KEY, :VK_LEFT],
55
+ [:ENHANCED_KEY, :VK_RIGHT],
56
+ [:ENHANCED_KEY, :VK_UP]
57
+ ].zip(code_values::ArrowPadSection)
58
+ ]
59
+
60
+ NumpadSection = Support::KeyMap.new({
61
+ [:ENHANCED_KEY, :VK_NUMLOCK] => 'NumLock',
62
+ :VK_NUMPAD0 => 'Numpad0',
63
+ :VK_INSERT => 'Numpad0',
64
+ :VK_NUMPAD1 => 'Numpad1',
65
+ :VK_END => 'Numpad1',
66
+ :VK_NUMPAD2 => 'Numpad2',
67
+ :VK_DOWN => 'Numpad2',
68
+ :VK_NUMPAD3 => 'Numpad3',
69
+ :VK_NEXT => 'Numpad3',
70
+ :VK_NUMPAD4 => 'Numpad4',
71
+ :VK_LEFT => 'Numpad4',
72
+ :VK_NUMPAD5 => 'Numpad5',
73
+ :VK_NUMPAD6 => 'Numpad6',
74
+ :VK_RIGHT => 'Numpad6',
75
+ :VK_NUMPAD7 => 'Numpad7',
76
+ :VK_HOME => 'Numpad7',
77
+ :VK_NUMPAD8 => 'Numpad8',
78
+ :VK_UP => 'Numpad8',
79
+ :VK_NUMPAD9 => 'Numpad9',
80
+ :VK_PRIOR => 'Numpad9',
81
+ :VK_ADD => 'NumpadAdd',
82
+ :'?' => 'NumpadBackspace',
83
+ :VK_DELETE => 'NumpadDecimal',
84
+ :VK_DECIMAL => 'NumpadDecimal',
85
+ [:ENHANCED_KEY, :VK_DIVIDE] => 'NumpadDivide',
86
+ [:ENHANCED_KEY, :VK_RETURN] => 'NumpadEnter',
87
+ :VK_MULTIPLY => 'NumpadMultiply',
88
+ :VK_SUBTRACT => 'NumpadSubtract'})
89
+ #'NumpadClear', 'NumpadClearEntry', 'NumpadComma', 'NumpadEqual', 'NumpadMemoryAdd', 'NumpadMemoryClear', 'NumpadMemoryRecall', 'NumpadMemoryStore', 'NumpadMemorySubtract', 'NumpadParenLeft', 'NumpadParenRight'
90
+
91
+ FunctionSection = Support::KeyMap.new({
92
+ :VK_MENU => %w(AltLeft AltRight),
93
+ :VK_LMENU => 'AltLeft',
94
+ :VK_RMENU => 'AltRight',
95
+ [:ENHANCED_KEY, :VK_MENU] => 'AltRight',
96
+ :VK_CAPITAL => 'CapsLock',
97
+ [:ENHANCED_KEY, :VK_APPS] => 'ContextMenu',
98
+ :VK_LWIN => 'ContextMenu',
99
+ :VK_RWIN => 'ContextMenu',
100
+ :VK_CONTROL => ['ControlLeft', 'ControlRight'],
101
+ :VK_LCONTROL => 'ControlLeft',
102
+ :VK_RCONTROL => 'ControlRight',
103
+ :VK_SCROLL => 'ScrollLock',
104
+ :VK_PAUSE => 'Pause',
105
+ :VK_SPACE => 'Space',
106
+ :VK_TAB => 'Tab'
107
+ })
108
+
109
+ #['Fn', 'FLock', 'PrintScreen', ]
110
+
111
+ MediaKeys = Support::KeyMap.new({
112
+ :VK_MEDIA_NEXT_TRACK => 'MediaTrackNext',
113
+ :VK_MEDIA_PREV_TRACK => 'MediaTrackPrevious',
114
+ :VK_LAUNCH_MEDIA_SELECT => 'MediaSelect'})
115
+
116
+ #'Eject', 'Power', 'WakeUp'
117
+
118
+ LegacyKeysandNon_StandardKeys = Support::KeyMap.new({:VK_SELECT => 'Select'})
119
+
120
+ #['Hyper', 'Super', 'Turbo', 'Abort', 'Resume', 'Suspend', 'Again', 'Copy', 'Cut', 'Find', 'Open', 'Paste', 'Props', 'Undo', 'Hiragana', 'Katakana']
121
+ end
122
+ CodeTable = CodeValuesTables.constants.each_with_object(Support::KeyMap.new()) do |table_name, memo|
123
+ table = CodeValuesTables.const_get(table_name)
124
+ table.right_side_alias(:dom_code)
125
+ table.right_side_alias(:dom_codes)
126
+ table.left_side_alias(:win_vk)
127
+ table.left_side_alias(:win_vks)
128
+ memo.merge! table
129
+ end
130
+
131
+ CodeTable.right_side_alias(:dom_code)
132
+ CodeTable.right_side_alias(:dom_codes)
133
+ CodeTable.left_side_alias(:win_vk)
134
+ CodeTable.left_side_alias(:win_vks)
135
+ end
136
+ end
@@ -0,0 +1,259 @@
1
+ require 'vigilem/support'
2
+
3
+ require 'vigilem/win32_api'
4
+ require 'vigilem/win32_api/utils/keyboard'
5
+
6
+ require 'vigilem/win32_api/virtual_keys'
7
+
8
+ require 'vigilem/win32_api/dom/key_values_tables'
9
+ require 'vigilem/win32_api/dom/code_values_tables'
10
+
11
+ module Vigilem
12
+ module Win32API
13
+ module DOM
14
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
15
+ # methods to convert InputRecords to DOM Events
16
+ # @abstract requires a dom_ir_utils_source method
17
+ # and included into the same module
18
+ # as RubyizedAPI
19
+ # @todo module KeyEventRecordUtils
20
+ module InputRecordUtils
21
+
22
+ NULL_STR = "\x00"
23
+
24
+ UNKNOWN_VAL = 'Unidentified'
25
+
26
+ include VirtualKeys
27
+
28
+ include Constants
29
+
30
+ include CodeValuesTables
31
+
32
+ include Utils::Keyboard
33
+
34
+ # the current keys being pressed
35
+ # @return [Array]
36
+ def current_keys
37
+ @current_keys ||= []
38
+ end
39
+
40
+ # converts and event_record to DOM KeyEvent
41
+ # @note the righ Alt and right ctrl are 'enhanced'
42
+ # @param [] event_record
43
+ # @return [Array<Vigilem::DOM::KeyboardEvent>]
44
+ def to_dom_key_event(event_record)
45
+ dw_state_names = dw_control_key_state_vks(event_record.dwControlKeyState)
46
+
47
+ # all test need fixed
48
+ # will this work for a range? if not it needs to
49
+ virtual_key_name = Map.virtual_keyname(vk_code = event_record.wVirtualKeyCode)
50
+
51
+ modifiers = dom_modifiers(*dw_state_names)
52
+
53
+ dom_loc = dom_location(virtual_key_name, event_record.wVirtualScanCode, dw_state_names)
54
+
55
+ key = dom_key(virtual_key_name, u_char = event_record.uChar.UnicodeChar)
56
+
57
+ code = dom_code(virtual_key_name, u_char, dom_loc, *dw_state_names)
58
+
59
+ options = {:key => key, :code => code, :location => dom_loc, :repeat => false,
60
+ :modifiers => modifiers, :os_specific => ::FFIUtils.struct_to_h(event_record) }
61
+
62
+ if event_record.bKeyDown == 1
63
+ if (prev_event = current_keys.last) and %w(keypress keydown).include?(prev_event.type) and prev_event.key == options[:key]
64
+ options[:repeat] = true
65
+ end
66
+
67
+ key_event = ::VDOM::KeyboardEvent.new('keydown', options)
68
+ key_down_events = [key_event, key_event.copy_to('keypress')]
69
+ @current_keys += key_down_events.flatten
70
+ key_down_events
71
+ else
72
+ key_event = ::VDOM::KeyboardEvent.new('keyup', options)
73
+ current_keys.delete_if {|current| current.key == key_event.key and current.location == key_event.location }
74
+ [*key_event].flatten
75
+ end
76
+ end
77
+
78
+ # converts a Integer representing dwControlKeyState from KEY_EVENT_RECORD to an
79
+ # array of virtual-keys, Symbols
80
+ # @param [Integer] dw_control_key_state
81
+ # @return [Array<Symbol>] the win modifiers
82
+ def dw_control_key_state_vks(dw_control_key_state)
83
+ DWControlKeys.constants.select do |const|
84
+ (dw_control_key_state & (value = DWControlKeys.const_get(const))) == value
85
+ end
86
+ end
87
+
88
+ #
89
+ # @return [Hash]
90
+ def location_less_vks_map
91
+ @location_less_vks_map ||= {:VK_MENU => /alt/i, :VK_CONTROL => /control|ctrl/i, :VK_SHIFT => /shift/i }
92
+ end
93
+
94
+ #
95
+ # @param [Symbol] vk_name
96
+ # @return [TrueClass || FalseClass]
97
+ def vk_without_location_info?(vk_name)
98
+ location_less_vks_map.keys.include? vk_name
99
+ end
100
+
101
+ #
102
+ # @return [Hash]
103
+ def shift_scan_code_to_location_vk
104
+ @shift_scan_location ||= { dom_ir_utils_source.map_virtual_key(VK[:LSHIFT], MAPVK::VK_TO_VSC) => :VK_LSHIFT,
105
+ dom_ir_utils_source.map_virtual_key(VK[:RSHIFT], MAPVK::VK_TO_VSC) => :VK_RSHIFT }
106
+ end
107
+
108
+ class << self
109
+ #
110
+ # @param [String<'L'||'l'||'R'||'r'>] str, to convert
111
+ # @return [String<'R'||'r'||'L'||'l'>] its opposite
112
+ def flip_lr_sides(str)
113
+ str.tr('LlRr', 'RrLl')
114
+ end
115
+
116
+ #
117
+ # @param [Symbol] key_name
118
+ # @return [String || NilClass]
119
+ def lr_location_from_name(key_name)
120
+ key_name.to_s.gsub(/VK_(L(?!EFT)|R(?!IGHT))?.+/, '\1')[/L|R/]
121
+ end
122
+
123
+ #
124
+ # @param [String] str, value to test
125
+ # @return [TrueClass || FalseClass] whether or not the String
126
+ # is #empty? or just contains NULL_STR
127
+ def empty_or_null?(str)
128
+ str.strip.empty? or (str == NULL_STR * str.length)
129
+ end
130
+
131
+ end
132
+
133
+ #
134
+ # @param [Symbol] vk_name
135
+ # @param [Array<Symbol>] dw_state_names
136
+ # @return [Integer<0|1|2>]
137
+ def dom_location(vk_name, v_scancode, dw_state_names)
138
+ l_r_location = InputRecordUtils.lr_location_from_name(vk_name) ||
139
+ lr_not_in_name(vk_name, v_scancode, dw_state_names) || ""
140
+
141
+ ::VDOM::Utils.common_str_to_dom_location(l_r_location.upcase) || DOM_KEY_LOCATION_STANDARD
142
+ end
143
+
144
+ # gets the l or r using other params than just the name
145
+ # @see location_less_vks_map
146
+ # @param [Symbol] vk_name
147
+ # @param [Integer] v_scancode
148
+ # @param [Symbol<#{location_less_vks_map.keys}>]
149
+ # @raise [RuntimeError] when the location cannot be found
150
+ # @return [String<'l'|'r'>]
151
+ def lr_not_in_name!(vk_name, v_scancode, dw_state_names)
152
+ if lr = lr_not_in_name(vk_name, v_scancode, dw_state_names)
153
+ lr
154
+ else
155
+ raise RuntimeError, "Cannot get location from #{vk_name}, #{v_scancode}, #{current_keys}, #{dw_state_names}"
156
+ end
157
+ end
158
+
159
+ # gets the l or r using other params than just the name
160
+ # @see location_less_vks_map
161
+ # @param [Symbol] vk_name
162
+ # @param [Integer] v_scancode
163
+ # @param [Symbol<#{location_less_vks_map.keys}>]
164
+ # @return [String<'l'||'r'>]
165
+ def lr_not_in_name(vk_name, v_scancode, dw_state_names)
166
+ if vk_name == :VK_SHIFT
167
+ if lr = InputRecordUtils.lr_location_from_name(shift_scan_code_to_location_vk[v_scancode])
168
+ lr.downcase
169
+ end
170
+ else
171
+ regexp = location_less_vks_map[vk_name]
172
+ # other side key pressed? weird but eh
173
+ if other_location = current_keys.find {|current| current.key =~ regexp }
174
+ InputRecordUtils.flip_lr_sides(::VDOM::Utils.to_dom_location_common_str(other_location.location)).downcase
175
+ # ok other one isn't being pressed then the one showing up in dw_control_state is this
176
+ else
177
+ applicable_state_names = dw_state_names.grep(regexp)
178
+ # there are no previous keys
179
+ if applicable_state_names.size > 1
180
+ raise "Both `#{vk_name}' are pressed but there is no record in the current keys:#{current_keys.join(',')}"
181
+ elsif location = InputRecordUtils.lr_location_from_name(dw_state_names.grep(regexp).first)
182
+ location.downcase
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+ # @see MapVirtualKey,
189
+ # @param [Symbol] virtual_key
190
+ # @param u_char
191
+ # @return [String]
192
+ def dom_key(virtual_key, u_char)
193
+ vk = :"VK_#{virtual_key.to_s.gsub(/^VK_/, '')}"
194
+ # returns 0 when no character available
195
+ if KeyValuesTables::WhitespaceKeys.has_key?(vk) or
196
+ (character = dom_ir_utils_source.map_virtual_key(Map.virtual_key_code(vk), MAPVK::VK_TO_CHAR)) == 0
197
+ KeyTable.dom_key(vk) || UNKNOWN_VAL
198
+ else
199
+ u_char.chr
200
+ end
201
+ end
202
+
203
+ #
204
+ # @param [Symbol] virtual_key
205
+ # @param [String] u_char_value
206
+ # @param [String<"l"||"r"> || Integer] location
207
+ # @raise RuntimeError
208
+ # @return
209
+ def dom_code(virtual_key, u_char_value, location, *dw_state_names)
210
+ if (code = CodeTable.dom_code(Support::Utils.unwrap_ary([*dw_state_names.grep(:ENHANCED_KEY), virtual_key])))
211
+ if code.is_a? Array
212
+ dom_loc = location.is_a?(String) ? ::VDOM::Utils.common_str_to_dom_location(location.upcase) : location
213
+ code.grep(::VDOM::Utils.codes_regex[dom_loc]).first
214
+ else
215
+ code
216
+ end
217
+ else
218
+ if(char = u_char_value.chr) =~ /^[a-z]$/i
219
+ "Key#{char.upcase}"
220
+ elsif char =~ /^[0-9]$/
221
+ "Digit#{char}"
222
+ else
223
+ UNKNOWN_VAL
224
+ end
225
+ end
226
+ end
227
+
228
+ # @see Vigilem::DOM::KeyEvent::alternative_key_names
229
+ # @param [Array] dw_control_state_names
230
+ # @return [Array]
231
+ def dom_modifiers(*dw_control_state_names)
232
+ ::VDOM::KeyboardEvent::shared_keyboard_and_mouse_event_init(dw_control_state_names.map do |mod|
233
+ if mod == :RIGHT_ALT_PRESSED
234
+ :metaKey
235
+ else
236
+ mod.to_s.gsub(/right|left|pressed|on|_/i, '').downcase.to_sym
237
+ end
238
+ end)
239
+ end
240
+
241
+ private
242
+
243
+ attr_writer :dom_ir_utils_source
244
+
245
+ alias_method :dom_ir_utils_src=, :dom_ir_utils_source=
246
+
247
+ #
248
+ # @raise [NotImplementedError]
249
+ # @return
250
+ def dom_ir_utils_source
251
+ @dom_ir_utils_source ||= self
252
+ end
253
+
254
+ alias_method :dom_ir_utils_src=, :dom_ir_utils_source
255
+
256
+ end
257
+ end
258
+ end
259
+ end