Add lyxrc option to force the use of backing store

LyX relies on a a backing store to draw when running under macOS or
Wayland, because Qt arbitrarily overwrites parts of the workarea
before we paint (and we paint only the parts that need to be painted).
However it seems that this is also necessary on X11 when the WM theme
is translucid. Since there is no way that I know of to detect this
situation, this patch adds a LyXRC setting to manually select this
drawing strategy.

Note that using a backing store is not always a good solution, since
this disables subpixel aliasing.

At this point there is no UI for the variable.

Fixes bug #12119
This commit is contained in:
Jean-Marc Lasgouttes 2021-12-16 12:38:19 +01:00
parent 056ab33f48
commit c213eb7f75
5 changed files with 66 additions and 9 deletions

View File

@ -107,6 +107,7 @@ LexerKeyword lyxrcTags[] = {
{ "\\dialogs_iconify_with_main", LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN }, { "\\dialogs_iconify_with_main", LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN },
{ "\\display_graphics", LyXRC::RC_DISPLAY_GRAPHICS }, { "\\display_graphics", LyXRC::RC_DISPLAY_GRAPHICS },
{ "\\document_path", LyXRC::RC_DOCUMENTPATH }, { "\\document_path", LyXRC::RC_DOCUMENTPATH },
{ "\\draw_strategy", LyXRC::RC_DRAW_STRATEGY },
{ "\\editor_alternatives", LyXRC::RC_EDITOR_ALTERNATIVES }, { "\\editor_alternatives", LyXRC::RC_EDITOR_ALTERNATIVES },
{ "\\escape_chars", LyXRC::RC_ESC_CHARS }, { "\\escape_chars", LyXRC::RC_ESC_CHARS },
{ "\\example_path", LyXRC::RC_EXAMPLEPATH }, { "\\example_path", LyXRC::RC_EXAMPLEPATH },
@ -1134,6 +1135,19 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool check_format)
} }
break; break;
case RC_DRAW_STRATEGY:
if (lexrc.next()) {
string const tmp = lexrc.getString();
if (tmp == "partial")
draw_strategy = DS_PARTIAL;
else if (tmp == "backingstore")
draw_strategy = DS_BACKINGSTORE;
else {
draw_strategy = DS_PARTIAL;
LYXERR0("Unrecognized draw strategy " << tmp <<'"');
}
}
break;
case RC_LAST: case RC_LAST:
break; // this is just a dummy break; // this is just a dummy
@ -2021,10 +2035,28 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc, string const & name) c
} }
if (tag != RC_LAST) if (tag != RC_LAST)
break; break;
// fall through
case RC_DRAW_STRATEGY:
if (ignore_system_lyxrc ||
draw_strategy != system_lyxrc.draw_strategy) {
string status;
switch (draw_strategy) {
case DS_PARTIAL:
status = "partial";
break;
case DS_BACKINGSTORE:
status = "backingstore";
break;
}
os << "\\draw_strategy " << status << '\n';
}
if (tag != RC_LAST)
break;
// fall through
os << "\n#\n" os << "\n#\n"
<< "# COLOR SECTION ###################################\n" << "# COLOR SECTION ###################################\n"
<< "#\n\n"; << "#\n\n";
// fall through // fall through
case RC_SET_COLOR: case RC_SET_COLOR:
@ -2910,6 +2942,7 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
package().document_dir() = FileName(lyxrc.document_path); package().document_dir() = FileName(lyxrc.document_path);
} }
// fall through // fall through
case LyXRC::RC_DRAW_STRATEGY:
case LyXRC::RC_EDITOR_ALTERNATIVES: case LyXRC::RC_EDITOR_ALTERNATIVES:
case LyXRC::RC_ESC_CHARS: case LyXRC::RC_ESC_CHARS:
case LyXRC::RC_EXAMPLEPATH: case LyXRC::RC_EXAMPLEPATH:

View File

@ -189,6 +189,7 @@ public:
RC_VIEWER_ALTERNATIVES, RC_VIEWER_ALTERNATIVES,
RC_VISUAL_CURSOR, RC_VISUAL_CURSOR,
RC_CLOSE_BUFFER_WITH_LAST_VIEW, RC_CLOSE_BUFFER_WITH_LAST_VIEW,
RC_DRAW_STRATEGY,
RC_LAST RC_LAST
}; };
@ -573,6 +574,17 @@ public:
/// ///
BookmarksVisibility bookmarks_visibility = BMK_NONE; BookmarksVisibility bookmarks_visibility = BMK_NONE;
enum DrawStrategy {
// draw all (not implemented yet)
// FS_FULL,
// draw only what has changed
DS_PARTIAL,
// draw in backing store (only what has changed)
DS_BACKINGSTORE
};
///
DrawStrategy draw_strategy = DS_PARTIAL;
}; };

View File

@ -2710,6 +2710,18 @@ Menus & GuiApplication::menus()
} }
bool GuiApplication::needsBackingStore() const
{
/* 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. It is also possible to force the use of the
* backing store for cases like x11 with transparent WM themes.
*/
return platformName() == "cocoa" || platformName().contains("wayland");
}
QList<int> GuiApplication::viewIds() const QList<int> GuiApplication::viewIds() const
{ {
return d->views_.keys(); return d->views_.keys();

View File

@ -110,6 +110,9 @@ public:
/// ///
Menus & menus(); Menus & menus();
/// \returns true if painting the workarea requires a backing store.
bool needsBackingStore() const;
/// \name Methods inherited from QApplication class /// \name Methods inherited from QApplication class
//@{ //@{
bool notify(QObject * receiver, QEvent * event) override; bool notify(QObject * receiver, QEvent * event) override;

View File

@ -132,13 +132,10 @@ SyntheticMouseEvent::SyntheticMouseEvent()
GuiWorkArea::Private::Private(GuiWorkArea * parent) GuiWorkArea::Private::Private(GuiWorkArea * parent)
: p(parent), completer_(new GuiCompleter(p, p)) : p(parent), completer_(new GuiCompleter(p, p))
{ {
/* Qt on macOS and Wayland does not respect the use_backingstore_ = lyxrc.draw_strategy == LyXRC::DS_BACKINGSTORE
* Qt::WA_OpaquePaintEvent attribute and resets the widget backing || guiApp->needsBackingStore();
* store at each update. Therefore, we use our own backing store LYXERR(Debug::WORKAREA, "Drawing strategy is: "
* in these two cases. << (use_backingstore_ ? "backingstore" : "partial"));
*/
use_backingstore_ = guiApp->platformName() == "cocoa"
|| guiApp->platformName().contains("wayland");
int const time = QApplication::cursorFlashTime() / 2; int const time = QApplication::cursorFlashTime() / 2;
if (time > 0) { if (time > 0) {