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(¤tX, ¤tY);
1164 GetSize(¤tW, ¤tH);
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( ¤tclientwidth , ¤tclientheight ) ;
1241 GetSize( ¤twidth , ¤theight ) ;
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