corrected painting implementation for wxDFB
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41185 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
47e5915415
commit
20671963ef
@ -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)
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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_
|
||||
|
@ -231,10 +231,11 @@ struct wxIDirectFBSurface : public wxDfbWrapper<IDirectFBSurface>
|
||||
(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<IDirectFBSurface>
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user