vcl: double dispose protection & unit test.
Widgets must be able to tolerate multiple 'dispose' calls.
Change-Id: I76069a10b83b8384ad84dd146766054cab5bd222
diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx
index 189f15b..90c5d85 100644
--- a/include/vcl/window.hxx
+++ b/include/vcl/window.hxx
@@ -363,6 +363,8 @@ class VclBuilder;
class ImplDockingWindowWrapper;
class ImplPopupFloatWin;
class MenuFloatingWindow;
class LifecycleTest;
namespace svt { class PopupWindowControllerImpl; }
struct WindowResHeader
@@ -392,6 +394,7 @@ class VCL_DLLPUBLIC Window : public ::OutputDevice, public Resource
friend class ::ImplBorderWindow;
friend class ::VclBuilder;
friend class ::PaintHelper;
friend class ::LifecycleTest;
// TODO: improve missing functionality
// only required because of SetFloatingMode()
diff --git a/vcl/qa/cppunit/lifecycle.cxx b/vcl/qa/cppunit/lifecycle.cxx
index d635dd6..1c887b9 100644
--- a/vcl/qa/cppunit/lifecycle.cxx
+++ b/vcl/qa/cppunit/lifecycle.cxx
@@ -20,15 +20,30 @@ class LifecycleTest : public test::BootstrapFixture
public:
LifecycleTest() : BootstrapFixture(true, false) {}
void testMultiDispose();
void testIsolatedWidgets();
void testParentedWidgets();
CPPUNIT_TEST_SUITE(LifecycleTest);
CPPUNIT_TEST(testMultiDispose);
CPPUNIT_TEST(testIsolatedWidgets);
CPPUNIT_TEST(testParentedWidgets);
CPPUNIT_TEST_SUITE_END();
};
void LifecycleTest::testMultiDispose()
{
VclReference<WorkWindow> xWin(new WorkWindow((vcl::Window *)NULL,
WB_APP|WB_STDWORK));
CPPUNIT_ASSERT(xWin.get() != NULL);
xWin->dispose();
xWin->dispose();
xWin->dispose();
CPPUNIT_ASSERT(xWin->GetWindow(0) == NULL);
CPPUNIT_ASSERT(xWin->GetChild(0) == NULL);
CPPUNIT_ASSERT(xWin->GetChildCount() == 0);
}
void LifecycleTest::testWidgets(vcl::Window *pParent)
{
{ PushButtonPtr aPtr(new PushButton(pParent)); }
diff --git a/vcl/source/window/stacking.cxx b/vcl/source/window/stacking.cxx
index ee29a8d..9d81501 100644
--- a/vcl/source/window/stacking.cxx
+++ b/vcl/source/window/stacking.cxx
@@ -1023,6 +1023,8 @@ void Window::SetParent( vcl::Window* pNewParent )
sal_uInt16 Window::GetChildCount() const
{
if (!mpWindowImpl)
return 0;
sal_uInt16 nChildCount = 0;
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
@@ -1037,6 +1039,8 @@ sal_uInt16 Window::GetChildCount() const
vcl::Window* Window::GetChild( sal_uInt16 nChild ) const
{
if (!mpWindowImpl)
return NULL;
sal_uInt16 nChildCount = 0;
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
@@ -1053,6 +1057,8 @@ vcl::Window* Window::GetChild( sal_uInt16 nChild ) const
vcl::Window* Window::GetWindow( sal_uInt16 nType ) const
{
if (!mpWindowImpl)
return 0;
switch ( nType )
{
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index 122181d..17b3cea 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -133,6 +133,9 @@ namespace
void Window::dispose()
{
if (!mpWindowImpl)
return;
// remove Key and Mouse events issued by Application::PostKey/MouseEvent
Application::RemoveMouseAndKeyEvents( this );