adapting char event handling to msw / gtk, see #13415, see #14197
[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$
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/frame.h"
17     #include "wx/log.h"
18     #include "wx/textctrl.h"
19     #include "wx/combobox.h"
20 #endif
21
22 #ifdef __WXMAC__
23     #include "wx/osx/private.h"
24 #endif
25
26 #include "wx/evtloop.h"
27
28 #if wxUSE_CARET
29     #include "wx/caret.h"
30 #endif
31
32 #if wxUSE_DRAG_AND_DROP
33     #include "wx/dnd.h"
34 #endif
35
36 #if wxUSE_TOOLTIPS
37     #include "wx/tooltip.h"
38 #endif
39
40 #include <objc/objc-runtime.h>
41
42 // Get the window with the focus
43
44 NSView* GetViewFromResponder( NSResponder* responder )
45 {
46     NSView* view = nil;
47     if ( [responder isKindOfClass:[NSTextView class]] )
48     {
49         NSView* delegate = (NSView*) [(NSTextView*)responder delegate];
50         if ( [delegate isKindOfClass:[NSTextField class] ] )
51             view = delegate;
52         else
53             view =  (NSView*) responder;
54     }
55     else
56     {
57         if ( [responder isKindOfClass:[NSView class]] )
58             view = (NSView*) responder;
59     }
60     return view;
61 }
62
63 NSView* GetFocusedViewInWindow( NSWindow* keyWindow )
64 {
65     NSView* focusedView = nil;
66     if ( keyWindow != nil )
67         focusedView = GetViewFromResponder([keyWindow firstResponder]);
68
69     return focusedView;
70 }
71
72 WXWidget wxWidgetImpl::FindFocus()
73 {
74     return GetFocusedViewInWindow( [NSApp keyWindow] );
75 }
76
77 NSRect wxOSXGetFrameForControl( wxWindowMac* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
78 {
79     int x, y, w, h ;
80
81     window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
82     wxRect bounds(x,y,w,h);
83     NSView* sv = (window->GetParent()->GetHandle() );
84
85     return wxToNSRect( sv, bounds );
86 }
87
88 @interface wxNSView : NSView
89 {
90     BOOL _hasToolTip;    
91     NSTrackingRectTag   _lastToolTipTrackTag;
92     id              _lastToolTipOwner;
93     void*           _lastUserData;
94     
95 }
96
97 @end // wxNSView
98
99 @interface NSView(PossibleMethods)
100 - (void)setTitle:(NSString *)aString;
101 - (void)setStringValue:(NSString *)aString;
102 - (void)setIntValue:(int)anInt;
103 - (void)setFloatValue:(float)aFloat;
104 - (void)setDoubleValue:(double)aDouble;
105
106 - (double)minValue;
107 - (double)maxValue;
108 - (void)setMinValue:(double)aDouble;
109 - (void)setMaxValue:(double)aDouble;
110
111 - (void)sizeToFit;
112
113 - (BOOL)isEnabled;
114 - (void)setEnabled:(BOOL)flag;
115
116 - (void)setImage:(NSImage *)image;
117 - (void)setControlSize:(NSControlSize)size;
118
119 - (void)setFont:(NSFont *)fontObject;
120
121 - (id)contentView;
122
123 - (void)setTarget:(id)anObject;
124 - (void)setAction:(SEL)aSelector;
125 - (void)setDoubleAction:(SEL)aSelector;
126 - (void)setBackgroundColor:(NSColor*)aColor;
127 - (void)setOpaque:(BOOL)opaque;
128 - (void)setTextColor:(NSColor *)color;
129 - (void)setImagePosition:(NSCellImagePosition)aPosition;
130 @end
131
132 // The following code is a combination of the code listed here:
133 // http://lists.apple.com/archives/cocoa-dev/2008/Apr/msg01582.html
134 // (which can't be used because KLGetCurrentKeyboardLayout etc aren't 64-bit)
135 // and the code here:
136 // http://inquisitivecocoa.com/category/objective-c/
137 @interface NSEvent (OsGuiUtilsAdditions)
138 - (NSString*) charactersIgnoringModifiersIncludingShift;
139 @end
140
141 @implementation NSEvent (OsGuiUtilsAdditions)
142 - (NSString*) charactersIgnoringModifiersIncludingShift {
143     // First try -charactersIgnoringModifiers and look for keys which UCKeyTranslate translates
144     // differently than AppKit.
145     NSString* c = [self charactersIgnoringModifiers];
146     if ([c length] == 1) {
147         unichar codepoint = [c characterAtIndex:0];
148         if ((codepoint >= 0xF700 && codepoint <= 0xF8FF) || codepoint == 0x7F) {
149             return c;
150         }
151     }
152     // This is not a "special" key, so ask UCKeyTranslate to give us the character with no
153     // modifiers attached.  Actually, that's not quite accurate; we attach the Command modifier
154     // which hints the OS to use Latin characters where possible, which is generally what we want.
155     NSString* result = @"";
156     TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
157     CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
158     CFRelease(currentKeyboard);
159     if (uchr == NULL) {
160         // this can happen for some non-U.S. input methods (eg. Romaji or Hiragana)
161         return c;
162     }
163     const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
164     if (keyboardLayout) {
165         UInt32 deadKeyState = 0;
166         UniCharCount maxStringLength = 255;
167         UniCharCount actualStringLength = 0;
168         UniChar unicodeString[maxStringLength];
169         
170         OSStatus status = UCKeyTranslate(keyboardLayout,
171                                          [self keyCode],
172                                          kUCKeyActionDown,
173                                          cmdKey >> 8,         // force the Command key to "on"
174                                          LMGetKbdType(),
175                                          kUCKeyTranslateNoDeadKeysMask,
176                                          &deadKeyState,
177                                          maxStringLength,
178                                          &actualStringLength,
179                                          unicodeString);
180         
181         if(status == noErr)
182             result = [NSString stringWithCharacters:unicodeString length:(NSInteger)actualStringLength];
183     }
184     return result;
185 }
186 @end
187
188 long wxOSXTranslateCocoaKey( NSEvent* event, int eventType )
189 {
190     long retval = 0;
191
192     if ([event type] != NSFlagsChanged)
193     {
194         NSString* s = [event charactersIgnoringModifiersIncludingShift];
195         // backspace char reports as delete w/modifiers for some reason
196         if ([s length] == 1)
197         {
198             if ( eventType == wxEVT_CHAR && ([event modifierFlags] & NSControlKeyMask) && ( [s characterAtIndex:0] >= 'a' && [s characterAtIndex:0] <= 'z' ) )
199             {
200                 retval = WXK_CONTROL_A + ([s characterAtIndex:0] - 'a');
201             }
202             else
203             {
204                 switch ( [s characterAtIndex:0] )
205                 {
206                     // backspace key
207                     case 0x7F :
208                     case 8 :
209                         retval = WXK_BACK;
210                         break;
211                     case NSUpArrowFunctionKey :
212                         retval = WXK_UP;
213                         break;
214                     case NSDownArrowFunctionKey :
215                         retval = WXK_DOWN;
216                         break;
217                     case NSLeftArrowFunctionKey :
218                         retval = WXK_LEFT;
219                         break;
220                     case NSRightArrowFunctionKey :
221                         retval = WXK_RIGHT;
222                         break;
223                     case NSInsertFunctionKey  :
224                         retval = WXK_INSERT;
225                         break;
226                     case NSDeleteFunctionKey  :
227                         retval = WXK_DELETE;
228                         break;
229                     case NSHomeFunctionKey  :
230                         retval = WXK_HOME;
231                         break;
232             //        case NSBeginFunctionKey  :
233             //            retval = WXK_BEGIN;
234             //            break;
235                     case NSEndFunctionKey  :
236                         retval = WXK_END;
237                         break;
238                     case NSPageUpFunctionKey  :
239                         retval = WXK_PAGEUP;
240                         break;
241                    case NSPageDownFunctionKey  :
242                         retval = WXK_PAGEDOWN;
243                         break;
244                    case NSHelpFunctionKey  :
245                         retval = WXK_HELP;
246                         break;
247                     default:
248                         int intchar = [s characterAtIndex: 0];
249                         if ( intchar >= NSF1FunctionKey && intchar <= NSF24FunctionKey )
250                             retval = WXK_F1 + (intchar - NSF1FunctionKey );
251                         else if ( intchar > 0 && intchar < 32 )
252                             retval = intchar;
253                         break;
254                 }
255             }
256         }
257     }
258
259     // Some keys don't seem to have constants. The code mimics the approach
260     // taken by WebKit. See:
261     // http://trac.webkit.org/browser/trunk/WebCore/platform/mac/KeyEventMac.mm
262     switch( [event keyCode] )
263     {
264         // command key
265         case 54:
266         case 55:
267             retval = WXK_CONTROL;
268             break;
269         // caps locks key
270         case 57: // Capslock
271             retval = WXK_CAPITAL;
272             break;
273         // shift key
274         case 56: // Left Shift
275         case 60: // Right Shift
276             retval = WXK_SHIFT;
277             break;
278         // alt key
279         case 58: // Left Alt
280         case 61: // Right Alt
281             retval = WXK_ALT;
282             break;
283         // ctrl key
284         case 59: // Left Ctrl
285         case 62: // Right Ctrl
286             retval = WXK_RAW_CONTROL;
287             break;
288         // clear key
289         case 71:
290             retval = WXK_CLEAR;
291             break;
292         // tab key
293         case 48:
294             retval = WXK_TAB;
295             break;
296
297         case 75: // /
298             retval = WXK_NUMPAD_DIVIDE;
299             break;
300         case 67: // *
301             retval = WXK_NUMPAD_MULTIPLY;
302             break;
303         case 78: // -
304             retval = WXK_NUMPAD_SUBTRACT;
305             break;
306         case 69: // +
307             retval = WXK_NUMPAD_ADD;
308             break;
309         case 76: // Enter
310             retval = WXK_NUMPAD_ENTER;
311             break;
312         case 65: // .
313             retval = WXK_NUMPAD_DECIMAL;
314             break;
315         case 82: // 0
316             retval = WXK_NUMPAD0;
317             break;
318         case 83: // 1
319             retval = WXK_NUMPAD1;
320             break;
321         case 84: // 2
322             retval = WXK_NUMPAD2;
323             break;
324         case 85: // 3
325             retval = WXK_NUMPAD3;
326             break;
327         case 86: // 4
328             retval = WXK_NUMPAD4;
329             break;
330         case 87: // 5
331             retval = WXK_NUMPAD5;
332             break;
333         case 88: // 6
334             retval = WXK_NUMPAD6;
335             break;
336         case 89: // 7
337             retval = WXK_NUMPAD7;
338             break;
339         case 91: // 8
340             retval = WXK_NUMPAD8;
341             break;
342         case 92: // 9
343             retval = WXK_NUMPAD9;
344             break;
345         default:
346             //retval = [event keyCode];
347             break;
348     }
349     return retval;
350 }
351
352 void wxWidgetCocoaImpl::SetupKeyEvent(wxKeyEvent &wxevent , NSEvent * nsEvent, NSString* charString)
353 {
354     UInt32 modifiers = [nsEvent modifierFlags] ;
355     int eventType = [nsEvent type];
356
357     wxevent.m_shiftDown = modifiers & NSShiftKeyMask;
358     wxevent.m_rawControlDown = modifiers & NSControlKeyMask;
359     wxevent.m_altDown = modifiers & NSAlternateKeyMask;
360     wxevent.m_controlDown = modifiers & NSCommandKeyMask;
361
362     wxevent.m_rawCode = [nsEvent keyCode];
363     wxevent.m_rawFlags = modifiers;
364
365     wxevent.SetTimestamp( (int)([nsEvent timestamp] * 1000) ) ;
366
367     wxString chars;
368     if ( eventType != NSFlagsChanged )
369     {
370         NSString* nschars = [[nsEvent charactersIgnoringModifiersIncludingShift] uppercaseString];
371         if ( charString )
372         {
373             // if charString is set, it did not come from key up / key down
374             wxevent.SetEventType( wxEVT_CHAR );
375             chars = wxCFStringRef::AsString(charString);
376         }
377         else if ( nschars )
378         {
379             chars = wxCFStringRef::AsString(nschars);
380         }
381     }
382
383     int aunichar = chars.Length() > 0 ? chars[0] : 0;
384     long keyval = 0;
385
386     if (wxevent.GetEventType() != wxEVT_CHAR)
387     {
388         keyval = wxOSXTranslateCocoaKey(nsEvent, wxevent.GetEventType()) ;
389         switch (eventType)
390         {
391             case NSKeyDown :
392                 wxevent.SetEventType( wxEVT_KEY_DOWN )  ;
393                 break;
394             case NSKeyUp :
395                 wxevent.SetEventType( wxEVT_KEY_UP )  ;
396                 break;
397             case NSFlagsChanged :
398                 switch (keyval)
399                 {
400                     case WXK_CONTROL:
401                         wxevent.SetEventType( wxevent.m_controlDown ? wxEVT_KEY_DOWN : wxEVT_KEY_UP);
402                         break;
403                     case WXK_SHIFT:
404                         wxevent.SetEventType( wxevent.m_shiftDown ? wxEVT_KEY_DOWN : wxEVT_KEY_UP);
405                         break;
406                     case WXK_ALT:
407                         wxevent.SetEventType( wxevent.m_altDown ? wxEVT_KEY_DOWN : wxEVT_KEY_UP);
408                         break;
409                     case WXK_RAW_CONTROL:
410                         wxevent.SetEventType( wxevent.m_rawControlDown ? wxEVT_KEY_DOWN : wxEVT_KEY_UP);
411                         break;
412                 }
413                 break;
414             default :
415                 break ;
416         }
417     }
418
419     if ( !keyval )
420     {
421         if ( wxevent.GetEventType() == wxEVT_KEY_UP || wxevent.GetEventType() == wxEVT_KEY_DOWN )
422             keyval = wxToupper( aunichar ) ;
423         else
424             keyval = aunichar;
425     }
426
427 #if wxUSE_UNICODE
428     // OS X generates events with key codes in Unicode private use area for
429     // unprintable symbols such as cursor arrows (WXK_UP is mapped to U+F700)
430     // and function keys (WXK_F2 is U+F705). We don't want to use them as the
431     // result of wxKeyEvent::GetUnicodeKey() however as it's supposed to return
432     // WXK_NONE for "non characters" so explicitly exclude them.
433     //
434     // We only exclude the private use area inside the Basic Multilingual Plane
435     // as key codes beyond it don't seem to be currently used.
436     if ( !(aunichar >= 0xe000 && aunichar < 0xf900) )
437         wxevent.m_uniChar = aunichar;
438 #endif
439     wxevent.m_keyCode = keyval;
440
441     wxWindowMac* peer = GetWXPeer();
442     if ( peer )
443     {
444         wxevent.SetEventObject(peer);
445         wxevent.SetId(peer->GetId()) ;
446     }
447 }
448
449 UInt32 g_lastButton = 0 ;
450 bool g_lastButtonWasFakeRight = false ;
451
452 // better scroll wheel support 
453 // see http://lists.apple.com/archives/cocoa-dev/2007/Feb/msg00050.html
454
455 @interface NSEvent (DeviceDelta)
456 - (CGFloat)deviceDeltaX;
457 - (CGFloat)deviceDeltaY;
458 @end
459
460 void wxWidgetCocoaImpl::SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
461 {
462     int eventType = [nsEvent type];
463     UInt32 modifiers = [nsEvent modifierFlags] ;
464
465     NSPoint locationInWindow = [nsEvent locationInWindow];
466     
467     // adjust coordinates for the window of the target view
468     if ( [nsEvent window] != [m_osxView window] )
469     {
470         if ( [nsEvent window] != nil )
471             locationInWindow = [[nsEvent window] convertBaseToScreen:locationInWindow];
472
473         if ( [m_osxView window] != nil )
474             locationInWindow = [[m_osxView window] convertScreenToBase:locationInWindow];
475     }
476
477     NSPoint locationInView = [m_osxView convertPoint:locationInWindow fromView:nil];
478     wxPoint locationInViewWX = wxFromNSPoint( m_osxView, locationInView );
479
480     // these parameters are not given for all events
481     UInt32 button = [nsEvent buttonNumber];
482     UInt32 clickCount = 0;
483
484     wxevent.m_x = locationInViewWX.x;
485     wxevent.m_y = locationInViewWX.y;
486     wxevent.m_shiftDown = modifiers & NSShiftKeyMask;
487     wxevent.m_rawControlDown = modifiers & NSControlKeyMask;
488     wxevent.m_altDown = modifiers & NSAlternateKeyMask;
489     wxevent.m_controlDown = modifiers & NSCommandKeyMask;
490     wxevent.SetTimestamp( (int)([nsEvent timestamp] * 1000) ) ;
491
492     UInt32 mouseChord = 0;
493
494     switch (eventType)
495     {
496         case NSLeftMouseDown :
497         case NSLeftMouseDragged :
498             mouseChord = 1U;
499             break;
500         case NSRightMouseDown :
501         case NSRightMouseDragged :
502             mouseChord = 2U;
503             break;
504         case NSOtherMouseDown :
505         case NSOtherMouseDragged :
506             mouseChord = 4U;
507             break;
508     }
509
510     // a control click is interpreted as a right click
511     bool thisButtonIsFakeRight = false ;
512     if ( button == 0 && (modifiers & NSControlKeyMask) )
513     {
514         button = 1 ;
515         thisButtonIsFakeRight = true ;
516     }
517
518     // otherwise we report double clicks by connecting a left click with a ctrl-left click
519     if ( clickCount > 1 && button != g_lastButton )
520         clickCount = 1 ;
521
522     // we must make sure that our synthetic 'right' button corresponds in
523     // mouse down, moved and mouse up, and does not deliver a right down and left up
524     switch (eventType)
525     {
526         case NSLeftMouseDown :
527         case NSRightMouseDown :
528         case NSOtherMouseDown :
529             g_lastButton = button ;
530             g_lastButtonWasFakeRight = thisButtonIsFakeRight ;
531             break;
532      }
533
534     if ( button == 0 )
535     {
536         g_lastButton = 0 ;
537         g_lastButtonWasFakeRight = false ;
538     }
539     else if ( g_lastButton == 1 && g_lastButtonWasFakeRight )
540         button = g_lastButton ;
541
542     // Adjust the chord mask to remove the primary button and add the
543     // secondary button.  It is possible that the secondary button is
544     // already pressed, e.g. on a mouse connected to a laptop, but this
545     // possibility is ignored here:
546     if( thisButtonIsFakeRight && ( mouseChord & 1U ) )
547         mouseChord = ((mouseChord & ~1U) | 2U);
548
549     if(mouseChord & 1U)
550                 wxevent.m_leftDown = true ;
551     if(mouseChord & 2U)
552                 wxevent.m_rightDown = true ;
553     if(mouseChord & 4U)
554                 wxevent.m_middleDown = true ;
555
556     // translate into wx types
557     switch (eventType)
558     {
559         case NSLeftMouseDown :
560         case NSRightMouseDown :
561         case NSOtherMouseDown :
562             clickCount = [nsEvent clickCount];
563             switch ( button )
564             {
565                 case 0 :
566                     wxevent.SetEventType( clickCount > 1 ? wxEVT_LEFT_DCLICK : wxEVT_LEFT_DOWN )  ;
567                     break ;
568
569                 case 1 :
570                     wxevent.SetEventType( clickCount > 1 ? wxEVT_RIGHT_DCLICK : wxEVT_RIGHT_DOWN ) ;
571                     break ;
572
573                 case 2 :
574                     wxevent.SetEventType( clickCount > 1 ? wxEVT_MIDDLE_DCLICK : wxEVT_MIDDLE_DOWN ) ;
575                     break ;
576
577                 default:
578                     break ;
579             }
580             break ;
581
582         case NSLeftMouseUp :
583         case NSRightMouseUp :
584         case NSOtherMouseUp :
585             clickCount = [nsEvent clickCount];
586             switch ( button )
587             {
588                 case 0 :
589                     wxevent.SetEventType( wxEVT_LEFT_UP )  ;
590                     break ;
591
592                 case 1 :
593                     wxevent.SetEventType( wxEVT_RIGHT_UP ) ;
594                     break ;
595
596                 case 2 :
597                     wxevent.SetEventType( wxEVT_MIDDLE_UP ) ;
598                     break ;
599
600                 default:
601                     break ;
602             }
603             break ;
604
605      case NSScrollWheel :
606         {
607             float deltaX = 0.0;
608             float deltaY = 0.0;
609
610             wxevent.SetEventType( wxEVT_MOUSEWHEEL ) ;
611
612             // see http://developer.apple.com/qa/qa2005/qa1453.html
613             // for more details on why we have to look for the exact type
614             
615             const EventRef cEvent = (EventRef) [nsEvent eventRef];
616             bool isMouseScrollEvent = false;
617             if ( cEvent )
618                 isMouseScrollEvent = ::GetEventKind(cEvent) == kEventMouseScroll;
619                 
620             if ( isMouseScrollEvent )
621             {
622                 deltaX = [nsEvent deviceDeltaX];
623                 deltaY = [nsEvent deviceDeltaY];
624             }
625             else
626             {
627                 deltaX = ([nsEvent deltaX] * 10);
628                 deltaY = ([nsEvent deltaY] * 10);
629             }
630             
631             wxevent.m_wheelDelta = 10;
632             wxevent.m_linesPerAction = 1;
633                 
634             if ( fabs(deltaX) > fabs(deltaY) )
635             {
636                 wxevent.m_wheelAxis = wxMOUSE_WHEEL_HORIZONTAL;
637                 wxevent.m_wheelRotation = (int)deltaX;
638             }
639             else
640             {
641                 wxevent.m_wheelRotation = (int)deltaY;
642             }
643
644         }
645         break ;
646
647         case NSMouseEntered :
648             wxevent.SetEventType( wxEVT_ENTER_WINDOW ) ;
649             break;
650         case NSMouseExited :
651             wxevent.SetEventType( wxEVT_LEAVE_WINDOW ) ;
652             break;
653         case NSLeftMouseDragged :
654         case NSRightMouseDragged :
655         case NSOtherMouseDragged :
656         case NSMouseMoved :
657             wxevent.SetEventType( wxEVT_MOTION ) ;
658             break;
659         default :
660             break ;
661     }
662
663     wxevent.m_clickCount = clickCount;
664     wxWindowMac* peer = GetWXPeer();
665     if ( peer )
666     {
667         wxevent.SetEventObject(peer);
668         wxevent.SetId(peer->GetId()) ;
669     }
670 }
671
672 @implementation wxNSView
673
674 + (void)initialize
675 {
676     static BOOL initialized = NO;
677     if (!initialized)
678     {
679         initialized = YES;
680         wxOSXCocoaClassAddWXMethods( self );
681     }
682 }
683
684 /* idea taken from webkit sources: overwrite the methods that (private) NSToolTipManager will use to attach its tracking rectangle 
685  * then when changing the tooltip send fake view-exit and view-enter methods which will lead to a tooltip refresh
686  */
687
688
689 - (void)_sendToolTipMouseExited
690 {
691     // Nothing matters except window, trackingNumber, and userData.
692     NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseExited
693                                                 location:NSMakePoint(0, 0)
694                                            modifierFlags:0
695                                                timestamp:0
696                                             windowNumber:[[self window] windowNumber]
697                                                  context:NULL
698                                              eventNumber:0
699                                           trackingNumber:_lastToolTipTrackTag
700                                                 userData:_lastUserData];
701     [_lastToolTipOwner mouseExited:fakeEvent];
702 }
703
704 - (void)_sendToolTipMouseEntered
705 {
706     // Nothing matters except window, trackingNumber, and userData.
707     NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseEntered
708                                                 location:NSMakePoint(0, 0)
709                                            modifierFlags:0
710                                                timestamp:0
711                                             windowNumber:[[self window] windowNumber]
712                                                  context:NULL
713                                              eventNumber:0
714                                           trackingNumber:_lastToolTipTrackTag
715                                                 userData:_lastUserData];
716     [_lastToolTipOwner mouseEntered:fakeEvent];
717 }
718
719 - (void)setToolTip:(NSString *)string;
720 {
721     if (string)
722     {
723         if ( _hasToolTip )
724         {
725             [self _sendToolTipMouseExited];
726         }
727
728         [super setToolTip:string];
729         _hasToolTip = YES;
730         [self _sendToolTipMouseEntered];
731     }
732     else 
733     {
734         if ( _hasToolTip )
735         {
736             [self _sendToolTipMouseExited];
737             [super setToolTip:nil];
738             _hasToolTip = NO;
739         }
740     }
741 }
742
743 - (NSTrackingRectTag)addTrackingRect:(NSRect)rect owner:(id)owner userData:(void *)data assumeInside:(BOOL)assumeInside
744 {
745     NSTrackingRectTag tag = [super addTrackingRect:rect owner:owner userData:data assumeInside:assumeInside];
746     if ( owner != self )
747     {
748         _lastUserData = data;
749         _lastToolTipOwner = owner;
750         _lastToolTipTrackTag = tag;
751     }
752     return tag;
753 }
754
755 - (void)removeTrackingRect:(NSTrackingRectTag)tag
756 {
757     if (tag == _lastToolTipTrackTag) 
758     {
759         _lastUserData = NULL;
760         _lastToolTipOwner = nil;
761         _lastToolTipTrackTag = 0;
762     }
763     [super removeTrackingRect:tag];
764 }
765 @end // wxNSView
766
767 //
768 // event handlers
769 //
770
771 #if wxUSE_DRAG_AND_DROP
772
773 // see http://lists.apple.com/archives/Cocoa-dev/2005/Jul/msg01244.html
774 // for details on the NSPasteboard -> PasteboardRef conversion
775
776 NSDragOperation wxOSX_draggingEntered( id self, SEL _cmd, id <NSDraggingInfo>sender )
777 {
778     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
779     if (impl == NULL)
780         return NSDragOperationNone;
781
782     return impl->draggingEntered(sender, self, _cmd);
783 }
784
785 void wxOSX_draggingExited( id self, SEL _cmd, id <NSDraggingInfo> sender )
786 {
787     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
788     if (impl == NULL)
789         return ;
790
791     return impl->draggingExited(sender, self, _cmd);
792 }
793
794 NSDragOperation wxOSX_draggingUpdated( id self, SEL _cmd, id <NSDraggingInfo>sender )
795 {
796     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
797     if (impl == NULL)
798         return NSDragOperationNone;
799
800     return impl->draggingUpdated(sender, self, _cmd);
801 }
802
803 BOOL wxOSX_performDragOperation( id self, SEL _cmd, id <NSDraggingInfo> sender )
804 {
805     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
806     if (impl == NULL)
807         return NSDragOperationNone;
808
809     return impl->performDragOperation(sender, self, _cmd) ? YES:NO ;
810 }
811
812 #endif
813
814 void wxOSX_mouseEvent(NSView* self, SEL _cmd, NSEvent *event)
815 {
816     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
817     if (impl == NULL)
818         return;
819
820     impl->mouseEvent(event, self, _cmd);
821 }
822
823 void wxOSX_cursorUpdate(NSView* self, SEL _cmd, NSEvent *event)
824 {
825     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
826     if (impl == NULL)
827         return;
828     
829     impl->cursorUpdate(event, self, _cmd);
830 }
831
832 BOOL wxOSX_acceptsFirstMouse(NSView* WXUNUSED(self), SEL WXUNUSED(_cmd), NSEvent *WXUNUSED(event))
833 {
834     // This is needed to support click through, otherwise the first click on a window
835     // will not do anything unless it is the active window already.
836     return YES;
837 }
838
839 void wxOSX_keyEvent(NSView* self, SEL _cmd, NSEvent *event)
840 {
841     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
842     if (impl == NULL)
843         return;
844
845     impl->keyEvent(event, self, _cmd);
846 }
847
848 void wxOSX_insertText(NSView* self, SEL _cmd, NSString* text)
849 {
850     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
851     if (impl == NULL)
852         return;
853
854     impl->insertText(text, self, _cmd);
855 }
856
857 BOOL wxOSX_performKeyEquivalent(NSView* self, SEL _cmd, NSEvent *event)
858 {
859     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
860     if (impl == NULL)
861         return NO;
862
863     return impl->performKeyEquivalent(event, self, _cmd);
864 }
865
866 BOOL wxOSX_acceptsFirstResponder(NSView* self, SEL _cmd)
867 {
868     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
869     if (impl == NULL)
870         return NO;
871
872     return impl->acceptsFirstResponder(self, _cmd);
873 }
874
875 BOOL wxOSX_becomeFirstResponder(NSView* self, SEL _cmd)
876 {
877     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
878     if (impl == NULL)
879         return NO;
880
881     return impl->becomeFirstResponder(self, _cmd);
882 }
883
884 BOOL wxOSX_resignFirstResponder(NSView* self, SEL _cmd)
885 {
886     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
887     if (impl == NULL)
888         return NO;
889
890     return impl->resignFirstResponder(self, _cmd);
891 }
892
893 BOOL wxOSX_isFlipped(NSView* self, SEL _cmd)
894 {
895     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
896     if (impl == NULL)
897         return NO;
898
899     return impl->isFlipped(self, _cmd) ? YES:NO;
900 }
901
902 typedef void (*wxOSX_DrawRectHandlerPtr)(NSView* self, SEL _cmd, NSRect rect);
903
904 void wxOSX_drawRect(NSView* self, SEL _cmd, NSRect rect)
905 {
906     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
907     if (impl == NULL)
908         return;
909
910 #if wxUSE_THREADS
911     // OS X starts a NSUIHeartBeatThread for animating the default button in a
912     // dialog. This causes a drawRect of the active dialog from outside the
913     // main UI thread. This causes an occasional crash since the wx drawing
914     // objects (like wxPen) are not thread safe.
915     //
916     // Notice that NSUIHeartBeatThread seems to be undocumented and doing
917     // [NSWindow setAllowsConcurrentViewDrawing:NO] does not affect it.
918     if ( !wxThread::IsMain() )
919     {
920         if ( impl->IsUserPane() )
921         {
922             wxWindow* win = impl->GetWXPeer();
923             if ( win->UseBgCol() )
924             {
925                 
926                 CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
927                 CGContextSaveGState( context );
928
929                 CGContextSetFillColorWithColor( context, win->GetBackgroundColour().GetCGColor());
930                 CGRect r = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
931                 CGContextFillRect( context, r );
932
933                 CGContextRestoreGState( context );
934             }
935         }
936         else 
937         {
938             // just call the superclass handler, we don't need any custom wx drawing
939             // here and it seems to work fine:
940             wxOSX_DrawRectHandlerPtr
941             superimpl = (wxOSX_DrawRectHandlerPtr)
942             [[self superclass] instanceMethodForSelector:_cmd];
943             superimpl(self, _cmd, rect);
944         }
945
946       return;
947     }
948 #endif // wxUSE_THREADS
949
950     return impl->drawRect(&rect, self, _cmd);
951 }
952
953 void wxOSX_controlAction(NSView* self, SEL _cmd, id sender)
954 {
955     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
956     if (impl == NULL)
957         return;
958
959     impl->controlAction(self, _cmd, sender);
960 }
961
962 void wxOSX_controlDoubleAction(NSView* self, SEL _cmd, id sender)
963 {
964     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
965     if (impl == NULL)
966         return;
967
968     impl->controlDoubleAction(self, _cmd, sender);
969 }
970
971 unsigned int wxWidgetCocoaImpl::draggingEntered(void* s, WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
972 {
973     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
974     NSPasteboard *pboard = [sender draggingPasteboard];
975     NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
976
977     wxWindow* wxpeer = GetWXPeer();
978     if ( wxpeer == NULL )
979         return NSDragOperationNone;
980
981     wxDropTarget* target = wxpeer->GetDropTarget();
982     if ( target == NULL )
983         return NSDragOperationNone;
984
985     wxDragResult result = wxDragNone;
986     NSPoint nspoint = [m_osxView convertPoint:[sender draggingLocation] fromView:nil];
987     wxPoint pt = wxFromNSPoint( m_osxView, nspoint );
988
989     if ( sourceDragMask & NSDragOperationLink )
990         result = wxDragLink;
991     else if ( sourceDragMask & NSDragOperationCopy )
992         result = wxDragCopy;
993     else if ( sourceDragMask & NSDragOperationMove )
994         result = wxDragMove;
995
996     PasteboardRef pboardRef;
997     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
998     target->SetCurrentDragPasteboard(pboardRef);
999     result = target->OnEnter(pt.x, pt.y, result);
1000     CFRelease(pboardRef);
1001
1002     NSDragOperation nsresult = NSDragOperationNone;
1003     switch (result )
1004     {
1005         case wxDragLink:
1006             nsresult = NSDragOperationLink;
1007         case wxDragMove:
1008             nsresult = NSDragOperationMove;
1009         case wxDragCopy:
1010             nsresult = NSDragOperationCopy;
1011         default :
1012             break;
1013     }
1014     return nsresult;
1015 }
1016
1017 void wxWidgetCocoaImpl::draggingExited(void* s, WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
1018 {
1019     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
1020     NSPasteboard *pboard = [sender draggingPasteboard];
1021
1022     wxWindow* wxpeer = GetWXPeer();
1023     if ( wxpeer == NULL )
1024         return;
1025
1026     wxDropTarget* target = wxpeer->GetDropTarget();
1027     if ( target == NULL )
1028         return;
1029
1030     PasteboardRef pboardRef;
1031     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
1032     target->SetCurrentDragPasteboard(pboardRef);
1033     target->OnLeave();
1034     CFRelease(pboardRef);
1035  }
1036
1037 unsigned int wxWidgetCocoaImpl::draggingUpdated(void* s, WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
1038 {
1039     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
1040     NSPasteboard *pboard = [sender draggingPasteboard];
1041     NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
1042
1043     wxWindow* wxpeer = GetWXPeer();
1044     if ( wxpeer == NULL )
1045         return NSDragOperationNone;
1046
1047     wxDropTarget* target = wxpeer->GetDropTarget();
1048     if ( target == NULL )
1049         return NSDragOperationNone;
1050
1051     wxDragResult result = wxDragNone;
1052     NSPoint nspoint = [m_osxView convertPoint:[sender draggingLocation] fromView:nil];
1053     wxPoint pt = wxFromNSPoint( m_osxView, nspoint );
1054
1055     if ( sourceDragMask & NSDragOperationLink )
1056         result = wxDragLink;
1057     else if ( sourceDragMask & NSDragOperationCopy )
1058         result = wxDragCopy;
1059     else if ( sourceDragMask & NSDragOperationMove )
1060         result = wxDragMove;
1061     
1062     PasteboardRef pboardRef;
1063     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
1064     target->SetCurrentDragPasteboard(pboardRef);
1065     result = target->OnDragOver(pt.x, pt.y, result);
1066     CFRelease(pboardRef);
1067
1068     NSDragOperation nsresult = NSDragOperationNone;
1069     switch (result )
1070     {
1071         case wxDragLink:
1072             nsresult = NSDragOperationLink;
1073         case wxDragMove:
1074             nsresult = NSDragOperationMove;
1075         case wxDragCopy:
1076             nsresult = NSDragOperationCopy;
1077         default :
1078             break;
1079     }
1080     return nsresult;
1081 }
1082
1083 bool wxWidgetCocoaImpl::performDragOperation(void* s, WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
1084 {
1085     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
1086
1087     NSPasteboard *pboard = [sender draggingPasteboard];
1088     NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
1089
1090     wxWindow* wxpeer = GetWXPeer();
1091     wxDropTarget* target = wxpeer->GetDropTarget();
1092     wxDragResult result = wxDragNone;
1093     NSPoint nspoint = [m_osxView convertPoint:[sender draggingLocation] fromView:nil];
1094     wxPoint pt = wxFromNSPoint( m_osxView, nspoint );
1095
1096     if ( sourceDragMask & NSDragOperationLink )
1097         result = wxDragLink;
1098     else if ( sourceDragMask & NSDragOperationCopy )
1099         result = wxDragCopy;
1100     else if ( sourceDragMask & NSDragOperationMove )
1101         result = wxDragMove;
1102
1103     PasteboardRef pboardRef;
1104     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
1105     target->SetCurrentDragPasteboard(pboardRef);
1106
1107     if (target->OnDrop(pt.x, pt.y))
1108         result = target->OnData(pt.x, pt.y, result);
1109
1110     CFRelease(pboardRef);
1111
1112     return result != wxDragNone;
1113 }
1114
1115 typedef void (*wxOSX_TextEventHandlerPtr)(NSView* self, SEL _cmd, NSString *event);
1116 typedef void (*wxOSX_EventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event);
1117 typedef BOOL (*wxOSX_PerformKeyEventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event);
1118 typedef BOOL (*wxOSX_FocusHandlerPtr)(NSView* self, SEL _cmd);
1119
1120 void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
1121 {
1122     if ( !DoHandleMouseEvent(event) )
1123     {
1124         // for plain NSView mouse events would propagate to parents otherwise
1125         if (!IsUserPane())
1126         {
1127             wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
1128             superimpl(slf, (SEL)_cmd, event);
1129             
1130             // super of built-ins keeps the mouse up, as wx expects this event, we have to synthesize it
1131             
1132             if ( [ event type]  == NSLeftMouseDown )
1133             {
1134                 wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
1135                 SetupMouseEvent(wxevent , event) ;
1136                 wxevent.SetEventType(wxEVT_LEFT_UP);
1137                 
1138                 GetWXPeer()->HandleWindowEvent(wxevent);
1139             }
1140         }
1141     }
1142 }
1143
1144 void wxWidgetCocoaImpl::cursorUpdate(WX_NSEvent event, WXWidget slf, void *_cmd)
1145 {
1146     NSCursor *cursor = (NSCursor*)GetWXPeer()->GetCursor().GetHCURSOR();
1147     if (cursor == NULL)
1148     {
1149         wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
1150         superimpl(slf, (SEL)_cmd, event);
1151     }
1152     else 
1153     {
1154         [cursor set];
1155     }
1156 }
1157
1158
1159
1160 void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
1161 {
1162     if ( [event type] == NSKeyDown )
1163     {
1164         // there are key equivalents that are not command-combos and therefore not handled by cocoa automatically, 
1165         // therefore we call the menubar directly here, exit if the menu is handling the shortcut
1166         if ( [[[NSApplication sharedApplication] mainMenu] performKeyEquivalent:event] )
1167             return;
1168     
1169         m_lastKeyDownEvent = event;
1170     }
1171     
1172     if ( GetFocusedViewInWindow([slf window]) != slf || m_hasEditor || !DoHandleKeyEvent(event) )
1173     {
1174         wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
1175         superimpl(slf, (SEL)_cmd, event);
1176     }
1177     m_lastKeyDownEvent = NULL;
1178 }
1179
1180 void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd)
1181 {
1182     if ( m_lastKeyDownEvent==NULL || m_hasEditor || !DoHandleCharEvent(m_lastKeyDownEvent, text) )
1183     {
1184         wxOSX_TextEventHandlerPtr superimpl = (wxOSX_TextEventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
1185         superimpl(slf, (SEL)_cmd, text);
1186     }
1187 }
1188
1189
1190 bool wxWidgetCocoaImpl::performKeyEquivalent(WX_NSEvent event, WXWidget slf, void *_cmd)
1191 {
1192     bool handled = false;
1193     
1194     wxKeyEvent wxevent(wxEVT_KEY_DOWN);
1195     SetupKeyEvent( wxevent, event );
1196    
1197     // because performKeyEquivalent is going up the entire view hierarchy, we don't have to
1198     // walk up the ancestors ourselves but let cocoa do it
1199     
1200     int command = m_wxPeer->GetAcceleratorTable()->GetCommand( wxevent );
1201     if (command != -1)
1202     {
1203         wxEvtHandler * const handler = m_wxPeer->GetEventHandler();
1204         
1205         wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
1206         command_event.SetEventObject( wxevent.GetEventObject() );
1207         handled = handler->ProcessEvent( command_event );
1208         
1209         if ( !handled )
1210         {
1211             // accelerators can also be used with buttons, try them too
1212             command_event.SetEventType(wxEVT_COMMAND_BUTTON_CLICKED);
1213             handled = handler->ProcessEvent( command_event );
1214         }
1215     }
1216     
1217     if ( !handled )
1218     {
1219         wxOSX_PerformKeyEventHandlerPtr superimpl = (wxOSX_PerformKeyEventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
1220         return superimpl(slf, (SEL)_cmd, event);
1221     }
1222     return YES;
1223 }
1224
1225 bool wxWidgetCocoaImpl::acceptsFirstResponder(WXWidget slf, void *_cmd)
1226 {
1227     if ( IsUserPane() )
1228         return m_wxPeer->AcceptsFocus();
1229     else
1230     {
1231         wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
1232         return superimpl(slf, (SEL)_cmd);
1233     }
1234 }
1235
1236 bool wxWidgetCocoaImpl::becomeFirstResponder(WXWidget slf, void *_cmd)
1237 {
1238     wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
1239     // get the current focus before running becomeFirstResponder
1240     NSView* otherView = FindFocus();
1241
1242     wxWidgetImpl* otherWindow = FindFromWXWidget(otherView);
1243     BOOL r = superimpl(slf, (SEL)_cmd);
1244     if ( r )
1245     {
1246         DoNotifyFocusEvent( true, otherWindow );
1247     }
1248
1249     return r;
1250 }
1251
1252 bool wxWidgetCocoaImpl::resignFirstResponder(WXWidget slf, void *_cmd)
1253 {
1254     wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
1255     BOOL r = superimpl(slf, (SEL)_cmd);
1256     // get the current focus after running resignFirstResponder
1257     // note that this value isn't reliable, it might return the same view that
1258     // is resigning
1259     NSView* otherView = FindFocus();
1260     wxWidgetImpl* otherWindow = FindFromWXWidget(otherView);
1261
1262     // It doesn't make sense to notify about the loss of focus if we're not
1263     // really losing it and the window which has just gained focus is the same
1264     // one as this window itself. Of course, this should never happen in the
1265     // first place but somehow it does in wxGrid code and without this check we
1266     // enter into an infinite recursion, see #12267.
1267     if ( otherWindow == this )
1268         return r;
1269
1270     // NSTextViews have an editor as true responder, therefore the might get the
1271     // resign notification if their editor takes over, don't trigger any event then
1272     if ( r && !m_hasEditor)
1273     {
1274         DoNotifyFocusEvent( false, otherWindow );
1275     }
1276     return r;
1277 }
1278
1279 bool wxWidgetCocoaImpl::isFlipped(WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd))
1280 {
1281     return m_isFlipped;
1282 }
1283
1284
1285 #define OSX_DEBUG_DRAWING 0
1286
1287 void wxWidgetCocoaImpl::drawRect(void* rect, WXWidget slf, void *WXUNUSED(_cmd))
1288 {
1289     // preparing the update region
1290     
1291     wxRegion updateRgn;
1292     const NSRect *rects;
1293     NSInteger count;
1294
1295     [slf getRectsBeingDrawn:&rects count:&count];
1296     for ( int i = 0 ; i < count ; ++i )
1297     {
1298         updateRgn.Union(wxFromNSRect(slf, rects[i]));
1299     }
1300
1301     wxWindow* wxpeer = GetWXPeer();
1302
1303     if ( wxpeer->MacGetLeftBorderSize() != 0 || wxpeer->MacGetTopBorderSize() != 0 )
1304     {
1305         // as this update region is in native window locals we must adapt it to wx window local
1306         updateRgn.Offset( wxpeer->MacGetLeftBorderSize() , wxpeer->MacGetTopBorderSize() );
1307     }
1308     
1309     // Restrict the update region to the shape of the window, if any, and also
1310     // remember the region that we need to clear later.
1311     wxNonOwnedWindow* const tlwParent = wxpeer->MacGetTopLevelWindow();
1312     const bool isTopLevel = tlwParent == wxpeer;
1313     wxRegion clearRgn;
1314     if ( tlwParent->GetWindowStyle() & wxFRAME_SHAPED )
1315     {
1316         if ( isTopLevel )
1317             clearRgn = updateRgn;
1318
1319         int xoffset = 0, yoffset = 0;
1320         wxRegion rgn = tlwParent->GetShape();
1321         wxpeer->MacRootWindowToWindow( &xoffset, &yoffset );
1322         rgn.Offset( xoffset, yoffset );
1323         updateRgn.Intersect(rgn);
1324
1325         if ( isTopLevel )
1326         {
1327             // Exclude the window shape from the region to be cleared below.
1328             rgn.Xor(wxpeer->GetSize());
1329             clearRgn.Intersect(rgn);
1330         }
1331     }
1332     
1333     wxpeer->GetUpdateRegion() = updateRgn;
1334
1335     // setting up the drawing context
1336     
1337     CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
1338     CGContextSaveGState( context );
1339     
1340 #if OSX_DEBUG_DRAWING
1341     CGContextBeginPath( context );
1342     CGContextMoveToPoint(context, 0, 0);
1343     NSRect bounds = [slf bounds];
1344     CGContextAddLineToPoint(context, 10, 0);
1345     CGContextMoveToPoint(context, 0, 0);
1346     CGContextAddLineToPoint(context, 0, 10);
1347     CGContextMoveToPoint(context, bounds.size.width, bounds.size.height);
1348     CGContextAddLineToPoint(context, bounds.size.width, bounds.size.height-10);
1349     CGContextMoveToPoint(context, bounds.size.width, bounds.size.height);
1350     CGContextAddLineToPoint(context, bounds.size.width-10, bounds.size.height);
1351     CGContextClosePath( context );
1352     CGContextStrokePath(context);
1353 #endif
1354     
1355     if ( !m_isFlipped )
1356     {
1357         CGContextTranslateCTM( context, 0,  [m_osxView bounds].size.height );
1358         CGContextScaleCTM( context, 1, -1 );
1359     }
1360     
1361     wxpeer->MacSetCGContextRef( context );
1362
1363     bool handled = wxpeer->MacDoRedraw( 0 );
1364     CGContextRestoreGState( context );
1365
1366     CGContextSaveGState( context );
1367     if ( !handled )
1368     {
1369         // call super
1370         SEL _cmd = @selector(drawRect:);
1371         wxOSX_DrawRectHandlerPtr superimpl = (wxOSX_DrawRectHandlerPtr) [[slf superclass] instanceMethodForSelector:_cmd];
1372         superimpl(slf, _cmd, *(NSRect*)rect);
1373         CGContextRestoreGState( context );
1374         CGContextSaveGState( context );
1375     }
1376     // as we called restore above, we have to flip again if necessary
1377     if ( !m_isFlipped )
1378     {
1379         CGContextTranslateCTM( context, 0,  [m_osxView bounds].size.height );
1380         CGContextScaleCTM( context, 1, -1 );
1381     }
1382
1383     if ( isTopLevel )
1384     {
1385         // We also need to explicitly draw the part of the top level window
1386         // outside of its region with transparent colour to ensure that it is
1387         // really transparent.
1388         if ( clearRgn.IsOk() )
1389         {
1390             wxMacCGContextStateSaver saveState(context);
1391             wxWindowDC dc(wxpeer);
1392             dc.SetBackground(wxBrush(wxTransparentColour));
1393             dc.SetDeviceClippingRegion(clearRgn);
1394             dc.Clear();
1395         }
1396
1397 #if wxUSE_GRAPHICS_CONTEXT
1398         // If the window shape is defined by a path, stroke the path to show
1399         // the window border.
1400         const wxGraphicsPath& path = tlwParent->GetShapePath();
1401         if ( !path.IsNull() )
1402         {
1403             CGContextSetLineWidth(context, 1);
1404             CGContextSetStrokeColorWithColor(context, wxLIGHT_GREY->GetCGColor());
1405             CGContextAddPath(context, (CGPathRef) path.GetNativePath());
1406             CGContextStrokePath(context);
1407         }
1408 #endif // wxUSE_GRAPHICS_CONTEXT
1409     }
1410
1411     wxpeer->MacPaintChildrenBorders();
1412     wxpeer->MacSetCGContextRef( NULL );
1413     CGContextRestoreGState( context );
1414 }
1415
1416 void wxWidgetCocoaImpl::controlAction( WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd), void *WXUNUSED(sender))
1417 {
1418     wxWindow* wxpeer = (wxWindow*) GetWXPeer();
1419     if ( wxpeer )
1420         wxpeer->OSXHandleClicked(0);
1421 }
1422
1423 void wxWidgetCocoaImpl::controlDoubleAction( WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd), void *WXUNUSED(sender))
1424 {
1425 }
1426
1427 void wxWidgetCocoaImpl::controlTextDidChange()
1428 {
1429     wxWindow* wxpeer = (wxWindow*)GetWXPeer();
1430     if ( wxpeer ) 
1431     {
1432         // since native rtti doesn't have to be enabled and wx' rtti is not aware of the mixin wxTextEntry, workaround is needed
1433         wxTextCtrl *tc = wxDynamicCast( wxpeer , wxTextCtrl );
1434         wxComboBox *cb = wxDynamicCast( wxpeer , wxComboBox );
1435         if ( tc )
1436             tc->SendTextUpdatedEventIfAllowed();
1437         else if ( cb )
1438             cb->SendTextUpdatedEventIfAllowed();
1439         else 
1440         {
1441             wxFAIL_MSG("Unexpected class for controlTextDidChange event");
1442         }
1443     }
1444 }
1445
1446 //
1447
1448 #if OBJC_API_VERSION >= 2
1449
1450 #define wxOSX_CLASS_ADD_METHOD( c, s, i, t ) \
1451     class_addMethod(c, s, i, t );
1452
1453 #else
1454
1455 #define wxOSX_CLASS_ADD_METHOD( c, s, i, t ) \
1456     { s, (char*) t, i },
1457
1458 #endif
1459
1460 void wxOSXCocoaClassAddWXMethods(Class c)
1461 {
1462
1463 #if OBJC_API_VERSION < 2
1464     static objc_method wxmethods[] =
1465     {
1466 #endif
1467
1468     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
1469     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
1470     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
1471
1472     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
1473     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
1474     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
1475
1476     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseMoved:), (IMP) wxOSX_mouseEvent, "v@:@" )
1477
1478     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
1479     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
1480     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
1481     
1482     wxOSX_CLASS_ADD_METHOD(c, @selector(acceptsFirstMouse:), (IMP) wxOSX_acceptsFirstMouse, "v@:@" )
1483
1484     wxOSX_CLASS_ADD_METHOD(c, @selector(scrollWheel:), (IMP) wxOSX_mouseEvent, "v@:@" )
1485     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseEntered:), (IMP) wxOSX_mouseEvent, "v@:@" )
1486     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseExited:), (IMP) wxOSX_mouseEvent, "v@:@" )
1487
1488     wxOSX_CLASS_ADD_METHOD(c, @selector(cursorUpdate:), (IMP) wxOSX_cursorUpdate, "v@:@" )
1489
1490     wxOSX_CLASS_ADD_METHOD(c, @selector(keyDown:), (IMP) wxOSX_keyEvent, "v@:@" )
1491     wxOSX_CLASS_ADD_METHOD(c, @selector(keyUp:), (IMP) wxOSX_keyEvent, "v@:@" )
1492     wxOSX_CLASS_ADD_METHOD(c, @selector(flagsChanged:), (IMP) wxOSX_keyEvent, "v@:@" )
1493
1494     wxOSX_CLASS_ADD_METHOD(c, @selector(insertText:), (IMP) wxOSX_insertText, "v@:@" )
1495
1496     wxOSX_CLASS_ADD_METHOD(c, @selector(performKeyEquivalent:), (IMP) wxOSX_performKeyEquivalent, "c@:@" )
1497
1498     wxOSX_CLASS_ADD_METHOD(c, @selector(acceptsFirstResponder), (IMP) wxOSX_acceptsFirstResponder, "c@:" )
1499     wxOSX_CLASS_ADD_METHOD(c, @selector(becomeFirstResponder), (IMP) wxOSX_becomeFirstResponder, "c@:" )
1500     wxOSX_CLASS_ADD_METHOD(c, @selector(resignFirstResponder), (IMP) wxOSX_resignFirstResponder, "c@:" )
1501
1502     wxOSX_CLASS_ADD_METHOD(c, @selector(isFlipped), (IMP) wxOSX_isFlipped, "c@:" )
1503     wxOSX_CLASS_ADD_METHOD(c, @selector(drawRect:), (IMP) wxOSX_drawRect, "v@:{_NSRect={_NSPoint=ff}{_NSSize=ff}}" )
1504
1505     wxOSX_CLASS_ADD_METHOD(c, @selector(controlAction:), (IMP) wxOSX_controlAction, "v@:@" )
1506     wxOSX_CLASS_ADD_METHOD(c, @selector(controlDoubleAction:), (IMP) wxOSX_controlDoubleAction, "v@:@" )
1507
1508 #if wxUSE_DRAG_AND_DROP
1509     wxOSX_CLASS_ADD_METHOD(c, @selector(draggingEntered:), (IMP) wxOSX_draggingEntered, "I@:@" )
1510     wxOSX_CLASS_ADD_METHOD(c, @selector(draggingUpdated:), (IMP) wxOSX_draggingUpdated, "I@:@" )
1511     wxOSX_CLASS_ADD_METHOD(c, @selector(draggingExited:), (IMP) wxOSX_draggingExited, "v@:@" )
1512     wxOSX_CLASS_ADD_METHOD(c, @selector(performDragOperation:), (IMP) wxOSX_performDragOperation, "c@:@" )
1513 #endif
1514
1515 #if OBJC_API_VERSION < 2
1516     } ;
1517     static int method_count = WXSIZEOF( wxmethods );
1518     static objc_method_list *wxmethodlist = NULL;
1519     if ( wxmethodlist == NULL )
1520     {
1521         wxmethodlist = (objc_method_list*) malloc(sizeof(objc_method_list) + sizeof(wxmethods) );
1522         memcpy( &wxmethodlist->method_list[0], &wxmethods[0], sizeof(wxmethods) );
1523         wxmethodlist->method_count = method_count;
1524         wxmethodlist->obsolete = 0;
1525     }
1526     class_addMethods( c, wxmethodlist );
1527 #endif
1528 }
1529
1530 //
1531 // C++ implementation class
1532 //
1533
1534 IMPLEMENT_DYNAMIC_CLASS( wxWidgetCocoaImpl , wxWidgetImpl )
1535
1536 wxWidgetCocoaImpl::wxWidgetCocoaImpl( wxWindowMac* peer , WXWidget w, bool isRootControl, bool isUserPane ) :
1537     wxWidgetImpl( peer, isRootControl, isUserPane )
1538 {
1539     Init();
1540     m_osxView = w;
1541
1542     // check if the user wants to create the control initially hidden
1543     if ( !peer->IsShown() )
1544         SetVisibility(false);
1545
1546     // gc aware handling
1547     if ( m_osxView )
1548         CFRetain(m_osxView);
1549     [m_osxView release];
1550 }
1551
1552 wxWidgetCocoaImpl::wxWidgetCocoaImpl()
1553 {
1554     Init();
1555 }
1556
1557 void wxWidgetCocoaImpl::Init()
1558 {
1559     m_osxView = NULL;
1560     m_isFlipped = true;
1561     m_lastKeyDownEvent = NULL;
1562     m_hasEditor = false;
1563 }
1564
1565 wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
1566 {
1567     RemoveAssociations( this );
1568
1569     if ( !IsRootControl() )
1570     {
1571         NSView *sv = [m_osxView superview];
1572         if ( sv != nil )
1573             [m_osxView removeFromSuperview];
1574     }
1575     // gc aware handling
1576     if ( m_osxView )
1577         CFRelease(m_osxView);
1578 }
1579
1580 bool wxWidgetCocoaImpl::IsVisible() const
1581 {
1582     return [m_osxView isHiddenOrHasHiddenAncestor] == NO;
1583 }
1584
1585 void wxWidgetCocoaImpl::SetVisibility( bool visible )
1586 {
1587     [m_osxView setHidden:(visible ? NO:YES)];
1588 }
1589
1590 // ----------------------------------------------------------------------------
1591 // window animation stuff
1592 // ----------------------------------------------------------------------------
1593
1594 // define a delegate used to refresh the window during animation
1595 @interface wxNSAnimationDelegate : NSObject wxOSX_10_6_AND_LATER(<NSAnimationDelegate>)
1596 {
1597     wxWindow *m_win;
1598     bool m_isDone;
1599 }
1600
1601 - (id)init:(wxWindow *)win;
1602
1603 - (bool)isDone;
1604
1605 // NSAnimationDelegate methods
1606 - (void)animationDidEnd:(NSAnimation*)animation;
1607 - (void)animation:(NSAnimation*)animation
1608         didReachProgressMark:(NSAnimationProgress)progress;
1609 @end
1610
1611 @implementation wxNSAnimationDelegate
1612
1613 - (id)init:(wxWindow *)win
1614 {
1615     self = [super init];
1616
1617     m_win = win;
1618     m_isDone = false;
1619
1620     return self;
1621 }
1622
1623 - (bool)isDone
1624 {
1625     return m_isDone;
1626 }
1627
1628 - (void)animation:(NSAnimation*)animation
1629         didReachProgressMark:(NSAnimationProgress)progress
1630 {
1631     wxUnusedVar(animation);
1632     wxUnusedVar(progress);
1633
1634     m_win->SendSizeEvent();
1635     m_win->MacOnInternalSize();
1636 }
1637
1638 - (void)animationDidEnd:(NSAnimation*)animation
1639 {
1640     wxUnusedVar(animation);
1641     m_isDone = true;
1642 }
1643
1644 @end
1645
1646 /* static */
1647 bool
1648 wxWidgetCocoaImpl::ShowViewOrWindowWithEffect(wxWindow *win,
1649                                               bool show,
1650                                               wxShowEffect effect,
1651                                               unsigned timeout)
1652 {
1653     // create the dictionary describing the animation to perform on this view
1654     NSObject * const
1655         viewOrWin = static_cast<NSObject *>(win->OSXGetViewOrWindow());
1656     NSMutableDictionary * const
1657         dict = [NSMutableDictionary dictionaryWithCapacity:4];
1658     [dict setObject:viewOrWin forKey:NSViewAnimationTargetKey];
1659
1660     // determine the start and end rectangles assuming we're hiding the window
1661     const wxRect rectOrig = win->GetRect();
1662     wxRect rectStart,
1663            rectEnd;
1664     rectStart =
1665     rectEnd = rectOrig;
1666
1667     if ( show )
1668     {
1669         if ( effect == wxSHOW_EFFECT_ROLL_TO_LEFT ||
1670                 effect == wxSHOW_EFFECT_SLIDE_TO_LEFT )
1671             effect = wxSHOW_EFFECT_ROLL_TO_RIGHT;
1672         else if ( effect == wxSHOW_EFFECT_ROLL_TO_RIGHT ||
1673                     effect == wxSHOW_EFFECT_SLIDE_TO_RIGHT )
1674             effect = wxSHOW_EFFECT_ROLL_TO_LEFT;
1675         else if ( effect == wxSHOW_EFFECT_ROLL_TO_TOP ||
1676                     effect == wxSHOW_EFFECT_SLIDE_TO_TOP )
1677             effect = wxSHOW_EFFECT_ROLL_TO_BOTTOM;
1678         else if ( effect == wxSHOW_EFFECT_ROLL_TO_BOTTOM ||
1679                     effect == wxSHOW_EFFECT_SLIDE_TO_BOTTOM )
1680             effect = wxSHOW_EFFECT_ROLL_TO_TOP;
1681     }
1682
1683     switch ( effect )
1684     {
1685         case wxSHOW_EFFECT_ROLL_TO_LEFT:
1686         case wxSHOW_EFFECT_SLIDE_TO_LEFT:
1687             rectEnd.width = 0;
1688             break;
1689
1690         case wxSHOW_EFFECT_ROLL_TO_RIGHT:
1691         case wxSHOW_EFFECT_SLIDE_TO_RIGHT:
1692             rectEnd.x = rectStart.GetRight();
1693             rectEnd.width = 0;
1694             break;
1695
1696         case wxSHOW_EFFECT_ROLL_TO_TOP:
1697         case wxSHOW_EFFECT_SLIDE_TO_TOP:
1698             rectEnd.height = 0;
1699             break;
1700
1701         case wxSHOW_EFFECT_ROLL_TO_BOTTOM:
1702         case wxSHOW_EFFECT_SLIDE_TO_BOTTOM:
1703             rectEnd.y = rectStart.GetBottom();
1704             rectEnd.height = 0;
1705             break;
1706
1707         case wxSHOW_EFFECT_EXPAND:
1708             rectEnd.x = rectStart.x + rectStart.width / 2;
1709             rectEnd.y = rectStart.y + rectStart.height / 2;
1710             rectEnd.width =
1711             rectEnd.height = 0;
1712             break;
1713
1714         case wxSHOW_EFFECT_BLEND:
1715             [dict setObject:(show ? NSViewAnimationFadeInEffect
1716                                   : NSViewAnimationFadeOutEffect)
1717                   forKey:NSViewAnimationEffectKey];
1718             break;
1719
1720         case wxSHOW_EFFECT_NONE:
1721         case wxSHOW_EFFECT_MAX:
1722             wxFAIL_MSG( "unexpected animation effect" );
1723             return false;
1724
1725         default:
1726             wxFAIL_MSG( "unknown animation effect" );
1727             return false;
1728     };
1729
1730     if ( show )
1731     {
1732         // we need to restore it to the original rectangle instead of making it
1733         // disappear
1734         wxSwap(rectStart, rectEnd);
1735
1736         // and as the window is currently hidden, we need to show it for the
1737         // animation to be visible at all (but don't restore it at its full
1738         // rectangle as it shouldn't appear immediately)
1739         win->SetSize(rectStart);
1740         win->Show();
1741     }
1742
1743     NSView * const parentView = [viewOrWin isKindOfClass:[NSView class]]
1744                                     ? [(NSView *)viewOrWin superview]
1745                                     : nil;
1746     const NSRect rStart = wxToNSRect(parentView, rectStart);
1747     const NSRect rEnd = wxToNSRect(parentView, rectEnd);
1748
1749     [dict setObject:[NSValue valueWithRect:rStart]
1750           forKey:NSViewAnimationStartFrameKey];
1751     [dict setObject:[NSValue valueWithRect:rEnd]
1752           forKey:NSViewAnimationEndFrameKey];
1753
1754     // create an animation using the values in the above dictionary
1755     NSViewAnimation * const
1756         anim = [[NSViewAnimation alloc]
1757                 initWithViewAnimations:[NSArray arrayWithObject:dict]];
1758
1759     if ( !timeout )
1760     {
1761         // what is a good default duration? Windows uses 200ms, Web frameworks
1762         // use anything from 250ms to 1s... choose something in the middle
1763         timeout = 500;
1764     }
1765
1766     [anim setDuration:timeout/1000.];   // duration is in seconds here
1767
1768     // if the window being animated changes its layout depending on its size
1769     // (which is almost always the case) we need to redo it during animation
1770     //
1771     // the number of layouts here is arbitrary, but 10 seems like too few (e.g.
1772     // controls in wxInfoBar visibly jump around)
1773     const int NUM_LAYOUTS = 20;
1774     for ( float f = 1./NUM_LAYOUTS; f < 1.; f += 1./NUM_LAYOUTS )
1775         [anim addProgressMark:f];
1776
1777     wxNSAnimationDelegate * const
1778         animDelegate = [[wxNSAnimationDelegate alloc] init:win];
1779     [anim setDelegate:animDelegate];
1780     [anim startAnimation];
1781
1782     // Cocoa is capable of doing animation asynchronously or even from separate
1783     // thread but wx API doesn't provide any way to be notified about the
1784     // animation end and without this we really must ensure that the window has
1785     // the expected (i.e. the same as if a simple Show() had been used) size
1786     // when we return, so block here until the animation finishes
1787     //
1788     // notice that because the default animation mode is NSAnimationBlocking,
1789     // no user input events ought to be processed from here
1790     {
1791         wxEventLoopGuarantor ensureEventLoopExistence;
1792         wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
1793         while ( ![animDelegate isDone] )
1794             loop->Dispatch();
1795     }
1796
1797     if ( !show )
1798     {
1799         // NSViewAnimation is smart enough to hide the NSView being animated at
1800         // the end but we also must ensure that it's hidden for wx too
1801         win->Hide();
1802
1803         // and we must also restore its size because it isn't expected to
1804         // change just because the window was hidden
1805         win->SetSize(rectOrig);
1806     }
1807     else
1808     {
1809         // refresh it once again after the end to ensure that everything is in
1810         // place
1811         win->SendSizeEvent();
1812         win->MacOnInternalSize();
1813     }
1814
1815     [anim setDelegate:nil];
1816     [animDelegate release];
1817     [anim release];
1818
1819     return true;
1820 }
1821
1822 bool wxWidgetCocoaImpl::ShowWithEffect(bool show,
1823                                        wxShowEffect effect,
1824                                        unsigned timeout)
1825 {
1826     return ShowViewOrWindowWithEffect(m_wxPeer, show, effect, timeout);
1827 }
1828
1829 /* note that the drawing order between siblings is not defined under 10.4 */
1830 /* only starting from 10.5 the subview order is respected */
1831
1832 /* NSComparisonResult is typedef'd as an enum pre-Leopard but typedef'd as
1833  * NSInteger post-Leopard.  Pre-Leopard the Cocoa toolkit expects a function
1834  * returning int and not NSComparisonResult.  Post-Leopard the Cocoa toolkit
1835  * expects a function returning the new non-enum NSComparsionResult.
1836  * Hence we create a typedef named CocoaWindowCompareFunctionResult.
1837  */
1838 #if defined(NSINTEGER_DEFINED)
1839 typedef NSComparisonResult CocoaWindowCompareFunctionResult;
1840 #else
1841 typedef int CocoaWindowCompareFunctionResult;
1842 #endif
1843
1844 class CocoaWindowCompareContext
1845 {
1846     wxDECLARE_NO_COPY_CLASS(CocoaWindowCompareContext);
1847 public:
1848     CocoaWindowCompareContext(); // Not implemented
1849     CocoaWindowCompareContext(NSView *target, NSArray *subviews)
1850     {
1851         m_target = target;
1852         // Cocoa sorts subviews in-place.. make a copy
1853         m_subviews = [subviews copy];
1854     }
1855     
1856     ~CocoaWindowCompareContext()
1857     {   // release the copy
1858         [m_subviews release];
1859     }
1860     NSView* target()
1861     {   return m_target; }
1862     
1863     NSArray* subviews()
1864     {   return m_subviews; }
1865     
1866     /* Helper function that returns the comparison based off of the original ordering */
1867     CocoaWindowCompareFunctionResult CompareUsingOriginalOrdering(id first, id second)
1868     {
1869         NSUInteger firstI = [m_subviews indexOfObjectIdenticalTo:first];
1870         NSUInteger secondI = [m_subviews indexOfObjectIdenticalTo:second];
1871         // NOTE: If either firstI or secondI is NSNotFound then it will be NSIntegerMax and thus will
1872         // likely compare higher than the other view which is reasonable considering the only way that
1873         // can happen is if the subview was added after our call to subviews but before the call to
1874         // sortSubviewsUsingFunction:context:.  Thus we don't bother checking.  Particularly because
1875         // that case should never occur anyway because that would imply a multi-threaded GUI call
1876         // which is a big no-no with Cocoa.
1877                 
1878         // Subviews are ordered from back to front meaning one that is already lower will have an lower index.
1879         NSComparisonResult result = (firstI < secondI)
1880                 ?   NSOrderedAscending /* -1 */
1881                 :   (firstI > secondI)
1882                 ?   NSOrderedDescending /* 1 */
1883                 :   NSOrderedSame /* 0 */;
1884                 
1885         return result;
1886     }
1887 private:
1888     /* The subview we are trying to Raise or Lower */
1889     NSView *m_target;
1890     /* A copy of the original array of subviews */
1891     NSArray *m_subviews;
1892 };
1893
1894 /* Causes Cocoa to raise the target view to the top of the Z-Order by telling the sort function that
1895  * the target view is always higher than every other view.  When comparing two views neither of
1896  * which is the target, it returns the correct response based on the original ordering
1897  */
1898 static CocoaWindowCompareFunctionResult CocoaRaiseWindowCompareFunction(id first, id second, void *ctx)
1899 {
1900     CocoaWindowCompareContext *compareContext = (CocoaWindowCompareContext*)ctx;
1901     // first should be ordered higher
1902     if(first==compareContext->target())
1903         return NSOrderedDescending;
1904     // second should be ordered higher
1905     if(second==compareContext->target())
1906         return NSOrderedAscending;
1907     return compareContext->CompareUsingOriginalOrdering(first,second);
1908 }
1909
1910 void wxWidgetCocoaImpl::Raise()
1911 {
1912         NSView* nsview = m_osxView;
1913         
1914     NSView *superview = [nsview superview];
1915     CocoaWindowCompareContext compareContext(nsview, [superview subviews]);
1916         
1917     [superview sortSubviewsUsingFunction:
1918          CocoaRaiseWindowCompareFunction
1919                                                                  context: &compareContext];
1920         
1921 }
1922
1923 /* Causes Cocoa to lower the target view to the bottom of the Z-Order by telling the sort function that
1924  * the target view is always lower than every other view.  When comparing two views neither of
1925  * which is the target, it returns the correct response based on the original ordering
1926  */
1927 static CocoaWindowCompareFunctionResult CocoaLowerWindowCompareFunction(id first, id second, void *ctx)
1928 {
1929     CocoaWindowCompareContext *compareContext = (CocoaWindowCompareContext*)ctx;
1930     // first should be ordered lower
1931     if(first==compareContext->target())
1932         return NSOrderedAscending;
1933     // second should be ordered lower
1934     if(second==compareContext->target())
1935         return NSOrderedDescending;
1936     return compareContext->CompareUsingOriginalOrdering(first,second);
1937 }
1938
1939 void wxWidgetCocoaImpl::Lower()
1940 {
1941         NSView* nsview = m_osxView;
1942         
1943     NSView *superview = [nsview superview];
1944     CocoaWindowCompareContext compareContext(nsview, [superview subviews]);
1945         
1946     [superview sortSubviewsUsingFunction:
1947          CocoaLowerWindowCompareFunction
1948                                                                  context: &compareContext];
1949 }
1950
1951 void wxWidgetCocoaImpl::ScrollRect( const wxRect *WXUNUSED(rect), int WXUNUSED(dx), int WXUNUSED(dy) )
1952 {
1953 #if 1
1954     SetNeedsDisplay() ;
1955 #else
1956     // We should do something like this, but it wasn't working in 10.4.
1957     if (GetNeedsDisplay() )
1958     {
1959         SetNeedsDisplay() ;
1960     }
1961     NSRect r = wxToNSRect( [m_osxView superview], *rect );
1962     NSSize offset = NSMakeSize((float)dx, (float)dy);
1963     [m_osxView scrollRect:r by:offset];
1964 #endif
1965 }
1966
1967 void wxWidgetCocoaImpl::Move(int x, int y, int width, int height)
1968 {
1969     wxWindowMac* parent = GetWXPeer()->GetParent();
1970     // under Cocoa we might have a contentView in the wxParent to which we have to
1971     // adjust the coordinates
1972     if (parent && [m_osxView superview] != parent->GetHandle() )
1973     {
1974         int cx = 0,cy = 0,cw = 0,ch = 0;
1975         if ( parent->GetPeer() )
1976         {
1977             parent->GetPeer()->GetContentArea(cx, cy, cw, ch);
1978             x -= cx;
1979             y -= cy;
1980         }
1981     }
1982     [[m_osxView superview] setNeedsDisplayInRect:[m_osxView frame]];
1983     NSRect r = wxToNSRect( [m_osxView superview], wxRect(x,y,width, height) );
1984     [m_osxView setFrame:r];
1985     [[m_osxView superview] setNeedsDisplayInRect:r];
1986 }
1987
1988 void wxWidgetCocoaImpl::GetPosition( int &x, int &y ) const
1989 {
1990     wxRect r = wxFromNSRect( [m_osxView superview], [m_osxView frame] );
1991     x = r.GetLeft();
1992     y = r.GetTop();
1993     
1994     // under Cocoa we might have a contentView in the wxParent to which we have to
1995     // adjust the coordinates
1996     wxWindowMac* parent = GetWXPeer()->GetParent();
1997     if (parent && [m_osxView superview] != parent->GetHandle() )
1998     {
1999         int cx = 0,cy = 0,cw = 0,ch = 0;
2000         if ( parent->GetPeer() )
2001         {
2002             parent->GetPeer()->GetContentArea(cx, cy, cw, ch);
2003             x += cx;
2004             y += cy;
2005         }
2006     }
2007 }
2008
2009 void wxWidgetCocoaImpl::GetSize( int &width, int &height ) const
2010 {
2011     NSRect rect = [m_osxView frame];
2012     width = (int)rect.size.width;
2013     height = (int)rect.size.height;
2014 }
2015
2016 void wxWidgetCocoaImpl::GetContentArea( int&left, int &top, int &width, int &height ) const
2017 {
2018     if ( [m_osxView respondsToSelector:@selector(contentView) ] )
2019     {
2020         NSView* cv = [m_osxView contentView];
2021
2022         NSRect bounds = [m_osxView bounds];
2023         NSRect rect = [cv frame];
2024
2025         int y = (int)rect.origin.y;
2026         int x = (int)rect.origin.x;
2027         if ( ![ m_osxView isFlipped ] )
2028             y = (int)(bounds.size.height - (rect.origin.y + rect.size.height));
2029         left = x;
2030         top = y;
2031         width = (int)rect.size.width;
2032         height = (int)rect.size.height;
2033     }
2034     else
2035     {
2036         left = top = 0;
2037         GetSize( width, height );
2038     }
2039 }
2040
2041 void wxWidgetCocoaImpl::SetNeedsDisplay( const wxRect* where )
2042 {
2043     if ( where )
2044         [m_osxView setNeedsDisplayInRect:wxToNSRect(m_osxView, *where )];
2045     else
2046         [m_osxView setNeedsDisplay:YES];
2047 }
2048
2049 bool wxWidgetCocoaImpl::GetNeedsDisplay() const
2050 {
2051     return [m_osxView needsDisplay];
2052 }
2053
2054 bool wxWidgetCocoaImpl::CanFocus() const
2055 {
2056     return [m_osxView canBecomeKeyView] == YES;
2057 }
2058
2059 bool wxWidgetCocoaImpl::HasFocus() const
2060 {
2061     return ( FindFocus() == m_osxView );
2062 }
2063
2064 bool wxWidgetCocoaImpl::SetFocus()
2065 {
2066     if ( !CanFocus() )
2067         return false;
2068
2069     // TODO remove if no issues arise: should not raise the window, only assign focus
2070     //[[m_osxView window] makeKeyAndOrderFront:nil] ;
2071     [[m_osxView window] makeFirstResponder: m_osxView] ;
2072     return true;
2073 }
2074
2075
2076 void wxWidgetCocoaImpl::RemoveFromParent()
2077 {
2078     [m_osxView removeFromSuperview];
2079 }
2080
2081 void wxWidgetCocoaImpl::Embed( wxWidgetImpl *parent )
2082 {
2083     NSView* container = parent->GetWXWidget() ;
2084     wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
2085     [container addSubview:m_osxView];
2086 }
2087
2088 void wxWidgetCocoaImpl::SetBackgroundColour( const wxColour &col )
2089 {
2090     NSView* targetView = m_osxView;
2091     if ( [m_osxView isKindOfClass:[NSScrollView class] ] )
2092         targetView = [(NSScrollView*) m_osxView documentView];
2093
2094     if ( [targetView respondsToSelector:@selector(setBackgroundColor:) ] )
2095     {
2096         [targetView setBackgroundColor:[NSColor colorWithCalibratedRed:(CGFloat) (col.Red() / 255.0)
2097                                                                 green:(CGFloat) (col.Green() / 255.0)
2098                                                                  blue:(CGFloat) (col.Blue() / 255.0)
2099                                                                 alpha:(CGFloat) (col.Alpha() / 255.0)]];
2100     }
2101 }
2102
2103 bool wxWidgetCocoaImpl::SetBackgroundStyle( wxBackgroundStyle style )
2104 {
2105     BOOL opaque = ( style == wxBG_STYLE_PAINT );
2106     
2107     if ( [m_osxView respondsToSelector:@selector(setOpaque:) ] )
2108     {
2109         [m_osxView setOpaque: opaque];
2110     }
2111     
2112     return true ;
2113 }
2114
2115 void wxWidgetCocoaImpl::SetLabel( const wxString& title, wxFontEncoding encoding )
2116 {
2117     if ( [m_osxView respondsToSelector:@selector(setTitle:) ] )
2118     {
2119         wxCFStringRef cf( title , encoding );
2120         [m_osxView setTitle:cf.AsNSString()];
2121     }
2122     else if ( [m_osxView respondsToSelector:@selector(setStringValue:) ] )
2123     {
2124         wxCFStringRef cf( title , encoding );
2125         [m_osxView setStringValue:cf.AsNSString()];
2126     }
2127 }
2128
2129
2130 void  wxWidgetImpl::Convert( wxPoint *pt , wxWidgetImpl *from , wxWidgetImpl *to )
2131 {
2132     NSPoint p = wxToNSPoint( from->GetWXWidget(), *pt );
2133     p = [from->GetWXWidget() convertPoint:p toView:to->GetWXWidget() ];
2134     *pt = wxFromNSPoint( to->GetWXWidget(), p );
2135 }
2136
2137 wxInt32 wxWidgetCocoaImpl::GetValue() const
2138 {
2139     return [(NSControl*)m_osxView intValue];
2140 }
2141
2142 void wxWidgetCocoaImpl::SetValue( wxInt32 v )
2143 {
2144     if (  [m_osxView respondsToSelector:@selector(setIntValue:)] )
2145     {
2146         [m_osxView setIntValue:v];
2147     }
2148     else if (  [m_osxView respondsToSelector:@selector(setFloatValue:)] )
2149     {
2150         [m_osxView setFloatValue:(double)v];
2151     }
2152     else if (  [m_osxView respondsToSelector:@selector(setDoubleValue:)] )
2153     {
2154         [m_osxView setDoubleValue:(double)v];
2155     }
2156 }
2157
2158 void wxWidgetCocoaImpl::SetMinimum( wxInt32 v )
2159 {
2160     if (  [m_osxView respondsToSelector:@selector(setMinValue:)] )
2161     {
2162         [m_osxView setMinValue:(double)v];
2163     }
2164 }
2165
2166 void wxWidgetCocoaImpl::SetMaximum( wxInt32 v )
2167 {
2168     if (  [m_osxView respondsToSelector:@selector(setMaxValue:)] )
2169     {
2170         [m_osxView setMaxValue:(double)v];
2171     }
2172 }
2173
2174 wxInt32 wxWidgetCocoaImpl::GetMinimum() const
2175 {
2176     if (  [m_osxView respondsToSelector:@selector(minValue)] )
2177     {
2178         return (int)[m_osxView minValue];
2179     }
2180     return 0;
2181 }
2182
2183 wxInt32 wxWidgetCocoaImpl::GetMaximum() const
2184 {
2185     if (  [m_osxView respondsToSelector:@selector(maxValue)] )
2186     {
2187         return (int)[m_osxView maxValue];
2188     }
2189     return 0;
2190 }
2191
2192 wxBitmap wxWidgetCocoaImpl::GetBitmap() const
2193 {
2194     wxBitmap bmp;
2195
2196     // TODO: how to create a wxBitmap from NSImage?
2197 #if 0
2198     if ( [m_osxView respondsToSelector:@selector(image:)] )
2199         bmp = [m_osxView image];
2200 #endif
2201
2202     return bmp;
2203 }
2204
2205 void wxWidgetCocoaImpl::SetBitmap( const wxBitmap& bitmap )
2206 {
2207     if (  [m_osxView respondsToSelector:@selector(setImage:)] )
2208     {
2209         if (bitmap.IsOk())
2210             [m_osxView setImage:bitmap.GetNSImage()];
2211         else
2212             [m_osxView setImage:nil];
2213
2214         [m_osxView setNeedsDisplay:YES];
2215     }
2216 }
2217
2218 void wxWidgetCocoaImpl::SetBitmapPosition( wxDirection dir )
2219 {
2220     if ( [m_osxView respondsToSelector:@selector(setImagePosition:)] )
2221     {
2222         NSCellImagePosition pos;
2223         switch ( dir )
2224         {
2225             case wxLEFT:
2226                 pos = NSImageLeft;
2227                 break;
2228
2229             case wxRIGHT:
2230                 pos = NSImageRight;
2231                 break;
2232
2233             case wxTOP:
2234                 pos = NSImageAbove;
2235                 break;
2236
2237             case wxBOTTOM:
2238                 pos = NSImageBelow;
2239                 break;
2240
2241             default:
2242                 wxFAIL_MSG( "invalid image position" );
2243                 pos = NSNoImage;
2244         }
2245
2246         [m_osxView setImagePosition:pos];
2247     }
2248 }
2249
2250 void wxWidgetCocoaImpl::SetupTabs( const wxNotebook& WXUNUSED(notebook))
2251 {
2252     // implementation in subclass
2253 }
2254
2255 void wxWidgetCocoaImpl::GetBestRect( wxRect *r ) const
2256 {
2257     r->x = r->y = r->width = r->height = 0;
2258
2259     if (  [m_osxView respondsToSelector:@selector(sizeToFit)] )
2260     {
2261         NSRect former = [m_osxView frame];
2262         [m_osxView sizeToFit];
2263         NSRect best = [m_osxView frame];
2264         [m_osxView setFrame:former];
2265         r->width = (int)best.size.width;
2266         r->height = (int)best.size.height;
2267     }
2268 }
2269
2270 bool wxWidgetCocoaImpl::IsEnabled() const
2271 {
2272     NSView* targetView = m_osxView;
2273     if ( [m_osxView isKindOfClass:[NSScrollView class] ] )
2274         targetView = [(NSScrollView*) m_osxView documentView];
2275
2276     if ( [targetView respondsToSelector:@selector(isEnabled) ] )
2277         return [targetView isEnabled];
2278     return true;
2279 }
2280
2281 void wxWidgetCocoaImpl::Enable( bool enable )
2282 {
2283     NSView* targetView = m_osxView;
2284     if ( [m_osxView isKindOfClass:[NSScrollView class] ] )
2285         targetView = [(NSScrollView*) m_osxView documentView];
2286
2287     if ( [targetView respondsToSelector:@selector(setEnabled:) ] )
2288         [targetView setEnabled:enable];
2289 }
2290
2291 void wxWidgetCocoaImpl::PulseGauge()
2292 {
2293 }
2294
2295 void wxWidgetCocoaImpl::SetScrollThumb( wxInt32 WXUNUSED(val), wxInt32 WXUNUSED(view) )
2296 {
2297 }
2298
2299 void wxWidgetCocoaImpl::SetControlSize( wxWindowVariant variant )
2300 {
2301     NSControlSize size = NSRegularControlSize;
2302
2303     switch ( variant )
2304     {
2305         case wxWINDOW_VARIANT_NORMAL :
2306             size = NSRegularControlSize;
2307             break ;
2308
2309         case wxWINDOW_VARIANT_SMALL :
2310             size = NSSmallControlSize;
2311             break ;
2312
2313         case wxWINDOW_VARIANT_MINI :
2314             size = NSMiniControlSize;
2315             break ;
2316
2317         case wxWINDOW_VARIANT_LARGE :
2318             size = NSRegularControlSize;
2319             break ;
2320
2321         default:
2322             wxFAIL_MSG(wxT("unexpected window variant"));
2323             break ;
2324     }
2325     if ( [m_osxView respondsToSelector:@selector(setControlSize:)] )
2326         [m_osxView setControlSize:size];
2327     else if ([m_osxView respondsToSelector:@selector(cell)])
2328     {
2329         id cell = [(id)m_osxView cell];
2330         if ([cell respondsToSelector:@selector(setControlSize:)])
2331             [cell setControlSize:size];
2332     }
2333 }
2334
2335 void wxWidgetCocoaImpl::SetFont(wxFont const& font, wxColour const&col, long, bool)
2336 {
2337     if ([m_osxView respondsToSelector:@selector(setFont:)])
2338         [m_osxView setFont: font.OSXGetNSFont()];
2339     if ([m_osxView respondsToSelector:@selector(setTextColor:)])
2340         [m_osxView setTextColor:[NSColor colorWithCalibratedRed:(CGFloat) (col.Red() / 255.0)
2341                                                                  green:(CGFloat) (col.Green() / 255.0)
2342                                                                   blue:(CGFloat) (col.Blue() / 255.0)
2343                                                                  alpha:(CGFloat) (col.Alpha() / 255.0)]];
2344 }
2345
2346 void wxWidgetCocoaImpl::SetToolTip(wxToolTip* tooltip)
2347 {
2348     if ( tooltip )
2349     {
2350         wxCFStringRef cf( tooltip->GetTip() , m_wxPeer->GetFont().GetEncoding() );
2351         [m_osxView setToolTip: cf.AsNSString()];
2352     }
2353     else 
2354     {
2355         [m_osxView setToolTip:nil];
2356     }
2357 }
2358
2359 void wxWidgetCocoaImpl::InstallEventHandler( WXWidget control )
2360 {
2361     WXWidget c =  control ? control : (WXWidget) m_osxView;
2362     wxWidgetImpl::Associate( c, this ) ;
2363     if ([c respondsToSelector:@selector(setAction:)])
2364     {
2365         [c setTarget: c];
2366         [c setAction: @selector(controlAction:)];
2367         if ([c respondsToSelector:@selector(setDoubleAction:)])
2368         {
2369             [c setDoubleAction: @selector(controlDoubleAction:)];
2370         }
2371
2372     }
2373     NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited|NSTrackingCursorUpdate|NSTrackingMouseMoved|NSTrackingActiveAlways|NSTrackingInVisibleRect;
2374         NSTrackingArea* area = [[NSTrackingArea alloc] initWithRect: NSZeroRect options: options owner: m_osxView userInfo: nil];
2375     [m_osxView addTrackingArea: area];
2376     [area release];
2377  }
2378
2379 bool wxWidgetCocoaImpl::DoHandleCharEvent(NSEvent *event, NSString *text)
2380 {
2381     wxKeyEvent wxevent(wxEVT_CHAR);
2382     SetupKeyEvent( wxevent, event, text );
2383
2384     return GetWXPeer()->OSXHandleKeyEvent(wxevent);
2385 }
2386
2387 bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event)
2388 {
2389     wxKeyEvent wxevent(wxEVT_KEY_DOWN);
2390     SetupKeyEvent( wxevent, event );
2391
2392     // Generate wxEVT_CHAR_HOOK before sending any other events but only when
2393     // the key is pressed, not when it's released (the type of wxevent is
2394     // changed by SetupKeyEvent() so it can be wxEVT_KEY_UP too by now).
2395     if ( wxevent.GetEventType() == wxEVT_KEY_DOWN )
2396     {
2397         wxKeyEvent eventHook(wxEVT_CHAR_HOOK, wxevent);
2398         if ( GetWXPeer()->OSXHandleKeyEvent(eventHook)
2399                 && !eventHook.IsNextEventAllowed() )
2400             return true;
2401     }
2402
2403     bool result = GetWXPeer()->OSXHandleKeyEvent(wxevent);
2404
2405     // this will fire higher level events, like insertText, to help
2406     // us handle EVT_CHAR, etc.
2407
2408     if ( !result )
2409     {
2410         if ( [event type] == NSKeyDown)
2411         {
2412             long keycode = wxOSXTranslateCocoaKey( event, wxEVT_CHAR );
2413             
2414             if ( (keycode > 0 && keycode < WXK_SPACE) || keycode == WXK_DELETE || keycode >= WXK_START )
2415             {
2416                 // eventually we could setup a doCommandBySelector catcher and retransform this into the wx key chars
2417                 wxKeyEvent wxevent2(wxevent) ;
2418                 wxevent2.SetEventType(wxEVT_CHAR);
2419                 SetupKeyEvent( wxevent2, event );
2420                 wxevent2.m_keyCode = keycode;
2421                 result = GetWXPeer()->OSXHandleKeyEvent(wxevent2);
2422             }
2423             else if (wxevent.CmdDown())
2424             {
2425                 wxKeyEvent wxevent2(wxevent) ;
2426                 wxevent2.SetEventType(wxEVT_CHAR);
2427                 SetupKeyEvent( wxevent2, event );
2428                 result = GetWXPeer()->OSXHandleKeyEvent(wxevent2);
2429             }
2430             else
2431             {
2432                 if ( IsUserPane() && !wxevent.CmdDown() )
2433                 {
2434                     if ( [m_osxView isKindOfClass:[NSScrollView class] ] )
2435                         [[(NSScrollView*)m_osxView documentView] interpretKeyEvents:[NSArray arrayWithObject:event]];
2436                     else
2437                         [m_osxView interpretKeyEvents:[NSArray arrayWithObject:event]];
2438                     result = true;
2439                 }
2440             }
2441         }
2442     }
2443
2444     return result;
2445 }
2446
2447 bool wxWidgetCocoaImpl::DoHandleMouseEvent(NSEvent *event)
2448 {
2449     wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
2450     SetupMouseEvent(wxevent , event) ;
2451     return GetWXPeer()->HandleWindowEvent(wxevent);
2452 }
2453
2454 void wxWidgetCocoaImpl::DoNotifyFocusEvent(bool receivedFocus, wxWidgetImpl* otherWindow)
2455 {
2456     wxWindow* thisWindow = GetWXPeer();
2457     if ( thisWindow->MacGetTopLevelWindow() && NeedsFocusRect() )
2458     {
2459         thisWindow->MacInvalidateBorders();
2460     }
2461
2462     if ( receivedFocus )
2463     {
2464         wxLogTrace(wxT("Focus"), wxT("focus set(%p)"), static_cast<void*>(thisWindow));
2465         wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
2466         thisWindow->HandleWindowEvent(eventFocus);
2467
2468 #if wxUSE_CARET
2469         if ( thisWindow->GetCaret() )
2470             thisWindow->GetCaret()->OnSetFocus();
2471 #endif
2472
2473         wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
2474         event.SetEventObject(thisWindow);
2475         if (otherWindow)
2476             event.SetWindow(otherWindow->GetWXPeer());
2477         thisWindow->HandleWindowEvent(event) ;
2478     }
2479     else // !receivedFocuss
2480     {
2481 #if wxUSE_CARET
2482         if ( thisWindow->GetCaret() )
2483             thisWindow->GetCaret()->OnKillFocus();
2484 #endif
2485
2486         wxLogTrace(wxT("Focus"), wxT("focus lost(%p)"), static_cast<void*>(thisWindow));
2487
2488         wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
2489         event.SetEventObject(thisWindow);
2490         if (otherWindow)
2491             event.SetWindow(otherWindow->GetWXPeer());
2492         thisWindow->HandleWindowEvent(event) ;
2493     }
2494 }
2495
2496 void wxWidgetCocoaImpl::SetCursor(const wxCursor& cursor)
2497 {
2498     if ( !wxIsBusy() )
2499     {
2500         NSPoint location = [NSEvent mouseLocation];
2501         location = [[m_osxView window] convertScreenToBase:location];
2502         NSPoint locationInView = [m_osxView convertPoint:location fromView:nil];
2503
2504         if( NSMouseInRect(locationInView, [m_osxView bounds], YES) )
2505         {
2506             [(NSCursor*)cursor.GetHCURSOR() set];
2507         }
2508     }
2509 }
2510
2511 void wxWidgetCocoaImpl::CaptureMouse()
2512 {
2513     [[m_osxView window] disableCursorRects];
2514 }
2515
2516 void wxWidgetCocoaImpl::ReleaseMouse()
2517 {
2518     [[m_osxView window] enableCursorRects];
2519 }
2520
2521 void wxWidgetCocoaImpl::SetFlipped(bool flipped)
2522 {
2523     m_isFlipped = flipped;
2524 }
2525
2526 //
2527 // Factory methods
2528 //
2529
2530 wxWidgetImpl* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, wxWindowMac* WXUNUSED(parent),
2531     wxWindowID WXUNUSED(id), const wxPoint& pos, const wxSize& size,
2532     long WXUNUSED(style), long WXUNUSED(extraStyle))
2533 {
2534     NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
2535     wxNSView* v = [[wxNSView alloc] initWithFrame:r];
2536
2537     // temporary hook for dnd
2538     [v registerForDraggedTypes:[NSArray arrayWithObjects:
2539         NSStringPboardType, NSFilenamesPboardType, NSTIFFPboardType, NSPICTPboardType, NSPDFPboardType, nil]];
2540
2541     wxWidgetCocoaImpl* c = new wxWidgetCocoaImpl( wxpeer, v, false, true );
2542     return c;
2543 }
2544
2545 wxWidgetImpl* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now )
2546 {
2547     NSWindow* tlw = now->GetWXWindow();
2548     
2549     wxWidgetCocoaImpl* c = NULL;
2550     if ( now->IsNativeWindowWrapper() )
2551     {
2552         NSView* cv = [tlw contentView];
2553         c = new wxWidgetCocoaImpl( now, cv, true );
2554         // increase ref count, because the impl destructor will decrement it again
2555         CFRetain(cv);
2556         if ( !now->IsShown() )
2557             [cv setHidden:NO];
2558         
2559     }
2560     else
2561     {
2562         wxNSView* v = [[wxNSView alloc] initWithFrame:[[tlw contentView] frame]];
2563         c = new wxWidgetCocoaImpl( now, v, true );
2564         c->InstallEventHandler();
2565         [tlw setContentView:v];
2566     }
2567     return c;
2568 }