X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2be39ac9d8aab94967b5e546a2acb6a56292eece..68cb30154e69c03d141aa649f024e916c5a96540:/src/os2/window.cpp?ds=inline diff --git a/src/os2/window.cpp b/src/os2/window.cpp index c1f50464dc..26e94bc0cc 100644 --- a/src/os2/window.cpp +++ b/src/os2/window.cpp @@ -306,6 +306,16 @@ wxWindow::~wxWindow() m_isBeingDeleted = TRUE; OS2DetachWindowMenu(); + for (wxWindow* pWin = GetParent(); pWin; pWin = pWin->GetParent()) + { + wxFrame* pFrame = wxDynamicCast(pWin, wxFrame); + + if (pFrame) + { + if (pFrame->GetLastFocus() == this) + pFrame->SetLastFocus((wxWindow*)NULL); + } + } if (m_parent) m_parent->RemoveChild(this); DestroyChildren(); @@ -332,6 +342,7 @@ bool wxWindow::Create( { HWND hParent = NULLHANDLE; wxPoint vPos = rPos; // The OS/2 position + ULONG ulCreateFlags = 0L; wxCHECK_MSG(pParent, FALSE, wxT("can't create wxWindow without parent")); @@ -347,12 +358,32 @@ bool wxWindow::Create( if (pParent) { + int nTempy; + pParent->AddChild(this); hParent = GetWinHwnd(pParent); // // OS2 uses normal coordinates, no bassackwards Windows ones // - vPos.y = pParent->GetSize().y - (vPos.y + rSize.y); + if (pParent->IsKindOf(CLASSINFO(wxGenericScrolledWindow)) || + pParent->IsKindOf(CLASSINFO(wxScrolledWindow)) + ) + { + wxWindow* pGrandParent = NULL; + + pGrandParent = pParent->GetParent(); + if (pGrandParent) + nTempy = pGrandParent->GetSize().y - (vPos.y + rSize.y); + else + nTempy = pParent->GetSize().y - (vPos.y + rSize.y); + } + else + nTempy = pParent->GetSize().y - (vPos.y + rSize.y); + vPos.y = nTempy; + if ( pParent->IsKindOf(CLASSINFO(wxGenericScrolledWindow)) || + pParent->IsKindOf(CLASSINFO(wxScrolledWindow)) + ) + ulCreateFlags |= WS_CLIPSIBLINGS; } else { @@ -363,9 +394,6 @@ bool wxWindow::Create( vPos.y = vRect.yTop - (vPos.y + rSize.y); } - ULONG ulCreateFlags = 0L; - - // // Most wxSTYLES are really PM Class specific styles and will be // set in those class create procs. PM's basic windows styles are @@ -374,18 +402,25 @@ bool wxWindow::Create( ulCreateFlags |= WS_VISIBLE; - if ( lStyle & wxCLIP_SIBLINGS ) + if (lStyle & wxCLIP_SIBLINGS) ulCreateFlags |= WS_CLIPSIBLINGS; if (lStyle & wxCLIP_CHILDREN ) ulCreateFlags |= WS_CLIPCHILDREN; // - // Empty stuff for now since PM has no custome 3D effects - // Doesn't mean someone cannot make some up though + // // bool bWant3D; - WXDWORD dwExStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &bWant3D); + WXDWORD dwExStyle = Determine3DEffects( WS_EX_CLIENTEDGE + ,&bWant3D + ); + + // + // Add the simple border style as we'll use this to draw borders + // + if (lStyle & wxSIMPLE_BORDER) + dwExStyle |= wxSIMPLE_BORDER; // // Generic OS/2 Windows are created with no owner, no Z Order, no Control data, @@ -402,6 +437,9 @@ bool wxWindow::Create( ,NULLHANDLE ,NULLHANDLE ,m_windowId + ,NULL + ,NULL + ,dwExStyle ); return(TRUE); @@ -602,7 +640,24 @@ void wxWindow::SetScrollRange( , bool bRefresh ) { - ::WinSendMsg(GetHwnd(), SBM_SETSCROLLBAR, (MPARAM)0, MPFROM2SHORT(0, nRange)); + int nRange1 = nRange; + int nPageSize = GetScrollPage(nOrient); + + if (nPpageSize > 1 && nRange > 0) + { + nRange1 += (nPageSize - 1); + } + + if (nOrient == wxHORIZONTAL) + { + ::WinSendMsg(m_hWndScrollBarHorz, SBM_SETSCROLLBAR, (MPARAM)0, MPFROM2SHORT(0, (SHORT)nRange1)); + ::WinSendMsg(m_hWndScrollBarHorz, SBM_SETTHUMBSIZE, MPFROM2SHORT((SHORT)nThumbVisible, (SHORT)nRange1), (MPARAM)0); + } + else + { + ::WinSendMsg(m_hWndScrollBarVert, SBM_SETSCROLLBAR, (MPARAM)0, MPFROM2SHORT(0, (SHORT)nRange1)); + ::WinSendMsg(m_hWndScrollBarVert, SBM_SETTHUMBSIZE, MPFROM2SHORT((SHORT)nThumbVisible, (SHORT)nRange1), (MPARAM)0); + } } // end of wxWindow::SetScrollRange void wxWindow::SetScrollPage( @@ -611,11 +666,11 @@ void wxWindow::SetScrollPage( , bool bRefresh ) { - if ( orient == wxHORIZONTAL ) - m_xThumbSize = page; + if (nOrient == wxHORIZONTAL ) + m_nXThumbSize = nPage; else - m_yThumbSize = page; -} + m_nYThumbSize = nPage; +} // end of wxWindow::SetScrollPage int wxWindow::OldGetScrollRange( int nOrient @@ -647,7 +702,10 @@ int wxWindow::GetScrollPos( int nOrient ) const { - return((int)::WinSendMsg(GetHwnd(), SBM_QUERYPOS, (MPARAM)NULL, (MPARAM)NULL)); + if (nOrient == wxHORIZONTAL) + return((int)::WinSendMsg(m_hWndScrollBarHorz, SBM_QUERYPOS, (MPARAM)NULL, (MPARAM)NULL)); + else + return((int)::WinSendMsg(m_hWndScrollBarVert, SBM_QUERYPOS, (MPARAM)NULL, (MPARAM)NULL)); } // end of wxWindow::GetScrollPos int wxWindow::GetScrollRange( @@ -656,7 +714,10 @@ int wxWindow::GetScrollRange( { MRESULT mr; - mr = ::WinSendMsg(GetHwnd(), SBM_QUERYRANGE, (MPARAM)NULL, (MPARAM)NULL); + if (nOrient == wxHORIZONTAL) + mr = ::WinSendMsg(m_hWndScrollBarHorz, SBM_QUERYRANGE, (MPARAM)NULL, (MPARAM)NULL); + else + mr = ::WinSendMsg(m_hWndScrollBarVert, SBM_QUERYRANGE, (MPARAM)NULL, (MPARAM)NULL); return((int)SHORT2FROMMR(mr)); } // end of wxWindow::GetScrollRange @@ -664,12 +725,10 @@ int wxWindow::GetScrollThumb( int nOrient ) const { - WNDPARAMS vWndParams; - PSBCDATA pSbcd; - - ::WinSendMsg(GetHwnd(), WM_QUERYWINDOWPARAMS, (MPARAM)&vWndParams, (MPARAM)NULL); - pSbcd = (PSBCDATA)vWndParams.pCtlData; - return((int)pSbcd->posThumb); + if (nOrient == wxHORIZONTAL ) + return m_nXThumbSize; + else + return m_nYThumbSize; } // end of wxWindow::GetScrollThumb void wxWindow::SetScrollPos( @@ -678,7 +737,10 @@ void wxWindow::SetScrollPos( , bool bRefresh ) { - ::WinSendMsg(GetHwnd(), SBM_SETPOS, (MPARAM)nPos, (MPARAM)NULL); + if (nOrient == wxHORIZONTAL ) + ::WinSendMsg(m_hWndScrollBarHorz, SBM_SETPOS, (MPARAM)nPos, (MPARAM)NULL); + else + ::WinSendMsg(m_hWndScrollBarVert, SBM_SETPOS, (MPARAM)nPos, (MPARAM)NULL); } // end of wxWindow::SetScrollPos( void wxWindow::SetScrollbar( @@ -694,7 +756,7 @@ void wxWindow::SetScrollbar( int nPageSize = nThumbVisible; SBCDATA vInfo; HWND hWnd = GetHwnd(); - ULONG ulStyle = WS_VISIBLE; + ULONG ulStyle = WS_VISIBLE | WS_SYNCPAINT; RECTL vRect; ::WinQueryWindowRect(hWnd, &vRect); @@ -713,6 +775,11 @@ void wxWindow::SetScrollbar( ulStyle |= SBS_HORZ; if (m_hWndScrollBarHorz == 0L) { + // + // We create the scrollbars with the desktop so that they are not + // registered as child windows of the window in order that child + // windows may be scrolled without scrolling the scrollbars themselves! + // m_hWndScrollBarHorz = ::WinCreateWindow( hWnd ,WC_SCROLLBAR ,(PSZ)NULL @@ -723,7 +790,7 @@ void wxWindow::SetScrollbar( ,20 ,hWnd ,HWND_TOP - ,-1 + ,FID_HORZSCROLL ,&vInfo ,NULL ); @@ -768,12 +835,12 @@ void wxWindow::SetScrollbar( ,(PSZ)NULL ,ulStyle ,vRect.xRight - 20 - ,vRect.yBottom + ,vRect.yBottom + 20 ,20 - ,vRect.yTop - vRect.yBottom + ,vRect.yTop - (vRect.yBottom + 20) ,hWnd ,HWND_TOP - ,-1 + ,FID_VERTSCROLL ,&vInfo ,NULL ); @@ -798,9 +865,9 @@ void wxWindow::SetScrollbar( ::WinSetWindowPos( m_hWndScrollBarVert ,HWND_TOP ,vRect.xRight - 20 - ,vRect.yBottom + ,vRect.yBottom + 20 ,20 - ,vRect.yTop - vRect.yBottom + ,vRect.yTop - (vRect.yBottom + 20) ,SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW ); } @@ -817,20 +884,87 @@ void wxWindow::ScrollWindow( , const wxRect* pRect ) { + RECTL vRect; RECTL vRect2; + nDy *= -1; // flip the sign of Dy as OS/2 is opposite wxWin. if (pRect) { vRect2.xLeft = pRect->x; - vRect2.yTop = pRect->y; + vRect2.yTop = pRect->y + pRect->height; vRect2.xRight = pRect->x + pRect->width; - vRect2.yBottom = pRect->y + pRect->height; + vRect2.yBottom = pRect->y; } + else + { + ::WinQueryWindowRect(GetHwnd(), &vRect2); + ::WinQueryWindowRect(m_hWndScrollBarHorz, &vRect); + vRect2.yBottom += vRect.yTop - vRect.yBottom; + ::WinQueryWindowRect(m_hWndScrollBarVert, &vRect); + vRect2.xRight -= vRect.xRight - vRect.xLeft; + } if (pRect) - ::WinScrollWindow(GetHwnd(), (LONG)nDx, (LONG)nDy, &vRect2, NULL, NULLHANDLE, NULL, 0L); + ::WinScrollWindow( GetHwnd() + ,(LONG)nDx + ,(LONG)nDy + ,&vRect2 + ,NULL + ,NULLHANDLE + ,NULL + ,SW_INVALIDATERGN + ); else - ::WinScrollWindow(GetHwnd(), nDx, nDy, NULL, NULL, NULLHANDLE, NULL, 0L); + ::WinScrollWindow( GetHwnd() + ,nDx + ,nDy + ,NULL + ,NULL + ,NULLHANDLE + ,NULL + ,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->GetHWND() == m_hWndScrollBarVert || + pChildWin->GetHWND() == m_hWndScrollBarHorz) + { + ::WinSetWindowPos( pChildWin->GetHWND() + ,HWND_TOP + ,vSwp.x + nDx + ,vSwp.y + nDy + ,0 + ,0 + ,SWP_MOVE | SWP_SHOW | SWP_ZORDER + ); + } + else + { + ::WinSetWindowPos( pChildWin->GetHWND() + ,HWND_BOTTOM + ,vSwp.x + nDx + ,vSwp.y + nDy + ,0 + ,0 + ,SWP_MOVE | SWP_ZORDER + ); + ::WinInvalidateRect(pChildWin->GetHWND(), &vRect, FALSE); + } + } + pCurrent = pCurrent->GetNext(); + } } // end of wxWindow::ScrollWindow // --------------------------------------------------------------------------- @@ -878,16 +1012,32 @@ WXDWORD wxWindow::MakeExtendedStyle( ) { // - // PM does not support extended style + // Simply fill out with wxWindow extended styles. We'll conjure + // something up in OS2Create and all window redrawing pieces later // - WXDWORD exStyle = 0; - return exStyle; + WXDWORD dwStyle = 0; + + if (lStyle & wxTRANSPARENT_WINDOW ) + dwStyle |= wxTRANSPARENT_WINDOW; + + if (!bEliminateBorders) + { + if (lStyle & wxSUNKEN_BORDER) + dwStyle |= wxSUNKEN_BORDER; + if (lStyle & wxDOUBLE_BORDER) + dwStyle |= wxDOUBLE_BORDER; + if (lStyle & wxRAISED_BORDER ) + dwStyle |= wxRAISED_BORDER; + if (lStyle & wxSTATIC_BORDER) + dwStyle |= wxSTATIC_BORDER; + } + return dwStyle; } // end of wxWindow::MakeExtendedStyle // -// Determines whether native 3D effects or CTL3D should be used, +// Determines whether simulated 3D effects or CTL3D should be used, // applying a default border style if required, and returning an extended -// style to pass to CreateWindowEx. +// style to pass to OS2Create. // WXDWORD wxWindow::Determine3DEffects( WXDWORD dwDefaultBorderStyle @@ -897,9 +1047,65 @@ WXDWORD wxWindow::Determine3DEffects( WXDWORD dwStyle = 0L; // - // Native PM does not have any specialize 3D effects like WIN32 does + // Native PM does not have any specialize 3D effects like WIN32 does, + // so we have to try and invent them. + // + + // + // If matches certain criteria, then assume no 3D effects + // unless specifically requested (dealt with in MakeExtendedStyle) + // + if (!GetParent() || + !IsKindOf(CLASSINFO(wxControl)) || + (m_windowStyle & wxNO_BORDER) + ) + { + *pbWant3D = FALSE; + return MakeExtendedStyle(m_windowStyle, FALSE); + } + + // + // 1) App can specify global 3D effects + // + *pbWant3D = wxTheApp->GetAuto3D(); + + // + // 2) If the parent is being drawn with user colours, or simple border + // specified, switch effects off. + // + if (GetParent() && + (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS) || + (m_windowStyle & wxSIMPLE_BORDER) + ) + *pbWant3D = FALSE; + + // + // 3) Control can override this global setting by defining + // a border style, e.g. wxSUNKEN_BORDER // - *pbWant3D = FALSE; + if ((m_windowStyle & wxDOUBLE_BORDER) || + (m_windowStyle & wxRAISED_BORDER) || + (m_windowStyle & wxSTATIC_BORDER) || + (m_windowStyle & wxSUNKEN_BORDER) + ) + *pbWant3D = TRUE; + + dwStyle = MakeExtendedStyle( m_windowStyle + ,FALSE + ); + + // + // If we want 3D, but haven't specified a border here, + // apply the default border style specified. + // + if (dwDefaultBorderStyle && (*pbWant3D) && + !((m_windowStyle & wxDOUBLE_BORDER) || + (m_windowStyle & wxRAISED_BORDER) || + (m_windowStyle & wxSTATIC_BORDER) || + (m_windowStyle & wxSIMPLE_BORDER) + ) + ) + dwStyle |= dwDefaultBorderStyle; return dwStyle; } // end of wxWindow::Determine3DEffects @@ -1220,7 +1426,10 @@ void wxWindow::DoGetClientSize( HWND hWndClient; RECTL vRect; - hWndClient = ::WinWindowFromID(GetHwnd(), FID_CLIENT); + if (IsKindOf(CLASSINFO(wxFrame))) + hWndClient = ::WinWindowFromID(GetHwnd(), FID_CLIENT); + else + hWndClient = NULLHANDLE; if( hWndClient == NULLHANDLE) ::WinQueryWindowRect(GetHwnd(), &vRect); else @@ -1239,6 +1448,17 @@ void wxWindow::DoMoveWindow( , int nHeight ) { + RECTL vRect; + HWND hParent; + wxWindow* pParent = GetParent(); + + if (pParent) + hParent = GetWinHwnd(pParent); + else + hParent = HWND_DESKTOP; + ::WinQueryWindowRect(hParent, &vRect); + nY = vRect.yTop - (nY + nHeight); + if ( !::WinSetWindowPos( GetHwnd() ,HWND_TOP ,(LONG)nX @@ -1590,6 +1810,26 @@ void wxWindow::GetCaretPos( // popup menu // --------------------------------------------------------------------------- +static void wxYieldForCommandsOnly() +{ + // + // Peek all WM_COMMANDs (it will always return WM_QUIT too but we don't + // want to process it here) + // + QMSG vMsg; + + while (::WinPeekMsg( vHabmain + ,&vMsg + ,(HWND)0 + ,WM_COMMAND + ,WM_COMMAND + ,PM_REMOVE + ) && vMsg.msg != WM_QUIT) + { + wxTheApp->DoMessage((WXMSG*)&vMsg); + } +} + bool wxWindow::DoPopupMenu( wxMenu* pMenu , int nX @@ -1616,7 +1856,14 @@ bool wxWindow::DoPopupMenu( ,0L ,PU_MOUSEBUTTON2DOWN | PU_MOUSEBUTTON2 | PU_KEYBOARD ); - wxYield(); + // we need to do it righ now as otherwise the events are never going to be + // sent to wxCurrentPopupMenu from HandleCommand() + // + // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't + // help and we'd still need wxYieldForCommandsOnly() as the menu may be + // destroyed as soon as we return (it can be a local variable in the caller + // for example) and so we do need to process the event immediately + wxYieldForCommandsOnly(); wxCurrentPopupMenu = NULL; pMenu->SetInvokingWindow(NULL); @@ -1874,9 +2121,18 @@ void wxWindow::UnpackScroll( , WXHWND* phWnd ) { - *pCode = LOWORD(wParam); - *pPos = HIWORD(wParam); - *phWnd = (WXHWND)lParam; + ULONG ulId; + HWND hWnd; + + ulId = (ULONG)LONGFROMMP(wParam); + hWnd = ::WinWindowFromID(GetHwnd(), ulId); + if (hWnd == m_hWndScrollBarHorz || hWnd == m_hWndScrollBarVert) + *phWnd = NULLHANDLE; + else + *phWnd = hWnd; + + *pPos = SHORT1FROMMP(lParam); + *pCode = SHORT2FROMMP(lParam); } // end of wxWindow::UnpackScroll void wxWindow::UnpackMenuSelect( @@ -2455,6 +2711,7 @@ bool wxWindow::OS2Create( , unsigned long ulId , void* pCtlData , void* pPresParams +, WXDWORD dwExStyle ) { ERRORID vError; @@ -2474,10 +2731,8 @@ bool wxWindow::OS2Create( RECTL vParentRect; HWND hWndClient; - if (lX > -1L) - lX1 = lX; - if (lY > -1L) - lY1 = lY; + lX1 = lX; + lY1 = lY; if (lWidth > -1L) lWidth1 = lWidth; if (lHeight > -1L) @@ -2545,6 +2800,7 @@ bool wxWindow::OS2Create( wxLogError("Can't create window of class %s!. Error: %s\n", zClass, sError); return FALSE; } + m_dwExStyle = dwExStyle; ::WinSetWindowULong(m_hWnd, QWL_USER, (ULONG) this); wxWndHook = NULL; @@ -3112,6 +3368,30 @@ bool wxWindow::HandlePaint() ); ::WinFillRect(hPS, &vRect, GetBackgroundColour().GetPixel()); + + if (m_dwExStyle) + { + LINEBUNDLE vLineBundle; + + vLineBundle.lColor = 0x00000000; // Black + vLineBundle.usMixMode = FM_OVERPAINT; + vLineBundle.fxWidth = 1; + vLineBundle.lGeomWidth = 1; + vLineBundle.usType = LINETYPE_SOLID; + vLineBundle.usEnd = 0; + vLineBundle.usJoin = 0; + ::GpiSetAttrs( hPS + ,PRIM_LINE + ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE + ,0L + ,&vLineBundle + ); + ::WinQueryWindowRect(GetHwnd(), &vRect); + wxDrawBorder( hPS + ,vRect + ,m_dwExStyle + ); + } ::WinEndPaint(hPS); } }