+#include "wx/wxprec.h"
+
+#include "wx/window.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/log.h"
+ #include "wx/app.h"
+ #include "wx/utils.h"
+ #include "wx/panel.h"
+ #include "wx/frame.h"
+ #include "wx/dc.h"
+ #include "wx/dcclient.h"
+ #include "wx/button.h"
+ #include "wx/menu.h"
+ #include "wx/dialog.h"
+ #include "wx/settings.h"
+ #include "wx/msgdlg.h"
+ #include "wx/scrolbar.h"
+ #include "wx/statbox.h"
+ #include "wx/textctrl.h"
+ #include "wx/toolbar.h"
+ #include "wx/layout.h"
+ #include "wx/statusbr.h"
+ #include "wx/menuitem.h"
+ #include "wx/treectrl.h"
+ #include "wx/listctrl.h"
+#endif
+
+#include "wx/tooltip.h"
+#include "wx/spinctrl.h"
+#include "wx/geometry.h"
+
+#if wxUSE_LISTCTRL
+ #include "wx/listctrl.h"
+#endif
+
+#if wxUSE_TREECTRL
+ #include "wx/treectrl.h"
+#endif
+
+#if wxUSE_CARET
+ #include "wx/caret.h"
+#endif
+
+#if wxUSE_POPUPWIN
+ #include "wx/popupwin.h"
+#endif
+
+#if wxUSE_DRAG_AND_DROP
+#include "wx/dnd.h"
+#endif
+
+#include "wx/mac/uma.h"
+
+#define MAC_SCROLLBAR_SIZE 15
+#define MAC_SMALL_SCROLLBAR_SIZE 11
+
+#ifndef __DARWIN__
+#include <Windows.h>
+#include <ToolUtils.h>
+#include <MacTextEditor.h>
+#endif
+
+#if TARGET_API_MAC_OSX
+#ifndef __HIVIEW__
+ #include <HIToolbox/HIView.h>
+#endif
+#endif
+
+#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)
+#if TARGET_API_MAC_OSX
+ EVT_PAINT(wxWindowMac::OnPaint)
+#endif
+ EVT_SET_FOCUS(wxWindowMac::OnSetFocus)
+ EVT_KILL_FOCUS(wxWindowMac::OnSetFocus)
+ 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
+// ---------------------------------------------------------------------------
+
+#if TARGET_API_MAC_OSX
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3
+enum
+{
+ kEventControlVisibilityChanged = 157
+};
+#endif
+
+#endif
+
+static const EventTypeSpec eventList[] =
+{
+ { kEventClassCommand, kEventProcessCommand } ,
+ { kEventClassCommand, kEventCommandUpdateStatus } ,
+
+ { kEventClassControl , kEventControlGetClickActivation } ,
+ { kEventClassControl , kEventControlHit } ,
+
+ { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
+ { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } ,
+
+ { kEventClassControl , kEventControlDraw } ,
+#if TARGET_API_MAC_OSX
+ { kEventClassControl , kEventControlVisibilityChanged } ,
+ { kEventClassControl , kEventControlEnabledStateChanged } ,
+ { kEventClassControl , kEventControlHiliteChanged } ,
+
+ { kEventClassControl , kEventControlActivate } ,
+ { kEventClassControl , kEventControlDeactivate } ,
+#endif
+ { kEventClassControl , kEventControlSetFocusPart } ,
+
+ { 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 ) )
+ {
+#if TARGET_API_MAC_OSX
+ case kEventControlDraw :
+ {
+ RgnHandle updateRgn = NULL ;
+ RgnHandle allocatedRgn = NULL ;
+ wxRegion visRegion = thisWindow->MacGetVisibleRegion() ;
+
+ if ( cEvent.GetParameter<RgnHandle>(kEventParamRgnHandle, &updateRgn) != noErr )
+ {
+ updateRgn = (RgnHandle) visRegion.GetWXHRGN() ;
+ }
+ 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 ;
+ }
+ }
+
+ Rect rgnBounds ;
+ GetRegionBounds( updateRgn , &rgnBounds ) ;
+
+#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
+
+ {
+#if wxMAC_USE_CORE_GRAPHICS
+ bool created = false ;
+ CGContextRef cgContext = NULL ;
+ OSStatus err = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef, &cgContext) ;
+ wxASSERT_MSG( err == noErr , wxT("Unable to retrieve CGContextRef") ) ;
+ thisWindow->MacSetCGContextRef( cgContext ) ;
+
+ {
+ wxMacCGContextStateSaver sg( cgContext ) ;
+ float alpha = 1.0 ;
+ {
+ wxWindow* iter = thisWindow ;
+ while ( iter )
+ {
+ alpha *= (float) 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 );
+ }
+
+
+#endif
+ if ( thisWindow->MacDoRedraw( updateRgn , cEvent.GetTicks() ) )
+ result = noErr ;
+
+#if wxMAC_USE_CORE_GRAPHICS
+ thisWindow->MacSetCGContextRef( NULL ) ;
+ }
+
+ if ( created )
+ CGContextRelease( cgContext ) ;
+#endif
+ }
+
+ if ( allocatedRgn )
+ DisposeRgn( allocatedRgn ) ;
+ }
+ break ;
+
+ case kEventControlVisibilityChanged :
+ 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 ;
+#endif // TARGET_API_MAC_OSX
+
+ // we emulate this event under Carbon CFM
+ case kEventControlSetFocusPart :
+ {
+ Boolean focusEverything = false ;
+ ControlPartCode controlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode );
+
+#ifdef __WXMAC_OSX__
+ if ( cEvent.GetParameter<Boolean>(kEventParamControlFocusEverything , &focusEverything ) == noErr )
+ {
+ }
+#endif
+
+ if ( thisWindow->MacIsUserPane() )
+ result = noErr ;
+
+ if ( controlPart == kControlFocusNoPart )
+ {
+#if wxUSE_CARET
+ if ( thisWindow->GetCaret() )
+ thisWindow->GetCaret()->OnKillFocus();
+#endif
+
+ static bool inKillFocusEvent = false ;
+
+ if ( !inKillFocusEvent )
+ {
+ inKillFocusEvent = true ;
+ wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
+ event.SetEventObject(thisWindow);
+ thisWindow->GetEventHandler()->ProcessEvent(event) ;
+ inKillFocusEvent = false ;
+ }
+ }
+ else
+ {
+ // panel wants to track the window which was the last to have focus in it
+ wxChildFocusEvent eventFocus(thisWindow);
+ thisWindow->GetEventHandler()->ProcessEvent(eventFocus);
+
+#if wxUSE_CARET
+ if ( thisWindow->GetCaret() )
+ thisWindow->GetCaret()->OnSetFocus();
+#endif
+
+ wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
+ event.SetEventObject(thisWindow);
+ thisWindow->GetEventHandler()->ProcessEvent(event) ;
+ }
+ }
+ 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 ) ) ;