Description
When more than one WebView is mounted at the same time (e.g. several
WebView, but only one of them actually responds to taps/clicks. The others
render fine but silently ignore all touch/click input (links don't navigate,
buttons don't react, etc.).
Steps to reproduce
- Build a screen with 3
WebViewControllers, each loading a different URL
(e.g. https://www.google.com, https://www.naver.com,
https://flutter.dev/), laid out side by side with WebViewWidget.
- Run on a Tizen (TV) device/emulator.
- Wait for all 3 pages to finish loading.
- Tap a link/button in each WebView.
Expected: all 3 WebViews respond to taps independently.
Actual: only one WebView (the one that ends up holding canvas focus last)
responds to taps. The others load content but never react to input.
Root cause (confirmed by source inspection)
All WebView instances share a single global offscreen Ecore_Evas canvas
(g_offscreen_host in webview.cc):
Ecore_Evas* WebView::GetOffscreenHost() {
if (!g_offscreen_host) {
g_offscreen_host = ecore_evas_new("wayland_shm", 0, 0, 1, 1, 0);
}
return g_offscreen_host;
}
InitWebView() unconditionally grabs focus on that shared canvas for every
new WebView instance:
Ecore_Evas* evas = GetOffscreenHost();
webview_instance_ = ewk_view_add(ecore_evas_get(evas));
...
ecore_evas_focus_set(evas, true);
ewk_view_focus_set(webview_instance_, true);
An Evas canvas can only have a single focused object at a time. Internally,
ewk_view_focus_set() reaches
RWHVAuraOffscreenHelperEfl::Focus() in chromium-efl
(tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc):
void RWHVAuraOffscreenHelperEfl::Focus(bool focus) {
elm_object_focus_set(content_image_elm_host_, focus);
evas_object_focus_set(content_image_, focus);
...
}
Since every WebView's content_image_ lives on the same shared canvas,
each newly created WebView silently steals focus away from whichever
WebView held it before. The WebView that loses focus gets its
RenderWidgetHost blurred:
void RWHVAuraOffscreenHelperEfl::OnHostFocusOut(...) {
thiz->GetRenderWidgetHostImpl()->Blur();
}
Rendering keeps working regardless of focus, but input handling that is
gated on the render widget's focus state (link activation, click handling,
etc.) stops working for every WebView except the one currently holding the
shared canvas's focus — which matches the reported symptom exactly.
Why the existing test didn't catch this
multiple WebViews can be used simultaneously in
example/integration_test/webview_flutter_test.dart (added in cf91ddc)
only checks currentUrl() and runJavaScriptReturningResult() for two
WebViews — it never simulates a tap/click, so it never exercises the
focus-stealing path described above.
Possible directions for a fix
- Don't unconditionally call ewk_view_focus_set(true) for every new
instance; only give focus to the WebView that actually receives
user input (e.g. wire it to PlatformView::SetFocus/ClearFocus, which
the embedder already calls per-view).
- Or give each WebView its own offscreen Ecore_Evas instead of sharing a
single global canvas, so focus is no longer a canvas-wide exclusive
resource.
Minimal repro
Run with flutter-tizen run -t lib/multiple_webview_example.dart after
saving this as example/lib/multiple_webview_example.dart (not wired into
main.dart):
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
const List<String> _urls = <String>[
'https://www.google.com',
'https://www.naver.com',
'https://flutter.dev/',
];
void main() => runApp(const MaterialApp(home: MultipleWebViewExample()));
class MultipleWebViewExample extends StatefulWidget {
const MultipleWebViewExample({super.key});
@override
State<MultipleWebViewExample> createState() =>
_MultipleWebViewExampleState();
}
class _MultipleWebViewExampleState extends State<MultipleWebViewExample> {
late final List<WebViewController> _controllers;
@override
void initState() {
super.initState();
_controllers = _urls.map((String url) {
final WebViewController controller = WebViewController();
controller
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onPageStarted: (String url) {
debugPrint('[$url] page started');
},
onPageFinished: (String url) {
debugPrint('[$url] page finished');
},
onWebResourceError: (WebResourceError error) {
debugPrint(
'[${error.url}] resource error: ${error.description}',
);
},
),
)
..loadRequest(Uri.parse(url));
return controller;
}).toList();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Multiple WebViews example')),
body: Row(
children: <Widget>[
for (final WebViewController controller in _controllers)
Expanded(child: WebViewWidget(controller: controller)),
],
),
);
}
}
After all 3 pages finish loading, tap a link inside the Naver or flutter.dev
WebView — the tap is ignored. Tapping inside the Google WebView works.
Description
When more than one
WebViewis mounted at the same time (e.g. severalWebView, but only one of them actually responds to taps/clicks. The others
render fine but silently ignore all touch/click input (links don't navigate,
buttons don't react, etc.).
Steps to reproduce
WebViewControllers, each loading a different URL(e.g.
https://www.google.com,https://www.naver.com,https://flutter.dev/), laid out side by side withWebViewWidget.Expected: all 3 WebViews respond to taps independently.
Actual: only one WebView (the one that ends up holding canvas focus last)
responds to taps. The others load content but never react to input.
Root cause (confirmed by source inspection)
All
WebViewinstances share a single global offscreenEcore_Evascanvas(
g_offscreen_hostinwebview.cc):InitWebView() unconditionally grabs focus on that shared canvas for every
new WebView instance:
An Evas canvas can only have a single focused object at a time. Internally,
ewk_view_focus_set() reaches
RWHVAuraOffscreenHelperEfl::Focus() in chromium-efl
(tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_offscreen_helper_efl.cc):
Since every WebView's content_image_ lives on the same shared canvas,
each newly created WebView silently steals focus away from whichever
WebView held it before. The WebView that loses focus gets its
RenderWidgetHost blurred:
Rendering keeps working regardless of focus, but input handling that is
gated on the render widget's focus state (link activation, click handling,
etc.) stops working for every WebView except the one currently holding the
shared canvas's focus — which matches the reported symptom exactly.
Why the existing test didn't catch this
multiple WebViews can be used simultaneously in
example/integration_test/webview_flutter_test.dart (added in cf91ddc)
only checks currentUrl() and runJavaScriptReturningResult() for two
WebViews — it never simulates a tap/click, so it never exercises the
focus-stealing path described above.
Possible directions for a fix
instance; only give focus to the WebView that actually receives
user input (e.g. wire it to PlatformView::SetFocus/ClearFocus, which
the embedder already calls per-view).
single global canvas, so focus is no longer a canvas-wide exclusive
resource.
Minimal repro
Run with
flutter-tizen run -t lib/multiple_webview_example.dartaftersaving this as
example/lib/multiple_webview_example.dart(not wired intomain.dart):After all 3 pages finish loading, tap a link inside the Naver or flutter.dev
WebView — the tap is ignored. Tapping inside the Google WebView works.