]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/wincmn.cpp
Return NULL from wxWindow::GetCapture() when the capture is being lost.
[wxWidgets.git] / src / common / wincmn.cpp
index fdeecde22213c39396ba63c56681ab6372c2659d..5d50b212b29464127899fe069301f7cd4c1b1995 100644 (file)
@@ -1,10 +1,9 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        src/common/window.cpp
+// Name:        src/common/wincmn.cpp
 // Purpose:     common (to all ports) wxWindow functions
 // Author:      Julian Smart, Vadim Zeitlin
 // Modified by:
 // Created:     13/07/98
-// RCS-ID:      $Id$
 // Copyright:   (c) wxWidgets team
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 #endif
 
 #include "wx/platinfo.h"
+#include "wx/recguard.h"
 #include "wx/private/window.h"
 
-#ifdef __WXMSW__
+#ifdef __WINDOWS__
     #include "wx/msw/wrapwin.h"
 #endif
 
@@ -87,6 +87,16 @@ WXDLLIMPEXP_DATA_CORE(wxWindowList) wxTopLevelWindows;
 wxMenu *wxCurrentPopupMenu = NULL;
 #endif // wxUSE_MENUS
 
+extern WXDLLEXPORT_DATA(const char) wxPanelNameStr[] = "panel";
+
+namespace wxMouseCapture
+{
+
+// Check if the given window is in the capture stack.
+bool IsInCaptureStack(wxWindowBase* win);
+
+} // wxMouseCapture
+
 // ----------------------------------------------------------------------------
 // static data
 // ----------------------------------------------------------------------------
@@ -114,6 +124,138 @@ END_EVENT_TABLE()
 // implementation of the common functionality of the wxWindow class
 // ============================================================================
 
+// ----------------------------------------------------------------------------
+// XTI
+// ----------------------------------------------------------------------------
+
+#if wxUSE_EXTENDED_RTTI
+
+// windows that are created from a parent window during its Create method, 
+// eg. spin controls in a calendar controls must never been streamed out 
+// separately otherwise chaos occurs. Right now easiest is to test for negative ids, 
+// as windows with negative ids never can be recreated anyway
+
+
+bool wxWindowStreamingCallback( const wxObject *object, wxObjectWriter *, 
+                               wxObjectWriterCallback *, const wxStringToAnyHashMap & )
+{
+    const wxWindow * win = wx_dynamic_cast(const wxWindow*, object);
+    if ( win && win->GetId() < 0 )
+        return false;
+    return true;
+}
+
+wxIMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxWindow, wxWindowBase, "wx/window.h", \
+                                       wxWindowStreamingCallback)
+
+// make wxWindowList known before the property is used
+
+wxCOLLECTION_TYPE_INFO( wxWindow*, wxWindowList );
+
+template<> void wxCollectionToVariantArray( wxWindowList const &theList, 
+                                           wxAnyList &value)
+{
+    wxListCollectionToAnyList<wxWindowList::compatibility_iterator>( theList, value );
+}
+
+wxDEFINE_FLAGS( wxWindowStyle )
+
+wxBEGIN_FLAGS( wxWindowStyle )
+// new style border flags, we put them first to
+// use them for streaming out
+
+wxFLAGS_MEMBER(wxBORDER_SIMPLE)
+wxFLAGS_MEMBER(wxBORDER_SUNKEN)
+wxFLAGS_MEMBER(wxBORDER_DOUBLE)
+wxFLAGS_MEMBER(wxBORDER_RAISED)
+wxFLAGS_MEMBER(wxBORDER_STATIC)
+wxFLAGS_MEMBER(wxBORDER_NONE)
+
+// old style border flags
+wxFLAGS_MEMBER(wxSIMPLE_BORDER)
+wxFLAGS_MEMBER(wxSUNKEN_BORDER)
+wxFLAGS_MEMBER(wxDOUBLE_BORDER)
+wxFLAGS_MEMBER(wxRAISED_BORDER)
+wxFLAGS_MEMBER(wxSTATIC_BORDER)
+wxFLAGS_MEMBER(wxBORDER)
+
+// standard window styles
+wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
+wxFLAGS_MEMBER(wxCLIP_CHILDREN)
+wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
+wxFLAGS_MEMBER(wxWANTS_CHARS)
+wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
+wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
+wxFLAGS_MEMBER(wxVSCROLL)
+wxFLAGS_MEMBER(wxHSCROLL)
+
+wxEND_FLAGS( wxWindowStyle )
+
+wxBEGIN_PROPERTIES_TABLE(wxWindow)
+wxEVENT_PROPERTY( Close, wxEVT_CLOSE_WINDOW, wxCloseEvent)
+wxEVENT_PROPERTY( Create, wxEVT_CREATE, wxWindowCreateEvent )
+wxEVENT_PROPERTY( Destroy, wxEVT_DESTROY, wxWindowDestroyEvent )
+// Always constructor Properties first
+
+wxREADONLY_PROPERTY( Parent,wxWindow*, GetParent, wxEMPTY_PARAMETER_VALUE, \
+                    0 /*flags*/, wxT("Helpstring"), wxT("group"))
+wxPROPERTY( Id,wxWindowID, SetId, GetId, -1 /*wxID_ANY*/, 0 /*flags*/, \
+           wxT("Helpstring"), wxT("group") )
+wxPROPERTY( Position,wxPoint, SetPosition, GetPosition, wxDefaultPosition, \
+           0 /*flags*/, wxT("Helpstring"), wxT("group")) // pos
+wxPROPERTY( Size,wxSize, SetSize, GetSize, wxDefaultSize, 0 /*flags*/, \
+           wxT("Helpstring"), wxT("group")) // size
+wxPROPERTY( WindowStyle, long, SetWindowStyleFlag, GetWindowStyleFlag, \
+           wxEMPTY_PARAMETER_VALUE, 0 /*flags*/, wxT("Helpstring"), wxT("group")) // style
+wxPROPERTY( Name,wxString, SetName, GetName, wxEmptyString, 0 /*flags*/, \
+           wxT("Helpstring"), wxT("group") )
+
+// Then all relations of the object graph
+
+wxREADONLY_PROPERTY_COLLECTION( Children, wxWindowList, wxWindowBase*, \
+                               GetWindowChildren, wxPROP_OBJECT_GRAPH /*flags*/, \
+                               wxT("Helpstring"), wxT("group"))
+
+// and finally all other properties
+
+wxPROPERTY( ExtraStyle, long, SetExtraStyle, GetExtraStyle, wxEMPTY_PARAMETER_VALUE, \
+           0 /*flags*/, wxT("Helpstring"), wxT("group")) // extstyle
+wxPROPERTY( BackgroundColour, wxColour, SetBackgroundColour, GetBackgroundColour, \
+           wxEMPTY_PARAMETER_VALUE, 0 /*flags*/, wxT("Helpstring"), wxT("group")) // bg
+wxPROPERTY( ForegroundColour, wxColour, SetForegroundColour, GetForegroundColour, \
+           wxEMPTY_PARAMETER_VALUE, 0 /*flags*/, wxT("Helpstring"), wxT("group")) // fg
+wxPROPERTY( Enabled, bool, Enable, IsEnabled, wxAny((bool)true), 0 /*flags*/, \
+           wxT("Helpstring"), wxT("group"))
+wxPROPERTY( Shown, bool, Show, IsShown, wxAny((bool)true), 0 /*flags*/, \
+           wxT("Helpstring"), wxT("group"))
+
+#if 0
+// possible property candidates (not in xrc) or not valid in all subclasses
+wxPROPERTY( Title,wxString, SetTitle, GetTitle, wxEmptyString )
+wxPROPERTY( Font, wxFont, SetFont, GetWindowFont , )
+wxPROPERTY( Label,wxString, SetLabel, GetLabel, wxEmptyString )
+// MaxHeight, Width, MinHeight, Width
+// TODO switch label to control and title to toplevels
+
+wxPROPERTY( ThemeEnabled, bool, SetThemeEnabled, GetThemeEnabled, )
+//wxPROPERTY( Cursor, wxCursor, SetCursor, GetCursor, )
+// wxPROPERTY( ToolTip, wxString, SetToolTip, GetToolTipText, )
+wxPROPERTY( AutoLayout, bool, SetAutoLayout, GetAutoLayout, )
+#endif
+wxEND_PROPERTIES_TABLE()
+
+wxEMPTY_HANDLERS_TABLE(wxWindow)
+
+wxCONSTRUCTOR_DUMMY(wxWindow)
+
+#else
+
+#ifndef __WXUNIVERSAL__
+IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
+#endif
+
+#endif
+
 // ----------------------------------------------------------------------------
 // initialization
 // ----------------------------------------------------------------------------
@@ -314,7 +456,9 @@ bool wxWindowBase::ToggleWindowStyle(int flag)
 // common clean up
 wxWindowBase::~wxWindowBase()
 {
-    wxASSERT_MSG( GetCapture() != this, wxT("attempt to destroy window with mouse capture") );
+    wxASSERT_MSG( !wxMouseCapture::IsInCaptureStack(this),
+                    "Destroying window before releasing mouse capture: this "
+                    "will result in a crash later." );
 
     // FIXME if these 2 cases result from programming errors in the user code
     //       we should probably assert here instead of silently fixing them
@@ -364,8 +508,7 @@ wxWindowBase::~wxWindowBase()
         // This removes any dangling pointers to this window in other windows'
         // constraintsInvolvedIn lists.
         UnsetConstraints(m_constraints);
-        delete m_constraints;
-        m_constraints = NULL;
+        wxDELETE(m_constraints);
     }
 #endif // wxUSE_CONSTRAINTS
 
@@ -421,7 +564,14 @@ void wxWindowBase::SendDestroyEvent()
 
 bool wxWindowBase::Destroy()
 {
-    SendDestroyEvent();
+    // If our handle is invalid, it means that this window has never been
+    // created, either because creating it failed or, more typically, because
+    // this wxWindow object was default-constructed and its Create() method had
+    // never been called. As we didn't send wxWindowCreateEvent in this case
+    // (which is sent after successful creation), don't send the matching
+    // wxWindowDestroyEvent neither.
+    if ( GetHandle() )
+        SendDestroyEvent();
 
     delete this;
 
@@ -480,20 +630,13 @@ void wxWindowBase::DoCentre(int dir)
 // fits the window around the children
 void wxWindowBase::Fit()
 {
-    if ( !GetChildren().empty() )
-    {
-        SetSize(GetBestSize());
-    }
-    //else: do nothing if we have no children
+    SetSize(GetBestSize());
 }
 
 // fits virtual size (ie. scrolled area etc.) around children
 void wxWindowBase::FitInside()
 {
-    if ( GetChildren().GetCount() > 0 )
-    {
-        SetVirtualSize( GetBestVirtualSize() );
-    }
+    SetVirtualSize( GetBestVirtualSize() );
 }
 
 // On Mac, scrollbars are explicitly children.
@@ -509,7 +652,7 @@ static bool wxHasRealChildren(const wxWindowBase* win)
         wxWindow *win = node->GetData();
         if ( !win->IsTopLevel() && win->IsShown()
 #if wxUSE_SCROLLBAR
-            && !win->IsKindOf(CLASSINFO(wxScrollBar))
+            && !wxDynamicCast(win, wxScrollBar)
 #endif
             )
             realChildCount ++;
@@ -720,6 +863,16 @@ wxSize wxWindowBase::GetWindowBorderSize() const
     return size*2;
 }
 
+bool
+wxWindowBase::InformFirstDirection(int direction,
+                                   int size,
+                                   int availableOtherDir)
+{
+    return GetSizer() && GetSizer()->InformFirstDirection(direction,
+                                                          size,
+                                                          availableOtherDir);
+}
+
 wxSize wxWindowBase::GetEffectiveMinSize() const
 {
     // merge the best size with the min size, giving priority to the min size
@@ -737,17 +890,14 @@ wxSize wxWindowBase::GetEffectiveMinSize() const
 
 wxSize wxWindowBase::DoGetBorderSize() const
 {
-    // there is one case in which we can implement it for all ports easily:
-    // do it as some classes used by both wxUniv and native ports (e.g.
-    // wxGenericStaticText) do override DoGetBestClientSize() and so this
-    // method must work for them and that ensures that it does, at least in
-    // the default case)
+    // there is one case in which we can implement it for all ports easily
     if ( GetBorder() == wxBORDER_NONE )
         return wxSize(0, 0);
 
-    wxFAIL_MSG( "must be overridden if called" );
-
-    return wxDefaultSize;
+    // otherwise use the difference between the real size and the client size
+    // as a fallback: notice that this is incorrect in general as client size
+    // also doesn't take the scrollbars into account
+    return GetSize() - GetClientSize();
 }
 
 wxSize wxWindowBase::GetBestSize() const
@@ -759,26 +909,53 @@ wxSize wxWindowBase::GetBestSize() const
     // it to be used
     wxSize size = DoGetBestClientSize();
     if ( size != wxDefaultSize )
-    {
         size += DoGetBorderSize();
+    else
+        size = DoGetBestSize();
 
-        CacheBestSize(size);
-        return size;
-    }
+    // Ensure that the best size is at least as large as min size.
+    size.IncTo(GetMinSize());
 
-    return DoGetBestSize();
+    // And not larger than max size.
+    size.DecToIfSpecified(GetMaxSize());
+
+    // Finally cache result and return.
+    CacheBestSize(size);
+    return size;
+}
+
+int wxWindowBase::GetBestHeight(int width) const
+{
+    const int height = DoGetBestClientHeight(width);
+
+    return height == wxDefaultCoord
+            ? GetBestSize().y
+            : height + DoGetBorderSize().y;
+}
+
+int wxWindowBase::GetBestWidth(int height) const
+{
+    const int width = DoGetBestClientWidth(height);
+
+    return width == wxDefaultCoord
+            ? GetBestSize().x
+            : width + DoGetBorderSize().x;
 }
 
 void wxWindowBase::SetMinSize(const wxSize& minSize)
 {
     m_minWidth = minSize.x;
     m_minHeight = minSize.y;
+
+    InvalidateBestSize();
 }
 
 void wxWindowBase::SetMaxSize(const wxSize& maxSize)
 {
     m_maxWidth = maxSize.x;
     m_maxHeight = maxSize.y;
+
+    InvalidateBestSize();
 }
 
 void wxWindowBase::SetInitialSize(const wxSize& size)
@@ -840,18 +1017,15 @@ void wxWindowBase::DoSetWindowVariant( wxWindowVariant variant )
             break;
 
         case wxWINDOW_VARIANT_SMALL:
-            size *= 3;
-            size /= 4;
+            size = wxRound(size * 3.0 / 4.0);
             break;
 
         case wxWINDOW_VARIANT_MINI:
-            size *= 2;
-            size /= 3;
+            size = wxRound(size * 2.0 / 3.0);
             break;
 
         case wxWINDOW_VARIANT_LARGE:
-            size *= 5;
-            size /= 4;
+            size = wxRound(size * 5.0 / 4.0);
             break;
 
         default:
@@ -927,7 +1101,7 @@ void wxWindowBase::SendSizeEvent(int flags)
     wxSizeEvent event(GetSize(), GetId());
     event.SetEventObject(this);
     if ( flags & wxSEND_EVENT_POST )
-        wxPostEvent(this, event);
+        wxPostEvent(GetEventHandler(), event);
     else
         HandleWindowEvent(event);
 }
@@ -978,18 +1152,29 @@ bool wxWindowBase::IsEnabled() const
 
 void wxWindowBase::NotifyWindowOnEnableChange(bool enabled)
 {
+    // Under some platforms there is no need to update the window state
+    // explicitly, it will become disabled when its parent is. On other ones we
+    // do need to disable all windows recursively though.
 #ifndef wxHAS_NATIVE_ENABLED_MANAGEMENT
     DoEnable(enabled);
 #endif // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
 
-    OnEnabled(enabled);
-
-    // If we are top-level then the logic doesn't apply - otherwise
-    // showing a modal dialog would result in total greying out (and ungreying
-    // out later) of everything which would be really ugly
-    if ( IsTopLevel() )
+    // Disabling a top level window is typically done when showing a modal
+    // dialog and we don't need to disable its children in this case, they will
+    // be logically disabled anyhow (i.e. their IsEnabled() will return false)
+    // and the TLW won't accept any input for them. Moreover, explicitly
+    // disabling them would look ugly as the entire TLW would be greyed out
+    // whenever a modal dialog is shown and no native applications under any
+    // platform behave like this.
+    if ( IsTopLevel() && !enabled )
         return;
 
+    // When disabling (or enabling back) a non-TLW window we need to
+    // recursively propagate the change of the state to its children, otherwise
+    // they would still show as enabled even though they wouldn't actually
+    // accept any input (at least under MSW where children don't accept input
+    // if any of the windows in their parent chain is enabled).
+#ifndef wxHAS_NATIVE_ENABLED_MANAGEMENT
     for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
           node;
           node = node->GetNext() )
@@ -998,6 +1183,7 @@ void wxWindowBase::NotifyWindowOnEnableChange(bool enabled)
         if ( !child->IsTopLevel() && child->IsThisEnabled() )
             child->NotifyWindowOnEnableChange(enabled);
     }
+#endif // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
 }
 
 bool wxWindowBase::Enable(bool enable)
@@ -1007,14 +1193,10 @@ bool wxWindowBase::Enable(bool enable)
 
     m_isEnabled = enable;
 
+    // If we call DoEnable() from NotifyWindowOnEnableChange(), we don't need
+    // to do it from here.
 #ifdef wxHAS_NATIVE_ENABLED_MANAGEMENT
     DoEnable(enable);
-#else // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
-    wxWindowBase * const parent = GetParent();
-    if( !IsTopLevel() && parent && !parent->IsEnabled() )
-    {
-        return true;
-    }
 #endif // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
 
     NotifyWindowOnEnableChange(enable);
@@ -1087,9 +1269,27 @@ void wxWindowBase::Thaw()
 }
 
 // ----------------------------------------------------------------------------
-// reparenting the window
+// Dealing with parents and children.
 // ----------------------------------------------------------------------------
 
+bool wxWindowBase::IsDescendant(wxWindowBase* win) const
+{
+    // Iterate until we find this window in the parent chain or exhaust it.
+    while ( win )
+    {
+        if ( win == this )
+            return true;
+
+        // Stop iterating on reaching the top level window boundary.
+        if ( win->IsTopLevel() )
+            break;
+
+        win = win->GetParent();
+    }
+
+    return false;
+}
+
 void wxWindowBase::AddChild(wxWindowBase *child)
 {
     wxCHECK_RET( child, wxT("can't add a NULL child") );
@@ -1124,6 +1324,20 @@ void wxWindowBase::RemoveChild(wxWindowBase *child)
     child->SetParent(NULL);
 }
 
+void wxWindowBase::SetParent(wxWindowBase *parent)
+{
+    // This assert catches typos which may result in using "this" instead of
+    // "parent" when creating the window. This doesn't happen often but when it
+    // does the results are unpleasant because the program typically just
+    // crashes when due to a stack overflow or something similar and this
+    // assert doesn't cost much (OTOH doing a more general check that the
+    // parent is not one of our children would be more expensive and probably
+    // not worth it).
+    wxASSERT_MSG( parent != this, wxS("Can't use window as its own parent") );
+
+    m_parent = (wxWindow *)parent;
+}
+
 bool wxWindowBase::Reparent(wxWindowBase *newParent)
 {
     wxWindow *oldParent = GetParent();
@@ -1247,15 +1461,18 @@ wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
         "the first handler of the wxWindow stack should have non-NULL next handler" );
 
     firstHandler->SetNextHandler(NULL);
-    secondHandler->SetPreviousHandler(NULL);
+
+    // It is harmless but useless to unset the previous handler of the window
+    // itself as it's always NULL anyhow, so don't do this.
+    if ( secondHandler != this )
+        secondHandler->SetPreviousHandler(NULL);
 
     // now firstHandler is completely unlinked; set secondHandler as the new window event handler
     SetEventHandler(secondHandler);
 
     if ( deleteHandler )
     {
-        delete firstHandler;
-        firstHandler = NULL;
+        wxDELETE(firstHandler);
     }
 
     return firstHandler;
@@ -1374,7 +1591,7 @@ wxColour wxWindowBase::GetBackgroundColour() const
         // wxWidgets versions where GetBackgroundColour() always returned
         // something -- so give them something even if it doesn't make sense
         // for this window (e.g. it has a themed background)
-        if ( !colBg.Ok() )
+        if ( !colBg.IsOk() )
             colBg = GetClassDefaultAttributes().colBg;
 
         return colBg;
@@ -1386,7 +1603,7 @@ wxColour wxWindowBase::GetBackgroundColour() const
 wxColour wxWindowBase::GetForegroundColour() const
 {
     // logic is the same as above
-    if ( !m_hasFgCol && !m_foregroundColour.Ok() )
+    if ( !m_hasFgCol && !m_foregroundColour.IsOk() )
     {
         wxColour colFg = GetDefaultAttributes().colFg;
 
@@ -1399,6 +1616,39 @@ wxColour wxWindowBase::GetForegroundColour() const
         return m_foregroundColour;
 }
 
+bool wxWindowBase::SetBackgroundStyle(wxBackgroundStyle style)
+{
+    // The checks below shouldn't be triggered if we're not really changing the
+    // style.
+    if ( style == m_backgroundStyle )
+        return true;
+
+    // Transparent background style can be only set before creation because of
+    // wxGTK limitation.
+    wxCHECK_MSG( (style != wxBG_STYLE_TRANSPARENT) || !GetHandle(),
+                 false,
+                 "wxBG_STYLE_TRANSPARENT style can only be set before "
+                 "Create()-ing the window." );
+
+    // And once it is set, wxBG_STYLE_TRANSPARENT can't be unset.
+    wxCHECK_MSG( (m_backgroundStyle != wxBG_STYLE_TRANSPARENT) ||
+                 (style == wxBG_STYLE_TRANSPARENT),
+                 false,
+                 "wxBG_STYLE_TRANSPARENT can't be unset once it was set." );
+
+    m_backgroundStyle = style;
+
+    return true;
+}
+
+bool wxWindowBase::IsTransparentBackgroundSupported(wxString *reason) const
+{
+    if ( reason )
+        *reason = _("This platform does not support background transparency.");
+
+    return false;
+}
+
 bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
 {
     if ( colour == m_backgroundColour )
@@ -1408,7 +1658,7 @@ bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
 
     m_inheritBgCol = m_hasBgCol;
     m_backgroundColour = colour;
-    SetThemeEnabled( !m_hasBgCol && !m_foregroundColour.Ok() );
+    SetThemeEnabled( !m_hasBgCol && !m_foregroundColour.IsOk() );
     return true;
 }
 
@@ -1420,7 +1670,7 @@ bool wxWindowBase::SetForegroundColour( const wxColour &colour )
     m_hasFgCol = colour.IsOk();
     m_inheritFgCol = m_hasFgCol;
     m_foregroundColour = colour;
-    SetThemeEnabled( !m_hasFgCol && !m_backgroundColour.Ok() );
+    SetThemeEnabled( !m_hasFgCol && !m_backgroundColour.IsOk() );
     return true;
 }
 
@@ -1729,6 +1979,7 @@ wxWindowBase::FindWindowById( long id, const wxWindow* parent )
 // dialog oriented functions
 // ----------------------------------------------------------------------------
 
+#if WXWIN_COMPATIBILITY_2_8
 void wxWindowBase::MakeModal(bool modal)
 {
     // Disable all other windows
@@ -1745,96 +1996,170 @@ void wxWindowBase::MakeModal(bool modal)
         }
     }
 }
+#endif // WXWIN_COMPATIBILITY_2_8
+
+#if wxUSE_VALIDATORS
+
+namespace
+{
+
+// This class encapsulates possibly recursive iteration on window children done
+// by Validate() and TransferData{To,From}Window() and allows to avoid code
+// duplication in all three functions.
+class ValidationTraverserBase
+{
+public:
+    wxEXPLICIT ValidationTraverserBase(wxWindowBase* win)
+        : m_win(static_cast<wxWindow*>(win))
+    {
+    }
+
+    // Traverse all the direct children calling OnDo() on them and also all
+    // grandchildren if wxWS_EX_VALIDATE_RECURSIVELY is used, calling
+    // OnRecurse() for them.
+    bool DoForAllChildren()
+    {
+        const bool recurse = m_win->HasExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
+
+        wxWindowList& children = m_win->GetChildren();
+        for ( wxWindowList::iterator i = children.begin();
+              i != children.end();
+              ++i )
+        {
+            wxWindow* const child = static_cast<wxWindow*>(*i);
+            wxValidator* const validator = child->GetValidator();
+            if ( validator && !OnDo(validator) )
+            {
+                return false;
+            }
+
+            // Notice that validation should never recurse into top level
+            // children, e.g. some other dialog which might happen to be
+            // currently shown.
+            if ( recurse && !child->IsTopLevel() && !OnRecurse(child) )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    // Give it a virtual dtor just to suppress gcc warnings about a class with
+    // virtual methods but non-virtual dtor -- even if this is completely safe
+    // here as we never use the objects of this class polymorphically.
+    virtual ~ValidationTraverserBase() { }
+
+protected:
+    // Called for each child, validator is guaranteed to be non-NULL.
+    virtual bool OnDo(wxValidator* validator) = 0;
+
+    // Called for each child if we need to recurse into its children.
+    virtual bool OnRecurse(wxWindow* child) = 0;
+
+
+    // The window whose children we're traversing.
+    wxWindow* const m_win;
+
+    wxDECLARE_NO_COPY_CLASS(ValidationTraverserBase);
+};
+
+} // anonymous namespace
+
+#endif // wxUSE_VALIDATORS
 
 bool wxWindowBase::Validate()
 {
 #if wxUSE_VALIDATORS
-    bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
-
-    wxWindowList::compatibility_iterator node;
-    for ( node = m_children.GetFirst(); node; node = node->GetNext() )
+    class ValidateTraverser : public ValidationTraverserBase
     {
-        wxWindowBase *child = node->GetData();
-        wxValidator *validator = child->GetValidator();
-        if ( validator && !validator->Validate((wxWindow *)this) )
+    public:
+        wxEXPLICIT ValidateTraverser(wxWindowBase* win)
+            : ValidationTraverserBase(win)
         {
-            return false;
         }
 
-        if ( recurse && !child->Validate() )
+        virtual bool OnDo(wxValidator* validator)
         {
-            return false;
+            return validator->Validate(m_win);
         }
-    }
-#endif // wxUSE_VALIDATORS
 
+        virtual bool OnRecurse(wxWindow* child)
+        {
+            return child->Validate();
+        }
+    };
+
+    return ValidateTraverser(this).DoForAllChildren();
+#else // !wxUSE_VALIDATORS
     return true;
+#endif // wxUSE_VALIDATORS/!wxUSE_VALIDATORS
 }
 
 bool wxWindowBase::TransferDataToWindow()
 {
 #if wxUSE_VALIDATORS
-    bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
-
-    wxWindowList::compatibility_iterator node;
-    for ( node = m_children.GetFirst(); node; node = node->GetNext() )
+    class DataToWindowTraverser : public ValidationTraverserBase
     {
-        wxWindowBase *child = node->GetData();
-        wxValidator *validator = child->GetValidator();
-        if ( validator && !validator->TransferToWindow() )
+    public:
+        wxEXPLICIT DataToWindowTraverser(wxWindowBase* win)
+            : ValidationTraverserBase(win)
         {
-            wxLogWarning(_("Could not transfer data to window"));
-#if wxUSE_LOG
-            wxLog::FlushActive();
-#endif // wxUSE_LOG
-
-            return false;
         }
 
-        if ( recurse )
+        virtual bool OnDo(wxValidator* validator)
         {
-            if ( !child->TransferDataToWindow() )
+            if ( !validator->TransferToWindow() )
             {
-                // warning already given
+                wxLogWarning(_("Could not transfer data to window"));
+#if wxUSE_LOG
+                wxLog::FlushActive();
+#endif // wxUSE_LOG
+
                 return false;
             }
+
+            return true;
         }
-    }
-#endif // wxUSE_VALIDATORS
 
+        virtual bool OnRecurse(wxWindow* child)
+        {
+            return child->TransferDataToWindow();
+        }
+    };
+
+    return DataToWindowTraverser(this).DoForAllChildren();
+#else // !wxUSE_VALIDATORS
     return true;
+#endif // wxUSE_VALIDATORS/!wxUSE_VALIDATORS
 }
 
 bool wxWindowBase::TransferDataFromWindow()
 {
 #if wxUSE_VALIDATORS
-    bool recurse = (GetExtraStyle() & wxWS_EX_VALIDATE_RECURSIVELY) != 0;
-
-    wxWindowList::compatibility_iterator node;
-    for ( node = m_children.GetFirst(); node; node = node->GetNext() )
+    class DataFromWindowTraverser : public ValidationTraverserBase
     {
-        wxWindow *child = node->GetData();
-        wxValidator *validator = child->GetValidator();
-        if ( validator && !validator->TransferFromWindow() )
+    public:
+        DataFromWindowTraverser(wxWindowBase* win)
+            : ValidationTraverserBase(win)
         {
-            // nop warning here because the application is supposed to give
-            // one itself - we don't know here what might have gone wrongly
+        }
 
-            return false;
+        virtual bool OnDo(wxValidator* validator)
+        {
+            return validator->TransferFromWindow();
         }
 
-        if ( recurse )
+        virtual bool OnRecurse(wxWindow* child)
         {
-            if ( !child->TransferDataFromWindow() )
-            {
-                // warning already given
-                return false;
-            }
+            return child->TransferDataFromWindow();
         }
-    }
-#endif // wxUSE_VALIDATORS
+    };
 
+    return DataFromWindowTraverser(this).DoForAllChildren();
+#else // !wxUSE_VALIDATORS
     return true;
+#endif // wxUSE_VALIDATORS/!wxUSE_VALIDATORS
 }
 
 void wxWindowBase::InitDialog()
@@ -1967,6 +2292,13 @@ void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
     }
 }
 
+bool wxWindowBase::CopyToolTip(wxToolTip *tip)
+{
+    SetToolTip(tip ? new wxToolTip(tip->GetTip()) : NULL);
+
+    return tip != NULL;
+}
+
 #endif // wxUSE_TOOLTIPS
 
 // ----------------------------------------------------------------------------
@@ -2011,7 +2343,7 @@ void wxWindowBase::UnsetConstraints(wxLayoutConstraints *c)
 {
     if ( c )
     {
-        if ( c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
+        if ( c->left.GetOtherWindow() && (c->left.GetOtherWindow() != this) )
             c->left.GetOtherWindow()->RemoveConstraintReference(this);
         if ( c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
             c->top.GetOtherWindow()->RemoveConstraintReference(this);
@@ -2076,8 +2408,7 @@ void wxWindowBase::DeleteRelatedConstraints()
             node = next;
         }
 
-        delete m_constraintsInvolvedIn;
-        m_constraintsInvolvedIn = NULL;
+        wxDELETE(m_constraintsInvolvedIn);
     }
 }
 
@@ -2289,6 +2620,8 @@ void wxWindowBase::SetConstraintSizes(bool recurse)
     wxLayoutConstraints *constr = GetConstraints();
     if ( constr && constr->AreSatisfied() )
     {
+        ChildrenRepositioningGuard repositionGuard(this);
+
         int x = constr->left.GetValue();
         int y = constr->top.GetValue();
         int w = constr->width.GetValue();
@@ -2297,7 +2630,9 @@ void wxWindowBase::SetConstraintSizes(bool recurse)
         if ( (constr->width.GetRelationship() != wxAsIs ) ||
              (constr->height.GetRelationship() != wxAsIs) )
         {
-            SetSize(x, y, w, h);
+            // We really shouldn't set negative sizes for the windows so make
+            // them at least of 1*1 size
+            SetSize(x, y, w > 0 ? w : 1, h > 0 ? h : 1);
         }
         else
         {
@@ -2412,17 +2747,12 @@ void wxWindowBase::GetPositionConstraint(int *x, int *y) const
 
 void wxWindowBase::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) const
 {
-    // don't do it for the dialogs/frames - they float independently of their
-    // parent
-    if ( !IsTopLevel() )
+    wxWindow *parent = GetParent();
+    if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
     {
-        wxWindow *parent = GetParent();
-        if ( !(sizeFlags & wxSIZE_NO_ADJUSTMENTS) && parent )
-        {
-            wxPoint pt(parent->GetClientAreaOrigin());
-            x += pt.x;
-            y += pt.y;
-        }
+        wxPoint pt(parent->GetClientAreaOrigin());
+        x += pt.x;
+        y += pt.y;
     }
 }
 
@@ -2462,6 +2792,44 @@ void wxWindowBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
         Show(event.GetShown());
 }
 
+// ----------------------------------------------------------------------------
+// Idle processing
+// ----------------------------------------------------------------------------
+
+// Send idle event to window and all subwindows
+bool wxWindowBase::SendIdleEvents(wxIdleEvent& event)
+{
+    bool needMore = false;
+
+    OnInternalIdle();
+
+    // should we send idle event to this window?
+    if (wxIdleEvent::GetMode() == wxIDLE_PROCESS_ALL ||
+        HasExtraStyle(wxWS_EX_PROCESS_IDLE))
+    {
+        event.SetEventObject(this);
+        HandleWindowEvent(event);
+
+        if (event.MoreRequested())
+            needMore = true;
+    }
+    wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+    for (; node; node = node->GetNext())
+    {
+        wxWindow* child = node->GetData();
+        if (child->SendIdleEvents(event))
+            needMore = true;
+    }
+
+    return needMore;
+}
+
+void wxWindowBase::OnInternalIdle()
+{
+    if ( wxUpdateUIEvent::CanUpdate(this) )
+        UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
+}
+
 // ----------------------------------------------------------------------------
 // dialog units translations
 // ----------------------------------------------------------------------------
@@ -2475,7 +2843,9 @@ void wxWindowBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
 // using them.
 wxSize wxWindowBase::GetDlgUnitBase() const
 {
-    const wxWindow *parent = wxGetTopLevelParent((wxWindow*)this);
+    const wxWindowBase * const parent = wxGetTopLevelParent((wxWindow*)this);
+
+    wxCHECK_MSG( parent, wxDefaultSize, wxS("Must have TLW parent") );
 
     if ( !parent->m_font.IsOk() )
     {
@@ -2567,6 +2937,9 @@ bool wxWindowBase::PopupMenu(wxMenu *menu, int x, int y)
 {
     wxCHECK_MSG( menu, false, "can't popup NULL menu" );
 
+    wxMenuInvokingWindowSetter
+        setInvokingWin(*menu, static_cast<wxWindow *>(this));
+
     wxCurrentPopupMenu = menu;
     const bool rc = DoPopupMenu(menu, x, y);
     wxCurrentPopupMenu = NULL;
@@ -2597,7 +2970,7 @@ wxWindowBase::DoGetPopupMenuSelectionFromUser(wxMenu& menu, int x, int y)
 {
     gs_popupMenuSelection = wxID_NONE;
 
-    Connect(wxEVT_COMMAND_MENU_SELECTED,
+    Connect(wxEVT_MENU,
             wxCommandEventHandler(wxWindowBase::InternalOnPopupMenu),
             NULL,
             this);
@@ -2620,7 +2993,7 @@ wxWindowBase::DoGetPopupMenuSelectionFromUser(wxMenu& menu, int x, int y)
                wxUpdateUIEventHandler(wxWindowBase::InternalOnPopupMenuUpdate),
                NULL,
                this);
-    Disconnect(wxEVT_COMMAND_MENU_SELECTED,
+    Disconnect(wxEVT_MENU,
                wxCommandEventHandler(wxWindowBase::InternalOnPopupMenu),
                NULL,
                this);
@@ -2732,8 +3105,10 @@ void wxWindowBase::OnMiddleClick( wxMouseEvent& event )
         else
 #endif // __WXDEBUG__
         {
+#if wxUSE_MSGDLG
             // just Ctrl-Alt-middle click shows information about wx version
             ::wxInfoMessageBox((wxWindow*)this);
+#endif // wxUSE_MSGDLG
         }
     }
     else
@@ -2776,19 +3151,19 @@ wxAccessible* wxWindowBase::CreateAccessible()
 // list classes implementation
 // ----------------------------------------------------------------------------
 
-#if wxUSE_STL
+#if wxUSE_STD_CONTAINERS
 
 #include "wx/listimpl.cpp"
 WX_DEFINE_LIST(wxWindowList)
 
-#else // !wxUSE_STL
+#else // !wxUSE_STD_CONTAINERS
 
 void wxWindowListNode::DeleteData()
 {
     delete (wxWindow *)GetData();
 }
 
-#endif // wxUSE_STL/!wxUSE_STL
+#endif // wxUSE_STD_CONTAINERS/!wxUSE_STD_CONTAINERS
 
 // ----------------------------------------------------------------------------
 // borders
@@ -2838,72 +3213,106 @@ wxHitTest wxWindowBase::DoHitTest(wxCoord x, wxCoord y) const
 // mouse capture
 // ----------------------------------------------------------------------------
 
-struct WXDLLEXPORT wxWindowNext
+// Private data used for mouse capture tracking.
+namespace wxMouseCapture
+{
+
+// Stack of the windows which previously had the capture, the top most element
+// is the window that has the mouse capture now.
+//
+// NB: We use wxVector and not wxStack to be able to examine all of the stack
+//     elements for debug checks, but only the stack operations should be
+//     performed with this vector.
+wxVector<wxWindow*> stack;
+
+// Flag preventing reentrancy in {Capture,Release}Mouse().
+wxRecursionGuardFlag changing;
+
+bool IsInCaptureStack(wxWindowBase* win)
 {
-    wxWindow *win;
-    wxWindowNext *next;
-} *wxWindowBase::ms_winCaptureNext = NULL;
-wxWindow *wxWindowBase::ms_winCaptureCurrent = NULL;
-bool wxWindowBase::ms_winCaptureChanging = false;
+    for ( wxVector<wxWindow*>::const_iterator it = stack.begin();
+          it != stack.end();
+          ++it )
+    {
+        if ( *it == win )
+            return true;
+    }
+
+    return false;
+}
+
+} // wxMouseCapture
 
 void wxWindowBase::CaptureMouse()
 {
     wxLogTrace(wxT("mousecapture"), wxT("CaptureMouse(%p)"), static_cast<void*>(this));
 
-    wxASSERT_MSG( !ms_winCaptureChanging, wxT("recursive CaptureMouse call?") );
+    wxRecursionGuard guard(wxMouseCapture::changing);
+    wxASSERT_MSG( !guard.IsInside(), wxT("recursive CaptureMouse call?") );
 
-    ms_winCaptureChanging = true;
+    wxASSERT_MSG( !wxMouseCapture::IsInCaptureStack(this),
+                    "Recapturing the mouse in the same window?" );
 
     wxWindow *winOld = GetCapture();
     if ( winOld )
-    {
         ((wxWindowBase*) winOld)->DoReleaseMouse();
 
-        // save it on stack
-        wxWindowNext *item = new wxWindowNext;
-        item->win = winOld;
-        item->next = ms_winCaptureNext;
-        ms_winCaptureNext = item;
-    }
-    //else: no mouse capture to save
-
     DoCaptureMouse();
-    ms_winCaptureCurrent = (wxWindow*)this;
 
-    ms_winCaptureChanging = false;
+    wxMouseCapture::stack.push_back(static_cast<wxWindow*>(this));
 }
 
 void wxWindowBase::ReleaseMouse()
 {
     wxLogTrace(wxT("mousecapture"), wxT("ReleaseMouse(%p)"), static_cast<void*>(this));
 
-    wxASSERT_MSG( !ms_winCaptureChanging, wxT("recursive ReleaseMouse call?") );
+    wxRecursionGuard guard(wxMouseCapture::changing);
+    wxASSERT_MSG( !guard.IsInside(), wxT("recursive ReleaseMouse call?") );
 
-    wxASSERT_MSG( GetCapture() == this,
-                  "attempt to release mouse, but this window hasn't captured it" );
-    wxASSERT_MSG( ms_winCaptureCurrent == this,
-                  "attempt to release mouse, but this window hasn't captured it" );
-
-    ms_winCaptureChanging = true;
+#if wxDEBUG_LEVEL
+    wxWindow* const winCapture = GetCapture();
+    if ( !winCapture )
+    {
+        wxFAIL_MSG
+        (
+          wxString::Format
+          (
+            "Releasing mouse in %p(%s) but it is not captured",
+            this, GetClassInfo()->GetClassName()
+          )
+        );
+    }
+    else if ( winCapture != this )
+    {
+        wxFAIL_MSG
+        (
+          wxString::Format
+          (
+            "Releasing mouse in %p(%s) but it is captured by %p(%s)",
+            this, GetClassInfo()->GetClassName(),
+            winCapture, winCapture->GetClassInfo()->GetClassName()
+          )
+        );
+    }
+#endif // wxDEBUG_LEVEL
 
     DoReleaseMouse();
-    ms_winCaptureCurrent = NULL;
 
-    if ( ms_winCaptureNext )
-    {
-        ((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse();
-        ms_winCaptureCurrent = ms_winCaptureNext->win;
+    wxCHECK_RET( !wxMouseCapture::stack.empty(),
+                    "Releasing mouse capture but capture stack empty?" );
+    wxCHECK_RET( wxMouseCapture::stack.back() == this,
+                    "Window releasing mouse capture not top of capture stack?" );
 
-        wxWindowNext *item = ms_winCaptureNext;
-        ms_winCaptureNext = item->next;
-        delete item;
-    }
-    //else: stack is empty, no previous capture
+    wxMouseCapture::stack.pop_back();
 
-    ms_winCaptureChanging = false;
+    // Restore the capture to the previous window, if any.
+    if ( !wxMouseCapture::stack.empty() )
+    {
+        ((wxWindowBase*)wxMouseCapture::stack.back())->DoCaptureMouse();
+    }
 
     wxLogTrace(wxT("mousecapture"),
-        (const wxChar *) wxT("After ReleaseMouse() mouse is captured by %p"),
+        wxT("After ReleaseMouse() mouse is captured by %p"),
         static_cast<void*>(GetCapture()));
 }
 
@@ -2926,26 +3335,17 @@ void wxWindowBase::NotifyCaptureLost()
 {
     // don't do anything if capture lost was expected, i.e. resulted from
     // a wx call to ReleaseMouse or CaptureMouse:
-    if ( ms_winCaptureChanging )
+    wxRecursionGuard guard(wxMouseCapture::changing);
+    if ( guard.IsInside() )
         return;
 
     // if the capture was lost unexpectedly, notify every window that has
     // capture (on stack or current) about it and clear the stack:
-
-    if ( ms_winCaptureCurrent )
+    while ( !wxMouseCapture::stack.empty() )
     {
-        DoNotifyWindowAboutCaptureLost(ms_winCaptureCurrent);
-        ms_winCaptureCurrent = NULL;
-    }
+        DoNotifyWindowAboutCaptureLost(wxMouseCapture::stack.back());
 
-    while ( ms_winCaptureNext )
-    {
-        wxWindowNext *item = ms_winCaptureNext;
-        ms_winCaptureNext = item->next;
-
-        DoNotifyWindowAboutCaptureLost(item->win);
-
-        delete item;
+        wxMouseCapture::stack.pop_back();
     }
 }
 
@@ -2980,7 +3380,7 @@ bool wxWindowBase::TryBefore(wxEvent& event)
     if ( event.GetEventObject() == this )
     {
         wxValidator * const validator = GetValidator();
-        if ( validator && validator->ProcessEventHere(event) )
+        if ( validator && validator->ProcessEventLocally(event) )
         {
             return true;
         }
@@ -3005,7 +3405,7 @@ bool wxWindowBase::TryAfter(wxEvent& event)
             wxWindow *parent = GetParent();
             if ( parent && !parent->IsBeingDeleted() )
             {
-                wxPropagateOnce propagateOnce(event);
+                wxPropagateOnce propagateOnce(event, this);
 
                 return parent->GetEventHandler()->ProcessEvent(event);
             }
@@ -3092,8 +3492,8 @@ void wxWindowBase::DoMoveInTabOrder(wxWindow *win, WindowOrder move)
     wxWindowList::compatibility_iterator i = siblings.Find(win);
     wxCHECK_RET( i, wxT("MoveBefore/AfterInTabOrder(): win is not a sibling") );
 
-    // unfortunately, when wxUSE_STL == 1 DetachNode() is not implemented so we
-    // can't just move the node around
+    // unfortunately, when wxUSE_STD_CONTAINERS == 1 DetachNode() is not
+    // implemented so we can't just move the node around
     wxWindow *self = (wxWindow *)this;
     siblings.DeleteObject(self);
     if ( move == OrderAfter )
@@ -3123,9 +3523,9 @@ void wxWindowBase::DoMoveInTabOrder(wxWindow *win, WindowOrder move)
 
 bool wxWindowBase::HasFocus() const
 {
-    wxWindowBase *win = DoFindFocus();
-    return win == this ||
-           win == wxConstCast(this, wxWindowBase)->GetMainWindowOfCompositeControl();
+    wxWindowBase* const win = DoFindFocus();
+    return win &&
+            (this == win || this == win->GetMainWindowOfCompositeControl());
 }
 
 // ----------------------------------------------------------------------------
@@ -3235,7 +3635,7 @@ wxAccStatus wxWindowAccessible::GetLocation(wxRect& rect, int elementId)
     if (win)
     {
         rect = win->GetRect();
-        if (win->GetParent() && !win->IsKindOf(CLASSINFO(wxTopLevelWindow)))
+        if (win->GetParent() && !wxDynamicCast(win, wxTopLevelWindow))
             rect.SetPosition(win->GetParent()->ClientToScreen(rect.GetPosition()));
         return wxACC_OK;
     }
@@ -3354,7 +3754,7 @@ wxAccStatus wxWindowAccessible::GetName(int childId, wxString* name)
     // accessible classes, one for each kind of wxWidgets
     // control or window.
 #if wxUSE_BUTTON
-    if (GetWindow()->IsKindOf(CLASSINFO(wxButton)))
+    if (wxDynamicCast(GetWindow(), wxButton))
         title = ((wxButton*) GetWindow())->GetLabel();
     else
 #endif
@@ -3513,14 +3913,14 @@ wxAccStatus wxWindowAccessible::GetRole(int childId, wxAccRole* role)
     if (childId > 0)
         return wxACC_NOT_IMPLEMENTED;
 
-    if (GetWindow()->IsKindOf(CLASSINFO(wxControl)))
+    if (wxDynamicCast(GetWindow(), wxControl))
         return wxACC_NOT_IMPLEMENTED;
 #if wxUSE_STATUSBAR
-    if (GetWindow()->IsKindOf(CLASSINFO(wxStatusBar)))
+    if (wxDynamicCast(GetWindow(), wxStatusBar))
         return wxACC_NOT_IMPLEMENTED;
 #endif
 #if wxUSE_TOOLBAR
-    if (GetWindow()->IsKindOf(CLASSINFO(wxToolBar)))
+    if (wxDynamicCast(GetWindow(), wxToolBar))
         return wxACC_NOT_IMPLEMENTED;
 #endif
 
@@ -3545,15 +3945,15 @@ wxAccStatus wxWindowAccessible::GetState(int childId, long* state)
     if (childId > 0)
         return wxACC_NOT_IMPLEMENTED;
 
-    if (GetWindow()->IsKindOf(CLASSINFO(wxControl)))
+    if (wxDynamicCast(GetWindow(), wxControl))
         return wxACC_NOT_IMPLEMENTED;
 
 #if wxUSE_STATUSBAR
-    if (GetWindow()->IsKindOf(CLASSINFO(wxStatusBar)))
+    if (wxDynamicCast(GetWindow(), wxStatusBar))
         return wxACC_NOT_IMPLEMENTED;
 #endif
 #if wxUSE_TOOLBAR
-    if (GetWindow()->IsKindOf(CLASSINFO(wxToolBar)))
+    if (wxDynamicCast(GetWindow(), wxToolBar))
         return wxACC_NOT_IMPLEMENTED;
 #endif