Merge 08198a6781
into 4cb5aa45ae
This commit is contained in:
commit
60e1b1bf4b
|
@ -185,6 +185,7 @@ const UI = {
|
||||||
UI.initSetting('bell', 'on');
|
UI.initSetting('bell', 'on');
|
||||||
UI.initSetting('view_only', false);
|
UI.initSetting('view_only', false);
|
||||||
UI.initSetting('show_dot', false);
|
UI.initSetting('show_dot', false);
|
||||||
|
UI.initSetting('gestures_mode', 'novnc');
|
||||||
UI.initSetting('path', 'websockify');
|
UI.initSetting('path', 'websockify');
|
||||||
UI.initSetting('repeaterID', '');
|
UI.initSetting('repeaterID', '');
|
||||||
UI.initSetting('reconnect', false);
|
UI.initSetting('reconnect', false);
|
||||||
|
@ -371,6 +372,7 @@ const UI = {
|
||||||
UI.addSettingChangeHandler('view_only', UI.updateViewOnly);
|
UI.addSettingChangeHandler('view_only', UI.updateViewOnly);
|
||||||
UI.addSettingChangeHandler('show_dot');
|
UI.addSettingChangeHandler('show_dot');
|
||||||
UI.addSettingChangeHandler('show_dot', UI.updateShowDotCursor);
|
UI.addSettingChangeHandler('show_dot', UI.updateShowDotCursor);
|
||||||
|
UI.addSettingChangeHandler('gestures_mode');
|
||||||
UI.addSettingChangeHandler('host');
|
UI.addSettingChangeHandler('host');
|
||||||
UI.addSettingChangeHandler('port');
|
UI.addSettingChangeHandler('port');
|
||||||
UI.addSettingChangeHandler('path');
|
UI.addSettingChangeHandler('path');
|
||||||
|
@ -441,6 +443,7 @@ const UI = {
|
||||||
UI.disableSetting('port');
|
UI.disableSetting('port');
|
||||||
UI.disableSetting('path');
|
UI.disableSetting('path');
|
||||||
UI.disableSetting('repeaterID');
|
UI.disableSetting('repeaterID');
|
||||||
|
UI.disableSetting('gestures_mode');
|
||||||
|
|
||||||
// Hide the controlbar after 2 seconds
|
// Hide the controlbar after 2 seconds
|
||||||
UI.closeControlbarTimeout = setTimeout(UI.closeControlbar, 2000);
|
UI.closeControlbarTimeout = setTimeout(UI.closeControlbar, 2000);
|
||||||
|
@ -451,6 +454,7 @@ const UI = {
|
||||||
UI.enableSetting('port');
|
UI.enableSetting('port');
|
||||||
UI.enableSetting('path');
|
UI.enableSetting('path');
|
||||||
UI.enableSetting('repeaterID');
|
UI.enableSetting('repeaterID');
|
||||||
|
UI.enableSetting('gestures_mode');
|
||||||
UI.updatePowerButton();
|
UI.updatePowerButton();
|
||||||
UI.keepControlbar();
|
UI.keepControlbar();
|
||||||
}
|
}
|
||||||
|
@ -1077,7 +1081,8 @@ const UI = {
|
||||||
url.href,
|
url.href,
|
||||||
{ shared: UI.getSetting('shared'),
|
{ shared: UI.getSetting('shared'),
|
||||||
repeaterID: UI.getSetting('repeaterID'),
|
repeaterID: UI.getSetting('repeaterID'),
|
||||||
credentials: { password: password } });
|
credentials: { password: password },
|
||||||
|
gesturesMode: UI.getSetting('gestures_mode') });
|
||||||
} catch (exc) {
|
} catch (exc) {
|
||||||
Log.Error("Failed to connect to server: " + exc);
|
Log.Error("Failed to connect to server: " + exc);
|
||||||
UI.updateVisualState('disconnected');
|
UI.updateVisualState('disconnected');
|
||||||
|
|
|
@ -25,6 +25,7 @@ export const encodings = {
|
||||||
pseudoEncodingCursor: -239,
|
pseudoEncodingCursor: -239,
|
||||||
pseudoEncodingQEMUExtendedKeyEvent: -258,
|
pseudoEncodingQEMUExtendedKeyEvent: -258,
|
||||||
pseudoEncodingQEMULedEvent: -261,
|
pseudoEncodingQEMULedEvent: -261,
|
||||||
|
pseudoEncodingGii: -305,
|
||||||
pseudoEncodingDesktopName: -307,
|
pseudoEncodingDesktopName: -307,
|
||||||
pseudoEncodingExtendedDesktopSize: -308,
|
pseudoEncodingExtendedDesktopSize: -308,
|
||||||
pseudoEncodingXvp: -309,
|
pseudoEncodingXvp: -309,
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
import * as Log from '../util/logging.js';
|
||||||
|
|
||||||
|
export default class TouchHandlerUltraVNC {
|
||||||
|
static PF_flag = 0x80000000; // Pressed Flag : active if the touch event is pressed, inactive if it's being released.
|
||||||
|
static R1_flag = 0x40000000; // Reserved 1
|
||||||
|
static IF_flag = 0x20000000; // Primary Flag : active if the touch event is the primary touch event.
|
||||||
|
static S1_flag = 0x10000000; // Size Flag : active if the message contains information about the size of the touch event. The events are currently all sent as symetrical ellipses.
|
||||||
|
static S2_flag = 0x8000000; // Reserved for asymetrical ellipses. Not supported yet and should be 0.
|
||||||
|
static RT_flag = 0x4000000; // Rectangle : the touch event is a rectangle instead of an ellipse.
|
||||||
|
static PR_flag = 0x2000000; // Pressure Flag : pressure of the touch. Currently unused.
|
||||||
|
static TI_flag = 0x1000000; // Timestamp : the timestamp of the touch event.
|
||||||
|
static HC_flag = 0x800000; // High Performance Counter
|
||||||
|
|
||||||
|
static LENGTH_16_flag = 0x10; // 16 bits signed for x touch coordinate followed by 16 bits signed for y together in a 32 bits word
|
||||||
|
static IDFORMAT_32 = 0x1; // 32 bits ID
|
||||||
|
static IDFORMAT_CLEAR = 0xF; // No more touch points
|
||||||
|
|
||||||
|
// GII
|
||||||
|
static giiMsgType = 253;
|
||||||
|
static giiEventInjectionMsgType = 128;
|
||||||
|
static giiDeviceVersionMsgType = 129;
|
||||||
|
static giiDeviceCreationMsgType = 130;
|
||||||
|
|
||||||
|
static giiDeviceCreationMsgSize = 172;
|
||||||
|
static giiDeviceVersion = 1;
|
||||||
|
static giiDeviceVersionMsgSize = 2;
|
||||||
|
|
||||||
|
static giiEventInjectionHeaderSize = 4;
|
||||||
|
static giiEventInjectionSize = this.giiEventInjectionHeaderSize + 16;
|
||||||
|
static giiEventInjectionTouchSize = 12;
|
||||||
|
static giiEventInjectionEventType = 12;
|
||||||
|
|
||||||
|
static giiDeviceName = "NOVNC-MT";
|
||||||
|
static giiDeviceNameSize = 31;
|
||||||
|
static giiDeviceLongName = "noVNC Multitouch Device";
|
||||||
|
static giiDeviceLongNameSize = 74;
|
||||||
|
static giiDeviceShortName = "NMD";
|
||||||
|
static giiDeviceShortNameSize = 4;
|
||||||
|
|
||||||
|
static giiDNTerm = 0;
|
||||||
|
static giiVendorID = 0x0908;
|
||||||
|
static giiProductID = 0x000b;
|
||||||
|
static giiEventMask = 0x00002000;
|
||||||
|
static giiNumRegisters = 0;
|
||||||
|
static giiNumValuators = 1;
|
||||||
|
static giiNumButtons = 5;
|
||||||
|
static giiNumTouches = 6;
|
||||||
|
static giiIndex = 0;
|
||||||
|
static giiLNTerm = 0;
|
||||||
|
static giiSNTerm = 0;
|
||||||
|
static giiRangeMin = 0;
|
||||||
|
static giiRangeCenter = 0;
|
||||||
|
static giiRangeMax = 0;
|
||||||
|
static giiSIUnit = 0;
|
||||||
|
static giiSIAdd = 0;
|
||||||
|
static giiSIMul = 0;
|
||||||
|
static giiSIDiv = 0;
|
||||||
|
static giiSIShift = 0;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._target = null;
|
||||||
|
|
||||||
|
this._currentTouches = [];
|
||||||
|
this._sendTouchesIntervalId = -1;
|
||||||
|
this._giiDeviceOrigin = 0;
|
||||||
|
this._isUltraVNCTouchActivated = false;
|
||||||
|
|
||||||
|
this._boundEventHandler = this._handleTouch.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
attach(target) {
|
||||||
|
this.detach();
|
||||||
|
|
||||||
|
this._target = target;
|
||||||
|
this._target.addEventListener('touchstart',
|
||||||
|
this._boundEventHandler);
|
||||||
|
this._target.addEventListener('touchmove',
|
||||||
|
this._boundEventHandler);
|
||||||
|
this._target.addEventListener('touchend',
|
||||||
|
this._boundEventHandler);
|
||||||
|
this._target.addEventListener('touchcancel',
|
||||||
|
this._boundEventHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
detach() {
|
||||||
|
if (!this._target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._target.removeEventListener('touchstart',
|
||||||
|
this._boundEventHandler);
|
||||||
|
this._target.removeEventListener('touchmove',
|
||||||
|
this._boundEventHandler);
|
||||||
|
this._target.removeEventListener('touchend',
|
||||||
|
this._boundEventHandler);
|
||||||
|
this._target.removeEventListener('touchcancel',
|
||||||
|
this._boundEventHandler);
|
||||||
|
|
||||||
|
clearInterval(this._sendTouchesIntervalId);
|
||||||
|
this._sendTouchesIntervalId = -1;
|
||||||
|
|
||||||
|
this._target = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleTouch(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopImmediatePropagation();
|
||||||
|
|
||||||
|
if (!this._isUltraVNCTouchActivated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev.type === "touchstart") {
|
||||||
|
for (let i = 0; i < ev.changedTouches.length; i++) {
|
||||||
|
ev.changedTouches[i].touchIdentifier = this._getTouchIdentifier();
|
||||||
|
this._currentTouches.push({ event: ev.changedTouches[i], status: "POINTER_DOWN" });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._sendTouchesIntervalId === -1 && this._target) {
|
||||||
|
this._dispatchTouchEvent(ev);
|
||||||
|
this._sendTouchesIntervalId = setInterval(() => {
|
||||||
|
this._dispatchTouchEvent(ev);
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
} else if (ev.type === "touchmove") {
|
||||||
|
for (let i = 0; i < ev.changedTouches.length; i++) {
|
||||||
|
const index = this._currentTouches.findIndex(t => t.event.identifier === ev.changedTouches[i].identifier);
|
||||||
|
if (index !== -1) {
|
||||||
|
ev.changedTouches[i].touchIdentifier = this._currentTouches[index].event.touchIdentifier;
|
||||||
|
this._currentTouches[index].event = ev.changedTouches[i];
|
||||||
|
this._currentTouches[index].status = "POINTER_UPDATE";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ev.type === "touchend" || ev.type === "touchcancel") {
|
||||||
|
for (let i = 0; i < ev.changedTouches.length; i++) {
|
||||||
|
const indexes = this._getAllIndexes(this._currentTouches, (t) => t.event.identifier === ev.changedTouches[i].identifier)
|
||||||
|
indexes.forEach((index) => this._currentTouches[index].status = "POINTER_UP");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getAllIndexes(arr, func) {
|
||||||
|
var indexes = [], i;
|
||||||
|
for (i = 0; i < arr.length; i++)
|
||||||
|
if (func(arr[i]))
|
||||||
|
indexes.push(i);
|
||||||
|
return indexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
_getTouchIdentifier() {
|
||||||
|
const ids = this._currentTouches.map((ev) => ev.event.touchIdentifier);
|
||||||
|
let i = 0;
|
||||||
|
while (ids.includes(i)) { i++; }
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dispatchTouchEvent(ev) {
|
||||||
|
let tev = new CustomEvent('ultravnctouch', { event: ev, detail: { currentTouches: this._currentTouches, giiDeviceOrigin: this._giiDeviceOrigin } });
|
||||||
|
this._target.dispatchEvent(tev);
|
||||||
|
}
|
||||||
|
|
||||||
|
_removeTouch(index) {
|
||||||
|
this._currentTouches.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
_interruptTouches() {
|
||||||
|
clearInterval(this._sendTouchesIntervalId);
|
||||||
|
this._sendTouchesIntervalId = -1;
|
||||||
|
}
|
||||||
|
}
|
192
core/rfb.js
192
core/rfb.js
|
@ -19,6 +19,7 @@ import Inflator from "./inflator.js";
|
||||||
import Deflator from "./deflator.js";
|
import Deflator from "./deflator.js";
|
||||||
import Keyboard from "./input/keyboard.js";
|
import Keyboard from "./input/keyboard.js";
|
||||||
import GestureHandler from "./input/gesturehandler.js";
|
import GestureHandler from "./input/gesturehandler.js";
|
||||||
|
import TouchHandlerUltraVNC from "./input/touchhandlerultravnc.js";
|
||||||
import Cursor from "./util/cursor.js";
|
import Cursor from "./util/cursor.js";
|
||||||
import Websock from "./websock.js";
|
import Websock from "./websock.js";
|
||||||
import KeyTable from "./input/keysym.js";
|
import KeyTable from "./input/keysym.js";
|
||||||
|
@ -119,6 +120,7 @@ export default class RFB extends EventTargetMixin {
|
||||||
this._shared = 'shared' in options ? !!options.shared : true;
|
this._shared = 'shared' in options ? !!options.shared : true;
|
||||||
this._repeaterID = options.repeaterID || '';
|
this._repeaterID = options.repeaterID || '';
|
||||||
this._wsProtocols = options.wsProtocols || [];
|
this._wsProtocols = options.wsProtocols || [];
|
||||||
|
this._gesturesMode = options.gesturesMode || ''
|
||||||
|
|
||||||
// Internal state
|
// Internal state
|
||||||
this._rfbConnectionState = '';
|
this._rfbConnectionState = '';
|
||||||
|
@ -208,6 +210,7 @@ export default class RFB extends EventTargetMixin {
|
||||||
handleMouse: this._handleMouse.bind(this),
|
handleMouse: this._handleMouse.bind(this),
|
||||||
handleWheel: this._handleWheel.bind(this),
|
handleWheel: this._handleWheel.bind(this),
|
||||||
handleGesture: this._handleGesture.bind(this),
|
handleGesture: this._handleGesture.bind(this),
|
||||||
|
handleUltraVNCTouch: this._handleUltraVNCTouch.bind(this),
|
||||||
handleRSAAESCredentialsRequired: this._handleRSAAESCredentialsRequired.bind(this),
|
handleRSAAESCredentialsRequired: this._handleRSAAESCredentialsRequired.bind(this),
|
||||||
handleRSAAESServerVerification: this._handleRSAAESServerVerification.bind(this),
|
handleRSAAESServerVerification: this._handleRSAAESServerVerification.bind(this),
|
||||||
};
|
};
|
||||||
|
@ -271,7 +274,13 @@ export default class RFB extends EventTargetMixin {
|
||||||
this._remoteCapsLock = null; // Null indicates unknown or irrelevant
|
this._remoteCapsLock = null; // Null indicates unknown or irrelevant
|
||||||
this._remoteNumLock = null;
|
this._remoteNumLock = null;
|
||||||
|
|
||||||
|
switch (this._gesturesMode) {
|
||||||
|
case 'ultravnc':
|
||||||
|
this._gestures = new TouchHandlerUltraVNC();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
this._gestures = new GestureHandler();
|
this._gestures = new GestureHandler();
|
||||||
|
}
|
||||||
|
|
||||||
this._sock = new Websock();
|
this._sock = new Websock();
|
||||||
this._sock.on('open', this._socketOpen.bind(this));
|
this._sock.on('open', this._socketOpen.bind(this));
|
||||||
|
@ -598,9 +607,15 @@ export default class RFB extends EventTargetMixin {
|
||||||
this._canvas.addEventListener("wheel", this._eventHandlers.handleWheel);
|
this._canvas.addEventListener("wheel", this._eventHandlers.handleWheel);
|
||||||
|
|
||||||
// Gesture events
|
// Gesture events
|
||||||
this._canvas.addEventListener("gesturestart", this._eventHandlers.handleGesture);
|
switch (this._gesturesMode) {
|
||||||
this._canvas.addEventListener("gesturemove", this._eventHandlers.handleGesture);
|
case 'ultravnc':
|
||||||
this._canvas.addEventListener("gestureend", this._eventHandlers.handleGesture);
|
this._canvas.addEventListener('ultravnctouch', this._eventHandlers.handleUltraVNCTouch);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this._canvas.addEventListener('gesturestart', this._eventHandlers.handleGesture);
|
||||||
|
this._canvas.addEventListener('gesturemove', this._eventHandlers.handleGesture);
|
||||||
|
this._canvas.addEventListener('gestureend', this._eventHandlers.handleGesture);
|
||||||
|
}
|
||||||
|
|
||||||
Log.Debug("<< RFB.connect");
|
Log.Debug("<< RFB.connect");
|
||||||
}
|
}
|
||||||
|
@ -608,9 +623,17 @@ export default class RFB extends EventTargetMixin {
|
||||||
_disconnect() {
|
_disconnect() {
|
||||||
Log.Debug(">> RFB.disconnect");
|
Log.Debug(">> RFB.disconnect");
|
||||||
this._cursor.detach();
|
this._cursor.detach();
|
||||||
this._canvas.removeEventListener("gesturestart", this._eventHandlers.handleGesture);
|
|
||||||
this._canvas.removeEventListener("gesturemove", this._eventHandlers.handleGesture);
|
switch (this._gesturesMode) {
|
||||||
this._canvas.removeEventListener("gestureend", this._eventHandlers.handleGesture);
|
case 'ultravnc':
|
||||||
|
this._canvas.removeEventListener('ultravnctouch', this._eventHandlers.handleUltraVNCTouch);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this._canvas.removeEventListener('gesturestart', this._eventHandlers.handleGesture);
|
||||||
|
this._canvas.removeEventListener('gesturemove', this._eventHandlers.handleGesture);
|
||||||
|
this._canvas.removeEventListener('gestureend', this._eventHandlers.handleGesture);
|
||||||
|
}
|
||||||
|
|
||||||
this._canvas.removeEventListener("wheel", this._eventHandlers.handleWheel);
|
this._canvas.removeEventListener("wheel", this._eventHandlers.handleWheel);
|
||||||
this._canvas.removeEventListener('mousedown', this._eventHandlers.handleMouse);
|
this._canvas.removeEventListener('mousedown', this._eventHandlers.handleMouse);
|
||||||
this._canvas.removeEventListener('mouseup', this._eventHandlers.handleMouse);
|
this._canvas.removeEventListener('mouseup', this._eventHandlers.handleMouse);
|
||||||
|
@ -1483,6 +1506,84 @@ export default class RFB extends EventTargetMixin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_handleUltraVNCTouch(ev) {
|
||||||
|
this._sock.sQpush8(TouchHandlerUltraVNC.giiMsgType); // GII message type
|
||||||
|
this._sock.sQpush8(TouchHandlerUltraVNC.giiEventInjectionMsgType); // GII event
|
||||||
|
this._sock.sQpush16(TouchHandlerUltraVNC.giiEventInjectionSize + (TouchHandlerUltraVNC.giiEventInjectionTouchSize * ev.detail.currentTouches.length)); // length, not used
|
||||||
|
this._sock.sQpush8(TouchHandlerUltraVNC.giiEventInjectionSize + (TouchHandlerUltraVNC.giiEventInjectionTouchSize * ev.detail.currentTouches.length)); // eventSize, not used
|
||||||
|
this._sock.sQpush8(TouchHandlerUltraVNC.giiEventInjectionEventType); // eventType, not used
|
||||||
|
this._sock.sQpush16(0); // padding
|
||||||
|
this._sock.sQpush32(ev.detail.giiDeviceOrigin);
|
||||||
|
this._sock.sQpush32(ev.detail.currentTouches.length); // nb of touch events
|
||||||
|
this._sock.sQpush32(TouchHandlerUltraVNC.giiNumTouches * ev.detail.currentTouches.length); // count
|
||||||
|
|
||||||
|
let pointerUpIds = [];
|
||||||
|
|
||||||
|
// Send all current touches
|
||||||
|
for (let i = 0; i < ev.detail.currentTouches.length; i++) {
|
||||||
|
let valuatorFlag = 0x00000000;
|
||||||
|
valuatorFlag |= TouchHandlerUltraVNC.LENGTH_16_flag;
|
||||||
|
valuatorFlag |= TouchHandlerUltraVNC.IDFORMAT_32;
|
||||||
|
if (ev.detail.currentTouches[i].status !== "POINTER_UP") valuatorFlag |= TouchHandlerUltraVNC.PF_flag;
|
||||||
|
if (ev.detail.currentTouches[i].event.identifier === 0) valuatorFlag |= TouchHandlerUltraVNC.IF_flag; // IF_flag
|
||||||
|
|
||||||
|
this._sock.sQpush32(valuatorFlag);
|
||||||
|
this._sock.sQpush32(ev.detail.currentTouches[i].event.touchIdentifier);
|
||||||
|
|
||||||
|
let scaledPosition = clientToElement(ev.detail.currentTouches[i].event.clientX, ev.detail.currentTouches[i].event.clientY,
|
||||||
|
this._canvas);
|
||||||
|
|
||||||
|
if ((valuatorFlag & TouchHandlerUltraVNC.LENGTH_16_flag) !== 0) {
|
||||||
|
let scaledX16 = this._display.absX(scaledPosition.x) & 0xFFFF;
|
||||||
|
let scaledY16 = this._display.absY(scaledPosition.y) & 0xFFFF;
|
||||||
|
let coordinates = (scaledX16 << 16) | scaledY16;
|
||||||
|
this._sock.sQpush32(coordinates);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep track of last released touches
|
||||||
|
if (ev.detail.currentTouches[i].status === "POINTER_UP") {
|
||||||
|
pointerUpIds.push(ev.detail.currentTouches[i].event.identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._sock.flush();
|
||||||
|
|
||||||
|
// Remove released touches from current touches in handler
|
||||||
|
for (let i = 0; i < pointerUpIds.length; i++) {
|
||||||
|
const index = ev.detail.currentTouches.findIndex(t => t.event.identifier === pointerUpIds[i]);
|
||||||
|
if (index !== -1) {
|
||||||
|
this._gestures._removeTouch(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interrupt touch sending interval
|
||||||
|
if (ev.detail.currentTouches.length === 0 && this._sendTouchesIntervalId !== -1) {
|
||||||
|
this._gestures._interruptTouches();
|
||||||
|
this._sendEmptyTouch(ev.detail.giiDeviceOrigin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_sendEmptyTouch(giiDeviceOrigin) {
|
||||||
|
let valuatorFlag = 0x00000000;
|
||||||
|
valuatorFlag |= TouchHandlerUltraVNC.LENGTH_16_flag;
|
||||||
|
valuatorFlag |= TouchHandlerUltraVNC.IDFORMAT_CLEAR;
|
||||||
|
|
||||||
|
this._sock.sQpush8(TouchHandlerUltraVNC.giiMsgType); // GII message type
|
||||||
|
this._sock.sQpush8(TouchHandlerUltraVNC.giiEventInjectionMsgType); // GII event
|
||||||
|
this._sock.sQpush16(TouchHandlerUltraVNC.giiEventInjectionHeaderSize + TouchHandlerUltraVNC.giiEventInjectionSize);
|
||||||
|
this._sock.sQpush8(TouchHandlerUltraVNC.giiEventInjectionHeaderSize + TouchHandlerUltraVNC.giiEventInjectionSize);
|
||||||
|
this._sock.sQpush8(TouchHandlerUltraVNC.giiEventInjectionEventType);
|
||||||
|
this._sock.sQpush16(0); // padding
|
||||||
|
this._sock.sQpush32(giiDeviceOrigin); // deviceOrigin
|
||||||
|
this._sock.sQpush32(1); // nb of touchevents
|
||||||
|
this._sock.sQpush32(4); // nb of values, not used
|
||||||
|
this._sock.sQpush32(valuatorFlag);
|
||||||
|
this._sock.sQpush32(0); // empty Id
|
||||||
|
this._sock.sQpush32(0); // empty coordinates
|
||||||
|
this._sock.flush();
|
||||||
|
}
|
||||||
|
|
||||||
_flushMouseMoveTimer(x, y) {
|
_flushMouseMoveTimer(x, y) {
|
||||||
if (this._mouseMoveTimer !== null) {
|
if (this._mouseMoveTimer !== null) {
|
||||||
clearTimeout(this._mouseMoveTimer);
|
clearTimeout(this._mouseMoveTimer);
|
||||||
|
@ -2261,6 +2362,10 @@ export default class RFB extends EventTargetMixin {
|
||||||
encs.push(encodings.pseudoEncodingExtendedClipboard);
|
encs.push(encodings.pseudoEncodingExtendedClipboard);
|
||||||
encs.push(encodings.pseudoEncodingExtendedMouseButtons);
|
encs.push(encodings.pseudoEncodingExtendedMouseButtons);
|
||||||
|
|
||||||
|
if (this._gesturesMode === 'ultravnc') {
|
||||||
|
encs.push(encodings.pseudoEncodingGii);
|
||||||
|
}
|
||||||
|
|
||||||
if (this._fbDepth == 24) {
|
if (this._fbDepth == 24) {
|
||||||
encs.push(encodings.pseudoEncodingVMwareCursor);
|
encs.push(encodings.pseudoEncodingVMwareCursor);
|
||||||
encs.push(encodings.pseudoEncodingCursor);
|
encs.push(encodings.pseudoEncodingCursor);
|
||||||
|
@ -2556,6 +2661,30 @@ export default class RFB extends EventTargetMixin {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_handleGiiMsg() {
|
||||||
|
if (this._sock.rQwait("GII message subtype", 1, 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let giiMsgSubtype = this._sock.rQshift8();
|
||||||
|
|
||||||
|
switch (giiMsgSubtype) {
|
||||||
|
case 129: // GII Version Message
|
||||||
|
if (this._sock.rQwait("GII version message", 34, 1)) { return false; }
|
||||||
|
this._sock.rQskipBytes(34);
|
||||||
|
RFB.messages.giiVersionMessage(this._sock);
|
||||||
|
RFB.messages.giiDeviceCreation(this._sock);
|
||||||
|
break;
|
||||||
|
case 130: // GII Device Creation
|
||||||
|
if (this._sock.rQwait("GII device creation", 6, 1)) { return false; }
|
||||||
|
this._sock.rQshiftBytes(2);
|
||||||
|
this._gestures._giiDeviceOrigin = this._sock.rQshift32();
|
||||||
|
if (this._gestures._giiDeviceOrigin) this._gestures._isUltraVNCTouchActivated = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
_normalMsg() {
|
_normalMsg() {
|
||||||
let msgType;
|
let msgType;
|
||||||
if (this._FBU.rects > 0) {
|
if (this._FBU.rects > 0) {
|
||||||
|
@ -2607,6 +2736,9 @@ export default class RFB extends EventTargetMixin {
|
||||||
case 250: // XVP
|
case 250: // XVP
|
||||||
return this._handleXvpMsg();
|
return this._handleXvpMsg();
|
||||||
|
|
||||||
|
case 253: // GII
|
||||||
|
return this._handleGiiMsg();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
this._fail("Unexpected server message (type " + msgType + ")");
|
this._fail("Unexpected server message (type " + msgType + ")");
|
||||||
Log.Debug("sock.rQpeekBytes(30): " + this._sock.rQpeekBytes(30));
|
Log.Debug("sock.rQpeekBytes(30): " + this._sock.rQpeekBytes(30));
|
||||||
|
@ -3070,6 +3202,16 @@ export default class RFB extends EventTargetMixin {
|
||||||
"raw", passwordChars, { name: "DES-ECB" }, false, ["encrypt"]);
|
"raw", passwordChars, { name: "DES-ECB" }, false, ["encrypt"]);
|
||||||
return legacyCrypto.encrypt({ name: "DES-ECB" }, key, challenge);
|
return legacyCrypto.encrypt({ name: "DES-ECB" }, key, challenge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static stringAsByteArrayWithPadding(str, size) {
|
||||||
|
let full = new Uint8Array(size);
|
||||||
|
let utf8Encode = new TextEncoder();
|
||||||
|
let strArray = utf8Encode.encode(str);
|
||||||
|
for (let i = 0; i < strArray.length; i++) {
|
||||||
|
full[i] = strArray[i];
|
||||||
|
}
|
||||||
|
return full;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Class Methods
|
// Class Methods
|
||||||
|
@ -3386,6 +3528,44 @@ RFB.messages = {
|
||||||
sock.sQpush8(ver);
|
sock.sQpush8(ver);
|
||||||
sock.sQpush8(op);
|
sock.sQpush8(op);
|
||||||
|
|
||||||
|
sock.flush();
|
||||||
|
},
|
||||||
|
|
||||||
|
giiVersionMessage(sock) {
|
||||||
|
sock.sQpush8(TouchHandlerUltraVNC.giiMsgType);
|
||||||
|
sock.sQpush8(TouchHandlerUltraVNC.giiDeviceVersionMsgType);
|
||||||
|
sock.sQpush16(TouchHandlerUltraVNC.giiDeviceVersionMsgSize);
|
||||||
|
sock.sQpush16(TouchHandlerUltraVNC.giiDeviceVersion);
|
||||||
|
|
||||||
|
sock.flush();
|
||||||
|
},
|
||||||
|
|
||||||
|
giiDeviceCreation(sock) {
|
||||||
|
sock.sQpush8(TouchHandlerUltraVNC.giiMsgType);
|
||||||
|
sock.sQpush8(TouchHandlerUltraVNC.giiDeviceCreationMsgType);
|
||||||
|
sock.sQpush16(TouchHandlerUltraVNC.giiDeviceCreationMsgSize);
|
||||||
|
sock.sQpushBytes(RFB.stringAsByteArrayWithPadding(TouchHandlerUltraVNC.giiDeviceName, TouchHandlerUltraVNC.giiDeviceNameSize));
|
||||||
|
sock.sQpush8(TouchHandlerUltraVNC.giiDNTerm);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiVendorID);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiProductID);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiEventMask);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiNumRegisters);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiNumValuators);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiNumButtons);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiIndex);
|
||||||
|
sock.sQpushBytes(RFB.stringAsByteArrayWithPadding(TouchHandlerUltraVNC.giiDeviceLongName, TouchHandlerUltraVNC.giiDeviceLongNameSize));
|
||||||
|
sock.sQpush8(TouchHandlerUltraVNC.giiLNTerm);
|
||||||
|
sock.sQpushBytes(RFB.stringAsByteArrayWithPadding(TouchHandlerUltraVNC.giiDeviceShortName, TouchHandlerUltraVNC.giiDeviceShortNameSize));
|
||||||
|
sock.sQpush8(TouchHandlerUltraVNC.giiSNTerm);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiRangeMin);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiRangeCenter);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiRangeMax);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiSIUnit);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiSIAdd);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiSIMul);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiSIDiv);
|
||||||
|
sock.sQpush32(TouchHandlerUltraVNC.giiSIShift);
|
||||||
|
|
||||||
sock.flush();
|
sock.flush();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
5
vnc.html
5
vnc.html
|
@ -295,6 +295,11 @@
|
||||||
class="toggle">
|
class="toggle">
|
||||||
Show dot when no cursor
|
Show dot when no cursor
|
||||||
</label>
|
</label>
|
||||||
|
<label for="noVNC_setting_gestures_mode">Gestures mode:</label>
|
||||||
|
<select id="noVNC_setting_gestures_mode" name="vncGestures">
|
||||||
|
<option value="novnc">Default (noVNC)</option>
|
||||||
|
<option value="ultravnc">UltraVNC</option>
|
||||||
|
</select>
|
||||||
</li>
|
</li>
|
||||||
<li><hr></li>
|
<li><hr></li>
|
||||||
<!-- Logging selection dropdown -->
|
<!-- Logging selection dropdown -->
|
||||||
|
|
Loading…
Reference in New Issue