x_(0), caret_width_(0)
{}
- void draw(QPainter & painter)
+ /* Draw the caret. Parameter \c horiz_offset is not 0 when there
+ * has been horizontal scrolling in current row
+ */
+ void draw(QPainter & painter, int horiz_offset)
{
if (!rect_.isValid())
return;
- int y = rect_.top();
- int l = x_ - rect_.left();
- int r = rect_.right() - x_;
- int bot = rect_.bottom();
+ int const x = x_ - horiz_offset;
+ int const y = rect_.top();
+ int const l = x_ - rect_.left();
+ int const r = rect_.right() - x_;
+ int const bot = rect_.bottom();
// draw vertical line
- painter.fillRect(x_, y, caret_width_, rect_.height(), color_);
+ painter.fillRect(x, y, caret_width_, rect_.height(), color_);
// draw RTL/LTR indication
painter.setPen(color_);
if (l_shape_) {
if (rtl_)
- painter.drawLine(x_, bot, x_ - l, bot);
+ painter.drawLine(x, bot, x - l, bot);
else
- painter.drawLine(x_, bot, x_ + caret_width_ + r, bot);
+ painter.drawLine(x, bot, x + caret_width_ + r, bot);
}
// draw completion triangle
int m = y + rect_.height() / 2;
int d = TabIndicatorWidth - 1;
if (rtl_) {
- painter.drawLine(x_ - 1, m - d, x_ - 1 - d, m);
- painter.drawLine(x_ - 1, m + d, x_ - 1 - d, m);
+ painter.drawLine(x - 1, m - d, x - 1 - d, m);
+ painter.drawLine(x - 1, m + d, x - 1 - d, m);
} else {
- painter.drawLine(x_ + caret_width_, m - d, x_ + caret_width_ + d, m);
- painter.drawLine(x_ + caret_width_, m + d, x_ + caret_width_ + d, m);
+ painter.drawLine(x + caret_width_, m - d, x + caret_width_ + d, m);
+ painter.drawLine(x + caret_width_, m + d, x + caret_width_ + d, m);
}
}
}
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);
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();
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);
&& !completer_->inlineVisible();
caret_visible_ = true;
- //int cur_x = buffer_view_->getPos(cur).x_;
- // We may have decided to slide the cursor row so that caret
- // is visible.
- point.x_ -= buffer_view_->horizScrollOffset();
-
caret_->update(point.x_, point.y_, h, l_shape, isrtl, completable);
}
return;
updateCaretGeometry();
- p->viewport()->update(caret_->rect());
+ p->viewport()->update();
}
caret_visible_ = false;
//if (!qApp->focusWidget())
- p->viewport()->update(caret_->rect());
+ p->viewport()->update();
}
}
+void GuiWorkArea::Private::resetScreen()
+{
+ if (use_backingstore_) {
+ int const pr = p->pixelRatio();
+ screen_ = QImage(static_cast<int>(pr * p->viewport()->width()),
+ static_cast<int>(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
// and the caret
if (d->caret_visible_)
- d->caret_->draw(pain);
+ d->caret_->draw(pain, d->buffer_view_->horizScrollOffset());
d->updateScreen(ev->rect());