]> git.lyx.org Git - features.git/commitdiff
Fixup b7f6b979: make caret geometry update lazy
authorJean-Marc Lasgouttes <lasgouttes@lyx.org>
Mon, 7 Sep 2020 13:45:30 +0000 (15:45 +0200)
committerJean-Marc Lasgouttes <lasgouttes@lyx.org>
Fri, 18 Sep 2020 07:27:55 +0000 (09:27 +0200)
Instead of working around crashes in update of caret geometry, only
request it as needed. The actual computation will take place just
before painting the caret.

It might be that this is overkill and that caret geometry should be
updated unconditionally. One would have to to some timing while idle to
ascertain that.

Fixes bug #11912.

(cherry picked from commit c1f8c6c26d5480556db1500160d1df6ce79a724f)

src/frontends/qt4/GuiWorkArea.cpp
src/frontends/qt4/GuiWorkArea_Private.h
status.23x

index e8cb4c48ba45c4ac8cdc20fcc4894d31a276d0b1..2352ecd85f5c089645dffde1fad8955403949f7b 100644 (file)
@@ -243,7 +243,7 @@ GuiWorkArea::Private::Private(GuiWorkArea * parent)
   caret_visible_(false), need_resize_(false), preedit_lines_(1),
   last_pixel_ratio_(1.0), completer_(new GuiCompleter(p, p)),
   dialog_mode_(false), shell_escape_(false), read_only_(false),
-  clean_(true), externally_modified_(false)
+  clean_(true), externally_modified_(false), needs_caret_geometry_update_(true)
 {
 /* Qt on macOS and Wayland does not respect the
  * Qt::WA_OpaquePaintEvent attribute and resets the widget backing
@@ -487,7 +487,7 @@ void GuiWorkArea::scheduleRedraw(bool update_metrics)
 
        // update caret position, because otherwise it has to wait until
        // the blinking interval is over
-       d->updateCaretGeometry();
+       d->resetCaret();
 
        LYXERR(Debug::WORKAREA, "WorkArea::redraw screen");
        viewport()->update();
@@ -587,7 +587,7 @@ void GuiWorkArea::Private::resizeBufferView()
        buffer_view_->resize(p->viewport()->width(), p->viewport()->height());
        if (caret_in_view)
                buffer_view_->scrollToCursor();
-       updateCaretGeometry();
+       resetCaret();
 
        // Update scrollbars which might have changed due different
        // BufferView dimension. This is especially important when the
@@ -605,6 +605,17 @@ void GuiWorkArea::Private::resizeBufferView()
 }
 
 
+void GuiWorkArea::Private::resetCaret()
+{
+       // Don't start blinking if the cursor isn't on screen.
+       if (!buffer_view_->caretInView())
+               return;
+
+       needs_caret_geometry_update_ = true;
+       caret_visible_ = true;
+}
+
+
 void GuiWorkArea::Private::updateCaretGeometry()
 {
        // we cannot update geometry if not ready and we do not need to if
@@ -637,18 +648,19 @@ void GuiWorkArea::Private::updateCaretGeometry()
                && completer_->completionAvailable()
                && !completer_->popupVisible()
                && !completer_->inlineVisible();
-       caret_visible_ = true;
 
        caret_->update(point.x_, point.y_, h, l_shape, isrtl, completable);
+       needs_caret_geometry_update_ = false;
 }
 
 
+
 void GuiWorkArea::Private::showCaret()
 {
        if (caret_visible_)
                return;
 
-       updateCaretGeometry();
+       resetCaret();
        p->viewport()->update();
 }
 
@@ -1359,8 +1371,14 @@ void GuiWorkArea::paintEvent(QPaintEvent * ev)
        d->paintPreeditText(pain);
 
        // and the caret
-       if (d->caret_visible_)
+       // FIXME: the code would be a little bit simpler if caret geometry
+       // was updated unconditionally. Some profiling is required to see
+       // how expensive this is (especially when idle).
+       if (d->caret_visible_) {
+               if (d->needs_caret_geometry_update_)
+                       d->updateCaretGeometry();
                d->caret_->draw(pain, d->buffer_view_->horizScrollOffset());
+       }
 
        d->updateScreen(ev->rect());
 
index 6342eaba4ac153fc7b1bf6201453ba39f5bd140b..39130162ad0572d1f16ff2a5447ebd902a155bdf 100644 (file)
@@ -85,6 +85,8 @@ struct GuiWorkArea::Private
 
        ///
        void dispatch(FuncRequest const & cmd0);
+       /// Make caret visible and signal that its geometry needs to be updated
+       void resetCaret();
        /// recompute the shape and position of the caret
        void updateCaretGeometry();
        /// show the caret if it is not visible
@@ -169,6 +171,8 @@ struct GuiWorkArea::Private
        bool clean_;
        ///
        bool externally_modified_;
+       ///
+       bool needs_caret_geometry_update_;
 
 }; // GuiWorkArea
 
index 57da79c4e526bb5698a432df7b1d45bc9ba57ede..b2e60f92de5e43eb73e73691859a4b70d9d5d01e 100644 (file)
@@ -113,6 +113,8 @@ What's new
 
 - Localize some previously unlocalized strings (bug 11954 ).
 
+- Fix bug where cursor blinks at the wrong position after changing layout (bug 11912).
+
 
 * INTERNALS