Remove modifier synchronisation
The fields provided cannot tell us if it is the left or right version of the key that's pressed, so they are inherently unreliable. It is also not a huge problem in practice as we'll get in sync on the next press or release of the modifier.
This commit is contained in:
parent
a784a9cabc
commit
9e6f71cb75
|
@ -120,10 +120,6 @@ Keyboard.prototype = {
|
||||||
|
|
||||||
//Log.Debug(">> Keyboard.ungrab");
|
//Log.Debug(">> Keyboard.ungrab");
|
||||||
},
|
},
|
||||||
|
|
||||||
sync: function (e) {
|
|
||||||
this._handler.syncModifiers(e);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
make_properties(Keyboard, [
|
make_properties(Keyboard, [
|
||||||
|
@ -178,10 +174,6 @@ Mouse.prototype = {
|
||||||
_handleMouseButton: function (e, down) {
|
_handleMouseButton: function (e, down) {
|
||||||
if (!this._focused) { return; }
|
if (!this._focused) { return; }
|
||||||
|
|
||||||
if (this._notify) {
|
|
||||||
this._notify(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pos = this._getMousePosition(e);
|
var pos = this._getMousePosition(e);
|
||||||
|
|
||||||
var bmask;
|
var bmask;
|
||||||
|
@ -248,10 +240,6 @@ Mouse.prototype = {
|
||||||
_handleMouseWheel: function (e) {
|
_handleMouseWheel: function (e) {
|
||||||
if (!this._focused) { return; }
|
if (!this._focused) { return; }
|
||||||
|
|
||||||
if (this._notify) {
|
|
||||||
this._notify(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pos = this._getMousePosition(e);
|
var pos = this._getMousePosition(e);
|
||||||
|
|
||||||
if (this._onMouseButton) {
|
if (this._onMouseButton) {
|
||||||
|
@ -278,10 +266,6 @@ Mouse.prototype = {
|
||||||
_handleMouseMove: function (e) {
|
_handleMouseMove: function (e) {
|
||||||
if (! this._focused) { return; }
|
if (! this._focused) { return; }
|
||||||
|
|
||||||
if (this._notify) {
|
|
||||||
this._notify(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pos = this._getMousePosition(e);
|
var pos = this._getMousePosition(e);
|
||||||
if (this._onMouseMove) {
|
if (this._onMouseMove) {
|
||||||
this._onMouseMove(pos.x, pos.y);
|
this._onMouseMove(pos.x, pos.y);
|
||||||
|
@ -373,7 +357,6 @@ Mouse.prototype = {
|
||||||
|
|
||||||
make_properties(Mouse, [
|
make_properties(Mouse, [
|
||||||
['target', 'ro', 'dom'], // DOM element that captures mouse input
|
['target', 'ro', 'dom'], // DOM element that captures mouse input
|
||||||
['notify', 'ro', 'func'], // Function to call to notify whenever a mouse event is received
|
|
||||||
['focused', 'rw', 'bool'], // Capture and send mouse clicks/movement
|
['focused', 'rw', 'bool'], // Capture and send mouse clicks/movement
|
||||||
|
|
||||||
['onMouseButton', 'rw', 'func'], // Handler for mouse button click/release
|
['onMouseButton', 'rw', 'func'], // Handler for mouse button click/release
|
||||||
|
|
|
@ -100,8 +100,6 @@ export function ModifierSync(charModifier) {
|
||||||
// sync on the appropriate keyboard event
|
// sync on the appropriate keyboard event
|
||||||
keydown: function(evt) { return syncKeyEvent(evt, true);},
|
keydown: function(evt) { return syncKeyEvent(evt, true);},
|
||||||
keyup: function(evt) { return syncKeyEvent(evt, false);},
|
keyup: function(evt) { return syncKeyEvent(evt, false);},
|
||||||
// Call this with a non-keyboard event (such as mouse events) to use its modifier state to synchronize anyway
|
|
||||||
syncAny: function(evt) { return sync(evt);},
|
|
||||||
|
|
||||||
// if a char modifier is down, return the keys it consists of, otherwise return null
|
// if a char modifier is down, return the keys it consists of, otherwise return null
|
||||||
activeCharModifier: function() { return hasCharModifier(charModifier, state) ? charModifier : null; }
|
activeCharModifier: function() { return hasCharModifier(charModifier, state) ? charModifier : null; }
|
||||||
|
@ -260,16 +258,10 @@ export function getKeysym(evt){
|
||||||
// Takes a DOM keyboard event and:
|
// Takes a DOM keyboard event and:
|
||||||
// - determines which keysym it represents
|
// - determines which keysym it represents
|
||||||
// - determines a code identifying the key that was pressed (corresponding to the code/keyCode properties on the DOM event)
|
// - determines a code identifying the key that was pressed (corresponding to the code/keyCode properties on the DOM event)
|
||||||
// - synthesizes events to synchronize modifier key state between which modifiers are actually down, and which we thought were down
|
|
||||||
// - marks each event with an 'escape' property if a modifier was down which should be "escaped"
|
// - marks each event with an 'escape' property if a modifier was down which should be "escaped"
|
||||||
// This information is collected into an object which is passed to the next() function. (one call per event)
|
// This information is collected into an object which is passed to the next() function. (one call per event)
|
||||||
export function KeyEventDecoder (modifierState, next) {
|
export function KeyEventDecoder (modifierState, next) {
|
||||||
"use strict";
|
"use strict";
|
||||||
function sendAll(evts) {
|
|
||||||
for (var i = 0; i < evts.length; ++i) {
|
|
||||||
next(evts[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function process(evt, type) {
|
function process(evt, type) {
|
||||||
var result = {type: type};
|
var result = {type: type};
|
||||||
var code = getKeycode(evt);
|
var code = getKeycode(evt);
|
||||||
|
@ -322,19 +314,16 @@ export function KeyEventDecoder (modifierState, next) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
keydown: function(evt) {
|
keydown: function(evt) {
|
||||||
sendAll(modifierState.keydown(evt));
|
modifierState.keydown(evt);
|
||||||
return process(evt, 'keydown');
|
return process(evt, 'keydown');
|
||||||
},
|
},
|
||||||
keypress: function(evt) {
|
keypress: function(evt) {
|
||||||
return process(evt, 'keypress');
|
return process(evt, 'keypress');
|
||||||
},
|
},
|
||||||
keyup: function(evt) {
|
keyup: function(evt) {
|
||||||
sendAll(modifierState.keyup(evt));
|
modifierState.keyup(evt);
|
||||||
return process(evt, 'keyup');
|
return process(evt, 'keyup');
|
||||||
},
|
},
|
||||||
syncModifiers: function(evt) {
|
|
||||||
sendAll(modifierState.syncAny(evt));
|
|
||||||
},
|
|
||||||
releaseAll: function() { next({type: 'releaseall'}); }
|
releaseAll: function() { next({type: 'releaseall'}); }
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -204,8 +204,7 @@ export default function RFB(defaults) {
|
||||||
|
|
||||||
this._mouse = new Mouse({target: this._target,
|
this._mouse = new Mouse({target: this._target,
|
||||||
onMouseButton: this._handleMouseButton.bind(this),
|
onMouseButton: this._handleMouseButton.bind(this),
|
||||||
onMouseMove: this._handleMouseMove.bind(this),
|
onMouseMove: this._handleMouseMove.bind(this)});
|
||||||
notify: this._keyboard.sync.bind(this._keyboard)});
|
|
||||||
|
|
||||||
this._sock = new Websock();
|
this._sock = new Websock();
|
||||||
this._sock.on('message', this._handle_message.bind(this));
|
this._sock.on('message', this._handle_message.bind(this));
|
||||||
|
|
|
@ -155,165 +155,4 @@ describe('Helpers', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Modifier Sync', function() { // return a list of fake events necessary to fix modifier state
|
|
||||||
describe('Toggle all modifiers', function() {
|
|
||||||
var sync = KeyboardUtil.ModifierSync();
|
|
||||||
it ('should do nothing if all modifiers are up as expected', function() {
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
ctrlKey: false,
|
|
||||||
altKey: false,
|
|
||||||
altGraphKey: false,
|
|
||||||
shiftKey: false,
|
|
||||||
metaKey: false})
|
|
||||||
).to.have.lengthOf(0);
|
|
||||||
});
|
|
||||||
it ('should synthesize events if all keys are unexpectedly down', function() {
|
|
||||||
var result = sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
ctrlKey: true,
|
|
||||||
altKey: true,
|
|
||||||
altGraphKey: true,
|
|
||||||
shiftKey: true,
|
|
||||||
metaKey: true
|
|
||||||
});
|
|
||||||
expect(result).to.have.lengthOf(5);
|
|
||||||
var keysyms = {};
|
|
||||||
for (var i = 0; i < result.length; ++i) {
|
|
||||||
keysyms[result[i].keysym] = (result[i].type == 'keydown');
|
|
||||||
}
|
|
||||||
expect(keysyms[0xffe3]);
|
|
||||||
expect(keysyms[0xffe9]);
|
|
||||||
expect(keysyms[0xfe03]);
|
|
||||||
expect(keysyms[0xffe1]);
|
|
||||||
expect(keysyms[0xffe7]);
|
|
||||||
});
|
|
||||||
it ('should do nothing if all modifiers are down as expected', function() {
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
ctrlKey: true,
|
|
||||||
altKey: true,
|
|
||||||
altGraphKey: true,
|
|
||||||
shiftKey: true,
|
|
||||||
metaKey: true
|
|
||||||
})).to.have.lengthOf(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('Toggle Ctrl', function() {
|
|
||||||
var sync = KeyboardUtil.ModifierSync();
|
|
||||||
it('should sync if modifier is suddenly down', function() {
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
ctrlKey: true,
|
|
||||||
})).to.be.deep.equal([{keysym: 0xffe3, type: 'keydown'}]);
|
|
||||||
});
|
|
||||||
it('should sync if modifier is suddenly up', function() {
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
ctrlKey: false
|
|
||||||
})).to.be.deep.equal([{keysym: 0xffe3, type: 'keyup'}]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('Toggle Alt', function() {
|
|
||||||
var sync = KeyboardUtil.ModifierSync();
|
|
||||||
it('should sync if modifier is suddenly down', function() {
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
altKey: true,
|
|
||||||
})).to.be.deep.equal([{keysym: 0xffe9, type: 'keydown'}]);
|
|
||||||
});
|
|
||||||
it('should sync if modifier is suddenly up', function() {
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
altKey: false
|
|
||||||
})).to.be.deep.equal([{keysym: 0xffe9, type: 'keyup'}]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('Toggle AltGr', function() {
|
|
||||||
var sync = KeyboardUtil.ModifierSync();
|
|
||||||
it('should sync if modifier is suddenly down', function() {
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
altGraphKey: true,
|
|
||||||
})).to.be.deep.equal([{keysym: 0xfe03, type: 'keydown'}]);
|
|
||||||
});
|
|
||||||
it('should sync if modifier is suddenly up', function() {
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
altGraphKey: false
|
|
||||||
})).to.be.deep.equal([{keysym: 0xfe03, type: 'keyup'}]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('Toggle Shift', function() {
|
|
||||||
var sync = KeyboardUtil.ModifierSync();
|
|
||||||
it('should sync if modifier is suddenly down', function() {
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
shiftKey: true,
|
|
||||||
})).to.be.deep.equal([{keysym: 0xffe1, type: 'keydown'}]);
|
|
||||||
});
|
|
||||||
it('should sync if modifier is suddenly up', function() {
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
shiftKey: false
|
|
||||||
})).to.be.deep.equal([{keysym: 0xffe1, type: 'keyup'}]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('Toggle Meta', function() {
|
|
||||||
var sync = KeyboardUtil.ModifierSync();
|
|
||||||
it('should sync if modifier is suddenly down', function() {
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
metaKey: true,
|
|
||||||
})).to.be.deep.equal([{keysym: 0xffe7, type: 'keydown'}]);
|
|
||||||
});
|
|
||||||
it('should sync if modifier is suddenly up', function() {
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
metaKey: false
|
|
||||||
})).to.be.deep.equal([{keysym: 0xffe7, type: 'keyup'}]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('Modifier keyevents', function() {
|
|
||||||
it('should not sync a modifier on its own events', function() {
|
|
||||||
expect(KeyboardUtil.ModifierSync().keydown({
|
|
||||||
code: 'ControlLeft',
|
|
||||||
ctrlKey: false
|
|
||||||
})).to.be.deep.equal([]);
|
|
||||||
expect(KeyboardUtil.ModifierSync().keydown({
|
|
||||||
code: 'ControlLeft',
|
|
||||||
ctrlKey: true
|
|
||||||
}), 'B').to.be.deep.equal([]);
|
|
||||||
})
|
|
||||||
it('should update state on modifier keyevents', function() {
|
|
||||||
var sync = KeyboardUtil.ModifierSync();
|
|
||||||
sync.keydown({
|
|
||||||
code: 'ControlLeft',
|
|
||||||
});
|
|
||||||
expect(sync.keydown({
|
|
||||||
code: 'KeyA',
|
|
||||||
ctrlKey: true,
|
|
||||||
})).to.be.deep.equal([]);
|
|
||||||
});
|
|
||||||
it('should sync other modifiers on ctrl events', function() {
|
|
||||||
expect(KeyboardUtil.ModifierSync().keydown({
|
|
||||||
code: 'ControlLeft',
|
|
||||||
altKey: true
|
|
||||||
})).to.be.deep.equal([{keysym: 0xffe9, type: 'keydown'}]);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
describe('sync modifiers on non-key events', function() {
|
|
||||||
it('should generate sync events when receiving non-keyboard events', function() {
|
|
||||||
expect(KeyboardUtil.ModifierSync().syncAny({
|
|
||||||
altKey: true
|
|
||||||
})).to.be.deep.equal([{keysym: 0xffe9, type: 'keydown'}]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('do not treat shift as a modifier key', function() {
|
|
||||||
it('should not treat shift as a char modifier', function() {
|
|
||||||
expect(KeyboardUtil.hasCharModifier([], {0xffe1 : true})).to.be.false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,29 +26,6 @@ describe('Key Event Pipeline Stages', function() {
|
||||||
done();
|
done();
|
||||||
}).keydown({code: 'KeyA', key: 'a'});
|
}).keydown({code: 'KeyA', key: 'a'});
|
||||||
});
|
});
|
||||||
it('should not sync modifiers on a keypress', function() {
|
|
||||||
// Firefox provides unreliable modifier state on keypress events
|
|
||||||
var count = 0;
|
|
||||||
KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) {
|
|
||||||
++count;
|
|
||||||
}).keypress({code: 'KeyA', key: 'a', ctrlKey: true});
|
|
||||||
expect(count).to.be.equal(1);
|
|
||||||
});
|
|
||||||
it('should sync modifiers if necessary', function(done) {
|
|
||||||
var count = 0;
|
|
||||||
KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) {
|
|
||||||
switch (count) {
|
|
||||||
case 0: // fake a ctrl keydown
|
|
||||||
expect(evt).to.be.deep.equal({keysym: 0xffe3, type: 'keydown'});
|
|
||||||
++count;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
expect(evt).to.be.deep.equal({code: 'KeyA', type: 'keydown', keysym: 0x61});
|
|
||||||
done();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}).keydown({code: 'KeyA', key: 'a', ctrlKey: true});
|
|
||||||
});
|
|
||||||
it('should forward keydown events with the right type', function(done) {
|
it('should forward keydown events with the right type', function(done) {
|
||||||
KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) {
|
KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) {
|
||||||
expect(evt).to.be.deep.equal({code: 'KeyA', keysym: 0x61, type: 'keydown'});
|
expect(evt).to.be.deep.equal({code: 'KeyA', keysym: 0x61, type: 'keydown'});
|
||||||
|
|
Loading…
Reference in New Issue