X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FGuiWorkArea.cpp;h=95cff6d5ec30f8c7d8de4903e3750115022cff16;hb=b7f6b979d0f889f08e735f35378bb20ba3788b4b;hp=5ef177dc37fb12bb8f5685f1459d015d90a3ebc1;hpb=7c35081d0c4e48b2ff73c5a11c5446f5288802af;p=lyx.git diff --git a/src/frontends/qt4/GuiWorkArea.cpp b/src/frontends/qt4/GuiWorkArea.cpp index 5ef177dc37..95cff6d5ec 100644 --- a/src/frontends/qt4/GuiWorkArea.cpp +++ b/src/frontends/qt4/GuiWorkArea.cpp @@ -239,13 +239,27 @@ SyntheticMouseEvent::SyntheticMouseEvent() GuiWorkArea::Private::Private(GuiWorkArea * parent) -: p(parent), buffer_view_(0), lyx_view_(0), - caret_(0), 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) -{ +: p(parent), buffer_view_(0), lyx_view_(0), caret_(0), + 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) +{ +/* Qt on macOS and Wayland does not respect the + * Qt::WA_OpaquePaintEvent attribute and resets the widget backing + * store at each update. Therefore, we use our own backing store in + * these two cases. */ +#if QT_VERSION >= 0x050000 + use_backingstore_ = guiApp->platformName() == "cocoa" + || guiApp->platformName().contains("wayland"); +#else +# ifdef Q_OS_MAC + use_backingstore_ = true; +# else + use_backingstore_ = false; +# endif +#endif + int const time = QApplication::cursorFlashTime() / 2; if (time > 0) { caret_timeout_.setInterval(time); @@ -429,12 +443,16 @@ void GuiWorkArea::startBlinkingCaret() if (view().busy()) return; - Point p; - int h = 0; - d->buffer_view_->caretPosAndHeight(p, h); - // Don't start blinking if the cursor isn't on screen. - if (!d->buffer_view_->cursorInView(p, h)) - return; + // we cannot update geometry if not ready and we do not need to if + // caret is not in view. + if (!d->buffer_view_->buffer().undo().activeUndoGroup()) { + Point p; + int h = 0; + d->buffer_view_->caretPosAndHeight(p, h); + // Don't start blinking if the cursor isn't on screen. + if (!d->buffer_view_->cursorInView(p, h)) + return; + } d->showCaret(); @@ -597,6 +615,11 @@ void GuiWorkArea::Private::resizeBufferView() void GuiWorkArea::Private::updateCaretGeometry() { + // we cannot update geometry if not ready and we do not need to if + // caret is not in view. + if (buffer_view_->buffer().undo().activeUndoGroup()) + return; + Point point; int h = 0; buffer_view_->caretPosAndHeight(point, h); @@ -1257,6 +1280,41 @@ void GuiWorkArea::Private::paintPreeditText(GuiPainter & pain) } +void GuiWorkArea::Private::resetScreen() +{ + if (use_backingstore_) { + int const pr = p->pixelRatio(); + screen_ = QImage(static_cast(pr * p->viewport()->width()), + static_cast(pr * p->viewport()->height()), + QImage::Format_ARGB32_Premultiplied); +# if QT_VERSION >= 0x050000 + screen_.setDevicePixelRatio(pr); +# endif + } +} + + +QPaintDevice * GuiWorkArea::Private::screenDevice() +{ + if (use_backingstore_) + return &screen_; + else + return p->viewport(); +} + + +void GuiWorkArea::Private::updateScreen(QRectF const & rc) +{ + if (use_backingstore_) { + QPainter qpain(p->viewport()); + double const pr = p->pixelRatio(); + QRectF const rcs = QRectF(rc.x() * pr, rc.y() * pr, + rc.width() * pr, rc.height() * pr); + qpain.drawImage(rc, screen_, rcs); + } +} + + void GuiWorkArea::paintEvent(QPaintEvent * ev) { // Do not trigger the painting machinery if we are not ready (see