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
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'vigilem/win32_api'
|
4
|
+
|
5
|
+
require 'timeout'
|
6
|
+
|
7
|
+
describe Vigilem::Win32API do
|
8
|
+
|
9
|
+
after(:example) do
|
10
|
+
flush
|
11
|
+
end
|
12
|
+
|
13
|
+
context '::GetStdHandle' do
|
14
|
+
it 'will return STD_INPUT_HANDLE' do
|
15
|
+
expect(subject.GetStdHandle(described_class::STD_INPUT_HANDLE)).to eql(std_handle)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
context 'methods except GetStdHandle,' do
|
21
|
+
|
22
|
+
describe '::PeekConsoleInputW' do
|
23
|
+
|
24
|
+
let(:args) do
|
25
|
+
{
|
26
|
+
:hConsoleInput => described_class.GetStdHandle(described_class::STD_INPUT_HANDLE),
|
27
|
+
:lpBuffer => described_class::PINPUT_RECORD.new(len = 1),
|
28
|
+
:nLength => len,
|
29
|
+
:lpNumberOfEventsRead => FFI::MemoryPointer.new(:dword, 1)
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
it %q(won't block when the queue is empty) do
|
34
|
+
flush
|
35
|
+
expect do
|
36
|
+
Timeout::timeout(5) do
|
37
|
+
subject.PeekConsoleInputW(*args.values)
|
38
|
+
end
|
39
|
+
end.to_not raise_error
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'will return one when it executes correctly' do
|
43
|
+
expect(subject.PeekConsoleInputW(*args.values)).to eql 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'user input' do
|
48
|
+
|
49
|
+
before :each do
|
50
|
+
flush
|
51
|
+
write_console_input_test
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '::PeekConsoleInputW' do
|
55
|
+
|
56
|
+
before :all do
|
57
|
+
@args = {
|
58
|
+
:hConsoleInput => std_handle,
|
59
|
+
:lpBuffer => described_class::PINPUT_RECORD.new(len = 1),
|
60
|
+
:nLength => len,
|
61
|
+
:lpNumberOfEventsRead => FFI::MemoryPointer.new(:dword, 1)
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'updates lpNumberOfEventsRead passed in arguments' do
|
66
|
+
expect do
|
67
|
+
Timeout::timeout(5) do
|
68
|
+
subject.PeekConsoleInputW(*@args.values) until @args[:lpNumberOfEventsRead].read_short > 0
|
69
|
+
end
|
70
|
+
end.to_not raise_error
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'updates the [:lpBuffer].INPUT_RECORD.EventType passed in arguments' do
|
74
|
+
#puts ">#{@args[:lpBuffer].first}"
|
75
|
+
# expected [] to respond to `a??`
|
76
|
+
#expect(args[:lpBuffer]).to be_a?(described_class::PINPUT_RECORD)
|
77
|
+
|
78
|
+
expect(0.upto(4).map {|n| 2**n }).to include(@args[:lpBuffer].first.EventType)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'updates the [:lpBuffer].INPUT_RECORD.Event.KeyEvent passed in arguments' do
|
82
|
+
expect(@args[:lpBuffer].first.Event.KeyEvent.uChar).to_not eql(0)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '::ReadConsoleInputW' do
|
88
|
+
|
89
|
+
before :all do
|
90
|
+
@rargs = {
|
91
|
+
:hConsoleInput => std_handle,
|
92
|
+
:lpBuffer => described_class::PINPUT_RECORD.new(len = 2),
|
93
|
+
:nLength => len,
|
94
|
+
:lpNumberOfEventsRead => FFI::MemoryPointer.new(:dword, 1)
|
95
|
+
}
|
96
|
+
write_console_input_test
|
97
|
+
described_class.ReadConsoleInputW(*@rargs.values)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'pulls input_records from queue' do
|
101
|
+
expect(@rargs[:lpNumberOfEventsRead].read_short).to be > 1
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'updates the [:lpBuffer].INPUT_RECORD.EventType passed in arguments' do
|
105
|
+
expect(@rargs[:lpBuffer].first.EventType).to eql(1)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'updates the [:lpBuffer].INPUT_RECORD.Event.KeyEvent passed in arguments' do
|
109
|
+
expect(@rargs[:lpBuffer].first.Event.KeyEvent.uChar).to_not be_nil
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
describe '::PeekConsoleInputW' do
|
115
|
+
|
116
|
+
before :all do
|
117
|
+
@pargs = {
|
118
|
+
:hConsoleInput => std_handle,
|
119
|
+
:lpBuffer => described_class::PINPUT_RECORD.new(len = 1),
|
120
|
+
:nLength => len,
|
121
|
+
:lpNumberOfEventsRead => FFI::MemoryPointer.new(:dword, 1)
|
122
|
+
}
|
123
|
+
@prargs = {
|
124
|
+
:hConsoleInput => std_handle,
|
125
|
+
:lpBuffer => described_class::PINPUT_RECORD.new(len = 1),
|
126
|
+
:nLength => len,
|
127
|
+
:lpNumberOfEventsRead => FFI::MemoryPointer.new(:dword, 1)
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'does not effect the queue' do
|
132
|
+
expect(subject.PeekConsoleInputW(*@pargs.values)).to be == subject.ReadConsoleInputW(*@prargs.values)
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'vigilem/win32_api/constants'
|
4
|
+
|
5
|
+
require 'vigilem/win32_api/types'
|
6
|
+
|
7
|
+
require 'vigilem/win32_api/console_input_events'
|
8
|
+
|
9
|
+
|
10
|
+
describe Vigilem::Win32API::ConsoleInputEvents do
|
11
|
+
|
12
|
+
describe described_class::MOUSE_EVENT_RECORD do
|
13
|
+
it_behaves_like 'attributes_and_size_test' do
|
14
|
+
let(:ary) { [:dwMousePosition, :dwButtonState, :dwControlKeyState, :dwEventFlags] }
|
15
|
+
let(:sze) { 16 }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe described_class::WINDOW_BUFFER_SIZE_RECORD do
|
20
|
+
it_behaves_like 'attributes_and_size_test' do
|
21
|
+
let(:ary) { [:dwSize] }
|
22
|
+
let(:sze) { 4 }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe described_class::MENU_EVENT_RECORD do
|
27
|
+
it_behaves_like 'attributes_and_size_test' do
|
28
|
+
let(:ary) { [:dwCommandId] }
|
29
|
+
let(:sze) { 4 }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe described_class::FOCUS_EVENT_RECORD do
|
34
|
+
it_behaves_like 'attributes_and_size_test' do
|
35
|
+
let(:ary) { [:bSetFocus] }
|
36
|
+
let(:sze) { 4 }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe described_class::KEY_EVENT_RECORD do
|
41
|
+
it_behaves_like 'attributes_and_size_test' do
|
42
|
+
let(:ary) { [:bKeyDown, :wRepeatCount, :wVirtualKeyCode, :wVirtualScanCode, :uChar, :dwControlKeyState] }
|
43
|
+
let(:sze) { 16 }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '::vk_names' do
|
48
|
+
it 'has the list of events' do
|
49
|
+
expect(described_class.vk_names).to eql([:KEY_EVENT, :MOUSE_EVENT, :WINDOW_BUFFER_SIZE_EVENT, :MENU_EVENT, :FOCUS_EVENT])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '::vk_hash' do
|
54
|
+
it 'to be a hash with keys equal to Constant values and values equal to constant names' do
|
55
|
+
expect(described_class.vk_hash).to eql(described_class.vk_names.map.with_object({}) {|vk, hsh| hsh[Vigilem::Win32API::Constants::Events.const_get(vk)] = vk })
|
56
|
+
end
|
57
|
+
end
|
58
|
+
=begin
|
59
|
+
describe '::structs' do
|
60
|
+
it 'will return an array of the structs that are the event types' do
|
61
|
+
expect(described_class.structs.sort).to eq([described_class::KEY_EVENT_RECORD,
|
62
|
+
described_class::MOUSE_EVENT_RECORD, described_class::WINDOW_BUFFER_SIZE_RECORD,
|
63
|
+
described_class::MENU_EVENT_RECORD, described_class::FOCUS_EVENT_RECORD].sort)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
=end
|
67
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'vigilem/win32_api/dom'
|
4
|
+
|
5
|
+
describe Vigilem::Win32API::DOM::Adapter do
|
6
|
+
|
7
|
+
let(:api) { Vigilem::Win32API }
|
8
|
+
|
9
|
+
after(:example) do
|
10
|
+
flush
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:dw_numlock) { 0x0020 }
|
14
|
+
|
15
|
+
let(:input_record) {
|
16
|
+
api::INPUT_RECORD[api::KEY_EVENT, {:KeyEvent => [1, 1, 0x41, 30, {:UnicodeChar => 65 }, dw_numlock]}]
|
17
|
+
}
|
18
|
+
|
19
|
+
def key_event_template(type, opts={})
|
20
|
+
{
|
21
|
+
:bubbles=>false, :cancelable=>false, :code=>"KeyA", :detail=>0, :isTrusted=>true, :isComposing=>false,
|
22
|
+
:key=>"A", :location=>0,
|
23
|
+
:modifier_state=>{"Accel"=>false, "Alt"=>false, "AltGraph"=>false, "CapsLock"=>false,
|
24
|
+
"Control"=>false, "Fn"=>false, "FnLock"=>false, "Hyper"=>false, "Meta"=>false,
|
25
|
+
"NumLock"=>false, "OS"=>false, "ScrollLock"=>false, "Shift"=>false, "Super"=>false,
|
26
|
+
"Symbol"=>false, "SymbolLock"=>false},
|
27
|
+
:os_specific=>{:bKeyDown=>1, :wRepeatCount=>1, :wVirtualKeyCode=>65, :wVirtualScanCode=>30,
|
28
|
+
:uChar=>{:UnicodeChar=>65, :AsciiChar=>65}, :dwControlKeyState=>32},
|
29
|
+
:repeat=>false, :timeStamp=>kind_of(Numeric), :type=>type,
|
30
|
+
:view=>nil
|
31
|
+
}.merge(opts)
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#handle' do
|
35
|
+
it 'sends Win32API::KEY_EVENT_RECORD events to #to_dom_key_event' do
|
36
|
+
allow(subject).to receive(:to_dom_key_event)
|
37
|
+
expect(subject).to receive(:to_dom_key_event)
|
38
|
+
subject.handle(input_record.event_record)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#read_many' do
|
43
|
+
it 'blocks until the number passed in is reached' do
|
44
|
+
allow(subject.send(:link)).to receive(:ReadConsoleInput) { [input_record] }
|
45
|
+
expect do
|
46
|
+
Timeout::timeout(4) {
|
47
|
+
subject.read_many(3)
|
48
|
+
}
|
49
|
+
end.to raise_error(Timeout::Error)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'retrieves multiple dom message' do
|
53
|
+
allow(subject.send(:link)).to receive(:read_many_nonblock).and_return([input_record, input_record])
|
54
|
+
Timeout::timeout(4) {
|
55
|
+
expect(subject.read_many(2)).to contain_exactly(
|
56
|
+
an_object_having_attributes(key_event_template("keydown")),
|
57
|
+
an_object_having_attributes(key_event_template("keypress"))
|
58
|
+
)
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'will fill the buffer with the leftovers' do
|
63
|
+
allow(subject.send(:link)).to receive(:read_many_nonblock).and_return([input_record, input_record])
|
64
|
+
subject.read_many(2)
|
65
|
+
Timeout::timeout(4) {
|
66
|
+
expect(subject.buffer.to_a).to contain_exactly(
|
67
|
+
an_object_having_attributes(key_event_template("keydown", repeat: true)),
|
68
|
+
an_object_having_attributes(key_event_template("keypress", repeat: true))
|
69
|
+
)
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#read_many_nonblock' do
|
75
|
+
|
76
|
+
it %q{doesn't block and returns nil when nothing in the queue} do
|
77
|
+
allow(subject.send(:link)).to receive(:read_console_input).with(:nLength => 1, :blocking => true).and_call_original
|
78
|
+
allow(subject.send(:link)).to receive(:ReadConsoleInput) { sleep 3.5 }
|
79
|
+
expect do
|
80
|
+
Timeout::timeout(3) {
|
81
|
+
subject.read_many_nonblock(3)
|
82
|
+
}
|
83
|
+
end.not_to raise_error
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'retrieves multiple dom messages' do
|
87
|
+
allow(subject.send(:link)).to receive(:read_many_nonblock).and_return([input_record, input_record])
|
88
|
+
expect(subject.read_many_nonblock(2)).to contain_exactly(
|
89
|
+
an_object_having_attributes(key_event_template("keydown")),
|
90
|
+
an_object_having_attributes(key_event_template("keypress"))
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'will fill the buffer with the leftovers' do
|
95
|
+
allow(subject.send(:link)).to receive(:read_many_nonblock).and_return([input_record, input_record])
|
96
|
+
subject.read_many_nonblock(2)
|
97
|
+
expect(subject.buffer.to_a).to contain_exactly(
|
98
|
+
an_object_having_attributes(key_event_template("keydown", repeat: true)),
|
99
|
+
an_object_having_attributes(key_event_template("keypress", repeat: true))
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
class UnknownEvent
|
104
|
+
def event_record
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'will return emty array if none of the events are handled' do
|
109
|
+
allow(subject.send(:link)).to receive(:read_many_nonblock).and_return([UnknownEvent.new])
|
110
|
+
expect(subject.read_many_nonblock(2)).to eql([])
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
describe '#read_one' do
|
116
|
+
|
117
|
+
it 'retrieves one dom message' do
|
118
|
+
allow(subject.send(:link)).to receive(:read_many_nonblock).and_return([input_record])
|
119
|
+
Timeout::timeout(4) {
|
120
|
+
expect(subject.read_one).to be_a(Vigilem::DOM::KeyboardEvent) and
|
121
|
+
have_attributes(key_event_template("keydown"))
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'will block when no messages in buffer and non in the windows message queue' do
|
126
|
+
allow(subject.send(:link)).to receive(:read_many_nonblock).and_call_original
|
127
|
+
allow(subject.send(:link)).to receive(:ReadConsoleInput) { sleep 2.5 }
|
128
|
+
expect do
|
129
|
+
Timeout::timeout(2) {
|
130
|
+
subject.read_one
|
131
|
+
}
|
132
|
+
end.to raise_error(Timeout::Error)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe '#read_one_nonblock' do
|
137
|
+
|
138
|
+
it 'retrieves one dom message' do
|
139
|
+
allow(subject.send(:link)).to receive(:read_many_nonblock).and_return([input_record])
|
140
|
+
Timeout::timeout(4) {
|
141
|
+
expect(subject.read_one_nonblock).to be_a(Vigilem::DOM::KeyboardEvent) and
|
142
|
+
have_attributes(key_event_template("keydown"))
|
143
|
+
}
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'will fill the buffer with the leftovers' do
|
147
|
+
allow(subject.send(:link)).to receive(:read_many_nonblock).and_return([input_record])
|
148
|
+
subject.read_one_nonblock
|
149
|
+
expect(subject.buffer.to_a).to contain_exactly(
|
150
|
+
an_object_having_attributes(key_event_template("keypress"))
|
151
|
+
)
|
152
|
+
end
|
153
|
+
|
154
|
+
it %q{will not block when no messages in buffer} do
|
155
|
+
allow(subject.send(:link)).to receive(:read_console_input).with(:nLength => 1, :blocking => false).and_call_original
|
156
|
+
allow(subject.send(:link)).to receive(:ReadConsoleInput) { sleep 2.5 }
|
157
|
+
expect do
|
158
|
+
Timeout::timeout(2) {
|
159
|
+
subject.read_one_nonblock
|
160
|
+
}
|
161
|
+
end.not_to raise_error
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,255 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'vigilem/dom'
|
4
|
+
|
5
|
+
require 'vigilem/win32_api'
|
6
|
+
|
7
|
+
require 'vigilem/win32_api/input_system_handler'
|
8
|
+
|
9
|
+
require 'vigilem/win32_api/dom/input_record_utils'
|
10
|
+
|
11
|
+
|
12
|
+
describe Vigilem::Win32API::DOM::InputRecordUtils do
|
13
|
+
|
14
|
+
let(:api) { Vigilem::Win32API }
|
15
|
+
|
16
|
+
let(:dw_numlock) { 0x0020 }
|
17
|
+
|
18
|
+
let(:dw_lmenu) { 0x0002 }
|
19
|
+
|
20
|
+
let(:dw_rmenu) { 0x0001 }
|
21
|
+
|
22
|
+
let(:dw_shift) { 0x0010 }
|
23
|
+
|
24
|
+
let(:key_event_record) { api::KEY_EVENT_RECORD[1, 1, 0x41, 30, {:UnicodeChar => 65 }, dw_numlock] }
|
25
|
+
|
26
|
+
let(:event_record_lmenu) { api::KEY_EVENT_RECORD[1, 1, 0x12, 30, {:UnicodeChar => 0 }, dw_numlock + dw_lmenu] }
|
27
|
+
|
28
|
+
let!(:host) do
|
29
|
+
class IRU
|
30
|
+
include Vigilem::Core::Adapters::Adapter
|
31
|
+
include Vigilem::Win32API::Rubyized
|
32
|
+
include Vigilem::Win32API::DOM::InputRecordUtils
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
self.win32_api_rubyized_src = self.link
|
36
|
+
end
|
37
|
+
|
38
|
+
def link
|
39
|
+
@isys ||= Vigilem::Win32API::InputSystemHandler.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
IRU.new
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#current_keys' do
|
46
|
+
it 'defaults to an empty array' do
|
47
|
+
expect(host.current_keys).to eql([])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#to_dom_key_event' do
|
52
|
+
|
53
|
+
def key_event(type, opts={})
|
54
|
+
{
|
55
|
+
bubbles: false, cancelable: false, code: "KeyA", detail: 0, isTrusted: true,
|
56
|
+
isComposing: false, key: "A", location: 0,
|
57
|
+
modifier_state: {"Accel"=>false, "Alt"=>false, "AltGraph"=>false, "CapsLock"=>false, "Control"=>false,
|
58
|
+
"Fn"=>false, "FnLock"=>false, "Hyper"=>false, "Meta"=>false, "NumLock"=>false, "OS"=>false,
|
59
|
+
"ScrollLock"=>false, "Shift"=>false, "Super"=>false, "Symbol"=>false, "SymbolLock"=>false},
|
60
|
+
os_specific: {:bKeyDown=>1, :wRepeatCount=>1, :wVirtualKeyCode=>65, :wVirtualScanCode=>30,
|
61
|
+
:uChar=>{:UnicodeChar=>65, :AsciiChar=>65}, :dwControlKeyState=>dw_numlock},
|
62
|
+
repeat: false, timeStamp: kind_of(Numeric), type: type, view: nil
|
63
|
+
}.merge(opts)
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'simple conversion' do
|
67
|
+
|
68
|
+
let!(:result) { host.to_dom_key_event(key_event_record) }
|
69
|
+
|
70
|
+
it 'converts an input_record to a DOM Event' do
|
71
|
+
expect(result).to match [
|
72
|
+
an_object_having_attributes(key_event('keydown')),
|
73
|
+
an_object_having_attributes(key_event('keypress'))
|
74
|
+
]
|
75
|
+
end
|
76
|
+
|
77
|
+
# @todo be more specific
|
78
|
+
it 'updates #current_keys' do
|
79
|
+
expect(host.current_keys.size).to be > 0
|
80
|
+
end
|
81
|
+
end
|
82
|
+
context 'repeats' do
|
83
|
+
|
84
|
+
let(:repeat_results) { 1.upto(2).map {|n| host.to_dom_key_event(key_event_record) } }
|
85
|
+
|
86
|
+
it 'converts an input_record to a DOM Event and keeps track of state' do
|
87
|
+
expect(repeat_results).to match [
|
88
|
+
[an_object_having_attributes(key_event('keydown')), # its wrongly making this repeat
|
89
|
+
an_object_having_attributes(key_event('keypress'))], # its wrongly making this repeat
|
90
|
+
[an_object_having_attributes(key_event('keydown', repeat: true)),
|
91
|
+
an_object_having_attributes(key_event('keypress', repeat: true))] # chrome 39.0.2171.95 m produces `false'
|
92
|
+
]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#dw_control_key_state_vks' do
|
99
|
+
it 'lists the names of the constants that represent the dw_control_state' do
|
100
|
+
expect(host.dw_control_key_state_vks(dw_numlock + dw_lmenu)).to eql([:LEFT_ALT_PRESSED, :NUMLOCK_ON])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#location_less_vks_map' do
|
105
|
+
it 'returns a Hash with vk as keys' do
|
106
|
+
expect(host.location_less_vks_map.keys).to all( be_instance_of(Symbol) )
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'returns a Hash with Regexp as values' do
|
110
|
+
expect(host.location_less_vks_map.values).to all( be_instance_of(Regexp) )
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe '#vk_without_location_info?' do
|
115
|
+
it 'returns whether or not a virtual key need location info' do
|
116
|
+
expect(:VK_MENU).to be_truthy
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe '#shift_scan_code_to_location_vk' do
|
121
|
+
|
122
|
+
let(:l_shift) { IRU::VK_LSHIFT }
|
123
|
+
|
124
|
+
let(:l_shift_vsc) { api.MapVirtualKeyW(l_shift, IRU::MapVK::VK_TO_VSC) }
|
125
|
+
|
126
|
+
it 'creates a hash that maps the scancodes to :VK_LSHIFT and :VK_RSHIFT ' do
|
127
|
+
expect(host.shift_scan_code_to_location_vk[l_shift_vsc]).to eql(:VK_LSHIFT)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '::flip_lr_sides' do
|
132
|
+
it 'converts "l" or "L" to "r" or "R"' do
|
133
|
+
expect(described_class.flip_lr_sides('L')).to eql('R')
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe '::lr_location_from_name' do
|
138
|
+
it 'pulls the "L" or "R" from the string name' do
|
139
|
+
expect(described_class.lr_location_from_name(:LEFT_CTRL_PRESSED)).to eql('L')
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '::empty_or_null?' do
|
144
|
+
it 'returns true for empty Strings ' do
|
145
|
+
expect(described_class.empty_or_null?("")).to be_truthy
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'returns true for a String with only "\x00"' do
|
149
|
+
expect(described_class.empty_or_null?("\x00\x00")).to be_truthy
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe '#dom_location' do
|
154
|
+
|
155
|
+
let(:vk_menu_vsc) { api.MapVirtualKeyW(IRU::VK_MENU, IRU::MapVK::VK_TO_VSC) }
|
156
|
+
|
157
|
+
context ', both ALT\'s are pressed yet niether in the current_keys' do
|
158
|
+
|
159
|
+
let(:dw_state_names) { host.dw_control_key_state_vks(3) }
|
160
|
+
|
161
|
+
it 'will raise an error in this situation' do
|
162
|
+
expect { host.dom_location(:VK_MENU, vk_menu_vsc, dw_state_names) }.to raise_error
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
context 'generic vk with dw_state_names' do
|
168
|
+
|
169
|
+
let(:dw_state_names) { host.dw_control_key_state_vks(2) }
|
170
|
+
|
171
|
+
let(:dw_state_names_right) { host.dw_control_key_state_vks(1) }
|
172
|
+
|
173
|
+
it 'will get left the location from the dw_state_name' do
|
174
|
+
expect(host.dom_location(:VK_MENU, vk_menu_vsc, dw_state_names)).to eql(1)
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'will get right the location from the dw_state_name' do
|
178
|
+
expect(host.dom_location(:VK_MENU, vk_menu_vsc, dw_state_names_right)).to eql(2)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
describe '#lr_not_in_name' do
|
185
|
+
|
186
|
+
let(:vk_menu_vsc) { api.MapVirtualKeyW(IRU::VK_MENU, IRU::MapVK::VK_TO_VSC) }
|
187
|
+
|
188
|
+
let(:vk_rmenu_vsc) { api.MapVirtualKeyW(IRU::VK_RMENU, IRU::MapVK::VK_TO_VSC) }
|
189
|
+
|
190
|
+
let(:vk_rshift_vsc) { api.MapVirtualKeyW(IRU::VK_RSHIFT, IRU::MapVK::VK_TO_VSC) }
|
191
|
+
|
192
|
+
let(:lr_menu_dw_state_names) { host.dw_control_key_state_vks(dw_numlock + dw_lmenu + dw_rmenu) }
|
193
|
+
|
194
|
+
let(:l_menu_dw_state_names) { host.dw_control_key_state_vks(dw_numlock + dw_lmenu) }
|
195
|
+
|
196
|
+
let(:dw_state_names_w_shift) { host.dw_control_key_state_vks(dw_shift) }
|
197
|
+
|
198
|
+
it 'gets the location info from virtual-key and dw_state_names' do
|
199
|
+
expect(host.lr_not_in_name(:VK_MENU, vk_menu_vsc, l_menu_dw_state_names)).to eql('l')
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'gets the location info from the scan code' do
|
203
|
+
expect(host.lr_not_in_name(:VK_SHIFT, vk_rshift_vsc, dw_state_names_w_shift)).to eql('r')
|
204
|
+
end
|
205
|
+
|
206
|
+
context 'with current keys' do
|
207
|
+
let!(:converted_result) { host.to_dom_key_event(event_record_lmenu) }
|
208
|
+
|
209
|
+
it 'gets the location info from the #current keys' do
|
210
|
+
expect(host.lr_not_in_name(:VK_MENU, vk_rmenu_vsc, lr_menu_dw_state_names)).to eql('r')
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe '#dom_key' do
|
216
|
+
|
217
|
+
let(:l_shift) { IRU::VK_LSHIFT }
|
218
|
+
|
219
|
+
it 'converts modifier virtual-key to dom_key' do
|
220
|
+
expect(host.dom_key(:VK_SHIFT, 0)).to eql('Shift')
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'converts character virtual-key to dom_key' do
|
224
|
+
expect(host.dom_key(:VK_A, 97)).to eql('a')
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe '#dom_code' do
|
229
|
+
it 'produces the code attribute for a character key For DOM::Keyboard Event' do
|
230
|
+
expect(host.dom_code(:VK_A, 65, 0)).to eql('KeyA')
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'produces the code attribute for a modifier key For DOM::Keyboard Event' do
|
234
|
+
expect(host.dom_code(:VK_MENU, 0, 'l')).to eql('AltLeft')
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'produces the code attribute for a modifier key For DOM::Keyboard Event' do
|
238
|
+
expect(host.dom_code(:VK_RETURN, 10, 3, :ENHANCED_KEY)).to eql('NumpadEnter')
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe '#dom_modifiers' do
|
243
|
+
|
244
|
+
it 'convert dw_control_names to more typical modifier names' do
|
245
|
+
expect(::VDOM::KeyboardEvent).to receive(:shared_keyboard_and_mouse_event_init).with([:alt, :numlock])
|
246
|
+
host.dom_modifiers(:LEFT_ALT_PRESSED, :NUMLOCK_ON)
|
247
|
+
end
|
248
|
+
it 'converts dw_control_state_names to an array of symbols' do
|
249
|
+
expect(host.dom_modifiers(:LEFT_ALT_PRESSED, :NUMLOCK_ON)).to eql({ :altKey=>true, :keyModifierStateAltGraph=>false, :keyModifierStateCapsLock=>false,
|
250
|
+
:ctrlKey=>false, :keyModifierStateFn=>false, :keyModifierStateFnLock=>false, :keyModifierStateHyper=>false,
|
251
|
+
:metaKey=>false, :keyModifierStateNumLock=>true, :keyModifierStateOS=>false, :keyModifierStateScrollLock=>false,
|
252
|
+
:shiftKey=>false, :keyModifierStateSuper=>false, :keyModifierStateSymbol=>false, :keyModifierStateSymbolLock=>false })
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|