From 20671963efabd70a208b415c4734ee813b9eb439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Wed, 13 Sep 2006 09:50:02 +0000 Subject: [PATCH] corrected painting implementation for wxDFB git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41185 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/dfb/dcclient.h | 27 ++++------ include/wx/dfb/toplevel.h | 9 +++- include/wx/dfb/window.h | 10 ++-- include/wx/dfb/wrapdfb.h | 13 +++-- src/dfb/dc.cpp | 4 ++ src/dfb/dcclient.cpp | 94 +++++++++++++++++++-------------- src/dfb/toplevel.cpp | 73 +++++++++++++++++++------- src/dfb/window.cpp | 107 ++++++++++++++++++++++++++------------ src/dfb/wrapdfb.cpp | 14 +++++ 9 files changed, 231 insertions(+), 120 deletions(-) diff --git a/include/wx/dfb/dcclient.h b/include/wx/dfb/dcclient.h index aac9a933c9..a4006f9cc0 100644 --- a/include/wx/dfb/dcclient.h +++ b/include/wx/dfb/dcclient.h @@ -22,39 +22,31 @@ class WXDLLIMPEXP_CORE wxWindow; class WXDLLIMPEXP_CORE wxWindowDC : public wxDC { public: - wxWindowDC() {} + wxWindowDC() : m_win(NULL) {} wxWindowDC(wxWindow *win); + virtual ~wxWindowDC(); protected: // initializes the DC for painting on given window; if rect!=NULL, then // for painting only on the given region of the window void InitForWin(wxWindow *win, const wxRect *rect); +private: + wxWindow *m_win; // the window the DC paints on + DECLARE_DYNAMIC_CLASS(wxWindowDC) DECLARE_NO_COPY_CLASS(wxWindowDC) }; -//----------------------------------------------------------------------------- -// base class for wxClientDC and wxPaintDC -//----------------------------------------------------------------------------- - -class WXDLLIMPEXP_CORE wxClientDCBase : public wxWindowDC -{ -public: - wxClientDCBase() {} - wxClientDCBase(wxWindow *win); -}; - //----------------------------------------------------------------------------- // wxClientDC //----------------------------------------------------------------------------- -class WXDLLIMPEXP_CORE wxClientDC : public wxClientDCBase +class WXDLLIMPEXP_CORE wxClientDC : public wxWindowDC { public: wxClientDC() {} - wxClientDC(wxWindow *win) : wxClientDCBase(win) {} - ~wxClientDC(); + wxClientDC(wxWindow *win); DECLARE_DYNAMIC_CLASS(wxClientDC) DECLARE_NO_COPY_CLASS(wxClientDC) @@ -65,12 +57,11 @@ public: // wxPaintDC //----------------------------------------------------------------------------- -class WXDLLIMPEXP_CORE wxPaintDC : public wxClientDCBase +class WXDLLIMPEXP_CORE wxPaintDC : public wxClientDC { public: wxPaintDC() {} - wxPaintDC(wxWindow *win) : wxClientDCBase(win) {} - ~wxPaintDC(); + wxPaintDC(wxWindow *win) : wxClientDC(win) {} DECLARE_DYNAMIC_CLASS(wxPaintDC) DECLARE_NO_COPY_CLASS(wxPaintDC) diff --git a/include/wx/dfb/toplevel.h b/include/wx/dfb/toplevel.h index d35f257c1b..f15d9e4fd7 100644 --- a/include/wx/dfb/toplevel.h +++ b/include/wx/dfb/toplevel.h @@ -77,6 +77,10 @@ public: wxIDirectFBWindowPtr GetDirectFBWindow() const { return m_dfbwin; } + // Returns true if some invalidated area of the TLW is currently being + // painted + bool IsPainting() const { return m_isPainting; } + protected: // common part of all ctors void Init(); @@ -88,7 +92,7 @@ protected: virtual void DoGetSize(int *width, int *height) const; virtual void DoMoveWindow(int x, int y, int width, int height); - virtual void DoRefreshRect(const wxRect& rect, bool eraseBack = true); + virtual void DoRefreshRect(const wxRect& rect); private: // do queued painting in idle time @@ -119,7 +123,10 @@ protected: wxIDirectFBWindowPtr m_dfbwin; private: + // invalidated areas of the TLW that need repainting wxDfbQueuedPaintRequests *m_toPaint; + // are we currently painting some area of this TLW? + bool m_isPainting; friend class wxEventLoop; // for HandleDFBWindowEvent }; diff --git a/include/wx/dfb/window.h b/include/wx/dfb/window.h index e30d2ae436..f5bc1b15b2 100644 --- a/include/wx/dfb/window.h +++ b/include/wx/dfb/window.h @@ -140,11 +140,12 @@ protected: void InvalidateDfbSurface(); // called by parent to render (part of) the window - void PaintWindow(const wxRect& rect, bool eraseBackground); + void PaintWindow(const wxRect& rect); - // implementation of Refresh() - void DoRefreshWindow(bool eraseBack = true); - virtual void DoRefreshRect(const wxRect& rect, bool eraseBack = true); + // refreshes the entire window (including non-client areas) + void DoRefreshWindow(); + // refreshes given rectangle of the window (in window, _not_ client coords) + virtual void DoRefreshRect(const wxRect& rect); // DirectFB events handling void HandleKeyEvent(const wxDFBWindowEvent& event_); @@ -177,5 +178,4 @@ private: DECLARE_EVENT_TABLE() }; - #endif // _WX_DFB_WINDOW_H_ diff --git a/include/wx/dfb/wrapdfb.h b/include/wx/dfb/wrapdfb.h index 30ef307513..bed40a9124 100644 --- a/include/wx/dfb/wrapdfb.h +++ b/include/wx/dfb/wrapdfb.h @@ -231,10 +231,11 @@ struct wxIDirectFBSurface : public wxDfbWrapper (DFBSurfaceTextFlags)flags)); } - bool Flip(const DFBRegion *region, int flags) - { - return Check(m_ptr->Flip(m_ptr, region, (DFBSurfaceFlipFlags)flags)); - } + /** + Updates the front buffer from the back buffer. If @a region is not + NULL, only given rectangle is updated. + */ + bool FlipToFront(const DFBRegion *region = NULL); wxIDirectFBSurfacePtr GetSubSurface(const DFBRectangle *rect) { @@ -293,6 +294,10 @@ struct wxIDirectFBSurface : public wxDfbWrapper size of this surface. */ wxIDirectFBSurfacePtr CreateCompatible(const wxSize& size = wxDefaultSize); + +private: + // this is private because we want user code to use FlipToFront() + bool Flip(const DFBRegion *region, int flags); }; diff --git a/src/dfb/dc.cpp b/src/dfb/dc.cpp index 72b7ff8138..f5d6a1691d 100644 --- a/src/dfb/dc.cpp +++ b/src/dfb/dc.cpp @@ -151,6 +151,10 @@ void wxDC::Clear() wxColour clr = m_backgroundBrush.GetColour(); m_surface->Clear(clr.Red(), clr.Green(), clr.Blue(), clr.Alpha()); + + wxSize size(GetSize()); + CalcBoundingBox(XDEV2LOG(0), YDEV2LOG(0)); + CalcBoundingBox(XDEV2LOG(size.x), YDEV2LOG(size.y)); } extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, diff --git a/src/dfb/dcclient.cpp b/src/dfb/dcclient.cpp index c51e6a509e..160f3e336d 100644 --- a/src/dfb/dcclient.cpp +++ b/src/dfb/dcclient.cpp @@ -31,6 +31,8 @@ #include "wx/dfb/private.h" +#define TRACE_PAINT _T("paint") + // =========================================================================== // implementation // =========================================================================== @@ -48,13 +50,12 @@ wxWindowDC::wxWindowDC(wxWindow *win) void wxWindowDC::InitForWin(wxWindow *win, const wxRect *rect) { + m_win = win; + wxCHECK_RET( win, _T("invalid window") ); - // check if the rectangle covers full window and so is not needed: - if ( rect && *rect == wxRect(win->GetSize()) ) - rect = NULL; - // obtain the surface used for painting: + wxPoint origin; wxIDirectFBSurfacePtr surface; if ( !win->IsVisible() ) @@ -64,21 +65,37 @@ void wxWindowDC::InitForWin(wxWindow *win, const wxRect *rect) // we still need a valid DC so that e.g. text extents can be measured, // so let's create a dummy surface that has the same format as the real // one would have and let the code paint on it: + wxLogTrace(TRACE_PAINT, _T("%p ('%s'): creating dummy DC surface"), + win, win->GetName().c_str()); wxSize size(rect ? rect->GetSize() : win->GetSize()); surface = win->GetDfbSurface()->CreateCompatible(size); } - else if ( !rect ) - { - wxCHECK_RET( win->GetSize().x > 0 && win->GetSize().y > 0, - _T("window has invalid size") ); - - surface = win->GetDfbSurface(); - } else { - wxCHECK_RET( !rect || !rect->IsEmpty(), _T("invalid rectangle") ); + wxRect rectOrig(rect ? *rect : wxRect(win->GetSize())); - DFBRectangle dfbrect = { rect->x, rect->y, rect->width, rect->height }; + // compute painting rectangle after clipping if we're in PaintWindow + // code, otherwise paint on the entire window: + wxRect r(rectOrig); + if ( win->GetTLW()->IsPainting() ) + r.Intersect(win->GetUpdateRegion().AsRect()); + + wxCHECK_RET( !r.IsEmpty(), _T("invalid painting rectangle") ); + + // if the DC was clipped thanks to rectPaint, we must adjust the origin + // accordingly; but we do *not* adjust for 'rect', because + // rect.GetPosition() has coordinates (0,0) in the DC: + origin.x = rectOrig.x - r.x; + origin.y = rectOrig.y - r.y; + + wxLogTrace(TRACE_PAINT, + _T("%p ('%s'): creating DC for area [%i,%i,%i,%i], clipped to [%i,%i,%i,%i], origin [%i,%i]"), + win, win->GetName().c_str(), + rectOrig.x, rectOrig.y, rectOrig.GetRight(), rectOrig.GetBottom(), + r.x, r.y, r.GetRight(), r.GetBottom(), + origin.x, origin.y); + + DFBRectangle dfbrect = { r.x, r.y, r.width, r.height }; surface = win->GetDfbSurface()->GetSubSurface(&dfbrect); } @@ -89,20 +106,31 @@ void wxWindowDC::InitForWin(wxWindow *win, const wxRect *rect) SetFont(win->GetFont()); // offset coordinates to account for subsurface's origin coordinates: - if ( rect ) - SetDeviceOrigin(rect->x, rect->y); + SetDeviceOrigin(origin.x, origin.y); } -//----------------------------------------------------------------------------- -// base class for wxClientDC and wxPaintDC -//----------------------------------------------------------------------------- - -wxClientDCBase::wxClientDCBase(wxWindow *win) +wxWindowDC::~wxWindowDC() { - wxCHECK_RET( win, _T("invalid window") ); + wxIDirectFBSurfacePtr surface(GetDirectFBSurface()); + if ( !surface || !m_win ) + return; - wxRect rect = win->GetClientRect(); - InitForWin(win, &rect); + // painting on hidden window has no effect on TLW's surface, don't + // waste time flipping the dummy surface: + if ( !m_win->IsVisible() ) + return; + + // if no painting was done on the DC, we don't have to flip the surface: + if ( !m_isBBoxValid ) + return; + + if ( !m_win->GetTLW()->IsPainting() ) + { + // FIXME: flip only modified parts of the surface + surface->FlipToFront(); + } + // else: don't flip the surface, wxTLW will do it when it finishes + // painting of its invalidated areas } //----------------------------------------------------------------------------- @@ -111,15 +139,12 @@ wxClientDCBase::wxClientDCBase(wxWindow *win) IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC) -wxClientDC::~wxClientDC() +wxClientDC::wxClientDC(wxWindow *win) { - // flip to surface so that the changes become visible - wxIDirectFBSurfacePtr surface(GetDirectFBSurface()); + wxCHECK_RET( win, _T("invalid window") ); - // FIXME: do this only if the surface was modified (as opposed to e.g. - // used only to obtain text metrics) - if ( surface ) - surface->Flip(NULL, DSFLIP_NONE); + wxRect rect = win->GetClientRect(); + InitForWin(win, &rect); } //----------------------------------------------------------------------------- @@ -127,12 +152,3 @@ wxClientDC::~wxClientDC() //----------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC) - -#warning "wxPaintDC ctor must respect m_updateRegion" - -wxPaintDC::~wxPaintDC() -{ - // NB: do *not* flip the surface: wxPaintDC is used with EVT_PAINT and the - // surface will be flipped for the entire TLW once all children are - // repainted -} diff --git a/src/dfb/toplevel.cpp b/src/dfb/toplevel.cpp index 41b05ce9b1..3aebd23e40 100644 --- a/src/dfb/toplevel.cpp +++ b/src/dfb/toplevel.cpp @@ -41,13 +41,10 @@ static wxDfbWindowsMap gs_dfbWindowsMap; struct wxDfbPaintRequest { - wxDfbPaintRequest(const wxRect& rect, bool eraseBackground) - : m_rect(rect), m_eraseBackground(eraseBackground) {} - wxDfbPaintRequest(const wxDfbPaintRequest& r) - : m_rect(r.m_rect), m_eraseBackground(r.m_eraseBackground) {} + wxDfbPaintRequest(const wxRect& rect) : m_rect(rect) {} + wxDfbPaintRequest(const wxDfbPaintRequest& r) : m_rect(r.m_rect) {} wxRect m_rect; - bool m_eraseBackground; }; WX_DEFINE_ARRAY_PTR(wxDfbPaintRequest*, wxDfbQueuedPaintRequestsList); @@ -59,8 +56,8 @@ public: ~wxDfbQueuedPaintRequests() { Clear(); } // Adds paint request to the queue - void Add(const wxRect& rect, bool eraseBack) - { m_queue.push_back(new wxDfbPaintRequest(rect, eraseBack)); } + void Add(const wxRect& rect) + { m_queue.push_back(new wxDfbPaintRequest(rect)); } // Is the queue empty? bool IsEmpty() const { return m_queue.empty(); } @@ -91,6 +88,7 @@ void wxTopLevelWindowDFB::Init() m_sizeSet = false; m_opacity = 255; m_toPaint = new wxDfbQueuedPaintRequests; + m_isPainting = false; } bool wxTopLevelWindowDFB::Create(wxWindow *parent, @@ -148,7 +146,8 @@ bool wxTopLevelWindowDFB::Create(wxWindow *parent, if ( !m_dfbwin->SetOpacity(wxALPHA_TRANSPARENT) ) return false; - wxWindow::Create(NULL, id, pos, size, style, name); + if ( !wxWindow::Create(NULL, id, pos, size, style, name) ) + return false; SetParent(parent); if ( parent ) @@ -217,7 +216,8 @@ void wxTopLevelWindowDFB::DoMoveWindow(int x, int y, int width, int height) { m_dfbwin->Resize(width, height); // we must repaint the window after it changed size: - Refresh(); + if ( IsShown() ) + DoRefreshWindow(); } } @@ -375,23 +375,30 @@ void wxTopLevelWindowDFB::HandleQueuedPaintRequests() wxRect winRect(wxPoint(0, 0), GetSize()); wxRect paintedRect; + // important note: all DCs created from now until m_isPainting is reset to + // false will not update the front buffer as this flag indicates that we'll + // blit the entire back buffer to front soon + m_isPainting = true; + size_t cnt = requests.size(); + wxLogTrace(TRACE_PAINT, _T("%p ('%s'): processing %i paint requests"), + this, GetName().c_str(), cnt); + for ( size_t i = 0; i < cnt; ++i ) { const wxDfbPaintRequest& request = *requests[i]; wxRect clipped(request.m_rect); - - wxLogTrace(TRACE_PAINT, - _T("%p ('%s'): processing paint request [x=%i,y=%i,w=%i,h=%i]"), - this, GetName().c_str(), - clipped.x, clipped.y, clipped.width, clipped.height); - clipped.Intersect(winRect); if ( clipped.IsEmpty() ) continue; // nothing to refresh - PaintWindow(clipped, request.m_eraseBackground); + wxLogTrace(TRACE_PAINT, + _T("%p ('%s'): processing paint request [%i,%i,%i,%i]"), + this, GetName().c_str(), + clipped.x, clipped.y, clipped.GetRight(), clipped.GetBottom()); + + PaintWindow(clipped); // remember rectangle covering all repainted areas: if ( paintedRect.IsEmpty() ) @@ -400,23 +407,49 @@ void wxTopLevelWindowDFB::HandleQueuedPaintRequests() paintedRect.Union(clipped); } + m_isPainting = false; + m_toPaint->Clear(); if ( paintedRect.IsEmpty() ) return; // no painting occurred, no need to flip - // flip the surface to make the changes visible: + // Flip the surface to make the changes visible. Note that the rectangle we + // flip is *superset* of the union of repainted rectangles (created as + // "rectangles union" by wxRect::Union) and so some parts of the back + // buffer that we didn't touch in this HandleQueuedPaintRequests call will + // be copied to the front buffer as well. This is safe/correct thing to do + // *only* because wx always use wxIDirectFBSurface::FlipToFront() and so + // the back and front buffers contain the same data. + // + // Note that we do _not_ split m_toPaint into disjoint rectangles and + // do FlipToFront() for each of them, because that could result in visible + // updating of the screen; instead, we prefer to flip everything at once. + DFBRegion r = {paintedRect.GetLeft(), paintedRect.GetTop(), paintedRect.GetRight(), paintedRect.GetBottom()}; DFBRegion *rptr = (winRect == paintedRect) ? NULL : &r; - GetDfbSurface()->Flip(rptr, DSFLIP_NONE); + GetDfbSurface()->FlipToFront(rptr); + + wxLogTrace(TRACE_PAINT, + _T("%p ('%s'): flipped surface: [%i,%i,%i,%i]"), + this, GetName().c_str(), + paintedRect.x, paintedRect.y, + paintedRect.GetRight(), paintedRect.GetBottom()); } -void wxTopLevelWindowDFB::DoRefreshRect(const wxRect& rect, bool eraseBack) +void wxTopLevelWindowDFB::DoRefreshRect(const wxRect& rect) { + wxASSERT_MSG( rect.width > 0 && rect.height > 0, _T("invalid rect") ); + + wxLogTrace(TRACE_PAINT, + _T("%p ('%s'): [TLW] refresh rect [%i,%i,%i,%i]"), + this, GetName().c_str(), + rect.x, rect.y, rect.GetRight(), rect.GetBottom()); + // defer painting until idle time or until Update() is called: - m_toPaint->Add(rect, eraseBack); + m_toPaint->Add(rect); } void wxTopLevelWindowDFB::Update() diff --git a/src/dfb/window.cpp b/src/dfb/window.cpp index f2b090be72..30e38e9827 100644 --- a/src/dfb/window.cpp +++ b/src/dfb/window.cpp @@ -590,34 +590,56 @@ void wxWindowDFB::Clear() dc.Clear(); } -void wxWindowDFB::Refresh(bool eraseBack, const wxRect *rect) +void wxWindowDFB::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect) { if ( !IsShown() || IsFrozen() ) return; + // NB[1]: We intentionally ignore the eraseBack argument here. This is + // because of the way wxDFB's painting is implemented: the refresh + // request is probagated up to wxTLW, which is then painted in + // top-down order. This means that this window's area is first + // painted by its parent and this window is then painted over it, so + // it's not safe to not paint this window's background even if + // eraseBack=false. + // NB[2]: wxWindow::Refresh() takes the rectangle in client coords, but + // wxUniv translates it to window coords before passing it to + // wxWindowDFB::Refresh(), so we can directly pass the rect to + // DoRefreshRect (which takes window, not client, coords) here. if ( rect ) - DoRefreshRect(*rect, eraseBack); + DoRefreshRect(*rect); else - DoRefreshWindow(eraseBack); + DoRefreshWindow(); } -void wxWindowDFB::DoRefreshWindow(bool eraseBack) +void wxWindowDFB::DoRefreshWindow() { - DoRefreshRect(wxRect(wxPoint(0, 0), GetSize()), eraseBack); + // NB: DoRefreshRect() takes window coords, not client, so this is correct + DoRefreshRect(wxRect(GetSize())); } -void wxWindowDFB::DoRefreshRect(const wxRect& rect, bool eraseBack) +void wxWindowDFB::DoRefreshRect(const wxRect& rect) { wxWindow *parent = GetParent(); wxCHECK_RET( parent, _T("no parent") ); + // don't overlap outside of the window (NB: 'rect' is in window coords): + wxRect r(rect); + r.Intersect(wxRect(GetSize())); + if ( r.IsEmpty() ) + return; + + wxLogTrace(TRACE_PAINT, + _T("%p ('%s'): refresh rect [%i,%i,%i,%i]"), + this, GetName().c_str(), + rect.x, rect.y, rect.GetRight(), rect.GetBottom()); + // convert the refresh rectangle to parent's coordinates and // recursively refresh the parent: - wxRect r(rect); r.Offset(GetPosition()); r.Offset(parent->GetClientAreaOrigin()); - parent->DoRefreshRect(r, eraseBack); + parent->DoRefreshRect(r); } void wxWindowDFB::Update() @@ -640,24 +662,21 @@ void wxWindowDFB::Thaw() if ( --m_frozenness == 0 ) { if ( IsShown() ) - Refresh(); + DoRefreshWindow(); } } -void wxWindowDFB::PaintWindow(const wxRect& rect, bool eraseBackground) +void wxWindowDFB::PaintWindow(const wxRect& rect) { wxCHECK_RET( !IsFrozen() && IsShown(), _T("shouldn't be called") ); wxLogTrace(TRACE_PAINT, - _T("%p ('%s'): painting region [x=%i,y=%i,w=%i,h=%i]"), + _T("%p ('%s'): painting region [%i,%i,%i,%i]"), this, GetName().c_str(), - rect.x, rect.y, rect.width, rect.height); + rect.x, rect.y, rect.GetRight(), rect.GetBottom()); m_updateRegion = rect; - // FIXME_DFB: don't waste time rendering the area if it's fully covered - // by some children, go directly to rendering the children - #if wxUSE_CARET // must hide caret temporarily, otherwise we'd get rendering artifacts wxCaret *caret = GetCaret(); @@ -665,27 +684,52 @@ void wxWindowDFB::PaintWindow(const wxRect& rect, bool eraseBackground) caret->Hide(); #endif // wxUSE_CARET - if ( eraseBackground ) + // FIXME_DFB: don't waste time rendering the area if it's fully covered + // by some children, go directly to rendering the children + + // NB: unconditionally send wxEraseEvent, because our implementation of + // wxWindow::Refresh() ignores the eraseBack argument + wxWindowDC dc((wxWindow*)this); + wxEraseEvent eventEr(m_windowId, &dc); + eventEr.SetEventObject(this); + GetEventHandler()->ProcessEvent(eventEr); + + wxRect clientRect(GetClientRect()); + + // only send wxNcPaintEvent if drawing at least part of nonclient area: + if ( !clientRect.Inside(rect) ) { - wxWindowDC dc((wxWindow*)this); - wxEraseEvent eventEr(m_windowId, &dc); - eventEr.SetEventObject(this); - GetEventHandler()->ProcessEvent(eventEr); + wxNcPaintEvent eventNc(GetId()); + eventNc.SetEventObject(this); + GetEventHandler()->ProcessEvent(eventNc); + } + else + { + wxLogTrace(TRACE_PAINT, _T("%p ('%s'): not sending wxNcPaintEvent"), + this, GetName().c_str()); } - wxNcPaintEvent eventNc(GetId()); - eventNc.SetEventObject(this); - GetEventHandler()->ProcessEvent(eventNc); - - wxPaintEvent eventPt(GetId()); - eventPt.SetEventObject(this); - GetEventHandler()->ProcessEvent(eventPt); + // only send wxPaintEvent if drawing at least part of client area: + if ( rect.Intersects(clientRect) ) + { + wxPaintEvent eventPt(GetId()); + eventPt.SetEventObject(this); + GetEventHandler()->ProcessEvent(eventPt); + } + else + { + wxLogTrace(TRACE_PAINT, _T("%p ('%s'): not sending wxPaintEvent"), + this, GetName().c_str()); + } #if wxUSE_CARET if ( caret ) caret->Show(); #endif // wxUSE_CARET + m_updateRegion.Clear(); + + // paint the children: wxPoint origin = GetClientAreaOrigin(); wxWindowList& children = GetChildren(); for ( wxWindowList::iterator i = children.begin(); @@ -704,13 +748,10 @@ void wxWindowDFB::PaintWindow(const wxRect& rect, bool eraseBackground) continue; // and repaint it: - wxPoint childpos(child->GetPosition()); - childrect.Offset(-childpos.x, -childpos.y); - childrect.Offset(-origin.x, -origin.y); - child->PaintWindow(childrect, eraseBackground); + childrect.Offset(-child->GetPosition()); + childrect.Offset(-origin); + child->PaintWindow(childrect); } - - m_updateRegion.Clear(); } diff --git a/src/dfb/wrapdfb.cpp b/src/dfb/wrapdfb.cpp index 873f040cde..c237966963 100644 --- a/src/dfb/wrapdfb.cpp +++ b/src/dfb/wrapdfb.cpp @@ -166,3 +166,17 @@ wxIDirectFBSurfacePtr wxIDirectFBSurface::Clone() return snew; } + +bool wxIDirectFBSurface::Flip(const DFBRegion *region, int flags) +{ + return Check(m_ptr->Flip(m_ptr, region, (DFBSurfaceFlipFlags)flags)); +} + +bool wxIDirectFBSurface::FlipToFront(const DFBRegion *region) +{ + // Blit to the front buffer instead of exchanging front and back ones. + // Always doing this ensures that back and front buffer have same content + // and so painting to the back buffer will never lose any previous + // drawings: + return Flip(region, DSFLIP_BLIT); +}