]> git.saurik.com Git - wxWidgets.git/blobdiff - src/dfb/window.cpp
missing commit
[wxWidgets.git] / src / dfb / window.cpp
index 014e7c32be0c47f173188e4edf6596781e84eae5..9caa5b23c274d1c379b52b385bf0bdf6e86eeb6c 100644 (file)
@@ -2,7 +2,7 @@
 // Name:        src/dfb/window.cpp
 // Purpose:     wxWindow
 // Author:      Vaclav Slavik
 // Name:        src/dfb/window.cpp
 // Purpose:     wxWindow
 // Author:      Vaclav Slavik
-//              (based on GTK, MSW, MGL implementations)
+//              (based on GTK, MSW implementations)
 // Created:     2006-80-10
 // RCS-ID:      $Id$
 // Copyright:   (c) 2006 REA Elektronik GmbH
 // Created:     2006-80-10
 // RCS-ID:      $Id$
 // Copyright:   (c) 2006 REA Elektronik GmbH
 
 #ifndef WX_PRECOMP
     #include "wx/dcclient.h"
 
 #ifndef WX_PRECOMP
     #include "wx/dcclient.h"
+    #include "wx/nonownedwnd.h"
 #endif
 
 #include "wx/caret.h"
 #endif
 
 #include "wx/caret.h"
+#include "wx/dynarray.h"
 
 #include "wx/dfb/private.h"
 
 #include "wx/dfb/private.h"
+#include "wx/private/overlay.h"
 
 
-#define TRACE_EVENTS _T("events")
-#define TRACE_PAINT  _T("paint")
+#define TRACE_EVENTS "events"
+#define TRACE_PAINT  "paint"
 
 // ===========================================================================
 // implementation
 
 // ===========================================================================
 // implementation
@@ -53,6 +56,12 @@ static wxWindow *gs_toBeFocusedWindow = NULL;
 // the window that has mouse capture
 static wxWindowDFB *gs_mouseCapture = NULL;
 
 // the window that has mouse capture
 static wxWindowDFB *gs_mouseCapture = NULL;
 
+// ---------------------------------------------------------------------------
+// overlays support
+// ---------------------------------------------------------------------------
+
+WX_DEFINE_ARRAY_PTR(wxOverlayImpl*, wxDfbOverlaysList);
+
 // ---------------------------------------------------------------------------
 // event tables
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 // event tables
 // ---------------------------------------------------------------------------
@@ -63,6 +72,15 @@ IMPLEMENT_ABSTRACT_CLASS(wxWindowDFB, wxWindowBase)
 BEGIN_EVENT_TABLE(wxWindowDFB, wxWindowBase)
 END_EVENT_TABLE()
 
 BEGIN_EVENT_TABLE(wxWindowDFB, wxWindowBase)
 END_EVENT_TABLE()
 
+//-----------------------------------------------------------------------------
+// global functions
+//-----------------------------------------------------------------------------
+
+wxWindow *wxGetActiveWindow()
+{
+    return wxWindow::FindFocus();
+}
+
 // ----------------------------------------------------------------------------
 // constructors and such
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // constructors and such
 // ----------------------------------------------------------------------------
@@ -70,8 +88,8 @@ END_EVENT_TABLE()
 void wxWindowDFB::Init()
 {
     m_isShown = true;
 void wxWindowDFB::Init()
 {
     m_isShown = true;
-    m_frozenness = 0;
     m_tlw = NULL;
     m_tlw = NULL;
+    m_overlays = NULL;
 }
 
 // Destructor
 }
 
 // Destructor
@@ -79,32 +97,11 @@ wxWindowDFB::~wxWindowDFB()
 {
     SendDestroyEvent();
 
 {
     SendDestroyEvent();
 
-    m_isBeingDeleted = true;
-
     if ( gs_mouseCapture == this )
         ReleaseMouse();
 
     if ( gs_mouseCapture == this )
         ReleaseMouse();
 
-#warning "FIXME: what to do with gs_activeFrame here and elsewhere?"
-#if 0
-    if (gs_activeFrame == this)
-    {
-        gs_activeFrame = NULL;
-        // activate next frame in Z-order:
-        if ( m_wnd->prev )
-        {
-            wxWindowDFB *win = (wxWindowDFB*)m_wnd->prev->userData;
-            win->SetFocus();
-        }
-        else if ( m_wnd->next )
-        {
-            wxWindowDFB *win = (wxWindowDFB*)m_wnd->next->userData;
-            win->SetFocus();
-        }
-    }
-#endif
-
     if ( gs_focusedWindow == this )
     if ( gs_focusedWindow == this )
-        KillFocus();
+        DFBKillFocus();
 
     DestroyChildren();
 }
 
     DestroyChildren();
 }
@@ -147,10 +144,10 @@ bool wxWindowDFB::Create(wxWindow *parent,
 
 wxIDirectFBSurfacePtr wxWindowDFB::ObtainDfbSurface() const
 {
 
 wxIDirectFBSurfacePtr wxWindowDFB::ObtainDfbSurface() const
 {
-    wxCHECK_MSG( m_parent, NULL, _T("parentless window?") );
+    wxCHECK_MSG( m_parent, NULL, "parentless window?" );
 
     wxIDirectFBSurfacePtr parentSurface(m_parent->GetDfbSurface());
 
     wxIDirectFBSurfacePtr parentSurface(m_parent->GetDfbSurface());
-    wxCHECK_MSG( parentSurface, NULL, _T("invalid parent surface") );
+    wxCHECK_MSG( parentSurface, NULL, "invalid parent surface" );
 
     wxRect r(GetRect());
     AdjustForParentClientOrigin(r.x, r.y, 0);
 
     wxRect r(GetRect());
     AdjustForParentClientOrigin(r.x, r.y, 0);
@@ -164,7 +161,7 @@ wxIDirectFBSurfacePtr wxWindowDFB::GetDfbSurface()
     if ( !m_surface )
     {
         m_surface = ObtainDfbSurface();
     if ( !m_surface )
     {
         m_surface = ObtainDfbSurface();
-        wxASSERT_MSG( m_surface, _T("invalid DirectFB surface") );
+        wxASSERT_MSG( m_surface, "invalid DirectFB surface" );
     }
 
     return m_surface;
     }
 
     return m_surface;
@@ -173,6 +170,14 @@ wxIDirectFBSurfacePtr wxWindowDFB::GetDfbSurface()
 void wxWindowDFB::InvalidateDfbSurface()
 {
     m_surface = NULL;
 void wxWindowDFB::InvalidateDfbSurface()
 {
     m_surface = NULL;
+
+    // surfaces of the children are subsurfaces of this window's surface,
+    // so they must be invalidated as well:
+    wxWindowList& children = GetChildren();
+    for ( wxWindowList::iterator i = children.begin(); i != children.end(); ++i )
+    {
+        (*i)->InvalidateDfbSurface();
+    }
 }
 
 // ---------------------------------------------------------------------------
 }
 
 // ---------------------------------------------------------------------------
@@ -181,49 +186,38 @@ void wxWindowDFB::InvalidateDfbSurface()
 
 void wxWindowDFB::SetFocus()
 {
 
 void wxWindowDFB::SetFocus()
 {
-    if ( gs_focusedWindow == this ) return;
+    if ( gs_focusedWindow == this )
+        return; // nothing to do, focused already
 
     wxWindowDFB *oldFocusedWindow = gs_focusedWindow;
 
     if ( gs_focusedWindow )
     {
         gs_toBeFocusedWindow = (wxWindow*)this;
 
     wxWindowDFB *oldFocusedWindow = gs_focusedWindow;
 
     if ( gs_focusedWindow )
     {
         gs_toBeFocusedWindow = (wxWindow*)this;
-        gs_focusedWindow->KillFocus();
+        gs_focusedWindow->DFBKillFocus();
         gs_toBeFocusedWindow = NULL;
     }
 
         gs_toBeFocusedWindow = NULL;
     }
 
-#warning "FIXME: implement in terms of DWET_{GOT,LOST}FOCUS"
-
-    wxIDirectFBWindowPtr dfbwin(m_tlw->GetDirectFBWindow());
-#warning "FIXME: RequestFocus() may only be called on visible TLW"
-    if ( !dfbwin->RequestFocus() )
-        return;
-
     gs_focusedWindow = this;
 
     gs_focusedWindow = this;
 
-    #warning "FIXME: keep this or not? not, think multiapp core"
-#if 0
-    wxWindowDFB *active = wxGetTopLevelParent((wxWindow*)this);
-    if ( !(m_windowStyle & wxPOPUP_WINDOW) && active != gs_activeFrame )
+    if ( IsShownOnScreen() &&
+         (!oldFocusedWindow || oldFocusedWindow->GetTLW() != m_tlw) )
     {
     {
-        if ( gs_activeFrame )
-        {
-            wxActivateEvent event(wxEVT_ACTIVATE, false, gs_activeFrame->GetId());
-            event.SetEventObject(gs_activeFrame);
-            gs_activeFrame->GetEventHandler()->ProcessEvent(event);
-        }
-
-        gs_activeFrame = active;
-        wxActivateEvent event(wxEVT_ACTIVATE, true, gs_activeFrame->GetId());
-        event.SetEventObject(gs_activeFrame);
-        gs_activeFrame->GetEventHandler()->ProcessEvent(event);
+        m_tlw->SetDfbFocus();
     }
     }
-#endif
+    // else: do nothing, because DirectFB windows cannot have focus if they
+    //       are hidden; when the TLW becomes visible, it will set the focus
+    //       to use from wxTLW::Show()
+
+    // notify the parent keeping track of focus for the kbd navigation
+    // purposes that we got it
+    wxChildFocusEvent eventFocus((wxWindow*)this);
+    HandleWindowEvent(eventFocus);
 
     wxFocusEvent event(wxEVT_SET_FOCUS, GetId());
     event.SetEventObject(this);
     event.SetWindow((wxWindow*)oldFocusedWindow);
 
     wxFocusEvent event(wxEVT_SET_FOCUS, GetId());
     event.SetEventObject(this);
     event.SetWindow((wxWindow*)oldFocusedWindow);
-    GetEventHandler()->ProcessEvent(event);
+    HandleWindowEvent(event);
 
 #if wxUSE_CARET
     // caret needs to be informed about focus change
 
 #if wxUSE_CARET
     // caret needs to be informed about focus change
@@ -233,12 +227,15 @@ void wxWindowDFB::SetFocus()
 #endif // wxUSE_CARET
 }
 
 #endif // wxUSE_CARET
 }
 
-void wxWindowDFB::KillFocus()
+void wxWindowDFB::DFBKillFocus()
 {
 {
-    if ( gs_focusedWindow != this ) return;
+    wxCHECK_RET( gs_focusedWindow == this,
+                 "killing focus on window that doesn't have it" );
+
     gs_focusedWindow = NULL;
 
     gs_focusedWindow = NULL;
 
-    if ( m_isBeingDeleted ) return;
+    if ( m_isBeingDeleted )
+        return; // don't send any events from dtor
 
 #if wxUSE_CARET
     // caret needs to be informed about focus change
 
 #if wxUSE_CARET
     // caret needs to be informed about focus change
@@ -250,7 +247,7 @@ void wxWindowDFB::KillFocus()
     wxFocusEvent event(wxEVT_KILL_FOCUS, GetId());
     event.SetEventObject(this);
     event.SetWindow(gs_toBeFocusedWindow);
     wxFocusEvent event(wxEVT_KILL_FOCUS, GetId());
     event.SetEventObject(this);
     event.SetWindow(gs_toBeFocusedWindow);
-    GetEventHandler()->ProcessEvent(event);
+    HandleWindowEvent(event);
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------
@@ -272,43 +269,19 @@ bool wxWindowDFB::Show(bool show)
     // parent area at the place of this window (if hiding):
     DoRefreshWindow();
 
     // parent area at the place of this window (if hiding):
     DoRefreshWindow();
 
-#warning "FIXME: all of this must be implemented for DFB"
-#if 0
-    DFB_wmShowWindow(m_wnd, show);
-
-    if (!show && gs_activeFrame == this)
-    {
-        // activate next frame in Z-order:
-        if ( m_wnd->prev )
-        {
-            wxWindowDFB *win = (wxWindowDFB*)m_wnd->prev->userData;
-            win->SetFocus();
-        }
-        else if ( m_wnd->next )
-        {
-            wxWindowDFB *win = (wxWindowDFB*)m_wnd->next->userData;
-            win->SetFocus();
-        }
-        else
-        {
-            gs_activeFrame = NULL;
-        }
-    }
-#endif
-
     return true;
 }
 
 // Raise the window to the top of the Z order
 void wxWindowDFB::Raise()
 {
     return true;
 }
 
 // Raise the window to the top of the Z order
 void wxWindowDFB::Raise()
 {
-    wxFAIL_MSG( _T("Raise() not implemented") );
+    wxFAIL_MSG( "Raise() not implemented" );
 }
 
 // Lower the window to the bottom of the Z order
 void wxWindowDFB::Lower()
 {
 }
 
 // Lower the window to the bottom of the Z order
 void wxWindowDFB::Lower()
 {
-    wxFAIL_MSG( _T("Lower() not implemented") );
+    wxFAIL_MSG( "Lower() not implemented" );
 }
 
 void wxWindowDFB::DoCaptureMouse()
 }
 
 void wxWindowDFB::DoCaptureMouse()
@@ -350,7 +323,7 @@ bool wxWindowDFB::SetCursor(const wxCursor& cursor)
 
 #warning "implement this"
 #if 0
 
 #warning "implement this"
 #if 0
-    if ( m_cursor.Ok() )
+    if ( m_cursor.IsOk() )
         DFB_wmSetWindowCursor(m_wnd, *m_cursor.GetDFBCursor());
     else
         DFB_wmSetWindowCursor(m_wnd, *wxSTANDARD_CURSOR->GetDFBCursor());
         DFB_wmSetWindowCursor(m_wnd, *m_cursor.GetDFBCursor());
     else
         DFB_wmSetWindowCursor(m_wnd, *wxSTANDARD_CURSOR->GetDFBCursor());
@@ -370,8 +343,8 @@ void wxWindowDFB::WarpPointer(int x, int y)
     if ( x >= w ) x = w-1;
     if ( y >= h ) y = h-1;
 
     if ( x >= w ) x = w-1;
     if ( y >= h ) y = h-1;
 
-    wxIDirectFBDisplayLayerPtr layer(wxDfbGetDisplayLayer());
-    wxCHECK_RET( layer, _T("no display layer") );
+    wxIDirectFBDisplayLayerPtr layer(wxIDirectFB::Get()->GetDisplayLayer());
+    wxCHECK_RET( layer, "no display layer" );
 
     layer->WarpCursor(x, y);
 }
 
     layer->WarpCursor(x, y);
 }
@@ -383,7 +356,7 @@ bool wxWindowDFB::Reparent(wxWindowBase *parent)
         return false;
 
 #warning "implement this"
         return false;
 
 #warning "implement this"
-    wxFAIL_MSG( _T("reparenting not yet implemented") );
+    wxFAIL_MSG( "reparenting not yet implemented" );
 
     return true;
 }
 
     return true;
 }
@@ -407,7 +380,7 @@ void wxWindowDFB::DoGetPosition(int *x, int *y) const
 
 static wxPoint GetScreenPosOfClientOrigin(const wxWindowDFB *win)
 {
 
 static wxPoint GetScreenPosOfClientOrigin(const wxWindowDFB *win)
 {
-    wxCHECK_MSG( win, wxPoint(0, 0), _T("no window provided") );
+    wxCHECK_MSG( win, wxPoint(0, 0), "no window provided" );
 
     wxPoint pt(win->GetPosition() + win->GetClientAreaOrigin());
 
 
     wxPoint pt(win->GetPosition() + win->GetClientAreaOrigin());
 
@@ -441,10 +414,21 @@ void wxWindowDFB::DoGetClientSize(int *x, int *y) const
 
 void wxWindowDFB::DoMoveWindow(int x, int y, int width, int height)
 {
 
 void wxWindowDFB::DoMoveWindow(int x, int y, int width, int height)
 {
+    // NB: [x,y] arguments are in (parent's) window coordinates, while
+    //     m_rect.{x,y} are in (parent's) client coordinates. That's why we
+    //     offset by parentOrigin in some places below
+
+    wxPoint parentOrigin(0, 0);
+    AdjustForParentClientOrigin(parentOrigin.x, parentOrigin.y);
+
     wxRect oldpos(m_rect);
     wxRect oldpos(m_rect);
+    oldpos.Offset(parentOrigin);
+
     wxRect newpos(x, y, width, height);
 
     wxRect newpos(x, y, width, height);
 
+    // input [x,y] is in window coords, but we store client coords in m_rect:
     m_rect = newpos;
     m_rect = newpos;
+    m_rect.Offset(-parentOrigin);
 
     // window's position+size changed and so did the subsurface that covers it
     InvalidateDfbSurface();
 
     // window's position+size changed and so did the subsurface that covers it
     InvalidateDfbSurface();
@@ -453,9 +437,15 @@ void wxWindowDFB::DoMoveWindow(int x, int y, int width, int height)
     {
         // queue both former and new position of the window for repainting:
         wxWindow *parent = GetParent();
     {
         // queue both former and new position of the window for repainting:
         wxWindow *parent = GetParent();
-        wxPoint origin(parent->GetClientAreaOrigin());
-        oldpos.Offset(origin);
-        newpos.Offset(origin);
+
+        // only refresh the visible parts:
+        if ( !CanBeOutsideClientArea() )
+        {
+            wxRect parentClient(parent->GetClientSize());
+            oldpos.Intersect(parentClient);
+            newpos.Intersect(parentClient);
+        }
+
         parent->RefreshRect(oldpos);
         parent->RefreshRect(newpos);
     }
         parent->RefreshRect(oldpos);
         parent->RefreshRect(newpos);
     }
@@ -489,8 +479,6 @@ void wxWindowDFB::DoSetSize(int x, int y, int width, int height, int sizeFlags)
         return;
     }
 
         return;
     }
 
-    AdjustForParentClientOrigin(x, y, sizeFlags);
-
     wxSize size(-1, -1);
     if ( width == -1 )
     {
     wxSize size(-1, -1);
     if ( width == -1 )
     {
@@ -538,12 +526,13 @@ void wxWindowDFB::DoSetSize(int x, int y, int width, int height, int sizeFlags)
     if ( m_rect.x != x || m_rect.y != y ||
          m_rect.width != width || m_rect.height != height )
     {
     if ( m_rect.x != x || m_rect.y != y ||
          m_rect.width != width || m_rect.height != height )
     {
+        AdjustForParentClientOrigin(x, y, sizeFlags);
         DoMoveWindow(x, y, width, height);
 
         wxSize newSize(width, height);
         wxSizeEvent event(newSize, GetId());
         event.SetEventObject(this);
         DoMoveWindow(x, y, width, height);
 
         wxSize newSize(width, height);
         wxSizeEvent event(newSize, GetId());
         event.SetEventObject(this);
-        GetEventHandler()->ProcessEvent(event);
+        HandleWindowEvent(event);
     }
 }
 
     }
 }
 
@@ -568,10 +557,11 @@ int wxWindowDFB::GetCharWidth() const
     return dc.GetCharWidth();
 }
 
     return dc.GetCharWidth();
 }
 
-void wxWindowDFB::GetTextExtent(const wxString& string,
-                             int *x, int *y,
-                             int *descent, int *externalLeading,
-                             const wxFont *theFont) const
+void wxWindowDFB::DoGetTextExtent(const wxString& string,
+                                  int *x, int *y,
+                                  int *descent,
+                                  int *externalLeading,
+                                  const wxFont *theFont) const
 {
     wxWindowDC dc((wxWindow*)this);
     dc.GetTextExtent(string, x, y, descent, externalLeading, (wxFont*)theFont);
 {
     wxWindowDC dc((wxWindow*)this);
     dc.GetTextExtent(string, x, y, descent, externalLeading, (wxFont*)theFont);
@@ -582,42 +572,69 @@ void wxWindowDFB::GetTextExtent(const wxString& string,
 // painting
 // ---------------------------------------------------------------------------
 
 // painting
 // ---------------------------------------------------------------------------
 
-void wxWindowDFB::Clear()
+void wxWindowDFB::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect)
 {
 {
-    wxClientDC dc((wxWindow *)this);
-    wxBrush brush(GetBackgroundColour(), wxSOLID);
-    dc.SetBackground(brush);
-    dc.Clear();
+    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 propagated 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);
+    else
+        DoRefreshWindow();
 }
 
 }
 
-void wxWindowDFB::Refresh(bool eraseBack, const wxRect *rect)
+void wxWindowDFB::RefreshWindowRect(const wxRect& rect)
 {
     if ( !IsShown() || IsFrozen() )
         return;
 
 {
     if ( !IsShown() || IsFrozen() )
         return;
 
-    if ( rect )
-        DoRefreshRect(*rect, eraseBack);
-    else
-        DoRefreshWindow(eraseBack);
+    DoRefreshRect(rect);
 }
 
 }
 
-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();
 {
     wxWindow *parent = GetParent();
-    wxCHECK_RET( parent, _T("no parent") );
+    wxCHECK_RET( parent, "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,
+               "%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:
 
     // convert the refresh rectangle to parent's coordinates and
     // recursively refresh the parent:
-    wxRect r(rect);
     r.Offset(GetPosition());
     r.Offset(parent->GetClientAreaOrigin());
 
     r.Offset(GetPosition());
     r.Offset(parent->GetClientAreaOrigin());
 
-    parent->DoRefreshRect(r, eraseBack);
+    // normal windows cannot extend out of its parent's client area, so don't
+    // refresh any hidden parts:
+    if ( !CanBeOutsideClientArea() )
+        r.Intersect(parent->GetClientRect());
+
+    parent->DoRefreshRect(r);
 }
 
 void wxWindowDFB::Update()
 }
 
 void wxWindowDFB::Update()
@@ -628,64 +645,72 @@ void wxWindowDFB::Update()
     GetParent()->Update();
 }
 
     GetParent()->Update();
 }
 
-void wxWindowDFB::Freeze()
-{
-    m_frozenness++;
-}
-
-void wxWindowDFB::Thaw()
+void wxWindowDFB::DoThaw()
 {
 {
-    wxASSERT_MSG( IsFrozen(), _T("Thaw() without matching Freeze()") );
-
-    if ( --m_frozenness == 0 )
-    {
-        if ( IsShown() )
-            Refresh();
-    }
+    if ( IsShown() )
+        DoRefreshWindow();
 }
 
 }
 
-void wxWindowDFB::PaintWindow(const wxRect& rect, bool eraseBackground)
+void wxWindowDFB::PaintWindow(const wxRect& rect)
 {
 {
-    wxCHECK_RET( !IsFrozen() && IsShown(), _T("shouldn't be called") );
+    wxCHECK_RET( !IsFrozen() && IsShown(), "shouldn't be called" );
 
     wxLogTrace(TRACE_PAINT,
 
     wxLogTrace(TRACE_PAINT,
-               _T("%p ('%s'): painting region [x=%i,y=%i,w=%i,h=%i]"),
+               "%p ('%s'): painting region [%i,%i,%i,%i]",
                this, GetName().c_str(),
                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
 
     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
+    //            (unless some child has HasTransparentBackground()=true!)
 
 
-#if wxUSE_CARET
-    // must hide caret temporarily, otherwise we'd get rendering artifacts
-    wxCaret *caret = GetCaret();
-    if ( caret )
-        caret->Hide();
-#endif // wxUSE_CARET
+    // 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);
+    HandleWindowEvent(eventEr);
+
+    wxRect clientRect(GetClientRect());
+
+    // only send wxNcPaintEvent if drawing at least part of nonclient area:
+    if ( !clientRect.Contains(rect) )
+    {
+        wxNcPaintEvent eventNc(GetId());
+        eventNc.SetEventObject(this);
+        HandleWindowEvent(eventNc);
+    }
+    else
+    {
+        wxLogTrace(TRACE_PAINT, "%p ('%s'): not sending wxNcPaintEvent",
+                   this, GetName().c_str());
+    }
 
 
-    if ( eraseBackground )
+    // only send wxPaintEvent if drawing at least part of client area:
+    if ( rect.Intersects(clientRect) )
     {
     {
-        wxWindowDC dc((wxWindow*)this);
-        wxEraseEvent eventEr(m_windowId, &dc);
-        eventEr.SetEventObject(this);
-        GetEventHandler()->ProcessEvent(eventEr);
+        wxPaintEvent eventPt(GetId());
+        eventPt.SetEventObject(this);
+        HandleWindowEvent(eventPt);
+    }
+    else
+    {
+        wxLogTrace(TRACE_PAINT, "%p ('%s'): not sending wxPaintEvent",
+                   this, GetName().c_str());
     }
 
     }
 
-    wxNcPaintEvent eventNc(GetId());
-    eventNc.SetEventObject(this);
-    GetEventHandler()->ProcessEvent(eventNc);
+    // draw window's overlays on top of the painted window, if we have any:
+    PaintOverlays(rect);
 
 
-    wxPaintEvent eventPt(GetId());
-    eventPt.SetEventObject(this);
-    GetEventHandler()->ProcessEvent(eventPt);
+    m_updateRegion.Clear();
 
 
-#if wxUSE_CARET
-    if ( caret )
-        caret->Show();
-#endif // wxUSE_CARET
+    // client area portion of 'rect':
+    wxRect rectClientOnly(rect);
+    rectClientOnly.Intersect(clientRect);
 
 
+    // paint the children:
     wxPoint origin = GetClientAreaOrigin();
     wxWindowList& children = GetChildren();
     for ( wxWindowList::iterator i = children.begin();
     wxPoint origin = GetClientAreaOrigin();
     wxWindowList& children = GetChildren();
     for ( wxWindowList::iterator i = children.begin();
@@ -699,18 +724,73 @@ void wxWindowDFB::PaintWindow(const wxRect& rect, bool eraseBackground)
         // compute child's area to repaint
         wxRect childrect(child->GetRect());
         childrect.Offset(origin);
         // compute child's area to repaint
         wxRect childrect(child->GetRect());
         childrect.Offset(origin);
-        childrect.Intersect(rect);
+
+        if ( child->CanBeOutsideClientArea() )
+            childrect.Intersect(rect);
+        else
+            childrect.Intersect(rectClientOnly);
+
         if ( childrect.IsEmpty() )
             continue;
 
         // and repaint it:
         if ( childrect.IsEmpty() )
             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();
+void wxWindowDFB::PaintOverlays(const wxRect& rect)
+{
+    if ( !m_overlays )
+        return;
+
+    for ( wxDfbOverlaysList::const_iterator i = m_overlays->begin();
+          i != m_overlays->end(); ++i )
+    {
+        const wxOverlayImpl * const overlay = *i;
+
+        wxRect orectOrig(overlay->GetRect());
+        wxRect orect(orectOrig);
+        orect.Intersect(rect);
+        if ( orect.IsEmpty() )
+            continue;
+
+        if ( overlay->IsEmpty() )
+            continue; // nothing to paint
+
+        DFBRectangle dfbRect = { orect.x - orectOrig.x, orect.y - orectOrig.y,
+                                 orect.width, orect.height };
+        GetDfbSurface()->Blit
+                         (
+                           overlay->GetDirectFBSurface(),
+                           &dfbRect,
+                           orect.x, orect.y
+                         );
+    }
+}
+
+void wxWindowDFB::AddOverlay(wxOverlayImpl *overlay)
+{
+    if ( !m_overlays )
+        m_overlays = new wxDfbOverlaysList;
+
+    m_overlays->Add(overlay);
+}
+
+void wxWindowDFB::RemoveOverlay(wxOverlayImpl *overlay)
+{
+    wxCHECK_RET( m_overlays, "no overlays to remove" );
+
+    m_overlays->Remove(overlay);
+
+    if ( m_overlays->empty() )
+    {
+        wxDELETE(m_overlays);
+    }
+
+    if ( !m_isBeingDeleted )
+        RefreshWindowRect(overlay->GetRect());
 }
 
 
 }
 
 
@@ -721,7 +801,7 @@ void wxWindowDFB::PaintWindow(const wxRect& rect, bool eraseBackground)
 #define KEY(dfb, wx)                                                \
     case dfb:                                                       \
           wxLogTrace(TRACE_EVENTS,                                  \
 #define KEY(dfb, wx)                                                \
     case dfb:                                                       \
           wxLogTrace(TRACE_EVENTS,                                  \
-                     _T("key " #dfb " mapped to " #wx));            \
+                     wxT("key " #dfb " mapped to " #wx));            \
           return wx
 
 // returns translated keycode, i.e. the one for KEYUP/KEYDOWN where 'a'..'z' is
           return wx
 
 // returns translated keycode, i.e. the one for KEYUP/KEYDOWN where 'a'..'z' is
@@ -789,6 +869,11 @@ static long GetTranslatedKeyCode(DFBInputDeviceKeyIdentifier key_id)
         KEY(DIKI_CONTROL_R,         WXK_CONTROL);
         KEY(DIKI_ALT_L,             WXK_ALT);
         KEY(DIKI_ALT_R,             WXK_ALT);
         KEY(DIKI_CONTROL_R,         WXK_CONTROL);
         KEY(DIKI_ALT_L,             WXK_ALT);
         KEY(DIKI_ALT_R,             WXK_ALT);
+        // this key was removed in 0.9.25 but include it for previous versions
+        // just to avoid gcc warnings about unhandled enum value in switch
+#if !wxCHECK_DFB_VERSION(0, 9, 24)
+        KEY(DIKI_ALTGR,             0);
+#endif
         KEY(DIKI_META_L,            0);
         KEY(DIKI_META_R,            0);
         KEY(DIKI_SUPER_L,           0);
         KEY(DIKI_META_L,            0);
         KEY(DIKI_META_R,            0);
         KEY(DIKI_SUPER_L,           0);
@@ -860,7 +945,7 @@ static long GetTranslatedKeyCode(DFBInputDeviceKeyIdentifier key_id)
 
         case DIKI_KEYDEF_END:
         case DIKI_NUMBER_OF_KEYS:
 
         case DIKI_KEYDEF_END:
         case DIKI_NUMBER_OF_KEYS:
-            wxFAIL_MSG( _T("invalid key_id value") );
+            wxFAIL_MSG( "invalid key_id value" );
             return 0;
     }
 
             return 0;
     }
 
@@ -882,13 +967,11 @@ static long GetUntraslatedKeyCode(DFBInputDeviceKeyIdentifier key_id,
                 return key_symbol;
             else
             {
                 return key_symbol;
             else
             {
-#if wxUSE_WCHAR_T
                 wchar_t chr = key_symbol;
                 wxCharBuffer buf(wxConvUI->cWC2MB(&chr, 1, NULL));
                 if ( buf )
                     return *buf; // may be 0 if failed
                 else
                 wchar_t chr = key_symbol;
                 wxCharBuffer buf(wxConvUI->cWC2MB(&chr, 1, NULL));
                 if ( buf )
                     return *buf; // may be 0 if failed
                 else
-#endif // wxUSE_WCHAR_T
                     return 0;
             }
 #endif
                     return 0;
             }
 #endif
@@ -908,8 +991,8 @@ void wxWindowDFB::HandleKeyEvent(const wxDFBWindowEvent& event_)
     const DFBWindowEvent& e = event_;
 
     wxLogTrace(TRACE_EVENTS,
     const DFBWindowEvent& e = event_;
 
     wxLogTrace(TRACE_EVENTS,
-               _T("handling key %s event for window %p ('%s')"),
-               e.type == DWET_KEYUP ? _T("up") : _T("down"),
+               "handling key %s event for window %p ('%s')",
+               e.type == DWET_KEYUP ? "up" : "down",
                this, GetName().c_str());
 
     // fill in wxKeyEvent fields:
                this, GetName().c_str());
 
     // fill in wxKeyEvent fields:
@@ -918,7 +1001,6 @@ void wxWindowDFB::HandleKeyEvent(const wxDFBWindowEvent& event_)
     event.SetTimestamp(wxDFB_EVENT_TIMESTAMP(e));
     event.m_rawCode = e.key_code;
     event.m_keyCode = GetTranslatedKeyCode(e.key_id);
     event.SetTimestamp(wxDFB_EVENT_TIMESTAMP(e));
     event.m_rawCode = e.key_code;
     event.m_keyCode = GetTranslatedKeyCode(e.key_id);
-    event.m_scanCode = 0; // not used by wx at all
 #if wxUSE_UNICODE
     event.m_uniChar = e.key_symbol;
 #endif
 #if wxUSE_UNICODE
     event.m_uniChar = e.key_symbol;
 #endif
@@ -936,7 +1018,7 @@ void wxWindowDFB::HandleKeyEvent(const wxDFBWindowEvent& event_)
     if ( e.type == DWET_KEYUP )
     {
         event.SetEventType(wxEVT_KEY_UP);
     if ( e.type == DWET_KEYUP )
     {
         event.SetEventType(wxEVT_KEY_UP);
-        GetEventHandler()->ProcessEvent(event);
+        HandleWindowEvent(event);
     }
     else
     {
     }
     else
     {
@@ -944,7 +1026,7 @@ void wxWindowDFB::HandleKeyEvent(const wxDFBWindowEvent& event_)
 
         event.SetEventType(wxEVT_KEY_DOWN);
 
 
         event.SetEventType(wxEVT_KEY_DOWN);
 
-        if ( GetEventHandler()->ProcessEvent(event) )
+        if ( HandleWindowEvent(event) )
             return;
 
         // only send wxEVT_CHAR event if not processed yet:
             return;
 
         // only send wxEVT_CHAR event if not processed yet:
@@ -952,7 +1034,7 @@ void wxWindowDFB::HandleKeyEvent(const wxDFBWindowEvent& event_)
         if ( event.m_keyCode != 0 )
         {
             event.SetEventType(wxEVT_CHAR);
         if ( event.m_keyCode != 0 )
         {
             event.SetEventType(wxEVT_CHAR);
-            if ( GetEventHandler()->ProcessEvent(event) )
+            if ( HandleWindowEvent(event) )
                 return;
         }
 
                 return;
         }
 
@@ -967,22 +1049,11 @@ void wxWindowDFB::HandleKeyEvent(const wxDFBWindowEvent& event_)
             // Ctrl-TAB changes the (parent) window, i.e. switch notebook page:
             navEvent.SetWindowChange(event.m_controlDown);
             navEvent.SetCurrentFocus(wxStaticCast(this, wxWindow));
             // Ctrl-TAB changes the (parent) window, i.e. switch notebook page:
             navEvent.SetWindowChange(event.m_controlDown);
             navEvent.SetCurrentFocus(wxStaticCast(this, wxWindow));
-            GetParent()->GetEventHandler()->ProcessEvent(navEvent);
+            GetParent()->HandleWindowEvent(navEvent);
         }
     }
 }
 
         }
     }
 }
 
-// ---------------------------------------------------------------------------
-// idle events processing
-// ---------------------------------------------------------------------------
-
-void wxWindowDFB::OnInternalIdle()
-{
-    if (wxUpdateUIEvent::CanUpdate(this))
-        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
-}
-
-
 // Find the wxWindow at the current mouse position, returning the mouse
 // position.
 wxWindow* wxFindWindowAtPointer(wxPoint& pt)
 // Find the wxWindow at the current mouse position, returning the mouse
 // position.
 wxWindow* wxFindWindowAtPointer(wxPoint& pt)
@@ -990,8 +1061,8 @@ wxWindow* wxFindWindowAtPointer(wxPoint& pt)
     return wxFindWindowAtPoint(pt = wxGetMousePosition());
 }
 
     return wxFindWindowAtPoint(pt = wxGetMousePosition());
 }
 
-wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
+wxWindow* wxFindWindowAtPoint(const wxPoint& WXUNUSED(pt))
 {
 {
-    wxFAIL_MSG( _T("wxFindWindowAtPoint not implemented") );
+    wxFAIL_MSG( "wxFindWindowAtPoint not implemented" );
     return NULL;
 }
     return NULL;
 }