Skip to content

Commit c81e9b8

Browse files
da-liiiclaude
andauthored
[1237] 鼠标拖选期间光标保持在按下位置 (#4427)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1450072 commit c81e9b8

2 files changed

Lines changed: 68 additions & 0 deletions

File tree

devel/1237.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# [1237] 鼠标拖选期间光标位置被改变
2+
3+
## 1 相关文档
4+
- [dddd.md](dddd.md) - 任务文档模板
5+
6+
## 2 任务相关的代码文件
7+
- src/Edit/Interface/edit_mouse.cpp
8+
9+
## 3 如何测试
10+
11+
### 3.1 确定性测试(单元测试)
12+
13+
本任务为鼠标交互时序行为,现有测试框架无法模拟真实鼠标拖选事件序列,
14+
无对应的自动化单元测试。
15+
16+
### 3.2 非确定性测试(文档验证)
17+
18+
手动 GUI 验证(`xmake b stem && xmake r stem` 启动后):
19+
20+
1. **拖选期间光标不动**:按住左键从某位置开始拖动,选区随鼠标扩展,
21+
但闪烁光标始终停留在按下左键的位置,不跟随鼠标移动
22+
2. **松开后光标仍回按下位置**:拖到别处松开左键,选区保留,光标仍在按下位置
23+
3. **普通点击行为不变**:单击某处(无拖动),光标仍跳到点击处
24+
4. **双击/三击选词选段**:双击选中单词、三击选中整段,光标位置不受影响
25+
5. **Shift+点击扩展选区**:已有选区时 Shift+点击,选区扩展,行为正常
26+
6. **图文混合场景**:在含图片/公式附近拖选,跨越图形边界时选区正常,
27+
不因 `inside_graphics` 状态切换出现光标跳变
28+
7. **拖选后编辑**:拖选一段文字后直接输入字符,选中文本被替换,
29+
替换发生在按下位置一侧的选区(与修改前替换结果一致)
30+
31+
## 4 如何提交
32+
33+
提交前执行以下最少步骤:
34+
35+
```bash
36+
gf fmt --changed-since=main
37+
```
38+
39+
## 5 What
40+
41+
修复鼠标拖选期间光标位置被改变的问题:
42+
43+
1. `mouse_drag``go_to` 前保存 `tp`,计算完选区后恢复,拖动期间光标固定在按下位置
44+
2. `mouse_select``drag=true`(拖选结束)时恢复到进入函数前的 `tp`
45+
单纯点击(`drag=false`)行为不变,仍跳到点击处
46+
47+
## 6 Why
48+
49+
按住鼠标左键进入选择模式后,移动鼠标的过程中光标位置会跟随鼠标改变;
50+
松开左键时光标又被移动到松开位置。预期:光标应保持在按下左键时的位置。
51+
52+
## 7 How
53+
54+
鼠标拖选关键路径(`src/Edit/Interface/edit_mouse.cpp`):
55+
56+
- `press-left``mouse_click()`:记录锚点 `start_x/start_y`
57+
- `dragging-left``mouse_drag()``go_to(x, y)` 把光标 `tp` 移到鼠标位置
58+
- `release-left``mouse_select(x, y, mods, drag=true)`:再次 `go_to(x, y)`
59+
60+
通过调试日志确认:`set_selection`/`select()` 只更新选区,不动 `tp`
61+
拖动及松开过程中光标移动完全来自两处 `go_to(x, y)`
62+
63+
因此在这两处 `go_to(x, y)` 前后保存/恢复 `tp`:拖动期间与拖选结束时
64+
光标都保持在按下位置,而点击(`drag=false`)路径不受影响。

src/Edit/Interface/edit_mouse.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ void
175175
edit_interface_rep::mouse_drag (SI x, SI y) {
176176
if (inside_graphics () && is_in_graphics_mode) return;
177177
if (mouse_message ("drag", x, y)) return;
178+
path last_tp= tp; // 拖选期间光标应保持在按下左键时的位置
178179
go_to (x, y);
179180
end_x= x;
180181
end_y= y;
@@ -188,6 +189,7 @@ edit_interface_rep::mouse_drag (SI x, SI y) {
188189
p2 = temp;
189190
}
190191
set_selection (p1, p2);
192+
go_to (last_tp);
191193
notify_change (THE_SELECTION);
192194
}
193195

@@ -211,6 +213,7 @@ edit_interface_rep::mouse_select (SI x, SI y, int mods, bool drag) {
211213
bool b0= inside_graphics (false);
212214
bool b = inside_graphics ();
213215
if (b) g= get_graphics ();
216+
path last_tp= tp; // 拖选结束时, 光标保持在按下左键时的位置
214217
go_to (x, y);
215218
if ((!b0 && inside_graphics (false)) || (b0 && !inside_graphics (false)))
216219
drag= false;
@@ -226,6 +229,7 @@ edit_interface_rep::mouse_select (SI x, SI y, int mods, bool drag) {
226229
set_selection (p0, p0);
227230
notify_change (THE_SELECTION);
228231
}
232+
else go_to (last_tp);
229233
if (selection_active_any ()) selection_set ("mouse", selection_get (), true);
230234
}
231235

0 commit comments

Comments
 (0)