commit 1def11d2966a72bcad9d33ef85f384cebd4e58d3
Author: Jean-Marc Lasgouttes <[email protected]>
Date:   Thu Dec 16 12:38:19 2021 +0100

    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
    
    (cherry picked from commit c213eb7f75d53165f55e64f0149fec833e5b5b5e)
    (cherry picked from commit 1ed9257c6dc57fc11990b86d5774ac9a8e70cfa6)
---
 lib/RELEASE-NOTES                    |   11 +++++++++
 src/LyXRC.cpp                        |   38 ++++++++++++++++++++++++++++++++-
 src/LyXRC.h                          |   12 ++++++++++
 src/frontends/qt4/GuiApplication.cpp |   20 +++++++++++++++++
 src/frontends/qt4/GuiApplication.h   |    3 ++
 src/frontends/qt4/GuiWorkArea.cpp    |   18 +++------------
 status.23x                           |    3 ++
 7 files changed, 89 insertions(+), 16 deletions(-)

diff --git a/lib/RELEASE-NOTES b/lib/RELEASE-NOTES
index a576038..f05fdd1 100644
--- a/lib/RELEASE-NOTES
+++ b/lib/RELEASE-NOTES
@@ -1,3 +1,14 @@
+!Important Change in LyX 2.3.7
+
+The following pref variable was added:
+
+* \draw_strategy partial|backingstore: when this is set to
+  "backingstore", the drawing code will force the use of an
+  intermediate surface, instead of just drawing changed regions on
+  screen. Note that "backingstore" is actually always enforced on
+  macOS and Wayland (default: partial).
+
+
 !Important Change in LyX 2.3.1
 
 * A change to how math macros are output can break some documents that use
diff --git a/src/LyXRC.cpp b/src/LyXRC.cpp
index e8e66e2..0753534 100644
--- a/src/LyXRC.cpp
+++ b/src/LyXRC.cpp
@@ -105,6 +105,7 @@ LexerKeyword lyxrcTags[] = {
        { "\\dialogs_iconify_with_main", LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN },
        { "\\display_graphics", LyXRC::RC_DISPLAY_GRAPHICS },
        { "\\document_path", LyXRC::RC_DOCUMENTPATH },
+       { "\\draw_strategy", LyXRC::RC_DRAW_STRATEGY },
        { "\\editor_alternatives", LyXRC::RC_EDITOR_ALTERNATIVES },
        { "\\escape_chars", LyXRC::RC_ESC_CHARS },
        { "\\example_path", LyXRC::RC_EXAMPLEPATH },
@@ -1244,6 +1245,20 @@ LyXRC::ReturnValues LyXRC::read(Lexer & lexrc, bool 
check_format)
                        lexrc >> mouse_middlebutton_paste;
                        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:
                        break; // this is just a dummy
                }
@@ -2064,10 +2079,28 @@ void LyXRC::write(ostream & os, bool 
ignore_system_lyxrc, string const & name) c
                }
                if (tag != RC_LAST)
                        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"
-                       << "# COLOR SECTION 
###################################\n"
-                       << "#\n\n";
+               << "# COLOR SECTION ###################################\n"
+               << "#\n\n";
 
        // fall through
        case RC_SET_COLOR:
@@ -2963,6 +2996,7 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC 
const & lyxrc_new)
                                package().document_dir() = 
FileName(lyxrc.document_path);
                }
                // fall through
+       case LyXRC::RC_DRAW_STRATEGY:
        case LyXRC::RC_EDITOR_ALTERNATIVES:
        case LyXRC::RC_ESC_CHARS:
        case LyXRC::RC_EXAMPLEPATH:
diff --git a/src/LyXRC.h b/src/LyXRC.h
index 7049bf8..6e494d0 100644
--- a/src/LyXRC.h
+++ b/src/LyXRC.h
@@ -183,6 +183,7 @@ public:
                RC_VIEWER_ALTERNATIVES,
                RC_VISUAL_CURSOR,
                RC_CLOSE_BUFFER_WITH_LAST_VIEW,
+               RC_DRAW_STRATEGY,
                RC_LAST
        };
 
@@ -533,6 +534,17 @@ public:
        int cursor_width;
        /// One of: yes, no, ask
        std::string close_buffer_with_last_view;
+
+       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;
 };
 
 
diff --git a/src/frontends/qt4/GuiApplication.cpp 
b/src/frontends/qt4/GuiApplication.cpp
index 271e4c7..246b456 100644
--- a/src/frontends/qt4/GuiApplication.cpp
+++ b/src/frontends/qt4/GuiApplication.cpp
@@ -2509,6 +2509,26 @@ 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.
+        */
+#if QT_VERSION >= 0x050000
+       return platformName() == "cocoa" || platformName().contains("wayland");
+#else
+#  ifdef Q_OS_MAC
+       return true;
+#  else
+    return false;
+#  endif // Q_OS_MAC
+#endif // QT_VERSION
+}
+
+
 QList<int> GuiApplication::viewIds() const
 {
        return d->views_.keys();
diff --git a/src/frontends/qt4/GuiApplication.h 
b/src/frontends/qt4/GuiApplication.h
index eb25bc1..8c6b0e0 100644
--- a/src/frontends/qt4/GuiApplication.h
+++ b/src/frontends/qt4/GuiApplication.h
@@ -103,6 +103,9 @@ public:
        ///
        Menus & menus();
 
+       /// \returns true if painting the workarea requires a backing store.
+       bool needsBackingStore() const;
+
        /// \name Methods inherited from QApplication class
        //@{
        bool notify(QObject * receiver, QEvent * event) override;
diff --git a/src/frontends/qt4/GuiWorkArea.cpp 
b/src/frontends/qt4/GuiWorkArea.cpp
index a16a9c8..7318020 100644
--- a/src/frontends/qt4/GuiWorkArea.cpp
+++ b/src/frontends/qt4/GuiWorkArea.cpp
@@ -245,20 +245,10 @@ GuiWorkArea::Private::Private(GuiWorkArea * parent)
   dialog_mode_(false), shell_escape_(false), read_only_(false),
   clean_(true), externally_modified_(false), needs_caret_geometry_update_(true)
 {
-/* 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
+       use_backingstore_ = lyxrc.draw_strategy == LyXRC::DS_BACKINGSTORE
+               || guiApp->needsBackingStore();
+       LYXERR(Debug::WORKAREA, "Drawing strategy is: "
+                               << (use_backingstore_ ? "backingstore" : 
"partial"));
 
        int const time = QApplication::cursorFlashTime() / 2;
        if (time > 0) {
diff --git a/status.23x b/status.23x
index 12af422..5f56fee 100644
--- a/status.23x
+++ b/status.23x
@@ -44,6 +44,9 @@ What's new
 
 - Fix broken modifier handling for Qt-5.12 on Mac (bug 12247).
 
+- Add new pref variable \draw_strategy to fix some cases where display
+  is blinking (bug 12119).
+
 
 * DOCUMENTATION AND LOCALIZATION
 
-- 
lyx-cvs mailing list
[email protected]
http://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to