webview_cef
webview_cef copied to clipboard
多实例支持
对原有的代码结构做了一些调整,以适应多实例,调整后的结构如下:
调整一
对于每一个 WebView 实例,包含:
- 一个
CefBrowser实例 - 一个
WebviewHandler实例 - 以及一个 Dart 端的
WebViewController实例 - 它们之间有一个
MethodChannel用于双向的方法调用,一个EventChannel用于 c++ 推送各种CefBrowser事件到 Dart,原来的一个 MethodChannel 作为插件级别 MethodChannel 使用,不与上面的混淆
这些应该都是平台无关的,以后添加大部分 CefBrowser 相关的功能时,应该实现一次就可以了。
调整二
平台相关的,比如纹理处理独立出来(TextureHandler)仍然放在平台目录下
目前的问题:
- 暂时屏蔽了键盘输入的功能,我后面看看能不能和输入法问题一起解决
- 由于缺乏相关知识,MacOS 平台还未做修改,所以暂时标记此 PR 为草稿,方便讨论一些存在的问题(后面我抽时间补一补相关知识再把 MacOS 平台的一并修改了,不过由于忙于其它事情,可能要等很久,如果 @hlwhl 想代劳实现的话我会非常感激!)
- C++ 新手,代码比较糙,有问题的地方请指出来,也可以直接修改不用通知我
最后,非常感谢这个项目,这个插件完善之后,可能是未来很长一段时间里 Flutter Windows 能唯一稳定使用的 WebView 插件了。
感谢贡献!最近我会抽时间review下代码,完善下macos的实现。
键盘输入确实是一个难点,目前看flutter中的api没有暴露出足够api用来实现ime支持,当前的实现仅输入英文字母也是存在bug。IME这块是本项目能否正常使用的关键点,如果有思路希望踊跃提出,感谢!
Hi @Doflatango , I cloned your repo, and the example/ app does not seem to compile.
It throws an error initially:
webview_cef/macos/Classes/cef_bridge.cc:5:10: fatal error: '../../common/webview_app.cc' file not found
#include "../../common/webview_app.cc"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
Which I was able to fix by changing macos/Classes/cef_bridge.cc
from:
#include "../../common/webview_app.cc"
#include "../../common/webview_handler.cc"
to:
#include "../../common/browser/webview_app.cc"
#include "../../common/browser/webview_handler.cc"
But then when I compile it again, I get this:
webview_cef/macos/Classes/../../common/browser/webview_handler.h:11:10: fatal error: 'flutter/method_channel.h' file not found
#include <flutter/method_channel.h>
^~~~~~~~~~~~~~~~~~~~~~~~~~
Am I doing something wrong? Am I missing something?
Hi @BullsEye34, sorry, these changes does not support MacOS yet.
对原有的代码结构做了一些调整,以适应多实例,调整后的结构如下:
调整一
对于每一个 WebView 实例,包含:
- 一个
CefBrowser实例- 一个
WebviewHandler实例- 以及一个 Dart 端的
WebViewController实例- 它们之间有一个
MethodChannel用于双向的方法调用,一个EventChannel用于 c++ 推送各种CefBrowser事件到 Dart,原来的一个 MethodChannel 作为插件级别 MethodChannel 使用,不与上面的混淆这些应该都是平台无关的,以后添加大部分 CefBrowser 相关的功能时,应该实现一次就可以了。
调整二
平台相关的,比如纹理处理独立出来(
TextureHandler)仍然放在平台目录下目前的问题:
- 暂时屏蔽了键盘输入的功能,我后面看看能不能和输入法问题一起解决
- 由于缺乏相关知识,MacOS 平台还未做修改,所以暂时标记此 PR 为草稿,方便讨论一些存在的问题(后面我抽时间补一补相关知识再把 MacOS 平台的一并修改了,不过由于忙于其它事情,可能要等很久,如果 @hlwhl 想代劳实现的话我会非常感激!)
- C++ 新手,代码比较糙,有问题的地方请指出来,也可以直接修改不用通知我
最后,非常感谢这个项目,这个插件完善之后,可能是未来很长一段时间里 Flutter Windows 能唯一稳定使用的 WebView 插件了。
hello,目前我这边IME support 的需求是比较强的,看了下您的fork,最近好像有重新针对IME这块做处理,找了一圈没找到您的联系方式,能不能聊下最新的方案是怎么考虑的。我这两天应该会介入这块的处理并且尝试在MacOS上同步完善
@SinyimZhi 主要是监听输入法开始事件,然后把键盘事件交给 Flutter engine 处理, 此时 dart 那边配合 DeltaTextInputClient 处理来自 Flutter engine 的输入法事件,实现下面两个主要的功能:
- 更新输入法在屏幕的位置以追随输入光标
- 对正在输入的拼音添加下划线的标志(打字的时候注意看看正在拼写的拼音部分,下面会有一条下划线)
输入法 C++ 部分的代码逻辑,macOS 与 Windows 会有些差别,所以我分开写了,但是仅实现了 Windows 的(https://github.com/Doflatango/webview_cef/blob/a/windows/webview_cef_plugin.cpp 搜索 ime 可以看到就那几个 method call 的逻辑)
@SinyimZhi 主要是监听输入法开始事件,然后把键盘事件交给 Flutter engine 处理, 此时 dart 那边配合
DeltaTextInputClient处理来自 Flutter engine 的输入法事件,实现下面两个主要的功能:
- 更新输入法在屏幕的位置以追随输入光标
- 对正在输入的拼音添加下划线的标志(打字的时候注意看看正在拼写的拼音部分,下面会有一条下划线)
输入法 C++ 部分的代码逻辑,macOS 与 Windows 会有些差别,所以我分开写了,但是仅实现了 Windows 的(https://github.com/Doflatango/webview_cef/blob/a/windows/webview_cef_plugin.cpp 搜索 ime 可以看到就那几个 method call 的逻辑)
十分感谢 我先研究下
@SinyimZhi 主要是监听输入法开始事件,然后把键盘事件交给 Flutter engine 处理, 此时 dart 那边配合
DeltaTextInputClient处理来自 Flutter engine 的输入法事件,实现下面两个主要的功能:
- 更新输入法在屏幕的位置以追随输入光标
- 对正在输入的拼音添加下划线的标志(打字的时候注意看看正在拼写的拼音部分,下面会有一条下划线)
输入法 C++ 部分的代码逻辑,macOS 与 Windows 会有些差别,所以我分开写了,但是仅实现了 Windows 的(https://github.com/Doflatango/webview_cef/blob/a/windows/webview_cef_plugin.cpp 搜索 ime 可以看到就那几个 method call 的逻辑)
个人觉着没必要用flutter处理,应该是cef直接监听imm32 我找到了一个类似的c#的处理 不知道能不能给您一点启发 https://www.cnblogs.com/Starts_2000/p/cefharp-wpf-osr-ime.html
@SinyimZhi 主要是监听输入法开始事件,然后把键盘事件交给 Flutter engine 处理, 此时 dart 那边配合
DeltaTextInputClient处理来自 Flutter engine 的输入法事件,实现下面两个主要的功能:
- 更新输入法在屏幕的位置以追随输入光标
- 对正在输入的拼音添加下划线的标志(打字的时候注意看看正在拼写的拼音部分,下面会有一条下划线)
输入法 C++ 部分的代码逻辑,macOS 与 Windows 会有些差别,所以我分开写了,但是仅实现了 Windows 的(https://github.com/Doflatango/webview_cef/blob/a/windows/webview_cef_plugin.cpp 搜索 ime 可以看到就那几个 method call 的逻辑)
个人觉着没必要用flutter处理,应该是cef直接监听imm32 我找到了一个类似的c#的处理 不知道能不能给您一点启发 https://www.cnblogs.com/Starts_2000/p/cefharp-wpf-osr-ime.html
ref: flutter engine中的实现:https://github.com/flutter/engine/blob/a74d9d1f4776ccaf371cc60638db8719ad730fbe/shell/platform/windows/text_input_manager.cc#L17
另,macos中,如果自己注册了text input client,flutter engine中的输入法处理可能会失效:https://github.com/flutter/engine/blob/a74d9d1f4776ccaf371cc60638db8719ad730fbe/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm#L341
输入法只能给 Flutter engine 管理,再由框架分发给对应 input client,如果插件也要直接接手输入法,会和 Flutter engine 打架,表现为输入法位置跳来跳去,内容会输入到错误的 widget 去,这个是后来为什么要重写输入功能的原因。
@Doflatango @hlwhl @welnstar 关于ime support,综合以上各位的意见,经过试验,在windows平台下如果在cef初始化时,通过processKeyEventForCEF函数给cef注册键盘事件,使用输入法会同时激活flutter engine 和 cef对imm32的监听,确实会导致冲突。由于我的团队更高优需求在linux support上,我接下来会优先介入linux support,ime_support会利用空余时间处理。在我的fork上的ime_support分支我做了一些相应的处理,主要方案是:
- cef内部的focus交给cef自己来处理,并且将node是否可编辑的message传给flutter,在接到可编辑message时,textinput做attach。
- flutter对cef的focus由flutter控制,通过onfocuschange来处理,unfocus时如果cef的focusnode为可编辑态,通知cef主动失去焦点。 目前遇到的问题:
- 输入法窗口总是出现在上一次设置的位置(第三方输入法,官方输入法设置保持在第一个字符前)。
- onfocuschange对于unfocus能够很好的触发,对于focus来说只有在节点是primary focu时才会触发,但是使用一次requestFocus函数后并没有将节点设置为primary focus,目前的解决方法是delay了50ms再requestFocus一次。怀疑是对Focus的使用有误,还需要再调整,目前尝试调整了Focus层级,在sizebox之前和texture之前均没有解决该问题。
- 输入法中使用左右来调节光标的位置没有实际的显示效果,并且如果移动了光标以后做删除字符会有问题。
- 以上方案在macos暂时无法验证,macos前置问题暂时没有解决,flutter engine确实失去了对输入法的控制,目前还在寻找关闭cef对NStextinput的监听的方法。可以验证的是,flutter对rawkeyevet的监听并没有失去,可以在Focus的onkeyevent方法里手写输入法事件,由我们的代码来做输入法处理,但我认为这不是一个好的方式。