1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/osx/window_osx.cpp
3 // Purpose:     wxWindowMac
4 // Author:      Stefan Csomor
5 // Modified by:
6 // Created:     1998-01-01
7 // Copyright:   (c) Stefan Csomor
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 #include "wx/wxprec.h"
12 
13 #include "wx/window.h"
14 
15 #ifndef WX_PRECOMP
16     #include "wx/log.h"
17     #include "wx/app.h"
18     #include "wx/utils.h"
19     #include "wx/panel.h"
20     #include "wx/frame.h"
21     #include "wx/dc.h"
22     #include "wx/dcclient.h"
23     #include "wx/button.h"
24     #include "wx/menu.h"
25     #include "wx/dialog.h"
26     #include "wx/settings.h"
27     #include "wx/msgdlg.h"
28     #include "wx/scrolbar.h"
29     #include "wx/statbox.h"
30     #include "wx/textctrl.h"
31     #include "wx/toolbar.h"
32     #include "wx/layout.h"
33     #include "wx/statusbr.h"
34     #include "wx/menuitem.h"
35     #include "wx/treectrl.h"
36     #include "wx/listctrl.h"
37 #endif
38 
39 #include "wx/tooltip.h"
40 #include "wx/spinctrl.h"
41 #include "wx/geometry.h"
42 #include "wx/weakref.h"
43 
44 #if wxUSE_LISTCTRL
45     #include "wx/listctrl.h"
46 #endif
47 
48 #if wxUSE_TREECTRL
49     #include "wx/treectrl.h"
50 #endif
51 
52 #if wxUSE_CARET
53     #include "wx/caret.h"
54 #endif
55 
56 #if wxUSE_POPUPWIN
57     #include "wx/popupwin.h"
58 #endif
59 
60 #if wxUSE_DRAG_AND_DROP
61     #include "wx/dnd.h"
62 #endif
63 
64 #include "wx/graphics.h"
65 
66 #if wxOSX_USE_CARBON
67     #include "wx/osx/uma.h"
68 #else
69     #include "wx/osx/private.h"
70 #endif
71 
72 #define MAC_SCROLLBAR_SIZE 15
73 #define MAC_SMALL_SCROLLBAR_SIZE 11
74 
75 #include <string.h>
76 
77 #ifdef __WXUNIVERSAL__
78     IMPLEMENT_ABSTRACT_CLASS(wxWindowMac, wxWindowBase)
79 #endif
80 
81 BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase)
82     EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent)
83 END_EVENT_TABLE()
84 
85 #define wxMAC_DEBUG_REDRAW 0
86 #ifndef wxMAC_DEBUG_REDRAW
87 #define wxMAC_DEBUG_REDRAW 0
88 #endif
89 
90 wxWidgetImplType* kOSXNoWidgetImpl = (wxWidgetImplType*) -1L;
91 
92 #if wxUSE_HOTKEY && wxOSX_USE_COCOA_OR_CARBON
93 
94 typedef struct  {
95     EventHotKeyRef ref;
96     int keyId;
97     wxWindow* window;
98 } wxHotKeyRec;
99 
100 wxVector<wxHotKeyRec> s_hotkeys;
101 
102 #endif
103 
104 // ===========================================================================
105 // implementation
106 // ===========================================================================
107 
108 // the grow box has to be implemented as an inactive window, so that nothing can direct
109 // the focus to it
110 
111 class WXDLLIMPEXP_CORE wxBlindPlateWindow : public wxWindow
112 {
113 public:
wxBlindPlateWindow()114     wxBlindPlateWindow() { Init(); }
115 
116     // Old-style constructor (no default values for coordinates to avoid
117     // ambiguity with the new one)
wxBlindPlateWindow(wxWindow * parent,int x,int y,int width,int height,long style=wxTAB_TRAVERSAL|wxNO_BORDER,const wxString & name=wxPanelNameStr)118     wxBlindPlateWindow(wxWindow *parent,
119             int x, int y, int width, int height,
120             long style = wxTAB_TRAVERSAL | wxNO_BORDER,
121             const wxString& name = wxPanelNameStr)
122     {
123         Init();
124 
125         Create(parent, wxID_ANY, wxPoint(x, y), wxSize(width, height), style, name);
126     }
127 
128     // Constructor
wxBlindPlateWindow(wxWindow * parent,wxWindowID winid=wxID_ANY,const wxPoint & pos=wxDefaultPosition,const wxSize & size=wxDefaultSize,long style=wxTAB_TRAVERSAL|wxNO_BORDER,const wxString & name=wxPanelNameStr)129     wxBlindPlateWindow(wxWindow *parent,
130             wxWindowID winid = wxID_ANY,
131             const wxPoint& pos = wxDefaultPosition,
132             const wxSize& size = wxDefaultSize,
133             long style = wxTAB_TRAVERSAL | wxNO_BORDER,
134             const wxString& name = wxPanelNameStr)
135     {
136         Init();
137 
138         Create(parent, winid, pos, size, style, name);
139     }
140 
141     // Pseudo ctor
Create(wxWindow * parent,wxWindowID winid=wxID_ANY,const wxPoint & pos=wxDefaultPosition,const wxSize & size=wxDefaultSize,long style=wxTAB_TRAVERSAL|wxNO_BORDER,const wxString & name=wxPanelNameStr)142     bool Create(wxWindow *parent,
143                 wxWindowID winid = wxID_ANY,
144                 const wxPoint& pos = wxDefaultPosition,
145                 const wxSize& size = wxDefaultSize,
146                 long style = wxTAB_TRAVERSAL | wxNO_BORDER,
147                 const wxString& name = wxPanelNameStr)
148     {
149         if ( !wxWindow::Create(parent, winid, pos, size, style, name) )
150             return false;
151 
152         // so that non-solid background renders correctly under GTK+:
153         SetThemeEnabled(true);
154         return true;
155     }
156 
157     virtual ~wxBlindPlateWindow();
158 
AcceptsFocus() const159     virtual bool AcceptsFocus() const
160     {
161         return false;
162     }
163 
164 protected:
165     // common part of all ctors
Init()166     void Init()
167     {
168     }
169 
170     DECLARE_DYNAMIC_CLASS_NO_COPY(wxBlindPlateWindow)
171     DECLARE_EVENT_TABLE()
172 };
173 
~wxBlindPlateWindow()174 wxBlindPlateWindow::~wxBlindPlateWindow()
175 {
176 }
177 
IMPLEMENT_DYNAMIC_CLASS(wxBlindPlateWindow,wxWindow)178 IMPLEMENT_DYNAMIC_CLASS(wxBlindPlateWindow, wxWindow)
179 
180 BEGIN_EVENT_TABLE(wxBlindPlateWindow, wxWindow)
181 END_EVENT_TABLE()
182 
183 
184 // ----------------------------------------------------------------------------
185  // constructors and such
186 // ----------------------------------------------------------------------------
187 
188 wxWindowMac::wxWindowMac()
189 {
190     Init();
191 }
192 
wxWindowMac(wxWindowMac * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)193 wxWindowMac::wxWindowMac(wxWindowMac *parent,
194             wxWindowID id,
195             const wxPoint& pos ,
196             const wxSize& size ,
197             long style ,
198             const wxString& name )
199 {
200     Init();
201     Create(parent, id, pos, size, style, name);
202 }
203 
Init()204 void wxWindowMac::Init()
205 {
206     m_peer = NULL ;
207     m_macAlpha = 255 ;
208     m_cgContextRef = NULL ;
209 
210     // as all windows are created with WS_VISIBLE style...
211     m_isShown = true;
212 
213     m_hScrollBar = NULL ;
214     m_vScrollBar = NULL ;
215     m_hScrollBarAlwaysShown = false;
216     m_vScrollBarAlwaysShown = false;
217     m_growBox = NULL ;
218 
219     m_clipChildren = false ;
220     m_cachedClippedRectValid = false ;
221     m_isNativeWindowWrapper = false;
222 }
223 
~wxWindowMac()224 wxWindowMac::~wxWindowMac()
225 {
226     SendDestroyEvent();
227 
228 #if wxUSE_HOTKEY && wxOSX_USE_COCOA_OR_CARBON
229     for ( int i = s_hotkeys.size()-1; i>=0; -- i )
230     {
231         if ( s_hotkeys[i].window == this )
232         {
233             EventHotKeyRef ref = s_hotkeys[i].ref;
234             s_hotkeys.erase(s_hotkeys.begin() + i);
235             if ( UnregisterEventHotKey(ref) != noErr )
236             {
237                 wxLogLastError(wxT("UnregisterHotKey"));
238             }
239         }
240     }
241 #endif
242 
243     MacInvalidateBorders() ;
244 
245 #ifndef __WXUNIVERSAL__
246     // VS: make sure there's no wxFrame with last focus set to us:
247     for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
248     {
249         wxFrame *frame = wxDynamicCast(win, wxFrame);
250         if ( frame )
251         {
252             if ( frame->GetLastFocus() == this )
253                 frame->SetLastFocus(NULL);
254             break;
255         }
256     }
257 #endif
258 
259     // destroy children before destroying this window itself
260     DestroyChildren();
261 
262     // wxRemoveMacControlAssociation( this ) ;
263     // If we delete an item, we should initialize the parent panel,
264     // because it could now be invalid.
265     wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent((wxWindow*)this), wxTopLevelWindow);
266     if ( tlw )
267     {
268         if ( tlw->GetDefaultItem() == (wxButton*) this)
269             tlw->SetDefaultItem(NULL);
270     }
271 
272     if ( g_MacLastWindow == this )
273         g_MacLastWindow = NULL ;
274 
275 #ifndef __WXUNIVERSAL__
276     wxFrame* frame = wxDynamicCast( wxGetTopLevelParent( (wxWindow*)this ) , wxFrame ) ;
277     if ( frame )
278     {
279         if ( frame->GetLastFocus() == this )
280             frame->SetLastFocus( NULL ) ;
281     }
282 #endif
283 
284     // delete our drop target if we've got one
285 #if wxUSE_DRAG_AND_DROP
286     wxDELETE(m_dropTarget);
287 #endif
288 
289     delete GetPeer() ;
290 }
291 
GetHandle() const292 WXWidget wxWindowMac::GetHandle() const
293 {
294     if ( GetPeer() )
295         return (WXWidget) GetPeer()->GetWXWidget() ;
296     return NULL;
297 }
298 
GetPeer() const299 wxOSXWidgetImpl* wxWindowMac::GetPeer() const
300 {
301     return m_peer == kOSXNoWidgetImpl ? NULL : m_peer ;
302 }
303 
ShouldCreatePeer() const304 bool wxWindowMac::ShouldCreatePeer() const
305 {
306     return m_peer != kOSXNoWidgetImpl;
307 }
308 
DontCreatePeer()309 void wxWindowMac::DontCreatePeer()
310 {
311     m_peer = kOSXNoWidgetImpl;
312 }
313 
SetWrappingPeer(wxOSXWidgetImpl * wrapper)314 void wxWindowMac::SetWrappingPeer(wxOSXWidgetImpl* wrapper)
315 {
316     wxOSXWidgetImpl* inner = GetPeer();
317     wxASSERT_MSG( inner != NULL && inner->IsOk(), "missing or incomplete inner peer" );
318     wxASSERT_MSG( wrapper != NULL && wrapper->IsOk(), "missing or incomplete wrapper" );
319 
320     if ( !(inner != NULL && inner->IsOk() && wrapper != NULL && wrapper->IsOk()) )
321         return;
322 
323     inner->RemoveFromParent();
324     wrapper->InstallEventHandler();
325     wrapper->Embed(inner);
326     m_peer = wrapper;
327 }
328 
SetPeer(wxOSXWidgetImpl * peer)329 void wxWindowMac::SetPeer(wxOSXWidgetImpl* peer)
330 {
331     if ( GetPeer() )
332     {
333         if ( !GetPeer()->IsRootControl() )
334             GetPeer()->RemoveFromParent();
335         wxDELETE(m_peer);
336     }
337 
338     m_peer = peer;
339 
340     if ( GetPeer() && !GetPeer()->IsRootControl())
341     {
342         wxASSERT_MSG( GetPeer()->IsOk() , wxT("The native control must exist already") ) ;
343 
344         if (!GetParent()->GetChildren().Find((wxWindow*)this))
345             GetParent()->AddChild( this );
346 
347         GetPeer()->InstallEventHandler();
348         GetPeer()->Embed(GetParent()->GetPeer());
349 
350         GetParent()->MacChildAdded() ;
351 
352         // adjust font, controlsize etc
353         GetPeer()->SetControlSize( m_windowVariant );
354         InheritAttributes();
355         // in case nothing has been set, use the variant default fonts
356         if ( !m_hasFont )
357             DoSetWindowVariant( m_windowVariant );
358 
359         GetPeer()->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics), GetFont().GetEncoding() ) ;
360 
361         // for controls we want to use best size for wxDefaultSize params )
362         if ( !GetPeer()->IsUserPane() )
363             SetInitialSize(GetMinSize());
364 
365         SetCursor( *wxSTANDARD_CURSOR ) ;
366     }
367 }
368 
369 #if WXWIN_COMPATIBILITY_2_8
370 
MacIsUserPane()371 bool wxWindowMac::MacIsUserPane()
372 {
373     return GetPeer() == NULL || GetPeer()->IsUserPane();
374 }
375 
376 #endif
377 
MacIsUserPane() const378 bool wxWindowMac::MacIsUserPane() const
379 {
380     return GetPeer() == NULL || GetPeer()->IsUserPane();
381 }
382 
383 // ---------------------------------------------------------------------------
384 // Utility Routines to move between different coordinate systems
385 // ---------------------------------------------------------------------------
386 
387 /*
388  * Right now we have the following setup :
389  * a border that is not part of the native control is always outside the
390  * control's border (otherwise we lose all native intelligence, future ways
391  * may be to have a second embedding control responsible for drawing borders
392  * and backgrounds eventually)
393  * so all this border calculations have to be taken into account when calling
394  * native methods or getting native oriented data
395  * so we have three coordinate systems here
396  * wx client coordinates
397  * wx window coordinates (including window frames)
398  * native coordinates
399  */
400 
401 //
402 //
403 
404 // Constructor
Create(wxWindowMac * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)405 bool wxWindowMac::Create(wxWindowMac *parent,
406     wxWindowID id,
407     const wxPoint& pos,
408     const wxSize& size,
409     long style,
410     const wxString& name)
411 {
412     wxCHECK_MSG( parent, false, wxT("can't create wxWindowMac without parent") );
413 
414     if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
415         return false;
416 
417     m_windowVariant = parent->GetWindowVariant() ;
418 
419     m_hScrollBarAlwaysShown =
420     m_vScrollBarAlwaysShown = HasFlag(wxALWAYS_SHOW_SB);
421 
422     if ( m_peer != kOSXNoWidgetImpl )
423     {
424         SetPeer(wxWidgetImpl::CreateUserPane( this, parent, id, pos, size , style, GetExtraStyle() ));
425         MacPostControlCreate(pos, size) ;
426     }
427 
428 #ifndef __WXUNIVERSAL__
429     // Don't give scrollbars to wxControls unless they ask for them
430     if ( (! IsKindOf(CLASSINFO(wxControl))
431 #if wxUSE_STATUSBAR
432         && ! IsKindOf(CLASSINFO(wxStatusBar))
433 #endif
434         )
435          || (IsKindOf(CLASSINFO(wxControl)) && ((style & wxHSCROLL) || (style & wxVSCROLL))))
436     {
437         MacCreateScrollBars( style ) ;
438     }
439 #endif
440 
441     wxWindowCreateEvent event((wxWindow*)this);
442     GetEventHandler()->AddPendingEvent(event);
443 
444     return true;
445 }
446 
MacChildAdded()447 void wxWindowMac::MacChildAdded()
448 {
449 #if wxUSE_SCROLLBAR
450     if ( m_vScrollBar )
451         m_vScrollBar->Raise() ;
452     if ( m_hScrollBar )
453         m_hScrollBar->Raise() ;
454     if ( m_growBox )
455         m_growBox->Raise() ;
456 #endif
457 }
458 
MacPostControlCreate(const wxPoint & pos,const wxSize & WXUNUSED (size))459 void wxWindowMac::MacPostControlCreate(const wxPoint& pos,
460                                        const wxSize& WXUNUSED(size))
461 {
462     // Some controls may have a nonzero layout inset,
463     // so we may need to adjust control position.
464     if ( pos.IsFullySpecified() && GetPosition() != pos )
465     {
466         SetPosition(pos);
467     }
468 
469     // todo remove if refactoring works correctly
470 #if 0
471     wxASSERT_MSG( GetPeer() != NULL && GetPeer()->IsOk() , wxT("No valid mac control") ) ;
472 
473     if (!GetParent()->GetChildren().Find((wxWindow*)this))
474         GetParent()->AddChild( this );
475 
476     GetPeer()->InstallEventHandler();
477     GetPeer()->Embed(GetParent()->GetPeer());
478 
479     GetParent()->MacChildAdded() ;
480 
481     // adjust font, controlsize etc
482     DoSetWindowVariant( m_windowVariant ) ;
483 
484     GetPeer()->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics), GetFont().GetEncoding() ) ;
485 
486     // for controls we want to use best size for wxDefaultSize params )
487     if ( !GetPeer()->IsUserPane() )
488         SetInitialSize(size);
489 
490     SetCursor( *wxSTANDARD_CURSOR ) ;
491 #endif
492 }
493 
DoSetWindowVariant(wxWindowVariant variant)494 void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
495 {
496     // Don't assert, in case we set the window variant before
497     // the window is created
498     // wxASSERT( GetPeer()->IsOk() ) ;
499 
500     m_windowVariant = variant ;
501 
502     if (GetPeer() == NULL || !GetPeer()->IsOk())
503         return;
504 
505     GetPeer()->SetControlSize( variant );
506 
507     switch ( variant )
508     {
509         case wxWINDOW_VARIANT_NORMAL :
510             static wxFont sysNormal(wxOSX_SYSTEM_FONT_NORMAL);
511             SetFont(sysNormal) ;
512             break ;
513 
514         case wxWINDOW_VARIANT_SMALL :
515             static wxFont sysSmall(wxOSX_SYSTEM_FONT_SMALL);
516             SetFont(sysSmall) ;
517             break ;
518 
519         case wxWINDOW_VARIANT_MINI :
520             static wxFont sysMini(wxOSX_SYSTEM_FONT_MINI);
521             SetFont(sysMini) ;
522             break ;
523 
524         case wxWINDOW_VARIANT_LARGE :
525             static wxFont sysLarge(wxOSX_SYSTEM_FONT_NORMAL);
526             SetFont(sysLarge) ;
527             break ;
528 
529         default:
530             wxFAIL_MSG(wxT("unexpected window variant"));
531             break ;
532     }
533 }
534 
MacUpdateControlFont()535 void wxWindowMac::MacUpdateControlFont()
536 {
537     if ( GetPeer() )
538         GetPeer()->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
539 
540     // do not trigger refreshes upon invisible and possible partly created objects
541     if ( IsShownOnScreen() )
542         Refresh() ;
543 }
544 
SetFont(const wxFont & font)545 bool wxWindowMac::SetFont(const wxFont& font)
546 {
547     bool retval = wxWindowBase::SetFont( font );
548 
549     MacUpdateControlFont() ;
550 
551     return retval;
552 }
553 
SetForegroundColour(const wxColour & col)554 bool wxWindowMac::SetForegroundColour(const wxColour& col )
555 {
556     bool retval = wxWindowBase::SetForegroundColour( col );
557 
558     if (retval)
559         MacUpdateControlFont();
560 
561     return retval;
562 }
563 
SetBackgroundStyle(wxBackgroundStyle style)564 bool wxWindowMac::SetBackgroundStyle(wxBackgroundStyle style)
565 {
566     if ( !wxWindowBase::SetBackgroundStyle(style) )
567         return false;
568 
569     if ( GetPeer() )
570         GetPeer()->SetBackgroundStyle(style);
571     return true;
572 }
573 
SetBackgroundColour(const wxColour & col)574 bool wxWindowMac::SetBackgroundColour(const wxColour& col )
575 {
576     if (m_growBox)
577     {
578         if ( m_backgroundColour.IsOk() )
579             m_growBox->SetBackgroundColour(m_backgroundColour);
580         else
581             m_growBox->SetBackgroundColour(*wxWHITE);
582     }
583 
584     if ( !wxWindowBase::SetBackgroundColour(col) && m_hasBgCol )
585         return false ;
586 
587     if ( GetPeer() )
588         GetPeer()->SetBackgroundColour( col ) ;
589 
590     return true ;
591 }
592 
wxIsWindowOrParentDisabled(wxWindow * w)593 static bool wxIsWindowOrParentDisabled(wxWindow* w)
594 {
595     while (w && !w->IsTopLevel())
596     {
597         if (!w->IsEnabled())
598             return true;
599         w = w->GetParent();
600     }
601     return false;
602 }
603 
SetFocus()604 void wxWindowMac::SetFocus()
605 {
606     if ( !AcceptsFocus() )
607             return ;
608 
609     if (wxIsWindowOrParentDisabled((wxWindow*) this))
610         return;
611 
612     wxWindow* former = FindFocus() ;
613     if ( former == this )
614         return ;
615 
616     GetPeer()->SetFocus() ;
617 }
618 
OSXSimulateFocusEvents()619 void wxWindowMac::OSXSimulateFocusEvents()
620 {
621     wxWeakRef<wxWindow> former = FindFocus() ;
622     if ( former != NULL && former != this )
623     {
624         {
625             wxFocusEvent event( wxEVT_KILL_FOCUS, former->GetId());
626             event.SetEventObject(former);
627             event.SetWindow(this);
628             former->HandleWindowEvent(event) ;
629         }
630 
631         // 'former' could have been destroyed by a wxEVT_KILL_FOCUS handler,
632         // so we must test it for non-NULL again
633         if ( former )
634         {
635             wxFocusEvent event(wxEVT_SET_FOCUS, former->GetId());
636             event.SetEventObject(former);
637             event.SetWindow(this);
638             former->HandleWindowEvent(event);
639         }
640     }
641 }
642 
DoCaptureMouse()643 void wxWindowMac::DoCaptureMouse()
644 {
645     wxApp::s_captureWindow = (wxWindow*) this ;
646     GetPeer()->CaptureMouse() ;
647 }
648 
GetCapture()649 wxWindow * wxWindowBase::GetCapture()
650 {
651     return wxApp::s_captureWindow ;
652 }
653 
DoReleaseMouse()654 void wxWindowMac::DoReleaseMouse()
655 {
656     wxApp::s_captureWindow = NULL ;
657 
658     GetPeer()->ReleaseMouse() ;
659 }
660 
661 #if wxUSE_DRAG_AND_DROP
662 
SetDropTarget(wxDropTarget * pDropTarget)663 void wxWindowMac::SetDropTarget(wxDropTarget *pDropTarget)
664 {
665     delete m_dropTarget;
666 
667     m_dropTarget = pDropTarget;
668 
669     GetPeer()->SetDropTarget(m_dropTarget) ;
670 }
671 
672 #endif
673 
674 // Old-style File Manager Drag & Drop
DragAcceptFiles(bool WXUNUSED (accept))675 void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept))
676 {
677     // TODO:
678 }
679 
680 // From a wx position / size calculate the appropriate size of the native control
681 
MacGetBoundsForControl(const wxPoint & pos,const wxSize & size,int & x,int & y,int & w,int & h,bool adjustOrigin) const682 bool wxWindowMac::MacGetBoundsForControl(
683     const wxPoint& pos,
684     const wxSize& size,
685     int& x, int& y,
686     int& w, int& h , bool adjustOrigin ) const
687 {
688     // the desired size, minus the border pixels gives the correct size of the control
689     x = (int)pos.x;
690     y = (int)pos.y;
691 
692     w = WidthDefault( size.x );
693     h = HeightDefault( size.y );
694 
695     x += MacGetLeftBorderSize() ;
696     y += MacGetTopBorderSize() ;
697     w -= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
698     h -= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
699 
700     if ( adjustOrigin )
701         AdjustForParentClientOrigin( x , y ) ;
702 
703     // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
704     if ( GetParent() && !GetParent()->IsTopLevel() )
705     {
706         x -= GetParent()->MacGetLeftBorderSize() ;
707         y -= GetParent()->MacGetTopBorderSize() ;
708     }
709 
710     return true ;
711 }
712 
713 // Get window size (not client size)
DoGetSize(int * x,int * y) const714 void wxWindowMac::DoGetSize(int *x, int *y) const
715 {
716     int width, height;
717     GetPeer()->GetSize( width, height );
718 
719     if (x)
720        *x = width + MacGetLeftBorderSize() + MacGetRightBorderSize() ;
721     if (y)
722        *y = height + MacGetTopBorderSize() + MacGetBottomBorderSize() ;
723 }
724 
725 // get the position of the bounds of this window in client coordinates of its parent
DoGetPosition(int * x,int * y) const726 void wxWindowMac::DoGetPosition(int *x, int *y) const
727 {
728     int x1, y1;
729 
730     GetPeer()->GetPosition( x1, y1 ) ;
731 
732     // get the wx window position from the native one
733     x1 -= MacGetLeftBorderSize() ;
734     y1 -= MacGetTopBorderSize() ;
735 
736     if ( !IsTopLevel() )
737     {
738         wxWindow *parent = GetParent();
739         if ( parent )
740         {
741             // we must first adjust it to be in window coordinates of the parent,
742             // as otherwise it gets lost by the ClientAreaOrigin fix
743             x1 += parent->MacGetLeftBorderSize() ;
744             y1 += parent->MacGetTopBorderSize() ;
745 
746             // and now to client coordinates
747             wxPoint pt(parent->GetClientAreaOrigin());
748             x1 -= pt.x ;
749             y1 -= pt.y ;
750         }
751     }
752 
753     if (x)
754        *x = x1 ;
755     if (y)
756        *y = y1 ;
757 }
758 
DoScreenToClient(int * x,int * y) const759 void wxWindowMac::DoScreenToClient(int *x, int *y) const
760 {
761     wxNonOwnedWindow* tlw = MacGetTopLevelWindow() ;
762     wxCHECK_RET( tlw , wxT("TopLevel Window missing") ) ;
763     tlw->GetNonOwnedPeer()->ScreenToWindow( x, y);
764     MacRootWindowToWindow( x , y ) ;
765 
766     wxPoint origin = GetClientAreaOrigin() ;
767     if (x)
768        *x -= origin.x ;
769     if (y)
770        *y -= origin.y ;
771 }
772 
DoClientToScreen(int * x,int * y) const773 void wxWindowMac::DoClientToScreen(int *x, int *y) const
774 {
775     wxNonOwnedWindow* tlw = MacGetTopLevelWindow() ;
776     wxCHECK_RET( tlw , wxT("TopLevel window missing") ) ;
777 
778     wxPoint origin = GetClientAreaOrigin() ;
779     if (x)
780        *x += origin.x ;
781     if (y)
782        *y += origin.y ;
783 
784     MacWindowToRootWindow( x , y ) ;
785     tlw->GetNonOwnedPeer()->WindowToScreen( x , y );
786 }
787 
MacClientToRootWindow(int * x,int * y) const788 void wxWindowMac::MacClientToRootWindow( int *x , int *y ) const
789 {
790     wxPoint origin = GetClientAreaOrigin() ;
791     if (x)
792        *x += origin.x ;
793     if (y)
794        *y += origin.y ;
795 
796     MacWindowToRootWindow( x , y ) ;
797 }
798 
MacWindowToRootWindow(int * x,int * y) const799 void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const
800 {
801     wxPoint pt ;
802 
803     if (x)
804         pt.x = *x ;
805     if (y)
806         pt.y = *y ;
807 
808     if ( !IsTopLevel() )
809     {
810         wxNonOwnedWindow* top = MacGetTopLevelWindow();
811         if (top)
812         {
813             pt.x -= MacGetLeftBorderSize() ;
814             pt.y -= MacGetTopBorderSize() ;
815             wxWidgetImpl::Convert( &pt , GetPeer() , top->GetPeer() ) ;
816         }
817     }
818 
819     if (x)
820         *x = (int) pt.x ;
821     if (y)
822         *y = (int) pt.y ;
823 }
824 
MacRootWindowToWindow(int * x,int * y) const825 void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const
826 {
827     wxPoint pt ;
828 
829     if (x)
830         pt.x = *x ;
831     if (y)
832         pt.y = *y ;
833 
834     if ( !IsTopLevel() )
835     {
836         wxNonOwnedWindow* top = MacGetTopLevelWindow();
837         if (top)
838         {
839             wxWidgetImpl::Convert( &pt , top->GetPeer() , GetPeer() ) ;
840             pt.x += MacGetLeftBorderSize() ;
841             pt.y += MacGetTopBorderSize() ;
842         }
843     }
844 
845     if (x)
846         *x = (int) pt.x ;
847     if (y)
848         *y = (int) pt.y ;
849 }
850 
DoGetSizeFromClientSize(const wxSize & size) const851 wxSize wxWindowMac::DoGetSizeFromClientSize( const wxSize & size )  const
852 {
853     wxSize sizeTotal = size;
854 
855     int innerwidth, innerheight;
856     int left, top;
857     int outerwidth, outerheight;
858 
859     GetPeer()->GetContentArea( left, top, innerwidth, innerheight );
860     GetPeer()->GetSize( outerwidth, outerheight );
861 
862     sizeTotal.x += outerwidth-innerwidth;
863     sizeTotal.y += outerheight-innerheight;
864 
865     sizeTotal.x += MacGetLeftBorderSize() + MacGetRightBorderSize() ;
866     sizeTotal.y += MacGetTopBorderSize() + MacGetBottomBorderSize() ;
867 
868     return sizeTotal;
869 }
870 
871 // Get size *available for subwindows* i.e. excluding menu bar etc.
DoGetClientSize(int * x,int * y) const872 void wxWindowMac::DoGetClientSize( int *x, int *y ) const
873 {
874     int ww, hh;
875 
876     int left, top;
877 
878     GetPeer()->GetContentArea( left, top, ww, hh );
879 #if wxUSE_SCROLLBAR
880     if (m_hScrollBar  && m_hScrollBar->IsShown() )
881         hh -= m_hScrollBar->GetSize().y ;
882 
883     if (m_vScrollBar  && m_vScrollBar->IsShown() )
884         ww -= m_vScrollBar->GetSize().x ;
885 
886 #endif
887     if (x)
888     {
889         // we shouldn't return invalid width
890         if ( ww < 0 )
891             ww = 0;
892 
893         *x = ww;
894     }
895 
896     if (y)
897     {
898         // we shouldn't return invalid height
899         if ( hh < 0 )
900             hh = 0;
901 
902         *y = hh;
903     }
904 }
905 
SetCursor(const wxCursor & cursor)906 bool wxWindowMac::SetCursor(const wxCursor& cursor)
907 {
908     if (m_cursor.IsSameAs(cursor))
909         return false;
910 
911     if (!cursor.IsOk())
912     {
913         if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR ) )
914             return false ;
915     }
916     else
917     {
918         if ( ! wxWindowBase::SetCursor( cursor ) )
919             return false ;
920     }
921 
922     wxASSERT_MSG( m_cursor.IsOk(),
923         wxT("cursor must be valid after call to the base version"));
924 
925     if ( GetPeer() != NULL )
926         GetPeer()->SetCursor( m_cursor );
927 
928     return true ;
929 }
930 
931 #if wxUSE_MENUS
DoPopupMenu(wxMenu * menu,int x,int y)932 bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y)
933 {
934 #ifndef __WXUNIVERSAL__
935     menu->UpdateUI();
936 
937     if ( x == wxDefaultCoord && y == wxDefaultCoord )
938     {
939         wxPoint mouse = wxGetMousePosition();
940         x = mouse.x;
941         y = mouse.y;
942     }
943     else
944     {
945         ClientToScreen( &x , &y ) ;
946     }
947     menu->GetPeer()->PopUp(this, x, y);
948     return true;
949 #else
950     // actually this shouldn't be called, because universal is having its own implementation
951     return false;
952 #endif
953 }
954 #endif
955 
956 // ----------------------------------------------------------------------------
957 // tooltips
958 // ----------------------------------------------------------------------------
959 
960 #if wxUSE_TOOLTIPS
961 
DoSetToolTip(wxToolTip * tooltip)962 void wxWindowMac::DoSetToolTip(wxToolTip *tooltip)
963 {
964     wxWindowBase::DoSetToolTip(tooltip);
965 
966     if ( m_tooltip )
967         m_tooltip->SetWindow(this);
968 
969     if (GetPeer())
970         GetPeer()->SetToolTip(tooltip);
971 }
972 
973 #endif
974 
MacInvalidateBorders()975 void wxWindowMac::MacInvalidateBorders()
976 {
977     if ( GetPeer() == NULL )
978         return ;
979 
980     bool vis = IsShownOnScreen() ;
981     if ( !vis )
982         return ;
983 
984     int outerBorder = MacGetLeftBorderSize() ;
985 
986     if ( GetPeer()->NeedsFocusRect() )
987         outerBorder += 4 ;
988 
989     if ( outerBorder == 0 )
990         return ;
991 
992     // now we know that we have something to do at all
993 
994     int tx,ty,tw,th;
995 
996     GetPeer()->GetSize( tw, th );
997     GetPeer()->GetPosition( tx, ty );
998 
999     wxRect leftupdate( tx-outerBorder,ty,outerBorder,th );
1000     wxRect rightupdate( tx+tw, ty, outerBorder, th );
1001     wxRect topupdate( tx-outerBorder, ty-outerBorder, tw + 2 * outerBorder, outerBorder );
1002     wxRect bottomupdate( tx-outerBorder, ty + th, tw + 2 * outerBorder, outerBorder );
1003 
1004     if (GetParent()) {
1005         GetParent()->GetPeer()->SetNeedsDisplay(&leftupdate);
1006         GetParent()->GetPeer()->SetNeedsDisplay(&rightupdate);
1007         GetParent()->GetPeer()->SetNeedsDisplay(&topupdate);
1008         GetParent()->GetPeer()->SetNeedsDisplay(&bottomupdate);
1009     }
1010 }
1011 
DoMoveWindow(int x,int y,int width,int height)1012 void wxWindowMac::DoMoveWindow(int x, int y, int width, int height)
1013 {
1014     // this is never called for a toplevel window, so we know we have a parent
1015     int former_x , former_y , former_w, former_h ;
1016 
1017     // Get true coordinates of former position
1018     DoGetPosition( &former_x , &former_y ) ;
1019     DoGetSize( &former_w , &former_h ) ;
1020 
1021     wxWindow *parent = GetParent();
1022     if ( parent )
1023     {
1024         wxPoint pt(parent->GetClientAreaOrigin());
1025         former_x += pt.x ;
1026         former_y += pt.y ;
1027     }
1028 
1029     int actualWidth = width ;
1030     int actualHeight = height ;
1031     int actualX = x;
1032     int actualY = y;
1033 
1034 #if 0
1035     // min and max sizes are only for sizers, not for explicit size setting
1036     if ((m_minWidth != -1) && (actualWidth < m_minWidth))
1037         actualWidth = m_minWidth;
1038     if ((m_minHeight != -1) && (actualHeight < m_minHeight))
1039         actualHeight = m_minHeight;
1040     if ((m_maxWidth != -1) && (actualWidth > m_maxWidth))
1041         actualWidth = m_maxWidth;
1042     if ((m_maxHeight != -1) && (actualHeight > m_maxHeight))
1043         actualHeight = m_maxHeight;
1044 #endif
1045 
1046     bool doMove = false, doResize = false ;
1047 
1048     if ( actualX != former_x || actualY != former_y )
1049         doMove = true ;
1050 
1051     if ( actualWidth != former_w || actualHeight != former_h )
1052         doResize = true ;
1053 
1054     if ( doMove || doResize )
1055     {
1056         // as the borders are drawn outside the native control, we adjust now
1057 
1058         wxRect bounds( wxPoint( actualX + MacGetLeftBorderSize() ,actualY + MacGetTopBorderSize() ),
1059             wxSize( actualWidth - (MacGetLeftBorderSize() + MacGetRightBorderSize()) ,
1060                 actualHeight - (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ;
1061 
1062         if ( parent && !parent->IsTopLevel() )
1063         {
1064             bounds.Offset( -parent->MacGetLeftBorderSize(), -parent->MacGetTopBorderSize() );
1065         }
1066 
1067         MacInvalidateBorders() ;
1068 
1069         m_cachedClippedRectValid = false ;
1070 
1071         GetPeer()->Move( bounds.x, bounds.y, bounds.width, bounds.height);
1072 
1073         wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
1074 
1075         MacInvalidateBorders() ;
1076 
1077         MacRepositionScrollBars() ;
1078         if ( doMove )
1079         {
1080             wxPoint point(actualX, actualY);
1081             wxMoveEvent event(point, m_windowId);
1082             event.SetEventObject(this);
1083             HandleWindowEvent(event) ;
1084         }
1085 
1086         if ( doResize )
1087         {
1088             MacRepositionScrollBars() ;
1089             SendSizeEvent();
1090         }
1091     }
1092 }
1093 
DoGetBestSize() const1094 wxSize wxWindowMac::DoGetBestSize() const
1095 {
1096     if ( GetPeer() == NULL || GetPeer()->IsUserPane() || IsTopLevel() )
1097     {
1098         return wxWindowBase::DoGetBestSize() ;
1099     }
1100     else
1101     {
1102         wxRect r ;
1103 
1104         GetPeer()->GetBestRect(&r);
1105 
1106         if ( r.GetWidth() == 0 && r.GetHeight() == 0 )
1107         {
1108             r.x =
1109             r.y = 0 ;
1110             r.width =
1111             r.height = 16 ;
1112 
1113 #if wxUSE_SCROLLBAR
1114             if ( IsKindOf( CLASSINFO( wxScrollBar ) ) )
1115             {
1116                 r.height = 16 ;
1117             }
1118             else
1119 #endif
1120 #if wxUSE_SPINBTN
1121             if ( IsKindOf( CLASSINFO( wxSpinButton ) ) )
1122             {
1123                 r.height = 24 ;
1124             }
1125             else
1126 #endif
1127             {
1128                 // return wxWindowBase::DoGetBestSize() ;
1129             }
1130         }
1131 
1132         int bestWidth = r.width + MacGetLeftBorderSize() +
1133                     MacGetRightBorderSize();
1134         int bestHeight = r.height + MacGetTopBorderSize() +
1135                      MacGetBottomBorderSize();
1136         if ( bestHeight < 10 )
1137             bestHeight = 13 ;
1138 
1139         return wxSize(bestWidth, bestHeight);
1140     }
1141 }
1142 
SendSizeEvent(int flags)1143 void wxWindowMac::SendSizeEvent(int flags)
1144 {
1145     MacOnInternalSize();
1146     wxWindowBase::SendSizeEvent(flags);
1147 }
1148 
1149 // set the size of the window: if the dimensions are positive, just use them,
1150 // but if any of them is equal to -1, it means that we must find the value for
1151 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1152 // which case -1 is a valid value for x and y)
1153 //
1154 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1155 // the width/height to best suit our contents, otherwise we reuse the current
1156 // width/height
DoSetSize(int x,int y,int width,int height,int sizeFlags)1157 void wxWindowMac::DoSetSize(int x, int y, int width, int height, int sizeFlags)
1158 {
1159     // get the current size and position...
1160     int currentX, currentY;
1161     int currentW, currentH;
1162 
1163     GetPosition(&currentX, &currentY);
1164     GetSize(&currentW, &currentH);
1165 
1166     // ... and don't do anything (avoiding flicker) if it's already ok
1167     if ( x == currentX && y == currentY &&
1168         width == currentW && height == currentH && ( height != -1 && width != -1 ) )
1169     {
1170         // TODO: REMOVE
1171         MacRepositionScrollBars() ; // we might have a real position shift
1172 
1173         if (sizeFlags & wxSIZE_FORCE_EVENT)
1174         {
1175             SendSizeEvent();
1176         }
1177 
1178         return;
1179     }
1180 
1181     if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
1182     {
1183         if ( x == wxDefaultCoord )
1184             x = currentX;
1185         if ( y == wxDefaultCoord )
1186             y = currentY;
1187     }
1188 
1189     AdjustForParentClientOrigin( x, y, sizeFlags );
1190 
1191     wxSize size = wxDefaultSize;
1192     if ( width == wxDefaultCoord )
1193     {
1194         if ( sizeFlags & wxSIZE_AUTO_WIDTH )
1195         {
1196             size = DoGetBestSize();
1197             width = size.x;
1198         }
1199         else
1200         {
1201             // just take the current one
1202             width = currentW;
1203         }
1204     }
1205 
1206     if ( height == wxDefaultCoord )
1207     {
1208         if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
1209         {
1210             if ( size.x == wxDefaultCoord )
1211                 size = DoGetBestSize();
1212             // else: already called DoGetBestSize() above
1213 
1214             height = size.y;
1215         }
1216         else
1217         {
1218             // just take the current one
1219             height = currentH;
1220         }
1221     }
1222 
1223     DoMoveWindow( x, y, width, height );
1224 }
1225 
GetClientAreaOrigin() const1226 wxPoint wxWindowMac::GetClientAreaOrigin() const
1227 {
1228     int left,top,width,height;
1229     GetPeer()->GetContentArea( left , top , width , height);
1230     return wxPoint( left + MacGetLeftBorderSize() , top + MacGetTopBorderSize() );
1231 }
1232 
DoSetClientSize(int clientwidth,int clientheight)1233 void wxWindowMac::DoSetClientSize(int clientwidth, int clientheight)
1234 {
1235     if ( clientwidth != wxDefaultCoord || clientheight != wxDefaultCoord )
1236     {
1237         int currentclientwidth , currentclientheight ;
1238         int currentwidth , currentheight ;
1239 
1240         GetClientSize( &currentclientwidth , &currentclientheight ) ;
1241         GetSize( &currentwidth , &currentheight ) ;
1242 
1243         DoSetSize( wxDefaultCoord , wxDefaultCoord , currentwidth + clientwidth - currentclientwidth ,
1244             currentheight + clientheight - currentclientheight , wxSIZE_USE_EXISTING ) ;
1245     }
1246 }
1247 
GetContentScaleFactor() const1248 double wxWindowMac::GetContentScaleFactor() const
1249 {
1250     return GetPeer()->GetContentScaleFactor();
1251 }
1252 
SetLabel(const wxString & title)1253 void wxWindowMac::SetLabel(const wxString& title)
1254 {
1255     if ( title == m_label )
1256         return;
1257 
1258     m_label = title ;
1259 
1260     InvalidateBestSize();
1261 
1262     if ( GetPeer() && GetPeer()->IsOk() )
1263         GetPeer()->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics), GetFont().GetEncoding() ) ;
1264 
1265     // do not trigger refreshes upon invisible and possible partly created objects
1266     if ( IsShownOnScreen() )
1267         Refresh() ;
1268 }
1269 
GetLabel() const1270 wxString wxWindowMac::GetLabel() const
1271 {
1272     return m_label ;
1273 }
1274 
Show(bool show)1275 bool wxWindowMac::Show(bool show)
1276 {
1277     if ( !show )
1278         MacInvalidateBorders();
1279 
1280     if ( !wxWindowBase::Show(show) )
1281         return false;
1282 
1283     if ( GetPeer() )
1284         GetPeer()->SetVisibility( show ) ;
1285 
1286     if ( show )
1287         MacInvalidateBorders();
1288 
1289 #ifdef __WXOSX_IPHONE__
1290     // only when there's no native event support
1291     if ( !IsTopLevel() )
1292 #endif
1293     {
1294         wxShowEvent eventShow(GetId(), show);
1295         eventShow.SetEventObject(this);
1296 
1297         HandleWindowEvent(eventShow);
1298     }
1299 
1300     return true;
1301 }
1302 
OSXShowWithEffect(bool show,wxShowEffect effect,unsigned timeout)1303 bool wxWindowMac::OSXShowWithEffect(bool show,
1304                                     wxShowEffect effect,
1305                                     unsigned timeout)
1306 {
1307     if ( effect == wxSHOW_EFFECT_NONE ||
1308             !GetPeer() || !GetPeer()->ShowWithEffect(show, effect, timeout) )
1309         return Show(show);
1310 
1311     return true;
1312 }
1313 
DoEnable(bool enable)1314 void wxWindowMac::DoEnable(bool enable)
1315 {
1316     GetPeer()->Enable( enable ) ;
1317     MacInvalidateBorders();
1318 }
1319 
1320 //
1321 // status change notifications
1322 //
1323 
MacVisibilityChanged()1324 void wxWindowMac::MacVisibilityChanged()
1325 {
1326 }
1327 
MacHiliteChanged()1328 void wxWindowMac::MacHiliteChanged()
1329 {
1330 }
1331 
MacEnabledStateChanged()1332 void wxWindowMac::MacEnabledStateChanged()
1333 {
1334 }
1335 
1336 //
1337 // status queries on the inherited window's state
1338 //
1339 
MacIsReallyEnabled()1340 bool wxWindowMac::MacIsReallyEnabled()
1341 {
1342     return GetPeer()->IsEnabled() ;
1343 }
1344 
MacIsReallyHilited()1345 bool wxWindowMac::MacIsReallyHilited()
1346 {
1347 #if wxOSX_USE_CARBON
1348     return GetPeer()->IsActive();
1349 #else
1350     return true; // TODO
1351 #endif
1352 }
1353 
GetCharHeight() const1354 int wxWindowMac::GetCharHeight() const
1355 {
1356     wxCoord height;
1357     GetTextExtent( wxT("g") , NULL , &height , NULL , NULL , NULL );
1358 
1359     return height;
1360 }
1361 
GetCharWidth() const1362 int wxWindowMac::GetCharWidth() const
1363 {
1364     wxCoord width;
1365     GetTextExtent( wxT("g") , &width , NULL , NULL , NULL , NULL );
1366 
1367     return width;
1368 }
1369 
DoGetTextExtent(const wxString & str,int * x,int * y,int * descent,int * externalLeading,const wxFont * theFont) const1370 void wxWindowMac::DoGetTextExtent(const wxString& str,
1371                                   int *x, int *y,
1372                                   int *descent,
1373                                   int *externalLeading,
1374                                   const wxFont *theFont) const
1375 {
1376     const wxFont *fontToUse = theFont;
1377     wxFont tempFont;
1378     if ( !fontToUse )
1379     {
1380         tempFont = GetFont();
1381         fontToUse = &tempFont;
1382     }
1383 
1384     wxGraphicsContext* ctx = wxGraphicsContext::Create();
1385     ctx->SetFont( *fontToUse, *wxBLACK );
1386 
1387     wxDouble h , d , e , w;
1388     ctx->GetTextExtent( str, &w, &h, &d, &e );
1389 
1390     delete ctx;
1391 
1392     if ( externalLeading )
1393         *externalLeading = (wxCoord)(e+0.5);
1394     if ( descent )
1395         *descent = (wxCoord)(d+0.5);
1396     if ( x )
1397         *x = (wxCoord)(w+0.5);
1398     if ( y )
1399         *y = (wxCoord)(h+0.5);
1400 }
1401 
1402 /*
1403  * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
1404  * we always intersect with the entire window, not only with the client area
1405  */
1406 
Refresh(bool WXUNUSED (eraseBack),const wxRect * rect)1407 void wxWindowMac::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect)
1408 {
1409     if ( GetPeer() == NULL )
1410         return ;
1411 
1412     if ( !IsShownOnScreen() )
1413         return ;
1414 
1415     if ( IsFrozen() )
1416         return;
1417 
1418     GetPeer()->SetNeedsDisplay( rect ) ;
1419 }
1420 
DoFreeze()1421 void wxWindowMac::DoFreeze()
1422 {
1423     if ( GetPeer() && GetPeer()->IsOk() )
1424         GetPeer()->SetDrawingEnabled( false ) ;
1425 }
1426 
DoThaw()1427 void wxWindowMac::DoThaw()
1428 {
1429     if ( GetPeer() && GetPeer()->IsOk() )
1430         GetPeer()->SetDrawingEnabled( true ) ;
1431 }
1432 
wxGetActiveWindow()1433 wxWindow *wxGetActiveWindow()
1434 {
1435     // actually this is a windows-only concept
1436     return NULL;
1437 }
1438 
1439 // Coordinates relative to the window
WarpPointer(int x_pos,int y_pos)1440 void wxWindowMac::WarpPointer(int x_pos, int y_pos)
1441 {
1442 #if wxOSX_USE_COCOA_OR_CARBON
1443     int x = x_pos;
1444     int y = y_pos;
1445     DoClientToScreen(&x, &y);
1446     CGPoint cgpoint = CGPointMake( x, y );
1447     CGWarpMouseCursorPosition( cgpoint );
1448     CGAssociateMouseAndMouseCursorPosition(true);
1449 
1450     // At least GTK sends a mouse moved event after WarpMouse
1451     wxMouseEvent event(wxEVT_MOTION);
1452     event.m_x = x_pos;
1453     event.m_y = y_pos;
1454     wxMouseState mState = ::wxGetMouseState();
1455 
1456     event.m_altDown = mState.AltDown();
1457     event.m_controlDown = mState.ControlDown();
1458     event.m_leftDown = mState.LeftIsDown();
1459     event.m_middleDown = mState.MiddleIsDown();
1460     event.m_rightDown = mState.RightIsDown();
1461     event.m_metaDown = mState.MetaDown();
1462     event.m_shiftDown = mState.ShiftDown();
1463     event.SetId(GetId());
1464     event.SetEventObject(this);
1465     GetEventHandler()->ProcessEvent(event);
1466 #endif
1467 }
1468 
GetScrollPos(int orient) const1469 int wxWindowMac::GetScrollPos(int orient) const
1470 {
1471 #if wxUSE_SCROLLBAR
1472     if ( orient == wxHORIZONTAL )
1473     {
1474        if ( m_hScrollBar )
1475            return m_hScrollBar->GetThumbPosition() ;
1476     }
1477     else
1478     {
1479        if ( m_vScrollBar )
1480            return m_vScrollBar->GetThumbPosition() ;
1481     }
1482 #endif
1483     return 0;
1484 }
1485 
1486 // This now returns the whole range, not just the number
1487 // of positions that we can scroll.
GetScrollRange(int orient) const1488 int wxWindowMac::GetScrollRange(int orient) const
1489 {
1490 #if wxUSE_SCROLLBAR
1491     if ( orient == wxHORIZONTAL )
1492     {
1493        if ( m_hScrollBar )
1494            return m_hScrollBar->GetRange() ;
1495     }
1496     else
1497     {
1498        if ( m_vScrollBar )
1499            return m_vScrollBar->GetRange() ;
1500     }
1501 #endif
1502     return 0;
1503 }
1504 
GetScrollThumb(int orient) const1505 int wxWindowMac::GetScrollThumb(int orient) const
1506 {
1507 #if wxUSE_SCROLLBAR
1508     if ( orient == wxHORIZONTAL )
1509     {
1510        if ( m_hScrollBar )
1511            return m_hScrollBar->GetThumbSize() ;
1512     }
1513     else
1514     {
1515        if ( m_vScrollBar )
1516            return m_vScrollBar->GetThumbSize() ;
1517     }
1518 #endif
1519     return 0;
1520 }
1521 
SetScrollPos(int orient,int pos,bool WXUNUSED (refresh))1522 void wxWindowMac::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
1523 {
1524 #if wxUSE_SCROLLBAR
1525     if ( orient == wxHORIZONTAL )
1526     {
1527        if ( m_hScrollBar )
1528            m_hScrollBar->SetThumbPosition( pos ) ;
1529     }
1530     else
1531     {
1532        if ( m_vScrollBar )
1533            m_vScrollBar->SetThumbPosition( pos ) ;
1534     }
1535 #endif
1536 }
1537 
1538 void
AlwaysShowScrollbars(bool hflag,bool vflag)1539 wxWindowMac::AlwaysShowScrollbars(bool hflag, bool vflag)
1540 {
1541     bool needVisibilityUpdate = false;
1542 
1543     if ( m_hScrollBarAlwaysShown != hflag )
1544     {
1545         m_hScrollBarAlwaysShown = hflag;
1546         needVisibilityUpdate = true;
1547     }
1548 
1549     if ( m_vScrollBarAlwaysShown != vflag )
1550     {
1551         m_vScrollBarAlwaysShown = vflag;
1552         needVisibilityUpdate = true;
1553     }
1554 
1555     if ( needVisibilityUpdate )
1556         DoUpdateScrollbarVisibility();
1557 }
1558 
1559 //
1560 // we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
1561 // our own window origin is at leftOrigin/rightOrigin
1562 //
1563 
MacPaintGrowBox()1564 void  wxWindowMac::MacPaintGrowBox()
1565 {
1566     if ( IsTopLevel() )
1567         return ;
1568 
1569 #if wxUSE_SCROLLBAR
1570     if ( MacHasScrollBarCorner() )
1571     {
1572 #if 0
1573         CGContextRef cgContext = (CGContextRef) MacGetCGContextRef() ;
1574         wxASSERT( cgContext ) ;
1575 
1576         int tx,ty,tw,th;
1577 
1578         GetPeer()->GetSize( tw, th );
1579         GetPeer()->GetPosition( tx, ty );
1580 
1581         Rect rect  = { ty,tx, ty+th, tx+tw };
1582 
1583 
1584         int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
1585         CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
1586         CGContextSaveGState( cgContext );
1587 
1588         if ( m_backgroundColour.IsOk() )
1589         {
1590             CGContextSetFillColorWithColor( cgContext, m_backgroundColour.GetCGColor() );
1591         }
1592         else
1593         {
1594             CGContextSetRGBFillColor( cgContext, (CGFloat) 1.0, (CGFloat)1.0 ,(CGFloat) 1.0 , (CGFloat)1.0 );
1595         }
1596         CGContextFillRect( cgContext, cgrect );
1597         CGContextRestoreGState( cgContext );
1598 #else
1599         if (m_growBox)
1600         {
1601              if ( m_backgroundColour.IsOk() )
1602                  m_growBox->SetBackgroundColour(m_backgroundColour);
1603              else
1604                  m_growBox->SetBackgroundColour(*wxWHITE);
1605         }
1606 #endif
1607     }
1608 
1609 #endif
1610 }
1611 
MacPaintBorders(int WXUNUSED (leftOrigin),int WXUNUSED (rightOrigin))1612 void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin) , int WXUNUSED(rightOrigin) )
1613 {
1614     if ( IsTopLevel() )
1615         return ;
1616 
1617     // back to the surrounding frame rectangle
1618     int tx,ty,tw,th;
1619 
1620     GetPeer()->GetSize( tw, th );
1621     GetPeer()->GetPosition( tx, ty );
1622 
1623 #if wxOSX_USE_COCOA_OR_CARBON
1624     {
1625         const bool hasFocus = GetPeer()->NeedsFocusRect() && HasFocus();
1626 
1627         CGRect cgrect = CGRectMake( tx-1 , ty-1 , tw+2 ,
1628             th+2 ) ;
1629 
1630         CGContextRef cgContext = (CGContextRef) GetParent()->MacGetCGContextRef() ;
1631         wxASSERT( cgContext ) ;
1632 
1633         if ( GetPeer()->NeedsFrame() )
1634         {
1635             HIThemeFrameDrawInfo info ;
1636             memset( &info, 0 , sizeof(info) ) ;
1637 
1638             info.version = 0 ;
1639             info.kind = 0 ;
1640             info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
1641             info.isFocused = hasFocus ;
1642 
1643             if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) )
1644             {
1645                 info.kind = kHIThemeFrameTextFieldSquare ;
1646                 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
1647             }
1648             else if ( HasFlag(wxSIMPLE_BORDER) )
1649             {
1650                 info.kind = kHIThemeFrameListBox ;
1651                 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
1652             }
1653         }
1654 
1655         if ( hasFocus )
1656         {
1657             HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
1658         }
1659     }
1660 #endif // wxOSX_USE_COCOA_OR_CARBON
1661 }
1662 
RemoveChild(wxWindowBase * child)1663 void wxWindowMac::RemoveChild( wxWindowBase *child )
1664 {
1665 #if wxUSE_SCROLLBAR
1666     if ( child == m_hScrollBar )
1667         m_hScrollBar = NULL ;
1668     if ( child == m_vScrollBar )
1669         m_vScrollBar = NULL ;
1670     if ( child == m_growBox )
1671         m_growBox = NULL ;
1672 #endif
1673     wxWindowBase::RemoveChild( child ) ;
1674 }
1675 
DoUpdateScrollbarVisibility()1676 void wxWindowMac::DoUpdateScrollbarVisibility()
1677 {
1678 #if wxUSE_SCROLLBAR
1679     bool triggerSizeEvent = false;
1680 
1681     if ( m_hScrollBar )
1682     {
1683         bool showHScrollBar = m_hScrollBarAlwaysShown || m_hScrollBar->IsNeeded();
1684 
1685         if ( m_hScrollBar->IsShown() != showHScrollBar )
1686         {
1687             m_hScrollBar->Show( showHScrollBar );
1688             triggerSizeEvent = true;
1689         }
1690     }
1691 
1692     if ( m_vScrollBar)
1693     {
1694         bool showVScrollBar = m_vScrollBarAlwaysShown || m_vScrollBar->IsNeeded();
1695 
1696         if ( m_vScrollBar->IsShown() != showVScrollBar )
1697         {
1698             m_vScrollBar->Show( showVScrollBar ) ;
1699             triggerSizeEvent = true;
1700         }
1701     }
1702 
1703     MacRepositionScrollBars() ;
1704     if ( triggerSizeEvent )
1705     {
1706         SendSizeEvent();
1707     }
1708 #endif
1709 }
1710 
1711 // New function that will replace some of the above.
SetScrollbar(int orient,int pos,int thumb,int range,bool refresh)1712 void wxWindowMac::SetScrollbar(int orient, int pos, int thumb,
1713                                int range, bool refresh)
1714 {
1715 #if wxUSE_SCROLLBAR
1716     // Updating scrollbars when window is being deleted is useless and
1717     // currently results in asserts in client-to-screen coordinates conversion
1718     // code which is used by DoUpdateScrollbarVisibility() so just skip it.
1719     if ( m_isBeingDeleted )
1720         return;
1721 
1722     if ( orient == wxHORIZONTAL && m_hScrollBar )
1723         m_hScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
1724     else if ( orient == wxVERTICAL && m_vScrollBar )
1725         m_vScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
1726 
1727     DoUpdateScrollbarVisibility();
1728 #endif
1729 }
1730 
1731 // Does a physical scroll
ScrollWindow(int dx,int dy,const wxRect * rect)1732 void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect)
1733 {
1734     if ( dx == 0 && dy == 0 )
1735         return ;
1736 
1737     int width , height ;
1738     GetClientSize( &width , &height ) ;
1739 
1740     {
1741         wxRect scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width , height ) ;
1742         if ( rect )
1743             scrollrect.Intersect( *rect ) ;
1744         // as the native control might be not a 0/0 wx window coordinates, we have to offset
1745         scrollrect.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
1746 
1747         GetPeer()->ScrollRect( &scrollrect, dx, dy );
1748     }
1749 
1750     wxWindowMac *child;
1751     int x, y, w, h;
1752     for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
1753     {
1754         child = node->GetData();
1755         if (child == NULL)
1756             continue;
1757 
1758         if (child->IsTopLevel())
1759             continue;
1760 
1761         if ( !IsClientAreaChild(child) )
1762             continue;
1763 
1764         child->GetPosition( &x, &y );
1765         child->GetSize( &w, &h );
1766         if (rect)
1767         {
1768             wxRect rc( x, y, w, h );
1769             if (rect->Intersects( rc ))
1770                 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
1771         }
1772         else
1773         {
1774             child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
1775         }
1776     }
1777 }
1778 
MacOnScroll(wxScrollEvent & event)1779 void wxWindowMac::MacOnScroll( wxScrollEvent &event )
1780 {
1781 #if wxUSE_SCROLLBAR
1782     if ( event.GetEventObject() == m_vScrollBar || event.GetEventObject() == m_hScrollBar )
1783     {
1784         wxScrollWinEvent wevent;
1785         wevent.SetPosition(event.GetPosition());
1786         wevent.SetOrientation(event.GetOrientation());
1787         wevent.SetEventObject(this);
1788 
1789         if (event.GetEventType() == wxEVT_SCROLL_TOP)
1790             wevent.SetEventType( wxEVT_SCROLLWIN_TOP );
1791         else if (event.GetEventType() == wxEVT_SCROLL_BOTTOM)
1792             wevent.SetEventType( wxEVT_SCROLLWIN_BOTTOM );
1793         else if (event.GetEventType() == wxEVT_SCROLL_LINEUP)
1794             wevent.SetEventType( wxEVT_SCROLLWIN_LINEUP );
1795         else if (event.GetEventType() == wxEVT_SCROLL_LINEDOWN)
1796             wevent.SetEventType( wxEVT_SCROLLWIN_LINEDOWN );
1797         else if (event.GetEventType() == wxEVT_SCROLL_PAGEUP)
1798             wevent.SetEventType( wxEVT_SCROLLWIN_PAGEUP );
1799         else if (event.GetEventType() == wxEVT_SCROLL_PAGEDOWN)
1800             wevent.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN );
1801         else if (event.GetEventType() == wxEVT_SCROLL_THUMBTRACK)
1802             wevent.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK );
1803         else if (event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE)
1804             wevent.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE );
1805 
1806         HandleWindowEvent(wevent);
1807     }
1808 #endif
1809 }
1810 
DoFindFocus()1811 wxWindow *wxWindowBase::DoFindFocus()
1812 {
1813     return wxFindWindowFromWXWidget(wxWidgetImpl::FindFocus());
1814 }
1815 
1816 // Raise the window to the top of the Z order
Raise()1817 void wxWindowMac::Raise()
1818 {
1819     GetPeer()->Raise();
1820 }
1821 
1822 // Lower the window to the bottom of the Z order
Lower()1823 void wxWindowMac::Lower()
1824 {
1825     GetPeer()->Lower();
1826 }
1827 
1828 // static wxWindow *gs_lastWhich = NULL;
1829 
MacSetupCursor(const wxPoint & pt)1830 bool wxWindowMac::MacSetupCursor( const wxPoint& pt )
1831 {
1832     // first trigger a set cursor event
1833 
1834     wxPoint clientorigin = GetClientAreaOrigin() ;
1835     wxSize clientsize = GetClientSize() ;
1836     wxCursor cursor ;
1837     if ( wxRect2DInt( clientorigin.x , clientorigin.y , clientsize.x , clientsize.y ).Contains( wxPoint2DInt( pt ) ) )
1838     {
1839         wxSetCursorEvent event( pt.x , pt.y );
1840         event.SetId(GetId());
1841         event.SetEventObject(this);
1842 
1843         bool processedEvtSetCursor = HandleWindowEvent(event);
1844         if ( processedEvtSetCursor && event.HasCursor() )
1845         {
1846             cursor = event.GetCursor() ;
1847         }
1848         else
1849         {
1850             // the test for processedEvtSetCursor is here to prevent using m_cursor
1851             // if the user code caught EVT_SET_CURSOR() and returned nothing from
1852             // it - this is a way to say that our cursor shouldn't be used for this
1853             // point
1854             if ( !processedEvtSetCursor && m_cursor.IsOk() )
1855                 cursor = m_cursor ;
1856 
1857             if ( !wxIsBusy() && !GetParent() )
1858                 cursor = *wxSTANDARD_CURSOR ;
1859         }
1860 
1861         if ( cursor.IsOk() )
1862             cursor.MacInstall() ;
1863     }
1864 
1865     return cursor.IsOk() ;
1866 }
1867 
MacGetToolTipString(wxPoint & WXUNUSED (pt))1868 wxString wxWindowMac::MacGetToolTipString( wxPoint &WXUNUSED(pt) )
1869 {
1870 #if wxUSE_TOOLTIPS
1871     if ( m_tooltip )
1872         return m_tooltip->GetTip() ;
1873 #endif
1874 
1875     return wxEmptyString ;
1876 }
1877 
ClearBackground()1878 void wxWindowMac::ClearBackground()
1879 {
1880     Refresh() ;
1881     Update() ;
1882 }
1883 
Update()1884 void wxWindowMac::Update()
1885 {
1886     wxNonOwnedWindow* top = MacGetTopLevelWindow();
1887     if (top)
1888         top->Update() ;
1889 }
1890 
MacGetTopLevelWindow() const1891 wxNonOwnedWindow* wxWindowMac::MacGetTopLevelWindow() const
1892 {
1893     wxWindowMac *iter = (wxWindowMac*)this ;
1894 
1895     while ( iter )
1896     {
1897         if ( iter->IsTopLevel() )
1898         {
1899             wxTopLevelWindow* toplevel = wxDynamicCast(iter,wxTopLevelWindow);
1900             if ( toplevel )
1901                 return toplevel;
1902 #if wxUSE_POPUPWIN
1903             wxPopupWindow* popupwin = wxDynamicCast(iter,wxPopupWindow);
1904             if ( popupwin )
1905                 return popupwin;
1906 #endif
1907         }
1908         iter = iter->GetParent() ;
1909     }
1910 
1911     return NULL ;
1912 }
1913 
MacGetClippedClientRect() const1914 const wxRect& wxWindowMac::MacGetClippedClientRect() const
1915 {
1916     MacUpdateClippedRects() ;
1917 
1918     return m_cachedClippedClientRect ;
1919 }
1920 
MacGetClippedRect() const1921 const wxRect& wxWindowMac::MacGetClippedRect() const
1922 {
1923     MacUpdateClippedRects() ;
1924 
1925     return m_cachedClippedRect ;
1926 }
1927 
MacGetClippedRectWithOuterStructure() const1928 const wxRect&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
1929 {
1930     MacUpdateClippedRects() ;
1931 
1932     return m_cachedClippedRectWithOuterStructure ;
1933 }
1934 
MacGetVisibleRegion(bool includeOuterStructures)1935 const wxRegion& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures )
1936 {
1937     static wxRegion emptyrgn ;
1938 
1939     if ( !m_isBeingDeleted && IsShownOnScreen() )
1940     {
1941         MacUpdateClippedRects() ;
1942         if ( includeOuterStructures )
1943             return m_cachedClippedRegionWithOuterStructure ;
1944         else
1945             return m_cachedClippedRegion ;
1946     }
1947     else
1948     {
1949         return emptyrgn ;
1950     }
1951 }
1952 
MacUpdateClippedRects() const1953 void wxWindowMac::MacUpdateClippedRects() const
1954 {
1955 #if wxOSX_USE_CARBON
1956     if ( m_cachedClippedRectValid )
1957         return ;
1958 
1959     // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
1960     // also a window dc uses this, in this case we only clip in the hierarchy for hard
1961     // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
1962     // to add focus borders everywhere
1963 
1964     Rect rIncludingOuterStructures ;
1965 
1966     int tx,ty,tw,th;
1967 
1968     GetPeer()->GetSize( tw, th );
1969     GetPeer()->GetPosition( tx, ty );
1970 
1971     Rect r  = { ty,tx, ty+th, tx+tw };
1972 
1973     r.left -= MacGetLeftBorderSize() ;
1974     r.top -= MacGetTopBorderSize() ;
1975     r.bottom += MacGetBottomBorderSize() ;
1976     r.right += MacGetRightBorderSize() ;
1977 
1978     r.right -= r.left ;
1979     r.bottom -= r.top ;
1980     r.left = 0 ;
1981     r.top = 0 ;
1982 
1983     rIncludingOuterStructures = r ;
1984     InsetRect( &rIncludingOuterStructures , -4 , -4 ) ;
1985 
1986     wxRect cl = GetClientRect() ;
1987     Rect rClient = { cl.y , cl.x , cl.y + cl.height , cl.x + cl.width } ;
1988 
1989     int x , y ;
1990     wxSize size ;
1991     const wxWindow* child = (wxWindow*) this ;
1992     const wxWindow* parent = NULL ;
1993 
1994     while ( !child->IsTopLevel() && ( parent = child->GetParent() ) != NULL )
1995     {
1996         if ( parent->MacIsChildOfClientArea(child) )
1997         {
1998             size = parent->GetClientSize() ;
1999             wxPoint origin = parent->GetClientAreaOrigin() ;
2000             x = origin.x ;
2001             y = origin.y ;
2002         }
2003         else
2004         {
2005             // this will be true for scrollbars, toolbars etc.
2006             size = parent->GetSize() ;
2007             y = parent->MacGetTopBorderSize() ;
2008             x = parent->MacGetLeftBorderSize() ;
2009             size.x -= parent->MacGetLeftBorderSize() + parent->MacGetRightBorderSize() ;
2010             size.y -= parent->MacGetTopBorderSize() + parent->MacGetBottomBorderSize() ;
2011         }
2012 
2013         parent->MacWindowToRootWindow( &x, &y ) ;
2014         MacRootWindowToWindow( &x , &y ) ;
2015 
2016         Rect rparent = { y , x , y + size.y , x + size.x } ;
2017 
2018         // the wxwindow and client rects will always be clipped
2019         SectRect( &r , &rparent , &r ) ;
2020         SectRect( &rClient , &rparent , &rClient ) ;
2021 
2022         // the structure only at 'hard' borders
2023         if ( parent->MacClipChildren() ||
2024             ( parent->GetParent() && parent->GetParent()->MacClipGrandChildren() ) )
2025         {
2026             SectRect( &rIncludingOuterStructures , &rparent , &rIncludingOuterStructures ) ;
2027         }
2028 
2029         child = parent ;
2030     }
2031 
2032     m_cachedClippedRect = wxRect( r.left , r.top , r.right - r.left , r.bottom - r.top ) ;
2033     m_cachedClippedClientRect = wxRect( rClient.left , rClient.top ,
2034         rClient.right - rClient.left , rClient.bottom - rClient.top ) ;
2035     m_cachedClippedRectWithOuterStructure = wxRect(
2036         rIncludingOuterStructures.left , rIncludingOuterStructures.top ,
2037         rIncludingOuterStructures.right - rIncludingOuterStructures.left ,
2038         rIncludingOuterStructures.bottom - rIncludingOuterStructures.top ) ;
2039 
2040     m_cachedClippedRegionWithOuterStructure = wxRegion( m_cachedClippedRectWithOuterStructure ) ;
2041     m_cachedClippedRegion = wxRegion( m_cachedClippedRect ) ;
2042     m_cachedClippedClientRegion = wxRegion( m_cachedClippedClientRect ) ;
2043 
2044     m_cachedClippedRectValid = true ;
2045 #endif
2046 }
2047 
2048 /*
2049     This function must not change the updatergn !
2050  */
MacDoRedraw(long time)2051 bool wxWindowMac::MacDoRedraw( long time )
2052 {
2053     bool handled = false ;
2054 
2055     wxRegion formerUpdateRgn = m_updateRegion;
2056     wxRegion clientUpdateRgn = formerUpdateRgn;
2057 
2058     const wxRect clientRect = GetClientRect();
2059 
2060     clientUpdateRgn.Intersect(clientRect);
2061 
2062     // first send an erase event to the entire update area
2063     const wxBackgroundStyle bgStyle = GetBackgroundStyle();
2064     switch ( bgStyle )
2065     {
2066         case wxBG_STYLE_ERASE:
2067         case wxBG_STYLE_SYSTEM:
2068         case wxBG_STYLE_COLOUR:
2069             {
2070                 // for the toplevel window this really is the entire area for
2071                 // all the others only their client area, otherwise they might
2072                 // be drawing with full alpha and eg put blue into the grow-box
2073                 // area of a scrolled window (scroll sample)
2074                 wxWindowDC dc(this);
2075                 if ( IsTopLevel() )
2076                     dc.SetDeviceClippingRegion(formerUpdateRgn);
2077                 else
2078                     dc.SetDeviceClippingRegion(clientUpdateRgn);
2079 
2080                 if ( bgStyle == wxBG_STYLE_ERASE )
2081                 {
2082                     wxEraseEvent eevent( GetId(), &dc );
2083                     eevent.SetEventObject( this );
2084                     if ( ProcessWindowEvent( eevent ) )
2085                         break;
2086                 }
2087 
2088                 if ( UseBgCol() )
2089                 {
2090                     dc.SetBackground(GetBackgroundColour());
2091                     dc.Clear();
2092                 }
2093             }
2094             break;
2095 
2096         case wxBG_STYLE_PAINT:
2097         case wxBG_STYLE_TRANSPARENT:
2098             // nothing to do, user-defined EVT_PAINT handler will overwrite the
2099             // entire window client area
2100             break;
2101 
2102         default:
2103             wxFAIL_MSG( "unsupported background style" );
2104     }
2105 
2106     // as this is a full window, shouldn't be necessary anymore
2107     // MacPaintGrowBox();
2108 
2109     // calculate a client-origin version of the update rgn and set
2110     // m_updateRegion to that
2111     clientUpdateRgn.Offset(-clientRect.GetPosition());
2112     m_updateRegion = clientUpdateRgn ;
2113 
2114     if ( !m_updateRegion.Empty() )
2115     {
2116         // paint the window itself
2117 
2118         wxPaintEvent event(GetId());
2119         event.SetTimestamp(time);
2120         event.SetEventObject(this);
2121         handled = HandleWindowEvent(event);
2122     }
2123 
2124     m_updateRegion = formerUpdateRgn;
2125 
2126     wxNonOwnedWindow* top = MacGetTopLevelWindow();
2127     if (top)
2128         top->WindowWasPainted() ;
2129 
2130     return handled;
2131 }
2132 
MacPaintChildrenBorders()2133 void wxWindowMac::MacPaintChildrenBorders()
2134 {
2135     // now we cannot rely on having its borders drawn by a window itself, as it does not
2136     // get the updateRgn wide enough to always do so, so we do it from the parent
2137     // this would also be the place to draw any custom backgrounds for native controls
2138     // in Composited windowing
2139     wxPoint clientOrigin = GetClientAreaOrigin() ;
2140 
2141     wxWindowMac *child;
2142     int x, y, w, h;
2143     for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
2144     {
2145         child = node->GetData();
2146         if (child == NULL)
2147             continue;
2148 #if wxUSE_SCROLLBAR
2149         if (child == m_vScrollBar)
2150             continue;
2151         if (child == m_hScrollBar)
2152             continue;
2153          if (child == m_growBox)
2154              continue;
2155 #endif
2156         if (child->IsTopLevel())
2157             continue;
2158         if (!child->IsShown())
2159             continue;
2160 
2161         // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
2162 
2163         child->GetPosition( &x, &y );
2164         child->GetSize( &w, &h );
2165 
2166         if ( m_updateRegion.Contains(clientOrigin.x+x-10, clientOrigin.y+y-10, w+20, h+20) )
2167         {
2168             // paint custom borders
2169             wxNcPaintEvent eventNc( child->GetId() );
2170             eventNc.SetEventObject( child );
2171             if ( !child->HandleWindowEvent( eventNc ) )
2172             {
2173                 child->MacPaintBorders(0, 0) ;
2174             }
2175         }
2176     }
2177 }
2178 
2179 
MacGetTopLevelWindowRef() const2180 WXWindow wxWindowMac::MacGetTopLevelWindowRef() const
2181 {
2182     wxNonOwnedWindow* tlw = MacGetTopLevelWindow();
2183     return tlw ? tlw->GetWXWindow() : NULL ;
2184 }
2185 
MacHasScrollBarCorner() const2186 bool wxWindowMac::MacHasScrollBarCorner() const
2187 {
2188 #if wxUSE_SCROLLBAR
2189     /* Returns whether the scroll bars in a wxScrolledWindow should be
2190      * shortened. Scroll bars should be shortened if either:
2191      *
2192      * - both scroll bars are visible, or
2193      *
2194      * - there is a resize box in the parent frame's corner and this
2195      *   window shares the bottom and right edge with the parent
2196      *   frame.
2197      */
2198 
2199     if ( m_hScrollBar == NULL && m_vScrollBar == NULL )
2200         return false;
2201 
2202     if ( ( m_hScrollBar && m_hScrollBar->IsShown() )
2203          && ( m_vScrollBar && m_vScrollBar->IsShown() ) )
2204     {
2205         // Both scroll bars visible
2206         return true;
2207     }
2208     else
2209     {
2210         wxPoint thisWindowBottomRight = GetScreenRect().GetBottomRight();
2211 
2212         for ( const wxWindow *win = (wxWindow*)this; win; win = win->GetParent() )
2213         {
2214             const wxFrame *frame = wxDynamicCast( win, wxFrame ) ;
2215             if ( frame )
2216             {
2217                 // starting from 10.7 there are no resize indicators anymore
2218                 if ( (frame->GetWindowStyleFlag() & wxRESIZE_BORDER) && UMAGetSystemVersion() < 0x1070)
2219                 {
2220                     // Parent frame has resize handle
2221                     wxPoint frameBottomRight = frame->GetScreenRect().GetBottomRight();
2222 
2223                     // Note: allow for some wiggle room here as wxMac's
2224                     // window rect calculations seem to be imprecise
2225                     if ( abs( thisWindowBottomRight.x - frameBottomRight.x ) <= 2
2226                         && abs( thisWindowBottomRight.y - frameBottomRight.y ) <= 2 )
2227                     {
2228                         // Parent frame has resize handle and shares
2229                         // right bottom corner
2230                         return true ;
2231                     }
2232                     else
2233                     {
2234                         // Parent frame has resize handle but doesn't
2235                         // share right bottom corner
2236                         return false ;
2237                     }
2238                 }
2239                 else
2240                 {
2241                     // Parent frame doesn't have resize handle
2242                     return false ;
2243                 }
2244             }
2245         }
2246 
2247         // No parent frame found
2248         return false ;
2249     }
2250 #else
2251     return false;
2252 #endif
2253 }
2254 
MacCreateScrollBars(long style)2255 void wxWindowMac::MacCreateScrollBars( long style )
2256 {
2257 #if wxUSE_SCROLLBAR
2258     wxASSERT_MSG( m_vScrollBar == NULL && m_hScrollBar == NULL , wxT("attempt to create window twice") ) ;
2259 
2260     if ( style & ( wxVSCROLL | wxHSCROLL ) )
2261     {
2262         int scrlsize = MAC_SCROLLBAR_SIZE ;
2263         if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL || GetWindowVariant() == wxWINDOW_VARIANT_MINI )
2264         {
2265             scrlsize = MAC_SMALL_SCROLLBAR_SIZE ;
2266         }
2267 
2268         int adjust = MacHasScrollBarCorner() ? scrlsize - 1: 0 ;
2269         int width, height ;
2270         GetClientSize( &width , &height ) ;
2271 
2272         wxPoint vPoint(width - scrlsize, 0) ;
2273         wxSize vSize(scrlsize, height - adjust) ;
2274         wxPoint hPoint(0, height - scrlsize) ;
2275         wxSize hSize(width - adjust, scrlsize) ;
2276 
2277         // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
2278         if ( style & wxVSCROLL )
2279         {
2280             m_vScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, vPoint, vSize , wxVERTICAL);
2281             m_vScrollBar->SetMinSize( wxDefaultSize );
2282         }
2283 
2284         if ( style  & wxHSCROLL )
2285         {
2286             m_hScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, hPoint, hSize , wxHORIZONTAL);
2287             m_hScrollBar->SetMinSize( wxDefaultSize );
2288         }
2289 
2290         wxPoint gPoint(width - scrlsize, height - scrlsize);
2291         wxSize gSize(scrlsize, scrlsize);
2292         m_growBox = new wxBlindPlateWindow((wxWindow *)this, wxID_ANY, gPoint, gSize, 0);
2293     }
2294 
2295     // because the create does not take into account the client area origin
2296     // we might have a real position shift
2297     MacRepositionScrollBars() ;
2298 #endif
2299 }
2300 
MacIsChildOfClientArea(const wxWindow * child) const2301 bool wxWindowMac::MacIsChildOfClientArea( const wxWindow* child ) const
2302 {
2303     bool result = ((child == NULL)
2304 #if wxUSE_SCROLLBAR
2305       || ((child != m_hScrollBar) && (child != m_vScrollBar) && (child != m_growBox))
2306 #endif
2307      );
2308 
2309     return result ;
2310 }
2311 
MacRepositionScrollBars()2312 void wxWindowMac::MacRepositionScrollBars()
2313 {
2314 #if wxUSE_SCROLLBAR
2315     if ( !m_hScrollBar && !m_vScrollBar )
2316         return ;
2317 
2318     int scrlsize = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
2319     int adjust = MacHasScrollBarCorner() ? scrlsize - 1 : 0 ;
2320 
2321     // get real client area
2322     int width, height ;
2323     GetSize( &width , &height );
2324 
2325     width -= MacGetLeftBorderSize() + MacGetRightBorderSize();
2326     height -= MacGetTopBorderSize() + MacGetBottomBorderSize();
2327 
2328     wxPoint vPoint( width - scrlsize, 0 ) ;
2329     wxSize vSize( scrlsize, height - adjust ) ;
2330     wxPoint hPoint( 0 , height - scrlsize ) ;
2331     wxSize hSize( width - adjust, scrlsize ) ;
2332 
2333     if ( m_vScrollBar )
2334         m_vScrollBar->SetSize( vPoint.x , vPoint.y, vSize.x, vSize.y , wxSIZE_ALLOW_MINUS_ONE );
2335     if ( m_hScrollBar )
2336         m_hScrollBar->SetSize( hPoint.x , hPoint.y, hSize.x, hSize.y, wxSIZE_ALLOW_MINUS_ONE );
2337     if ( m_growBox )
2338     {
2339         if ( MacHasScrollBarCorner() )
2340         {
2341             m_growBox->SetSize( width - scrlsize, height - scrlsize, wxDefaultCoord, wxDefaultCoord, wxSIZE_USE_EXISTING );
2342             if ( !m_growBox->IsShown() )
2343                 m_growBox->Show();
2344         }
2345         else
2346         {
2347             if ( m_growBox->IsShown() )
2348                 m_growBox->Hide();
2349         }
2350     }
2351 #endif
2352 }
2353 
AcceptsFocus() const2354 bool wxWindowMac::AcceptsFocus() const
2355 {
2356     if ( GetPeer() == NULL || GetPeer()->IsUserPane() )
2357         return wxWindowBase::AcceptsFocus();
2358     else
2359         return GetPeer()->CanFocus();
2360 }
2361 
MacSuperChangedPosition()2362 void wxWindowMac::MacSuperChangedPosition()
2363 {
2364     // only window-absolute structures have to be moved i.e. controls
2365 
2366     m_cachedClippedRectValid = false ;
2367 
2368     wxWindowMac *child;
2369     wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2370     while ( node )
2371     {
2372         child = node->GetData();
2373         child->MacSuperChangedPosition() ;
2374 
2375         node = node->GetNext();
2376     }
2377 }
2378 
MacTopLevelWindowChangedPosition()2379 void wxWindowMac::MacTopLevelWindowChangedPosition()
2380 {
2381     // only screen-absolute structures have to be moved i.e. glcanvas
2382 
2383     wxWindowMac *child;
2384     wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2385     while ( node )
2386     {
2387         child = node->GetData();
2388         child->MacTopLevelWindowChangedPosition() ;
2389 
2390         node = node->GetNext();
2391     }
2392 }
2393 
MacGetWXBorderSize() const2394 long wxWindowMac::MacGetWXBorderSize() const
2395 {
2396     if ( IsTopLevel() )
2397         return 0 ;
2398 
2399     SInt32 border = 0 ;
2400 
2401     if ( GetPeer() && GetPeer()->NeedsFrame() )
2402     {
2403         if (HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER))
2404         {
2405 #if wxOSX_USE_COCOA_OR_CARBON
2406             // this metric is only the 'outset' outside the simple frame rect
2407             GetThemeMetric( kThemeMetricEditTextFrameOutset , &border ) ;
2408             border += 1;
2409 #else
2410             border += 2;
2411 #endif
2412         }
2413         else if (HasFlag(wxSIMPLE_BORDER))
2414         {
2415 #if wxOSX_USE_COCOA_OR_CARBON
2416             // this metric is only the 'outset' outside the simple frame rect
2417             GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ;
2418             border += 1;
2419 #else
2420             border += 1;
2421 #endif
2422         }
2423     }
2424 
2425     return border ;
2426 }
2427 
MacGetLeftBorderSize() const2428 long wxWindowMac::MacGetLeftBorderSize() const
2429 {
2430     // the wx borders are all symmetric in mac themes
2431     long border = MacGetWXBorderSize() ;
2432 
2433     if ( GetPeer() )
2434     {
2435         int left, top, right, bottom;
2436         GetPeer()->GetLayoutInset( left, top, right, bottom );
2437         border -= left;
2438     }
2439 
2440     return border;
2441 }
2442 
2443 
MacGetRightBorderSize() const2444 long wxWindowMac::MacGetRightBorderSize() const
2445 {
2446     // the wx borders are all symmetric in mac themes
2447     long border = MacGetWXBorderSize() ;
2448 
2449     if ( GetPeer() )
2450     {
2451         int left, top, right, bottom;
2452         GetPeer()->GetLayoutInset( left, top, right, bottom );
2453         border -= right;
2454     }
2455 
2456     return border;
2457 }
2458 
MacGetTopBorderSize() const2459 long wxWindowMac::MacGetTopBorderSize() const
2460 {
2461     // the wx borders are all symmetric in mac themes
2462     long border = MacGetWXBorderSize() ;
2463 
2464     if ( GetPeer() )
2465     {
2466         int left, top, right, bottom;
2467         GetPeer()->GetLayoutInset( left, top, right, bottom );
2468         border -= top;
2469     }
2470 
2471     return border;
2472 }
2473 
MacGetBottomBorderSize() const2474 long wxWindowMac::MacGetBottomBorderSize() const
2475 {
2476     // the wx borders are all symmetric in mac themes
2477     long border = MacGetWXBorderSize() ;
2478 
2479     if ( GetPeer() )
2480     {
2481         int left, top, right, bottom;
2482         GetPeer()->GetLayoutInset( left, top, right, bottom );
2483         border -= bottom;
2484     }
2485 
2486     return border;
2487 }
2488 
MacRemoveBordersFromStyle(long style)2489 long wxWindowMac::MacRemoveBordersFromStyle( long style )
2490 {
2491     return style & ~wxBORDER_MASK ;
2492 }
2493 
2494 // Find the wxWindowMac at the current mouse position, returning the mouse
2495 // position.
wxFindWindowAtPointer(wxPoint & pt)2496 wxWindow * wxFindWindowAtPointer( wxPoint& pt )
2497 {
2498     pt = wxGetMousePosition();
2499     wxWindowMac* found = wxFindWindowAtPoint(pt);
2500 
2501     return (wxWindow*) found;
2502 }
2503 
2504 // Get the current mouse position.
wxGetMousePosition()2505 wxPoint wxGetMousePosition()
2506 {
2507     int x, y;
2508 
2509     wxGetMousePosition( &x, &y );
2510 
2511     return wxPoint(x, y);
2512 }
2513 
OnMouseEvent(wxMouseEvent & event)2514 void wxWindowMac::OnMouseEvent( wxMouseEvent &event )
2515 {
2516     if ( event.GetEventType() == wxEVT_RIGHT_DOWN )
2517     {
2518         // copied from wxGTK : CS
2519         // VZ: shouldn't we move this to base class then?
2520 
2521         // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
2522         // except that:
2523         //
2524         // (a) it's a command event and so is propagated to the parent
2525         // (b) under MSW it can be generated from kbd too
2526         // (c) it uses screen coords (because of (a))
2527         wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU,
2528                                   this->GetId(),
2529                                   this->ClientToScreen(event.GetPosition()));
2530         evtCtx.SetEventObject(this);
2531         if ( ! HandleWindowEvent(evtCtx) )
2532             event.Skip() ;
2533     }
2534     else
2535     {
2536         event.Skip() ;
2537     }
2538 }
2539 
TriggerScrollEvent(wxEventType WXUNUSED (scrollEvent))2540 void wxWindowMac::TriggerScrollEvent( wxEventType WXUNUSED(scrollEvent) )
2541 {
2542 }
2543 
wxMacGetBoundsForControl(wxWindowMac * window,const wxPoint & pos,const wxSize & size,bool adjustForOrigin)2544 Rect wxMacGetBoundsForControl( wxWindowMac* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
2545 {
2546     int x, y, w, h ;
2547 
2548     window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
2549     Rect bounds = { static_cast<short>(y), static_cast<short>(x), static_cast<short>(y + h), static_cast<short>(x + w) };
2550 
2551     return bounds ;
2552 }
2553 
OSXHandleClicked(double WXUNUSED (timestampsec))2554 bool wxWindowMac::OSXHandleClicked( double WXUNUSED(timestampsec) )
2555 {
2556     return false;
2557 }
2558 
2559 #if wxOSX_USE_COCOA_OR_IPHONE
OSXGetViewOrWindow() const2560 void *wxWindowMac::OSXGetViewOrWindow() const
2561 {
2562     return GetHandle();
2563 }
2564 #endif
2565 
MacControlHit(WXEVENTHANDLERREF WXUNUSED (handler),WXEVENTREF event)2566 wxInt32 wxWindowMac::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF event )
2567 {
2568 #if wxOSX_USE_COCOA_OR_CARBON
2569     if ( OSXHandleClicked( GetEventTime((EventRef)event) ) )
2570         return noErr;
2571 
2572     return eventNotHandledErr ;
2573 #else
2574     return 0;
2575 #endif
2576 }
2577 
Reparent(wxWindowBase * newParentBase)2578 bool wxWindowMac::Reparent(wxWindowBase *newParentBase)
2579 {
2580     wxWindowMac *newParent = (wxWindowMac *)newParentBase;
2581     if ( !wxWindowBase::Reparent(newParent) )
2582         return false;
2583 
2584     GetPeer()->RemoveFromParent();
2585     GetPeer()->Embed( GetParent()->GetPeer() );
2586 
2587     MacChildAdded();
2588     return true;
2589 }
2590 
SetTransparent(wxByte alpha)2591 bool wxWindowMac::SetTransparent(wxByte alpha)
2592 {
2593     SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
2594 
2595     if ( alpha != m_macAlpha )
2596     {
2597         m_macAlpha = alpha ;
2598         Refresh() ;
2599     }
2600     return true ;
2601 }
2602 
2603 
CanSetTransparent()2604 bool wxWindowMac::CanSetTransparent()
2605 {
2606     return true ;
2607 }
2608 
GetTransparent() const2609 wxByte wxWindowMac::GetTransparent() const
2610 {
2611     return m_macAlpha ;
2612 }
2613 
IsShownOnScreen() const2614 bool wxWindowMac::IsShownOnScreen() const
2615 {
2616     if ( GetPeer() && GetPeer()->IsOk() )
2617     {
2618         bool peerVis = GetPeer()->IsVisible();
2619         bool wxVis = wxWindowBase::IsShownOnScreen();
2620         if( peerVis != wxVis )
2621         {
2622             // CS : put a breakpoint here to investigate differences
2623             // between native an wx visibilities
2624             // the only place where I've encountered them until now
2625             // are the hiding/showing sequences where the vis-changed event is
2626             // first sent to the innermost control, while wx does things
2627             // from the outmost control
2628             wxVis = wxWindowBase::IsShownOnScreen();
2629             return wxVis;
2630         }
2631 
2632         return GetPeer()->IsVisible();
2633     }
2634     return wxWindowBase::IsShownOnScreen();
2635 }
2636 
2637 #if wxUSE_HOTKEY && wxOSX_USE_COCOA_OR_CARBON
2638 
2639 OSStatus
wxHotKeyHandler(EventHandlerCallRef WXUNUSED (nextHandler),EventRef event,void * WXUNUSED (userData))2640 wxHotKeyHandler(EventHandlerCallRef WXUNUSED(nextHandler),
2641                 EventRef event,
2642                 void* WXUNUSED(userData))
2643 {
2644     EventHotKeyID hotKeyId;
2645 
2646     GetEventParameter( event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(hotKeyId), NULL, &hotKeyId);
2647 
2648     for ( unsigned i = 0; i < s_hotkeys.size(); ++i )
2649     {
2650         if ( s_hotkeys[i].keyId == static_cast<int>(hotKeyId.id) )
2651         {
2652             unsigned char charCode ;
2653             UInt32 keyCode ;
2654             UInt32 modifiers ;
2655             UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
2656 
2657             GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, NULL, 1, NULL, &charCode );
2658             GetEventParameter( event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
2659             GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
2660 
2661             UInt32 keymessage = (keyCode << 8) + charCode;
2662 
2663             wxKeyEvent wxevent(wxEVT_HOTKEY);
2664             wxevent.SetId(hotKeyId.id);
2665             wxTheApp->MacCreateKeyEvent( wxevent, s_hotkeys[i].window , keymessage ,
2666                                         modifiers , when , 0 ) ;
2667 
2668             s_hotkeys[i].window->HandleWindowEvent(wxevent);
2669         }
2670     }
2671 
2672     return noErr;
2673 }
2674 
RegisterHotKey(int hotkeyId,int modifiers,int keycode)2675 bool wxWindowMac::RegisterHotKey(int hotkeyId, int modifiers, int keycode)
2676 {
2677     for ( unsigned i = 0; i < s_hotkeys.size(); ++i )
2678     {
2679         if ( s_hotkeys[i].keyId == hotkeyId )
2680         {
2681             wxLogLastError(wxT("hotkeyId already registered"));
2682 
2683             return false;
2684         }
2685     }
2686 
2687     static bool installed = false;
2688     if ( !installed )
2689     {
2690         EventTypeSpec eventType;
2691         eventType.eventClass=kEventClassKeyboard;
2692         eventType.eventKind=kEventHotKeyPressed;
2693 
2694         InstallApplicationEventHandler(&wxHotKeyHandler, 1, &eventType, NULL, NULL);
2695         installed = true;
2696     }
2697 
2698     UInt32 mac_modifiers=0;
2699     if ( modifiers & wxMOD_ALT )
2700         mac_modifiers |= optionKey;
2701     if ( modifiers & wxMOD_SHIFT )
2702         mac_modifiers |= shiftKey;
2703     if ( modifiers & wxMOD_RAW_CONTROL )
2704         mac_modifiers |= controlKey;
2705     if ( modifiers & wxMOD_CONTROL )
2706         mac_modifiers |= cmdKey;
2707 
2708     EventHotKeyRef hotKeyRef;
2709     EventHotKeyID hotKeyIDmac;
2710 
2711     hotKeyIDmac.signature = 'WXMC';
2712     hotKeyIDmac.id = hotkeyId;
2713 
2714     if ( RegisterEventHotKey(wxCharCodeWXToOSX((wxKeyCode)keycode), mac_modifiers, hotKeyIDmac,
2715                         GetApplicationEventTarget(), 0, &hotKeyRef) != noErr )
2716     {
2717         wxLogLastError(wxT("RegisterHotKey"));
2718 
2719         return false;
2720     }
2721     else
2722     {
2723         wxHotKeyRec v;
2724         v.ref = hotKeyRef;
2725         v.keyId = hotkeyId;
2726         v.window = this;
2727 
2728         s_hotkeys.push_back(v);
2729     }
2730 
2731     return true;
2732 }
2733 
UnregisterHotKey(int hotkeyId)2734 bool wxWindowMac::UnregisterHotKey(int hotkeyId)
2735 {
2736     for ( int i = ((int)s_hotkeys.size())-1; i>=0; -- i )
2737     {
2738         if ( s_hotkeys[i].keyId == hotkeyId )
2739         {
2740             EventHotKeyRef ref = s_hotkeys[i].ref;
2741             s_hotkeys.erase(s_hotkeys.begin() + i);
2742             if ( UnregisterEventHotKey(ref) != noErr )
2743             {
2744                 wxLogLastError(wxT("UnregisterHotKey"));
2745 
2746                 return false;
2747             }
2748             else
2749                 return true;
2750         }
2751     }
2752 
2753     return false;
2754 }
2755 
2756 #endif // wxUSE_HOTKEY
2757 
OSXHandleKeyEvent(wxKeyEvent & event)2758 bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event )
2759 {
2760     bool handled = false;
2761 
2762     // moved the ordinary key event sending AFTER the accel evaluation
2763 
2764 #if wxUSE_ACCEL
2765     if ( !handled && event.GetEventType() == wxEVT_KEY_DOWN)
2766     {
2767         wxWindow *ancestor = this;
2768         while (ancestor)
2769         {
2770             int command = ancestor->GetAcceleratorTable()->GetCommand( event );
2771             if (command != -1)
2772             {
2773                 wxEvtHandler * const handler = ancestor->GetEventHandler();
2774 
2775                 wxCommandEvent command_event( wxEVT_MENU, command );
2776                 handled = handler->ProcessEvent( command_event );
2777 
2778                 if ( !handled )
2779                 {
2780                     // accelerators can also be used with buttons, try them too
2781                     command_event.SetEventType(wxEVT_BUTTON);
2782                     handled = handler->ProcessEvent( command_event );
2783                 }
2784 
2785                 break;
2786             }
2787 
2788             if (ancestor->IsTopLevel())
2789                 break;
2790 
2791             ancestor = ancestor->GetParent();
2792         }
2793     }
2794 #endif // wxUSE_ACCEL
2795 
2796     if ( !handled )
2797     {
2798         handled = HandleWindowEvent( event ) ;
2799         if ( handled && event.GetSkipped() )
2800             handled = false ;
2801     }
2802 
2803     return handled ;
2804 }
2805 
2806 //
2807 // wxWidgetImpl
2808 //
2809 
2810 // we are maintaining a n:1 map from native controls (ControlRef / NSView*) to their wxWidgetImpl
2811 // n:1 because we might have an embedded view eg within a scrollview, both being part of the same impl
2812 // the impl is calling Associate with its newly created native control(s), e.g. in InstallHandler
2813 
2814 WX_DECLARE_HASH_MAP(WXWidget, wxWidgetImpl*, wxPointerHash, wxPointerEqual, MacControlMap);
2815 
2816 static MacControlMap wxWinMacControlList;
2817 
wxFindWindowFromWXWidget(WXWidget inControl)2818 wxWindowMac *wxFindWindowFromWXWidget(WXWidget inControl )
2819 {
2820     wxWidgetImpl* impl = wxWidgetImpl::FindFromWXWidget( inControl );
2821     if ( impl )
2822         return impl->GetWXPeer();
2823 
2824     return NULL;
2825 }
2826 
FindFromWXWidget(WXWidget inControl)2827 wxWidgetImpl *wxWidgetImpl::FindFromWXWidget(WXWidget inControl )
2828 {
2829     MacControlMap::iterator node = wxWinMacControlList.find(inControl);
2830 
2831     return (node == wxWinMacControlList.end()) ? NULL : node->second;
2832 }
2833 
Associate(WXWidget inControl,wxWidgetImpl * impl)2834 void wxWidgetImpl::Associate(WXWidget inControl, wxWidgetImpl *impl)
2835 {
2836     // adding NULL ControlRef is (first) surely a result of an error and
2837     // (secondly) breaks native event processing
2838     wxCHECK_RET( inControl != (WXWidget) NULL, wxT("attempt to add a NULL WXWidget to control map") );
2839 
2840     wxWinMacControlList[inControl] = impl;
2841 }
2842 
RemoveAssociations(wxWidgetImpl * impl)2843 void wxWidgetImpl::RemoveAssociations(wxWidgetImpl* impl)
2844 {
2845    // iterate over all the elements in the class
2846     // is the iterator stable ? as we might have two associations pointing to the same wxWindow
2847     // we should go on...
2848 
2849     bool found = true ;
2850     while ( found )
2851     {
2852         found = false ;
2853         MacControlMap::iterator it;
2854         for ( it = wxWinMacControlList.begin(); it != wxWinMacControlList.end(); ++it )
2855         {
2856             if ( it->second == impl )
2857             {
2858                 wxWinMacControlList.erase(it);
2859                 found = true ;
2860                 break;
2861             }
2862         }
2863     }
2864 }
2865 
IMPLEMENT_ABSTRACT_CLASS(wxWidgetImpl,wxObject)2866 IMPLEMENT_ABSTRACT_CLASS( wxWidgetImpl , wxObject )
2867 
2868 wxWidgetImpl::wxWidgetImpl( wxWindowMac* peer , bool isRootControl, bool isUserPane )
2869 {
2870     Init();
2871     m_isRootControl = isRootControl;
2872     m_isUserPane = isUserPane;
2873     m_wxPeer = peer;
2874     m_shouldSendEvents = true;
2875 }
2876 
wxWidgetImpl()2877 wxWidgetImpl::wxWidgetImpl()
2878 {
2879     Init();
2880 }
2881 
~wxWidgetImpl()2882 wxWidgetImpl::~wxWidgetImpl()
2883 {
2884     m_wxPeer = NULL;
2885 }
2886 
Init()2887 void wxWidgetImpl::Init()
2888 {
2889     m_isRootControl = false;
2890     m_wxPeer = NULL;
2891     m_needsFocusRect = false;
2892     m_needsFrame = true;
2893 }
2894 
SetNeedsFocusRect(bool needs)2895 void wxWidgetImpl::SetNeedsFocusRect( bool needs )
2896 {
2897     m_needsFocusRect = needs;
2898 }
2899 
NeedsFocusRect() const2900 bool wxWidgetImpl::NeedsFocusRect() const
2901 {
2902     return m_needsFocusRect;
2903 }
2904 
SetNeedsFrame(bool needs)2905 void wxWidgetImpl::SetNeedsFrame( bool needs )
2906 {
2907     m_needsFrame = needs;
2908 }
2909 
NeedsFrame() const2910 bool wxWidgetImpl::NeedsFrame() const
2911 {
2912     return m_needsFrame;
2913 }
2914 
SetDrawingEnabled(bool WXUNUSED (enabled))2915 void wxWidgetImpl::SetDrawingEnabled(bool WXUNUSED(enabled))
2916 {
2917 }
2918