summaryrefslogtreecommitdiff
path: root/vcl/unx
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@suse.cz>2011-03-08 16:14:48 +0100
committerLuboš Luňák <l.lunak@suse.cz>2011-03-08 16:16:07 +0100
commitc6753d78c3044a12133614904aa8d577fda49bbf (patch)
tree925976ded16c82ad55b0775310f8a7193dae7c43 /vcl/unx
parent86fb5fff88be611785b7908aac2a44475d77705f (diff)
avoid race condition with multiple window resizing (bnc#674806)
Diffstat (limited to 'vcl/unx')
-rw-r--r--vcl/unx/inc/salframe.h4
-rw-r--r--vcl/unx/source/window/salframe.cxx38
2 files changed, 42 insertions, 0 deletions
diff --git a/vcl/unx/inc/salframe.h b/vcl/unx/inc/salframe.h
index e9c6331fcb70..5ec3f04355a0 100644
--- a/vcl/unx/inc/salframe.h
+++ b/vcl/unx/inc/salframe.h
@@ -140,6 +140,7 @@ class VCL_DLLPUBLIC X11SalFrame : public SalFrame
int m_nCurClipRect;
int m_nMaxClipRect;
+ bool mPendingSizeEvent;
void GetPosSize( Rectangle &rPosSize );
void SetSize ( const Size &rSize );
@@ -279,6 +280,9 @@ public:
static void SaveYourselfDone( SalFrame* );
static Bool checkKeyReleaseForRepeat( Display*, XEvent*, XPointer pX11SalFrame );
+
+ /// @internal
+ void setPendingSizeEvent();
};
#ifdef _SV_SALDISP_HXX
diff --git a/vcl/unx/source/window/salframe.cxx b/vcl/unx/source/window/salframe.cxx
index ef813e4fc8d6..5068724f7da4 100644
--- a/vcl/unx/source/window/salframe.cxx
+++ b/vcl/unx/source/window/salframe.cxx
@@ -3611,9 +3611,37 @@ void X11SalFrame::RestackChildren()
}
}
+static Bool size_event_predicate( Display*, XEvent* event, XPointer arg )
+{
+ if( event->type != ConfigureNotify )
+ return False;
+ X11SalFrame* frame = reinterpret_cast< X11SalFrame* >( arg );
+ XConfigureEvent* pEvent = &event->xconfigure;
+ if( pEvent->window != frame->GetShellWindow()
+ && pEvent->window != frame->GetWindow()
+ && pEvent->window != frame->GetForeignParent()
+ && pEvent->window != frame->GetStackingWindow())
+ { // ignored at top of HandleSizeEvent()
+ return False;
+ }
+ if( pEvent->window == frame->GetStackingWindow())
+ return False; // filtered later in HandleSizeEvent()
+ // at this point we know that there is another similar event in the queue
+ frame->setPendingSizeEvent();
+ return False; // but do not process the new event out of order
+}
+
+void X11SalFrame::setPendingSizeEvent()
+{
+ mPendingSizeEvent = true;
+}
+
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
long X11SalFrame::HandleSizeEvent( XConfigureEvent *pEvent )
{
+ // NOTE: if you add more tests in this function, make sure to update size_event_predicate()
+ // so that it finds exactly the same events
+
if ( pEvent->window != GetShellWindow()
&& pEvent->window != GetWindow()
&& pEvent->window != GetForeignParent()
@@ -3661,6 +3689,16 @@ long X11SalFrame::HandleSizeEvent( XConfigureEvent *pEvent )
if( SHOWSTATE_UNKNOWN == nShowState_ && bMapped_ )
nShowState_ = SHOWSTATE_NORMAL;
+ // Avoid a race condition where resizing this window to one size and shortly after that
+ // to another size generates first size event with the old size and only after that
+ // with the new size, temporarily making us think the old size is valid (bnc#674806).
+ // So if there is another size event for this window pending, ignore this one.
+ mPendingSizeEvent = false;
+ XEvent dummy;
+ XCheckIfEvent( GetXDisplay(), &dummy, size_event_predicate, reinterpret_cast< XPointer >( this ));
+ if( mPendingSizeEvent )
+ return 1;
+
nWidth_ = pEvent->width;
nHeight_ = pEvent->height;