include/vcl/task.hxx         |    1 +
 vcl/skia/gdiimpl.cxx         |   19 ++++++++++++++++---
 vcl/source/app/scheduler.cxx |   30 ++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 3 deletions(-)

New commits:
commit e98ff952bf8712410b204623c215fbcc19ddd473
Author:     Patrick Luby <guibmac...@gmail.com>
AuthorDate: Fri Feb 28 22:52:13 2025 -0500
Commit:     Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
CommitDate: Tue Mar 4 18:26:45 2025 +0100

    tdf#165277 On macOS, only delay priorities lower than POST_PAINT
    
    macOS bugs tdf#157312 and tdf#163945 were fixed by firing the
    Skia flush task with TaskPriority::POST_PAINT.
    
    The problem is that this method often executes within an
    NSTimer and NSTimers are always fired while LibreOffice is in
    -[NSApp nextEventMatchingMask:untilDate:inMode:dequeue:].
    
    Since fetching the next native event doesn't handle pending
    events until *after* all of the pending NSTimers have fired,
    calling SalInstance::AnyInput() will almost always return true
    due to the pending events that will be handled immediately
    after all of the the pending NSTimers have fired.
    
    The result is that the Skia flush task is frequently delayed
    and, in cases like tdf#165277, a user's attempts to get
    LibreOffice to paint the window through key and mouse events
    leads to an endless delaying of the Skia flush task.
    
    After experimenting with both Skia/Metal and Skia/Raster,
    tdf#165277 requires the Skia flush task to run immediately
    before the TaskPriority::POST_PAINT tasks. After that, all
    TaskPriority::POST_PAINT tasks must run so the Skia flush
    task now uses the TaskPriority::SKIA_FLUSH priority on macOS.
    
    One positive side effect of this change is that live resizing
    on macOS is now much smoother. Even with Skia disabled (which
    does not paint using a task but does use tasks to handle live
    resizing), the content resizes much more quickly when a user
    repidly changes window's size.
    
    Change-Id: I727b2d215382dbd2ebc2608d401f8b5c0dd49773
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182391
    Tested-by: Jenkins
    Reviewed-by: Patrick Luby <guibomac...@gmail.com>
    Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>

diff --git a/include/vcl/task.hxx b/include/vcl/task.hxx
index 41c73bf39644..859315a99421 100644
--- a/include/vcl/task.hxx
+++ b/include/vcl/task.hxx
@@ -32,6 +32,7 @@ enum class TaskPriority
     HIGH_IDLE,     ///< Important idle events to be run before processing 
drawing events
     RESIZE,        ///< Resize runs before repaint, so we won't paint twice
     REPAINT,       ///< All repaint events should go in here
+    SKIA_FLUSH,    ///< tdf#165277 Skia needs to flush immediately before 
POST_PAINT tasks on macOS
     POST_PAINT,    ///< Everything running directly after painting
     DEFAULT_IDLE,  ///< Default idle priority
     LOWEST,        ///< Low, very idle cleanup tasks
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 4da83890a31d..3a97258e6d45 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -245,8 +245,14 @@ public:
         : Idle(get_debug_name(pGraphics))
         , mpGraphics(pGraphics)
     {
+#ifdef MACOSX
+        // tdf#165277 Skia needs to flush immediately before POST_PAINT
+        // tasks on macOS
+        SetPriority(TaskPriority::SKIA_FLUSH);
+#else
         // We don't want to be swapping before we've painted.
         SetPriority(TaskPriority::POST_PAINT);
+#endif
     }
 #ifndef NDEBUG
     virtual ~SkiaFlushIdle() { free(debugname); }
@@ -273,11 +279,12 @@ public:
         // tdf#157312 and tdf#163945 Lower Skia flush timer priority on macOS
         // On macOS, flushing with Skia/Metal is noticeably slower than
         // with Skia/Raster. So lower the flush timer priority to
-        // TaskPriority::POST_PAINT so that the flush timer runs less
+        // TaskPriority::SKIA_FLUSH so that the flush timer runs less
         // frequently but each pass copies a more up-to-date offscreen
         // surface.
-        // TODO: fix tdf#163734 on macOS
-        SetPriority(TaskPriority::POST_PAINT);
+        // tdf#165277 Skia needs to flush immediately before POST_PAINT
+        // tasks on macOS
+        SetPriority(TaskPriority::SKIA_FLUSH);
 #else
         SetPriority(TaskPriority::HIGHEST);
 #endif
@@ -318,7 +325,13 @@ void SkiaSalGraphicsImpl::createSurface()
 
     // We don't want to be swapping before we've painted.
     mFlush->Stop();
+#ifdef MACOSX
+    // tdf#165277 Skia needs to flush immediately before POST_PAINT
+    // tasks on macOS
+    mFlush->SetPriority(TaskPriority::SKIA_FLUSH);
+#else
     mFlush->SetPriority(TaskPriority::POST_PAINT);
+#endif
 }
 
 void SkiaSalGraphicsImpl::createWindowSurface(bool forceRaster)
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index eaca69adafa1..32f7c78acab0 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -478,6 +478,36 @@ void Scheduler::CallbackTaskScheduling()
 
     bool bIsHighPriorityIdle = pMostUrgent->mePriority >= 
TaskPriority::HIGH_IDLE;
 
+#ifdef MACOSX
+    // tdf#165277 On macOS, only delay priorities lower than POST_PAINT
+    // macOS bugs tdf#157312 and tdf#163945 were fixed by firing the
+    // Skia flush task with TaskPriority::POST_PAINT.
+    // The problem is that this method often executes within an
+    // NSTimer and NSTimers are always fired while LibreOffice is in
+    // -[NSApp nextEventMatchingMask:untilDate:inMode:dequeue:].
+    // Since fetching the next native event doesn't handle pending
+    // events until *after* all of the pending NSTimers have fired,
+    // calling SalInstance::AnyInput() will almost always return true
+    // due to the pending events that will be handled immediately
+    // after all of the the pending NSTimers have fired.
+    // The result is that the Skia flush task is frequently delayed
+    // and, in cases like tdf#165277, a user's attempts to get
+    // LibreOffice to paint the window through key and mouse events
+    // leads to an endless delaying of the Skia flush task.
+    // After experimenting with both Skia/Metal and Skia/Raster,
+    // tdf#165277 requires the Skia flush task to run immediately
+    // before the TaskPriority::POST_PAINT tasks. After that, all
+    // TaskPriority::POST_PAINT tasks must run so the Skia flush
+    // task now uses the TaskPriority::SKIA_FLUSH priority on macOS.
+    // One positive side effect of this change is that live resizing
+    // on macOS is now much smoother. Even with Skia disabled (which
+    // does not paint using a task but does use tasks to handle live
+    // resizing), the content resizes much more quickly when a user
+    // repidly changes window's size.
+    if (bIsHighPriorityIdle && pMostUrgent->mePriority <= 
TaskPriority::POST_PAINT)
+        bIsHighPriorityIdle = false;
+#endif
+
     // invoke the task
     Unlock();
 

Reply via email to