2022-11-20 17:46:27 +03:00
import ' dart:async ' ;
2022-09-27 15:35:02 +03:00
import ' dart:convert ' ;
import ' dart:math ' ;
2022-11-02 17:23:23 +03:00
import ' dart:ui ' as ui ;
2022-09-27 15:35:02 +03:00
2022-09-15 09:49:59 +03:00
import ' package:flutter/gestures.dart ' ;
import ' package:flutter/services.dart ' ;
import ' package:flutter/widgets.dart ' ;
2022-09-27 15:35:02 +03:00
import ' package:get/get.dart ' ;
2022-09-15 09:49:59 +03:00
import ' ../../models/model.dart ' ;
import ' ../../models/platform_model.dart ' ;
2022-09-27 15:35:02 +03:00
import ' ../common.dart ' ;
2022-09-15 09:49:59 +03:00
import ' ../consts.dart ' ;
2022-11-01 12:01:43 +03:00
import ' ./state_model.dart ' ;
2022-09-15 09:49:59 +03:00
2022-09-27 15:35:02 +03:00
/// Mouse button enum.
enum MouseButtons { left , right , wheel }
2022-09-15 09:49:59 +03:00
2023-01-04 15:06:48 +03:00
const _kMouseEventDown = ' mousedown ' ;
const _kMouseEventUp = ' mouseup ' ;
const _kMouseEventMove = ' mousemove ' ;
2022-09-27 15:35:02 +03:00
extension ToString on MouseButtons {
String get value {
switch ( this ) {
case MouseButtons . left:
return ' left ' ;
case MouseButtons . right:
return ' right ' ;
case MouseButtons . wheel:
return ' wheel ' ;
}
2022-09-15 09:49:59 +03:00
}
2022-09-27 15:35:02 +03:00
}
class InputModel {
final WeakReference < FFI > parent ;
String keyboardMode = " legacy " ;
// keyboard
var shift = false ;
var ctrl = false ;
var alt = false ;
var command = false ;
2022-11-20 17:46:27 +03:00
// trackpad
2023-03-20 13:42:03 +03:00
final _trackpadSpeed = 0.02 ;
var _trackpadLastDelta = Offset . zero ;
2023-03-09 13:28:27 +03:00
var _trackpadScrollUnsent = Offset . zero ;
2023-03-20 13:42:03 +03:00
var _stopFling = true ;
2022-11-20 17:46:27 +03:00
Timer ? _flingTimer ;
2023-03-20 13:42:03 +03:00
final _flingBaseDelay = 10 ;
2022-11-20 17:46:27 +03:00
2022-09-27 15:35:02 +03:00
// mouse
2022-09-27 17:16:27 +03:00
final isPhysicalMouse = false . obs ;
2023-01-05 09:58:38 +03:00
int _lastButtons = 0 ;
2022-11-14 10:05:44 +03:00
Offset lastMousePos = Offset . zero ;
2022-09-27 15:35:02 +03:00
get id = > parent . target ? . id ? ? " " ;
InputModel ( this . parent ) ;
2022-09-15 09:49:59 +03:00
KeyEventResult handleRawKeyEvent ( FocusNode data , RawKeyEvent e ) {
2023-02-21 13:43:43 +03:00
if ( ! stateGlobal . grabKeyboard ) {
return KeyEventResult . handled ;
}
2023-02-09 17:14:24 +03:00
// * Currently mobile does not enable map mode
if ( isDesktop ) {
bind . sessionGetKeyboardMode ( id: id ) . then ( ( result ) {
keyboardMode = result . toString ( ) ;
} ) ;
}
2022-09-15 09:49:59 +03:00
2022-09-27 06:01:01 +03:00
final key = e . logicalKey ;
if ( e is RawKeyDownEvent ) {
2022-09-27 15:35:02 +03:00
if ( ! e . repeat ) {
if ( e . isAltPressed & & ! alt ) {
alt = true ;
} else if ( e . isControlPressed & & ! ctrl ) {
ctrl = true ;
} else if ( e . isShiftPressed & & ! shift ) {
shift = true ;
} else if ( e . isMetaPressed & & ! command ) {
command = true ;
2022-09-27 06:01:01 +03:00
}
}
}
if ( e is RawKeyUpEvent ) {
if ( key = = LogicalKeyboardKey . altLeft | |
key = = LogicalKeyboardKey . altRight ) {
2022-09-27 15:35:02 +03:00
alt = false ;
2022-09-27 06:01:01 +03:00
} else if ( key = = LogicalKeyboardKey . controlLeft | |
key = = LogicalKeyboardKey . controlRight ) {
2022-09-27 15:35:02 +03:00
ctrl = false ;
2022-09-27 06:01:01 +03:00
} else if ( key = = LogicalKeyboardKey . shiftRight | |
key = = LogicalKeyboardKey . shiftLeft ) {
2022-09-27 15:35:02 +03:00
shift = false ;
2022-09-27 06:01:01 +03:00
} else if ( key = = LogicalKeyboardKey . metaLeft | |
key = = LogicalKeyboardKey . metaRight | |
key = = LogicalKeyboardKey . superKey ) {
2022-09-27 15:35:02 +03:00
command = false ;
2022-09-27 06:01:01 +03:00
}
}
2023-02-09 17:14:24 +03:00
// * Currently mobile does not enable map mode
if ( isDesktop & & keyboardMode = = ' map ' ) {
2022-09-15 09:49:59 +03:00
mapKeyboardMode ( e ) ;
} else {
legacyKeyboardMode ( e ) ;
}
return KeyEventResult . handled ;
}
void mapKeyboardMode ( RawKeyEvent e ) {
int scanCode ;
int keyCode ;
bool down ;
if ( e . data is RawKeyEventDataMacOs ) {
RawKeyEventDataMacOs newData = e . data as RawKeyEventDataMacOs ;
scanCode = newData . keyCode ;
keyCode = newData . keyCode ;
} else if ( e . data is RawKeyEventDataWindows ) {
RawKeyEventDataWindows newData = e . data as RawKeyEventDataWindows ;
scanCode = newData . scanCode ;
keyCode = newData . keyCode ;
} else if ( e . data is RawKeyEventDataLinux ) {
RawKeyEventDataLinux newData = e . data as RawKeyEventDataLinux ;
2023-01-10 09:11:49 +03:00
// scanCode and keyCode of RawKeyEventDataLinux are incorrect.
// 1. scanCode means keycode
// 2. keyCode means keysym
scanCode = 0 ;
keyCode = newData . scanCode ;
2022-09-29 13:56:47 +03:00
} else if ( e . data is RawKeyEventDataAndroid ) {
2022-09-28 10:12:08 +03:00
RawKeyEventDataAndroid newData = e . data as RawKeyEventDataAndroid ;
scanCode = newData . scanCode + 8 ;
keyCode = newData . keyCode ;
2022-09-29 13:56:47 +03:00
} else {
2022-09-15 09:49:59 +03:00
scanCode = - 1 ;
keyCode = - 1 ;
}
if ( e is RawKeyDownEvent ) {
down = true ;
} else {
down = false ;
}
2023-01-10 09:11:49 +03:00
inputRawKey ( e . character ? ? ' ' , keyCode , scanCode , down ) ;
2022-09-27 15:35:02 +03:00
}
2022-09-15 09:49:59 +03:00
2022-09-27 15:35:02 +03:00
/// Send raw Key Event
void inputRawKey ( String name , int keyCode , int scanCode , bool down ) {
2023-01-10 09:11:49 +03:00
const capslock = 1 ;
const numlock = 2 ;
const scrolllock = 3 ;
int lockModes = 0 ;
if ( HardwareKeyboard . instance . lockModesEnabled
. contains ( KeyboardLockMode . capsLock ) ) {
lockModes | = ( 1 < < capslock ) ;
}
if ( HardwareKeyboard . instance . lockModesEnabled
. contains ( KeyboardLockMode . numLock ) ) {
lockModes | = ( 1 < < numlock ) ;
}
if ( HardwareKeyboard . instance . lockModesEnabled
. contains ( KeyboardLockMode . scrollLock ) ) {
lockModes | = ( 1 < < scrolllock ) ;
}
2022-09-27 15:35:02 +03:00
bind . sessionHandleFlutterKeyEvent (
id: id ,
name: name ,
keycode: keyCode ,
scancode: scanCode ,
2023-01-10 09:11:49 +03:00
lockModes: lockModes ,
2022-09-27 15:35:02 +03:00
downOrUp: down ) ;
2022-09-15 09:49:59 +03:00
}
void legacyKeyboardMode ( RawKeyEvent e ) {
if ( e is RawKeyDownEvent ) {
if ( e . repeat ) {
sendRawKey ( e , press: true ) ;
} else {
sendRawKey ( e , down: true ) ;
}
}
if ( e is RawKeyUpEvent ) {
sendRawKey ( e ) ;
}
}
void sendRawKey ( RawKeyEvent e , { bool ? down , bool ? press } ) {
// for maximum compatibility
2022-09-26 10:50:12 +03:00
final label = physicalKeyMap [ e . physicalKey . usbHidUsage ] ? ?
logicalKeyMap [ e . logicalKey . keyId ] ? ?
2022-09-15 09:49:59 +03:00
e . logicalKey . keyLabel ;
2022-09-27 15:35:02 +03:00
inputKey ( label , down: down , press: press ? ? false ) ;
2022-09-15 09:49:59 +03:00
}
2022-09-27 15:35:02 +03:00
/// Send key stroke event.
/// [down] indicates the key's state(down or up).
/// [press] indicates a click event(down and up).
void inputKey ( String name , { bool ? down , bool ? press } ) {
if ( ! parent . target ! . ffiModel . keyboard ( ) ) return ;
bind . sessionInputKey (
id: id ,
name: name ,
down: down ? ? false ,
press: press ? ? true ,
alt: alt ,
ctrl: ctrl ,
shift: shift ,
command: command ) ;
2022-09-15 09:49:59 +03:00
}
Map < String , dynamic > getEvent ( PointerEvent evt , String type ) {
final Map < String , dynamic > out = { } ;
out [ ' x ' ] = evt . position . dx ;
out [ ' y ' ] = evt . position . dy ;
2022-09-27 15:35:02 +03:00
if ( alt ) out [ ' alt ' ] = ' true ' ;
if ( shift ) out [ ' shift ' ] = ' true ' ;
if ( ctrl ) out [ ' ctrl ' ] = ' true ' ;
if ( command ) out [ ' command ' ] = ' true ' ;
2023-01-04 15:06:48 +03:00
// Check update event type and set buttons to be sent.
2023-01-05 09:58:38 +03:00
int buttons = _lastButtons ;
2023-01-04 15:06:48 +03:00
if ( type = = _kMouseEventMove ) {
2023-01-09 10:30:18 +03:00
// flutter may emit move event if one button is pressed and another button
2023-01-04 15:06:48 +03:00
// is pressing or releasing.
2023-01-05 09:58:38 +03:00
if ( evt . buttons ! = _lastButtons ) {
2023-01-04 15:06:48 +03:00
// For simplicity
// Just consider 3 - 1 ((Left + Right buttons) - Left button)
// Do not consider 2 - 1 (Right button - Left button)
// or 6 - 5 ((Right + Mid buttons) - (Left + Mid buttons))
// and so on
2023-01-05 09:58:38 +03:00
buttons = evt . buttons - _lastButtons ;
2023-01-04 15:06:48 +03:00
if ( buttons > 0 ) {
type = _kMouseEventDown ;
} else {
type = _kMouseEventUp ;
buttons = - buttons ;
}
}
2022-09-15 09:49:59 +03:00
} else {
2023-01-04 15:06:48 +03:00
if ( evt . buttons ! = 0 ) {
buttons = evt . buttons ;
}
2022-09-15 09:49:59 +03:00
}
2023-01-05 09:58:38 +03:00
_lastButtons = evt . buttons ;
2023-01-04 15:06:48 +03:00
out [ ' buttons ' ] = buttons ;
out [ ' type ' ] = type ;
2022-09-15 09:49:59 +03:00
return out ;
}
2022-09-27 15:35:02 +03:00
/// Send a mouse tap event(down and up).
void tap ( MouseButtons button ) {
sendMouse ( ' down ' , button ) ;
sendMouse ( ' up ' , button ) ;
}
/// Send scroll event with scroll distance [y].
void scroll ( int y ) {
bind . sessionSendMouse (
id: id ,
msg: json
. encode ( modify ( { ' id ' : id , ' type ' : ' wheel ' , ' y ' : y . toString ( ) } ) ) ) ;
}
/// Reset key modifiers to false, including [shift], [ctrl], [alt] and [command].
void resetModifiers ( ) {
shift = ctrl = alt = command = false ;
}
/// Modify the given modifier map [evt] based on current modifier key status.
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 ;
}
/// Send mouse press event.
void sendMouse ( String type , MouseButtons button ) {
if ( ! parent . target ! . ffiModel . keyboard ( ) ) return ;
bind . sessionSendMouse (
id: id ,
msg: json . encode ( modify ( { ' type ' : type , ' buttons ' : button . value } ) ) ) ;
}
void enterOrLeave ( bool enter ) {
// Fix status
if ( ! enter ) {
resetModifiers ( ) ;
}
2022-11-20 17:46:27 +03:00
_flingTimer ? . cancel ( ) ;
2022-09-27 15:35:02 +03:00
bind . sessionEnterOrLeave ( id: id , enter: enter ) ;
}
/// Send mouse movement event with distance in [x] and [y].
void moveMouse ( double x , double y ) {
if ( ! parent . target ! . ffiModel . keyboard ( ) ) return ;
var x2 = x . toInt ( ) ;
var y2 = y . toInt ( ) ;
bind . sessionSendMouse (
id: id , msg: json . encode ( modify ( { ' x ' : ' $ x2 ' , ' y ' : ' $ y2 ' } ) ) ) ;
}
2022-09-15 09:49:59 +03:00
void onPointHoverImage ( PointerHoverEvent e ) {
2023-03-20 13:42:03 +03:00
_stopFling = true ;
2022-09-15 09:49:59 +03:00
if ( e . kind ! = ui . PointerDeviceKind . mouse ) return ;
2022-09-27 17:16:27 +03:00
if ( ! isPhysicalMouse . value ) {
isPhysicalMouse . value = true ;
2022-09-15 09:49:59 +03:00
}
2022-09-27 17:16:27 +03:00
if ( isPhysicalMouse . value ) {
2023-01-04 15:06:48 +03:00
handleMouse ( getEvent ( e , _kMouseEventMove ) ) ;
2022-09-15 09:49:59 +03:00
}
}
2022-11-20 17:46:27 +03:00
int _signOrZero ( num x ) {
if ( x = = 0 ) {
return 0 ;
} else {
return x > 0 ? 1 : - 1 ;
}
}
2023-03-20 13:42:03 +03:00
void onPointerPanZoomStart ( PointerPanZoomStartEvent e ) {
_stopFling = true ;
}
2022-11-20 17:46:27 +03:00
// https://docs.flutter.dev/release/breaking-changes/trackpad-gestures
// TODO(support zoom in/out)
void onPointerPanZoomUpdate ( PointerPanZoomUpdateEvent e ) {
var delta = e . panDelta ;
2023-03-20 13:42:03 +03:00
_trackpadLastDelta = delta ;
2023-03-09 13:28:27 +03:00
_trackpadScrollUnsent + = ( delta * _trackpadSpeed ) ;
2023-03-20 13:42:03 +03:00
var x = _trackpadScrollUnsent . dx . truncate ( ) ;
var y = _trackpadScrollUnsent . dy . truncate ( ) ;
2023-03-09 13:28:27 +03:00
_trackpadScrollUnsent - = Offset ( _trackpadScrollUnsent . dx - x . toDouble ( ) ,
_trackpadScrollUnsent . dy - y . toDouble ( ) ) ;
2023-03-20 13:42:03 +03:00
if ( x = = 0 & & y = = 0 ) {
x = delta . dx > 1 ? 1 : ( delta . dx < - 1 ? - 1 : 0 ) ;
y = delta . dy > 1 ? 1 : ( delta . dy < - 1 ? - 1 : 0 ) ;
if ( x . abs ( ) > y . abs ( ) ) {
y = 0 ;
} else {
x = 0 ;
}
2023-03-09 13:28:27 +03:00
}
2023-03-20 13:42:03 +03:00
bind . sessionSendMouse (
id: id , msg: ' {"type": "trackpad", "x": " $ x ", "y": " $ y "} ' ) ;
2022-11-20 17:46:27 +03:00
}
// Simple simulation for fling.
void _scheduleFling ( var x , y , dx , dy ) {
if ( dx < = 0 & & dy < = 0 ) {
return ;
}
_flingTimer = Timer ( Duration ( milliseconds: 10 ) , ( ) {
bind . sessionSendMouse (
id: id , msg: ' {"type": "trackpad", "x": " $ x ", "y": " $ y "} ' ) ;
dx - - ;
dy - - ;
if ( dx = = 0 ) {
x = 0 ;
}
if ( dy = = 0 ) {
y = 0 ;
}
_scheduleFling ( x , y , dx , dy ) ;
} ) ;
}
2023-03-20 13:42:03 +03:00
void _scheduleFling2 ( double x , double y , int delay ) {
if ( ( x = = 0 & & y = = 0 ) | | _stopFling ) {
return ;
}
_flingTimer = Timer ( Duration ( milliseconds: delay ) , ( ) {
if ( _stopFling ) {
return ;
}
final d = 0.95 ;
x * = d ;
y * = d ;
final dx0 = x * _trackpadSpeed * 2 ;
final dy0 = y * _trackpadSpeed * 2 ;
// Try set delta (x,y) and delay.
var dx = dx0 . toInt ( ) ;
var dy = dy0 . toInt ( ) ;
var delay = _flingBaseDelay ;
// Try set min delta (x,y), and increase delay.
if ( dx = = 0 & & dy = = 0 ) {
final thr = 25 ;
var vx = thr ;
var vy = thr ;
if ( dx0 ! = 0 ) {
vx = 1.0 ~ / dx0 . abs ( ) ;
}
if ( dy0 ! = 0 ) {
vy = 1.0 ~ / dy0 . abs ( ) ;
}
if ( vx < vy & & vx < thr ) {
delay * = vx ;
dx = dx0 > 0 ? 1 : ( dx0 < 0 ? - 1 : 0 ) ;
} else if ( vy < thr ) {
delay * = vy ;
dy = dy0 > 0 ? 1 : ( dy0 < 0 ? - 1 : 0 ) ;
}
}
if ( dx = = 0 & & dy = = 0 ) {
return ;
}
bind . sessionSendMouse (
id: id , msg: ' {"type": "trackpad", "x": " $ dx ", "y": " $ dy "} ' ) ;
_scheduleFling2 ( x , y , delay ) ;
} ) ;
}
2022-11-20 17:46:27 +03:00
void onPointerPanZoomEnd ( PointerPanZoomEndEvent e ) {
2023-03-20 13:42:03 +03:00
_stopFling = false ;
2023-03-09 13:28:27 +03:00
_trackpadScrollUnsent = Offset . zero ;
2023-03-20 13:42:03 +03:00
_scheduleFling2 ( _trackpadLastDelta . dx , _trackpadLastDelta . dy , _flingBaseDelay ) ;
_trackpadLastDelta = Offset . zero ;
2022-11-20 17:46:27 +03:00
}
2023-02-01 11:29:13 +03:00
2022-09-15 09:49:59 +03:00
void onPointDownImage ( PointerDownEvent e ) {
2022-09-27 15:35:02 +03:00
debugPrint ( " onPointDownImage " ) ;
2023-03-20 13:42:03 +03:00
_stopFling = true ;
2022-09-15 09:49:59 +03:00
if ( e . kind ! = ui . PointerDeviceKind . mouse ) {
2022-09-27 17:16:27 +03:00
if ( isPhysicalMouse . value ) {
isPhysicalMouse . value = false ;
2022-09-15 09:49:59 +03:00
}
}
2022-09-27 17:16:27 +03:00
if ( isPhysicalMouse . value ) {
2023-01-04 15:06:48 +03:00
handleMouse ( getEvent ( e , _kMouseEventDown ) ) ;
2022-09-15 09:49:59 +03:00
}
}
void onPointUpImage ( PointerUpEvent e ) {
if ( e . kind ! = ui . PointerDeviceKind . mouse ) return ;
2022-09-27 17:16:27 +03:00
if ( isPhysicalMouse . value ) {
2023-01-04 15:06:48 +03:00
handleMouse ( getEvent ( e , _kMouseEventUp ) ) ;
2022-09-15 09:49:59 +03:00
}
}
void onPointMoveImage ( PointerMoveEvent e ) {
if ( e . kind ! = ui . PointerDeviceKind . mouse ) return ;
2022-09-27 17:16:27 +03:00
if ( isPhysicalMouse . value ) {
2023-01-04 15:06:48 +03:00
handleMouse ( getEvent ( e , _kMouseEventMove ) ) ;
2022-09-15 09:49:59 +03:00
}
}
void onPointerSignalImage ( PointerSignalEvent e ) {
if ( e is PointerScrollEvent ) {
var dx = e . scrollDelta . dx . toInt ( ) ;
var dy = e . scrollDelta . dy . toInt ( ) ;
if ( dx > 0 ) {
dx = - 1 ;
} else if ( dx < 0 ) {
dx = 1 ;
}
if ( dy > 0 ) {
dy = - 1 ;
} else if ( dy < 0 ) {
dy = 1 ;
}
bind . sessionSendMouse (
2022-09-27 15:35:02 +03:00
id: id , msg: ' {"type": "wheel", "x": " $ dx ", "y": " $ dy "} ' ) ;
}
}
2023-01-30 17:12:36 +03:00
void refreshMousePos ( ) = > handleMouse ( {
' x ' : lastMousePos . dx ,
' y ' : lastMousePos . dy ,
' buttons ' : 0 ,
' type ' : _kMouseEventMove ,
} ) ;
2023-03-13 16:05:41 +03:00
void tryMoveEdgeOnExit ( Offset pos ) = > handleMouse (
2023-03-13 16:03:43 +03:00
{
' x ' : pos . dx ,
' y ' : pos . dy ,
' buttons ' : 0 ,
' type ' : _kMouseEventMove ,
} ,
onExit: true ,
) ;
int trySetNearestRange ( int v , int min , int max , int n ) {
if ( v < min & & v > = min - n ) {
v = min ;
}
if ( v > max & & v < = max + n ) {
v = max ;
}
return v ;
}
Offset setNearestEdge ( double x , double y , Display d ) {
double left = x - d . x ;
double right = d . x + d . width - 1 - x ;
double top = y - d . y ;
double bottom = d . y + d . height - 1 - y ;
if ( left < right & & left < top & & left < bottom ) {
x = d . x ;
}
if ( right < left & & right < top & & right < bottom ) {
x = d . x + d . width - 1 ;
}
if ( top < left & & top < right & & top < bottom ) {
y = d . y ;
}
if ( bottom < left & & bottom < right & & bottom < top ) {
y = d . y + d . height - 1 ;
}
return Offset ( x , y ) ;
}
void handleMouse (
Map < String , dynamic > evt , {
bool onExit = false ,
} ) {
2022-11-08 07:01:51 +03:00
double x = evt [ ' x ' ] ;
double y = max ( 0.0 , evt [ ' y ' ] ) ;
final cursorModel = parent . target ! . cursorModel ;
2022-11-14 10:05:44 +03:00
if ( cursorModel . isPeerControlProtected ) {
lastMousePos = ui . Offset ( x , y ) ;
2022-11-08 08:37:08 +03:00
return ;
}
2022-11-14 10:05:44 +03:00
if ( ! cursorModel . gotMouseControl ) {
bool selfGetControl =
( x - lastMousePos . dx ) . abs ( ) > kMouseControlDistance | |
( y - lastMousePos . dy ) . abs ( ) > kMouseControlDistance ;
if ( selfGetControl ) {
cursorModel . gotMouseControl = true ;
2022-11-08 07:01:51 +03:00
} else {
2022-11-14 10:05:44 +03:00
lastMousePos = ui . Offset ( x , y ) ;
2022-11-08 07:01:51 +03:00
return ;
}
}
2022-11-14 10:05:44 +03:00
lastMousePos = ui . Offset ( x , y ) ;
2022-11-08 07:01:51 +03:00
2022-09-27 15:35:02 +03:00
var type = ' ' ;
var isMove = false ;
switch ( evt [ ' type ' ] ) {
2023-01-04 15:06:48 +03:00
case _kMouseEventDown:
2022-09-27 15:35:02 +03:00
type = ' down ' ;
break ;
2023-01-04 15:06:48 +03:00
case _kMouseEventUp:
2022-09-27 15:35:02 +03:00
type = ' up ' ;
break ;
2023-01-04 15:06:48 +03:00
case _kMouseEventMove:
2022-09-27 15:35:02 +03:00
isMove = true ;
break ;
default :
return ;
}
evt [ ' type ' ] = type ;
2023-02-28 10:30:46 +03:00
y - = CanvasModel . topToEdge ;
x - = CanvasModel . leftToEdge ;
2022-09-27 15:35:02 +03:00
final canvasModel = parent . target ! . canvasModel ;
2023-02-24 18:38:23 +03:00
final nearThr = 3 ;
var nearRight = ( canvasModel . size . width - x ) < nearThr ;
var nearBottom = ( canvasModel . size . height - y ) < nearThr ;
2022-09-27 15:35:02 +03:00
final ffiModel = parent . target ! . ffiModel ;
if ( isMove ) {
canvasModel . moveDesktopMouse ( x , y ) ;
}
final d = ffiModel . display ;
2023-02-24 18:38:23 +03:00
final imageWidth = d . width * canvasModel . scale ;
final imageHeight = d . height * canvasModel . scale ;
2022-09-27 15:35:02 +03:00
if ( canvasModel . scrollStyle = = ScrollStyle . scrollbar ) {
x + = imageWidth * canvasModel . scrollX ;
y + = imageHeight * canvasModel . scrollY ;
// boxed size is a center widget
if ( canvasModel . size . width > imageWidth ) {
x - = ( ( canvasModel . size . width - imageWidth ) / 2 ) ;
}
if ( canvasModel . size . height > imageHeight ) {
y - = ( ( canvasModel . size . height - imageHeight ) / 2 ) ;
}
} else {
x - = canvasModel . x ;
y - = canvasModel . y ;
}
x / = canvasModel . scale ;
y / = canvasModel . scale ;
2023-02-24 18:38:23 +03:00
if ( canvasModel . scale > 0 & & canvasModel . scale < 1 ) {
final step = 1.0 / canvasModel . scale - 1 ;
if ( nearRight ) {
x + = step ;
}
if ( nearBottom ) {
y + = step ;
}
}
2022-09-27 15:35:02 +03:00
x + = d . x ;
y + = d . y ;
2023-03-13 16:03:43 +03:00
if ( onExit ) {
final pos = setNearestEdge ( x , y , d ) ;
x = pos . dx ;
y = pos . dy ;
}
2023-02-26 18:29:36 +03:00
var evtX = 0 ;
var evtY = 0 ;
try {
2023-02-26 18:31:11 +03:00
evtX = x . round ( ) ;
evtY = y . round ( ) ;
2023-02-26 18:29:36 +03:00
} catch ( e ) {
debugPrintStack (
label: ' canvasModel.scale value ${ canvasModel . scale } , $ e ' ) ;
return ;
}
2023-02-10 16:32:51 +03:00
2023-03-13 16:03:43 +03:00
int minX = d . x . toInt ( ) ;
int maxX = ( d . x + d . width ) . toInt ( ) - 1 ;
int minY = d . y . toInt ( ) ;
int maxY = ( d . y + d . height ) . toInt ( ) - 1 ;
2023-03-13 16:18:10 +03:00
evtX = trySetNearestRange ( evtX , minX , maxX , 5 ) ;
evtY = trySetNearestRange ( evtY , minY , maxY , 5 ) ;
2023-03-13 16:03:43 +03:00
if ( evtX < minX | | evtY < minY | | evtX > maxX | | evtY > maxY ) {
2023-02-10 16:32:51 +03:00
// If left mouse up, no early return.
if ( evt [ ' buttons ' ] ! = kPrimaryMouseButton | | type ! = ' up ' ) {
return ;
}
}
2022-09-27 15:35:02 +03:00
if ( type ! = ' ' ) {
2023-02-26 18:29:36 +03:00
evtX = 0 ;
evtY = 0 ;
2022-09-27 15:35:02 +03:00
}
2023-02-10 16:32:51 +03:00
2023-02-26 18:29:36 +03:00
evt [ ' x ' ] = ' $ evtX ' ;
evt [ ' y ' ] = ' $ evtY ' ;
2022-09-27 15:35:02 +03:00
var buttons = ' ' ;
switch ( evt [ ' buttons ' ] ) {
2023-01-05 12:14:44 +03:00
case kPrimaryMouseButton:
2022-09-27 15:35:02 +03:00
buttons = ' left ' ;
break ;
2023-01-05 12:14:44 +03:00
case kSecondaryMouseButton:
2022-09-27 15:35:02 +03:00
buttons = ' right ' ;
break ;
2023-01-05 12:14:44 +03:00
case kMiddleMouseButton:
2022-09-27 15:35:02 +03:00
buttons = ' wheel ' ;
break ;
2023-01-05 12:14:44 +03:00
case kBackMouseButton:
buttons = ' back ' ;
break ;
case kForwardMouseButton:
buttons = ' forward ' ;
break ;
2022-09-27 15:35:02 +03:00
}
evt [ ' buttons ' ] = buttons ;
bind . sessionSendMouse ( id: id , msg: json . encode ( evt ) ) ;
}
/// Web only
void listenToMouse ( bool yesOrNo ) {
if ( yesOrNo ) {
platformFFI . startDesktopWebListener ( ) ;
} else {
platformFFI . stopDesktopWebListener ( ) ;
2022-09-15 09:49:59 +03:00
}
}
}