]> git.saurik.com Git - wxWidgets.git/blob - src/osx/carbon/window.cpp
move notebook event definition to common code
[wxWidgets.git] / src / osx / carbon / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/window.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 #if wxOSX_USE_CARBON
65 #include "wx/osx/uma.h"
66 #else
67 #include "wx/osx/private.h"
68 #endif
69
70 #define MAC_SCROLLBAR_SIZE 15
71 #define MAC_SMALL_SCROLLBAR_SIZE 11
72
73 #include <string.h>
74
75 #ifdef __WXUNIVERSAL__
76 IMPLEMENT_ABSTRACT_CLASS(wxWindowMac, wxWindowBase)
77 #else
78 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
79 #endif
80
81 BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase)
82 EVT_NC_PAINT(wxWindowMac::OnNcPaint)
83 EVT_ERASE_BACKGROUND(wxWindowMac::OnEraseBackground)
84 EVT_PAINT(wxWindowMac::OnPaint)
85 EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent)
86 END_EVENT_TABLE()
87
88 #define wxMAC_DEBUG_REDRAW 0
89 #ifndef wxMAC_DEBUG_REDRAW
90 #define wxMAC_DEBUG_REDRAW 0
91 #endif
92
93 //
94 // TODO BEGIN move to window_osx.cpp
95 //
96 // ===========================================================================
97 // implementation
98 // ===========================================================================
99
100 WX_DECLARE_HASH_MAP(WXWidget, wxWindow*, wxPointerHash, wxPointerEqual, MacControlMap);
101
102 static MacControlMap wxWinMacControlList;
103
104 wxWindowMac *wxFindWindowFromWXWidget(WXWidget inControl )
105 {
106 MacControlMap::iterator node = wxWinMacControlList.find(inControl);
107
108 return (node == wxWinMacControlList.end()) ? NULL : node->second;
109 }
110
111 void wxAssociateWindowWithWXWidget(WXWidget inControl, wxWindow *control)
112 {
113 // adding NULL ControlRef is (first) surely a result of an error and
114 // (secondly) breaks native event processing
115 wxCHECK_RET( inControl != (WXWidget) NULL, wxT("attempt to add a NULL WindowRef to window list") );
116
117 wxWinMacControlList[inControl] = control;
118 }
119
120 void wxRemoveWXWidgetAssociation(wxWindow *control)
121 {
122 // iterate over all the elements in the class
123 // is the iterator stable ? as we might have two associations pointing to the same wxWindow
124 // we should go on...
125
126 bool found = true ;
127 while ( found )
128 {
129 found = false ;
130 MacControlMap::iterator it;
131 for ( it = wxWinMacControlList.begin(); it != wxWinMacControlList.end(); ++it )
132 {
133 if ( it->second == control )
134 {
135 wxWinMacControlList.erase(it);
136 found = true ;
137 break;
138 }
139 }
140 }
141 }
142
143 // ----------------------------------------------------------------------------
144 // constructors and such
145 // ----------------------------------------------------------------------------
146
147 wxWindowMac::wxWindowMac()
148 {
149 Init();
150 }
151
152 wxWindowMac::wxWindowMac(wxWindowMac *parent,
153 wxWindowID id,
154 const wxPoint& pos ,
155 const wxSize& size ,
156 long style ,
157 const wxString& name )
158 {
159 Init();
160 Create(parent, id, pos, size, style, name);
161 }
162
163 void wxWindowMac::Init()
164 {
165 m_peer = NULL ;
166 m_macAlpha = 255 ;
167 m_cgContextRef = NULL ;
168
169 // as all windows are created with WS_VISIBLE style...
170 m_isShown = true;
171
172 m_hScrollBar = NULL ;
173 m_vScrollBar = NULL ;
174 m_hScrollBarAlwaysShown = false;
175 m_vScrollBarAlwaysShown = false;
176
177 m_macIsUserPane = true;
178 m_clipChildren = false ;
179 m_cachedClippedRectValid = false ;
180 }
181
182 wxWindowMac::~wxWindowMac()
183 {
184 SendDestroyEvent();
185
186 m_isBeingDeleted = true;
187
188 MacInvalidateBorders() ;
189
190 #ifndef __WXUNIVERSAL__
191 // VS: make sure there's no wxFrame with last focus set to us:
192 for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
193 {
194 wxFrame *frame = wxDynamicCast(win, wxFrame);
195 if ( frame )
196 {
197 if ( frame->GetLastFocus() == this )
198 frame->SetLastFocus((wxWindow*)NULL);
199 break;
200 }
201 }
202 #endif
203
204 // destroy children before destroying this window itself
205 DestroyChildren();
206
207 // wxRemoveMacControlAssociation( this ) ;
208 // If we delete an item, we should initialize the parent panel,
209 // because it could now be invalid.
210 wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent((wxWindow*)this), wxTopLevelWindow);
211 if ( tlw )
212 {
213 if ( tlw->GetDefaultItem() == (wxButton*) this)
214 tlw->SetDefaultItem(NULL);
215 }
216
217 if ( m_peer && m_peer->IsOk() )
218 {
219 m_peer->Destroy() ;
220 }
221
222 if ( g_MacLastWindow == this )
223 g_MacLastWindow = NULL ;
224
225 #ifndef __WXUNIVERSAL__
226 wxFrame* frame = wxDynamicCast( wxGetTopLevelParent( (wxWindow*)this ) , wxFrame ) ;
227 if ( frame )
228 {
229 if ( frame->GetLastFocus() == this )
230 frame->SetLastFocus( NULL ) ;
231 }
232 #endif
233
234 // delete our drop target if we've got one
235 #if wxUSE_DRAG_AND_DROP
236 if ( m_dropTarget != NULL )
237 {
238 delete m_dropTarget;
239 m_dropTarget = NULL;
240 }
241 #endif
242
243 delete m_peer ;
244 }
245
246 WXWidget wxWindowMac::GetHandle() const
247 {
248 return (WXWidget) m_peer->GetWXWidget() ;
249 }
250
251 //
252 // TODO END move to window_osx.cpp
253 //
254
255 // ---------------------------------------------------------------------------
256 // Utility Routines to move between different coordinate systems
257 // ---------------------------------------------------------------------------
258
259 /*
260 * Right now we have the following setup :
261 * a border that is not part of the native control is always outside the
262 * control's border (otherwise we loose all native intelligence, future ways
263 * may be to have a second embedding control responsible for drawing borders
264 * and backgrounds eventually)
265 * so all this border calculations have to be taken into account when calling
266 * native methods or getting native oriented data
267 * so we have three coordinate systems here
268 * wx client coordinates
269 * wx window coordinates (including window frames)
270 * native coordinates
271 */
272
273 //
274 //
275
276 // Constructor
277 bool wxWindowMac::Create(wxWindowMac *parent,
278 wxWindowID id,
279 const wxPoint& pos,
280 const wxSize& size,
281 long style,
282 const wxString& name)
283 {
284 wxCHECK_MSG( parent, false, wxT("can't create wxWindowMac without parent") );
285
286 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
287 return false;
288
289 m_windowVariant = parent->GetWindowVariant() ;
290
291 if ( m_macIsUserPane )
292 {
293 #if wxOSX_USE_CARBON
294 m_peer = (wxMacControl*) wxWidgetImpl::CreateUserPane( this, pos, size , style, GetExtraStyle() , name );
295 #else
296 m_peer = wxWidgetImpl::CreateUserPane( this, pos, size , style, GetExtraStyle() , name );
297 #endif
298 MacPostControlCreate(pos, size) ;
299 }
300
301 #ifndef __WXUNIVERSAL__
302 // Don't give scrollbars to wxControls unless they ask for them
303 if ( (! IsKindOf(CLASSINFO(wxControl)) && ! IsKindOf(CLASSINFO(wxStatusBar)))
304 || (IsKindOf(CLASSINFO(wxControl)) && ((style & wxHSCROLL) || (style & wxVSCROLL))))
305 {
306 MacCreateScrollBars( style ) ;
307 }
308 #endif
309
310 wxWindowCreateEvent event((wxWindow*)this);
311 GetEventHandler()->AddPendingEvent(event);
312
313 return true;
314 }
315
316 void wxWindowMac::MacChildAdded()
317 {
318 if ( m_vScrollBar )
319 m_vScrollBar->Raise() ;
320 if ( m_hScrollBar )
321 m_hScrollBar->Raise() ;
322 }
323
324 void wxWindowMac::MacPostControlCreate(const wxPoint& WXUNUSED(pos), const wxSize& size)
325 {
326 wxASSERT_MSG( m_peer != NULL && m_peer->IsOk() , wxT("No valid mac control") ) ;
327
328 #if wxOSX_USE_CARBON
329 m_peer->SetReference( (URefCon) this ) ;
330 #endif
331
332 GetParent()->AddChild( this );
333
334 #if wxOSX_USE_CARBON
335 m_peer->InstallEventHandler();
336
337 ControlRef container = (ControlRef) GetParent()->GetHandle() ;
338 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
339 ::EmbedControl( m_peer->GetControlRef() , container ) ;
340 #endif
341 GetParent()->MacChildAdded() ;
342
343 // adjust font, controlsize etc
344 DoSetWindowVariant( m_windowVariant ) ;
345 #if wxOSX_USE_CARBON
346 m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ;
347 #endif
348 if (!m_macIsUserPane)
349 SetInitialSize(size);
350
351 SetCursor( *wxSTANDARD_CURSOR ) ;
352 }
353
354 void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
355 {
356 // Don't assert, in case we set the window variant before
357 // the window is created
358 // wxASSERT( m_peer->Ok() ) ;
359
360 m_windowVariant = variant ;
361
362 if (m_peer == NULL || !m_peer->IsOk())
363 return;
364
365 #if wxOSX_USE_COCOA_OR_CARBON
366
367 ControlSize size ;
368 ThemeFontID themeFont = kThemeSystemFont ;
369
370 // we will get that from the settings later
371 // and make this NORMAL later, but first
372 // we have a few calculations that we must fix
373
374 switch ( variant )
375 {
376 case wxWINDOW_VARIANT_NORMAL :
377 size = kControlSizeNormal;
378 themeFont = kThemeSystemFont ;
379 break ;
380
381 case wxWINDOW_VARIANT_SMALL :
382 size = kControlSizeSmall;
383 themeFont = kThemeSmallSystemFont ;
384 break ;
385
386 case wxWINDOW_VARIANT_MINI :
387 // not always defined in the headers
388 size = 3 ;
389 themeFont = 109 ;
390 break ;
391
392 case wxWINDOW_VARIANT_LARGE :
393 size = kControlSizeLarge;
394 themeFont = kThemeSystemFont ;
395 break ;
396
397 default:
398 wxFAIL_MSG(_T("unexpected window variant"));
399 break ;
400 }
401
402 #if wxOSX_USE_CARBON
403 m_peer->SetData<ControlSize>(kControlEntireControl, kControlSizeTag, &size ) ;
404 #endif
405
406 wxFont font ;
407 font.MacCreateFromThemeFont( themeFont ) ;
408 SetFont( font ) ;
409 #endif
410 }
411
412 void wxWindowMac::MacUpdateControlFont()
413 {
414 #if wxOSX_USE_CARBON
415 m_peer->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
416 #endif
417 // do not trigger refreshes upon invisible and possible partly created objects
418 if ( IsShownOnScreen() )
419 Refresh() ;
420 }
421
422 bool wxWindowMac::SetFont(const wxFont& font)
423 {
424 bool retval = wxWindowBase::SetFont( font );
425
426 MacUpdateControlFont() ;
427
428 return retval;
429 }
430
431 bool wxWindowMac::SetForegroundColour(const wxColour& col )
432 {
433 bool retval = wxWindowBase::SetForegroundColour( col );
434
435 if (retval)
436 MacUpdateControlFont();
437
438 return retval;
439 }
440
441 bool wxWindowMac::SetBackgroundColour(const wxColour& col )
442 {
443 if ( !wxWindowBase::SetBackgroundColour(col) && m_hasBgCol )
444 return false ;
445
446 if ( m_peer )
447 m_peer->SetBackgroundColour( col ) ;
448
449 return true ;
450 }
451
452 void wxWindowMac::SetFocus()
453 {
454 if ( !AcceptsFocus() )
455 return ;
456
457 wxWindow* former = FindFocus() ;
458 if ( former == this )
459 return ;
460
461 m_peer->SetFocus() ;
462 }
463
464 void wxWindowMac::DoCaptureMouse()
465 {
466 wxApp::s_captureWindow = (wxWindow*) this ;
467 }
468
469 wxWindow * wxWindowBase::GetCapture()
470 {
471 return wxApp::s_captureWindow ;
472 }
473
474 void wxWindowMac::DoReleaseMouse()
475 {
476 wxApp::s_captureWindow = NULL ;
477 }
478
479 #if wxUSE_DRAG_AND_DROP
480
481 void wxWindowMac::SetDropTarget(wxDropTarget *pDropTarget)
482 {
483 if ( m_dropTarget != NULL )
484 delete m_dropTarget;
485
486 m_dropTarget = pDropTarget;
487 if ( m_dropTarget != NULL )
488 {
489 // TODO:
490 }
491 }
492
493 #endif
494
495 // Old-style File Manager Drag & Drop
496 void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept))
497 {
498 // TODO:
499 }
500
501 // From a wx position / size calculate the appropriate size of the native control
502
503 bool wxWindowMac::MacGetBoundsForControl(
504 const wxPoint& pos,
505 const wxSize& size,
506 int& x, int& y,
507 int& w, int& h , bool adjustOrigin ) const
508 {
509 // the desired size, minus the border pixels gives the correct size of the control
510 x = (int)pos.x;
511 y = (int)pos.y;
512
513 // TODO: the default calls may be used as soon as PostCreateControl Is moved here
514 w = wxMax(size.x, 0) ; // WidthDefault( size.x );
515 h = wxMax(size.y, 0) ; // HeightDefault( size.y ) ;
516
517 x += MacGetLeftBorderSize() ;
518 y += MacGetTopBorderSize() ;
519 w -= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
520 h -= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
521
522 if ( adjustOrigin )
523 AdjustForParentClientOrigin( x , y ) ;
524
525 // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
526 if ( !GetParent()->IsTopLevel() )
527 {
528 x -= GetParent()->MacGetLeftBorderSize() ;
529 y -= GetParent()->MacGetTopBorderSize() ;
530 }
531
532 return true ;
533 }
534
535 // Get window size (not client size)
536 void wxWindowMac::DoGetSize(int *x, int *y) const
537 {
538 int width, height;
539 m_peer->GetSize( width, height );
540
541 if (x)
542 *x = width + MacGetLeftBorderSize() + MacGetRightBorderSize() ;
543 if (y)
544 *y = height + MacGetTopBorderSize() + MacGetBottomBorderSize() ;
545 }
546
547 // get the position of the bounds of this window in client coordinates of its parent
548 void wxWindowMac::DoGetPosition(int *x, int *y) const
549 {
550 int x1, y1;
551
552 m_peer->GetPosition( x1, y1 ) ;
553
554 // get the wx window position from the native one
555 x1 -= MacGetLeftBorderSize() ;
556 y1 -= MacGetTopBorderSize() ;
557
558 if ( !IsTopLevel() )
559 {
560 wxWindow *parent = GetParent();
561 if ( parent )
562 {
563 // we must first adjust it to be in window coordinates of the parent,
564 // as otherwise it gets lost by the ClientAreaOrigin fix
565 x1 += parent->MacGetLeftBorderSize() ;
566 y1 += parent->MacGetTopBorderSize() ;
567
568 // and now to client coordinates
569 wxPoint pt(parent->GetClientAreaOrigin());
570 x1 -= pt.x ;
571 y1 -= pt.y ;
572 }
573 }
574
575 if (x)
576 *x = x1 ;
577 if (y)
578 *y = y1 ;
579 }
580
581 void wxWindowMac::DoScreenToClient(int *x, int *y) const
582 {
583 wxNonOwnedWindow* tlw = MacGetTopLevelWindow() ;
584 wxCHECK_RET( tlw , wxT("TopLevel Window missing") ) ;
585 tlw->GetNonOwnedPeer()->ScreenToWindow( x, y);
586 MacRootWindowToWindow( x , y ) ;
587
588 wxPoint origin = GetClientAreaOrigin() ;
589 if (x)
590 *x -= origin.x ;
591 if (y)
592 *y -= origin.y ;
593 }
594
595 void wxWindowMac::DoClientToScreen(int *x, int *y) const
596 {
597 wxNonOwnedWindow* tlw = MacGetTopLevelWindow() ;
598 wxCHECK_RET( tlw , wxT("TopLevel window missing") ) ;
599
600 wxPoint origin = GetClientAreaOrigin() ;
601 if (x)
602 *x += origin.x ;
603 if (y)
604 *y += origin.y ;
605
606 MacWindowToRootWindow( x , y ) ;
607 tlw->GetNonOwnedPeer()->WindowToScreen( x , y );
608 }
609
610 void wxWindowMac::MacClientToRootWindow( int *x , int *y ) const
611 {
612 wxPoint origin = GetClientAreaOrigin() ;
613 if (x)
614 *x += origin.x ;
615 if (y)
616 *y += origin.y ;
617
618 MacWindowToRootWindow( x , y ) ;
619 }
620
621 void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const
622 {
623 wxPoint pt ;
624
625 if (x)
626 pt.x = *x ;
627 if (y)
628 pt.y = *y ;
629
630 if ( !IsTopLevel() )
631 {
632 wxNonOwnedWindow* top = MacGetTopLevelWindow();
633 if (top)
634 {
635 pt.x -= MacGetLeftBorderSize() ;
636 pt.y -= MacGetTopBorderSize() ;
637 wxWidgetImpl::Convert( &pt , m_peer , top->m_peer ) ;
638 }
639 }
640
641 if (x)
642 *x = (int) pt.x ;
643 if (y)
644 *y = (int) pt.y ;
645 }
646
647 void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const
648 {
649 wxPoint pt ;
650
651 if (x)
652 pt.x = *x ;
653 if (y)
654 pt.y = *y ;
655
656 if ( !IsTopLevel() )
657 {
658 wxNonOwnedWindow* top = MacGetTopLevelWindow();
659 if (top)
660 {
661 wxWidgetImpl::Convert( &pt , top->m_peer , m_peer ) ;
662 pt.x += MacGetLeftBorderSize() ;
663 pt.y += MacGetTopBorderSize() ;
664 }
665 }
666
667 if (x)
668 *x = (int) pt.x ;
669 if (y)
670 *y = (int) pt.y ;
671 }
672
673 wxSize wxWindowMac::DoGetSizeFromClientSize( const wxSize & size ) const
674 {
675 wxSize sizeTotal = size;
676
677 int innerwidth, innerheight;
678 int left, top;
679 int outerwidth, outerheight;
680
681 m_peer->GetContentArea( left, top, innerwidth, innerheight );
682 m_peer->GetSize( outerwidth, outerheight );
683
684 sizeTotal.x += left + (outerwidth-innerwidth);
685 sizeTotal.y += top + (outerheight-innerheight);
686
687 sizeTotal.x += MacGetLeftBorderSize() + MacGetRightBorderSize() ;
688 sizeTotal.y += MacGetTopBorderSize() + MacGetBottomBorderSize() ;
689
690 return sizeTotal;
691 }
692
693 // Get size *available for subwindows* i.e. excluding menu bar etc.
694 void wxWindowMac::DoGetClientSize( int *x, int *y ) const
695 {
696 int ww, hh;
697
698 int left, top;
699
700 m_peer->GetContentArea( left, top, ww, hh );
701
702 if (m_hScrollBar && m_hScrollBar->IsShown() )
703 hh -= m_hScrollBar->GetSize().y ;
704
705 if (m_vScrollBar && m_vScrollBar->IsShown() )
706 ww -= m_vScrollBar->GetSize().x ;
707
708 if (x)
709 *x = ww;
710 if (y)
711 *y = hh;
712 }
713
714 bool wxWindowMac::SetCursor(const wxCursor& cursor)
715 {
716 if (m_cursor.IsSameAs(cursor))
717 return false;
718
719 if (!cursor.IsOk())
720 {
721 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR ) )
722 return false ;
723 }
724 else
725 {
726 if ( ! wxWindowBase::SetCursor( cursor ) )
727 return false ;
728 }
729
730 wxASSERT_MSG( m_cursor.Ok(),
731 wxT("cursor must be valid after call to the base version"));
732
733 wxWindowMac *mouseWin = 0 ;
734 #if wxOSX_USE_CARBON
735 {
736 wxNonOwnedWindow *tlw = MacGetTopLevelWindow() ;
737 WindowRef window = (WindowRef) ( tlw ? tlw->GetWXWindow() : 0 ) ;
738
739 ControlPartCode part ;
740 ControlRef control ;
741 Point pt ;
742 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
743 HIPoint hiPoint ;
744 HIGetMousePosition(kHICoordSpaceWindow, window, &hiPoint);
745 pt.h = hiPoint.x;
746 pt.v = hiPoint.y;
747 #else
748 GetGlobalMouse( &pt );
749 int x = pt.h;
750 int y = pt.v;
751 ScreenToClient(&x, &y);
752 pt.h = x;
753 pt.v = y;
754 #endif
755 control = FindControlUnderMouse( pt , window , &part ) ;
756 if ( control )
757 mouseWin = wxFindWindowFromWXWidget( (WXWidget) control ) ;
758
759 }
760 #endif
761
762 if ( mouseWin == this && !wxIsBusy() )
763 m_cursor.MacInstall() ;
764
765 return true ;
766 }
767
768 #if wxUSE_MENUS
769 bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y)
770 {
771 #ifndef __WXUNIVERSAL__
772 menu->SetInvokingWindow((wxWindow*)this);
773 menu->UpdateUI();
774
775 if ( x == wxDefaultCoord && y == wxDefaultCoord )
776 {
777 wxPoint mouse = wxGetMousePosition();
778 x = mouse.x;
779 y = mouse.y;
780 }
781 else
782 {
783 ClientToScreen( &x , &y ) ;
784 }
785
786 menu->MacBeforeDisplay( true ) ;
787 long menuResult = ::PopUpMenuSelect((MenuHandle) menu->GetHMenu() , y, x, 0) ;
788 if ( HiWord(menuResult) != 0 )
789 {
790 MenuCommand macid;
791 GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult)) , LoWord(menuResult) , &macid );
792 int id = wxMacCommandToId( macid );
793 wxMenuItem* item = NULL ;
794 wxMenu* realmenu ;
795 item = menu->FindItem( id, &realmenu ) ;
796 if ( item )
797 {
798 if (item->IsCheckable())
799 item->Check( !item->IsChecked() ) ;
800
801 menu->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ;
802 }
803 }
804
805 menu->MacAfterDisplay( true ) ;
806 menu->SetInvokingWindow( NULL );
807
808 return true;
809 #else
810 // actually this shouldn't be called, because universal is having its own implementation
811 return false;
812 #endif
813 }
814 #endif
815
816 // ----------------------------------------------------------------------------
817 // tooltips
818 // ----------------------------------------------------------------------------
819
820 #if wxUSE_TOOLTIPS
821
822 void wxWindowMac::DoSetToolTip(wxToolTip *tooltip)
823 {
824 wxWindowBase::DoSetToolTip(tooltip);
825
826 if ( m_tooltip )
827 m_tooltip->SetWindow(this);
828 }
829
830 #endif
831
832 void wxWindowMac::MacInvalidateBorders()
833 {
834 if ( m_peer == NULL )
835 return ;
836
837 bool vis = IsShownOnScreen() ;
838 if ( !vis )
839 return ;
840
841 int outerBorder = MacGetLeftBorderSize() ;
842 #if wxOSX_USE_CARBON
843 if ( m_peer->NeedsFocusRect() /* && m_peer->HasFocus() */ )
844 outerBorder += 4 ;
845 #endif
846
847 if ( outerBorder == 0 )
848 return ;
849
850 // now we know that we have something to do at all
851
852
853 int tx,ty,tw,th;
854
855 m_peer->GetSize( tw, th );
856 m_peer->GetPosition( tx, ty );
857
858 wxRect leftupdate( tx-outerBorder,ty,outerBorder,th );
859 wxRect rightupdate( tx+tw, ty, outerBorder, th );
860 wxRect topupdate( tx-outerBorder, ty-outerBorder, tw + 2 * outerBorder, outerBorder );
861 wxRect bottomupdate( tx-outerBorder, ty + th, tw + 2 * outerBorder, outerBorder );
862
863 GetParent()->m_peer->SetNeedsDisplay(&leftupdate);
864 GetParent()->m_peer->SetNeedsDisplay(&rightupdate);
865 GetParent()->m_peer->SetNeedsDisplay(&topupdate);
866 GetParent()->m_peer->SetNeedsDisplay(&bottomupdate);
867 }
868
869 void wxWindowMac::DoMoveWindow(int x, int y, int width, int height)
870 {
871 // this is never called for a toplevel window, so we know we have a parent
872 int former_x , former_y , former_w, former_h ;
873
874 // Get true coordinates of former position
875 DoGetPosition( &former_x , &former_y ) ;
876 DoGetSize( &former_w , &former_h ) ;
877
878 wxWindow *parent = GetParent();
879 if ( parent )
880 {
881 wxPoint pt(parent->GetClientAreaOrigin());
882 former_x += pt.x ;
883 former_y += pt.y ;
884 }
885
886 int actualWidth = width ;
887 int actualHeight = height ;
888 int actualX = x;
889 int actualY = y;
890
891 if ((m_minWidth != -1) && (actualWidth < m_minWidth))
892 actualWidth = m_minWidth;
893 if ((m_minHeight != -1) && (actualHeight < m_minHeight))
894 actualHeight = m_minHeight;
895 if ((m_maxWidth != -1) && (actualWidth > m_maxWidth))
896 actualWidth = m_maxWidth;
897 if ((m_maxHeight != -1) && (actualHeight > m_maxHeight))
898 actualHeight = m_maxHeight;
899
900 bool doMove = false, doResize = false ;
901
902 if ( actualX != former_x || actualY != former_y )
903 doMove = true ;
904
905 if ( actualWidth != former_w || actualHeight != former_h )
906 doResize = true ;
907
908 if ( doMove || doResize )
909 {
910 // as the borders are drawn outside the native control, we adjust now
911
912 wxRect bounds( wxPoint( actualX + MacGetLeftBorderSize() ,actualY + MacGetTopBorderSize() ),
913 wxSize( actualWidth - (MacGetLeftBorderSize() + MacGetRightBorderSize()) ,
914 actualHeight - (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ;
915
916 if ( !GetParent()->IsTopLevel() )
917 {
918 bounds.Offset( -GetParent()->MacGetLeftBorderSize(), -GetParent()->MacGetTopBorderSize() );
919 }
920
921 MacInvalidateBorders() ;
922
923 m_cachedClippedRectValid = false ;
924
925 m_peer->Move( bounds.x, bounds.y, bounds.width, bounds.height);
926
927 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
928
929 MacInvalidateBorders() ;
930
931 MacRepositionScrollBars() ;
932 if ( doMove )
933 {
934 wxPoint point(actualX, actualY);
935 wxMoveEvent event(point, m_windowId);
936 event.SetEventObject(this);
937 HandleWindowEvent(event) ;
938 }
939
940 if ( doResize )
941 {
942 MacRepositionScrollBars() ;
943 wxSize size(actualWidth, actualHeight);
944 wxSizeEvent event(size, m_windowId);
945 event.SetEventObject(this);
946 HandleWindowEvent(event);
947 }
948 }
949 }
950
951 wxSize wxWindowMac::DoGetBestSize() const
952 {
953 if ( m_macIsUserPane || IsTopLevel() )
954 {
955 return wxWindowBase::DoGetBestSize() ;
956 }
957 else
958 {
959
960 Rect bestsize = { 0 , 0 , 0 , 0 } ;
961 int bestWidth, bestHeight ;
962
963 #if wxOSX_USE_COCOA_OR_CARBON
964 #if wxOSX_USE_CARBON
965 m_peer->GetBestRect( &bestsize ) ;
966 #endif
967 if ( EmptyRect( &bestsize ) )
968 {
969 bestsize.left =
970 bestsize.top = 0 ;
971 bestsize.right =
972 bestsize.bottom = 16 ;
973
974 if ( IsKindOf( CLASSINFO( wxScrollBar ) ) )
975 {
976 bestsize.bottom = 16 ;
977 }
978 #if wxUSE_SPINBTN
979 else if ( IsKindOf( CLASSINFO( wxSpinButton ) ) )
980 {
981 bestsize.bottom = 24 ;
982 }
983 #endif
984 else
985 {
986 // return wxWindowBase::DoGetBestSize() ;
987 }
988 }
989 #endif
990 bestWidth = bestsize.right - bestsize.left + MacGetLeftBorderSize() +
991 MacGetRightBorderSize();
992 bestHeight = bestsize.bottom - bestsize.top + MacGetTopBorderSize() +
993 MacGetBottomBorderSize();
994 if ( bestHeight < 10 )
995 bestHeight = 13 ;
996
997 return wxSize(bestWidth, bestHeight);
998 }
999 }
1000
1001 // set the size of the window: if the dimensions are positive, just use them,
1002 // but if any of them is equal to -1, it means that we must find the value for
1003 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1004 // which case -1 is a valid value for x and y)
1005 //
1006 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1007 // the width/height to best suit our contents, otherwise we reuse the current
1008 // width/height
1009 void wxWindowMac::DoSetSize(int x, int y, int width, int height, int sizeFlags)
1010 {
1011 // get the current size and position...
1012 int currentX, currentY;
1013 int currentW, currentH;
1014
1015 GetPosition(&currentX, &currentY);
1016 GetSize(&currentW, &currentH);
1017
1018 // ... and don't do anything (avoiding flicker) if it's already ok
1019 if ( x == currentX && y == currentY &&
1020 width == currentW && height == currentH && ( height != -1 && width != -1 ) )
1021 {
1022 // TODO: REMOVE
1023 MacRepositionScrollBars() ; // we might have a real position shift
1024
1025 return;
1026 }
1027
1028 if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) )
1029 {
1030 if ( x == wxDefaultCoord )
1031 x = currentX;
1032 if ( y == wxDefaultCoord )
1033 y = currentY;
1034 }
1035
1036 AdjustForParentClientOrigin( x, y, sizeFlags );
1037
1038 wxSize size = wxDefaultSize;
1039 if ( width == wxDefaultCoord )
1040 {
1041 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
1042 {
1043 size = DoGetBestSize();
1044 width = size.x;
1045 }
1046 else
1047 {
1048 // just take the current one
1049 width = currentW;
1050 }
1051 }
1052
1053 if ( height == wxDefaultCoord )
1054 {
1055 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
1056 {
1057 if ( size.x == wxDefaultCoord )
1058 size = DoGetBestSize();
1059 // else: already called DoGetBestSize() above
1060
1061 height = size.y;
1062 }
1063 else
1064 {
1065 // just take the current one
1066 height = currentH;
1067 }
1068 }
1069
1070 DoMoveWindow( x, y, width, height );
1071 }
1072
1073 wxPoint wxWindowMac::GetClientAreaOrigin() const
1074 {
1075 #if wxOSX_USE_CARBON
1076 RgnHandle rgn = NewRgn() ;
1077 Rect content ;
1078 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
1079 {
1080 GetRegionBounds( rgn , &content ) ;
1081 }
1082 else
1083 {
1084 content.left =
1085 content.top = 0 ;
1086 }
1087
1088 DisposeRgn( rgn ) ;
1089
1090 return wxPoint( content.left + MacGetLeftBorderSize() , content.top + MacGetTopBorderSize() );
1091 #else
1092 return wxPoint(0,0);
1093 #endif
1094 }
1095
1096 void wxWindowMac::DoSetClientSize(int clientwidth, int clientheight)
1097 {
1098 if ( clientwidth != wxDefaultCoord || clientheight != wxDefaultCoord )
1099 {
1100 int currentclientwidth , currentclientheight ;
1101 int currentwidth , currentheight ;
1102
1103 GetClientSize( &currentclientwidth , &currentclientheight ) ;
1104 GetSize( &currentwidth , &currentheight ) ;
1105
1106 DoSetSize( wxDefaultCoord , wxDefaultCoord , currentwidth + clientwidth - currentclientwidth ,
1107 currentheight + clientheight - currentclientheight , wxSIZE_USE_EXISTING ) ;
1108 }
1109 }
1110
1111 void wxWindowMac::SetLabel(const wxString& title)
1112 {
1113 m_label = title ;
1114
1115 #if wxOSX_USE_CARBON
1116 if ( m_peer && m_peer->IsOk() )
1117 m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ;
1118 #endif
1119
1120 // do not trigger refreshes upon invisible and possible partly created objects
1121 if ( IsShownOnScreen() )
1122 Refresh() ;
1123 }
1124
1125 wxString wxWindowMac::GetLabel() const
1126 {
1127 return m_label ;
1128 }
1129
1130 bool wxWindowMac::Show(bool show)
1131 {
1132 if ( !wxWindowBase::Show(show) )
1133 return false;
1134
1135 if ( m_peer )
1136 m_peer->SetVisibility( show ) ;
1137
1138 return true;
1139 }
1140
1141 void wxWindowMac::DoEnable(bool enable)
1142 {
1143 #if wxOSX_USE_CARBON
1144 m_peer->Enable( enable ) ;
1145 #endif
1146 }
1147
1148 //
1149 // status change notifications
1150 //
1151
1152 void wxWindowMac::MacVisibilityChanged()
1153 {
1154 }
1155
1156 void wxWindowMac::MacHiliteChanged()
1157 {
1158 }
1159
1160 void wxWindowMac::MacEnabledStateChanged()
1161 {
1162 #if wxOSX_USE_CARBON
1163 OnEnabled( m_peer->IsEnabled() );
1164 #endif
1165 }
1166
1167 //
1168 // status queries on the inherited window's state
1169 //
1170
1171 bool wxWindowMac::MacIsReallyEnabled()
1172 {
1173 #if wxOSX_USE_CARBON
1174 return m_peer->IsEnabled() ;
1175 #endif
1176 }
1177
1178 bool wxWindowMac::MacIsReallyHilited()
1179 {
1180 #if wxOSX_USE_CARBON
1181 return m_peer->IsActive();
1182 #endif
1183 }
1184
1185 int wxWindowMac::GetCharHeight() const
1186 {
1187 wxClientDC dc( (wxWindow*)this ) ;
1188
1189 return dc.GetCharHeight() ;
1190 }
1191
1192 int wxWindowMac::GetCharWidth() const
1193 {
1194 wxClientDC dc( (wxWindow*)this ) ;
1195
1196 return dc.GetCharWidth() ;
1197 }
1198
1199 void wxWindowMac::GetTextExtent(const wxString& string, int *x, int *y,
1200 int *descent, int *externalLeading, const wxFont *theFont ) const
1201 {
1202 const wxFont *fontToUse = theFont;
1203 wxFont tempFont;
1204 if ( !fontToUse )
1205 {
1206 tempFont = GetFont();
1207 fontToUse = &tempFont;
1208 }
1209
1210 wxClientDC dc( (wxWindow*) this ) ;
1211 wxCoord lx,ly,ld,le ;
1212 dc.GetTextExtent( string , &lx , &ly , &ld, &le, (wxFont *)fontToUse ) ;
1213 if ( externalLeading )
1214 *externalLeading = le ;
1215 if ( descent )
1216 *descent = ld ;
1217 if ( x )
1218 *x = lx ;
1219 if ( y )
1220 *y = ly ;
1221 }
1222
1223 /*
1224 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect
1225 * we always intersect with the entire window, not only with the client area
1226 */
1227
1228 void wxWindowMac::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect)
1229 {
1230 if ( m_peer == NULL )
1231 return ;
1232
1233 if ( !IsShownOnScreen() )
1234 return ;
1235
1236 m_peer->SetNeedsDisplay( rect ) ;
1237 }
1238
1239 void wxWindowMac::DoFreeze()
1240 {
1241 #if wxOSX_USE_CARBON
1242 if ( m_peer && m_peer->IsOk() )
1243 m_peer->SetDrawingEnabled( false ) ;
1244 #endif
1245 }
1246
1247 void wxWindowMac::DoThaw()
1248 {
1249 #if wxOSX_USE_CARBON
1250 if ( m_peer && m_peer->IsOk() )
1251 {
1252 m_peer->SetDrawingEnabled( true ) ;
1253 m_peer->InvalidateWithChildren() ;
1254 }
1255 #endif
1256 }
1257
1258 wxWindow *wxGetActiveWindow()
1259 {
1260 // actually this is a windows-only concept
1261 return NULL;
1262 }
1263
1264 // Coordinates relative to the window
1265 void wxWindowMac::WarpPointer(int WXUNUSED(x_pos), int WXUNUSED(y_pos))
1266 {
1267 // We really don't move the mouse programmatically under Mac.
1268 }
1269
1270 void wxWindowMac::OnEraseBackground(wxEraseEvent& event)
1271 {
1272 if ( MacGetTopLevelWindow() == NULL )
1273 return ;
1274 /*
1275 #if TARGET_API_MAC_OSX
1276 if ( !m_backgroundColour.Ok() || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
1277 {
1278 }
1279 else
1280 #endif
1281 */
1282 if ( GetBackgroundStyle() == wxBG_STYLE_COLOUR )
1283 {
1284 event.GetDC()->Clear() ;
1285 }
1286 else if ( GetBackgroundStyle() == wxBG_STYLE_CUSTOM )
1287 {
1288 // don't skip the event here, custom background means that the app
1289 // is drawing it itself in its OnPaint(), so don't draw it at all
1290 // now to avoid flicker
1291 }
1292 else
1293 {
1294 event.Skip() ;
1295 }
1296 }
1297
1298 void wxWindowMac::OnNcPaint( wxNcPaintEvent& event )
1299 {
1300 event.Skip() ;
1301 }
1302
1303 int wxWindowMac::GetScrollPos(int orient) const
1304 {
1305 if ( orient == wxHORIZONTAL )
1306 {
1307 if ( m_hScrollBar )
1308 return m_hScrollBar->GetThumbPosition() ;
1309 }
1310 else
1311 {
1312 if ( m_vScrollBar )
1313 return m_vScrollBar->GetThumbPosition() ;
1314 }
1315
1316 return 0;
1317 }
1318
1319 // This now returns the whole range, not just the number
1320 // of positions that we can scroll.
1321 int wxWindowMac::GetScrollRange(int orient) const
1322 {
1323 if ( orient == wxHORIZONTAL )
1324 {
1325 if ( m_hScrollBar )
1326 return m_hScrollBar->GetRange() ;
1327 }
1328 else
1329 {
1330 if ( m_vScrollBar )
1331 return m_vScrollBar->GetRange() ;
1332 }
1333
1334 return 0;
1335 }
1336
1337 int wxWindowMac::GetScrollThumb(int orient) const
1338 {
1339 if ( orient == wxHORIZONTAL )
1340 {
1341 if ( m_hScrollBar )
1342 return m_hScrollBar->GetThumbSize() ;
1343 }
1344 else
1345 {
1346 if ( m_vScrollBar )
1347 return m_vScrollBar->GetThumbSize() ;
1348 }
1349
1350 return 0;
1351 }
1352
1353 void wxWindowMac::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh))
1354 {
1355 if ( orient == wxHORIZONTAL )
1356 {
1357 if ( m_hScrollBar )
1358 m_hScrollBar->SetThumbPosition( pos ) ;
1359 }
1360 else
1361 {
1362 if ( m_vScrollBar )
1363 m_vScrollBar->SetThumbPosition( pos ) ;
1364 }
1365 }
1366
1367 void
1368 wxWindowMac::AlwaysShowScrollbars(bool hflag, bool vflag)
1369 {
1370 bool needVisibilityUpdate = false;
1371
1372 if ( m_hScrollBarAlwaysShown != hflag )
1373 {
1374 m_hScrollBarAlwaysShown = hflag;
1375 needVisibilityUpdate = true;
1376 }
1377
1378 if ( m_vScrollBarAlwaysShown != vflag )
1379 {
1380 m_vScrollBarAlwaysShown = vflag;
1381 needVisibilityUpdate = true;
1382 }
1383
1384 if ( needVisibilityUpdate )
1385 DoUpdateScrollbarVisibility();
1386 }
1387
1388 //
1389 // we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef
1390 // our own window origin is at leftOrigin/rightOrigin
1391 //
1392
1393 void wxWindowMac::MacPaintGrowBox()
1394 {
1395 if ( IsTopLevel() )
1396 return ;
1397
1398 if ( MacHasScrollBarCorner() )
1399 {
1400 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef() ;
1401 wxASSERT( cgContext ) ;
1402
1403 int tx,ty,tw,th;
1404
1405 m_peer->GetSize( tw, th );
1406 m_peer->GetPosition( tx, ty );
1407
1408 Rect rect = { ty,tx, ty+th, tx+tw };
1409
1410
1411 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
1412 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
1413 CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ;
1414 CGContextSaveGState( cgContext );
1415
1416 if ( m_backgroundColour.Ok() )
1417 {
1418 CGContextSetFillColorWithColor( cgContext, m_backgroundColour.GetCGColor() );
1419 }
1420 else
1421 {
1422 CGContextSetRGBFillColor( cgContext, (CGFloat) 1.0, (CGFloat)1.0 ,(CGFloat) 1.0 , (CGFloat)1.0 );
1423 }
1424 CGContextFillRect( cgContext, cgrect );
1425 CGContextRestoreGState( cgContext );
1426 }
1427 }
1428
1429 void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin) , int WXUNUSED(rightOrigin) )
1430 {
1431 if ( IsTopLevel() )
1432 return ;
1433
1434 bool hasFocus = m_peer->NeedsFocusRect() && m_peer->HasFocus() ;
1435
1436 // back to the surrounding frame rectangle
1437 int tx,ty,tw,th;
1438
1439 m_peer->GetSize( tw, th );
1440 m_peer->GetPosition( tx, ty );
1441
1442 Rect rect = { ty,tx, ty+th, tx+tw };
1443
1444 #if wxOSX_USE_COCOA_OR_CARBON
1445
1446 InsetRect( &rect, -1 , -1 ) ;
1447
1448 {
1449 CGRect cgrect = CGRectMake( rect.left , rect.top , rect.right - rect.left ,
1450 rect.bottom - rect.top ) ;
1451
1452 HIThemeFrameDrawInfo info ;
1453 memset( &info, 0 , sizeof(info) ) ;
1454
1455 info.version = 0 ;
1456 info.kind = 0 ;
1457 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
1458 info.isFocused = hasFocus ;
1459
1460 CGContextRef cgContext = (CGContextRef) GetParent()->MacGetCGContextRef() ;
1461 wxASSERT( cgContext ) ;
1462
1463 if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) )
1464 {
1465 info.kind = kHIThemeFrameTextFieldSquare ;
1466 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
1467 }
1468 else if ( HasFlag(wxSIMPLE_BORDER) )
1469 {
1470 info.kind = kHIThemeFrameListBox ;
1471 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ;
1472 }
1473 else if ( hasFocus )
1474 {
1475 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ;
1476 }
1477 #if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself
1478 m_peer->GetRect( &rect ) ;
1479 if ( MacHasScrollBarCorner() )
1480 {
1481 int variant = (m_hScrollBar == NULL ? m_vScrollBar : m_hScrollBar ) ->GetWindowVariant();
1482 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
1483 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ;
1484 CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ;
1485 HIThemeGrowBoxDrawInfo info ;
1486 memset( &info, 0, sizeof(info) ) ;
1487 info.version = 0 ;
1488 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ;
1489 info.kind = kHIThemeGrowBoxKindNone ;
1490 // contrary to the docs ...SizeSmall does not work
1491 info.size = kHIThemeGrowBoxSizeNormal ;
1492 info.direction = 0 ;
1493 HIThemeDrawGrowBox( &cgpoint , &info , cgContext , kHIThemeOrientationNormal ) ;
1494 }
1495 #endif
1496 }
1497 #endif // wxOSX_USE_COCOA_OR_CARBON
1498 }
1499
1500 void wxWindowMac::RemoveChild( wxWindowBase *child )
1501 {
1502 if ( child == m_hScrollBar )
1503 m_hScrollBar = NULL ;
1504 if ( child == m_vScrollBar )
1505 m_vScrollBar = NULL ;
1506
1507 wxWindowBase::RemoveChild( child ) ;
1508 }
1509
1510 void wxWindowMac::DoUpdateScrollbarVisibility()
1511 {
1512 bool triggerSizeEvent = false;
1513
1514 if ( m_hScrollBar )
1515 {
1516 bool showHScrollBar = m_hScrollBarAlwaysShown || m_hScrollBar->IsNeeded();
1517
1518 if ( m_hScrollBar->IsShown() != showHScrollBar )
1519 {
1520 m_hScrollBar->Show( showHScrollBar );
1521 triggerSizeEvent = true;
1522 }
1523 }
1524
1525 if ( m_vScrollBar)
1526 {
1527 bool showVScrollBar = m_vScrollBarAlwaysShown || m_vScrollBar->IsNeeded();
1528
1529 if ( m_vScrollBar->IsShown() != showVScrollBar )
1530 {
1531 m_vScrollBar->Show( showVScrollBar ) ;
1532 triggerSizeEvent = true;
1533 }
1534 }
1535
1536 MacRepositionScrollBars() ;
1537 if ( triggerSizeEvent )
1538 {
1539 wxSizeEvent event(GetSize(), m_windowId);
1540 event.SetEventObject(this);
1541 HandleWindowEvent(event);
1542 }
1543 }
1544
1545 // New function that will replace some of the above.
1546 void wxWindowMac::SetScrollbar(int orient, int pos, int thumb,
1547 int range, bool refresh)
1548 {
1549 if ( orient == wxHORIZONTAL && m_hScrollBar )
1550 m_hScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
1551 else if ( orient == wxVERTICAL && m_vScrollBar )
1552 m_vScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh);
1553
1554 DoUpdateScrollbarVisibility();
1555 }
1556
1557 // Does a physical scroll
1558 void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect)
1559 {
1560 if ( dx == 0 && dy == 0 )
1561 return ;
1562
1563 int width , height ;
1564 GetClientSize( &width , &height ) ;
1565
1566 {
1567 wxRect scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width , height ) ;
1568 if ( rect )
1569 scrollrect.Intersect( *rect ) ;
1570 // as the native control might be not a 0/0 wx window coordinates, we have to offset
1571 scrollrect.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ;
1572
1573 m_peer->ScrollRect( &scrollrect, dx, dy );
1574 }
1575
1576 wxWindowMac *child;
1577 int x, y, w, h;
1578 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
1579 {
1580 child = node->GetData();
1581 if (child == NULL)
1582 continue;
1583 if (child == m_vScrollBar)
1584 continue;
1585 if (child == m_hScrollBar)
1586 continue;
1587 if (child->IsTopLevel())
1588 continue;
1589
1590 child->GetPosition( &x, &y );
1591 child->GetSize( &w, &h );
1592 if (rect)
1593 {
1594 wxRect rc( x, y, w, h );
1595 if (rect->Intersects( rc ))
1596 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
1597 }
1598 else
1599 {
1600 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE );
1601 }
1602 }
1603 }
1604
1605 void wxWindowMac::MacOnScroll( wxScrollEvent &event )
1606 {
1607 if ( event.GetEventObject() == m_vScrollBar || event.GetEventObject() == m_hScrollBar )
1608 {
1609 wxScrollWinEvent wevent;
1610 wevent.SetPosition(event.GetPosition());
1611 wevent.SetOrientation(event.GetOrientation());
1612 wevent.SetEventObject(this);
1613
1614 if (event.GetEventType() == wxEVT_SCROLL_TOP)
1615 wevent.SetEventType( wxEVT_SCROLLWIN_TOP );
1616 else if (event.GetEventType() == wxEVT_SCROLL_BOTTOM)
1617 wevent.SetEventType( wxEVT_SCROLLWIN_BOTTOM );
1618 else if (event.GetEventType() == wxEVT_SCROLL_LINEUP)
1619 wevent.SetEventType( wxEVT_SCROLLWIN_LINEUP );
1620 else if (event.GetEventType() == wxEVT_SCROLL_LINEDOWN)
1621 wevent.SetEventType( wxEVT_SCROLLWIN_LINEDOWN );
1622 else if (event.GetEventType() == wxEVT_SCROLL_PAGEUP)
1623 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEUP );
1624 else if (event.GetEventType() == wxEVT_SCROLL_PAGEDOWN)
1625 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN );
1626 else if (event.GetEventType() == wxEVT_SCROLL_THUMBTRACK)
1627 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK );
1628 else if (event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE)
1629 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE );
1630
1631 HandleWindowEvent(wevent);
1632 }
1633 }
1634
1635 // Get the window with the focus
1636 wxWindow *wxWindowBase::DoFindFocus()
1637 {
1638 #if wxOSX_USE_CARBON
1639 ControlRef control ;
1640 GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
1641 return wxFindWindowFromWXWidget( (WXWidget) control ) ;
1642 #else
1643 return NULL;
1644 #endif
1645 }
1646
1647 void wxWindowMac::OnInternalIdle()
1648 {
1649 // This calls the UI-update mechanism (querying windows for
1650 // menu/toolbar/control state information)
1651 if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
1652 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
1653 }
1654
1655 // Raise the window to the top of the Z order
1656 void wxWindowMac::Raise()
1657 {
1658 m_peer->Raise();
1659 }
1660
1661 // Lower the window to the bottom of the Z order
1662 void wxWindowMac::Lower()
1663 {
1664 m_peer->Lower();
1665 }
1666
1667 // static wxWindow *gs_lastWhich = NULL;
1668
1669 bool wxWindowMac::MacSetupCursor( const wxPoint& pt )
1670 {
1671 // first trigger a set cursor event
1672
1673 wxPoint clientorigin = GetClientAreaOrigin() ;
1674 wxSize clientsize = GetClientSize() ;
1675 wxCursor cursor ;
1676 if ( wxRect2DInt( clientorigin.x , clientorigin.y , clientsize.x , clientsize.y ).Contains( wxPoint2DInt( pt ) ) )
1677 {
1678 wxSetCursorEvent event( pt.x , pt.y );
1679
1680 bool processedEvtSetCursor = HandleWindowEvent(event);
1681 if ( processedEvtSetCursor && event.HasCursor() )
1682 {
1683 cursor = event.GetCursor() ;
1684 }
1685 else
1686 {
1687 // the test for processedEvtSetCursor is here to prevent using m_cursor
1688 // if the user code caught EVT_SET_CURSOR() and returned nothing from
1689 // it - this is a way to say that our cursor shouldn't be used for this
1690 // point
1691 if ( !processedEvtSetCursor && m_cursor.Ok() )
1692 cursor = m_cursor ;
1693
1694 if ( !wxIsBusy() && !GetParent() )
1695 cursor = *wxSTANDARD_CURSOR ;
1696 }
1697
1698 if ( cursor.Ok() )
1699 cursor.MacInstall() ;
1700 }
1701
1702 return cursor.Ok() ;
1703 }
1704
1705 wxString wxWindowMac::MacGetToolTipString( wxPoint &WXUNUSED(pt) )
1706 {
1707 #if wxUSE_TOOLTIPS
1708 if ( m_tooltip )
1709 return m_tooltip->GetTip() ;
1710 #endif
1711
1712 return wxEmptyString ;
1713 }
1714
1715 void wxWindowMac::ClearBackground()
1716 {
1717 Refresh() ;
1718 Update() ;
1719 }
1720
1721 void wxWindowMac::Update()
1722 {
1723 wxNonOwnedWindow* top = MacGetTopLevelWindow();
1724 if (top)
1725 top->Update() ;
1726 }
1727
1728 wxNonOwnedWindow* wxWindowMac::MacGetTopLevelWindow() const
1729 {
1730 wxWindowMac *iter = (wxWindowMac*)this ;
1731
1732 while ( iter )
1733 {
1734 if ( iter->IsTopLevel() )
1735 {
1736 wxTopLevelWindow* toplevel = wxDynamicCast(iter,wxTopLevelWindow);
1737 if ( toplevel )
1738 return toplevel;
1739 #if wxUSE_POPUPWIN
1740 wxPopupWindow* popupwin = wxDynamicCast(iter,wxPopupWindow);
1741 if ( popupwin )
1742 return popupwin;
1743 #endif
1744 }
1745 iter = iter->GetParent() ;
1746 }
1747
1748 return NULL ;
1749 }
1750
1751 const wxRect& wxWindowMac::MacGetClippedClientRect() const
1752 {
1753 MacUpdateClippedRects() ;
1754
1755 return m_cachedClippedClientRect ;
1756 }
1757
1758 const wxRect& wxWindowMac::MacGetClippedRect() const
1759 {
1760 MacUpdateClippedRects() ;
1761
1762 return m_cachedClippedRect ;
1763 }
1764
1765 const wxRect&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
1766 {
1767 MacUpdateClippedRects() ;
1768
1769 return m_cachedClippedRectWithOuterStructure ;
1770 }
1771
1772 const wxRegion& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures )
1773 {
1774 static wxRegion emptyrgn ;
1775
1776 if ( !m_isBeingDeleted && IsShownOnScreen() )
1777 {
1778 MacUpdateClippedRects() ;
1779 if ( includeOuterStructures )
1780 return m_cachedClippedRegionWithOuterStructure ;
1781 else
1782 return m_cachedClippedRegion ;
1783 }
1784 else
1785 {
1786 return emptyrgn ;
1787 }
1788 }
1789
1790 void wxWindowMac::MacUpdateClippedRects() const
1791 {
1792 #if wxOSX_USE_CARBON
1793 if ( m_cachedClippedRectValid )
1794 return ;
1795
1796 // includeOuterStructures is true if we try to draw somthing like a focus ring etc.
1797 // also a window dc uses this, in this case we only clip in the hierarchy for hard
1798 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having
1799 // to add focus borders everywhere
1800
1801 Rect rIncludingOuterStructures ;
1802
1803 int tx,ty,tw,th;
1804
1805 m_peer->GetSize( tw, th );
1806 m_peer->GetPosition( tx, ty );
1807
1808 Rect r = { ty,tx, ty+th, tx+tw };
1809
1810 r.left -= MacGetLeftBorderSize() ;
1811 r.top -= MacGetTopBorderSize() ;
1812 r.bottom += MacGetBottomBorderSize() ;
1813 r.right += MacGetRightBorderSize() ;
1814
1815 r.right -= r.left ;
1816 r.bottom -= r.top ;
1817 r.left = 0 ;
1818 r.top = 0 ;
1819
1820 rIncludingOuterStructures = r ;
1821 InsetRect( &rIncludingOuterStructures , -4 , -4 ) ;
1822
1823 wxRect cl = GetClientRect() ;
1824 Rect rClient = { cl.y , cl.x , cl.y + cl.height , cl.x + cl.width } ;
1825
1826 int x , y ;
1827 wxSize size ;
1828 const wxWindow* child = (wxWindow*) this ;
1829 const wxWindow* parent = NULL ;
1830
1831 while ( !child->IsTopLevel() && ( parent = child->GetParent() ) != NULL )
1832 {
1833 if ( parent->MacIsChildOfClientArea(child) )
1834 {
1835 size = parent->GetClientSize() ;
1836 wxPoint origin = parent->GetClientAreaOrigin() ;
1837 x = origin.x ;
1838 y = origin.y ;
1839 }
1840 else
1841 {
1842 // this will be true for scrollbars, toolbars etc.
1843 size = parent->GetSize() ;
1844 y = parent->MacGetTopBorderSize() ;
1845 x = parent->MacGetLeftBorderSize() ;
1846 size.x -= parent->MacGetLeftBorderSize() + parent->MacGetRightBorderSize() ;
1847 size.y -= parent->MacGetTopBorderSize() + parent->MacGetBottomBorderSize() ;
1848 }
1849
1850 parent->MacWindowToRootWindow( &x, &y ) ;
1851 MacRootWindowToWindow( &x , &y ) ;
1852
1853 Rect rparent = { y , x , y + size.y , x + size.x } ;
1854
1855 // the wxwindow and client rects will always be clipped
1856 SectRect( &r , &rparent , &r ) ;
1857 SectRect( &rClient , &rparent , &rClient ) ;
1858
1859 // the structure only at 'hard' borders
1860 if ( parent->MacClipChildren() ||
1861 ( parent->GetParent() && parent->GetParent()->MacClipGrandChildren() ) )
1862 {
1863 SectRect( &rIncludingOuterStructures , &rparent , &rIncludingOuterStructures ) ;
1864 }
1865
1866 child = parent ;
1867 }
1868
1869 m_cachedClippedRect = wxRect( r.left , r.top , r.right - r.left , r.bottom - r.top ) ;
1870 m_cachedClippedClientRect = wxRect( rClient.left , rClient.top ,
1871 rClient.right - rClient.left , rClient.bottom - rClient.top ) ;
1872 m_cachedClippedRectWithOuterStructure = wxRect(
1873 rIncludingOuterStructures.left , rIncludingOuterStructures.top ,
1874 rIncludingOuterStructures.right - rIncludingOuterStructures.left ,
1875 rIncludingOuterStructures.bottom - rIncludingOuterStructures.top ) ;
1876
1877 m_cachedClippedRegionWithOuterStructure = wxRegion( m_cachedClippedRectWithOuterStructure ) ;
1878 m_cachedClippedRegion = wxRegion( m_cachedClippedRect ) ;
1879 m_cachedClippedClientRegion = wxRegion( m_cachedClippedClientRect ) ;
1880
1881 m_cachedClippedRectValid = true ;
1882 #endif
1883 }
1884
1885 /*
1886 This function must not change the updatergn !
1887 */
1888 bool wxWindowMac::MacDoRedraw( void* updatergnr , long time )
1889 {
1890 bool handled = false ;
1891 #if wxOSX_USE_CARBON
1892 Rect updatebounds ;
1893 RgnHandle updatergn = (RgnHandle) updatergnr ;
1894 GetRegionBounds( updatergn , &updatebounds ) ;
1895
1896 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
1897
1898 if ( !EmptyRgn(updatergn) )
1899 {
1900 RgnHandle newupdate = NewRgn() ;
1901 wxSize point = GetClientSize() ;
1902 wxPoint origin = GetClientAreaOrigin() ;
1903 SetRectRgn( newupdate , origin.x , origin.y , origin.x + point.x , origin.y + point.y ) ;
1904 SectRgn( newupdate , updatergn , newupdate ) ;
1905
1906 // first send an erase event to the entire update area
1907 {
1908 // for the toplevel window this really is the entire area
1909 // for all the others only their client area, otherwise they
1910 // might be drawing with full alpha and eg put blue into
1911 // the grow-box area of a scrolled window (scroll sample)
1912 wxDC* dc = new wxWindowDC(this);
1913 if ( IsTopLevel() )
1914 dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn)));
1915 else
1916 dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate)));
1917
1918 wxEraseEvent eevent( GetId(), dc );
1919 eevent.SetEventObject( this );
1920 HandleWindowEvent( eevent );
1921 delete dc ;
1922 }
1923
1924 MacPaintGrowBox();
1925
1926 // calculate a client-origin version of the update rgn and set m_updateRegion to that
1927 OffsetRgn( newupdate , -origin.x , -origin.y ) ;
1928 m_updateRegion = wxRegion(HIShapeCreateWithQDRgn(newupdate)) ;
1929 DisposeRgn( newupdate ) ;
1930
1931 if ( !m_updateRegion.Empty() )
1932 {
1933 // paint the window itself
1934
1935 wxPaintEvent event;
1936 event.SetTimestamp(time);
1937 event.SetEventObject(this);
1938 HandleWindowEvent(event);
1939 handled = true ;
1940 }
1941
1942 // now we cannot rely on having its borders drawn by a window itself, as it does not
1943 // get the updateRgn wide enough to always do so, so we do it from the parent
1944 // this would also be the place to draw any custom backgrounds for native controls
1945 // in Composited windowing
1946 wxPoint clientOrigin = GetClientAreaOrigin() ;
1947
1948 wxWindowMac *child;
1949 int x, y, w, h;
1950 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext())
1951 {
1952 child = node->GetData();
1953 if (child == NULL)
1954 continue;
1955 if (child == m_vScrollBar)
1956 continue;
1957 if (child == m_hScrollBar)
1958 continue;
1959 if (child->IsTopLevel())
1960 continue;
1961 if (!child->IsShown())
1962 continue;
1963
1964 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
1965
1966 child->GetPosition( &x, &y );
1967 child->GetSize( &w, &h );
1968 Rect childRect = { y , x , y + h , x + w } ;
1969 OffsetRect( &childRect , clientOrigin.x , clientOrigin.y ) ;
1970 InsetRect( &childRect , -10 , -10) ;
1971
1972 if ( RectInRgn( &childRect , updatergn ) )
1973 {
1974 // paint custom borders
1975 wxNcPaintEvent eventNc( child->GetId() );
1976 eventNc.SetEventObject( child );
1977 if ( !child->HandleWindowEvent( eventNc ) )
1978 {
1979 child->MacPaintBorders(0, 0) ;
1980 }
1981 }
1982 }
1983 }
1984 #endif
1985 return handled ;
1986 }
1987
1988
1989 WXWindow wxWindowMac::MacGetTopLevelWindowRef() const
1990 {
1991 wxNonOwnedWindow* tlw = MacGetTopLevelWindow();
1992 return tlw ? tlw->GetWXWindow() : NULL ;
1993 }
1994
1995 bool wxWindowMac::MacHasScrollBarCorner() const
1996 {
1997 /* Returns whether the scroll bars in a wxScrolledWindow should be
1998 * shortened. Scroll bars should be shortened if either:
1999 *
2000 * - both scroll bars are visible, or
2001 *
2002 * - there is a resize box in the parent frame's corner and this
2003 * window shares the bottom and right edge with the parent
2004 * frame.
2005 */
2006
2007 if ( m_hScrollBar == NULL && m_vScrollBar == NULL )
2008 return false;
2009
2010 if ( ( m_hScrollBar && m_hScrollBar->IsShown() )
2011 && ( m_vScrollBar && m_vScrollBar->IsShown() ) )
2012 {
2013 // Both scroll bars visible
2014 return true;
2015 }
2016 else
2017 {
2018 wxPoint thisWindowBottomRight = GetScreenRect().GetBottomRight();
2019
2020 for ( const wxWindow *win = (wxWindow*)this; win; win = win->GetParent() )
2021 {
2022 const wxFrame *frame = wxDynamicCast( win, wxFrame ) ;
2023 if ( frame )
2024 {
2025 if ( frame->GetWindowStyleFlag() & wxRESIZE_BORDER )
2026 {
2027 // Parent frame has resize handle
2028 wxPoint frameBottomRight = frame->GetScreenRect().GetBottomRight();
2029
2030 // Note: allow for some wiggle room here as wxMac's
2031 // window rect calculations seem to be imprecise
2032 if ( abs( thisWindowBottomRight.x - frameBottomRight.x ) <= 2
2033 && abs( thisWindowBottomRight.y - frameBottomRight.y ) <= 2 )
2034 {
2035 // Parent frame has resize handle and shares
2036 // right bottom corner
2037 return true ;
2038 }
2039 else
2040 {
2041 // Parent frame has resize handle but doesn't
2042 // share right bottom corner
2043 return false ;
2044 }
2045 }
2046 else
2047 {
2048 // Parent frame doesn't have resize handle
2049 return false ;
2050 }
2051 }
2052 }
2053
2054 // No parent frame found
2055 return false ;
2056 }
2057 }
2058
2059 void wxWindowMac::MacCreateScrollBars( long style )
2060 {
2061 wxASSERT_MSG( m_vScrollBar == NULL && m_hScrollBar == NULL , wxT("attempt to create window twice") ) ;
2062
2063 if ( style & ( wxVSCROLL | wxHSCROLL ) )
2064 {
2065 int scrlsize = MAC_SCROLLBAR_SIZE ;
2066 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL || GetWindowVariant() == wxWINDOW_VARIANT_MINI )
2067 {
2068 scrlsize = MAC_SMALL_SCROLLBAR_SIZE ;
2069 }
2070
2071 int adjust = MacHasScrollBarCorner() ? scrlsize - 1: 0 ;
2072 int width, height ;
2073 GetClientSize( &width , &height ) ;
2074
2075 wxPoint vPoint(width - scrlsize, 0) ;
2076 wxSize vSize(scrlsize, height - adjust) ;
2077 wxPoint hPoint(0, height - scrlsize) ;
2078 wxSize hSize(width - adjust, scrlsize) ;
2079
2080 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
2081 if ( style & wxVSCROLL )
2082 {
2083 m_vScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, vPoint, vSize , wxVERTICAL);
2084 m_vScrollBar->SetMinSize( wxDefaultSize );
2085 }
2086
2087 if ( style & wxHSCROLL )
2088 {
2089 m_hScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, hPoint, hSize , wxHORIZONTAL);
2090 m_hScrollBar->SetMinSize( wxDefaultSize );
2091 }
2092 }
2093
2094 // because the create does not take into account the client area origin
2095 // we might have a real position shift
2096 MacRepositionScrollBars() ;
2097 }
2098
2099 bool wxWindowMac::MacIsChildOfClientArea( const wxWindow* child ) const
2100 {
2101 bool result = ((child == NULL) || ((child != m_hScrollBar) && (child != m_vScrollBar)));
2102
2103 return result ;
2104 }
2105
2106 void wxWindowMac::MacRepositionScrollBars()
2107 {
2108 if ( !m_hScrollBar && !m_vScrollBar )
2109 return ;
2110
2111 int scrlsize = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ;
2112 int adjust = MacHasScrollBarCorner() ? scrlsize - 1 : 0 ;
2113
2114 // get real client area
2115 int width, height ;
2116 GetSize( &width , &height );
2117
2118 width -= MacGetLeftBorderSize() + MacGetRightBorderSize();
2119 height -= MacGetTopBorderSize() + MacGetBottomBorderSize();
2120
2121 wxPoint vPoint( width - scrlsize, 0 ) ;
2122 wxSize vSize( scrlsize, height - adjust ) ;
2123 wxPoint hPoint( 0 , height - scrlsize ) ;
2124 wxSize hSize( width - adjust, scrlsize ) ;
2125
2126 if ( m_vScrollBar )
2127 m_vScrollBar->SetSize( vPoint.x , vPoint.y, vSize.x, vSize.y , wxSIZE_ALLOW_MINUS_ONE );
2128 if ( m_hScrollBar )
2129 m_hScrollBar->SetSize( hPoint.x , hPoint.y, hSize.x, hSize.y, wxSIZE_ALLOW_MINUS_ONE );
2130 }
2131
2132 bool wxWindowMac::AcceptsFocus() const
2133 {
2134 return m_peer->CanFocus() && wxWindowBase::AcceptsFocus();
2135 }
2136
2137 void wxWindowMac::MacSuperChangedPosition()
2138 {
2139 // only window-absolute structures have to be moved i.e. controls
2140
2141 m_cachedClippedRectValid = false ;
2142
2143 wxWindowMac *child;
2144 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2145 while ( node )
2146 {
2147 child = node->GetData();
2148 child->MacSuperChangedPosition() ;
2149
2150 node = node->GetNext();
2151 }
2152 }
2153
2154 void wxWindowMac::MacTopLevelWindowChangedPosition()
2155 {
2156 // only screen-absolute structures have to be moved i.e. glcanvas
2157
2158 wxWindowMac *child;
2159 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
2160 while ( node )
2161 {
2162 child = node->GetData();
2163 child->MacTopLevelWindowChangedPosition() ;
2164
2165 node = node->GetNext();
2166 }
2167 }
2168
2169 long wxWindowMac::MacGetLeftBorderSize() const
2170 {
2171 if ( IsTopLevel() )
2172 return 0 ;
2173
2174 SInt32 border = 0 ;
2175
2176 if (HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER))
2177 {
2178 #if wxOSX_USE_COCOA_OR_CARBON
2179 // this metric is only the 'outset' outside the simple frame rect
2180 GetThemeMetric( kThemeMetricEditTextFrameOutset , &border ) ;
2181 border += 1;
2182 #else
2183 border += 2;
2184 #endif
2185 }
2186 else if (HasFlag(wxSIMPLE_BORDER))
2187 {
2188 #if wxOSX_USE_COCOA_OR_CARBON
2189 // this metric is only the 'outset' outside the simple frame rect
2190 GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ;
2191 border += 1;
2192 #else
2193 border += 1;
2194 #endif
2195 }
2196
2197 return border ;
2198 }
2199
2200 long wxWindowMac::MacGetRightBorderSize() const
2201 {
2202 // they are all symmetric in mac themes
2203 return MacGetLeftBorderSize() ;
2204 }
2205
2206 long wxWindowMac::MacGetTopBorderSize() const
2207 {
2208 // they are all symmetric in mac themes
2209 return MacGetLeftBorderSize() ;
2210 }
2211
2212 long wxWindowMac::MacGetBottomBorderSize() const
2213 {
2214 // they are all symmetric in mac themes
2215 return MacGetLeftBorderSize() ;
2216 }
2217
2218 long wxWindowMac::MacRemoveBordersFromStyle( long style )
2219 {
2220 return style & ~wxBORDER_MASK ;
2221 }
2222
2223 // Find the wxWindowMac at the current mouse position, returning the mouse
2224 // position.
2225 wxWindow * wxFindWindowAtPointer( wxPoint& pt )
2226 {
2227 pt = wxGetMousePosition();
2228 wxWindowMac* found = wxFindWindowAtPoint(pt);
2229
2230 return (wxWindow*) found;
2231 }
2232
2233 // Get the current mouse position.
2234 wxPoint wxGetMousePosition()
2235 {
2236 int x, y;
2237
2238 wxGetMousePosition( &x, &y );
2239
2240 return wxPoint(x, y);
2241 }
2242
2243 void wxWindowMac::OnMouseEvent( wxMouseEvent &event )
2244 {
2245 if ( event.GetEventType() == wxEVT_RIGHT_DOWN )
2246 {
2247 // copied from wxGTK : CS
2248 // VZ: shouldn't we move this to base class then?
2249
2250 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
2251 // except that:
2252 //
2253 // (a) it's a command event and so is propagated to the parent
2254 // (b) under MSW it can be generated from kbd too
2255 // (c) it uses screen coords (because of (a))
2256 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU,
2257 this->GetId(),
2258 this->ClientToScreen(event.GetPosition()));
2259 evtCtx.SetEventObject(this);
2260 if ( ! HandleWindowEvent(evtCtx) )
2261 event.Skip() ;
2262 }
2263 else
2264 {
2265 event.Skip() ;
2266 }
2267 }
2268
2269 void wxWindowMac::OnPaint( wxPaintEvent & WXUNUSED(event) )
2270 {
2271 #if wxOSX_USE_COCOA_OR_CARBON
2272 // for native controls: call their native paint method
2273 if ( !MacIsUserPane() || ( IsTopLevel() && GetBackgroundStyle() == wxBG_STYLE_SYSTEM ) )
2274 {
2275 if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL
2276 && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT )
2277 CallNextEventHandler(
2278 (EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() ,
2279 (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
2280 }
2281 #endif
2282 }
2283
2284 void wxWindowMac::MacHandleControlClick(WXWidget WXUNUSED(control),
2285 wxInt16 WXUNUSED(controlpart),
2286 bool WXUNUSED(mouseStillDown))
2287 {
2288 }
2289
2290 Rect wxMacGetBoundsForControl( wxWindowMac* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
2291 {
2292 int x, y, w, h ;
2293
2294 window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
2295 Rect bounds = { y, x, y + h, x + w };
2296
2297 return bounds ;
2298 }
2299
2300 wxInt32 wxWindowMac::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
2301 {
2302 #if wxOSX_USE_COCOA_OR_CARBON
2303 return eventNotHandledErr ;
2304 #else
2305 return 0;
2306 #endif
2307 }
2308
2309 bool wxWindowMac::Reparent(wxWindowBase *newParentBase)
2310 {
2311 wxWindowMac *newParent = (wxWindowMac *)newParentBase;
2312 if ( !wxWindowBase::Reparent(newParent) )
2313 return false;
2314
2315 m_peer->RemoveFromParent();
2316 m_peer->Embed( GetParent()->GetPeer() );
2317 return true;
2318 }
2319
2320 bool wxWindowMac::SetTransparent(wxByte alpha)
2321 {
2322 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
2323
2324 if ( alpha != m_macAlpha )
2325 {
2326 m_macAlpha = alpha ;
2327 Refresh() ;
2328 }
2329 return true ;
2330 }
2331
2332
2333 bool wxWindowMac::CanSetTransparent()
2334 {
2335 return true ;
2336 }
2337
2338 wxByte wxWindowMac::GetTransparent() const
2339 {
2340 return m_macAlpha ;
2341 }
2342
2343 bool wxWindowMac::IsShownOnScreen() const
2344 {
2345 if ( m_peer && m_peer->IsOk() )
2346 {
2347 bool peerVis = m_peer->IsVisible();
2348 bool wxVis = wxWindowBase::IsShownOnScreen();
2349 if( peerVis != wxVis )
2350 {
2351 // CS : put a breakpoint here to investigate differences
2352 // between native an wx visibilities
2353 // the only place where I've encountered them until now
2354 // are the hiding/showing sequences where the vis-changed event is
2355 // first sent to the innermost control, while wx does things
2356 // from the outmost control
2357 wxVis = wxWindowBase::IsShownOnScreen();
2358 return wxVis;
2359 }
2360
2361 return m_peer->IsVisible();
2362 }
2363 return wxWindowBase::IsShownOnScreen();
2364 }
2365
2366 #if wxOSX_USE_CARBON
2367 //
2368 // impl
2369 //
2370
2371
2372 // ---------------------------------------------------------------------------
2373 // Carbon Events
2374 // ---------------------------------------------------------------------------
2375
2376 static const EventTypeSpec eventList[] =
2377 {
2378 { kEventClassCommand, kEventProcessCommand } ,
2379 { kEventClassCommand, kEventCommandUpdateStatus } ,
2380
2381 { kEventClassControl , kEventControlGetClickActivation } ,
2382 { kEventClassControl , kEventControlHit } ,
2383
2384 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
2385 { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } ,
2386
2387 { kEventClassControl , kEventControlDraw } ,
2388
2389 { kEventClassControl , kEventControlVisibilityChanged } ,
2390 { kEventClassControl , kEventControlEnabledStateChanged } ,
2391 { kEventClassControl , kEventControlHiliteChanged } ,
2392
2393 { kEventClassControl , kEventControlActivate } ,
2394 { kEventClassControl , kEventControlDeactivate } ,
2395
2396 { kEventClassControl , kEventControlSetFocusPart } ,
2397 { kEventClassControl , kEventControlFocusPartChanged } ,
2398
2399 { kEventClassService , kEventServiceGetTypes },
2400 { kEventClassService , kEventServiceCopy },
2401 { kEventClassService , kEventServicePaste },
2402
2403 // { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only
2404 // { kEventClassControl , kEventControlBoundsChanged } ,
2405 } ;
2406
2407 static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
2408 {
2409 OSStatus result = eventNotHandledErr ;
2410 static wxWindowMac* targetFocusWindow = NULL;
2411 static wxWindowMac* formerFocusWindow = NULL;
2412
2413 wxMacCarbonEvent cEvent( event ) ;
2414
2415 ControlRef controlRef ;
2416 wxWindowMac* thisWindow = (wxWindowMac*) data ;
2417
2418 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
2419
2420 switch ( GetEventKind( event ) )
2421 {
2422 case kEventControlDraw :
2423 {
2424 RgnHandle updateRgn = NULL ;
2425 RgnHandle allocatedRgn = NULL ;
2426 wxRegion visRegion = thisWindow->MacGetVisibleRegion() ;
2427
2428 if ( cEvent.GetParameter<RgnHandle>(kEventParamRgnHandle, &updateRgn) != noErr )
2429 {
2430 HIShapeGetAsQDRgn( visRegion.GetWXHRGN(), updateRgn );
2431 }
2432 else
2433 {
2434 if ( thisWindow->MacGetLeftBorderSize() != 0 || thisWindow->MacGetTopBorderSize() != 0 )
2435 {
2436 // as this update region is in native window locals we must adapt it to wx window local
2437 allocatedRgn = NewRgn() ;
2438 CopyRgn( updateRgn , allocatedRgn ) ;
2439
2440 // hide the given region by the new region that must be shifted
2441 OffsetRgn( allocatedRgn , thisWindow->MacGetLeftBorderSize() , thisWindow->MacGetTopBorderSize() ) ;
2442 updateRgn = allocatedRgn ;
2443 }
2444 }
2445
2446 #if wxMAC_DEBUG_REDRAW
2447 if ( thisWindow->MacIsUserPane() )
2448 {
2449 static float color = 0.5 ;
2450 static int channel = 0 ;
2451 HIRect bounds;
2452 CGContextRef cgContext = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef) ;
2453
2454 HIViewGetBounds( controlRef, &bounds );
2455 CGContextSetRGBFillColor( cgContext, channel == 0 ? color : 0.5 ,
2456 channel == 1 ? color : 0.5 , channel == 2 ? color : 0.5 , 1 );
2457 CGContextFillRect( cgContext, bounds );
2458 color += 0.1 ;
2459 if ( color > 0.9 )
2460 {
2461 color = 0.5 ;
2462 channel++ ;
2463 if ( channel == 3 )
2464 channel = 0 ;
2465 }
2466 }
2467 #endif
2468
2469 {
2470 bool created = false ;
2471 CGContextRef cgContext = NULL ;
2472 OSStatus err = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef, &cgContext) ;
2473 if ( err != noErr )
2474 {
2475 wxFAIL_MSG("Unable to retrieve CGContextRef");
2476 }
2477
2478 thisWindow->MacSetCGContextRef( cgContext ) ;
2479
2480 {
2481 wxMacCGContextStateSaver sg( cgContext ) ;
2482 CGFloat alpha = (CGFloat)1.0 ;
2483 {
2484 wxWindow* iter = thisWindow ;
2485 while ( iter )
2486 {
2487 alpha *= (CGFloat)( iter->GetTransparent()/255.0 ) ;
2488 if ( iter->IsTopLevel() )
2489 iter = NULL ;
2490 else
2491 iter = iter->GetParent() ;
2492 }
2493 }
2494 CGContextSetAlpha( cgContext , alpha ) ;
2495
2496 if ( thisWindow->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
2497 {
2498 HIRect bounds;
2499 HIViewGetBounds( controlRef, &bounds );
2500 CGContextClearRect( cgContext, bounds );
2501 }
2502
2503
2504
2505 if ( thisWindow->MacDoRedraw( updateRgn , cEvent.GetTicks() ) )
2506 result = noErr ;
2507
2508 thisWindow->MacSetCGContextRef( NULL ) ;
2509 }
2510
2511 if ( created )
2512 CGContextRelease( cgContext ) ;
2513 }
2514
2515 if ( allocatedRgn )
2516 DisposeRgn( allocatedRgn ) ;
2517 }
2518 break ;
2519
2520 case kEventControlVisibilityChanged :
2521 // we might have two native controls attributed to the same wxWindow instance
2522 // eg a scrollview and an embedded textview, make sure we only fire for the 'outer'
2523 // control, as otherwise native and wx visibility are different
2524 if ( thisWindow->GetPeer() != NULL && thisWindow->GetPeer()->GetControlRef() == controlRef )
2525 {
2526 thisWindow->MacVisibilityChanged() ;
2527 }
2528 break ;
2529
2530 case kEventControlEnabledStateChanged :
2531 thisWindow->MacEnabledStateChanged();
2532 break ;
2533
2534 case kEventControlHiliteChanged :
2535 thisWindow->MacHiliteChanged() ;
2536 break ;
2537
2538 case kEventControlActivate :
2539 case kEventControlDeactivate :
2540 // FIXME: we should have a virtual function for this!
2541 #if wxUSE_TREECTRL
2542 if ( thisWindow->IsKindOf( CLASSINFO( wxTreeCtrl ) ) )
2543 thisWindow->Refresh();
2544 #endif
2545 #if wxUSE_LISTCTRL
2546 if ( thisWindow->IsKindOf( CLASSINFO( wxListCtrl ) ) )
2547 thisWindow->Refresh();
2548 #endif
2549 break ;
2550
2551 //
2552 // focus handling
2553 // different handling on OS X
2554 //
2555
2556 case kEventControlFocusPartChanged :
2557 // the event is emulated by wxmac for systems lower than 10.5
2558 {
2559 if ( UMAGetSystemVersion() < 0x1050 )
2560 {
2561 // as it is synthesized here, we have to manually avoid propagation
2562 result = noErr;
2563 }
2564 ControlPartCode previousControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPreviousPart , typeControlPartCode );
2565 ControlPartCode currentControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlCurrentPart , typeControlPartCode );
2566
2567 if ( thisWindow->MacGetTopLevelWindow() && thisWindow->GetPeer()->NeedsFocusRect() )
2568 {
2569 thisWindow->MacInvalidateBorders();
2570 }
2571
2572 if ( currentControlPart == 0 )
2573 {
2574 // kill focus
2575 #if wxUSE_CARET
2576 if ( thisWindow->GetCaret() )
2577 thisWindow->GetCaret()->OnKillFocus();
2578 #endif
2579
2580 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow));
2581
2582 // remove this as soon as posting the synthesized event works properly
2583 static bool inKillFocusEvent = false ;
2584
2585 if ( !inKillFocusEvent )
2586 {
2587 inKillFocusEvent = true ;
2588 wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
2589 event.SetEventObject(thisWindow);
2590 event.SetWindow(targetFocusWindow);
2591 thisWindow->HandleWindowEvent(event) ;
2592 inKillFocusEvent = false ;
2593 targetFocusWindow = NULL;
2594 }
2595 }
2596 else if ( previousControlPart == 0 )
2597 {
2598 // set focus
2599 // panel wants to track the window which was the last to have focus in it
2600 wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow));
2601 wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
2602 thisWindow->HandleWindowEvent(eventFocus);
2603
2604 #if wxUSE_CARET
2605 if ( thisWindow->GetCaret() )
2606 thisWindow->GetCaret()->OnSetFocus();
2607 #endif
2608
2609 wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
2610 event.SetEventObject(thisWindow);
2611 event.SetWindow(formerFocusWindow);
2612 thisWindow->HandleWindowEvent(event) ;
2613 formerFocusWindow = NULL;
2614 }
2615 }
2616 break;
2617 case kEventControlSetFocusPart :
2618 {
2619 Boolean focusEverything = false ;
2620 if ( cEvent.GetParameter<Boolean>(kEventParamControlFocusEverything , &focusEverything ) == noErr )
2621 {
2622 // put a breakpoint here to catch focus everything events
2623 }
2624 ControlPartCode controlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
2625 if ( controlPart != kControlFocusNoPart )
2626 {
2627 targetFocusWindow = thisWindow;
2628 wxLogTrace(_T("Focus"), _T("focus to be set(%p)"), wx_static_cast(void*, thisWindow));
2629 }
2630 else
2631 {
2632 formerFocusWindow = thisWindow;
2633 wxLogTrace(_T("Focus"), _T("focus to be lost(%p)"), wx_static_cast(void*, thisWindow));
2634 }
2635
2636 ControlPartCode previousControlPart = 0;
2637 verify_noerr( HIViewGetFocusPart(controlRef, &previousControlPart));
2638
2639 if ( thisWindow->MacIsUserPane() )
2640 {
2641 if ( controlPart != kControlFocusNoPart )
2642 cEvent.SetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, 1 ) ;
2643 result = noErr ;
2644 }
2645 else
2646 result = CallNextEventHandler(handler, event);
2647
2648 if ( UMAGetSystemVersion() < 0x1050 )
2649 {
2650 // set back to 0 if problems arise
2651 #if 1
2652 if ( result == noErr )
2653 {
2654 ControlPartCode currentControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
2655 // synthesize the event focus changed event
2656 EventRef evRef = NULL ;
2657
2658 OSStatus err = MacCreateEvent(
2659 NULL , kEventClassControl , kEventControlFocusPartChanged , TicksToEventTime( TickCount() ) ,
2660 kEventAttributeUserEvent , &evRef );
2661 verify_noerr( err );
2662
2663 wxMacCarbonEvent iEvent( evRef ) ;
2664 iEvent.SetParameter<ControlRef>( kEventParamDirectObject , controlRef );
2665 iEvent.SetParameter<EventTargetRef>( kEventParamPostTarget, typeEventTargetRef, GetControlEventTarget( controlRef ) );
2666 iEvent.SetParameter<ControlPartCode>( kEventParamControlPreviousPart, typeControlPartCode, previousControlPart );
2667 iEvent.SetParameter<ControlPartCode>( kEventParamControlCurrentPart, typeControlPartCode, currentControlPart );
2668
2669 #if 1
2670 // TODO test this first, avoid double posts etc...
2671 PostEventToQueue( GetMainEventQueue(), evRef , kEventPriorityHigh );
2672 #else
2673 wxMacWindowControlEventHandler( NULL , evRef , data ) ;
2674 #endif
2675 ReleaseEvent( evRef ) ;
2676 }
2677 #else
2678 // old implementation, to be removed if the new one works
2679 if ( controlPart == kControlFocusNoPart )
2680 {
2681 #if wxUSE_CARET
2682 if ( thisWindow->GetCaret() )
2683 thisWindow->GetCaret()->OnKillFocus();
2684 #endif
2685
2686 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow));
2687
2688 static bool inKillFocusEvent = false ;
2689
2690 if ( !inKillFocusEvent )
2691 {
2692 inKillFocusEvent = true ;
2693 wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
2694 event.SetEventObject(thisWindow);
2695 thisWindow->HandleWindowEvent(event) ;
2696 inKillFocusEvent = false ;
2697 }
2698 }
2699 else
2700 {
2701 // panel wants to track the window which was the last to have focus in it
2702 wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow));
2703 wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
2704 thisWindow->HandleWindowEvent(eventFocus);
2705
2706 #if wxUSE_CARET
2707 if ( thisWindow->GetCaret() )
2708 thisWindow->GetCaret()->OnSetFocus();
2709 #endif
2710
2711 wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
2712 event.SetEventObject(thisWindow);
2713 thisWindow->HandleWindowEvent(event) ;
2714 }
2715 #endif
2716 }
2717 }
2718 break ;
2719
2720 case kEventControlHit :
2721 result = thisWindow->MacControlHit( handler , event ) ;
2722 break ;
2723
2724 case kEventControlGetClickActivation :
2725 {
2726 // fix to always have a proper activation for DataBrowser controls (stay in bkgnd otherwise)
2727 WindowRef owner = cEvent.GetParameter<WindowRef>(kEventParamWindowRef);
2728 if ( !IsWindowActive(owner) )
2729 {
2730 cEvent.SetParameter(kEventParamClickActivation,typeClickActivationResult, (UInt32) kActivateAndIgnoreClick) ;
2731 result = noErr ;
2732 }
2733 }
2734 break ;
2735
2736 default :
2737 break ;
2738 }
2739
2740 return result ;
2741 }
2742
2743 static pascal OSStatus
2744 wxMacWindowServiceEventHandler(EventHandlerCallRef WXUNUSED(handler),
2745 EventRef event,
2746 void *data)
2747 {
2748 OSStatus result = eventNotHandledErr ;
2749
2750 wxMacCarbonEvent cEvent( event ) ;
2751
2752 ControlRef controlRef ;
2753 wxWindowMac* thisWindow = (wxWindowMac*) data ;
2754 wxTextCtrl* textCtrl = wxDynamicCast( thisWindow , wxTextCtrl ) ;
2755 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
2756
2757 switch ( GetEventKind( event ) )
2758 {
2759 case kEventServiceGetTypes :
2760 if ( textCtrl )
2761 {
2762 long from, to ;
2763 textCtrl->GetSelection( &from , &to ) ;
2764
2765 CFMutableArrayRef copyTypes = 0 , pasteTypes = 0;
2766 if ( from != to )
2767 copyTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServiceCopyTypes , typeCFMutableArrayRef ) ;
2768 if ( textCtrl->IsEditable() )
2769 pasteTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServicePasteTypes , typeCFMutableArrayRef ) ;
2770
2771 static const OSType textDataTypes[] = { kTXNTextData /* , 'utxt', 'PICT', 'MooV', 'AIFF' */ };
2772 for ( size_t i = 0 ; i < WXSIZEOF(textDataTypes) ; ++i )
2773 {
2774 CFStringRef typestring = CreateTypeStringWithOSType(textDataTypes[i]);
2775 if ( typestring )
2776 {
2777 if ( copyTypes )
2778 CFArrayAppendValue(copyTypes, typestring) ;
2779 if ( pasteTypes )
2780 CFArrayAppendValue(pasteTypes, typestring) ;
2781
2782 CFRelease( typestring ) ;
2783 }
2784 }
2785
2786 result = noErr ;
2787 }
2788 break ;
2789
2790 case kEventServiceCopy :
2791 if ( textCtrl )
2792 {
2793 long from, to ;
2794
2795 textCtrl->GetSelection( &from , &to ) ;
2796 wxString val = textCtrl->GetValue() ;
2797 val = val.Mid( from , to - from ) ;
2798 PasteboardRef pasteboard = cEvent.GetParameter<PasteboardRef>( kEventParamPasteboardRef, typePasteboardRef );
2799 verify_noerr( PasteboardClear( pasteboard ) ) ;
2800 PasteboardSynchronize( pasteboard );
2801 // TODO add proper conversion
2802 CFDataRef data = CFDataCreate( kCFAllocatorDefault, (const UInt8*)val.c_str(), val.length() );
2803 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) 1, CFSTR("com.apple.traditional-mac-plain-text"), data, 0);
2804 CFRelease( data );
2805 result = noErr ;
2806 }
2807 break ;
2808
2809 case kEventServicePaste :
2810 if ( textCtrl )
2811 {
2812 PasteboardRef pasteboard = cEvent.GetParameter<PasteboardRef>( kEventParamPasteboardRef, typePasteboardRef );
2813 PasteboardSynchronize( pasteboard );
2814 ItemCount itemCount;
2815 verify_noerr( PasteboardGetItemCount( pasteboard, &itemCount ) );
2816 for( UInt32 itemIndex = 1; itemIndex <= itemCount; itemIndex++ )
2817 {
2818 PasteboardItemID itemID;
2819 if ( PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID ) == noErr )
2820 {
2821 CFDataRef flavorData = NULL;
2822 if ( PasteboardCopyItemFlavorData( pasteboard, itemID, CFSTR("com.apple.traditional-mac-plain-text"), &flavorData ) == noErr )
2823 {
2824 CFIndex flavorDataSize = CFDataGetLength( flavorData );
2825 char *content = new char[flavorDataSize+1] ;
2826 memcpy( content, CFDataGetBytePtr( flavorData ), flavorDataSize );
2827 content[flavorDataSize]=0;
2828 CFRelease( flavorData );
2829 #if wxUSE_UNICODE
2830 textCtrl->WriteText( wxString( content , wxConvLocal ) );
2831 #else
2832 textCtrl->WriteText( wxString( content ) ) ;
2833 #endif
2834
2835 delete[] content ;
2836 result = noErr ;
2837 }
2838 }
2839 }
2840 }
2841 break ;
2842
2843 default:
2844 break ;
2845 }
2846
2847 return result ;
2848 }
2849
2850 pascal OSStatus wxMacUnicodeTextEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
2851 {
2852 OSStatus result = eventNotHandledErr ;
2853 wxWindowMac* focus = (wxWindowMac*) data ;
2854
2855 wchar_t* uniChars = NULL ;
2856 UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
2857
2858 UniChar* charBuf = NULL;
2859 ByteCount dataSize = 0 ;
2860 int numChars = 0 ;
2861 UniChar buf[2] ;
2862 if ( GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr )
2863 {
2864 numChars = dataSize / sizeof( UniChar) + 1;
2865 charBuf = buf ;
2866
2867 if ( (size_t) numChars * 2 > sizeof(buf) )
2868 charBuf = new UniChar[ numChars ] ;
2869 else
2870 charBuf = buf ;
2871
2872 uniChars = new wchar_t[ numChars ] ;
2873 GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ;
2874 charBuf[ numChars - 1 ] = 0;
2875 #if SIZEOF_WCHAR_T == 2
2876 uniChars = (wchar_t*) charBuf ;
2877 /* memcpy( uniChars , charBuf , numChars * 2 ) ;*/ // is there any point in copying charBuf over itself? (in fact, memcpy isn't even guaranteed to work correctly if the source and destination ranges overlap...)
2878 #else
2879 // the resulting string will never have more chars than the utf16 version, so this is safe
2880 wxMBConvUTF16 converter ;
2881 numChars = converter.MB2WC( uniChars , (const char*)charBuf , numChars ) ;
2882 #endif
2883 }
2884
2885 switch ( GetEventKind( event ) )
2886 {
2887 case kEventTextInputUpdateActiveInputArea :
2888 {
2889 // An IME input event may return several characters, but we need to send one char at a time to
2890 // EVT_CHAR
2891 for (int pos=0 ; pos < numChars ; pos++)
2892 {
2893 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
2894 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
2895 wxTheApp->MacSetCurrentEvent( event , handler ) ;
2896
2897 UInt32 message = uniChars[pos] < 128 ? (char)uniChars[pos] : '?';
2898 /*
2899 NB: faking a charcode here is problematic. The kEventTextInputUpdateActiveInputArea event is sent
2900 multiple times to update the active range during inline input, so this handler will often receive
2901 uncommited text, which should usually not trigger side effects. It might be a good idea to check the
2902 kEventParamTextInputSendFixLen parameter and verify if input is being confirmed (see CarbonEvents.h).
2903 On the other hand, it can be useful for some applications to react to uncommitted text (for example,
2904 to update a status display), as long as it does not disrupt the inline input session. Ideally, wx
2905 should add new event types to support advanced text input. For now, I would keep things as they are.
2906
2907 However, the code that was being used caused additional problems:
2908 UInt32 message = (0 << 8) + ((char)uniChars[pos] );
2909 Since it simply truncated the unichar to the last byte, it ended up causing weird bugs with inline
2910 input, such as switching to another field when one attempted to insert the character U+4E09 (the kanji
2911 for "three"), because it was truncated to 09 (kTabCharCode), which was later "converted" to WXK_TAB
2912 (still 09) in wxMacTranslateKey; or triggering the default button when one attempted to insert U+840D
2913 (the kanji for "name"), which got truncated to 0D and interpreted as a carriage return keypress.
2914 Note that even single-byte characters could have been misinterpreted, since MacRoman charcodes only
2915 overlap with Unicode within the (7-bit) ASCII range.
2916 But simply passing a NUL charcode would disable text updated events, because wxTextCtrl::OnChar checks
2917 for codes within a specific range. Therefore I went for the solution seen above, which keeps ASCII
2918 characters as they are and replaces the rest with '?', ensuring that update events are triggered.
2919 It would be better to change wxTextCtrl::OnChar to look at the actual unicode character instead, but
2920 I don't have time to look into that right now.
2921 -- CL
2922 */
2923 if ( wxTheApp->MacSendCharEvent(
2924 focus , message , 0 , when , 0 , 0 , uniChars[pos] ) )
2925 {
2926 result = noErr ;
2927 }
2928
2929 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
2930 }
2931 }
2932 break ;
2933 case kEventTextInputUnicodeForKeyEvent :
2934 {
2935 UInt32 keyCode, modifiers ;
2936 Point point ;
2937 EventRef rawEvent ;
2938 unsigned char charCode ;
2939
2940 GetEventParameter( event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent ) ;
2941 GetEventParameter( rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
2942 GetEventParameter( rawEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
2943 GetEventParameter( rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
2944 GetEventParameter( rawEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
2945
2946 UInt32 message = (keyCode << 8) + charCode;
2947
2948 // An IME input event may return several characters, but we need to send one char at a time to
2949 // EVT_CHAR
2950 for (int pos=0 ; pos < numChars ; pos++)
2951 {
2952 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
2953 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
2954 wxTheApp->MacSetCurrentEvent( event , handler ) ;
2955
2956 if ( wxTheApp->MacSendCharEvent(
2957 focus , message , modifiers , when , point.h , point.v , uniChars[pos] ) )
2958 {
2959 result = noErr ;
2960 }
2961
2962 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
2963 }
2964 }
2965 break;
2966 default:
2967 break ;
2968 }
2969
2970 delete [] uniChars ;
2971 if ( charBuf != buf )
2972 delete [] charBuf ;
2973
2974 return result ;
2975 }
2976
2977 static pascal OSStatus
2978 wxMacWindowCommandEventHandler(EventHandlerCallRef WXUNUSED(handler),
2979 EventRef event,
2980 void *data)
2981 {
2982 OSStatus result = eventNotHandledErr ;
2983 wxWindowMac* focus = (wxWindowMac*) data ;
2984
2985 HICommand command ;
2986
2987 wxMacCarbonEvent cEvent( event ) ;
2988 cEvent.GetParameter<HICommand>(kEventParamDirectObject,typeHICommand,&command) ;
2989
2990 wxMenuItem* item = NULL ;
2991 wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ;
2992 int id = wxMacCommandToId( command.commandID ) ;
2993
2994 if ( item )
2995 {
2996 wxASSERT( itemMenu != NULL ) ;
2997
2998 switch ( cEvent.GetKind() )
2999 {
3000 case kEventProcessCommand :
3001 result = itemMenu->MacHandleCommandProcess( item, id, focus );
3002 break ;
3003
3004 case kEventCommandUpdateStatus:
3005 result = itemMenu->MacHandleCommandUpdateStatus( item, id, focus );
3006 break ;
3007
3008 default :
3009 break ;
3010 }
3011 }
3012 return result ;
3013 }
3014
3015 pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
3016 {
3017 EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
3018 EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ;
3019 wxTheApp->MacSetCurrentEvent( event , handler ) ;
3020 OSStatus result = eventNotHandledErr ;
3021
3022 switch ( GetEventClass( event ) )
3023 {
3024 case kEventClassCommand :
3025 result = wxMacWindowCommandEventHandler( handler , event , data ) ;
3026 break ;
3027
3028 case kEventClassControl :
3029 result = wxMacWindowControlEventHandler( handler, event, data ) ;
3030 break ;
3031
3032 case kEventClassService :
3033 result = wxMacWindowServiceEventHandler( handler, event , data ) ;
3034 break ;
3035
3036 case kEventClassTextInput :
3037 result = wxMacUnicodeTextEventHandler( handler , event , data ) ;
3038 break ;
3039
3040 default :
3041 break ;
3042 }
3043
3044 wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ;
3045
3046 return result ;
3047 }
3048
3049 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler )
3050
3051 // ---------------------------------------------------------------------------
3052 // Scrollbar Tracking for all
3053 // ---------------------------------------------------------------------------
3054
3055 pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode ) ;
3056 pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode )
3057 {
3058 if ( partCode != 0)
3059 {
3060 wxWindow* wx = wxFindWindowFromWXWidget( (WXWidget) control ) ;
3061 if ( wx )
3062 wx->MacHandleControlClick( (WXWidget) control , partCode , true /* stillDown */ ) ;
3063 }
3064 }
3065 wxMAC_DEFINE_PROC_GETTER( ControlActionUPP , wxMacLiveScrollbarActionProc ) ;
3066
3067 wxWidgetImpl* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, const wxPoint& pos, const wxSize& size,
3068 long style, long extraStyle, const wxString& name)
3069 {
3070 OSStatus err = noErr;
3071 Rect bounds = wxMacGetBoundsForControl( wxpeer , pos , size ) ;
3072 wxMacControl* c = new wxMacControl(wxpeer) ;
3073 UInt32 features = 0
3074 | kControlSupportsEmbedding
3075 | kControlSupportsLiveFeedback
3076 | kControlGetsFocusOnClick
3077 // | kControlHasSpecialBackground
3078 // | kControlSupportsCalcBestRect
3079 | kControlHandlesTracking
3080 | kControlSupportsFocus
3081 | kControlWantsActivate
3082 | kControlWantsIdle ;
3083
3084 err =::CreateUserPaneControl( MAC_WXHWND(wxpeer->GetParent()->MacGetTopLevelWindowRef()) , &bounds, features , c->GetControlRefAddr() );
3085 verify_noerr( err );
3086 return c;
3087 }
3088
3089
3090 void wxMacControl::MacInstallEventHandler( ControlRef control, wxWindowMac* wxPeer )
3091 {
3092 wxAssociateWindowWithWXWidget( (WXWidget) control , wxPeer ) ;
3093 ::InstallControlEventHandler( control , GetwxMacWindowEventHandlerUPP(),
3094 GetEventTypeCount(eventList), eventList, wxPeer, NULL);
3095 }
3096
3097 IMPLEMENT_DYNAMIC_CLASS( wxMacControl , wxWidgetImpl )
3098
3099 wxMacControl::wxMacControl()
3100 {
3101 Init();
3102 }
3103
3104 wxMacControl::wxMacControl(wxWindowMac* peer , bool isRootControl ) :
3105 wxWidgetImpl( peer, isRootControl )
3106 {
3107 Init();
3108 }
3109
3110 wxMacControl::~wxMacControl()
3111 {
3112 }
3113
3114 void wxMacControl::Init()
3115 {
3116 m_controlRef = NULL;
3117 m_macControlEventHandler = NULL;
3118 }
3119
3120 void wxMacControl::Destroy()
3121 {
3122 wxASSERT_MSG( m_controlRef != NULL , wxT("Control Handle already NULL, Dispose called twice ?") );
3123 wxASSERT_MSG( IsValidControlHandle(m_controlRef) , wxT("Invalid Control Handle (maybe already released) in Dispose") );
3124
3125 wxRemoveWXWidgetAssociation( m_wxPeer) ;
3126 // we cannot check the ref count here anymore, as autorelease objects might delete their refs later
3127 // we can have situations when being embedded, where the control gets deleted behind our back, so only
3128 // CFRelease if we are safe
3129 if ( IsValidControlHandle(m_controlRef) )
3130 CFRelease(m_controlRef);
3131 m_controlRef = NULL;
3132 }
3133
3134 void wxMacControl::SetReference( URefCon data )
3135 {
3136 SetControlReference( m_controlRef , data );
3137 }
3138
3139 void wxMacControl::RemoveFromParent()
3140 {
3141 // nothing to do here for carbon
3142 }
3143
3144 void wxMacControl::Embed( wxWidgetImpl *parent )
3145 {
3146 // copied from MacPostControlCreate
3147 ControlRef container = (ControlRef) parent->GetWXWidget() ;
3148 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
3149 ::EmbedControl( m_controlRef , container ) ;
3150 }
3151
3152 void wxMacControl::SetNeedsDisplay( const wxRect* rect )
3153 {
3154 if ( !IsVisible() )
3155 return;
3156
3157 if ( rect != NULL )
3158 {
3159 HIRect updatearea = CGRectMake( rect->x , rect->y , rect->width , rect->height);
3160 HIViewSetNeedsDisplayInRect( m_controlRef, &updatearea, true );
3161 }
3162 else
3163 HIViewSetNeedsDisplay( m_controlRef , true );
3164 }
3165
3166 void wxMacControl::Raise()
3167 {
3168 verify_noerr( HIViewSetZOrder( m_controlRef, kHIViewZOrderAbove, NULL ) );
3169 }
3170
3171 void wxMacControl::Lower()
3172 {
3173 verify_noerr( HIViewSetZOrder( m_controlRef, kHIViewZOrderBelow, NULL ) );
3174 }
3175
3176 void wxMacControl::GetContentArea(int &left , int &top , int &width , int &height) const
3177 {
3178 RgnHandle rgn = NewRgn() ;
3179 Rect content ;
3180 if ( GetControlRegion( m_controlRef, kControlContentMetaPart , rgn ) == noErr )
3181 GetRegionBounds( rgn , &content ) ;
3182 else
3183 GetControlBounds( m_controlRef , &content );
3184 DisposeRgn( rgn ) ;
3185
3186 left = content.left;
3187 top = content.top;
3188
3189 width = content.right - content.left ;
3190 height = content.bottom - content.top ;
3191 }
3192
3193 void wxMacControl::Move(int x, int y, int width, int height)
3194 {
3195 HIRect hir = CGRectMake(x,y,width,height);
3196 HIViewSetFrame ( m_controlRef , &hir );
3197 }
3198
3199 void wxMacControl::GetPosition( int &x, int &y ) const
3200 {
3201 Rect r;
3202 GetControlBounds( m_controlRef , &r );
3203 x = r.left;
3204 y = r.top;
3205 }
3206
3207 void wxMacControl::GetSize( int &width, int &height ) const
3208 {
3209 Rect r;
3210 GetControlBounds( m_controlRef , &r );
3211 width = r.right - r.left;
3212 height = r.bottom - r.top;
3213 }
3214
3215 void wxMacControl::ScrollRect( const wxRect *rect, int dx, int dy )
3216 {
3217 if (GetNeedsDisplay() )
3218 {
3219 // because HIViewScrollRect does not scroll the already invalidated area we have two options:
3220 // in case there is already a pending redraw on that area
3221 // either immediate redraw or full invalidate
3222 #if 1
3223 // is the better overall solution, as it does not slow down scrolling
3224 SetNeedsDisplay() ;
3225 #else
3226 // this would be the preferred version for fast drawing controls
3227 HIViewRender(GetControlRef()) ;
3228 #endif
3229 }
3230
3231 // note there currently is a bug in OSX (10.3 +?) which makes inefficient refreshes in case an entire control
3232 // area is scrolled, this does not occur if width and height are 2 pixels less,
3233 // TODO: write optimal workaround
3234
3235 HIRect scrollarea = CGRectMake( rect->x , rect->y , rect->width , rect->height);
3236 HIViewScrollRect ( m_controlRef , &scrollarea , dx ,dy );
3237
3238 #if 0
3239 // this would be the preferred version for fast drawing controls
3240 HIViewRender(GetControlRef()) ;
3241 #endif
3242 }
3243
3244 bool wxMacControl::CanFocus() const
3245 {
3246 // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so
3247 // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning,
3248 // but the value range is nowhere documented
3249 Boolean keyExistsAndHasValidFormat ;
3250 CFIndex fullKeyboardAccess = CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) ,
3251 kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat );
3252
3253 if ( keyExistsAndHasValidFormat && fullKeyboardAccess > 0 )
3254 {
3255 return true ;
3256 }
3257 else
3258 {
3259 UInt32 features = 0 ;
3260 GetControlFeatures( m_controlRef, &features ) ;
3261
3262 return features & ( kControlSupportsFocus | kControlGetsFocusOnClick ) ;
3263 }
3264 }
3265
3266 bool wxMacControl::GetNeedsDisplay() const
3267 {
3268 return HIViewGetNeedsDisplay( m_controlRef );
3269 }
3270
3271 void wxWidgetImpl::Convert( wxPoint *pt , wxWidgetImpl *from , wxWidgetImpl *to )
3272 {
3273 HIPoint hiPoint;
3274
3275 hiPoint.x = pt->x;
3276 hiPoint.y = pt->y;
3277 HIViewConvertPoint( &hiPoint , (ControlRef) from->GetWXWidget() , (ControlRef) to->GetWXWidget() );
3278 pt->x = (int)hiPoint.x;
3279 pt->y = (int)hiPoint.y;
3280 }
3281
3282 bool wxMacControl::SetFocus()
3283 {
3284 // as we cannot rely on the control features to find out whether we are in full keyboard mode,
3285 // we can only leave in case of an error
3286
3287 OSStatus err = SetKeyboardFocus( GetControlOwner( m_controlRef ), m_controlRef, kControlFocusNextPart );
3288 if ( err == errCouldntSetFocus )
3289 return false ;
3290 SetUserFocusWindow(GetControlOwner( m_controlRef ) );
3291
3292 return true;
3293 }
3294
3295 bool wxMacControl::HasFocus() const
3296 {
3297 ControlRef control;
3298 GetKeyboardFocus( GetUserFocusWindow() , &control );
3299 return control == m_controlRef;
3300 }
3301
3302 //
3303 // subclass specifics
3304 //
3305
3306 OSStatus wxMacControl::GetData(ControlPartCode inPartCode , ResType inTag , Size inBufferSize , void * inOutBuffer , Size * outActualSize ) const
3307 {
3308 return ::GetControlData( m_controlRef , inPartCode , inTag , inBufferSize , inOutBuffer , outActualSize );
3309 }
3310
3311 OSStatus wxMacControl::GetDataSize(ControlPartCode inPartCode , ResType inTag , Size * outActualSize ) const
3312 {
3313 return ::GetControlDataSize( m_controlRef , inPartCode , inTag , outActualSize );
3314 }
3315
3316 OSStatus wxMacControl::SetData(ControlPartCode inPartCode , ResType inTag , Size inSize , const void * inData)
3317 {
3318 return ::SetControlData( m_controlRef , inPartCode , inTag , inSize , inData );
3319 }
3320
3321 OSStatus wxMacControl::SendEvent( EventRef event , OptionBits inOptions )
3322 {
3323 return SendEventToEventTargetWithOptions( event,
3324 HIObjectGetEventTarget( (HIObjectRef) m_controlRef ), inOptions );
3325 }
3326
3327 OSStatus wxMacControl::SendHICommand( HICommand &command , OptionBits inOptions )
3328 {
3329 wxMacCarbonEvent event( kEventClassCommand , kEventCommandProcess );
3330
3331 event.SetParameter<HICommand>(kEventParamDirectObject,command);
3332
3333 return SendEvent( event , inOptions );
3334 }
3335
3336 OSStatus wxMacControl::SendHICommand( UInt32 commandID , OptionBits inOptions )
3337 {
3338 HICommand command;
3339
3340 memset( &command, 0 , sizeof(command) );
3341 command.commandID = commandID;
3342 return SendHICommand( command , inOptions );
3343 }
3344
3345 void wxMacControl::Flash( ControlPartCode part , UInt32 ticks )
3346 {
3347 unsigned long finalTicks;
3348
3349 HiliteControl( m_controlRef , part );
3350 Delay( ticks , &finalTicks );
3351 HiliteControl( m_controlRef , kControlNoPart );
3352 }
3353
3354 SInt32 wxMacControl::GetValue() const
3355 {
3356 return ::GetControl32BitValue( m_controlRef );
3357 }
3358
3359 SInt32 wxMacControl::GetMaximum() const
3360 {
3361 return ::GetControl32BitMaximum( m_controlRef );
3362 }
3363
3364 SInt32 wxMacControl::GetMinimum() const
3365 {
3366 return ::GetControl32BitMinimum( m_controlRef );
3367 }
3368
3369 void wxMacControl::SetValue( SInt32 v )
3370 {
3371 ::SetControl32BitValue( m_controlRef , v );
3372 }
3373
3374 void wxMacControl::SetMinimum( SInt32 v )
3375 {
3376 ::SetControl32BitMinimum( m_controlRef , v );
3377 }
3378
3379 void wxMacControl::SetMaximum( SInt32 v )
3380 {
3381 ::SetControl32BitMaximum( m_controlRef , v );
3382 }
3383
3384 void wxMacControl::SetValueAndRange( SInt32 value , SInt32 minimum , SInt32 maximum )
3385 {
3386 ::SetControl32BitMinimum( m_controlRef , minimum );
3387 ::SetControl32BitMaximum( m_controlRef , maximum );
3388 ::SetControl32BitValue( m_controlRef , value );
3389 }
3390
3391 void wxMacControl::VisibilityChanged(bool WXUNUSED(shown))
3392 {
3393 }
3394
3395 void wxMacControl::SuperChangedPosition()
3396 {
3397 }
3398
3399 void wxMacControl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle )
3400 {
3401 m_font = font;
3402 #if wxOSX_USE_CORE_TEXT
3403 if ( UMAGetSystemVersion() >= 0x1050 )
3404 {
3405 HIViewPartCode part = 0;
3406 HIThemeTextHorizontalFlush flush = kHIThemeTextHorizontalFlushDefault;
3407 if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_CENTER_HORIZONTAL )
3408 flush = kHIThemeTextHorizontalFlushCenter;
3409 else if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_RIGHT )
3410 flush = kHIThemeTextHorizontalFlushRight;
3411 HIViewSetTextFont( m_controlRef , part , (CTFontRef) font.MacGetCTFont() );
3412 HIViewSetTextHorizontalFlush( m_controlRef, part, flush );
3413
3414 if ( foreground != *wxBLACK )
3415 {
3416 ControlFontStyleRec fontStyle;
3417 foreground.GetRGBColor( &fontStyle.foreColor );
3418 fontStyle.flags = kControlUseForeColorMask;
3419 ::SetControlFontStyle( m_controlRef , &fontStyle );
3420 }
3421 }
3422 #endif
3423 #if wxOSX_USE_ATSU_TEXT
3424 ControlFontStyleRec fontStyle;
3425 if ( font.MacGetThemeFontID() != kThemeCurrentPortFont )
3426 {
3427 switch ( font.MacGetThemeFontID() )
3428 {
3429 case kThemeSmallSystemFont :
3430 fontStyle.font = kControlFontSmallSystemFont;
3431 break;
3432
3433 case 109 : // mini font
3434 fontStyle.font = -5;
3435 break;
3436
3437 case kThemeSystemFont :
3438 fontStyle.font = kControlFontBigSystemFont;
3439 break;
3440
3441 default :
3442 fontStyle.font = kControlFontBigSystemFont;
3443 break;
3444 }
3445
3446 fontStyle.flags = kControlUseFontMask;
3447 }
3448 else
3449 {
3450 fontStyle.font = font.MacGetFontNum();
3451 fontStyle.style = font.MacGetFontStyle();
3452 fontStyle.size = font.MacGetFontSize();
3453 fontStyle.flags = kControlUseFontMask | kControlUseFaceMask | kControlUseSizeMask;
3454 }
3455
3456 fontStyle.just = teJustLeft;
3457 fontStyle.flags |= kControlUseJustMask;
3458 if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_CENTER_HORIZONTAL )
3459 fontStyle.just = teJustCenter;
3460 else if ( ( windowStyle & wxALIGN_MASK ) & wxALIGN_RIGHT )
3461 fontStyle.just = teJustRight;
3462
3463
3464 // we only should do this in case of a non-standard color, as otherwise 'disabled' controls
3465 // won't get grayed out by the system anymore
3466
3467 if ( foreground != *wxBLACK )
3468 {
3469 foreground.GetRGBColor( &fontStyle.foreColor );
3470 fontStyle.flags |= kControlUseForeColorMask;
3471 }
3472
3473 ::SetControlFontStyle( m_controlRef , &fontStyle );
3474 #endif
3475 }
3476
3477 void wxMacControl::SetBackgroundColour( const wxColour &WXUNUSED(col) )
3478 {
3479 // HITextViewSetBackgroundColor( m_textView , color );
3480 }
3481
3482 void wxMacControl::SetRange( SInt32 minimum , SInt32 maximum )
3483 {
3484 ::SetControl32BitMinimum( m_controlRef , minimum );
3485 ::SetControl32BitMaximum( m_controlRef , maximum );
3486 }
3487
3488 short wxMacControl::HandleKey( SInt16 keyCode, SInt16 charCode, EventModifiers modifiers )
3489 {
3490 return HandleControlKey( m_controlRef , keyCode , charCode , modifiers );
3491 }
3492
3493 void wxMacControl::SetActionProc( ControlActionUPP actionProc )
3494 {
3495 SetControlAction( m_controlRef , actionProc );
3496 }
3497
3498 void wxMacControl::SetViewSize( SInt32 viewSize )
3499 {
3500 SetControlViewSize(m_controlRef , viewSize );
3501 }
3502
3503 SInt32 wxMacControl::GetViewSize() const
3504 {
3505 return GetControlViewSize( m_controlRef );
3506 }
3507
3508 bool wxMacControl::IsVisible() const
3509 {
3510 return IsControlVisible( m_controlRef );
3511 }
3512
3513 void wxMacControl::SetVisibility( bool visible )
3514 {
3515 SetControlVisibility( m_controlRef , visible, true );
3516 }
3517
3518 bool wxMacControl::IsEnabled() const
3519 {
3520 return IsControlEnabled( m_controlRef );
3521 }
3522
3523 bool wxMacControl::IsActive() const
3524 {
3525 return IsControlActive( m_controlRef );
3526 }
3527
3528 void wxMacControl::Enable( bool enable )
3529 {
3530 if ( enable )
3531 EnableControl( m_controlRef );
3532 else
3533 DisableControl( m_controlRef );
3534 }
3535
3536 void wxMacControl::SetDrawingEnabled( bool enable )
3537 {
3538 HIViewSetDrawingEnabled( m_controlRef , enable );
3539 }
3540
3541 void wxMacControl::GetRectInWindowCoords( Rect *r )
3542 {
3543 GetControlBounds( m_controlRef , r ) ;
3544
3545 WindowRef tlwref = GetControlOwner( m_controlRef ) ;
3546
3547 wxNonOwnedWindow* tlwwx = wxNonOwnedWindow::GetFromWXWindow( (WXWindow) tlwref ) ;
3548 if ( tlwwx != NULL )
3549 {
3550 ControlRef rootControl = tlwwx->GetPeer()->GetControlRef() ;
3551 HIPoint hiPoint = CGPointMake( 0 , 0 ) ;
3552 HIViewConvertPoint( &hiPoint , HIViewGetSuperview(m_controlRef) , rootControl ) ;
3553 OffsetRect( r , (short) hiPoint.x , (short) hiPoint.y ) ;
3554 }
3555 }
3556
3557 void wxMacControl::GetBestRect( Rect *r )
3558 {
3559 short baselineoffset;
3560
3561 GetBestControlRect( m_controlRef , r , &baselineoffset );
3562 }
3563
3564 void wxMacControl::SetLabel( const wxString &title )
3565 {
3566 wxFontEncoding encoding;
3567
3568 if ( m_font.Ok() )
3569 encoding = m_font.GetEncoding();
3570 else
3571 encoding = wxFont::GetDefaultEncoding();
3572
3573 SetControlTitleWithCFString( m_controlRef , wxCFStringRef( title , encoding ) );
3574 }
3575
3576 void wxMacControl::GetFeatures( UInt32 * features )
3577 {
3578 GetControlFeatures( m_controlRef , features );
3579 }
3580
3581 OSStatus wxMacControl::GetRegion( ControlPartCode partCode , RgnHandle region )
3582 {
3583 OSStatus err = GetControlRegion( m_controlRef , partCode , region );
3584 return err;
3585 }
3586
3587 // SetNeedsDisplay would not invalidate the children
3588 static void InvalidateControlAndChildren( HIViewRef control )
3589 {
3590 HIViewSetNeedsDisplay( control , true );
3591 UInt16 childrenCount = 0;
3592 OSStatus err = CountSubControls( control , &childrenCount );
3593 if ( err == errControlIsNotEmbedder )
3594 return;
3595
3596 wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") );
3597
3598 for ( UInt16 i = childrenCount; i >=1; --i )
3599 {
3600 HIViewRef child;
3601
3602 err = GetIndexedSubControl( control , i , & child );
3603 if ( err == errControlIsNotEmbedder )
3604 return;
3605
3606 InvalidateControlAndChildren( child );
3607 }
3608 }
3609
3610 void wxMacControl::InvalidateWithChildren()
3611 {
3612 InvalidateControlAndChildren( m_controlRef );
3613 }
3614
3615 OSType wxMacCreator = 'WXMC';
3616 OSType wxMacControlProperty = 'MCCT';
3617
3618 void wxMacControl::SetReferenceInNativeControl()
3619 {
3620 void * data = this;
3621 verify_noerr( SetControlProperty ( m_controlRef ,
3622 wxMacCreator,wxMacControlProperty, sizeof(data), &data ) );
3623 }
3624
3625 wxMacControl* wxMacControl::GetReferenceFromNativeControl(ControlRef control)
3626 {
3627 wxMacControl* ctl = NULL;
3628 ByteCount actualSize;
3629 if ( GetControlProperty( control ,wxMacCreator,wxMacControlProperty, sizeof(ctl) ,
3630 &actualSize , &ctl ) == noErr )
3631 {
3632 return ctl;
3633 }
3634 return NULL;
3635 }
3636
3637
3638 //
3639 // Tab Control
3640 //
3641
3642 OSStatus wxMacControl::SetTabEnabled( SInt16 tabNo , bool enable )
3643 {
3644 return ::SetTabEnabled( m_controlRef , tabNo , enable );
3645 }
3646
3647
3648
3649 // Control Factory
3650
3651 wxWidgetImpl* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now )
3652 {
3653 // There is a bug in 10.2.X for ::GetRootControl returning the window view instead of
3654 // the content view, so we have to retrieve it explicitly
3655
3656 wxMacControl* contentview = new wxMacControl(now , true /*isRootControl*/);
3657 HIViewFindByID( HIViewGetRoot( (WindowRef) now->GetWXWindow() ) , kHIViewWindowContentID ,
3658 contentview->GetControlRefAddr() ) ;
3659 if ( !contentview->IsOk() )
3660 {
3661 // compatibility mode fallback
3662 GetRootControl( (WindowRef) now->GetWXWindow() , contentview->GetControlRefAddr() ) ;
3663 }
3664
3665 // the root control level handler
3666 contentview->InstallEventHandler() ;
3667 return contentview;
3668 }
3669
3670 #endif // wxOSX_USE_CARBON