include/vcl/scheduler.hxx    |    7 +
 sc/qa/unoapi/sc_4.sce        |    7 +
 sfx2/source/appl/appinit.cxx |    5 
 vcl/inc/schedulerimpl.hxx    |   35 ++++++
 vcl/inc/svdata.hxx           |  232 ++++++++++++++++++++++---------------------
 vcl/source/app/scheduler.cxx |   93 ++++++++++++++---
 vcl/source/app/svapp.cxx     |   38 ++++---
 vcl/source/app/svdata.cxx    |   10 -
 8 files changed, 267 insertions(+), 160 deletions(-)

New commits:
commit 31c450e6a07ae74f654cff71f68c12dd6b0513e4
Author: Stephan Bergmann <sberg...@redhat.com>
Date:   Sat Oct 8 23:45:40 2016 +0200

    loplugin:badstatics
    
    ...so make aPostedEventList a member of the global ImpSVAppData singleton
    
    Reviewed-on: https://gerrit.libreoffice.org/29612
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>
    
     Conflicts:
            vcl/inc/svdata.hxx
    
    Change-Id: Ie7ac49b56107eb393514d9ba1d91ee66296f60a0

diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx
index c4daa04d5555..4b1c1d7b3fa1 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -32,10 +32,12 @@
 #include "impfontcache.hxx"
 #include "xconnection.hxx"
 
+#include <list>
 #include <unordered_map>
 #include <boost/functional/hash.hpp>
 #include "schedulerimpl.hxx"
 
+struct ImplPostEventData;
 struct ImplTimerData;
 struct ImplIdleData;
 struct ImplConfigData;
@@ -110,6 +112,8 @@ public:
 
 typedef std::vector<Link<VclWindowEvent&,bool> > SVAppKeyListeners;
 
+typedef std::pair<VclPtr<vcl::Window>, ImplPostEventData *> ImplPostEventPair;
+
 struct ImplSVAppData
 {
     enum ImeStatusWindowMode
@@ -119,42 +123,43 @@ struct ImplSVAppData
         ImeStatusWindowMode_SHOW
     };
 
-    AllSettings*            mpSettings;                     // Application 
settings
-    LocaleConfigurationListener* mpCfgListener;
-    VclEventListeners*      mpEventListeners;               // listeners for 
vcl events (eg, extended toolkit)
-    SVAppKeyListeners*      mpKeyListeners;                 // listeners for 
key events only (eg, extended toolkit)
-    ImplAccelManager*       mpAccelMgr;                     // Accelerator 
Manager
-    OUString*               mpAppName;                      // Application name
-    OUString*               mpAppFileName;                  // Abs. 
Application FileName
-    OUString*               mpDisplayName;                  // Application 
Display Name
-    OUString*               mpToolkitName;                  // Toolkit Name
-    Help*                   mpHelp;                         // Application help
+    AllSettings*            mpSettings = nullptr;           // Application 
settings
+    LocaleConfigurationListener* mpCfgListener = nullptr;
+    VclEventListeners*      mpEventListeners = nullptr;     // listeners for 
vcl events (eg, extended toolkit)
+    SVAppKeyListeners*      mpKeyListeners = nullptr;       // listeners for 
key events only (eg, extended toolkit)
+    std::list<ImplPostEventPair> maPostedEventList;
+    ImplAccelManager*       mpAccelMgr = nullptr;           // Accelerator 
Manager
+    OUString*               mpAppName = nullptr;            // Application name
+    OUString*               mpAppFileName = nullptr;        // Abs. 
Application FileName
+    OUString*               mpDisplayName = nullptr;        // Application 
Display Name
+    OUString*               mpToolkitName = nullptr;        // Toolkit Name
+    Help*                   mpHelp = nullptr;               // Application help
     PopupMenu*              mpActivePopupMenu;              // Actives 
Popup-Menu (in Execute)
     ImplIdleMgr*            mpIdleMgr;                      // Idle-Manager
     VclPtr<ImplWheelWindow> mpWheelWindow;                  // WheelWindow
-    ImplHotKey*             mpFirstHotKey;                  // 
HotKey-Verwaltung
-    ImplEventHook*          mpFirstEventHook;               // Event-Hooks
-    sal_uInt64              mnLastInputTime;                // 
GetLastInputTime()
-    sal_uInt16              mnDispatchLevel;                // DispatchLevel
-    sal_uInt16              mnModalMode;                    // ModalMode Count
-    SystemWindowFlags       mnSysWinMode;                   // Mode, when 
SystemWindows should be created
+    ImplHotKey*             mpFirstHotKey = nullptr;        // 
HotKey-Verwaltung
+    ImplEventHook*          mpFirstEventHook = nullptr;     // Event-Hooks
+    sal_uInt64              mnLastInputTime = 0;            // 
GetLastInputTime()
+    sal_uInt16              mnDispatchLevel = 0;            // DispatchLevel
+    sal_uInt16              mnModalMode = 0;                // ModalMode Count
+    SystemWindowFlags       mnSysWinMode = SystemWindowFlags(0); // Mode, when 
SystemWindows should be created
     short                   mnDialogScaleX;                 // Scale 
X-Positions and sizes in Dialogs
-    bool                    mbInAppMain;                    // is 
Application::Main() on stack
-    bool                    mbInAppExecute;                 // is 
Application::Execute() on stack
-    bool                    mbAppQuit;                      // is 
Application::Quit() called
-    bool                    mbSettingsInit;                 // true: Settings 
are initialized
-    Application::DialogCancelMode meDialogCancel;           // true: All 
Dialog::Execute() calls will be terminated immediately with return false
+    bool                    mbInAppMain = false;            // is 
Application::Main() on stack
+    bool                    mbInAppExecute = false;         // is 
Application::Execute() on stack
+    bool                    mbAppQuit = false;              // is 
Application::Quit() called
+    bool                    mbSettingsInit = false;         // true: Settings 
are initialized
+    Application::DialogCancelMode meDialogCancel; // true: All 
Dialog::Execute() calls will be terminated immediately with return false
 
     /** Controls whether showing any IME status window is toggled on or off.
 
         Only meaningful if showing IME status windows can be toggled on and off
         externally (see Application::CanToggleImeStatusWindow).
      */
-    ImeStatusWindowMode meShowImeStatusWindow;
+    ImeStatusWindowMode meShowImeStatusWindow = ImeStatusWindowMode_UNKNOWN;
 
-    SvFileStream*       mpEventTestInput;
-    Idle*               mpEventTestingIdle;
-    int                 mnEventTestLimit;
+    SvFileStream*       mpEventTestInput = nullptr;
+    Idle*               mpEventTestingIdle = nullptr;
+    int                 mnEventTestLimit = 0;
 
     DECL_STATIC_LINK_TYPED(ImplSVAppData, ImplQuitMsg, void*, void);
     DECL_STATIC_LINK_TYPED(ImplSVAppData, ImplPrepareExitMsg, void*, void);
@@ -176,20 +181,20 @@ struct ImplSVGDIData
     VclPtr<OutputDevice>    mpLastPrnGraphics;              // Last 
OutputDevice with a InfoPrinter Graphics
     VclPtr<VirtualDevice>   mpFirstVirDev;                  // First 
VirtualDevice
     VclPtr<VirtualDevice>   mpLastVirDev;                   // Last 
VirtualDevice
-    OpenGLContext*          mpFirstContext;                 // First 
OpenGLContext
-    OpenGLContext*          mpLastContext;                  // Last 
OpenGLContext
+    OpenGLContext*          mpFirstContext = nullptr;       // First 
OpenGLContext
+    OpenGLContext*          mpLastContext = nullptr;        // Last 
OpenGLContext
     VclPtr<Printer>         mpFirstPrinter;                 // First Printer
     VclPtr<Printer>         mpLastPrinter;                  // Last Printer
-    ImplPrnQueueList*       mpPrinterQueueList;             // List of all 
printer queue
-    PhysicalFontCollection* mpScreenFontList;               // Screen-Font-List
-    ImplFontCache*          mpScreenFontCache;              // 
Screen-Font-Cache
-    ImplDirectFontSubstitution* mpDirectFontSubst;          // 
Font-Substitutons defined in Tools->Options->Fonts
-    GraphicConverter*       mpGrfConverter;                 // Converter for 
graphics
+    ImplPrnQueueList*       mpPrinterQueueList = nullptr;   // List of all 
printer queue
+    PhysicalFontCollection* mpScreenFontList = nullptr;     // Screen-Font-List
+    ImplFontCache*          mpScreenFontCache = nullptr;    // 
Screen-Font-Cache
+    ImplDirectFontSubstitution* mpDirectFontSubst = nullptr; // 
Font-Substitutons defined in Tools->Options->Fonts
+    GraphicConverter*       mpGrfConverter = nullptr;       // Converter for 
graphics
     long                    mnRealAppFontX;                 // AppFont 
X-Numenator for 40/tel Width
-    long                    mnAppFontX;                     // AppFont 
X-Numenator for 40/tel Width + DialogScaleX
-    long                    mnAppFontY;                     // AppFont 
Y-Numenator for 80/tel Height
-    bool                    mbFontSubChanged;               // true: 
FontSubstitution was changed between Begin/End
-    bool                    mbNativeFontConfig;             // true: do not 
override UI font
+    long                    mnAppFontX = 0;                 // AppFont 
X-Numenator for 40/tel Width
+    long                    mnAppFontY = 0;                 // AppFont 
Y-Numenator for 80/tel Height
+    bool                    mbFontSubChanged = false;       // true: 
FontSubstitution was changed between Begin/End
+    bool                    mbNativeFontConfig = false;     // true: do not 
override UI font
 };
 
 struct ImplSVWinData
@@ -204,56 +209,58 @@ struct ImplSVWinData
     VclPtr<Dialog>          mpLastExecuteDlg;               // First Dialog 
that is in Execute
     VclPtr<vcl::Window>     mpExtTextInputWin;              // Window, which 
is in ExtTextInput
     VclPtr<vcl::Window>     mpTrackWin;                     // window, that is 
in tracking mode
-    AutoTimer*              mpTrackTimer;                   // tracking timer
-    ImageList*              mpMsgBoxImgList;                // ImageList for 
MessageBox
+    AutoTimer*              mpTrackTimer = nullptr;         // tracking timer
+    ImageList*              mpMsgBoxImgList = nullptr;      // ImageList for 
MessageBox
     VclPtr<vcl::Window>     mpAutoScrollWin;                // window, that is 
in AutoScrollMode mode
     VclPtr<vcl::Window>     mpLastWheelWindow;              // window, that 
last received a mouse wheel event
-    StartTrackingFlags      mnTrackFlags;                   // tracking flags
-    StartAutoScrollFlags    mnAutoScrollFlags;              // auto scroll 
flags
-    bool                    mbNoDeactivate;                 // true: do not 
execute Deactivate
-    bool                    mbNoSaveFocus;                  // true: menus 
must not save/restore focus
+    SalWheelMouseEvent      maLastWheelEvent;               // the last 
received mouse whell event
+
+    StartTrackingFlags      mnTrackFlags = StartTrackingFlags::NONE; // 
tracking flags
+    StartAutoScrollFlags    mnAutoScrollFlags = StartAutoScrollFlags::NONE; // 
auto scroll flags
+    bool                    mbNoDeactivate = false;         // true: do not 
execute Deactivate
+    bool                    mbNoSaveFocus = false;          // true: menus 
must not save/restore focus
 };
 
 typedef std::vector< std::pair< OUString, FieldUnit > > FieldUnitStringList;
 
 struct ImplSVCtrlData
 {
-    ImageList*              mpCheckImgList;                 // ImageList for 
CheckBoxes
-    ImageList*              mpRadioImgList;                 // ImageList for 
RadioButtons
-    ImageList*              mpPinImgList;                   // ImageList for 
PIN
-    ImageList*              mpSplitHPinImgList;             // ImageList for 
Horizontale SplitWindows
-    ImageList*              mpSplitVPinImgList;             // ImageList for 
Vertikale SplitWindows (PIN's)
+    ImageList*              mpCheckImgList = nullptr;       // ImageList for 
CheckBoxes
+    ImageList*              mpRadioImgList = nullptr;       // ImageList for 
RadioButtons
+    ImageList*              mpPinImgList = nullptr;         // ImageList for 
PIN
+    ImageList*              mpSplitHPinImgList = nullptr;   // ImageList for 
Horizontale SplitWindows
+    ImageList*              mpSplitVPinImgList = nullptr;   // ImageList for 
Vertikale SplitWindows (PIN's)
     ImageList*              mpSplitHArwImgList;             // ImageList for 
Horizontale SplitWindows (Arrows)
     ImageList*              mpSplitVArwImgList;             // ImageList for 
Vertikale SplitWindows (Arrows)
-    Image*                  mpDisclosurePlus;
-    Image*                  mpDisclosureMinus;
-    ImplTBDragMgr*          mpTBDragMgr;                    // DragMgr for 
ToolBox
-    sal_uInt16              mnCheckStyle;                   // CheckBox-Style 
for ImageList-Update
-    sal_uInt16              mnRadioStyle;                   // Radio-Style for 
ImageList-Update
-    sal_uLong               mnLastCheckFColor;              // Letzte 
FaceColor fuer CheckImage
-    sal_uLong               mnLastCheckWColor;              // Letzte 
WindowColor fuer CheckImage
-    sal_uLong               mnLastCheckLColor;              // Letzte 
LightColor fuer CheckImage
-    sal_uLong               mnLastRadioFColor;              // Letzte 
FaceColor fuer RadioImage
-    sal_uLong               mnLastRadioWColor;              // Letzte 
WindowColor fuer RadioImage
-    sal_uLong               mnLastRadioLColor;              // Letzte 
LightColor fuer RadioImage
-    FieldUnitStringList*    mpFieldUnitStrings;             // list with field 
units
-    FieldUnitStringList*    mpCleanUnitStrings;             // same list but 
with some "fluff" like spaces removed
+    Image*                  mpDisclosurePlus = nullptr;
+    Image*                  mpDisclosureMinus = nullptr;
+    ImplTBDragMgr*          mpTBDragMgr = nullptr;          // DragMgr for 
ToolBox
+    sal_uInt16              mnCheckStyle = 0;               // CheckBox-Style 
for ImageList-Update
+    sal_uInt16              mnRadioStyle = 0;               // Radio-Style for 
ImageList-Update
+    sal_uLong               mnLastCheckFColor = 0;          // Letzte 
FaceColor fuer CheckImage
+    sal_uLong               mnLastCheckWColor = 0;          // Letzte 
WindowColor fuer CheckImage
+    sal_uLong               mnLastCheckLColor = 0;          // Letzte 
LightColor fuer CheckImage
+    sal_uLong               mnLastRadioFColor = 0;          // Letzte 
FaceColor fuer RadioImage
+    sal_uLong               mnLastRadioWColor = 0;          // Letzte 
WindowColor fuer RadioImage
+    sal_uLong               mnLastRadioLColor = 0;          // Letzte 
LightColor fuer RadioImage
+    FieldUnitStringList*    mpFieldUnitStrings = nullptr;   // list with field 
units
+    FieldUnitStringList*    mpCleanUnitStrings = nullptr;   // same list but 
with some "fluff" like spaces removed
 };
 
 struct ImplSVHelpData
 {
-    bool                    mbContextHelp       : 1;        // is ContextHelp 
enabled
-    bool                    mbExtHelp           : 1;        // is ExtendedHelp 
enabled
-    bool                    mbExtHelpMode       : 1;        // is in 
ExtendedHelp Mode
-    bool                    mbOldBalloonMode    : 1;        // BalloonMode, 
before ExtHelpMode started
-    bool                    mbBalloonHelp       : 1;        // is BalloonHelp 
enabled
-    bool                    mbQuickHelp         : 1;        // is QuickHelp 
enabled
-    bool                    mbSetKeyboardHelp   : 1;        // tiphelp was 
activated by keyboard
-    bool                    mbKeyboardHelp      : 1;        // tiphelp was 
activated by keyboard
-    bool                    mbAutoHelpId        : 1;        // generate HelpIds
-    bool                    mbRequestingHelp    : 1;        // In 
Window::RequestHelp
+    bool                    mbContextHelp = false;          // is ContextHelp 
enabled
+    bool                    mbExtHelp = false;              // is ExtendedHelp 
enabled
+    bool                    mbExtHelpMode = false;          // is in 
ExtendedHelp Mode
+    bool                    mbOldBalloonMode = false;       // BalloonMode, 
before ExtHelpMode started
+    bool                    mbBalloonHelp = false;          // is BalloonHelp 
enabled
+    bool                    mbQuickHelp = false;            // is QuickHelp 
enabled
+    bool                    mbSetKeyboardHelp = false;      // tiphelp was 
activated by keyboard
+    bool                    mbKeyboardHelp = false;         // tiphelp was 
activated by keyboard
+    bool                    mbAutoHelpId = true;            // generate HelpIds
+    bool                    mbRequestingHelp = false;       // In 
Window::RequestHelp
     VclPtr<HelpTextWindow>  mpHelpWin;                      // HelpWindow
-    sal_uInt64              mnLastHelpHideTime;             // ticks of last 
show
+    sal_uInt64              mnLastHelpHideTime = 0;         // ticks of last 
show
 };
 
 // "NWF" means "Native Widget Framework" and was the term used for the
@@ -263,37 +270,37 @@ struct ImplSVHelpData
 
 struct ImplSVNWFData
 {
-    int                     mnStatusBarLowerRightOffset;    // amount in pixel 
to avoid in the lower righthand corner
-    int                     mnMenuFormatBorderX;            // horizontal 
inner popup menu border
-    int                     mnMenuFormatBorderY;            // vertical inner 
popup menu border
-    int                     mnMenuSeparatorBorderX;         // gap at each 
side of separator
-    ::Color                 maMenuBarHighlightTextColor;    // override 
higlight text color
+    int                     mnStatusBarLowerRightOffset = 0; // amount in 
pixel to avoid in the lower righthand corner
+    int                     mnMenuFormatBorderX = 0;        // horizontal 
inner popup menu border
+    int                     mnMenuFormatBorderY = 0;        // vertical inner 
popup menu border
+    int                     mnMenuSeparatorBorderX = 0;     // gap at each 
side of separator
+    ::Color                 maMenuBarHighlightTextColor = Color( 
COL_TRANSPARENT ); // override higlight text color
                                                             // in menubar if 
not transparent
-    bool                    mbMenuBarDockingAreaCommonBG:1; // e.g. WinXP 
default theme
-    bool                    mbDockingAreaSeparateTB:1;      // individual 
toolbar backgrounds
+    bool                    mbMenuBarDockingAreaCommonBG = false; // e.g. 
WinXP default theme
+    bool                    mbDockingAreaSeparateTB = false; // individual 
toolbar backgrounds
                                                             // instead of one 
for docking area
-    bool                    mbDockingAreaAvoidTBFrames:1;   ///< don't draw 
frames around the individual toolbars if mbDockingAreaSeparateTB is false
-    bool                    mbToolboxDropDownSeparate:1;    // two adjacent 
buttons for
+    bool                    mbDockingAreaAvoidTBFrames = false; ///< don't 
draw frames around the individual toolbars if mbDockingAreaSeparateTB is false
+    bool                    mbToolboxDropDownSeparate = false; // two adjacent 
buttons for
                                                             // toolbox 
dropdown buttons
-    bool                    mbFlatMenu:1;                   // no popup 3D 
border
-    bool                    mbOpenMenuOnF10:1;              // on gnome the 
first menu opens on F10
-    bool                    mbNoFocusRects:1;               // on Aqua/Gtk3 
use native focus rendering, except for flat buttons
-    bool                    mbNoFocusRectsForFlatButtons:1; // on Gtk3 native 
focusing is also preferred for flat buttons
-    bool                    mbCenteredTabs:1;               // on Aqua, tabs 
are centered
-    bool                    mbNoActiveTabTextRaise:1;       // on Aqua the 
text for the selected tab
+    bool                    mbFlatMenu = false;             // no popup 3D 
border
+    bool                    mbOpenMenuOnF10 = false;        // on gnome the 
first menu opens on F10
+    bool                    mbNoFocusRects = false;         // on Aqua/Gtk3 
use native focus rendering, except for flat buttons
+    bool                    mbNoFocusRectsForFlatButtons = false; // on Gtk3 
native focusing is also preferred for flat buttons
+    bool                    mbCenteredTabs = false;         // on Aqua, tabs 
are centered
+    bool                    mbNoActiveTabTextRaise = false; // on Aqua the 
text for the selected tab
                                                             // should not 
"jump up" a pixel
-    bool                    mbProgressNeedsErase:1;         // set true for 
platforms that should draw the
+    bool                    mbProgressNeedsErase = false;   // set true for 
platforms that should draw the
                                                             // window 
background before drawing the native
                                                             // progress bar
-    bool                    mbCheckBoxNeedsErase:1;         // set true for 
platforms that should draw the
+    bool                    mbCheckBoxNeedsErase = false;   // set true for 
platforms that should draw the
                                                             // window 
background before drawing the native
                                                             // checkbox
-    bool                    mbCanDrawWidgetAnySize:1;       // set to true 
currently on gtk
+    bool                    mbCanDrawWidgetAnySize = false; // set to true 
currently on gtk
 
     /// entire drop down listbox resembles a button, no textarea/button parts 
(as currently on Windows)
-    bool                    mbDDListBoxNoTextArea:1;
-    bool                    mbEnableAccel:1;                // whether or not 
accelerators are shown
-    bool                    mbAutoAccel:1;                  // whether 
accelerators are only shown when Alt is held down
+    bool                    mbDDListBoxNoTextArea = false;
+    bool                    mbEnableAccel = true;           // whether or not 
accelerators are shown
+    bool                    mbAutoAccel = false;            // whether 
accelerators are only shown when Alt is held down
 };
 
 struct BlendFrameCache
@@ -331,36 +338,37 @@ struct ImplSchedulerContext
 
 struct ImplSVData
 {
-    ImplSVData();
-
-    SalData*                mpSalData;
-    SalInstance*            mpDefInst;                      // Default 
SalInstance
-    Application*            mpApp;                          // pApp
+    SalData*                mpSalData = nullptr;
+    SalInstance*            mpDefInst = nullptr;            // Default 
SalInstance
+    Application*            mpApp = nullptr;                // pApp
     VclPtr<WorkWindow>      mpDefaultWin;                   // Default-Window
-    bool                    mbDeInit;                       // Is VCL 
deinitializing
-    SalI18NImeStatus*       mpImeStatus;                    // interface to 
ime status window
-    SalSystem*              mpSalSystem;                    // SalSystem 
interface
-    ResMgr*                 mpResMgr;                       // 
SV-Resource-Manager
-    ImplSchedulerContext    maSchedCtx;                     // indepen data 
for class Scheduler
+    ImplSchedulerContext    maSchedCtx;                    // indepen data for 
class Scheduler
+    bool                    mbDeInit = false;               // Is VCL 
deinitializing
+    ImplSchedulerData*      mpFirstSchedulerData = nullptr; // list of all 
running tasks
+    SalTimer*               mpSalTimer = nullptr;           // interface to 
sal event loop/timers
+    SalI18NImeStatus*       mpImeStatus = nullptr;          // interface to 
ime status window
+    SalSystem*              mpSalSystem = nullptr;          // SalSystem 
interface
+    ResMgr*                 mpResMgr = nullptr;             // 
SV-Resource-Manager
+    sal_uInt64              mnTimerPeriod = 0;              // current timer 
period
     ImplSVAppData           maAppData;                      // indepen data 
for class Application
     ImplSVGDIData           maGDIData;                      // indepen data 
for Output classes
     ImplSVWinData           maWinData;                      // indepen data 
for Windows classes
     ImplSVCtrlData          maCtrlData;                     // indepen data 
for Control classes
     ImplSVHelpData          maHelpData;                     // indepen data 
for Help classes
     ImplSVNWFData           maNWFData;
-    UnoWrapperBase*         mpUnoWrapper;
+    UnoWrapperBase*         mpUnoWrapper = nullptr;
     VclPtr<vcl::Window>     mpIntroWindow;                  // the splash 
screen
-    DockingManager*         mpDockingManager;
-    BlendFrameCache*        mpBlendFrameCache;
-    vcl::CommandInfoProvider* mpCommandInfoProvider;
+    DockingManager*         mpDockingManager = nullptr;
+    BlendFrameCache*        mpBlendFrameCache = nullptr;
+    vcl::CommandInfoProvider* mpCommandInfoProvider = nullptr;
 
-    oslThreadIdentifier     mnMainThreadId;
+    oslThreadIdentifier     mnMainThreadId = 0;
     rtl::Reference< vcl::DisplayConnection > mxDisplayConnection;
 
     css::uno::Reference< css::lang::XComponent > mxAccessBridge;
-    vcl::SettingsConfigItem* mpSettingsConfigItem;
-    std::list< vcl::DeleteOnDeinitBase* >* mpDeinitDeleteList;
-    std::unordered_map< int, OUString >* mpPaperNames;
+    vcl::SettingsConfigItem* mpSettingsConfigItem = nullptr;
+    std::list< vcl::DeleteOnDeinitBase* >* mpDeinitDeleteList = nullptr;
+    std::unordered_map< int, OUString >* mpPaperNames = nullptr;
 
     Link<LinkParamNone*,void> maDeInitHook;
 };
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index db69f9847bb2..6af3c7c1c7cf 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -192,10 +192,6 @@ struct ImplPostEventData
     ~ImplPostEventData() {}
 };
 
-typedef ::std::pair< VclPtr<vcl::Window>, ImplPostEventData* > 
ImplPostEventPair;
-
-static ::std::list< ImplPostEventPair > aPostedEventList;
-
 Application* GetpApp()
 {
     ImplSVData* pSVData = ImplGetSVData();
@@ -927,7 +923,7 @@ ImplSVEvent * Application::PostKeyEvent( sal_uLong nEvent, 
vcl::Window *pWin, Ke
         if( nEventId )
         {
             pPostEventData->mnEventId = nEventId;
-            aPostedEventList.push_back( ImplPostEventPair( pWin, 
pPostEventData ) );
+            ImplGetSVData()->maAppData.maPostedEventList.push_back( 
ImplPostEventPair( pWin, pPostEventData ) );
         }
         else
             delete pPostEventData;
@@ -960,7 +956,7 @@ ImplSVEvent * Application::PostMouseEvent( sal_uLong 
nEvent, vcl::Window *pWin,
         if( nEventId )
         {
             pPostEventData->mnEventId = nEventId;
-            aPostedEventList.push_back( ImplPostEventPair( pWin, 
pPostEventData ) );
+            ImplGetSVData()->maAppData.maPostedEventList.push_back( 
ImplPostEventPair( pWin, pPostEventData ) );
         }
         else
             delete pPostEventData;
@@ -1025,14 +1021,15 @@ IMPL_STATIC_LINK_TYPED( Application, PostEventHandler, 
void*, pCallData, void )
         ImplWindowFrameProc( 
pData->mpWin.get()->mpWindowImpl->mpFrameWindow.get(), nEvent, pEventData );
 
     // remove this event from list of posted events, watch for destruction of 
internal data
-    ::std::list< ImplPostEventPair >::iterator aIter( aPostedEventList.begin() 
);
+    auto svdata = ImplGetSVData();
+    ::std::list< ImplPostEventPair >::iterator aIter( 
svdata->maAppData.maPostedEventList.begin() );
 
-    while( aIter != aPostedEventList.end() )
+    while( aIter != svdata->maAppData.maPostedEventList.end() )
     {
         if( nEventId == (*aIter).second->mnEventId )
         {
             delete (*aIter).second;
-            aIter = aPostedEventList.erase( aIter );
+            aIter = svdata->maAppData.maPostedEventList.erase( aIter );
         }
         else
             ++aIter;
@@ -1044,9 +1041,10 @@ void Application::RemoveMouseAndKeyEvents( vcl::Window* 
pWin )
     const SolarMutexGuard aGuard;
 
     // remove all events for specific window, watch for destruction of 
internal data
-    ::std::list< ImplPostEventPair >::iterator aIter( aPostedEventList.begin() 
);
+    auto svdata = ImplGetSVData();
+    ::std::list< ImplPostEventPair >::iterator aIter( 
svdata->maAppData.maPostedEventList.begin() );
 
-    while( aIter != aPostedEventList.end() )
+    while( aIter != svdata->maAppData.maPostedEventList.end() )
     {
         if( pWin == (*aIter).first )
         {
@@ -1054,7 +1052,7 @@ void Application::RemoveMouseAndKeyEvents( vcl::Window* 
pWin )
                 RemoveUserEvent( (*aIter).second->mnEventId );
 
             delete (*aIter).second;
-            aIter = aPostedEventList.erase( aIter );
+            aIter = svdata->maAppData.maPostedEventList.erase( aIter );
         }
         else
             ++aIter;
diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx
index ddad3e3738e8..99bf8976ce8f 100644
--- a/vcl/source/app/svdata.cxx
+++ b/vcl/source/app/svdata.cxx
@@ -79,16 +79,6 @@ SalSystem* ImplGetSalSystem()
     return pSVData->mpSalSystem;
 }
 
-ImplSVData::ImplSVData()
-{
-    // init global instance data
-    memset( this, 0, sizeof( ImplSVData ) );
-    maHelpData.mbAutoHelpId = true;
-    maNWFData.maMenuBarHighlightTextColor = Color( COL_TRANSPARENT );
-    maNWFData.mbEnableAccel = true;
-    maNWFData.mbAutoAccel = false;
-}
-
 ImplSVGDIData::~ImplSVGDIData()
 {
     // FIXME: deliberately leak any remaining OutputDevice
commit 63f2e482857986e44f8fbc9b378e688b071d83d3
Author: Jan-Marek Glogowski <glo...@fbihome.de>
Date:   Thu Jul 27 11:42:31 2017 +0200

    Implement VCL Scheduler locking
    
    Replces the SolarMutex scheduler locking by using a distinct mutex
    included in the scheduler context.
    
    It should also get rid of the spurious assert( !bAniIdle ) failures,
    as the test now holds the Scheduler lock for the whole time.
    
    This includes reverting the additional scheduler de-init from commit
    2e29a518b04250b5f9cc9d0d77da3df076834d60, as I couldn't reproduce
    the bug running the unit test in valgrind.
    
    Reviewed-on: https://gerrit.libreoffice.org/40497
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Jan-Marek Glogowski <glo...@fbihome.de>
    
     Conflicts:
            vcl/inc/svdata.hxx
            vcl/source/app/scheduler.cxx
    
    Change-Id: If33f815fe86c8f82175e96adceb1084b925319dd

diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx
index 0c0559a40b2b..d23148a7fde3 100644
--- a/include/vcl/scheduler.hxx
+++ b/include/vcl/scheduler.hxx
@@ -22,6 +22,7 @@
 
 #include <vcl/dllapi.h>
 
+class SchedulerGuard;
 class Task;
 struct TaskImpl;
 struct ImplSchedulerContext;
@@ -29,8 +30,9 @@ struct ImplSchedulerData;
 
 class VCL_DLLPUBLIC Scheduler final
 {
+    friend class SchedulerGuard;
     friend class Task;
-    Scheduler() = delete;
+    Scheduler() SAL_DELETED_FUNCTION;
 
     static inline bool HasPendingTasks( const ImplSchedulerContext &rSchedCtx,
                                         const sal_uInt64 nTime );
@@ -41,6 +43,9 @@ class VCL_DLLPUBLIC Scheduler final
 
     static void ImplStartTimer ( sal_uInt64 nMS, bool bForce, sal_uInt64 nTime 
);
 
+    static bool Lock( sal_uInt32 nLockCount = 1 );
+    static sal_uInt32 Unlock( bool bUnlockAll = false );
+
 public:
     static const SAL_CONSTEXPR sal_uInt64 ImmediateTimeoutMs = 0;
     static const SAL_CONSTEXPR sal_uInt64 InfiniteTimeoutMs = SAL_MAX_UINT64; 
// 1 day
diff --git a/sc/qa/unoapi/sc_4.sce b/sc/qa/unoapi/sc_4.sce
index b501c1189146..61bd5b557867 100644
--- a/sc/qa/unoapi/sc_4.sce
+++ b/sc/qa/unoapi/sc_4.sce
@@ -30,7 +30,12 @@
 -o sc.ScHeaderFieldsObj
 -o sc.ScHeaderFooterContentObj
 -o sc.ScHeaderFooterTextCursor
--o sc.ScHeaderFooterTextObj
+# SHF_TextObj is composed of SHF_TextData, which has a weak reference to
+# SHF_ContentObj, which itself has three references to SHF_TextObj.
+# 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.
+# -o sc.ScHeaderFooterTextObj
 -o sc.ScIndexEnumeration_CellAnnotationsEnumeration
 -o sc.ScIndexEnumeration_CellAreaLinksEnumeration
 -o sc.ScIndexEnumeration_DDELinksEnumeration
diff --git a/sfx2/source/appl/appinit.cxx b/sfx2/source/appl/appinit.cxx
index bd00ae5ee589..6d58627af32a 100644
--- a/sfx2/source/appl/appinit.cxx
+++ b/sfx2/source/appl/appinit.cxx
@@ -47,7 +47,6 @@
 #include <cppuhelper/supportsservice.hxx>
 
 #include <vcl/edit.hxx>
-#include <vcl/scheduler.hxx>
 
 #include <sfx2/unoctitm.hxx>
 #include "app.hrc"
@@ -107,10 +106,6 @@ void SAL_CALL 
SfxTerminateListener_Impl::notifyTermination( const EventObject& a
     SolarMutexGuard aGuard;
     utl::ConfigManager::storeConfigItems();
 
-    // Timers may access the SfxApplication and are only deleted in
-    // Application::Quit(), which is asynchronous (PostUserEvent) - disable!
-    Scheduler::ImplDeInitScheduler();
-
     SfxApplication* pApp = SfxGetpApp();
     pApp->Broadcast( SfxSimpleHint( SFX_HINT_DEINITIALIZING ) );
     pApp->Get_Impl()->pAppDispatch->ReleaseAll();
diff --git a/vcl/inc/schedulerimpl.hxx b/vcl/inc/schedulerimpl.hxx
index 2c29de6a6b30..df10fc930bda 100644
--- a/vcl/inc/schedulerimpl.hxx
+++ b/vcl/inc/schedulerimpl.hxx
@@ -21,6 +21,8 @@
 #define INCLUDED_VCL_INC_SCHEDULERIMPL_HXX
 
 #include <salwtype.hxx>
+#include <osl/mutex.hxx>
+#include <vcl/scheduler.hxx>
 
 class Task;
 
@@ -35,6 +37,39 @@ struct ImplSchedulerData final
     const char *GetDebugName() const;
 };
 
+class SchedulerMutex final
+{
+    sal_uInt32          mnLockDepth;
+    osl::Mutex          maMutex;
+
+public:
+    SchedulerMutex() : mnLockDepth( 0 ) {}
+
+    bool acquire( sal_uInt32 nLockCount = 1 );
+    sal_uInt32 release( bool bUnlockAll = false );
+    sal_uInt32 lockDepth() const { return mnLockDepth; }
+};
+
+class SchedulerGuard final
+{
+    bool mbLocked;
+
+public:
+    SchedulerGuard()
+        : mbLocked( false )
+    {
+        mbLocked = Scheduler::Lock();
+        assert( mbLocked );
+    }
+
+    ~SchedulerGuard()
+    {
+        if ( !mbLocked )
+            return;
+        Scheduler::Unlock();
+    }
+};
+
 #endif // INCLUDED_VCL_INC_SCHEDULERIMPL_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx
index dd9ec19269af..c4daa04d5555 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -34,6 +34,7 @@
 
 #include <unordered_map>
 #include <boost/functional/hash.hpp>
+#include "schedulerimpl.hxx"
 
 struct ImplTimerData;
 struct ImplIdleData;
@@ -41,7 +42,6 @@ struct ImplConfigData;
 class ImplDirectFontSubstitution;
 struct ImplHotKey;
 struct ImplEventHook;
-struct ImplSchedulerData;
 class Point;
 class ResMgr;
 class ImplAccelManager;
@@ -325,6 +325,8 @@ struct ImplSchedulerContext
     SalTimer*               mpSalTimer = nullptr;           ///< interface to 
sal event loop / system timer
     sal_uInt64              mnTimerStart = 0;               ///< start time of 
the timer
     sal_uInt64              mnTimerPeriod = SAL_MAX_UINT64; ///< current timer 
period
+    SchedulerMutex          maMutex;                        ///< lock counting 
mutex for scheduler locking
+    bool                    mbActive = true;                ///< is the 
scheduler active?
 };
 
 struct ImplSVData
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 2cd0940fc534..ccd127c08453 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -85,20 +85,29 @@ inline std::basic_ostream<charT, traits> & operator <<(
 
 void Scheduler::ImplDeInitScheduler()
 {
-    ImplSVData*           pSVData = ImplGetSVData();
+    ImplSVData* pSVData = ImplGetSVData();
     assert( pSVData != nullptr );
     ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
 
+    DBG_TESTSOLARMUTEX();
+
+    SchedulerGuard aSchedulerGuard;
+    rSchedCtx.mbActive = false;
+
+    assert( nullptr == rSchedCtx.mpSchedulerStack );
+    assert( 1 == rSchedCtx.maMutex.lockDepth() );
+
     if (rSchedCtx.mpSalTimer) rSchedCtx.mpSalTimer->Stop();
     DELETEZ( rSchedCtx.mpSalTimer );
 
     ImplSchedulerData* pSchedulerData = rSchedCtx.mpFirstSchedulerData;
     while ( pSchedulerData )
     {
-        if ( pSchedulerData->mpTask )
+        Task *pTask = pSchedulerData->mpTask;
+        if ( pTask )
         {
-            pSchedulerData->mpTask->mbActive = false;
-            pSchedulerData->mpTask->mpSchedulerData = nullptr;
+            pTask->mbActive = false;
+            pTask->mpSchedulerData = nullptr;
         }
         ImplSchedulerData* pDeleteSchedulerData = pSchedulerData;
         pSchedulerData = pSchedulerData->mpNext;
@@ -110,6 +119,55 @@ void Scheduler::ImplDeInitScheduler()
     rSchedCtx.mnTimerPeriod        = InfiniteTimeoutMs;
 }
 
+bool SchedulerMutex::acquire( sal_uInt32 nLockCount )
+{
+    do {
+        if ( !maMutex.acquire() )
+            return false;
+        ++mnLockDepth;
+    }
+    while ( --nLockCount );
+    return true;
+}
+
+sal_uInt32 SchedulerMutex::release( bool bUnlockAll )
+{
+    sal_uInt32 nLockCount = 0;
+    if ( mnLockDepth )
+    {
+        if ( bUnlockAll )
+        {
+            nLockCount = mnLockDepth;
+            do {
+                --mnLockDepth;
+                maMutex.release();
+            }
+            while ( mnLockDepth );
+        }
+        else
+        {
+            nLockCount = 1;
+            --mnLockDepth;
+            maMutex.release();
+        }
+    }
+    return nLockCount;
+}
+
+bool Scheduler::Lock( sal_uInt32 nLockCount )
+{
+    ImplSVData* pSVData = ImplGetSVData();
+    assert( pSVData != nullptr );
+    return pSVData->maSchedCtx.maMutex.acquire( nLockCount );
+}
+
+sal_uInt32 Scheduler::Unlock( bool bUnlockAll )
+{
+    ImplSVData* pSVData = ImplGetSVData();
+    assert( pSVData != nullptr );
+    return pSVData->maSchedCtx.maMutex.release( bUnlockAll );
+}
+
 /**
  * Start a new timer if we need to for nMS duration.
  *
@@ -120,16 +178,12 @@ void Scheduler::ImplDeInitScheduler()
 void Scheduler::ImplStartTimer(sal_uInt64 nMS, bool bForce, sal_uInt64 nTime)
 {
     ImplSVData* pSVData = ImplGetSVData();
-    if (pSVData->mbDeInit)
-    {
-        // do not start new timers during shutdown - if that happens after
-        // ImplSalStopTimer() on WNT the timer queue is restarted and never 
ends
+    ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
+    if ( !rSchedCtx.mbActive )
         return;
-    }
 
     DBG_TESTSOLARMUTEX();
 
-    ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
     if (!rSchedCtx.mpSalTimer)
     {
         rSchedCtx.mnTimerStart = 0;
@@ -228,10 +282,14 @@ bool Scheduler::ProcessTaskScheduling()
 {
     ImplSVData *pSVData = ImplGetSVData();
     ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
-    sal_uInt64 nTime = tools::Time::GetSystemTicks();
-    if ( pSVData->mbDeInit || InfiniteTimeoutMs == rSchedCtx.mnTimerPeriod )
+
+    DBG_TESTSOLARMUTEX();
+
+    SchedulerGuard aSchedulerGuard;
+    if ( !rSchedCtx.mbActive || InfiniteTimeoutMs == rSchedCtx.mnTimerPeriod )
         return false;
 
+    sal_uInt64 nTime = tools::Time::GetSystemTicks();
     if ( nTime < rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod )
     {
         SAL_WARN( "vcl.schedule", "we're too early - restart the timer!" );
@@ -326,7 +384,9 @@ next_entry:
         // defer pushing the scheduler stack to next run, as most tasks will
         // not run a nested Scheduler loop and don't need a stack push!
         pMostUrgent->mbInScheduler = true;
+        sal_uInt32 nLockCount = Unlock( true );
         pTask->Invoke();
+        Lock( nLockCount );
         pMostUrgent->mbInScheduler = false;
 
         SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
@@ -379,12 +439,12 @@ void Task::SetDeletionFlags()
 void Task::Start()
 {
     ImplSVData *const pSVData = ImplGetSVData();
-    if (pSVData->mbDeInit)
-    {
-        return;
-    }
     ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
 
+    SchedulerGuard aSchedulerGuard;
+    if ( !rSchedCtx.mbActive )
+        return;
+
     // Mark timer active
     mbActive = true;
 
@@ -448,6 +508,7 @@ Task::Task( const Task& rTask )
 
 Task::~Task()
 {
+    SchedulerGuard aSchedulerGuard;
     if ( mpSchedulerData )
         mpSchedulerData->mpTask = nullptr;
 }
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index 41e6377c752d..db69f9847bb2 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -519,6 +519,13 @@ bool Application::Reschedule( bool i_bAllEvents )
 void Scheduler::ProcessEventsToIdle()
 {
     int nSanity = 1;
+#if OSL_DEBUG_LEVEL > 0
+    const ImplSVData* pSVData = ImplGetSVData();
+    bool bIsMainThread = pSVData->mpDefInst->IsMainThread();
+    bool mbLocked = false;
+    if ( bIsMainThread )
+        mbLocked = Scheduler::Lock();
+#endif
     while( Application::Reschedule( true ) )
     {
         if (0 == ++nSanity % 1000)
@@ -530,10 +537,9 @@ void Scheduler::ProcessEventsToIdle()
     // If we yield from a non-main thread we just can guarantee that all idle
     // events were processed at some point, but our check can't prevent further
     // processing in the main thread, which may add new events, so skip it.
-    const ImplSVData* pSVData = ImplGetSVData();
-    if ( !pSVData->mpDefInst->IsMainThread() )
+    if ( !bIsMainThread )
         return;
-    const ImplSchedulerData* pSchedulerData = 
ImplGetSVData()->maSchedCtx.mpFirstSchedulerData;
+    const ImplSchedulerData* pSchedulerData = 
pSVData->maSchedCtx.mpFirstSchedulerData;
     bool bAnyIdle = false;
     while ( pSchedulerData )
     {
@@ -543,12 +549,14 @@ void Scheduler::ProcessEventsToIdle()
             if ( pIdle && pIdle->IsActive() )
             {
                 bAnyIdle = true;
-                SAL_WARN( "vcl.schedule",  "Unprocessed Idle: " << 
pIdle->GetDebugName() );
+                SAL_WARN( "vcl.schedule", "Unprocessed Idle: " << 
pIdle->GetDebugName() );
             }
         }
         pSchedulerData = pSchedulerData->mpNext;
     }
     assert( !bAnyIdle );
+    if ( mbLocked )
+        Scheduler::Unlock();
 #endif
 }
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to