2020-11-19 00:32:46 +08:00
import ' package:ffi/ffi.dart ' ;
2020-11-28 13:22:19 +08:00
import ' package:flutter/services.dart ' ;
2020-11-25 14:41:57 +08:00
import ' package:flutter/gestures.dart ' ;
2020-11-19 00:32:46 +08:00
import ' package:path_provider/path_provider.dart ' ;
2020-11-26 20:28:37 +08:00
import ' package:device_info/device_info.dart ' ;
2020-11-19 00:32:46 +08:00
import ' dart:io ' ;
2020-11-24 12:11:55 +08:00
import ' dart:math ' ;
2020-11-19 00:32:46 +08:00
import ' dart:ffi ' ;
import ' dart:convert ' ;
import ' dart:typed_data ' ;
import ' dart:ui ' as ui ;
import ' package:flutter/material.dart ' ;
2020-11-23 23:18:42 +08:00
import ' package:tuple/tuple.dart ' ;
2020-11-19 00:32:46 +08:00
import ' dart:async ' ;
import ' common.dart ' ;
class RgbaFrame extends Struct {
@ Uint32 ( )
int len ;
Pointer < Uint8 > data ;
}
typedef F1 = void Function ( Pointer < Utf8 > ) ;
typedef F2 = Pointer < Utf8 > Function ( Pointer < Utf8 > , Pointer < Utf8 > ) ;
typedef F3 = void Function ( Pointer < Utf8 > , Pointer < Utf8 > ) ;
typedef F4 = void Function ( Pointer < RgbaFrame > ) ;
typedef F5 = Pointer < RgbaFrame > Function ( ) ;
class FfiModel with ChangeNotifier {
2020-11-22 21:08:19 +08:00
PeerInfo _pi ;
Display _display ;
2020-11-28 17:42:29 +08:00
var _decoding = false ;
2020-11-22 21:08:19 +08:00
bool _waitForImage ;
2020-11-24 22:03:04 +08:00
bool _initialized = false ;
2020-11-22 21:08:19 +08:00
final _permissions = Map < String , bool > ( ) ;
2020-11-29 00:13:55 +08:00
bool _secure ;
bool _direct ;
2020-11-22 21:08:19 +08:00
get permissions = > _permissions ;
2020-11-24 22:03:04 +08:00
get initialized = > _initialized ;
2020-11-29 00:13:55 +08:00
get secure = > _secure ;
get direct = > _direct ;
2020-11-25 23:52:58 +08:00
get pi = > _pi ;
2020-11-19 00:32:46 +08:00
FfiModel ( ) {
2020-11-22 21:08:19 +08:00
clear ( ) ;
( ) async {
await FFI . init ( ) ;
2020-11-24 22:03:04 +08:00
_initialized = true ;
2020-11-22 21:08:19 +08:00
notifyListeners ( ) ;
} ( ) ;
2020-11-19 00:32:46 +08:00
}
2020-11-22 21:08:19 +08:00
void updatePermission ( Map < String , dynamic > evt ) {
evt . forEach ( ( k , v ) {
if ( k = = ' name ' ) return ;
_permissions [ k ] = v = = ' true ' ;
} ) ;
2020-11-23 17:45:38 +08:00
print ( ' $ _permissions ' ) ;
2020-11-19 00:32:46 +08:00
}
2020-11-24 23:36:46 +08:00
bool keyboard ( ) = > _permissions [ ' keyboard ' ] ! = false ;
2020-11-23 23:18:42 +08:00
2020-11-19 00:32:46 +08:00
void clear ( ) {
2020-11-22 21:08:19 +08:00
_pi = PeerInfo ( ) ;
_display = Display ( ) ;
_waitForImage = false ;
2020-11-29 00:13:55 +08:00
_secure = null ;
_direct = null ;
2020-11-28 13:22:19 +08:00
clearPermissions ( ) ;
}
2020-11-29 00:13:55 +08:00
void setConnectionType ( bool secure , bool direct ) {
_secure = secure ;
_direct = direct ;
}
Image getConnectionImage ( ) {
String icon ;
if ( secure = = true & & direct = = true ) {
icon = ' secure ' ;
} else if ( secure = = false & & direct = = true ) {
icon = ' insecure ' ;
} else if ( secure = = false & & direct = = false ) {
icon = ' insecure_relay ' ;
} else if ( secure = = true & & direct = = false ) {
icon = ' secure_relay ' ;
}
return icon = = null
? null
: Image . asset ( ' assets/ $ icon .png ' , width: 48 , height: 48 ) ;
}
2020-11-28 13:22:19 +08:00
void clearPermissions ( ) {
2020-11-22 21:08:19 +08:00
_permissions . clear ( ) ;
2020-11-19 00:32:46 +08:00
}
2020-11-27 10:52:09 +08:00
void update (
2020-11-19 21:59:49 +08:00
String id ,
BuildContext context ,
2020-11-29 00:13:55 +08:00
void Function (
Map < String , dynamic > evt ,
String id ,
)
2020-11-27 10:52:09 +08:00
handleMsgbox ) {
2020-11-23 23:52:30 +08:00
var pos ;
2020-11-19 18:22:06 +08:00
for ( ; ; ) {
var evt = FFI . popEvent ( ) ;
if ( evt = = null ) break ;
2020-11-19 00:32:46 +08:00
var name = evt [ ' name ' ] ;
if ( name = = ' msgbox ' ) {
2020-11-29 00:13:55 +08:00
handleMsgbox ( evt , id ) ;
2020-11-19 00:32:46 +08:00
} else if ( name = = ' peer_info ' ) {
2020-11-26 21:41:25 +08:00
handlePeerInfo ( evt , context ) ;
2020-11-29 00:13:55 +08:00
} else if ( name = = ' connection_ready ' ) {
FFI . ffiModel . setConnectionType (
evt [ ' secure ' ] = = ' true ' , evt [ ' direct ' ] = = ' true ' ) ;
2020-11-19 00:32:46 +08:00
} else if ( name = = ' switch_display ' ) {
handleSwitchDisplay ( evt ) ;
} else if ( name = = ' cursor_data ' ) {
FFI . cursorModel . updateCursorData ( evt ) ;
} else if ( name = = ' cursor_id ' ) {
FFI . cursorModel . updateCursorId ( evt ) ;
} else if ( name = = ' cursor_position ' ) {
2020-11-23 23:52:30 +08:00
pos = evt ;
2020-11-28 13:22:19 +08:00
} else if ( name = = ' clipboard ' ) {
Clipboard . setData ( ClipboardData ( text: evt [ ' content ' ] ) ) ;
2020-11-22 21:08:19 +08:00
} else if ( name = = ' permission ' ) {
FFI . ffiModel . updatePermission ( evt ) ;
2020-11-19 00:32:46 +08:00
}
}
2020-11-23 23:52:30 +08:00
if ( pos ! = null ) FFI . cursorModel . updateCursorPosition ( pos ) ;
2020-11-19 00:32:46 +08:00
if ( ! _decoding ) {
var rgba = FFI . getRgba ( ) ;
if ( rgba ! = null ) {
2020-11-19 00:53:10 +08:00
if ( _waitForImage ) {
_waitForImage = false ;
dismissLoading ( ) ;
}
2020-11-19 00:32:46 +08:00
_decoding = true ;
2020-11-28 17:42:29 +08:00
final pid = FFI . id ;
2020-11-19 00:32:46 +08:00
ui . decodeImageFromPixels (
rgba , _display . width , _display . height , ui . PixelFormat . bgra8888 ,
( image ) {
FFI . clearRgbaFrame ( ) ;
_decoding = false ;
2020-11-28 17:42:29 +08:00
if ( FFI . id ! = pid ) return ;
2020-11-19 00:32:46 +08:00
try {
// my throw exception, because the listener maybe already dispose
FFI . imageModel . update ( image ) ;
2020-11-26 20:28:37 +08:00
} catch ( e ) {
print ( ' update image: $ e ' ) ;
}
2020-11-19 00:32:46 +08:00
} ) ;
}
2020-11-27 10:52:09 +08:00
}
2020-11-19 00:32:46 +08:00
}
void handleSwitchDisplay ( Map < String , dynamic > evt ) {
_pi . currentDisplay = int . parse ( evt [ ' display ' ] ) ;
_display . x = double . parse ( evt [ ' x ' ] ) ;
_display . y = double . parse ( evt [ ' y ' ] ) ;
_display . width = int . parse ( evt [ ' width ' ] ) ;
_display . height = int . parse ( evt [ ' height ' ] ) ;
FFI . cursorModel . updateDisplayOrigin ( _display . x , _display . y ) ;
2020-11-25 23:52:58 +08:00
notifyListeners ( ) ;
2020-11-19 00:32:46 +08:00
}
2020-11-26 21:41:25 +08:00
void handlePeerInfo ( Map < String , dynamic > evt , BuildContext context ) {
2020-11-19 00:32:46 +08:00
dismissLoading ( ) ;
2020-11-27 17:34:09 +08:00
_pi . version = evt [ ' version ' ] ;
2020-11-19 00:32:46 +08:00
_pi . username = evt [ ' username ' ] ;
_pi . hostname = evt [ ' hostname ' ] ;
_pi . platform = evt [ ' platform ' ] ;
_pi . sasEnabled = evt [ ' sas_enabled ' ] = = " true " ;
_pi . currentDisplay = int . parse ( evt [ ' current_display ' ] ) ;
List < dynamic > displays = json . decode ( evt [ ' displays ' ] ) ;
_pi . displays = List < Display > ( ) ;
for ( int i = 0 ; i < displays . length ; + + i ) {
Map < String , dynamic > d0 = displays [ i ] ;
var d = Display ( ) ;
d . x = d0 [ ' x ' ] . toDouble ( ) ;
d . y = d0 [ ' y ' ] . toDouble ( ) ;
d . width = d0 [ ' width ' ] ;
d . height = d0 [ ' height ' ] ;
_pi . displays . add ( d ) ;
}
if ( _pi . currentDisplay < _pi . displays . length ) {
_display = _pi . displays [ _pi . currentDisplay ] ;
FFI . cursorModel . updateDisplayOrigin ( _display . x , _display . y ) ;
}
2020-11-23 01:16:17 +08:00
if ( displays . length > 0 ) {
2020-11-26 21:41:25 +08:00
showLoading ( ' Waiting for image... ' , context ) ;
2020-11-19 00:53:10 +08:00
_waitForImage = true ;
}
2020-11-19 00:32:46 +08:00
}
}
class ImageModel with ChangeNotifier {
ui . Image _image ;
ui . Image get image = > _image ;
void update ( ui . Image image ) {
2020-11-24 22:03:04 +08:00
if ( _image = = null & & image ! = null ) {
final size = MediaQueryData . fromWindow ( ui . window ) . size ;
final xscale = size . width / image . width ;
final yscale = size . height / image . height ;
FFI . canvasModel . scale = max ( xscale , yscale ) ;
}
2020-11-19 00:32:46 +08:00
_image = image ;
2020-11-19 18:22:06 +08:00
if ( image ! = null ) notifyListeners ( ) ;
2020-11-19 00:32:46 +08:00
}
2020-11-24 12:11:55 +08:00
double get maxScale {
if ( _image = = null ) return 1.0 ;
final size = MediaQueryData . fromWindow ( ui . window ) . size ;
final xscale = size . width / _image . width ;
final yscale = size . height / _image . height ;
return max ( 1.0 , max ( xscale , yscale ) ) ;
}
double get minScale {
if ( _image = = null ) return 1.0 ;
final size = MediaQueryData . fromWindow ( ui . window ) . size ;
final xscale = size . width / _image . width ;
final yscale = size . height / _image . height ;
return min ( xscale , yscale ) ;
}
2020-11-19 00:32:46 +08:00
}
2020-11-23 23:18:42 +08:00
class CanvasModel with ChangeNotifier {
double _x ;
double _y ;
double _scale ;
CanvasModel ( ) {
clear ( ) ;
}
double get x = > _x ;
double get y = > _y ;
double get scale = > _scale ;
2020-11-24 12:11:55 +08:00
set scale ( v ) {
_scale = v ;
notifyListeners ( ) ;
}
2020-11-24 22:03:04 +08:00
void panX ( double dx ) {
_x + = dx ;
notifyListeners ( ) ;
2020-11-23 23:18:42 +08:00
}
2020-11-27 17:59:42 +08:00
void resetOffset ( ) {
_x = 0 ;
_y = 0 ;
notifyListeners ( ) ;
}
2020-11-24 22:03:04 +08:00
void panY ( double dy ) {
2020-11-23 23:18:42 +08:00
_y + = dy ;
notifyListeners ( ) ;
}
void updateScale ( double v ) {
2020-11-27 10:52:09 +08:00
if ( FFI . imageModel . image = = null ) return ;
2020-11-25 14:41:57 +08:00
final offset = FFI . cursorModel . offset ;
var r = FFI . cursorModel . getVisibleRect ( ) ;
final px0 = ( offset . dx - r . left ) * _scale ;
final py0 = ( offset . dy - r . top ) * _scale ;
2020-11-23 23:18:42 +08:00
_scale * = v ;
2020-11-24 12:11:55 +08:00
final maxs = FFI . imageModel . maxScale ;
final mins = FFI . imageModel . minScale ;
if ( _scale > maxs ) _scale = maxs ;
if ( _scale < mins ) _scale = mins ;
2020-11-25 14:41:57 +08:00
r = FFI . cursorModel . getVisibleRect ( ) ;
final px1 = ( offset . dx - r . left ) * _scale ;
final py1 = ( offset . dy - r . top ) * _scale ;
_x - = px1 - px0 ;
_y - = py1 - py0 ;
2020-11-23 23:18:42 +08:00
notifyListeners ( ) ;
}
void clear ( ) {
_x = 0 ;
_y = 0 ;
_scale = 1.0 ;
}
}
2020-11-19 00:32:46 +08:00
class CursorModel with ChangeNotifier {
ui . Image _image ;
2020-11-23 23:18:42 +08:00
final _images = Map < int , Tuple3 < ui . Image , double , double > > ( ) ;
2020-11-22 18:29:04 +08:00
double _x = - 10000 ;
double _y = - 10000 ;
2020-11-19 00:32:46 +08:00
double _hotx = 0 ;
double _hoty = 0 ;
double _displayOriginX = 0 ;
double _displayOriginY = 0 ;
ui . Image get image = > _image ;
2020-11-23 23:18:42 +08:00
double get x = > _x - _displayOriginX ;
double get y = > _y - _displayOriginY ;
2020-11-25 14:41:57 +08:00
Offset get offset = > Offset ( _x , _y ) ;
2020-11-23 23:18:42 +08:00
double get hotx = > _hotx ;
double get hoty = > _hoty ;
2020-11-19 00:32:46 +08:00
2020-11-25 14:41:57 +08:00
// remote physical display coordinate
2020-11-24 22:03:04 +08:00
Rect getVisibleRect ( ) {
final size = MediaQueryData . fromWindow ( ui . window ) . size ;
final xoffset = FFI . canvasModel . x ;
final yoffset = FFI . canvasModel . y ;
final scale = FFI . canvasModel . scale ;
final x0 = _displayOriginX - xoffset / scale ;
final y0 = _displayOriginY - yoffset / scale ;
return Rect . fromLTWH ( x0 , y0 , size . width / scale , size . height / scale ) ;
}
2020-11-25 11:20:40 +08:00
double adjustForKeyboard ( ) {
var keyboardHeight = MediaQueryData . fromWindow ( ui . window ) . viewInsets . bottom ;
if ( keyboardHeight < 100 ) return 0 ;
2020-11-25 14:41:57 +08:00
final s = FFI . canvasModel . scale ;
final thresh = 120 ;
var h = ( _y - getVisibleRect ( ) . top ) * s ; // local physical display height
2020-11-27 12:05:23 +08:00
return h - thresh ;
2020-11-25 11:20:40 +08:00
}
2020-11-24 22:03:04 +08:00
void updatePan ( double dx , double dy ) {
2020-11-27 10:52:09 +08:00
if ( FFI . imageModel . image = = null ) return ;
2020-11-25 00:13:23 +08:00
final scale = FFI . canvasModel . scale ;
dx / = scale ;
dy / = scale ;
2020-11-24 22:03:04 +08:00
final r = getVisibleRect ( ) ;
var cx = r . center . dx ;
var cy = r . center . dy ;
var tryMoveCanvasX = false ;
if ( dx > 0 ) {
final maxCanvasCanMove =
_displayOriginX + FFI . imageModel . image . width - r . right ;
tryMoveCanvasX = _x + dx > cx & & maxCanvasCanMove > 0 ;
if ( tryMoveCanvasX ) {
dx = min ( dx , maxCanvasCanMove ) ;
} else {
final maxCursorCanMove = r . right - _x ;
dx = min ( dx , maxCursorCanMove ) ;
}
} else if ( dx < 0 ) {
final maxCanvasCanMove = _displayOriginX - r . left ;
tryMoveCanvasX = _x + dx < cx & & maxCanvasCanMove < 0 ;
if ( tryMoveCanvasX ) {
dx = max ( dx , maxCanvasCanMove ) ;
} else {
final maxCursorCanMove = r . left - _x ;
dx = max ( dx , maxCursorCanMove ) ;
}
}
var tryMoveCanvasY = false ;
if ( dy > 0 ) {
final mayCanvasCanMove =
2020-11-24 23:36:46 +08:00
_displayOriginY + FFI . imageModel . image . height - r . bottom ;
2020-11-24 22:03:04 +08:00
tryMoveCanvasY = _y + dy > cy & & mayCanvasCanMove > 0 ;
if ( tryMoveCanvasY ) {
dy = min ( dy , mayCanvasCanMove ) ;
} else {
2020-11-24 23:36:46 +08:00
final mayCursorCanMove = r . bottom - _y ;
2020-11-24 22:03:04 +08:00
dy = min ( dy , mayCursorCanMove ) ;
}
} else if ( dy < 0 ) {
2020-11-24 23:36:46 +08:00
final mayCanvasCanMove = _displayOriginY - r . top ;
2020-11-24 22:03:04 +08:00
tryMoveCanvasY = _y + dy < cy & & mayCanvasCanMove < 0 ;
if ( tryMoveCanvasY ) {
dy = max ( dy , mayCanvasCanMove ) ;
} else {
2020-11-24 23:36:46 +08:00
final mayCursorCanMove = r . top - _y ;
2020-11-24 22:03:04 +08:00
dy = max ( dy , mayCursorCanMove ) ;
}
}
if ( dx = = 0 & & dy = = 0 ) return ;
_x + = dx ;
_y + = dy ;
if ( tryMoveCanvasX & & dx ! = 0 ) {
2020-11-24 23:36:46 +08:00
FFI . canvasModel . panX ( - dx ) ;
2020-11-24 22:03:04 +08:00
}
if ( tryMoveCanvasY & & dy ! = 0 ) {
2020-11-24 23:36:46 +08:00
FFI . canvasModel . panY ( - dy ) ;
2020-11-24 22:03:04 +08:00
}
2020-11-25 00:13:23 +08:00
FFI . moveMouse ( _x , _y ) ;
2020-11-24 22:03:04 +08:00
notifyListeners ( ) ;
}
2020-11-19 00:32:46 +08:00
void updateCursorData ( Map < String , dynamic > evt ) {
var id = int . parse ( evt [ ' id ' ] ) ;
_hotx = double . parse ( evt [ ' hotx ' ] ) ;
_hoty = double . parse ( evt [ ' hoty ' ] ) ;
var width = int . parse ( evt [ ' width ' ] ) ;
var height = int . parse ( evt [ ' height ' ] ) ;
List < dynamic > colors = json . decode ( evt [ ' colors ' ] ) ;
final rgba = Uint8List . fromList ( colors . map ( ( s ) = > s as int ) . toList ( ) ) ;
2020-11-28 17:42:29 +08:00
var pid = FFI . id ;
2020-11-19 00:32:46 +08:00
ui . decodeImageFromPixels ( rgba , width , height , ui . PixelFormat . rgba8888 ,
( image ) {
2020-11-28 17:42:29 +08:00
if ( FFI . id ! = pid ) return ;
2020-11-19 00:32:46 +08:00
_image = image ;
2020-11-23 23:18:42 +08:00
_images [ id ] = Tuple3 ( image , _hotx , _hoty ) ;
2020-11-19 00:32:46 +08:00
try {
// my throw exception, because the listener maybe already dispose
notifyListeners ( ) ;
2020-11-26 20:28:37 +08:00
} catch ( e ) {
print ( ' notify cursor: $ e ' ) ;
}
2020-11-19 00:32:46 +08:00
} ) ;
}
void updateCursorId ( Map < String , dynamic > evt ) {
final tmp = _images [ int . parse ( evt [ ' id ' ] ) ] ;
if ( tmp ! = null ) {
2020-11-23 23:18:42 +08:00
_image = tmp . item1 ;
_hotx = tmp . item2 ;
_hoty = tmp . item3 ;
2020-11-19 00:32:46 +08:00
notifyListeners ( ) ;
}
}
void updateCursorPosition ( Map < String , dynamic > evt ) {
_x = double . parse ( evt [ ' x ' ] ) ;
_y = double . parse ( evt [ ' y ' ] ) ;
notifyListeners ( ) ;
}
void updateDisplayOrigin ( double x , double y ) {
_displayOriginX = x ;
_displayOriginY = y ;
2020-11-24 23:36:46 +08:00
_x = x ;
_y = y ;
FFI . moveMouse ( x , y ) ;
2020-11-27 22:50:24 +08:00
FFI . canvasModel . resetOffset ( ) ;
2020-11-19 00:32:46 +08:00
notifyListeners ( ) ;
}
void clear ( ) {
2020-11-22 18:29:04 +08:00
_x = - 10000 ;
_x = - 10000 ;
2020-11-19 00:32:46 +08:00
_image = null ;
_images . clear ( ) ;
}
}
class FFI {
2020-11-28 17:42:29 +08:00
static String id = " " ;
2020-11-25 18:33:09 +08:00
static String _dir = ' ' ;
2020-11-19 00:32:46 +08:00
static F1 _freeCString ;
static F2 _getByName ;
static F3 _setByName ;
static F4 _freeRgba ;
static F5 _getRgba ;
static Pointer < RgbaFrame > _lastRgbaFrame ;
2020-11-25 16:28:46 +08:00
static var shift = false ;
static var ctrl = false ;
static var alt = false ;
static var command = false ;
2020-11-19 00:32:46 +08:00
static final imageModel = ImageModel ( ) ;
static final ffiModel = FfiModel ( ) ;
static final cursorModel = CursorModel ( ) ;
2020-11-23 23:18:42 +08:00
static final canvasModel = CanvasModel ( ) ;
2020-11-19 00:32:46 +08:00
static String getId ( ) {
return getByName ( ' remote_id ' ) ;
}
2020-11-25 17:02:27 +08:00
static void tap ( bool right ) {
sendMouse ( ' down ' , right ? ' right ' : ' left ' ) ;
sendMouse ( ' up ' , right ? ' right ' : ' left ' ) ;
}
static void scroll ( double y ) {
var y2 = y . round ( ) ;
if ( y2 = = 0 ) return ;
setByName ( ' send_mouse ' ,
json . encode ( modify ( { ' type ' : ' wheel ' , ' y ' : y2 . toString ( ) } ) ) ) ;
2020-11-25 16:28:46 +08:00
}
2020-11-28 13:22:19 +08:00
static void reconnect ( ) {
setByName ( ' reconnect ' ) ;
FFI . ffiModel . clearPermissions ( ) ;
}
2020-11-25 16:28:46 +08:00
static void resetModifiers ( ) {
shift = ctrl = alt = command = false ;
}
static Map < String , String > modify ( Map < String , String > evt ) {
if ( ctrl ) evt [ ' ctrl ' ] = ' true ' ;
if ( shift ) evt [ ' shift ' ] = ' true ' ;
if ( alt ) evt [ ' alt ' ] = ' true ' ;
if ( command ) evt [ ' command ' ] = ' true ' ;
return evt ;
2020-11-24 12:11:55 +08:00
}
static void sendMouse ( String type , String buttons ) {
2020-11-25 16:28:46 +08:00
if ( ! ffiModel . keyboard ( ) ) return ;
setByName (
' send_mouse ' , json . encode ( modify ( { ' type ' : type , ' buttons ' : buttons } ) ) ) ;
}
static void inputKey ( String name ) {
if ( ! ffiModel . keyboard ( ) ) return ;
setByName ( ' input_key ' , json . encode ( modify ( { ' name ' : name } ) ) ) ;
2020-11-24 12:11:55 +08:00
}
2020-11-24 23:36:46 +08:00
static void moveMouse ( double x , double y ) {
2020-11-25 16:28:46 +08:00
if ( ! ffiModel . keyboard ( ) ) return ;
2020-11-24 23:36:46 +08:00
var x2 = x . toInt ( ) ;
var y2 = y . toInt ( ) ;
2020-11-25 16:28:46 +08:00
setByName ( ' send_mouse ' , json . encode ( modify ( { ' x ' : ' $ x2 ' , ' y ' : ' $ y2 ' } ) ) ) ;
2020-11-24 23:36:46 +08:00
}
2020-11-19 00:32:46 +08:00
static List < Peer > peers ( ) {
try {
List < dynamic > peers = json . decode ( getByName ( ' peers ' ) ) ;
return peers
. map ( ( s ) = > s as List < dynamic > )
. map ( ( s ) = >
Peer . fromJson ( s [ 0 ] as String , s [ 1 ] as Map < String , dynamic > ) )
. toList ( ) ;
} catch ( e ) {
2020-11-26 20:28:37 +08:00
print ( ' peers(): $ e ' ) ;
2020-11-19 00:32:46 +08:00
}
return [ ] ;
}
static void connect ( String id ) {
setByName ( ' connect ' , id ) ;
2020-11-28 17:42:29 +08:00
FFI . id = id ;
2020-11-19 00:32:46 +08:00
}
static void clearRgbaFrame ( ) {
if ( _lastRgbaFrame ! = null & & _lastRgbaFrame ! = nullptr )
_freeRgba ( _lastRgbaFrame ) ;
}
static Uint8List getRgba ( ) {
_lastRgbaFrame = _getRgba ( ) ;
if ( _lastRgbaFrame = = null | | _lastRgbaFrame = = nullptr ) return null ;
final ref = _lastRgbaFrame . ref ;
return Uint8List . sublistView ( ref . data . asTypedList ( ref . len ) ) ;
}
static Map < String , dynamic > popEvent ( ) {
var s = getByName ( ' event ' ) ;
if ( s = = ' ' ) return null ;
try {
Map < String , dynamic > event = json . decode ( s ) ;
return event ;
} catch ( e ) {
2020-11-26 20:28:37 +08:00
print ( ' popEvent(): $ e ' ) ;
2020-11-19 00:32:46 +08:00
}
return null ;
}
static void login ( String password , bool remember ) {
setByName (
' login ' ,
json . encode ( {
' password ' : password ,
' remember ' : remember ? ' true ' : ' false ' ,
} ) ) ;
}
static void close ( ) {
2020-11-28 17:42:29 +08:00
id = " " ;
2020-11-19 00:32:46 +08:00
setByName ( ' close ' , ' ' ) ;
2020-11-25 16:28:46 +08:00
imageModel . update ( null ) ;
cursorModel . clear ( ) ;
ffiModel . clear ( ) ;
canvasModel . clear ( ) ;
resetModifiers ( ) ;
2020-11-19 00:32:46 +08:00
}
2020-11-20 16:37:48 +08:00
static void setByName ( String name , [ String value = ' ' ] ) {
2020-11-19 00:32:46 +08:00
_setByName ( Utf8 . toUtf8 ( name ) , Utf8 . toUtf8 ( value ) ) ;
}
2020-11-20 02:12:48 +08:00
static String getByName ( String name , [ String arg = ' ' ] ) {
2020-11-19 00:32:46 +08:00
var p = _getByName ( Utf8 . toUtf8 ( name ) , Utf8 . toUtf8 ( arg ) ) ;
assert ( p ! = nullptr & & p ! = null ) ;
var res = Utf8 . fromUtf8 ( p ) ;
_freeCString ( p ) ;
return res ;
}
static Future < Null > init ( ) async {
final dylib = Platform . isAndroid
? DynamicLibrary . open ( ' librustdesk.so ' )
: DynamicLibrary . process ( ) ;
_getByName = dylib . lookupFunction < F2 , F2 > ( ' get_by_name ' ) ;
_setByName =
dylib . lookupFunction < Void Function ( Pointer < Utf8 > , Pointer < Utf8 > ) , F3 > (
' set_by_name ' ) ;
_freeCString = dylib
. lookupFunction < Void Function ( Pointer < Utf8 > ) , F1 > ( ' rust_cstr_free ' ) ;
_freeRgba = dylib
. lookupFunction < Void Function ( Pointer < RgbaFrame > ) , F4 > ( ' free_rgba ' ) ;
_getRgba = dylib . lookupFunction < F5 , F5 > ( ' get_rgba ' ) ;
2020-11-25 18:33:09 +08:00
_dir = ( await getApplicationDocumentsDirectory ( ) ) . path ;
2020-11-26 20:28:37 +08:00
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin ( ) ;
AndroidDeviceInfo androidInfo = await deviceInfo . androidInfo ;
2020-11-26 21:41:25 +08:00
final name = ' ${ androidInfo . brand } - ${ androidInfo . model } ' ;
final id = androidInfo . id ;
setByName ( ' info1 ' , id ) ;
setByName ( ' info2 ' , name ) ;
2020-11-25 18:33:09 +08:00
setByName ( ' init ' , _dir ) ;
2020-11-19 00:32:46 +08:00
}
}
class Peer {
final String id ;
final String username ;
final String hostname ;
final String platform ;
Peer . fromJson ( String id , Map < String , dynamic > json )
: id = id ,
username = json [ ' username ' ] ,
hostname = json [ ' hostname ' ] ,
platform = json [ ' platform ' ] ;
}
class Display {
double x = 0 ;
double y = 0 ;
int width = 0 ;
int height = 0 ;
}
class PeerInfo {
2020-11-27 17:34:09 +08:00
String version ;
2020-11-19 00:32:46 +08:00
String username ;
String hostname ;
String platform ;
bool sasEnabled ;
int currentDisplay ;
List < Display > displays ;
}