From 45e0dc94770d598a1cc84d83730d470dd1cfbcca Mon Sep 17 00:00:00 2001
From: David Webster <Dave.Webster@bhmi.com>
Date: Mon, 4 Feb 2002 04:19:14 +0000
Subject: [PATCH] OS/2 scrolling support

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@13988 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 include/wx/os2/region.h   |  14 +-
 include/wx/os2/toplevel.h |   3 +
 include/wx/os2/window.h   |   5 +
 include/wx/toplevel.h     |   1 +
 include/wx/window.h       |   7 +
 src/common/toplvcmn.cpp   |   8 +-
 src/common/wincmn.cpp     |   5 +-
 src/os2/toplevel.cpp      |  93 ++++++++-
 src/os2/window.cpp        | 429 ++++++++++++++++++--------------------
 src/os2/wx23.def          |  24 ++-
 10 files changed, 342 insertions(+), 247 deletions(-)

diff --git a/include/wx/os2/region.h b/include/wx/os2/region.h
index e8868bf631..92b49a2980 100644
--- a/include/wx/os2/region.h
+++ b/include/wx/os2/region.h
@@ -33,8 +33,6 @@ enum wxRegionOp { wxRGN_AND         // Creates the intersection of the two combi
 
 class WXDLLEXPORT wxRegion : public wxGDIObject
 {
-DECLARE_DYNAMIC_CLASS(wxRegion);
-    friend class WXDLLEXPORT wxRegionIterator;
 public:
     wxRegion( wxCoord x
              ,wxCoord y
@@ -67,6 +65,10 @@ public:
     //
     void Clear(void);
 
+    bool Offset( wxCoord x
+                ,wxCoord y
+               );
+
     //
     // Union rectangle or region with this.
     //
@@ -208,6 +210,14 @@ public:
     //
     WXHRGN GetHRGN(void) const;
     void   SetPS(HPS hPS);
+
+protected:
+    virtual wxObjectRefData* CreateData(void) const;
+    virtual wxObjectRefData* CloneData(wxObjectRefData* pData) const;
+    
+    friend class WXDLLEXPORT wxRegionIterator;
+    DECLARE_DYNAMIC_CLASS(wxRegion);
+
 }; // end of CLASS wxRegion
 
 class WXDLLEXPORT wxRegionIterator : public wxObject
diff --git a/include/wx/os2/toplevel.h b/include/wx/os2/toplevel.h
index 7ad9f88570..2557c3981f 100644
--- a/include/wx/os2/toplevel.h
+++ b/include/wx/os2/toplevel.h
@@ -85,8 +85,10 @@ public:
     //
            virtual void AlterChildPos(void); // OS/2 child control positioning
            virtual void UpdateInternalSize( wxWindow* pChild
+                                           ,int       nWidth
                                            ,int       nHeight
                                           );
+           PSWP         GetSwpClient(void) { return &m_vSwpClient; }
 protected:
     //
     // Common part of all ctors
@@ -157,6 +159,7 @@ protected:
     WXHWND                          m_hFrame;
     SWP                             m_vSwp;
     SWP                             m_vSwpClient;
+    static bool                     m_sbInitialized;
 }; // end of CLASS wxTopLevelWindowOS2
 
 //
diff --git a/include/wx/os2/window.h b/include/wx/os2/window.h
index e18f1662cb..aa2553e8fa 100644
--- a/include/wx/os2/window.h
+++ b/include/wx/os2/window.h
@@ -142,6 +142,8 @@ public:
                                   ,const wxRect* pRect = (wxRect *)NULL
                                  );
 
+    inline HWND                   GetScrollBarHorz(void) const {return m_hWndScrollBarHorz;}
+    inline HWND                   GetScrollBarVert(void) const {return m_hWndScrollBarVert;};
 #if wxUSE_DRAG_AND_DROP
     virtual void SetDropTarget(wxDropTarget* pDropTarget);
 #endif // wxUSE_DRAG_AND_DROP
@@ -539,6 +541,7 @@ protected:
 #endif // wxUSE_TOOLTIPS
 
     int  GetOS2ParentHeight(wxWindowOS2* pParent);
+    virtual void OS2Layout(int nWidth, int nHeight);
 
 private:
     // common part of all ctors
@@ -561,9 +564,11 @@ private:
     // the helper functions used by HandleChar/KeyXXX methods
     wxKeyEvent CreateKeyEvent(wxEventType evType, int id, WXLPARAM lp) const;
 
+
     DECLARE_DYNAMIC_CLASS(wxWindowOS2);
     DECLARE_NO_COPY_CLASS(wxWindowOS2)
     DECLARE_EVENT_TABLE()
+
 private:
     HWND                            m_hWndScrollBarHorz;
     HWND                            m_hWndScrollBarVert;
diff --git a/include/wx/toplevel.h b/include/wx/toplevel.h
index a2cc6c0ef8..44d3a45f8a 100644
--- a/include/wx/toplevel.h
+++ b/include/wx/toplevel.h
@@ -127,6 +127,7 @@ public:
     // method updates any internal sizing parameters such as OS/2's SWP struct
     inline virtual void AlterChildPos(void) { }
     inline virtual void UpdateInternalSize( wxWindow* WXUNUSED(pChild)
+                                           ,int WXUNUSED(nWidth)
                                            ,int WXUNUSED(nHeight)
                                           ) { }
 
diff --git a/include/wx/window.h b/include/wx/window.h
index 76c8865089..80ced6d6ab 100644
--- a/include/wx/window.h
+++ b/include/wx/window.h
@@ -845,6 +845,7 @@ protected:
     bool                 m_themeEnabled;
 
 protected:
+
     // common part of all ctors: it is not virtual because it is called from
     // ctor
     void InitBase();
@@ -935,7 +936,13 @@ protected:
     // a toolbar that it manages itself).
     virtual void AdjustForParentClientOrigin(int& x, int& y, int sizeFlags);
 
+#ifdef __WXPM__
+    // extra OS/2 layout processing
+    virtual void OS2Layout(int width, int height) { };
+#endif
+
 private:
+
     // contains the last id generated by NewControlId
     static int ms_lastControlId;
 
diff --git a/src/common/toplvcmn.cpp b/src/common/toplvcmn.cpp
index 0e21ec247b..a67959b9f0 100644
--- a/src/common/toplvcmn.cpp
+++ b/src/common/toplvcmn.cpp
@@ -162,9 +162,13 @@ void wxTopLevelWindowBase::OnSize(wxSizeEvent& WXUNUSED(event))
             static const int ofs = 0;
 #endif
 
-            child->SetSize(ofs, ofs, clientW - 2*ofs, clientH - 2*ofs);
 #ifdef __WXPM__
-            UpdateInternalSize(child, clientH);
+            // OS/2 PM has to do a LOT of stuff to get things
+            // positioned right, especially if the child is a
+            // scrolled window.
+            UpdateInternalSize(child, clientW, clientH);
+#else
+            child->SetSize(ofs, ofs, clientW - 2*ofs, clientH - 2*ofs);
 #endif
         }
     }
diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp
index 89f902063e..ce68b5ac34 100644
--- a/src/common/wincmn.cpp
+++ b/src/common/wincmn.cpp
@@ -1161,6 +1161,9 @@ bool wxWindowBase::Layout()
         GetClientSize(&w, &h);
 
         GetSizer()->SetDimension( 0, 0, w, h );
+#if defined __WXPM__
+        OS2Layout(w, h);
+#endif
     }
     else
     {
@@ -1667,7 +1670,7 @@ struct WXDLLEXPORT wxWindowNext
 void wxWindowBase::CaptureMouse()
 {
     wxLogTrace(_T("mousecapture"), _T("CaptureMouse(0x%08x)"), this);
-    
+
     wxWindow *winOld = GetCapture();
     if ( winOld )
     {
diff --git a/src/os2/toplevel.cpp b/src/os2/toplevel.cpp
index c0187c6f00..6be4e147df 100644
--- a/src/os2/toplevel.cpp
+++ b/src/os2/toplevel.cpp
@@ -56,6 +56,7 @@ wxWindowList wxModelessWindows;
 extern void          wxAssociateWinWithHandle( HWND         hWnd
                                               ,wxWindowOS2* pWin
                                              );
+bool                 wxTopLevelWindowOS2::m_sbInitialized = FALSE;
 
 // ============================================================================
 // wxTopLevelWindowMSW implementation
@@ -515,6 +516,12 @@ void wxTopLevelWindowOS2::AlterChildPos()
     RECTL                                   vRect;
     SWP                                     vSwp;
 
+    if (GetAutoLayout)
+        //
+        // Auto layouts taken care of elsewhere
+        //
+        return;
+
     ::WinQueryWindowRect(GetHwnd(), &vRect);
     for (wxWindowList::Node* pNode = GetChildren().GetFirst();
          pNode;
@@ -551,10 +558,92 @@ void wxTopLevelWindowOS2::AlterChildPos()
 
 void wxTopLevelWindowOS2::UpdateInternalSize(
   wxWindow*                         pChild
-, int                               nHeight
+, int                               nChildWidth
+, int                               nChildHeight
 )
 {
-    pChild->MoveChildren(m_vSwpClient.cy - nHeight);
+    int                             nWidthAdjust = 0;
+    int                             nHeightAdjust = 0;
+    int                             nPosX;
+    int                             nPosY;
+    bool                            bNewYSize = FALSE;
+    bool                            bNewXSize = FALSE;
+
+    //
+    // Under OS/2, if we have a srolled window as the child, the
+    // scrollbars will be SIBLINGS of the scrolled window.  So, in
+    // order to be able to display the scrollbars properly we have to
+    // resize the scrolled window.  Of course, that means dealing with
+    // child windows of that window as well, because OS/2 does not
+    // tend to put them in the right place.
+    //
+    if (nChildHeight != m_vSwpClient.cy)
+        bNewYSize = TRUE;
+    if (nChildWidth != m_vSwpClient.cx)
+        bNewXSize = TRUE;
+    if (bNewXSize || bNewYSize)
+        pChild->SetSize( 0
+                        ,0
+                        ,nChildWidth
+                        ,nChildHeight
+                       );
+    if(bNewYSize)
+    {
+        //
+        // This is needed SetSize will mess up the OS/2 child window
+        // positioning because we position in wxWindows coordinates,
+        // not OS/2 coordinates.
+        //
+        pChild->MoveChildren(m_vSwpClient.cy - nChildHeight);
+        pChild->Refresh();
+    }
+
+    if (pChild->GetScrollBarHorz() != NULLHANDLE ||
+        pChild->GetScrollBarVert() != NULLHANDLE)
+    {
+        if (bNewXSize || bNewYSize)
+        {
+            pChild->GetSize( &nChildWidth
+                            ,&nChildHeight
+                           );
+            if (pChild->GetScrollBarHorz() != NULLHANDLE)
+                nHeightAdjust = 20;
+            if (pChild->GetScrollBarVert() != NULLHANDLE)
+                nWidthAdjust = 20;
+            pChild->GetPosition( &nPosX
+                                ,&nPosY
+                               );
+            ::WinSetWindowPos( pChild->GetHWND()
+                              ,HWND_TOP
+                              ,nPosX
+                              ,nPosY + nHeightAdjust
+                              ,nChildWidth - nWidthAdjust
+                              ,nChildHeight - nHeightAdjust
+                              ,SWP_MOVE | SWP_SIZE
+                             );
+        }
+        if (bNewYSize && !m_sbInitialized)
+        {
+            //
+            // Only need to readjust child control positions of
+            // scrolled windows once on initialization.  After that
+            // the sizing takes care of things itself.
+            //
+            pChild->MoveChildren(nHeightAdjust);
+            m_sbInitialized = TRUE;
+        }
+        if (bNewXSize || bNewYSize)
+        {
+            //
+            // Always refresh to keep scollbars visible.  They are
+            // children of the Toplevel window, not the child panel.
+            //
+            pChild->Refresh();
+        }
+    }
+    //
+    // This brings the internal "last size" up to date.
+    //
     ::WinQueryWindowPos(GetHwnd(), &m_vSwpClient);
 } // end of wxTopLevelWindowOS2::UpdateInternalSize
 
diff --git a/src/os2/window.cpp b/src/os2/window.cpp
index 3d0ae02f03..935143f040 100644
--- a/src/os2/window.cpp
+++ b/src/os2/window.cpp
@@ -759,16 +759,37 @@ void wxWindowOS2::SetScrollbar(
 , bool                              WXUNUSED(bRefresh)
 )
 {
+    HWND                            hWnd = GetHwnd();
     int                             nOldRange = nRange - nThumbVisible;
     int                             nRange1 = nOldRange;
     int                             nPageSize = nThumbVisible;
+
     SBCDATA                         vInfo;
-    HWND                            hWnd = GetHwnd();
-    ULONG                           ulStyle = WS_VISIBLE;
-    RECTL                           vRect;
+    ULONG                           ulStyle = WS_VISIBLE | WS_SYNCPAINT;
     SWP                             vSwp;
+    RECTL                           vRect;
+    HWND                            hWndParent;
+    HWND                            hWndClient;
+    wxWindow*                       pParent = GetParent();
+
+    if (pParent && pParent->IsKindOf(CLASSINFO(wxFrame)))
+    {
+        wxFrame*                    pFrame;
+
+        pFrame = wxDynamicCast(pParent, wxFrame);
+        hWndParent = pFrame->GetFrame();
+        hWndClient = GetHwndOf(pParent);
+    }
+    else
+    {
+        if (pParent)
+            hWndParent = GetHwndOf(pParent);
+        else
+            hWndParent = GetHwnd();
+        hWndClient = hWndParent;
+    }
+    ::WinQueryWindowPos(hWndClient, &vSwp);
 
-    ::WinQueryWindowRect(hWnd, &vRect);
     if (nPageSize > 1 && nRange > 0)
     {
         nRange1 += (nPageSize - 1);
@@ -784,13 +805,13 @@ void wxWindowOS2::SetScrollbar(
         ulStyle |= SBS_HORZ;
         if (m_hWndScrollBarHorz == 0L)
         {
-            m_hWndScrollBarHorz = ::WinCreateWindow( hWnd
+            m_hWndScrollBarHorz = ::WinCreateWindow( hWndParent
                                                     ,WC_SCROLLBAR
                                                     ,(PSZ)NULL
                                                     ,ulStyle
-                                                    ,vRect.xLeft
-                                                    ,vRect.yBottom
-                                                    ,vRect.xRight - vRect.xLeft - 20
+                                                    ,vSwp.x
+                                                    ,vSwp.y
+                                                    ,vSwp.cx - 20
                                                     ,20
                                                     ,hWnd
                                                     ,HWND_TOP
@@ -801,32 +822,26 @@ void wxWindowOS2::SetScrollbar(
         }
         else
         {
-            RECTL                   vRect2;
-
-            //
-            // Only want to resize the scrollbar if it changes, otherwise
-            // we'd probably end up in a recursive loop until we crash the call stack
-            // because this method is called in a ScrolledWindow OnSize event and SWP_MOVE | SWP_SIZE
-            // generates those events.
-            //
-            ::WinQueryWindowRect(m_hWndScrollBarHorz, &vRect2);
-            if (!(vRect2.xLeft == vRect.xLeft     &&
-                  vRect2.xRight == vRect.xRight   &&
-                  vRect2.yBottom == vRect.yBottom &&
-                  vRect2.yTop == vRect.yTop
-                ) )
-            {
-                ::WinSetWindowPos( m_hWndScrollBarHorz
-                                  ,HWND_TOP
-                                  ,vRect.xLeft
-                                  ,vRect.yBottom
-                                  ,vRect.xRight - vRect.xLeft - 20
-                                  ,20
-                                  ,SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW
-                                 );
-            }
-            ::WinSendMsg(m_hWndScrollBarHorz, SBM_SETSCROLLBAR, (MPARAM)nPos, MPFROM2SHORT(0, (SHORT)nRange1));
-            ::WinSendMsg(m_hWndScrollBarHorz, SBM_SETTHUMBSIZE, MPFROM2SHORT((SHORT)nThumbVisible, (SHORT)nRange1), (MPARAM)0);
+            ::WinSetWindowPos( m_hWndScrollBarHorz
+                              ,HWND_TOP
+                              ,vSwp.x
+                              ,vSwp.y
+                              ,vSwp.cx - 20
+                              ,20
+                              ,SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ACTIVATE | SWP_ZORDER
+                             );
+            ::WinSendMsg( m_hWndScrollBarHorz
+                         ,SBM_SETSCROLLBAR
+                         ,(MPARAM)nPos
+                         ,MPFROM2SHORT(0, (SHORT)nRange1)
+                        );
+            ::WinSendMsg( m_hWndScrollBarHorz
+                         ,SBM_SETTHUMBSIZE
+                         ,MPFROM2SHORT( (SHORT)nThumbVisible
+                                       ,(SHORT)nRange1
+                                      )
+                         ,(MPARAM)0
+                        );
         }
     }
     else
@@ -834,14 +849,14 @@ void wxWindowOS2::SetScrollbar(
         ulStyle |= SBS_VERT;
         if (m_hWndScrollBarVert == 0L)
         {
-            m_hWndScrollBarVert = ::WinCreateWindow( hWnd
+            m_hWndScrollBarVert = ::WinCreateWindow( hWndParent
                                                     ,WC_SCROLLBAR
                                                     ,(PSZ)NULL
                                                     ,ulStyle
-                                                    ,vRect.xRight - 20
-                                                    ,vRect.yBottom + 20
+                                                    ,vSwp.x + vSwp.cx - 20
+                                                    ,vSwp.y + 20
                                                     ,20
-                                                    ,vRect.yTop - (vRect.yBottom + 20)
+                                                    ,vSwp.cy - 20
                                                     ,hWnd
                                                     ,HWND_TOP
                                                     ,60001
@@ -851,32 +866,26 @@ void wxWindowOS2::SetScrollbar(
         }
         else
         {
-            RECTL                   vRect2;
-
-            //
-            // Only want to resize the scrollbar if it changes, otherwise
-            // we'd probably end up in a recursive loop until we crash the call stack
-            // because this method is called in a ScrolledWindow OnSize event and SWP_MOVE | SWP_SIZE
-            // generates those events.
-            //
-            ::WinQueryWindowRect(m_hWndScrollBarVert, &vRect2);
-            if (!(vRect2.xLeft == vRect.xLeft     &&
-                  vRect2.xRight == vRect.xRight   &&
-                  vRect2.yBottom == vRect.yBottom &&
-                  vRect2.yTop == vRect.yTop
-                ) )
-            {
-                ::WinSetWindowPos( m_hWndScrollBarVert
-                                  ,HWND_TOP
-                                  ,vRect.xRight - 20
-                                  ,vRect.yBottom + 20
-                                  ,20
-                                  ,vRect.yTop - (vRect.yBottom + 20)
-                                  ,SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW
-                                 );
-            }
-            ::WinSendMsg(m_hWndScrollBarVert, SBM_SETSCROLLBAR, (MPARAM)nPos, MPFROM2SHORT(0, (SHORT)nRange1));
-            ::WinSendMsg(m_hWndScrollBarVert, SBM_SETTHUMBSIZE, MPFROM2SHORT((SHORT)nThumbVisible, (SHORT)nRange1), (MPARAM)0);
+            ::WinSetWindowPos( m_hWndScrollBarVert
+                              ,HWND_TOP
+                              ,vSwp.x + vSwp.cx - 20
+                              ,vSwp.y + 20
+                              ,20
+                              ,vSwp.cy - 20
+                              ,SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW
+                             );
+            ::WinSendMsg( m_hWndScrollBarVert
+                         ,SBM_SETSCROLLBAR
+                         ,(MPARAM)nPos
+                         ,MPFROM2SHORT(0, (SHORT)nRange1)
+                        );
+            ::WinSendMsg( m_hWndScrollBarVert
+                         ,SBM_SETTHUMBSIZE
+                         ,MPFROM2SHORT( (SHORT)nThumbVisible
+                                       ,(SHORT)nRange1
+                                      )
+                         ,(MPARAM)0
+                        );
         }
         m_nYThumbSize = nThumbVisible;
     }
@@ -888,7 +897,6 @@ void wxWindowOS2::ScrollWindow(
 , const wxRect*                     pRect
 )
 {
-    nDy *= -1; // flip the sign of Dy as OS/2 is opposite Windows.
     RECTL                           vRect;
     RECTL                           vRectHorz;
     RECTL                           vRectVert;
@@ -904,116 +912,17 @@ void wxWindowOS2::ScrollWindow(
     else
     {
         ::WinQueryWindowRect(GetHwnd(), &vRect);
-        ::WinQueryWindowRect(m_hWndScrollBarHorz, &vRectHorz);
-        vRect.yBottom += vRectHorz.yTop - vRectHorz.yBottom;
-        ::WinQueryWindowRect(m_hWndScrollBarVert, &vRectVert);
-        vRect.xRight -= vRectVert.xRight - vRectVert.xLeft;
-
     }
+    nDy *= -1; // flip the sign of Dy as OS/2 is opposite Windows.
     ::WinScrollWindow( GetHwnd()
                       ,(LONG)nDx
                       ,(LONG)nDy
                       ,&vRect
-                      ,NULL
+                      ,&vRect
                       ,NULLHANDLE
                       ,NULL
-                      ,SW_INVALIDATERGN
+                      ,SW_SCROLLCHILDREN | SW_INVALIDATERGN
                      );
-    //
-    // Move the children
-    //
-    wxWindowList::Node*             pCurrent = GetChildren().GetFirst();
-    SWP                             vSwp;
-
-    while (pCurrent)
-    {
-        wxWindow*                   pChildWin = pCurrent->GetData();
-
-        if (pChildWin->GetHWND() != NULLHANDLE)
-        {
-            ::WinQueryWindowPos(pChildWin->GetHWND(), &vSwp);
-            ::WinQueryWindowRect(pChildWin->GetHWND(), &vRect);
-            if (pChildWin->IsKindOf(CLASSINFO(wxControl)))
-            {
-                wxControl*          pCtrl;
-
-                //
-                // Must deal with controls that have margins like ENTRYFIELD.  The SWP
-                // struct of such a control will have and origin offset from its intended
-                // position by the width of the margins.
-                //
-                pCtrl = wxDynamicCast(pChildWin, wxControl);
-                vSwp.y -= pCtrl->GetYComp();
-                vSwp.x -= pCtrl->GetXComp();
-            }
-            ::WinSetWindowPos( pChildWin->GetHWND()
-                              ,HWND_BOTTOM
-                              ,vSwp.x + nDx
-                              ,vSwp.y + nDy
-                              ,0
-                              ,0
-                              ,SWP_MOVE
-                             );
-            if (pChildWin->IsKindOf(CLASSINFO(wxRadioBox)))
-            {
-                wxRadioBox*         pRadioBox;
-
-                pRadioBox = wxDynamicCast(pChildWin, wxRadioBox);
-                pRadioBox->AdjustButtons( (int)vSwp.x + nDx
-                                         ,(int)vSwp.y + nDy
-                                         ,(int)vSwp.cx
-                                         ,(int)vSwp.cy
-                                         ,pRadioBox->GetSizeFlags()
-                                        );
-            }
-            if (pChildWin->IsKindOf(CLASSINFO(wxSlider)))
-            {
-                wxSlider*           pSlider;
-
-                pSlider = wxDynamicCast(pChildWin, wxSlider);
-                pSlider->AdjustSubControls( (int)vSwp.x + nDx
-                                           ,(int)vSwp.y + nDy
-                                           ,(int)vSwp.cx
-                                           ,(int)vSwp.cy
-                                           ,pSlider->GetSizeFlags()
-                                          );
-            }
-            ::WinInvalidateRect(pChildWin->GetHWND(), &vRectChild, FALSE);
-        }
-        pCurrent = pCurrent->GetNext();
-    }
-    if (GetChildren().GetCount() > 0)
-    {
-        //
-        // Clean up child window slop
-        //
-        ::WinQueryWindowRect(GetHwnd(), &vRect);
-        vRect.xRight -= 20;
-        vRect.yBottom += 20;
-        ::WinInvalidateRect(GetHwnd(), &vRect, TRUE);
-    }
-
-    //
-    // Takes a lot to keep the scrollbars on top of everything
-    //
-    ::WinSetWindowPos( m_hWndScrollBarHorz
-                      ,HWND_TOP
-                      ,0
-                      ,0
-                      ,0
-                      ,0
-                      ,SWP_ZORDER
-                     );
-    ::WinSetWindowPos( m_hWndScrollBarVert
-                      ,HWND_TOP
-                      ,0
-                      ,0
-                      ,0
-                      ,0
-                      ,SWP_ZORDER
-                     );
-    ::WinInvalidateRect(m_hWndScrollBarHorz, &vRectHorz, FALSE);
-    ::WinInvalidateRect(m_hWndScrollBarVert, &vRectVert, FALSE);
 } // end of wxWindowOS2::ScrollWindow
 
 // ---------------------------------------------------------------------------
@@ -1343,6 +1252,10 @@ void wxWindowOS2::Refresh(
         }
         else
             ::WinInvalidateRect(hWnd, NULL, bEraseBack);
+        if (m_hWndScrollBarHorz != NULLHANDLE)
+            ::WinInvalidateRect(m_hWndScrollBarHorz, NULL, TRUE);
+        if (m_hWndScrollBarVert != NULLHANDLE)
+            ::WinInvalidateRect(m_hWndScrollBarVert, NULL, TRUE);
     }
 } // end of wxWindowOS2::Refresh
 
@@ -2384,7 +2297,18 @@ MRESULT EXPENTRY wxWndProc(
     else
     {
         if (pWnd)
+        {
             rc = pWnd->OS2WindowProc(ulMsg, wParam, lParam);
+            if ( (pWnd->GetScrollBarHorz() != NULLHANDLE ||
+                  pWnd->GetScrollBarVert() != NULLHANDLE) &&
+                  ulMsg == WM_PAINT)
+            {
+                if (pWnd->GetScrollBarHorz() != NULLHANDLE)
+                    ::WinInvalidateRect(pWnd->GetScrollBarHorz(), NULL, TRUE);
+                if (pWnd->GetScrollBarVert() != NULLHANDLE)
+                    ::WinInvalidateRect(pWnd->GetScrollBarVert(), NULL, TRUE);
+            }
+        }
         else
             rc = ::WinDefWindowProc(hWnd, ulMsg, wParam, lParam);
     }
@@ -4118,68 +4042,6 @@ void wxWindowOS2::MoveChildren(
                                        ,(int)pSlider->GetSizeFlags()
                                       );
         }
-        //
-        // Originally created before Panel was properly sized, most likely.
-        // So now the the panel is sized correctly, resize the scrollbars
-        // and bring them to the top of all the other panel children
-        //
-        if (m_hWndScrollBarVert != NULLHANDLE ||
-            m_hWndScrollBarHorz != NULLHANDLE)
-        {
-            RECTL                   vRect;
-
-            ::WinQueryWindowRect(GetHwnd(), &vRect);
-            ::WinQueryWindowPos(m_hWndScrollBarHorz, &vSwp);
-            if ( (vRect.xRight - vRect.xLeft) - vSwp.cx != 20)
-            {
-                ::WinSetWindowPos( m_hWndScrollBarHorz
-                                  ,HWND_TOP
-                                  ,0
-                                  ,0
-                                  ,(vRect.xRight - vRect.xLeft) - 20
-                                  ,vSwp.cy
-                                  ,SWP_ZORDER | SWP_SIZE
-                                 );
-            }
-            else
-            {
-                ::WinSetWindowPos( m_hWndScrollBarHorz
-                                  ,HWND_TOP
-                                  ,0
-                                  ,0
-                                  ,0
-                                  ,0
-                                  ,SWP_ZORDER
-                                 );
-            }
-            ::WinQueryWindowPos(m_hWndScrollBarVert, &vSwp);
-            if ( (vRect.yTop - vRect.yBottom) - vSwp.cy != 20)
-            {
-                ::WinSetWindowPos( m_hWndScrollBarVert
-                                  ,HWND_TOP
-                                  ,vSwp.x
-                                  ,vSwp.y + 20
-                                  ,vSwp.cx
-                                  ,(vRect.yTop - vRect.yBottom) - 20
-                                  ,SWP_ZORDER | SWP_SIZE | SWP_MOVE
-                                 );
-            }
-            else
-            {
-                ::WinSetWindowPos( m_hWndScrollBarVert
-                                  ,HWND_TOP
-                                  ,0
-                                  ,0
-                                  ,0
-                                  ,0
-                                  ,SWP_ZORDER
-                                 );
-            }
-            ::WinQueryWindowRect(m_hWndScrollBarHorz, &vRect);
-            ::WinInvalidateRect(m_hWndScrollBarHorz, &vRect, FALSE);
-            ::WinQueryWindowRect(m_hWndScrollBarVert, &vRect);
-            ::WinInvalidateRect(m_hWndScrollBarVert, &vRect, FALSE);
-        }
     }
 } // end of wxWindowOS2::MoveChildren
 
@@ -4276,6 +4138,115 @@ int wxWindowOS2::GetOS2ParentHeight(
     return(0L);
 } // end of wxWindowOS2::GetOS2ParentHeight
 
+//
+// OS/2 needs a lot extra manipulation to deal with layouts
+// for canvas windows, particularly scrolled ones.
+//
+void wxWindowOS2::OS2Layout(
+  int                               nWidth
+, int                               nHeight
+)
+{
+    //
+    // Frames laying out canvas windows need the held.
+    // Dialogs or Frames laying out child controls do not.
+    //
+    if (IsKindOf(CLASSINFO(wxFrame)))
+    {
+        RECTL                       vRectFrame;
+        RECTL                       vRectClient;
+        RECTL                       vRectChild;
+        RECTL                       vRectHorz;
+        RECTL                       vRectVert;
+        SWP                         vSwpFrame;
+        SWP                         vSwpClient;
+        SWP                         vSwpChild;
+        SWP                         vSwpHorz;
+        SWP                         vSwpVert;
+        wxFrame*                    pFrame = wxDynamicCast(this, wxFrame);
+        bool                        bNewYSize = FALSE;
+        bool                        bNewXSize = FALSE;
+
+        ::WinQueryWindowPos(pFrame->GetFrame(), &vSwpFrame);
+        ::WinQueryWindowPos(GetHwnd(), &vSwpClient);
+
+        if (vSwpClient.cy != pFrame->GetSwpClient()->cy)
+            bNewYSize = TRUE;
+        if (vSwpClient.cx != pFrame->GetSwpClient()->cx)
+            bNewXSize = TRUE;
+
+        for (wxWindowList::Node* pNode = GetChildren().GetFirst();
+             pNode;
+             pNode = pNode->GetNext())
+        {
+            wxWindow*               pChild = pNode->GetData();
+            int                     nWidthAdjust = 0;
+            int                     nHeightAdjust = 0;
+
+            if ( pChild->IsKindOf(CLASSINFO(wxGenericScrolledWindow)) ||
+                 pChild->IsKindOf(CLASSINFO(wxScrolledWindow))
+               )
+            {
+                if(bNewYSize)
+                {
+                    //
+                    // This is needed SetSize will mess up the OS/2 child window
+                    // positioning because we position in wxWindows coordinates,
+                    // not OS/2 coordinates.
+                    //
+                    pChild->MoveChildren(pFrame->GetSwpClient()->cy - vSwpClient.cy);
+                    pChild->Refresh();
+                }
+                ::WinQueryWindowPos(pChild->GetHWND(), &vSwpChild);
+
+                //
+                // Reset the child window size to account for scrollbars
+                //
+                if (pChild->GetScrollBarHorz() != NULLHANDLE)
+                    nHeightAdjust = 20;
+                if (pChild->GetScrollBarVert() != NULLHANDLE)
+                    nWidthAdjust = 20;
+                ::WinSetWindowPos( pChild->GetHWND()
+                                  ,HWND_TOP
+                                  ,vSwpChild.x
+                                  ,vSwpChild.y + nHeightAdjust
+                                  ,vSwpChild.cx - nWidthAdjust
+                                  ,vSwpChild.cy - nHeightAdjust
+                                  ,SWP_MOVE | SWP_SIZE
+                                 );
+
+                //
+                // Reset the scrollbar sizes...they will be all messed up after
+                // auto layouts
+                //
+                if (pChild->GetScrollBarHorz() != NULLHANDLE)
+                {
+                    ::WinSetWindowPos( pChild->GetScrollBarHorz()
+                                      ,HWND_TOP
+                                      ,vSwpClient.x + vSwpChild.x
+                                      ,vSwpClient.y + vSwpChild.y
+                                      ,vSwpChild.cx - 20
+                                      ,20
+                                      ,SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ACTIVATE | SWP_ZORDER
+                                     );
+                }
+                if (pChild->GetScrollBarVert() != NULLHANDLE)
+                {
+                    ::WinSetWindowPos( pChild->GetScrollBarVert()
+                                      ,HWND_TOP
+                                      ,vSwpClient.x + vSwpChild.x + vSwpChild.cx - 20
+                                      ,vSwpClient.y + vSwpChild.y  + 20
+                                      ,20
+                                      ,vSwpChild.cy - 20
+                                      ,SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ACTIVATE | SWP_ZORDER
+                                     );
+                }
+            }
+        }
+        ::WinQueryWindowPos(GetHwnd(), pFrame->GetSwpClient());
+    }
+} // end of wxWindowOS2::OS2Layout
+
 wxWindowCreationHook::wxWindowCreationHook(
   wxWindow*                         pWinBeingCreated
 )
diff --git a/src/os2/wx23.def b/src/os2/wx23.def
index 1d4803ddd8..5dc8b0e5b6 100644
--- a/src/os2/wx23.def
+++ b/src/os2/wx23.def
@@ -4,7 +4,7 @@ DATA MULTIPLE NONSHARED READWRITE LOADONCALL
 CODE LOADONCALL
 
 EXPORTS
-;From library:  H:\DEV\WX2\WXWINDOWS\LIB\wx.lib
+;From library:  F:\DEV\WX2\WXWINDOWS\LIB\wx.lib
   ;From object file:  dummy.cpp
     ;PUBDEFs (Symbols available from object file):
       wxDummyChar
@@ -1772,7 +1772,7 @@ EXPORTS
       wxEVT_NC_LEFT_DCLICK
       wxEVT_INIT_DIALOG
       wxEVT_COMMAND_SET_FOCUS
-  ;From object file:  H:\DEV\WX2\WXWINDOWS\src\common\extended.c
+  ;From object file:  F:\DEV\WX2\WXWINDOWS\src\common\extended.c
     ;PUBDEFs (Symbols available from object file):
       ConvertToIeeeExtended
       ConvertFromIeeeExtended
@@ -2167,12 +2167,10 @@ EXPORTS
       ms_root__16wxLocalFSHandler
       ;wxFileSystemHandler::GetMimeTypeFromExt(const wxString&)
       GetMimeTypeFromExt__19wxFileSystemHandlerFRC8wxString
-      ;wxFSFile::sm_classwxFSFile
-      sm_classwxFSFile__8wxFSFile
-      ;wxFileSystemModule::sm_classwxFileSystemModule
-      sm_classwxFileSystemModule__18wxFileSystemModule
       ;wxFileSystem::m_Handlers
       m_Handlers__12wxFileSystem
+      ;wxFileSystemModule::sm_classwxFileSystemModule
+      sm_classwxFileSystemModule__18wxFileSystemModule
       ;wxFileSystemHandler::FindNext()
       FindNext__19wxFileSystemHandlerFv
       ;wxFileSystem::CleanUpHandlers()
@@ -2774,8 +2772,8 @@ EXPORTS
       CopyHashTable__17_wxHashTableBase2FPP21_wxHashTable_NodeBaseUiP17_wxHashTableBase2T1PFP17_wxHashTableBase2P21_wxHashTable_NodeBase_UlPFP21_wxHashTable_NodeBase_P21_wxHashTable_NodeBase
       ;wxStringHash::wxCharStringHash(const char*)
       wxCharStringHash__12wxStringHashFPCc
-      ;_wxHashTableBase2::s_primes
-      s_primes__17_wxHashTableBase2
+      ;_wxHashTableBase2::ms_primes
+      ms_primes__17_wxHashTableBase2
       ;_wxHashTableBase2::DummyProcessNode(_wxHashTable_NodeBase*)
       DummyProcessNode__17_wxHashTableBase2FP21_wxHashTable_NodeBase
       ;_wxHashTableBase2::DeleteNodes(unsigned int,_wxHashTable_NodeBase**,void(*)(_wxHashTable_NodeBase*))
@@ -5797,7 +5795,7 @@ EXPORTS
       Read32__17wxTextInputStreamFv
       ;wxTextInputStream::SkipIfEndOfLine(char)
       SkipIfEndOfLine__17wxTextInputStreamFc
-  ;From object file:  H:\DEV\WX2\WXWINDOWS\src\common\unzip.c
+  ;From object file:  F:\DEV\WX2\WXWINDOWS\src\common\unzip.c
     ;PUBDEFs (Symbols available from object file):
       unzReadCurrentFile
       unzGetCurrentFileInfo
@@ -14332,6 +14330,8 @@ EXPORTS
       CreateFrame__19wxTopLevelWindowOS2FRC8wxStringRC7wxPointRC6wxSize
       ;wxTopLevelWindowOS2::~wxTopLevelWindowOS2()
       __dt__19wxTopLevelWindowOS2Fv
+      ;wxTopLevelWindowOS2::UpdateInternalSize(wxWindow*,int,int)
+      UpdateInternalSize__19wxTopLevelWindowOS2FP8wxWindowiT2
       ;wxTopLevelWindowOS2::ShowFullScreen(unsigned long,long)
       ShowFullScreen__19wxTopLevelWindowOS2FUll
       ;wxTopLevelWindowOS2::CreateDialog(unsigned long,const wxString&,const wxPoint&,const wxSize&)
@@ -14340,6 +14340,8 @@ EXPORTS
       DoShowWindow__19wxTopLevelWindowOS2Fi
       ;wxTopLevelWindowOS2::Init()
       Init__19wxTopLevelWindowOS2Fv
+      ;wxTopLevelWindowOS2::m_sbInitialized
+      m_sbInitialized__19wxTopLevelWindowOS2
       ;wxTopLevelWindowOS2::OS2GetCreateWindowFlags(long*) const
       OS2GetCreateWindowFlags__19wxTopLevelWindowOS2CFPl
       ;wxTopLevelWindowOS2::Iconize(unsigned long)
@@ -14358,8 +14360,6 @@ EXPORTS
       Maximize__19wxTopLevelWindowOS2FUl
       ;wxTopLevelWindowOS2::EnableCloseButton(unsigned long)
       EnableCloseButton__19wxTopLevelWindowOS2FUl
-      ;wxTopLevelWindowOS2::UpdateInternalSize(wxWindow*,int)
-      UpdateInternalSize__19wxTopLevelWindowOS2FP8wxWindowi
       ;wxTopLevelWindowOS2::DoGetClientSize(int*,int*) const
       DoGetClientSize__19wxTopLevelWindowOS2CFPiT1
       ;wxTopLevelWindowOS2::Create(wxWindow*,int,const wxString&,const wxPoint&,const wxSize&,long,const wxString&)
@@ -14668,6 +14668,8 @@ EXPORTS
       ;wxWindow::WarpPointer(int,int)
       WarpPointer__8wxWindowFiT1
       wxCurrentPopupMenu
+      ;wxWindow::OS2Layout(int,int)
+      OS2Layout__8wxWindowFiT1
       ;wxWindow::MoveChildren(int)
       MoveChildren__8wxWindowFi
       ;wxWindow::HandleShow(unsigned long,int)
-- 
2.50.0

