1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/window.cpp
3 // Purpose: wxWindowMac
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
14 #include "wx/window.h"
23 #include "wx/dcclient.h"
24 #include "wx/button.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"
40 #include "wx/tooltip.h"
41 #include "wx/spinctrl.h"
42 #include "wx/geometry.h"
45 #include "wx/listctrl.h"
49 #include "wx/treectrl.h"
57 #include "wx/popupwin.h"
60 #if wxUSE_DRAG_AND_DROP
65 #include "wx/osx/uma.h"
67 #include "wx/osx/private.h"
70 #define MAC_SCROLLBAR_SIZE 15
71 #define MAC_SMALL_SCROLLBAR_SIZE 11
75 #ifdef __WXUNIVERSAL__
76 IMPLEMENT_ABSTRACT_CLASS(wxWindowMac
, wxWindowBase
)
78 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
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
)
88 #define wxMAC_DEBUG_REDRAW 0
89 #ifndef wxMAC_DEBUG_REDRAW
90 #define wxMAC_DEBUG_REDRAW 0
94 // TODO BEGIN move to window_osx.cpp
96 // ===========================================================================
98 // ===========================================================================
100 WX_DECLARE_HASH_MAP(WXWidget
, wxWindow
*, wxPointerHash
, wxPointerEqual
, MacControlMap
);
102 static MacControlMap wxWinMacControlList
;
104 wxWindowMac
*wxFindWindowFromWXWidget(WXWidget inControl
)
106 MacControlMap::iterator node
= wxWinMacControlList
.find(inControl
);
108 return (node
== wxWinMacControlList
.end()) ? NULL
: node
->second
;
111 void wxAssociateWindowWithWXWidget(WXWidget inControl
, wxWindow
*control
)
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") );
117 wxWinMacControlList
[inControl
] = control
;
120 void wxRemoveWXWidgetAssociation(wxWindow
*control
)
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...
130 MacControlMap::iterator it
;
131 for ( it
= wxWinMacControlList
.begin(); it
!= wxWinMacControlList
.end(); ++it
)
133 if ( it
->second
== control
)
135 wxWinMacControlList
.erase(it
);
143 // ----------------------------------------------------------------------------
144 // constructors and such
145 // ----------------------------------------------------------------------------
147 wxWindowMac::wxWindowMac()
152 wxWindowMac::wxWindowMac(wxWindowMac
*parent
,
157 const wxString
& name
)
160 Create(parent
, id
, pos
, size
, style
, name
);
163 void wxWindowMac::Init()
167 m_cgContextRef
= NULL
;
169 // as all windows are created with WS_VISIBLE style...
172 m_hScrollBar
= NULL
;
173 m_vScrollBar
= NULL
;
174 m_hScrollBarAlwaysShown
= false;
175 m_vScrollBarAlwaysShown
= false;
177 m_macIsUserPane
= true;
178 m_clipChildren
= false ;
179 m_cachedClippedRectValid
= false ;
182 wxWindowMac::~wxWindowMac()
186 m_isBeingDeleted
= true;
188 MacInvalidateBorders() ;
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() )
194 wxFrame
*frame
= wxDynamicCast(win
, wxFrame
);
197 if ( frame
->GetLastFocus() == this )
198 frame
->SetLastFocus((wxWindow
*)NULL
);
204 // destroy children before destroying this window itself
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
);
213 if ( tlw
->GetDefaultItem() == (wxButton
*) this)
214 tlw
->SetDefaultItem(NULL
);
217 if ( m_peer
&& m_peer
->IsOk() )
222 if ( g_MacLastWindow
== this )
223 g_MacLastWindow
= NULL
;
225 #ifndef __WXUNIVERSAL__
226 wxFrame
* frame
= wxDynamicCast( wxGetTopLevelParent( (wxWindow
*)this ) , wxFrame
) ;
229 if ( frame
->GetLastFocus() == this )
230 frame
->SetLastFocus( NULL
) ;
234 // delete our drop target if we've got one
235 #if wxUSE_DRAG_AND_DROP
236 if ( m_dropTarget
!= NULL
)
246 WXWidget
wxWindowMac::GetHandle() const
248 return (WXWidget
) m_peer
->GetWXWidget() ;
252 // TODO END move to window_osx.cpp
255 // ---------------------------------------------------------------------------
256 // Utility Routines to move between different coordinate systems
257 // ---------------------------------------------------------------------------
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)
277 bool wxWindowMac::Create(wxWindowMac
*parent
,
282 const wxString
& name
)
284 wxCHECK_MSG( parent
, false, wxT("can't create wxWindowMac without parent") );
286 if ( !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
289 m_windowVariant
= parent
->GetWindowVariant() ;
291 if ( m_macIsUserPane
)
294 m_peer
= (wxMacControl
*) wxWidgetImpl::CreateUserPane( this, pos
, size
, style
, GetExtraStyle() , name
);
296 m_peer
= wxWidgetImpl::CreateUserPane( this, pos
, size
, style
, GetExtraStyle() , name
);
298 MacPostControlCreate(pos
, size
) ;
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
))))
306 MacCreateScrollBars( style
) ;
310 wxWindowCreateEvent
event((wxWindow
*)this);
311 GetEventHandler()->AddPendingEvent(event
);
316 void wxWindowMac::MacChildAdded()
319 m_vScrollBar
->Raise() ;
321 m_hScrollBar
->Raise() ;
324 void wxWindowMac::MacPostControlCreate(const wxPoint
& WXUNUSED(pos
), const wxSize
& size
)
326 wxASSERT_MSG( m_peer
!= NULL
&& m_peer
->IsOk() , wxT("No valid mac control") ) ;
329 m_peer
->SetReference( (URefCon
) this ) ;
332 GetParent()->AddChild( this );
335 m_peer
->InstallEventHandler();
337 ControlRef container
= (ControlRef
) GetParent()->GetHandle() ;
338 wxASSERT_MSG( container
!= NULL
, wxT("No valid mac container control") ) ;
339 ::EmbedControl( m_peer
->GetControlRef() , container
) ;
341 GetParent()->MacChildAdded() ;
343 // adjust font, controlsize etc
344 DoSetWindowVariant( m_windowVariant
) ;
346 m_peer
->SetLabel( wxStripMenuCodes(m_label
, wxStrip_Mnemonics
) ) ;
348 if (!m_macIsUserPane
)
349 SetInitialSize(size
);
351 SetCursor( *wxSTANDARD_CURSOR
) ;
354 void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant
)
356 // Don't assert, in case we set the window variant before
357 // the window is created
358 // wxASSERT( m_peer->Ok() ) ;
360 m_windowVariant
= variant
;
362 if (m_peer
== NULL
|| !m_peer
->IsOk())
365 #if wxOSX_USE_COCOA_OR_CARBON
368 ThemeFontID themeFont
= kThemeSystemFont
;
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
376 case wxWINDOW_VARIANT_NORMAL
:
377 size
= kControlSizeNormal
;
378 themeFont
= kThemeSystemFont
;
381 case wxWINDOW_VARIANT_SMALL
:
382 size
= kControlSizeSmall
;
383 themeFont
= kThemeSmallSystemFont
;
386 case wxWINDOW_VARIANT_MINI
:
387 // not always defined in the headers
392 case wxWINDOW_VARIANT_LARGE
:
393 size
= kControlSizeLarge
;
394 themeFont
= kThemeSystemFont
;
398 wxFAIL_MSG(_T("unexpected window variant"));
403 m_peer
->SetData
<ControlSize
>(kControlEntireControl
, kControlSizeTag
, &size
) ;
407 font
.MacCreateFromThemeFont( themeFont
) ;
412 void wxWindowMac::MacUpdateControlFont()
415 m_peer
->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
417 // do not trigger refreshes upon invisible and possible partly created objects
418 if ( IsShownOnScreen() )
422 bool wxWindowMac::SetFont(const wxFont
& font
)
424 bool retval
= wxWindowBase::SetFont( font
);
426 MacUpdateControlFont() ;
431 bool wxWindowMac::SetForegroundColour(const wxColour
& col
)
433 bool retval
= wxWindowBase::SetForegroundColour( col
);
436 MacUpdateControlFont();
441 bool wxWindowMac::SetBackgroundColour(const wxColour
& col
)
443 if ( !wxWindowBase::SetBackgroundColour(col
) && m_hasBgCol
)
447 m_peer
->SetBackgroundColour( col
) ;
452 void wxWindowMac::SetFocus()
454 if ( !AcceptsFocus() )
457 wxWindow
* former
= FindFocus() ;
458 if ( former
== this )
464 void wxWindowMac::DoCaptureMouse()
466 wxApp::s_captureWindow
= (wxWindow
*) this ;
469 wxWindow
* wxWindowBase::GetCapture()
471 return wxApp::s_captureWindow
;
474 void wxWindowMac::DoReleaseMouse()
476 wxApp::s_captureWindow
= NULL
;
479 #if wxUSE_DRAG_AND_DROP
481 void wxWindowMac::SetDropTarget(wxDropTarget
*pDropTarget
)
483 if ( m_dropTarget
!= NULL
)
486 m_dropTarget
= pDropTarget
;
487 if ( m_dropTarget
!= NULL
)
495 // Old-style File Manager Drag & Drop
496 void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept
))
501 // From a wx position / size calculate the appropriate size of the native control
503 bool wxWindowMac::MacGetBoundsForControl(
507 int& w
, int& h
, bool adjustOrigin
) const
509 // the desired size, minus the border pixels gives the correct size of the control
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 ) ;
517 x
+= MacGetLeftBorderSize() ;
518 y
+= MacGetTopBorderSize() ;
519 w
-= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
520 h
-= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
523 AdjustForParentClientOrigin( x
, y
) ;
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() )
528 x
-= GetParent()->MacGetLeftBorderSize() ;
529 y
-= GetParent()->MacGetTopBorderSize() ;
535 // Get window size (not client size)
536 void wxWindowMac::DoGetSize(int *x
, int *y
) const
539 m_peer
->GetSize( width
, height
);
542 *x
= width
+ MacGetLeftBorderSize() + MacGetRightBorderSize() ;
544 *y
= height
+ MacGetTopBorderSize() + MacGetBottomBorderSize() ;
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
552 m_peer
->GetPosition( x1
, y1
) ;
554 // get the wx window position from the native one
555 x1
-= MacGetLeftBorderSize() ;
556 y1
-= MacGetTopBorderSize() ;
560 wxWindow
*parent
= GetParent();
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() ;
568 // and now to client coordinates
569 wxPoint
pt(parent
->GetClientAreaOrigin());
581 void wxWindowMac::DoScreenToClient(int *x
, int *y
) const
583 wxNonOwnedWindow
* tlw
= MacGetTopLevelWindow() ;
584 wxCHECK_RET( tlw
, wxT("TopLevel Window missing") ) ;
585 tlw
->GetNonOwnedPeer()->ScreenToWindow( x
, y
);
586 MacRootWindowToWindow( x
, y
) ;
588 wxPoint origin
= GetClientAreaOrigin() ;
595 void wxWindowMac::DoClientToScreen(int *x
, int *y
) const
597 wxNonOwnedWindow
* tlw
= MacGetTopLevelWindow() ;
598 wxCHECK_RET( tlw
, wxT("TopLevel window missing") ) ;
600 wxPoint origin
= GetClientAreaOrigin() ;
606 MacWindowToRootWindow( x
, y
) ;
607 tlw
->GetNonOwnedPeer()->WindowToScreen( x
, y
);
610 void wxWindowMac::MacClientToRootWindow( int *x
, int *y
) const
612 wxPoint origin
= GetClientAreaOrigin() ;
618 MacWindowToRootWindow( x
, y
) ;
621 void wxWindowMac::MacWindowToRootWindow( int *x
, int *y
) const
632 wxNonOwnedWindow
* top
= MacGetTopLevelWindow();
635 pt
.x
-= MacGetLeftBorderSize() ;
636 pt
.y
-= MacGetTopBorderSize() ;
637 wxWidgetImpl::Convert( &pt
, m_peer
, top
->m_peer
) ;
647 void wxWindowMac::MacRootWindowToWindow( int *x
, int *y
) const
658 wxNonOwnedWindow
* top
= MacGetTopLevelWindow();
661 wxWidgetImpl::Convert( &pt
, top
->m_peer
, m_peer
) ;
662 pt
.x
+= MacGetLeftBorderSize() ;
663 pt
.y
+= MacGetTopBorderSize() ;
673 wxSize
wxWindowMac::DoGetSizeFromClientSize( const wxSize
& size
) const
675 wxSize sizeTotal
= size
;
677 int innerwidth
, innerheight
;
679 int outerwidth
, outerheight
;
681 m_peer
->GetContentArea( left
, top
, innerwidth
, innerheight
);
682 m_peer
->GetSize( outerwidth
, outerheight
);
684 sizeTotal
.x
+= left
+ (outerwidth
-innerwidth
);
685 sizeTotal
.y
+= top
+ (outerheight
-innerheight
);
687 sizeTotal
.x
+= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
688 sizeTotal
.y
+= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
693 // Get size *available for subwindows* i.e. excluding menu bar etc.
694 void wxWindowMac::DoGetClientSize( int *x
, int *y
) const
700 m_peer
->GetContentArea( left
, top
, ww
, hh
);
702 if (m_hScrollBar
&& m_hScrollBar
->IsShown() )
703 hh
-= m_hScrollBar
->GetSize().y
;
705 if (m_vScrollBar
&& m_vScrollBar
->IsShown() )
706 ww
-= m_vScrollBar
->GetSize().x
;
714 bool wxWindowMac::SetCursor(const wxCursor
& cursor
)
716 if (m_cursor
.IsSameAs(cursor
))
721 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
) )
726 if ( ! wxWindowBase::SetCursor( cursor
) )
730 wxASSERT_MSG( m_cursor
.Ok(),
731 wxT("cursor must be valid after call to the base version"));
733 wxWindowMac
*mouseWin
= 0 ;
736 wxNonOwnedWindow
*tlw
= MacGetTopLevelWindow() ;
737 WindowRef window
= (WindowRef
) ( tlw
? tlw
->GetWXWindow() : 0 ) ;
739 ControlPartCode part
;
742 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
744 HIGetMousePosition(kHICoordSpaceWindow
, window
, &hiPoint
);
748 GetGlobalMouse( &pt
);
751 ScreenToClient(&x
, &y
);
755 control
= FindControlUnderMouse( pt
, window
, &part
) ;
757 mouseWin
= wxFindWindowFromWXWidget( (WXWidget
) control
) ;
762 if ( mouseWin
== this && !wxIsBusy() )
763 m_cursor
.MacInstall() ;
769 bool wxWindowMac::DoPopupMenu(wxMenu
*menu
, int x
, int y
)
771 #ifndef __WXUNIVERSAL__
772 menu
->SetInvokingWindow((wxWindow
*)this);
775 if ( x
== wxDefaultCoord
&& y
== wxDefaultCoord
)
777 wxPoint mouse
= wxGetMousePosition();
783 ClientToScreen( &x
, &y
) ;
786 menu
->MacBeforeDisplay( true ) ;
787 long menuResult
= ::PopUpMenuSelect((MenuHandle
) menu
->GetHMenu() , y
, x
, 0) ;
788 if ( HiWord(menuResult
) != 0 )
791 GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult
)) , LoWord(menuResult
) , &macid
);
792 int id
= wxMacCommandToId( macid
);
793 wxMenuItem
* item
= NULL
;
795 item
= menu
->FindItem( id
, &realmenu
) ;
798 if (item
->IsCheckable())
799 item
->Check( !item
->IsChecked() ) ;
801 menu
->SendEvent( id
, item
->IsCheckable() ? item
->IsChecked() : -1 ) ;
805 menu
->MacAfterDisplay( true ) ;
806 menu
->SetInvokingWindow( NULL
);
810 // actually this shouldn't be called, because universal is having its own implementation
816 // ----------------------------------------------------------------------------
818 // ----------------------------------------------------------------------------
822 void wxWindowMac::DoSetToolTip(wxToolTip
*tooltip
)
824 wxWindowBase::DoSetToolTip(tooltip
);
827 m_tooltip
->SetWindow(this);
832 void wxWindowMac::MacInvalidateBorders()
834 if ( m_peer
== NULL
)
837 bool vis
= IsShownOnScreen() ;
841 int outerBorder
= MacGetLeftBorderSize() ;
843 if ( m_peer
->NeedsFocusRect() /* && m_peer->HasFocus() */ )
847 if ( outerBorder
== 0 )
850 // now we know that we have something to do at all
855 m_peer
->GetSize( tw
, th
);
856 m_peer
->GetPosition( tx
, ty
);
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
);
863 GetParent()->m_peer
->SetNeedsDisplay(&leftupdate
);
864 GetParent()->m_peer
->SetNeedsDisplay(&rightupdate
);
865 GetParent()->m_peer
->SetNeedsDisplay(&topupdate
);
866 GetParent()->m_peer
->SetNeedsDisplay(&bottomupdate
);
869 void wxWindowMac::DoMoveWindow(int x
, int y
, int width
, int height
)
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
;
874 // Get true coordinates of former position
875 DoGetPosition( &former_x
, &former_y
) ;
876 DoGetSize( &former_w
, &former_h
) ;
878 wxWindow
*parent
= GetParent();
881 wxPoint
pt(parent
->GetClientAreaOrigin());
886 int actualWidth
= width
;
887 int actualHeight
= height
;
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
;
900 bool doMove
= false, doResize
= false ;
902 if ( actualX
!= former_x
|| actualY
!= former_y
)
905 if ( actualWidth
!= former_w
|| actualHeight
!= former_h
)
908 if ( doMove
|| doResize
)
910 // as the borders are drawn outside the native control, we adjust now
912 wxRect
bounds( wxPoint( actualX
+ MacGetLeftBorderSize() ,actualY
+ MacGetTopBorderSize() ),
913 wxSize( actualWidth
- (MacGetLeftBorderSize() + MacGetRightBorderSize()) ,
914 actualHeight
- (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ;
916 if ( !GetParent()->IsTopLevel() )
918 bounds
.Offset( -GetParent()->MacGetLeftBorderSize(), -GetParent()->MacGetTopBorderSize() );
921 MacInvalidateBorders() ;
923 m_cachedClippedRectValid
= false ;
925 m_peer
->Move( bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
);
927 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified
929 MacInvalidateBorders() ;
931 MacRepositionScrollBars() ;
934 wxPoint
point(actualX
, actualY
);
935 wxMoveEvent
event(point
, m_windowId
);
936 event
.SetEventObject(this);
937 HandleWindowEvent(event
) ;
942 MacRepositionScrollBars() ;
943 wxSize
size(actualWidth
, actualHeight
);
944 wxSizeEvent
event(size
, m_windowId
);
945 event
.SetEventObject(this);
946 HandleWindowEvent(event
);
951 wxSize
wxWindowMac::DoGetBestSize() const
953 if ( m_macIsUserPane
|| IsTopLevel() )
955 return wxWindowBase::DoGetBestSize() ;
960 Rect bestsize
= { 0 , 0 , 0 , 0 } ;
961 int bestWidth
, bestHeight
;
963 #if wxOSX_USE_COCOA_OR_CARBON
965 m_peer
->GetBestRect( &bestsize
) ;
967 if ( EmptyRect( &bestsize
) )
972 bestsize
.bottom
= 16 ;
974 if ( IsKindOf( CLASSINFO( wxScrollBar
) ) )
976 bestsize
.bottom
= 16 ;
979 else if ( IsKindOf( CLASSINFO( wxSpinButton
) ) )
981 bestsize
.bottom
= 24 ;
986 // return wxWindowBase::DoGetBestSize() ;
990 bestWidth
= bestsize
.right
- bestsize
.left
+ MacGetLeftBorderSize() +
991 MacGetRightBorderSize();
992 bestHeight
= bestsize
.bottom
- bestsize
.top
+ MacGetTopBorderSize() +
993 MacGetBottomBorderSize();
994 if ( bestHeight
< 10 )
997 return wxSize(bestWidth
, bestHeight
);
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)
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
1009 void wxWindowMac::DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
1011 // get the current size and position...
1012 int currentX
, currentY
;
1013 int currentW
, currentH
;
1015 GetPosition(¤tX
, ¤tY
);
1016 GetSize(¤tW
, ¤tH
);
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 ) )
1023 MacRepositionScrollBars() ; // we might have a real position shift
1028 if ( !(sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) )
1030 if ( x
== wxDefaultCoord
)
1032 if ( y
== wxDefaultCoord
)
1036 AdjustForParentClientOrigin( x
, y
, sizeFlags
);
1038 wxSize size
= wxDefaultSize
;
1039 if ( width
== wxDefaultCoord
)
1041 if ( sizeFlags
& wxSIZE_AUTO_WIDTH
)
1043 size
= DoGetBestSize();
1048 // just take the current one
1053 if ( height
== wxDefaultCoord
)
1055 if ( sizeFlags
& wxSIZE_AUTO_HEIGHT
)
1057 if ( size
.x
== wxDefaultCoord
)
1058 size
= DoGetBestSize();
1059 // else: already called DoGetBestSize() above
1065 // just take the current one
1070 DoMoveWindow( x
, y
, width
, height
);
1073 wxPoint
wxWindowMac::GetClientAreaOrigin() const
1075 #if wxOSX_USE_CARBON
1076 RgnHandle rgn
= NewRgn() ;
1078 if ( m_peer
->GetRegion( kControlContentMetaPart
, rgn
) == noErr
)
1080 GetRegionBounds( rgn
, &content
) ;
1090 return wxPoint( content
.left
+ MacGetLeftBorderSize() , content
.top
+ MacGetTopBorderSize() );
1092 return wxPoint(0,0);
1096 void wxWindowMac::DoSetClientSize(int clientwidth
, int clientheight
)
1098 if ( clientwidth
!= wxDefaultCoord
|| clientheight
!= wxDefaultCoord
)
1100 int currentclientwidth
, currentclientheight
;
1101 int currentwidth
, currentheight
;
1103 GetClientSize( ¤tclientwidth
, ¤tclientheight
) ;
1104 GetSize( ¤twidth
, ¤theight
) ;
1106 DoSetSize( wxDefaultCoord
, wxDefaultCoord
, currentwidth
+ clientwidth
- currentclientwidth
,
1107 currentheight
+ clientheight
- currentclientheight
, wxSIZE_USE_EXISTING
) ;
1111 void wxWindowMac::SetLabel(const wxString
& title
)
1115 #if wxOSX_USE_CARBON
1116 if ( m_peer
&& m_peer
->IsOk() )
1117 m_peer
->SetLabel( wxStripMenuCodes(m_label
, wxStrip_Mnemonics
) ) ;
1120 // do not trigger refreshes upon invisible and possible partly created objects
1121 if ( IsShownOnScreen() )
1125 wxString
wxWindowMac::GetLabel() const
1130 bool wxWindowMac::Show(bool show
)
1132 if ( !wxWindowBase::Show(show
) )
1136 m_peer
->SetVisibility( show
) ;
1141 void wxWindowMac::DoEnable(bool enable
)
1143 #if wxOSX_USE_CARBON
1144 m_peer
->Enable( enable
) ;
1149 // status change notifications
1152 void wxWindowMac::MacVisibilityChanged()
1156 void wxWindowMac::MacHiliteChanged()
1160 void wxWindowMac::MacEnabledStateChanged()
1162 #if wxOSX_USE_CARBON
1163 OnEnabled( m_peer
->IsEnabled() );
1168 // status queries on the inherited window's state
1171 bool wxWindowMac::MacIsReallyEnabled()
1173 #if wxOSX_USE_CARBON
1174 return m_peer
->IsEnabled() ;
1178 bool wxWindowMac::MacIsReallyHilited()
1180 #if wxOSX_USE_CARBON
1181 return m_peer
->IsActive();
1185 int wxWindowMac::GetCharHeight() const
1187 wxClientDC
dc( (wxWindow
*)this ) ;
1189 return dc
.GetCharHeight() ;
1192 int wxWindowMac::GetCharWidth() const
1194 wxClientDC
dc( (wxWindow
*)this ) ;
1196 return dc
.GetCharWidth() ;
1199 void wxWindowMac::GetTextExtent(const wxString
& string
, int *x
, int *y
,
1200 int *descent
, int *externalLeading
, const wxFont
*theFont
) const
1202 const wxFont
*fontToUse
= theFont
;
1206 tempFont
= GetFont();
1207 fontToUse
= &tempFont
;
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
;
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
1228 void wxWindowMac::Refresh(bool WXUNUSED(eraseBack
), const wxRect
*rect
)
1230 if ( m_peer
== NULL
)
1233 if ( !IsShownOnScreen() )
1236 m_peer
->SetNeedsDisplay( rect
) ;
1239 void wxWindowMac::DoFreeze()
1241 #if wxOSX_USE_CARBON
1242 if ( m_peer
&& m_peer
->IsOk() )
1243 m_peer
->SetDrawingEnabled( false ) ;
1247 void wxWindowMac::DoThaw()
1249 #if wxOSX_USE_CARBON
1250 if ( m_peer
&& m_peer
->IsOk() )
1252 m_peer
->SetDrawingEnabled( true ) ;
1253 m_peer
->InvalidateWithChildren() ;
1258 wxWindow
*wxGetActiveWindow()
1260 // actually this is a windows-only concept
1264 // Coordinates relative to the window
1265 void wxWindowMac::WarpPointer(int WXUNUSED(x_pos
), int WXUNUSED(y_pos
))
1267 // We really don't move the mouse programmatically under Mac.
1270 void wxWindowMac::OnEraseBackground(wxEraseEvent
& event
)
1272 if ( MacGetTopLevelWindow() == NULL
)
1275 #if TARGET_API_MAC_OSX
1276 if ( !m_backgroundColour.Ok() || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
1282 if ( GetBackgroundStyle() == wxBG_STYLE_COLOUR
)
1284 event
.GetDC()->Clear() ;
1286 else if ( GetBackgroundStyle() == wxBG_STYLE_CUSTOM
)
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
1298 void wxWindowMac::OnNcPaint( wxNcPaintEvent
& event
)
1303 int wxWindowMac::GetScrollPos(int orient
) const
1305 if ( orient
== wxHORIZONTAL
)
1308 return m_hScrollBar
->GetThumbPosition() ;
1313 return m_vScrollBar
->GetThumbPosition() ;
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
1323 if ( orient
== wxHORIZONTAL
)
1326 return m_hScrollBar
->GetRange() ;
1331 return m_vScrollBar
->GetRange() ;
1337 int wxWindowMac::GetScrollThumb(int orient
) const
1339 if ( orient
== wxHORIZONTAL
)
1342 return m_hScrollBar
->GetThumbSize() ;
1347 return m_vScrollBar
->GetThumbSize() ;
1353 void wxWindowMac::SetScrollPos(int orient
, int pos
, bool WXUNUSED(refresh
))
1355 if ( orient
== wxHORIZONTAL
)
1358 m_hScrollBar
->SetThumbPosition( pos
) ;
1363 m_vScrollBar
->SetThumbPosition( pos
) ;
1368 wxWindowMac::AlwaysShowScrollbars(bool hflag
, bool vflag
)
1370 bool needVisibilityUpdate
= false;
1372 if ( m_hScrollBarAlwaysShown
!= hflag
)
1374 m_hScrollBarAlwaysShown
= hflag
;
1375 needVisibilityUpdate
= true;
1378 if ( m_vScrollBarAlwaysShown
!= vflag
)
1380 m_vScrollBarAlwaysShown
= vflag
;
1381 needVisibilityUpdate
= true;
1384 if ( needVisibilityUpdate
)
1385 DoUpdateScrollbarVisibility();
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
1393 void wxWindowMac::MacPaintGrowBox()
1398 if ( MacHasScrollBarCorner() )
1400 CGContextRef cgContext
= (CGContextRef
) MacGetCGContextRef() ;
1401 wxASSERT( cgContext
) ;
1405 m_peer
->GetSize( tw
, th
);
1406 m_peer
->GetPosition( tx
, ty
);
1408 Rect rect
= { ty
,tx
, ty
+th
, tx
+tw
};
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
);
1416 if ( m_backgroundColour
.Ok() )
1418 CGContextSetFillColorWithColor( cgContext
, m_backgroundColour
.GetCGColor() );
1422 CGContextSetRGBFillColor( cgContext
, (CGFloat
) 1.0, (CGFloat
)1.0 ,(CGFloat
) 1.0 , (CGFloat
)1.0 );
1424 CGContextFillRect( cgContext
, cgrect
);
1425 CGContextRestoreGState( cgContext
);
1429 void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin
) , int WXUNUSED(rightOrigin
) )
1434 bool hasFocus
= m_peer
->NeedsFocusRect() && m_peer
->HasFocus() ;
1436 // back to the surrounding frame rectangle
1439 m_peer
->GetSize( tw
, th
);
1440 m_peer
->GetPosition( tx
, ty
);
1442 Rect rect
= { ty
,tx
, ty
+th
, tx
+tw
};
1444 #if wxOSX_USE_COCOA_OR_CARBON
1446 InsetRect( &rect
, -1 , -1 ) ;
1449 CGRect cgrect
= CGRectMake( rect
.left
, rect
.top
, rect
.right
- rect
.left
,
1450 rect
.bottom
- rect
.top
) ;
1452 HIThemeFrameDrawInfo info
;
1453 memset( &info
, 0 , sizeof(info
) ) ;
1457 info
.state
= IsEnabled() ? kThemeStateActive
: kThemeStateInactive
;
1458 info
.isFocused
= hasFocus
;
1460 CGContextRef cgContext
= (CGContextRef
) GetParent()->MacGetCGContextRef() ;
1461 wxASSERT( cgContext
) ;
1463 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
) )
1465 info
.kind
= kHIThemeFrameTextFieldSquare
;
1466 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
1468 else if ( HasFlag(wxSIMPLE_BORDER
) )
1470 info
.kind
= kHIThemeFrameListBox
;
1471 HIThemeDrawFrame( &cgrect
, &info
, cgContext
, kHIThemeOrientationNormal
) ;
1473 else if ( hasFocus
)
1475 HIThemeDrawFocusRect( &cgrect
, true , cgContext
, kHIThemeOrientationNormal
) ;
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() )
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
) ) ;
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
) ;
1497 #endif // wxOSX_USE_COCOA_OR_CARBON
1500 void wxWindowMac::RemoveChild( wxWindowBase
*child
)
1502 if ( child
== m_hScrollBar
)
1503 m_hScrollBar
= NULL
;
1504 if ( child
== m_vScrollBar
)
1505 m_vScrollBar
= NULL
;
1507 wxWindowBase::RemoveChild( child
) ;
1510 void wxWindowMac::DoUpdateScrollbarVisibility()
1512 bool triggerSizeEvent
= false;
1516 bool showHScrollBar
= m_hScrollBarAlwaysShown
|| m_hScrollBar
->IsNeeded();
1518 if ( m_hScrollBar
->IsShown() != showHScrollBar
)
1520 m_hScrollBar
->Show( showHScrollBar
);
1521 triggerSizeEvent
= true;
1527 bool showVScrollBar
= m_vScrollBarAlwaysShown
|| m_vScrollBar
->IsNeeded();
1529 if ( m_vScrollBar
->IsShown() != showVScrollBar
)
1531 m_vScrollBar
->Show( showVScrollBar
) ;
1532 triggerSizeEvent
= true;
1536 MacRepositionScrollBars() ;
1537 if ( triggerSizeEvent
)
1539 wxSizeEvent
event(GetSize(), m_windowId
);
1540 event
.SetEventObject(this);
1541 HandleWindowEvent(event
);
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
)
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
);
1554 DoUpdateScrollbarVisibility();
1557 // Does a physical scroll
1558 void wxWindowMac::ScrollWindow(int dx
, int dy
, const wxRect
*rect
)
1560 if ( dx
== 0 && dy
== 0 )
1563 int width
, height
;
1564 GetClientSize( &width
, &height
) ;
1567 wxRect
scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width
, height
) ;
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() ) ;
1573 m_peer
->ScrollRect( &scrollrect
, dx
, dy
);
1578 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
1580 child
= node
->GetData();
1583 if (child
== m_vScrollBar
)
1585 if (child
== m_hScrollBar
)
1587 if (child
->IsTopLevel())
1590 child
->GetPosition( &x
, &y
);
1591 child
->GetSize( &w
, &h
);
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
);
1600 child
->SetSize( x
+ dx
, y
+ dy
, w
, h
, wxSIZE_AUTO
|wxSIZE_ALLOW_MINUS_ONE
);
1605 void wxWindowMac::MacOnScroll( wxScrollEvent
&event
)
1607 if ( event
.GetEventObject() == m_vScrollBar
|| event
.GetEventObject() == m_hScrollBar
)
1609 wxScrollWinEvent wevent
;
1610 wevent
.SetPosition(event
.GetPosition());
1611 wevent
.SetOrientation(event
.GetOrientation());
1612 wevent
.SetEventObject(this);
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
);
1631 HandleWindowEvent(wevent
);
1635 // Get the window with the focus
1636 wxWindow
*wxWindowBase::DoFindFocus()
1638 #if wxOSX_USE_CARBON
1639 ControlRef control
;
1640 GetKeyboardFocus( GetUserFocusWindow() , &control
) ;
1641 return wxFindWindowFromWXWidget( (WXWidget
) control
) ;
1647 void wxWindowMac::OnInternalIdle()
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
);
1655 // Raise the window to the top of the Z order
1656 void wxWindowMac::Raise()
1661 // Lower the window to the bottom of the Z order
1662 void wxWindowMac::Lower()
1667 // static wxWindow *gs_lastWhich = NULL;
1669 bool wxWindowMac::MacSetupCursor( const wxPoint
& pt
)
1671 // first trigger a set cursor event
1673 wxPoint clientorigin
= GetClientAreaOrigin() ;
1674 wxSize clientsize
= GetClientSize() ;
1676 if ( wxRect2DInt( clientorigin
.x
, clientorigin
.y
, clientsize
.x
, clientsize
.y
).Contains( wxPoint2DInt( pt
) ) )
1678 wxSetCursorEvent
event( pt
.x
, pt
.y
);
1680 bool processedEvtSetCursor
= HandleWindowEvent(event
);
1681 if ( processedEvtSetCursor
&& event
.HasCursor() )
1683 cursor
= event
.GetCursor() ;
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
1691 if ( !processedEvtSetCursor
&& m_cursor
.Ok() )
1694 if ( !wxIsBusy() && !GetParent() )
1695 cursor
= *wxSTANDARD_CURSOR
;
1699 cursor
.MacInstall() ;
1702 return cursor
.Ok() ;
1705 wxString
wxWindowMac::MacGetToolTipString( wxPoint
&WXUNUSED(pt
) )
1709 return m_tooltip
->GetTip() ;
1712 return wxEmptyString
;
1715 void wxWindowMac::ClearBackground()
1721 void wxWindowMac::Update()
1723 wxNonOwnedWindow
* top
= MacGetTopLevelWindow();
1728 wxNonOwnedWindow
* wxWindowMac::MacGetTopLevelWindow() const
1730 wxWindowMac
*iter
= (wxWindowMac
*)this ;
1734 if ( iter
->IsTopLevel() )
1736 wxTopLevelWindow
* toplevel
= wxDynamicCast(iter
,wxTopLevelWindow
);
1740 wxPopupWindow
* popupwin
= wxDynamicCast(iter
,wxPopupWindow
);
1745 iter
= iter
->GetParent() ;
1751 const wxRect
& wxWindowMac::MacGetClippedClientRect() const
1753 MacUpdateClippedRects() ;
1755 return m_cachedClippedClientRect
;
1758 const wxRect
& wxWindowMac::MacGetClippedRect() const
1760 MacUpdateClippedRects() ;
1762 return m_cachedClippedRect
;
1765 const wxRect
&wxWindowMac:: MacGetClippedRectWithOuterStructure() const
1767 MacUpdateClippedRects() ;
1769 return m_cachedClippedRectWithOuterStructure
;
1772 const wxRegion
& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures
)
1774 static wxRegion emptyrgn
;
1776 if ( !m_isBeingDeleted
&& IsShownOnScreen() )
1778 MacUpdateClippedRects() ;
1779 if ( includeOuterStructures
)
1780 return m_cachedClippedRegionWithOuterStructure
;
1782 return m_cachedClippedRegion
;
1790 void wxWindowMac::MacUpdateClippedRects() const
1792 #if wxOSX_USE_CARBON
1793 if ( m_cachedClippedRectValid
)
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
1801 Rect rIncludingOuterStructures
;
1805 m_peer
->GetSize( tw
, th
);
1806 m_peer
->GetPosition( tx
, ty
);
1808 Rect r
= { ty
,tx
, ty
+th
, tx
+tw
};
1810 r
.left
-= MacGetLeftBorderSize() ;
1811 r
.top
-= MacGetTopBorderSize() ;
1812 r
.bottom
+= MacGetBottomBorderSize() ;
1813 r
.right
+= MacGetRightBorderSize() ;
1820 rIncludingOuterStructures
= r
;
1821 InsetRect( &rIncludingOuterStructures
, -4 , -4 ) ;
1823 wxRect cl
= GetClientRect() ;
1824 Rect rClient
= { cl
.y
, cl
.x
, cl
.y
+ cl
.height
, cl
.x
+ cl
.width
} ;
1828 const wxWindow
* child
= (wxWindow
*) this ;
1829 const wxWindow
* parent
= NULL
;
1831 while ( !child
->IsTopLevel() && ( parent
= child
->GetParent() ) != NULL
)
1833 if ( parent
->MacIsChildOfClientArea(child
) )
1835 size
= parent
->GetClientSize() ;
1836 wxPoint origin
= parent
->GetClientAreaOrigin() ;
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() ;
1850 parent
->MacWindowToRootWindow( &x
, &y
) ;
1851 MacRootWindowToWindow( &x
, &y
) ;
1853 Rect rparent
= { y
, x
, y
+ size
.y
, x
+ size
.x
} ;
1855 // the wxwindow and client rects will always be clipped
1856 SectRect( &r
, &rparent
, &r
) ;
1857 SectRect( &rClient
, &rparent
, &rClient
) ;
1859 // the structure only at 'hard' borders
1860 if ( parent
->MacClipChildren() ||
1861 ( parent
->GetParent() && parent
->GetParent()->MacClipGrandChildren() ) )
1863 SectRect( &rIncludingOuterStructures
, &rparent
, &rIncludingOuterStructures
) ;
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
) ;
1877 m_cachedClippedRegionWithOuterStructure
= wxRegion( m_cachedClippedRectWithOuterStructure
) ;
1878 m_cachedClippedRegion
= wxRegion( m_cachedClippedRect
) ;
1879 m_cachedClippedClientRegion
= wxRegion( m_cachedClippedClientRect
) ;
1881 m_cachedClippedRectValid
= true ;
1886 This function must not change the updatergn !
1888 bool wxWindowMac::MacDoRedraw( void* updatergnr
, long time
)
1890 bool handled
= false ;
1891 #if wxOSX_USE_CARBON
1893 RgnHandle updatergn
= (RgnHandle
) updatergnr
;
1894 GetRegionBounds( updatergn
, &updatebounds
) ;
1896 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ;
1898 if ( !EmptyRgn(updatergn
) )
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
) ;
1906 // first send an erase event to the entire update area
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);
1914 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn
)));
1916 dc
->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate
)));
1918 wxEraseEvent
eevent( GetId(), dc
);
1919 eevent
.SetEventObject( this );
1920 HandleWindowEvent( eevent
);
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
) ;
1931 if ( !m_updateRegion
.Empty() )
1933 // paint the window itself
1936 event
.SetTimestamp(time
);
1937 event
.SetEventObject(this);
1938 HandleWindowEvent(event
);
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() ;
1950 for (wxWindowList::compatibility_iterator node
= GetChildren().GetFirst(); node
; node
= node
->GetNext())
1952 child
= node
->GetData();
1955 if (child
== m_vScrollBar
)
1957 if (child
== m_hScrollBar
)
1959 if (child
->IsTopLevel())
1961 if (!child
->IsShown())
1964 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects
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) ;
1972 if ( RectInRgn( &childRect
, updatergn
) )
1974 // paint custom borders
1975 wxNcPaintEvent
eventNc( child
->GetId() );
1976 eventNc
.SetEventObject( child
);
1977 if ( !child
->HandleWindowEvent( eventNc
) )
1979 child
->MacPaintBorders(0, 0) ;
1989 WXWindow
wxWindowMac::MacGetTopLevelWindowRef() const
1991 wxNonOwnedWindow
* tlw
= MacGetTopLevelWindow();
1992 return tlw
? tlw
->GetWXWindow() : NULL
;
1995 bool wxWindowMac::MacHasScrollBarCorner() const
1997 /* Returns whether the scroll bars in a wxScrolledWindow should be
1998 * shortened. Scroll bars should be shortened if either:
2000 * - both scroll bars are visible, or
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
2007 if ( m_hScrollBar
== NULL
&& m_vScrollBar
== NULL
)
2010 if ( ( m_hScrollBar
&& m_hScrollBar
->IsShown() )
2011 && ( m_vScrollBar
&& m_vScrollBar
->IsShown() ) )
2013 // Both scroll bars visible
2018 wxPoint thisWindowBottomRight
= GetScreenRect().GetBottomRight();
2020 for ( const wxWindow
*win
= (wxWindow
*)this; win
; win
= win
->GetParent() )
2022 const wxFrame
*frame
= wxDynamicCast( win
, wxFrame
) ;
2025 if ( frame
->GetWindowStyleFlag() & wxRESIZE_BORDER
)
2027 // Parent frame has resize handle
2028 wxPoint frameBottomRight
= frame
->GetScreenRect().GetBottomRight();
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 )
2035 // Parent frame has resize handle and shares
2036 // right bottom corner
2041 // Parent frame has resize handle but doesn't
2042 // share right bottom corner
2048 // Parent frame doesn't have resize handle
2054 // No parent frame found
2059 void wxWindowMac::MacCreateScrollBars( long style
)
2061 wxASSERT_MSG( m_vScrollBar
== NULL
&& m_hScrollBar
== NULL
, wxT("attempt to create window twice") ) ;
2063 if ( style
& ( wxVSCROLL
| wxHSCROLL
) )
2065 int scrlsize
= MAC_SCROLLBAR_SIZE
;
2066 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL
|| GetWindowVariant() == wxWINDOW_VARIANT_MINI
)
2068 scrlsize
= MAC_SMALL_SCROLLBAR_SIZE
;
2071 int adjust
= MacHasScrollBarCorner() ? scrlsize
- 1: 0 ;
2073 GetClientSize( &width
, &height
) ;
2075 wxPoint
vPoint(width
- scrlsize
, 0) ;
2076 wxSize
vSize(scrlsize
, height
- adjust
) ;
2077 wxPoint
hPoint(0, height
- scrlsize
) ;
2078 wxSize
hSize(width
- adjust
, scrlsize
) ;
2080 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize)
2081 if ( style
& wxVSCROLL
)
2083 m_vScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, vPoint
, vSize
, wxVERTICAL
);
2084 m_vScrollBar
->SetMinSize( wxDefaultSize
);
2087 if ( style
& wxHSCROLL
)
2089 m_hScrollBar
= new wxScrollBar((wxWindow
*)this, wxID_ANY
, hPoint
, hSize
, wxHORIZONTAL
);
2090 m_hScrollBar
->SetMinSize( wxDefaultSize
);
2094 // because the create does not take into account the client area origin
2095 // we might have a real position shift
2096 MacRepositionScrollBars() ;
2099 bool wxWindowMac::MacIsChildOfClientArea( const wxWindow
* child
) const
2101 bool result
= ((child
== NULL
) || ((child
!= m_hScrollBar
) && (child
!= m_vScrollBar
)));
2106 void wxWindowMac::MacRepositionScrollBars()
2108 if ( !m_hScrollBar
&& !m_vScrollBar
)
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 ;
2114 // get real client area
2116 GetSize( &width
, &height
);
2118 width
-= MacGetLeftBorderSize() + MacGetRightBorderSize();
2119 height
-= MacGetTopBorderSize() + MacGetBottomBorderSize();
2121 wxPoint
vPoint( width
- scrlsize
, 0 ) ;
2122 wxSize
vSize( scrlsize
, height
- adjust
) ;
2123 wxPoint
hPoint( 0 , height
- scrlsize
) ;
2124 wxSize
hSize( width
- adjust
, scrlsize
) ;
2127 m_vScrollBar
->SetSize( vPoint
.x
, vPoint
.y
, vSize
.x
, vSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
2129 m_hScrollBar
->SetSize( hPoint
.x
, hPoint
.y
, hSize
.x
, hSize
.y
, wxSIZE_ALLOW_MINUS_ONE
);
2132 bool wxWindowMac::AcceptsFocus() const
2134 return m_peer
->CanFocus() && wxWindowBase::AcceptsFocus();
2137 void wxWindowMac::MacSuperChangedPosition()
2139 // only window-absolute structures have to be moved i.e. controls
2141 m_cachedClippedRectValid
= false ;
2144 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
2147 child
= node
->GetData();
2148 child
->MacSuperChangedPosition() ;
2150 node
= node
->GetNext();
2154 void wxWindowMac::MacTopLevelWindowChangedPosition()
2156 // only screen-absolute structures have to be moved i.e. glcanvas
2159 wxWindowList::compatibility_iterator node
= GetChildren().GetFirst();
2162 child
= node
->GetData();
2163 child
->MacTopLevelWindowChangedPosition() ;
2165 node
= node
->GetNext();
2169 long wxWindowMac::MacGetLeftBorderSize() const
2176 if (HasFlag(wxRAISED_BORDER
) || HasFlag( wxSUNKEN_BORDER
) || HasFlag(wxDOUBLE_BORDER
))
2178 #if wxOSX_USE_COCOA_OR_CARBON
2179 // this metric is only the 'outset' outside the simple frame rect
2180 GetThemeMetric( kThemeMetricEditTextFrameOutset
, &border
) ;
2186 else if (HasFlag(wxSIMPLE_BORDER
))
2188 #if wxOSX_USE_COCOA_OR_CARBON
2189 // this metric is only the 'outset' outside the simple frame rect
2190 GetThemeMetric( kThemeMetricListBoxFrameOutset
, &border
) ;
2200 long wxWindowMac::MacGetRightBorderSize() const
2202 // they are all symmetric in mac themes
2203 return MacGetLeftBorderSize() ;
2206 long wxWindowMac::MacGetTopBorderSize() const
2208 // they are all symmetric in mac themes
2209 return MacGetLeftBorderSize() ;
2212 long wxWindowMac::MacGetBottomBorderSize() const
2214 // they are all symmetric in mac themes
2215 return MacGetLeftBorderSize() ;
2218 long wxWindowMac::MacRemoveBordersFromStyle( long style
)
2220 return style
& ~wxBORDER_MASK
;
2223 // Find the wxWindowMac at the current mouse position, returning the mouse
2225 wxWindow
* wxFindWindowAtPointer( wxPoint
& pt
)
2227 pt
= wxGetMousePosition();
2228 wxWindowMac
* found
= wxFindWindowAtPoint(pt
);
2230 return (wxWindow
*) found
;
2233 // Get the current mouse position.
2234 wxPoint
wxGetMousePosition()
2238 wxGetMousePosition( &x
, &y
);
2240 return wxPoint(x
, y
);
2243 void wxWindowMac::OnMouseEvent( wxMouseEvent
&event
)
2245 if ( event
.GetEventType() == wxEVT_RIGHT_DOWN
)
2247 // copied from wxGTK : CS
2248 // VZ: shouldn't we move this to base class then?
2250 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN
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
,
2258 this->ClientToScreen(event
.GetPosition()));
2259 evtCtx
.SetEventObject(this);
2260 if ( ! HandleWindowEvent(evtCtx
) )
2269 void wxWindowMac::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
2271 #if wxOSX_USE_COCOA_OR_CARBON
2272 // for native controls: call their native paint method
2273 if ( !MacIsUserPane() || ( IsTopLevel() && GetBackgroundStyle() == wxBG_STYLE_SYSTEM
) )
2275 if ( wxTheApp
->MacGetCurrentEvent() != NULL
&& wxTheApp
->MacGetCurrentEventHandlerCallRef() != NULL
2276 && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT
)
2277 CallNextEventHandler(
2278 (EventHandlerCallRef
)wxTheApp
->MacGetCurrentEventHandlerCallRef() ,
2279 (EventRef
) wxTheApp
->MacGetCurrentEvent() ) ;
2284 void wxWindowMac::MacHandleControlClick(WXWidget
WXUNUSED(control
),
2285 wxInt16
WXUNUSED(controlpart
),
2286 bool WXUNUSED(mouseStillDown
))
2290 Rect
wxMacGetBoundsForControl( wxWindowMac
* window
, const wxPoint
& pos
, const wxSize
&size
, bool adjustForOrigin
)
2294 window
->MacGetBoundsForControl( pos
, size
, x
, y
, w
, h
, adjustForOrigin
) ;
2295 Rect bounds
= { y
, x
, y
+ h
, x
+ w
};
2300 wxInt32
wxWindowMac::MacControlHit(WXEVENTHANDLERREF
WXUNUSED(handler
) , WXEVENTREF
WXUNUSED(event
) )
2302 #if wxOSX_USE_COCOA_OR_CARBON
2303 return eventNotHandledErr
;
2309 bool wxWindowMac::Reparent(wxWindowBase
*newParentBase
)
2311 wxWindowMac
*newParent
= (wxWindowMac
*)newParentBase
;
2312 if ( !wxWindowBase::Reparent(newParent
) )
2315 m_peer
->RemoveFromParent();
2316 m_peer
->Embed( GetParent()->GetPeer() );
2320 bool wxWindowMac::SetTransparent(wxByte alpha
)
2322 SetBackgroundStyle(wxBG_STYLE_TRANSPARENT
);
2324 if ( alpha
!= m_macAlpha
)
2326 m_macAlpha
= alpha
;
2333 bool wxWindowMac::CanSetTransparent()
2338 wxByte
wxWindowMac::GetTransparent() const
2343 bool wxWindowMac::IsShownOnScreen() const
2345 if ( m_peer
&& m_peer
->IsOk() )
2347 bool peerVis
= m_peer
->IsVisible();
2348 bool wxVis
= wxWindowBase::IsShownOnScreen();
2349 if( peerVis
!= wxVis
)
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();
2361 return m_peer
->IsVisible();
2363 return wxWindowBase::IsShownOnScreen();
2366 #if wxOSX_USE_CARBON
2372 // ---------------------------------------------------------------------------
2374 // ---------------------------------------------------------------------------
2376 static const EventTypeSpec eventList
[] =
2378 { kEventClassCommand
, kEventProcessCommand
} ,
2379 { kEventClassCommand
, kEventCommandUpdateStatus
} ,
2381 { kEventClassControl
, kEventControlGetClickActivation
} ,
2382 { kEventClassControl
, kEventControlHit
} ,
2384 { kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
} ,
2385 { kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
} ,
2387 { kEventClassControl
, kEventControlDraw
} ,
2389 { kEventClassControl
, kEventControlVisibilityChanged
} ,
2390 { kEventClassControl
, kEventControlEnabledStateChanged
} ,
2391 { kEventClassControl
, kEventControlHiliteChanged
} ,
2393 { kEventClassControl
, kEventControlActivate
} ,
2394 { kEventClassControl
, kEventControlDeactivate
} ,
2396 { kEventClassControl
, kEventControlSetFocusPart
} ,
2397 { kEventClassControl
, kEventControlFocusPartChanged
} ,
2399 { kEventClassService
, kEventServiceGetTypes
},
2400 { kEventClassService
, kEventServiceCopy
},
2401 { kEventClassService
, kEventServicePaste
},
2403 // { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only
2404 // { kEventClassControl , kEventControlBoundsChanged } ,
2407 static pascal OSStatus
wxMacWindowControlEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
2409 OSStatus result
= eventNotHandledErr
;
2410 static wxWindowMac
* targetFocusWindow
= NULL
;
2411 static wxWindowMac
* formerFocusWindow
= NULL
;
2413 wxMacCarbonEvent
cEvent( event
) ;
2415 ControlRef controlRef
;
2416 wxWindowMac
* thisWindow
= (wxWindowMac
*) data
;
2418 cEvent
.GetParameter( kEventParamDirectObject
, &controlRef
) ;
2420 switch ( GetEventKind( event
) )
2422 case kEventControlDraw
:
2424 RgnHandle updateRgn
= NULL
;
2425 RgnHandle allocatedRgn
= NULL
;
2426 wxRegion visRegion
= thisWindow
->MacGetVisibleRegion() ;
2428 if ( cEvent
.GetParameter
<RgnHandle
>(kEventParamRgnHandle
, &updateRgn
) != noErr
)
2430 HIShapeGetAsQDRgn( visRegion
.GetWXHRGN(), updateRgn
);
2434 if ( thisWindow
->MacGetLeftBorderSize() != 0 || thisWindow
->MacGetTopBorderSize() != 0 )
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
) ;
2440 // hide the given region by the new region that must be shifted
2441 OffsetRgn( allocatedRgn
, thisWindow
->MacGetLeftBorderSize() , thisWindow
->MacGetTopBorderSize() ) ;
2442 updateRgn
= allocatedRgn
;
2446 #if wxMAC_DEBUG_REDRAW
2447 if ( thisWindow
->MacIsUserPane() )
2449 static float color
= 0.5 ;
2450 static int channel
= 0 ;
2452 CGContextRef cgContext
= cEvent
.GetParameter
<CGContextRef
>(kEventParamCGContextRef
) ;
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
);
2470 bool created
= false ;
2471 CGContextRef cgContext
= NULL
;
2472 OSStatus err
= cEvent
.GetParameter
<CGContextRef
>(kEventParamCGContextRef
, &cgContext
) ;
2475 wxFAIL_MSG("Unable to retrieve CGContextRef");
2478 thisWindow
->MacSetCGContextRef( cgContext
) ;
2481 wxMacCGContextStateSaver
sg( cgContext
) ;
2482 CGFloat alpha
= (CGFloat
)1.0 ;
2484 wxWindow
* iter
= thisWindow
;
2487 alpha
*= (CGFloat
)( iter
->GetTransparent()/255.0 ) ;
2488 if ( iter
->IsTopLevel() )
2491 iter
= iter
->GetParent() ;
2494 CGContextSetAlpha( cgContext
, alpha
) ;
2496 if ( thisWindow
->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT
)
2499 HIViewGetBounds( controlRef
, &bounds
);
2500 CGContextClearRect( cgContext
, bounds
);
2505 if ( thisWindow
->MacDoRedraw( updateRgn
, cEvent
.GetTicks() ) )
2508 thisWindow
->MacSetCGContextRef( NULL
) ;
2512 CGContextRelease( cgContext
) ;
2516 DisposeRgn( allocatedRgn
) ;
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
)
2526 thisWindow
->MacVisibilityChanged() ;
2530 case kEventControlEnabledStateChanged
:
2531 thisWindow
->MacEnabledStateChanged();
2534 case kEventControlHiliteChanged
:
2535 thisWindow
->MacHiliteChanged() ;
2538 case kEventControlActivate
:
2539 case kEventControlDeactivate
:
2540 // FIXME: we should have a virtual function for this!
2542 if ( thisWindow
->IsKindOf( CLASSINFO( wxTreeCtrl
) ) )
2543 thisWindow
->Refresh();
2546 if ( thisWindow
->IsKindOf( CLASSINFO( wxListCtrl
) ) )
2547 thisWindow
->Refresh();
2553 // different handling on OS X
2556 case kEventControlFocusPartChanged
:
2557 // the event is emulated by wxmac for systems lower than 10.5
2559 if ( UMAGetSystemVersion() < 0x1050 )
2561 // as it is synthesized here, we have to manually avoid propagation
2564 ControlPartCode previousControlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlPreviousPart
, typeControlPartCode
);
2565 ControlPartCode currentControlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlCurrentPart
, typeControlPartCode
);
2567 if ( thisWindow
->MacGetTopLevelWindow() && thisWindow
->GetPeer()->NeedsFocusRect() )
2569 thisWindow
->MacInvalidateBorders();
2572 if ( currentControlPart
== 0 )
2576 if ( thisWindow
->GetCaret() )
2577 thisWindow
->GetCaret()->OnKillFocus();
2580 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow
));
2582 // remove this as soon as posting the synthesized event works properly
2583 static bool inKillFocusEvent
= false ;
2585 if ( !inKillFocusEvent
)
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
;
2596 else if ( previousControlPart
== 0 )
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
);
2605 if ( thisWindow
->GetCaret() )
2606 thisWindow
->GetCaret()->OnSetFocus();
2609 wxFocusEvent
event(wxEVT_SET_FOCUS
, thisWindow
->GetId());
2610 event
.SetEventObject(thisWindow
);
2611 event
.SetWindow(formerFocusWindow
);
2612 thisWindow
->HandleWindowEvent(event
) ;
2613 formerFocusWindow
= NULL
;
2617 case kEventControlSetFocusPart
:
2619 Boolean focusEverything
= false ;
2620 if ( cEvent
.GetParameter
<Boolean
>(kEventParamControlFocusEverything
, &focusEverything
) == noErr
)
2622 // put a breakpoint here to catch focus everything events
2624 ControlPartCode controlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlPart
, typeControlPartCode
);
2625 if ( controlPart
!= kControlFocusNoPart
)
2627 targetFocusWindow
= thisWindow
;
2628 wxLogTrace(_T("Focus"), _T("focus to be set(%p)"), wx_static_cast(void*, thisWindow
));
2632 formerFocusWindow
= thisWindow
;
2633 wxLogTrace(_T("Focus"), _T("focus to be lost(%p)"), wx_static_cast(void*, thisWindow
));
2636 ControlPartCode previousControlPart
= 0;
2637 verify_noerr( HIViewGetFocusPart(controlRef
, &previousControlPart
));
2639 if ( thisWindow
->MacIsUserPane() )
2641 if ( controlPart
!= kControlFocusNoPart
)
2642 cEvent
.SetParameter
<ControlPartCode
>( kEventParamControlPart
, typeControlPartCode
, 1 ) ;
2646 result
= CallNextEventHandler(handler
, event
);
2648 if ( UMAGetSystemVersion() < 0x1050 )
2650 // set back to 0 if problems arise
2652 if ( result
== noErr
)
2654 ControlPartCode currentControlPart
= cEvent
.GetParameter
<ControlPartCode
>(kEventParamControlPart
, typeControlPartCode
);
2655 // synthesize the event focus changed event
2656 EventRef evRef
= NULL
;
2658 OSStatus err
= MacCreateEvent(
2659 NULL
, kEventClassControl
, kEventControlFocusPartChanged
, TicksToEventTime( TickCount() ) ,
2660 kEventAttributeUserEvent
, &evRef
);
2661 verify_noerr( err
);
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
);
2670 // TODO test this first, avoid double posts etc...
2671 PostEventToQueue( GetMainEventQueue(), evRef
, kEventPriorityHigh
);
2673 wxMacWindowControlEventHandler( NULL
, evRef
, data
) ;
2675 ReleaseEvent( evRef
) ;
2678 // old implementation, to be removed if the new one works
2679 if ( controlPart
== kControlFocusNoPart
)
2682 if ( thisWindow
->GetCaret() )
2683 thisWindow
->GetCaret()->OnKillFocus();
2686 wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow
));
2688 static bool inKillFocusEvent
= false ;
2690 if ( !inKillFocusEvent
)
2692 inKillFocusEvent
= true ;
2693 wxFocusEvent
event( wxEVT_KILL_FOCUS
, thisWindow
->GetId());
2694 event
.SetEventObject(thisWindow
);
2695 thisWindow
->HandleWindowEvent(event
) ;
2696 inKillFocusEvent
= false ;
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
);
2707 if ( thisWindow
->GetCaret() )
2708 thisWindow
->GetCaret()->OnSetFocus();
2711 wxFocusEvent
event(wxEVT_SET_FOCUS
, thisWindow
->GetId());
2712 event
.SetEventObject(thisWindow
);
2713 thisWindow
->HandleWindowEvent(event
) ;
2720 case kEventControlHit
:
2721 result
= thisWindow
->MacControlHit( handler
, event
) ;
2724 case kEventControlGetClickActivation
:
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
) )
2730 cEvent
.SetParameter(kEventParamClickActivation
,typeClickActivationResult
, (UInt32
) kActivateAndIgnoreClick
) ;
2743 static pascal OSStatus
2744 wxMacWindowServiceEventHandler(EventHandlerCallRef
WXUNUSED(handler
),
2748 OSStatus result
= eventNotHandledErr
;
2750 wxMacCarbonEvent
cEvent( event
) ;
2752 ControlRef controlRef
;
2753 wxWindowMac
* thisWindow
= (wxWindowMac
*) data
;
2754 wxTextCtrl
* textCtrl
= wxDynamicCast( thisWindow
, wxTextCtrl
) ;
2755 cEvent
.GetParameter( kEventParamDirectObject
, &controlRef
) ;
2757 switch ( GetEventKind( event
) )
2759 case kEventServiceGetTypes
:
2763 textCtrl
->GetSelection( &from
, &to
) ;
2765 CFMutableArrayRef copyTypes
= 0 , pasteTypes
= 0;
2767 copyTypes
= cEvent
.GetParameter
< CFMutableArrayRef
>( kEventParamServiceCopyTypes
, typeCFMutableArrayRef
) ;
2768 if ( textCtrl
->IsEditable() )
2769 pasteTypes
= cEvent
.GetParameter
< CFMutableArrayRef
>( kEventParamServicePasteTypes
, typeCFMutableArrayRef
) ;
2771 static const OSType textDataTypes
[] = { kTXNTextData
/* , 'utxt', 'PICT', 'MooV', 'AIFF' */ };
2772 for ( size_t i
= 0 ; i
< WXSIZEOF(textDataTypes
) ; ++i
)
2774 CFStringRef typestring
= CreateTypeStringWithOSType(textDataTypes
[i
]);
2778 CFArrayAppendValue(copyTypes
, typestring
) ;
2780 CFArrayAppendValue(pasteTypes
, typestring
) ;
2782 CFRelease( typestring
) ;
2790 case kEventServiceCopy
:
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);
2809 case kEventServicePaste
:
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
++ )
2818 PasteboardItemID itemID
;
2819 if ( PasteboardGetItemIdentifier( pasteboard
, itemIndex
, &itemID
) == noErr
)
2821 CFDataRef flavorData
= NULL
;
2822 if ( PasteboardCopyItemFlavorData( pasteboard
, itemID
, CFSTR("com.apple.traditional-mac-plain-text"), &flavorData
) == noErr
)
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
);
2830 textCtrl
->WriteText( wxString( content
, wxConvLocal
) );
2832 textCtrl
->WriteText( wxString( content
) ) ;
2850 pascal OSStatus
wxMacUnicodeTextEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
2852 OSStatus result
= eventNotHandledErr
;
2853 wxWindowMac
* focus
= (wxWindowMac
*) data
;
2855 wchar_t* uniChars
= NULL
;
2856 UInt32 when
= EventTimeToTicks( GetEventTime( event
) ) ;
2858 UniChar
* charBuf
= NULL
;
2859 ByteCount dataSize
= 0 ;
2862 if ( GetEventParameter( event
, kEventParamTextInputSendText
, typeUnicodeText
, NULL
, 0 , &dataSize
, NULL
) == noErr
)
2864 numChars
= dataSize
/ sizeof( UniChar
) + 1;
2867 if ( (size_t) numChars
* 2 > sizeof(buf
) )
2868 charBuf
= new UniChar
[ numChars
] ;
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...)
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
) ;
2885 switch ( GetEventKind( event
) )
2887 case kEventTextInputUpdateActiveInputArea
:
2889 // An IME input event may return several characters, but we need to send one char at a time to
2891 for (int pos
=0 ; pos
< numChars
; pos
++)
2893 WXEVENTREF formerEvent
= wxTheApp
->MacGetCurrentEvent() ;
2894 WXEVENTHANDLERCALLREF formerHandler
= wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
2895 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
2897 UInt32 message
= uniChars
[pos
] < 128 ? (char)uniChars
[pos
] : '?';
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.
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.
2923 if ( wxTheApp
->MacSendCharEvent(
2924 focus
, message
, 0 , when
, 0 , 0 , uniChars
[pos
] ) )
2929 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerHandler
) ;
2933 case kEventTextInputUnicodeForKeyEvent
:
2935 UInt32 keyCode
, modifiers
;
2938 unsigned char charCode
;
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
);
2946 UInt32 message
= (keyCode
<< 8) + charCode
;
2948 // An IME input event may return several characters, but we need to send one char at a time to
2950 for (int pos
=0 ; pos
< numChars
; pos
++)
2952 WXEVENTREF formerEvent
= wxTheApp
->MacGetCurrentEvent() ;
2953 WXEVENTHANDLERCALLREF formerHandler
= wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
2954 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
2956 if ( wxTheApp
->MacSendCharEvent(
2957 focus
, message
, modifiers
, when
, point
.h
, point
.v
, uniChars
[pos
] ) )
2962 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerHandler
) ;
2970 delete [] uniChars
;
2971 if ( charBuf
!= buf
)
2977 static pascal OSStatus
2978 wxMacWindowCommandEventHandler(EventHandlerCallRef
WXUNUSED(handler
),
2982 OSStatus result
= eventNotHandledErr
;
2983 wxWindowMac
* focus
= (wxWindowMac
*) data
;
2987 wxMacCarbonEvent
cEvent( event
) ;
2988 cEvent
.GetParameter
<HICommand
>(kEventParamDirectObject
,typeHICommand
,&command
) ;
2990 wxMenuItem
* item
= NULL
;
2991 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
2992 int id
= wxMacCommandToId( command
.commandID
) ;
2996 wxASSERT( itemMenu
!= NULL
) ;
2998 switch ( cEvent
.GetKind() )
3000 case kEventProcessCommand
:
3001 result
= itemMenu
->MacHandleCommandProcess( item
, id
, focus
);
3004 case kEventCommandUpdateStatus
:
3005 result
= itemMenu
->MacHandleCommandUpdateStatus( item
, id
, focus
);
3015 pascal OSStatus
wxMacWindowEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
3017 EventRef formerEvent
= (EventRef
) wxTheApp
->MacGetCurrentEvent() ;
3018 EventHandlerCallRef formerEventHandlerCallRef
= (EventHandlerCallRef
) wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
3019 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
3020 OSStatus result
= eventNotHandledErr
;
3022 switch ( GetEventClass( event
) )
3024 case kEventClassCommand
:
3025 result
= wxMacWindowCommandEventHandler( handler
, event
, data
) ;
3028 case kEventClassControl
:
3029 result
= wxMacWindowControlEventHandler( handler
, event
, data
) ;
3032 case kEventClassService
:
3033 result
= wxMacWindowServiceEventHandler( handler
, event
, data
) ;
3036 case kEventClassTextInput
:
3037 result
= wxMacUnicodeTextEventHandler( handler
, event
, data
) ;
3044 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerEventHandlerCallRef
) ;
3049 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler
)
3051 // ---------------------------------------------------------------------------
3052 // Scrollbar Tracking for all
3053 // ---------------------------------------------------------------------------
3055 pascal void wxMacLiveScrollbarActionProc( ControlRef control
, ControlPartCode partCode
) ;
3056 pascal void wxMacLiveScrollbarActionProc( ControlRef control
, ControlPartCode partCode
)
3060 wxWindow
* wx
= wxFindWindowFromWXWidget( (WXWidget
) control
) ;
3062 wx
->MacHandleControlClick( (WXWidget
) control
, partCode
, true /* stillDown */ ) ;
3065 wxMAC_DEFINE_PROC_GETTER( ControlActionUPP
, wxMacLiveScrollbarActionProc
) ;
3067 wxWidgetImpl
* wxWidgetImpl::CreateUserPane( wxWindowMac
* wxpeer
, const wxPoint
& pos
, const wxSize
& size
,
3068 long style
, long extraStyle
, const wxString
& name
)
3070 OSStatus err
= noErr
;
3071 Rect bounds
= wxMacGetBoundsForControl( wxpeer
, pos
, size
) ;
3072 wxMacControl
* c
= new wxMacControl(wxpeer
) ;
3074 | kControlSupportsEmbedding
3075 | kControlSupportsLiveFeedback
3076 | kControlGetsFocusOnClick
3077 // | kControlHasSpecialBackground
3078 // | kControlSupportsCalcBestRect
3079 | kControlHandlesTracking
3080 | kControlSupportsFocus
3081 | kControlWantsActivate
3082 | kControlWantsIdle
;
3084 err
=::CreateUserPaneControl( MAC_WXHWND(wxpeer
->GetParent()->MacGetTopLevelWindowRef()) , &bounds
, features
, c
->GetControlRefAddr() );
3085 verify_noerr( err
);
3090 void wxMacControl::MacInstallEventHandler( ControlRef control
, wxWindowMac
* wxPeer
)
3092 wxAssociateWindowWithWXWidget( (WXWidget
) control
, wxPeer
) ;
3093 ::InstallControlEventHandler( control
, GetwxMacWindowEventHandlerUPP(),
3094 GetEventTypeCount(eventList
), eventList
, wxPeer
, NULL
);
3097 IMPLEMENT_DYNAMIC_CLASS( wxMacControl
, wxWidgetImpl
)
3099 wxMacControl::wxMacControl()
3104 wxMacControl::wxMacControl(wxWindowMac
* peer
, bool isRootControl
) :
3105 wxWidgetImpl( peer
, isRootControl
)
3110 wxMacControl::~wxMacControl()
3114 void wxMacControl::Init()
3116 m_controlRef
= NULL
;
3117 m_macControlEventHandler
= NULL
;
3120 void wxMacControl::Destroy()
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") );
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
;
3134 void wxMacControl::SetReference( URefCon data
)
3136 SetControlReference( m_controlRef
, data
);
3139 void wxMacControl::RemoveFromParent()
3141 // nothing to do here for carbon
3144 void wxMacControl::Embed( wxWidgetImpl
*parent
)
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
) ;
3152 void wxMacControl::SetNeedsDisplay( const wxRect
* rect
)
3159 HIRect updatearea
= CGRectMake( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3160 HIViewSetNeedsDisplayInRect( m_controlRef
, &updatearea
, true );
3163 HIViewSetNeedsDisplay( m_controlRef
, true );
3166 void wxMacControl::Raise()
3168 verify_noerr( HIViewSetZOrder( m_controlRef
, kHIViewZOrderAbove
, NULL
) );
3171 void wxMacControl::Lower()
3173 verify_noerr( HIViewSetZOrder( m_controlRef
, kHIViewZOrderBelow
, NULL
) );
3176 void wxMacControl::GetContentArea(int &left
, int &top
, int &width
, int &height
) const
3178 RgnHandle rgn
= NewRgn() ;
3180 if ( GetControlRegion( m_controlRef
, kControlContentMetaPart
, rgn
) == noErr
)
3181 GetRegionBounds( rgn
, &content
) ;
3183 GetControlBounds( m_controlRef
, &content
);
3186 left
= content
.left
;
3189 width
= content
.right
- content
.left
;
3190 height
= content
.bottom
- content
.top
;
3193 void wxMacControl::Move(int x
, int y
, int width
, int height
)
3195 HIRect hir
= CGRectMake(x
,y
,width
,height
);
3196 HIViewSetFrame ( m_controlRef
, &hir
);
3199 void wxMacControl::GetPosition( int &x
, int &y
) const
3202 GetControlBounds( m_controlRef
, &r
);
3207 void wxMacControl::GetSize( int &width
, int &height
) const
3210 GetControlBounds( m_controlRef
, &r
);
3211 width
= r
.right
- r
.left
;
3212 height
= r
.bottom
- r
.top
;
3215 void wxMacControl::ScrollRect( const wxRect
*rect
, int dx
, int dy
)
3217 if (GetNeedsDisplay() )
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
3223 // is the better overall solution, as it does not slow down scrolling
3226 // this would be the preferred version for fast drawing controls
3227 HIViewRender(GetControlRef()) ;
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
3235 HIRect scrollarea
= CGRectMake( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3236 HIViewScrollRect ( m_controlRef
, &scrollarea
, dx
,dy
);
3239 // this would be the preferred version for fast drawing controls
3240 HIViewRender(GetControlRef()) ;
3244 bool wxMacControl::CanFocus() const
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
);
3253 if ( keyExistsAndHasValidFormat
&& fullKeyboardAccess
> 0 )
3259 UInt32 features
= 0 ;
3260 GetControlFeatures( m_controlRef
, &features
) ;
3262 return features
& ( kControlSupportsFocus
| kControlGetsFocusOnClick
) ;
3266 bool wxMacControl::GetNeedsDisplay() const
3268 return HIViewGetNeedsDisplay( m_controlRef
);
3271 void wxWidgetImpl::Convert( wxPoint
*pt
, wxWidgetImpl
*from
, wxWidgetImpl
*to
)
3277 HIViewConvertPoint( &hiPoint
, (ControlRef
) from
->GetWXWidget() , (ControlRef
) to
->GetWXWidget() );
3278 pt
->x
= (int)hiPoint
.x
;
3279 pt
->y
= (int)hiPoint
.y
;
3282 bool wxMacControl::SetFocus()
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
3287 OSStatus err
= SetKeyboardFocus( GetControlOwner( m_controlRef
), m_controlRef
, kControlFocusNextPart
);
3288 if ( err
== errCouldntSetFocus
)
3290 SetUserFocusWindow(GetControlOwner( m_controlRef
) );
3295 bool wxMacControl::HasFocus() const
3298 GetKeyboardFocus( GetUserFocusWindow() , &control
);
3299 return control
== m_controlRef
;
3303 // subclass specifics
3306 OSStatus
wxMacControl::GetData(ControlPartCode inPartCode
, ResType inTag
, Size inBufferSize
, void * inOutBuffer
, Size
* outActualSize
) const
3308 return ::GetControlData( m_controlRef
, inPartCode
, inTag
, inBufferSize
, inOutBuffer
, outActualSize
);
3311 OSStatus
wxMacControl::GetDataSize(ControlPartCode inPartCode
, ResType inTag
, Size
* outActualSize
) const
3313 return ::GetControlDataSize( m_controlRef
, inPartCode
, inTag
, outActualSize
);
3316 OSStatus
wxMacControl::SetData(ControlPartCode inPartCode
, ResType inTag
, Size inSize
, const void * inData
)
3318 return ::SetControlData( m_controlRef
, inPartCode
, inTag
, inSize
, inData
);
3321 OSStatus
wxMacControl::SendEvent( EventRef event
, OptionBits inOptions
)
3323 return SendEventToEventTargetWithOptions( event
,
3324 HIObjectGetEventTarget( (HIObjectRef
) m_controlRef
), inOptions
);
3327 OSStatus
wxMacControl::SendHICommand( HICommand
&command
, OptionBits inOptions
)
3329 wxMacCarbonEvent
event( kEventClassCommand
, kEventCommandProcess
);
3331 event
.SetParameter
<HICommand
>(kEventParamDirectObject
,command
);
3333 return SendEvent( event
, inOptions
);
3336 OSStatus
wxMacControl::SendHICommand( UInt32 commandID
, OptionBits inOptions
)
3340 memset( &command
, 0 , sizeof(command
) );
3341 command
.commandID
= commandID
;
3342 return SendHICommand( command
, inOptions
);
3345 void wxMacControl::Flash( ControlPartCode part
, UInt32 ticks
)
3347 unsigned long finalTicks
;
3349 HiliteControl( m_controlRef
, part
);
3350 Delay( ticks
, &finalTicks
);
3351 HiliteControl( m_controlRef
, kControlNoPart
);
3354 SInt32
wxMacControl::GetValue() const
3356 return ::GetControl32BitValue( m_controlRef
);
3359 SInt32
wxMacControl::GetMaximum() const
3361 return ::GetControl32BitMaximum( m_controlRef
);
3364 SInt32
wxMacControl::GetMinimum() const
3366 return ::GetControl32BitMinimum( m_controlRef
);
3369 void wxMacControl::SetValue( SInt32 v
)
3371 ::SetControl32BitValue( m_controlRef
, v
);
3374 void wxMacControl::SetMinimum( SInt32 v
)
3376 ::SetControl32BitMinimum( m_controlRef
, v
);
3379 void wxMacControl::SetMaximum( SInt32 v
)
3381 ::SetControl32BitMaximum( m_controlRef
, v
);
3384 void wxMacControl::SetValueAndRange( SInt32 value
, SInt32 minimum
, SInt32 maximum
)
3386 ::SetControl32BitMinimum( m_controlRef
, minimum
);
3387 ::SetControl32BitMaximum( m_controlRef
, maximum
);
3388 ::SetControl32BitValue( m_controlRef
, value
);
3391 void wxMacControl::VisibilityChanged(bool WXUNUSED(shown
))
3395 void wxMacControl::SuperChangedPosition()
3399 void wxMacControl::SetFont( const wxFont
& font
, const wxColour
& foreground
, long windowStyle
)
3402 #if wxOSX_USE_CORE_TEXT
3403 if ( UMAGetSystemVersion() >= 0x1050 )
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
);
3414 if ( foreground
!= *wxBLACK
)
3416 ControlFontStyleRec fontStyle
;
3417 foreground
.GetRGBColor( &fontStyle
.foreColor
);
3418 fontStyle
.flags
= kControlUseForeColorMask
;
3419 ::SetControlFontStyle( m_controlRef
, &fontStyle
);
3423 #if wxOSX_USE_ATSU_TEXT
3424 ControlFontStyleRec fontStyle
;
3425 if ( font
.MacGetThemeFontID() != kThemeCurrentPortFont
)
3427 switch ( font
.MacGetThemeFontID() )
3429 case kThemeSmallSystemFont
:
3430 fontStyle
.font
= kControlFontSmallSystemFont
;
3433 case 109 : // mini font
3434 fontStyle
.font
= -5;
3437 case kThemeSystemFont
:
3438 fontStyle
.font
= kControlFontBigSystemFont
;
3442 fontStyle
.font
= kControlFontBigSystemFont
;
3446 fontStyle
.flags
= kControlUseFontMask
;
3450 fontStyle
.font
= font
.MacGetFontNum();
3451 fontStyle
.style
= font
.MacGetFontStyle();
3452 fontStyle
.size
= font
.MacGetFontSize();
3453 fontStyle
.flags
= kControlUseFontMask
| kControlUseFaceMask
| kControlUseSizeMask
;
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
;
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
3467 if ( foreground
!= *wxBLACK
)
3469 foreground
.GetRGBColor( &fontStyle
.foreColor
);
3470 fontStyle
.flags
|= kControlUseForeColorMask
;
3473 ::SetControlFontStyle( m_controlRef
, &fontStyle
);
3477 void wxMacControl::SetBackgroundColour( const wxColour
&WXUNUSED(col
) )
3479 // HITextViewSetBackgroundColor( m_textView , color );
3482 void wxMacControl::SetRange( SInt32 minimum
, SInt32 maximum
)
3484 ::SetControl32BitMinimum( m_controlRef
, minimum
);
3485 ::SetControl32BitMaximum( m_controlRef
, maximum
);
3488 short wxMacControl::HandleKey( SInt16 keyCode
, SInt16 charCode
, EventModifiers modifiers
)
3490 return HandleControlKey( m_controlRef
, keyCode
, charCode
, modifiers
);
3493 void wxMacControl::SetActionProc( ControlActionUPP actionProc
)
3495 SetControlAction( m_controlRef
, actionProc
);
3498 void wxMacControl::SetViewSize( SInt32 viewSize
)
3500 SetControlViewSize(m_controlRef
, viewSize
);
3503 SInt32
wxMacControl::GetViewSize() const
3505 return GetControlViewSize( m_controlRef
);
3508 bool wxMacControl::IsVisible() const
3510 return IsControlVisible( m_controlRef
);
3513 void wxMacControl::SetVisibility( bool visible
)
3515 SetControlVisibility( m_controlRef
, visible
, true );
3518 bool wxMacControl::IsEnabled() const
3520 return IsControlEnabled( m_controlRef
);
3523 bool wxMacControl::IsActive() const
3525 return IsControlActive( m_controlRef
);
3528 void wxMacControl::Enable( bool enable
)
3531 EnableControl( m_controlRef
);
3533 DisableControl( m_controlRef
);
3536 void wxMacControl::SetDrawingEnabled( bool enable
)
3538 HIViewSetDrawingEnabled( m_controlRef
, enable
);
3541 void wxMacControl::GetRectInWindowCoords( Rect
*r
)
3543 GetControlBounds( m_controlRef
, r
) ;
3545 WindowRef tlwref
= GetControlOwner( m_controlRef
) ;
3547 wxNonOwnedWindow
* tlwwx
= wxNonOwnedWindow::GetFromWXWindow( (WXWindow
) tlwref
) ;
3548 if ( tlwwx
!= NULL
)
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
) ;
3557 void wxMacControl::GetBestRect( Rect
*r
)
3559 short baselineoffset
;
3561 GetBestControlRect( m_controlRef
, r
, &baselineoffset
);
3564 void wxMacControl::SetLabel( const wxString
&title
)
3566 wxFontEncoding encoding
;
3569 encoding
= m_font
.GetEncoding();
3571 encoding
= wxFont::GetDefaultEncoding();
3573 SetControlTitleWithCFString( m_controlRef
, wxCFStringRef( title
, encoding
) );
3576 void wxMacControl::GetFeatures( UInt32
* features
)
3578 GetControlFeatures( m_controlRef
, features
);
3581 OSStatus
wxMacControl::GetRegion( ControlPartCode partCode
, RgnHandle region
)
3583 OSStatus err
= GetControlRegion( m_controlRef
, partCode
, region
);
3587 // SetNeedsDisplay would not invalidate the children
3588 static void InvalidateControlAndChildren( HIViewRef control
)
3590 HIViewSetNeedsDisplay( control
, true );
3591 UInt16 childrenCount
= 0;
3592 OSStatus err
= CountSubControls( control
, &childrenCount
);
3593 if ( err
== errControlIsNotEmbedder
)
3596 wxASSERT_MSG( err
== noErr
, wxT("Unexpected error when accessing subcontrols") );
3598 for ( UInt16 i
= childrenCount
; i
>=1; --i
)
3602 err
= GetIndexedSubControl( control
, i
, & child
);
3603 if ( err
== errControlIsNotEmbedder
)
3606 InvalidateControlAndChildren( child
);
3610 void wxMacControl::InvalidateWithChildren()
3612 InvalidateControlAndChildren( m_controlRef
);
3615 OSType wxMacCreator
= 'WXMC';
3616 OSType wxMacControlProperty
= 'MCCT';
3618 void wxMacControl::SetReferenceInNativeControl()
3621 verify_noerr( SetControlProperty ( m_controlRef
,
3622 wxMacCreator
,wxMacControlProperty
, sizeof(data
), &data
) );
3625 wxMacControl
* wxMacControl::GetReferenceFromNativeControl(ControlRef control
)
3627 wxMacControl
* ctl
= NULL
;
3628 ByteCount actualSize
;
3629 if ( GetControlProperty( control
,wxMacCreator
,wxMacControlProperty
, sizeof(ctl
) ,
3630 &actualSize
, &ctl
) == noErr
)
3642 OSStatus
wxMacControl::SetTabEnabled( SInt16 tabNo
, bool enable
)
3644 return ::SetTabEnabled( m_controlRef
, tabNo
, enable
);
3651 wxWidgetImpl
* wxWidgetImpl::CreateContentView( wxNonOwnedWindow
* now
)
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
3656 wxMacControl
* contentview
= new wxMacControl(now
, true /*isRootControl*/);
3657 HIViewFindByID( HIViewGetRoot( (WindowRef
) now
->GetWXWindow() ) , kHIViewWindowContentID
,
3658 contentview
->GetControlRefAddr() ) ;
3659 if ( !contentview
->IsOk() )
3661 // compatibility mode fallback
3662 GetRootControl( (WindowRef
) now
->GetWXWindow() , contentview
->GetControlRefAddr() ) ;
3665 // the root control level handler
3666 contentview
->InstallEventHandler() ;
3670 #endif // wxOSX_USE_CARBON