+#include "wx/mac/uma.h"
+
+#define MAC_SCROLLBAR_SIZE 15
+#define MAC_SMALL_SCROLLBAR_SIZE 11
+
+#include <string.h>
+
+#ifdef __WXUNIVERSAL__
+ IMPLEMENT_ABSTRACT_CLASS(wxWindowMac, wxWindowBase)
+#else
+ IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
+#endif
+
+BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase)
+ EVT_NC_PAINT(wxWindowMac::OnNcPaint)
+ EVT_ERASE_BACKGROUND(wxWindowMac::OnEraseBackground)
+ EVT_PAINT(wxWindowMac::OnPaint)
+ EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent)
+END_EVENT_TABLE()
+
+#define wxMAC_DEBUG_REDRAW 0
+#ifndef wxMAC_DEBUG_REDRAW
+#define wxMAC_DEBUG_REDRAW 0
+#endif
+
+// ---------------------------------------------------------------------------
+// Utility Routines to move between different coordinate systems
+// ---------------------------------------------------------------------------
+
+/*
+ * Right now we have the following setup :
+ * a border that is not part of the native control is always outside the
+ * control's border (otherwise we loose all native intelligence, future ways
+ * may be to have a second embedding control responsible for drawing borders
+ * and backgrounds eventually)
+ * so all this border calculations have to be taken into account when calling
+ * native methods or getting native oriented data
+ * so we have three coordinate systems here
+ * wx client coordinates
+ * wx window coordinates (including window frames)
+ * native coordinates
+ */
+
+//
+// originating from native control
+//
+
+
+void wxMacNativeToWindow( const wxWindow* window , RgnHandle handle )
+{
+ OffsetRgn( handle , window->MacGetLeftBorderSize() , window->MacGetTopBorderSize() ) ;
+}
+
+void wxMacNativeToWindow( const wxWindow* window , Rect *rect )
+{
+ OffsetRect( rect , window->MacGetLeftBorderSize() , window->MacGetTopBorderSize() ) ;
+}
+
+//
+// directed towards native control
+//
+
+void wxMacWindowToNative( const wxWindow* window , RgnHandle handle )
+{
+ OffsetRgn( handle , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() );
+}
+
+void wxMacWindowToNative( const wxWindow* window , Rect *rect )
+{
+ OffsetRect( rect , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() ) ;
+}
+
+// ---------------------------------------------------------------------------
+// Carbon Events
+// ---------------------------------------------------------------------------
+
+static const EventTypeSpec eventList[] =
+{
+ { kEventClassCommand, kEventProcessCommand } ,
+ { kEventClassCommand, kEventCommandUpdateStatus } ,
+
+ { kEventClassControl , kEventControlGetClickActivation } ,
+ { kEventClassControl , kEventControlHit } ,
+
+ { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
+ { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } ,
+
+ { kEventClassControl , kEventControlDraw } ,
+
+ { kEventClassControl , kEventControlVisibilityChanged } ,
+ { kEventClassControl , kEventControlEnabledStateChanged } ,
+ { kEventClassControl , kEventControlHiliteChanged } ,
+
+ { kEventClassControl , kEventControlActivate } ,
+ { kEventClassControl , kEventControlDeactivate } ,
+
+ { kEventClassControl , kEventControlSetFocusPart } ,
+ { kEventClassControl , kEventControlFocusPartChanged } ,
+
+ { kEventClassService , kEventServiceGetTypes },
+ { kEventClassService , kEventServiceCopy },
+ { kEventClassService , kEventServicePaste },
+
+// { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only
+// { kEventClassControl , kEventControlBoundsChanged } ,
+} ;
+
+static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
+{
+ OSStatus result = eventNotHandledErr ;
+
+ wxMacCarbonEvent cEvent( event ) ;
+
+ ControlRef controlRef ;
+ wxWindowMac* thisWindow = (wxWindowMac*) data ;
+
+ cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
+
+ switch ( GetEventKind( event ) )
+ {
+ case kEventControlDraw :
+ {
+ RgnHandle updateRgn = NULL ;
+ RgnHandle allocatedRgn = NULL ;
+ wxRegion visRegion = thisWindow->MacGetVisibleRegion() ;
+
+ if ( cEvent.GetParameter<RgnHandle>(kEventParamRgnHandle, &updateRgn) != noErr )
+ {
+ HIShapeGetAsQDRgn( visRegion.GetWXHRGN(), updateRgn );
+ }
+ else
+ {
+ if ( thisWindow->MacGetLeftBorderSize() != 0 || thisWindow->MacGetTopBorderSize() != 0 )
+ {
+ // as this update region is in native window locals we must adapt it to wx window local
+ allocatedRgn = NewRgn() ;
+ CopyRgn( updateRgn , allocatedRgn ) ;
+
+ // hide the given region by the new region that must be shifted
+ wxMacNativeToWindow( thisWindow , allocatedRgn ) ;
+ updateRgn = allocatedRgn ;
+ }
+ }
+
+#if wxMAC_DEBUG_REDRAW
+ if ( thisWindow->MacIsUserPane() )
+ {
+ static float color = 0.5 ;
+ static channel = 0 ;
+ HIRect bounds;
+ CGContextRef cgContext = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef) ;
+
+ HIViewGetBounds( controlRef, &bounds );
+ CGContextSetRGBFillColor( cgContext, channel == 0 ? color : 0.5 ,
+ channel == 1 ? color : 0.5 , channel == 2 ? color : 0.5 , 1 );
+ CGContextFillRect( cgContext, bounds );
+ color += 0.1 ;
+ if ( color > 0.9 )
+ {
+ color = 0.5 ;
+ channel++ ;
+ if ( channel == 3 )
+ channel = 0 ;
+ }
+ }
+#endif
+
+ {
+ bool created = false ;
+ CGContextRef cgContext = NULL ;
+ OSStatus err = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef, &cgContext) ;
+ if ( err != noErr )
+ {
+ wxFAIL_MSG("Unable to retrieve CGContextRef");
+ }
+
+ thisWindow->MacSetCGContextRef( cgContext ) ;
+
+ {
+ wxMacCGContextStateSaver sg( cgContext ) ;
+ CGFloat alpha = (CGFloat)1.0 ;
+ {
+ wxWindow* iter = thisWindow ;
+ while ( iter )
+ {
+ alpha *= (CGFloat)( iter->GetTransparent()/255.0 ) ;
+ if ( iter->IsTopLevel() )
+ iter = NULL ;
+ else
+ iter = iter->GetParent() ;
+ }
+ }
+ CGContextSetAlpha( cgContext , alpha ) ;
+
+ if ( thisWindow->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT )
+ {
+ HIRect bounds;
+ HIViewGetBounds( controlRef, &bounds );
+ CGContextClearRect( cgContext, bounds );
+ }
+
+
+
+ if ( thisWindow->MacDoRedraw( updateRgn , cEvent.GetTicks() ) )
+ result = noErr ;
+
+ thisWindow->MacSetCGContextRef( NULL ) ;
+ }
+
+ if ( created )
+ CGContextRelease( cgContext ) ;
+ }
+
+ if ( allocatedRgn )
+ DisposeRgn( allocatedRgn ) ;
+ }
+ break ;
+
+ case kEventControlVisibilityChanged :
+ // we might have two native controls attributed to the same wxWindow instance
+ // eg a scrollview and an embedded textview, make sure we only fire for the 'outer'
+ // control, as otherwise native and wx visibility are different
+ if ( thisWindow->GetPeer() != NULL && thisWindow->GetPeer()->GetControlRef() == controlRef )
+ {
+ thisWindow->MacVisibilityChanged() ;
+ }
+ break ;
+
+ case kEventControlEnabledStateChanged :
+ thisWindow->MacEnabledStateChanged();
+ break ;
+
+ case kEventControlHiliteChanged :
+ thisWindow->MacHiliteChanged() ;
+ break ;
+
+ case kEventControlActivate :
+ case kEventControlDeactivate :
+ // FIXME: we should have a virtual function for this!
+#if wxUSE_TREECTRL
+ if ( thisWindow->IsKindOf( CLASSINFO( wxTreeCtrl ) ) )
+ thisWindow->Refresh();
+#endif
+#if wxUSE_LISTCTRL
+ if ( thisWindow->IsKindOf( CLASSINFO( wxListCtrl ) ) )
+ thisWindow->Refresh();
+#endif
+ break ;
+
+ //
+ // focus handling
+ // different handling on OS X
+ //
+
+ case kEventControlFocusPartChanged :
+ // the event is emulated by wxmac for systems lower than 10.5
+ {
+ ControlPartCode previousControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPreviousPart , typeControlPartCode );
+ ControlPartCode currentControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlCurrentPart , typeControlPartCode );
+
+ if ( thisWindow->MacGetTopLevelWindow() && thisWindow->GetPeer()->NeedsFocusRect() )
+ {
+ thisWindow->MacInvalidateBorders();
+ }
+
+ if ( currentControlPart == 0 )
+ {
+ // kill focus
+#if wxUSE_CARET
+ if ( thisWindow->GetCaret() )
+ thisWindow->GetCaret()->OnKillFocus();
+#endif
+
+ wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow));
+
+ // remove this as soon as posting the synthesized event works properly
+ static bool inKillFocusEvent = false ;
+
+ if ( !inKillFocusEvent )
+ {
+ inKillFocusEvent = true ;
+ wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
+ event.SetEventObject(thisWindow);
+ thisWindow->HandleWindowEvent(event) ;
+ inKillFocusEvent = false ;
+ }
+ }
+ else if ( previousControlPart == 0 )
+ {
+ // set focus
+ // panel wants to track the window which was the last to have focus in it
+ wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow));
+ wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
+ thisWindow->HandleWindowEvent(eventFocus);
+
+#if wxUSE_CARET
+ if ( thisWindow->GetCaret() )
+ thisWindow->GetCaret()->OnSetFocus();
+#endif
+
+ wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
+ event.SetEventObject(thisWindow);
+ thisWindow->HandleWindowEvent(event) ;
+ }
+ }
+ break;
+ case kEventControlSetFocusPart :
+ {
+#ifdef __WXMAC_OSX__
+ Boolean focusEverything = false ;
+ if ( cEvent.GetParameter<Boolean>(kEventParamControlFocusEverything , &focusEverything ) == noErr )
+ {
+ // put a breakpoint here to catch focus everything events
+ }
+#endif
+ ControlPartCode controlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
+
+ ControlPartCode previousControlPart = 0;
+ verify_noerr( HIViewGetFocusPart(controlRef, &previousControlPart));
+
+ if ( thisWindow->MacIsUserPane() )
+ {
+ if ( controlPart != kControlFocusNoPart )
+ cEvent.SetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, 1 ) ;
+ result = noErr ;
+ }
+ else
+ result = CallNextEventHandler(handler, event);
+
+ if ( UMAGetSystemVersion() < 0x1050 )
+ {
+// set back to 0 if problems arise
+#if 1
+ ControlPartCode currentControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
+ // synthesize the event focus changed event
+ EventRef evRef = NULL ;
+
+ OSStatus err = MacCreateEvent(
+ NULL , kEventClassControl , kEventControlFocusPartChanged , TicksToEventTime( TickCount() ) ,
+ kEventAttributeUserEvent , &evRef );
+ verify_noerr( err );
+
+ wxMacCarbonEvent iEvent( evRef ) ;
+ iEvent.SetParameter<ControlRef>( kEventParamDirectObject , controlRef ) ;
+ iEvent.SetParameter<ControlPartCode>( kEventParamControlPreviousPart, typeControlPartCode, previousControlPart ) ;
+ iEvent.SetParameter<ControlPartCode>( kEventParamControlCurrentPart, typeControlPartCode, currentControlPart ) ;
+
+#if 0
+ // TODO test this first, avoid double posts etc...
+ PostEventToQueue( GetMainEventQueue(), evRef , kEventPriorityHigh );
+#else
+ wxMacWindowControlEventHandler( NULL , evRef , data ) ;
+#endif
+ ReleaseEvent( evRef ) ;
+#else
+ // old implementation, to be removed if the new one works
+ if ( controlPart == kControlFocusNoPart )
+ {
+#if wxUSE_CARET
+ if ( thisWindow->GetCaret() )
+ thisWindow->GetCaret()->OnKillFocus();
+#endif
+
+ wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow));
+
+ static bool inKillFocusEvent = false ;
+
+ if ( !inKillFocusEvent )
+ {
+ inKillFocusEvent = true ;
+ wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
+ event.SetEventObject(thisWindow);
+ thisWindow->HandleWindowEvent(event) ;
+ inKillFocusEvent = false ;
+ }
+ }
+ else
+ {
+ // panel wants to track the window which was the last to have focus in it
+ wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow));
+ wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
+ thisWindow->HandleWindowEvent(eventFocus);
+
+ #if wxUSE_CARET
+ if ( thisWindow->GetCaret() )
+ thisWindow->GetCaret()->OnSetFocus();
+ #endif
+
+ wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
+ event.SetEventObject(thisWindow);
+ thisWindow->HandleWindowEvent(event) ;
+ }
+#endif
+ }
+ }
+ break ;
+
+ case kEventControlHit :
+ result = thisWindow->MacControlHit( handler , event ) ;
+ break ;
+
+ case kEventControlGetClickActivation :
+ {
+ // fix to always have a proper activation for DataBrowser controls (stay in bkgnd otherwise)
+ WindowRef owner = cEvent.GetParameter<WindowRef>(kEventParamWindowRef);
+ if ( !IsWindowActive(owner) )
+ {
+ cEvent.SetParameter(kEventParamClickActivation,(UInt32) kActivateAndIgnoreClick) ;
+ result = noErr ;
+ }
+ }
+ break ;
+
+ default :
+ break ;
+ }
+
+ return result ;
+}
+
+static pascal OSStatus
+wxMacWindowServiceEventHandler(EventHandlerCallRef WXUNUSED(handler),
+ EventRef event,
+ void *data)
+{
+ OSStatus result = eventNotHandledErr ;
+
+ wxMacCarbonEvent cEvent( event ) ;
+
+ ControlRef controlRef ;
+ wxWindowMac* thisWindow = (wxWindowMac*) data ;
+ wxTextCtrl* textCtrl = wxDynamicCast( thisWindow , wxTextCtrl ) ;
+ cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
+
+ switch ( GetEventKind( event ) )
+ {
+ case kEventServiceGetTypes :
+ if ( textCtrl )
+ {
+ long from, to ;
+ textCtrl->GetSelection( &from , &to ) ;
+
+ CFMutableArrayRef copyTypes = 0 , pasteTypes = 0;
+ if ( from != to )
+ copyTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServiceCopyTypes , typeCFMutableArrayRef ) ;
+ if ( textCtrl->IsEditable() )
+ pasteTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServicePasteTypes , typeCFMutableArrayRef ) ;
+
+ static const OSType textDataTypes[] = { kTXNTextData /* , 'utxt', 'PICT', 'MooV', 'AIFF' */ };
+ for ( size_t i = 0 ; i < WXSIZEOF(textDataTypes) ; ++i )
+ {
+ CFStringRef typestring = CreateTypeStringWithOSType(textDataTypes[i]);
+ if ( typestring )
+ {
+ if ( copyTypes )
+ CFArrayAppendValue(copyTypes, typestring) ;
+ if ( pasteTypes )
+ CFArrayAppendValue(pasteTypes, typestring) ;
+
+ CFRelease( typestring ) ;
+ }
+ }
+
+ result = noErr ;
+ }
+ break ;
+
+ case kEventServiceCopy :
+ if ( textCtrl )
+ {
+ long from, to ;
+
+ textCtrl->GetSelection( &from , &to ) ;
+ wxString val = textCtrl->GetValue() ;
+ val = val.Mid( from , to - from ) ;
+ PasteboardRef pasteboard = cEvent.GetParameter<PasteboardRef>( kEventParamPasteboardRef, typePasteboardRef );
+ verify_noerr( PasteboardClear( pasteboard ) ) ;
+ PasteboardSynchronize( pasteboard );
+ // TODO add proper conversion
+ CFDataRef data = CFDataCreate( kCFAllocatorDefault, (const UInt8*)val.c_str(), val.length() );
+ PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) 1, CFSTR("com.apple.traditional-mac-plain-text"), data, 0);
+ CFRelease( data );
+ result = noErr ;
+ }
+ break ;
+
+ case kEventServicePaste :
+ if ( textCtrl )
+ {
+ PasteboardRef pasteboard = cEvent.GetParameter<PasteboardRef>( kEventParamPasteboardRef, typePasteboardRef );
+ PasteboardSynchronize( pasteboard );
+ ItemCount itemCount;
+ verify_noerr( PasteboardGetItemCount( pasteboard, &itemCount ) );
+ for( UInt32 itemIndex = 1; itemIndex <= itemCount; itemIndex++ )
+ {
+ PasteboardItemID itemID;
+ if ( PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID ) == noErr )
+ {
+ CFDataRef flavorData = NULL;
+ if ( PasteboardCopyItemFlavorData( pasteboard, itemID, CFSTR("com.apple.traditional-mac-plain-text"), &flavorData ) == noErr )
+ {
+ CFIndex flavorDataSize = CFDataGetLength( flavorData );
+ char *content = new char[flavorDataSize+1] ;
+ memcpy( content, CFDataGetBytePtr( flavorData ), flavorDataSize );
+ content[flavorDataSize]=0;
+ CFRelease( flavorData );
+#if wxUSE_UNICODE
+ textCtrl->WriteText( wxString( content , wxConvLocal ) );
+#else
+ textCtrl->WriteText( wxString( content ) ) ;
+#endif
+
+ delete[] content ;
+ result = noErr ;
+ }
+ }
+ }
+ }
+ break ;
+
+ default:
+ break ;
+ }
+
+ return result ;
+}
+
+pascal OSStatus wxMacUnicodeTextEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
+{
+ OSStatus result = eventNotHandledErr ;
+ wxWindowMac* focus = (wxWindowMac*) data ;
+
+ wchar_t* uniChars = NULL ;
+ UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
+
+ UniChar* charBuf = NULL;
+ ByteCount dataSize = 0 ;
+ int numChars = 0 ;
+ UniChar buf[2] ;
+ if ( GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr )
+ {
+ numChars = dataSize / sizeof( UniChar) + 1;
+ charBuf = buf ;
+
+ if ( (size_t) numChars * 2 > sizeof(buf) )
+ charBuf = new UniChar[ numChars ] ;
+ else
+ charBuf = buf ;
+
+ uniChars = new wchar_t[ numChars ] ;
+ GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ;
+ charBuf[ numChars - 1 ] = 0;
+#if SIZEOF_WCHAR_T == 2
+ uniChars = (wchar_t*) charBuf ;
+/* 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...)
+#else
+ // the resulting string will never have more chars than the utf16 version, so this is safe
+ wxMBConvUTF16 converter ;
+ numChars = converter.MB2WC( uniChars , (const char*)charBuf , numChars ) ;
+#endif
+ }
+
+ switch ( GetEventKind( event ) )
+ {
+ case kEventTextInputUpdateActiveInputArea :
+ {
+ // An IME input event may return several characters, but we need to send one char at a time to
+ // EVT_CHAR
+ for (int pos=0 ; pos < numChars ; pos++)
+ {
+ WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
+ WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
+ wxTheApp->MacSetCurrentEvent( event , handler ) ;
+
+ UInt32 message = uniChars[pos] < 128 ? (char)uniChars[pos] : '?';
+/*
+ NB: faking a charcode here is problematic. The kEventTextInputUpdateActiveInputArea event is sent
+ multiple times to update the active range during inline input, so this handler will often receive
+ uncommited text, which should usually not trigger side effects. It might be a good idea to check the
+ kEventParamTextInputSendFixLen parameter and verify if input is being confirmed (see CarbonEvents.h).
+ On the other hand, it can be useful for some applications to react to uncommitted text (for example,
+ to update a status display), as long as it does not disrupt the inline input session. Ideally, wx
+ should add new event types to support advanced text input. For now, I would keep things as they are.
+
+ However, the code that was being used caused additional problems:
+ UInt32 message = (0 << 8) + ((char)uniChars[pos] );
+ Since it simply truncated the unichar to the last byte, it ended up causing weird bugs with inline
+ input, such as switching to another field when one attempted to insert the character U+4E09 (the kanji
+ for "three"), because it was truncated to 09 (kTabCharCode), which was later "converted" to WXK_TAB
+ (still 09) in wxMacTranslateKey; or triggering the default button when one attempted to insert U+840D
+ (the kanji for "name"), which got truncated to 0D and interpreted as a carriage return keypress.
+ Note that even single-byte characters could have been misinterpreted, since MacRoman charcodes only
+ overlap with Unicode within the (7-bit) ASCII range.
+ But simply passing a NUL charcode would disable text updated events, because wxTextCtrl::OnChar checks
+ for codes within a specific range. Therefore I went for the solution seen above, which keeps ASCII
+ characters as they are and replaces the rest with '?', ensuring that update events are triggered.
+ It would be better to change wxTextCtrl::OnChar to look at the actual unicode character instead, but
+ I don't have time to look into that right now.
+ -- CL
+*/
+ if ( wxTheApp->MacSendCharEvent(
+ focus , message , 0 , when , 0 , 0 , uniChars[pos] ) )
+ {
+ result = noErr ;
+ }
+
+ wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
+ }
+ }
+ break ;
+ case kEventTextInputUnicodeForKeyEvent :
+ {
+ UInt32 keyCode, modifiers ;
+ Point point ;
+ EventRef rawEvent ;
+ unsigned char charCode ;
+
+ GetEventParameter( event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent ) ;
+ GetEventParameter( rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
+ GetEventParameter( rawEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
+ GetEventParameter( rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
+ GetEventParameter( rawEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
+
+ UInt32 message = (keyCode << 8) + charCode;
+
+ // An IME input event may return several characters, but we need to send one char at a time to
+ // EVT_CHAR
+ for (int pos=0 ; pos < numChars ; pos++)
+ {
+ WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
+ WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
+ wxTheApp->MacSetCurrentEvent( event , handler ) ;
+
+ if ( wxTheApp->MacSendCharEvent(
+ focus , message , modifiers , when , point.h , point.v , uniChars[pos] ) )
+ {
+ result = noErr ;
+ }
+
+ wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
+ }
+ }
+ break;
+ default:
+ break ;
+ }
+
+ delete [] uniChars ;
+ if ( charBuf != buf )
+ delete [] charBuf ;
+
+ return result ;
+}
+
+static pascal OSStatus
+wxMacWindowCommandEventHandler(EventHandlerCallRef WXUNUSED(handler),
+ EventRef event,
+ void *data)
+{
+ OSStatus result = eventNotHandledErr ;
+ wxWindowMac* focus = (wxWindowMac*) data ;
+
+ HICommand command ;
+
+ wxMacCarbonEvent cEvent( event ) ;
+ cEvent.GetParameter<HICommand>(kEventParamDirectObject,typeHICommand,&command) ;
+
+ wxMenuItem* item = NULL ;
+ wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ;
+ int id = wxMacCommandToId( command.commandID ) ;
+
+ if ( item )
+ {
+ wxASSERT( itemMenu != NULL ) ;
+
+ switch ( cEvent.GetKind() )
+ {
+ case kEventProcessCommand :
+ result = itemMenu->MacHandleCommandProcess( item, id, focus );
+ break ;
+
+ case kEventCommandUpdateStatus:
+ result = itemMenu->MacHandleCommandUpdateStatus( item, id, focus );
+ break ;
+
+ default :
+ break ;
+ }
+ }
+ return result ;
+}
+
+pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
+{
+ EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
+ EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ;
+ wxTheApp->MacSetCurrentEvent( event , handler ) ;
+ OSStatus result = eventNotHandledErr ;
+
+ switch ( GetEventClass( event ) )
+ {
+ case kEventClassCommand :
+ result = wxMacWindowCommandEventHandler( handler , event , data ) ;
+ break ;
+
+ case kEventClassControl :
+ result = wxMacWindowControlEventHandler( handler, event, data ) ;
+ break ;
+
+ case kEventClassService :
+ result = wxMacWindowServiceEventHandler( handler, event , data ) ;
+ break ;
+
+ case kEventClassTextInput :
+ result = wxMacUnicodeTextEventHandler( handler , event , data ) ;
+ break ;
+
+ default :
+ break ;
+ }
+
+ wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ;
+
+ return result ;
+}
+
+DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler )
+
+// ---------------------------------------------------------------------------
+// Scrollbar Tracking for all
+// ---------------------------------------------------------------------------
+
+pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode ) ;
+pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode )
+{
+ if ( partCode != 0)
+ {
+ wxWindow* wx = wxFindControlFromMacControl( control ) ;
+ if ( wx )
+ wx->MacHandleControlClick( (WXWidget) control , partCode , true /* stillDown */ ) ;
+ }
+}
+wxMAC_DEFINE_PROC_GETTER( ControlActionUPP , wxMacLiveScrollbarActionProc ) ;
+
+// ===========================================================================
+// implementation
+// ===========================================================================
+
+WX_DECLARE_HASH_MAP(ControlRef, wxWindow*, wxPointerHash, wxPointerEqual, MacControlMap);
+
+static MacControlMap wxWinMacControlList;
+
+wxWindow *wxFindControlFromMacControl(ControlRef inControl )
+{
+ MacControlMap::iterator node = wxWinMacControlList.find(inControl);
+
+ return (node == wxWinMacControlList.end()) ? NULL : node->second;
+}
+
+void wxAssociateControlWithMacControl(ControlRef inControl, wxWindow *control)
+{
+ // adding NULL ControlRef is (first) surely a result of an error and
+ // (secondly) breaks native event processing
+ wxCHECK_RET( inControl != (ControlRef) NULL, wxT("attempt to add a NULL WindowRef to window list") );
+
+ wxWinMacControlList[inControl] = control;
+}
+
+void wxRemoveMacControlAssociation(wxWindow *control)
+{
+ // iterate over all the elements in the class
+ // is the iterator stable ? as we might have two associations pointing to the same wxWindow
+ // we should go on...
+
+ bool found = true ;
+ while ( found )
+ {
+ found = false ;
+ MacControlMap::iterator it;
+ for ( it = wxWinMacControlList.begin(); it != wxWinMacControlList.end(); ++it )
+ {
+ if ( it->second == control )
+ {
+ wxWinMacControlList.erase(it);
+ found = true ;
+ break;
+ }
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+ // constructors and such
+// ----------------------------------------------------------------------------
+
+wxWindowMac::wxWindowMac()
+{
+ Init();
+}
+
+wxWindowMac::wxWindowMac(wxWindowMac *parent,
+ wxWindowID id,
+ const wxPoint& pos ,
+ const wxSize& size ,
+ long style ,
+ const wxString& name )
+{
+ Init();
+ Create(parent, id, pos, size, style, name);
+}
+
+void wxWindowMac::Init()
+{
+ m_peer = NULL ;
+ m_macAlpha = 255 ;
+ m_cgContextRef = NULL ;
+
+ // as all windows are created with WS_VISIBLE style...
+ m_isShown = true;
+
+ m_hScrollBar = NULL ;
+ m_vScrollBar = NULL ;
+ m_hScrollBarAlwaysShown = false;
+ m_vScrollBarAlwaysShown = false;
+
+ m_macIsUserPane = true;
+ m_clipChildren = false ;
+ m_cachedClippedRectValid = false ;
+}
+
+wxWindowMac::~wxWindowMac()
+{
+ SendDestroyEvent();
+
+ m_isBeingDeleted = true;
+
+ MacInvalidateBorders() ;
+
+#ifndef __WXUNIVERSAL__
+ // VS: make sure there's no wxFrame with last focus set to us:
+ for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
+ {
+ wxFrame *frame = wxDynamicCast(win, wxFrame);
+ if ( frame )
+ {
+ if ( frame->GetLastFocus() == this )
+ frame->SetLastFocus((wxWindow*)NULL);
+ break;
+ }
+ }
+#endif
+
+ // destroy children before destroying this window itself
+ DestroyChildren();
+
+ // wxRemoveMacControlAssociation( this ) ;
+ // If we delete an item, we should initialize the parent panel,
+ // because it could now be invalid.
+ wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
+ if ( tlw )
+ {
+ if ( tlw->GetDefaultItem() == (wxButton*) this)
+ tlw->SetDefaultItem(NULL);
+ }
+
+ if ( m_peer && m_peer->Ok() )
+ {
+ // in case the callback might be called during destruction
+ wxRemoveMacControlAssociation( this) ;
+ ::RemoveEventHandler( (EventHandlerRef ) m_macControlEventHandler ) ;
+ // we currently are not using this hook
+ // ::SetControlColorProc( *m_peer , NULL ) ;
+ m_peer->Dispose() ;
+ }
+
+ if ( g_MacLastWindow == this )
+ g_MacLastWindow = NULL ;
+
+#ifndef __WXUNIVERSAL__
+ wxFrame* frame = wxDynamicCast( wxGetTopLevelParent( (wxWindow*)this ) , wxFrame ) ;
+ if ( frame )
+ {
+ if ( frame->GetLastFocus() == this )
+ frame->SetLastFocus( NULL ) ;
+ }
+#endif
+
+ // delete our drop target if we've got one
+#if wxUSE_DRAG_AND_DROP
+ if ( m_dropTarget != NULL )
+ {
+ delete m_dropTarget;
+ m_dropTarget = NULL;
+ }
+#endif
+
+ delete m_peer ;
+}
+
+WXWidget wxWindowMac::GetHandle() const
+{
+ return (WXWidget) m_peer->GetControlRef() ;
+}
+
+void wxWindowMac::MacInstallEventHandler( WXWidget control )
+{
+ wxAssociateControlWithMacControl( (ControlRef) control , this ) ;
+ InstallControlEventHandler( (ControlRef)control , GetwxMacWindowEventHandlerUPP(),
+ GetEventTypeCount(eventList), eventList, this,
+ (EventHandlerRef *)&m_macControlEventHandler);
+}
+
+// Constructor
+bool wxWindowMac::Create(wxWindowMac *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name)
+{
+ wxCHECK_MSG( parent, false, wxT("can't create wxWindowMac without parent") );
+
+ if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
+ return false;
+
+ m_windowVariant = parent->GetWindowVariant() ;
+
+ if ( m_macIsUserPane )
+ {
+ Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
+
+ UInt32 features = 0
+ | kControlSupportsEmbedding
+ | kControlSupportsLiveFeedback
+ | kControlGetsFocusOnClick
+// | kControlHasSpecialBackground
+// | kControlSupportsCalcBestRect
+ | kControlHandlesTracking
+ | kControlSupportsFocus
+ | kControlWantsActivate
+ | kControlWantsIdle ;
+
+ m_peer = new wxMacControl(this) ;
+ OSStatus err =::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds, features , m_peer->GetControlRefAddr() );
+ verify_noerr( err );
+
+ MacPostControlCreate(pos, size) ;
+ }
+
+#ifndef __WXUNIVERSAL__
+ // Don't give scrollbars to wxControls unless they ask for them
+ if ( (! IsKindOf(CLASSINFO(wxControl)) && ! IsKindOf(CLASSINFO(wxStatusBar)))
+ || (IsKindOf(CLASSINFO(wxControl)) && ((style & wxHSCROLL) || (style & wxVSCROLL))))
+ {
+ MacCreateScrollBars( style ) ;
+ }
+#endif
+
+ wxWindowCreateEvent event(this);
+ GetEventHandler()->AddPendingEvent(event);
+
+ return true;
+}
+
+void wxWindowMac::MacChildAdded()
+{
+ if ( m_vScrollBar )
+ m_vScrollBar->Raise() ;
+ if ( m_hScrollBar )
+ m_hScrollBar->Raise() ;
+}
+
+void wxWindowMac::MacPostControlCreate(const wxPoint& WXUNUSED(pos), const wxSize& size)
+{
+ wxASSERT_MSG( m_peer != NULL && m_peer->Ok() , wxT("No valid mac control") ) ;
+
+ m_peer->SetReference( (URefCon) this ) ;
+ GetParent()->AddChild( this );
+
+ MacInstallEventHandler( (WXWidget) m_peer->GetControlRef() );
+
+ ControlRef container = (ControlRef) GetParent()->GetHandle() ;
+ wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
+ ::EmbedControl( m_peer->GetControlRef() , container ) ;
+ GetParent()->MacChildAdded() ;
+
+ // adjust font, controlsize etc
+ DoSetWindowVariant( m_windowVariant ) ;
+
+ m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ;
+
+ if (!m_macIsUserPane)
+ SetInitialSize(size);
+
+ SetCursor( *wxSTANDARD_CURSOR ) ;
+}
+
+void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant )
+{
+ // Don't assert, in case we set the window variant before
+ // the window is created
+ // wxASSERT( m_peer->Ok() ) ;
+
+ m_windowVariant = variant ;
+
+ if (m_peer == NULL || !m_peer->Ok())
+ return;
+
+ ControlSize size ;
+ ThemeFontID themeFont = kThemeSystemFont ;
+
+ // we will get that from the settings later
+ // and make this NORMAL later, but first
+ // we have a few calculations that we must fix
+
+ switch ( variant )
+ {
+ case wxWINDOW_VARIANT_NORMAL :
+ size = kControlSizeNormal;
+ themeFont = kThemeSystemFont ;
+ break ;
+
+ case wxWINDOW_VARIANT_SMALL :
+ size = kControlSizeSmall;
+ themeFont = kThemeSmallSystemFont ;
+ break ;
+
+ case wxWINDOW_VARIANT_MINI :
+ // not always defined in the headers
+ size = 3 ;
+ themeFont = 109 ;
+ break ;
+
+ case wxWINDOW_VARIANT_LARGE :
+ size = kControlSizeLarge;
+ themeFont = kThemeSystemFont ;
+ break ;
+
+ default:
+ wxFAIL_MSG(_T("unexpected window variant"));
+ break ;
+ }
+
+ m_peer->SetData<ControlSize>(kControlEntireControl, kControlSizeTag, &size ) ;
+
+ wxFont font ;
+ font.MacCreateFromThemeFont( themeFont ) ;
+ SetFont( font ) ;
+}
+
+void wxWindowMac::MacUpdateControlFont()
+{
+ m_peer->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ;
+ // do not trigger refreshes upon invisible and possible partly created objects
+ if ( IsShownOnScreen() )
+ Refresh() ;
+}
+
+bool wxWindowMac::SetFont(const wxFont& font)
+{
+ bool retval = wxWindowBase::SetFont( font );
+
+ MacUpdateControlFont() ;
+
+ return retval;
+}
+
+bool wxWindowMac::SetForegroundColour(const wxColour& col )
+{
+ bool retval = wxWindowBase::SetForegroundColour( col );
+
+ if (retval)
+ MacUpdateControlFont();
+
+ return retval;
+}
+
+bool wxWindowMac::SetBackgroundColour(const wxColour& col )
+{
+ if ( !wxWindowBase::SetBackgroundColour(col) && m_hasBgCol )
+ return false ;
+
+ m_peer->SetBackgroundColour( col ) ;
+
+ return true ;
+}
+
+bool wxWindowMac::MacCanFocus() const
+{
+ // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so
+ // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning,
+ // but the value range is nowhere documented
+ Boolean keyExistsAndHasValidFormat ;
+ CFIndex fullKeyboardAccess = CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) ,
+ kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat );
+
+ if ( keyExistsAndHasValidFormat && fullKeyboardAccess > 0 )
+ {
+ return true ;
+ }
+ else
+ {
+ UInt32 features = 0 ;
+ m_peer->GetFeatures( &features ) ;
+
+ return features & ( kControlSupportsFocus | kControlGetsFocusOnClick ) ;
+ }
+}
+
+void wxWindowMac::SetFocus()
+{
+ if ( !AcceptsFocus() )
+ return ;
+
+ wxWindow* former = FindFocus() ;
+ if ( former == this )
+ return ;
+
+ // as we cannot rely on the control features to find out whether we are in full keyboard mode,
+ // we can only leave in case of an error
+ OSStatus err = m_peer->SetFocus( kControlFocusNextPart ) ;
+ if ( err == errCouldntSetFocus )
+ return ;
+
+ SetUserFocusWindow( (WindowRef)MacGetTopLevelWindowRef() );
+}
+
+void wxWindowMac::DoCaptureMouse()
+{
+ wxApp::s_captureWindow = this ;
+}
+
+wxWindow * wxWindowBase::GetCapture()
+{
+ return wxApp::s_captureWindow ;
+}
+
+void wxWindowMac::DoReleaseMouse()
+{
+ wxApp::s_captureWindow = NULL ;
+}
+
+#if wxUSE_DRAG_AND_DROP
+
+void wxWindowMac::SetDropTarget(wxDropTarget *pDropTarget)
+{
+ if ( m_dropTarget != NULL )
+ delete m_dropTarget;
+
+ m_dropTarget = pDropTarget;
+ if ( m_dropTarget != NULL )
+ {
+ // TODO:
+ }
+}
+
+#endif
+
+// Old-style File Manager Drag & Drop
+void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept))
+{
+ // TODO:
+}
+
+// Returns the size of the native control. In the case of the toplevel window
+// this is the content area root control
+
+void wxWindowMac::MacGetPositionAndSizeFromControl(int& WXUNUSED(x),
+ int& WXUNUSED(y),
+ int& WXUNUSED(w),
+ int& WXUNUSED(h)) const
+{
+ wxFAIL_MSG( wxT("Not currently supported") ) ;
+}
+
+// From a wx position / size calculate the appropriate size of the native control
+
+bool wxWindowMac::MacGetBoundsForControl(
+ const wxPoint& pos,
+ const wxSize& size,
+ int& x, int& y,
+ int& w, int& h , bool adjustOrigin ) const
+{
+ // the desired size, minus the border pixels gives the correct size of the control
+ x = (int)pos.x;
+ y = (int)pos.y;
+
+ // TODO: the default calls may be used as soon as PostCreateControl Is moved here
+ w = wxMax(size.x, 0) ; // WidthDefault( size.x );
+ h = wxMax(size.y, 0) ; // HeightDefault( size.y ) ;
+
+ x += MacGetLeftBorderSize() ;
+ y += MacGetTopBorderSize() ;
+ w -= MacGetLeftBorderSize() + MacGetRightBorderSize() ;
+ h -= MacGetTopBorderSize() + MacGetBottomBorderSize() ;
+
+ if ( adjustOrigin )
+ AdjustForParentClientOrigin( x , y ) ;
+
+ // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border
+ if ( !GetParent()->IsTopLevel() )
+ {
+ x -= GetParent()->MacGetLeftBorderSize() ;
+ y -= GetParent()->MacGetTopBorderSize() ;
+ }
+
+ return true ;
+}
+
+// Get window size (not client size)
+void wxWindowMac::DoGetSize(int *x, int *y) const
+{
+ Rect bounds ;
+ m_peer->GetRect( &bounds ) ;
+
+ if (x)
+ *x = bounds.right - bounds.left + MacGetLeftBorderSize() + MacGetRightBorderSize() ;
+ if (y)
+ *y = bounds.bottom - bounds.top + MacGetTopBorderSize() + MacGetBottomBorderSize() ;
+}
+
+// get the position of the bounds of this window in client coordinates of its parent
+void wxWindowMac::DoGetPosition(int *x, int *y) const
+{
+ Rect bounds ;
+ m_peer->GetRect( &bounds ) ;
+
+ int x1 = bounds.left ;
+ int y1 = bounds.top ;
+
+ // get the wx window position from the native one
+ x1 -= MacGetLeftBorderSize() ;
+ y1 -= MacGetTopBorderSize() ;
+
+ if ( !IsTopLevel() )
+ {
+ wxWindow *parent = GetParent();
+ if ( parent )
+ {
+ // we must first adjust it to be in window coordinates of the parent,
+ // as otherwise it gets lost by the ClientAreaOrigin fix
+ x1 += parent->MacGetLeftBorderSize() ;
+ y1 += parent->MacGetTopBorderSize() ;
+
+ // and now to client coordinates
+ wxPoint pt(parent->GetClientAreaOrigin());
+ x1 -= pt.x ;
+ y1 -= pt.y ;
+ }
+ }
+
+ if (x)
+ *x = x1 ;
+ if (y)
+ *y = y1 ;
+}
+
+void wxWindowMac::DoScreenToClient(int *x, int *y) const
+{
+ WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
+ wxCHECK_RET( window , wxT("TopLevel Window missing") ) ;
+
+ Point localwhere = { 0, 0 } ;
+
+ if (x)
+ localwhere.h = *x ;
+ if (y)
+ localwhere.v = *y ;
+
+ wxMacGlobalToLocal( window , &localwhere ) ;
+
+ if (x)
+ *x = localwhere.h ;
+ if (y)
+ *y = localwhere.v ;
+
+ MacRootWindowToWindow( x , y ) ;
+
+ wxPoint origin = GetClientAreaOrigin() ;
+ if (x)
+ *x -= origin.x ;
+ if (y)
+ *y -= origin.y ;
+}
+
+void wxWindowMac::DoClientToScreen(int *x, int *y) const
+{
+ WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ;
+ wxCHECK_RET( window , wxT("TopLevel window missing") ) ;
+
+ wxPoint origin = GetClientAreaOrigin() ;
+ if (x)
+ *x += origin.x ;
+ if (y)
+ *y += origin.y ;
+
+ MacWindowToRootWindow( x , y ) ;
+
+ Point localwhere = { 0, 0 };
+ if (x)
+ localwhere.h = *x ;
+ if (y)
+ localwhere.v = *y ;
+
+ wxMacLocalToGlobal( window, &localwhere ) ;
+
+ if (x)
+ *x = localwhere.h ;
+ if (y)
+ *y = localwhere.v ;
+}
+
+void wxWindowMac::MacClientToRootWindow( int *x , int *y ) const
+{
+ wxPoint origin = GetClientAreaOrigin() ;
+ if (x)
+ *x += origin.x ;
+ if (y)
+ *y += origin.y ;
+
+ MacWindowToRootWindow( x , y ) ;
+}
+
+void wxWindowMac::MacRootWindowToClient( int *x , int *y ) const
+{
+ MacRootWindowToWindow( x , y ) ;
+
+ wxPoint origin = GetClientAreaOrigin() ;
+ if (x)
+ *x -= origin.x ;
+ if (y)
+ *y -= origin.y ;
+}
+
+void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const
+{
+ wxPoint pt ;
+
+ if (x)
+ pt.x = *x ;
+ if (y)
+ pt.y = *y ;
+
+ if ( !IsTopLevel() )
+ {
+ wxTopLevelWindowMac* top = MacGetTopLevelWindow();
+ if (top)
+ {
+ pt.x -= MacGetLeftBorderSize() ;
+ pt.y -= MacGetTopBorderSize() ;
+ wxMacControl::Convert( &pt , m_peer , top->m_peer ) ;
+ }
+ }
+
+ if (x)
+ *x = (int) pt.x ;
+ if (y)
+ *y = (int) pt.y ;
+}
+
+void wxWindowMac::MacWindowToRootWindow( short *x , short *y ) const
+{
+ int x1 , y1 ;
+
+ if (x)
+ x1 = *x ;
+ if (y)
+ y1 = *y ;
+
+ MacWindowToRootWindow( &x1 , &y1 ) ;
+
+ if (x)
+ *x = x1 ;
+ if (y)
+ *y = y1 ;
+}
+
+void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const
+{
+ wxPoint pt ;
+
+ if (x)
+ pt.x = *x ;
+ if (y)
+ pt.y = *y ;
+
+ if ( !IsTopLevel() )
+ {
+ wxTopLevelWindowMac* top = MacGetTopLevelWindow();
+ if (top)
+ {
+ wxMacControl::Convert( &pt , top->m_peer , m_peer ) ;
+ pt.x += MacGetLeftBorderSize() ;
+ pt.y += MacGetTopBorderSize() ;
+ }
+ }
+
+ if (x)
+ *x = (int) pt.x ;
+ if (y)
+ *y = (int) pt.y ;
+}
+
+void wxWindowMac::MacRootWindowToWindow( short *x , short *y ) const
+{
+ int x1 , y1 ;
+
+ if (x)
+ x1 = *x ;
+ if (y)
+ y1 = *y ;
+
+ MacRootWindowToWindow( &x1 , &y1 ) ;
+
+ if (x)
+ *x = x1 ;
+ if (y)
+ *y = y1 ;
+}
+
+void wxWindowMac::MacGetContentAreaInset( int &left , int &top , int &right , int &bottom )
+{
+ RgnHandle rgn = NewRgn() ;
+
+ if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
+ {
+ Rect structure, content ;
+
+ GetRegionBounds( rgn , &content ) ;
+ m_peer->GetRect( &structure ) ;
+ OffsetRect( &structure, -structure.left , -structure.top ) ;
+
+ left = content.left - structure.left ;
+ top = content.top - structure.top ;
+ right = structure.right - content.right ;
+ bottom = structure.bottom - content.bottom ;
+ }
+ else
+ {
+ left = top = right = bottom = 0 ;
+ }
+
+ DisposeRgn( rgn ) ;
+}
+
+wxSize wxWindowMac::DoGetSizeFromClientSize( const wxSize & size ) const
+{
+ wxSize sizeTotal = size;
+
+ RgnHandle rgn = NewRgn() ;
+ if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
+ {
+ Rect content, structure ;
+ GetRegionBounds( rgn , &content ) ;
+ m_peer->GetRect( &structure ) ;
+
+ // structure is in parent coordinates, but we only need width and height, so it's ok
+
+ sizeTotal.x += (structure.right - structure.left) - (content.right - content.left) ;
+ sizeTotal.y += (structure.bottom - structure.top) - (content.bottom - content.top) ;
+ }
+
+ DisposeRgn( rgn ) ;
+
+ sizeTotal.x += MacGetLeftBorderSize() + MacGetRightBorderSize() ;
+ sizeTotal.y += MacGetTopBorderSize() + MacGetBottomBorderSize() ;
+
+ return sizeTotal;
+}
+
+// Get size *available for subwindows* i.e. excluding menu bar etc.
+void wxWindowMac::DoGetClientSize( int *x, int *y ) const
+{
+ int ww, hh;
+
+ RgnHandle rgn = NewRgn() ;
+ Rect content ;
+ if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr )
+ GetRegionBounds( rgn , &content ) ;
+ else
+ m_peer->GetRect( &content ) ;
+ DisposeRgn( rgn ) ;
+
+ ww = content.right - content.left ;
+ hh = content.bottom - content.top ;
+
+ if (m_hScrollBar && m_hScrollBar->IsShown() )
+ hh -= m_hScrollBar->GetSize().y ;
+
+ if (m_vScrollBar && m_vScrollBar->IsShown() )
+ ww -= m_vScrollBar->GetSize().x ;
+
+ if (x)
+ *x = ww;
+ if (y)
+ *y = hh;
+}
+
+bool wxWindowMac::SetCursor(const wxCursor& cursor)
+{
+ if (m_cursor.IsSameAs(cursor))
+ return false;
+
+ if (!cursor.IsOk())
+ {
+ if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR ) )
+ return false ;
+ }
+ else
+ {
+ if ( ! wxWindowBase::SetCursor( cursor ) )
+ return false ;
+ }
+
+ wxASSERT_MSG( m_cursor.Ok(),
+ wxT("cursor must be valid after call to the base version"));
+
+ wxWindowMac *mouseWin = 0 ;
+ {
+ wxTopLevelWindowMac *tlw = MacGetTopLevelWindow() ;
+ WindowRef window = (WindowRef) ( tlw ? tlw->MacGetWindowRef() : 0 ) ;
+
+ ControlPartCode part ;
+ ControlRef control ;
+ Point pt ;
+ #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
+ HIPoint hiPoint ;
+ HIGetMousePosition(kHICoordSpaceWindow, window, &hiPoint);
+ pt.h = hiPoint.x;
+ pt.v = hiPoint.y;
+ #else
+ GetGlobalMouse( &pt );
+ int x = pt.h;
+ int y = pt.v;
+ ScreenToClient(&x, &y);
+ pt.h = x;
+ pt.v = y;
+#endif
+ control = FindControlUnderMouse( pt , window , &part ) ;
+ if ( control )
+ mouseWin = wxFindControlFromMacControl( control ) ;
+
+ }
+
+ if ( mouseWin == this && !wxIsBusy() )
+ m_cursor.MacInstall() ;
+
+ return true ;
+}
+
+#if wxUSE_MENUS
+bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y)
+{
+#ifndef __WXUNIVERSAL__
+ menu->SetInvokingWindow((wxWindow*)this);
+ menu->UpdateUI();
+
+ if ( x == wxDefaultCoord && y == wxDefaultCoord )
+ {
+ wxPoint mouse = wxGetMousePosition();
+ x = mouse.x;
+ y = mouse.y;
+ }
+ else
+ {
+ ClientToScreen( &x , &y ) ;
+ }