weasel icon indicating copy to clipboard operation
weasel copied to clipboard

有输入框的TAURI桌面程序,处于置顶状态时,用weasel向输入框打字,weasel会卡死

Open uqiu opened this issue 1 year ago • 17 comments

上报前请检查

  • [x] 我遇到的问题没有其他人在 issue 里提到过
  • [x] 我的小狼毫版本于 rime/weasel 下载
  • [x] 我在使用小狼毫的最新发布版本,或最新发布版本后的 CI 构建

操作系统信息

  • OS 详细版本: [ 运行 winver.exe 获取,如 Windows 11 22H2 22621.1555] 图片

  • 小狼毫版本: [ 如 0.15.0.0 , CI 构建版请附短 commit hash ,如 372c9c ] 387496639-eee01148-ea92-4da2-a10e-1a164ba4ab3f-1

描述遇到的问题 tauri写的Windows桌面程序,且该程序处于置顶状态(可以用Windows powertoy设定窗口置顶,或者程序自身支持置顶) 这时用WEASEL再该程序的输入框里输入文字,WESEL自身就会卡死

这是TAURI那边的issue,暂时不知道是谁的锅 https://github.com/tauri-apps/tauri/issues/6879

复现步骤 重现问题的步骤,如:

  1. 打开 tauri编写的 软件(比如 https://github.com/pot-app/pot-desktop )
  2. 打开设定页面,用POWERTOY把该窗口置顶
  3. 在设定页面,找一个输入框
  4. 用weasel输入任何文字
  5. weasel卡住

预期行为 正常输入

用户文件 请于此附上 weasel 用户文件夹下的内容,方便开发者调试问题

截图 如果问题需要,可附上 GIF 图片

其他补充说明 如果有其他补充说明,可以写在这里

uqiu avatar Nov 20 '24 03:11 uqiu

https://github.com/pot-app/pot-desktop/issues/60

↑另外的讨论

uqiu avatar Nov 20 '24 03:11 uqiu

我编译了之前据说没问题的版本. 各位测试看看 https://github.com/pot-app/pot-desktop/issues/870#issuecomment-2487464966

uqiu avatar Nov 20 '24 06:11 uqiu

问题可能出在 https://github.com/rime/weasel/blob/37c8fa161a221a263bb439a1158ba401c0cf90a3/WeaselTSF/Composition.cpp#L241-L242 注释掉任意一行都可以正常打字

CDHJS avatar Nov 22 '24 10:11 CDHJS

@CDHJS 老哥我看你描述是用GPT做的DEBUG,具体是咋实现的呢?用的什么工具呢?

uqiu avatar Nov 22 '24 13:11 uqiu

@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里最新的结果你可以试试

CDHJS avatar Nov 22 '24 14:11 CDHJS

我测试了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 avatar Nov 23 '24 10:11 CDHJS

@CDHJS 我本来以为是有什么新工具可以一键自动DEBUG呢,感谢回答

uqiu avatar Nov 23 '24 12:11 uqiu

在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)

CDHJS avatar Nov 23 '24 17:11 CDHJS

就咱俩在这讨论,不知道维护的大佬有没有计划修复 😢

uqiu avatar Dec 04 '24 02:12 uqiu

候选窗是作为应用的子窗口popup的形式存在,上面提到的注释掉部分代码,注释掉的正是光标跟随的部分,底层是SetWindowPos,m_client.UpdateInputPosition是通过ipc通知服务端在必要的时候SetWindowPos,两个潜在SetWindowPos的对象都是候选窗而不是父窗口

如果SetWindowPos都不支持,那还可以怎么修实在想不到了

fxliang avatar Dec 04 '24 04:12 fxliang

使用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 希望对修复这个问题有所帮助

CDHJS avatar Jan 07 '25 17:01 CDHJS

另外想请教一下m_client.UpdateInputPosition在什么情况下会使用到,在我的使用中是否有这行的版本表现并无不同 Floorp、Chromium在输入后移动窗口UI会跟着移动,其它多数应用会停留在原本的位置在按下键盘后跳到正确的位置,tao+wry/tauri移动窗口则会销毁UI或始终保持在原位,哪一种情况是正确的feature?

CDHJS avatar Jan 07 '25 17:01 CDHJS

使用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模板库的问题。

fxliang avatar Jan 08 '25 02:01 fxliang

使用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) 我不太理解为什么只有在窗口置顶时会死循环

CDHJS avatar Jan 08 '25 04:01 CDHJS

对于这个问题,我来补充一下。 我和楼主@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,在此请求开发者修复此问题。

loicaplay avatar Mar 01 '25 07:03 loicaplay

对于这个问题,我来补充一下。 我和楼主@uqiu 一样在使用pot(https://github.com/pot-app/pot-desktop) 问题基本和楼主一样,就是在打开的pot窗口中,使用小狼毫拼音输入法输入一个单词后会卡死。无法关闭pot的窗口,除非切换为其它输入法。这时会强行关闭掉这个打开的pot输入窗口(并不会关闭整个程序)。

右击Pot的托盘图标看上去能取消卡死状态。

yfdyh000 avatar Mar 01 '25 14:03 yfdyh000