有输入框的TAURI桌面程序,处于置顶状态时,用weasel向输入框打字,weasel会卡死
上报前请检查
- [x] 我遇到的问题没有其他人在 issue 里提到过
- [x] 我的小狼毫版本于 rime/weasel 下载
- [x] 我在使用小狼毫的最新发布版本,或最新发布版本后的 CI 构建
操作系统信息
-
OS 详细版本: [ 运行 winver.exe 获取,如 Windows 11 22H2 22621.1555]
-
小狼毫版本: [ 如 0.15.0.0 , CI 构建版请附短 commit hash ,如 372c9c ]
描述遇到的问题 tauri写的Windows桌面程序,且该程序处于置顶状态(可以用Windows powertoy设定窗口置顶,或者程序自身支持置顶) 这时用WEASEL再该程序的输入框里输入文字,WESEL自身就会卡死
这是TAURI那边的issue,暂时不知道是谁的锅 https://github.com/tauri-apps/tauri/issues/6879
复现步骤 重现问题的步骤,如:
- 打开 tauri编写的 软件(比如 https://github.com/pot-app/pot-desktop )
- 打开设定页面,用POWERTOY把该窗口置顶
- 在设定页面,找一个输入框
- 用weasel输入任何文字
- weasel卡住
预期行为 正常输入
用户文件 请于此附上 weasel 用户文件夹下的内容,方便开发者调试问题
截图 如果问题需要,可附上 GIF 图片
其他补充说明 如果有其他补充说明,可以写在这里
https://github.com/pot-app/pot-desktop/issues/60
↑另外的讨论
我编译了之前据说没问题的版本. 各位测试看看 https://github.com/pot-app/pot-desktop/issues/870#issuecomment-2487464966
问题可能出在 https://github.com/rime/weasel/blob/37c8fa161a221a263bb439a1158ba401c0cf90a3/WeaselTSF/Composition.cpp#L241-L242 注释掉任意一行都可以正常打字
@CDHJS 老哥我看你描述是用GPT做的DEBUG,具体是咋实现的呢?用的什么工具呢?
@CDHJS 老哥我看你描述是用GPT做的DEBUG,具体是咋实现的呢?用的什么工具呢?
我最早的思路其实是去找“winapi获取活动窗口句柄”误打误撞找到了 https://github.com/rime/weasel/blob/37c8fa161a221a263bb439a1158ba401c0cf90a3/WeaselTSF/Composition.cpp#L188 然后fork并删掉了整个代码块,我没装C++的编译环境所以用Actions编译,也是误打误撞删掉了 https://github.com/rime/weasel/blob/37c8fa161a221a263bb439a1158ba401c0cf90a3/WeaselTSF/Composition.cpp#L205 发现bug不存在了,上面的commit只是错误的以为bug来源是GetForegroundWindow把整块代码扔给GPT去重写了而已 以及我到现在没找到m_client是什么(VSCode只能找字符串),但我注释掉之后bug消失了,我fork的actions里最新的结果你可以试试
我测试了Chromium,Floorp,Edge,VSCode,Steam,wails,单独tao,winit+wry,webview2-rs(wry的上游)都正常,只有tao+wry和tauri会卡死,不过删除m_client.UpdateInputPosition(rc);的版本能正常运行,以及删除https://github.com/rime/weasel/blob/37c8fa161a221a263bb439a1158ba401c0cf90a3/WeaselUI/WeaselPanel.cpp#L1213-L1214 也能正常运行,但定位会在桌面左上角不动 卡死时【Webview tauri主进程 算法服务】加起来的CPU会有一个接近单核满载的占用,并且其中一个Webview进程内存缓慢增加(内存泄露?) 如果有托盘图标菜单的话右键托盘图标会解除卡死并关闭菜单,操作了几步就需要右键几下 如果点击了别的窗口卡死的UI会跟着新的窗口移动,如果此时输入会出现两个UI,新出现的UI正常
@CDHJS 我本来以为是有什么新工具可以一键自动DEBUG呢,感谢回答
在tao+wry如果给 https://github.com/tauri-apps/tao/blob/fa9aaa6066dcc0316d57038fc1b1e3353dc5c3e7/src/platform_impl/windows/event_loop.rs#L248 后面加上println!("{:?}", msg); 会一直输出: MSG { hwnd: HWND(0x608b0), message: 15, wParam: WPARAM(0), lParam: LPARAM(0), time: 21220500, pt: POINT { x: 1457, y: 644 } } 而非正常阻塞,此时移动鼠标POINT的值会实时变化(排除过多相同消息导致阻塞) 并且webview不会未响应(如果阻塞会导致未响应,比如sleep)
就咱俩在这讨论,不知道维护的大佬有没有计划修复 😢
候选窗是作为应用的子窗口popup的形式存在,上面提到的注释掉部分代码,注释掉的正是光标跟随的部分,底层是SetWindowPos,m_client.UpdateInputPosition是通过ipc通知服务端在必要的时候SetWindowPos,两个潜在SetWindowPos的对象都是候选窗而不是父窗口
如果SetWindowPos都不支持,那还可以怎么修实在想不到了
使用api-monitor可以观察到
GetMessageW的DefSubclassProc出现了死循环,在wry中可以找到:https://github.com/tauri-apps/wry/blob/cbbcccc38af7d900a0f8f7fa5ea5e6667765ed81/src/webview2/mod.rs#L1158-L1161
删除后卡死消失
在此仓库可以找到:
https://github.com/rime/weasel/blob/588a31f8eedf6066e5b6a1cc7f010ed528154445/include/wtl/atlframe.h#L1506
可能是诱发此bug的原因
附上chatGPT的解释:
@fxliang 希望对修复这个问题有所帮助
另外想请教一下m_client.UpdateInputPosition在什么情况下会使用到,在我的使用中是否有这行的版本表现并无不同 Floorp、Chromium在输入后移动窗口UI会跟着移动,其它多数应用会停留在原本的位置在按下键盘后跳到正确的位置,tao+wry/tauri移动窗口则会销毁UI或始终保持在原位,哪一种情况是正确的feature?
使用api-monitor可以观察到
GetMessageW的DefSubclassProc出现了死循环,在wry中可以找到:https://github.com/tauri-apps/wry/blob/cbbcccc38af7d900a0f8f7fa5ea5e6667765ed81/src/webview2/mod.rs#L1158-L1161 删除后卡死消失 在此仓库可以找到:
https://github.com/rime/weasel/blob/588a31f8eedf6066e5b6a1cc7f010ed528154445/include/wtl/atlframe.h#L1506
可能是诱发此bug的原因 附上chatGPT的解释:
@fxliang 希望对修复这个问题有所帮助
一些猜想:WeaselUI中未注册WM_WINDOWPOSCHANGED 的响应回调,那这个消息会向上传递到上一层应用的窗口对象;然后如你指出的状态似乎这个应用框架会手动触发一次WM_WINDOWPOSCHANGED消息,tsf中有注册如果光标位置变化的话,会响应调整输入框位置,这个又会调用一次SetWindowPos,于是死循环了?
weasel/include/wtl/atlframe.h是WTL的模板库代码,这个是微软官方的模板框架,完成度已经极高,相比这次报问题的框架的完成度,高的肯定不是一个数量级,基本不可能是WTL模板库的问题。
使用api-monitor可以观察到
GetMessageW的DefSubclassProc出现了死循环,在wry中可以找到:https://github.com/tauri-apps/wry/blob/cbbcccc38af7d900a0f8f7fa5ea5e6667765ed81/src/webview2/mod.rs#L1158-L1161 删除后卡死消失 在此仓库可以找到: https://github.com/rime/weasel/blob/588a31f8eedf6066e5b6a1cc7f010ed528154445/include/wtl/atlframe.h#L1506
可能是诱发此bug的原因 附上chatGPT的解释:
@fxliang 希望对修复这个问题有所帮助
一些猜想:WeaselUI中未注册WM_WINDOWPOSCHANGED 的响应回调,那这个消息会向上传递到上一层应用的窗口对象;然后如你指出的状态似乎这个应用框架会手动触发一次WM_WINDOWPOSCHANGED消息,tsf中有注册如果光标位置变化的话,会响应调整输入框位置,这个又会调用一次SetWindowPos,于是死循环了?
weasel/include/wtl/atlframe.h是WTL的模板库代码,这个是微软官方的模板框架,完成度已经极高,相比这次报问题的框架的完成度,高的肯定不是一个数量级,基本不可能是WTL模板库的问题。
按照你的猜想,修复这个问题的方法是给SetWindowPos增加一个防抖来防止过短时间内的多次调用 这是否可以解释删除m_client.UpdateInputPosition后问题消失的情况 这个问题只会在tao+wry并置顶窗口时出现,在我的测试中使用wry的examples/wgpu.rs时手动将其置顶并不会出现此问题(这个文件用的winit) 我不太理解为什么只有在窗口置顶时会死循环
对于这个问题,我来补充一下。 我和楼主@uqiu 一样在使用pot(https://github.com/pot-app/pot-desktop) 问题基本和楼主一样,就是在打开的pot窗口中,使用小狼毫拼音输入法输入一个单词后会卡死。无法关闭pot的窗口,除非切换为其它输入法。这时会强行关闭掉这个打开的pot输入窗口(并不会关闭整个程序)。
这个问题在0.15.00版本可以避免,在目前的最新版0.16.3.0版本无法避免。 这个问题无论在Windows10还是Windows11都会出现。
出现的bug和这个讨论一致:https://github.com/pot-app/pot-desktop/issues/60
因此我现在只能使用0.15.00,在此请求开发者修复此问题。
对于这个问题,我来补充一下。 我和楼主@uqiu 一样在使用pot(https://github.com/pot-app/pot-desktop) 问题基本和楼主一样,就是在打开的pot窗口中,使用小狼毫拼音输入法输入一个单词后会卡死。无法关闭pot的窗口,除非切换为其它输入法。这时会强行关闭掉这个打开的pot输入窗口(并不会关闭整个程序)。
右击Pot的托盘图标看上去能取消卡死状态。
GetMessageW的DefSubclassProc出现了死循环,在wry中可以找到:https://github.com/tauri-apps/wry/blob/cbbcccc38af7d900a0f8f7fa5ea5e6667765ed81/src/webview2/mod.rs#L1158-L1161 删除后卡死消失 在此仓库可以找到:
@fxliang 希望对修复这个问题有所帮助