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