Skip to content

Commit def5cdc

Browse files
committed
Send keyCode if the key information is gone
1 parent 5c1b806 commit def5cdc

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

src/lib/vm-listener-hoc.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ const vmListenerHOC = function (WrappedComponent) {
8787
// Don't capture keys intended for Blockly inputs.
8888
if (e.target !== document && e.target !== document.body) return;
8989

90+
const key = (!e.key || e.key === 'Dead') ? e.keyCode : e.key;
9091
this.props.vm.postIOData('keyboard', {
91-
keyCode: e.keyCode,
92-
key: e.key,
92+
key: key,
9393
isDown: true
9494
});
9595

@@ -102,9 +102,9 @@ const vmListenerHOC = function (WrappedComponent) {
102102
handleKeyUp (e) {
103103
// Always capture up events,
104104
// even those that have switched to other targets.
105+
const key = (!e.key || e.key === 'Dead') ? e.keyCode : e.key;
105106
this.props.vm.postIOData('keyboard', {
106-
keyCode: e.keyCode,
107-
key: e.key,
107+
key: key,
108108
isDown: false
109109
});
110110

test/unit/util/vm-listener-hoc.test.jsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,49 @@ describe('VMListenerHOC', () => {
133133
const actions = store.getActions();
134134
expect(actions.length).toEqual(0);
135135
});
136+
137+
test('keypresses go to the vm', () => {
138+
const Component = () => (<div />);
139+
const WrappedComponent = vmListenerHOC(Component);
140+
141+
// Mock document.addEventListener so we can trigger keypresses manually
142+
// Cannot use the enzyme simulate method because that only works on synthetic events
143+
const eventTriggers = {};
144+
document.addEventListener = jest.fn((event, cb) => {
145+
eventTriggers[event] = cb;
146+
});
147+
148+
vm.postIOData = jest.fn();
149+
150+
store = mockStore({
151+
scratchGui: {
152+
mode: {isFullScreen: true},
153+
modals: {soundRecorder: true},
154+
vm: vm
155+
}
156+
});
157+
mount(
158+
<WrappedComponent
159+
attachKeyboardEvents
160+
store={store}
161+
vm={vm}
162+
/>
163+
);
164+
165+
// keyboard events that do not target the document or body are ignored
166+
eventTriggers.keydown({key: 'A', target: null});
167+
expect(vm.postIOData).not.toHaveBeenLastCalledWith('keyboard', {key: 'A', isDown: true});
168+
169+
// keydown/up with target as the document are sent to the vm via postIOData
170+
eventTriggers.keydown({key: 'A', target: document});
171+
expect(vm.postIOData).toHaveBeenLastCalledWith('keyboard', {key: 'A', isDown: true});
172+
173+
eventTriggers.keyup({key: 'A', target: document});
174+
expect(vm.postIOData).toHaveBeenLastCalledWith('keyboard', {key: 'A', isDown: false});
175+
176+
// When key is 'Dead' e.g. bluetooth keyboards on iOS, it sends keyCode instead
177+
// because the VM can process both named keys or keyCodes as the `key` property
178+
eventTriggers.keyup({key: 'Dead', keyCode: 10, target: document});
179+
expect(vm.postIOData).toHaveBeenLastCalledWith('keyboard', {key: 10, isDown: false});
180+
});
136181
});

0 commit comments

Comments
 (0)