]> git.saurik.com Git - wxWidgets.git/blobdiff - src/os2/window.cpp
corrections for theme brush alignments under X (no more SetOrigin calls)
[wxWidgets.git] / src / os2 / window.cpp
index 767e20d794021ead6fb232bffc3ecee19c6dbbde..e06c94650cf99c62b33d38a0fe524f8e98928b5c 100644 (file)
@@ -147,6 +147,9 @@ static void TranslateKbdEventToMouse( wxWindow* pWin
 //
 static inline bool IsShiftDown() { return (::WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x8000) != 0; }
 static inline bool IsCtrlDown() { return (::WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000) != 0; }
+
+static wxWindow*                    gpWinBeingCreated = NULL;
+
 // ---------------------------------------------------------------------------
 // event tables
 // ---------------------------------------------------------------------------
@@ -1305,6 +1308,27 @@ void wxWindowOS2::Clear()
     vDc.Clear();
 } // end of wxWindowOS2::Clear
 
+void wxWindowOS2::Update()
+{
+    ::WinUpdateWindow(GetHwnd());
+} // end of wxWindowOS2::Update
+
+void wxWindowOS2::Freeze()
+{
+   ::WinSendMsg(GetHwnd(), WM_VRNDISABLED, (MPARAM)0, (MPARAM)0);
+} // end of wxWindowOS2::Freeze
+
+void wxWindowOS2::Thaw()
+{
+   ::WinSendMsg(GetHwnd(), WM_VRNENABLED, (MPARAM)TRUE, (MPARAM)0);
+
+    //
+    // We need to refresh everything or otherwise he invalidated area is not
+    // repainted.
+    //
+    Refresh();
+} // end of wxWindowOS2::Thaw
+
 void wxWindowOS2::Refresh(
   bool                              bEraseBack
 , const wxRect*                     pRect
@@ -1410,49 +1434,36 @@ void wxWindowOS2::DoGetPosition(
 ) const
 {
     HWND                            hWnd = GetHwnd();
-    RECT                            vRect;
+    SWP                             vSwp;
     POINTL                          vPoint;
+    wxWindow*                       pParent = GetParent();
 
-    ::WinQueryWindowRect(hWnd, &vRect);
+    //
+    // It would seem that WinQueryWindowRect would be the correlary to
+    // the WIN32 WinGetRect, but unlike WinGetRect which returns the window
+    // origin position in screen coordinates, WinQueryWindowRect returns it
+    // relative to itself, i.e. (0,0).  To get the same under PM we must
+    // us WinQueryWindowPos.  This call, unlike the WIN32 call, however,
+    // returns a position relative to it's parent, so no parent adujstments
+    // are needed under OS/2.  Also, windows should be created using
+    // wxWindow coordinates, i.e 0,0 is the TOP left so vSwp will already
+    // reflect that.
+    //
+    ::WinQueryWindowPos(hWnd, &vSwp);
 
-    vPoint.x = vRect.xLeft;
-    vPoint.y = vRect.yBottom;
+    vPoint.x = vSwp.x;
+    vPoint.y = vSwp.y;
 
     //
-    // We do the adjustments with respect to the parent only for the "real"
-    // children, not for the dialogs/frames
+    // We may be faking the client origin. So a window that's really at (0,
+    // 30) may appear (to wxWin apps) to be at (0, 0).
     //
-    if (!IsTopLevel())
+    if (pParent)
     {
-        HWND                        hParentWnd = 0;
-        wxWindow*                   pParent = GetParent();
-
-        if (pParent)
-            hParentWnd = GetWinHwnd(pParent);
-
-        //
-        // Since we now have the absolute screen coords, if there's a parent we
-        // must subtract its bottom left corner
-        //
-        if (hParentWnd)
-        {
-            RECTL                   vRect2;
-
-            ::WinQueryWindowRect(hParentWnd, &vRect2);
-            vPoint.x -= vRect.xLeft;
-            vPoint.y -= vRect.yBottom;
-        }
-
-        //
-        // We may be faking the client origin. So a window that's really at (0,
-        // 30) may appear (to wxWin apps) to be at (0, 0).
-        //
-        if (pParent) {
-            wxPoint                     vPt(pParent->GetClientAreaOrigin());
+        wxPoint                     vPt(pParent->GetClientAreaOrigin());
 
-            vPoint.x -= vPt.x;
-            vPoint.y -= vPt.y;
-        }
+        vPoint.x -= vPt.x;
+        vPoint.y -= vPt.y;
     }
 
     if (pX)
@@ -1467,18 +1478,14 @@ void wxWindowOS2::DoScreenToClient(
 ) const
 {
     HWND                            hWnd = GetHwnd();
-    POINTL                          ptl;
-
-    ptl.x = pX ? *pX : 0;
-    ptl.y = pY ? *pY : 0;
+    SWP                             vSwp;
 
-    ::WinMapWindowPoints(HWND_DESKTOP, hWnd, &ptl, 1);
+    ::WinQueryWindowPos(hWnd, &vSwp);
 
     if (pX)
-        *pX = ptl.x;
+        *pX += vSwp.x;
     if (pY)
-        *pY = ptl.y;
-
+        *pY += vSwp.y;
 } // end of wxWindowOS2::DoScreenToClient
 
 void wxWindowOS2::DoClientToScreen(
@@ -1487,17 +1494,14 @@ void wxWindowOS2::DoClientToScreen(
 ) const
 {
     HWND                            hWnd = GetHwnd();
-    POINTL                          ptl;
-
-    ptl.x = pX ? *pX : 0;
-    ptl.y = pY ? *pY : 0;
+    SWP                             vSwp;
 
-    ::WinMapWindowPoints(hWnd, HWND_DESKTOP, &ptl, 1);
+    ::WinQueryWindowPos(hWnd, &vSwp);
 
     if (pX)
-        *pX = ptl.x;
+        *pX += vSwp.x;
     if (pY)
-        *pY = ptl.y;
+        *pY += vSwp.y;
 } // end of wxWindowOS2::DoClientToScreen
 
 //
@@ -1541,19 +1545,9 @@ void wxWindowOS2::DoMoveWindow(
 
     if (pParent)
     {
-        hParent = GetWinHwnd(pParent);
-        if (pParent->IsKindOf(CLASSINFO(wxFrame)))
-        {
-            if (IsKindOf(CLASSINFO(wxStatusBar)) ||
-                IsKindOf(CLASSINFO(wxMenuBar)) ||
-                IsKindOf(CLASSINFO(wxToolBar))
-               )
-                nY = pParent->GetSize().y - (nY + nHeight);
-            else
-                nY = pParent->GetClientSize().y - (nY + nHeight);
-        }
-        else
-            nY = pParent->GetSize().y - (nY + nHeight);
+        int                         nOS2Height = GetOS2ParentHeight(pParent);
+
+        nY = nOS2Height - (nY + nHeight);
     }
     else
     {
@@ -1663,79 +1657,28 @@ void wxWindowOS2::DoSetClientSize(
 {
     wxWindow*                       pParent = GetParent();
     HWND                            hWnd = GetHwnd();
-#if 0
     HWND                            hParentWnd = (HWND)0;
-    HWND                            hClientWnd = (HWND)0;
+    POINTL                          vPoint;
     RECTL                           vRect;
-    RECT                            vRect2;
-    RECT                            vRect3;
+    RECTL                           vRect2;
+    RECTL                           vRect3;
+    HWND                            hClientWnd = (HWND)0;
 
-    hClientWnd = ::WinWindowFromID(GetHwnd(), FID_CLIENT);
+    hClientWnd = ::WinWindowFromID(hWnd, FID_CLIENT);
     ::WinQueryWindowRect(hClientWnd, &vRect2);
-
-    if (pParent)
-        hParentWnd = (HWND) pParent->GetHWND();
-
     ::WinQueryWindowRect(hWnd, &vRect);
     ::WinQueryWindowRect(hParentWnd, &vRect3);
-    //
-    // Find the difference between the entire window (title bar and all)
-    // and the client area; add this to the new client size to move the
-    // window. OS/2 is backward from windows on height
-    //
+
     int                             nActualWidth = vRect2.xRight - vRect2.xLeft - vRect.xRight + nWidth;
     int                             nActualHeight = vRect2.yTop - vRect2.yBottom - vRect.yTop + nHeight;
 
-    //
-    // If there's a parent, must subtract the parent's bottom left corner
-    // since MoveWindow moves relative to the parent
-    //
-    POINTL                          vPoint;
-
     vPoint.x = vRect2.xLeft;
     vPoint.y = vRect2.yBottom;
     if (pParent)
-    {             x
+    {
         vPoint.x -= vRect3.xLeft;
         vPoint.y -= vRect3.yBottom;
     }
-#else
-    HWND                            hParentWnd = (HWND)0;
-    HWND                            hClientWnd = (HWND)0;
-    RECTL                           vRect;
-    RECT                            vRect2;
-
-    hClientWnd = ::WinWindowFromID(GetHwnd(), FID_CLIENT);
-    ::WinQueryWindowRect(hClientWnd, &vRect2);
-    ::WinQueryWindowRect(hWnd, &vRect2);
-
-    if (pParent)
-        hParentWnd = (HWND) pParent->GetHWND();
-
-    ::WinQueryWindowRect(hWnd, &vRect);
-    //
-    // Find the difference between the entire window (title bar and all)
-    // and the client area; add this to the new client size to move the
-    // window. OS/2 is backward from windows on height
-    //
-    int nActualWidth  = vRect2.xRight - vRect2.xLeft - vRect.xRight + nWidth;
-    int nActualHeight = vRect2.yTop - vRect2.yBottom - vRect.yTop + nHeight;
-
-    nActualWidth  = nWidth;
-    nActualHeight = nHeight;
-    //
-    // If there's a parent, must subtract the parent's bottom left corner
-    // since MoveWindow moves relative to the parent
-    //
-    POINTL                          vPoint;
-
-    vPoint.x = vRect2.xLeft;
-    vPoint.y = vRect2.yBottom;
-    if (pParent)
-    {
-        ::WinMapWindowPoints(hWnd, hParentWnd, &vPoint, 1);
-    }
-#endif
 
     DoMoveWindow(vPoint.x, vPoint.y, nActualWidth, nActualHeight);
 
@@ -1883,6 +1826,26 @@ void wxWindowOS2::GetTextExtent(
     ::WinReleasePS(hPS);
 } // end of wxWindow::GetTextExtent
 
+bool wxWindowOS2::IsMouseInWindow() const
+{
+    //
+    // Get the mouse position
+    POINTL                          vPt;
+
+    ::WinQueryPointerPos(HWND_DESKTOP, &vPt);
+
+    //
+    // Find the window which currently has the cursor and go up the window
+    // chain until we find this window - or exhaust it
+    //
+    HWND                            hWnd = ::WinWindowFromPoint(HWND_DESKTOP, &vPt, TRUE);
+
+    while (hWnd && (hWnd != GetHwnd()))
+        hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
+
+    return hWnd != NULL;
+} // end of wxWindowOS2::IsMouseInWindow
+
 #if wxUSE_CARET && WXWIN_COMPATIBILITY
 // ---------------------------------------------------------------------------
 // Caret manipulation
@@ -2614,6 +2577,48 @@ MRESULT wxWindowOS2::OS2WindowProc(
             }
             break;
 
+        case WM_CONTROL:
+            switch(SHORT2FROMMP(wParam))
+            {
+                case SPBN_UPARROW:
+                case SPBN_DOWNARROW:
+                case SPBN_CHANGE:
+                    {
+                        char        zVal[10];
+                        long        lVal;
+
+                        ::WinSendMsg( HWNDFROMMP(lParam)
+                                     ,SPBM_QUERYVALUE
+                                     ,&zVal
+                                     ,MPFROM2SHORT( (USHORT)10
+                                                   ,(USHORT)SPBQ_UPDATEIFVALID
+                                                  )
+                                    );
+                        lVal = atol(zVal);
+                        bProcessed = OS2OnScroll( wxVERTICAL
+                                                 ,(int)SHORT2FROMMP(wParam)
+                                                 ,(int)lVal
+                                                 ,HWNDFROMMP(lParam)
+                                                );
+                    }
+                    break;
+
+                case SLN_SLIDERTRACK:
+                    {
+                        HWND                hWnd = ::WinWindowFromID(GetHWND(), SHORT1FROMMP(wParam));
+                        wxWindowOS2*        pChild = wxFindWinFromHandle(hWnd);
+
+                        if (pChild->IsKindOf(CLASSINFO(wxSlider)))
+                            bProcessed = OS2OnScroll( wxVERTICAL
+                                                     ,(int)SHORT2FROMMP(wParam)
+                                                     ,(int)LONGFROMMP(lParam)
+                                                     ,hWnd
+                                                    );
+                    }
+                    break;
+            }
+            break;
+
 #if defined(__VISAGECPP__) && (__IBMCPP__ >= 400)
         case WM_CTLCOLORCHANGE:
             {
@@ -2814,6 +2819,46 @@ void wxWindowOS2::OS2DetachWindowMenu()
 #endif // __WXUNIVERSAL__
 } // end of wxWindowOS2::OS2DetachWindowMenu
 
+bool wxWindowOS2::OS2GetCreateWindowCoords(
+  const wxPoint&                    rPos
+, const wxSize&                     rSize
+, int&                              rnX
+, int&                              rnY
+, int&                              rnWidth
+, int&                              rnHeight
+) const
+{
+    bool                            bNonDefault = FALSE;
+
+    if (rPos.x == -1)
+    {
+        //
+        // If set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can
+        // just as well set it to CW_USEDEFAULT as well
+        rnX = rnY = CW_USEDEFAULT;
+    }
+    else
+    {
+        rnX = rPos.x;
+        rnY = rPos.y == -1 ? CW_USEDEFAULT : rPos.y;
+        bNonDefault = TRUE;
+    }
+    if (rSize.x == -1)
+    {
+        //
+        // As abobe, h is not used at all in this case anyhow
+        //
+        rnWidth = rnHeight = CW_USEDEFAULT;
+    }
+    else
+    {
+        rnWidth  = rSize.x;
+        rnHeight = rSize.y == -1 ? CW_USEDEFAULT : rSize.y;
+        bNonDefault = TRUE;
+    }
+    return bNonDefault;
+} // end of wxWindowOS2::OS2GetCreateWindowCoords
+
 bool wxWindowOS2::OS2Create(
   WXHWND                            hParent
 , PSZ                               zClass
@@ -3928,6 +3973,174 @@ bool wxWindowOS2::OS2OnScroll(
     return GetEventHandler()->ProcessEvent(vEvent);
 } // end of wxWindowOS2::OS2OnScroll
 
+void wxWindowOS2::MoveChildren(
+  int                               nDiff
+)
+{
+    SWP                                 vSwp;
+
+    for (wxWindowList::Node* pNode = GetChildren().GetFirst();
+         pNode;
+         pNode = pNode->GetNext())
+    {
+        wxWindow*                   pWin = pNode->GetData();
+
+        ::WinQueryWindowPos( GetHwndOf(pWin)
+                            ,&vSwp
+                           );
+        if (pWin->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(pWin, wxControl);
+            vSwp.y -= pCtrl->GetYComp();
+            vSwp.x -= pCtrl->GetXComp();
+        }
+        ::WinSetWindowPos( GetHwndOf(pWin)
+                          ,HWND_TOP
+                          ,vSwp.x
+                          ,vSwp.y - nDiff
+                          ,vSwp.cx
+                          ,vSwp.cy
+                          ,SWP_MOVE
+                         );
+        if (pWin->IsKindOf(CLASSINFO(wxRadioBox)))
+        {
+            wxRadioBox*     pRadioBox;
+
+            pRadioBox = wxDynamicCast(pWin, wxRadioBox);
+            pRadioBox->AdjustButtons( (int)vSwp.x
+                                     ,(int)vSwp.y - nDiff
+                                     ,(int)vSwp.cx
+                                     ,(int)vSwp.cy
+                                     ,pRadioBox->GetSizeFlags()
+                                    );
+        }
+        if (pWin->IsKindOf(CLASSINFO(wxSlider)))
+        {
+            wxSlider*           pSlider;
+
+            pSlider = wxDynamicCast(pWin, wxSlider);
+            pSlider->AdjustSubControls( (int)vSwp.x
+                                       ,(int)vSwp.y - nDiff
+                                       ,(int)vSwp.cx
+                                       ,(int)vSwp.cy
+                                       ,(int)pSlider->GetSizeFlags()
+                                      );
+        }
+    }
+} // end of wxWindowOS2::MoveChildren
+
+//
+//  Getting the Y position for a window, like a control, is a real
+//  pain.  There are three sitatuions we must deal with in determining
+//  the OS2 to wxWindows Y coordinate.
+//
+//  1)  The controls are created in a dialog.
+//      This is the easiest since a dialog is created with its original
+//      size so the standard: Y = ParentHeight - (Y + ControlHeight);
+//
+//  2)  The controls are direct children of a frame
+//      In this instance the controls are actually children of the Frame's
+//      client.  During creation the frame's client resizes several times
+//      during creation of the status bar and toolbars.  The CFrame class
+//      will take care of this using its AlterChildPos proc.
+//
+//  3)  The controls are children of a panel, which in turn is a child of
+//      a frame.
+//      This is the nastiest case.  A panel is created as the only child of
+//      the frame and as such, when a frame has only one child, the child is
+//      expanded to fit the entire client area of the frame.  Because the
+//      controls are created BEFORE this occurs their positions are totally
+//      whacked and any call to WinQueryWindowPos will return invalid
+//      coordinates.  So for this situation we have to compare the size of
+//      the panel at control creation time with that of the frame client.  If
+//      they are the same we can use the standard Y position equation.  If
+//      not, then we must use the Frame Client's dimensions to position them
+//      as that will be the eventual size of the panel after the frame resizes
+//      it!
+//
+int wxWindowOS2::GetOS2ParentHeight(
+  wxWindowOS2*               pParent
+)
+{
+    wxWindowOS2*             pGrandParent = NULL;
+
+    //
+    // Case 1
+    //
+    if (pParent->IsKindOf(CLASSINFO(wxDialog)))
+        return(pParent->GetSize().y);
+
+    //
+    // Case 2 -- if we are one of the separately built standard Frame
+    //           children, like a statusbar, menubar, or toolbar we want to
+    //           use the frame, itself, for positioning.  Otherwise we are
+    //           child window and want to use the Frame's client.
+    //
+    else if (pParent->IsKindOf(CLASSINFO(wxFrame)))
+    {
+        if (IsKindOf(CLASSINFO(wxStatusBar)) ||
+            IsKindOf(CLASSINFO(wxMenuBar))   ||
+            IsKindOf(CLASSINFO(wxToolBar))
+           )
+            return(pParent->GetSize().y);
+        else
+            return(pParent->GetClientSize().y);
+    }
+
+    //
+    // Case 3 -- this is for any window that is the sole child of a Frame.
+    //           The grandparent must exist and it must be of type CFrame
+    //           and it's height must be different. Otherwise the standard
+    //           applies.
+    //
+    else
+    {
+        pGrandParent = pParent->GetParent();
+        if (pGrandParent &&
+            pGrandParent->IsKindOf(CLASSINFO(wxFrame)) &&
+            pGrandParent->GetClientSize().y != pParent->GetSize().y
+           )
+        {
+            int                     nParentHeight = 0L;
+            int                     nStatusBarHeight = 0L;
+            wxFrame*                pFrame = wxDynamicCast(pGrandParent, wxFrame);
+            wxStatusBar*            pStatbar = pFrame->GetStatusBar();
+
+            nParentHeight = pGrandParent->GetClientSize().y;
+            if (pStatbar)
+                nStatusBarHeight = pStatbar->GetSize().y;
+            nParentHeight -= nStatusBarHeight;
+            return(nParentHeight);
+        }
+        else
+            //
+            // Panel is a child of some other kind of window so we'll
+            // just use it's original size
+            //
+            return(pParent->GetClientSize().y);
+    }
+    return(0L);
+} // end of wxWindowOS2::GetOS2ParentHeight
+
+wxWindowCreationHook::wxWindowCreationHook(
+  wxWindow*                         pWinBeingCreated
+)
+{
+    gpWinBeingCreated = pWinBeingCreated;
+} // end of wxWindowCreationHook::wxWindowCreationHook
+
+wxWindowCreationHook::~wxWindowCreationHook()
+{
+    gpWinBeingCreated = NULL;
+} // end of wxWindowCreationHook::~wxWindowCreationHook
+
 // ===========================================================================
 // global functions
 // ===========================================================================