1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/nonownedwnd_osx.cpp
3 // Purpose: implementation of wxNonOwnedWindow
4 // Author: Stefan Csomor
7 // Copyright: (c) Stefan Csomor 2008
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
19 #include "wx/hashmap.h"
20 #include "wx/evtloop.h"
21 #include "wx/tooltip.h"
22 #include "wx/nonownedwnd.h"
24 #include "wx/osx/private.h"
25 #include "wx/settings.h"
28 #if wxUSE_SYSTEM_OPTIONS
29 #include "wx/sysopt.h"
32 // ----------------------------------------------------------------------------
34 // ----------------------------------------------------------------------------
36 // trace mask for activation tracing messages
37 #define TRACE_ACTIVATE "activation"
39 wxWindow
* g_MacLastWindow
= NULL
;
41 // unified title and toolbar constant - not in Tiger headers, so we duplicate it here
42 #define kWindowUnifiedTitleAndToolbarAttribute (1 << 7)
44 // ---------------------------------------------------------------------------
45 // wxWindowMac utility functions
46 // ---------------------------------------------------------------------------
48 WX_DECLARE_HASH_MAP(WXWindow
, wxNonOwnedWindowImpl
*, wxPointerHash
, wxPointerEqual
, MacWindowMap
);
50 static MacWindowMap wxWinMacWindowList
;
52 wxNonOwnedWindow
* wxNonOwnedWindow
::GetFromWXWindow( WXWindow win
)
54 wxNonOwnedWindowImpl
* impl
= wxNonOwnedWindowImpl
::FindFromWXWindow(win
);
56 return ( impl
!= NULL ? impl
->GetWXPeer() : NULL
) ;
59 wxNonOwnedWindowImpl
* wxNonOwnedWindowImpl
::FindFromWXWindow (WXWindow window
)
61 MacWindowMap
::iterator node
= wxWinMacWindowList
.find(window
);
63 return (node
== wxWinMacWindowList
.end()) ? NULL
: node
->second
;
66 void wxNonOwnedWindowImpl
::RemoveAssociations( wxNonOwnedWindowImpl
* impl
)
68 MacWindowMap
::iterator it
;
69 for ( it
= wxWinMacWindowList
.begin(); it
!= wxWinMacWindowList
.end(); ++it
)
71 if ( it
->second
== impl
)
73 wxWinMacWindowList
.erase(it
);
79 void wxNonOwnedWindowImpl
::Associate( WXWindow window
, wxNonOwnedWindowImpl
*impl
)
81 // adding NULL WindowRef is (first) surely a result of an error and
83 wxCHECK_RET( window
!= (WXWindow
) NULL
, wxT("attempt to add a NULL WindowRef to window list") );
85 wxWinMacWindowList
[window
] = impl
;
88 // ----------------------------------------------------------------------------
89 // wxNonOwnedWindow creation
90 // ----------------------------------------------------------------------------
92 IMPLEMENT_ABSTRACT_CLASS( wxNonOwnedWindowImpl
, wxObject
)
94 wxNonOwnedWindow
*wxNonOwnedWindow
::s_macDeactivateWindow
= NULL
;
96 void wxNonOwnedWindow
::Init()
99 m_isNativeWindowWrapper
= false;
102 bool wxNonOwnedWindow
::Create(wxWindow
*parent
,
104 const wxPoint
& posOrig
,
105 const wxSize
& sizeOrig
,
107 const wxString
& name
)
109 m_windowStyle
= style
;
113 m_windowId
= id
== -1 ?
NewControlId() : id
;
114 m_windowStyle
= style
;
117 // use the appropriate defaults for the position and size if necessary
118 wxSize
size(sizeOrig
);
119 if ( !size
.IsFullySpecified() )
120 size
.SetDefaults(wxTopLevelWindow
::GetDefaultSize());
122 wxPoint
pos(posOrig
);
123 if ( !pos
.IsFullySpecified() )
125 wxRect rectWin
= wxRect(size
).CentreIn(wxGetClientDisplayRect());
127 // The size of the window is often not really known yet, TLWs are often
128 // created with some small initial size and later are fitted to contain
129 // their children so centering the window will show it too much to the
130 // right and bottom, adjust for it by putting it more to the left and
135 pos
.SetDefaults(rectWin
.GetPosition());
139 m_nowpeer
= wxNonOwnedWindowImpl
::CreateNonOwnedWindow
143 style
, GetExtraStyle(),
146 wxNonOwnedWindowImpl
::Associate( m_nowpeer
->GetWXWindow() , m_nowpeer
) ;
147 SetPeer(wxWidgetImpl
::CreateContentView(this));
149 DoSetWindowVariant( m_windowVariant
) ;
151 wxWindowCreateEvent
event(this);
152 HandleWindowEvent(event
);
154 SetBackgroundColour(wxSystemSettings
::GetColour( wxSYS_COLOUR_3DFACE
));
157 parent
->AddChild(this);
162 bool wxNonOwnedWindow
::Create(wxWindow
*parent
, WXWindow nativeWindow
)
165 parent
->AddChild(this);
167 SubclassWin(nativeWindow
);
172 void wxNonOwnedWindow
::SubclassWin(WXWindow nativeWindow
)
174 wxASSERT_MSG( !m_isNativeWindowWrapper
, wxT("subclassing window twice?") );
175 wxASSERT_MSG( m_nowpeer
== NULL
, wxT("window already was created") );
177 m_nowpeer
= wxNonOwnedWindowImpl
::CreateNonOwnedWindow(this, GetParent(), nativeWindow
);
178 m_isNativeWindowWrapper
= true;
179 wxNonOwnedWindowImpl
::Associate( m_nowpeer
->GetWXWindow() , m_nowpeer
) ;
180 SetPeer(wxWidgetImpl
::CreateContentView(this));
183 void wxNonOwnedWindow
::UnsubclassWin()
185 wxASSERT_MSG( m_isNativeWindowWrapper
, wxT("window was not subclassed") );
188 GetParent()->RemoveChild(this);
190 wxNonOwnedWindowImpl
::RemoveAssociations(m_nowpeer
) ;
193 m_isNativeWindowWrapper
= false;
197 wxNonOwnedWindow
::~wxNonOwnedWindow()
201 wxNonOwnedWindowImpl
::RemoveAssociations(m_nowpeer
) ;
207 // avoid dangling refs
208 if ( s_macDeactivateWindow
== this )
209 s_macDeactivateWindow
= NULL
;
212 bool wxNonOwnedWindow
::Destroy()
216 return wxWindow
::Destroy();
219 void wxNonOwnedWindow
::WillBeDestroyed()
222 m_nowpeer
->WillBeDestroyed();
225 // ----------------------------------------------------------------------------
226 // wxNonOwnedWindow misc
227 // ----------------------------------------------------------------------------
229 bool wxNonOwnedWindow
::OSXShowWithEffect(bool show
,
233 // Cocoa code needs to manage window visibility on its own and so calls
234 // wxWindow::Show() as needed but if we already changed the internal
235 // visibility flag here, Show() would do nothing, so avoid doing it
237 if ( !wxWindow
::Show(show
) )
241 if ( effect
== wxSHOW_EFFECT_NONE
||
242 !m_nowpeer
|| !m_nowpeer
->ShowWithEffect(show
, effect
, timeout
) )
247 // as apps expect a size event to occur when the window is shown,
248 // generate one when it is shown with effect too
249 wxSizeEvent
event(GetSize(), m_windowId
);
250 event
.SetEventObject(this);
251 HandleWindowEvent(event
);
257 wxPoint wxNonOwnedWindow
::GetClientAreaOrigin() const
259 int left
, top
, width
, height
;
260 m_nowpeer
->GetContentArea(left
, top
, width
, height
);
261 return wxPoint(left
, top
);
264 bool wxNonOwnedWindow
::SetBackgroundColour(const wxColour
& c
)
266 if ( !wxWindow
::SetBackgroundColour(c
) && m_hasBgCol
)
269 if ( GetBackgroundStyle() != wxBG_STYLE_CUSTOM
)
272 return m_nowpeer
->SetBackgroundColour(c
);
277 void wxNonOwnedWindow
::SetWindowStyleFlag(long flags
)
279 if (flags
== GetWindowStyleFlag())
282 wxWindow
::SetWindowStyleFlag(flags
);
285 m_nowpeer
->SetWindowStyleFlag(flags
);
288 // Raise the window to the top of the Z order
289 void wxNonOwnedWindow
::Raise()
294 // Lower the window to the bottom of the Z order
295 void wxNonOwnedWindow
::Lower()
300 void wxNonOwnedWindow
::HandleActivated( double timestampsec
, bool didActivate
)
302 MacActivate( (int) (timestampsec
* 1000) , didActivate
);
303 wxActivateEvent
wxevent(wxEVT_ACTIVATE
, didActivate
, GetId());
304 wxevent
.SetTimestamp( (int) (timestampsec
* 1000) );
305 wxevent
.SetEventObject(this);
306 HandleWindowEvent(wxevent
);
309 void wxNonOwnedWindow
::HandleResized( double timestampsec
)
311 wxSizeEvent
wxevent( GetSize() , GetId());
312 wxevent
.SetTimestamp( (int) (timestampsec
* 1000) );
313 wxevent
.SetEventObject( this );
314 HandleWindowEvent(wxevent
);
315 // we have to inform some controls that have to reset things
316 // relative to the toplevel window (e.g. OpenGL buffers)
317 wxWindowMac
::MacSuperChangedPosition() ; // like this only children will be notified
320 void wxNonOwnedWindow
::HandleResizing( double WXUNUSED(timestampsec
), wxRect
* rect
)
324 // this is a EVT_SIZING not a EVT_SIZE type !
325 wxSizeEvent
wxevent( r
, GetId() ) ;
326 wxevent
.SetEventObject( this ) ;
327 if ( HandleWindowEvent(wxevent
) )
328 r
= wxevent
.GetRect() ;
330 if ( GetMaxWidth() != -1 && r
.GetWidth() > GetMaxWidth() )
331 r
.SetWidth( GetMaxWidth() ) ;
332 if ( GetMaxHeight() != -1 && r
.GetHeight() > GetMaxHeight() )
333 r
.SetHeight( GetMaxHeight() ) ;
334 if ( GetMinWidth() != -1 && r
.GetWidth() < GetMinWidth() )
335 r
.SetWidth( GetMinWidth() ) ;
336 if ( GetMinHeight() != -1 && r
.GetHeight() < GetMinHeight() )
337 r
.SetHeight( GetMinHeight() ) ;
340 // TODO actuall this is too early, in case the window extents are adjusted
341 wxWindowMac
::MacSuperChangedPosition() ; // like this only children will be notified
344 void wxNonOwnedWindow
::HandleMoved( double timestampsec
)
346 wxMoveEvent
wxevent( GetPosition() , GetId());
347 wxevent
.SetTimestamp( (int) (timestampsec
* 1000) );
348 wxevent
.SetEventObject( this );
349 HandleWindowEvent(wxevent
);
352 void wxNonOwnedWindow
::MacDelayedDeactivation(long timestamp
)
354 if (s_macDeactivateWindow
)
356 wxLogTrace(TRACE_ACTIVATE
,
357 wxT("Doing delayed deactivation of %p"),
358 s_macDeactivateWindow
);
360 s_macDeactivateWindow
->MacActivate(timestamp
, false);
364 void wxNonOwnedWindow
::MacActivate( long timestamp
, bool WXUNUSED(inIsActivating
) )
366 wxLogTrace(TRACE_ACTIVATE
, wxT("TopLevel=%p::MacActivate"), this);
368 if (s_macDeactivateWindow
== this)
369 s_macDeactivateWindow
= NULL
;
371 MacDelayedDeactivation(timestamp
);
374 bool wxNonOwnedWindow
::Show(bool show
)
376 if ( !wxWindow
::Show(show
) )
380 m_nowpeer
->Show(show
);
384 // because apps expect a size event to occur at this moment
385 wxSizeEvent
event(GetSize() , m_windowId
);
386 event
.SetEventObject(this);
387 HandleWindowEvent(event
);
393 bool wxNonOwnedWindow
::SetTransparent(wxByte alpha
)
395 return m_nowpeer
->SetTransparent(alpha
);
399 bool wxNonOwnedWindow
::CanSetTransparent()
401 return m_nowpeer
->CanSetTransparent();
405 void wxNonOwnedWindow
::SetExtraStyle(long exStyle
)
407 if ( GetExtraStyle() == exStyle
)
410 wxWindow
::SetExtraStyle( exStyle
) ;
413 m_nowpeer
->SetExtraStyle(exStyle
);
416 bool wxNonOwnedWindow
::SetBackgroundStyle(wxBackgroundStyle style
)
418 if ( !wxWindow
::SetBackgroundStyle(style
) )
421 return m_nowpeer ? m_nowpeer
->SetBackgroundStyle(style
) : true;
424 void wxNonOwnedWindow
::DoMoveWindow(int x
, int y
, int width
, int height
)
426 if ( m_nowpeer
== NULL
)
429 m_cachedClippedRectValid
= false ;
431 m_nowpeer
->MoveWindow(x
, y
, width
, height
);
432 wxWindowMac
::MacSuperChangedPosition() ; // like this only children will be notified
435 void wxNonOwnedWindow
::DoGetPosition( int *x
, int *y
) const
437 if ( m_nowpeer
== NULL
)
441 m_nowpeer
->GetPosition(x1
, y1
);
449 void wxNonOwnedWindow
::DoGetSize( int *width
, int *height
) const
451 if ( m_nowpeer
== NULL
)
456 m_nowpeer
->GetSize(w
, h
);
464 void wxNonOwnedWindow
::DoGetClientSize( int *width
, int *height
) const
466 if ( m_nowpeer
== NULL
)
470 // under iphone with a translucent status bar the m_nowpeer returns the
471 // inner area, while the content area extends under the translucent
472 // status bar, therefore we use the content view's area
473 #ifdef __WXOSX_IPHONE__
474 GetPeer()->GetContentArea(left
, top
, w
, h
);
476 m_nowpeer
->GetContentArea(left
, top
, w
, h
);
486 void wxNonOwnedWindow
::Update()
491 WXWindow wxNonOwnedWindow
::GetWXWindow() const
493 return m_nowpeer ? m_nowpeer
->GetWXWindow() : NULL
;
496 // ---------------------------------------------------------------------------
497 // Shape implementation
498 // ---------------------------------------------------------------------------
501 bool wxNonOwnedWindow
::DoSetShape(const wxRegion
& region
)
503 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false,
504 wxT("Shaped windows must be created with the wxFRAME_SHAPED style."));
508 // The empty region signifies that the shape
509 // should be removed from the window.
510 if ( region
.IsEmpty() )
512 wxSize sz
= GetClientSize();
513 wxRegion
rgn(0, 0, sz
.x
, sz
.y
);
517 return DoSetShape(rgn
);
520 return m_nowpeer
->SetShape(region
);