vigilem-win32_api 0.0.10
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/lib/vigilem/win32_api/console_input_events.rb +78 -0
- data/lib/vigilem/win32_api/constants.rb +97 -0
- data/lib/vigilem/win32_api/dom/adapter.rb +59 -0
- data/lib/vigilem/win32_api/dom/code_values_tables.rb +136 -0
- data/lib/vigilem/win32_api/dom/input_record_utils.rb +259 -0
- data/lib/vigilem/win32_api/dom/key_values_tables.rb +123 -0
- data/lib/vigilem/win32_api/dom.rb +5 -0
- data/lib/vigilem/win32_api/eventable.rb +41 -0
- data/lib/vigilem/win32_api/input__record.rb +53 -0
- data/lib/vigilem/win32_api/input_system_handler.rb +124 -0
- data/lib/vigilem/win32_api/p_input__record.rb +55 -0
- data/lib/vigilem/win32_api/rubyized.rb +114 -0
- data/lib/vigilem/win32_api/types.rb +153 -0
- data/lib/vigilem/win32_api/utils/keyboard.rb +120 -0
- data/lib/vigilem/win32_api/version.rb +5 -0
- data/lib/vigilem/win32_api/virtual_keys/map.rb +211 -0
- data/lib/vigilem/win32_api/virtual_keys.rb +9 -0
- data/lib/vigilem/win32_api.rb +61 -0
- data/spec/acceptance/custom_input_system.feature +3 -0
- data/spec/acceptance/dom_adapter.feature +7 -0
- data/spec/acceptance/rubyized.feature +6 -0
- data/spec/acceptance/steps/custom_input_system_steps.rb +37 -0
- data/spec/acceptance/steps/dom_adapter_steps.rb +7 -0
- data/spec/acceptance/steps/rubyized_steps.rb +20 -0
- data/spec/attributes_and_size_test.rb +10 -0
- data/spec/input_helper.rb +41 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/turnip_helper.rb +1 -0
- data/spec/vigilem/api_spec.rb +139 -0
- data/spec/vigilem/win32_api/console_input_events_spec.rb +67 -0
- data/spec/vigilem/win32_api/dom/adapter_spec.rb +164 -0
- data/spec/vigilem/win32_api/dom/code_values_tables_spec.rb +5 -0
- data/spec/vigilem/win32_api/dom/input_record_utils_spec.rb +255 -0
- data/spec/vigilem/win32_api/dom/key_values_tables_spec.rb +5 -0
- data/spec/vigilem/win32_api/eventable_spec.rb +96 -0
- data/spec/vigilem/win32_api/input__record_spec.rb +113 -0
- data/spec/vigilem/win32_api/input_system_handler_spec.rb +164 -0
- data/spec/vigilem/win32_api/p_input__record_spec.rb +43 -0
- data/spec/vigilem/win32_api/rubyized_spec.rb +134 -0
- data/spec/vigilem/win32_api/types_spec.rb +139 -0
- data/spec/vigilem/win32_api/utils/keyboard_spec.rb +126 -0
- data/spec/vigilem/win32_api/virtual_keys/map_spec.rb +10 -0
- data/spec/vigilem/win32_api/virtual_keys_spec.rb +28 -0
- 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
|