Forgot about the drag source delegate, which is the perfect place to put GiveFeedback...
[wxWidgets.git] / src / osx / cocoa / window.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/osx/cocoa/window.mm
3 // Purpose:     widgets (non tlw) for cocoa
4 // Author:      Stefan Csomor
5 // Modified by:
6 // Created:     2008-06-20
7 // RCS-ID:      $Id: window.mm 48805 2007-09-19 14:52:25Z SC $
8 // Copyright:   (c) Stefan Csomor
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #ifndef WX_PRECOMP
15     #include "wx/dcclient.h"
16     #include "wx/nonownedwnd.h"
17     #include "wx/log.h"
18 #endif
19
20 #ifdef __WXMAC__
21     #include "wx/osx/private.h"
22 #endif
23
24 #include "wx/evtloop.h"
25
26 #if wxUSE_CARET
27     #include "wx/caret.h"
28 #endif
29
30 #if wxUSE_DRAG_AND_DROP
31     #include "wx/dnd.h"
32 #endif
33
34 #include <objc/objc-runtime.h>
35
36 // Get the window with the focus
37
38 NSView* GetViewFromResponder( NSResponder* responder )
39 {
40     NSView* view = nil;
41     if ( [responder isKindOfClass:[NSTextView class]] )
42     {
43         NSView* delegate = (NSView*) [(NSTextView*)responder delegate];
44         if ( [delegate isKindOfClass:[NSTextField class] ] )
45             view = delegate;
46         else
47             view =  (NSView*) responder;
48     }
49     else
50     {
51         if ( [responder isKindOfClass:[NSView class]] )
52             view = (NSView*) responder;
53     }
54     return view;
55 }
56
57 NSView* GetFocusedViewInWindow( NSWindow* keyWindow )
58 {
59     NSView* focusedView = nil;
60     if ( keyWindow != nil )
61         focusedView = GetViewFromResponder([keyWindow firstResponder]);
62
63     return focusedView;
64 }
65
66 WXWidget wxWidgetImpl::FindFocus()
67 {
68     return GetFocusedViewInWindow( [[NSApplication sharedApplication] keyWindow] );
69 }
70
71 NSRect wxOSXGetFrameForControl( wxWindowMac* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
72 {
73     int x, y, w, h ;
74
75     window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
76     wxRect bounds(x,y,w,h);
77     NSView* sv = (window->GetParent()->GetHandle() );
78
79     return wxToNSRect( sv, bounds );
80 }
81
82 @interface wxNSView : NSView
83 {
84     NSTrackingRectTag rectTag;
85 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
86     NSTrackingArea* _trackingArea;
87 #endif
88 }
89
90 // the tracking tag is needed to track mouse enter / exit events
91 - (void) setTrackingTag: (NSTrackingRectTag)tag;
92 - (NSTrackingRectTag) trackingTag;
93 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
94 // under 10.5 we can also track mouse moved events on non-focused windows if
95 // we use the new NSTrackingArea APIs. 
96 - (void) updateTrackingArea;
97 - (NSTrackingArea*) trackingArea;
98 #endif
99 @end // wxNSView
100
101 @interface NSView(PossibleMethods)
102 - (void)setTitle:(NSString *)aString;
103 - (void)setStringValue:(NSString *)aString;
104 - (void)setIntValue:(int)anInt;
105 - (void)setFloatValue:(float)aFloat;
106 - (void)setDoubleValue:(double)aDouble;
107
108 - (double)minValue;
109 - (double)maxValue;
110 - (void)setMinValue:(double)aDouble;
111 - (void)setMaxValue:(double)aDouble;
112
113 - (void)sizeToFit;
114
115 - (BOOL)isEnabled;
116 - (void)setEnabled:(BOOL)flag;
117
118 - (void)setImage:(NSImage *)image;
119 - (void)setControlSize:(NSControlSize)size;
120
121 - (void)setFont:(NSFont *)fontObject;
122
123 - (id)contentView;
124
125 - (void)setTarget:(id)anObject;
126 - (void)setAction:(SEL)aSelector;
127 - (void)setDoubleAction:(SEL)aSelector;
128 - (void)setBackgroundColor:(NSColor*)aColor;
129 - (void)setImagePosition:(NSCellImagePosition)aPosition;
130 @end
131
132 long wxOSXTranslateCocoaKey( NSEvent* event )
133 {
134     long retval = 0;
135
136     if ([event type] != NSFlagsChanged)
137     {
138         NSString* s = [event charactersIgnoringModifiers];
139         // backspace char reports as delete w/modifiers for some reason
140         if ([s length] == 1)
141         {
142             switch ( [s characterAtIndex:0] )
143             {
144                 // backspace key
145                 case 0x7F :
146                 case 8 :
147                     retval = WXK_BACK;
148                     break;
149                 case NSUpArrowFunctionKey :
150                     retval = WXK_UP;
151                     break;
152                 case NSDownArrowFunctionKey :
153                     retval = WXK_DOWN;
154                     break;
155                 case NSLeftArrowFunctionKey :
156                     retval = WXK_LEFT;
157                     break;
158                 case NSRightArrowFunctionKey :
159                     retval = WXK_RIGHT;
160                     break;
161                 case NSInsertFunctionKey  :
162                     retval = WXK_INSERT;
163                     break;
164                 case NSDeleteFunctionKey  :
165                     retval = WXK_DELETE;
166                     break;
167                 case NSHomeFunctionKey  :
168                     retval = WXK_HOME;
169                     break;
170         //        case NSBeginFunctionKey  :
171         //            retval = WXK_BEGIN;
172         //            break;
173                 case NSEndFunctionKey  :
174                     retval = WXK_END;
175                     break;
176                 case NSPageUpFunctionKey  :
177                     retval = WXK_PAGEUP;
178                     break;
179                case NSPageDownFunctionKey  :
180                     retval = WXK_PAGEDOWN;
181                     break;
182                case NSHelpFunctionKey  :
183                     retval = WXK_HELP;
184                     break;
185                 default:
186                     int intchar = [s characterAtIndex: 0];
187                     if ( intchar >= NSF1FunctionKey && intchar <= NSF24FunctionKey )
188                         retval = WXK_F1 + (intchar - NSF1FunctionKey );
189                     break;
190             }
191         }
192     }
193
194     // Some keys don't seem to have constants. The code mimics the approach
195     // taken by WebKit. See:
196     // http://trac.webkit.org/browser/trunk/WebCore/platform/mac/KeyEventMac.mm
197     switch( [event keyCode] )
198     {
199         // command key
200         case 54:
201         case 55:
202             retval = WXK_COMMAND;
203             break;
204         // caps locks key
205         case 57: // Capslock
206             retval = WXK_CAPITAL;
207             break;
208         // shift key
209         case 56: // Left Shift
210         case 60: // Right Shift
211             retval = WXK_SHIFT;
212             break;
213         // alt key
214         case 58: // Left Alt
215         case 61: // Right Alt
216             retval = WXK_ALT;
217             break;
218         // ctrl key
219         case 59: // Left Ctrl
220         case 62: // Right Ctrl
221             retval = WXK_CONTROL;
222             break;
223         // clear key
224         case 71:
225             retval = WXK_CLEAR;
226             break;
227         // tab key
228         case 48:
229             retval = WXK_TAB;
230             break;
231
232         case 75: // /
233             retval = WXK_NUMPAD_DIVIDE;
234             break;
235         case 67: // *
236             retval = WXK_NUMPAD_MULTIPLY;
237             break;
238         case 78: // -
239             retval = WXK_NUMPAD_SUBTRACT;
240             break;
241         case 69: // +
242             retval = WXK_NUMPAD_ADD;
243             break;
244         case 76: // Enter
245             retval = WXK_NUMPAD_ENTER;
246             break;
247         case 65: // .
248             retval = WXK_NUMPAD_DECIMAL;
249             break;
250         case 82: // 0
251             retval = WXK_NUMPAD0;
252             break;
253         case 83: // 1
254             retval = WXK_NUMPAD1;
255             break;
256         case 84: // 2
257             retval = WXK_NUMPAD2;
258             break;
259         case 85: // 3
260             retval = WXK_NUMPAD3;
261             break;
262         case 86: // 4
263             retval = WXK_NUMPAD4;
264             break;
265         case 87: // 5
266             retval = WXK_NUMPAD5;
267             break;
268         case 88: // 6
269             retval = WXK_NUMPAD6;
270             break;
271         case 89: // 7
272             retval = WXK_NUMPAD7;
273             break;
274         case 91: // 8
275             retval = WXK_NUMPAD8;
276             break;
277         case 92: // 9
278             retval = WXK_NUMPAD9;
279             break;
280         default:
281             //retval = [event keyCode];
282             break;
283     }
284     return retval;
285 }
286
287 void wxWidgetCocoaImpl::SetupKeyEvent(wxKeyEvent &wxevent , NSEvent * nsEvent, NSString* charString)
288 {
289     UInt32 modifiers = [nsEvent modifierFlags] ;
290     int eventType = [nsEvent type];
291
292     wxevent.m_shiftDown = modifiers & NSShiftKeyMask;
293     wxevent.m_controlDown = modifiers & NSControlKeyMask;
294     wxevent.m_altDown = modifiers & NSAlternateKeyMask;
295     wxevent.m_metaDown = modifiers & NSCommandKeyMask;
296
297     wxevent.m_rawCode = [nsEvent keyCode];
298     wxevent.m_rawFlags = modifiers;
299
300     wxevent.SetTimestamp( (int)([nsEvent timestamp] * 1000) ) ;
301
302     wxString chars;
303     if ( eventType != NSFlagsChanged )
304     {
305         NSString* nschars = [nsEvent charactersIgnoringModifiers];
306         if ( charString )
307         {
308             // if charString is set, it did not come from key up / key down
309             wxevent.SetEventType( wxEVT_CHAR );
310             chars = wxCFStringRef::AsString(charString);
311         }
312         else if ( nschars )
313         {
314             chars = wxCFStringRef::AsString(nschars);
315         }
316     }
317
318     int aunichar = chars.Length() > 0 ? chars[0] : 0;
319     long keyval = 0;
320
321     if (wxevent.GetEventType() != wxEVT_CHAR)
322     {
323         keyval = wxOSXTranslateCocoaKey(nsEvent) ;
324         switch (eventType)
325         {
326             case NSKeyDown :
327                 wxevent.SetEventType( wxEVT_KEY_DOWN )  ;
328                 break;
329             case NSKeyUp :
330                 wxevent.SetEventType( wxEVT_KEY_UP )  ;
331                 break;
332             case NSFlagsChanged :
333                 switch (keyval)
334                 {
335                     case WXK_CONTROL:
336                         wxevent.SetEventType( wxevent.m_controlDown ? wxEVT_KEY_DOWN : wxEVT_KEY_UP);
337                         break;
338                     case WXK_SHIFT:
339                         wxevent.SetEventType( wxevent.m_shiftDown ? wxEVT_KEY_DOWN : wxEVT_KEY_UP);
340                         break;
341                     case WXK_ALT:
342                         wxevent.SetEventType( wxevent.m_altDown ? wxEVT_KEY_DOWN : wxEVT_KEY_UP);
343                         break;
344                     case WXK_COMMAND:
345                         wxevent.SetEventType( wxevent.m_metaDown ? wxEVT_KEY_DOWN : wxEVT_KEY_UP);
346                         break;
347                 }
348                 break;
349             default :
350                 break ;
351         }
352     }
353
354     if ( !keyval )
355     {
356         if ( wxevent.GetEventType() == wxEVT_KEY_UP || wxevent.GetEventType() == wxEVT_KEY_DOWN )
357             keyval = wxToupper( aunichar ) ;
358         else
359             keyval = aunichar;
360     }
361
362 #if wxUSE_UNICODE
363     wxevent.m_uniChar = aunichar;
364 #endif
365     wxevent.m_keyCode = keyval;
366
367     wxWindowMac* peer = GetWXPeer();
368     if ( peer )
369     {
370         wxevent.SetEventObject(peer);
371         wxevent.SetId(peer->GetId()) ;
372     }
373 }
374
375 UInt32 g_lastButton = 0 ;
376 bool g_lastButtonWasFakeRight = false ;
377
378 // better scroll wheel support 
379 // see http://lists.apple.com/archives/cocoa-dev/2007/Feb/msg00050.html
380
381 @interface NSEvent (DeviceDelta)
382 - (float)deviceDeltaX;
383 - (float)deviceDeltaY;
384 @end
385
386 void wxWidgetCocoaImpl::SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
387 {
388     int eventType = [nsEvent type];
389     UInt32 modifiers = [nsEvent modifierFlags] ;
390     wxPoint screenMouseLocation = wxFromNSPoint( NULL, [nsEvent locationInWindow]);
391
392     // these parameters are not given for all events
393     UInt32 button = [nsEvent buttonNumber];
394     UInt32 clickCount = 0;
395
396     wxevent.m_x = screenMouseLocation.x;
397     wxevent.m_y = screenMouseLocation.y;
398     wxevent.m_shiftDown = modifiers & NSShiftKeyMask;
399     wxevent.m_controlDown = modifiers & NSControlKeyMask;
400     wxevent.m_altDown = modifiers & NSAlternateKeyMask;
401     wxevent.m_metaDown = modifiers & NSCommandKeyMask;
402     wxevent.SetTimestamp( (int)([nsEvent timestamp] * 1000) ) ;
403
404     UInt32 mouseChord = 0;
405
406     switch (eventType)
407     {
408         case NSLeftMouseDown :
409         case NSLeftMouseDragged :
410             mouseChord = 1U;
411             break;
412         case NSRightMouseDown :
413         case NSRightMouseDragged :
414             mouseChord = 2U;
415             break;
416         case NSOtherMouseDown :
417         case NSOtherMouseDragged :
418             mouseChord = 4U;
419             break;
420     }
421
422     // a control click is interpreted as a right click
423     bool thisButtonIsFakeRight = false ;
424     if ( button == 0 && (modifiers & NSControlKeyMask) )
425     {
426         button = 1 ;
427         thisButtonIsFakeRight = true ;
428     }
429
430     // otherwise we report double clicks by connecting a left click with a ctrl-left click
431     if ( clickCount > 1 && button != g_lastButton )
432         clickCount = 1 ;
433
434     // we must make sure that our synthetic 'right' button corresponds in
435     // mouse down, moved and mouse up, and does not deliver a right down and left up
436     switch (eventType)
437     {
438         case NSLeftMouseDown :
439         case NSRightMouseDown :
440         case NSOtherMouseDown :
441             g_lastButton = button ;
442             g_lastButtonWasFakeRight = thisButtonIsFakeRight ;
443             break;
444      }
445
446     if ( button == 0 )
447     {
448         g_lastButton = 0 ;
449         g_lastButtonWasFakeRight = false ;
450     }
451     else if ( g_lastButton == 1 && g_lastButtonWasFakeRight )
452         button = g_lastButton ;
453
454     // Adjust the chord mask to remove the primary button and add the
455     // secondary button.  It is possible that the secondary button is
456     // already pressed, e.g. on a mouse connected to a laptop, but this
457     // possibility is ignored here:
458     if( thisButtonIsFakeRight && ( mouseChord & 1U ) )
459         mouseChord = ((mouseChord & ~1U) | 2U);
460
461     if(mouseChord & 1U)
462                 wxevent.m_leftDown = true ;
463     if(mouseChord & 2U)
464                 wxevent.m_rightDown = true ;
465     if(mouseChord & 4U)
466                 wxevent.m_middleDown = true ;
467
468     // translate into wx types
469     switch (eventType)
470     {
471         case NSLeftMouseDown :
472         case NSRightMouseDown :
473         case NSOtherMouseDown :
474             clickCount = [nsEvent clickCount];
475             switch ( button )
476             {
477                 case 0 :
478                     wxevent.SetEventType( clickCount > 1 ? wxEVT_LEFT_DCLICK : wxEVT_LEFT_DOWN )  ;
479                     break ;
480
481                 case 1 :
482                     wxevent.SetEventType( clickCount > 1 ? wxEVT_RIGHT_DCLICK : wxEVT_RIGHT_DOWN ) ;
483                     break ;
484
485                 case 2 :
486                     wxevent.SetEventType( clickCount > 1 ? wxEVT_MIDDLE_DCLICK : wxEVT_MIDDLE_DOWN ) ;
487                     break ;
488
489                 default:
490                     break ;
491             }
492             break ;
493
494         case NSLeftMouseUp :
495         case NSRightMouseUp :
496         case NSOtherMouseUp :
497             clickCount = [nsEvent clickCount];
498             switch ( button )
499             {
500                 case 0 :
501                     wxevent.SetEventType( wxEVT_LEFT_UP )  ;
502                     break ;
503
504                 case 1 :
505                     wxevent.SetEventType( wxEVT_RIGHT_UP ) ;
506                     break ;
507
508                 case 2 :
509                     wxevent.SetEventType( wxEVT_MIDDLE_UP ) ;
510                     break ;
511
512                 default:
513                     break ;
514             }
515             break ;
516
517      case NSScrollWheel :
518         {
519             float deltaX = 0.0;
520             float deltaY = 0.0;
521
522             wxevent.SetEventType( wxEVT_MOUSEWHEEL ) ;
523
524             // see http://developer.apple.com/qa/qa2005/qa1453.html
525             // for more details on why we have to look for the exact type
526             
527             const EventRef cEvent = (EventRef) [nsEvent eventRef];
528             bool isMouseScrollEvent = false;
529             if ( cEvent )
530                 isMouseScrollEvent = ::GetEventKind(cEvent) == kEventMouseScroll;
531                 
532             if ( isMouseScrollEvent )
533             {
534                 deltaX = [nsEvent deviceDeltaX];
535                 deltaY = [nsEvent deviceDeltaY];
536             }
537             else
538             {
539                 deltaX = ([nsEvent deltaX] * 10);
540                 deltaY = ([nsEvent deltaY] * 10);
541             }
542             
543             wxevent.m_wheelDelta = 10;
544             wxevent.m_linesPerAction = 1;
545                 
546             if ( fabs(deltaX) > fabs(deltaY) )
547             {
548                 wxevent.m_wheelAxis = 1;
549                 wxevent.m_wheelRotation = (int)deltaX;
550             }
551             else
552             {
553                 wxevent.m_wheelRotation = (int)deltaY;
554             }
555
556         }
557         break ;
558
559         case NSMouseEntered :
560             wxevent.SetEventType( wxEVT_ENTER_WINDOW ) ;
561             break;
562         case NSMouseExited :
563             wxevent.SetEventType( wxEVT_LEAVE_WINDOW ) ;
564             break;
565         case NSLeftMouseDragged :
566         case NSRightMouseDragged :
567         case NSOtherMouseDragged :
568         case NSMouseMoved :
569             wxevent.SetEventType( wxEVT_MOTION ) ;
570             break;
571         default :
572             break ;
573     }
574
575     wxevent.m_clickCount = clickCount;
576     wxWindowMac* peer = GetWXPeer();
577     if ( peer )
578     {
579         wxevent.SetEventObject(peer);
580         wxevent.SetId(peer->GetId()) ;
581     }
582 }
583
584 @implementation wxNSView
585
586 + (void)initialize
587 {
588     static BOOL initialized = NO;
589     if (!initialized)
590     {
591         initialized = YES;
592         wxOSXCocoaClassAddWXMethods( self );
593     }
594 }
595
596 - (void) setTrackingTag: (NSTrackingRectTag)tag
597 {
598     rectTag = tag;
599 }
600
601 - (NSTrackingRectTag) trackingTag
602 {
603     return rectTag;
604 }
605
606 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
607 - (void) updateTrackingArea
608 {
609     if (_trackingArea)
610     {
611         [self removeTrackingArea: _trackingArea];
612         [_trackingArea release];
613     }
614     
615     NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited|NSTrackingMouseMoved|NSTrackingActiveAlways;
616         
617     NSTrackingArea* area = [[NSTrackingArea alloc] initWithRect: [self bounds] options: options owner: self userInfo: nil];
618     [self addTrackingArea: area];
619
620     _trackingArea = area;
621 }
622
623 - (NSTrackingArea*) trackingArea
624 {
625     return _trackingArea;
626 }
627 #endif
628 @end // wxNSView
629
630 //
631 // event handlers
632 //
633
634 #if wxUSE_DRAG_AND_DROP
635
636 // see http://lists.apple.com/archives/Cocoa-dev/2005/Jul/msg01244.html
637 // for details on the NSPasteboard -> PasteboardRef conversion
638
639 NSDragOperation wxOSX_draggingEntered( id self, SEL _cmd, id <NSDraggingInfo>sender )
640 {
641     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
642     if (impl == NULL)
643         return NSDragOperationNone;
644
645     return impl->draggingEntered(sender, self, _cmd);
646 }
647
648 void wxOSX_draggingExited( id self, SEL _cmd, id <NSDraggingInfo> sender )
649 {
650     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
651     if (impl == NULL)
652         return ;
653
654     return impl->draggingExited(sender, self, _cmd);
655 }
656
657 NSDragOperation wxOSX_draggingUpdated( id self, SEL _cmd, id <NSDraggingInfo>sender )
658 {
659     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
660     if (impl == NULL)
661         return NSDragOperationNone;
662
663     return impl->draggingUpdated(sender, self, _cmd);
664 }
665
666 BOOL wxOSX_performDragOperation( id self, SEL _cmd, id <NSDraggingInfo> sender )
667 {
668     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
669     if (impl == NULL)
670         return NSDragOperationNone;
671
672     return impl->performDragOperation(sender, self, _cmd) ? YES:NO ;
673 }
674
675 #endif
676
677 void wxOSX_mouseEvent(NSView* self, SEL _cmd, NSEvent *event)
678 {
679     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
680     if (impl == NULL)
681         return;
682
683     impl->mouseEvent(event, self, _cmd);
684 }
685
686 BOOL wxOSX_acceptsFirstMouse(NSView* self, SEL _cmd, NSEvent *event)
687 {
688     // This is needed to support click through, otherwise the first click on a window
689     // will not do anything unless it is the active window already.
690     return YES;
691 }
692
693 void wxOSX_keyEvent(NSView* self, SEL _cmd, NSEvent *event)
694 {
695     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
696     if (impl == NULL)
697         return;
698
699     impl->keyEvent(event, self, _cmd);
700 }
701
702 void wxOSX_insertText(NSView* self, SEL _cmd, NSString* text)
703 {
704     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
705     if (impl == NULL)
706         return;
707
708     impl->insertText(text, self, _cmd);
709 }
710
711 BOOL wxOSX_performKeyEquivalent(NSView* self, SEL _cmd, NSEvent *event)
712 {
713     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
714     if (impl == NULL)
715         return NO;
716
717     return impl->performKeyEquivalent(event, self, _cmd);
718 }
719
720 BOOL wxOSX_acceptsFirstResponder(NSView* self, SEL _cmd)
721 {
722     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
723     if (impl == NULL)
724         return NO;
725
726     return impl->acceptsFirstResponder(self, _cmd);
727 }
728
729 BOOL wxOSX_becomeFirstResponder(NSView* self, SEL _cmd)
730 {
731     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
732     if (impl == NULL)
733         return NO;
734
735     return impl->becomeFirstResponder(self, _cmd);
736 }
737
738 BOOL wxOSX_resignFirstResponder(NSView* self, SEL _cmd)
739 {
740     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
741     if (impl == NULL)
742         return NO;
743
744     return impl->resignFirstResponder(self, _cmd);
745 }
746
747 void wxOSX_resetCursorRects(NSView* self, SEL _cmd)
748 {
749     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
750     if (impl == NULL)
751         return;
752
753     impl->resetCursorRects(self, _cmd);
754 }
755
756 BOOL wxOSX_isFlipped(NSView* self, SEL _cmd)
757 {
758     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
759     if (impl == NULL)
760         return NO;
761
762     return impl->isFlipped(self, _cmd) ? YES:NO;
763 }
764
765 void wxOSX_drawRect(NSView* self, SEL _cmd, NSRect rect)
766 {
767     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
768     if (impl == NULL)
769         return;
770
771     return impl->drawRect(&rect, self, _cmd);
772 }
773
774 void wxOSX_controlAction(NSView* self, SEL _cmd, id sender)
775 {
776     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
777     if (impl == NULL)
778         return;
779
780     impl->controlAction(self, _cmd, sender);
781 }
782
783 void wxOSX_controlDoubleAction(NSView* self, SEL _cmd, id sender)
784 {
785     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
786     if (impl == NULL)
787         return;
788
789     impl->controlDoubleAction(self, _cmd, sender);
790 }
791
792 unsigned int wxWidgetCocoaImpl::draggingEntered(void* s, WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
793 {
794     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
795     NSPasteboard *pboard = [sender draggingPasteboard];
796     NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
797
798     wxWindow* wxpeer = GetWXPeer();
799     if ( wxpeer == NULL )
800         return NSDragOperationNone;
801
802     wxDropTarget* target = wxpeer->GetDropTarget();
803     if ( target == NULL )
804         return NSDragOperationNone;
805
806     wxDragResult result = wxDragNone;
807     NSPoint nspoint = [m_osxView convertPoint:[sender draggingLocation] fromView:nil];
808     wxPoint pt = wxFromNSPoint( m_osxView, nspoint );
809
810     if ( sourceDragMask & NSDragOperationLink )
811         result = wxDragLink;
812     else if ( sourceDragMask & NSDragOperationCopy )
813         result = wxDragCopy;
814     else if ( sourceDragMask & NSDragOperationMove )
815         result = wxDragMove;
816
817     PasteboardRef pboardRef;
818     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
819     target->SetCurrentDragPasteboard(pboardRef);
820     result = target->OnEnter(pt.x, pt.y, result);
821     CFRelease(pboardRef);
822
823     NSDragOperation nsresult = NSDragOperationNone;
824     switch (result )
825     {
826         case wxDragLink:
827             nsresult = NSDragOperationLink;
828         case wxDragMove:
829             nsresult = NSDragOperationMove;
830         case wxDragCopy:
831             nsresult = NSDragOperationCopy;
832         default :
833             break;
834     }
835     return nsresult;
836 }
837
838 void wxWidgetCocoaImpl::draggingExited(void* s, WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
839 {
840     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
841     NSPasteboard *pboard = [sender draggingPasteboard];
842
843     wxWindow* wxpeer = GetWXPeer();
844     if ( wxpeer == NULL )
845         return;
846
847     wxDropTarget* target = wxpeer->GetDropTarget();
848     if ( target == NULL )
849         return;
850
851     PasteboardRef pboardRef;
852     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
853     target->SetCurrentDragPasteboard(pboardRef);
854     target->OnLeave();
855     CFRelease(pboardRef);
856  }
857
858 unsigned int wxWidgetCocoaImpl::draggingUpdated(void* s, WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
859 {
860     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
861     NSPasteboard *pboard = [sender draggingPasteboard];
862     NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
863
864     wxWindow* wxpeer = GetWXPeer();
865     if ( wxpeer == NULL )
866         return NSDragOperationNone;
867
868     wxDropTarget* target = wxpeer->GetDropTarget();
869     if ( target == NULL )
870         return NSDragOperationNone;
871
872     wxDragResult result = wxDragNone;
873     NSPoint nspoint = [m_osxView convertPoint:[sender draggingLocation] fromView:nil];
874     wxPoint pt = wxFromNSPoint( m_osxView, nspoint );
875
876     if ( sourceDragMask & NSDragOperationLink )
877         result = wxDragLink;
878     else if ( sourceDragMask & NSDragOperationCopy )
879         result = wxDragCopy;
880     else if ( sourceDragMask & NSDragOperationMove )
881         result = wxDragMove;
882     
883     PasteboardRef pboardRef;
884     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
885     target->SetCurrentDragPasteboard(pboardRef);
886     result = target->OnDragOver(pt.x, pt.y, result);
887     CFRelease(pboardRef);
888
889     NSDragOperation nsresult = NSDragOperationNone;
890     switch (result )
891     {
892         case wxDragLink:
893             nsresult = NSDragOperationLink;
894         case wxDragMove:
895             nsresult = NSDragOperationMove;
896         case wxDragCopy:
897             nsresult = NSDragOperationCopy;
898         default :
899             break;
900     }
901     return nsresult;
902 }
903
904 bool wxWidgetCocoaImpl::performDragOperation(void* s, WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
905 {
906     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
907
908     NSPasteboard *pboard = [sender draggingPasteboard];
909     NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
910
911     wxWindow* wxpeer = GetWXPeer();
912     wxDropTarget* target = wxpeer->GetDropTarget();
913     wxDragResult result = wxDragNone;
914     NSPoint nspoint = [m_osxView convertPoint:[sender draggingLocation] fromView:nil];
915     wxPoint pt = wxFromNSPoint( m_osxView, nspoint );
916
917     if ( sourceDragMask & NSDragOperationLink )
918         result = wxDragLink;
919     else if ( sourceDragMask & NSDragOperationCopy )
920         result = wxDragCopy;
921     else if ( sourceDragMask & NSDragOperationMove )
922         result = wxDragMove;
923
924     PasteboardRef pboardRef;
925     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
926     target->SetCurrentDragPasteboard(pboardRef);
927
928     if (target->OnDrop(pt.x, pt.y))
929         result = target->OnData(pt.x, pt.y, result);
930
931     CFRelease(pboardRef);
932
933     return result != wxDragNone;
934 }
935
936 typedef void (*wxOSX_TextEventHandlerPtr)(NSView* self, SEL _cmd, NSString *event);
937 typedef void (*wxOSX_EventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event);
938 typedef BOOL (*wxOSX_PerformKeyEventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event);
939 typedef BOOL (*wxOSX_FocusHandlerPtr)(NSView* self, SEL _cmd);
940 typedef BOOL (*wxOSX_ResetCursorRectsHandlerPtr)(NSView* self, SEL _cmd);
941 typedef void (*wxOSX_DrawRectHandlerPtr)(NSView* self, SEL _cmd, NSRect rect);
942
943 void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
944 {
945     if ( !DoHandleMouseEvent(event) )
946     {
947         // for plain NSView mouse events would propagate to parents otherwise
948         if (!m_wxPeer->MacIsUserPane())
949         {
950             wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
951             superimpl(slf, (SEL)_cmd, event);
952         }
953     }
954 }
955
956 void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
957 {
958     if ( [event type] == NSKeyDown )
959         m_lastKeyDownEvent = event;
960     if ( GetFocusedViewInWindow([slf window]) != slf || m_hasEditor || !DoHandleKeyEvent(event) )
961     {
962         wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
963         superimpl(slf, (SEL)_cmd, event);
964     }
965     m_lastKeyDownEvent = NULL;
966 }
967
968 void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd)
969 {
970     if ( m_lastKeyDownEvent==NULL || m_hasEditor || !DoHandleCharEvent(m_lastKeyDownEvent, text) )
971     {
972         wxOSX_TextEventHandlerPtr superimpl = (wxOSX_TextEventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
973         superimpl(slf, (SEL)_cmd, text);
974     }
975 }
976
977
978 bool wxWidgetCocoaImpl::performKeyEquivalent(WX_NSEvent event, WXWidget slf, void *_cmd)
979 {
980     wxOSX_PerformKeyEventHandlerPtr superimpl = (wxOSX_PerformKeyEventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
981     return superimpl(slf, (SEL)_cmd, event);
982 }
983
984 bool wxWidgetCocoaImpl::acceptsFirstResponder(WXWidget slf, void *_cmd)
985 {
986     if ( m_wxPeer->MacIsUserPane() )
987         return m_wxPeer->AcceptsFocus();
988     else
989     {
990         wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
991         return superimpl(slf, (SEL)_cmd);
992     }
993 }
994
995 bool wxWidgetCocoaImpl::becomeFirstResponder(WXWidget slf, void *_cmd)
996 {
997     wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
998     // get the current focus before running becomeFirstResponder
999     NSView* otherView = FindFocus();
1000
1001     wxWidgetImpl* otherWindow = FindFromWXWidget(otherView);
1002     BOOL r = superimpl(slf, (SEL)_cmd);
1003     if ( r )
1004     {
1005         DoNotifyFocusEvent( true, otherWindow );
1006     }
1007
1008     return r;
1009 }
1010
1011 bool wxWidgetCocoaImpl::resignFirstResponder(WXWidget slf, void *_cmd)
1012 {
1013     wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
1014     BOOL r = superimpl(slf, (SEL)_cmd);
1015     // get the current focus after running resignFirstResponder
1016     // note that this value isn't reliable, it might return the same view that
1017     // is resigning
1018     NSView* otherView = FindFocus();
1019     wxWidgetImpl* otherWindow = FindFromWXWidget(otherView);
1020     // NSTextViews have an editor as true responder, therefore the might get the
1021     // resign notification if their editor takes over, don't trigger any event then
1022     if ( r && !m_hasEditor)
1023     {
1024         DoNotifyFocusEvent( false, otherWindow );
1025     }
1026     return r;
1027 }
1028
1029 void wxWidgetCocoaImpl::resetCursorRects(WXWidget slf, void *_cmd)
1030 {
1031     wxWindow* wxpeer = GetWXPeer();
1032     if ( wxpeer )
1033     {
1034         NSCursor *cursor = (NSCursor*)wxpeer->GetCursor().GetHCURSOR();
1035         if (cursor == NULL)
1036         {
1037             wxOSX_ResetCursorRectsHandlerPtr superimpl = (wxOSX_ResetCursorRectsHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
1038             superimpl(slf, (SEL)_cmd);
1039         }
1040         else
1041         {
1042             [slf addCursorRect: [slf bounds]
1043                 cursor: cursor];
1044         }
1045     }
1046 }
1047
1048 bool wxWidgetCocoaImpl::isFlipped(WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
1049 {
1050     return m_isFlipped;
1051 }
1052
1053
1054 #define OSX_DEBUG_DRAWING 0
1055
1056 void wxWidgetCocoaImpl::drawRect(void* rect, WXWidget slf, void *WXUNUSED(_cmd))
1057 {
1058     CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
1059     CGContextSaveGState( context );
1060
1061 #if OSX_DEBUG_DRAWING
1062     CGContextBeginPath( context );
1063     CGContextMoveToPoint(context, 0, 0);
1064     NSRect bounds = [self bounds];
1065     CGContextAddLineToPoint(context, 10, 0);
1066     CGContextMoveToPoint(context, 0, 0);
1067     CGContextAddLineToPoint(context, 0, 10);
1068     CGContextMoveToPoint(context, bounds.size.width, bounds.size.height);
1069     CGContextAddLineToPoint(context, bounds.size.width, bounds.size.height-10);
1070     CGContextMoveToPoint(context, bounds.size.width, bounds.size.height);
1071     CGContextAddLineToPoint(context, bounds.size.width-10, bounds.size.height);
1072     CGContextClosePath( context );
1073     CGContextStrokePath(context);
1074 #endif
1075
1076     if ( !m_isFlipped )
1077     {
1078         CGContextTranslateCTM( context, 0,  [m_osxView bounds].size.height );
1079         CGContextScaleCTM( context, 1, -1 );
1080     }
1081
1082     wxRegion updateRgn;
1083     const NSRect *rects;
1084     NSInteger count;
1085
1086     [slf getRectsBeingDrawn:&rects count:&count];
1087     for ( int i = 0 ; i < count ; ++i )
1088     {
1089         updateRgn.Union(wxFromNSRect(slf, rects[i]) );
1090     }
1091
1092     wxWindow* wxpeer = GetWXPeer();
1093     wxpeer->GetUpdateRegion() = updateRgn;
1094     wxpeer->MacSetCGContextRef( context );
1095
1096     bool handled = wxpeer->MacDoRedraw( 0 );
1097
1098     CGContextRestoreGState( context );
1099
1100     CGContextSaveGState( context );
1101     if ( !handled )
1102     {
1103         // call super
1104         SEL _cmd = @selector(drawRect:);
1105         wxOSX_DrawRectHandlerPtr superimpl = (wxOSX_DrawRectHandlerPtr) [[slf superclass] instanceMethodForSelector:_cmd];
1106         superimpl(slf, _cmd, *(NSRect*)rect);
1107         CGContextRestoreGState( context );
1108         CGContextSaveGState( context );
1109     }
1110     wxpeer->MacPaintChildrenBorders();
1111     wxpeer->MacSetCGContextRef( NULL );
1112     CGContextRestoreGState( context );
1113 }
1114
1115 void wxWidgetCocoaImpl::controlAction( WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd), void *WXUNUSED(sender))
1116 {
1117     wxWindow* wxpeer = (wxWindow*) GetWXPeer();
1118     if ( wxpeer )
1119         wxpeer->OSXHandleClicked(0);
1120 }
1121
1122 void wxWidgetCocoaImpl::controlDoubleAction( WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd), void *WXUNUSED(sender))
1123 {
1124 }
1125
1126 //
1127
1128 #if OBJC_API_VERSION >= 2
1129
1130 #define wxOSX_CLASS_ADD_METHOD( c, s, i, t ) \
1131     class_addMethod(c, s, i, t );
1132
1133 #else
1134
1135 #define wxOSX_CLASS_ADD_METHOD( c, s, i, t ) \
1136     { s, t, i },
1137
1138 #endif
1139
1140 void wxOSXCocoaClassAddWXMethods(Class c)
1141 {
1142
1143 #if OBJC_API_VERSION < 2
1144     static objc_method wxmethods[] =
1145     {
1146 #endif
1147
1148     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
1149     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
1150     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
1151
1152     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
1153     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
1154     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
1155
1156     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseMoved:), (IMP) wxOSX_mouseEvent, "v@:@" )
1157
1158     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
1159     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
1160     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
1161     
1162     wxOSX_CLASS_ADD_METHOD(c, @selector(acceptsFirstMouse:), (IMP) wxOSX_acceptsFirstMouse, "v@:@" )
1163
1164     wxOSX_CLASS_ADD_METHOD(c, @selector(scrollWheel:), (IMP) wxOSX_mouseEvent, "v@:@" )
1165     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseEntered:), (IMP) wxOSX_mouseEvent, "v@:@" )
1166     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseExited:), (IMP) wxOSX_mouseEvent, "v@:@" )
1167
1168     wxOSX_CLASS_ADD_METHOD(c, @selector(keyDown:), (IMP) wxOSX_keyEvent, "v@:@" )
1169     wxOSX_CLASS_ADD_METHOD(c, @selector(keyUp:), (IMP) wxOSX_keyEvent, "v@:@" )
1170     wxOSX_CLASS_ADD_METHOD(c, @selector(flagsChanged:), (IMP) wxOSX_keyEvent, "v@:@" )
1171
1172     wxOSX_CLASS_ADD_METHOD(c, @selector(insertText:), (IMP) wxOSX_insertText, "v@:@" )
1173
1174     wxOSX_CLASS_ADD_METHOD(c, @selector(performKeyEquivalent:), (IMP) wxOSX_performKeyEquivalent, "c@:@" )
1175
1176     wxOSX_CLASS_ADD_METHOD(c, @selector(acceptsFirstResponder), (IMP) wxOSX_acceptsFirstResponder, "c@:" )
1177     wxOSX_CLASS_ADD_METHOD(c, @selector(becomeFirstResponder), (IMP) wxOSX_becomeFirstResponder, "c@:" )
1178     wxOSX_CLASS_ADD_METHOD(c, @selector(resignFirstResponder), (IMP) wxOSX_resignFirstResponder, "c@:" )
1179     wxOSX_CLASS_ADD_METHOD(c, @selector(resetCursorRects), (IMP) wxOSX_resetCursorRects, "v@:" )
1180
1181     wxOSX_CLASS_ADD_METHOD(c, @selector(isFlipped), (IMP) wxOSX_isFlipped, "c@:" )
1182     wxOSX_CLASS_ADD_METHOD(c, @selector(drawRect:), (IMP) wxOSX_drawRect, "v@:{_NSRect={_NSPoint=ff}{_NSSize=ff}}" )
1183
1184     wxOSX_CLASS_ADD_METHOD(c, @selector(controlAction:), (IMP) wxOSX_controlAction, "v@:@" )
1185     wxOSX_CLASS_ADD_METHOD(c, @selector(controlDoubleAction:), (IMP) wxOSX_controlDoubleAction, "v@:@" )
1186
1187 #if wxUSE_DRAG_AND_DROP
1188     wxOSX_CLASS_ADD_METHOD(c, @selector(draggingEntered:), (IMP) wxOSX_draggingEntered, "I@:@" )
1189     wxOSX_CLASS_ADD_METHOD(c, @selector(draggingUpdated:), (IMP) wxOSX_draggingUpdated, "I@:@" )
1190     wxOSX_CLASS_ADD_METHOD(c, @selector(draggingExited:), (IMP) wxOSX_draggingExited, "v@:@" )
1191     wxOSX_CLASS_ADD_METHOD(c, @selector(performDragOperation:), (IMP) wxOSX_performDragOperation, "c@:@" )
1192 #endif
1193
1194 #if OBJC_API_VERSION < 2
1195     } ;
1196     static int method_count = WXSIZEOF( wxmethods );
1197     static objc_method_list *wxmethodlist = NULL;
1198     if ( wxmethodlist == NULL )
1199     {
1200         wxmethodlist = (objc_method_list*) malloc(sizeof(objc_method_list) + sizeof(wxmethods) );
1201         memcpy( &wxmethodlist->method_list[0], &wxmethods[0], sizeof(wxmethods) );
1202         wxmethodlist->method_count = method_count;
1203         wxmethodlist->obsolete = 0;
1204     }
1205     class_addMethods( c, wxmethodlist );
1206 #endif
1207 }
1208
1209 //
1210 // C++ implementation class
1211 //
1212
1213 IMPLEMENT_DYNAMIC_CLASS( wxWidgetCocoaImpl , wxWidgetImpl )
1214
1215 wxWidgetCocoaImpl::wxWidgetCocoaImpl( wxWindowMac* peer , WXWidget w, bool isRootControl ) :
1216     wxWidgetImpl( peer, isRootControl )
1217 {
1218     Init();
1219     m_osxView = w;
1220
1221     // check if the user wants to create the control initially hidden
1222     if ( !peer->IsShown() )
1223         SetVisibility(false);
1224
1225     // gc aware handling
1226     if ( m_osxView )
1227         CFRetain(m_osxView);
1228     [m_osxView release];
1229 }
1230
1231 wxWidgetCocoaImpl::wxWidgetCocoaImpl()
1232 {
1233     Init();
1234 }
1235
1236 void wxWidgetCocoaImpl::Init()
1237 {
1238     m_osxView = NULL;
1239     m_isFlipped = true;
1240     m_lastKeyDownEvent = NULL;
1241     m_hasEditor = false;
1242 }
1243
1244 wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
1245 {
1246     RemoveAssociations( this );
1247
1248     if ( !IsRootControl() )
1249     {
1250         NSView *sv = [m_osxView superview];
1251         if ( sv != nil )
1252             [m_osxView removeFromSuperview];
1253     }
1254     // gc aware handling
1255     if ( m_osxView )
1256         CFRelease(m_osxView);
1257 }
1258
1259 bool wxWidgetCocoaImpl::IsVisible() const
1260 {
1261     return [m_osxView isHiddenOrHasHiddenAncestor] == NO;
1262 }
1263
1264 void wxWidgetCocoaImpl::SetVisibility( bool visible )
1265 {
1266     [m_osxView setHidden:(visible ? NO:YES)];
1267 }
1268
1269 // ----------------------------------------------------------------------------
1270 // window animation stuff
1271 // ----------------------------------------------------------------------------
1272
1273 // define a delegate used to refresh the window during animation
1274 @interface wxNSAnimationDelegate : NSObject wxOSX_10_6_AND_LATER(<NSAnimationDelegate>)
1275 {
1276     wxWindow *m_win;
1277     bool m_isDone;
1278 }
1279
1280 - (id)init:(wxWindow *)win;
1281
1282 - (bool)isDone;
1283
1284 // NSAnimationDelegate methods
1285 - (void)animationDidEnd:(NSAnimation*)animation;
1286 - (void)animation:(NSAnimation*)animation
1287         didReachProgressMark:(NSAnimationProgress)progress;
1288 @end
1289
1290 @implementation wxNSAnimationDelegate
1291
1292 - (id)init:(wxWindow *)win
1293 {
1294     [super init];
1295
1296     m_win = win;
1297     m_isDone = false;
1298
1299     return self;
1300 }
1301
1302 - (bool)isDone
1303 {
1304     return m_isDone;
1305 }
1306
1307 - (void)animation:(NSAnimation*)animation
1308         didReachProgressMark:(NSAnimationProgress)progress
1309 {
1310     wxUnusedVar(animation);
1311     wxUnusedVar(progress);
1312
1313     m_win->SendSizeEvent();
1314 }
1315
1316 - (void)animationDidEnd:(NSAnimation*)animation
1317 {
1318     m_isDone = true;
1319 }
1320
1321 @end
1322
1323 /* static */
1324 bool
1325 wxWidgetCocoaImpl::ShowViewOrWindowWithEffect(wxWindow *win,
1326                                               bool show,
1327                                               wxShowEffect effect,
1328                                               unsigned timeout)
1329 {
1330     // create the dictionary describing the animation to perform on this view
1331     NSObject * const
1332         viewOrWin = static_cast<NSObject *>(win->OSXGetViewOrWindow());
1333     NSMutableDictionary * const
1334         dict = [NSMutableDictionary dictionaryWithCapacity:4];
1335     [dict setObject:viewOrWin forKey:NSViewAnimationTargetKey];
1336
1337     // determine the start and end rectangles assuming we're hiding the window
1338     const wxRect rectOrig = win->GetRect();
1339     wxRect rectStart,
1340            rectEnd;
1341     rectStart =
1342     rectEnd = rectOrig;
1343
1344     if ( show )
1345     {
1346         if ( effect == wxSHOW_EFFECT_ROLL_TO_LEFT ||
1347                 effect == wxSHOW_EFFECT_SLIDE_TO_LEFT )
1348             effect = wxSHOW_EFFECT_ROLL_TO_RIGHT;
1349         else if ( effect == wxSHOW_EFFECT_ROLL_TO_RIGHT ||
1350                     effect == wxSHOW_EFFECT_SLIDE_TO_RIGHT )
1351             effect = wxSHOW_EFFECT_ROLL_TO_LEFT;
1352         else if ( effect == wxSHOW_EFFECT_ROLL_TO_TOP ||
1353                     effect == wxSHOW_EFFECT_SLIDE_TO_TOP )
1354             effect = wxSHOW_EFFECT_ROLL_TO_BOTTOM;
1355         else if ( effect == wxSHOW_EFFECT_ROLL_TO_BOTTOM ||
1356                     effect == wxSHOW_EFFECT_SLIDE_TO_BOTTOM )
1357             effect = wxSHOW_EFFECT_ROLL_TO_TOP;
1358     }
1359
1360     switch ( effect )
1361     {
1362         case wxSHOW_EFFECT_ROLL_TO_LEFT:
1363         case wxSHOW_EFFECT_SLIDE_TO_LEFT:
1364             rectEnd.width = 0;
1365             break;
1366
1367         case wxSHOW_EFFECT_ROLL_TO_RIGHT:
1368         case wxSHOW_EFFECT_SLIDE_TO_RIGHT:
1369             rectEnd.x = rectStart.GetRight();
1370             rectEnd.width = 0;
1371             break;
1372
1373         case wxSHOW_EFFECT_ROLL_TO_TOP:
1374         case wxSHOW_EFFECT_SLIDE_TO_TOP:
1375             rectEnd.height = 0;
1376             break;
1377
1378         case wxSHOW_EFFECT_ROLL_TO_BOTTOM:
1379         case wxSHOW_EFFECT_SLIDE_TO_BOTTOM:
1380             rectEnd.y = rectStart.GetBottom();
1381             rectEnd.height = 0;
1382             break;
1383
1384         case wxSHOW_EFFECT_EXPAND:
1385             rectEnd.x = rectStart.x + rectStart.width / 2;
1386             rectEnd.y = rectStart.y + rectStart.height / 2;
1387             rectEnd.width =
1388             rectEnd.height = 0;
1389             break;
1390
1391         case wxSHOW_EFFECT_BLEND:
1392             [dict setObject:(show ? NSViewAnimationFadeInEffect
1393                                   : NSViewAnimationFadeOutEffect)
1394                   forKey:NSViewAnimationEffectKey];
1395             break;
1396
1397         case wxSHOW_EFFECT_NONE:
1398         case wxSHOW_EFFECT_MAX:
1399             wxFAIL_MSG( "unexpected animation effect" );
1400             return false;
1401
1402         default:
1403             wxFAIL_MSG( "unknown animation effect" );
1404             return false;
1405     };
1406
1407     if ( show )
1408     {
1409         // we need to restore it to the original rectangle instead of making it
1410         // disappear
1411         wxSwap(rectStart, rectEnd);
1412
1413         // and as the window is currently hidden, we need to show it for the
1414         // animation to be visible at all (but don't restore it at its full
1415         // rectangle as it shouldn't appear immediately)
1416         win->SetSize(rectStart);
1417         win->Show();
1418     }
1419
1420     NSView * const parentView = [viewOrWin isKindOfClass:[NSView class]]
1421                                     ? [(NSView *)viewOrWin superview]
1422                                     : nil;
1423     const NSRect rStart = wxToNSRect(parentView, rectStart);
1424     const NSRect rEnd = wxToNSRect(parentView, rectEnd);
1425
1426     [dict setObject:[NSValue valueWithRect:rStart]
1427           forKey:NSViewAnimationStartFrameKey];
1428     [dict setObject:[NSValue valueWithRect:rEnd]
1429           forKey:NSViewAnimationEndFrameKey];
1430
1431     // create an animation using the values in the above dictionary
1432     NSViewAnimation * const
1433         anim = [[NSViewAnimation alloc]
1434                 initWithViewAnimations:[NSArray arrayWithObject:dict]];
1435
1436     if ( !timeout )
1437     {
1438         // what is a good default duration? Windows uses 200ms, Web frameworks
1439         // use anything from 250ms to 1s... choose something in the middle
1440         timeout = 500;
1441     }
1442
1443     [anim setDuration:timeout/1000.];   // duration is in seconds here
1444
1445     // if the window being animated changes its layout depending on its size
1446     // (which is almost always the case) we need to redo it during animation
1447     //
1448     // the number of layouts here is arbitrary, but 10 seems like too few (e.g.
1449     // controls in wxInfoBar visibly jump around)
1450     const int NUM_LAYOUTS = 20;
1451     for ( float f = 1./NUM_LAYOUTS; f < 1.; f += 1./NUM_LAYOUTS )
1452         [anim addProgressMark:f];
1453
1454     wxNSAnimationDelegate * const
1455         animDelegate = [[wxNSAnimationDelegate alloc] init:win];
1456     [anim setDelegate:animDelegate];
1457     [anim startAnimation];
1458
1459     // Cocoa is capable of doing animation asynchronously or even from separate
1460     // thread but wx API doesn't provide any way to be notified about the
1461     // animation end and without this we really must ensure that the window has
1462     // the expected (i.e. the same as if a simple Show() had been used) size
1463     // when we return, so block here until the animation finishes
1464     //
1465     // notice that because the default animation mode is NSAnimationBlocking,
1466     // no user input events ought to be processed from here
1467     {
1468         wxEventLoopGuarantor ensureEventLoopExistence;
1469         wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
1470         while ( ![animDelegate isDone] )
1471             loop->Dispatch();
1472     }
1473
1474     if ( !show )
1475     {
1476         // NSViewAnimation is smart enough to hide the NSView being animated at
1477         // the end but we also must ensure that it's hidden for wx too
1478         win->Hide();
1479
1480         // and we must also restore its size because it isn't expected to
1481         // change just because the window was hidden
1482         win->SetSize(rectOrig);
1483     }
1484     else
1485     {
1486         // refresh it once again after the end to ensure that everything is in
1487         // place
1488         win->SendSizeEvent();
1489     }
1490
1491     [anim setDelegate:nil];
1492     [animDelegate release];
1493     [anim release];
1494
1495     return true;
1496 }
1497
1498 bool wxWidgetCocoaImpl::ShowWithEffect(bool show,
1499                                        wxShowEffect effect,
1500                                        unsigned timeout)
1501 {
1502     return ShowViewOrWindowWithEffect(m_wxPeer, show, effect, timeout);
1503 }
1504
1505 void wxWidgetCocoaImpl::Raise()
1506 {
1507     // Not implemented
1508 }
1509
1510 void wxWidgetCocoaImpl::Lower()
1511 {
1512     // Not implemented
1513 }
1514
1515 void wxWidgetCocoaImpl::ScrollRect( const wxRect *WXUNUSED(rect), int WXUNUSED(dx), int WXUNUSED(dy) )
1516 {
1517 #if 1
1518     SetNeedsDisplay() ;
1519 #else
1520     // We should do something like this, but it wasn't working in 10.4.
1521     if (GetNeedsDisplay() )
1522     {
1523         SetNeedsDisplay() ;
1524     }
1525     NSRect r = wxToNSRect( [m_osxView superview], *rect );
1526     NSSize offset = NSMakeSize((float)dx, (float)dy);
1527     [m_osxView scrollRect:r by:offset];
1528 #endif
1529 }
1530
1531 void wxWidgetCocoaImpl::Move(int x, int y, int width, int height)
1532 {
1533     wxWindowMac* parent = GetWXPeer()->GetParent();
1534     // under Cocoa we might have a contentView in the wxParent to which we have to
1535     // adjust the coordinates
1536     if (parent && [m_osxView superview] != parent->GetHandle() )
1537     {
1538         int cx = 0,cy = 0,cw = 0,ch = 0;
1539         if ( parent->GetPeer() )
1540         {
1541             parent->GetPeer()->GetContentArea(cx, cy, cw, ch);
1542             x -= cx;
1543             y -= cy;
1544         }
1545     }
1546     [[m_osxView superview] setNeedsDisplayInRect:[m_osxView frame]];
1547     NSRect r = wxToNSRect( [m_osxView superview], wxRect(x,y,width, height) );
1548     [m_osxView setFrame:r];
1549     [[m_osxView superview] setNeedsDisplayInRect:r];
1550
1551     wxNSView* wxview = (wxNSView*)m_osxView;
1552 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
1553     if ([wxview respondsToSelector:@selector(updateTrackingArea)] )
1554         [wxview updateTrackingArea]; 
1555 #else
1556     if ([m_osxView respondsToSelector:@selector(trackingTag)] )
1557     {
1558         if ( [wxview trackingTag] )
1559             [wxview removeTrackingRect: [wxview trackingTag]];
1560
1561         [wxview setTrackingTag: [wxview addTrackingRect: [m_osxView bounds] owner: wxview userData: nil assumeInside: NO]];
1562     }
1563 #endif
1564 }
1565
1566 void wxWidgetCocoaImpl::GetPosition( int &x, int &y ) const
1567 {
1568     wxRect r = wxFromNSRect( [m_osxView superview], [m_osxView frame] );
1569     x = r.GetLeft();
1570     y = r.GetTop();
1571 }
1572
1573 void wxWidgetCocoaImpl::GetSize( int &width, int &height ) const
1574 {
1575     NSRect rect = [m_osxView frame];
1576     width = (int)rect.size.width;
1577     height = (int)rect.size.height;
1578 }
1579
1580 void wxWidgetCocoaImpl::GetContentArea( int&left, int &top, int &width, int &height ) const
1581 {
1582     if ( [m_osxView respondsToSelector:@selector(contentView) ] )
1583     {
1584         NSView* cv = [m_osxView contentView];
1585
1586         NSRect bounds = [m_osxView bounds];
1587         NSRect rect = [cv frame];
1588
1589         int y = (int)rect.origin.y;
1590         int x = (int)rect.origin.x;
1591         if ( ![ m_osxView isFlipped ] )
1592             y = (int)(bounds.size.height - (rect.origin.y + rect.size.height));
1593         left = x;
1594         top = y;
1595         width = (int)rect.size.width;
1596         height = (int)rect.size.height;
1597     }
1598     else
1599     {
1600         left = top = 0;
1601         GetSize( width, height );
1602     }
1603 }
1604
1605 void wxWidgetCocoaImpl::SetNeedsDisplay( const wxRect* where )
1606 {
1607     if ( where )
1608         [m_osxView setNeedsDisplayInRect:wxToNSRect(m_osxView, *where )];
1609     else
1610         [m_osxView setNeedsDisplay:YES];
1611 }
1612
1613 bool wxWidgetCocoaImpl::GetNeedsDisplay() const
1614 {
1615     return [m_osxView needsDisplay];
1616 }
1617
1618 bool wxWidgetCocoaImpl::CanFocus() const
1619 {
1620     return [m_osxView canBecomeKeyView] == YES;
1621 }
1622
1623 bool wxWidgetCocoaImpl::HasFocus() const
1624 {
1625     return ( FindFocus() == m_osxView );
1626 }
1627
1628 bool wxWidgetCocoaImpl::SetFocus()
1629 {
1630     if ( [m_osxView canBecomeKeyView] == NO )
1631         return false;
1632
1633     [[m_osxView window] makeFirstResponder: m_osxView] ;
1634     [[m_osxView window] makeKeyAndOrderFront:nil] ;
1635     return true;
1636 }
1637
1638
1639 void wxWidgetCocoaImpl::RemoveFromParent()
1640 {
1641     [m_osxView removeFromSuperview];
1642 }
1643
1644 void wxWidgetCocoaImpl::Embed( wxWidgetImpl *parent )
1645 {
1646     NSView* container = parent->GetWXWidget() ;
1647     wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
1648     [container addSubview:m_osxView];
1649 }
1650
1651 void wxWidgetCocoaImpl::SetBackgroundColour( const wxColour &col )
1652 {
1653     NSView* targetView = m_osxView;
1654     if ( [m_osxView isKindOfClass:[NSScrollView class] ] )
1655         targetView = [(NSScrollView*) m_osxView documentView];
1656
1657     if ( [targetView respondsToSelector:@selector(setBackgroundColor:) ] )
1658     {
1659         [targetView setBackgroundColor:[NSColor colorWithCalibratedRed:(CGFloat) (col.Red() / 255.0)
1660                                                                 green:(CGFloat) (col.Green() / 255.0)
1661                                                                  blue:(CGFloat) (col.Blue() / 255.0)
1662                                                                 alpha:(CGFloat) (col.Alpha() / 255.0)]];
1663     }
1664 }
1665
1666 void wxWidgetCocoaImpl::SetLabel( const wxString& title, wxFontEncoding encoding )
1667 {
1668     if ( [m_osxView respondsToSelector:@selector(setTitle:) ] )
1669     {
1670         wxCFStringRef cf( title , encoding );
1671         [m_osxView setTitle:cf.AsNSString()];
1672     }
1673     else if ( [m_osxView respondsToSelector:@selector(setStringValue:) ] )
1674     {
1675         wxCFStringRef cf( title , encoding );
1676         [m_osxView setStringValue:cf.AsNSString()];
1677     }
1678 }
1679
1680
1681 void  wxWidgetImpl::Convert( wxPoint *pt , wxWidgetImpl *from , wxWidgetImpl *to )
1682 {
1683     NSPoint p = wxToNSPoint( from->GetWXWidget(), *pt );
1684     p = [from->GetWXWidget() convertPoint:p toView:to->GetWXWidget() ];
1685     *pt = wxFromNSPoint( to->GetWXWidget(), p );
1686 }
1687
1688 wxInt32 wxWidgetCocoaImpl::GetValue() const
1689 {
1690     return [(NSControl*)m_osxView intValue];
1691 }
1692
1693 void wxWidgetCocoaImpl::SetValue( wxInt32 v )
1694 {
1695     if (  [m_osxView respondsToSelector:@selector(setIntValue:)] )
1696     {
1697         [m_osxView setIntValue:v];
1698     }
1699     else if (  [m_osxView respondsToSelector:@selector(setFloatValue:)] )
1700     {
1701         [m_osxView setFloatValue:(double)v];
1702     }
1703     else if (  [m_osxView respondsToSelector:@selector(setDoubleValue:)] )
1704     {
1705         [m_osxView setDoubleValue:(double)v];
1706     }
1707 }
1708
1709 void wxWidgetCocoaImpl::SetMinimum( wxInt32 v )
1710 {
1711     if (  [m_osxView respondsToSelector:@selector(setMinValue:)] )
1712     {
1713         [m_osxView setMinValue:(double)v];
1714     }
1715 }
1716
1717 void wxWidgetCocoaImpl::SetMaximum( wxInt32 v )
1718 {
1719     if (  [m_osxView respondsToSelector:@selector(setMaxValue:)] )
1720     {
1721         [m_osxView setMaxValue:(double)v];
1722     }
1723 }
1724
1725 wxInt32 wxWidgetCocoaImpl::GetMinimum() const
1726 {
1727     if (  [m_osxView respondsToSelector:@selector(getMinValue:)] )
1728     {
1729         return (int)[m_osxView minValue];
1730     }
1731     return 0;
1732 }
1733
1734 wxInt32 wxWidgetCocoaImpl::GetMaximum() const
1735 {
1736     if (  [m_osxView respondsToSelector:@selector(getMaxValue:)] )
1737     {
1738         return (int)[m_osxView maxValue];
1739     }
1740     return 0;
1741 }
1742
1743 wxBitmap wxWidgetCocoaImpl::GetBitmap() const
1744 {
1745     wxBitmap bmp;
1746
1747     // TODO: how to create a wxBitmap from NSImage?
1748 #if 0
1749     if ( [m_osxView respondsToSelector:@selector(image:)] )
1750         bmp = [m_osxView image];
1751 #endif
1752
1753     return bmp;
1754 }
1755
1756 void wxWidgetCocoaImpl::SetBitmap( const wxBitmap& bitmap )
1757 {
1758     if (  [m_osxView respondsToSelector:@selector(setImage:)] )
1759     {
1760         [m_osxView setImage:bitmap.GetNSImage()];
1761         [m_osxView setNeedsDisplay:YES];
1762     }
1763 }
1764
1765 void wxWidgetCocoaImpl::SetBitmapPosition( wxDirection dir )
1766 {
1767     if ( [m_osxView respondsToSelector:@selector(setImagePosition:)] )
1768     {
1769         NSCellImagePosition pos;
1770         switch ( dir )
1771         {
1772             case wxLEFT:
1773                 pos = NSImageLeft;
1774                 break;
1775
1776             case wxRIGHT:
1777                 pos = NSImageRight;
1778                 break;
1779
1780             case wxTOP:
1781                 pos = NSImageAbove;
1782                 break;
1783
1784             case wxBOTTOM:
1785                 pos = NSImageBelow;
1786                 break;
1787
1788             default:
1789                 wxFAIL_MSG( "invalid image position" );
1790                 pos = NSNoImage;
1791         }
1792
1793         [m_osxView setImagePosition:pos];
1794     }
1795 }
1796
1797 void wxWidgetCocoaImpl::SetupTabs( const wxNotebook& WXUNUSED(notebook))
1798 {
1799     // implementation in subclass
1800 }
1801
1802 void wxWidgetCocoaImpl::GetBestRect( wxRect *r ) const
1803 {
1804     r->x = r->y = r->width = r->height = 0;
1805
1806     if (  [m_osxView respondsToSelector:@selector(sizeToFit)] )
1807     {
1808         NSRect former = [m_osxView frame];
1809         [m_osxView sizeToFit];
1810         NSRect best = [m_osxView frame];
1811         [m_osxView setFrame:former];
1812         r->width = (int)best.size.width;
1813         r->height = (int)best.size.height;
1814     }
1815 }
1816
1817 bool wxWidgetCocoaImpl::IsEnabled() const
1818 {
1819     if ( [m_osxView respondsToSelector:@selector(isEnabled) ] )
1820         return [m_osxView isEnabled];
1821     return true;
1822 }
1823
1824 void wxWidgetCocoaImpl::Enable( bool enable )
1825 {
1826     if ( [m_osxView respondsToSelector:@selector(setEnabled:) ] )
1827         [m_osxView setEnabled:enable];
1828 }
1829
1830 void wxWidgetCocoaImpl::PulseGauge()
1831 {
1832 }
1833
1834 void wxWidgetCocoaImpl::SetScrollThumb( wxInt32 WXUNUSED(val), wxInt32 WXUNUSED(view) )
1835 {
1836 }
1837
1838 void wxWidgetCocoaImpl::SetControlSize( wxWindowVariant variant )
1839 {
1840     NSControlSize size = NSRegularControlSize;
1841
1842     switch ( variant )
1843     {
1844         case wxWINDOW_VARIANT_NORMAL :
1845             size = NSRegularControlSize;
1846             break ;
1847
1848         case wxWINDOW_VARIANT_SMALL :
1849             size = NSSmallControlSize;
1850             break ;
1851
1852         case wxWINDOW_VARIANT_MINI :
1853             size = NSMiniControlSize;
1854             break ;
1855
1856         case wxWINDOW_VARIANT_LARGE :
1857             size = NSRegularControlSize;
1858             break ;
1859
1860         default:
1861             wxFAIL_MSG(wxT("unexpected window variant"));
1862             break ;
1863     }
1864     if ( [m_osxView respondsToSelector:@selector(setControlSize:)] )
1865         [m_osxView setControlSize:size];
1866     else if ([m_osxView respondsToSelector:@selector(cell)])
1867     {
1868         id cell = [(id)m_osxView cell];
1869         if ([cell respondsToSelector:@selector(setControlSize:)])
1870             [cell setControlSize:size];
1871     }
1872 }
1873
1874 void wxWidgetCocoaImpl::SetFont(wxFont const& font, wxColour const&, long, bool)
1875 {
1876     if ([m_osxView respondsToSelector:@selector(setFont:)])
1877         [m_osxView setFont: font.OSXGetNSFont()];
1878 }
1879
1880 void wxWidgetCocoaImpl::InstallEventHandler( WXWidget control )
1881 {
1882     WXWidget c =  control ? control : (WXWidget) m_osxView;
1883     wxWidgetImpl::Associate( c, this ) ;
1884     if ([c respondsToSelector:@selector(setAction:)])
1885     {
1886         [c setTarget: c];
1887         [c setAction: @selector(controlAction:)];
1888         if ([c respondsToSelector:@selector(setDoubleAction:)])
1889         {
1890             [c setDoubleAction: @selector(controlDoubleAction:)];
1891         }
1892
1893     }
1894 }
1895
1896 bool wxWidgetCocoaImpl::DoHandleCharEvent(NSEvent *event, NSString *text)
1897 {
1898     wxKeyEvent wxevent(wxEVT_CHAR);
1899     SetupKeyEvent( wxevent, event, text );
1900
1901     return GetWXPeer()->OSXHandleKeyEvent(wxevent);
1902 }
1903
1904 bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event)
1905 {
1906     wxKeyEvent wxevent(wxEVT_KEY_DOWN);
1907     SetupKeyEvent( wxevent, event );
1908     bool result = GetWXPeer()->OSXHandleKeyEvent(wxevent);
1909
1910     // this will fire higher level events, like insertText, to help
1911     // us handle EVT_CHAR, etc.
1912
1913     if ( m_wxPeer->MacIsUserPane() && [event type] == NSKeyDown)
1914     {
1915         if ( !result )
1916         {
1917             if ( [m_osxView isKindOfClass:[NSScrollView class] ] )
1918                 [[(NSScrollView*)m_osxView documentView] interpretKeyEvents:[NSArray arrayWithObject:event]];
1919             else
1920                 [m_osxView interpretKeyEvents:[NSArray arrayWithObject:event]];
1921             result = true;
1922         }
1923     }
1924
1925     return result;
1926 }
1927
1928 bool wxWidgetCocoaImpl::DoHandleMouseEvent(NSEvent *event)
1929 {
1930     NSPoint clickLocation;
1931     clickLocation = [m_osxView convertPoint:[event locationInWindow] fromView:nil];
1932     wxPoint pt = wxFromNSPoint( m_osxView, clickLocation );
1933     wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
1934     SetupMouseEvent(wxevent , event) ;
1935     wxevent.m_x = pt.x;
1936     wxevent.m_y = pt.y;
1937
1938     return GetWXPeer()->HandleWindowEvent(wxevent);
1939 }
1940
1941 void wxWidgetCocoaImpl::DoNotifyFocusEvent(bool receivedFocus, wxWidgetImpl* otherWindow)
1942 {
1943     wxWindow* thisWindow = GetWXPeer();
1944     if ( thisWindow->MacGetTopLevelWindow() && NeedsFocusRect() )
1945     {
1946         thisWindow->MacInvalidateBorders();
1947     }
1948
1949     if ( receivedFocus )
1950     {
1951         wxLogTrace(wxT("Focus"), wxT("focus set(%p)"), static_cast<void*>(thisWindow));
1952         wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
1953         thisWindow->HandleWindowEvent(eventFocus);
1954
1955 #if wxUSE_CARET
1956         if ( thisWindow->GetCaret() )
1957             thisWindow->GetCaret()->OnSetFocus();
1958 #endif
1959
1960         wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
1961         event.SetEventObject(thisWindow);
1962         if (otherWindow)
1963             event.SetWindow(otherWindow->GetWXPeer());
1964         thisWindow->HandleWindowEvent(event) ;
1965     }
1966     else // !receivedFocuss
1967     {
1968 #if wxUSE_CARET
1969         if ( thisWindow->GetCaret() )
1970             thisWindow->GetCaret()->OnKillFocus();
1971 #endif
1972
1973         wxLogTrace(wxT("Focus"), wxT("focus lost(%p)"), static_cast<void*>(thisWindow));
1974
1975         wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
1976         event.SetEventObject(thisWindow);
1977         if (otherWindow)
1978             event.SetWindow(otherWindow->GetWXPeer());
1979         thisWindow->HandleWindowEvent(event) ;
1980     }
1981 }
1982
1983 void wxWidgetCocoaImpl::SetCursor(const wxCursor& cursor)
1984 {
1985     NSPoint location = [NSEvent mouseLocation];
1986     location = [[m_osxView window] convertScreenToBase:location];
1987     NSPoint locationInView = [m_osxView convertPoint:location fromView:nil];
1988
1989     if( NSMouseInRect(locationInView, [m_osxView bounds], YES) )
1990     {
1991         [(NSCursor*)cursor.GetHCURSOR() set];
1992     }
1993     [[m_osxView window] invalidateCursorRectsForView:m_osxView];
1994 }
1995
1996 void wxWidgetCocoaImpl::CaptureMouse()
1997 {
1998     [[m_osxView window] disableCursorRects];
1999 }
2000
2001 void wxWidgetCocoaImpl::ReleaseMouse()
2002 {
2003     [[m_osxView window] enableCursorRects];
2004 }
2005
2006 void wxWidgetCocoaImpl::SetFlipped(bool flipped)
2007 {
2008     m_isFlipped = flipped;
2009 }
2010
2011 //
2012 // Factory methods
2013 //
2014
2015 wxWidgetImpl* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, wxWindowMac* WXUNUSED(parent),
2016     wxWindowID WXUNUSED(id), const wxPoint& pos, const wxSize& size,
2017     long WXUNUSED(style), long WXUNUSED(extraStyle))
2018 {
2019     NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
2020     wxNSView* v = [[wxNSView alloc] initWithFrame:r];
2021
2022     // temporary hook for dnd
2023     [v registerForDraggedTypes:[NSArray arrayWithObjects:
2024         NSStringPboardType, NSFilenamesPboardType, NSTIFFPboardType, NSPICTPboardType, NSPDFPboardType, nil]];
2025
2026     wxWidgetCocoaImpl* c = new wxWidgetCocoaImpl( wxpeer, v );
2027     return c;
2028 }
2029
2030 wxWidgetImpl* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now )
2031 {
2032     NSWindow* tlw = now->GetWXWindow();
2033     wxNSView* v = [[wxNSView alloc] initWithFrame:[[tlw contentView] frame]];
2034     wxWidgetCocoaImpl* c = new wxWidgetCocoaImpl( now, v, true );
2035     c->InstallEventHandler();
2036     [tlw setContentView:v];
2037     return c;
2038 }