2017-08-28 19:27:45 +03:00
/ * *
* @ description Remote Desktop
* @ author Ylian Saint - Hilaire
* @ version v0 . 0.2 g
* /
2020-05-24 06:12:08 +03:00
// Polyfill Uint8Array.slice() for IE
if ( ! Uint8Array . prototype . slice ) { Object . defineProperty ( Uint8Array . prototype , 'slice' , { value : function ( begin , end ) { return new Uint8Array ( Array . prototype . slice . call ( this , begin , end ) ) ; } } ) ; }
2023-12-07 06:48:16 +03:00
function isWindowsBrowser ( ) {
return navigator && ! ! ( /win/i ) . exec ( navigator . platform ) ;
}
2017-08-28 19:27:45 +03:00
// Construct a MeshServer object
var CreateAgentRemoteDesktop = function ( canvasid , scrolldiv ) {
var obj = { }
obj . CanvasId = canvasid ;
if ( typeof canvasid === 'string' ) obj . CanvasId = Q ( canvasid ) ;
2020-08-08 01:01:28 +03:00
obj . Canvas = obj . CanvasId . getContext ( '2d' ) ;
2017-08-28 19:27:45 +03:00
obj . scrolldiv = scrolldiv ;
obj . State = 0 ;
obj . PendingOperations = [ ] ;
obj . tilesReceived = 0 ;
obj . TilesDrawn = 0 ;
obj . KillDraw = 0 ;
obj . ipad = false ;
obj . tabletKeyboardVisible = false ;
obj . LastX = 0 ;
obj . LastY = 0 ;
obj . touchenabled = 0 ;
obj . submenuoffset = 0 ;
obj . touchtimer = null ;
obj . TouchArray = { } ;
obj . connectmode = 0 ; // 0 = HTTP, 1 = WebSocket, 2 = WebRTC
obj . connectioncount = 0 ;
obj . rotation = 0 ;
obj . protocol = 2 ; // KVM
2018-01-10 07:13:41 +03:00
obj . debugmode = 0 ;
2018-01-15 08:01:06 +03:00
obj . firstUpKeys = [ ] ;
obj . stopInput = false ;
2019-03-10 01:28:08 +03:00
obj . localKeyMap = true ;
2020-11-19 08:30:33 +03:00
obj . remoteKeyMap = false ; // If false, the remote keyboard mapping is not used.
2020-02-07 05:04:55 +03:00
obj . pressedKeys = [ ] ;
2023-12-07 06:48:16 +03:00
obj . _altGrArmed = false ; // Windows AltGr detection
obj . _altGrTimeout = 0 ;
obj . isWindowsBrowser = isWindowsBrowser ( ) ;
2017-08-28 19:27:45 +03:00
obj . sessionid = 0 ;
obj . username ;
obj . oldie = false ;
2021-08-11 07:50:11 +03:00
obj . ImageType = 1 ; // 1 = JPEG, 2 = PNG, 3 = TIFF, 4 = WebP
2017-08-28 19:27:45 +03:00
obj . CompressionLevel = 50 ;
obj . ScalingLevel = 1024 ;
2020-04-25 04:24:24 +03:00
obj . FrameRateTimer = 100 ;
2020-09-29 21:44:53 +03:00
obj . SwapMouse = false ;
2022-03-01 21:30:14 +03:00
obj . UseExtendedKeyFlag = true ;
2017-08-28 19:27:45 +03:00
obj . FirstDraw = false ;
2021-04-29 01:46:19 +03:00
// Remote user mouse and keyboard lock
obj . onRemoteInputLockChanged = null ;
obj . RemoteInputLock = null ;
2022-02-28 20:52:35 +03:00
// Remote keyboard state
obj . onKeyboardStateChanged = null ;
obj . KeyboardState = 0 ; // 1 = NumLock, 2 = ScrollLock, 4 = CapsLock
2017-08-28 19:27:45 +03:00
obj . ScreenWidth = 960 ;
2020-11-07 03:33:54 +03:00
obj . ScreenHeight = 701 ;
2017-08-28 19:27:45 +03:00
obj . width = 960 ;
obj . height = 960 ;
2020-05-11 03:20:44 +03:00
obj . displays = null ;
obj . selectedDisplay = null ;
2018-01-15 08:01:06 +03:00
obj . onScreenSizeChange = null ;
2017-08-28 19:27:45 +03:00
obj . onMessage = null ;
obj . onConnectCountChanged = null ;
obj . onDebugMessage = null ;
obj . onTouchEnabledChanged = null ;
2018-01-03 03:52:49 +03:00
obj . onDisplayinfo = null ;
2019-02-05 05:06:01 +03:00
obj . accumulator = null ;
2017-08-28 19:27:45 +03:00
2020-05-16 00:49:18 +03:00
var xMouseCursorActive = true ;
var xMouseCursorCurrent = 'default' ;
obj . mouseCursorActive = function ( x ) { if ( xMouseCursorActive == x ) return ; xMouseCursorActive = x ; obj . CanvasId . style . cursor = ( ( x == true ) ? xMouseCursorCurrent : 'default' ) ; }
2020-03-07 01:06:33 +03:00
var mouseCursors = [ 'default' , 'progress' , 'crosshair' , 'pointer' , 'help' , 'text' , 'no-drop' , 'move' , 'nesw-resize' , 'ns-resize' , 'nwse-resize' , 'w-resize' , 'alias' , 'wait' , 'none' , 'not-allowed' , 'col-resize' , 'row-resize' , 'copy' , 'zoom-in' , 'zoom-out' ] ;
2020-05-16 00:49:18 +03:00
2017-08-28 19:27:45 +03:00
obj . Start = function ( ) {
obj . State = 0 ;
2019-02-05 05:06:01 +03:00
obj . accumulator = null ;
2017-08-28 19:27:45 +03:00
}
obj . Stop = function ( ) {
obj . setRotation ( 0 ) ;
obj . UnGrabKeyInput ( ) ;
obj . UnGrabMouseInput ( ) ;
obj . touchenabled = 0 ;
2021-03-19 07:09:56 +03:00
if ( obj . onScreenSizeChange != null ) { obj . onScreenSizeChange ( obj , obj . ScreenWidth , obj . ScreenHeight , obj . CanvasId ) ; }
2017-08-28 19:27:45 +03:00
obj . Canvas . clearRect ( 0 , 0 , obj . CanvasId . width , obj . CanvasId . height ) ;
}
obj . xxStateChange = function ( newstate ) {
if ( obj . State == newstate ) return ;
obj . State = newstate ;
2019-02-06 23:05:55 +03:00
obj . CanvasId . style . cursor = 'default' ;
2017-08-28 19:27:45 +03:00
//console.log('xxStateChange', newstate);
switch ( newstate ) {
case 0 : {
// Disconnect
obj . Stop ( ) ;
break ;
}
case 3 : {
// Websocket connected
break ;
}
}
}
2018-02-12 04:13:26 +03:00
obj . send = function ( x ) {
2020-11-13 23:37:05 +03:00
if ( obj . debugmode > 2 ) { console . log ( 'KSend(' + x . length + '): ' + rstr2hex ( x ) ) ; }
2019-08-11 08:34:21 +03:00
if ( obj . parent != null ) { obj . parent . send ( x ) ; }
2017-08-28 19:27:45 +03:00
}
// KVM Control.
// Routines for processing incoming packets from the AJAX server, and handling individual messages.
2020-05-17 00:07:53 +03:00
obj . ProcessPictureMsg = function ( data , X , Y ) {
2017-08-28 19:27:45 +03:00
//if (obj.targetnode != null) obj.Debug("ProcessPictureMsg " + X + "," + Y + " - " + obj.targetnode.substring(0, 8));
var tile = new Image ( ) ;
2018-01-19 02:43:43 +03:00
tile . xcount = obj . tilesReceived ++ ;
2020-05-19 03:57:11 +03:00
var r = obj . tilesReceived , tdata = data . slice ( 4 ) , ptr = 0 , strs = [ ] ;
// String.fromCharCode.apply() can't handle very large argument count, so we have to split like this.
while ( ( tdata . byteLength - ptr ) > 50000 ) { strs . push ( String . fromCharCode . apply ( null , tdata . slice ( ptr , ptr + 50000 ) ) ) ; ptr += 50000 ; }
if ( ptr > 0 ) { strs . push ( String . fromCharCode . apply ( null , tdata . slice ( ptr ) ) ) ; } else { strs . push ( String . fromCharCode . apply ( null , tdata ) ) ; }
2020-11-13 23:37:05 +03:00
tile . src = 'data:image/jpeg;base64,' + btoa ( strs . join ( '' ) ) ;
2017-08-28 19:27:45 +03:00
tile . onload = function ( ) {
2018-01-19 02:43:43 +03:00
//console.log('DecodeTile #' + this.xcount);
2020-05-19 03:57:11 +03:00
if ( ( obj . Canvas != null ) && ( obj . KillDraw < r ) && ( obj . State != 0 ) ) {
2017-08-28 19:27:45 +03:00
obj . PendingOperations . push ( [ r , 2 , tile , X , Y ] ) ;
while ( obj . DoPendingOperations ( ) ) { }
2020-05-19 03:57:11 +03:00
} else {
obj . PendingOperations . push ( [ r , 0 ] ) ;
2017-08-28 19:27:45 +03:00
}
}
2018-01-19 02:43:43 +03:00
tile . error = function ( ) { console . log ( 'DecodeTileError' ) ; }
2017-08-28 19:27:45 +03:00
}
obj . DoPendingOperations = function ( ) {
if ( obj . PendingOperations . length == 0 ) return false ;
for ( var i = 0 ; i < obj . PendingOperations . length ; i ++ ) { // && KillDraw < tilesDrawn
var Msg = obj . PendingOperations [ i ] ;
if ( Msg [ 0 ] == ( obj . TilesDrawn + 1 ) ) {
2021-07-05 01:53:51 +03:00
if ( obj . onPreDrawImage != null ) obj . onPreDrawImage ( ) ; // Notify that we are about to draw on the canvas.
2017-08-28 19:27:45 +03:00
if ( Msg [ 1 ] == 1 ) { obj . ProcessCopyRectMsg ( Msg [ 2 ] ) ; }
else if ( Msg [ 1 ] == 2 ) { obj . Canvas . drawImage ( Msg [ 2 ] , obj . rotX ( Msg [ 3 ] , Msg [ 4 ] ) , obj . rotY ( Msg [ 3 ] , Msg [ 4 ] ) ) ; delete Msg [ 2 ] ; }
obj . PendingOperations . splice ( i , 1 ) ;
delete Msg ;
obj . TilesDrawn ++ ;
2020-05-19 03:57:11 +03:00
if ( ( obj . TilesDrawn == obj . tilesReceived ) && ( obj . KillDraw < obj . TilesDrawn ) ) { obj . KillDraw = obj . TilesDrawn = obj . tilesReceived = 0 ; }
2017-08-28 19:27:45 +03:00
return true ;
}
}
if ( obj . oldie && obj . PendingOperations . length > 0 ) { obj . TilesDrawn ++ ; }
return false ;
}
obj . ProcessCopyRectMsg = function ( str ) {
var SX = ( ( str . charCodeAt ( 0 ) & 0xFF ) << 8 ) + ( str . charCodeAt ( 1 ) & 0xFF ) ;
var SY = ( ( str . charCodeAt ( 2 ) & 0xFF ) << 8 ) + ( str . charCodeAt ( 3 ) & 0xFF ) ;
var DX = ( ( str . charCodeAt ( 4 ) & 0xFF ) << 8 ) + ( str . charCodeAt ( 5 ) & 0xFF ) ;
var DY = ( ( str . charCodeAt ( 6 ) & 0xFF ) << 8 ) + ( str . charCodeAt ( 7 ) & 0xFF ) ;
var WIDTH = ( ( str . charCodeAt ( 8 ) & 0xFF ) << 8 ) + ( str . charCodeAt ( 9 ) & 0xFF ) ;
var HEIGHT = ( ( str . charCodeAt ( 10 ) & 0xFF ) << 8 ) + ( str . charCodeAt ( 11 ) & 0xFF ) ;
obj . Canvas . drawImage ( Canvas . canvas , SX , SY , WIDTH , HEIGHT , DX , DY , WIDTH , HEIGHT ) ;
}
obj . SendUnPause = function ( ) {
2020-11-13 23:37:05 +03:00
if ( obj . debugmode > 1 ) { console . log ( 'SendUnPause' ) ; }
2017-08-28 19:27:45 +03:00
//obj.xxStateChange(3);
2018-02-12 04:13:26 +03:00
obj . send ( String . fromCharCode ( 0x00 , 0x08 , 0x00 , 0x05 , 0x00 ) ) ;
2017-08-28 19:27:45 +03:00
}
obj . SendPause = function ( ) {
2020-11-13 23:37:05 +03:00
if ( obj . debugmode > 1 ) { console . log ( 'SendPause' ) ; }
2017-08-28 19:27:45 +03:00
//obj.xxStateChange(2);
2018-02-12 04:13:26 +03:00
obj . send ( String . fromCharCode ( 0x00 , 0x08 , 0x00 , 0x05 , 0x01 ) ) ;
2017-08-28 19:27:45 +03:00
}
2021-08-11 07:50:11 +03:00
obj . SendCompressionLevel = function ( type , level , scaling , frametimer ) { // Type: 1 = JPEG, 2 = PNG, 3 = TIFF, 4 = WebP
obj . ImageType = type ;
2017-08-28 19:27:45 +03:00
if ( level ) { obj . CompressionLevel = level ; }
if ( scaling ) { obj . ScalingLevel = scaling ; }
if ( frametimer ) { obj . FrameRateTimer = frametimer ; }
2018-02-12 04:13:26 +03:00
obj . send ( String . fromCharCode ( 0x00 , 0x05 , 0x00 , 0x0A , type , obj . CompressionLevel ) + obj . shortToStr ( obj . ScalingLevel ) + obj . shortToStr ( obj . FrameRateTimer ) ) ;
2017-08-28 19:27:45 +03:00
}
obj . SendRefresh = function ( ) {
2018-02-12 04:13:26 +03:00
obj . send ( String . fromCharCode ( 0x00 , 0x06 , 0x00 , 0x04 ) ) ;
2017-08-28 19:27:45 +03:00
}
obj . ProcessScreenMsg = function ( width , height ) {
2020-11-13 23:37:05 +03:00
if ( obj . debugmode > 0 ) { console . log ( 'ScreenSize: ' + width + ' x ' + height ) ; }
if ( ( obj . ScreenWidth == width ) && ( obj . ScreenHeight == height ) ) return ; // Ignore change if screen is same size.
2017-08-28 19:27:45 +03:00
obj . Canvas . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
obj . rotation = 0 ;
obj . FirstDraw = true ;
obj . ScreenWidth = obj . width = width ;
obj . ScreenHeight = obj . height = height ;
obj . KillDraw = obj . tilesReceived ;
while ( obj . PendingOperations . length > 0 ) { obj . PendingOperations . shift ( ) ; }
2021-08-11 07:50:11 +03:00
obj . SendCompressionLevel ( obj . ImageType ) ;
2017-08-28 19:27:45 +03:00
obj . SendUnPause ( ) ;
2021-04-29 01:46:19 +03:00
obj . SendRemoteInputLock ( 2 ) ; // Query input lock state
2021-03-19 07:09:56 +03:00
// No need to event the display size change now, it will be evented on first draw.
2018-01-15 08:01:06 +03:00
if ( obj . onScreenSizeChange != null ) { obj . onScreenSizeChange ( obj , obj . ScreenWidth , obj . ScreenHeight , obj . CanvasId ) ; }
2017-08-28 19:27:45 +03:00
}
2020-05-17 00:07:53 +03:00
obj . ProcessBinaryCommand = function ( cmd , cmdsize , view ) {
var X , Y ;
if ( ( cmd == 3 ) || ( cmd == 4 ) || ( cmd == 7 ) ) { X = ( view [ 4 ] << 8 ) + view [ 5 ] ; Y = ( view [ 6 ] << 8 ) + view [ 7 ] ; }
2020-09-18 01:39:33 +03:00
if ( obj . debugmode > 2 ) { console . log ( 'CMD' , cmd , cmdsize , X , Y ) ; }
2017-08-28 19:27:45 +03:00
2020-06-18 22:47:34 +03:00
// Record the command if needed
if ( obj . recordedData != null ) {
if ( cmdsize > 65000 ) {
obj . recordedData . push ( recordingEntry ( 2 , 1 , obj . shortToStr ( 27 ) + obj . shortToStr ( 8 ) + obj . intToStr ( cmdsize ) + obj . shortToStr ( cmd ) + obj . shortToStr ( 0 ) + obj . shortToStr ( 0 ) + obj . shortToStr ( 0 ) + String . fromCharCode . apply ( null , view ) ) ) ;
} else {
obj . recordedData . push ( recordingEntry ( 2 , 1 , String . fromCharCode . apply ( null , view ) ) ) ;
}
}
2020-05-17 00:07:53 +03:00
switch ( cmd ) {
2017-08-28 19:27:45 +03:00
case 3 : // Tile
if ( obj . FirstDraw ) obj . onResize ( ) ;
2021-08-11 19:12:57 +03:00
//console.log('TILE', X, Y, cmdsize);
2020-05-17 00:07:53 +03:00
obj . ProcessPictureMsg ( view . slice ( 4 ) , X , Y ) ;
2017-08-28 19:27:45 +03:00
break ;
case 7 : // Screen size
obj . ProcessScreenMsg ( X , Y ) ;
obj . SendKeyMsgKC ( obj . KeyAction . UP , 16 ) ; // Shift
obj . SendKeyMsgKC ( obj . KeyAction . UP , 17 ) ; // Ctrl
obj . SendKeyMsgKC ( obj . KeyAction . UP , 18 ) ; // Alt
obj . SendKeyMsgKC ( obj . KeyAction . UP , 91 ) ; // Left-Windows
obj . SendKeyMsgKC ( obj . KeyAction . UP , 92 ) ; // Right-Windows
2018-01-15 08:01:06 +03:00
obj . SendKeyMsgKC ( obj . KeyAction . UP , 16 ) ; // Shift
2018-02-12 04:13:26 +03:00
obj . send ( String . fromCharCode ( 0x00 , 0x0E , 0x00 , 0x04 ) ) ;
2017-08-28 19:27:45 +03:00
break ;
2020-05-17 00:07:53 +03:00
case 11 : // GetDisplays (TODO)
var selectedDisplay = 0 , displays = { } , dcount = ( view [ 4 ] << 8 ) + view [ 5 ] ;
2018-01-03 03:52:49 +03:00
if ( dcount > 0 ) {
2017-08-28 19:27:45 +03:00
// Many displays present
2020-05-17 00:07:53 +03:00
selectedDisplay = ( view [ 6 + ( dcount * 2 ) ] << 8 ) + view [ 7 + ( dcount * 2 ) ] ;
2017-08-28 19:27:45 +03:00
for ( var i = 0 ; i < dcount ; i ++ ) {
2020-05-17 00:07:53 +03:00
var disp = ( view [ 6 + ( i * 2 ) ] << 8 ) + view [ 7 + ( i * 2 ) ] ;
2019-04-28 01:36:11 +03:00
if ( disp == 65535 ) { displays [ disp ] = 'All Displays' ; } else { displays [ disp ] = 'Display ' + disp ; }
2017-08-28 19:27:45 +03:00
}
}
2019-05-21 02:00:33 +03:00
//console.log('Get Displays', displays, selectedDisplay, rstr2hex(str));
2020-05-11 03:20:44 +03:00
obj . displays = displays ; obj . selectedDisplay = selectedDisplay ;
2019-04-28 01:36:11 +03:00
if ( obj . onDisplayinfo != null ) { obj . onDisplayinfo ( obj , displays , selectedDisplay ) ; }
2017-08-28 19:27:45 +03:00
break ;
case 12 : // SetDisplay
2018-02-02 23:46:09 +03:00
//console.log('SetDisplayConfirmed');
2017-08-28 19:27:45 +03:00
break ;
case 14 : // KVM_INIT_TOUCH
obj . touchenabled = 1 ;
obj . TouchArray = { } ;
if ( obj . onTouchEnabledChanged != null ) obj . onTouchEnabledChanged ( obj . touchenabled ) ;
break ;
case 15 : // KVM_TOUCH
obj . TouchArray = { } ;
break ;
case 17 : // MNG_KVM_MESSAGE
2021-03-19 00:36:21 +03:00
var str = String . fromCharCode . apply ( null , view . slice ( 4 ) ) ;
2020-11-13 23:37:05 +03:00
console . log ( 'Got KVM Message: ' + str ) ;
2020-05-17 00:07:53 +03:00
if ( obj . onMessage != null ) obj . onMessage ( str , obj ) ;
2017-08-28 19:27:45 +03:00
break ;
2022-02-28 23:32:07 +03:00
case 18 : // MNG_KVM_KEYSTATE
if ( ( cmdsize != 5 ) || ( obj . KeyboardState == view [ 4 ] ) ) break ;
obj . KeyboardState = view [ 4 ] ; // 1 = NumLock, 2 = ScrollLock, 4 = CapsLock
if ( obj . onKeyboardStateChanged ) { obj . onKeyboardStateChanged ( obj , obj . KeyboardState ) ; }
console . log ( 'MNG_KVM_KEYSTATE:' + ( ( obj . KeyboardState & 1 ) ? ' NumLock' : '' ) + ( ( obj . KeyboardState & 2 ) ? ' ScrollLock' : '' ) + ( ( obj . KeyboardState & 4 ) ? ' CapsLock' : '' ) ) ;
break ;
2019-01-24 05:07:02 +03:00
case 65 : // Alert
2021-03-19 00:36:21 +03:00
var str = String . fromCharCode . apply ( null , view . slice ( 4 ) ) ;
2019-05-21 02:00:33 +03:00
if ( str [ 0 ] != '.' ) {
console . log ( str ) ; //alert('KVM: ' + str);
2020-04-19 05:44:07 +03:00
if ( obj . parent && obj . parent . setConsoleMessage ) { obj . parent . setConsoleMessage ( str ) ; }
2019-05-21 02:00:33 +03:00
} else {
console . log ( 'KVM: ' + str . substring ( 1 ) ) ;
}
2019-01-24 05:07:02 +03:00
break ;
2021-05-16 22:44:49 +03:00
case 82 : // DISPLAY LOCATION & SIZE
if ( ( cmdsize < 4 ) || ( ( ( cmdsize - 4 ) % 10 ) != 0 ) ) break ;
var screenCount = ( ( cmdsize - 4 ) / 10 ) , screenInfo = { } , ptr = 4 ;
for ( var i = 0 ; i < screenCount ; i ++ ) { screenInfo [ ( view [ ptr + 0 ] << 8 ) + view [ ptr + 1 ] ] = { x : ( ( view [ ptr + 2 ] << 8 ) + view [ ptr + 3 ] ) , y : ( ( view [ ptr + 4 ] << 8 ) + view [ ptr + 5 ] ) , w : ( ( view [ ptr + 6 ] << 8 ) + view [ ptr + 7 ] ) , h : ( ( view [ ptr + 8 ] << 8 ) + view [ ptr + 9 ] ) } ; ptr += 10 ; }
2021-07-13 21:20:44 +03:00
//console.log('ScreenInfo', JSON.stringify(screenInfo, null, 2));
2021-05-16 22:44:49 +03:00
break ;
2021-04-29 01:46:19 +03:00
case 87 : // MNG_KVM_INPUT_LOCK
if ( cmdsize != 5 ) break ;
2021-04-29 05:25:26 +03:00
if ( ( obj . RemoteInputLock == null ) || ( obj . RemoteInputLock !== ( view [ 4 ] != 0 ) ) ) {
2021-04-29 01:46:19 +03:00
obj . RemoteInputLock = ( view [ 4 ] != 0 ) ;
if ( obj . onRemoteInputLockChanged ) { obj . onRemoteInputLockChanged ( obj , obj . RemoteInputLock ) ; }
}
break ;
2019-09-20 03:24:05 +03:00
case 88 : // MNG_KVM_MOUSE_CURSOR
2021-01-17 12:41:20 +03:00
if ( ( cmdsize != 5 ) || ( obj . stopInput ) ) break ;
2020-05-17 00:07:53 +03:00
var cursorNum = view [ 4 ] ;
2019-09-20 03:24:05 +03:00
if ( cursorNum > mouseCursors . length ) { cursorNum = 0 ; }
2020-05-16 00:49:18 +03:00
xMouseCursorCurrent = mouseCursors [ cursorNum ] ;
if ( xMouseCursorActive ) { obj . CanvasId . style . cursor = xMouseCursorCurrent ; }
2019-09-20 03:24:05 +03:00
break ;
2020-05-17 00:07:53 +03:00
default :
console . log ( 'Unknown command' , cmd , cmdsize ) ;
break ;
2017-08-28 19:27:45 +03:00
}
2020-05-17 00:07:53 +03:00
}
2017-08-28 19:27:45 +03:00
// Keyboard and Mouse I/O.
obj . MouseButton = { "NONE" : 0x00 , "LEFT" : 0x02 , "RIGHT" : 0x08 , "MIDDLE" : 0x20 } ;
2019-01-24 05:07:02 +03:00
obj . KeyAction = { "NONE" : 0 , "DOWN" : 1 , "UP" : 2 , "SCROLL" : 3 , "EXUP" : 4 , "EXDOWN" : 5 , "DBLCLICK" : 6 } ;
2020-11-18 06:30:26 +03:00
obj . InputType = { "KEY" : 1 , "MOUSE" : 2 , "CTRLALTDEL" : 10 , "TOUCH" : 15 , "KEYUNICODE" : 85 } ;
2017-08-28 19:27:45 +03:00
obj . Alternate = 0 ;
2019-01-07 07:23:29 +03:00
var convertKeyCodeTable = {
"Pause" : 19 ,
"CapsLock" : 20 ,
"Space" : 32 ,
"Quote" : 222 ,
"Minus" : 189 ,
"NumpadMultiply" : 106 ,
"NumpadAdd" : 107 ,
"PrintScreen" : 44 ,
"Comma" : 188 ,
"NumpadSubtract" : 109 ,
"NumpadDecimal" : 110 ,
"Period" : 190 ,
"Slash" : 191 ,
"NumpadDivide" : 111 ,
"Semicolon" : 186 ,
"Equal" : 187 ,
"OSLeft" : 91 ,
"BracketLeft" : 219 ,
"OSRight" : 91 ,
"Backslash" : 220 ,
"BracketRight" : 221 ,
"ContextMenu" : 93 ,
"Backquote" : 192 ,
"NumLock" : 144 ,
"ScrollLock" : 145 ,
"Backspace" : 8 ,
"Tab" : 9 ,
"Enter" : 13 ,
"NumpadEnter" : 13 ,
"Escape" : 27 ,
"Delete" : 46 ,
"Home" : 36 ,
"PageUp" : 33 ,
"PageDown" : 34 ,
"ArrowLeft" : 37 ,
"ArrowUp" : 38 ,
"ArrowRight" : 39 ,
"ArrowDown" : 40 ,
"End" : 35 ,
"Insert" : 45 ,
"F1" : 112 ,
"F2" : 113 ,
"F3" : 114 ,
"F4" : 115 ,
"F5" : 116 ,
"F6" : 117 ,
"F7" : 118 ,
"F8" : 119 ,
"F9" : 120 ,
"F10" : 121 ,
"F11" : 122 ,
"F12" : 123 ,
"ShiftLeft" : 16 ,
"ShiftRight" : 16 ,
"ControlLeft" : 17 ,
"ControlRight" : 17 ,
"AltLeft" : 18 ,
"AltRight" : 18 ,
"MetaLeft" : 91 ,
"MetaRight" : 92 ,
"VolumeMute" : 181
//"LaunchMail":
//"LaunchApp1":
//"LaunchApp2":
//"BrowserStop":
//"MediaStop":
//"MediaTrackPrevious":
//"MediaTrackNext":
//"MediaPlayPause":
//"MediaSelect":
}
function convertKeyCode ( e ) {
if ( e . code . startsWith ( 'Key' ) && e . code . length == 4 ) { return e . code . charCodeAt ( 3 ) ; }
if ( e . code . startsWith ( 'Digit' ) && e . code . length == 6 ) { return e . code . charCodeAt ( 5 ) ; }
if ( e . code . startsWith ( 'Numpad' ) && e . code . length == 7 ) { return e . code . charCodeAt ( 6 ) + 48 ; }
return convertKeyCodeTable [ e . code ] ;
}
2022-02-24 01:07:42 +03:00
var extendedKeyTable = [ 'ShiftRight' , 'AltRight' , 'ControlRight' , 'Home' , 'End' , 'Insert' , 'Delete' , 'PageUp' , 'PageDown' , 'NumpadDivide' , 'NumpadEnter' , 'NumLock' , 'Pause' ] ;
2017-08-28 19:27:45 +03:00
obj . SendKeyMsg = function ( action , event ) {
if ( action == null ) return ;
2019-01-07 07:23:29 +03:00
if ( ! event ) { event = window . event ; }
2022-02-24 01:07:42 +03:00
2022-02-28 23:32:07 +03:00
var extendedKey = false ; // Test feature, add ?extkeys=1 to url to use.
2023-12-07 06:48:16 +03:00
if ( ( obj . UseExtendedKeyFlag || ( urlargs . extkeys == 1 ) ) && ( typeof event . code == 'string' ) && ( event . code . startsWith ( 'Arrow' ) || ( extendedKeyTable . indexOf ( event . code ) >= 0 ) ) ) {
extendedKey = true ;
}
if ( obj . isWindowsBrowser ) {
if ( obj . checkAltGr ( obj , event , action ) ) {
return ;
} ;
}
2022-02-24 01:07:42 +03:00
if ( ( extendedKey == false ) && event . code && ( event . code . startsWith ( 'NumPad' ) == false ) && ( obj . localKeyMap == false ) ) {
2019-01-07 07:23:29 +03:00
// Convert "event.code" into a scancode. This works the same regardless of the keyboard language.
// Older browsers will not support this.
var kc = convertKeyCode ( event ) ;
2022-02-24 01:07:42 +03:00
if ( kc != null ) { obj . SendKeyMsgKC ( action , kc , extendedKey ) ; }
2019-01-07 07:23:29 +03:00
} else {
// Use this keycode, this works best with "US-EN" keyboards.
// Older browser support this.
var kc = event . keyCode ;
if ( kc == 0x3B ) { kc = 0xBA ; } // Fix the ';' key
2019-07-06 01:25:03 +03:00
else if ( kc == 173 ) { kc = 189 ; } // Fix the '-' key for Firefox
else if ( kc == 61 ) { kc = 187 ; } // Fix the '=' key for Firefox
2022-02-24 01:07:42 +03:00
obj . SendKeyMsgKC ( action , kc , extendedKey ) ;
2019-01-07 07:23:29 +03:00
}
2017-08-28 19:27:45 +03:00
}
2023-12-07 06:48:16 +03:00
const ControlLeftKc = 17 ;
const AltGrKc = 225 ;
//return true: Key is alredy handled.
obj . checkAltGr = function ( obj , event , action ) {
// Windows doesn't have a proper AltGr, but handles it using
// fake Ctrl+Alt. However the remote end might not be Windows,
// so we need to merge those into a single AltGr event. We
// detect this case by seeing the two key events directly after
// each other with a very short time between them (<50ms).
if ( obj . _altGrArmed ) {
obj . _altGrArmed = false ;
clearTimeout ( obj . _altGrTimeout ) ;
if ( ( event . code === "AltRight" ) && ( ( event . timeStamp - obj . _altGrCtrlTime ) < 50 ) ) {
//AltGr detected.
obj . SendKeyMsgKC ( action , AltGrKc , false ) ;
return true ;
}
}
// Possible start of AltGr sequence?
if ( ( event . code === "ControlLeft" ) && ! ( ControlLeftKc in obj . pressedKeys ) ) {
obj . _altGrArmed = true ;
obj . _altGrCtrlTime = event . timeStamp ;
if ( action == 1 ) {
obj . _altGrTimeout = setTimeout ( obj . _handleAltGrTimeout . bind ( obj ) , 100 ) ;
return true ;
}
}
return false ;
}
obj . _handleAltGrTimeout = function ( ) { //Windows and no Ctrl+Alt -> send only Ctrl.
obj . _altGrArmed = false ;
clearTimeout ( obj . _altGrTimeout ) ;
obj . SendKeyMsgKC ( 1 , ControlLeftKc , false ) ; // (KeyDown, "ControlLeft", false)
}
2021-04-29 01:46:19 +03:00
// Send remote input lock. 0 = Unlock, 1 = Lock, 2 = Query
2021-04-29 03:05:40 +03:00
obj . SendRemoteInputLock = function ( code ) { obj . send ( String . fromCharCode ( 0x00 , 87 , 0x00 , 0x05 , code ) ) ; }
2021-04-29 01:46:19 +03:00
2017-08-28 19:27:45 +03:00
obj . SendMessage = function ( msg ) {
2018-02-12 04:13:26 +03:00
if ( obj . State == 3 ) obj . send ( String . fromCharCode ( 0x00 , 0x11 ) + obj . shortToStr ( 4 + msg . length ) + msg ) ; // 0x11 = 17 MNG_KVM_MESSAGE
2017-08-28 19:27:45 +03:00
}
2022-02-24 01:07:42 +03:00
obj . SendKeyMsgKC = function ( action , kc , extendedKey ) {
2018-04-29 01:36:10 +03:00
if ( obj . State != 3 ) return ;
2022-02-24 01:07:42 +03:00
if ( typeof action == 'object' ) { for ( var i in action ) { obj . SendKeyMsgKC ( action [ i ] [ 0 ] , action [ i ] [ 1 ] , action [ i ] [ 2 ] ) ; } }
2020-02-07 05:04:55 +03:00
else {
if ( action == 1 ) { // Key Down
if ( obj . pressedKeys . indexOf ( kc ) == - 1 ) { obj . pressedKeys . unshift ( kc ) ; } // Add key press to start of array
} else if ( action == 2 ) { // Key Up
var i = obj . pressedKeys . indexOf ( kc ) ;
if ( i != - 1 ) { obj . pressedKeys . splice ( i , 1 ) ; } // Remove the key press from the pressed array
}
2020-12-20 04:21:42 +03:00
if ( obj . debugmode > 0 ) { console . log ( 'Sending Key ' + kc + ', action ' + action ) ; }
2022-02-24 01:07:42 +03:00
var up = ( action - 1 ) ;
if ( extendedKey ) { if ( up == 1 ) { up = 3 ; } else { up = 4 ; } }
obj . send ( String . fromCharCode ( 0x00 , obj . InputType . KEY , 0x00 , 0x06 , up , kc ) ) ;
2020-02-07 05:04:55 +03:00
}
2017-08-28 19:27:45 +03:00
}
2020-11-19 04:03:49 +03:00
obj . SendStringUnicode = function ( str ) {
if ( obj . State != 3 ) return ;
2021-04-16 01:38:38 +03:00
for ( var i = 0 ; i < str . length ; i ++ ) {
obj . send ( String . fromCharCode ( 0x00 , obj . InputType . KEYUNICODE , 0x00 , 0x07 , 0 ) + ShortToStr ( str . charCodeAt ( i ) ) ) ;
obj . send ( String . fromCharCode ( 0x00 , obj . InputType . KEYUNICODE , 0x00 , 0x07 , 1 ) + ShortToStr ( str . charCodeAt ( i ) ) ) ;
}
2020-11-19 04:03:49 +03:00
}
2020-11-18 06:30:26 +03:00
obj . SendKeyUnicode = function ( action , val ) {
if ( obj . State != 3 ) return ;
2023-12-07 06:48:16 +03:00
if ( obj . debugmode > 0 ) { console . log ( 'Sending UnicodeKey ' + val + ', action ' + action ) ; }
2020-11-18 06:30:26 +03:00
obj . send ( String . fromCharCode ( 0x00 , obj . InputType . KEYUNICODE , 0x00 , 0x07 , ( action - 1 ) ) + ShortToStr ( val ) ) ;
}
2017-08-28 19:27:45 +03:00
obj . sendcad = function ( ) { obj . SendCtrlAltDelMsg ( ) ; }
obj . SendCtrlAltDelMsg = function ( ) {
2018-02-12 04:13:26 +03:00
if ( obj . State == 3 ) { obj . send ( String . fromCharCode ( 0x00 , obj . InputType . CTRLALTDEL , 0x00 , 0x04 ) ) ; }
2017-08-28 19:27:45 +03:00
}
obj . SendEscKey = function ( ) {
2018-02-12 04:13:26 +03:00
if ( obj . State == 3 ) obj . send ( String . fromCharCode ( 0x00 , obj . InputType . KEY , 0x00 , 0x06 , 0x00 , 0x1B , 0x00 , obj . InputType . KEY , 0x00 , 0x06 , 0x01 , 0x1B ) ) ;
2017-08-28 19:27:45 +03:00
}
obj . SendStartMsg = function ( ) {
obj . SendKeyMsgKC ( obj . KeyAction . EXDOWN , 0x5B ) ; // L-Windows
obj . SendKeyMsgKC ( obj . KeyAction . EXUP , 0x5B ) ; // L-Windows
}
obj . SendCharmsMsg = function ( ) {
obj . SendKeyMsgKC ( obj . KeyAction . EXDOWN , 0x5B ) ; // L-Windows
obj . SendKeyMsgKC ( obj . KeyAction . DOWN , 67 ) ; // C
obj . SendKeyMsgKC ( obj . KeyAction . UP , 67 ) ; // C
obj . SendKeyMsgKC ( obj . KeyAction . EXUP , 0x5B ) ; // L-Windows
}
obj . SendTouchMsg1 = function ( id , flags , x , y ) {
2018-02-12 04:13:26 +03:00
if ( obj . State == 3 ) obj . send ( String . fromCharCode ( 0x00 , obj . InputType . TOUCH ) + obj . shortToStr ( 14 ) + String . fromCharCode ( 0x01 , id ) + obj . intToStr ( flags ) + obj . shortToStr ( x ) + obj . shortToStr ( y ) ) ;
2017-08-28 19:27:45 +03:00
}
obj . SendTouchMsg2 = function ( id , flags ) {
var msg = '' ;
var flags2 ;
var str = "TOUCHSEND: " ;
for ( var k in obj . TouchArray ) {
if ( k == id ) { flags2 = flags ; } else {
if ( obj . TouchArray [ k ] . f == 1 ) { flags2 = 0x00010000 | 0x00000002 | 0x00000004 ; obj . TouchArray [ k ] . f = 3 ; str += "START" + k ; } // POINTER_FLAG_DOWN
else if ( obj . TouchArray [ k ] . f == 2 ) { flags2 = 0x00040000 ; str += "STOP" + k ; } // POINTER_FLAG_UP
else flags2 = 0x00000002 | 0x00000004 | 0x00020000 ; // POINTER_FLAG_UPDATE
}
msg += String . fromCharCode ( k ) + obj . intToStr ( flags2 ) + obj . shortToStr ( obj . TouchArray [ k ] . x ) + obj . shortToStr ( obj . TouchArray [ k ] . y ) ;
if ( obj . TouchArray [ k ] . f == 2 ) delete obj . TouchArray [ k ] ;
}
2018-02-12 04:13:26 +03:00
if ( obj . State == 3 ) obj . send ( String . fromCharCode ( 0x00 , obj . InputType . TOUCH ) + obj . shortToStr ( 5 + msg . length ) + String . fromCharCode ( 0x02 ) + msg ) ;
2017-08-28 19:27:45 +03:00
if ( Object . keys ( obj . TouchArray ) . length == 0 && obj . touchtimer != null ) { clearInterval ( obj . touchtimer ) ; obj . touchtimer = null ; }
}
obj . SendMouseMsg = function ( Action , event ) {
if ( obj . State != 3 ) return ;
if ( Action != null && obj . Canvas != null ) {
if ( ! event ) { var event = window . event ; }
2019-04-27 02:10:17 +03:00
2017-08-28 19:27:45 +03:00
var ScaleFactorHeight = ( obj . Canvas . canvas . height / obj . CanvasId . clientHeight ) ;
var ScaleFactorWidth = ( obj . Canvas . canvas . width / obj . CanvasId . clientWidth ) ;
var Offsets = obj . GetPositionOfControl ( obj . Canvas . canvas ) ;
var X = ( ( event . pageX - Offsets [ 0 ] ) * ScaleFactorWidth ) ;
var Y = ( ( event . pageY - Offsets [ 1 ] ) * ScaleFactorHeight ) ;
2019-04-27 02:10:17 +03:00
if ( event . addx ) { X += event . addx ; }
if ( event . addy ) { Y += event . addy ; }
2017-08-28 19:27:45 +03:00
if ( X >= 0 && X <= obj . Canvas . canvas . width && Y >= 0 && Y <= obj . Canvas . canvas . height ) {
var Button = 0 ;
var Delta = 0 ;
if ( Action == obj . KeyAction . UP || Action == obj . KeyAction . DOWN ) {
if ( event . which ) { ( ( event . which == 1 ) ? ( Button = obj . MouseButton . LEFT ) : ( ( event . which == 2 ) ? ( Button = obj . MouseButton . MIDDLE ) : ( Button = obj . MouseButton . RIGHT ) ) ) ; }
else if ( event . button ) { ( ( event . button == 0 ) ? ( Button = obj . MouseButton . LEFT ) : ( ( event . button == 1 ) ? ( Button = obj . MouseButton . MIDDLE ) : ( Button = obj . MouseButton . RIGHT ) ) ) ; }
}
else if ( Action == obj . KeyAction . SCROLL ) {
if ( event . detail ) { Delta = ( - 1 * ( event . detail * 120 ) ) ; } else if ( event . wheelDelta ) { Delta = ( event . wheelDelta * 3 ) ; }
}
2020-09-29 21:44:53 +03:00
// Swap mouse buttons if needed
if ( obj . SwapMouse === true ) {
if ( Button == obj . MouseButton . LEFT ) { Button = obj . MouseButton . RIGHT ; }
else if ( Button == obj . MouseButton . RIGHT ) { Button = obj . MouseButton . LEFT ; }
}
2022-06-20 20:55:11 +03:00
// Reverse mouse wheel if needed
if ( obj . ReverseMouseWheel ) { Delta = - 1 * Delta ; }
2017-08-28 19:27:45 +03:00
var MouseMsg = "" ;
2019-01-24 05:07:02 +03:00
if ( Action == obj . KeyAction . DBLCLICK ) {
MouseMsg = String . fromCharCode ( 0x00 , obj . InputType . MOUSE , 0x00 , 0x0A , 0x00 , 0x88 , ( ( X / 256 ) & 0xFF ) , ( X & 0xFF ) , ( ( Y / 256 ) & 0xFF ) , ( Y & 0xFF ) ) ;
} else if ( Action == obj . KeyAction . SCROLL ) {
2020-05-22 10:06:34 +03:00
var deltaHigh = 0 , deltaLow = 0 ;
if ( Delta < 0 ) { deltaHigh = ( 255 - ( Math . abs ( Delta ) >> 8 ) ) ; deltaLow = ( 255 - ( Math . abs ( Delta ) & 0xFF ) ) ; } else { deltaHigh = ( Delta >> 8 ) ; deltaLow = ( Delta & 0xFF ) ; }
MouseMsg = String . fromCharCode ( 0x00 , obj . InputType . MOUSE , 0x00 , 0x0C , 0x00 , 0x00 , ( ( X / 256 ) & 0xFF ) , ( X & 0xFF ) , ( ( Y / 256 ) & 0xFF ) , ( Y & 0xFF ) , deltaHigh , deltaLow ) ;
2019-01-24 05:07:02 +03:00
} else {
MouseMsg = String . fromCharCode ( 0x00 , obj . InputType . MOUSE , 0x00 , 0x0A , 0x00 , ( ( Action == obj . KeyAction . DOWN ) ? Button : ( ( Button * 2 ) & 0xFF ) ) , ( ( X / 256 ) & 0xFF ) , ( X & 0xFF ) , ( ( Y / 256 ) & 0xFF ) , ( Y & 0xFF ) ) ;
}
if ( obj . Action == obj . KeyAction . NONE ) {
if ( obj . Alternate == 0 || obj . ipad ) { obj . send ( MouseMsg ) ; obj . Alternate = 1 ; } else { obj . Alternate = 0 ; }
} else {
obj . send ( MouseMsg ) ;
}
2017-08-28 19:27:45 +03:00
}
}
}
2018-02-12 04:13:26 +03:00
obj . GetDisplayNumbers = function ( ) { obj . send ( String . fromCharCode ( 0x00 , 0x0B , 0x00 , 0x04 ) ) ; } // Get Terminal display
2020-03-26 02:20:11 +03:00
obj . SetDisplay = function ( number ) { /*console.log('Set display', number);*/ obj . send ( String . fromCharCode ( 0x00 , 0x0C , 0x00 , 0x06 , number >> 8 , number & 0xFF ) ) ; } // Set Terminal display
2017-08-28 19:27:45 +03:00
obj . intToStr = function ( x ) { return String . fromCharCode ( ( x >> 24 ) & 0xFF , ( x >> 16 ) & 0xFF , ( x >> 8 ) & 0xFF , x & 0xFF ) ; }
obj . shortToStr = function ( x ) { return String . fromCharCode ( ( x >> 8 ) & 0xFF , x & 0xFF ) ; }
obj . onResize = function ( ) {
if ( obj . ScreenWidth == 0 || obj . ScreenHeight == 0 ) return ;
2022-05-03 07:06:32 +03:00
if ( ( obj . Canvas . canvas . width == obj . ScreenWidth ) && ( obj . Canvas . canvas . height == obj . ScreenHeight ) ) return ;
2017-08-28 19:27:45 +03:00
if ( obj . FirstDraw ) {
obj . Canvas . canvas . width = obj . ScreenWidth ;
obj . Canvas . canvas . height = obj . ScreenHeight ;
obj . Canvas . fillRect ( 0 , 0 , obj . ScreenWidth , obj . ScreenHeight ) ;
2021-03-19 07:09:56 +03:00
if ( obj . onScreenSizeChange != null ) { obj . onScreenSizeChange ( obj , obj . ScreenWidth , obj . ScreenHeight , obj . CanvasId ) ; }
2017-08-28 19:27:45 +03:00
}
obj . FirstDraw = false ;
2020-09-18 01:39:33 +03:00
if ( obj . debugmode > 1 ) { console . log ( "onResize: " + obj . ScreenWidth + " x " + obj . ScreenHeight ) ; }
2017-08-28 19:27:45 +03:00
}
obj . xxMouseInputGrab = false ;
obj . xxKeyInputGrab = false ;
obj . xxMouseMove = function ( e ) { if ( obj . State == 3 ) obj . SendMouseMsg ( obj . KeyAction . NONE , e ) ; if ( e . preventDefault ) e . preventDefault ( ) ; if ( e . stopPropagation ) e . stopPropagation ( ) ; return false ; }
obj . xxMouseUp = function ( e ) { if ( obj . State == 3 ) obj . SendMouseMsg ( obj . KeyAction . UP , e ) ; if ( e . preventDefault ) e . preventDefault ( ) ; if ( e . stopPropagation ) e . stopPropagation ( ) ; return false ; }
obj . xxMouseDown = function ( e ) { if ( obj . State == 3 ) obj . SendMouseMsg ( obj . KeyAction . DOWN , e ) ; if ( e . preventDefault ) e . preventDefault ( ) ; if ( e . stopPropagation ) e . stopPropagation ( ) ; return false ; }
2019-01-24 05:07:02 +03:00
obj . xxMouseDblClick = function ( e ) { if ( obj . State == 3 ) obj . SendMouseMsg ( obj . KeyAction . DBLCLICK , e ) ; if ( e . preventDefault ) e . preventDefault ( ) ; if ( e . stopPropagation ) e . stopPropagation ( ) ; return false ; }
2017-08-28 19:27:45 +03:00
obj . xxDOMMouseScroll = function ( e ) { if ( obj . State == 3 ) { obj . SendMouseMsg ( obj . KeyAction . SCROLL , e ) ; return false ; } return true ; }
obj . xxMouseWheel = function ( e ) { if ( obj . State == 3 ) { obj . SendMouseMsg ( obj . KeyAction . SCROLL , e ) ; return false ; } return true ; }
2020-11-18 06:30:26 +03:00
obj . xxKeyUp = function ( e ) {
if ( ( e . key != 'Dead' ) && ( obj . State == 3 ) ) {
2022-03-01 07:14:56 +03:00
if ( ( typeof e . key == 'string' ) && ( e . key . length == 1 ) && ( e . ctrlKey != true ) && ( e . altKey != true ) && ( obj . remoteKeyMap == false ) ) {
2022-02-28 23:32:07 +03:00
obj . SendKeyUnicode ( obj . KeyAction . UP , e . key . charCodeAt ( 0 ) ) ;
} else {
obj . SendKeyMsg ( obj . KeyAction . UP , e ) ;
}
2020-11-18 06:30:26 +03:00
}
if ( e . preventDefault ) e . preventDefault ( ) ; if ( e . stopPropagation ) e . stopPropagation ( ) ; return false ;
}
obj . xxKeyDown = function ( e ) {
if ( ( e . key != 'Dead' ) && ( obj . State == 3 ) ) {
2022-03-01 07:14:56 +03:00
if ( ! ( ( typeof e . key == 'string' ) && ( e . key . length == 1 ) && ( e . ctrlKey != true ) && ( e . altKey != true ) && ( obj . remoteKeyMap == false ) ) ) {
2020-11-27 20:07:08 +03:00
obj . SendKeyMsg ( obj . KeyAction . DOWN , e ) ;
if ( e . preventDefault ) e . preventDefault ( ) ; if ( e . stopPropagation ) e . stopPropagation ( ) ; return false ;
}
2020-11-18 06:30:26 +03:00
}
}
obj . xxKeyPress = function ( e ) {
2020-11-27 20:07:08 +03:00
if ( ( e . key != 'Dead' ) && ( obj . State == 3 ) ) {
2022-03-01 07:14:56 +03:00
if ( ( typeof e . key == 'string' ) && ( e . key . length == 1 ) && ( e . ctrlKey != true ) && ( e . altKey != true ) && ( obj . remoteKeyMap == false ) ) {
2022-02-28 23:32:07 +03:00
obj . SendKeyUnicode ( obj . KeyAction . DOWN , e . key . charCodeAt ( 0 ) ) ;
} // else { obj.SendKeyMsg(obj.KeyAction.DOWN, e); }
2020-11-27 20:07:08 +03:00
}
2020-11-18 06:30:26 +03:00
if ( e . preventDefault ) e . preventDefault ( ) ; if ( e . stopPropagation ) e . stopPropagation ( ) ; return false ;
}
2017-08-28 19:27:45 +03:00
// Key handlers
2020-11-18 06:30:26 +03:00
obj . handleKeys = function ( e ) {
//console.log('keypress', e.code, e.key, e.keyCode, (e.key.length == 1) ? e.key.charCodeAt(0) : 0);
if ( obj . stopInput == true || desktop . State != 3 ) return false ;
return obj . xxKeyPress ( e ) ;
}
2018-01-15 08:01:06 +03:00
obj . handleKeyUp = function ( e ) {
2020-11-18 06:30:26 +03:00
//console.log('keyup', e.code, e.key, e.keyCode, (e.key.length == 1)?e.key.charCodeAt(0):0);
2018-01-15 08:01:06 +03:00
if ( obj . stopInput == true || desktop . State != 3 ) return false ;
if ( obj . firstUpKeys . length < 5 ) {
obj . firstUpKeys . push ( e . keyCode ) ;
if ( ( obj . firstUpKeys . length == 5 ) ) { var j = obj . firstUpKeys . join ( ',' ) ; if ( ( j == '16,17,91,91,16' ) || ( j == '16,17,18,91,92' ) ) { obj . stopInput = true ; } }
2019-07-06 01:25:03 +03:00
}
return obj . xxKeyUp ( e ) ;
}
obj . handleKeyDown = function ( e ) {
2020-11-18 06:30:26 +03:00
//console.log('keydown', e.code, e.key, e.keyCode, (e.key.length == 1) ? e.key.charCodeAt(0) : 0);
2019-07-06 01:25:03 +03:00
if ( obj . stopInput == true || desktop . State != 3 ) return false ;
return obj . xxKeyDown ( e ) ;
}
// Release the CTRL, ALT, SHIFT keys if they are pressed.
obj . handleReleaseKeys = function ( ) {
2020-02-07 05:04:55 +03:00
var p = JSON . parse ( JSON . stringify ( obj . pressedKeys ) ) ; // Clone the pressed array
for ( var i in p ) { obj . SendKeyMsgKC ( obj . KeyAction . UP , p [ i ] ) ; } // Release all keys
2018-01-15 08:01:06 +03:00
}
2017-08-28 19:27:45 +03:00
// Mouse handlers
2019-01-24 05:07:02 +03:00
obj . mousedblclick = function ( e ) { if ( obj . stopInput == true ) return false ; return obj . xxMouseDblClick ( e ) ; }
2018-01-15 08:01:06 +03:00
obj . mousedown = function ( e ) { if ( obj . stopInput == true ) return false ; return obj . xxMouseDown ( e ) ; }
obj . mouseup = function ( e ) { if ( obj . stopInput == true ) return false ; return obj . xxMouseUp ( e ) ; }
obj . mousemove = function ( e ) { if ( obj . stopInput == true ) return false ; return obj . xxMouseMove ( e ) ; }
obj . mousewheel = function ( e ) { if ( obj . stopInput == true ) return false ; return obj . xxMouseWheel ( e ) ; }
2017-08-28 19:27:45 +03:00
obj . xxMsTouchEvent = function ( evt ) {
if ( evt . originalEvent . pointerType == 4 ) return ; // If this is a mouse pointer, ignore this event. Touch & pen are ok.
if ( evt . preventDefault ) evt . preventDefault ( ) ;
if ( evt . stopPropagation ) evt . stopPropagation ( ) ;
if ( evt . type == 'MSPointerDown' || evt . type == 'MSPointerMove' || evt . type == 'MSPointerUp' ) {
var flags = 0 ;
var id = evt . originalEvent . pointerId % 256 ;
var X = evt . offsetX * ( Canvas . canvas . width / obj . CanvasId . clientWidth ) ;
var Y = evt . offsetY * ( Canvas . canvas . height / obj . CanvasId . clientHeight ) ;
if ( evt . type == 'MSPointerDown' ) flags = 0x00010000 | 0x00000002 | 0x00000004 ; // POINTER_FLAG_DOWN
else if ( evt . type == 'MSPointerMove' ) {
//if (obj.TouchArray[id] && MuchTheSame(obj.TouchArray[id].x, X) && MuchTheSame(obj.TouchArray[id].y, Y)) return;
flags = 0x00020000 | 0x00000002 | 0x00000004 ; // POINTER_FLAG_UPDATE
}
else if ( evt . type == 'MSPointerUp' ) flags = 0x00040000 ; // POINTER_FLAG_UP
if ( ! obj . TouchArray [ id ] ) obj . TouchArray [ id ] = { x : X , y : Y } ;
obj . SendTouchMsg2 ( id , flags )
if ( evt . type == 'MSPointerUp' ) delete obj . TouchArray [ id ] ;
} else {
alert ( evt . type ) ;
}
return true ;
}
obj . xxTouchStart = function ( e ) {
if ( obj . State != 3 ) return ;
if ( e . preventDefault ) e . preventDefault ( ) ;
if ( obj . touchenabled == 0 || obj . touchenabled == 1 ) {
if ( e . originalEvent . touches . length > 1 ) return ;
var t = e . originalEvent . touches [ 0 ] ;
e . which = 1 ;
obj . LastX = e . pageX = t . pageX ;
obj . LastY = e . pageY = t . pageY ;
obj . SendMouseMsg ( KeyAction . DOWN , e ) ;
} else {
var Offsets = obj . GetPositionOfControl ( Canvas . canvas ) ;
for ( var i in e . originalEvent . changedTouches ) {
if ( ! e . originalEvent . changedTouches [ i ] . identifier ) continue ;
var id = e . originalEvent . changedTouches [ i ] . identifier % 256 ;
if ( ! obj . TouchArray [ id ] ) { obj . TouchArray [ id ] = { x : ( e . originalEvent . touches [ i ] . pageX - Offsets [ 0 ] ) * ( Canvas . canvas . width / obj . CanvasId . clientWidth ) , y : ( e . originalEvent . touches [ i ] . pageY - Offsets [ 1 ] ) * ( Canvas . canvas . height / obj . CanvasId . clientHeight ) , f : 1 } ; }
}
if ( Object . keys ( obj . TouchArray ) . length > 0 && touchtimer == null ) { obj . touchtimer = setInterval ( function ( ) { obj . SendTouchMsg2 ( 256 , 0 ) ; } , 50 ) ; }
}
}
obj . xxTouchMove = function ( e ) {
if ( obj . State != 3 ) return ;
if ( e . preventDefault ) e . preventDefault ( ) ;
if ( obj . touchenabled == 0 || obj . touchenabled == 1 ) {
if ( e . originalEvent . touches . length > 1 ) return ;
var t = e . originalEvent . touches [ 0 ] ;
e . which = 1 ;
obj . LastX = e . pageX = t . pageX ;
obj . LastY = e . pageY = t . pageY ;
obj . SendMouseMsg ( obj . KeyAction . NONE , e ) ;
} else {
var Offsets = obj . GetPositionOfControl ( Canvas . canvas ) ;
for ( var i in e . originalEvent . changedTouches ) {
if ( ! e . originalEvent . changedTouches [ i ] . identifier ) continue ;
var id = e . originalEvent . changedTouches [ i ] . identifier % 256 ;
if ( obj . TouchArray [ id ] ) {
obj . TouchArray [ id ] . x = ( e . originalEvent . touches [ i ] . pageX - Offsets [ 0 ] ) * ( obj . Canvas . canvas . width / obj . CanvasId . clientWidth ) ;
obj . TouchArray [ id ] . y = ( e . originalEvent . touches [ i ] . pageY - Offsets [ 1 ] ) * ( obj . Canvas . canvas . height / obj . CanvasId . clientHeight ) ;
}
}
}
}
obj . xxTouchEnd = function ( e ) {
if ( obj . State != 3 ) return ;
if ( e . preventDefault ) e . preventDefault ( ) ;
if ( obj . touchenabled == 0 || obj . touchenabled == 1 ) {
if ( e . originalEvent . touches . length > 1 ) return ;
e . which = 1 ;
e . pageX = LastX ;
e . pageY = LastY ;
obj . SendMouseMsg ( KeyAction . UP , e ) ;
} else {
for ( var i in e . originalEvent . changedTouches ) {
if ( ! e . originalEvent . changedTouches [ i ] . identifier ) continue ;
var id = e . originalEvent . changedTouches [ i ] . identifier % 256 ;
if ( obj . TouchArray [ id ] ) obj . TouchArray [ id ] . f = 2 ;
}
}
}
obj . GrabMouseInput = function ( ) {
if ( obj . xxMouseInputGrab == true ) return ;
var c = obj . CanvasId ;
c . onmousemove = obj . xxMouseMove ;
c . onmouseup = obj . xxMouseUp ;
c . onmousedown = obj . xxMouseDown ;
c . touchstart = obj . xxTouchStart ;
c . touchmove = obj . xxTouchMove ;
c . touchend = obj . xxTouchEnd ;
c . MSPointerDown = obj . xxMsTouchEvent ;
c . MSPointerMove = obj . xxMsTouchEvent ;
c . MSPointerUp = obj . xxMsTouchEvent ;
if ( navigator . userAgent . match ( /mozilla/i ) ) c . DOMMouseScroll = obj . xxDOMMouseScroll ; else c . onmousewheel = obj . xxMouseWheel ;
obj . xxMouseInputGrab = true ;
}
obj . UnGrabMouseInput = function ( ) {
if ( obj . xxMouseInputGrab == false ) return ;
var c = obj . CanvasId ;
c . onmousemove = null ;
c . onmouseup = null ;
c . onmousedown = null ;
c . touchstart = null ;
c . touchmove = null ;
c . touchend = null ;
c . MSPointerDown = null ;
c . MSPointerMove = null ;
c . MSPointerUp = null ;
if ( navigator . userAgent . match ( /mozilla/i ) ) c . DOMMouseScroll = null ; else c . onmousewheel = null ;
obj . xxMouseInputGrab = false ;
}
obj . GrabKeyInput = function ( ) {
if ( obj . xxKeyInputGrab == true ) return ;
document . onkeyup = obj . xxKeyUp ;
document . onkeydown = obj . xxKeyDown ;
2021-08-11 07:50:11 +03:00
document . onkeypress = obj . xxKeyPress ; c
2017-08-28 19:27:45 +03:00
obj . xxKeyInputGrab = true ;
}
obj . UnGrabKeyInput = function ( ) {
if ( obj . xxKeyInputGrab == false ) return ;
document . onkeyup = null ;
document . onkeydown = null ;
document . onkeypress = null ;
obj . xxKeyInputGrab = false ;
}
obj . GetPositionOfControl = function ( Control ) {
var Position = Array ( 2 ) ;
Position [ 0 ] = Position [ 1 ] = 0 ;
while ( Control ) { Position [ 0 ] += Control . offsetLeft ; Position [ 1 ] += Control . offsetTop ; Control = Control . offsetParent ; }
return Position ;
}
obj . crotX = function ( x , y ) {
if ( obj . rotation == 0 ) return x ;
if ( obj . rotation == 1 ) return y ;
if ( obj . rotation == 2 ) return obj . Canvas . canvas . width - x ;
if ( obj . rotation == 3 ) return obj . Canvas . canvas . height - y ;
}
obj . crotY = function ( x , y ) {
if ( obj . rotation == 0 ) return y ;
if ( obj . rotation == 1 ) return obj . Canvas . canvas . width - x ;
if ( obj . rotation == 2 ) return obj . Canvas . canvas . height - y ;
if ( obj . rotation == 3 ) return x ;
}
obj . rotX = function ( x , y ) {
if ( obj . rotation == 0 || obj . rotation == 1 ) return x ;
if ( obj . rotation == 2 ) return x - obj . Canvas . canvas . width ;
if ( obj . rotation == 3 ) return x - obj . Canvas . canvas . height ;
}
obj . rotY = function ( x , y ) {
if ( obj . rotation == 0 || obj . rotation == 3 ) return y ;
if ( obj . rotation == 1 ) return y - obj . Canvas . canvas . width ;
if ( obj . rotation == 2 ) return y - obj . Canvas . canvas . height ;
}
obj . tcanvas = null ;
obj . setRotation = function ( x ) {
while ( x < 0 ) { x += 4 ; }
var newrotation = x % 4 ;
if ( newrotation == obj . rotation ) return true ;
var rw = obj . Canvas . canvas . width ;
var rh = obj . Canvas . canvas . height ;
if ( obj . rotation == 1 || obj . rotation == 3 ) { rw = obj . Canvas . canvas . height ; rh = obj . Canvas . canvas . width ; }
// Copy the canvas, put it back in the correct direction
if ( obj . tcanvas == null ) obj . tcanvas = document . createElement ( 'canvas' ) ;
var tcanvasctx = obj . tcanvas . getContext ( '2d' ) ;
tcanvasctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
tcanvasctx . canvas . width = rw ;
tcanvasctx . canvas . height = rh ;
tcanvasctx . rotate ( ( obj . rotation * - 90 ) * Math . PI / 180 ) ;
if ( obj . rotation == 0 ) tcanvasctx . drawImage ( obj . Canvas . canvas , 0 , 0 ) ;
if ( obj . rotation == 1 ) tcanvasctx . drawImage ( obj . Canvas . canvas , - obj . Canvas . canvas . width , 0 ) ;
if ( obj . rotation == 2 ) tcanvasctx . drawImage ( obj . Canvas . canvas , - obj . Canvas . canvas . width , - obj . Canvas . canvas . height ) ;
if ( obj . rotation == 3 ) tcanvasctx . drawImage ( obj . Canvas . canvas , 0 , - obj . Canvas . canvas . height ) ;
// Change the size and orientation and copy the canvas back into the rotation
if ( obj . rotation == 0 || obj . rotation == 2 ) { obj . Canvas . canvas . height = rw ; obj . Canvas . canvas . width = rh ; }
if ( obj . rotation == 1 || obj . rotation == 3 ) { obj . Canvas . canvas . height = rh ; obj . Canvas . canvas . width = rw ; }
obj . Canvas . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
obj . Canvas . rotate ( ( newrotation * 90 ) * Math . PI / 180 ) ;
obj . rotation = newrotation ;
obj . Canvas . drawImage ( obj . tcanvas , obj . rotX ( 0 , 0 ) , obj . rotY ( 0 , 0 ) ) ;
obj . ScreenWidth = obj . Canvas . canvas . width ;
obj . ScreenHeight = obj . Canvas . canvas . height ;
2021-03-19 07:09:56 +03:00
if ( obj . onScreenSizeChange != null ) { console . log ( 's4' , obj . ScreenWidth , obj . ScreenHeight ) ; obj . onScreenSizeChange ( obj , obj . ScreenWidth , obj . ScreenHeight , obj . CanvasId ) ; }
2017-08-28 19:27:45 +03:00
return true ;
}
2020-05-02 23:49:56 +03:00
obj . StartRecording = function ( ) {
2020-05-03 03:59:12 +03:00
if ( obj . recordedData != null ) return ;
// Take a screen shot and save it to file
obj . CanvasId [ 'toBlob' ] ( function ( blob ) {
var fileReader = new FileReader ( ) ;
fileReader . readAsArrayBuffer ( blob ) ;
fileReader . onload = function ( event ) {
// This is an ArrayBuffer, convert it to a string array
var binary = '' , bytes = new Uint8Array ( fileReader . result ) , length = bytes . byteLength ;
for ( var i = 0 ; i < length ; i ++ ) { binary += String . fromCharCode ( bytes [ i ] ) ; }
obj . recordedData = [ ] ;
obj . recordedStart = Date . now ( ) ;
obj . recordedSize = 0 ;
obj . recordedData . push ( recordingEntry ( 1 , 0 , JSON . stringify ( { magic : 'MeshCentralRelaySession' , ver : 1 , time : new Date ( ) . toLocaleString ( ) , protocol : 2 } ) ) ) ; // Metadata (nodeid: obj.nodeid)
obj . recordedData . push ( recordingEntry ( 2 , 1 , obj . shortToStr ( 7 ) + obj . shortToStr ( 8 ) + obj . shortToStr ( obj . ScreenWidth ) + obj . shortToStr ( obj . ScreenHeight ) ) ) ; // Screen width and height
// Save a screenshot
2020-06-18 22:47:34 +03:00
var cmdlen = ( 8 + binary . length ) ;
2020-05-03 03:59:12 +03:00
if ( cmdlen > 65000 ) {
// Jumbo Packet
obj . recordedData . push ( recordingEntry ( 2 , 1 , obj . shortToStr ( 27 ) + obj . shortToStr ( 8 ) + obj . intToStr ( cmdlen ) + obj . shortToStr ( 3 ) + obj . shortToStr ( 0 ) + obj . shortToStr ( 0 ) + obj . shortToStr ( 0 ) + binary ) ) ;
} else {
// Normal packet
obj . recordedData . push ( recordingEntry ( 2 , 1 , obj . shortToStr ( 3 ) + obj . shortToStr ( cmdlen ) + obj . shortToStr ( 0 ) + obj . shortToStr ( 0 ) + binary ) ) ;
}
} ;
} ) ;
2020-05-02 23:49:56 +03:00
}
obj . StopRecording = function ( ) {
2020-05-03 03:59:12 +03:00
if ( obj . recordedData == null ) return ;
2020-05-02 23:49:56 +03:00
var r = obj . recordedData ;
2020-05-03 03:59:12 +03:00
r . push ( recordingEntry ( 3 , 0 , 'MeshCentralMCREC' ) ) ;
2020-05-02 23:49:56 +03:00
delete obj . recordedData ;
delete obj . recordedStart ;
2020-05-03 03:59:12 +03:00
delete obj . recordedSize ;
2020-05-02 23:49:56 +03:00
return r ;
}
2020-05-03 03:59:12 +03:00
function recordingEntry ( type , flags , data ) {
// Header: Type (2) + Flags (2) + Size(4) + Time(8)
// Type (1 = Header, 2 = Network Data), Flags (1 = Binary, 2 = User), Size (4 bytes), Time (8 bytes)
var now = Date . now ( ) ;
if ( typeof data == 'number' ) {
obj . recordedSize += data ;
return obj . shortToStr ( type ) + obj . shortToStr ( flags ) + obj . intToStr ( data ) + obj . intToStr ( now >> 32 ) + obj . intToStr ( now & 32 ) ;
} else {
obj . recordedSize += data . length ;
return obj . shortToStr ( type ) + obj . shortToStr ( flags ) + obj . intToStr ( data . length ) + obj . intToStr ( now >> 32 ) + obj . intToStr ( now & 32 ) + data ;
}
}
2017-08-28 19:27:45 +03:00
// Private method
obj . MuchTheSame = function ( a , b ) { return ( Math . abs ( a - b ) < 4 ) ; }
obj . Debug = function ( msg ) { console . log ( msg ) ; }
2020-09-16 03:56:10 +03:00
obj . getIEVersion = function ( ) { var r = - 1 ; if ( navigator . appName == 'Microsoft Internet Explorer' ) { var ua = navigator . userAgent ; var re = new RegExp ( "MSIE ([0-9]{1,}[.0-9]{0,})" ) ; if ( re . exec ( ua ) != null ) r = parseFloat ( RegExp . $1 ) ; } return r ; }
2017-08-28 19:27:45 +03:00
obj . haltEvent = function ( e ) { if ( e . preventDefault ) e . preventDefault ( ) ; if ( e . stopPropagation ) e . stopPropagation ( ) ; return false ; }
return obj ;
}