Open dattran-pt19 opened 2 years ago
Yes, we are facing the same issue.
Yes, we are facing the same issue.
@gmuehlenberg Can you fix it, I only face issue in touch device
We're facing the the same sort of issue on touch devices: -we're not able to focus input/textarea fields -the targeted element is active (check via document.activeElement) but the cursor doesn't appear and the keyboard doesn't pop up -with the mouse it works, but not with the touch We have found a workaround --> the user touches the input/textarea for more than 1-2 seconds and then the focus & cursor are set to the field. On desktop works perfectly.
terms: flutter app -> the flutter window, where the app is running webview -> the webview widget inside the flutter app
I noticed that for a very brief moment the webview gets the focus but immediately loses it to the parent/flutter app right after the touch input. This must be the reason why it does not work, but i could not look deeper into it yet.
@jnschulze you have any idea how to "not lose" the focus of the webview when tapping with a touch input?
@jnschulze maybe it has to do with this handling? I'm new to this, but I found it here:
File:
webview.cc
https://github.com/jnschulze/flutter-webview-windows/blob/main/windows/webview.cc
composition_controller_->add_CursorChanged(
Callback<ICoreWebView2CursorChangedEventHandler>(
[this](ICoreWebView2CompositionController* sender,
IUnknown* args) -> HRESULT {
HCURSOR cursor;
if (cursor_changed_callback_ &&
sender->get_Cursor(&cursor) == S_OK) {
cursor_changed_callback_(cursor);
}
return S_OK;
})
.Get(),
&event_registrations_.cursor_changed_token_);
webview_controller_->add_GotFocus(
Callback<ICoreWebView2FocusChangedEventHandler>(
[this](ICoreWebView2Controller* sender, IUnknown* args) -> HRESULT {
if (focus_changed_callback_) {
focus_changed_callback_(true);
}
return S_OK;
})
.Get(),
&event_registrations_.got_focus_token_);
webview_controller_->add_LostFocus(
Callback<ICoreWebView2FocusChangedEventHandler>(
[this](ICoreWebView2Controller* sender, IUnknown* args) -> HRESULT {
if (focus_changed_callback_) {
focus_changed_callback_(false);
}
return S_OK;
})
.Get(),
&event_registrations_.lost_focus_token_);
Hm, my guess is that some e.g. touchUp
-Event might bubble up to the flutter parent window. @jnschulze the touchDown
-Event seems to work perfectly. I need to take a closer look but might this be the cause?
Another point of interest:
webview.cc
line 515++
host_->CreateWebViewPointerInfo(
[this, pointer, event, pointerFlags, point, rect, pressure](
wil::com_ptr<ICoreWebView2PointerInfo> pointerInfo,
std::unique_ptr<WebviewCreationError> error) {
if (pointerInfo) {
ICoreWebView2PointerInfo* pInfo = pointerInfo.get();
pInfo->put_PointerId(pointer);
pInfo->put_PointerKind(PT_TOUCH);
pInfo->put_PointerFlags(pointerFlags);
pInfo->put_TouchFlags(TOUCH_FLAG_NONE);
pInfo->put_TouchMask(TOUCH_MASK_CONTACTAREA | TOUCH_MASK_PRESSURE);
pInfo->put_TouchPressure(
std::clamp((UINT32)(pressure == 0.0 ? 1024 : 1024 * pressure),
(UINT32)0, (UINT32)1024));
pInfo->put_PixelLocationRaw(point);
pInfo->put_TouchContactRaw(rect);
composition_controller_->SendPointerInput(event, pInfo);
}
});
}
Here's a very plain workaround-widget for the issue.
Keep in mind that this should be seen as a workaround hack
and not as a solution.
Usage:
WebviewTouchWrapper(
child: Webview(ctrl),
),
webview_touch_wrapper.dart
(copy or create own file)
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class WebviewTouchWrapper extends StatelessWidget {
const WebviewTouchWrapper({required this.child, Key? key}) : super(key: key);
final Widget child;
static Offset oldPosition = Offset.zero;
void simulatePress(TapUpDetails details) {
const kind = PointerDeviceKind.touch;
final currentPosition = details.globalPosition;
if ((details.kind == kind) && (oldPosition != currentPosition)) {
oldPosition = currentPosition;
WidgetsBinding.instance.addPostFrameCallback((_) async {
try {
await Future.delayed(Duration(milliseconds: 36));
final tOffset = details.globalPosition;
GestureBinding.instance.handlePointerEvent(PointerMoveEvent(
position: tOffset,
kind: kind,
size: 70,
));
await Future.delayed(Duration(milliseconds: 36));
GestureBinding.instance.handlePointerEvent(PointerDownEvent(
position: tOffset,
kind: kind,
size: 70,
));
await Future.delayed(Duration(milliseconds: 36));
GestureBinding.instance.handlePointerEvent(PointerUpEvent(
position: tOffset,
kind: kind,
size: 70,
));
} catch (e, s) {
print(e);
print(s);
}
});
}
}
@override
Widget build(BuildContext context) => GestureDetector(
onTapUp: simulatePress,
child: child,
);
}
Here's a very plain workaround-widget for the issue. Keep in mind that this should be seen as a
workaround hack
and not as a solution.Usage:
WebviewTouchWrapper( child: Webview(ctrl), ),
webview_touch_wrapper.dart
(copy or create own file)import 'package:flutter/gestures.dart'; ...
@Eerey many thanks for this hack-like solution. We have tried this but after a while we noticed every tap/touch event ends with double tap/touch so that two events are forwarded to webview widget and then to the DOM where it causes various problems - e.g. open/close of UI components at the same time etc. Is there a way to make it work only on input/textarea elements? I think there is no way to know what exactly has been touched by webview event.
@maciola as you suggest I don't think that you're able to detect it beforehand. Please let us know if you find a good or better solution for it. Thanks for exploring my hacky solution!
@jnschulze any updates about this issue ?
I make a app run on Windows 10. when I click on input form in the webview. keyboard is showing and close right away. Anyone face same issue