[Libreoffice-commits] core.git: Branch 'private/jmux/scheduler-fixes' - 92 commits - accessibility/inc accessibility/source basctl/source basegfx/source basegfx/test canvas/source canvas/workben chart2/source cli_ure/qa comphelper/source compilerplugins/clang configure.ac connectivity/source cppcanvas/inc cppcanvas/source cui/inc cui/source cui/uiconfig dbaccess/source desktop/source drawinglayer/inc drawinglayer/source dtrans/source editeng/source emfio/inc emfio/source extensions/source external/firebird external/libmspub filter/source formula/source fpicker/source framework/source icon-themes/tango include/basegfx include/comphelper include/drawinglayer include/formula include/oox include/sfx2 include/svx include/vcl lingucomponent/source odk/examples offapi/com officecfg/README officecfg/registry oox/inc oox/source package/source postprocess/Module_postprocess.mk pyuno/source reportdesign/source Repository.mk sal/osl sc/inc sc/qa sc/source sdext/source sd/inc sd/qa sd/source sd/uiconfig sfx2/ source shell/source slideshow/inc slideshow/source slideshow/test solenv/bin soltools/cpp sot/qa sot/source svgio/inc svgio/source svtools/source svx/sdi svx/source svx/uiconfig swext/mediawiki sw/inc sw/qa sw/sdi sw/source sw/uiconfig sw/UIConfig_sglobal.mk test/source toolkit/source tools/source vcl/headless vcl/inc vcl/Library_vcl.mk vcl/opengl vcl/osx vcl/qa vcl/quartz vcl/README.scheduler vcl/source vcl/unx vcl/win vcl/workben winaccessibility/source wizards/com writerfilter/source writerperfect/qa writerperfect/source xmloff/source

Tue, 26 Sep 2017 09:02:57 -0700

Rebased ref, commits from common ancestor:
commit 5a103c3d5c538fe407b1f57d9fbdf06b12af6d66
Author: Jan-Marek Glogowski <glo...@fbihome.de>
Date:   Tue Sep 5 18:54:49 2017 +0200

    OSX revert fix for i#90083
    
    Part of commit d6f7c94e5c27ba02ff5c3229760c9808cc9b5bea
    
    At least on my current OSX box application based window switching
    "just works" "out of the box", even without the code.
    
    With the replacement of the list with a set, the result is a little
    bit unexpected and as all the code has a comment "FIXME: lousy
    workaround", my fix is simply to drop it.
    
    Change-Id: I456503a74d8cddbd1e81b4a826b94381b424c78c

diff --git a/vcl/inc/osx/vclnsapp.h b/vcl/inc/osx/vclnsapp.h
index c899ffce59d1..39bd3170abaf 100644
--- a/vcl/inc/osx/vclnsapp.h
+++ b/vcl/inc/osx/vclnsapp.h
@@ -61,8 +61,6 @@ class AquaSalFrame;
 #endif
 -(BOOL)applicationShouldHandleReopen: (NSApplication*)pApp hasVisibleWindows: 
(BOOL)bWinVisible;
 -(void)setDockIconClickHandler: (NSObject*)pHandler;
--(void)cycleFrameForward: (AquaSalFrame*)pCurFrame;
--(void)cycleFrameBackward: (AquaSalFrame*)pCurFrame;
 @end
 
 #endif // INCLUDED_VCL_INC_OSX_VCLNSAPP_H
diff --git a/vcl/osx/vclnsapp.mm b/vcl/osx/vclnsapp.mm
index f06c9fd0b2ab..dafcdb97aca5 100644
--- a/vcl/osx/vclnsapp.mm
+++ b/vcl/osx/vclnsapp.mm
@@ -136,24 +136,6 @@ SAL_WNODEPRECATED_DECLARATIONS_PUSH
                 }
             }
 
-            // #i90083# handle frame switching
-            // FIXME: lousy workaround
-            if( (nModMask & (NSControlKeyMask|NSAlternateKeyMask)) == 0 )
-            {
-                if( [[pEvent characters] isEqualToString: @"<"] ||
-                    [[pEvent characters] isEqualToString: @"~"] )
-                {
-                    [self cycleFrameForward: pFrame];
-                    return;
-                }
-                else if( [[pEvent characters] isEqualToString: @">"] ||
-                         [[pEvent characters] isEqualToString: @"`"] )
-                {
-                    [self cycleFrameBackward: pFrame];
-                    return;
-                }
-            }
-
             // get information whether the event was handled; keyDown returns 
nothing
             GetSalData()->maKeyEventAnswer[ pEvent ] = false;
             bool bHandled = false;
@@ -245,77 +227,6 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
     [super sendEvent: pEvent];
 }
 
--(void)cycleFrameForward: (AquaSalFrame*)pCurFrame
-{
-    // find current frame in list
-    auto &rFrames( GetSalData()->mpFirstInstance->getFrames() );
-    auto it = rFrames.find( pCurFrame );
-    if( it != rFrames.end() )
-    {
-        ++it;
-        // now find the next frame (or end)
-        for( ; it != rFrames.end(); ++it )
-        {
-            auto pFrame = static_cast<const AquaSalFrame*>( *it );
-            if( pFrame->mpDockMenuEntry != nullptr && pFrame->mbShown )
-            {
-                [pFrame->getNSWindow() makeKeyAndOrderFront: NSApp];
-                return;
-            }
-        }
-        // cycle around, find the next up to pCurFrame
-        for( it = rFrames.begin(); *it != pCurFrame; ++it )
-        {
-            auto pFrame = static_cast<const AquaSalFrame*>( *it );
-            if( pFrame->mpDockMenuEntry != nullptr && pFrame->mbShown )
-            {
-                [pFrame->getNSWindow() makeKeyAndOrderFront: NSApp];
-                return;
-            }
-        }
-    }
-}
-
-template< class Iterator >
-std::reverse_iterator<Iterator> make_reverse_iterator( Iterator i )
-{
-    return std::reverse_iterator<Iterator>(i);
-}
-
--(void)cycleFrameBackward: (AquaSalFrame*)pCurFrame
-{
-    // do the same as cycleFrameForward only with a reverse iterator
-
-    // find current frame in list
-    auto &rFrames( GetSalData()->mpFirstInstance->getFrames() );
-    auto search_it = rFrames.find( pCurFrame );
-    if( search_it != rFrames.end() )
-    {
-        auto it = ::make_reverse_iterator( search_it );
-        ++it;
-        // now find the next frame (or end)
-        for( ; it != rFrames.rend(); ++it )
-        {
-            auto pFrame = static_cast<const AquaSalFrame*>( *it );
-            if( pFrame->mpDockMenuEntry != nullptr && pFrame->mbShown )
-            {
-                [pFrame->getNSWindow() makeKeyAndOrderFront: NSApp];
-                return;
-            }
-        }
-        // cycle around, find the next up to pCurFrame
-        for( it = rFrames.rbegin(); *it != pCurFrame; ++it )
-        {
-            auto pFrame = static_cast<const AquaSalFrame*>( *it );
-            if( pFrame->mpDockMenuEntry != nullptr && pFrame->mbShown )
-            {
-                [pFrame->getNSWindow() makeKeyAndOrderFront: NSApp];
-                return;
-            }
-        }
-    }
-}
-
 -(NSMenu*)applicationDockMenu:(NSApplication *)sender
 {
     (void)sender;
commit 5957986b5f508d95c60a56ca672c8017c071d9cd
Author: Jan-Marek Glogowski <glo...@fbihome.de>
Date:   Mon Sep 4 17:40:13 2017 +0200

    Unify SalUserEvent handling
    
    Change-Id: I188b567e44fd79c162b2d9cabbd771d1f66c7dc4

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 1aa3095d0a6c..5d62542e8b13 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -321,6 +321,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/app/help \
     vcl/source/app/i18nhelp \
        vcl/source/app/idle \
+       vcl/source/app/salusereventlist \
     vcl/source/app/salvtables \
        vcl/source/app/scheduler \
     vcl/source/app/session \
diff --git a/vcl/headless/svpframe.cxx b/vcl/headless/svpframe.cxx
index 9a086c0b3d6a..08c6a09ef834 100644
--- a/vcl/headless/svpframe.cxx
+++ b/vcl/headless/svpframe.cxx
@@ -94,10 +94,9 @@ SvpSalFrame::~SvpSalFrame()
         // pass focus to another frame, preferably a document style window
         if( s_pFocusFrame == nullptr )
         {
-            const std::list< SalFrame* >& rFrames( m_pInstance->getFrames() );
-            for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); 
it != rFrames.end(); ++it )
+            for (auto pSalFrame : m_pInstance->getFrames() )
             {
-                SvpSalFrame* pFrame = static_cast<SvpSalFrame*>(*it);
+                SvpSalFrame* pFrame = static_cast<SvpSalFrame*>( 
const_cast<SalFrame*>( pSalFrame ) );
                 if( pFrame->m_bVisible        &&
                     pFrame->m_pParent == nullptr &&
                     (pFrame->m_nStyle & (SalFrameStyleFlags::MOVEABLE |
diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
index ab8f91eac31f..5153c8952f4a 100644
--- a/vcl/headless/svpinst.cxx
+++ b/vcl/headless/svpinst.cxx
@@ -47,19 +47,6 @@
 // FIXME: remove when we re-work the svp mainloop
 #include "unx/salunxtime.h"
 
-bool SvpSalInstance::isFrameAlive( const SalFrame* pFrame ) const
-{
-    for( std::list< SalFrame* >::const_iterator it = m_aFrames.begin();
-         it != m_aFrames.end(); ++it )
-    {
-        if( *it == pFrame )
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
 SvpSalInstance* SvpSalInstance::s_pDefaultInstance = nullptr;
 
 #if !defined(ANDROID) && !defined(IOS)
@@ -165,12 +152,8 @@ void SvpSalInstance::CreateWakeupPipe(bool log)
 
 #endif
 
-void SvpSalInstance::PostEvent(const SalFrame* pFrame, ImplSVEvent* pData, 
SalEvent nEvent)
+void SvpSalInstance::TriggerUserEventProcessing()
 {
-    {
-        osl::MutexGuard g(m_aEventGuard);
-        m_aUserEvents.emplace_back( pFrame, pData, nEvent );
-    }
     Wakeup();
 }
 
@@ -186,31 +169,6 @@ bool SvpSalInstance::PostedEventsInQueue()
 }
 #endif
 
-void SvpSalInstance::deregisterFrame( SalFrame* pFrame )
-{
-    m_aFrames.remove( pFrame );
-
-    osl::MutexGuard g(m_aEventGuard);
-    // cancel outstanding events for this frame
-    if( ! m_aUserEvents.empty() )
-    {
-        std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
-        do
-        {
-            if( it->m_pFrame == pFrame )
-            {
-                if (it->m_nEvent == SalEvent::UserEvent)
-                {
-                    delete it->m_pData;
-                }
-                it = m_aUserEvents.erase( it );
-            }
-            else
-                ++it;
-        } while( it != m_aUserEvents.end() );
-    }
-}
-
 void SvpSalInstance::Wakeup()
 {
 #ifndef IOS
@@ -304,44 +262,24 @@ SalBitmap* SvpSalInstance::CreateSalBitmap()
 #endif
 }
 
-bool SvpSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
+void SvpSalInstance::ProcessEvent( SalUserEvent aEvent )
 {
-    // first, check for already queued events.
-    std::list< SalUserEvent > aEvents;
+    aEvent.m_pFrame->CallCallback( aEvent.m_nEvent, aEvent.m_pData );
+    if( aEvent.m_nEvent == SalEvent::Resize )
     {
-        osl::MutexGuard g(m_aEventGuard);
-        if( ! m_aUserEvents.empty() )
-        {
-            if( bHandleAllCurrentEvents )
-            {
-                aEvents = m_aUserEvents;
-                m_aUserEvents.clear();
-            }
-            else
-            {
-                aEvents.push_back( m_aUserEvents.front() );
-                m_aUserEvents.pop_front();
-            }
-        }
+        // this would be a good time to post a paint
+        const SvpSalFrame* pSvpFrame = static_cast<const SvpSalFrame*>( 
aEvent.m_pFrame);
+        pSvpFrame->PostPaint();
     }
+}
 
-    bool bEvent = !aEvents.empty();
-    if( bEvent )
-    {
-        for( std::list<SalUserEvent>::const_iterator it = aEvents.begin(); it 
!= aEvents.end(); ++it )
-        {
-            if ( isFrameAlive( it->m_pFrame ) )
-            {
-                it->m_pFrame->CallCallback( it->m_nEvent, it->m_pData );
-                if( it->m_nEvent == SalEvent::Resize )
-                {
-                    // this would be a good time to post a paint
-                    const SvpSalFrame* pSvpFrame = static_cast<const 
SvpSalFrame*>(it->m_pFrame);
-                    pSvpFrame->PostPaint();
-                }
-            }
-        }
-    }
+
+bool SvpSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
+{
+    // first, process current user events
+    bool bEvent = DispatchUserEvents( bHandleAllCurrentEvents );
+    if ( !bHandleAllCurrentEvents &&bEvent )
+        return true;
 
     bEvent = CheckTimeout() || bEvent;
 
diff --git a/vcl/headless/svpprn.cxx b/vcl/headless/svpprn.cxx
index 488f17bb4084..aa865cadfd0c 100644
--- a/vcl/headless/svpprn.cxx
+++ b/vcl/headless/svpprn.cxx
@@ -257,10 +257,9 @@ OUString SvpSalInstance::GetDefaultPrinter()
 
 void SvpSalInstance::PostPrintersChanged()
 {
-    const std::list< SalFrame* >& rList = 
SvpSalInstance::s_pDefaultInstance->getFrames();
-    for( std::list< SalFrame* >::const_iterator it = rList.begin();
-         it != rList.end(); ++it )
-        SvpSalInstance::s_pDefaultInstance->PostEvent( *it, nullptr, 
SalEvent::PrinterChanged );
+    SvpSalInstance *pInst = SvpSalInstance::s_pDefaultInstance;
+    for (auto pSalFrame : pInst->getFrames() )
+        pInst->PostEvent( const_cast<SalFrame*>( pSalFrame ), nullptr, 
SalEvent::PrinterChanged );
 }
 
 GenPspGraphics *SvpSalInstance::CreatePrintGraphics()
diff --git a/vcl/inc/headless/svpinst.hxx b/vcl/inc/headless/svpinst.hxx
index 0883981c4406..a411315c761d 100644
--- a/vcl/inc/headless/svpinst.hxx
+++ b/vcl/inc/headless/svpinst.hxx
@@ -25,6 +25,7 @@
 #include <salinst.hxx>
 #include <salwtype.hxx>
 #include <saltimer.hxx>
+#include <salusereventlist.hxx>
 #include <unx/geninst.h>
 #include <unx/genprn.h>
 
@@ -57,35 +58,18 @@ class GenPspGraphics;
 
 SalInstance* svp_create_SalInstance();
 
-class VCL_DLLPUBLIC SvpSalInstance : public SalGenericInstance
+class VCL_DLLPUBLIC SvpSalInstance : public SalGenericInstance, public 
SalUserEventList
 {
     timeval                 m_aTimeout;
     sal_uLong               m_nTimeoutMS;
     int                     m_pTimeoutFDS[2];
 
-    // internal event queue
-    struct SalUserEvent
-    {
-        const SalFrame*     m_pFrame;
-        ImplSVEvent*        m_pData;
-        SalEvent            m_nEvent;
-
-        SalUserEvent( const SalFrame* pFrame, ImplSVEvent* pData, SalEvent 
nEvent )
-                : m_pFrame( pFrame ),
-                  m_pData( pData ),
-                  m_nEvent( nEvent )
-        {}
-    };
-
-    osl::Mutex              m_aEventGuard;
-    std::list< SalUserEvent > m_aUserEvents;
-
-    std::list< SalFrame* >  m_aFrames;
-
-    bool                    isFrameAlive( const SalFrame* pFrame ) const;
-
     void                    DoReleaseYield( int nTimeoutMS );
 
+    virtual void            TriggerUserEventProcessing() override;
+    virtual void            ProcessEvent( SalUserEvent aEvent ) override;
+    void                    Wakeup();
+
 public:
     static SvpSalInstance*  s_pDefaultInstance;
 
@@ -95,20 +79,15 @@ public:
     void                    CloseWakeupPipe(bool log);
     void                    CreateWakeupPipe(bool log);
 
-    void                    PostEvent(const SalFrame* pFrame, ImplSVEvent* 
pData, SalEvent nEvent);
-
 #ifdef ANDROID
     bool                    PostedEventsInQueue();
 #endif
 
     void                    StartTimer( sal_uLong nMS );
     void                    StopTimer();
-    void                    Wakeup();
 
-    void                    registerFrame( SalFrame* pFrame ) { 
m_aFrames.push_back( pFrame ); }
-    void                    deregisterFrame( SalFrame* pFrame );
-    const std::list< SalFrame* >&
-                            getFrames() const { return m_aFrames; }
+    inline void             registerFrame( const SalFrame* pFrame );
+    inline void             deregisterFrame( const SalFrame* pFrame );
 
     bool                    CheckTimeout( bool bExecuteTimers = true );
 
@@ -171,6 +150,16 @@ public:
     virtual GenPspGraphics *CreatePrintGraphics() override;
 };
 
+inline void SvpSalInstance::registerFrame( const SalFrame* pFrame )
+{
+    insertFrame( pFrame );
+}
+
+inline void SvpSalInstance::deregisterFrame( const SalFrame* pFrame )
+{
+    eraseFrame( pFrame );
+}
+
 #endif // INCLUDED_VCL_INC_HEADLESS_SVPINST_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/osx/saldata.hxx b/vcl/inc/osx/saldata.hxx
index fbc28e05391d..f69366518be5 100644
--- a/vcl/inc/osx/saldata.hxx
+++ b/vcl/inc/osx/saldata.hxx
@@ -45,6 +45,7 @@
 
 #include "apple_remote/RemoteMainController.h"
 
+class AquaSalFrame;
 class AquaSalInstance;
 class SalObject;
 class SalFrame;
@@ -54,7 +55,6 @@ class SystemFontList;
 
 #define SAL_CLIPRECT_COUNT 16
 
-class AquaSalFrame;
 struct FrameHash : public std::hash<sal_IntPtr>
 {
     size_t operator()(const AquaSalFrame* frame) const
@@ -71,8 +71,6 @@ class SalData
 public:
     SALTIMERPROC                                  mpTimerProc;      // timer 
callback proc
     AquaSalInstance                              *mpFirstInstance;  // pointer 
of first instance
-    std::list<AquaSalFrame*>                      maFrames;         // list of 
all frames
-    std::unordered_set<const AquaSalFrame*,FrameHash>  maFrameCheck;// for 
fast check of frame existence
     std::list<AquaSalFrame*>                      maPresentationFrames;  // 
list of frames in presentation mode
     SalObject                                    *mpFirstObject;    // pointer 
of first object window
     SalVirtualDevice                             *mpFirstVD;        // first 
VirDev
diff --git a/vcl/inc/osx/salframe.h b/vcl/inc/osx/salframe.h
index e99a3175876d..f8cef1834106 100644
--- a/vcl/inc/osx/salframe.h
+++ b/vcl/inc/osx/salframe.h
@@ -26,6 +26,7 @@
 
 #include <vcl/sysdata.hxx>
 
+#include "osx/salinst.h"
 #include "osx/salmenu.h"
 #include "osx/saldata.hxx"
 #include "osx/osxvcltypes.h"
@@ -163,8 +164,7 @@ public:
     // trigger painting of the window
     void SendPaintEvent( const tools::Rectangle* pRect = nullptr );
 
-    static bool isAlive( const AquaSalFrame* pFrame )
-    { return GetSalData()->maFrameCheck.find( pFrame ) != 
GetSalData()->maFrameCheck.end(); }
+    static inline bool isAlive( const AquaSalFrame* pFrame );
 
     static AquaSalFrame* GetCaptureFrame() { return s_pCaptureFrame; }
 
@@ -204,6 +204,12 @@ private: // data
     AquaSalFrame& operator=(const AquaSalFrame&) = delete;
 };
 
+inline bool AquaSalFrame::isAlive( const AquaSalFrame* pFrame )
+{
+    AquaSalInstance *pInst = GetSalData()->mpFirstInstance;
+    return pInst && pInst->isFrameAlive( pFrame );
+}
+
 #endif // INCLUDED_VCL_INC_OSX_SALFRAME_H
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index 0e30dfafb693..272cfc722d64 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -34,6 +34,8 @@
 
 #include "osx/runinmain.hxx"
 
+#include "salusereventlist.hxx"
+
 class AquaSalFrame;
 class SalFrame;
 class SalObject;
@@ -59,27 +61,18 @@ public:
     virtual bool IsCurrentThread() const override;
 };
 
-class AquaSalInstance : public SalInstance
+class AquaSalInstance : public SalInstance, public SalUserEventList
 {
-    struct SalUserEvent
-    {
-        AquaSalFrame*   mpFrame;
-        void*           mpData;
-        SalEvent        mnType;
-
-        SalUserEvent( AquaSalFrame* pFrame, void* pData, SalEvent nType ) :
-            mpFrame( pFrame ), mpData( pData ), mnType( nType )
-        {}
-    };
-
     bool RunInMainYield( bool bHandleAllCurrentEvents );
 
+    virtual void TriggerUserEventProcessing() override;
+    virtual void ProcessEvent( SalUserEvent aEvent ) override;
+
 public:
     SalYieldMutex*                          mpSalYieldMutex;        // 
Sal-Yield-Mutex
     OUString                                maDefaultPrinter;
     oslThreadIdentifier                     maMainThread;
     int                                     mnActivePrintJobs;
-    std::list< SalUserEvent >               maUserEvents;
     osl::Mutex                              maUserEventListMutex;
     osl::Condition                          maWaitingYieldCond;
     bool                                    mbIsLiveResize;
@@ -145,7 +138,6 @@ public:
 public:
     friend class AquaSalFrame;
 
-    void PostUserEvent( AquaSalFrame* pFrame, SalEvent nType, void* pData );
     void delayedSettingsChanged( bool bInvalidate );
 
     // Is this the NSAppThread?
diff --git a/vcl/inc/salusereventlist.hxx b/vcl/inc/salusereventlist.hxx
new file mode 100644
index 000000000000..94c32d4ba55a
--- /dev/null
+++ b/vcl/inc/salusereventlist.hxx
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_VCL_INC_SALUSEREVENTLIST_HXX
+#define INCLUDED_VCL_INC_SALUSEREVENTLIST_HXX
+
+#include <sal/config.h>
+#include <vcl/dllapi.h>
+#include <osl/mutex.hxx>
+
+#include <assert.h>
+
+#include <list>
+#include <set>
+
+class SalFrame;
+enum class SalEvent;
+
+class VCL_PLUGIN_PUBLIC SalUserEventList
+{
+public:
+    struct SalUserEvent
+    {
+        SalFrame*     m_pFrame;
+        void*         m_pData;
+        SalEvent      m_nEvent;
+
+        SalUserEvent( SalFrame* pFrame, void* pData, SalEvent nEvent )
+                : m_pFrame( pFrame ),
+                  m_pData( pData ),
+                  m_nEvent( nEvent )
+        {}
+
+        bool operator==(const SalUserEvent &aEvent) const
+        {
+            return m_pFrame == aEvent.m_pFrame
+                && m_pData == aEvent.m_pData
+                && m_nEvent== aEvent.m_nEvent;
+        }
+    };
+
+protected:
+    mutable osl::Mutex            m_aUserEventsMutex;
+    std::list< SalUserEvent >     m_aUserEvents;
+    std::list< SalUserEvent >     m_aProcessingUserEvents;
+    std::set< const SalFrame* >   m_aFrames;
+
+    virtual void ProcessEvent( SalUserEvent aEvent ) = 0;
+    virtual void TriggerUserEventProcessing() = 0;
+    virtual void TriggerAllUserEventsProcessed() {};
+
+public:
+    SalUserEventList();
+    virtual ~SalUserEventList();
+
+    inline const std::set< const SalFrame* >& getFrames() const;
+    inline SalFrame* anyFrame() const;
+    void insertFrame( const SalFrame* pFrame );
+    void eraseFrame( const SalFrame* pFrame );
+    inline bool isFrameAlive( const SalFrame* pFrame ) const;
+
+    void PostEvent( SalFrame* pFrame, void* pData, SalEvent nEvent );
+    bool RemoveEvent( SalFrame* pFrame, void* pData, SalEvent nEvent );
+    inline bool HasUserEvents() const;
+
+    bool DispatchUserEvents( bool bHandleAllCurrentEvents );
+};
+
+inline SalFrame* SalUserEventList::anyFrame() const
+{
+    if ( m_aFrames.empty() )
+        return nullptr;
+    return const_cast<SalFrame*>( *m_aFrames.begin() );
+}
+
+inline bool SalUserEventList::isFrameAlive( const SalFrame* pFrame ) const
+{
+    auto it = m_aFrames.find( pFrame );
+    return it != m_aFrames.end();
+}
+
+inline bool SalUserEventList::HasUserEvents() const
+{
+    osl::MutexGuard aGuard( m_aUserEventsMutex );
+    return !(m_aUserEvents.empty() && m_aProcessingUserEvents.empty());
+}
+
+inline void SalUserEventList::PostEvent( SalFrame* pFrame, void* pData, 
SalEvent nEvent )
+{
+    osl::MutexGuard aGuard( m_aUserEventsMutex );
+    m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) );
+    TriggerUserEventProcessing();
+}
+
+inline const std::set< const SalFrame* >& SalUserEventList::getFrames() const
+{
+    return m_aFrames;
+}
+
+#endif // INCLUDED_VCL_INC_SALUSEREVENTLIST_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/gendisp.hxx b/vcl/inc/unx/gendisp.hxx
index 64564237a232..13f1247e20d3 100644
--- a/vcl/inc/unx/gendisp.hxx
+++ b/vcl/inc/unx/gendisp.hxx
@@ -27,45 +27,27 @@
 #include <vcl/dllapi.h>
 #include <list>
 #include <vector>
+#include <salusereventlist.hxx>
 
 class SalFrame;
-class VCL_DLLPUBLIC SalGenericDisplay
+class VCL_DLLPUBLIC SalGenericDisplay : public SalUserEventList
 {
-    mutable osl::Mutex m_aEventGuard;
-    struct SalUserEvent
-    {
-        SalFrame*  m_pFrame;
-        void*      m_pData;
-        SalEvent   m_nEvent;
-
-        SalUserEvent( SalFrame* pFrame, void* pData,
-                      SalEvent nEvent )
-                : m_pFrame( pFrame ),
-                  m_pData( pData ),
-                  m_nEvent( nEvent )
-        {}
-    };
-    std::list< SalUserEvent > m_aUserEvents;
 protected:
     SalFrame* m_pCapture;
-    std::list<SalFrame*> m_aFrames;
+
+    virtual void ProcessEvent( SalUserEvent aEvent ) override;
+
 public:
                  SalGenericDisplay();
-    virtual      ~SalGenericDisplay();
+    virtual      ~SalGenericDisplay() override;
 
-    osl::Mutex& getEventGuardMutex() { return m_aEventGuard; }
-
-    void registerFrame( SalFrame* pFrame );
-    virtual void deregisterFrame( SalFrame* pFrame );
+    void registerFrame( const SalFrame* pFrame );
+    virtual void deregisterFrame( const SalFrame* pFrame );
     void emitDisplayChanged();
 
-    // Event handling
-    virtual void PostUserEvent() = 0;
-
     void SendInternalEvent( SalFrame* pFrame, void* pData, SalEvent nEvent = 
SalEvent::UserEvent );
-    void CancelInternalEvent( SalFrame const * pFrame, void const * pData, 
SalEvent nEvent );
+    void CancelInternalEvent( SalFrame* pFrame, void* pData, SalEvent nEvent );
     bool DispatchInternalEvent();
-    bool HasUserEvents() const;
 
     bool     MouseCaptured( const SalFrame *pFrameData ) const
                         { return m_pCapture == pFrameData; }
diff --git a/vcl/inc/unx/gtk/gtkdata.hxx b/vcl/inc/unx/gtk/gtkdata.hxx
index 4f4d520fc141..1a510095f342 100644
--- a/vcl/inc/unx/gtk/gtkdata.hxx
+++ b/vcl/inc/unx/gtk/gtkdata.hxx
@@ -117,9 +117,9 @@ public:
     static void initNWF();
     static void deInitNWF();
 
-    static gboolean userEventFn( gpointer data );
+    void TriggerUserEventProcessing();
+    void TriggerAllUserEventsProcessed();
 
-    void PostUserEvent();
     bool Yield( bool bWait, bool bHandleAllCurrentEvents );
     inline GdkDisplay *GetGdkDisplay();
 
@@ -146,6 +146,7 @@ class GtkSalDisplay : public SalDisplay
 
     GdkCursor* getFromXBM( const unsigned char *pBitmap, const unsigned char 
*pMask,
                            int nWidth, int nHeight, int nXHot, int nYHot );
+
 public:
              GtkSalDisplay( GdkDisplay* pDisplay );
     virtual ~GtkSalDisplay() override;
@@ -157,7 +158,7 @@ public:
 
     GtkWidget* findGtkWidgetForNativeHandle(sal_uIntPtr hWindow) const;
 
-    virtual void deregisterFrame( SalFrame* pFrame ) override;
+    virtual void deregisterFrame( const SalFrame* pFrame ) override;
     GdkCursor *getCursor( PointerStyle ePointerStyle );
 #if GTK_CHECK_VERSION(3,0,0)
     virtual int CaptureMouse( SalFrame* pFrame );
@@ -180,7 +181,8 @@ public:
     void screenSizeChanged( GdkScreen const * );
     void monitorsChanged( GdkScreen const * );
 
-    virtual void PostUserEvent() override;
+    virtual void TriggerUserEventProcessing() override;
+    virtual void TriggerAllUserEventsProcessed() override;
 
 #if !GTK_CHECK_VERSION(3,0,0)
     virtual bool Dispatch( XEvent *pEvent ) override;
diff --git a/vcl/inc/unx/saldisp.hxx b/vcl/inc/unx/saldisp.hxx
index 0ec4e10e7d65..2388c3281f37 100644
--- a/vcl/inc/unx/saldisp.hxx
+++ b/vcl/inc/unx/saldisp.hxx
@@ -168,7 +168,7 @@ public:
 
     virtual bool    Yield( bool bWait, bool bHandleAllCurrentEvents );
     virtual void    Wakeup();
-    virtual void    PostUserEvent();
+    void            TriggerUserEventProcessing();
 
     virtual void    Insert( int fd, void* data,
                             YieldFunc   pending,
@@ -371,12 +371,10 @@ public:
             { return getDataForScreen( nXScreen ).m_aRoot; }
     unsigned int GetXScreenCount() const { return m_aScreens.size(); }
 
-    const std::list< SalFrame* >& getFrames() const { return m_aFrames; }
+    const std::set< const SalFrame* >& getFrames() const { return m_aFrames; }
     bool            IsNumLockFromXS() const { return bNumLockFromXS_; }
 
     std::list< SalObject* >& getSalObjects() { return m_aSalObjects; }
-
-    virtual void    PostUserEvent() override = 0;
 };
 
 inline  Display *SalColormap::GetXDisplay() const
@@ -390,7 +388,7 @@ public:
 
     virtual bool        Dispatch( XEvent *pEvent ) override;
     virtual void        Yield();
-    virtual void        PostUserEvent() override;
+    virtual void        TriggerUserEventProcessing() override;
 
     bool                IsEvent();
     void                SetupInput();
diff --git a/vcl/osx/salframe.cxx b/vcl/osx/salframe.cxx
index e54073cdf4f1..dcdfe6d9c936 100644
--- a/vcl/osx/salframe.cxx
+++ b/vcl/osx/salframe.cxx
@@ -87,8 +87,7 @@ AquaSalFrame::AquaSalFrame( SalFrame* pParent, 
SalFrameStyleFlags salFrameStyle
     initWindowAndView();
 
     SalData* pSalData = GetSalData();
-    pSalData->maFrames.push_front( this );
-    pSalData->maFrameCheck.insert( this );
+    pSalData->mpFirstInstance->insertFrame( this );
 }
 
 AquaSalFrame::~AquaSalFrame()
@@ -106,8 +105,7 @@ AquaSalFrame::~AquaSalFrame()
     [SalFrameView unsetMouseFrame: this];
 
     SalData* pSalData = GetSalData();
-    pSalData->maFrames.remove( this );
-    pSalData->maFrameCheck.erase( this );
+    pSalData->mpFirstInstance->eraseFrame( this );
     pSalData->maPresentationFrames.remove( this );
 
     SAL_WARN_IF( this == s_pCaptureFrame, "vcl", "capture frame destroyed" );
@@ -296,7 +294,7 @@ void AquaSalFrame::ReleaseGraphics( SalGraphics *pGraphics )
 
 bool AquaSalFrame::PostEvent(ImplSVEvent* pData)
 {
-    GetSalData()->mpFirstInstance->PostUserEvent( this, SalEvent::UserEvent, 
pData );
+    GetSalData()->mpFirstInstance->PostEvent( this, pData, SalEvent::UserEvent 
);
     return TRUE;
 }
 
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index f55e9b4aa297..a57879802f52 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -79,7 +79,8 @@ static bool bLeftMain = false;
 class AquaDelayedSettingsChanged : public Idle
 {
     bool            mbInvalidate;
-    public:
+
+public:
     AquaDelayedSettingsChanged( bool bInvalidate ) :
         mbInvalidate( bInvalidate )
     {
@@ -87,20 +88,20 @@ class AquaDelayedSettingsChanged : public Idle
 
     virtual void Invoke() override
     {
-        SalData* pSalData = GetSalData();
-        if( ! pSalData->maFrames.empty() )
-            pSalData->maFrames.front()->CallCallback( 
SalEvent::SettingsChanged, nullptr );
+        AquaSalInstance *pInst = GetSalData()->mpFirstInstance;
+        SalFrame *pAnyFrame = pInst->anyFrame();
+        if( pAnyFrame )
+            pAnyFrame->CallCallback( SalEvent::SettingsChanged, nullptr );
 
         if( mbInvalidate )
         {
-            for( std::list< AquaSalFrame* >::iterator it = 
pSalData->maFrames.begin();
-                it != pSalData->maFrames.end(); ++it )
+            for( auto pSalFrame : pInst->getFrames() )
             {
-                if( (*it)->mbShown )
-                    (*it)->SendPaintEvent();
+                AquaSalFrame* pFrame = static_cast<AquaSalFrame*>( 
const_cast<SalFrame*>( pSalFrame ) );
+                if( pFrame->mbShown )
+                    pFrame->SendPaintEvent();
             }
         }
-        Stop();
         delete this;
     }
 };
@@ -390,17 +391,19 @@ AquaSalInstance::~AquaSalInstance()
     delete mpSalYieldMutex;
 }
 
-void AquaSalInstance::PostUserEvent( AquaSalFrame* pFrame, SalEvent nType, 
void* pData )
+void AquaSalInstance::TriggerUserEventProcessing()
 {
-    {
-        osl::MutexGuard g( maUserEventListMutex );
-        maUserEvents.push_back( SalUserEvent( pFrame, pData, nType ) );
-    }
     dispatch_async(dispatch_get_main_queue(),^{
         ImplNSAppPostEvent( AquaSalInstance::YieldWakeupEvent, NO );
     });
 }
 
+void AquaSalInstance::ProcessEvent( SalUserEvent aEvent )
+{
+    aEvent.m_pFrame->CallCallback( aEvent.m_nEvent, aEvent.m_pData );
+    maWaitingYieldCond.set();
+}
+
 comphelper::SolarMutex* AquaSalInstance::GetYieldMutex()
 {
     return mpSalYieldMutex;
@@ -453,15 +456,17 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* 
pEvent )
     case AppleRemoteControlEvent: // Defined in 
<apple_remote/RemoteMainController.h>
     {
         MediaCommand nCommand;
-        SalData* pSalData = GetSalData();
+        AquaSalInstance *pInst = GetSalData()->mpFirstInstance;
         bool bIsFullScreenMode = false;
 
-        std::list<AquaSalFrame*>::iterator it = pSalData->maFrames.begin();
-        while( it != pSalData->maFrames.end() )
+        for( auto pSalFrame : pInst->getFrames() )
         {
-            if ( (*it) && (*it)->mbFullScreen )
+            const AquaSalFrame* pFrame = static_cast<const AquaSalFrame*>( 
pSalFrame );
+            if ( pFrame->mbFullScreen )
+            {
                 bIsFullScreenMode = true;
-            ++it;
+                break;
+            }
         }
 
         switch ([pEvent data1])
@@ -497,9 +502,8 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* 
pEvent )
             default:
                 break;
         }
-        AquaSalFrame* pFrame = pSalData->maFrames.front();
+        AquaSalFrame* pFrame = static_cast<AquaSalFrame*>( pInst->anyFrame() );
         vcl::Window* pWindow = pFrame ? pFrame->GetWindow() : nullptr;
-
         if( pWindow )
         {
             const Point aPoint;
@@ -532,6 +536,7 @@ bool AquaSalInstance::RunInMainYield( bool 
bHandleAllCurrentEvents )
     return false;
 
 }
+
 static bool isWakeupEvent( NSEvent *pEvent )
 {
 SAL_WNODEPRECATED_DECLARATIONS_PUSH
@@ -542,8 +547,6 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
 
 bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
 {
-    bool bHadEvent = false;
-
     // ensure that the per thread autorelease pool is top level and
     // will therefore not be destroyed by cocoa implicitly
     SalData::ensureThreadAutoreleasePool();
@@ -552,36 +555,10 @@ bool AquaSalInstance::DoYield(bool bWait, bool 
bHandleAllCurrentEvents)
     // an own pool for each yield level
     ReleasePoolHolder aReleasePool;
 
-    // Release all locks so that we don't deadlock when we pull pending
-    // events from the event queue
-    bool bDispatchUser = true;
-    while( bDispatchUser )
-    {
-        // get one user event
-        SalUserEvent aEvent( nullptr, nullptr, SalEvent::NONE );
-        {
-            osl::MutexGuard g( maUserEventListMutex );
-            if( ! maUserEvents.empty() )
-            {
-                aEvent = maUserEvents.front();
-                maUserEvents.pop_front();
-                bHadEvent = true;
-            }
-            else
-                bDispatchUser = false;
-        }
-
-        // dispatch it
-        if( aEvent.mpFrame && AquaSalFrame::isAlive( aEvent.mpFrame ) )
-        {
-            aEvent.mpFrame->CallCallback( aEvent.mnType, aEvent.mpData );
-            maWaitingYieldCond.set();
-        }
-
-        // return if only one event is asked for
-        if( !bHandleAllCurrentEvents && bDispatchUser )
-            return true;
-    }
+    // first, process current user events
+    bool bHadEvent = DispatchUserEvents( bHandleAllCurrentEvents );
+    if ( !bHandleAllCurrentEvents && bHadEvent )
+        return true;
 
     // handle cocoa event queue
     // cocoa events may be only handled in the thread the NSApp was created
@@ -639,13 +616,13 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
         }
 
         // collect update rectangles
-        const std::list< AquaSalFrame* > rFrames( GetSalData()->maFrames );
-        for( std::list< AquaSalFrame* >::const_iterator it = rFrames.begin(); 
it != rFrames.end(); ++it )
+        for( auto pSalFrame : GetSalData()->mpFirstInstance->getFrames() )
         {
-            if( (*it)->mbShown && ! (*it)->maInvalidRect.IsEmpty() )
+            AquaSalFrame* pFrame = static_cast<AquaSalFrame*>( 
const_cast<SalFrame*>( pSalFrame ) );
+            if( pFrame->mbShown && ! pFrame->maInvalidRect.IsEmpty() )
             {
-                (*it)->Flush( (*it)->maInvalidRect );
-                (*it)->maInvalidRect.SetEmpty();
+                pFrame->Flush( pFrame->maInvalidRect );
+                pFrame->maInvalidRect.SetEmpty();
             }
         }
 
diff --git a/vcl/osx/vclnsapp.mm b/vcl/osx/vclnsapp.mm
index 651fa2a014cc..f06c9fd0b2ab 100644
--- a/vcl/osx/vclnsapp.mm
+++ b/vcl/osx/vclnsapp.mm
@@ -248,77 +248,70 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
 -(void)cycleFrameForward: (AquaSalFrame*)pCurFrame
 {
     // find current frame in list
-    std::list< AquaSalFrame* >& rFrames( GetSalData()->maFrames );
-    std::list< AquaSalFrame* >::iterator it = rFrames.begin();
-    for( ; it != rFrames.end() && *it != pCurFrame; ++it )
-        ;
+    auto &rFrames( GetSalData()->mpFirstInstance->getFrames() );
+    auto it = rFrames.find( pCurFrame );
     if( it != rFrames.end() )
     {
+        ++it;
         // now find the next frame (or end)
-        do
+        for( ; it != rFrames.end(); ++it )
         {
-            ++it;
-            if( it != rFrames.end() )
+            auto pFrame = static_cast<const AquaSalFrame*>( *it );
+            if( pFrame->mpDockMenuEntry != nullptr && pFrame->mbShown )
             {
-                if( (*it)->mpDockMenuEntry != nullptr &&
-                    (*it)->mbShown )
-                {
-                    [(*it)->getNSWindow() makeKeyAndOrderFront: NSApp];
-                    return;
-                }
+                [pFrame->getNSWindow() makeKeyAndOrderFront: NSApp];
+                return;
             }
-        } while( it != rFrames.end() );
+        }
         // cycle around, find the next up to pCurFrame
-        it = rFrames.begin();
-        while( *it != pCurFrame )
+        for( it = rFrames.begin(); *it != pCurFrame; ++it )
         {
-            if( (*it)->mpDockMenuEntry != nullptr &&
-                (*it)->mbShown )
+            auto pFrame = static_cast<const AquaSalFrame*>( *it );
+            if( pFrame->mpDockMenuEntry != nullptr && pFrame->mbShown )
             {
-                [(*it)->getNSWindow() makeKeyAndOrderFront: NSApp];
+                [pFrame->getNSWindow() makeKeyAndOrderFront: NSApp];
                 return;
             }
-            ++it;
         }
     }
 }
 
+template< class Iterator >
+std::reverse_iterator<Iterator> make_reverse_iterator( Iterator i )
+{
+    return std::reverse_iterator<Iterator>(i);
+}
+
 -(void)cycleFrameBackward: (AquaSalFrame*)pCurFrame
 {
     // do the same as cycleFrameForward only with a reverse iterator
 
     // find current frame in list
-    std::list< AquaSalFrame* >& rFrames( GetSalData()->maFrames );
-    std::list< AquaSalFrame* >::reverse_iterator it = rFrames.rbegin();
-    for( ; it != rFrames.rend() && *it != pCurFrame; ++it )
-        ;
-    if( it != rFrames.rend() )
+    auto &rFrames( GetSalData()->mpFirstInstance->getFrames() );
+    auto search_it = rFrames.find( pCurFrame );
+    if( search_it != rFrames.end() )
     {
+        auto it = ::make_reverse_iterator( search_it );
+        ++it;
         // now find the next frame (or end)
-        do
+        for( ; it != rFrames.rend(); ++it )
         {
-            ++it;
-            if( it != rFrames.rend() )
+            auto pFrame = static_cast<const AquaSalFrame*>( *it );
+            if( pFrame->mpDockMenuEntry != nullptr && pFrame->mbShown )
             {
-                if( (*it)->mpDockMenuEntry != nullptr &&
-                    (*it)->mbShown )
-                {
-                    [(*it)->getNSWindow() makeKeyAndOrderFront: NSApp];
-                    return;
-                }
+                [pFrame->getNSWindow() makeKeyAndOrderFront: NSApp];
+                return;
             }
-        } while( it != rFrames.rend() );
+        }
         // cycle around, find the next up to pCurFrame
-        it = rFrames.rbegin();
-        while( *it != pCurFrame )
+        for( it = rFrames.rbegin(); *it != pCurFrame; ++it )
         {
-            if( (*it)->mpDockMenuEntry != nullptr &&
-                (*it)->mbShown )
+            auto pFrame = static_cast<const AquaSalFrame*>( *it );
+            if( pFrame->mpDockMenuEntry != nullptr && pFrame->mbShown )
             {
-                [(*it)->getNSWindow() makeKeyAndOrderFront: NSApp];
+                [pFrame->getNSWindow() makeKeyAndOrderFront: NSApp];
                 return;
             }
-            ++it;
         }
     }
 }
@@ -413,12 +406,13 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
     {
         SolarMutexGuard aGuard;
 
-        SalData* pSalData = GetSalData();
-        if( ! pSalData->maFrames.empty() )
+        AquaSalInstance *pInst = GetSalData()->mpFirstInstance;
+        SalFrame *pAnyFrame = pInst->anyFrame();
+        if( pAnyFrame )
         {
             // the following QueryExit will likely present a message box, 
activate application
             [NSApp activateIgnoringOtherApps: YES];
-            aReply = pSalData->maFrames.front()->CallCallback( 
SalEvent::Shutdown, nullptr ) ? NSTerminateCancel : NSTerminateNow;
+            aReply = pAnyFrame->CallCallback( SalEvent::Shutdown, nullptr ) ? 
NSTerminateCancel : NSTerminateNow;
         }
 
         if( aReply == NSTerminateNow )
@@ -439,9 +433,10 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
     (void)pNotification;
     SolarMutexGuard aGuard;
 
-    const SalData* pSalData = GetSalData();
-    if( !pSalData->maFrames.empty() )
-        pSalData->maFrames.front()->CallCallback( SalEvent::SettingsChanged, 
nullptr );
+    AquaSalInstance *pInst = GetSalData()->mpFirstInstance;
+    SalFrame *pAnyFrame = pInst->anyFrame();
+    if(  pAnyFrame )
+        pAnyFrame->CallCallback( SalEvent::SettingsChanged, nullptr );
 }
 
 -(void)screenParametersChanged: (NSNotification*) pNotification
@@ -449,11 +444,10 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
     (void)pNotification;
     SolarMutexGuard aGuard;
 
-    SalData* pSalData = GetSalData();
-    std::list< AquaSalFrame* >::iterator it;
-    for( it = pSalData->maFrames.begin(); it != pSalData->maFrames.end(); ++it 
)
+    for( auto pSalFrame : GetSalData()->mpFirstInstance->getFrames() )
     {
-        (*it)->screenParametersChanged();
+        AquaSalFrame *pFrame = static_cast<AquaSalFrame*>( 
const_cast<SalFrame*>( pSalFrame ) );
+        pFrame->screenParametersChanged();
     }
 }
 
diff --git a/vcl/quartz/salvd.cxx b/vcl/quartz/salvd.cxx
index 3110398b8784..fe48f0b80326 100644
--- a/vcl/quartz/salvd.cxx
+++ b/vcl/quartz/salvd.cxx
@@ -255,19 +255,10 @@ bool AquaSalVirtualDevice::SetSize( long nDX, long nDY )
         AquaSalFrame* pSalFrame = mpGraphics->getGraphicsFrame();
         if( !pSalFrame || !AquaSalFrame::isAlive( pSalFrame ))
         {
-            if( !GetSalData()->maFrames.empty() )
-            {
-                // get the first matching frame
-                pSalFrame = *GetSalData()->maFrames.begin();
-            }
-            else
-            {
-                // ensure we don't reuse a dead AquaSalFrame on the very
-                // unlikely case of no other frame to use
-                pSalFrame = nullptr;
-            }
-            // update the frame reference
-            mpGraphics->setGraphicsFrame( pSalFrame );
+            pSalFrame = static_cast<AquaSalFrame*>( 
GetSalData()->mpFirstInstance->anyFrame() );
+            if ( pSalFrame )
+                // update the frame reference
+                mpGraphics->setGraphicsFrame( pSalFrame );
         }
         if( pSalFrame )
         {
diff --git a/vcl/source/app/salusereventlist.cxx 
b/vcl/source/app/salusereventlist.cxx
new file mode 100644
index 000000000000..22ae1b73d728
--- /dev/null
+++ b/vcl/source/app/salusereventlist.cxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <salusereventlist.hxx>
+#include <salwtype.hxx>
+
+#include <algorithm>
+
+SalUserEventList::SalUserEventList()
+{
+}
+
+SalUserEventList::~SalUserEventList()
+{
+}
+
+void SalUserEventList::insertFrame( const SalFrame* pFrame )
+{
+    auto aPair = m_aFrames.insert( pFrame );
+    assert( aPair.second ); (void) aPair;
+}
+
+void SalUserEventList::eraseFrame( const SalFrame* pFrame )
+{
+    auto it = m_aFrames.find( pFrame );
+    assert( it != m_aFrames.end() );
+    if ( it != m_aFrames.end() )
+        m_aFrames.erase( it );
+}
+
+bool SalUserEventList::DispatchUserEvents( bool bHandleAllCurrentEvents )
+{
+    bool bWasEvent = false;
+
+    {
+        osl::MutexGuard aGuard( m_aUserEventsMutex );
+        if( ! m_aUserEvents.empty() )
+        {
+            if( bHandleAllCurrentEvents )
+                m_aProcessingUserEvents.swap( m_aUserEvents );
+            else
+            {
+                m_aProcessingUserEvents.push_back( m_aUserEvents.front() );
+                m_aUserEvents.pop_front();
+            }
+            bWasEvent = true;
+        }
+    }
+
+    if( bWasEvent )
+    {
+        SalUserEvent aEvent( nullptr, nullptr, SalEvent::NONE );
+        do {
+            {
+                osl::MutexGuard aGuard( m_aUserEventsMutex );
+                if ( m_aProcessingUserEvents.empty() )
+                    break;
+                aEvent = m_aProcessingUserEvents.front();
+                m_aProcessingUserEvents.pop_front();
+            }
+
+            if ( isFrameAlive( aEvent.m_pFrame ) )
+                ProcessEvent( aEvent );
+        }
+        while( true );
+    }
+
+    osl::MutexGuard aGuard( m_aUserEventsMutex );
+    if ( !HasUserEvents() )
+        TriggerAllUserEventsProcessed();
+
+    return bWasEvent;
+}
+
+bool SalUserEventList::RemoveEvent( SalFrame* pFrame, void* pData, SalEvent 
nEvent )
+{
+    SalUserEvent aEvent( pFrame, pData, nEvent );
+    bool bResult = false;
+
+    osl::MutexGuard aGuard( m_aUserEventsMutex );
+    auto it = std::find( m_aUserEvents.begin(), m_aUserEvents.end(), aEvent );
+    if ( it != m_aUserEvents.end() )
+    {
+        m_aUserEvents.erase( it );
+        bResult = true;
+    }
+    else
+    {
+        it = std::find( m_aProcessingUserEvents.begin(), 
m_aProcessingUserEvents.end(), aEvent );
+        if ( it != m_aProcessingUserEvents.end() )
+        {
+            m_aProcessingUserEvents.erase( it );
+            bResult = true;
+        }
+    }
+
+    if ( bResult && !HasUserEvents() )
+        TriggerAllUserEventsProcessed();
+
+    return bResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/app/gendisp.cxx b/vcl/unx/generic/app/gendisp.cxx
index edaf0e6ffb95..fbb27657e76d 100644
--- a/vcl/unx/generic/app/gendisp.cxx
+++ b/vcl/unx/generic/app/gendisp.cxx
@@ -22,7 +22,6 @@
 #include <unx/geninst.h>
 
 SalGenericDisplay::SalGenericDisplay()
- : m_aEventGuard()
 {
     m_pCapture = nullptr;
 }
@@ -31,96 +30,41 @@ SalGenericDisplay::~SalGenericDisplay()
 {
 }
 
-void SalGenericDisplay::registerFrame( SalFrame* pFrame )
+void SalGenericDisplay::registerFrame( const SalFrame* pFrame )
 {
-    m_aFrames.push_front( pFrame );
+    insertFrame( pFrame );
 }
 
-void SalGenericDisplay::deregisterFrame( SalFrame* pFrame )
+void SalGenericDisplay::deregisterFrame( const SalFrame* pFrame )
 {
-    {
-        osl::MutexGuard g( m_aEventGuard );
-        std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
-        while ( it != m_aUserEvents.end() )
-        {
-            if( it->m_pFrame == pFrame )
-            {
-                if (it->m_nEvent == SalEvent::UserEvent) {
-                    delete static_cast<ImplSVEvent *>(it->m_pData);
-                }
-                it = m_aUserEvents.erase( it );
-            }
-            else
-                ++it;
-        }
-    }
-
-    m_aFrames.remove( pFrame );
+    eraseFrame( pFrame );
 }
 
 void SalGenericDisplay::emitDisplayChanged()
 {
-    if( !m_aFrames.empty() )
-        m_aFrames.front()->CallCallback( SalEvent::DisplayChanged, nullptr );
+    SalFrame *pAnyFrame = anyFrame();
+    if( pAnyFrame )
+        pAnyFrame->CallCallback( SalEvent::DisplayChanged, nullptr );
 }
 
 bool SalGenericDisplay::DispatchInternalEvent()
 {
-    void* pData = nullptr;
-    SalFrame* pFrame = nullptr;
-    SalEvent nEvent = SalEvent::NONE;
-
-    {
-        osl::MutexGuard g( m_aEventGuard );
-        if( !m_aUserEvents.empty() )
-        {
-            pFrame  = m_aUserEvents.front().m_pFrame;
-            pData   = m_aUserEvents.front().m_pData;
-            nEvent  = m_aUserEvents.front().m_nEvent;
-
-            m_aUserEvents.pop_front();
-        }
-    }
-
-    if( pFrame )
-        pFrame->CallCallback( nEvent, pData );
-
-    return pFrame != nullptr;
+    return DispatchUserEvents( false );
 }
 
 void SalGenericDisplay::SendInternalEvent( SalFrame* pFrame, void* pData, 
SalEvent nEvent )
 {
-    osl::MutexGuard g( m_aEventGuard );
-
-    m_aUserEvents.emplace_back( pFrame, pData, nEvent );
-
-    PostUserEvent(); // wakeup the concrete mainloop
+    PostEvent( pFrame, pData, nEvent );
 }
 
-void SalGenericDisplay::CancelInternalEvent( SalFrame const * pFrame, void 
const * pData, SalEvent nEvent )
+void SalGenericDisplay::CancelInternalEvent( SalFrame* pFrame, void* pData, 
SalEvent nEvent )
 {
-    osl::MutexGuard g( m_aEventGuard );
-    if( ! m_aUserEvents.empty() )
-    {
-        std::list< SalUserEvent >::iterator it = m_aUserEvents.begin();
-        while (it != m_aUserEvents.end())
-        {
-            if( it->m_pFrame    == pFrame   &&
-                it->m_pData     == pData    &&
-                it->m_nEvent    == nEvent )
-            {
-                it = m_aUserEvents.erase( it );
-            }
-            else
-                ++it;
-        }
-    }
+    RemoveEvent( pFrame, pData, nEvent );
 }
 
-bool SalGenericDisplay::HasUserEvents() const
+void SalGenericDisplay::ProcessEvent( SalUserEvent aEvent )
 {
-    osl::MutexGuard g( m_aEventGuard );
-    return !m_aUserEvents.empty();
+    aEvent.m_pFrame->CallCallback( aEvent.m_nEvent, aEvent.m_pData );
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/app/i18n_status.cxx 
b/vcl/unx/generic/app/i18n_status.cxx
index f2be4d7b47a2..81ce3a5450b2 100644
--- a/vcl/unx/generic/app/i18n_status.cxx
+++ b/vcl/unx/generic/app/i18n_status.cxx
@@ -170,12 +170,9 @@ bool XIMStatusWindow::checkLastParent() const
 {
     if( m_pLastParent )
     {
-        const std::list< SalFrame* >& rFrames = 
vcl_sal::getSalDisplay(GetGenericUnixSalData())->getFrames();
-        for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it 
!= rFrames.end(); ++it )
-        {
-            if( *it == m_pLastParent )
-                return true;
-        }
+        auto rFrameList = 
vcl_sal::getSalDisplay(GetGenericUnixSalData())->getFrames();
+        auto it = rFrameList.find( m_pLastParent );
+        return it != rFrameList.end();
     }
     return false;
 }
diff --git a/vcl/unx/generic/app/saldata.cxx b/vcl/unx/generic/app/saldata.cxx
index 930356b76992..4ad2c02db54f 100644
--- a/vcl/unx/generic/app/saldata.cxx
+++ b/vcl/unx/generic/app/saldata.cxx
@@ -786,7 +786,7 @@ void SalXLib::Wakeup()
     OSL_VERIFY(write (m_pTimeoutFDS[1], "", 1) == 1);
 }
 
-void SalXLib::PostUserEvent()
+void SalXLib::TriggerUserEventProcessing()
 {
     Wakeup();
 }
diff --git a/vcl/unx/generic/app/saldisp.cxx b/vcl/unx/generic/app/saldisp.cxx
index cd96818420ad..51c73c4915bc 100644
--- a/vcl/unx/generic/app/saldisp.cxx
+++ b/vcl/unx/generic/app/saldisp.cxx
@@ -431,10 +431,10 @@ SalX11Display::~SalX11Display()
     }
 }
 
-void SalX11Display::PostUserEvent()
+void SalX11Display::TriggerUserEventProcessing()
 {
     if( pXLib_ )
-        pXLib_->PostUserEvent();
+        pXLib_->TriggerUserEventProcessing();
 }
 
 SalDisplay::ScreenData *
@@ -1935,17 +1935,16 @@ bool SalX11Display::Dispatch( XEvent *pEvent )
     {
         ::Window aWindow = pEvent->xkey.window;
 
-        std::list< SalFrame* >::const_iterator it;
-        for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
+        for (auto pSalFrame : m_aFrames )
         {
-            const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it);
+            const X11SalFrame* pFrame = static_cast< const X11SalFrame* >( 
pSalFrame );
             if( pFrame->GetWindow() == aWindow || pFrame->GetShellWindow() == 
aWindow )
             {
                 aWindow = pFrame->GetWindow();
                 break;
             }
         }
-        if( it != m_aFrames.end() )
+        if( aWindow != pEvent->xkey.window )
         {
             if ( pInputMethod && pInputMethod->FilterEvent( pEvent , aWindow ) 
)
                 return false;
@@ -1975,9 +1974,8 @@ bool SalX11Display::Dispatch( XEvent *pEvent )
                 {
                     if( pEvent->xproperty.window == rScreen.m_aRefWindow )
                     {
-                        std::list< SalFrame* >::const_iterator it;
-                        for( it = m_aFrames.begin(); it != m_aFrames.end(); 
++it )
-                            (*it)->CallCallback( SalEvent::SettingsChanged, 
nullptr );
+                        for (auto pSalFrame : m_aFrames )
+                             pSalFrame->CallCallback( 
SalEvent::SettingsChanged, nullptr );
                         return false;
                     }
                 }
@@ -2009,10 +2007,10 @@ bool SalX11Display::Dispatch( XEvent *pEvent )
             break;
     }
 
-    std::list< SalFrame* >::iterator it;
-    for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it )
+    for (auto pSalFrame : m_aFrames )
     {
-        X11SalFrame* pFrame = static_cast< X11SalFrame* >(*it);
+        X11SalFrame* pFrame = static_cast<X11SalFrame*>( 
const_cast<SalFrame*>( pSalFrame ) );
+
         ::Window aDispatchWindow = pEvent->xany.window;
         if( pFrame->GetWindow() == aDispatchWindow
             || pFrame->GetShellWindow() == aDispatchWindow
diff --git a/vcl/unx/generic/app/salinst.cxx b/vcl/unx/generic/app/salinst.cxx
index e38164ee247b..d722f28e686c 100644
--- a/vcl/unx/generic/app/salinst.cxx
+++ b/vcl/unx/generic/app/salinst.cxx
@@ -225,10 +225,8 @@ void X11SalInstance::AddToRecentDocumentList(const 
OUString& rFileUrl, const OUS
 void X11SalInstance::PostPrintersChanged()
 {
     SalDisplay* pDisp = vcl_sal::getSalDisplay(GetGenericUnixSalData());
-    const std::list< SalFrame* >& rList = pDisp->getFrames();
-    for( std::list< SalFrame* >::const_iterator it = rList.begin();
-         it != rList.end(); ++it )
-        pDisp->SendInternalEvent( *it, nullptr, SalEvent::PrinterChanged );
+    for (auto pSalFrame : pDisp->getFrames() )
+        pDisp->PostEvent( const_cast<SalFrame*>( pSalFrame ), nullptr, 
SalEvent::PrinterChanged );
 }
 
 GenPspGraphics *X11SalInstance::CreatePrintGraphics()
diff --git a/vcl/unx/generic/app/sm.cxx b/vcl/unx/generic/app/sm.cxx
index e6da11244074..4beb1d58b2c3 100644
--- a/vcl/unx/generic/app/sm.cxx
+++ b/vcl/unx/generic/app/sm.cxx
@@ -293,10 +293,9 @@ IMPL_STATIC_LINK( SessionManagerClient, SaveYourselfHdl, 
void*, pStateVal, void
           task of the quick-starter)
         */
         *pSmRestartHint = SmRestartNever;
-        const std::list< SalFrame* >& rFrames = 
vcl_sal::getSalDisplay(GetGenericUnixSalData())->getFrames();
-        for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it 
!= rFrames.end(); ++it )
+        for (auto pSalFrame : 
vcl_sal::getSalDisplay(GetGenericUnixSalData())->getFrames() )
         {
-            vcl::Window *pWindow = (*it)->GetWindow();
+            vcl::Window *pWindow = pSalFrame->GetWindow();
             if (pWindow && pWindow->IsVisible())
             {
                 *pSmRestartHint = SmRestartIfRunning;
@@ -394,11 +393,10 @@ IMPL_STATIC_LINK_NOARG( SessionManagerClient, 
ShutDownHdl, void*, void )
         m_pSession->CallCallback( &aEvent );
     }
 
-    const std::list< SalFrame* >& rFrames = 
vcl_sal::getSalDisplay(GetGenericUnixSalData())->getFrames();
-
-    SAL_INFO("vcl.sm.debug", "  rFrames.empty() = " << (rFrames.empty() ? 
"true" : "false"));
-    if( !rFrames.empty() )
-        rFrames.front()->CallCallback( SalEvent::Shutdown, nullptr );
+    SalFrame *pAnyFrame = 
vcl_sal::getSalDisplay(GetGenericUnixSalData())->anyFrame();
+    SAL_INFO("vcl.sm.debug", "  rFrames.empty() = " << (pAnyFrame ? "true" : 
"false"));
+    if( pAnyFrame )
+        pAnyFrame->CallCallback( SalEvent::Shutdown, nullptr );
 }
 
 void SessionManagerClient::DieProc(
diff --git a/vcl/unx/generic/gdi/salgdi2.cxx b/vcl/unx/generic/gdi/salgdi2.cxx
index 6c4aba94f9d4..4c3175bcc09f 100644
--- a/vcl/unx/generic/gdi/salgdi2.cxx
+++ b/vcl/unx/generic/gdi/salgdi2.cxx
@@ -127,12 +127,11 @@ void X11SalGraphics::YieldGraphicsExpose()
     ::Window aWindow = GetDrawable();
     if( ! pFrame )
     {
-        const std::list< SalFrame* >& rFrames = 
vcl_sal::getSalDisplay(GetGenericUnixSalData())->getFrames();
-        for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it 
!= rFrames.end() && ! pFrame; ++it )
+        for (auto pSalFrame : 
vcl_sal::getSalDisplay(GetGenericUnixSalData())->getFrames() )
         {
-            const SystemEnvData* pEnvData = (*it)->GetSystemData();
+            const SystemEnvData* pEnvData = pSalFrame->GetSystemData();
             if( Drawable(pEnvData->aWindow) == aWindow )
-                pFrame = *it;
+                pFrame = const_cast<SalFrame*>( pSalFrame );
         }
         if( ! pFrame )
             return;
diff --git a/vcl/unx/generic/window/salframe.cxx 
b/vcl/unx/generic/window/salframe.cxx
index b89a736581d2..e2eb2ee2d237 100644
--- a/vcl/unx/generic/window/salframe.cxx
+++ b/vcl/unx/generic/window/salframe.cxx
@@ -492,15 +492,14 @@ void X11SalFrame::Init( SalFrameStyleFlags 
nSalFrameStyle, SalX11Screen nXScreen
 
         // check if this is really one of our own frames
         // do not change the input mask in that case
-        const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
-        std::list< SalFrame* >::const_iterator it = rFrames.begin();
-        while( it != rFrames.end() && mhForeignParent != static_cast<const 
X11SalFrame*>(*it)->GetWindow() )
-            ++it;
-
-        if( it == rFrames.end() )
+        for (auto pSalFrame : GetDisplay()->getFrames() )
         {
-            XSelectInput( GetDisplay()->GetDisplay(), mhForeignParent, 
StructureNotifyMask | FocusChangeMask );
-            XSelectInput( GetDisplay()->GetDisplay(), mhShellWindow, 
StructureNotifyMask | FocusChangeMask );
+            if ( static_cast<const X11SalFrame*>( pSalFrame )->GetWindow() == 
mhForeignParent )
+            {
+                XSelectInput( GetDisplay()->GetDisplay(), mhForeignParent, 
StructureNotifyMask | FocusChangeMask );
+                XSelectInput( GetDisplay()->GetDisplay(), mhShellWindow, 
StructureNotifyMask | FocusChangeMask );
+                break;
+            }
         }
     }
     else
@@ -521,11 +520,9 @@ void X11SalFrame::Init( SalFrameStyleFlags nSalFrameStyle, 
SalX11Screen nXScreen
             {
                 // find the last document window (if any)
                 const X11SalFrame* pFrame = nullptr;
-                const std::list< SalFrame* >& rFrames = 
GetDisplay()->getFrames();
-                std::list< SalFrame* >::const_iterator it = rFrames.begin();
-                while( it != rFrames.end() )
+                for (auto pSalFrame : GetDisplay()->getFrames() )
                 {
-                    pFrame = static_cast< const X11SalFrame* >(*it);
+                    pFrame = static_cast< const X11SalFrame* >( pSalFrame );
                     if( ! ( pFrame->mpParent
                             || pFrame->mbFullScreen
                             || ! ( pFrame->nStyle_ & 
SalFrameStyleFlags::SIZEABLE )
@@ -534,10 +531,9 @@ void X11SalFrame::Init( SalFrameStyleFlags nSalFrameStyle, 
SalX11Screen nXScreen
                             )
                         )
                         break;
-                    ++it;
                 }
 
-                if( it != rFrames.end() )
+                if( pFrame )
                 {
                     // set a document position and size
                     // the first frame gets positioned by the window manager
@@ -954,13 +950,12 @@ X11SalFrame::~X11SalFrame()
      *  check if there is only the status frame left
      *  if so, free it
      */
-    if( ! GetDisplay()->getFrames().empty() && vcl::I18NStatus::exists() )
+    auto &rFrames = GetDisplay()->getFrames();
+    if( ! rFrames.empty() && vcl::I18NStatus::exists() )
     {
         SalFrame* pStatusFrame = vcl::I18NStatus::get().getStatusFrame();
-        std::list< SalFrame* >::const_iterator sit = 
GetDisplay()->getFrames().begin();
-        if( pStatusFrame
-            && *sit == pStatusFrame
-            && ++sit == GetDisplay()->getFrames().end() )
+        auto sit = rFrames.begin();
+        if( pStatusFrame && *sit == pStatusFrame && ++sit == rFrames.end() )
             vcl::I18NStatus::free();
     }
 }
@@ -1204,10 +1199,9 @@ void X11SalFrame::Show( bool bVisible, bool bNoActivate )
         if( ! (nStyle_ & SalFrameStyleFlags::INTRO) )
         {
             // hide all INTRO frames
-            const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
-            for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); 
it != rFrames.end(); ++it )
+            for (auto pSalFrame : GetDisplay()->getFrames() )
             {
-                const X11SalFrame* pFrame = static_cast< const X11SalFrame* 
>(*it);
+                const X11SalFrame* pFrame = static_cast< const X11SalFrame* >( 
pSalFrame );
                 // look for intro bit map; if present, hide it
                 if( pFrame->nStyle_ & SalFrameStyleFlags::INTRO )
                 {
@@ -2698,10 +2692,9 @@ bool X11SalFrame::HandleMouseEvent( XEvent *pEvent )
             // see if the user clicks outside all of the floats
             // if yes release the grab
             bool bInside = false;
-            const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames();
-            for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); 
it != rFrames.end(); ++it )
+            for (auto pSalFrame : GetDisplay()->getFrames() )
             {
-                const X11SalFrame* pFrame = static_cast< const X11SalFrame* 
>(*it);
+                const X11SalFrame* pFrame = static_cast< const X11SalFrame* >( 
pSalFrame );
                 if( pFrame->IsFloatGrabWindow()                                
     &&
                     pFrame->bMapped_                                           
     &&
                     pEvent->xbutton.x_root >= pFrame->maGeometry.nX            
                 &&
@@ -2738,9 +2731,9 @@ bool X11SalFrame::HandleMouseEvent( XEvent *pEvent )
                     && aChild // pointer may not be in any child
                     )
                 {
-                    for( std::list< SalFrame* >::const_iterator it = 
rFrames.begin(); it != rFrames.end(); ++it )
+                    for (auto pSalFrame : GetDisplay()->getFrames() )
                     {
-                        const X11SalFrame* pFrame = static_cast< const 
X11SalFrame* >(*it);
+                        const X11SalFrame* pFrame = static_cast< const 
X11SalFrame* >( pSalFrame );
                         if( ! pFrame->IsFloatGrabWindow()
                             && ( pFrame->GetWindow() == aChild ||
                                  pFrame->GetShellWindow() == aChild ||
diff --git a/vcl/unx/gtk/gtkdata.cxx b/vcl/unx/gtk/gtkdata.cxx
index eaa34d9461e5..bba4355ced6a 100644
--- a/vcl/unx/gtk/gtkdata.cxx
+++ b/vcl/unx/gtk/gtkdata.cxx
@@ -133,19 +133,17 @@ GdkFilterReturn GtkSalDisplay::filterGdkEvent( GdkXEvent* 
sys_event )
         // so we need to listen for corresponding property notifications here
         // these should be rare enough so that we can assume that the settings
         // actually change when a corresponding PropertyNotify occurs
-        if( pEvent->type == PropertyNotify &&
-            pEvent->xproperty.atom == getWMAdaptor()->getAtom( 
WMAdaptor::XSETTINGS ) &&
-            ! m_aFrames.empty()
-           )
+        SalFrame *pAnyFrame = anyFrame();
+        if( pAnyFrame && pEvent->type == PropertyNotify &&
+            pEvent->xproperty.atom == getWMAdaptor()->getAtom( 
WMAdaptor::XSETTINGS ) )
         {
-            SendInternalEvent( m_aFrames.front(), nullptr, 
SalEvent::SettingsChanged );
+            PostEvent( pAnyFrame, nullptr, SalEvent::SettingsChanged );
         }
         // let's see if one of our frames wants to swallow these events
         // get the frame
-        for( std::list< SalFrame* >::const_iterator it = m_aFrames.begin();
-                 it != m_aFrames.end(); ++it )
+        for (auto pSalFrame : m_aFrames )
         {
-            GtkSalFrame* pFrame = static_cast<GtkSalFrame*>(*it);
+            GtkSalFrame* pFrame = static_cast<GtkSalFrame*>( 
const_cast<SalFrame*>( pSalFrame ) );
             if( pFrame->GetSystemData()->aWindow == pEvent->xany.window ||
                 ( pFrame->getForeignParent() && 
pFrame->getForeignParentWindow() == pEvent->xany.window ) ||
                 ( pFrame->getForeignTopLevel() && 
pFrame->getForeignTopLevelWindow() == pEvent->xany.window )
@@ -213,11 +211,10 @@ bool GtkSalDisplay::Dispatch( XEvent* pEvent )
     {
         // let's see if one of our frames wants to swallow these events
         // get the child frame
-        for( std::list< SalFrame* >::const_iterator it = m_aFrames.begin();
-             it != m_aFrames.end(); ++it )
+        for (auto pSalFrame : m_aFrames )
         {
-            if ((*it)->GetSystemData()->aWindow == pEvent->xany.window)
-                return static_cast<GtkSalFrame*>(*it)->Dispatch( pEvent );
+            if (pSalFrame->GetSystemData()->aWindow == pEvent->xany.window)
+                return static_cast<GtkSalFrame*>( const_cast<SalFrame*>( 
pSalFrame ) )->Dispatch( pEvent );
         }
     }
 
@@ -816,47 +813,23 @@ void GtkSalTimer::Stop()
     }
 }
 
-gboolean GtkSalData::userEventFn( gpointer data )
-{
-    gboolean bContinue = FALSE;
-    GtkSalData *pThis = static_cast<GtkSalData *>(data);
-    GenericUnixSalData *pData = GetGenericUnixSalData();
-    SolarMutexGuard aGuard;
-    const SalGenericDisplay *pDisplay = pData->GetDisplay();
-    if (pDisplay)
-    {
-        OSL_ASSERT(static_cast<const SalGenericDisplay 
*>(pThis->GetGtkDisplay()) == pDisplay);
-        {
-            osl::MutexGuard g (pThis->GetGtkDisplay()->getEventGuardMutex());
-
-            if( !pThis->GetGtkDisplay()->HasUserEvents() )
-            {
-                if( pThis->m_pUserEvent )
-                {
-                    g_source_unref (pThis->m_pUserEvent);
-                    pThis->m_pUserEvent = nullptr;
-                }
-                bContinue = FALSE;
-            }
-            else
-                bContinue = TRUE;
-        }
-        pThis->GetGtkDisplay()->DispatchInternalEvent();
-    }
-
-    return bContinue;
-}
-
 extern "C" {
     static gboolean call_userEventFn( void *data )
     {
+        GtkSalData *pThis = static_cast<GtkSalData *>(data);
         SolarMutexGuard aGuard;
-        return GtkSalData::userEventFn( data );
+        const SalGenericDisplay *pDisplay = 
GetGenericUnixSalData()->GetDisplay();
+        if ( pDisplay )
+        {
+            GtkSalDisplay *pThisDisplay = pThis->GetGtkDisplay();
+            assert(static_cast<const SalGenericDisplay *>(pThisDisplay) == 
pDisplay);
+            pThisDisplay->DispatchInternalEvent();
+        }
+        return TRUE;
     }
 }
 
-// hEventGuard_ held during this invocation
-void GtkSalData::PostUserEvent()
+void GtkSalData::TriggerUserEventProcessing()
 {
     if (m_pUserEvent)
         g_main_context_wakeup (nullptr); // really needed ?
@@ -871,16 +844,28 @@ void GtkSalData::PostUserEvent()
     }
 }
 
-void GtkSalDisplay::PostUserEvent()
+void GtkSalData::TriggerAllUserEventsProcessed()
+{
+    assert( m_pUserEvent );
+    g_source_destroy( m_pUserEvent );
+    g_source_unref( m_pUserEvent );
+    m_pUserEvent = nullptr;
+}
+
+void GtkSalDisplay::TriggerUserEventProcessing()
+{
+    GetGtkSalData()->TriggerUserEventProcessing();
+}
+
+void GtkSalDisplay::TriggerAllUserEventsProcessed()
 {
-    GetGtkSalData()->PostUserEvent();
+    GetGtkSalData()->TriggerAllUserEventsProcessed();
 }
 
 GtkWidget* GtkSalDisplay::findGtkWidgetForNativeHandle(sal_uIntPtr hWindow) 
const
 {
-    for (auto it = m_aFrames.begin(); it != m_aFrames.end(); ++it)
+    for (auto pFrame : m_aFrames)
     {
-        SalFrame* pFrame = *it;
         const SystemEnvData* pEnvData = pFrame->GetSystemData();
         if (pEnvData->aWindow == hWindow)
             return GTK_WIDGET(pEnvData->pWidget);
@@ -888,7 +873,7 @@ GtkWidget* 
GtkSalDisplay::findGtkWidgetForNativeHandle(sal_uIntPtr hWindow) cons
     return nullptr;
 }
 
-void GtkSalDisplay::deregisterFrame( SalFrame* pFrame )
+void GtkSalDisplay::deregisterFrame( const SalFrame* pFrame )
 {
     if( m_pCapture == pFrame )
     {
diff --git a/vcl/unx/gtk/gtksalframe.cxx b/vcl/unx/gtk/gtksalframe.cxx
index 3ca2b4816ad8..0077a056bb53 100644
--- a/vcl/unx/gtk/gtksalframe.cxx
+++ b/vcl/unx/gtk/gtksalframe.cxx
@@ -2180,10 +2180,9 @@ void GtkSalFrame::grabPointer( bool bGrab, bool 
bOwnerEvents )
     if( bGrab )
     {
         bool bUseGdkGrab = true;
-        const std::list< SalFrame* >& rFrames = getDisplay()->getFrames();
-        for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it 
!= rFrames.end(); ++it )
+        for (auto pSalFrame : getDisplay()->getFrames() )
         {
-            const GtkSalFrame* pFrame = static_cast< const GtkSalFrame* >(*it);
+            const GtkSalFrame* pFrame = static_cast< const GtkSalFrame* >( 
pSalFrame );
             if( pFrame->m_bWindowIsGtkPlug )
             {
                 bUseGdkGrab = false;
diff --git a/vcl/unx/gtk3/gtk3gtkdata.cxx b/vcl/unx/gtk3/gtk3gtkdata.cxx
index 844dc77f20c1..acb7db876b73 100644
--- a/vcl/unx/gtk3/gtk3gtkdata.cxx
+++ b/vcl/unx/gtk3/gtk3gtkdata.cxx
@@ -778,47 +778,23 @@ void GtkSalTimer::Stop()
     }
 }
 
-gboolean GtkSalData::userEventFn( gpointer data )
-{
-    gboolean bContinue = FALSE;
-    GtkSalData *pThis = static_cast<GtkSalData *>(data);
-    GenericUnixSalData *pData = GetGenericUnixSalData();
-    SolarMutexGuard aGuard;
-    const SalGenericDisplay *pDisplay = pData->GetDisplay();
-    if (pDisplay)
-    {
-        OSL_ASSERT(static_cast<const SalGenericDisplay 
*>(pThis->GetGtkDisplay()) == pDisplay);
-        {
-            osl::MutexGuard g (pThis->GetGtkDisplay()->getEventGuardMutex());
-
-            if( !pThis->GetGtkDisplay()->HasUserEvents() )
-            {
-                if( pThis->m_pUserEvent )
-                {
-                    g_source_unref (pThis->m_pUserEvent);
-                    pThis->m_pUserEvent = nullptr;
-                }
-                bContinue = FALSE;
-            }
-            else
-                bContinue = TRUE;
-        }
-        pThis->GetGtkDisplay()->DispatchInternalEvent();
-    }
-
-    return bContinue;
-}
-
 extern "C" {
     static gboolean call_userEventFn( void *data )
     {
+        GtkSalData *pThis = static_cast<GtkSalData *>(data);
         SolarMutexGuard aGuard;
-        return GtkSalData::userEventFn( data );
+        const SalGenericDisplay *pDisplay = 
GetGenericUnixSalData()->GetDisplay();
+        if ( pDisplay )
+        {
+            GtkSalDisplay *pThisDisplay = pThis->GetGtkDisplay();
+            assert(static_cast<const SalGenericDisplay *>(pThisDisplay) == 
pDisplay);
+            pThisDisplay->DispatchInternalEvent();
+        }
+        return TRUE;
     }
 }
 
-// hEventGuard_ held during this invocation
-void GtkSalData::PostUserEvent()
+void GtkSalData::TriggerUserEventProcessing()
 {
     if (m_pUserEvent)
         g_main_context_wakeup (nullptr); // really needed ?
@@ -836,24 +812,36 @@ void GtkSalData::PostUserEvent()
     }
 }
 
-void GtkSalDisplay::PostUserEvent()
+void GtkSalData::TriggerAllUserEventsProcessed()
+{
+    assert( m_pUserEvent );
+    g_source_destroy( m_pUserEvent );
+    g_source_unref( m_pUserEvent );
+    m_pUserEvent = nullptr;
+}
+
+void GtkSalDisplay::TriggerUserEventProcessing()
+{
+    GetGtkSalData()->TriggerUserEventProcessing();
+}
+
+void GtkSalDisplay::TriggerAllUserEventsProcessed()
 {
-    GetGtkSalData()->PostUserEvent();
+    GetGtkSalData()->TriggerAllUserEventsProcessed();
 }
 
 GtkWidget* GtkSalDisplay::findGtkWidgetForNativeHandle(sal_uIntPtr hWindow) 
const
 {
-    for (auto it = m_aFrames.begin(); it != m_aFrames.end(); ++it)
+    for (auto pSalFrame : m_aFrames )
     {
-        SalFrame* pFrame = *it;
-        const SystemEnvData* pEnvData = pFrame->GetSystemData();
+        const SystemEnvData* pEnvData = pSalFrame->GetSystemData();
         if (pEnvData->aWindow == hWindow)
             return GTK_WIDGET(pEnvData->pWidget);
     }
     return nullptr;
 }
 
-void GtkSalDisplay::deregisterFrame( SalFrame* pFrame )
+void GtkSalDisplay::deregisterFrame( const SalFrame* pFrame )
 {
     if( m_pCapture == pFrame )
     {
diff --git a/vcl/unx/kde4/KDESalDisplay.cxx b/vcl/unx/kde4/KDESalDisplay.cxx
index 4647b3d111c8..8a2422a3918d 100644
--- a/vcl/unx/kde4/KDESalDisplay.cxx
+++ b/vcl/unx/kde4/KDESalDisplay.cxx
@@ -86,4 +86,9 @@ bool SalKDEDisplay::checkDirectInputEvent( XEvent* ev )
     return false;
 }
 
+void SalKDEDisplay::TriggerUserEventProcessing()
+{
+    static_cast<KDEXLib*>(GetXLib())->TriggerUserEventProcessing();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/KDESalDisplay.hxx b/vcl/unx/kde4/KDESalDisplay.hxx
index 4a0458dcc5c2..07b5ca3dadf5 100644
--- a/vcl/unx/kde4/KDESalDisplay.hxx
+++ b/vcl/unx/kde4/KDESalDisplay.hxx
@@ -23,15 +23,18 @@
 
 class SalKDEDisplay : public SalX11Display
 {
-    public:
-        explicit SalKDEDisplay( Display* pDisp );
-        virtual ~SalKDEDisplay() override;
-        static SalKDEDisplay* self();
-        virtual void Yield() override;
-        bool checkDirectInputEvent( XEvent* ev );
-    private:
-        Atom xim_protocol;
-        static SalKDEDisplay* selfptr;
+    Atom xim_protocol;
+    static SalKDEDisplay* selfptr;
+
+protected:
+    virtual void TriggerUserEventProcessing() override;
+
+public:
+    explicit SalKDEDisplay( Display* pDisp );
+    virtual ~SalKDEDisplay() override;
+    static SalKDEDisplay* self();
+    virtual void Yield() override;
+    bool checkDirectInputEvent( XEvent* ev );
 };
 
 inline SalKDEDisplay* SalKDEDisplay::self()
diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx
index 402461e45bc6..f047ed9fce65 100644
--- a/vcl/unx/kde4/KDEXLib.cxx
+++ b/vcl/unx/kde4/KDEXLib.cxx
@@ -357,10 +357,10 @@ void KDEXLib::Wakeup()
     QAbstractEventDispatcher::instance( qApp->thread())->wakeUp(); // main 
thread event loop
 }
 
-void KDEXLib::PostUserEvent()
+void KDEXLib::TriggerUserEventProcessing()
 {
     if( !m_isGlibEventLoopType )
-        return SalXLib::PostUserEvent();
+        return SalXLib::TriggerUserEventProcessing();
     QApplication::postEvent(this, new QEvent(QEvent::Type( m_postUserEventId 
)));
 }
 
diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx
index 2fe497d019fa..4c06104b4c59 100644
--- a/vcl/unx/kde4/KDEXLib.hxx
+++ b/vcl/unx/kde4/KDEXLib.hxx
@@ -83,7 +83,7 @@ class KDEXLib : public QObject, public SalXLib
         virtual void StartTimer( sal_uLong nMS ) override;
         virtual void StopTimer() override;
         virtual void Wakeup() override;
-        virtual void PostUserEvent() override;
+        void TriggerUserEventProcessing();
 
         void doStartup();
         bool allowKdeDialogs() { return m_allowKdeDialogs; }
commit f073e6a326abac83b493fbf405a1be14685cd266
Author: Jan-Marek Glogowski <glo...@fbihome.de>
Date:   Tue Aug 29 09:40:01 2017 +0200

    Don't wait-yield non-main threads in the main thread
    
    This prevents blocking the main thread by a yielding non-main thread.
    The current solution is to wait on a condition, which is set by the
    main thread on wakeup.
    
    Change-Id: I8d680bb51a36ce1e0d3d4713d47d8e2ef93d7297

diff --git a/vcl/README.scheduler b/vcl/README.scheduler
index 9f3d8b203829..1b769f349cc9 100644
--- a/vcl/README.scheduler
+++ b/vcl/README.scheduler
@@ -122,6 +122,14 @@ basically the same we're doing with the LO scheduler as a 
system event.
 The gen X11 backend has some levels of redirection, but needs quite some work
 to get this fixed.
 
+== General: non-main thread yield ==
+
+Yielding from a non-main thread must not wait in the main thread, as this
+may block the main thread until some events happen.
+
+Currently we wait on an extra conditional, which is cleared by the main event
+loop.
+
 == MacOS implementation details ==
 
 Generally the Scheduler is handled as expected, except on resize, which is
diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index 65db0d0b0f2a..0e30dfafb693 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -72,6 +72,8 @@ class AquaSalInstance : public SalInstance
         {}
     };
 
+    bool RunInMainYield( bool bHandleAllCurrentEvents );
+
 public:
     SalYieldMutex*                          mpSalYieldMutex;        // 
Sal-Yield-Mutex
     OUString                                maDefaultPrinter;
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index e3e101cbc13e..f55e9b4aa297 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -525,6 +525,13 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* 
pEvent )
     };
 }
 
+bool AquaSalInstance::RunInMainYield( bool bHandleAllCurrentEvents )
+{
+    OSX_SALDATA_RUNINMAIN_UNION( DoYield( false, bHandleAllCurrentEvents), 
boolean )
+    assert( false && "Don't call this from the main thread!" );
+    return false;
+
+}
 static bool isWakeupEvent( NSEvent *pEvent )
 {
 SAL_WNODEPRECATED_DECLARATIONS_PUSH
@@ -645,13 +652,17 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
         if ( bHadEvent )
             maWaitingYieldCond.set();
     }
-    else if( bWait )
+    else
     {
-        // #i103162#
-        // wait until the main thread has dispatched an event
-        maWaitingYieldCond.reset();
-        SolarMutexReleaser aReleaser;
-        maWaitingYieldCond.wait();
+        bHadEvent = RunInMainYield( bHandleAllCurrentEvents );
+        if ( !bHadEvent && bWait )
+        {
+            // #i103162#
+            // wait until the main thread has dispatched an event
+            maWaitingYieldCond.reset();
+            SolarMutexReleaser aReleaser;
+            maWaitingYieldCond.wait();
+        }
     }
 
     // we get some apple events way too early
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index 23e48532d3b9..b77e84eac739 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -572,31 +572,16 @@ bool WinSalInstance::DoYield(bool bWait, bool 
bHandleAllCurrentEvents)
     SolarMutexReleaser aReleaser;
     if ( !IsMainThread() )
     {
-        if ( bWait )
+        // If you change the SendMessageW function, you might need to update
+        // the PeekMessage( ... PM_QS_POSTMESSAGE) calls!
+        bDidWork = SendMessageW( mhComWnd, SAL_MSG_THREADYIELD,
+                                 (WPARAM) false, (LPARAM) 
bHandleAllCurrentEvents );
+        if ( !bDidWork && bWait )
         {
             maWaitingYieldCond.reset();
             maWaitingYieldCond.wait();
             bDidWork = true;
         }
-        else {
-            // #97739# A SendMessage call blocks until the called thread 
(here: the main thread)
-            // returns. During a yield however, messages are processed in the 
main thread that might
-            // result in a new message loop due to opening a dialog. Thus, 
SendMessage would not
-            // return which will block this thread!
-            // Solution: just give up the time slice and hope that messages 
are processed
-            // by the main thread anyway (where all windows are created)
-            // If the mainthread is not currently handling messages, then our 
SendMessage would
-            // also do nothing, so this seems to be reasonable.
-
-            // #i18883# only sleep if potential deadlock scenario, ie, when a 
dialog is open
-            if( ImplGetSVData()->maAppData.mnModalMode )
-                Sleep(1);
-            else
-                // If you change the SendMessageW function, you might need to 
update
-                // the PeekMessage( ... PM_QS_POSTMESSAGE) calls!
-                bDidWork = SendMessageW( mhComWnd, SAL_MSG_THREADYIELD,
-                                         (WPARAM)bWait, 
(LPARAM)bHandleAllCurrentEvents );
-        }
     }
     else
     {
@@ -616,7 +601,8 @@ LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM 
wParam, LPARAM lParam, i
     switch ( nMsg )
     {
         case SAL_MSG_THREADYIELD:
-            nRet = static_cast<LRESULT>(ImplSalYield( (bool)wParam, 
(bool)lParam ));
+            assert( !(bool)wParam );
+            nRet = static_cast<LRESULT>(ImplSalYield( false, (bool)lParam ));
             rDef = FALSE;
             break;
         case SAL_MSG_STARTTIMER:
commit 5b414b2211e4bdb7dfa4f0789074ad0ed756ace8
Author: Jan-Marek Glogowski <glo...@fbihome.de>
Date:   Fri Aug 25 14:52:38 2017 +0200

    Disable ScHeaderFooterTextCursor scenario test
    
    Just like the ScHeaderFooterTextObj, it depends on weak referenced
    objects, which might be gone / cleaned up at test time.
    
    Change-Id: I52503646c51b0915df11f5c7f90c16208e45879a

diff --git a/sc/qa/unoapi/sc_4.sce b/sc/qa/unoapi/sc_4.sce
index d631ac99878b..ce879cc83272 100644
--- a/sc/qa/unoapi/sc_4.sce
+++ b/sc/qa/unoapi/sc_4.sce
@@ -36,6 +36,8 @@
 # The css::text::XTextRange test fails often when the weak SHF_ContentObj is
 # already gone. If just this test is disabled, later tests of this object fail
 # too, so this disables the whole interface.
+# Same for ScHeaderFooterTextCursor.
+# -o sc.ScHeaderFooterTextCursor
 # -o sc.ScHeaderFooterTextObj
 -o sc.ScIndexEnumeration_CellAnnotationsEnumeration
 -o sc.ScIndexEnumeration_CellAreaLinksEnumeration
commit c10b3f85a3e600aefe88565356f98c9e78abd1ce
Author: Caolán McNamara <caol...@redhat.com>
Date:   Tue Sep 26 09:59:48 2017 +0100

    AddressSanitizer: undefined-behavior
    
    Change-Id: I55a92512ad9e1508c49ee3149394196f5be5f162
    Reviewed-on: https://gerrit.libreoffice.org/42784
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    Tested-by: Caolán McNamara <caol...@redhat.com>

diff --git a/sd/qa/unit/data/ppt/pass/large-bounding-box.ppt 
b/sot/qa/cppunit/data/fail/oversized-fat-1.compound
similarity index 100%
rename from sd/qa/unit/data/ppt/pass/large-bounding-box.ppt
rename to sot/qa/cppunit/data/fail/oversized-fat-1.compound
diff --git a/sot/source/sdstor/stgio.cxx b/sot/source/sdstor/stgio.cxx
index 4376210055bd..15774bf64a2b 100644
--- a/sot/source/sdstor/stgio.cxx
+++ b/sot/source/sdstor/stgio.cxx
@@ -24,6 +24,7 @@
 #include "stgstrms.hxx"
 #include "stgdir.hxx"
 #include "stgio.hxx"
+#include <o3tl/safeint.hxx>
 #include <rtl/instance.hxx>
 
 #include <memory>
@@ -88,9 +89,21 @@ void StgIo::SetupStreams()
     m_pDataStrm = nullptr;
     m_pFAT      = nullptr;
     ResetError();
-    SetPhysPageSize( 1 << m_aHdr.GetPageSize() );
-    m_pFAT = new StgFATStrm( *this );
-    m_pTOC = new StgDirStrm( *this );
+    short nPhysPageSize = 1 << m_aHdr.GetPageSize();
+    SetPhysPageSize(nPhysPageSize);
+    sal_Int32 nFatStrmSize;
+    if (o3tl::checked_multiply<sal_Int32>(m_aHdr.GetFATSize(), nPhysPageSize, 
nFatStrmSize))
+    {
+        SAL_WARN("sot", "Error: " << m_aHdr.GetFATSize() << " * " << 
nPhysPageSize << " would overflow");
+        SetError(SVSTREAM_FILEFORMAT_ERROR);
+        m_pFAT = nullptr;
+        m_pTOC = nullptr;
+    }
+    else
+    {
+        m_pFAT = new StgFATStrm(*this, nFatStrmSize);
+        m_pTOC = new StgDirStrm( *this );
+    }
     if( !GetError() )
     {
         StgDirEntry* pRoot = m_pTOC->GetRoot();
diff --git a/sot/source/sdstor/stgstrms.cxx b/sot/source/sdstor/stgstrms.cxx
index f449874b3b10..1f7f0769f0ce 100644
--- a/sot/source/sdstor/stgstrms.cxx
+++ b/sot/source/sdstor/stgstrms.cxx
@@ -572,10 +572,10 @@ bool StgStrm::SetSize( sal_Int32 nBytes )
 // Since this access is implemented as a StgStrm, we can use the
 // FAT allocator.
 
-StgFATStrm::StgFATStrm( StgIo& r ) : StgStrm( r )
+StgFATStrm::StgFATStrm(StgIo& r, sal_Int32 nFatStrmSize) : StgStrm( r )
 {
     m_pFat.reset( new StgFAT( *this, true ) );
-    m_nSize = m_rIo.m_aHdr.GetFATSize() * m_nPageSize;
+    m_nSize = nFatStrmSize;
 }
 
 bool StgFATStrm::Pos2Page( sal_Int32 nBytePos )
diff --git a/sot/source/sdstor/stgstrms.hxx b/sot/source/sdstor/stgstrms.hxx
index bdd3e8755813..c8432e212e49 100644
--- a/sot/source/sdstor/stgstrms.hxx
+++ b/sot/source/sdstor/stgstrms.hxx
@@ -101,7 +101,7 @@ class StgFATStrm : public StgStrm {     // the master FAT 
stream
     virtual bool Pos2Page( sal_Int32 nBytePos ) override;
     bool  SetPage( short, sal_Int32 );
 public:
-    explicit StgFATStrm( StgIo& );
+    explicit StgFATStrm(StgIo&, sal_Int32 nFatStrmSize);
     using StgStrm::GetPage;
     sal_Int32 GetPage( short, bool, sal_uInt16 *pnMasterAlloc = nullptr);
     virtual bool SetSize( sal_Int32 ) override;
commit 865f8a9055c55ee30a404ddc1e30f67ce482f05b
Author: Muhammet Kara <muhammet.k...@pardus.org.tr>
Date:   Tue Sep 26 08:21:29 2017 +0000

    Cleanup unused strings in cui
    
    Change-Id: I7ab055f301785a73d189e58465056ac4b2e8b494
    Reviewed-on: https://gerrit.libreoffice.org/42783
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Katarina Behrens <katarina.behr...@cib.de>

diff --git a/cui/inc/strings.hrc b/cui/inc/strings.hrc
index 266f93bdd5de..40270de92037 100644
--- a/cui/inc/strings.hrc
+++ b/cui/inc/strings.hrc
@@ -51,16 +51,10 @@
 #define RID_SVXSTR_MOVE_MENU                        
NC_("RID_SVXSTR_MOVE_MENU", "Move Menu")
 #define RID_SVXSTR_ADD_SUBMENU                      
NC_("RID_SVXSTR_ADD_SUBMENU", "Add Submenu")
 #define RID_SVXSTR_SUBMENU_NAME                     
NC_("RID_SVXSTR_SUBMENU_NAME", "Submenu name")
-#define RID_SVXSTR_MENU_ADDCOMMANDS_DESCRIPTION     
NC_("RID_SVXSTR_MENU_ADDCOMMANDS_DESCRIPTION", "To add a command to a menu, 
select the category and then the command. You can also drag the command to the 
Commands list of the Menus tab page in the Customize dialog.")
 #define RID_SVXSTR_DELETE_ICON_CONFIRM              
NC_("RID_SVXSTR_DELETE_ICON_CONFIRM", "Are you sure to delete the image?")
 #define RID_SVXSTR_REPLACE_ICON_WARNING             
NC_("RID_SVXSTR_REPLACE_ICON_WARNING", "The icon %ICONNAME is already contained 
in the image list.\nWould you like to replace the existing icon?")
 #define RID_SVXSTR_REPLACE_ICON_CONFIRM             
NC_("RID_SVXSTR_REPLACE_ICON_CONFIRM", "Confirm Icon Replacement")
 #define RID_SVXSTR_YESTOALL                         NC_("RID_SVXSTR_YESTOALL", 
"Yes to All")
-#define RID_SVXSTR_PRODUCTNAME_TOOLBARS             
NC_("RID_SVXSTR_PRODUCTNAME_TOOLBARS", "%PRODUCTNAME %MODULENAME Toolbars")
-#define RID_SVXSTR_PRODUCTNAME_CONTEXTMENUS         
NC_("RID_SVXSTR_PRODUCTNAME_CONTEXTMENUS", "%PRODUCTNAME %MODULENAME Context 
Menus")
-#define RID_SVXSTR_TOOLBAR                          NC_("RID_SVXSTR_TOOLBAR", 
"Toolbar")
-//#define RID_SVXSTR_TOOLBAR_CONTENT                  
NC_("RID_SVXSTR_TOOLBAR_CONTENT", "Toolbar Content")
-#define RID_SVXSTR_COMMANDS                         NC_("RID_SVXSTR_COMMANDS", 
"Commands")
 #define RID_SXVSTR_CONFIRM_DELETE_TOOLBAR           
NC_("RID_SXVSTR_CONFIRM_DELETE_TOOLBAR", "There are no more commands on the 
toolbar. Do you want to delete the toolbar?")
 /* Translators: Do not translate %SAVE IN SELECTION% It is a placeholder
    and will be replaced at runtime by the name of the selected application
commit 8e7897588d7185ef1964e8120669c1de3d1ce734
Author: Tor Lillqvist <t...@collabora.com>
Date:   Fri Sep 22 14:12:07 2017 +0300

    Rename the basegfx::tools namespace to basegfx::utils
    
    Reduce potential confusion with the global tools namespace. Will
    hopefully make it possible to remove the annoying initial :: when
    referring to the global tools namespace. Unless we have even more
    tools subnamespaces somewhere.
    
    Thorsten said it was OK.
    
    Change-Id: Id088dfe8f4244cb79df9aa988995b31a1758c996
    Reviewed-on: https://gerrit.libreoffice.org/42644
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Tor Lillqvist <t...@collabora.com>

diff --git a/basegfx/source/color/bcolortools.cxx 
b/basegfx/source/color/bcolortools.cxx
index b28607bf298d..7b5bf9cae140 100644
--- a/basegfx/source/color/bcolortools.cxx
+++ b/basegfx/source/color/bcolortools.cxx
@@ -21,7 +21,7 @@
 #include <basegfx/color/bcolor.hxx>
 #include <basegfx/color/bcolortools.hxx>
 
-namespace basegfx { namespace tools
+namespace basegfx { namespace utils
 {
     BColor rgb2hsl(const BColor& rRGBColor)
     {
diff --git a/basegfx/source/matrix/b2dhommatrix.cxx 
b/basegfx/source/matrix/b2dhommatrix.cxx
index f9bc24e81ea4..9f7d5bff0156 100644
--- a/basegfx/source/matrix/b2dhommatrix.cxx
+++ b/basegfx/source/matrix/b2dhommatrix.cxx
@@ -188,7 +188,7 @@ namespace basegfx
             double fSin(0.0);
             double fCos(1.0);
 
-            tools::createSinCosOrthogonal(fSin, fCos, fRadiant);
+            utils::createSinCosOrthogonal(fSin, fCos, fRadiant);
             Impl2DHomMatrix aRotMat;
 
             aRotMat.set(0, 0, fCos);
diff --git a/basegfx/source/matrix/b2dhommatrixtools.cxx 
b/basegfx/source/matrix/b2dhommatrixtools.cxx
index 89ab91424706..a267b05b96d1 100644
--- a/basegfx/source/matrix/b2dhommatrixtools.cxx
+++ b/basegfx/source/matrix/b2dhommatrixtools.cxx
@@ -25,7 +25,7 @@
 
 namespace basegfx
 {
-    namespace tools
+    namespace utils
     {
         void createSinCosOrthogonal(double& o_rSin, double& o_rCos, double 
fRadiant)
         {
@@ -412,7 +412,7 @@ namespace basegfx
         {
             return B2DTuple(rMatrix.get(0, nCol), rMatrix.get(1, nCol));
         }
-    } // end of namespace tools
+    } // end of namespace utils
 } // end of namespace basegfx
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/source/polygon/b2dlinegeometry.cxx 
b/basegfx/source/polygon/b2dlinegeometry.cxx
index 8ae52d508fd2..042cb480437b 100644
--- a/basegfx/source/polygon/b2dlinegeometry.cxx
+++ b/basegfx/source/polygon/b2dlinegeometry.cxx
@@ -33,7 +33,7 @@
 
 namespace basegfx
 {
-    namespace tools
+    namespace utils
     {
         B2DPolyPolygon createAreaGeometryForLineStartEnd(
             const B2DPolygon& rCandidate,
@@ -47,7 +47,7 @@ namespace basegfx
         {
             B2DPolyPolygon aRetval;
             OSL_ENSURE(rCandidate.count() > 1, 
"createAreaGeometryForLineStartEnd: Line polygon has too less points (!)");
-            OSL_ENSURE(rArrow.count() > 0, "createAreaGeometryForLineStartEnd: 
Empty arrow tools::PolyPolygon (!)");
+            OSL_ENSURE(rArrow.count() > 0, "createAreaGeometryForLineStartEnd: 
Empty arrow utils::PolyPolygon (!)");
             OSL_ENSURE(fWidth > 0.0, "createAreaGeometryForLineStartEnd: Width 
too small (!)");
             OSL_ENSURE(fDockingPosition >= 0.0 && fDockingPosition <= 1.0,
                 "createAreaGeometryForLineStartEnd: fDockingPosition out of 
range [0.0 .. 1.0] (!)");
@@ -75,7 +75,7 @@ namespace basegfx
                 const B2DRange aArrowSize(getRange(rArrow));
 
                 // build ArrowTransform; center in X, align with axis in Y
-                B2DHomMatrix 
aArrowTransform(basegfx::tools::createTranslateB2DHomMatrix(
+                B2DHomMatrix 
aArrowTransform(basegfx::utils::createTranslateB2DHomMatrix(
                     -aArrowSize.getCenter().getX(), 
-aArrowSize.getMinimum().getY()));
 
                 // scale to target size
@@ -125,7 +125,7 @@ namespace basegfx
 
             return aRetval;
         }
-    } // end of namespace tools
+    } // end of namespace utils
 } // end of namespace basegfx
 
 namespace basegfx
@@ -359,7 +359,7 @@ namespace basegfx
                 const B2DVector aPerpendStartA(aNormalizedPerpendicularA * 
-fHalfLineWidth);
                 const B2DVector aPerpendEndA(aNormalizedPerpendicularB * 
-fHalfLineWidth);
                 double fCutA(0.0);
-                const CutFlagValue aCutA(tools::findCut(
+                const CutFlagValue aCutA(utils::findCut(
                     rEdge.getStartPoint(), aPerpendStartA,
                     rEdge.getEndPoint(), aPerpendEndA,
                     CutFlagValue::ALL, &fCutA));
@@ -369,7 +369,7 @@ namespace basegfx
                 const B2DVector aPerpendStartB(aNormalizedPerpendicularA * 
fHalfLineWidth);
                 const B2DVector aPerpendEndB(aNormalizedPerpendicularB * 
fHalfLineWidth);
                 double fCutB(0.0);
-                const CutFlagValue aCutB(tools::findCut(
+                const CutFlagValue aCutB(utils::findCut(
                     rEdge.getEndPoint(), aPerpendEndB,
                     rEdge.getStartPoint(), aPerpendStartB,
                     CutFlagValue::ALL, &fCutB));
@@ -384,10 +384,10 @@ namespace basegfx
                 {
                     if(bStartRound)
                     {
-                        basegfx::B2DPolygon 
aStartPolygon(tools::createHalfUnitCircle());
+                        basegfx::B2DPolygon 
aStartPolygon(utils::createHalfUnitCircle());
 
                         aStartPolygon.transform(
-                            
tools::createScaleShearXRotateTranslateB2DHomMatrix(
+                            
utils::createScaleShearXRotateTranslateB2DHomMatrix(
                                 fHalfLineWidth, fHalfLineWidth,
                                 0.0,
                                 atan2(aTangentA.getY(), aTangentA.getX()) + 
F_PI2,
@@ -447,10 +447,10 @@ namespace basegfx
                 {
                     if(bEndRound)
                     {
-                        basegfx::B2DPolygon 
aEndPolygon(tools::createHalfUnitCircle());
+                        basegfx::B2DPolygon 
aEndPolygon(utils::createHalfUnitCircle());
 
                         aEndPolygon.transform(
-                            
tools::createScaleShearXRotateTranslateB2DHomMatrix(
+                            
utils::createScaleShearXRotateTranslateB2DHomMatrix(
                                 fHalfLineWidth, fHalfLineWidth,
                                 0.0,
                                 atan2(aTangentB.getY(), aTangentB.getX()) - 
F_PI2,
@@ -522,7 +522,7 @@ namespace basegfx
                     // Remark: This nearly never happens due to curve 
preparations to extreme points
                     // and maximum angle turning, but I constructed a test 
case and checked that it is
                     // working properly.
-                    const B2DPolyPolygon 
aTemp(tools::solveCrossovers(aBezierPolygon));
+                    const B2DPolyPolygon 
aTemp(utils::solveCrossovers(aBezierPolygon));
                     const sal_uInt32 nTempCount(aTemp.count());
 
                     if(nTempCount)
@@ -589,11 +589,11 @@ namespace basegfx
                 // create left vertical
                 if(bStartRound)
                 {
-                    aEdgePolygon = tools::createHalfUnitCircle();
+                    aEdgePolygon = utils::createHalfUnitCircle();
                     fAngle = atan2(aTangent.getY(), aTangent.getX());
                     bAngle = true;
                     aEdgePolygon.transform(
-                        tools::createScaleShearXRotateTranslateB2DHomMatrix(
+                        utils::createScaleShearXRotateTranslateB2DHomMatrix(
                             fHalfLineWidth, fHalfLineWidth,
                             0.0,
                             fAngle + F_PI2,
@@ -623,7 +623,7 @@ namespace basegfx
                 // create right vertical
                 if(bEndRound)
                 {
-                    basegfx::B2DPolygon 
aEndPolygon(tools::createHalfUnitCircle());
+                    basegfx::B2DPolygon 
aEndPolygon(utils::createHalfUnitCircle());
 
                     if(!bAngle)
                     {
@@ -631,7 +631,7 @@ namespace basegfx
                     }
 
                     aEndPolygon.transform(
-                        tools::createScaleShearXRotateTranslateB2DHomMatrix(
+                        utils::createScaleShearXRotateTranslateB2DHomMatrix(
                             fHalfLineWidth, fHalfLineWidth,
                             0.0,
                             fAngle - F_PI2,
@@ -713,7 +713,7 @@ namespace basegfx
                     // is not needed since the same fCut will be found on the 
first edge.
                     // If it exists, insert it to complete the mitered fill 
polygon.
                     double fCutPos(0.0);
-                    tools::findCut(aStartPoint, rTangentPrev, aEndPoint, 
rTangentEdge, CutFlagValue::ALL, &fCutPos);
+                    utils::findCut(aStartPoint, rTangentPrev, aEndPoint, 
rTangentEdge, CutFlagValue::ALL, &fCutPos);
 
                     if(fCutPos != 0.0)
                     {
@@ -740,7 +740,7 @@ namespace basegfx
                         fAngleEnd += F_2PI;
                     }
 
-                    const B2DPolygon 
aBow(tools::createPolygonFromEllipseSegment(rPoint, fHalfLineWidth, 
fHalfLineWidth, fAngleStart, fAngleEnd));
+                    const B2DPolygon 
aBow(utils::createPolygonFromEllipseSegment(rPoint, fHalfLineWidth, 
fHalfLineWidth, fAngleStart, fAngleEnd));
 
                     if(aBow.count() > 1)
                     {
@@ -777,7 +777,7 @@ namespace basegfx
         }
     } // end of anonymus namespace
 
-    namespace tools
+    namespace utils
     {
         B2DPolyPolygon createAreaGeometry(
             const B2DPolygon& rCandidate,
@@ -971,7 +971,7 @@ namespace basegfx
                 return B2DPolyPolygon(rCandidate);
             }
         }
-    } // end of namespace tools
+    } // end of namespace utils
 } // end of namespace basegfx
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/source/polygon/b2dpolygon.cxx 
b/basegfx/source/polygon/b2dpolygon.cxx
index aa528ad861ac..17df4c4b3738 100644
--- a/basegfx/source/polygon/b2dpolygon.cxx
+++ b/basegfx/source/polygon/b2dpolygon.cxx
@@ -477,7 +477,7 @@ public:
     {
         if(!mpDefaultSubdivision)
         {
-            const_cast< ImplBufferedData* 
>(this)->mpDefaultSubdivision.reset(new 
basegfx::B2DPolygon(basegfx::tools::adaptiveSubdivideByAngle(rSource)));
+            const_cast< ImplBufferedData* 
>(this)->mpDefaultSubdivision.reset(new 
basegfx::B2DPolygon(basegfx::utils::adaptiveSubdivideByAngle(rSource)));
         }
 
         return *mpDefaultSubdivision;
diff --git a/basegfx/source/polygon/b2dpolygonclipper.cxx 
b/basegfx/source/polygon/b2dpolygonclipper.cxx
index 63d3ac8c2210..5057fc52d977 100644
--- a/basegfx/source/polygon/b2dpolygonclipper.cxx
+++ b/basegfx/source/polygon/b2dpolygonclipper.cxx
@@ -25,12 +25,12 @@
 #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
 #include <basegfx/polygon/b2dpolypolygontools.hxx>
 #include <basegfx/curve/b2dcubicbezier.hxx>
-#include <basegfx/tools/rectcliptools.hxx>
+#include <basegfx/utils/rectcliptools.hxx>
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 
 namespace basegfx
 {
-    namespace tools
+    namespace utils
     {
         B2DPolyPolygon clipPolygonOnParallelAxis(const B2DPolygon& rCandidate, 
bool bParallelToXAxis, bool bAboveAxis, double fValueOnOtherAxis, bool bStroke)
         {
@@ -360,7 +360,7 @@ namespace basegfx
                         {
                             aCandidate.getBezierSegment(b, aEdge);
                             const B2DPoint 
aTestPoint(aEdge.interpolatePoint(0.5));
-                            const bool bIsInside(tools::isInside(rClip, 
aTestPoint) == bInside);
+                            const bool bIsInside(utils::isInside(rClip, 
aTestPoint) == bInside);
 
                             if(bIsInside)
                             {
@@ -413,10 +413,10 @@ namespace basegfx
                     // check for simplification with ranges if !bStroke 
(handling as stroke is more simple),
                     // but also only when bInside, else the simplification may 
lead to recursive calls (see

... etc. - the rest is truncated
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to