webview_cef icon indicating copy to clipboard operation
webview_cef copied to clipboard

多实例支持

Open Doflatango opened this issue 2 years ago • 12 comments

对原有的代码结构做了一些调整,以适应多实例,调整后的结构如下:

调整一

对于每一个 WebView 实例,包含:

  • 一个 CefBrowser 实例
  • 一个 WebviewHandler 实例
  • 以及一个 Dart 端的 WebViewController 实例
  • 它们之间有一个 MethodChannel 用于双向的方法调用,一个 EventChannel 用于 c++ 推送各种 CefBrowser 事件到 Dart,原来的一个 MethodChannel 作为插件级别 MethodChannel 使用,不与上面的混淆

这些应该都是平台无关的,以后添加大部分 CefBrowser 相关的功能时,应该实现一次就可以了。

调整二

平台相关的,比如纹理处理独立出来(TextureHandler)仍然放在平台目录下

目前的问题:

  1. 暂时屏蔽了键盘输入的功能,我后面看看能不能和输入法问题一起解决
  2. 由于缺乏相关知识,MacOS 平台还未做修改,所以暂时标记此 PR 为草稿,方便讨论一些存在的问题(后面我抽时间补一补相关知识再把 MacOS 平台的一并修改了,不过由于忙于其它事情,可能要等很久,如果 @hlwhl 想代劳实现的话我会非常感激!)
  3. C++ 新手,代码比较糙,有问题的地方请指出来,也可以直接修改不用通知我

最后,非常感谢这个项目,这个插件完善之后,可能是未来很长一段时间里 Flutter Windows 能唯一稳定使用的 WebView 插件了。

Doflatango avatar Dec 29 '22 14:12 Doflatango

感谢贡献!最近我会抽时间review下代码,完善下macos的实现。

键盘输入确实是一个难点,目前看flutter中的api没有暴露出足够api用来实现ime支持,当前的实现仅输入英文字母也是存在bug。IME这块是本项目能否正常使用的关键点,如果有思路希望踊跃提出,感谢!

hlwhl avatar Dec 30 '22 09:12 hlwhl

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?

BullsEye34 avatar May 19 '23 11:05 BullsEye34

Hi @BullsEye34, sorry, these changes does not support MacOS yet.

Doflatango avatar May 19 '23 13:05 Doflatango

对原有的代码结构做了一些调整,以适应多实例,调整后的结构如下:

调整一

对于每一个 WebView 实例,包含:

  • 一个 CefBrowser 实例
  • 一个 WebviewHandler 实例
  • 以及一个 Dart 端的 WebViewController 实例
  • 它们之间有一个 MethodChannel 用于双向的方法调用,一个 EventChannel 用于 c++ 推送各种 CefBrowser 事件到 Dart,原来的一个 MethodChannel 作为插件级别 MethodChannel 使用,不与上面的混淆

这些应该都是平台无关的,以后添加大部分 CefBrowser 相关的功能时,应该实现一次就可以了。

调整二

平台相关的,比如纹理处理独立出来(TextureHandler)仍然放在平台目录下

目前的问题:

  1. 暂时屏蔽了键盘输入的功能,我后面看看能不能和输入法问题一起解决
  2. 由于缺乏相关知识,MacOS 平台还未做修改,所以暂时标记此 PR 为草稿,方便讨论一些存在的问题(后面我抽时间补一补相关知识再把 MacOS 平台的一并修改了,不过由于忙于其它事情,可能要等很久,如果 @hlwhl 想代劳实现的话我会非常感激!)
  3. C++ 新手,代码比较糙,有问题的地方请指出来,也可以直接修改不用通知我

最后,非常感谢这个项目,这个插件完善之后,可能是未来很长一段时间里 Flutter Windows 能唯一稳定使用的 WebView 插件了。

hello,目前我这边IME support 的需求是比较强的,看了下您的fork,最近好像有重新针对IME这块做处理,找了一圈没找到您的联系方式,能不能聊下最新的方案是怎么考虑的。我这两天应该会介入这块的处理并且尝试在MacOS上同步完善

SinyimZhi avatar May 23 '23 09:05 SinyimZhi

@SinyimZhi 主要是监听输入法开始事件,然后把键盘事件交给 Flutter engine 处理, 此时 dart 那边配合 DeltaTextInputClient 处理来自 Flutter engine 的输入法事件,实现下面两个主要的功能:

  1. 更新输入法在屏幕的位置以追随输入光标
  2. 对正在输入的拼音添加下划线的标志(打字的时候注意看看正在拼写的拼音部分,下面会有一条下划线)

输入法 C++ 部分的代码逻辑,macOS 与 Windows 会有些差别,所以我分开写了,但是仅实现了 Windows 的(https://github.com/Doflatango/webview_cef/blob/a/windows/webview_cef_plugin.cpp 搜索 ime 可以看到就那几个 method call 的逻辑)

Doflatango avatar May 23 '23 12:05 Doflatango

@SinyimZhi 主要是监听输入法开始事件,然后把键盘事件交给 Flutter engine 处理, 此时 dart 那边配合 DeltaTextInputClient 处理来自 Flutter engine 的输入法事件,实现下面两个主要的功能:

  1. 更新输入法在屏幕的位置以追随输入光标
  2. 对正在输入的拼音添加下划线的标志(打字的时候注意看看正在拼写的拼音部分,下面会有一条下划线)

输入法 C++ 部分的代码逻辑,macOS 与 Windows 会有些差别,所以我分开写了,但是仅实现了 Windows 的(https://github.com/Doflatango/webview_cef/blob/a/windows/webview_cef_plugin.cpp 搜索 ime 可以看到就那几个 method call 的逻辑)

十分感谢 我先研究下

SinyimZhi avatar May 24 '23 02:05 SinyimZhi

@SinyimZhi 主要是监听输入法开始事件,然后把键盘事件交给 Flutter engine 处理, 此时 dart 那边配合 DeltaTextInputClient 处理来自 Flutter engine 的输入法事件,实现下面两个主要的功能:

  1. 更新输入法在屏幕的位置以追随输入光标
  2. 对正在输入的拼音添加下划线的标志(打字的时候注意看看正在拼写的拼音部分,下面会有一条下划线)

输入法 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

welnstar avatar May 25 '23 07:05 welnstar

@SinyimZhi 主要是监听输入法开始事件,然后把键盘事件交给 Flutter engine 处理, 此时 dart 那边配合 DeltaTextInputClient 处理来自 Flutter engine 的输入法事件,实现下面两个主要的功能:

  1. 更新输入法在屏幕的位置以追随输入光标
  2. 对正在输入的拼音添加下划线的标志(打字的时候注意看看正在拼写的拼音部分,下面会有一条下划线)

输入法 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

hlwhl avatar May 25 '23 09:05 hlwhl

另,macos中,如果自己注册了text input client,flutter engine中的输入法处理可能会失效:https://github.com/flutter/engine/blob/a74d9d1f4776ccaf371cc60638db8719ad730fbe/shell/platform/darwin/macos/framework/Source/FlutterTextInputPlugin.mm#L341

hlwhl avatar May 25 '23 10:05 hlwhl

输入法只能给 Flutter engine 管理,再由框架分发给对应 input client,如果插件也要直接接手输入法,会和 Flutter engine 打架,表现为输入法位置跳来跳去,内容会输入到错误的 widget 去,这个是后来为什么要重写输入功能的原因。

Doflatango avatar May 25 '23 15:05 Doflatango

@Doflatango @hlwhl @welnstar 关于ime support,综合以上各位的意见,经过试验,在windows平台下如果在cef初始化时,通过processKeyEventForCEF函数给cef注册键盘事件,使用输入法会同时激活flutter engine 和 cef对imm32的监听,确实会导致冲突。由于我的团队更高优需求在linux support上,我接下来会优先介入linux support,ime_support会利用空余时间处理。在我的fork上的ime_support分支我做了一些相应的处理,主要方案是:

  1. cef内部的focus交给cef自己来处理,并且将node是否可编辑的message传给flutter,在接到可编辑message时,textinput做attach。
  2. 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方法里手写输入法事件,由我们的代码来做输入法处理,但我认为这不是一个好的方式。

SinyimZhi avatar Jun 05 '23 03:06 SinyimZhi