Use a backing store on macOS

Qt on macOS does not respect the Qt::WA_OpaquePaintEvent attribute and
clears the widget backing store at each update. Therefore, we use our
own backing store in this case.

This restores a simplified version of the code that was removed at 24c29908.
This commit is contained in:
Jean-Marc Lasgouttes 2017-11-25 12:31:11 +01:00
parent 28029074b2
commit 2316435f2f
2 changed files with 53 additions and 2 deletions

View File

@ -304,6 +304,7 @@ void GuiWorkArea::init()
generateSyntheticMouseEvent();
});
d->resetScreen();
// With Qt4.5 a mouse event will happen before the first paint event
// so make sure that the buffer view has an up to date metrics.
d->buffer_view_->resize(viewport()->width(), viewport()->height());
@ -1231,12 +1232,15 @@ void GuiWorkArea::paintEvent(QPaintEvent * ev)
// LYXERR(Debug::PAINTING, "paintEvent begin: x: " << rc.x()
// << " y: " << rc.y() << " w: " << rc.width() << " h: " << rc.height());
if (d->need_resize_ || pixelRatio() != d->last_pixel_ratio_)
if (d->need_resize_ || pixelRatio() != d->last_pixel_ratio_) {
d->resetScreen();
d->resizeBufferView();
}
d->last_pixel_ratio_ = pixelRatio();
GuiPainter pain(viewport(), pixelRatio());
GuiPainter pain(d->screenDevice(), pixelRatio());
d->buffer_view_->draw(pain, d->caret_visible_);
// The preedit text, if needed
@ -1245,6 +1249,9 @@ void GuiWorkArea::paintEvent(QPaintEvent * ev)
// and the caret
if (d->caret_visible_)
d->caret_->draw(pain);
d->updateScreen(ev->rect());
ev->accept();
}

View File

@ -20,6 +20,14 @@
#include <QMouseEvent>
#include <QTimer>
#ifdef Q_OS_MAC
/* Qt on macOS 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 this case */
#define LYX_BACKINGSTORE 1
#include <QPainter>
#endif
namespace lyx {
class Buffer;
@ -99,6 +107,38 @@ struct GuiWorkArea::Private
void paintPreeditText(GuiPainter & pain);
void resetScreen() {
#ifdef LYX_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
#endif
}
QPaintDevice * screenDevice() {
#ifdef LYX_BACKINGSTORE
return &screen_;
#else
return p->viewport();
#endif
}
#ifdef LYX_BACKINGSTORE
void updateScreen(QRectF const & rc) {
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);
}
#else
void updateScreen(QRectF const & ) {}
#endif
///
GuiWorkArea * p;
///
@ -106,6 +146,10 @@ struct GuiWorkArea::Private
///
GuiView * lyx_view_;
#ifdef LYX_BACKINGSTORE
///
QImage screen_;
#endif
///
CaretWidget * caret_;
/// is the caret currently displayed