+
+ wxevent.m_clickCount = clickCount;
+ wxWindowMac* peer = GetWXPeer();
+ if ( peer )
+ {
+ wxevent.SetEventObject(peer);
+ wxevent.SetId(peer->GetId()) ;
+ }
+}
+
+@implementation wxNSView
+
++ (void)initialize
+{
+ static BOOL initialized = NO;
+ if (!initialized)
+ {
+ initialized = YES;
+ wxOSXCocoaClassAddWXMethods( self );
+ }
+}
+
+/* idea taken from webkit sources: overwrite the methods that (private) NSToolTipManager will use to attach its tracking rectangle
+ * then when changing the tooltip send fake view-exit and view-enter methods which will lead to a tooltip refresh
+ */
+
+
+- (void)_sendToolTipMouseExited
+{
+ // Nothing matters except window, trackingNumber, and userData.
+ NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseExited
+ location:NSMakePoint(0, 0)
+ modifierFlags:0
+ timestamp:0
+ windowNumber:[[self window] windowNumber]
+ context:NULL
+ eventNumber:0
+ trackingNumber:_lastToolTipTrackTag
+ userData:_lastUserData];
+ [_lastToolTipOwner mouseExited:fakeEvent];
+}
+
+- (void)_sendToolTipMouseEntered
+{
+ // Nothing matters except window, trackingNumber, and userData.
+ NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseEntered
+ location:NSMakePoint(0, 0)
+ modifierFlags:0
+ timestamp:0
+ windowNumber:[[self window] windowNumber]
+ context:NULL
+ eventNumber:0
+ trackingNumber:_lastToolTipTrackTag
+ userData:_lastUserData];
+ [_lastToolTipOwner mouseEntered:fakeEvent];
+}
+
+- (void)setToolTip:(NSString *)string;
+{
+ if (string)
+ {
+ if ( _hasToolTip )
+ {
+ [self _sendToolTipMouseExited];
+ }
+
+ [super setToolTip:string];
+ _hasToolTip = YES;
+ [self _sendToolTipMouseEntered];
+ }
+ else
+ {
+ if ( _hasToolTip )
+ {
+ [self _sendToolTipMouseExited];
+ [super setToolTip:nil];
+ _hasToolTip = NO;
+ }
+ }
+}
+
+- (NSTrackingRectTag)addTrackingRect:(NSRect)rect owner:(id)owner userData:(void *)data assumeInside:(BOOL)assumeInside
+{
+ NSTrackingRectTag tag = [super addTrackingRect:rect owner:owner userData:data assumeInside:assumeInside];
+ if ( owner != self )
+ {
+ _lastUserData = data;
+ _lastToolTipOwner = owner;
+ _lastToolTipTrackTag = tag;
+ }
+ return tag;
+}
+
+- (void)removeTrackingRect:(NSTrackingRectTag)tag
+{
+ if (tag == _lastToolTipTrackTag)
+ {
+ _lastUserData = NULL;
+ _lastToolTipOwner = nil;
+ _lastToolTipTrackTag = 0;
+ }
+ [super removeTrackingRect:tag];
+}
+@end // wxNSView
+
+//
+// event handlers
+//
+
+#if wxUSE_DRAG_AND_DROP
+
+// see http://lists.apple.com/archives/Cocoa-dev/2005/Jul/msg01244.html
+// for details on the NSPasteboard -> PasteboardRef conversion
+
+NSDragOperation wxOSX_draggingEntered( id self, SEL _cmd, id <NSDraggingInfo>sender )
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return NSDragOperationNone;
+
+ return impl->draggingEntered(sender, self, _cmd);
+}
+
+void wxOSX_draggingExited( id self, SEL _cmd, id <NSDraggingInfo> sender )
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return ;
+
+ return impl->draggingExited(sender, self, _cmd);
+}
+
+NSDragOperation wxOSX_draggingUpdated( id self, SEL _cmd, id <NSDraggingInfo>sender )
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return NSDragOperationNone;
+
+ return impl->draggingUpdated(sender, self, _cmd);
+}
+
+BOOL wxOSX_performDragOperation( id self, SEL _cmd, id <NSDraggingInfo> sender )
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return NSDragOperationNone;
+
+ return impl->performDragOperation(sender, self, _cmd) ? YES:NO ;
+}
+
+#endif
+
+void wxOSX_mouseEvent(NSView* self, SEL _cmd, NSEvent *event)
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return;
+
+ impl->mouseEvent(event, self, _cmd);
+}
+
+void wxOSX_cursorUpdate(NSView* self, SEL _cmd, NSEvent *event)
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return;
+
+ impl->cursorUpdate(event, self, _cmd);
+}
+
+BOOL wxOSX_acceptsFirstMouse(NSView* WXUNUSED(self), SEL WXUNUSED(_cmd), NSEvent *WXUNUSED(event))
+{
+ // This is needed to support click through, otherwise the first click on a window
+ // will not do anything unless it is the active window already.
+ return YES;
+}
+
+void wxOSX_keyEvent(NSView* self, SEL _cmd, NSEvent *event)
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return;
+
+ impl->keyEvent(event, self, _cmd);
+}
+
+void wxOSX_insertText(NSView* self, SEL _cmd, NSString* text)
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return;
+
+ impl->insertText(text, self, _cmd);
+}
+
+BOOL wxOSX_performKeyEquivalent(NSView* self, SEL _cmd, NSEvent *event)
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return NO;
+
+ return impl->performKeyEquivalent(event, self, _cmd);
+}
+
+BOOL wxOSX_acceptsFirstResponder(NSView* self, SEL _cmd)
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return NO;
+
+ return impl->acceptsFirstResponder(self, _cmd);
+}
+
+BOOL wxOSX_becomeFirstResponder(NSView* self, SEL _cmd)
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return NO;
+
+ return impl->becomeFirstResponder(self, _cmd);
+}
+
+BOOL wxOSX_resignFirstResponder(NSView* self, SEL _cmd)
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return NO;
+
+ return impl->resignFirstResponder(self, _cmd);
+}
+
+BOOL wxOSX_isFlipped(NSView* self, SEL _cmd)
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return NO;
+
+ return impl->isFlipped(self, _cmd) ? YES:NO;
+}
+
+typedef void (*wxOSX_DrawRectHandlerPtr)(NSView* self, SEL _cmd, NSRect rect);
+
+void wxOSX_drawRect(NSView* self, SEL _cmd, NSRect rect)
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return;
+
+#if wxUSE_THREADS
+ // OS X starts a NSUIHeartBeatThread for animating the default button in a
+ // dialog. This causes a drawRect of the active dialog from outside the
+ // main UI thread. This causes an occasional crash since the wx drawing
+ // objects (like wxPen) are not thread safe.
+ //
+ // Notice that NSUIHeartBeatThread seems to be undocumented and doing
+ // [NSWindow setAllowsConcurrentViewDrawing:NO] does not affect it.
+ if ( !wxThread::IsMain() )
+ {
+ if ( impl->IsUserPane() )
+ {
+ wxWindow* win = impl->GetWXPeer();
+ if ( win->UseBgCol() )
+ {
+
+ CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
+ CGContextSaveGState( context );
+
+ CGContextSetFillColorWithColor( context, win->GetBackgroundColour().GetCGColor());
+ CGRect r = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
+ CGContextFillRect( context, r );
+
+ CGContextRestoreGState( context );
+ }
+ }
+ else
+ {
+ // just call the superclass handler, we don't need any custom wx drawing
+ // here and it seems to work fine:
+ wxOSX_DrawRectHandlerPtr
+ superimpl = (wxOSX_DrawRectHandlerPtr)
+ [[self superclass] instanceMethodForSelector:_cmd];
+ superimpl(self, _cmd, rect);
+ }
+
+ return;
+ }
+#endif // wxUSE_THREADS
+
+ return impl->drawRect(&rect, self, _cmd);
+}
+
+void wxOSX_controlAction(NSView* self, SEL _cmd, id sender)
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return;
+
+ impl->controlAction(self, _cmd, sender);
+}
+
+void wxOSX_controlDoubleAction(NSView* self, SEL _cmd, id sender)
+{
+ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
+ if (impl == NULL)
+ return;
+
+ impl->controlDoubleAction(self, _cmd, sender);
+}
+
+unsigned int wxWidgetCocoaImpl::draggingEntered(void* s, WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
+{
+ id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
+ NSPasteboard *pboard = [sender draggingPasteboard];
+ NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
+
+ wxWindow* wxpeer = GetWXPeer();
+ if ( wxpeer == NULL )
+ return NSDragOperationNone;
+
+ wxDropTarget* target = wxpeer->GetDropTarget();
+ if ( target == NULL )
+ return NSDragOperationNone;
+
+ wxDragResult result = wxDragNone;
+ NSPoint nspoint = [m_osxView convertPoint:[sender draggingLocation] fromView:nil];
+ wxPoint pt = wxFromNSPoint( m_osxView, nspoint );
+
+ if ( sourceDragMask & NSDragOperationLink )
+ result = wxDragLink;
+ else if ( sourceDragMask & NSDragOperationCopy )
+ result = wxDragCopy;
+ else if ( sourceDragMask & NSDragOperationMove )
+ result = wxDragMove;
+
+ PasteboardRef pboardRef;
+ PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
+ target->SetCurrentDragPasteboard(pboardRef);
+ result = target->OnEnter(pt.x, pt.y, result);
+ CFRelease(pboardRef);
+
+ NSDragOperation nsresult = NSDragOperationNone;
+ switch (result )
+ {
+ case wxDragLink:
+ nsresult = NSDragOperationLink;
+ case wxDragMove:
+ nsresult = NSDragOperationMove;
+ case wxDragCopy:
+ nsresult = NSDragOperationCopy;
+ default :
+ break;
+ }
+ return nsresult;
+}
+
+void wxWidgetCocoaImpl::draggingExited(void* s, WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
+{
+ id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
+ NSPasteboard *pboard = [sender draggingPasteboard];
+
+ wxWindow* wxpeer = GetWXPeer();
+ if ( wxpeer == NULL )
+ return;
+
+ wxDropTarget* target = wxpeer->GetDropTarget();
+ if ( target == NULL )
+ return;
+
+ PasteboardRef pboardRef;
+ PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
+ target->SetCurrentDragPasteboard(pboardRef);
+ target->OnLeave();
+ CFRelease(pboardRef);
+ }
+
+unsigned int wxWidgetCocoaImpl::draggingUpdated(void* s, WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
+{
+ id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
+ NSPasteboard *pboard = [sender draggingPasteboard];
+ NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
+
+ wxWindow* wxpeer = GetWXPeer();
+ if ( wxpeer == NULL )
+ return NSDragOperationNone;
+
+ wxDropTarget* target = wxpeer->GetDropTarget();
+ if ( target == NULL )
+ return NSDragOperationNone;
+
+ wxDragResult result = wxDragNone;
+ NSPoint nspoint = [m_osxView convertPoint:[sender draggingLocation] fromView:nil];
+ wxPoint pt = wxFromNSPoint( m_osxView, nspoint );
+
+ if ( sourceDragMask & NSDragOperationLink )
+ result = wxDragLink;
+ else if ( sourceDragMask & NSDragOperationCopy )
+ result = wxDragCopy;
+ else if ( sourceDragMask & NSDragOperationMove )
+ result = wxDragMove;
+
+ PasteboardRef pboardRef;
+ PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
+ target->SetCurrentDragPasteboard(pboardRef);
+ result = target->OnDragOver(pt.x, pt.y, result);
+ CFRelease(pboardRef);
+
+ NSDragOperation nsresult = NSDragOperationNone;
+ switch (result )
+ {
+ case wxDragLink:
+ nsresult = NSDragOperationLink;
+ case wxDragMove:
+ nsresult = NSDragOperationMove;
+ case wxDragCopy:
+ nsresult = NSDragOperationCopy;
+ default :
+ break;
+ }
+ return nsresult;
+}
+
+bool wxWidgetCocoaImpl::performDragOperation(void* s, WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
+{
+ id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
+
+ NSPasteboard *pboard = [sender draggingPasteboard];
+ NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
+
+ wxWindow* wxpeer = GetWXPeer();
+ wxDropTarget* target = wxpeer->GetDropTarget();
+ wxDragResult result = wxDragNone;
+ NSPoint nspoint = [m_osxView convertPoint:[sender draggingLocation] fromView:nil];
+ wxPoint pt = wxFromNSPoint( m_osxView, nspoint );
+
+ if ( sourceDragMask & NSDragOperationLink )
+ result = wxDragLink;
+ else if ( sourceDragMask & NSDragOperationCopy )
+ result = wxDragCopy;
+ else if ( sourceDragMask & NSDragOperationMove )
+ result = wxDragMove;
+
+ PasteboardRef pboardRef;
+ PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
+ target->SetCurrentDragPasteboard(pboardRef);
+
+ if (target->OnDrop(pt.x, pt.y))
+ result = target->OnData(pt.x, pt.y, result);
+
+ CFRelease(pboardRef);
+
+ return result != wxDragNone;
+}
+
+typedef void (*wxOSX_TextEventHandlerPtr)(NSView* self, SEL _cmd, NSString *event);
+typedef void (*wxOSX_EventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event);
+typedef BOOL (*wxOSX_PerformKeyEventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event);
+typedef BOOL (*wxOSX_FocusHandlerPtr)(NSView* self, SEL _cmd);
+
+void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
+{
+ if ( !DoHandleMouseEvent(event) )
+ {
+ // for plain NSView mouse events would propagate to parents otherwise
+ if (!IsUserPane())
+ {
+ wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
+ superimpl(slf, (SEL)_cmd, event);
+
+ // super of built-ins keeps the mouse up, as wx expects this event, we have to synthesize it
+
+ if ( [ event type] == NSLeftMouseDown )
+ {
+ wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
+ SetupMouseEvent(wxevent , event) ;
+ wxevent.SetEventType(wxEVT_LEFT_UP);
+
+ GetWXPeer()->HandleWindowEvent(wxevent);
+ }
+ }
+ }
+}
+
+void wxWidgetCocoaImpl::cursorUpdate(WX_NSEvent event, WXWidget slf, void *_cmd)
+{
+ NSCursor *cursor = (NSCursor*)GetWXPeer()->GetCursor().GetHCURSOR();
+ if (cursor == NULL)
+ {
+ wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
+ superimpl(slf, (SEL)_cmd, event);
+ }
+ else
+ {
+ [cursor set];
+ }
+}
+
+
+
+void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
+{
+ if ( [event type] == NSKeyDown )
+ {
+ // there are key equivalents that are not command-combos and therefore not handled by cocoa automatically,
+ // therefore we call the menubar directly here, exit if the menu is handling the shortcut
+ if ( [[[NSApplication sharedApplication] mainMenu] performKeyEquivalent:event] )
+ return;
+
+ m_lastKeyDownEvent = event;
+ }
+
+ if ( GetFocusedViewInWindow([slf window]) != slf || m_hasEditor || !DoHandleKeyEvent(event) )
+ {
+ wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
+ superimpl(slf, (SEL)_cmd, event);
+ }
+ m_lastKeyDownEvent = NULL;
+}
+
+void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd)
+{
+ if ( m_lastKeyDownEvent==NULL || m_hasEditor || !DoHandleCharEvent(m_lastKeyDownEvent, text) )
+ {
+ wxOSX_TextEventHandlerPtr superimpl = (wxOSX_TextEventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
+ superimpl(slf, (SEL)_cmd, text);
+ }
+}
+
+
+bool wxWidgetCocoaImpl::performKeyEquivalent(WX_NSEvent event, WXWidget slf, void *_cmd)
+{
+ bool handled = false;
+
+ wxKeyEvent wxevent(wxEVT_KEY_DOWN);
+ SetupKeyEvent( wxevent, event );
+
+ // because performKeyEquivalent is going up the entire view hierarchy, we don't have to
+ // walk up the ancestors ourselves but let cocoa do it
+
+ int command = m_wxPeer->GetAcceleratorTable()->GetCommand( wxevent );
+ if (command != -1)
+ {
+ wxEvtHandler * const handler = m_wxPeer->GetEventHandler();
+
+ wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
+ command_event.SetEventObject( wxevent.GetEventObject() );
+ handled = handler->ProcessEvent( command_event );
+
+ if ( !handled )
+ {
+ // accelerators can also be used with buttons, try them too
+ command_event.SetEventType(wxEVT_COMMAND_BUTTON_CLICKED);
+ handled = handler->ProcessEvent( command_event );
+ }
+ }
+
+ if ( !handled )
+ {
+ wxOSX_PerformKeyEventHandlerPtr superimpl = (wxOSX_PerformKeyEventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
+ return superimpl(slf, (SEL)_cmd, event);
+ }
+ return YES;
+}
+
+bool wxWidgetCocoaImpl::acceptsFirstResponder(WXWidget slf, void *_cmd)
+{
+ if ( IsUserPane() )
+ return m_wxPeer->AcceptsFocus();
+ else
+ {
+ wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
+ return superimpl(slf, (SEL)_cmd);
+ }
+}
+
+bool wxWidgetCocoaImpl::becomeFirstResponder(WXWidget slf, void *_cmd)
+{
+ wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
+ // get the current focus before running becomeFirstResponder
+ NSView* otherView = FindFocus();
+
+ wxWidgetImpl* otherWindow = FindFromWXWidget(otherView);
+ BOOL r = superimpl(slf, (SEL)_cmd);
+ if ( r )
+ {
+ DoNotifyFocusEvent( true, otherWindow );
+ }
+
+ return r;
+}
+
+bool wxWidgetCocoaImpl::resignFirstResponder(WXWidget slf, void *_cmd)
+{
+ wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
+ BOOL r = superimpl(slf, (SEL)_cmd);
+ // get the current focus after running resignFirstResponder
+ // note that this value isn't reliable, it might return the same view that
+ // is resigning
+ NSView* otherView = FindFocus();
+ wxWidgetImpl* otherWindow = FindFromWXWidget(otherView);
+
+ // It doesn't make sense to notify about the loss of focus if we're not
+ // really losing it and the window which has just gained focus is the same
+ // one as this window itself. Of course, this should never happen in the
+ // first place but somehow it does in wxGrid code and without this check we
+ // enter into an infinite recursion, see #12267.
+ if ( otherWindow == this )
+ return r;
+
+ // NSTextViews have an editor as true responder, therefore the might get the
+ // resign notification if their editor takes over, don't trigger any event then
+ if ( r && !m_hasEditor)
+ {
+ DoNotifyFocusEvent( false, otherWindow );
+ }
+ return r;
+}
+
+bool wxWidgetCocoaImpl::isFlipped(WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
+{
+ return m_isFlipped;
+}
+
+
+#define OSX_DEBUG_DRAWING 0
+
+void wxWidgetCocoaImpl::drawRect(void* rect, WXWidget slf, void *WXUNUSED(_cmd))
+{
+ // preparing the update region
+
+ wxRegion updateRgn;
+ const NSRect *rects;
+ NSInteger count;
+
+ [slf getRectsBeingDrawn:&rects count:&count];
+ for ( int i = 0 ; i < count ; ++i )
+ {
+ updateRgn.Union(wxFromNSRect(slf, rects[i]));
+ }
+
+ wxWindow* wxpeer = GetWXPeer();
+
+ if ( wxpeer->MacGetLeftBorderSize() != 0 || wxpeer->MacGetTopBorderSize() != 0 )
+ {
+ // as this update region is in native window locals we must adapt it to wx window local
+ updateRgn.Offset( wxpeer->MacGetLeftBorderSize() , wxpeer->MacGetTopBorderSize() );
+ }
+
+ // Restrict the update region to the shape of the window, if any, and also
+ // remember the region that we need to clear later.
+ wxNonOwnedWindow* const tlwParent = wxpeer->MacGetTopLevelWindow();
+ const bool isTopLevel = tlwParent == wxpeer;
+ wxRegion clearRgn;
+ if ( tlwParent->GetWindowStyle() & wxFRAME_SHAPED )
+ {
+ if ( isTopLevel )
+ clearRgn = updateRgn;
+
+ int xoffset = 0, yoffset = 0;
+ wxRegion rgn = tlwParent->GetShape();
+ wxpeer->MacRootWindowToWindow( &xoffset, &yoffset );
+ rgn.Offset( xoffset, yoffset );
+ updateRgn.Intersect(rgn);
+
+ if ( isTopLevel )
+ {
+ // Exclude the window shape from the region to be cleared below.
+ rgn.Xor(wxpeer->GetSize());
+ clearRgn.Intersect(rgn);
+ }
+ }
+
+ wxpeer->GetUpdateRegion() = updateRgn;
+
+ // setting up the drawing context
+
+ CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
+ CGContextSaveGState( context );
+
+#if OSX_DEBUG_DRAWING
+ CGContextBeginPath( context );
+ CGContextMoveToPoint(context, 0, 0);
+ NSRect bounds = [slf bounds];
+ CGContextAddLineToPoint(context, 10, 0);
+ CGContextMoveToPoint(context, 0, 0);
+ CGContextAddLineToPoint(context, 0, 10);
+ CGContextMoveToPoint(context, bounds.size.width, bounds.size.height);
+ CGContextAddLineToPoint(context, bounds.size.width, bounds.size.height-10);
+ CGContextMoveToPoint(context, bounds.size.width, bounds.size.height);
+ CGContextAddLineToPoint(context, bounds.size.width-10, bounds.size.height);
+ CGContextClosePath( context );
+ CGContextStrokePath(context);
+#endif
+
+ if ( !m_isFlipped )
+ {
+ CGContextTranslateCTM( context, 0, [m_osxView bounds].size.height );
+ CGContextScaleCTM( context, 1, -1 );
+ }
+
+ wxpeer->MacSetCGContextRef( context );
+
+ bool handled = wxpeer->MacDoRedraw( 0 );
+ CGContextRestoreGState( context );
+
+ CGContextSaveGState( context );
+ if ( !handled )
+ {
+ // call super
+ SEL _cmd = @selector(drawRect:);
+ wxOSX_DrawRectHandlerPtr superimpl = (wxOSX_DrawRectHandlerPtr) [[slf superclass] instanceMethodForSelector:_cmd];
+ superimpl(slf, _cmd, *(NSRect*)rect);
+ CGContextRestoreGState( context );
+ CGContextSaveGState( context );
+ }
+ // as we called restore above, we have to flip again if necessary
+ if ( !m_isFlipped )
+ {
+ CGContextTranslateCTM( context, 0, [m_osxView bounds].size.height );
+ CGContextScaleCTM( context, 1, -1 );
+ }
+
+ if ( isTopLevel )
+ {
+ // We also need to explicitly draw the part of the top level window
+ // outside of its region with transparent colour to ensure that it is
+ // really transparent.
+ if ( clearRgn.IsOk() )
+ {
+ wxMacCGContextStateSaver saveState(context);
+ wxWindowDC dc(wxpeer);
+ dc.SetBackground(wxBrush(wxTransparentColour));
+ dc.SetDeviceClippingRegion(clearRgn);
+ dc.Clear();
+ }
+
+#if wxUSE_GRAPHICS_CONTEXT
+ // If the window shape is defined by a path, stroke the path to show
+ // the window border.
+ const wxGraphicsPath& path = tlwParent->GetShapePath();
+ if ( !path.IsNull() )
+ {
+ CGContextSetLineWidth(context, 1);
+ CGContextSetStrokeColorWithColor(context, wxLIGHT_GREY->GetCGColor());
+ CGContextAddPath(context, (CGPathRef) path.GetNativePath());
+ CGContextStrokePath(context);
+ }
+#endif // wxUSE_GRAPHICS_CONTEXT
+ }
+
+ wxpeer->MacPaintChildrenBorders();
+ wxpeer->MacSetCGContextRef( NULL );
+ CGContextRestoreGState( context );
+}
+
+void wxWidgetCocoaImpl::controlAction( WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd), void *WXUNUSED(sender))
+{
+ wxWindow* wxpeer = (wxWindow*) GetWXPeer();
+ if ( wxpeer )
+ wxpeer->OSXHandleClicked(0);
+}
+
+void wxWidgetCocoaImpl::controlDoubleAction( WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd), void *WXUNUSED(sender))
+{
+}
+
+void wxWidgetCocoaImpl::controlTextDidChange()
+{
+ wxWindow* wxpeer = (wxWindow*)GetWXPeer();
+ if ( wxpeer )
+ {
+ // since native rtti doesn't have to be enabled and wx' rtti is not aware of the mixin wxTextEntry, workaround is needed
+ wxTextCtrl *tc = wxDynamicCast( wxpeer , wxTextCtrl );
+ wxComboBox *cb = wxDynamicCast( wxpeer , wxComboBox );
+ if ( tc )
+ tc->SendTextUpdatedEventIfAllowed();
+ else if ( cb )
+ cb->SendTextUpdatedEventIfAllowed();
+ else
+ {
+ wxFAIL_MSG("Unexpected class for controlTextDidChange event");
+ }
+ }
+}
+
+//
+
+#if OBJC_API_VERSION >= 2
+
+#define wxOSX_CLASS_ADD_METHOD( c, s, i, t ) \
+ class_addMethod(c, s, i, t );
+
+#else
+
+#define wxOSX_CLASS_ADD_METHOD( c, s, i, t ) \
+ { s, (char*) t, i },
+
+#endif
+
+void wxOSXCocoaClassAddWXMethods(Class c)
+{
+
+#if OBJC_API_VERSION < 2
+ static objc_method wxmethods[] =
+ {
+#endif
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(mouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(mouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(mouseMoved:), (IMP) wxOSX_mouseEvent, "v@:@" )
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(mouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(acceptsFirstMouse:), (IMP) wxOSX_acceptsFirstMouse, "v@:@" )
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(scrollWheel:), (IMP) wxOSX_mouseEvent, "v@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(mouseEntered:), (IMP) wxOSX_mouseEvent, "v@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(mouseExited:), (IMP) wxOSX_mouseEvent, "v@:@" )
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(cursorUpdate:), (IMP) wxOSX_cursorUpdate, "v@:@" )
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(keyDown:), (IMP) wxOSX_keyEvent, "v@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(keyUp:), (IMP) wxOSX_keyEvent, "v@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(flagsChanged:), (IMP) wxOSX_keyEvent, "v@:@" )
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(insertText:), (IMP) wxOSX_insertText, "v@:@" )
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(performKeyEquivalent:), (IMP) wxOSX_performKeyEquivalent, "c@:@" )
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(acceptsFirstResponder), (IMP) wxOSX_acceptsFirstResponder, "c@:" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(becomeFirstResponder), (IMP) wxOSX_becomeFirstResponder, "c@:" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(resignFirstResponder), (IMP) wxOSX_resignFirstResponder, "c@:" )
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(isFlipped), (IMP) wxOSX_isFlipped, "c@:" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(drawRect:), (IMP) wxOSX_drawRect, "v@:{_NSRect={_NSPoint=ff}{_NSSize=ff}}" )
+
+ wxOSX_CLASS_ADD_METHOD(c, @selector(controlAction:), (IMP) wxOSX_controlAction, "v@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(controlDoubleAction:), (IMP) wxOSX_controlDoubleAction, "v@:@" )
+
+#if wxUSE_DRAG_AND_DROP
+ wxOSX_CLASS_ADD_METHOD(c, @selector(draggingEntered:), (IMP) wxOSX_draggingEntered, "I@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(draggingUpdated:), (IMP) wxOSX_draggingUpdated, "I@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(draggingExited:), (IMP) wxOSX_draggingExited, "v@:@" )
+ wxOSX_CLASS_ADD_METHOD(c, @selector(performDragOperation:), (IMP) wxOSX_performDragOperation, "c@:@" )
+#endif
+
+#if OBJC_API_VERSION < 2
+ } ;
+ static int method_count = WXSIZEOF( wxmethods );
+ static objc_method_list *wxmethodlist = NULL;
+ if ( wxmethodlist == NULL )
+ {
+ wxmethodlist = (objc_method_list*) malloc(sizeof(objc_method_list) + sizeof(wxmethods) );
+ memcpy( &wxmethodlist->method_list[0], &wxmethods[0], sizeof(wxmethods) );
+ wxmethodlist->method_count = method_count;
+ wxmethodlist->obsolete = 0;
+ }
+ class_addMethods( c, wxmethodlist );
+#endif
+}
+
+//
+// C++ implementation class
+//
+
+IMPLEMENT_DYNAMIC_CLASS( wxWidgetCocoaImpl , wxWidgetImpl )
+
+wxWidgetCocoaImpl::wxWidgetCocoaImpl( wxWindowMac* peer , WXWidget w, bool isRootControl, bool isUserPane ) :
+ wxWidgetImpl( peer, isRootControl, isUserPane )
+{
+ Init();
+ m_osxView = w;
+
+ // check if the user wants to create the control initially hidden
+ if ( !peer->IsShown() )
+ SetVisibility(false);
+
+ // gc aware handling
+ if ( m_osxView )
+ CFRetain(m_osxView);
+ [m_osxView release];
+}
+
+wxWidgetCocoaImpl::wxWidgetCocoaImpl()
+{
+ Init();
+}
+
+void wxWidgetCocoaImpl::Init()
+{
+ m_osxView = NULL;
+ m_isFlipped = true;
+ m_lastKeyDownEvent = NULL;
+ m_hasEditor = false;
+}
+
+wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
+{
+ RemoveAssociations( this );
+
+ if ( !IsRootControl() )
+ {
+ NSView *sv = [m_osxView superview];
+ if ( sv != nil )
+ [m_osxView removeFromSuperview];
+ }
+ // gc aware handling
+ if ( m_osxView )
+ CFRelease(m_osxView);
+}
+
+bool wxWidgetCocoaImpl::IsVisible() const
+{
+ return [m_osxView isHiddenOrHasHiddenAncestor] == NO;
+}
+
+void wxWidgetCocoaImpl::SetVisibility( bool visible )
+{
+ [m_osxView setHidden:(visible ? NO:YES)];