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

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

Open
3 tasks done
uqiu opened this issue Nov 20, 2024 · 14 comments
Open
3 tasks done

Comments

@uqiu
Copy link

uqiu commented Nov 20, 2024

上报前请检查

  • 我遇到的问题没有其他人在 issue 里提到过
  • 我的小狼毫版本于 rime/weasel 下载
  • 我在使用小狼毫的最新发布版本,或最新发布版本后的 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,暂时不知道是谁的锅
tauri-apps/tauri#6879

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

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

预期行为
正常输入

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

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

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

@uqiu
Copy link
Author

uqiu commented Nov 20, 2024

pot-app/pot-desktop#60

↑另外的讨论

@uqiu
Copy link
Author

uqiu commented Nov 20, 2024

我编译了之前据说没问题的版本.
各位测试看看
pot-app/pot-desktop#870 (comment)

CDHJS added a commit to CDHJS/weasel that referenced this issue Nov 22, 2024
@CDHJS
Copy link

CDHJS commented Nov 22, 2024

问题可能出在

m_client.UpdateInputPosition(rc);
_cand->UpdateInputPosition(rc);

注释掉任意一行都可以正常打字

@uqiu
Copy link
Author

uqiu commented Nov 22, 2024

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

@CDHJS
Copy link

CDHJS commented Nov 22, 2024

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

我最早的思路其实是去找“winapi获取活动窗口句柄”误打误撞找到了

hwnd = GetForegroundWindow();

然后fork并删掉了整个代码块,我没装C++的编译环境所以用Actions编译,也是误打误撞删掉了
_pTextService->_SetCompositionPosition(rc);

发现bug不存在了,上面的commit只是错误的以为bug来源是GetForegroundWindow把整块代码扔给GPT去重写了而已
以及我到现在没找到m_client是什么(VSCode只能找字符串),但我注释掉之后bug消失了,我fork的actions里最新的结果你可以试试

@CDHJS
Copy link

CDHJS commented Nov 23, 2024

我测试了Chromium,Floorp,Edge,VSCode,Steam,wails,单独tao,winit+wry,webview2-rs(wry的上游)都正常,只有tao+wry和tauri会卡死,不过删除m_client.UpdateInputPosition(rc);的版本能正常运行,以及删除

SetWindowPos(HWND_TOPMOST, x, y, 0, 0,
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW);

也能正常运行,但定位会在桌面左上角不动
卡死时【Webview tauri主进程 算法服务】加起来的CPU会有一个接近单核满载的占用,并且其中一个Webview进程内存缓慢增加(内存泄露?)
如果有托盘图标菜单的话右键托盘图标会解除卡死并关闭菜单,操作了几步就需要右键几下
如果点击了别的窗口卡死的UI会跟着新的窗口移动,如果此时输入会出现两个UI,新出现的UI正常

@uqiu
Copy link
Author

uqiu commented Nov 23, 2024

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

@CDHJS
Copy link

CDHJS commented Nov 23, 2024

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

@uqiu
Copy link
Author

uqiu commented Dec 4, 2024

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

@fxliang
Copy link
Contributor

fxliang commented Dec 4, 2024

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

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

@CDHJS
Copy link

CDHJS commented Jan 7, 2025

使用api-monitor可以观察到图片
GetMessageW的DefSubclassProc出现了死循环,在wry中可以找到:https://github.com/tauri-apps/wry/blob/cbbcccc38af7d900a0f8f7fa5ea5e6667765ed81/src/webview2/mod.rs#L1158-L1161
删除后卡死消失
在此仓库可以找到:

MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged)

可能是诱发此bug的原因
附上chatGPT的解释:
图片
@fxliang 希望对修复这个问题有所帮助

@CDHJS
Copy link

CDHJS commented Jan 7, 2025

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

@fxliang
Copy link
Contributor

fxliang commented Jan 8, 2025

使用api-monitor可以观察到图片 GetMessageW的DefSubclassProc出现了死循环,在wry中可以找到:https://github.com/tauri-apps/wry/blob/cbbcccc38af7d900a0f8f7fa5ea5e6667765ed81/src/webview2/mod.rs#L1158-L1161 删除后卡死消失 在此仓库可以找到:

MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged)

可能是诱发此bug的原因
附上chatGPT的解释:
图片
@fxliang 希望对修复这个问题有所帮助

一些猜想:WeaselUI中未注册WM_WINDOWPOSCHANGED 的响应回调,那这个消息会向上传递到上一层应用的窗口对象;然后如你指出的状态似乎这个应用框架会手动触发一次WM_WINDOWPOSCHANGED消息,tsf中有注册如果光标位置变化的话,会响应调整输入框位置,这个又会调用一次SetWindowPos,于是死循环了?

weasel/include/wtl/atlframe.h是WTL的模板库代码,这个是微软官方的模板框架,完成度已经极高,相比这次报问题的框架的完成度,高的肯定不是一个数量级,基本不可能是WTL模板库的问题。

@CDHJS
Copy link

CDHJS commented Jan 8, 2025

使用api-monitor可以观察到图片 GetMessageW的DefSubclassProc出现了死循环,在wry中可以找到:https://github.com/tauri-apps/wry/blob/cbbcccc38af7d900a0f8f7fa5ea5e6667765ed81/src/webview2/mod.rs#L1158-L1161 删除后卡死消失 在此仓库可以找到:

MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged)

可能是诱发此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)
我不太理解为什么只有在窗口置顶时会死循环

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

No branches or pull requests

3 participants