Check that paragraph has a position when computing cursor position

Rename BufferView::paragraphVisible to BufferView::hasPosition to
reflect better its semantics. Add a check on the validity of paragraph
position in metrics.

In Cursor::saveBeforeDispatchPosXY, check BufferView::hasPosition
before computing position.

Finally, use caretInView in GuiCompleter::updatePopup, since this is
what is really needed here.

There still remains cases where getPos() is called without a proper
check of the metrics beforehand. Time will tell whether they are a problem.
This commit is contained in:
Jean-Marc Lasgouttes 2025-01-09 12:00:04 +01:00
parent 7d97b66233
commit 0fa3aba5c6
4 changed files with 12 additions and 9 deletions

View File

@ -3455,7 +3455,7 @@ Point BufferView::coordOffset(DocIterator const & dit) const
Point BufferView::getPos(DocIterator const & dit) const Point BufferView::getPos(DocIterator const & dit) const
{ {
if (!paragraphVisible(dit)) if (!hasPosition(dit))
return Point(-1, -1); return Point(-1, -1);
CursorSlice const & bot = dit.bottom(); CursorSlice const & bot = dit.bottom();
@ -3468,12 +3468,12 @@ Point BufferView::getPos(DocIterator const & dit) const
} }
bool BufferView::paragraphVisible(DocIterator const & dit) const bool BufferView::hasPosition(DocIterator const & dit) const
{ {
CursorSlice const & bot = dit.bottom(); CursorSlice const & bot = dit.bottom();
TextMetrics const & tm = textMetrics(bot.text()); TextMetrics const & tm = textMetrics(bot.text());
return tm.contains(bot.pit()); return tm.contains(bot.pit()) && tm.parMetrics(bot.pit()).hasPosition();
} }
@ -3585,7 +3585,7 @@ frontend::CaretGeometry const & BufferView::caretGeometry() const
bool BufferView::caretInView() const bool BufferView::caretInView() const
{ {
if (!paragraphVisible(cursor())) if (!hasPosition(cursor()))
return false; return false;
Point p; Point p;
Dimension dim; Dimension dim;

View File

@ -339,8 +339,8 @@ public:
/// ///
Point getPos(DocIterator const & dit) const; Point getPos(DocIterator const & dit) const;
/// is the paragraph of the cursor visible ? /// is there enough metrics information to compute iterator position?
bool paragraphVisible(DocIterator const & dit) const; bool hasPosition(DocIterator const & dit) const;
/// is the caret currently visible in the view /// is the caret currently visible in the view
bool caretInView() const; bool caretInView() const;
/// get the position and height of the caret /// get the position and height of the caret

View File

@ -772,7 +772,11 @@ bool Cursor::getStatus(FuncRequest const & cmd, FuncStatus & status) const
void Cursor::saveBeforeDispatchPosXY() void Cursor::saveBeforeDispatchPosXY()
{ {
getPos(beforeDispatchPosX_, beforeDispatchPosY_); // FIXME: it is known that the case where the position is not
// known exist, in particular with previews. The question is
// whether not saving the cursor position is bad in these cases.
if (bv().hasPosition(*this))
getPos(beforeDispatchPosX_, beforeDispatchPosY_);
} }

View File

@ -431,8 +431,7 @@ void GuiCompleter::updatePopup(Cursor const & cur)
void GuiCompleter::asyncUpdatePopup() void GuiCompleter::asyncUpdatePopup()
{ {
Cursor cur = gui_->bufferView().cursor(); Cursor cur = gui_->bufferView().cursor();
if (!cur.inset().completionSupported(cur) if (!cur.inset().completionSupported(cur) || !cur.bv().caretInView()) {
|| !cur.bv().paragraphVisible(cur)) {
popupVisible_ = false; popupVisible_ = false;
return; return;
} }