X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0aaa6ace7ede4240453251d6a1c84c918c54c321..63e1921d0be4956ab729735189ccf637773a7e27:/src/osx/nonownedwnd_osx.cpp diff --git a/src/osx/nonownedwnd_osx.cpp b/src/osx/nonownedwnd_osx.cpp index 12d8d61aab..10daf9d052 100644 --- a/src/osx/nonownedwnd_osx.cpp +++ b/src/osx/nonownedwnd_osx.cpp @@ -3,7 +3,7 @@ // Purpose: implementation of wxNonOwnedWindow // Author: Stefan Csomor // Created: 2008-03-24 -// RCS-ID: $Id: nonownedwnd.cpp 50329 2007-11-29 17:00:58Z VS $ +// RCS-ID: $Id$ // Copyright: (c) Stefan Csomor 2008 // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -13,6 +13,7 @@ #ifndef WX_PRECOMP #include "wx/app.h" + #include "wx/dcmemory.h" #include "wx/log.h" #endif // WX_PRECOMP @@ -38,6 +39,8 @@ wxWindow* g_MacLastWindow = NULL ; +clock_t wxNonOwnedWindow::s_lastFlush = 0; + // unified title and toolbar constant - not in Tiger headers, so we duplicate it here #define kWindowUnifiedTitleAndToolbarAttribute (1 << 7) @@ -45,36 +48,30 @@ wxWindow* g_MacLastWindow = NULL ; // wxWindowMac utility functions // --------------------------------------------------------------------------- -// Find an item given the Macintosh Window Reference - -WX_DECLARE_HASH_MAP(WXWindow, wxNonOwnedWindow*, wxPointerHash, wxPointerEqual, MacWindowMap); +WX_DECLARE_HASH_MAP(WXWindow, wxNonOwnedWindowImpl*, wxPointerHash, wxPointerEqual, MacWindowMap); static MacWindowMap wxWinMacWindowList; -wxNonOwnedWindow *wxFindWindowFromWXWindow(WXWindow inWindowRef) +wxNonOwnedWindow* wxNonOwnedWindow::GetFromWXWindow( WXWindow win ) { - MacWindowMap::iterator node = wxWinMacWindowList.find(inWindowRef); + wxNonOwnedWindowImpl* impl = wxNonOwnedWindowImpl::FindFromWXWindow(win); - return (node == wxWinMacWindowList.end()) ? NULL : node->second; + return ( impl != NULL ? impl->GetWXPeer() : NULL ) ; } -void wxAssociateWindowWithWXWindow(WXWindow inWindowRef, wxNonOwnedWindow *win) ; -void wxAssociateWindowWithWXWindow(WXWindow inWindowRef, wxNonOwnedWindow *win) +wxNonOwnedWindowImpl* wxNonOwnedWindowImpl::FindFromWXWindow (WXWindow window) { - // adding NULL WindowRef is (first) surely a result of an error and - // nothing else :-) - wxCHECK_RET( inWindowRef != (WXWindow) NULL, wxT("attempt to add a NULL WindowRef to window list") ); + MacWindowMap::iterator node = wxWinMacWindowList.find(window); - wxWinMacWindowList[inWindowRef] = win; + return (node == wxWinMacWindowList.end()) ? NULL : node->second; } -void wxRemoveWXWindowAssociation(wxNonOwnedWindow *win) ; -void wxRemoveWXWindowAssociation(wxNonOwnedWindow *win) +void wxNonOwnedWindowImpl::RemoveAssociations( wxNonOwnedWindowImpl* impl) { MacWindowMap::iterator it; for ( it = wxWinMacWindowList.begin(); it != wxWinMacWindowList.end(); ++it ) { - if ( it->second == win ) + if ( it->second == impl ) { wxWinMacWindowList.erase(it); break; @@ -82,9 +79,13 @@ void wxRemoveWXWindowAssociation(wxNonOwnedWindow *win) } } -wxNonOwnedWindow* wxNonOwnedWindow::GetFromWXWindow( WXWindow win ) +void wxNonOwnedWindowImpl::Associate( WXWindow window, wxNonOwnedWindowImpl *impl ) { - return wxFindWindowFromWXWindow( win ); + // adding NULL WindowRef is (first) surely a result of an error and + // nothing else :-) + wxCHECK_RET( window != (WXWindow) NULL, wxT("attempt to add a NULL WindowRef to window list") ); + + wxWinMacWindowList[window] = impl; } // ---------------------------------------------------------------------------- @@ -98,18 +99,16 @@ wxNonOwnedWindow *wxNonOwnedWindow::s_macDeactivateWindow = NULL; void wxNonOwnedWindow::Init() { m_nowpeer = NULL; + m_isNativeWindowWrapper = false; } bool wxNonOwnedWindow::Create(wxWindow *parent, wxWindowID id, - const wxPoint& pos, - const wxSize& size, + const wxPoint& posOrig, + const wxSize& sizeOrig, long style, const wxString& name) { - // init our fields - Init(); - m_windowStyle = style; SetName( name ); @@ -118,24 +117,37 @@ bool wxNonOwnedWindow::Create(wxWindow *parent, m_windowStyle = style; m_isShown = false; - // create frame. - int x = (int)pos.x; - int y = (int)pos.y; - - wxRect display = wxGetClientDisplayRect() ; + // use the appropriate defaults for the position and size if necessary + wxSize size(sizeOrig); + if ( !size.IsFullySpecified() ) + size.SetDefaults(wxTopLevelWindow::GetDefaultSize()); - if ( x == wxDefaultPosition.x ) - x = display.x ; + wxPoint pos(posOrig); + if ( !pos.IsFullySpecified() ) + { + wxRect rectWin = wxRect(size).CentreIn(wxGetClientDisplayRect()); - if ( y == wxDefaultPosition.y ) - y = display.y ; + // The size of the window is often not really known yet, TLWs are often + // created with some small initial size and later are fitted to contain + // their children so centering the window will show it too much to the + // right and bottom, adjust for it by putting it more to the left and + // center. + rectWin.x /= 2; + rectWin.y /= 2; - int w = WidthDefault(size.x); - int h = HeightDefault(size.y); + pos.SetDefaults(rectWin.GetPosition()); + } - m_nowpeer = wxNonOwnedWindowImpl::CreateNonOwnedWindow(this, parent, wxPoint(x,y) , wxSize(w,h) , style , GetExtraStyle(), name ); - wxAssociateWindowWithWXWindow( m_nowpeer->GetWXWindow() , this ) ; - m_peer = wxWidgetImpl::CreateContentView(this); + // create frame. + m_nowpeer = wxNonOwnedWindowImpl::CreateNonOwnedWindow + ( + this, parent, + pos , size, + style, GetExtraStyle(), + name + ); + wxNonOwnedWindowImpl::Associate( m_nowpeer->GetWXWindow() , m_nowpeer ) ; + SetPeer(wxWidgetImpl::CreateContentView(this)); DoSetWindowVariant( m_windowVariant ) ; @@ -147,32 +159,68 @@ bool wxNonOwnedWindow::Create(wxWindow *parent, if ( parent ) parent->AddChild(this); - wxBIND_OR_CONNECT_HACK(this, wxEVT_DESTROY, wxWindowDestroyEventHandler, - wxNonOwnedWindow::OnWindowDestroy, this); + return true; +} + +bool wxNonOwnedWindow::Create(wxWindow *parent, WXWindow nativeWindow) +{ + if ( parent ) + parent->AddChild(this); + + SubclassWin(nativeWindow); return true; } +void wxNonOwnedWindow::SubclassWin(WXWindow nativeWindow) +{ + wxASSERT_MSG( !m_isNativeWindowWrapper, wxT("subclassing window twice?") ); + wxASSERT_MSG( m_nowpeer == NULL, wxT("window already was created") ); + + m_nowpeer = wxNonOwnedWindowImpl::CreateNonOwnedWindow(this, GetParent(), nativeWindow ); + m_isNativeWindowWrapper = true; + wxNonOwnedWindowImpl::Associate( m_nowpeer->GetWXWindow() , m_nowpeer ) ; + SetPeer(wxWidgetImpl::CreateContentView(this)); +} + +void wxNonOwnedWindow::UnsubclassWin() +{ + wxASSERT_MSG( m_isNativeWindowWrapper, wxT("window was not subclassed") ); + + if ( GetParent() ) + GetParent()->RemoveChild(this); + + wxNonOwnedWindowImpl::RemoveAssociations(m_nowpeer) ; + wxDELETE(m_nowpeer); + SetPeer(NULL); + m_isNativeWindowWrapper = false; +} + + wxNonOwnedWindow::~wxNonOwnedWindow() { SendDestroyEvent(); - wxRemoveWXWindowAssociation( this ) ; + wxNonOwnedWindowImpl::RemoveAssociations(m_nowpeer) ; DestroyChildren(); - delete m_nowpeer; - m_nowpeer = NULL; + wxDELETE(m_nowpeer); // avoid dangling refs if ( s_macDeactivateWindow == this ) s_macDeactivateWindow = NULL; } -void wxNonOwnedWindow::OnWindowDestroy( wxWindowDestroyEvent &event) +bool wxNonOwnedWindow::Destroy() +{ + WillBeDestroyed(); + + return wxWindow::Destroy(); +} + +void wxNonOwnedWindow::WillBeDestroyed() { - event.Skip(); - if ( m_nowpeer ) m_nowpeer->WillBeDestroyed(); } @@ -201,6 +249,7 @@ bool wxNonOwnedWindow::OSXShowWithEffect(bool show, { // as apps expect a size event to occur when the window is shown, // generate one when it is shown with effect too + MacOnInternalSize(); wxSizeEvent event(GetSize(), m_windowId); event.SetEventObject(this); HandleWindowEvent(event); @@ -233,9 +282,9 @@ void wxNonOwnedWindow::SetWindowStyleFlag(long flags) { if (flags == GetWindowStyleFlag()) return; - + wxWindow::SetWindowStyleFlag(flags); - + if (m_nowpeer) m_nowpeer->SetWindowStyleFlag(flags); } @@ -263,6 +312,7 @@ void wxNonOwnedWindow::HandleActivated( double timestampsec, bool didActivate ) void wxNonOwnedWindow::HandleResized( double timestampsec ) { + MacOnInternalSize(); wxSizeEvent wxevent( GetSize() , GetId()); wxevent.SetTimestamp( (int) (timestampsec * 1000) ); wxevent.SetEventObject( this ); @@ -337,6 +387,7 @@ bool wxNonOwnedWindow::Show(bool show) if ( show ) { // because apps expect a size event to occur at this moment + MacOnInternalSize(); wxSizeEvent event(GetSize() , m_windowId); event.SetEventObject(this); HandleWindowEvent(event); @@ -422,9 +473,11 @@ void wxNonOwnedWindow::DoGetClientSize( int *width, int *height ) const return; int left, top, w, h; - // perhaps we should do this for all ? + // under iphone with a translucent status bar the m_nowpeer returns the + // inner area, while the content area extends under the translucent + // status bar, therefore we use the content view's area #ifdef __WXOSX_IPHONE__ - m_peer->GetContentArea(left, top, w, h); + GetPeer()->GetContentArea(left, top, w, h); #else m_nowpeer->GetContentArea(left, top, w, h); #endif @@ -435,10 +488,18 @@ void wxNonOwnedWindow::DoGetClientSize( int *width, int *height ) const *height = h ; } +void wxNonOwnedWindow::WindowWasPainted() +{ + s_lastFlush = clock(); +} void wxNonOwnedWindow::Update() { - m_nowpeer->Update(); + if ( clock() - s_lastFlush > CLOCKS_PER_SEC / 30 ) + { + s_lastFlush = clock(); + m_nowpeer->Update(); + } } WXWindow wxNonOwnedWindow::GetWXWindow() const @@ -450,23 +511,49 @@ WXWindow wxNonOwnedWindow::GetWXWindow() const // Shape implementation // --------------------------------------------------------------------------- +bool wxNonOwnedWindow::DoClearShape() +{ + m_shape.Clear(); + + wxSize sz = GetClientSize(); + wxRegion region(0, 0, sz.x, sz.y); + + return m_nowpeer->SetShape(region); +} + +bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion& region) +{ + m_shape = region; + + return m_nowpeer->SetShape(region); +} + +#if wxUSE_GRAPHICS_CONTEXT -bool wxNonOwnedWindow::DoSetShape(const wxRegion& region) +#include "wx/scopedptr.h" + +bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& path) { - wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false, - wxT("Shaped windows must be created with the wxFRAME_SHAPED style.")); + m_shapePath = path; + + // Convert the path to wxRegion by rendering the path on a window-sized + // bitmap, creating a mask from it and finally creating the region from + // this mask. + wxBitmap bmp(GetSize()); - // The empty region signifies that the shape - // should be removed from the window. - if ( region.IsEmpty() ) { - wxSize sz = GetClientSize(); - wxRegion rgn(0, 0, sz.x, sz.y); - if ( rgn.IsEmpty() ) - return false ; - else - return DoSetShape(rgn); + wxMemoryDC dc(bmp); + dc.SetBackground(*wxBLACK); + dc.Clear(); + + wxScopedPtr context(wxGraphicsContext::Create(dc)); + context->SetBrush(*wxWHITE); + context->FillPath(m_shapePath); } - return m_nowpeer->SetShape(region); + bmp.SetMask(new wxMask(bmp, *wxBLACK)); + + return DoSetRegionShape(wxRegion(bmp)); } + +#endif // wxUSE_GRAPHICS_CONTEXT