Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

多实例支持 #40

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft

多实例支持 #40

wants to merge 7 commits into from

Conversation

Doflatango
Copy link
Contributor

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

调整一

对于每一个 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 插件了。

@hlwhl
Copy link
Owner

hlwhl commented Dec 30, 2022

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

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

@BullsEye34
Copy link
Contributor

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?

@Doflatango
Copy link
Contributor Author

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

@SinyimZhi
Copy link
Collaborator

SinyimZhi commented May 23, 2023

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

调整一

对于每一个 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上同步完善

@Doflatango
Copy link
Contributor Author

@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
Copy link
Collaborator

@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 的逻辑)

十分感谢 我先研究下

@welnstar
Copy link

@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

@hlwhl
Copy link
Owner

hlwhl commented May 25, 2023

@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
Copy link
Owner

hlwhl commented May 25, 2023

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

@Doflatango
Copy link
Contributor Author

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

@SinyimZhi
Copy link
Collaborator

SinyimZhi commented Jun 5, 2023

@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方法里手写输入法事件,由我们的代码来做输入法处理,但我认为这不是一个好的方式。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants