Kaydet (Commit) aab8bed7 authored tarafından Caolán McNamara's avatar Caolán McNamara

Resolves: rhbz#1283426 using vdevs based on now dead physical devs is unsafe

This is the same problem that

commit 133e04fc
Author: Caolán McNamara <caolanm@redhat.com>
Date:   Wed Jun 17 09:23:32 2015 +0100

    Resolves: tdf#91880 Invalidate graphics when the gtk window is destroyed

    not just when the GtkSalFrame is dtored

tried to fix, but that just made it more unlikely to fail

Change-Id: Icba750c787adb6cd5c5ed0874ef07e6201c4cf25
(cherry picked from commit 26c32cfe)
üst ff2bdd52
...@@ -43,6 +43,11 @@ namespace ...@@ -43,6 +43,11 @@ namespace
// allocated/used buffers (remembered to allow deleting them in destructor) // allocated/used buffers (remembered to allow deleting them in destructor)
aBuffers maUsedBuffers; aBuffers maUsedBuffers;
// remember what outputdevice was the template passed to VirtualDevice::Create
// so we can test if that OutputDevice was disposed before reusing a
// virtualdevice because that isn't safe to do at least for Gtk2
std::map< VclPtr<VirtualDevice>, VclPtr<OutputDevice> > maDeviceTemplates;
public: public:
VDevBuffer(); VDevBuffer();
virtual ~VDevBuffer(); virtual ~VDevBuffer();
...@@ -87,14 +92,14 @@ namespace ...@@ -87,14 +92,14 @@ namespace
sal_Int32 nBits = bMonoChrome ? 1 : rOutDev.GetBitCount(); sal_Int32 nBits = bMonoChrome ? 1 : rOutDev.GetBitCount();
bool bOkay(false);
if(!maFreeBuffers.empty()) if(!maFreeBuffers.empty())
{ {
bool bOkay(false);
aBuffers::iterator aFound(maFreeBuffers.end()); aBuffers::iterator aFound(maFreeBuffers.end());
for(aBuffers::iterator a(maFreeBuffers.begin()); a != maFreeBuffers.end(); ++a) for(aBuffers::iterator a(maFreeBuffers.begin()); a != maFreeBuffers.end(); ++a)
{ {
OSL_ENSURE(*a, "Empty pointer in VDevBuffer (!)"); assert(*a && "Empty pointer in VDevBuffer (!)");
if (nBits == (*a)->GetBitCount()) if (nBits == (*a)->GetBitCount())
{ {
...@@ -144,10 +149,25 @@ namespace ...@@ -144,10 +149,25 @@ namespace
{ {
pRetval = *aFound; pRetval = *aFound;
maFreeBuffers.erase(aFound); maFreeBuffers.erase(aFound);
}
}
if(bOkay) if (pRetval)
{
// found a suitable cached virtual device, but the
// outputdevice it was based on has been disposed,
// drop it and create a new one instead as reusing
// such devices is unsafe under at least Gtk2
if (maDeviceTemplates[pRetval]->isDisposed())
{
maDeviceTemplates.erase(pRetval);
pRetval = nullptr;
}
else
{
if (bOkay)
{ {
if(bClear) if (bClear)
{ {
pRetval->Erase(Rectangle(0, 0, rSizePixel.getWidth(), rSizePixel.getHeight())); pRetval->Erase(Rectangle(0, 0, rSizePixel.getWidth(), rSizePixel.getHeight()));
} }
...@@ -163,6 +183,7 @@ namespace ...@@ -163,6 +183,7 @@ namespace
if(!pRetval) if(!pRetval)
{ {
pRetval = VclPtr<VirtualDevice>::Create(rOutDev, bMonoChrome ? DeviceFormat::BITMASK : DeviceFormat::DEFAULT); pRetval = VclPtr<VirtualDevice>::Create(rOutDev, bMonoChrome ? DeviceFormat::BITMASK : DeviceFormat::DEFAULT);
maDeviceTemplates[pRetval] = &rOutDev;
pRetval->SetOutputSizePixel(rSizePixel, bClear); pRetval->SetOutputSizePixel(rSizePixel, bClear);
} }
else else
...@@ -196,7 +217,9 @@ namespace ...@@ -196,7 +217,9 @@ namespace
while(!maFreeBuffers.empty()) while(!maFreeBuffers.empty())
{ {
(*(maFreeBuffers.end() - 1)).disposeAndClear(); aBuffers::iterator aLastOne(maFreeBuffers.end() - 1);
maDeviceTemplates.erase(*aLastOne);
aLastOne->disposeAndClear();
maFreeBuffers.pop_back(); maFreeBuffers.pop_back();
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment