]> git.saurik.com Git - wxWidgets.git/blobdiff - src/univ/winuniv.cpp
added wxNativeContainerWindow and implemented it for wxMSW and wxGTK
[wxWidgets.git] / src / univ / winuniv.cpp
index dbb420c484c78fcf24e4b33ff5d96105654a78fd..bea3acdaf1054b8d819516b8d54fe1f612a23b11 100644 (file)
@@ -1,12 +1,12 @@
 ///////////////////////////////////////////////////////////////////////////////
-// Name:        univ/window.cpp
+// Name:        src/univ/window.cpp
 // Purpose:     implementation of extra wxWindow methods for wxUniv port
 // Author:      Vadim Zeitlin
 // Modified by:
 // Created:     06.08.00
 // RCS-ID:      $Id$
 // Copyright:   (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
-// Licence:     wxWindows license
+// Licence:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 
 // ===========================================================================
 // headers
 // ---------------------------------------------------------------------------
 
-#ifdef __GNUG__
-    #pragma implementation "univwindow.h"
-#endif
-
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
     #pragma hdrstop
 #endif
 
+#include "wx/window.h"
+
 #ifndef WX_PRECOMP
     #include "wx/app.h"
-    #include "wx/window.h"
     #include "wx/dcclient.h"
     #include "wx/dcmemory.h"
     #include "wx/event.h"
     #include "wx/scrolbar.h"
     #include "wx/menu.h"
     #include "wx/frame.h"
+    #include "wx/log.h"
 #endif // WX_PRECOMP
 
 #include "wx/univ/colschem.h"
 // implementation
 // ============================================================================
 
+// ----------------------------------------------------------------------------
+// scrollbars class
+// ----------------------------------------------------------------------------
+
+// This is scrollbar class used to implement wxWindow's "built-in" scrollbars;
+// unlike the standard wxScrollBar class, this one is positioned outside of its
+// parent's client area
+class wxWindowScrollBar : public wxScrollBar
+{
+public:
+    wxWindowScrollBar(wxWindow *parent,
+                      wxWindowID id,
+                      const wxPoint& pos = wxDefaultPosition,
+                      const wxSize& size = wxDefaultSize,
+                      long style = wxSB_HORIZONTAL)
+        : wxScrollBar(parent, id, pos, size, style)
+    {
+    }
+
+    virtual bool CanBeOutsideClientArea() const { return true; }
+};
+
+
 // ----------------------------------------------------------------------------
 // event tables
 // ----------------------------------------------------------------------------
     IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowGTK)
 #elif defined(__WXMGL__)
     IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowMGL)
+#elif defined(__WXDFB__)
+    IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowDFB)
+#elif defined(__WXX11__)
+    IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowX11)
 #elif defined(__WXPM__)
     IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowOS2)
 #endif
@@ -100,12 +125,17 @@ END_EVENT_TABLE()
 
 void wxWindow::Init()
 {
+#if wxUSE_SCROLLBAR
     m_scrollbarVert =
     m_scrollbarHorz = (wxScrollBar *)NULL;
+#endif // wxUSE_SCROLLBAR
 
-    m_isCurrent = FALSE;
+    m_isCurrent = false;
 
     m_renderer = wxTheme::Get()->GetRenderer();
+
+    m_oldSize.x = wxDefaultCoord;
+    m_oldSize.y = wxDefaultCoord;
 }
 
 bool wxWindow::Create(wxWindow *parent,
@@ -115,27 +145,99 @@ bool wxWindow::Create(wxWindow *parent,
                       long style,
                       const wxString& name)
 {
+    // Get default border
+    wxBorder border = GetBorder(style);
+    style &= ~wxBORDER_MASK;
+    style |= border;
+
+    long actualStyle = style;
+
     // we add wxCLIP_CHILDREN to get the same ("natural") behaviour under MSW
     // as under the other platforms
-    if ( !wxWindowNative::Create(parent, id, pos, size,
-                                 style | wxCLIP_CHILDREN,
-                                 name) )
+    actualStyle |= wxCLIP_CHILDREN;
+
+    actualStyle &= ~wxVSCROLL;
+    actualStyle &= ~wxHSCROLL;
+
+#ifdef __WXMSW__
+    // without this, borders (non-client areas in general) are not repainted
+    // correctly when resizing; apparently, native NC areas are fully repainted
+    // even without this style by MSW, but wxUniv implements client area
+    // itself, so it doesn't work correctly for us
+    //
+    // FIXME: this is very expensive, we need to fix the (commented-out) code
+    //        in OnSize() instead
+    actualStyle |= wxFULL_REPAINT_ON_RESIZE;
+#endif
+
+    if ( !wxWindowNative::Create(parent, id, pos, size, actualStyle, name) )
+        return false;
+
+    // Set full style again, including those we didn't want present
+    // when calling the base window Create().
+    wxWindowBase::SetWindowStyleFlag(style);
+
+    // if we allow or should always have a vertical scrollbar, make it
+    if ( style & wxVSCROLL || style & wxALWAYS_SHOW_SB )
     {
-        return FALSE;
+#if wxUSE_TWO_WINDOWS
+        SetInsertIntoMain( true );
+#endif
+#if wxUSE_SCROLLBAR
+        m_scrollbarVert = new wxWindowScrollBar(this, wxID_ANY,
+                                                wxDefaultPosition, wxDefaultSize,
+                                                wxSB_VERTICAL);
+#endif // wxUSE_SCROLLBAR
+#if wxUSE_TWO_WINDOWS
+        SetInsertIntoMain( false );
+#endif
     }
 
-    // if we should always have the scrollbar, do show it
-    if ( GetWindowStyle() & wxALWAYS_SHOW_SB )
+    // if we should allow a horizontal scrollbar, make it
+    if ( style & wxHSCROLL )
     {
-        m_scrollbarVert = new wxScrollBar(this, -1,
-                                          wxDefaultPosition, wxDefaultSize,
-                                          wxSB_VERTICAL);
+#if wxUSE_TWO_WINDOWS
+        SetInsertIntoMain( true );
+#endif
+#if wxUSE_SCROLLBAR
+        m_scrollbarHorz = new wxWindowScrollBar(this, wxID_ANY,
+                                                wxDefaultPosition, wxDefaultSize,
+                                                wxSB_HORIZONTAL);
+#endif // wxUSE_SCROLLBAR
+#if wxUSE_TWO_WINDOWS
+        SetInsertIntoMain( false );
+#endif
+    }
 
-        // and position it
+#if wxUSE_SCROLLBAR
+    if (m_scrollbarHorz || m_scrollbarVert)
+    {
+        // position it/them
         PositionScrollbars();
     }
+#endif // wxUSE_SCROLLBAR
+
+    return true;
+}
+
+wxWindow::~wxWindow()
+{
+    m_isBeingDeleted = true;
+
+#if wxUSE_SCROLLBAR
+    // clear pointers to scrollbar before deleting the children: they are
+    // children and so will be deleted by DestroyChildren() call below and if
+    // any code using the scrollbars would be called in the process or from
+    // ~wxWindowBase, the app would crash:
+    m_scrollbarVert = m_scrollbarHorz = NULL;
+#endif
 
-    return TRUE;
+    // we have to destroy our children before we're destroyed because our
+    // children suppose that we're of type wxWindow, not just wxWindowNative,
+    // and so bad things may happen if they're deleted from the base class dtor
+    // as by then we're not a wxWindow any longer and wxUniv-specific virtual
+    // functions can't be called
+    DestroyChildren();
 }
 
 // ----------------------------------------------------------------------------
@@ -169,52 +271,15 @@ const wxBitmap& wxWindow::GetBackgroundBitmap(int *alignment,
 // painting
 // ----------------------------------------------------------------------------
 
-// the event handler executed when the window background must be painted
-void wxWindow::OnErase(wxEraseEvent& event)
-{
-    if ( !m_renderer )
-    {
-        event.Skip();
-
-        return;
-    }
-
-    DoDrawBackground(*event.GetDC());
-
-    // if we have both scrollbars, we also have a square in the corner between
-    // them which we must paint
-    if ( m_scrollbarVert && m_scrollbarHorz )
-    {
-        wxSize size = GetSize();
-        wxRect rectClient = GetClientRect(),
-               rectBorder = m_renderer->GetBorderDimensions(GetBorder());
-
-        wxRect rectCorner;
-        rectCorner.x = rectClient.GetRight() + 1;
-        rectCorner.y = rectClient.GetBottom() + 1;
-        rectCorner.SetRight(size.x - rectBorder.width);
-        rectCorner.SetBottom(size.y - rectBorder.height);
-
-        if ( GetUpdateRegion().Contains(rectCorner) )
-        {
-            m_renderer->DrawScrollCorner(*event.GetDC(), rectCorner);
-        }
-    }
-}
-
 // the event handlers executed when the window must be repainted
-void wxWindow::OnNcPaint(wxPaintEvent& event)
+void wxWindow::OnNcPaint(wxNcPaintEvent& WXUNUSED(event))
 {
     if ( m_renderer )
     {
         // get the window rect
-        wxRect rect;
-        wxSize size = GetSize();
-        rect.x =
-        rect.y = 0;
-        rect.width = size.x;
-        rect.height = size.y;
+        wxRect rect(GetSize());
 
+#if wxUSE_SCROLLBAR
         // if the scrollbars are outside the border, we must adjust the rect to
         // exclude them
         if ( !m_renderer->AreScrollbarsInsideBorder() )
@@ -227,6 +292,7 @@ void wxWindow::OnNcPaint(wxPaintEvent& event)
             if ( scrollbar )
                 rect.height -= scrollbar->GetSize().y;
         }
+#endif // wxUSE_SCROLLBAR
 
         // get the DC and draw the border on it
         wxWindowDC dc(this);
@@ -252,43 +318,109 @@ void wxWindow::OnPaint(wxPaintEvent& event)
     }
 }
 
+// the event handler executed when the window background must be painted
+void wxWindow::OnErase(wxEraseEvent& event)
+{
+    if ( !m_renderer )
+    {
+        event.Skip();
+
+        return;
+    }
+
+    DoDrawBackground(*event.GetDC());
+
+#if wxUSE_SCROLLBAR
+    // if we have both scrollbars, we also have a square in the corner between
+    // them which we must paint
+    if ( m_scrollbarVert && m_scrollbarHorz )
+    {
+        wxSize size = GetSize();
+        wxRect rectClient = GetClientRect(),
+               rectBorder = m_renderer->GetBorderDimensions(GetBorder());
+
+        wxRect rectCorner;
+        rectCorner.x = rectClient.GetRight() + 1;
+        rectCorner.y = rectClient.GetBottom() + 1;
+        rectCorner.SetRight(size.x - rectBorder.width);
+        rectCorner.SetBottom(size.y - rectBorder.height);
+
+        if ( GetUpdateRegion().Contains(rectCorner) )
+        {
+            m_renderer->DrawScrollCorner(*event.GetDC(), rectCorner);
+        }
+    }
+#endif // wxUSE_SCROLLBAR
+}
+
 bool wxWindow::DoDrawBackground(wxDC& dc)
 {
-    // FIXME: leaving this code in leads to partial bg redraws sometimes under
-    //        MSW
     wxRect rect;
-#ifndef __WXMSW__
-    rect = GetUpdateRegion().GetBox();
-    if ( !rect.width && !rect.height )
-#endif
+
+    wxSize size = GetSize();  // Why not GetClientSize() ?
+    rect.x = 0;
+    rect.y = 0;
+    rect.width = size.x;
+    rect.height = size.y;
+
+    wxWindow * const parent = GetParent();
+    if ( HasTransparentBackground() && !UseBgCol() && parent )
     {
-        wxSize size = GetSize();
-        rect.width = size.x;
-        rect.height = size.y;
+        // DirectFB paints the parent first, then its child windows, so by
+        // the time this code is called, parent's background was already
+        // drawn and there's no point in (imperfectly!) duplicating the work
+        // here:
+#ifndef __WXDFB__
+        wxASSERT( !IsTopLevel() );
+
+        wxPoint pos = GetPosition();
+
+        AdjustForParentClientOrigin( pos.x, pos.y, 0 );
+
+        // Adjust DC logical origin
+        wxCoord org_x, org_y, x, y;
+        dc.GetLogicalOrigin( &org_x, &org_y );
+        x = org_x + pos.x;
+        y = org_y + pos.y;
+        dc.SetLogicalOrigin( x, y );
+
+        // Adjust draw rect
+        rect.x = pos.x;
+        rect.y = pos.y;
+
+        // Let parent draw the background
+        parent->EraseBackground( dc, rect );
+
+        // Restore DC logical origin
+        dc.SetLogicalOrigin( org_x, org_y );
+#endif // !__WXDFB__
+    }
+    else
+    {
+        // Draw background ourselves
+        EraseBackground( dc, rect );
     }
 
+    return true;
+}
+
+void wxWindow::EraseBackground(wxDC& dc, const wxRect& rect)
+{
     if ( GetBackgroundBitmap().Ok() )
     {
-        // get the bitmap and the flags
+        // Get the bitmap and the flags
         int alignment;
         wxStretch stretch;
         wxBitmap bmp = GetBackgroundBitmap(&alignment, &stretch);
         wxControlRenderer::DrawBitmap(dc, bmp, rect, alignment, stretch);
     }
-    else // just fill it with bg colour if no bitmap
+    else
     {
+        // Just fill it with bg colour if no bitmap
+
         m_renderer->DrawBackground(dc, wxTHEME_BG_COLOUR(this),
                                    rect, GetStateFlags());
     }
-
-    return TRUE;
-}
-
-void wxWindow::EraseBackground(wxDC& dc, const wxRect& rect)
-{
-    // TODO: handle bg bitmaps here!
-
-    m_renderer->DrawBackground(dc, wxTHEME_BG_COLOUR(this), rect, GetStateFlags());
 }
 
 void wxWindow::DoDrawBorder(wxDC& dc, const wxRect& rect)
@@ -303,41 +435,43 @@ void wxWindow::DoDrawBorder(wxDC& dc, const wxRect& rect)
     }
 }
 
-void wxWindow::DoDraw(wxControlRenderer *renderer)
+void wxWindow::DoDraw(wxControlRenderer * WXUNUSED(renderer))
 {
 }
 
-void wxWindow::Refresh(bool eraseBackground, const wxRect *rectClient)
+void wxWindow::Refresh(bool eraseBackground, const wxRect *rect)
 {
-    wxRect rectWin;
-    wxPoint pt = GetClientAreaOrigin();
+    wxRect rectClient; // the same rectangle in client coordinates
+    wxPoint origin = GetClientAreaOrigin();
 
     wxSize size = GetClientSize();
 
-    if ( rectClient )
+    if ( rect )
     {
-        rectWin = *rectClient;
+        // the rectangle passed as argument is in client coordinates
+        rectClient = *rect;
 
         // don't refresh anything beyond the client area (scrollbars for
         // example)
-        if ( rectWin.GetRight() > size.x )
-            rectWin.SetRight(size.x);
-        if ( rectWin.GetBottom() > size.y )
-            rectWin.SetBottom(size.y);
+        if ( rectClient.GetRight() > size.x )
+            rectClient.SetRight(size.x);
+        if ( rectClient.GetBottom() > size.y )
+            rectClient.SetBottom(size.y);
 
-        rectWin.Offset(pt);
     }
     else // refresh the entire client area
     {
-        rectWin.x = pt.x;
-        rectWin.y = pt.y;
-        rectWin.width = size.x;
-        rectWin.height = size.y;
+        // x,y is already set to 0 by default
+        rectClient.SetSize(size);
     }
 
+    // convert refresh rectangle to window coordinates:
+    wxRect rectWin(rectClient);
+    rectWin.Offset(origin);
+
     // debugging helper
 #ifdef WXDEBUG_REFRESH
-    static bool s_refreshDebug = FALSE;
+    static bool s_refreshDebug = false;
     if ( s_refreshDebug )
     {
         wxWindowDC dc(this);
@@ -354,6 +488,33 @@ void wxWindow::Refresh(bool eraseBackground, const wxRect *rectClient)
 #endif // WXDEBUG_REFRESH
 
     wxWindowNative::Refresh(eraseBackground, &rectWin);
+
+    // Refresh all sub controls if any.
+    wxWindowList& children = GetChildren();
+    for ( wxWindowList::iterator i = children.begin(); i != children.end(); ++i )
+    {
+        wxWindow *child = *i;
+        // only refresh subcontrols if they are visible:
+        if ( child->IsTopLevel() || !child->IsShown() || child->IsFrozen() )
+            continue;
+
+        // ...and when the subcontrols are in the update region:
+        wxRect childrect(child->GetRect());
+        childrect.Intersect(rectClient);
+        if ( childrect.IsEmpty() )
+            continue;
+
+        // refresh the subcontrol now:
+        childrect.Offset(-child->GetPosition());
+        // NB: We must call wxWindowNative version because we need to refresh
+        //     the entire control, not just its client area, and this is why we
+        //     don't account for child client area origin here neither. Also
+        //     note that we don't pass eraseBackground to the child, but use
+        //     true instead: this is because we can't be sure that
+        //     eraseBackground=false is safe for children as well and not only
+        //     for the parent.
+        child->wxWindowNative::Refresh(eraseBackground, &childrect);
+    }
 }
 
 // ----------------------------------------------------------------------------
@@ -363,7 +524,7 @@ void wxWindow::Refresh(bool eraseBackground, const wxRect *rectClient)
 bool wxWindow::Enable(bool enable)
 {
     if ( !wxWindowNative::Enable(enable) )
-        return FALSE;
+        return false;
 
     // disabled window can't keep focus
     if ( FindFocus() == this && GetParent() != NULL )
@@ -378,23 +539,22 @@ bool wxWindow::Enable(bool enable)
         Refresh();
     }
 
-    return TRUE;
+    return true;
 }
 
 bool wxWindow::IsFocused() const
 {
-    wxWindow *self = wxConstCast(this, wxWindow);
-    return self->FindFocus() == self;
+    return FindFocus() == this;
 }
 
 bool wxWindow::IsPressed() const
 {
-    return FALSE;
+    return false;
 }
 
 bool wxWindow::IsDefault() const
 {
-    return FALSE;
+    return false;
 }
 
 bool wxWindow::IsCurrent() const
@@ -405,14 +565,14 @@ bool wxWindow::IsCurrent() const
 bool wxWindow::SetCurrent(bool doit)
 {
     if ( doit == m_isCurrent )
-        return FALSE;
+        return false;
 
     m_isCurrent = doit;
 
     if ( CanBeHighlighted() )
         Refresh();
 
-    return TRUE;
+    return true;
 }
 
 int wxWindow::GetStateFlags() const
@@ -444,12 +604,116 @@ int wxWindow::GetStateFlags() const
 
 void wxWindow::OnSize(wxSizeEvent& event)
 {
+    event.Skip();
+
+#if wxUSE_SCROLLBAR
     if ( m_scrollbarVert || m_scrollbarHorz )
     {
         PositionScrollbars();
     }
+#endif // wxUSE_SCROLLBAR
 
-    event.Skip();
+#if 0   // ndef __WXMSW__
+    // Refresh the area (strip) previously occupied by the border
+
+    if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) && IsShown() )
+    {
+        // This code assumes that wxSizeEvent.GetSize() returns
+        // the area of the entire window, not just the client
+        // area.
+        wxSize newSize = event.GetSize();
+
+        if (m_oldSize.x == wxDefaultCoord && m_oldSize.y == wxDefaultCoord)
+        {
+            m_oldSize = newSize;
+            return;
+        }
+
+        if (HasFlag( wxSIMPLE_BORDER ))
+        {
+            if (newSize.y > m_oldSize.y)
+            {
+                wxRect rect;
+                rect.x = 0;
+                rect.width = m_oldSize.x;
+                rect.y = m_oldSize.y-2;
+                rect.height = 1;
+                Refresh( true, &rect );
+            }
+            else if (newSize.y < m_oldSize.y)
+            {
+                wxRect rect;
+                rect.y = newSize.y;
+                rect.x = 0;
+                rect.height = 1;
+                rect.width = newSize.x;
+                wxWindowNative::Refresh( true, &rect );
+            }
+
+            if (newSize.x > m_oldSize.x)
+            {
+                wxRect rect;
+                rect.y = 0;
+                rect.height = m_oldSize.y;
+                rect.x = m_oldSize.x-2;
+                rect.width = 1;
+                Refresh( true, &rect );
+            }
+            else if (newSize.x < m_oldSize.x)
+            {
+                wxRect rect;
+                rect.x = newSize.x;
+                rect.y = 0;
+                rect.width = 1;
+                rect.height = newSize.y;
+                wxWindowNative::Refresh( true, &rect );
+            }
+        }
+        else
+        if (HasFlag( wxSUNKEN_BORDER ) || HasFlag( wxRAISED_BORDER ) || HasFlag( wxBORDER_THEME ))
+        {
+            if (newSize.y > m_oldSize.y)
+            {
+                wxRect rect;
+                rect.x = 0;
+                rect.width = m_oldSize.x;
+                rect.y = m_oldSize.y-4;
+                rect.height = 2;
+                Refresh( true, &rect );
+            }
+            else if (newSize.y < m_oldSize.y)
+            {
+                wxRect rect;
+                rect.y = newSize.y;
+                rect.x = 0;
+                rect.height = 2;
+                rect.width = newSize.x;
+                wxWindowNative::Refresh( true, &rect );
+            }
+
+            if (newSize.x > m_oldSize.x)
+            {
+                wxRect rect;
+                rect.y = 0;
+                rect.height = m_oldSize.y;
+                rect.x = m_oldSize.x-4;
+                rect.width = 2;
+                Refresh( true, &rect );
+            }
+            else if (newSize.x < m_oldSize.x)
+            {
+                wxRect rect;
+                rect.x = newSize.x;
+                rect.y = 0;
+                rect.width = 2;
+                rect.height = newSize.y;
+                wxWindowNative::Refresh( true, &rect );
+            }
+        }
+
+        m_oldSize = newSize;
+    }
+#endif
 }
 
 wxSize wxWindow::DoGetBestSize() const
@@ -474,8 +738,11 @@ wxPoint wxWindow::GetClientAreaOrigin() const
 {
     wxPoint pt = wxWindowBase::GetClientAreaOrigin();
 
+#if wxUSE_TWO_WINDOWS
+#else
     if ( m_renderer )
         pt += m_renderer->GetBorderDimensions(GetBorder()).GetPosition();
+#endif
 
     return pt;
 }
@@ -501,21 +768,16 @@ void wxWindow::DoGetClientSize(int *width, int *height) const
     if ( m_renderer )
         rectBorder = m_renderer->GetBorderDimensions(GetBorder());
 
-    bool inside = m_renderer->AreScrollbarsInsideBorder();
-
     if ( width )
     {
+#if wxUSE_SCROLLBAR
         // in any case, take account of the scrollbar
         if ( m_scrollbarVert )
             w -= m_scrollbarVert->GetSize().x;
+#endif // wxUSE_SCROLLBAR
 
-        // if we don't have scrollbar or if it is outside the border (and not
-        // blended into it), take account of the right border as well
-        if ( !m_scrollbarVert || inside )
-            w -= rectBorder.width;
-
-        // and always account for the left border
-        *width = w - rectBorder.x;
+        // account for the left and right borders
+        *width = w - rectBorder.x - rectBorder.width;
 
         // we shouldn't return invalid width
         if ( *width < 0 )
@@ -524,13 +786,12 @@ void wxWindow::DoGetClientSize(int *width, int *height) const
 
     if ( height )
     {
+#if wxUSE_SCROLLBAR
         if ( m_scrollbarHorz )
             h -= m_scrollbarHorz->GetSize().y;
+#endif // wxUSE_SCROLLBAR
 
-        if ( !m_scrollbarHorz || inside )
-            h -= rectBorder.height;
-
-        *height = h - rectBorder.y;
+        *height = h - rectBorder.y - rectBorder.height;
 
         // we shouldn't return invalid height
         if ( *height < 0 )
@@ -548,17 +809,18 @@ void wxWindow::DoSetClientSize(int width, int height)
     // and the scrollbars (as they may be offset into the border, use the
     // scrollbar position, not size - this supposes that PositionScrollbars()
     // had been called before)
-    bool inside = m_renderer->AreScrollbarsInsideBorder();
     wxSize size = GetSize();
+#if wxUSE_SCROLLBAR
     if ( m_scrollbarVert )
         width += size.x - m_scrollbarVert->GetPosition().x;
-    if ( !m_scrollbarVert || inside )
-        width += rectBorder.width;
+#endif // wxUSE_SCROLLBAR
+    width += rectBorder.width;
 
+#if wxUSE_SCROLLBAR
     if ( m_scrollbarHorz )
         height += size.y - m_scrollbarHorz->GetPosition().y;
-    if ( !m_scrollbarHorz || inside )
-        height += rectBorder.height;
+#endif // wxUSE_SCROLLBAR
+    height += rectBorder.height;
 
     wxWindowNative::DoSetClientSize(width, height);
 }
@@ -566,6 +828,8 @@ void wxWindow::DoSetClientSize(int width, int height)
 wxHitTest wxWindow::DoHitTest(wxCoord x, wxCoord y) const
 {
     wxHitTest ht = wxWindowNative::DoHitTest(x, y);
+
+#if wxUSE_SCROLLBAR
     if ( ht == wxHT_WINDOW_INSIDE )
     {
         if ( m_scrollbarVert && x >= m_scrollbarVert->GetPosition().x )
@@ -580,6 +844,7 @@ wxHitTest wxWindow::DoHitTest(wxCoord x, wxCoord y) const
                                                   : wxHT_WINDOW_HORZ_SCROLLBAR;
         }
     }
+#endif // wxUSE_SCROLLBAR
 
     return ht;
 }
@@ -592,15 +857,18 @@ wxHitTest wxWindow::DoHitTest(wxCoord x, wxCoord y) const
 
 void wxWindow::RefreshScrollbars()
 {
+#if wxUSE_SCROLLBAR
     if ( m_scrollbarHorz )
         m_scrollbarHorz->Refresh();
 
     if ( m_scrollbarVert )
         m_scrollbarVert->Refresh();
+#endif // wxUSE_SCROLLBAR
 }
 
 void wxWindow::PositionScrollbars()
 {
+#if wxUSE_SCROLLBAR
     // do not use GetClientSize/Rect as it relies on the scrollbars being
     // correctly positioned
 
@@ -646,6 +914,7 @@ void wxWindow::PositionScrollbars()
     }
 
     RefreshScrollbars();
+#endif // wxUSE_SCROLLBAR
 }
 
 void wxWindow::SetScrollbar(int orient,
@@ -654,27 +923,34 @@ void wxWindow::SetScrollbar(int orient,
                             int range,
                             bool refresh)
 {
+#if wxUSE_SCROLLBAR
     wxASSERT_MSG( pageSize <= range,
                     _T("page size can't be greater than range") );
 
-    bool hasClientSizeChanged = FALSE;
+    bool hasClientSizeChanged = false;
     wxScrollBar *scrollbar = GetScrollbar(orient);
     if ( range && (pageSize < range) )
     {
         if ( !scrollbar )
         {
             // create it
-            scrollbar = new wxScrollBar(this, -1,
-                                        wxDefaultPosition, wxDefaultSize,
-                                        orient & wxVERTICAL ? wxSB_VERTICAL
-                                                            : wxSB_HORIZONTAL);
+#if wxUSE_TWO_WINDOWS
+            SetInsertIntoMain( true );
+#endif
+            scrollbar = new wxWindowScrollBar(this, wxID_ANY,
+                                              wxDefaultPosition, wxDefaultSize,
+                                              orient & wxVERTICAL ? wxSB_VERTICAL
+                                                                  : wxSB_HORIZONTAL);
+#if wxUSE_TWO_WINDOWS
+            SetInsertIntoMain( false );
+#endif
             if ( orient & wxVERTICAL )
                 m_scrollbarVert = scrollbar;
             else
                 m_scrollbarHorz = scrollbar;
 
             // the client area diminished as we created a scrollbar
-            hasClientSizeChanged = TRUE;
+            hasClientSizeChanged = true;
 
             PositionScrollbars();
         }
@@ -707,7 +983,7 @@ void wxWindow::SetScrollbar(int orient,
                     m_scrollbarHorz = NULL;
 
                 // the client area increased as we removed a scrollbar
-                hasClientSizeChanged = TRUE;
+                hasClientSizeChanged = true;
 
                 // the size of the remaining scrollbar must be adjusted
                 if ( m_scrollbarHorz || m_scrollbarVert )
@@ -721,17 +997,29 @@ void wxWindow::SetScrollbar(int orient,
     // give the window a chance to relayout
     if ( hasClientSizeChanged )
     {
+#if wxUSE_TWO_WINDOWS
+        wxWindowNative::SetSize( GetSize() );
+#else
         wxSizeEvent event(GetSize());
         (void)GetEventHandler()->ProcessEvent(event);
+#endif
     }
+#else
+    wxUnusedVar(orient);
+    wxUnusedVar(pos);
+    wxUnusedVar(pageSize);
+    wxUnusedVar(range);
+    wxUnusedVar(refresh);
+#endif // wxUSE_SCROLLBAR
 }
 
-void wxWindow::SetScrollPos(int orient, int pos, bool refresh)
+void wxWindow::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
 {
+#if wxUSE_SCROLLBAR
     wxScrollBar *scrollbar = GetScrollbar(orient);
-    wxCHECK_RET( scrollbar, _T("no scrollbar to set position for") );
 
-    scrollbar->SetThumbPosition(pos);
+    if (scrollbar)
+        scrollbar->SetThumbPosition(pos);
 
     // VZ: I think we can safely ignore this as we always refresh it
     //     automatically whenever the value chanegs
@@ -739,28 +1027,55 @@ void wxWindow::SetScrollPos(int orient, int pos, bool refresh)
     if ( refresh )
         Refresh();
 #endif
+#else
+    wxUnusedVar(orient);
+    wxUnusedVar(pos);
+#endif // wxUSE_SCROLLBAR
 }
 
 int wxWindow::GetScrollPos(int orient) const
 {
+#if wxUSE_SCROLLBAR
     wxScrollBar *scrollbar = GetScrollbar(orient);
     return scrollbar ? scrollbar->GetThumbPosition() : 0;
+#else
+    wxUnusedVar(orient);
+    return 0;
+#endif // wxUSE_SCROLLBAR
 }
 
 int wxWindow::GetScrollThumb(int orient) const
 {
+#if wxUSE_SCROLLBAR
     wxScrollBar *scrollbar = GetScrollbar(orient);
     return scrollbar ? scrollbar->GetThumbSize() : 0;
+#else
+    wxUnusedVar(orient);
+    return 0;
+#endif // wxUSE_SCROLLBAR
 }
 
 int wxWindow::GetScrollRange(int orient) const
 {
+#if wxUSE_SCROLLBAR
     wxScrollBar *scrollbar = GetScrollbar(orient);
     return scrollbar ? scrollbar->GetRange() : 0;
+#else
+    wxUnusedVar(orient);
+    return 0;
+#endif // wxUSE_SCROLLBAR
 }
 
 void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
 {
+    // use native scrolling when available and do it in generic way
+    // otherwise:
+#ifdef __WXX11__
+
+    wxWindowNative::ScrollWindow(dx, dy, rect);
+
+#else // !wxX11
+
     // before scrolling it, ensure that we don't have any unpainted areas
     Update();
 
@@ -769,14 +1084,61 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
     if ( dx )
     {
         r = ScrollNoRefresh(dx, 0, rect);
-        Refresh(TRUE /* erase bkgnd */, &r);
+        Refresh(true /* erase bkgnd */, &r);
     }
 
     if ( dy )
     {
         r = ScrollNoRefresh(0, dy, rect);
-        Refresh(TRUE /* erase bkgnd */, &r);
+        Refresh(true /* erase bkgnd */, &r);
     }
+
+    // scroll children accordingly:
+    wxPoint offset(dx, dy);
+
+    for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
+         node; node = node->GetNext())
+    {
+        wxWindow *child = node->GetData();
+#if wxUSE_SCROLLBAR
+        if ( child == m_scrollbarVert || child == m_scrollbarHorz )
+            continue;
+#endif // wxUSE_SCROLLBAR
+
+        // VS: Scrolling children has non-trivial semantics. If rect=NULL then
+        //     it is easy: we scroll all children. Otherwise it gets
+        //     complicated:
+        //       1. if scrolling in one direction only, scroll only
+        //          those children that intersect shaft defined by the rectangle
+        //          and scrolling direction
+        //       2. if scrolling in both axes, scroll all children
+
+        bool shouldMove = false;
+
+        if ( rect && (dx * dy == 0 /* moving in only one of x, y axis */) )
+        {
+            wxRect childRect = child->GetRect();
+            if ( dx == 0 && (childRect.GetLeft() <= rect->GetRight() ||
+                             childRect.GetRight() >= rect->GetLeft()) )
+            {
+                shouldMove = true;
+            }
+            else if ( dy == 0 && (childRect.GetTop() <= rect->GetBottom() ||
+                                  childRect.GetBottom() >= rect->GetTop()) )
+            {
+                shouldMove = true;
+            }
+            // else: child outside of scrolling shaft, don't move
+        }
+        else // scrolling in both axes or rect=NULL
+        {
+            shouldMove = true;
+        }
+
+        if ( shouldMove )
+            child->Move(child->GetPosition() + offset, wxSIZE_ALLOW_MINUS_ONE);
+    }
+#endif // wxX11/!wxX11
 }
 
 wxRect wxWindow::ScrollNoRefresh(int dx, int dy, const wxRect *rectTotal)
@@ -859,12 +1221,12 @@ wxRect wxWindow::ScrollNoRefresh(int dx, int dy, const wxRect *rectTotal)
         wxMemoryDC dcMem;
         dcMem.SelectObject(bmp);
 
-        dcMem.Blit(wxPoint(0, 0), size, &dc, ptSource
+        dcMem.Blit(wxPoint(0,0), size, &dc, ptSource
 #if defined(__WXGTK__) && !defined(wxHAS_WORKING_GTK_DC_BLIT)
                 + GetClientAreaOrigin()
 #endif // broken wxGTK wxDC::Blit
                   );
-        dc.Blit(ptDest, size, &dcMem, wxPoint(0, 0));
+        dc.Blit(ptDest, size, &dcMem, wxPoint(0,0));
 
         wxLogTrace(_T("scroll"),
                    _T("Blit: (%d, %d) of size %dx%d -> (%d, %d)"),
@@ -933,53 +1295,6 @@ wxRect wxWindow::ScrollNoRefresh(int dx, int dy, const wxRect *rectTotal)
     return rect;
 }
 
-// ----------------------------------------------------------------------------
-// mouse capture
-// ----------------------------------------------------------------------------
-
-struct WXDLLEXPORT wxWindowNext
-{
-    wxWindow *win;
-    wxWindowNext *next;
-} *wxWindow::ms_winCaptureNext = NULL;
-
-void wxWindow::CaptureMouse()
-{
-    wxLogTrace(_T("mousecapture"), _T("CaptureMouse(0x%08x)"), this);
-
-    wxWindow *winOld = GetCapture();
-    if ( winOld )
-    {
-        // save it on stack
-        wxWindowNext *item = new wxWindowNext;
-        item->win = winOld;
-        item->next = ms_winCaptureNext;
-        ms_winCaptureNext = item;
-    }
-    //else: no mouse capture to save
-
-    wxWindowNative::CaptureMouse();
-}
-
-void wxWindow::ReleaseMouse()
-{
-    wxWindowNative::ReleaseMouse();
-
-    if ( ms_winCaptureNext )
-    {
-        ms_winCaptureNext->win->CaptureMouse();
-
-        wxWindowNext *item = ms_winCaptureNext;
-        ms_winCaptureNext = item->next;
-        delete item;
-    }
-    //else: stack is empty, no previous capture
-
-    wxLogTrace(_T("mousecapture"),
-               _T("After ReleaseMouse() mouse is captured by 0x%08x"),
-               GetCapture());
-}
-
 // ----------------------------------------------------------------------------
 // accelerators and menu hot keys
 // ----------------------------------------------------------------------------
@@ -995,7 +1310,7 @@ void wxWindow::OnKeyDown(wxKeyEvent& event)
 {
 #if wxUSE_MENUS
     int key = event.GetKeyCode();
-    if ( !event.ControlDown() && (key == WXK_MENU || key == WXK_F10) )
+    if ( !event.ControlDown() && (key == WXK_ALT || key == WXK_F10) )
     {
         ms_winLastAltPress = this;
 
@@ -1036,6 +1351,24 @@ void wxWindow::OnKeyDown(wxKeyEvent& event)
             }
 #endif // wxUSE_MENUS
 
+#if wxUSE_BUTTON
+            // if it wasn't in a menu, try to find a button
+            if ( command != -1 )
+            {
+                wxWindow* child = win->FindWindow(command);
+                if ( child && wxDynamicCast(child, wxButton) )
+                {
+                    wxCommandEvent eventCmd(wxEVT_COMMAND_BUTTON_CLICKED, command);
+                    eventCmd.SetEventObject(child);
+                    if ( child->GetEventHandler()->ProcessEvent(eventCmd) )
+                    {
+                        // skip "event.Skip()" below
+                        return;
+                    }
+                }
+            }
+#endif // wxUSE_BUTTON
+
             // don't propagate accels from the child frame to the parent one
             break;
         }
@@ -1090,13 +1423,32 @@ void wxWindow::OnChar(wxKeyEvent& event)
         }
     }
 
+    // if Return was pressed, see if there's a default button to activate
+    if ( !event.HasModifiers() && event.GetKeyCode() == WXK_RETURN )
+    {
+        wxTopLevelWindow *
+            tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
+        if ( tlw )
+        {
+            wxButton *btn = wxDynamicCast(tlw->GetDefaultItem(), wxButton);
+            if ( btn )
+            {
+                wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED, btn->GetId());
+                evt.SetEventObject(btn);
+                btn->Command(evt);
+                return;
+            }
+        }
+    }
+
+
     event.Skip();
 }
 
 void wxWindow::OnKeyUp(wxKeyEvent& event)
 {
     int key = event.GetKeyCode();
-    if ( !event.HasModifiers() && (key == WXK_MENU || key == WXK_F10) )
+    if ( !event.HasModifiers() && (key == WXK_ALT || key == WXK_F10) )
     {
         // only process Alt release specially if there were no other key
         // presses since Alt had been pressed and if both events happened in
@@ -1121,3 +1473,28 @@ void wxWindow::OnKeyUp(wxKeyEvent& event)
 
 #endif // wxUSE_MENUS
 
+// ----------------------------------------------------------------------------
+// MSW-specific section
+// ----------------------------------------------------------------------------
+
+#ifdef __WXMSW__
+
+#include "wx/msw/private.h"
+
+WXLRESULT wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
+{
+    if ( message == WM_NCHITTEST )
+    {
+        // the windows which contain the other windows should let the mouse
+        // events through, otherwise a window inside a static box would
+        // never get any events at all
+        if ( IsStaticBox() )
+        {
+            return HTTRANSPARENT;
+        }
+    }
+
+    return wxWindowNative::MSWWindowProc(message, wParam, lParam);
+}
+
+#endif // __WXMSW__