Fix problem with nested wxEVT_PAINT handlers in wxMSW
If wxEVT_PAINT handler did something that resulted in another window being repainted, the state of the global wxDidCreatePaintDC flag got out of sync with reality, resulting in refresh problems. This notably happened with wxStyledTextCtrl, which generates wxEVT_STC_UPDATEUI from its own paint handler, and so wxSTC itself wasn't redrawn correctly if wxEVT_STC_UPDATEUI handler did anything resulting in another repaint itself, such as calling wxStatusBar::SetStatusText(). Fix this by replacing a single global bool with a stack of booleans, with each window being repainted storing and removing its own flag indicating whether a wxPaintDC was created for it in this stack. This is sufficient for nested repaints and we really shouldn't have any interleaved ones in any case, os it's not a problem not to support those. Closes #18451.
This commit is contained in:
committed by
Vadim Zeitlin
parent
4f7dde18ca
commit
5646ba7261
@@ -63,6 +63,7 @@
|
||||
#include "wx/popupwin.h"
|
||||
#include "wx/power.h"
|
||||
#include "wx/scopeguard.h"
|
||||
#include "wx/stack.h"
|
||||
#include "wx/sysopt.h"
|
||||
|
||||
#if wxUSE_DRAG_AND_DROP
|
||||
@@ -5261,8 +5262,8 @@ wxColour wxWindowMSW::MSWGetThemeColour(const wchar_t *themeName,
|
||||
// endless stream of WM_PAINT messages for this window resulting in a lot of
|
||||
// difficult to debug problems (e.g. impossibility to repaint other windows,
|
||||
// lack of timer and idle events and so on)
|
||||
extern bool wxDidCreatePaintDC;
|
||||
bool wxDidCreatePaintDC = false;
|
||||
extern wxStack<bool> wxDidCreatePaintDC;
|
||||
wxStack<bool> wxDidCreatePaintDC;
|
||||
|
||||
bool wxWindowMSW::HandlePaint()
|
||||
{
|
||||
@@ -5278,14 +5279,14 @@ bool wxWindowMSW::HandlePaint()
|
||||
|
||||
m_updateRegion = wxRegion((WXHRGN) hRegion);
|
||||
|
||||
wxDidCreatePaintDC = false;
|
||||
wxDidCreatePaintDC.push(false);
|
||||
|
||||
wxPaintEvent event(m_windowId);
|
||||
event.SetEventObject(this);
|
||||
|
||||
bool processed = HandleWindowEvent(event);
|
||||
|
||||
if ( wxDidCreatePaintDC && !processed )
|
||||
if ( wxDidCreatePaintDC.top() && !processed )
|
||||
{
|
||||
// Event handler did paint something as wxPaintDC object was created
|
||||
// but then it must have skipped the event to indicate that default
|
||||
@@ -5316,7 +5317,9 @@ bool wxWindowMSW::HandlePaint()
|
||||
// was processed, we must still call MSWDefWindowProc() to ensure that the
|
||||
// window is validated, i.e. to avoid the problem described in the comment
|
||||
// before wxDidCreatePaintDC definition above.
|
||||
return wxDidCreatePaintDC;
|
||||
const bool ret = wxDidCreatePaintDC.top();
|
||||
wxDidCreatePaintDC.pop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Can be called from an application's OnPaint handler
|
||||
|
Reference in New Issue
Block a user