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"
16 #include "wx/dcmemory.h"
20 #include "wx/hashmap.h"
21 #include "wx/evtloop.h"
22 #include "wx/tooltip.h"
23 #include "wx/nonownedwnd.h"
25 #include "wx/osx/private.h"
26 #include "wx/settings.h"
29 #if wxUSE_SYSTEM_OPTIONS
30 #include "wx/sysopt.h"
33 // ----------------------------------------------------------------------------
35 // ----------------------------------------------------------------------------
37 // trace mask for activation tracing messages
38 #define TRACE_ACTIVATE "activation"
40 wxWindow
* g_MacLastWindow
= NULL
;
42 clock_t wxNonOwnedWindow::s_lastFlush
= 0;
44 // unified title and toolbar constant - not in Tiger headers, so we duplicate it here
45 #define kWindowUnifiedTitleAndToolbarAttribute (1 << 7)
47 // ---------------------------------------------------------------------------
48 // wxWindowMac utility functions
49 // ---------------------------------------------------------------------------
51 WX_DECLARE_HASH_MAP(WXWindow
, wxNonOwnedWindowImpl
*, wxPointerHash
, wxPointerEqual
, MacWindowMap
);
53 static MacWindowMap wxWinMacWindowList
;
55 wxNonOwnedWindow
* wxNonOwnedWindow::GetFromWXWindow( WXWindow win
)
57 wxNonOwnedWindowImpl
* impl
= wxNonOwnedWindowImpl::FindFromWXWindow(win
);
59 return ( impl
!= NULL
? impl
->GetWXPeer() : NULL
) ;
62 wxNonOwnedWindowImpl
* wxNonOwnedWindowImpl::FindFromWXWindow (WXWindow window
)
64 MacWindowMap::iterator node
= wxWinMacWindowList
.find(window
);
66 return (node
== wxWinMacWindowList
.end()) ? NULL
: node
->second
;
69 void wxNonOwnedWindowImpl::RemoveAssociations( wxNonOwnedWindowImpl
* impl
)
71 MacWindowMap::iterator it
;
72 for ( it
= wxWinMacWindowList
.begin(); it
!= wxWinMacWindowList
.end(); ++it
)
74 if ( it
->second
== impl
)
76 wxWinMacWindowList
.erase(it
);
82 void wxNonOwnedWindowImpl::Associate( WXWindow window
, wxNonOwnedWindowImpl
*impl
)
84 // adding NULL WindowRef is (first) surely a result of an error and
86 wxCHECK_RET( window
!= (WXWindow
) NULL
, wxT("attempt to add a NULL WindowRef to window list") );
88 wxWinMacWindowList
[window
] = impl
;
91 // ----------------------------------------------------------------------------
92 // wxNonOwnedWindow creation
93 // ----------------------------------------------------------------------------
95 IMPLEMENT_ABSTRACT_CLASS( wxNonOwnedWindowImpl
, wxObject
)
97 wxNonOwnedWindow
*wxNonOwnedWindow::s_macDeactivateWindow
= NULL
;
99 void wxNonOwnedWindow::Init()
102 m_isNativeWindowWrapper
= false;
105 bool wxNonOwnedWindow::Create(wxWindow
*parent
,
107 const wxPoint
& posOrig
,
108 const wxSize
& sizeOrig
,
110 const wxString
& name
)
112 m_windowStyle
= style
;
116 m_windowId
= id
== -1 ? NewControlId() : id
;
117 m_windowStyle
= style
;
120 // use the appropriate defaults for the position and size if necessary
121 wxSize
size(sizeOrig
);
122 if ( !size
.IsFullySpecified() )
123 size
.SetDefaults(wxTopLevelWindow::GetDefaultSize());
125 wxPoint
pos(posOrig
);
126 if ( !pos
.IsFullySpecified() )
128 wxRect rectWin
= wxRect(size
).CentreIn(wxGetClientDisplayRect());
130 // The size of the window is often not really known yet, TLWs are often
131 // created with some small initial size and later are fitted to contain
132 // their children so centering the window will show it too much to the
133 // right and bottom, adjust for it by putting it more to the left and
138 pos
.SetDefaults(rectWin
.GetPosition());
142 m_nowpeer
= wxNonOwnedWindowImpl::CreateNonOwnedWindow
146 style
, GetExtraStyle(),
149 wxNonOwnedWindowImpl::Associate( m_nowpeer
->GetWXWindow() , m_nowpeer
) ;
150 SetPeer(wxWidgetImpl::CreateContentView(this));
152 DoSetWindowVariant( m_windowVariant
) ;
154 wxWindowCreateEvent
event(this);
155 HandleWindowEvent(event
);
157 SetBackgroundColour(wxSystemSettings::GetColour( wxSYS_COLOUR_3DFACE
));
160 parent
->AddChild(this);
165 bool wxNonOwnedWindow::Create(wxWindow
*parent
, WXWindow nativeWindow
)
168 parent
->AddChild(this);
170 SubclassWin(nativeWindow
);
175 void wxNonOwnedWindow::SubclassWin(WXWindow nativeWindow
)
177 wxASSERT_MSG( !m_isNativeWindowWrapper
, wxT("subclassing window twice?") );
178 wxASSERT_MSG( m_nowpeer
== NULL
, wxT("window already was created") );
180 m_nowpeer
= wxNonOwnedWindowImpl::CreateNonOwnedWindow(this, GetParent(), nativeWindow
);
181 m_isNativeWindowWrapper
= true;
182 wxNonOwnedWindowImpl::Associate( m_nowpeer
->GetWXWindow() , m_nowpeer
) ;
183 SetPeer(wxWidgetImpl::CreateContentView(this));
186 void wxNonOwnedWindow::UnsubclassWin()
188 wxASSERT_MSG( m_isNativeWindowWrapper
, wxT("window was not subclassed") );
191 GetParent()->RemoveChild(this);
193 wxNonOwnedWindowImpl::RemoveAssociations(m_nowpeer
) ;
196 m_isNativeWindowWrapper
= false;
200 wxNonOwnedWindow::~wxNonOwnedWindow()
204 wxNonOwnedWindowImpl::RemoveAssociations(m_nowpeer
) ;
210 // avoid dangling refs
211 if ( s_macDeactivateWindow
== this )
212 s_macDeactivateWindow
= NULL
;
215 bool wxNonOwnedWindow::Destroy()
219 return wxWindow::Destroy();
222 void wxNonOwnedWindow::WillBeDestroyed()
225 m_nowpeer
->WillBeDestroyed();
228 // ----------------------------------------------------------------------------
229 // wxNonOwnedWindow misc
230 // ----------------------------------------------------------------------------
232 bool wxNonOwnedWindow::OSXShowWithEffect(bool show
,
236 // Cocoa code needs to manage window visibility on its own and so calls
237 // wxWindow::Show() as needed but if we already changed the internal
238 // visibility flag here, Show() would do nothing, so avoid doing it
240 if ( !wxWindow::Show(show
) )
244 if ( effect
== wxSHOW_EFFECT_NONE
||
245 !m_nowpeer
|| !m_nowpeer
->ShowWithEffect(show
, effect
, timeout
) )
250 // as apps expect a size event to occur when the window is shown,
251 // generate one when it is shown with effect too
252 wxSizeEvent
event(GetSize(), m_windowId
);
253 event
.SetEventObject(this);
254 HandleWindowEvent(event
);
260 wxPoint
wxNonOwnedWindow::GetClientAreaOrigin() const
262 int left
, top
, width
, height
;
263 m_nowpeer
->GetContentArea(left
, top
, width
, height
);
264 return wxPoint(left
, top
);
267 bool wxNonOwnedWindow::SetBackgroundColour(const wxColour
& c
)
269 if ( !wxWindow::SetBackgroundColour(c
) && m_hasBgCol
)
272 if ( GetBackgroundStyle() != wxBG_STYLE_CUSTOM
)
275 return m_nowpeer
->SetBackgroundColour(c
);
280 void wxNonOwnedWindow::SetWindowStyleFlag(long flags
)
282 if (flags
== GetWindowStyleFlag())
285 wxWindow::SetWindowStyleFlag(flags
);
288 m_nowpeer
->SetWindowStyleFlag(flags
);
291 // Raise the window to the top of the Z order
292 void wxNonOwnedWindow::Raise()
297 // Lower the window to the bottom of the Z order
298 void wxNonOwnedWindow::Lower()
303 void wxNonOwnedWindow::HandleActivated( double timestampsec
, bool didActivate
)
305 MacActivate( (int) (timestampsec
* 1000) , didActivate
);
306 wxActivateEvent
wxevent(wxEVT_ACTIVATE
, didActivate
, GetId());
307 wxevent
.SetTimestamp( (int) (timestampsec
* 1000) );
308 wxevent
.SetEventObject(this);
309 HandleWindowEvent(wxevent
);
312 void wxNonOwnedWindow::HandleResized( double timestampsec
)
314 wxSizeEvent
wxevent( GetSize() , GetId());
315 wxevent
.SetTimestamp( (int) (timestampsec
* 1000) );
316 wxevent
.SetEventObject( this );
317 HandleWindowEvent(wxevent
);
318 // we have to inform some controls that have to reset things
319 // relative to the toplevel window (e.g. OpenGL buffers)
320 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
323 void wxNonOwnedWindow::HandleResizing( double WXUNUSED(timestampsec
), wxRect
* rect
)
327 // this is a EVT_SIZING not a EVT_SIZE type !
328 wxSizeEvent
wxevent( r
, GetId() ) ;
329 wxevent
.SetEventObject( this ) ;
330 if ( HandleWindowEvent(wxevent
) )
331 r
= wxevent
.GetRect() ;
333 if ( GetMaxWidth() != -1 && r
.GetWidth() > GetMaxWidth() )
334 r
.SetWidth( GetMaxWidth() ) ;
335 if ( GetMaxHeight() != -1 && r
.GetHeight() > GetMaxHeight() )
336 r
.SetHeight( GetMaxHeight() ) ;
337 if ( GetMinWidth() != -1 && r
.GetWidth() < GetMinWidth() )
338 r
.SetWidth( GetMinWidth() ) ;
339 if ( GetMinHeight() != -1 && r
.GetHeight() < GetMinHeight() )
340 r
.SetHeight( GetMinHeight() ) ;
343 // TODO actuall this is too early, in case the window extents are adjusted
344 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
347 void wxNonOwnedWindow::HandleMoved( double timestampsec
)
349 wxMoveEvent
wxevent( GetPosition() , GetId());
350 wxevent
.SetTimestamp( (int) (timestampsec
* 1000) );
351 wxevent
.SetEventObject( this );
352 HandleWindowEvent(wxevent
);
355 void wxNonOwnedWindow::MacDelayedDeactivation(long timestamp
)
357 if (s_macDeactivateWindow
)
359 wxLogTrace(TRACE_ACTIVATE
,
360 wxT("Doing delayed deactivation of %p"),
361 s_macDeactivateWindow
);
363 s_macDeactivateWindow
->MacActivate(timestamp
, false);
367 void wxNonOwnedWindow::MacActivate( long timestamp
, bool WXUNUSED(inIsActivating
) )
369 wxLogTrace(TRACE_ACTIVATE
, wxT("TopLevel=%p::MacActivate"), this);
371 if (s_macDeactivateWindow
== this)
372 s_macDeactivateWindow
= NULL
;
374 MacDelayedDeactivation(timestamp
);
377 bool wxNonOwnedWindow::Show(bool show
)
379 if ( !wxWindow::Show(show
) )
383 m_nowpeer
->Show(show
);
387 // because apps expect a size event to occur at this moment
388 wxSizeEvent
event(GetSize() , m_windowId
);
389 event
.SetEventObject(this);
390 HandleWindowEvent(event
);
396 bool wxNonOwnedWindow::SetTransparent(wxByte alpha
)
398 return m_nowpeer
->SetTransparent(alpha
);
402 bool wxNonOwnedWindow::CanSetTransparent()
404 return m_nowpeer
->CanSetTransparent();
408 void wxNonOwnedWindow::SetExtraStyle(long exStyle
)
410 if ( GetExtraStyle() == exStyle
)
413 wxWindow::SetExtraStyle( exStyle
) ;
416 m_nowpeer
->SetExtraStyle(exStyle
);
419 bool wxNonOwnedWindow::SetBackgroundStyle(wxBackgroundStyle style
)
421 if ( !wxWindow::SetBackgroundStyle(style
) )
424 return m_nowpeer
? m_nowpeer
->SetBackgroundStyle(style
) : true;
427 void wxNonOwnedWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
429 if ( m_nowpeer
== NULL
)
432 m_cachedClippedRectValid
= false ;
434 m_nowpeer
->MoveWindow(x
, y
, width
, height
);
435 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
438 void wxNonOwnedWindow::DoGetPosition( int *x
, int *y
) const
440 if ( m_nowpeer
== NULL
)
444 m_nowpeer
->GetPosition(x1
, y1
);
452 void wxNonOwnedWindow::DoGetSize( int *width
, int *height
) const
454 if ( m_nowpeer
== NULL
)
459 m_nowpeer
->GetSize(w
, h
);
467 void wxNonOwnedWindow::DoGetClientSize( int *width
, int *height
) const
469 if ( m_nowpeer
== NULL
)
473 // under iphone with a translucent status bar the m_nowpeer returns the
474 // inner area, while the content area extends under the translucent
475 // status bar, therefore we use the content view's area
476 #ifdef __WXOSX_IPHONE__
477 GetPeer()->GetContentArea(left
, top
, w
, h
);
479 m_nowpeer
->GetContentArea(left
, top
, w
, h
);
488 void wxNonOwnedWindow::WindowWasPainted()
490 s_lastFlush
= clock();
493 void wxNonOwnedWindow::Update()
495 if ( clock() - s_lastFlush
> CLOCKS_PER_SEC
/ 30 )
497 s_lastFlush
= clock();
502 WXWindow
wxNonOwnedWindow::GetWXWindow() const
504 return m_nowpeer
? m_nowpeer
->GetWXWindow() : NULL
;
507 // ---------------------------------------------------------------------------
508 // Shape implementation
509 // ---------------------------------------------------------------------------
511 bool wxNonOwnedWindow::DoClearShape()
515 wxSize sz
= GetClientSize();
516 wxRegion
region(0, 0, sz
.x
, sz
.y
);
518 return m_nowpeer
->SetShape(region
);
521 bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion
& region
)
525 return m_nowpeer
->SetShape(region
);
528 #if wxUSE_GRAPHICS_CONTEXT
530 #include "wx/scopedptr.h"
532 bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath
& path
)
536 // Convert the path to wxRegion by rendering the path on a window-sized
537 // bitmap, creating a mask from it and finally creating the region from
539 wxBitmap
bmp(GetSize());
543 dc
.SetBackground(*wxBLACK
);
546 wxScopedPtr
<wxGraphicsContext
> context(wxGraphicsContext::Create(dc
));
547 context
->SetBrush(*wxWHITE
);
548 context
->FillPath(m_shapePath
);
551 bmp
.SetMask(new wxMask(bmp
, *wxBLACK
));
553 return DoSetRegionShape(wxRegion(bmp
));
556 #endif // wxUSE_GRAPHICS_CONTEXT