weasel
weasel copied to clipboard
Windows 11 edge/Chrome中打字总是从光标位置左边飞入输入框
请问是否有办法解决。谢谢!
刚在没有外接显示器的情况下,又测试了。 第一次打,还是“飞入”感觉。输入一半,删除编码区,那么就没有“飞入”的感觉(应该是找到了输入点)。
这个问题确实存在,在 chrome 内核的浏览器或其他产品中会有这个问题。 经过调试发现,这个现象跟 void WeaselPanel::MoveTo(RECT const& rc) 函数有关,当在 chrome 的 Input 框中打字时 rc.left 的值 不准确。
原因分析
中文输入状态下,按下字符后,每次按键 WeaselPanel::MoveTo 函数都会被调用多次(大概是7-9次样子),此时 rc.left 的值是不稳定的(部分值比实际位置 小,通常出现在第 2-4 次),会导致楼主提到的现象。
上图中红色字体,3个值就是导致这个问题的原因。
临时解决方案
为了解决这个问题,我用了临时的解决方案(WIN11下测试正常),应该不是最佳解决方案 这个方案的思路就是取 m_composing_count == 5 时候的值(跳过不稳定的值),避免闪烁。 以下的程序在解决闪烁问题的基础上,也实现了候选框不随着光标移动。
void WeaselPanel::MoveTo(RECT const& rc) {
if (!m_layout)
return; // avoid handling nullptr in _RepositionWindow
m_redraw_by_monitor_change = false;
if (m_status.composing) {
++m_composing_count;
} else {
m_composing_count = 0;
m_composing_moved = false;
}
if (1 == m_composing_count) {
m_composing_count1_pos = rc.left;
}
// if (5 == m_composing_count) {
// m_composing_count5_pos = rc.left;
//}
const int x_offeset = 2;
// if ascii_tip_follow_cursor set, move tip icon to mouse cursor
if (m_style.ascii_tip_follow_cursor && m_ctx.empty() &&
(!m_status.composing) && m_layout->ShouldDisplayStatusIcon()) {
// ascii icon follow cursor
POINT p;
::GetCursorPos(&p);
RECT irc{p.x - STATUS_ICON_SIZE, p.y - STATUS_ICON_SIZE, p.x, p.y};
m_inputPos = irc;
_RepositionWindow(true);
RedrawWindow();
} else if (!m_status.composing || // 除这个条件外,其他条件都是在 composing
// 状态下执行的
((abs(rc.left - m_composing_count1_pos) != x_offeset || // wps
abs(rc.left - m_composing_count1_pos) != x_offeset) && // chrome
(5 == m_composing_count &&
!m_composing_moved)) || // m_composing_count == 5
// 的时候位置是准确的
abs(rc.bottom - m_inputPos.bottom) != 6 ||
(abs(rc.bottom - m_inputPos.bottom) == 6 &&
rc.left < m_inputPos.left && m_composing_count > 5)) {
// in some apps like word 2021, with inline_preedit set,
// bottom of rc would flicker 1 px or 2, make the candidate flickering
if (m_status.composing && !m_composing_moved) {
m_composing_moved = true;
}
m_inputPos = rc;
m_inputPos.OffsetRect(-x_offeset, 6);
// buffer current m_istorepos status
bool m_istorepos_buf = m_istorepos;
// with parameter to avoid vertical flicker
_RepositionWindow(true);
// m_istorepos status changed by _RepositionWindow, or tips to show,
// redrawing is required
if (m_istorepos != m_istorepos_buf || !m_ctx.aux.empty() ||
m_layout->ShouldDisplayStatusIcon() || m_redraw_by_monitor_change)
RedrawWindow();
}
}
其他说明
而在 【记事本】等程序中,则不会出现这种情况。
谢谢!请问您这个如何使用,我也测试一下。再次感谢!
谢谢!请问您这个如何使用,我也测试一下。再次感谢!
WeaselUI.zip 是 WeaselPanel.cpp WeaselPanel.h ,可以自己编译 win11下没有问题,win10 没有充分测试 WeaselUI.zip
weasel-1.0.8.2-installer.zip 是编译好的完整版: weasel-1.0.8.2-installer.zip
的确好了很多。暂时先用着,等着fxliang大大更新。谢谢!
的确好了很多。暂时先用着,等着fxliang大大更新。谢谢!
不客气
不是很确定,是不是和异步编辑相关联。在ui里过滤其实可能不是最好的办法
考虑试下在这个位置考虑处理一下可能会更加合适
https://github.com/rime/weasel/blob/master/WeaselTSF/Composition.cpp#L388
不是很确定,是不是和异步编辑相关联。在ui里过滤其实可能不是最好的办法
考虑试下在这个位置考虑处理一下可能会更加合适
https://github.com/rime/weasel/blob/master/WeaselTSF/Composition.cpp#L388
这个问题应该是一直存在,我每天都会查看并下载安装最新的测试版。期望可以得到解决。
嘿嘿,又来催促了。看着新的master,还是没解决这个,心里着急😄
谢谢!请问您这个如何使用,我也测试一下。再次感谢!
WeaselUI.zip 是 WeaselPanel.cpp WeaselPanel.h ,可以自己编译 win11下没有问题,win10 没有充分测试 WeaselUI.zip
试着自己编译,会发生以下错误。 WeaselUI/WeaselPanel.h:149:7: error: code should be clang-formatted [-Wclang-format-violations] long ^ WeaselUI/WeaselPanel.h:150:25: error: code should be clang-formatted [-Wclang-format-violations] m_composing_count; // ��¼ composing ״̬�£����� MoveTo �����Ĵ��� WeaselUI/WeaselPanel.h:151:68: error: code should be clang-formatted [-Wclang-format-violations] long m_composing_count1_pos; // composing ״̬�� �� ��¼�״ν���
@liangzhi52 可否帮助解决一下。谢谢!
烦请大佬们关注@fxliang
烦请大佬们关注@fxliang
没有Windows 11机器,没有复现问题,关注不了。等风吧
@liangzhi52 有办法解决吗?适配最新的master。 您之前发的,我编译后,总是出现错误:Please lint your code by "./clang-format.sh -n". 可有偿。感谢!
@liangzhi52 有办法解决吗?适配最新的master。 您之前发的,我编译后,总是出现错误:Please lint your code by "./clang-format.sh -n". 可有偿。感谢!
安装llvm 18.1.6或更高版本,确保clang-format 在path中,在git-bash 中切换到代码目录,执行上面提示的命令,更新提交ci编译
谢谢回复。我其实之前也默默的捐赠了 冰阔落🥤 :)
按照您的指导,跟着GPT的建议,竟然成功了。导师的每一句话都是有用的😄。谢谢!
@wzv5 感觉这个问题是不是也与最近您的几个pr有关系。请帮助查看。谢谢!
@wzv5 感觉这个问题是不是也与最近您的几个pr有关系。请帮助查看。谢谢!
呃,这么强迫症么。大概看起来像是 chrome 的问题? 我之前没注意过这个问题,刚测试了一下,确实存在,但频率挺低的,也不影响使用,我决定无视了。。
+1. 打字快的了,感觉非常明显。好像是会记录上次光标的位置
这个问题确实存在,在 chrome 内核的浏览器或其他产品中会有这个问题。 经过调试发现,这个现象跟 void WeaselPanel::MoveTo(RECT const& rc) 函数有关,当在 chrome 的 Input 框中打字时 rc.left 的值 不准确。
原因分析
中文输入状态下,按下字符后,每次按键 WeaselPanel::MoveTo 函数都会被调用多次(大概是7-9次样子),此时 rc.left 的值是不稳定的(部分值比实际位置 小,通常出现在第 2-4 次),会导致楼主提到的现象。
上图中红色字体,3个值就是导致这个问题的原因。
临时解决方案
为了解决这个问题,我用了临时的解决方案(WIN11下测试正常),应该不是最佳解决方案 这个方案的思路就是取 m_composing_count == 5 时候的值(跳过不稳定的值),避免闪烁。 以下的程序在解决闪烁问题的基础上,也实现了候选框不随着光标移动。
void WeaselPanel::MoveTo(RECT const& rc) { if (!m_layout) return; // avoid handling nullptr in _RepositionWindow m_redraw_by_monitor_change = false;
if (m_status.composing) { ++m_composing_count; } else { m_composing_count = 0; m_composing_moved = false; }
if (1 == m_composing_count) { m_composing_count1_pos = rc.left; }
// if (5 == m_composing_count) { // m_composing_count5_pos = rc.left; //}
const int x_offeset = 2;
// if ascii_tip_follow_cursor set, move tip icon to mouse cursor if (m_style.ascii_tip_follow_cursor && m_ctx.empty() && (!m_status.composing) && m_layout->ShouldDisplayStatusIcon()) { // ascii icon follow cursor POINT p; ::GetCursorPos(&p); RECT irc{p.x - STATUS_ICON_SIZE, p.y - STATUS_ICON_SIZE, p.x, p.y}; m_inputPos = irc; _RepositionWindow(true); RedrawWindow(); } else if (!m_status.composing || // 除这个条件外,其他条件都是在 composing // 状态下执行的 ((abs(rc.left - m_composing_count1_pos) != x_offeset || // wps abs(rc.left - m_composing_count1_pos) != x_offeset) && // chrome (5 == m_composing_count && !m_composing_moved)) || // m_composing_count == 5 // 的时候位置是准确的 abs(rc.bottom - m_inputPos.bottom) != 6 || (abs(rc.bottom - m_inputPos.bottom) == 6 && rc.left < m_inputPos.left && m_composing_count > 5)) { // in some apps like word 2021, with inline_preedit set, // bottom of rc would flicker 1 px or 2, make the candidate flickering
if (m_status.composing && !m_composing_moved) { m_composing_moved = true; } m_inputPos = rc; m_inputPos.OffsetRect(-x_offeset, 6); // buffer current m_istorepos status bool m_istorepos_buf = m_istorepos; // with parameter to avoid vertical flicker _RepositionWindow(true); // m_istorepos status changed by _RepositionWindow, or tips to show, // redrawing is required if (m_istorepos != m_istorepos_buf || !m_ctx.aux.empty() || m_layout->ShouldDisplayStatusIcon() || m_redraw_by_monitor_change) RedrawWindow();} }
其他说明
而在 【记事本】等程序中,则不会出现这种情况。
这个真的能解决。