flutter_desktop: remote window cursor debug
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
af2e555e41
commit
fd8c83497d
@ -41,6 +41,7 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
String _value = '';
|
String _value = '';
|
||||||
double _scale = 1;
|
double _scale = 1;
|
||||||
double _mouseScrollIntegral = 0; // mouse scroll speed controller
|
double _mouseScrollIntegral = 0; // mouse scroll speed controller
|
||||||
|
var _cursorOverImage = false.obs;
|
||||||
|
|
||||||
var _more = true;
|
var _more = true;
|
||||||
var _fn = false;
|
var _fn = false;
|
||||||
@ -291,114 +292,61 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget getRawPointerAndKeyBody(Widget child) {
|
Widget getRawPointerAndKeyBody(Widget child) {
|
||||||
return Listener(
|
return Consumer<FfiModel>(
|
||||||
onPointerHover: (e) {
|
builder: (context, FfiModel, _child) => MouseRegion(
|
||||||
if (e.kind != ui.PointerDeviceKind.mouse) return;
|
cursor: FfiModel.permissions['keyboard'] != false
|
||||||
if (!_isPhysicalMouse) {
|
? SystemMouseCursors.none
|
||||||
setState(() {
|
: MouseCursor.defer,
|
||||||
_isPhysicalMouse = true;
|
child: FocusScope(
|
||||||
});
|
autofocus: true,
|
||||||
}
|
child: Focus(
|
||||||
if (_isPhysicalMouse) {
|
|
||||||
_ffi.handleMouse(getEvent(e, 'mousemove'),
|
|
||||||
tabBarHeight: super.widget.tabBarHeight);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onPointerDown: (e) {
|
|
||||||
if (e.kind != ui.PointerDeviceKind.mouse) {
|
|
||||||
if (_isPhysicalMouse) {
|
|
||||||
setState(() {
|
|
||||||
_isPhysicalMouse = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_isPhysicalMouse) {
|
|
||||||
_ffi.handleMouse(getEvent(e, 'mousedown'),
|
|
||||||
tabBarHeight: super.widget.tabBarHeight);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onPointerUp: (e) {
|
|
||||||
if (e.kind != ui.PointerDeviceKind.mouse) return;
|
|
||||||
if (_isPhysicalMouse) {
|
|
||||||
_ffi.handleMouse(getEvent(e, 'mouseup'),
|
|
||||||
tabBarHeight: super.widget.tabBarHeight);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onPointerMove: (e) {
|
|
||||||
if (e.kind != ui.PointerDeviceKind.mouse) return;
|
|
||||||
if (_isPhysicalMouse) {
|
|
||||||
_ffi.handleMouse(getEvent(e, 'mousemove'),
|
|
||||||
tabBarHeight: super.widget.tabBarHeight);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onPointerSignal: (e) {
|
|
||||||
if (e is PointerScrollEvent) {
|
|
||||||
var dx = e.scrollDelta.dx;
|
|
||||||
var dy = e.scrollDelta.dy;
|
|
||||||
if (dx > 0)
|
|
||||||
dx = -1;
|
|
||||||
else if (dx < 0) dx = 1;
|
|
||||||
if (dy > 0)
|
|
||||||
dy = -1;
|
|
||||||
else if (dy < 0) dy = 1;
|
|
||||||
bind.sessionSendMouse(
|
|
||||||
id: widget.id,
|
|
||||||
msg: '{"type": "wheel", "x": "$dx", "y": "$dy"}');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Consumer<FfiModel>(
|
|
||||||
builder: (context, FfiModel, _child) => MouseRegion(
|
|
||||||
cursor: FfiModel.permissions['keyboard'] != false
|
|
||||||
? SystemMouseCursors.none
|
|
||||||
: MouseCursor.defer,
|
|
||||||
child: FocusScope(
|
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: Focus(
|
canRequestFocus: true,
|
||||||
autofocus: true,
|
focusNode: _physicalFocusNode,
|
||||||
canRequestFocus: true,
|
onKey: (data, e) {
|
||||||
focusNode: _physicalFocusNode,
|
final key = e.logicalKey;
|
||||||
onKey: (data, e) {
|
if (e is RawKeyDownEvent) {
|
||||||
final key = e.logicalKey;
|
if (e.repeat) {
|
||||||
if (e is RawKeyDownEvent) {
|
sendRawKey(e, press: true);
|
||||||
if (e.repeat) {
|
} else {
|
||||||
sendRawKey(e, press: true);
|
if (e.isAltPressed && !_ffi.alt) {
|
||||||
} else {
|
_ffi.alt = true;
|
||||||
if (e.isAltPressed && !_ffi.alt) {
|
} else if (e.isControlPressed && !_ffi.ctrl) {
|
||||||
_ffi.alt = true;
|
_ffi.ctrl = true;
|
||||||
} else if (e.isControlPressed && !_ffi.ctrl) {
|
} else if (e.isShiftPressed && !_ffi.shift) {
|
||||||
_ffi.ctrl = true;
|
_ffi.shift = true;
|
||||||
} else if (e.isShiftPressed && !_ffi.shift) {
|
} else if (e.isMetaPressed && !_ffi.command) {
|
||||||
_ffi.shift = true;
|
_ffi.command = true;
|
||||||
} else if (e.isMetaPressed && !_ffi.command) {
|
|
||||||
_ffi.command = true;
|
|
||||||
}
|
|
||||||
sendRawKey(e, down: true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// [!_showEdit] workaround for soft-keyboard's control_key like Backspace / Enter
|
sendRawKey(e, down: true);
|
||||||
if (!_showEdit && e is RawKeyUpEvent) {
|
}
|
||||||
if (key == LogicalKeyboardKey.altLeft ||
|
}
|
||||||
key == LogicalKeyboardKey.altRight) {
|
// [!_showEdit] workaround for soft-keyboard's control_key like Backspace / Enter
|
||||||
_ffi.alt = false;
|
if (!_showEdit && e is RawKeyUpEvent) {
|
||||||
} else if (key == LogicalKeyboardKey.controlLeft ||
|
if (key == LogicalKeyboardKey.altLeft ||
|
||||||
key == LogicalKeyboardKey.controlRight) {
|
key == LogicalKeyboardKey.altRight) {
|
||||||
_ffi.ctrl = false;
|
_ffi.alt = false;
|
||||||
} else if (key == LogicalKeyboardKey.shiftRight ||
|
} else if (key == LogicalKeyboardKey.controlLeft ||
|
||||||
key == LogicalKeyboardKey.shiftLeft) {
|
key == LogicalKeyboardKey.controlRight) {
|
||||||
_ffi.shift = false;
|
_ffi.ctrl = false;
|
||||||
} else if (key == LogicalKeyboardKey.metaLeft ||
|
} else if (key == LogicalKeyboardKey.shiftRight ||
|
||||||
key == LogicalKeyboardKey.metaRight) {
|
key == LogicalKeyboardKey.shiftLeft) {
|
||||||
_ffi.command = false;
|
_ffi.shift = false;
|
||||||
}
|
} else if (key == LogicalKeyboardKey.metaLeft ||
|
||||||
sendRawKey(e);
|
key == LogicalKeyboardKey.metaRight) {
|
||||||
}
|
_ffi.command = false;
|
||||||
return KeyEventResult.handled;
|
}
|
||||||
},
|
sendRawKey(e);
|
||||||
child: child)))));
|
}
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
},
|
||||||
|
child: child))));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget? getBottomAppBar() {
|
Widget? getBottomAppBar() {
|
||||||
return BottomAppBar(
|
return MouseRegion(
|
||||||
|
cursor: SystemMouseCursors.basic,
|
||||||
|
child: BottomAppBar(
|
||||||
elevation: 10,
|
elevation: 10,
|
||||||
color: MyTheme.accent,
|
color: MyTheme.accent,
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -429,40 +377,40 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
? []
|
? []
|
||||||
: _ffi.ffiModel.isPeerAndroid
|
: _ffi.ffiModel.isPeerAndroid
|
||||||
? [
|
? [
|
||||||
|
IconButton(
|
||||||
|
color: Colors.white,
|
||||||
|
icon: Icon(Icons.build),
|
||||||
|
onPressed: () {
|
||||||
|
if (mobileActionsOverlayEntry == null) {
|
||||||
|
showMobileActionsOverlay();
|
||||||
|
} else {
|
||||||
|
hideMobileActionsOverlay();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
IconButton(
|
||||||
|
color: Colors.white,
|
||||||
|
icon: Icon(Icons.keyboard),
|
||||||
|
onPressed: openKeyboard),
|
||||||
|
IconButton(
|
||||||
|
color: Colors.white,
|
||||||
|
icon: Icon(_ffi.ffiModel.touchMode
|
||||||
|
? Icons.touch_app
|
||||||
|
: Icons.mouse),
|
||||||
|
onPressed: changeTouchMode,
|
||||||
|
),
|
||||||
|
]) +
|
||||||
|
(isWeb
|
||||||
|
? []
|
||||||
|
: <Widget>[
|
||||||
IconButton(
|
IconButton(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
icon: Icon(Icons.build),
|
icon: Icon(Icons.message),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (mobileActionsOverlayEntry == null) {
|
_ffi.chatModel
|
||||||
showMobileActionsOverlay();
|
.changeCurrentID(ChatModel.clientModeID);
|
||||||
} else {
|
|
||||||
hideMobileActionsOverlay();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
IconButton(
|
|
||||||
color: Colors.white,
|
|
||||||
icon: Icon(Icons.keyboard),
|
|
||||||
onPressed: openKeyboard),
|
|
||||||
IconButton(
|
|
||||||
color: Colors.white,
|
|
||||||
icon: Icon(_ffi.ffiModel.touchMode
|
|
||||||
? Icons.touch_app
|
|
||||||
: Icons.mouse),
|
|
||||||
onPressed: changeTouchMode,
|
|
||||||
),
|
|
||||||
]) +
|
|
||||||
(isWeb
|
|
||||||
? []
|
|
||||||
: <Widget>[
|
|
||||||
IconButton(
|
|
||||||
color: Colors.white,
|
|
||||||
icon: Icon(Icons.message),
|
|
||||||
onPressed: () {
|
|
||||||
_ffi.chatModel
|
|
||||||
.changeCurrentID(ChatModel.clientModeID);
|
|
||||||
_ffi.chatModel.toggleChatOverlay();
|
_ffi.chatModel.toggleChatOverlay();
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -498,6 +446,81 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
/// DoubleFiner -> right click
|
/// DoubleFiner -> right click
|
||||||
/// HoldDrag -> left drag
|
/// HoldDrag -> left drag
|
||||||
|
|
||||||
|
void _onPointHoverImage(PointerHoverEvent e) {
|
||||||
|
if (e.kind != ui.PointerDeviceKind.mouse) return;
|
||||||
|
if (!_isPhysicalMouse) {
|
||||||
|
setState(() {
|
||||||
|
_isPhysicalMouse = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (_isPhysicalMouse) {
|
||||||
|
_ffi.handleMouse(getEvent(e, 'mousemove'),
|
||||||
|
tabBarHeight: super.widget.tabBarHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onPointDownImage(PointerDownEvent e) {
|
||||||
|
if (e.kind != ui.PointerDeviceKind.mouse) {
|
||||||
|
if (_isPhysicalMouse) {
|
||||||
|
setState(() {
|
||||||
|
_isPhysicalMouse = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_isPhysicalMouse) {
|
||||||
|
_ffi.handleMouse(getEvent(e, 'mousedown'),
|
||||||
|
tabBarHeight: super.widget.tabBarHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onPointUpImage(PointerUpEvent e) {
|
||||||
|
if (e.kind != ui.PointerDeviceKind.mouse) return;
|
||||||
|
if (_isPhysicalMouse) {
|
||||||
|
_ffi.handleMouse(getEvent(e, 'mouseup'),
|
||||||
|
tabBarHeight: super.widget.tabBarHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onPointMoveImage(PointerMoveEvent e) {
|
||||||
|
if (e.kind != ui.PointerDeviceKind.mouse) return;
|
||||||
|
if (_isPhysicalMouse) {
|
||||||
|
_ffi.handleMouse(getEvent(e, 'mousemove'),
|
||||||
|
tabBarHeight: super.widget.tabBarHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onPointerSignalImage(PointerSignalEvent e) {
|
||||||
|
if (e is PointerScrollEvent) {
|
||||||
|
var dx = e.scrollDelta.dx;
|
||||||
|
var dy = e.scrollDelta.dy;
|
||||||
|
if (dx > 0)
|
||||||
|
dx = -1;
|
||||||
|
else if (dx < 0) dx = 1;
|
||||||
|
if (dy > 0)
|
||||||
|
dy = -1;
|
||||||
|
else if (dy < 0) dy = 1;
|
||||||
|
bind.sessionSendMouse(
|
||||||
|
id: widget.id, msg: '{"type": "wheel", "x": "$dx", "y": "$dy"}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildImageListener(Widget child) {
|
||||||
|
return Listener(
|
||||||
|
onPointerHover: _onPointHoverImage,
|
||||||
|
onPointerDown: _onPointDownImage,
|
||||||
|
onPointerUp: _onPointUpImage,
|
||||||
|
onPointerMove: _onPointMoveImage,
|
||||||
|
onPointerSignal: _onPointerSignalImage,
|
||||||
|
child: MouseRegion(
|
||||||
|
onEnter: (evt) {
|
||||||
|
_cursorOverImage.value = true;
|
||||||
|
},
|
||||||
|
onExit: (evt) {
|
||||||
|
_cursorOverImage.value = false;
|
||||||
|
},
|
||||||
|
child: child));
|
||||||
|
}
|
||||||
|
|
||||||
Widget getBodyForDesktop(BuildContext context, bool keyboard) {
|
Widget getBodyForDesktop(BuildContext context, bool keyboard) {
|
||||||
var paints = <Widget>[
|
var paints = <Widget>[
|
||||||
MouseRegion(onEnter: (evt) {
|
MouseRegion(onEnter: (evt) {
|
||||||
@ -824,10 +847,17 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
|
|
||||||
class ImagePaint extends StatelessWidget {
|
class ImagePaint extends StatelessWidget {
|
||||||
final String id;
|
final String id;
|
||||||
|
final Rx<bool> cursorOverImage;
|
||||||
|
final Widget Function(Widget)? listenerBuilder;
|
||||||
final ScrollController _horizontal = ScrollController();
|
final ScrollController _horizontal = ScrollController();
|
||||||
final ScrollController _vertical = ScrollController();
|
final ScrollController _vertical = ScrollController();
|
||||||
|
|
||||||
ImagePaint({Key? key, required this.id}) : super(key: key);
|
ImagePaint(
|
||||||
|
{Key? key,
|
||||||
|
required this.id,
|
||||||
|
required this.cursorOverImage,
|
||||||
|
this.listenerBuilder = null})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -835,6 +865,12 @@ class ImagePaint extends StatelessWidget {
|
|||||||
var c = Provider.of<CanvasModel>(context);
|
var c = Provider.of<CanvasModel>(context);
|
||||||
final s = c.scale;
|
final s = c.scale;
|
||||||
if (c.scrollStyle == ScrollStyle.scrollbar) {
|
if (c.scrollStyle == ScrollStyle.scrollbar) {
|
||||||
|
final imageWidget = SizedBox(
|
||||||
|
width: c.getDisplayWidth() * s,
|
||||||
|
height: c.getDisplayHeight() * s,
|
||||||
|
child: CustomPaint(
|
||||||
|
painter: new ImagePainter(image: m.image, x: 0, y: 0, scale: s),
|
||||||
|
));
|
||||||
return Center(
|
return Center(
|
||||||
child: NotificationListener<ScrollNotification>(
|
child: NotificationListener<ScrollNotification>(
|
||||||
onNotification: (_notification) {
|
onNotification: (_notification) {
|
||||||
@ -849,61 +885,51 @@ class ImagePaint extends StatelessWidget {
|
|||||||
c.setScrollPercent(percentX, percentY);
|
c.setScrollPercent(percentX, percentY);
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
child: Scrollbar(
|
child: Obx(() => MouseRegion(
|
||||||
controller: _vertical,
|
cursor: cursorOverImage.value
|
||||||
thumbVisibility: true,
|
? SystemMouseCursors.none
|
||||||
trackVisibility: true,
|
: SystemMouseCursors.basic,
|
||||||
child: Scrollbar(
|
child: _buildCrossScrollbar(_buildListener(imageWidget)))),
|
||||||
controller: _horizontal,
|
|
||||||
thumbVisibility: true,
|
|
||||||
trackVisibility: true,
|
|
||||||
notificationPredicate: (notif) => notif.depth == 1,
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
controller: _vertical,
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
controller: _horizontal,
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
child: buildListener(SizedBox(
|
|
||||||
width: c.getDisplayWidth() * s,
|
|
||||||
height: c.getDisplayHeight() * s,
|
|
||||||
child: CustomPaint(
|
|
||||||
painter: new ImagePainter(
|
|
||||||
image: m.image, x: 0, y: 0, scale: s),
|
|
||||||
)))),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
return buildListener(CustomPaint(
|
final imageWidget = SizedBox(
|
||||||
painter:
|
width: c.size.width,
|
||||||
new ImagePainter(image: m.image, x: c.x / s, y: c.y / s, scale: s),
|
height: c.size.height,
|
||||||
));
|
child: CustomPaint(
|
||||||
|
painter: new ImagePainter(
|
||||||
|
image: m.image, x: c.x / s, y: c.y / s, scale: s),
|
||||||
|
));
|
||||||
|
return _buildListener(imageWidget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildListener(Widget child) {
|
Widget _buildCrossScrollbar(Widget child) {
|
||||||
return Listener(
|
return Scrollbar(
|
||||||
onPointerHover: (e) {
|
controller: _vertical,
|
||||||
debugPrint(
|
thumbVisibility: true,
|
||||||
'REMOVE ME ======================== 4444 onPointerHover ${e.position}');
|
trackVisibility: true,
|
||||||
},
|
child: Scrollbar(
|
||||||
onPointerDown: (e) {
|
controller: _horizontal,
|
||||||
debugPrint(
|
thumbVisibility: true,
|
||||||
'REMOVE ME ======================== 4444 onPointerDown ${e.position}');
|
trackVisibility: true,
|
||||||
},
|
notificationPredicate: (notif) => notif.depth == 1,
|
||||||
onPointerUp: (e) {
|
child: SingleChildScrollView(
|
||||||
debugPrint(
|
controller: _vertical,
|
||||||
'REMOVE ME ======================== 4444 onPointerUp ${e.position}');
|
child: SingleChildScrollView(
|
||||||
},
|
controller: _horizontal,
|
||||||
onPointerMove: (e) {
|
scrollDirection: Axis.horizontal,
|
||||||
debugPrint(
|
child: child,
|
||||||
'REMOVE ME ======================== 4444 onPointerMove ${e.position}');
|
),
|
||||||
},
|
),
|
||||||
onPointerSignal: (e) {
|
));
|
||||||
debugPrint(
|
}
|
||||||
'REMOVE ME ======================== 3333 onPointerSignal ${e.position}');
|
|
||||||
},
|
Widget _buildListener(Widget child) {
|
||||||
child: child);
|
if (listenerBuilder != null) {
|
||||||
|
return listenerBuilder!(child);
|
||||||
|
} else {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user