[LyX/master] Fix notifyCursorLeavesOrEnters with selections
Jean-Marc Lasgouttes
lasgouttes at lyx.org
Fri Jun 26 17:52:04 UTC 2026
commit 4dd20ebe45f3f8b1e6880edcee7e49cde29d392f
Author: Jean-Marc Lasgouttes <lasgouttes at lyx.org>
Date: Tue Jun 16 17:15:54 2026 +0200
Fix notifyCursorLeavesOrEnters with selections
It may happen that cursor "old" points deeper inside an inset than the
anchor when doing a selection. This can happens for example when
selecting with the mouse, where BufferView::mouseEventDispatch() will
first put the main DocIterator inside a nested inset and later will
correct that to have a depth compatible with the anchor.
When this happens, notifyCursorLeavesOrEnters could notify a `leave'
to the selected insets, which is not desirable.
This commit fixes the function so that, when selecting, it only
considers slices that are compatible with the anchors of both old and
new cursor.
Fixes bug #13338 (see #13305 for a discussion).
---
src/Cursor.cpp | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/src/Cursor.cpp b/src/Cursor.cpp
index 3141660515..2b713a80f5 100644
--- a/src/Cursor.cpp
+++ b/src/Cursor.cpp
@@ -2453,15 +2453,34 @@ void Cursor::sanitize()
bool notifyCursorLeavesOrEnters(Cursor const & old, Cursor & cur)
{
+ // handle selections: the real depth is the deepest element shared
+ // by cursor and anchor.
+ // First the new cursor...
+ size_type real_cur_depth = cur.depth();
+ if (cur.selection())
+ for (size_type i = 0 ; i < min(cur.depth(), cur.realAnchor().depth()) ; ++i)
+ if (&cur[i].inset() != &cur.realAnchor()[i].inset()) {
+ real_cur_depth = i;
+ break;
+ }
+ // ... and then the old one.
+ size_type real_old_depth = old.depth();
+ if (old.selection())
+ for (size_type i = 0 ; i < min(old.depth(), old.realAnchor().depth()) ; ++i)
+ if (&old[i].inset() != &old.realAnchor()[i].inset()) {
+ real_old_depth = i;
+ break;
+ }
+
// find inset in common
size_type i;
- for (i = 0; i < old.depth() && i < cur.depth(); ++i) {
+ for (i = 0; i < real_old_depth && i < real_cur_depth; ++i) {
if (old[i].realInset() != cur[i].realInset())
break;
}
// update words if we just moved to another paragraph
- if (i == old.depth() && i == cur.depth()
+ if (i == real_old_depth && i == real_cur_depth
&& !cur.buffer()->isClean()
&& cur.inTexted() && old.inTexted()
&& cur.pit() != old.pit()) {
@@ -2470,7 +2489,7 @@ bool notifyCursorLeavesOrEnters(Cursor const & old, Cursor & cur)
// notify everything on top of the common part in old cursor,
// but stop if the inset claims the cursor to be invalid now
- for (size_type j = i; j < old.depth(); ++j) {
+ for (size_type j = i; j < real_old_depth; ++j) {
Cursor inset_pos = old;
inset_pos.resize(j + 1);
if (old[j].realInset()->notifyCursorLeaves(inset_pos, cur))
@@ -2479,7 +2498,7 @@ bool notifyCursorLeavesOrEnters(Cursor const & old, Cursor & cur)
// notify everything on top of the common part in new cursor,
// but stop if the inset claims the cursor to be invalid now
- for (; i < cur.depth(); ++i) {
+ for (; i < real_cur_depth; ++i) {
if (cur[i].realInset()->notifyCursorEnters(old, cur))
return true;
}
More information about the lyx-cvs
mailing list