Use backing store also with wayland platform

Like with macOS, the Wayland compositor seems to require a
backingstore when doing partial updates like we do.

This extends the mechanism that has been introduced for macOS. This
has to be done at run time, not compile time.
This commit is contained in:
Jean-Marc Lasgouttes 2019-07-13 16:21:37 +02:00
parent db638018d9
commit 575761c665
2 changed files with 64 additions and 47 deletions

View File

@ -235,13 +235,27 @@ SyntheticMouseEvent::SyntheticMouseEvent()
GuiWorkArea::Private::Private(GuiWorkArea * parent) GuiWorkArea::Private::Private(GuiWorkArea * parent)
: p(parent), buffer_view_(0), lyx_view_(0), : p(parent), buffer_view_(0), lyx_view_(0), caret_(0),
caret_(0), caret_visible_(false), caret_visible_(false), need_resize_(false), preedit_lines_(1),
need_resize_(false), preedit_lines_(1), last_pixel_ratio_(1.0), completer_(new GuiCompleter(p, p)),
last_pixel_ratio_(1.0), dialog_mode_(false), shell_escape_(false), read_only_(false),
completer_(new GuiCompleter(p, p)), dialog_mode_(false), shell_escape_(false), clean_(true), externally_modified_(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; int const time = QApplication::cursorFlashTime() / 2;
if (time > 0) { if (time > 0) {
caret_timeout_.setInterval(time); caret_timeout_.setInterval(time);
@ -1261,6 +1275,41 @@ void GuiWorkArea::Private::paintPreeditText(GuiPainter & pain)
} }
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) void GuiWorkArea::paintEvent(QPaintEvent * ev)
{ {
// Do not trigger the painting machinery if we are not ready (see // Do not trigger the painting machinery if we are not ready (see

View File

@ -20,14 +20,6 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <QTimer> #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 { namespace lyx {
class Buffer; class Buffer;
@ -107,37 +99,12 @@ struct GuiWorkArea::Private
void paintPreeditText(GuiPainter & pain); void paintPreeditText(GuiPainter & pain);
void resetScreen() { /// Prepare screen for next painting
#ifdef LYX_BACKINGSTORE void resetScreen();
int const pr = p->pixelRatio(); /// Where painting takes place
screen_ = QImage(static_cast<int>(pr * p->viewport()->width()), QPaintDevice * screenDevice();
static_cast<int>(pr * p->viewport()->height()), /// Put backingstore to screen if necessary
QImage::Format_ARGB32_Premultiplied); void updateScreen(QRectF const & rc);
# 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; GuiWorkArea * p;
@ -146,10 +113,11 @@ struct GuiWorkArea::Private
/// ///
GuiView * lyx_view_; GuiView * lyx_view_;
#ifdef LYX_BACKINGSTORE /// Do we need an intermediate image when painting (for now macOS and Wayland)
bool use_backingstore_;
/// ///
QImage screen_; QImage screen_;
#endif
/// ///
CaretWidget * caret_; CaretWidget * caret_;
/// is the caret currently displayed /// is the caret currently displayed