KASM-5697 Account for improper keyboard implementation of oculus browser (#103)
* KASM-5697 Account for improper keyboard implementation of oculus browser * fix mouse drag * fix touch gestures on secondary displays --------- Co-authored-by: mattmcclaskey <matt@kasmweb.com>
This commit is contained in:
parent
8ac23d2609
commit
bf7a417ab7
|
@ -427,6 +427,8 @@ const UI = {
|
|||
addTouchSpecificHandlers() {
|
||||
document.getElementById("noVNC_keyboard_button")
|
||||
.addEventListener('click', UI.toggleVirtualKeyboard);
|
||||
document.getElementById("noVNC_keyboard_button")
|
||||
.addEventListener('touch', UI.toggleVirtualKeyboard);
|
||||
document.getElementById("noVNC_keyboardinput")
|
||||
.addEventListener('focus', UI.onfocusVirtualKeyboard);
|
||||
document.getElementById("noVNC_keyboardinput")
|
||||
|
|
|
@ -67,7 +67,7 @@ export function getKeycode(evt) {
|
|||
// Get 'KeyboardEvent.key', handling legacy browsers
|
||||
export function getKey(evt) {
|
||||
// Are we getting a proper key value?
|
||||
if (evt.key !== undefined) {
|
||||
if ((evt.key !== undefined) && (evt.key !== 'Unidentified')) {
|
||||
// Mozilla isn't fully in sync with the spec yet
|
||||
switch (evt.key) {
|
||||
case 'OS': return 'Meta';
|
||||
|
|
59
core/rfb.js
59
core/rfb.js
|
@ -12,7 +12,7 @@ import { toUnsigned32bit, toSigned32bit } from './util/int.js';
|
|||
import * as Log from './util/logging.js';
|
||||
import { encodeUTF8, decodeUTF8, uuidv4 } from './util/strings.js';
|
||||
import { hashUInt8Array } from './util/int.js';
|
||||
import { dragThreshold, supportsCursorURIs, isTouchDevice, isWindows, isMac, isIOS } from './util/browser.js';
|
||||
import { dragThreshold, supportsCursorURIs, isTouchDevice, isWindows, isMac, isIOS, isDesktop } from './util/browser.js';
|
||||
import { clientToElement } from './util/element.js';
|
||||
import { setCapture } from './util/events.js';
|
||||
import EventTargetMixin from './util/eventtarget.js';
|
||||
|
@ -2224,7 +2224,7 @@ export default class RFB extends EventTargetMixin {
|
|||
|
||||
// With multiple displays, it is possible to end up in a state where we lost the mouseup event
|
||||
// If a mouse move indicates no buttons are down but the current state shows something down, lets clear the plate
|
||||
if (this._mouseButtonMask !== 0 && !down && !simulated) {
|
||||
if (this._display.screens.length > 1 && this._mouseButtonMask !== 0 && !down && !simulated && isDesktop()) {
|
||||
this._mouseButtonMask = 0;
|
||||
Log.Debug('Mouse event button down mismatch with current mask, resetting mask to 0.')
|
||||
}
|
||||
|
@ -2375,8 +2375,14 @@ export default class RFB extends EventTargetMixin {
|
|||
}
|
||||
|
||||
_fakeMouseMove(ev, elementX, elementY) {
|
||||
if (this._isPrimaryDisplay) {
|
||||
this._handleMouseMove(elementX, elementY, false, true);
|
||||
this._cursor.move(ev.detail.clientX, ev.detail.clientY);
|
||||
} else {
|
||||
this._proxyRFBMessage('mousemove', [ elementX, elementY, true, false ]);
|
||||
this._cursor.move(ev.detail.clientX, ev.detail.clientY);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
_handleTapEvent(ev, bmask) {
|
||||
|
@ -2406,8 +2412,20 @@ export default class RFB extends EventTargetMixin {
|
|||
this._gestureLastTapTime = Date.now();
|
||||
|
||||
this._fakeMouseMove(this._gestureFirstDoubleTapEv, pos.x, pos.y);
|
||||
this._handleMouseButton(pos.x, pos.y, true, bmask);
|
||||
this._handleMouseButton(pos.x, pos.y, false, bmask);
|
||||
this._fakeMouseButton(pos.x, pos.y, true, bmask);
|
||||
this._fakeMouseButton(pos.x, pos.y, false, bmask);
|
||||
}
|
||||
|
||||
_fakeMouseButton(x, y, down, mask) {
|
||||
if (this._isPrimaryDisplay) {
|
||||
this._handleMouseButton(x, y, down, mask);
|
||||
} else {
|
||||
if (down) {
|
||||
this._proxyRFBMessage('mousedown', [ x, y, mask ]);
|
||||
} else {
|
||||
this._proxyRFBMessage('mouseup', [ x, y, mask ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_handleGesture(ev) {
|
||||
|
@ -2429,11 +2447,12 @@ export default class RFB extends EventTargetMixin {
|
|||
break;
|
||||
case 'drag':
|
||||
this._fakeMouseMove(ev, pos.x, pos.y);
|
||||
this._handleMouseButton(pos.x, pos.y, true, 0x1);
|
||||
|
||||
this._fakeMouseButton(pos.x, pos.y, true, 0x1);
|
||||
break;
|
||||
case 'longpress':
|
||||
this._fakeMouseMove(ev, pos.x, pos.y);
|
||||
this._handleMouseButton(pos.x, pos.y, true, 0x4);
|
||||
this._fakeMouseButton(pos.x, pos.y, true, 0x4);
|
||||
break;
|
||||
|
||||
case 'twodrag':
|
||||
|
@ -2465,23 +2484,23 @@ export default class RFB extends EventTargetMixin {
|
|||
// every update.
|
||||
this._fakeMouseMove(ev, pos.x, pos.y);
|
||||
while ((ev.detail.magnitudeY - this._gestureLastMagnitudeY) > GESTURE_SCRLSENS) {
|
||||
this._handleMouseButton(pos.x, pos.y, true, 0x8);
|
||||
this._handleMouseButton(pos.x, pos.y, false, 0x8);
|
||||
this._fakeMouseButton(pos.x, pos.y, true, 0x8);
|
||||
this._fakeMouseButton(pos.x, pos.y, false, 0x8);
|
||||
this._gestureLastMagnitudeY += GESTURE_SCRLSENS;
|
||||
}
|
||||
while ((ev.detail.magnitudeY - this._gestureLastMagnitudeY) < -GESTURE_SCRLSENS) {
|
||||
this._handleMouseButton(pos.x, pos.y, true, 0x10);
|
||||
this._handleMouseButton(pos.x, pos.y, false, 0x10);
|
||||
this._fakeMouseButton(pos.x, pos.y, true, 0x10);
|
||||
this._fakeMouseButton(pos.x, pos.y, false, 0x10);
|
||||
this._gestureLastMagnitudeY -= GESTURE_SCRLSENS;
|
||||
}
|
||||
while ((ev.detail.magnitudeX - this._gestureLastMagnitudeX) > GESTURE_SCRLSENS) {
|
||||
this._handleMouseButton(pos.x, pos.y, true, 0x20);
|
||||
this._handleMouseButton(pos.x, pos.y, false, 0x20);
|
||||
this._fakeMouseButton(pos.x, pos.y, true, 0x20);
|
||||
this._fakeMouseButton(pos.x, pos.y, false, 0x20);
|
||||
this._gestureLastMagnitudeX += GESTURE_SCRLSENS;
|
||||
}
|
||||
while ((ev.detail.magnitudeX - this._gestureLastMagnitudeX) < -GESTURE_SCRLSENS) {
|
||||
this._handleMouseButton(pos.x, pos.y, true, 0x40);
|
||||
this._handleMouseButton(pos.x, pos.y, false, 0x40);
|
||||
this._fakeMouseButton(pos.x, pos.y, true, 0x40);
|
||||
this._fakeMouseButton(pos.x, pos.y, false, 0x40);
|
||||
this._gestureLastMagnitudeX -= GESTURE_SCRLSENS;
|
||||
}
|
||||
break;
|
||||
|
@ -2494,13 +2513,13 @@ export default class RFB extends EventTargetMixin {
|
|||
if (Math.abs(magnitude - this._gestureLastMagnitudeX) > GESTURE_ZOOMSENS) {
|
||||
this._handleKeyEvent(KeyTable.XK_Control_L, "ControlLeft", true);
|
||||
while ((magnitude - this._gestureLastMagnitudeX) > GESTURE_ZOOMSENS) {
|
||||
this._handleMouseButton(pos.x, pos.y, true, 0x8);
|
||||
this._handleMouseButton(pos.x, pos.y, false, 0x8);
|
||||
this._fakeMouseButton(pos.x, pos.y, true, 0x8);
|
||||
this._fakeMouseButton(pos.x, pos.y, false, 0x8);
|
||||
this._gestureLastMagnitudeX += GESTURE_ZOOMSENS;
|
||||
}
|
||||
while ((magnitude - this._gestureLastMagnitudeX) < -GESTURE_ZOOMSENS) {
|
||||
this._handleMouseButton(pos.x, pos.y, true, 0x10);
|
||||
this._handleMouseButton(pos.x, pos.y, false, 0x10);
|
||||
this._fakeMouseButton(pos.x, pos.y, true, 0x10);
|
||||
this._fakeMouseButton(pos.x, pos.y, false, 0x10);
|
||||
this._gestureLastMagnitudeX -= GESTURE_ZOOMSENS;
|
||||
}
|
||||
}
|
||||
|
@ -2519,11 +2538,11 @@ export default class RFB extends EventTargetMixin {
|
|||
break;
|
||||
case 'drag':
|
||||
this._fakeMouseMove(ev, pos.x, pos.y);
|
||||
this._handleMouseButton(pos.x, pos.y, false, 0x1);
|
||||
this._fakeMouseButton(pos.x, pos.y, false, 0x1);
|
||||
break;
|
||||
case 'longpress':
|
||||
this._fakeMouseMove(ev, pos.x, pos.y);
|
||||
this._handleMouseButton(pos.x, pos.y, false, 0x4);
|
||||
this._fakeMouseButton(pos.x, pos.y, false, 0x4);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -85,6 +85,10 @@ export function isWindows() {
|
|||
return navigator && !!(/win/i).exec(navigator.platform);
|
||||
}
|
||||
|
||||
export function isLinux() {
|
||||
return navigator && !!(/linux/i).exec(navigator.platform)
|
||||
}
|
||||
|
||||
export function isIOS() {
|
||||
return navigator &&
|
||||
(!!(/ipad/i).exec(navigator.platform) ||
|
||||
|
@ -97,6 +101,18 @@ export function isSafari() {
|
|||
navigator.userAgent.indexOf('Chrome') === -1);
|
||||
}
|
||||
|
||||
//is the client a desktop like operating system
|
||||
export function isDesktop() {
|
||||
var userAgent = navigator.userAgent;
|
||||
if (isIOS() || userAgent.indexOf("OculusBrowser") != -1 || userAgent.indexOf("SamsungBrowser") != -1) {
|
||||
return false
|
||||
} else if (userAgent.indexOf("Windows") != -1 || userAgent.indexOf("Mac") != -1 || userAgent.indexOf("X11") != -1 || userAgent.indexOf("Linux") != -1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns IE version number if IE or older Edge browser
|
||||
export function isIE() {
|
||||
var ua = window.navigator.userAgent;
|
||||
|
|
|
@ -116,6 +116,8 @@ describe('Helpers', function () {
|
|||
});
|
||||
it('should use charCode if no key', function () {
|
||||
expect(KeyboardUtil.getKey({charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.be.equal('Š');
|
||||
// Broken Oculus browser
|
||||
expect(KeyboardUtil.getKey({charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43, key: 'Unidentified'})).to.be.equal('Š');
|
||||
});
|
||||
it('should return Unidentified when it cannot map the key', function () {
|
||||
expect(KeyboardUtil.getKey({keycode: 0x42})).to.be.equal('Unidentified');
|
||||
|
|
Loading…
Reference in New Issue