]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/wincmn.cpp
The check column needs more space
[wxWidgets.git] / src / common / wincmn.cpp
index d109b28adf13a61b74d05b08cc87cbbb50970381..5b3fb6b85307a644533eb1886a140a83c8af6fe5 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
-// Name:        common/window.cpp
+// Name:        src/common/window.cpp
 // Purpose:     common (to all ports) wxWindow functions
 // Author:      Julian Smart, Vadim Zeitlin
 // Modified by:
 // Purpose:     common (to all ports) wxWindow functions
 // Author:      Julian Smart, Vadim Zeitlin
 // Modified by:
 // headers
 // ----------------------------------------------------------------------------
 
 // headers
 // ----------------------------------------------------------------------------
 
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-    #pragma implementation "windowbase.h"
-#endif
-
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
@@ -33,7 +29,6 @@
     #include "wx/log.h"
     #include "wx/intl.h"
     #include "wx/frame.h"
     #include "wx/log.h"
     #include "wx/intl.h"
     #include "wx/frame.h"
-    #include "wx/defs.h"
     #include "wx/window.h"
     #include "wx/control.h"
     #include "wx/checkbox.h"
     #include "wx/window.h"
     #include "wx/control.h"
     #include "wx/checkbox.h"
     #include "wx/dialog.h"
     #include "wx/msgdlg.h"
     #include "wx/statusbr.h"
     #include "wx/dialog.h"
     #include "wx/msgdlg.h"
     #include "wx/statusbr.h"
+    #include "wx/toolbar.h"
     #include "wx/dcclient.h"
     #include "wx/dcclient.h"
-#endif //WX_PRECOMP
-
-#if defined(__WXMAC__) && wxUSE_SCROLLBAR
     #include "wx/scrolbar.h"
     #include "wx/scrolbar.h"
-#endif
-
-#if wxUSE_CONSTRAINTS
     #include "wx/layout.h"
     #include "wx/layout.h"
-#endif // wxUSE_CONSTRAINTS
-
-#include "wx/sizer.h"
+    #include "wx/sizer.h"
+    #include "wx/menu.h"
+#endif //WX_PRECOMP
 
 #if wxUSE_DRAG_AND_DROP
     #include "wx/dnd.h"
 
 #if wxUSE_DRAG_AND_DROP
     #include "wx/dnd.h"
     #include "wx/sysopt.h"
 #endif
 
     #include "wx/sysopt.h"
 #endif
 
+// For reporting compile- and runtime version of GTK+ in the ctrl+alt+mclick dialog.
+// The gtk includes don't pull any other headers in, at least not on my system - MR
+#ifdef __WXGTK__
+    #ifdef __WXGTK20__
+        #include <gtk/gtkversion.h>
+    #else
+        #include <gtk/gtkfeatures.h>
+    #endif
+#endif
+
+#include "wx/platinfo.h"
+
+// Windows List
+WXDLLIMPEXP_DATA_CORE(wxWindowList) wxTopLevelWindows;
+
+// globals
+#if wxUSE_MENUS
+wxMenu *wxCurrentPopupMenu = NULL;
+#endif // wxUSE_MENUS
+
 // ----------------------------------------------------------------------------
 // static data
 // ----------------------------------------------------------------------------
 
 // ----------------------------------------------------------------------------
 // static data
 // ----------------------------------------------------------------------------
 
-#if defined(__WXPALMOS__)
-int wxWindowBase::ms_lastControlId = 65535;
-#elif defined(__WXPM__)
-int wxWindowBase::ms_lastControlId = 2000;
-#else
-int wxWindowBase::ms_lastControlId = -200;
-#endif
 
 IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler)
 
 
 IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler)
 
@@ -122,7 +125,7 @@ END_EVENT_TABLE()
 wxWindowBase::wxWindowBase()
 {
     // no window yet, no parent nor children
 wxWindowBase::wxWindowBase()
 {
     // no window yet, no parent nor children
-    m_parent = (wxWindow *)NULL;
+    m_parent = NULL;
     m_windowId = wxID_ANY;
 
     // no constraints on the minimal window size
     m_windowId = wxID_ANY;
 
     // no constraints on the minimal window size
@@ -143,7 +146,7 @@ wxWindowBase::wxWindowBase()
 
 #if wxUSE_VALIDATORS
     // no validator
 
 #if wxUSE_VALIDATORS
     // no validator
-    m_windowValidator = (wxValidator *) NULL;
+    m_windowValidator = NULL;
 #endif // wxUSE_VALIDATORS
 
     // the colours/fonts are default for now, so leave m_font,
 #endif // wxUSE_VALIDATORS
 
     // the colours/fonts are default for now, so leave m_font,
@@ -163,24 +166,24 @@ wxWindowBase::wxWindowBase()
 
 #if wxUSE_CONSTRAINTS
     // no constraints whatsoever
 
 #if wxUSE_CONSTRAINTS
     // no constraints whatsoever
-    m_constraints = (wxLayoutConstraints *) NULL;
-    m_constraintsInvolvedIn = (wxWindowList *) NULL;
+    m_constraints = NULL;
+    m_constraintsInvolvedIn = NULL;
 #endif // wxUSE_CONSTRAINTS
 
 #endif // wxUSE_CONSTRAINTS
 
-    m_windowSizer = (wxSizer *) NULL;
-    m_containingSizer = (wxSizer *) NULL;
+    m_windowSizer = NULL;
+    m_containingSizer = NULL;
     m_autoLayout = false;
 
 #if wxUSE_DRAG_AND_DROP
     m_autoLayout = false;
 
 #if wxUSE_DRAG_AND_DROP
-    m_dropTarget = (wxDropTarget *)NULL;
+    m_dropTarget = NULL;
 #endif // wxUSE_DRAG_AND_DROP
 
 #if wxUSE_TOOLTIPS
 #endif // wxUSE_DRAG_AND_DROP
 
 #if wxUSE_TOOLTIPS
-    m_tooltip = (wxToolTip *)NULL;
+    m_tooltip = NULL;
 #endif // wxUSE_TOOLTIPS
 
 #if wxUSE_CARET
 #endif // wxUSE_TOOLTIPS
 
 #if wxUSE_CARET
-    m_caret = (wxCaret *)NULL;
+    m_caret = NULL;
 #endif // wxUSE_CARET
 
 #if wxUSE_PALETTE
 #endif // wxUSE_CARET
 
 #if wxUSE_PALETTE
@@ -193,10 +196,7 @@ wxWindowBase::wxWindowBase()
 
     m_virtualSize = wxDefaultSize;
 
 
     m_virtualSize = wxDefaultSize;
 
-    m_minVirtualWidth =
-    m_maxVirtualWidth = wxDefaultCoord;
-    m_minVirtualHeight =
-    m_maxVirtualHeight = wxDefaultCoord;
+    m_scrollHelper = NULL;
 
     m_windowVariant = wxWINDOW_VARIANT_NORMAL;
 #if wxUSE_SYSTEM_OPTIONS
 
     m_windowVariant = wxWINDOW_VARIANT_NORMAL;
 #if wxUSE_SYSTEM_OPTIONS
@@ -209,8 +209,12 @@ wxWindowBase::wxWindowBase()
     // Whether we're using the current theme for this window (wxGTK only for now)
     m_themeEnabled = false;
 
     // Whether we're using the current theme for this window (wxGTK only for now)
     m_themeEnabled = false;
 
-    // VZ: this one shouldn't exist...
+    // This is set to true by SendDestroyEvent() which should be called by the
+    // most derived class to ensure that the destruction event is sent as soon
+    // as possible to allow its handlers to still see the undestroyed window
     m_isBeingDeleted = false;
     m_isBeingDeleted = false;
+
+    m_freezeCount = 0;
 }
 
 // common part of window creation process
 }
 
 // common part of window creation process
@@ -236,14 +240,26 @@ bool wxWindowBase::CreateBase(wxWindowBase *parent,
     // ids are limited to 16 bits under MSW so if you care about portability,
     // it's not a good idea to use ids out of this range (and negative ids are
     // reserved for wxWidgets own usage)
     // ids are limited to 16 bits under MSW so if you care about portability,
     // it's not a good idea to use ids out of this range (and negative ids are
     // reserved for wxWidgets own usage)
-    wxASSERT_MSG( id == wxID_ANY || (id >= 0 && id < 32767),
+    wxASSERT_MSG( id == wxID_ANY || (id >= 0 && id < 32767) ||
+                  (id >= wxID_AUTO_LOWEST && id <= wxID_AUTO_HIGHEST),
                   _T("invalid id value") );
 
     // generate a new id if the user doesn't care about it
                   _T("invalid id value") );
 
     // generate a new id if the user doesn't care about it
-    m_windowId = id == wxID_ANY ? NewControlId() : id;
+    if ( id == wxID_ANY )
+    {
+        m_windowId = NewControlId();
+    }
+    else // valid id specified
+    {
+        m_windowId = id;
+    }
+
+    // don't use SetWindowStyleFlag() here, this function should only be called
+    // to change the flag after creation as it tries to reflect the changes in
+    // flags by updating the window dynamically and we don't need this here
+    m_windowStyle = style;
 
     SetName(name);
 
     SetName(name);
-    SetWindowStyleFlag(style);
     SetParent(parent);
 
 #if wxUSE_VALIDATORS
     SetParent(parent);
 
 #if wxUSE_VALIDATORS
@@ -261,6 +277,28 @@ bool wxWindowBase::CreateBase(wxWindowBase *parent,
     return true;
 }
 
     return true;
 }
 
+bool wxWindowBase::ToggleWindowStyle(int flag)
+{
+    wxASSERT_MSG( flag, _T("flags with 0 value can't be toggled") );
+
+    bool rc;
+    long style = GetWindowStyleFlag();
+    if ( style & flag )
+    {
+        style &= ~flag;
+        rc = false;
+    }
+    else // currently off
+    {
+        style |= flag;
+        rc = true;
+    }
+
+    SetWindowStyleFlag(style);
+
+    return rc;
+}
+
 // ----------------------------------------------------------------------------
 // destruction
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // destruction
 // ----------------------------------------------------------------------------
@@ -281,18 +319,18 @@ wxWindowBase::~wxWindowBase()
     // we weren't a dialog class
     wxTopLevelWindows.DeleteObject((wxWindow*)this);
 
     // we weren't a dialog class
     wxTopLevelWindows.DeleteObject((wxWindow*)this);
 
+#if wxUSE_MENUS
+    // The associated popup menu can still be alive, disassociate from it in
+    // this case
+    if ( wxCurrentPopupMenu && wxCurrentPopupMenu->GetInvokingWindow() == this )
+        wxCurrentPopupMenu->SetInvokingWindow(NULL);
+#endif // wxUSE_MENUS
+
     wxASSERT_MSG( GetChildren().GetCount() == 0, wxT("children not destroyed") );
 
     wxASSERT_MSG( GetChildren().GetCount() == 0, wxT("children not destroyed") );
 
-    // reset the dangling pointer our parent window may keep to us
+    // notify the parent about this window destruction
     if ( m_parent )
     if ( m_parent )
-    {
-        if ( m_parent->GetDefaultItem() == this )
-        {
-            m_parent->SetDefaultItem(NULL);
-        }
-
         m_parent->RemoveChild(this);
         m_parent->RemoveChild(this);
-    }
 
 #if wxUSE_CARET
     delete m_caret;
 
 #if wxUSE_CARET
     delete m_caret;
@@ -333,10 +371,44 @@ wxWindowBase::~wxWindowBase()
 #if wxUSE_ACCESSIBILITY
     delete m_accessible;
 #endif
 #if wxUSE_ACCESSIBILITY
     delete m_accessible;
 #endif
+
+#if wxUSE_HELP
+    // NB: this has to be called unconditionally, because we don't know
+    //     whether this window has associated help text or not
+    wxHelpProvider *helpProvider = wxHelpProvider::Get();
+    if ( helpProvider )
+        helpProvider->RemoveHelp(this);
+#endif
+}
+
+bool wxWindowBase::IsBeingDeleted() const
+{
+    return m_isBeingDeleted ||
+            (!IsTopLevel() && m_parent && m_parent->IsBeingDeleted());
+}
+
+void wxWindowBase::SendDestroyEvent()
+{
+    if ( m_isBeingDeleted )
+    {
+        // we could have been already called from a more derived class dtor,
+        // e.g. ~wxTLW calls us and so does ~wxWindow and the latter call
+        // should be simply ignored
+        return;
+    }
+
+    m_isBeingDeleted = true;
+
+    wxWindowDestroyEvent event;
+    event.SetEventObject(this);
+    event.SetId(GetId());
+    GetEventHandler()->ProcessEvent(event);
 }
 
 bool wxWindowBase::Destroy()
 {
 }
 
 bool wxWindowBase::Destroy()
 {
+    SendDestroyEvent();
+
     delete this;
 
     return true;
     delete this;
 
     return true;
@@ -350,7 +422,7 @@ bool wxWindowBase::Close(bool force)
 
     // return false if window wasn't closed because the application vetoed the
     // close event
 
     // return false if window wasn't closed because the application vetoed the
     // close event
-    return GetEventHandler()->ProcessEvent(event) && !event.GetVeto();
+    return HandleWindowEvent(event) && !event.GetVeto();
 }
 
 bool wxWindowBase::DestroyChildren()
 }
 
 bool wxWindowBase::DestroyChildren()
@@ -365,11 +437,11 @@ bool wxWindowBase::DestroyChildren()
 
         wxWindow *child = node->GetData();
 
 
         wxWindow *child = node->GetData();
 
-        // note that we really want to call delete and not ->Destroy() here
-        // because we want to delete the child immediately, before we are
-        // deleted, and delayed deletion would result in problems as our (top
-        // level) child could outlive its parent
-        delete child;
+        // note that we really want to delete it immediately so don't call the
+        // possible overridden Destroy() version which might not delete the
+        // child immediately resulting in problems with our (top level) child
+        // outliving its parent
+        child->wxWindowBase::Destroy();
 
         wxASSERT_MSG( !GetChildren().Find(child),
                       wxT("child didn't remove itself using RemoveChild()") );
 
         wxASSERT_MSG( !GetChildren().Find(child),
                       wxT("child didn't remove itself using RemoveChild()") );
@@ -383,132 +455,20 @@ bool wxWindowBase::DestroyChildren()
 // ----------------------------------------------------------------------------
 
 // centre the window with respect to its parent in either (or both) directions
 // ----------------------------------------------------------------------------
 
 // centre the window with respect to its parent in either (or both) directions
-void wxWindowBase::Centre(int direction)
+void wxWindowBase::DoCentre(int dir)
 {
 {
-    // the position/size of the parent window or of the entire screen
-    wxPoint posParent;
-    int widthParent, heightParent;
-
-    wxWindow *parent = NULL;
-    wxTopLevelWindow *winTop = NULL;
-
-    if ( !(direction & wxCENTRE_ON_SCREEN) )
-    {
-        // find the parent to centre this window on: it should be the
-        // immediate parent for the controls but the top level parent for the
-        // top level windows (like dialogs)
-        parent = GetParent();
-        if ( IsTopLevel() )
-        {
-            while ( parent && !parent->IsTopLevel() )
-            {
-                parent = parent->GetParent();
-            }
-        }
-
-        // there is no wxTopLevelWindow under wxMotif yet
-#ifndef __WXMOTIF__
-        // we shouldn't center the dialog on the iconized window: under
-        // Windows, for example, this places it completely off the screen
-        if ( parent )
-        {
-            winTop = wxDynamicCast(parent, wxTopLevelWindow);
-            if ( winTop && winTop->IsIconized() )
-            {
-                winTop = NULL;
-                parent = NULL;
-            }
-        }
-#endif // __WXMOTIF__
-
-        // did we find the parent?
-        if ( !parent )
-        {
-            // no other choice
-            direction |= wxCENTRE_ON_SCREEN;
-        }
-    }
-
-    if ( direction & wxCENTRE_ON_SCREEN )
-    {
-        // centre with respect to the whole screen
-        wxDisplaySize(&widthParent, &heightParent);
-    }
-    else
-    {
-        if ( IsTopLevel() )
-        {
-            if(winTop)
-                winTop->GetRectForTopLevelChildren(&posParent.x, &posParent.y, &widthParent, &heightParent);
-            else
-            {
-                // centre on the parent
-                parent->GetSize(&widthParent, &heightParent);
-
-                // adjust to the parents position
-                posParent = parent->GetPosition();
-            }
-        }
-        else
-        {
-            // centre inside the parents client rectangle
-            parent->GetClientSize(&widthParent, &heightParent);
-        }
-    }
+    wxCHECK_RET( !(dir & wxCENTRE_ON_SCREEN) && GetParent(),
+                 _T("this method only implements centering child windows") );
 
 
-    int width, height;
-    GetSize(&width, &height);
-
-    int xNew = wxDefaultCoord,
-        yNew = wxDefaultCoord;
-
-    if ( direction & wxHORIZONTAL )
-        xNew = (widthParent - width)/2;
-
-    if ( direction & wxVERTICAL )
-        yNew = (heightParent - height)/2;
-
-    xNew += posParent.x;
-    yNew += posParent.y;
-
-    // Base size of the visible dimensions of the display
-    // to take into account the taskbar. And the Mac menu bar at top.
-    wxRect clientrect = wxGetClientDisplayRect();
-
-    // NB: in wxMSW, negative position may not neccessary mean "out of screen",
-    //     but it may mean that the window is placed on other than the main
-    //     display. Therefore we only make sure centered window is on the main display
-    //     if the parent is at least partially present here.
-    if (posParent.x + widthParent >= 0)  // if parent is (partially) on the main display
-    {
-        if (xNew < clientrect.GetLeft())
-            xNew = clientrect.GetLeft();
-        else if (xNew + width > clientrect.GetRight())
-            xNew = clientrect.GetRight() - width;
-    }
-    if (posParent.y + heightParent >= 0)  // if parent is (partially) on the main display
-    {
-        if (yNew + height > clientrect.GetBottom())
-            yNew = clientrect.GetBottom() - height;
-
-        // Make certain that the title bar is initially visible
-        // always, even if this would push the bottom of the
-        // dialog off the visible area of the display
-        if (yNew < clientrect.GetTop())
-            yNew = clientrect.GetTop();
-    }
-
-    // move the window to this position (keeping the old size but using
-    // SetSize() and not Move() to allow xNew and/or yNew to be wxDefaultCoord)
-    SetSize(xNew, yNew, width, height, wxSIZE_ALLOW_MINUS_ONE);
+    SetSize(GetRect().CentreIn(GetParent()->GetClientSize(), dir));
 }
 
 // fits the window around the children
 void wxWindowBase::Fit()
 {
 }
 
 // fits the window around the children
 void wxWindowBase::Fit()
 {
-    if ( GetChildren().GetCount() > 0 )
+    if ( !GetChildren().empty() )
     {
     {
-        SetClientSize(GetBestSize());
+        SetSize(GetBestSize());
     }
     //else: do nothing if we have no children
 }
     }
     //else: do nothing if we have no children
 }
@@ -545,17 +505,21 @@ void wxWindowBase::InvalidateBestSize()
     m_bestSizeCache = wxDefaultSize;
 
     // parent's best size calculation may depend on its children's
     m_bestSizeCache = wxDefaultSize;
 
     // parent's best size calculation may depend on its children's
-    // best sizes, so let's invalidate it as well to be safe:
-    if (m_parent)
+    // as long as child window we are in is not top level window itself
+    // (because the TLW size is never resized automatically)
+    // so let's invalidate it as well to be safe:
+    if (m_parent && !IsTopLevel())
         m_parent->InvalidateBestSize();
 }
 
 // return the size best suited for the current window
 wxSize wxWindowBase::DoGetBestSize() const
 {
         m_parent->InvalidateBestSize();
 }
 
 // return the size best suited for the current window
 wxSize wxWindowBase::DoGetBestSize() const
 {
+    wxSize best;
+
     if ( m_windowSizer )
     {
     if ( m_windowSizer )
     {
-        return m_windowSizer->GetMinSize();
+        best = m_windowSizer->GetMinSize();
     }
 #if wxUSE_CONSTRAINTS
     else if ( m_constraints )
     }
 #if wxUSE_CONSTRAINTS
     else if ( m_constraints )
@@ -591,7 +555,7 @@ wxSize wxWindowBase::DoGetBestSize() const
             //       will never return a size bigger than the current one :-(
         }
 
             //       will never return a size bigger than the current one :-(
         }
 
-        return wxSize(maxX, maxY);
+        best = wxSize(maxX, maxY);
     }
 #endif // wxUSE_CONSTRAINTS
     else if ( !GetChildren().empty()
     }
 #endif // wxUSE_CONSTRAINTS
     else if ( !GetChildren().empty()
@@ -600,7 +564,8 @@ wxSize wxWindowBase::DoGetBestSize() const
 #endif
               )
     {
 #endif
               )
     {
-        // our minimal acceptable size is such that all our visible child windows fit inside
+        // our minimal acceptable size is such that all our visible child
+        // windows fit inside
         int maxX = 0,
             maxY = 0;
 
         int maxX = 0,
             maxY = 0;
 
@@ -609,9 +574,10 @@ wxSize wxWindowBase::DoGetBestSize() const
               node = node->GetNext() )
         {
             wxWindow *win = node->GetData();
               node = node->GetNext() )
         {
             wxWindow *win = node->GetData();
-            if ( win->IsTopLevel()  || ( ! win->IsShown() )
+            if ( win->IsTopLevel()
+                    || !win->IsShown()
 #if wxUSE_STATUSBAR
 #if wxUSE_STATUSBAR
-                    || wxDynamicCast(win, wxStatusBar)
+                        || wxDynamicCast(win, wxStatusBar)
 #endif // wxUSE_STATUSBAR
                )
             {
 #endif // wxUSE_STATUSBAR
                )
             {
@@ -638,47 +604,152 @@ wxSize wxWindowBase::DoGetBestSize() const
                 maxY = wy + wh;
         }
 
                 maxY = wy + wh;
         }
 
-        // for compatibility with the old versions and because it really looks
-        // slightly more pretty like this, add a pad
-        maxX += 7;
-        maxY += 14;
-
-        return wxSize(maxX, maxY);
+        best = wxSize(maxX, maxY);
     }
     else // ! has children
     {
     }
     else // ! has children
     {
-        // for a generic window there is no natural best size - just use either the
-        // minimum size if there is one, or the current size
-        if ( GetMinSize().IsFullySpecified() )
-            return GetMinSize();
-        else
-            return GetSize();
+        // for a generic window there is no natural best size so, if the
+        // minimal size is not set, use the current size but take care to
+        // remember it as minimal size for the next time because our best size
+        // should be constant: otherwise we could get into a situation when the
+        // window is initially at some size, then expanded to a larger size and
+        // then, when the containing window is shrunk back (because our initial
+        // best size had been used for computing the parent min size), we can't
+        // be shrunk back any more because our best size is now bigger
+        wxSize size = GetMinSize();
+        if ( !size.IsFullySpecified() )
+        {
+            size.SetDefaults(GetSize());
+            wxConstCast(this, wxWindowBase)->SetMinSize(size);
+        }
+
+        // return as-is, unadjusted by the client size difference.
+        return size;
     }
     }
+
+    // Add any difference between size and client size
+    wxSize diff = GetSize() - GetClientSize();
+    best.x += wxMax(0, diff.x);
+    best.y += wxMax(0, diff.y);
+
+    return best;
 }
 
 }
 
+// helper of GetWindowBorderSize(): as many ports don't implement support for
+// wxSYS_BORDER/EDGE_X/Y metrics in their wxSystemSettings, use hard coded
+// fallbacks in this case
+static int wxGetMetricOrDefault(wxSystemMetric what, const wxWindowBase* win)
+{
+    int rc = wxSystemSettings::GetMetric(
+        what, static_cast<wxWindow*>(const_cast<wxWindowBase*>(win)));
+    if ( rc == -1 )
+    {
+        switch ( what )
+        {
+            case wxSYS_BORDER_X:
+            case wxSYS_BORDER_Y:
+                // 2D border is by default 1 pixel wide
+                rc = 1;
+                break;
+
+            case wxSYS_EDGE_X:
+            case wxSYS_EDGE_Y:
+                // 3D borders are by default 2 pixels
+                rc = 2;
+                break;
+
+            default:
+                wxFAIL_MSG( _T("unexpected wxGetMetricOrDefault() argument") );
+                rc = 0;
+        }
+    }
+
+    return rc;
+}
 
 
-wxSize wxWindowBase::GetBestFittingSize() const
+wxSize wxWindowBase::GetWindowBorderSize() const
+{
+    wxSize size;
+
+    switch ( GetBorder() )
+    {
+        case wxBORDER_NONE:
+            // nothing to do, size is already (0, 0)
+            break;
+
+        case wxBORDER_SIMPLE:
+        case wxBORDER_STATIC:
+            size.x = wxGetMetricOrDefault(wxSYS_BORDER_X, this);
+            size.y = wxGetMetricOrDefault(wxSYS_BORDER_Y, this);
+            break;
+
+        case wxBORDER_SUNKEN:
+        case wxBORDER_RAISED:
+            size.x = wxMax(wxGetMetricOrDefault(wxSYS_EDGE_X, this),
+                           wxGetMetricOrDefault(wxSYS_BORDER_X, this));
+            size.y = wxMax(wxGetMetricOrDefault(wxSYS_EDGE_Y, this),
+                           wxGetMetricOrDefault(wxSYS_BORDER_Y, this));
+            break;
+
+        case wxBORDER_DOUBLE:
+            size.x = wxGetMetricOrDefault(wxSYS_EDGE_X, this) +
+                        wxGetMetricOrDefault(wxSYS_BORDER_X, this);
+            size.y = wxGetMetricOrDefault(wxSYS_EDGE_Y, this) +
+                        wxGetMetricOrDefault(wxSYS_BORDER_Y, this);
+            break;
+
+        default:
+            wxFAIL_MSG(_T("Unknown border style."));
+            break;
+    }
+
+    // we have borders on both sides
+    return size*2;
+}
+
+wxSize wxWindowBase::GetEffectiveMinSize() const
 {
     // merge the best size with the min size, giving priority to the min size
     wxSize min = GetMinSize();
 {
     // merge the best size with the min size, giving priority to the min size
     wxSize min = GetMinSize();
+    
     if (min.x == wxDefaultCoord || min.y == wxDefaultCoord)
     {
         wxSize best = GetBestSize();
         if (min.x == wxDefaultCoord) min.x =  best.x;
         if (min.y == wxDefaultCoord) min.y =  best.y;
     }
     if (min.x == wxDefaultCoord || min.y == wxDefaultCoord)
     {
         wxSize best = GetBestSize();
         if (min.x == wxDefaultCoord) min.x =  best.x;
         if (min.y == wxDefaultCoord) min.y =  best.y;
     }
+    
     return min;
 }
 
     return min;
 }
 
+wxSize wxWindowBase::GetBestSize() const
+{
+    if ((!m_windowSizer) && (m_bestSizeCache.IsFullySpecified()))
+        return m_bestSizeCache;
+        
+    return DoGetBestSize();
+}
+
+void wxWindowBase::SetMinSize(const wxSize& minSize)
+{ 
+    m_minWidth = minSize.x; 
+    m_minHeight = minSize.y; 
+}
+
+void wxWindowBase::SetMaxSize(const wxSize& maxSize)
+{ 
+    m_maxWidth = maxSize.x; 
+    m_maxHeight = maxSize.y;
+}
 
 
-void wxWindowBase::SetBestFittingSize(const wxSize& size)
+void wxWindowBase::SetInitialSize(const wxSize& size)
 {
     // Set the min size to the size passed in.  This will usually either be
     // wxDefaultSize or the size passed to this window's ctor/Create function.
     SetMinSize(size);
 
     // Merge the size with the best size if needed
 {
     // Set the min size to the size passed in.  This will usually either be
     // wxDefaultSize or the size passed to this window's ctor/Create function.
     SetMinSize(size);
 
     // Merge the size with the best size if needed
-    wxSize best = GetBestFittingSize();
+    wxSize best = GetEffectiveMinSize();
 
     // If the current size doesn't match then change it
     if (GetSize() != best)
 
     // If the current size doesn't match then change it
     if (GetSize() != best)
@@ -689,24 +760,23 @@ void wxWindowBase::SetBestFittingSize(const wxSize& size)
 // by default the origin is not shifted
 wxPoint wxWindowBase::GetClientAreaOrigin() const
 {
 // by default the origin is not shifted
 wxPoint wxWindowBase::GetClientAreaOrigin() const
 {
-    return wxPoint(0, 0);
+    return wxPoint(0,0);
 }
 
 }
 
-// set the min/max size of the window
-void wxWindowBase::DoSetSizeHints(int minW, int minH,
-                                  int maxW, int maxH,
-                                  int WXUNUSED(incW), int WXUNUSED(incH))
+wxSize wxWindowBase::ClientToWindowSize(const wxSize& size) const
 {
 {
-    // setting min width greater than max width leads to infinite loops under
-    // X11 and generally doesn't make any sense, so don't allow it
-    wxCHECK_RET( (minW == wxDefaultCoord || maxW == wxDefaultCoord || minW <= maxW) &&
-                    (minH == wxDefaultCoord || maxH == wxDefaultCoord || minH <= maxH),
-                 _T("min width/height must be less than max width/height!") );
+    const wxSize diff(GetSize() - GetClientSize());
 
 
-    m_minWidth = minW;
-    m_maxWidth = maxW;
-    m_minHeight = minH;
-    m_maxHeight = maxH;
+    return wxSize(size.x == -1 ? -1 : size.x + diff.x,
+                  size.y == -1 ? -1 : size.y + diff.y);
+}
+
+wxSize wxWindowBase::WindowToClientSize(const wxSize& size) const
+{
+    const wxSize diff(GetSize() - GetClientSize());
+
+    return wxSize(size.x == -1 ? -1 : size.x - diff.x,
+                  size.y == -1 ? -1 : size.y - diff.y);
 }
 
 void wxWindowBase::SetWindowVariant( wxWindowVariant variant )
 }
 
 void wxWindowBase::SetWindowVariant( wxWindowVariant variant )
@@ -754,35 +824,80 @@ void wxWindowBase::DoSetWindowVariant( wxWindowVariant variant )
     SetFont(font);
 }
 
     SetFont(font);
 }
 
-void wxWindowBase::SetVirtualSizeHints( int minW, int minH,
-                                        int maxW, int maxH )
+void wxWindowBase::DoSetSizeHints( int minW, int minH,
+                                   int maxW, int maxH,
+                                   int WXUNUSED(incW), int WXUNUSED(incH) )
 {
 {
-    m_minVirtualWidth = minW;
-    m_maxVirtualWidth = maxW;
-    m_minVirtualHeight = minH;
-    m_maxVirtualHeight = maxH;
+    wxCHECK_RET( (minW == wxDefaultCoord || maxW == wxDefaultCoord || minW <= maxW) &&
+                    (minH == wxDefaultCoord || maxH == wxDefaultCoord || minH <= maxH),
+                 _T("min width/height must be less than max width/height!") );
+
+    m_minWidth = minW;
+    m_maxWidth = maxW;
+    m_minHeight = minH;
+    m_maxHeight = maxH;
 }
 
 }
 
-void wxWindowBase::DoSetVirtualSize( int x, int y )
+
+#if WXWIN_COMPATIBILITY_2_8
+void wxWindowBase::SetVirtualSizeHints(int WXUNUSED(minW), int WXUNUSED(minH),
+                                       int WXUNUSED(maxW), int WXUNUSED(maxH))
+{
+}
+
+void wxWindowBase::SetVirtualSizeHints(const wxSize& WXUNUSED(minsize),
+                                       const wxSize& WXUNUSED(maxsize))
 {
 {
-    if ( m_minVirtualWidth != wxDefaultCoord && m_minVirtualWidth > x )
-        x = m_minVirtualWidth;
-    if ( m_maxVirtualWidth != wxDefaultCoord && m_maxVirtualWidth < x )
-        x = m_maxVirtualWidth;
-    if ( m_minVirtualHeight != wxDefaultCoord && m_minVirtualHeight > y )
-        y = m_minVirtualHeight;
-    if ( m_maxVirtualHeight != wxDefaultCoord && m_maxVirtualHeight < y )
-        y = m_maxVirtualHeight;
+}
+#endif // WXWIN_COMPATIBILITY_2_8
 
 
+void wxWindowBase::DoSetVirtualSize( int x, int y )
+{
     m_virtualSize = wxSize(x, y);
 }
 
 wxSize wxWindowBase::DoGetVirtualSize() const
 {
     m_virtualSize = wxSize(x, y);
 }
 
 wxSize wxWindowBase::DoGetVirtualSize() const
 {
-    wxSize  s( GetClientSize() );
+    // we should use the entire client area so if it is greater than our
+    // virtual size, expand it to fit (otherwise if the window is big enough we
+    // wouldn't be using parts of it)
+    wxSize size = GetClientSize();
+    if ( m_virtualSize.x > size.x )
+        size.x = m_virtualSize.x;
+
+    if ( m_virtualSize.y >= size.y )
+        size.y = m_virtualSize.y;
 
 
-    return wxSize( wxMax( m_virtualSize.GetWidth(), s.GetWidth() ),
-                   wxMax( m_virtualSize.GetHeight(), s.GetHeight() ) );
+    return size;
+}
+
+void wxWindowBase::DoGetScreenPosition(int *x, int *y) const
+{
+    // screen position is the same as (0, 0) in client coords for non TLWs (and
+    // TLWs override this method)
+    if ( x )
+        *x = 0;
+    if ( y )
+        *y = 0;
+
+    ClientToScreen(x, y);
+}
+
+void wxWindowBase::SendSizeEvent(int flags)
+{
+    wxSizeEvent event(GetSize(), GetId());
+    event.SetEventObject(this);
+    if ( flags & wxSEND_EVENT_POST )
+        wxPostEvent(this, event);
+    else
+        HandleWindowEvent(event);
+}
+
+void wxWindowBase::SendSizeEventToParent(int flags)
+{
+    wxWindow * const parent = GetParent();
+    if ( parent && !parent->IsBeingDeleted() )
+        parent->SendSizeEvent(flags);
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------
@@ -803,19 +918,66 @@ bool wxWindowBase::Show(bool show)
     }
 }
 
     }
 }
 
-bool wxWindowBase::Enable(bool enable)
+bool wxWindowBase::IsEnabled() const
 {
 {
-    if ( enable != m_isEnabled )
-    {
-        m_isEnabled = enable;
+    return IsThisEnabled() && (IsTopLevel() || !GetParent() || GetParent()->IsEnabled());
+}
 
 
-        return true;
-    }
-    else
+void wxWindowBase::NotifyWindowOnEnableChange(bool enabled)
+{
+#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() )
+        return;
+
+    for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+          node;
+          node = node->GetNext() )
     {
     {
+        wxWindowBase * const child = node->GetData();
+        if ( !child->IsTopLevel() && child->IsThisEnabled() )
+            child->NotifyWindowOnEnableChange(enabled);
+    }
+}
+
+bool wxWindowBase::Enable(bool enable)
+{
+    if ( enable == IsThisEnabled() )
         return false;
         return false;
+
+    m_isEnabled = enable;
+
+#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);
+
+    return true;
 }
 }
+
+bool wxWindowBase::IsShownOnScreen() const
+{
+    // A window is shown on screen if it itself is shown and so are all its
+    // parents. But if a window is toplevel one, then its always visible on
+    // screen if IsShown() returns true, even if it has a hidden parent.
+    return IsShown() &&
+           (IsTopLevel() || GetParent() == NULL || GetParent()->IsShownOnScreen());
+}
+
 // ----------------------------------------------------------------------------
 // RTTI
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // RTTI
 // ----------------------------------------------------------------------------
@@ -825,6 +987,52 @@ bool wxWindowBase::IsTopLevel() const
     return false;
 }
 
     return false;
 }
 
+// ----------------------------------------------------------------------------
+// Freeze/Thaw
+// ----------------------------------------------------------------------------
+
+void wxWindowBase::Freeze()
+{
+    if ( !m_freezeCount++ )
+    {
+        // physically freeze this window:
+        DoFreeze();
+
+        // and recursively freeze all children:
+        for ( wxWindowList::iterator i = GetChildren().begin();
+              i != GetChildren().end(); ++i )
+        {
+            wxWindow *child = *i;
+            if ( child->IsTopLevel() )
+                continue;
+
+            child->Freeze();
+        }
+    }
+}
+
+void wxWindowBase::Thaw()
+{
+    wxASSERT_MSG( m_freezeCount, "Thaw() without matching Freeze()" );
+
+    if ( !--m_freezeCount )
+    {
+        // recursively thaw all children:
+        for ( wxWindowList::iterator i = GetChildren().begin();
+              i != GetChildren().end(); ++i )
+        {
+            wxWindow *child = *i;
+            if ( child->IsTopLevel() )
+                continue;
+
+            child->Thaw();
+        }
+
+        // physically thaw this window:
+        DoThaw();
+    }
+}
+
 // ----------------------------------------------------------------------------
 // reparenting the window
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // reparenting the window
 // ----------------------------------------------------------------------------
@@ -840,12 +1048,25 @@ void wxWindowBase::AddChild(wxWindowBase *child)
 
     GetChildren().Append((wxWindow*)child);
     child->SetParent(this);
 
     GetChildren().Append((wxWindow*)child);
     child->SetParent(this);
+
+    // adding a child while frozen will assert when thawed, so freeze it as if
+    // it had been already present when we were frozen
+    if ( IsFrozen() && !child->IsTopLevel() )
+        child->Freeze();
 }
 
 void wxWindowBase::RemoveChild(wxWindowBase *child)
 {
     wxCHECK_RET( child, wxT("can't remove a NULL child") );
 
 }
 
 void wxWindowBase::RemoveChild(wxWindowBase *child)
 {
     wxCHECK_RET( child, wxT("can't remove a NULL child") );
 
+    // removing a child while frozen may result in permanently frozen window
+    // if used e.g. from Reparent(), so thaw it
+    //
+    // NB: IsTopLevel() doesn't return true any more when a TLW child is being
+    //     removed from its ~wxWindowBase, so check for IsBeingDeleted() too
+    if ( IsFrozen() && !child->IsBeingDeleted() && !child->IsTopLevel() )
+        child->Thaw();
+
     GetChildren().DeleteObject((wxWindow *)child);
     child->SetParent(NULL);
 }
     GetChildren().DeleteObject((wxWindow *)child);
     child->SetParent(NULL);
 }
@@ -859,6 +1080,8 @@ bool wxWindowBase::Reparent(wxWindowBase *newParent)
         return false;
     }
 
         return false;
     }
 
+    const bool oldEnabledState = IsEnabled();
+
     // unlink this window from the existing parent.
     if ( oldParent )
     {
     // unlink this window from the existing parent.
     if ( oldParent )
     {
@@ -879,6 +1102,14 @@ bool wxWindowBase::Reparent(wxWindowBase *newParent)
         wxTopLevelWindows.Append((wxWindow *)this);
     }
 
         wxTopLevelWindows.Append((wxWindow *)this);
     }
 
+    // We need to notify window (and its subwindows) if by changing the parent
+    // we also change our enabled/disabled status.
+    const bool newEnabledState = IsEnabled();
+    if ( newEnabledState != oldEnabledState )
+    {
+        NotifyWindowOnEnableChange(newEnabledState);
+    }
+
     return true;
 }
 
     return true;
 }
 
@@ -886,73 +1117,121 @@ bool wxWindowBase::Reparent(wxWindowBase *newParent)
 // event handler stuff
 // ----------------------------------------------------------------------------
 
 // event handler stuff
 // ----------------------------------------------------------------------------
 
-void wxWindowBase::PushEventHandler(wxEvtHandler *handler)
+void wxWindowBase::SetEventHandler(wxEvtHandler *handler)
+{
+    wxCHECK_RET(handler != NULL, "SetEventHandler(NULL) called");
+
+    m_eventHandler = handler;
+}
+
+void wxWindowBase::SetNextHandler(wxEvtHandler *WXUNUSED(handler))
+{
+    // disable wxEvtHandler chain mechanism for wxWindows:
+    // wxWindow uses its own stack mechanism which doesn't mix well with wxEvtHandler's one
+
+    wxFAIL_MSG("wxWindow cannot be part of a wxEvtHandler chain");
+}
+void wxWindowBase::SetPreviousHandler(wxEvtHandler *WXUNUSED(handler))
+{
+    // we can't simply wxFAIL here as in SetNextHandler: in fact the last
+    // handler of our stack when is destroyed will be Unlink()ed and thus
+    // will call this function to update the pointer of this window...
+
+    //wxFAIL_MSG("wxWindow cannot be part of a wxEvtHandler chain");
+}
+
+void wxWindowBase::PushEventHandler(wxEvtHandler *handlerToPush)
 {
 {
+    wxCHECK_RET( handlerToPush != NULL, "PushEventHandler(NULL) called" );
+
+    // the new handler is going to be part of the wxWindow stack of event handlers:
+    // it can't be part also of an event handler double-linked chain:
+    wxASSERT_MSG(handlerToPush->IsUnlinked(),
+        "The handler being pushed in the wxWindow stack shouldn't be part of "
+        "a wxEvtHandler chain; call Unlink() on it first");
+
     wxEvtHandler *handlerOld = GetEventHandler();
     wxEvtHandler *handlerOld = GetEventHandler();
+    wxCHECK_RET( handlerOld, "an old event handler is NULL?" );
 
 
-    handler->SetNextHandler(handlerOld);
+    // now use wxEvtHandler double-linked list to implement a stack:
+    handlerToPush->SetNextHandler(handlerOld);
 
 
-    if ( handlerOld )
-        GetEventHandler()->SetPreviousHandler(handler);
+    if (handlerOld != this)
+        handlerOld->SetPreviousHandler(handlerToPush);
 
 
-    SetEventHandler(handler);
+    SetEventHandler(handlerToPush);
+
+#ifdef __WXDEBUG__
+    // final checks of the operations done above:
+    wxASSERT_MSG( handlerToPush->GetPreviousHandler() == NULL,
+        "the first handler of the wxWindow stack should have no previous handlers set" );
+    wxASSERT_MSG( handlerToPush->GetNextHandler() != NULL,
+        "the first handler of the wxWindow stack should have non-NULL next handler" );
+
+    wxEvtHandler* pLast = handlerToPush;
+    while (pLast && pLast != this)
+        pLast = pLast->GetNextHandler();
+    wxASSERT_MSG( pLast->GetNextHandler() == NULL,
+        "the last handler of the wxWindow stack should have this window as next handler" );
+#endif
 }
 
 wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
 {
 }
 
 wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
 {
-    wxEvtHandler *handlerA = GetEventHandler();
-    if ( handlerA )
-    {
-        wxEvtHandler *handlerB = handlerA->GetNextHandler();
-        handlerA->SetNextHandler((wxEvtHandler *)NULL);
+    // we need to pop the wxWindow stack, i.e. we need to remove the first handler
 
 
-        if ( handlerB )
-            handlerB->SetPreviousHandler((wxEvtHandler *)NULL);
-        SetEventHandler(handlerB);
+    wxEvtHandler *firstHandler = GetEventHandler();
+    wxCHECK_MSG( firstHandler != NULL, NULL, "wxWindow cannot have a NULL event handler" );
+    wxCHECK_MSG( firstHandler != this, NULL, "cannot pop the wxWindow itself" );
+    wxCHECK_MSG( firstHandler->GetPreviousHandler() == NULL, NULL,
+        "the first handler of the wxWindow stack should have no previous handlers set" );
 
 
-        if ( deleteHandler )
-        {
-            delete handlerA;
-            handlerA = (wxEvtHandler *)NULL;
-        }
+    wxEvtHandler *secondHandler = firstHandler->GetNextHandler();
+    wxCHECK_MSG( secondHandler != NULL, NULL,
+        "the first handler of the wxWindow stack should have non-NULL next handler" );
+
+    firstHandler->SetNextHandler(NULL);
+    secondHandler->SetPreviousHandler(NULL);
+
+    // now firstHandler is completely unlinked; set secondHandler as the new window event handler
+    SetEventHandler(secondHandler);
+
+    if ( deleteHandler )
+    {
+        delete firstHandler;
+        firstHandler = NULL;
     }
 
     }
 
-    return handlerA;
+    return firstHandler;
 }
 
 }
 
-bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handler)
+bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handlerToRemove)
 {
 {
-    wxCHECK_MSG( handler, false, _T("RemoveEventHandler(NULL) called") );
+    wxCHECK_MSG( handlerToRemove != NULL, false, "RemoveEventHandler(NULL) called" );
+    wxCHECK_MSG( handlerToRemove != this, false, "Cannot remove the window itself" );
+
+    if (handlerToRemove == GetEventHandler())
+    {
+        // removing the first event handler is equivalent to "popping" the stack
+        PopEventHandler(false);
+        return true;
+    }
 
 
-    wxEvtHandler *handlerPrev = NULL,
-                 *handlerCur = GetEventHandler();
-    while ( handlerCur )
+    // NOTE: the wxWindow event handler list is always terminated with "this" handler
+    wxEvtHandler *handlerCur = GetEventHandler()->GetNextHandler();
+    while ( handlerCur != this )
     {
         wxEvtHandler *handlerNext = handlerCur->GetNextHandler();
 
     {
         wxEvtHandler *handlerNext = handlerCur->GetNextHandler();
 
-        if ( handlerCur == handler )
+        if ( handlerCur == handlerToRemove )
         {
         {
-            if ( handlerPrev )
-            {
-                handlerPrev->SetNextHandler(handlerNext);
-            }
-            else
-            {
-                SetEventHandler(handlerNext);
-            }
-
-            if ( handlerNext )
-            {
-                handlerNext->SetPreviousHandler ( handlerPrev );
-            }
-
-            handler->SetNextHandler(NULL);
-            handler->SetPreviousHandler(NULL);
+            handlerCur->Unlink();
 
 
+            wxASSERT_MSG( handlerCur != GetEventHandler(),
+                        "the case Remove == Pop should was already handled" );
             return true;
         }
 
             return true;
         }
 
-        handlerPrev = handlerCur;
         handlerCur = handlerNext;
     }
 
         handlerCur = handlerNext;
     }
 
@@ -961,6 +1240,12 @@ bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handler)
     return false;
 }
 
     return false;
 }
 
+bool wxWindowBase::HandleWindowEvent(wxEvent& event) const
+{
+    // SafelyProcessEvent() will handle exceptions nicely
+    return GetEventHandler()->SafelyProcessEvent(event);
+}
+
 // ----------------------------------------------------------------------------
 // colours, fonts &c
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // colours, fonts &c
 // ----------------------------------------------------------------------------
@@ -1005,14 +1290,23 @@ wxWindowBase::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
     wxVisualAttributes attrs;
     attrs.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
     attrs.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
     wxVisualAttributes attrs;
     attrs.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
     attrs.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
-    attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
 
 
+    // On Smartphone/PocketPC, wxSYS_COLOUR_WINDOW is a better reflection of
+    // the usual background colour than wxSYS_COLOUR_BTNFACE.
+    // It's a pity that wxSYS_COLOUR_WINDOW isn't always a suitable background
+    // colour on other platforms.
+
+#if defined(__WXWINCE__) && (defined(__SMARTPHONE__) || defined(__POCKETPC__))
+    attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
+#else
+    attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
+#endif
     return attrs;
 }
 
 wxColour wxWindowBase::GetBackgroundColour() const
 {
     return attrs;
 }
 
 wxColour wxWindowBase::GetBackgroundColour() const
 {
-    if ( !m_backgroundColour.Ok() )
+    if ( !m_backgroundColour.IsOk() )
     {
         wxASSERT_MSG( !m_hasBgCol, _T("we have invalid explicit bg colour?") );
 
     {
         wxASSERT_MSG( !m_hasBgCol, _T("we have invalid explicit bg colour?") );
 
@@ -1038,11 +1332,9 @@ wxColour wxWindowBase::GetForegroundColour() const
     // logic is the same as above
     if ( !m_hasFgCol && !m_foregroundColour.Ok() )
     {
     // logic is the same as above
     if ( !m_hasFgCol && !m_foregroundColour.Ok() )
     {
-        wxASSERT_MSG( !m_hasFgCol, _T("we have invalid explicit fg colour?") );
-
         wxColour colFg = GetDefaultAttributes().colFg;
 
         wxColour colFg = GetDefaultAttributes().colFg;
 
-        if ( !colFg.Ok() )
+        if ( !colFg.IsOk() )
             colFg = GetClassDefaultAttributes().colFg;
 
         return colFg;
             colFg = GetClassDefaultAttributes().colFg;
 
         return colFg;
@@ -1056,7 +1348,7 @@ bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
     if ( colour == m_backgroundColour )
         return false;
 
     if ( colour == m_backgroundColour )
         return false;
 
-    m_hasBgCol = colour.Ok();
+    m_hasBgCol = colour.IsOk();
     if ( m_backgroundStyle != wxBG_STYLE_CUSTOM )
         m_backgroundStyle = m_hasBgCol ? wxBG_STYLE_COLOUR : wxBG_STYLE_SYSTEM;
 
     if ( m_backgroundStyle != wxBG_STYLE_CUSTOM )
         m_backgroundStyle = m_hasBgCol ? wxBG_STYLE_COLOUR : wxBG_STYLE_SYSTEM;
 
@@ -1071,7 +1363,7 @@ bool wxWindowBase::SetForegroundColour( const wxColour &colour )
     if (colour == m_foregroundColour )
         return false;
 
     if (colour == m_foregroundColour )
         return false;
 
-    m_hasFgCol = colour.Ok();
+    m_hasFgCol = colour.IsOk();
     m_inheritFgCol = m_hasFgCol;
     m_foregroundColour = colour;
     SetThemeEnabled( !m_hasFgCol && !m_backgroundColour.Ok() );
     m_inheritFgCol = m_hasFgCol;
     m_foregroundColour = colour;
     SetThemeEnabled( !m_hasFgCol && !m_backgroundColour.Ok() );
@@ -1082,7 +1374,7 @@ bool wxWindowBase::SetCursor(const wxCursor& cursor)
 {
     // setting an invalid cursor is ok, it means that we don't have any special
     // cursor
 {
     // setting an invalid cursor is ok, it means that we don't have any special
     // cursor
-    if ( m_cursor == cursor )
+    if ( m_cursor.IsSameAs(cursor) )
     {
         // no change
         return false;
     {
         // no change
         return false;
@@ -1096,12 +1388,12 @@ bool wxWindowBase::SetCursor(const wxCursor& cursor)
 wxFont wxWindowBase::GetFont() const
 {
     // logic is the same as in GetBackgroundColour()
 wxFont wxWindowBase::GetFont() const
 {
     // logic is the same as in GetBackgroundColour()
-    if ( !m_font.Ok() )
+    if ( !m_font.IsOk() )
     {
         wxASSERT_MSG( !m_hasFont, _T("we have invalid explicit font?") );
 
         wxFont font = GetDefaultAttributes().font;
     {
         wxASSERT_MSG( !m_hasFont, _T("we have invalid explicit font?") );
 
         wxFont font = GetDefaultAttributes().font;
-        if ( !font.Ok() )
+        if ( !font.IsOk() )
             font = GetClassDefaultAttributes().font;
 
         return font;
             font = GetClassDefaultAttributes().font;
 
         return font;
@@ -1119,7 +1411,7 @@ bool wxWindowBase::SetFont(const wxFont& font)
     }
 
     m_font = font;
     }
 
     m_font = font;
-    m_hasFont = font.Ok();
+    m_hasFont = font.IsOk();
     m_inheritFont = m_hasFont;
 
     InvalidateBestSize();
     m_inheritFont = m_hasFont;
 
     InvalidateBestSize();
@@ -1203,12 +1495,12 @@ wxRect wxWindowBase::GetUpdateClientRect() const
     return rectUpdate;
 }
 
     return rectUpdate;
 }
 
-bool wxWindowBase::IsExposed(int x, int y) const
+bool wxWindowBase::DoIsExposed(int x, int y) const
 {
     return m_updateRegion.Contains(x, y) != wxOutRegion;
 }
 
 {
     return m_updateRegion.Contains(x, y) != wxOutRegion;
 }
 
-bool wxWindowBase::IsExposed(int x, int y, int w, int h) const
+bool wxWindowBase::DoIsExposed(int x, int y, int w, int h) const
 {
     return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
 }
 {
     return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
 }
@@ -1218,7 +1510,7 @@ void wxWindowBase::ClearBackground()
     // wxGTK uses its own version, no need to add never used code
 #ifndef __WXGTK__
     wxClientDC dc((wxWindow *)this);
     // wxGTK uses its own version, no need to add never used code
 #ifndef __WXGTK__
     wxClientDC dc((wxWindow *)this);
-    wxBrush brush(GetBackgroundColour(), wxSOLID);
+    wxBrush brush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID);
     dc.SetBackground(brush);
     dc.Clear();
 #endif // __WXGTK__
     dc.SetBackground(brush);
     dc.Clear();
 #endif // __WXGTK__
@@ -1233,7 +1525,7 @@ wxWindow *wxWindowBase::FindWindow(long id) const
     if ( id == m_windowId )
         return (wxWindow *)this;
 
     if ( id == m_windowId )
         return (wxWindow *)this;
 
-    wxWindowBase *res = (wxWindow *)NULL;
+    wxWindowBase *res = NULL;
     wxWindowList::compatibility_iterator node;
     for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
     {
     wxWindowList::compatibility_iterator node;
     for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
     {
@@ -1249,7 +1541,7 @@ wxWindow *wxWindowBase::FindWindow(const wxString& name) const
     if ( name == m_windowName )
         return (wxWindow *)this;
 
     if ( name == m_windowName )
         return (wxWindow *)this;
 
-    wxWindowBase *res = (wxWindow *)NULL;
+    wxWindowBase *res = NULL;
     wxWindowList::compatibility_iterator node;
     for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
     {
     wxWindowList::compatibility_iterator node;
     for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
     {
@@ -1376,7 +1668,7 @@ wxWindowBase::FindWindowByName(const wxString& title, const wxWindow *parent)
 wxWindow *
 wxWindowBase::FindWindowById( long id, const wxWindow* parent )
 {
 wxWindow *
 wxWindowBase::FindWindowById( long id, const wxWindow* parent )
 {
-    return wxFindWindowHelper(parent, _T(""), id, wxFindWindowCmpIds);
+    return wxFindWindowHelper(parent, wxEmptyString, id, wxFindWindowCmpIds);
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------
@@ -1514,6 +1806,7 @@ void wxWindowBase::SetHelpText(const wxString& text)
     }
 }
 
     }
 }
 
+#if WXWIN_COMPATIBILITY_2_8
 // associate this help text with all windows with the same id as this
 // one
 void wxWindowBase::SetHelpTextForId(const wxString& text)
 // associate this help text with all windows with the same id as this
 // one
 void wxWindowBase::SetHelpTextForId(const wxString& text)
@@ -1524,9 +1817,13 @@ void wxWindowBase::SetHelpTextForId(const wxString& text)
         helpProvider->AddHelp(GetId(), text);
     }
 }
         helpProvider->AddHelp(GetId(), text);
     }
 }
+#endif // WXWIN_COMPATIBILITY_2_8
 
 // get the help string associated with this window (may be empty)
 
 // get the help string associated with this window (may be empty)
-wxString wxWindowBase::GetHelpText() const
+// default implementation forwards calls to the help provider
+wxString
+wxWindowBase::GetHelpTextAtPoint(const wxPoint & WXUNUSED(pt),
+                                 wxHelpEvent::Origin WXUNUSED(origin)) const
 {
     wxString text;
     wxHelpProvider *helpProvider = wxHelpProvider::Get();
 {
     wxString text;
     wxHelpProvider *helpProvider = wxHelpProvider::Get();
@@ -1544,7 +1841,29 @@ void wxWindowBase::OnHelp(wxHelpEvent& event)
     wxHelpProvider *helpProvider = wxHelpProvider::Get();
     if ( helpProvider )
     {
     wxHelpProvider *helpProvider = wxHelpProvider::Get();
     if ( helpProvider )
     {
-        if ( helpProvider->ShowHelp(this) )
+        wxPoint pos = event.GetPosition();
+        const wxHelpEvent::Origin origin = event.GetOrigin();
+        if ( origin == wxHelpEvent::Origin_Keyboard )
+        {
+            // if the help event was generated from keyboard it shouldn't
+            // appear at the mouse position (which is still the only position
+            // associated with help event) if the mouse is far away, although
+            // we still do use the mouse position if it's over the window
+            // because we suppose the user looks approximately at the mouse
+            // already and so it would be more convenient than showing tooltip
+            // at some arbitrary position which can be quite far from it
+            const wxRect rectClient = GetClientRect();
+            if ( !rectClient.Contains(ScreenToClient(pos)) )
+            {
+                // position help slightly under and to the right of this window
+                pos = ClientToScreen(wxPoint(
+                        2*GetCharWidth(),
+                        rectClient.height + GetCharHeight()
+                      ));
+            }
+        }
+
+        if ( helpProvider->ShowHelpAtPoint(this, pos, origin) )
         {
             // skip the event.Skip() below
             return;
         {
             // skip the event.Skip() below
             return;
@@ -1557,7 +1876,7 @@ void wxWindowBase::OnHelp(wxHelpEvent& event)
 #endif // wxUSE_HELP
 
 // ----------------------------------------------------------------------------
 #endif // wxUSE_HELP
 
 // ----------------------------------------------------------------------------
-// tooltipsroot.Replace("\\", "/");
+// tooltips
 // ----------------------------------------------------------------------------
 
 #if wxUSE_TOOLTIPS
 // ----------------------------------------------------------------------------
 
 #if wxUSE_TOOLTIPS
@@ -1575,15 +1894,18 @@ void wxWindowBase::SetToolTip( const wxString &tip )
     }
 
     // setting empty tooltip text does not remove the tooltip any more - use
     }
 
     // setting empty tooltip text does not remove the tooltip any more - use
-    // SetToolTip((wxToolTip *)NULL) for this
+    // SetToolTip(NULL) for this
 }
 
 void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
 {
 }
 
 void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
 {
-    if ( m_tooltip )
-        delete m_tooltip;
+    if ( m_tooltip != tooltip )
+    {
+        if ( m_tooltip )
+            delete m_tooltip;
 
 
-    m_tooltip = tooltip;
+        m_tooltip = tooltip;
+    }
 }
 
 #endif // wxUSE_TOOLTIPS
 }
 
 #endif // wxUSE_TOOLTIPS
@@ -1696,7 +2018,7 @@ void wxWindowBase::DeleteRelatedConstraints()
         }
 
         delete m_constraintsInvolvedIn;
         }
 
         delete m_constraintsInvolvedIn;
-        m_constraintsInvolvedIn = (wxWindowList *) NULL;
+        m_constraintsInvolvedIn = NULL;
     }
 }
 
     }
 }
 
@@ -1707,12 +2029,21 @@ void wxWindowBase::SetSizer(wxSizer *sizer, bool deleteOld)
     if ( sizer == m_windowSizer)
         return;
 
     if ( sizer == m_windowSizer)
         return;
 
-    if ( deleteOld )
-        delete m_windowSizer;
+    if ( m_windowSizer )
+    {
+        m_windowSizer->SetContainingWindow(NULL);
+
+        if ( deleteOld )
+            delete m_windowSizer;
+    }
 
     m_windowSizer = sizer;
 
     m_windowSizer = sizer;
+    if ( m_windowSizer )
+    {
+        m_windowSizer->SetContainingWindow((wxWindow *)this);
+    }
 
 
-    SetAutoLayout( sizer != NULL );
+    SetAutoLayout(m_windowSizer != NULL);
 }
 
 void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld)
 }
 
 void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld)
@@ -1766,7 +2097,7 @@ bool wxWindowBase::Layout()
     // If there is a sizer, use it instead of the constraints
     if ( GetSizer() )
     {
     // If there is a sizer, use it instead of the constraints
     if ( GetSizer() )
     {
-        int w, h;
+        int w = 0, h = 0;
         GetVirtualSize(&w, &h);
         GetSizer()->SetDimension( 0, 0, w, h );
     }
         GetVirtualSize(&w, &h);
         GetSizer()->SetDimension( 0, 0, w, h );
     }
@@ -2029,7 +2360,7 @@ void wxWindowBase::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags) co
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------
-// do Update UI processing for child controls
+// Update UI processing
 // ----------------------------------------------------------------------------
 
 void wxWindowBase::UpdateWindowUI(long flags)
 // ----------------------------------------------------------------------------
 
 void wxWindowBase::UpdateWindowUI(long flags)
@@ -2055,62 +2386,14 @@ void wxWindowBase::UpdateWindowUI(long flags)
 }
 
 // do the window-specific processing after processing the update event
 }
 
 // do the window-specific processing after processing the update event
-// TODO: take specific knowledge out of this function and
-// put in each control's base class. Unfortunately we don't
-// yet have base implementation files for wxCheckBox and wxRadioButton.
 void wxWindowBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
 {
     if ( event.GetSetEnabled() )
         Enable(event.GetEnabled());
 
 void wxWindowBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
 {
     if ( event.GetSetEnabled() )
         Enable(event.GetEnabled());
 
-#if wxUSE_CONTROLS
-    if ( event.GetSetText() )
-    {
-        wxControl *control = wxDynamicCastThis(wxControl);
-        if ( control )
-        {
-            if ( event.GetText() != control->GetLabel() )
-                control->SetLabel(event.GetText());
-        }
-    }
-#endif // wxUSE_CONTROLS
-
-    if ( event.GetSetChecked() )
-    {
-#if wxUSE_CHECKBOX
-        wxCheckBox *checkbox = wxDynamicCastThis(wxCheckBox);
-        if ( checkbox )
-        {
-            checkbox->SetValue(event.GetChecked());
-        }
-#endif // wxUSE_CHECKBOX
-
-#if wxUSE_RADIOBTN
-        wxRadioButton *radiobtn = wxDynamicCastThis(wxRadioButton);
-        if ( radiobtn )
-        {
-            radiobtn->SetValue(event.GetChecked());
-        }
-#endif // wxUSE_RADIOBTN
-    }
-}
-
-#if 0
-// call internal idle recursively
-// may be obsolete (wait until OnIdle scheme stabilises)
-void wxWindowBase::ProcessInternalIdle()
-{
-    OnInternalIdle();
-
-    wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
-    while (node)
-    {
-        wxWindow *child = node->GetData();
-        child->ProcessInternalIdle();
-        node = node->GetNext();
-    }
+    if ( event.GetSetShown() )
+        Show(event.GetShown());
 }
 }
-#endif
 
 // ----------------------------------------------------------------------------
 // dialog units translations
 
 // ----------------------------------------------------------------------------
 // dialog units translations
@@ -2178,71 +2461,156 @@ void wxWindowBase::OnInitDialog( wxInitDialogEvent &WXUNUSED(event) )
     UpdateWindowUI(wxUPDATE_UI_RECURSE);
 }
 
     UpdateWindowUI(wxUPDATE_UI_RECURSE);
 }
 
-// process Ctrl-Alt-mclick
-void wxWindowBase::OnMiddleClick( wxMouseEvent& event )
+// ----------------------------------------------------------------------------
+// menu-related functions
+// ----------------------------------------------------------------------------
+
+#if wxUSE_MENUS
+
+bool wxWindowBase::PopupMenu(wxMenu *menu, int x, int y)
 {
 {
-#if wxUSE_MSGDLG
-    if ( event.ControlDown() && event.AltDown() )
-    {
-        // don't translate these strings
-        wxString port;
+    wxCHECK_MSG( menu, false, "can't popup NULL menu" );
+
+    wxCurrentPopupMenu = menu;
+    const bool rc = DoPopupMenu(menu, x, y);
+    wxCurrentPopupMenu = NULL;
+
+    return rc;
+}
 
 
-#ifdef __WXUNIVERSAL__
-        port = _T("Univ/");
-#endif // __WXUNIVERSAL__
+// this is used to pass the id of the selected item from the menu event handler
+// to the main function itself
+//
+// it's ok to use a global here as there can be at most one popup menu shown at
+// any time
+static int gs_popupMenuSelection = wxID_NONE;
+
+void wxWindowBase::InternalOnPopupMenu(wxCommandEvent& event)
+{
+    // store the id in a global variable where we'll retrieve it from later
+    gs_popupMenuSelection = event.GetId();
+}
 
 
-        switch ( wxGetOsVersion() )
+void wxWindowBase::InternalOnPopupMenuUpdate(wxUpdateUIEvent& WXUNUSED(event))
+{
+    // nothing to do but do not skip it
+}
+
+int
+wxWindowBase::DoGetPopupMenuSelectionFromUser(wxMenu& menu, int x, int y)
+{
+    gs_popupMenuSelection = wxID_NONE;
+
+    Connect(wxEVT_COMMAND_MENU_SELECTED,
+            wxCommandEventHandler(wxWindowBase::InternalOnPopupMenu),
+            NULL,
+            this);
+
+    // it is common to construct the menu passed to this function dynamically
+    // using some fixed range of ids which could clash with the ids used
+    // elsewhere in the program, which could result in some menu items being
+    // unintentionally disabled or otherwise modified by update UI handlers
+    // elsewhere in the program code and this is difficult to avoid in the
+    // program itself, so instead we just temporarily suspend UI updating while
+    // this menu is shown
+    Connect(wxEVT_UPDATE_UI,
+            wxUpdateUIEventHandler(wxWindowBase::InternalOnPopupMenuUpdate),
+            NULL,
+            this);
+
+    PopupMenu(&menu, x, y);
+
+    Disconnect(wxEVT_UPDATE_UI,
+               wxUpdateUIEventHandler(wxWindowBase::InternalOnPopupMenuUpdate),
+               NULL,
+               this);
+    Disconnect(wxEVT_COMMAND_MENU_SELECTED,
+               wxCommandEventHandler(wxWindowBase::InternalOnPopupMenu),
+               NULL,
+               this);
+
+    return gs_popupMenuSelection;
+}
+
+#endif // wxUSE_MENUS
+
+// methods for drawing the sizers in a visible way
+#ifdef __WXDEBUG__
+
+static void DrawSizers(wxWindowBase *win);
+
+static void DrawBorder(wxWindowBase *win, const wxRect& rect, bool fill = false)
+{
+    wxClientDC dc((wxWindow *)win);
+    dc.SetPen(*wxRED_PEN);
+    dc.SetBrush(fill ? wxBrush(*wxRED, wxBRUSHSTYLE_CROSSDIAG_HATCH) : *wxTRANSPARENT_BRUSH);
+    dc.DrawRectangle(rect.Deflate(1, 1));
+}
+
+static void DrawSizer(wxWindowBase *win, wxSizer *sizer)
+{
+    const wxSizerItemList& items = sizer->GetChildren();
+    for ( wxSizerItemList::const_iterator i = items.begin(),
+                                        end = items.end();
+          i != end;
+          ++i )
+    {
+        wxSizerItem *item = *i;
+        if ( item->IsSizer() )
+        {
+            DrawBorder(win, item->GetRect().Deflate(2));
+            DrawSizer(win, item->GetSizer());
+        }
+        else if ( item->IsSpacer() )
+        {
+            DrawBorder(win, item->GetRect().Deflate(2), true);
+        }
+        else if ( item->IsWindow() )
         {
         {
-            case wxMOTIF_X:     port += _T("Motif"); break;
-            case wxMAC:
-            case wxMAC_DARWIN:  port += _T("Mac"); break;
-            case wxBEOS:        port += _T("BeOS"); break;
-            case wxGTK:
-            case wxGTK_WIN32:
-            case wxGTK_OS2:
-            case wxGTK_BEOS:    port += _T("GTK"); break;
-            case wxWINDOWS:
-            case wxPENWINDOWS:
-            case wxWINDOWS_NT:
-            case wxWIN32S:
-            case wxWIN95:
-            case wxWIN386:      port += _T("MS Windows"); break;
-            case wxMGL_UNIX:
-            case wxMGL_X:
-            case wxMGL_WIN32:
-            case wxMGL_OS2:     port += _T("MGL"); break;
-            case wxWINDOWS_OS2:
-            case wxOS2_PM:      port += _T("OS/2"); break;
-            default:            port += _T("unknown"); break;
+            DrawSizers(item->GetWindow());
         }
         }
+    }
+}
 
 
-        wxMessageBox(wxString::Format(
-                                      _T(
-                                        "       wxWidgets Library (%s port)\nVersion %u.%u.%u%s%s, compiled at %s %s\n   Copyright (c) 1995-2004 wxWidgets team"
-                                        ),
-                                      port.c_str(),
-                                      wxMAJOR_VERSION,
-                                      wxMINOR_VERSION,
-                                      wxRELEASE_NUMBER,
-#if wxUSE_UNICODE
-                                      L" (Unicode)",
-#else
-                                      "",
-#endif
+static void DrawSizers(wxWindowBase *win)
+{
+    wxSizer *sizer = win->GetSizer();
+    if ( sizer )
+    {
+        DrawBorder(win, win->GetClientSize());
+        DrawSizer(win, sizer);
+    }
+    else // no sizer, still recurse into the children
+    {
+        const wxWindowList& children = win->GetChildren();
+        for ( wxWindowList::const_iterator i = children.begin(),
+                                         end = children.end();
+              i != end;
+              ++i )
+        {
+            DrawSizers(*i);
+        }
+    }
+}
+
+#endif // __WXDEBUG__
+
+// process special middle clicks
+void wxWindowBase::OnMiddleClick( wxMouseEvent& event )
+{
+    if ( event.ControlDown() && event.AltDown() )
+    {
 #ifdef __WXDEBUG__
 #ifdef __WXDEBUG__
-                                      _T(" Debug build"),
-#else
-                                      _T(""),
-#endif
-                                      __TDATE__,
-                                      __TTIME__
-                                     ),
-                     _T("wxWidgets information"),
-                     wxICON_INFORMATION | wxOK,
-                     (wxWindow *)this);
+        // Ctrl-Alt-Shift-mclick makes the sizers visible in debug builds
+        if ( event.ShiftDown() )
+        {
+            DrawSizers(this);
+            return;
+        }
+#endif // __WXDEBUG__
+        ::wxInfoMessageBox((wxWindow*)this);
     }
     else
     }
     else
-#endif // wxUSE_MSGDLG
     {
         event.Skip();
     }
     {
         event.Skip();
     }
@@ -2278,16 +2646,23 @@ wxAccessible* wxWindowBase::CreateAccessible()
 
 #endif
 
 
 #endif
 
-#if !wxUSE_STL
 // ----------------------------------------------------------------------------
 // list classes implementation
 // ----------------------------------------------------------------------------
 
 // ----------------------------------------------------------------------------
 // list classes implementation
 // ----------------------------------------------------------------------------
 
+#if wxUSE_STL
+
+#include "wx/listimpl.cpp"
+WX_DEFINE_LIST(wxWindowList)
+
+#else // !wxUSE_STL
+
 void wxWindowListNode::DeleteData()
 {
     delete (wxWindow *)GetData();
 }
 void wxWindowListNode::DeleteData()
 {
     delete (wxWindow *)GetData();
 }
-#endif
+
+#endif // wxUSE_STL/!wxUSE_STL
 
 // ----------------------------------------------------------------------------
 // borders
 
 // ----------------------------------------------------------------------------
 // borders
@@ -2300,6 +2675,10 @@ wxBorder wxWindowBase::GetBorder(long flags) const
     {
         border = GetDefaultBorder();
     }
     {
         border = GetDefaultBorder();
     }
+    else if ( border == wxBORDER_THEME )
+    {
+        border = GetDefaultBorderForControl();
+    }
 
     return border;
 }
 
     return border;
 }
@@ -2338,10 +2717,16 @@ struct WXDLLEXPORT wxWindowNext
     wxWindow *win;
     wxWindowNext *next;
 } *wxWindowBase::ms_winCaptureNext = NULL;
     wxWindow *win;
     wxWindowNext *next;
 } *wxWindowBase::ms_winCaptureNext = NULL;
+wxWindow *wxWindowBase::ms_winCaptureCurrent = NULL;
+bool wxWindowBase::ms_winCaptureChanging = false;
 
 void wxWindowBase::CaptureMouse()
 {
 
 void wxWindowBase::CaptureMouse()
 {
-    wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), this);
+    wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), static_cast<void*>(this));
+
+    wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive CaptureMouse call?") );
+
+    ms_winCaptureChanging = true;
 
     wxWindow *winOld = GetCapture();
     if ( winOld )
 
     wxWindow *winOld = GetCapture();
     if ( winOld )
@@ -2357,19 +2742,31 @@ void wxWindowBase::CaptureMouse()
     //else: no mouse capture to save
 
     DoCaptureMouse();
     //else: no mouse capture to save
 
     DoCaptureMouse();
+    ms_winCaptureCurrent = (wxWindow*)this;
+
+    ms_winCaptureChanging = false;
 }
 
 void wxWindowBase::ReleaseMouse()
 {
 }
 
 void wxWindowBase::ReleaseMouse()
 {
-    wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), this);
+    wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), static_cast<void*>(this));
+
+    wxASSERT_MSG( !ms_winCaptureChanging, _T("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" );
 
 
-    wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") );
+    ms_winCaptureChanging = true;
 
     DoReleaseMouse();
 
     DoReleaseMouse();
+    ms_winCaptureCurrent = NULL;
 
     if ( ms_winCaptureNext )
     {
         ((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse();
 
     if ( ms_winCaptureNext )
     {
         ((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse();
+        ms_winCaptureCurrent = ms_winCaptureNext->win;
 
         wxWindowNext *item = ms_winCaptureNext;
         ms_winCaptureNext = item->next;
 
         wxWindowNext *item = ms_winCaptureNext;
         ms_winCaptureNext = item->next;
@@ -2377,9 +2774,53 @@ void wxWindowBase::ReleaseMouse()
     }
     //else: stack is empty, no previous capture
 
     }
     //else: stack is empty, no previous capture
 
+    ms_winCaptureChanging = false;
+
     wxLogTrace(_T("mousecapture"),
         (const wxChar *) _T("After ReleaseMouse() mouse is captured by %p"),
     wxLogTrace(_T("mousecapture"),
         (const wxChar *) _T("After ReleaseMouse() mouse is captured by %p"),
-        GetCapture());
+        static_cast<void*>(GetCapture()));
+}
+
+static void DoNotifyWindowAboutCaptureLost(wxWindow *win)
+{
+    wxMouseCaptureLostEvent event(win->GetId());
+    event.SetEventObject(win);
+    if ( !win->GetEventHandler()->ProcessEvent(event) )
+    {
+        // windows must handle this event, otherwise the app wouldn't behave
+        // correctly if it loses capture unexpectedly; see the discussion here:
+        // http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863
+        // http://article.gmane.org/gmane.comp.lib.wxwidgets.devel/82376
+        wxFAIL_MSG( _T("window that captured the mouse didn't process wxEVT_MOUSE_CAPTURE_LOST") );
+    }
+}
+
+/* static */
+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 )
+        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 )
+    {
+        DoNotifyWindowAboutCaptureLost(ms_winCaptureCurrent);
+        ms_winCaptureCurrent = NULL;
+    }
+
+    while ( ms_winCaptureNext )
+    {
+        wxWindowNext *item = ms_winCaptureNext;
+        ms_winCaptureNext = item->next;
+
+        DoNotifyWindowAboutCaptureLost(item->win);
+
+        delete item;
+    }
 }
 
 #if wxUSE_HOTKEY
 }
 
 #if wxUSE_HOTKEY
@@ -2401,14 +2842,6 @@ bool wxWindowBase::UnregisterHotKey(int WXUNUSED(hotkeyId))
 
 #endif // wxUSE_HOTKEY
 
 
 #endif // wxUSE_HOTKEY
 
-void wxWindowBase::SendDestroyEvent()
-{
-    wxWindowDestroyEvent event;
-    event.SetEventObject(this);
-    event.SetId(GetId());
-    GetEventHandler()->ProcessEvent(event);
-}
-
 // ----------------------------------------------------------------------------
 // event processing
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // event processing
 // ----------------------------------------------------------------------------
@@ -2420,8 +2853,8 @@ bool wxWindowBase::TryValidator(wxEvent& wxVALIDATOR_PARAM(event))
     // is receiving the event
     if ( event.GetEventObject() == this )
     {
     // is receiving the event
     if ( event.GetEventObject() == this )
     {
-        wxValidator *validator = GetValidator();
-        if ( validator && validator->ProcessEvent(event) )
+        wxValidator * const validator = GetValidator();
+        if ( validator && validator->ProcessEventHere(event) )
         {
             return true;
         }
         {
             return true;
         }
@@ -2433,7 +2866,7 @@ bool wxWindowBase::TryValidator(wxEvent& wxVALIDATOR_PARAM(event))
 
 bool wxWindowBase::TryParent(wxEvent& event)
 {
 
 bool wxWindowBase::TryParent(wxEvent& event)
 {
-    // carry on up the parent-child hierarchy if the propgation count hasn't
+    // carry on up the parent-child hierarchy if the propagation count hasn't
     // reached zero yet
     if ( event.ShouldPropagate() )
     {
     // reached zero yet
     if ( event.ShouldPropagate() )
     {
@@ -2456,24 +2889,68 @@ bool wxWindowBase::TryParent(wxEvent& event)
     return wxEvtHandler::TryParent(event);
 }
 
     return wxEvtHandler::TryParent(event);
 }
 
+// ----------------------------------------------------------------------------
+// window relationships
+// ----------------------------------------------------------------------------
+
+wxWindow *wxWindowBase::DoGetSibling(WindowOrder order) const
+{
+    wxCHECK_MSG( GetParent(), NULL,
+                    _T("GetPrev/NextSibling() don't work for TLWs!") );
+
+    wxWindowList& siblings = GetParent()->GetChildren();
+    wxWindowList::compatibility_iterator i = siblings.Find((wxWindow *)this);
+    wxCHECK_MSG( i, NULL, _T("window not a child of its parent?") );
+
+    if ( order == OrderBefore )
+        i = i->GetPrevious();
+    else // OrderAfter
+        i = i->GetNext();
+
+    return i ? i->GetData() : NULL;
+}
+
 // ----------------------------------------------------------------------------
 // keyboard navigation
 // ----------------------------------------------------------------------------
 
 // ----------------------------------------------------------------------------
 // keyboard navigation
 // ----------------------------------------------------------------------------
 
-// Navigates in the specified direction.
-bool wxWindowBase::Navigate(int flags)
+// Navigates in the specified direction inside this window
+bool wxWindowBase::DoNavigateIn(int flags)
 {
 {
+#ifdef wxHAS_NATIVE_TAB_TRAVERSAL
+    // native code doesn't process our wxNavigationKeyEvents anyhow
+    wxUnusedVar(flags);
+    return false;
+#else // !wxHAS_NATIVE_TAB_TRAVERSAL
     wxNavigationKeyEvent eventNav;
     wxNavigationKeyEvent eventNav;
+    wxWindow *focused = FindFocus();
+    eventNav.SetCurrentFocus(focused);
+    eventNav.SetEventObject(focused);
     eventNav.SetFlags(flags);
     eventNav.SetFlags(flags);
-    eventNav.SetEventObject(this);
-    if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) )
-    {
-        return true;
-    }
-    return false;
+    return GetEventHandler()->ProcessEvent(eventNav);
+#endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
 }
 
 }
 
-void wxWindowBase::DoMoveInTabOrder(wxWindow *win, MoveKind move)
+bool wxWindowBase::HandleAsNavigationKey(const wxKeyEvent& event)
+{
+    if ( event.GetKeyCode() != WXK_TAB )
+        return false;
+
+    int flags = wxNavigationKeyEvent::FromTab;
+
+    if ( event.ShiftDown() )
+        flags |= wxNavigationKeyEvent::IsBackward;
+    else
+        flags |= wxNavigationKeyEvent::IsForward;
+
+    if ( event.ControlDown() )
+        flags |= wxNavigationKeyEvent::WinChange;
+
+    Navigate(flags);
+    return true;
+}
+
+void wxWindowBase::DoMoveInTabOrder(wxWindow *win, WindowOrder move)
 {
     // check that we're not a top level window
     wxCHECK_RET( GetParent(),
 {
     // check that we're not a top level window
     wxCHECK_RET( GetParent(),
@@ -2493,7 +2970,7 @@ void wxWindowBase::DoMoveInTabOrder(wxWindow *win, MoveKind move)
     // can't just move the node around
     wxWindow *self = (wxWindow *)this;
     siblings.DeleteObject(self);
     // can't just move the node around
     wxWindow *self = (wxWindow *)this;
     siblings.DeleteObject(self);
-    if ( move == MoveAfter )
+    if ( move == OrderAfter )
     {
         i = i->GetNext();
     }
     {
         i = i->GetNext();
     }
@@ -2502,7 +2979,7 @@ void wxWindowBase::DoMoveInTabOrder(wxWindow *win, MoveKind move)
     {
         siblings.Insert(i, self);
     }
     {
         siblings.Insert(i, self);
     }
-    else // MoveAfter and win was the last sibling
+    else // OrderAfter and win was the last sibling
     {
         siblings.Append(self);
     }
     {
         siblings.Append(self);
     }
@@ -2518,6 +2995,68 @@ void wxWindowBase::DoMoveInTabOrder(wxWindow *win, MoveKind move)
     return win ? win->GetMainWindowOfCompositeControl() : NULL;
 }
 
     return win ? win->GetMainWindowOfCompositeControl() : NULL;
 }
 
+bool wxWindowBase::HasFocus() const
+{
+    wxWindowBase *win = DoFindFocus();
+    return win == this ||
+           win == wxConstCast(this, wxWindowBase)->GetMainWindowOfCompositeControl();
+}
+
+// ----------------------------------------------------------------------------
+// drag and drop
+// ----------------------------------------------------------------------------
+
+#if wxUSE_DRAG_AND_DROP && !defined(__WXMSW__)
+
+namespace
+{
+
+class DragAcceptFilesTarget : public wxFileDropTarget
+{
+public:
+    DragAcceptFilesTarget(wxWindowBase *win) : m_win(win) {}
+
+    virtual bool OnDropFiles(wxCoord x, wxCoord y,
+                             const wxArrayString& filenames)
+    {
+        wxDropFilesEvent event(wxEVT_DROP_FILES,
+                               filenames.size(),
+                               wxCArrayString(filenames).Release());
+        event.SetEventObject(m_win);
+        event.m_pos.x = x;
+        event.m_pos.y = y;
+
+        return m_win->HandleWindowEvent(event);
+    }
+
+private:
+    wxWindowBase * const m_win;
+
+    DECLARE_NO_COPY_CLASS(DragAcceptFilesTarget)
+};
+
+
+} // anonymous namespace
+
+// Generic version of DragAcceptFiles(). It works by installing a simple
+// wxFileDropTarget-to-EVT_DROP_FILES adaptor and therefore cannot be used
+// together with explicit SetDropTarget() calls.
+void wxWindowBase::DragAcceptFiles(bool accept)
+{
+    if ( accept )
+    {
+        wxASSERT_MSG( !GetDropTarget(),
+                      "cannot use DragAcceptFiles() and SetDropTarget() together" );
+        SetDropTarget(new DragAcceptFilesTarget(this));
+    }
+    else
+    {
+        SetDropTarget(NULL);
+    }
+}
+
+#endif // wxUSE_DRAG_AND_DROP && !defined(__WXMSW__)
+
 // ----------------------------------------------------------------------------
 // global functions
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // global functions
 // ----------------------------------------------------------------------------
@@ -2800,7 +3339,7 @@ wxAccStatus wxWindowAccessible::GetDescription(int WXUNUSED(childId), wxString*
     if (!GetWindow())
         return wxACC_FAIL;
 
     if (!GetWindow())
         return wxACC_FAIL;
 
-    wxString ht(GetWindow()->GetHelpText());
+    wxString ht(GetWindow()->GetHelpTextAtPoint(wxDefaultPosition, wxHelpEvent::Origin_Keyboard));
     if (!ht.empty())
     {
         *description = ht;
     if (!ht.empty())
     {
         *description = ht;
@@ -2816,7 +3355,7 @@ wxAccStatus wxWindowAccessible::GetHelpText(int WXUNUSED(childId), wxString* hel
     if (!GetWindow())
         return wxACC_FAIL;
 
     if (!GetWindow())
         return wxACC_FAIL;
 
-    wxString ht(GetWindow()->GetHelpText());
+    wxString ht(GetWindow()->GetHelpTextAtPoint(wxDefaultPosition, wxHelpEvent::Origin_Keyboard));
     if (!ht.empty())
     {
         *helpText = ht;
     if (!ht.empty())
     {
         *helpText = ht;
@@ -2934,6 +3473,7 @@ wxAccStatus wxWindowAccessible::GetFocus(int* WXUNUSED(childId), wxAccessible**
     return wxACC_NOT_IMPLEMENTED;
 }
 
     return wxACC_NOT_IMPLEMENTED;
 }
 
+#if wxUSE_VARIANT
 // Gets a variant representing the selected children
 // of this object.
 // Acceptable values:
 // Gets a variant representing the selected children
 // of this object.
 // Acceptable values:
@@ -2950,5 +3490,25 @@ wxAccStatus wxWindowAccessible::GetSelections(wxVariant* WXUNUSED(selections))
 
     return wxACC_NOT_IMPLEMENTED;
 }
 
     return wxACC_NOT_IMPLEMENTED;
 }
+#endif // wxUSE_VARIANT
 
 #endif // wxUSE_ACCESSIBILITY
 
 #endif // wxUSE_ACCESSIBILITY
+
+// ----------------------------------------------------------------------------
+// RTL support
+// ----------------------------------------------------------------------------
+
+wxCoord
+wxWindowBase::AdjustForLayoutDirection(wxCoord x,
+                                       wxCoord width,
+                                       wxCoord widthTotal) const
+{
+    if ( GetLayoutDirection() == wxLayout_RightToLeft )
+    {
+        x = widthTotal - x - width;
+    }
+
+    return x;
+}
+
+