Added Web-RDP mouse cursor support.
This commit is contained in:
parent
339e3efbef
commit
6dbae08c40
12
apprelays.js
12
apprelays.js
|
@ -202,10 +202,16 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) {
|
|||
delete bitmap.data;
|
||||
send(['rdp-bitmap', bitmap]); // Send the bitmap metadata seperately, without bitmap data.
|
||||
}).on('clipboard', function (content) {
|
||||
// Clipboard data changed
|
||||
send(['rdp-clipboard', content]);
|
||||
send(['rdp-clipboard', content]); // The clipboard data has changed
|
||||
}).on('pointer', function (cursorId, cursorStr) {
|
||||
if (cursorStr == null) { cursorStr = 'default'; }
|
||||
if (obj.lastCursorStrSent != cursorStr) {
|
||||
obj.lastCursorStrSent = cursorStr;
|
||||
//console.log('pointer', cursorStr);
|
||||
send(['rdp-pointer', cursorStr]); // The mouse pointer has changed
|
||||
}
|
||||
}).on('close', function () {
|
||||
send(['rdp-close']);
|
||||
send(['rdp-close']); // This RDP session has closed
|
||||
}).on('error', function (err) {
|
||||
if (typeof err == 'string') { send(['rdp-error', err]); }
|
||||
if ((typeof err == 'object') && (err.err) && (err.code)) { send(['rdp-error', err.err, err.code]); }
|
||||
|
|
|
@ -18,6 +18,10 @@ var CreateRDPDesktop = function (canvasid) {
|
|||
obj.m.onClipboardChanged = null;
|
||||
obj.onConsoleMessageChange = null;
|
||||
|
||||
var xMouseCursorActive = true;
|
||||
var xMouseCursorCurrent = 'default';
|
||||
obj.mouseCursorActive = function (x) { if (xMouseCursorActive == x) return; xMouseCursorActive = x; obj.CanvasId.style.cursor = ((x == true) ? xMouseCursorCurrent : 'default'); }
|
||||
|
||||
function mouseButtonMap(button) {
|
||||
// Swap mouse buttons if needed
|
||||
if (obj.m.SwapMouse === true) return [2, 0, 1, 0, 0][button];
|
||||
|
@ -75,6 +79,12 @@ var CreateRDPDesktop = function (canvasid) {
|
|||
obj.render.update(bitmap);
|
||||
break;
|
||||
}
|
||||
case 'rdp-pointer': {
|
||||
var pointer = msg[1];
|
||||
xMouseCursorCurrent = pointer;
|
||||
if (xMouseCursorActive) { obj.CanvasId.style.cursor = pointer; }
|
||||
break;
|
||||
}
|
||||
case 'rdp-close': {
|
||||
obj.Stop();
|
||||
break;
|
||||
|
|
|
@ -22,7 +22,7 @@ var fs = require('fs');
|
|||
var type = require('./type');
|
||||
var log = require('./log');
|
||||
var tls = require('tls');
|
||||
var crypto = require('crypto');
|
||||
//var crypto = require('crypto');
|
||||
var events = require('events');
|
||||
|
||||
/**
|
||||
|
|
|
@ -186,7 +186,7 @@ var FastPathUpdateType = {
|
|||
FASTPATH_UPDATETYPE_PTR_NULL : 0x5,
|
||||
FASTPATH_UPDATETYPE_PTR_DEFAULT : 0x6,
|
||||
FASTPATH_UPDATETYPE_PTR_POSITION : 0x8,
|
||||
FASTPATH_UPDATETYPE_COLOR : 0x9,
|
||||
FASTPATH_UPDATETYPE_COLOR : 0x9, // Mouse cursor
|
||||
FASTPATH_UPDATETYPE_CACHED : 0xA,
|
||||
FASTPATH_UPDATETYPE_POINTER : 0xB
|
||||
};
|
||||
|
@ -1075,7 +1075,7 @@ function clipPDU() {
|
|||
* @param opt {object} type option
|
||||
* @returns {type.Component}
|
||||
*/
|
||||
function fastPathBitmapUpdateDataPDU (opt) {
|
||||
function fastPathBitmapUpdateDataPDU(opt) {
|
||||
var self = {
|
||||
__FASTPATH_UPDATE_TYPE__ : FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP,
|
||||
header : new type.UInt16Le(FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP, { constant : true }),
|
||||
|
@ -1093,13 +1093,67 @@ function fastPathBitmapUpdateDataPDU (opt) {
|
|||
return new type.Component(self, opt);
|
||||
}
|
||||
|
||||
// This is a table of cursorid to cursor name.
|
||||
// Created by movering the mouse over this page: https://www.w3schools.com/csSref/tryit.asp?filename=trycss_cursor
|
||||
const cursorIdTable = {
|
||||
// Normal style mouse cursor
|
||||
903013897: 'alias',
|
||||
370524792: 'all-scroll',
|
||||
853046751: 'cell',
|
||||
2101250798: 'col-resize',
|
||||
703681364: 'copy',
|
||||
992638936: 'crosshair',
|
||||
1539083673: 'ew-resize',
|
||||
1919796298: 'grab',
|
||||
1010243511: 'grabbing',
|
||||
1247283057: 'help',
|
||||
1390892051: 'none',
|
||||
885751489: 'not-allowed',
|
||||
1732952247: 'row-resize',
|
||||
747144997: 'url',
|
||||
2018345610: 'zoom-in',
|
||||
347367048: 'zoom-out',
|
||||
1872942890: 'default',
|
||||
1737852989: 'text',
|
||||
1932827019: 'ns-resize',
|
||||
1884471290: 'nesw-resize',
|
||||
1204065391: 'nwse-resize',
|
||||
2030531519: 'progress',
|
||||
1050842114: 'pointer',
|
||||
|
||||
// Black style cursors
|
||||
1258195498: 'default',
|
||||
219484254: 'all-scroll',
|
||||
399295089: 'text',
|
||||
1912613597: 'wait',
|
||||
864127801: 'ew-resize',
|
||||
23245044: 'nesw-resize',
|
||||
1966995494: 'not-allowed',
|
||||
1873216615: 'help',
|
||||
255126408: 'nesw-resize',
|
||||
157191894: 'ns-resize',
|
||||
1768446509: 'pointer',
|
||||
1032011501: 'crosshair'
|
||||
}
|
||||
|
||||
function fastPathPointerUpdateDataPDU(opt, cursorId, cursorStr) {
|
||||
var self = {
|
||||
__FASTPATH_UPDATE_TYPE__: FastPathUpdateType.FASTPATH_UPDATETYPE_COLOR,
|
||||
header: new type.UInt16Le(FastPathUpdateType.FASTPATH_UPDATETYPE_COLOR, { constant: true }),
|
||||
cursorId: cursorId,
|
||||
cursorStr: cursorStr
|
||||
};
|
||||
|
||||
return new type.Component(self, opt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see http://msdn.microsoft.com/en-us/library/cc240622.aspx
|
||||
* @param updateData {type.Component}
|
||||
* @param opt {object} type option
|
||||
* @returns {type.Component}
|
||||
*/
|
||||
function fastPathUpdatePDU (updateData, opt) {
|
||||
function fastPathUpdatePDU(updateData, opt) {
|
||||
var self = {
|
||||
updateHeader : new type.UInt8( function () {
|
||||
return self.updateData.obj.__FASTPATH_UPDATE_TYPE__;
|
||||
|
@ -1116,12 +1170,27 @@ function fastPathUpdatePDU (updateData, opt) {
|
|||
}) };
|
||||
|
||||
switch (self.updateHeader.value & 0xf) {
|
||||
case FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP:
|
||||
self.updateData = fastPathBitmapUpdateDataPDU(options).read(s);
|
||||
break;
|
||||
default:
|
||||
self.updateData = new type.BinaryString(null, options).read(s);
|
||||
log.debug('unknown fast path pdu type ' + (self.updateHeader.value & 0xf));
|
||||
case FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP: {
|
||||
self.updateData = fastPathBitmapUpdateDataPDU(options).read(s);
|
||||
break;
|
||||
}
|
||||
case FastPathUpdateType.FASTPATH_UPDATETYPE_COLOR: {
|
||||
var data = new type.BinaryString(null, options).read(s);
|
||||
|
||||
// Hash the data to get a cursor id.
|
||||
// This is a hack since the cursor bitmap is sent but we can't use that, we has hash the bitmap and use that as a hint as to what cursor we need to display
|
||||
const hasher = require('crypto').createHash('sha384');
|
||||
hasher.update(data.value);
|
||||
const cursorid = Math.abs(hasher.digest().readInt32BE(0));
|
||||
const cursorStr = cursorIdTable[cursorid];
|
||||
//if (cursorStr == null) { console.log('Unknown cursorId: ' + cursorid); }
|
||||
self.updateData = fastPathPointerUpdateDataPDU(options, cursorid, cursorStr);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
self.updateData = new type.BinaryString(null, options).read(s);
|
||||
log.debug('unknown fast path pdu type ' + (self.updateHeader.value & 0xf));
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
|
|
@ -268,11 +268,16 @@ Client.prototype.recvServerFontMapPDU = function(s) {
|
|||
*/
|
||||
Client.prototype.recvFastPath = function (secFlag, s) {
|
||||
while (s.availableLength() > 0) {
|
||||
var pdu = data.fastPathUpdatePDU().read(s);
|
||||
var pdu = data.fastPathUpdatePDU().read(s);
|
||||
switch (pdu.obj.updateHeader.value & 0xf) {
|
||||
case data.FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP:
|
||||
this.emit('bitmap', pdu.obj.updateData.obj.rectangles.obj);
|
||||
break;
|
||||
case data.FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP: {
|
||||
this.emit('bitmap', pdu.obj.updateData.obj.rectangles.obj);
|
||||
break;
|
||||
}
|
||||
case data.FastPathUpdateType.FASTPATH_UPDATETYPE_COLOR: {
|
||||
this.emit('pointer', pdu.obj.updateData.obj.cursorId, pdu.obj.updateData.obj.cursorStr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,6 +160,8 @@ function RdpClient(config) {
|
|||
}).on('close', function () {
|
||||
self.connected = false;
|
||||
self.emit('close');
|
||||
}).on('pointer', function (cursorId, cursorStr) {
|
||||
self.emit('pointer', cursorId, cursorStr);
|
||||
}).on('bitmap', function (bitmaps) {
|
||||
for (var bitmap in bitmaps) {
|
||||
var bitmapData = bitmaps[bitmap].obj.bitmapDataStream.value;
|
||||
|
|
Loading…
Reference in New Issue