diff options
author | Luboš Luňák <l.lunak@suse.cz> | 2011-03-08 16:14:48 +0100 |
---|---|---|
committer | Luboš Luňák <l.lunak@suse.cz> | 2011-03-08 16:16:07 +0100 |
commit | c6753d78c3044a12133614904aa8d577fda49bbf (patch) | |
tree | 925976ded16c82ad55b0775310f8a7193dae7c43 /vcl/unx | |
parent | 86fb5fff88be611785b7908aac2a44475d77705f (diff) |
avoid race condition with multiple window resizing (bnc#674806)
Diffstat (limited to 'vcl/unx')
-rw-r--r-- | vcl/unx/inc/salframe.h | 4 | ||||
-rw-r--r-- | vcl/unx/source/window/salframe.cxx | 38 |
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; |