+}
+
+
+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
+ // bug #10989). The second test triggers when in the middle of a
+ // dispatch operation.
+ if (view().busy() || d->buffer_view_->buffer().undo().activeUndoGroup()) {
+ // Since macOS has turned the screen black at this point, our
+ // backing store has to be copied to screen (this is a no-op
+ // except on macOS).
+ d->updateScreen(ev->rect());
+ // Ignore this paint event, but request a new one for later.
+ viewport()->update(ev->rect());
+ ev->accept();
+ return;
+ }
+
+ // 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_) {
+ d->resetScreen();
+ d->resizeBufferView();
+ }
+
+ d->last_pixel_ratio_ = pixelRatio();
+
+ GuiPainter pain(d->screenDevice(), pixelRatio());
+
+ d->buffer_view_->draw(pain, d->caret_visible_);
+
+ // The preedit text, if needed
+ d->paintPreeditText(pain);
+
+ // and the caret
+ if (d->caret_visible_)
+ d->caret_->draw(pain, d->buffer_view_->horizScrollOffset());
+
+ d->updateScreen(ev->rect());
+
+ ev->accept();
+}
+
+
+void GuiWorkArea::inputMethodEvent(QInputMethodEvent * e)
+{
+ LYXERR(Debug::KEY, "preeditString: " << e->preeditString()
+ << " commitString: " << e->commitString());
+
+ // insert the processed text in the document (handles undo)
+ if (!e->commitString().isEmpty()) {
+ FuncRequest cmd(LFUN_SELF_INSERT,
+ qstring_to_ucs4(e->commitString()),
+ FuncRequest::KEYBOARD);
+ dispatch(cmd);
+ // FIXME: this is supposed to remove traces from preedit
+ // string. Can we avoid calling it explicitely?
+ d->buffer_view_->updateMetrics();
+ }
+
+ // Hide the caret during the test transformation.
+ if (e->preeditString().isEmpty())
+ startBlinkingCaret();
+ else
+ stopBlinkingCaret();
+
+ if (d->preedit_string_.empty() && e->preeditString().isEmpty()) {
+ // Nothing to do
+ e->accept();
+ return;
+ }
+
+ // The preedit text and its attributes will be used in paintPreeditText
+ d->preedit_string_ = qstring_to_ucs4(e->preeditString());
+ d->preedit_attr_ = e->attributes();
+