Landing basic EVT_CHAR support, along with the rest of EVT_TEXT support fix.
[wxWidgets.git] / src / osx / cocoa / window.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/osx/cocoa/window.mm
3 // Purpose:     widgets (non tlw) for cocoa
4 // Author:      Stefan Csomor
5 // Modified by:
6 // Created:     2008-06-20
7 // RCS-ID:      $Id: window.mm 48805 2007-09-19 14:52:25Z SC $
8 // Copyright:   (c) Stefan Csomor
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #ifndef WX_PRECOMP
15     #include "wx/dcclient.h"
16     #include "wx/nonownedwnd.h"
17     #include "wx/log.h"
18 #endif
19
20 #ifdef __WXMAC__
21     #include "wx/osx/private.h"
22 #endif
23
24 #if wxUSE_CARET
25     #include "wx/caret.h"
26 #endif
27
28 #if wxUSE_DRAG_AND_DROP
29     #include "wx/dnd.h"
30 #endif
31
32 #include <objc/objc-runtime.h>
33
34 NSRect wxOSXGetFrameForControl( wxWindowMac* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin )
35 {
36     int x, y, w, h ;
37
38     window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ;
39     wxRect bounds(x,y,w,h);
40     NSView* sv = (window->GetParent()->GetHandle() );
41
42     return wxToNSRect( sv, bounds );
43 }
44
45 @interface wxNSView : NSView
46 {
47     NSTrackingRectTag rectTag;
48 }
49
50 - (BOOL) canBecomeKeyView;
51 // the tracking tag is needed to track mouse enter / exit events 
52 - (void) setTrackingTag: (NSTrackingRectTag)tag;
53 - (NSTrackingRectTag) trackingTag;
54 @end // wxNSView
55
56 @interface NSView(PossibleMethods) 
57 - (void)setTitle:(NSString *)aString;
58 - (void)setStringValue:(NSString *)aString;
59 - (void)setIntValue:(int)anInt;
60 - (void)setFloatValue:(float)aFloat;
61 - (void)setDoubleValue:(double)aDouble;
62
63 - (double)minValue;
64 - (double)maxValue;
65 - (void)setMinValue:(double)aDouble;
66 - (void)setMaxValue:(double)aDouble;
67
68 - (void)sizeToFit;
69
70 - (BOOL)isEnabled;
71 - (void)setEnabled:(BOOL)flag;
72
73 - (void)setImage:(NSImage *)image;
74 - (void)setControlSize:(NSControlSize)size;
75
76 - (id)contentView;
77
78 - (void)setTarget:(id)anObject;
79 - (void)setAction:(SEL)aSelector;
80 - (void)setDoubleAction:(SEL)aSelector;
81 @end 
82
83 long wxOSXTranslateCocoaKey( int unichar )
84 {
85     long retval = unichar;
86     switch( unichar )
87     {
88         case NSUpArrowFunctionKey :
89             retval = WXK_UP;
90             break;
91         case NSDownArrowFunctionKey :
92             retval = WXK_DOWN;
93             break;
94         case NSLeftArrowFunctionKey :
95             retval = WXK_LEFT;
96             break;
97         case NSRightArrowFunctionKey :
98             retval = WXK_RIGHT;
99             break;
100         case NSInsertFunctionKey  :
101             retval = WXK_INSERT;
102             break;
103         case NSDeleteFunctionKey  :
104             retval = WXK_DELETE;
105             break;
106         case NSHomeFunctionKey  :
107             retval = WXK_HOME;
108             break;
109 //        case NSBeginFunctionKey  :
110 //            retval = WXK_BEGIN;
111 //            break;
112         case NSEndFunctionKey  :
113             retval = WXK_END;
114             break;
115         case NSPageUpFunctionKey  :
116             retval = WXK_PAGEUP;
117             break;
118        case NSPageDownFunctionKey  :
119             retval = WXK_PAGEDOWN;
120             break;
121        case NSHelpFunctionKey  :
122             retval = WXK_HELP;
123             break;
124
125         default :
126             if ( unichar >= NSF1FunctionKey && unichar >= NSF24FunctionKey )
127                 retval = WXK_F1 + (unichar - NSF1FunctionKey );
128             break;
129     }
130     return retval;
131 }
132
133 void SetupKeyEvent( wxKeyEvent &wxevent , NSEvent * nsEvent, NSString* charString = NULL )
134 {
135     UInt32 modifiers = [nsEvent modifierFlags] ;
136     int eventType = [nsEvent type];
137
138     wxevent.m_shiftDown = modifiers & NSShiftKeyMask;
139     wxevent.m_controlDown = modifiers & NSControlKeyMask;
140     wxevent.m_altDown = modifiers & NSAlternateKeyMask;
141     wxevent.m_metaDown = modifiers & NSCommandKeyMask;
142     
143     wxevent.m_rawCode = [nsEvent keyCode];
144     wxevent.m_rawFlags = modifiers;
145     
146     wxevent.SetTimestamp( [nsEvent timestamp] * 1000.0 ) ;
147     switch (eventType)
148     {
149         case NSKeyDown :
150             wxevent.SetEventType( wxEVT_KEY_DOWN )  ;
151             break;
152         case NSKeyUp :
153             wxevent.SetEventType( wxEVT_KEY_UP )  ;
154             break;
155         case NSFlagsChanged :
156             // setup common code here
157             break;
158         default :
159             break ;
160     }
161
162     wxString chars;
163     if ( eventType != NSFlagsChanged )
164     {
165         NSString* nschars = [nsEvent characters];
166         if ( charString )
167             nschars = charString;
168         
169         if ( nschars )
170         {
171             wxCFStringRef cfchars((CFStringRef)[nschars retain]);
172             chars = cfchars.AsString();
173         }
174     }
175     
176     int unichar = chars.Length() > 0 ? chars[0] : 0;
177     long keyval = wxOSXTranslateCocoaKey(unichar) ;
178     if ( keyval == unichar && ( wxevent.GetEventType() == wxEVT_KEY_UP || wxevent.GetEventType() == wxEVT_KEY_DOWN ) )
179         keyval = wxToupper( keyval ) ;
180
181 #if wxUSE_UNICODE
182     wxevent.m_uniChar = unichar;
183 #endif
184     wxevent.m_keyCode = keyval;
185 }
186
187 UInt32 g_lastButton = 0 ;
188 bool g_lastButtonWasFakeRight = false ;
189
190 void SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
191 {
192     int eventType = [nsEvent type];
193     UInt32 modifiers = [nsEvent modifierFlags] ;
194     wxPoint screenMouseLocation = wxFromNSPoint( NULL, [nsEvent locationInWindow]);
195
196     // these parameters are not given for all events
197     UInt32 button = [nsEvent buttonNumber];
198     UInt32 clickCount = 0;
199     if ( [nsEvent respondsToSelector:@selector(clickCount:)] ) 
200         [nsEvent clickCount];
201
202     wxevent.m_x = screenMouseLocation.x;
203     wxevent.m_y = screenMouseLocation.y;
204     wxevent.m_shiftDown = modifiers & NSShiftKeyMask;
205     wxevent.m_controlDown = modifiers & NSControlKeyMask;
206     wxevent.m_altDown = modifiers & NSAlternateKeyMask;
207     wxevent.m_metaDown = modifiers & NSCommandKeyMask;
208     wxevent.m_clickCount = clickCount;
209     wxevent.SetTimestamp( [nsEvent timestamp] * 1000.0 ) ;
210
211     UInt32 mouseChord = 0; 
212
213     switch (eventType)
214     {
215         case NSLeftMouseDown :
216         case NSLeftMouseDragged :
217             mouseChord = 1U;
218             break;
219         case NSRightMouseDown :
220         case NSRightMouseDragged :
221             mouseChord = 2U;
222             break;
223         case NSOtherMouseDown :
224         case NSOtherMouseDragged :
225             mouseChord = 4U;
226             break;
227     }
228
229     // a control click is interpreted as a right click
230     bool thisButtonIsFakeRight = false ;
231     if ( button == 0 && (modifiers & NSControlKeyMask) )
232     {
233         button = 1 ;
234         thisButtonIsFakeRight = true ;
235     }
236
237     // otherwise we report double clicks by connecting a left click with a ctrl-left click
238     if ( clickCount > 1 && button != g_lastButton )
239         clickCount = 1 ;
240
241     // we must make sure that our synthetic 'right' button corresponds in
242     // mouse down, moved and mouse up, and does not deliver a right down and left up
243     switch (eventType)
244     {
245         case NSLeftMouseDown :
246         case NSRightMouseDown :
247         case NSOtherMouseDown :
248             g_lastButton = button ;
249             g_lastButtonWasFakeRight = thisButtonIsFakeRight ;
250             break;
251      }
252
253     if ( button == 0 )
254     {
255         g_lastButton = 0 ;
256         g_lastButtonWasFakeRight = false ;
257     }
258     else if ( g_lastButton == 1 && g_lastButtonWasFakeRight )
259         button = g_lastButton ;
260
261     // Adjust the chord mask to remove the primary button and add the
262     // secondary button.  It is possible that the secondary button is
263     // already pressed, e.g. on a mouse connected to a laptop, but this
264     // possibility is ignored here:
265     if( thisButtonIsFakeRight && ( mouseChord & 1U ) )
266         mouseChord = ((mouseChord & ~1U) | 2U);
267
268     if(mouseChord & 1U)
269                 wxevent.m_leftDown = true ;
270     if(mouseChord & 2U)
271                 wxevent.m_rightDown = true ;
272     if(mouseChord & 4U)
273                 wxevent.m_middleDown = true ;
274
275     // translate into wx types
276     switch (eventType)
277     {
278         case NSLeftMouseDown :
279         case NSRightMouseDown :
280         case NSOtherMouseDown :
281             switch ( button )
282             {
283                 case 0 :
284                     wxevent.SetEventType( clickCount > 1 ? wxEVT_LEFT_DCLICK : wxEVT_LEFT_DOWN )  ;
285                     break ;
286
287                 case 1 :
288                     wxevent.SetEventType( clickCount > 1 ? wxEVT_RIGHT_DCLICK : wxEVT_RIGHT_DOWN ) ;
289                     break ;
290
291                 case 2 :
292                     wxevent.SetEventType( clickCount > 1 ? wxEVT_MIDDLE_DCLICK : wxEVT_MIDDLE_DOWN ) ;
293                     break ;
294
295                 default:
296                     break ;
297             }
298             break ;
299
300         case NSLeftMouseUp :
301         case NSRightMouseUp :
302         case NSOtherMouseUp :
303             switch ( button )
304             {
305                 case 0 :
306                     wxevent.SetEventType( wxEVT_LEFT_UP )  ;
307                     break ;
308
309                 case 1 :
310                     wxevent.SetEventType( wxEVT_RIGHT_UP ) ;
311                     break ;
312
313                 case 2 :
314                     wxevent.SetEventType( wxEVT_MIDDLE_UP ) ;
315                     break ;
316
317                 default:
318                     break ;
319             }
320             break ;
321
322      case NSScrollWheel :
323         {
324             wxevent.SetEventType( wxEVT_MOUSEWHEEL ) ;
325             wxevent.m_wheelDelta = 10;
326             wxevent.m_linesPerAction = 1;
327             NSLog(@"deltaX %f, deltaY %f",[nsEvent deltaX], [nsEvent deltaY]);
328             if ( abs([nsEvent deltaX]) > abs([nsEvent deltaY]) )
329             {
330                 wxevent.m_wheelAxis = 1;
331                 wxevent.m_wheelRotation = [nsEvent deltaX] * 10.0;
332             }
333             else
334             {
335                 wxevent.m_wheelRotation = [nsEvent deltaY] * 10.0;
336             }
337         }
338         break ;
339
340         case NSMouseEntered :
341             wxevent.SetEventType( wxEVT_ENTER_WINDOW ) ;
342             break;
343         case NSMouseExited :
344             wxevent.SetEventType( wxEVT_LEAVE_WINDOW ) ;
345             break;
346         case NSLeftMouseDragged :
347         case NSRightMouseDragged :
348         case NSOtherMouseDragged :
349         case NSMouseMoved :
350             wxevent.SetEventType( wxEVT_MOTION ) ;
351             break;
352         default :
353             break ;
354     }
355 }
356
357 @implementation wxNSView
358
359 + (void)initialize
360 {
361     static BOOL initialized = NO;
362     if (!initialized) 
363     {
364         initialized = YES;
365         wxOSXCocoaClassAddWXMethods( self );
366     }
367 }
368
369 - (BOOL) canBecomeKeyView
370 {
371     return YES;
372 }
373
374 - (void) setTrackingTag: (NSTrackingRectTag)tag
375 {
376     rectTag = tag;
377 }
378
379 - (NSTrackingRectTag) trackingTag
380 {
381     return rectTag;
382 }
383
384 @end // wxNSView
385
386 //
387 // event handlers
388 //
389
390 #if wxUSE_DRAG_AND_DROP
391
392 // see http://lists.apple.com/archives/Cocoa-dev/2005/Jul/msg01244.html
393 // for details on the NSPasteboard -> PasteboardRef conversion
394
395 NSDragOperation wxOSX_draggingEntered( id self, SEL _cmd, id <NSDraggingInfo>sender )
396 {
397     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
398     if (impl == NULL)
399         return NSDragOperationNone;
400         
401     return impl->draggingEntered(sender, self, _cmd);
402 }
403
404 void wxOSX_draggingExited( id self, SEL _cmd, id <NSDraggingInfo> sender )
405 {
406     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
407     if (impl == NULL)
408         return ;
409         
410     return impl->draggingExited(sender, self, _cmd);
411 }
412
413 NSDragOperation wxOSX_draggingUpdated( id self, SEL _cmd, id <NSDraggingInfo>sender )
414 {
415     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
416     if (impl == NULL)
417         return NSDragOperationNone;
418         
419     return impl->draggingUpdated(sender, self, _cmd);
420 }
421
422 BOOL wxOSX_performDragOperation( id self, SEL _cmd, id <NSDraggingInfo> sender )
423 {
424     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
425     if (impl == NULL)
426         return NSDragOperationNone;
427         
428     return impl->performDragOperation(sender, self, _cmd) ? YES:NO ;
429 }
430
431 void wxOSX_mouseEvent(NSView* self, SEL _cmd, NSEvent *event) 
432 {
433     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
434     if (impl == NULL)
435         return;
436         
437     impl->mouseEvent(event, self, _cmd);
438 }
439
440 void wxOSX_keyEvent(NSView* self, SEL _cmd, NSEvent *event) 
441 {
442     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
443     if (impl == NULL)
444         return;
445         
446     impl->keyEvent(event, self, _cmd);
447 }
448
449 void wxOSX_insertText(NSView* self, SEL _cmd, NSString* text) 
450 {
451     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
452     if (impl == NULL)
453         return;
454         
455     impl->insertText(text, self, _cmd);
456 }
457
458 BOOL wxOSX_performKeyEquivalent(NSView* self, SEL _cmd, NSEvent *event) 
459 {
460     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
461     if (impl == NULL)
462         return NO;
463         
464     return impl->performKeyEquivalent(event, self, _cmd);
465 }
466
467 BOOL wxOSX_becomeFirstResponder(NSView* self, SEL _cmd)
468 {
469     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
470     if (impl == NULL)
471         return NO;
472         
473     return impl->becomeFirstResponder(self, _cmd);
474 }
475
476 BOOL wxOSX_resignFirstResponder(NSView* self, SEL _cmd)
477 {
478     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
479     if (impl == NULL)
480         return NO;
481         
482     return impl->resignFirstResponder(self, _cmd);
483 }
484
485 void wxOSX_resetCursorRects(NSView* self, SEL _cmd)
486 {
487     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
488     if (impl == NULL)
489         return;
490         
491     impl->resetCursorRects(self, _cmd);
492 }
493
494 BOOL wxOSX_isFlipped(NSView* self, SEL _cmd)
495 {
496     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
497     if (impl == NULL)
498         return NO;
499         
500     return impl->isFlipped(self, _cmd) ? YES:NO;
501 }
502
503 void wxOSX_drawRect(NSView* self, SEL _cmd, NSRect rect)
504 {
505     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
506     if (impl == NULL)
507         return;
508         
509     return impl->drawRect(&rect, self, _cmd);
510 }
511
512 void wxOSX_controlAction(NSView* self, SEL _cmd, id sender)
513 {
514     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
515     if (impl == NULL)
516         return;
517         
518     impl->controlAction(self, _cmd, sender);
519 }
520
521 void wxOSX_controlDoubleAction(NSView* self, SEL _cmd, id sender)
522 {
523     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
524     if (impl == NULL)
525         return;
526         
527     impl->controlDoubleAction(self, _cmd, sender);
528 }
529
530 unsigned int wxWidgetCocoaImpl::draggingEntered(void* s, WXWidget slf, void *_cmd)
531 {
532     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
533     NSPasteboard *pboard = [sender draggingPasteboard];
534     NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
535     
536     wxWindow* wxpeer = GetWXPeer();
537     if ( wxpeer == NULL )
538         return NSDragOperationNone;
539         
540     wxDropTarget* target = wxpeer->GetDropTarget();
541     if ( target == NULL )
542         return NSDragOperationNone;
543
544     wxDragResult result = wxDragNone;
545     wxPoint pt = wxFromNSPoint( m_osxView, [sender draggingLocation] );
546
547     if ( sourceDragMask & NSDragOperationLink )
548         result = wxDragLink;
549     else if ( sourceDragMask & NSDragOperationCopy )
550         result = wxDragCopy;
551     else if ( sourceDragMask & NSDragOperationMove )
552         result = wxDragMove;
553
554     PasteboardRef pboardRef;    
555     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
556     target->SetCurrentDragPasteboard(pboardRef);
557     result = target->OnEnter(pt.x, pt.y, result);
558     CFRelease(pboardRef);
559      
560     NSDragOperation nsresult = NSDragOperationNone;
561     switch (result )
562     {
563         case wxDragLink:
564             nsresult = NSDragOperationLink;
565         case wxDragMove:
566             nsresult = NSDragOperationMove;
567         case wxDragCopy:
568             nsresult = NSDragOperationCopy;
569         default :
570             break;
571     }
572     return nsresult;
573 }
574
575 void wxWidgetCocoaImpl::draggingExited(void* s, WXWidget slf, void *_cmd)
576 {
577     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
578     NSPasteboard *pboard = [sender draggingPasteboard];
579     
580     wxWindow* wxpeer = GetWXPeer();
581     if ( wxpeer == NULL )
582         return;
583         
584     wxDropTarget* target = wxpeer->GetDropTarget();
585     if ( target == NULL )
586         return;
587         
588     PasteboardRef pboardRef;    
589     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
590     target->SetCurrentDragPasteboard(pboardRef);
591     target->OnLeave();
592     CFRelease(pboardRef);
593  }
594
595 unsigned int wxWidgetCocoaImpl::draggingUpdated(void* s, WXWidget slf, void *_cmd)
596 {
597     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
598     NSPasteboard *pboard = [sender draggingPasteboard];
599     NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
600         
601     wxWindow* wxpeer = GetWXPeer();
602     if ( wxpeer == NULL )
603         return NSDragOperationNone;
604         
605     wxDropTarget* target = wxpeer->GetDropTarget();
606     if ( target == NULL )
607         return NSDragOperationNone;
608
609     wxDragResult result = wxDragNone;
610     wxPoint pt = wxFromNSPoint( m_osxView, [sender draggingLocation] );
611
612     if ( sourceDragMask & NSDragOperationLink )
613         result = wxDragLink;
614     else if ( sourceDragMask & NSDragOperationCopy )
615         result = wxDragCopy;
616     else if ( sourceDragMask & NSDragOperationMove )
617         result = wxDragMove;
618
619     PasteboardRef pboardRef;    
620     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
621     target->SetCurrentDragPasteboard(pboardRef);
622     result = target->OnDragOver(pt.x, pt.y, result);
623     CFRelease(pboardRef);
624      
625     NSDragOperation nsresult = NSDragOperationNone;
626     switch (result )
627     {
628         case wxDragLink:
629             nsresult = NSDragOperationLink;
630         case wxDragMove:
631             nsresult = NSDragOperationMove;
632         case wxDragCopy:
633             nsresult = NSDragOperationCopy;
634         default :
635             break;
636     }
637     return nsresult;
638 }
639
640 bool wxWidgetCocoaImpl::performDragOperation(void* s, WXWidget slf, void *_cmd)
641 {
642     id <NSDraggingInfo>sender = (id <NSDraggingInfo>) s;
643
644     NSPasteboard *pboard = [sender draggingPasteboard];
645     NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
646     
647     wxWindow* wxpeer = GetWXPeer();
648     wxDropTarget* target = wxpeer->GetDropTarget();
649     wxDragResult result = wxDragNone;
650     wxPoint pt = wxFromNSPoint( m_osxView, [sender draggingLocation] );
651
652     if ( sourceDragMask & NSDragOperationLink )
653         result = wxDragLink;
654     else if ( sourceDragMask & NSDragOperationCopy )
655         result = wxDragCopy;
656     else if ( sourceDragMask & NSDragOperationMove )
657         result = wxDragMove;
658
659     PasteboardRef pboardRef;    
660     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
661     target->SetCurrentDragPasteboard(pboardRef);
662     result = target->OnData(pt.x, pt.y, result);
663     CFRelease(pboardRef);
664      
665     return result != wxDragNone;
666 }
667
668 #endif
669
670 typedef void (*wxOSX_EventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event);
671 typedef BOOL (*wxOSX_PerformKeyEventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event);
672 typedef BOOL (*wxOSX_FocusHandlerPtr)(NSView* self, SEL _cmd);
673 typedef BOOL (*wxOSX_ResetCursorRectsHandlerPtr)(NSView* self, SEL _cmd);
674 typedef BOOL (*wxOSX_DrawRectHandlerPtr)(NSView* self, SEL _cmd, NSRect rect);
675
676 void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
677 {
678     if ( !DoHandleMouseEvent(event) )
679     {
680         wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
681         superimpl(slf, (SEL)_cmd, event);
682     }
683 }
684
685 void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
686 {
687     if ( [[slf window] firstResponder] != slf || !DoHandleKeyEvent(event) )
688     {
689         wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
690         superimpl(slf, (SEL)_cmd, event);
691     }
692 }
693
694 void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd)
695 {
696     if (m_lastKeyDownEvent && !DoHandleCharEvent(m_lastKeyDownEvent, text) )
697     {
698             wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:@selector(insertText:)];
699             superimpl(slf, @selector(insertText:), text);
700     }
701     m_lastKeyDownEvent = NULL;
702 }
703
704
705 bool wxWidgetCocoaImpl::performKeyEquivalent(WX_NSEvent event, WXWidget slf, void *_cmd)
706 {
707     wxOSX_PerformKeyEventHandlerPtr superimpl = (wxOSX_PerformKeyEventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
708     return superimpl(slf, (SEL)_cmd, event);
709 }
710
711 bool wxWidgetCocoaImpl::becomeFirstResponder(WXWidget slf, void *_cmd)
712 {
713     wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
714     BOOL r = superimpl(slf, (SEL)_cmd);
715     if ( r )
716         DoNotifyFocusEvent( true );
717     return r;
718 }
719
720 bool wxWidgetCocoaImpl::resignFirstResponder(WXWidget slf, void *_cmd)
721 {
722     wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
723     BOOL r = superimpl(slf, (SEL)_cmd);
724     if ( r )
725         DoNotifyFocusEvent( false );
726     return r;
727 }
728
729 void wxWidgetCocoaImpl::resetCursorRects(WXWidget slf, void *_cmd)
730 {
731     wxWindow* wxpeer = GetWXPeer();
732     if ( wxpeer )
733     {
734         NSCursor *cursor = (NSCursor*)wxpeer->GetCursor().GetHCURSOR();
735         if (cursor == NULL)
736         {
737             wxOSX_ResetCursorRectsHandlerPtr superimpl = (wxOSX_ResetCursorRectsHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
738             superimpl(slf, (SEL)_cmd);
739         }
740         else
741         {
742             [slf addCursorRect: [slf bounds]
743                 cursor: cursor];
744         }
745     }
746 }
747   
748 bool wxWidgetCocoaImpl::isFlipped(WXWidget slf, void *_cmd)
749 {
750     return m_isFlipped;
751 }
752
753
754 #define OSX_DEBUG_DRAWING 0
755
756 void wxWidgetCocoaImpl::drawRect(void* rect, WXWidget slf, void *_cmd)
757 {
758     CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
759     CGContextSaveGState( context );
760     
761 #if OSX_DEBUG_DRAWING
762     CGContextBeginPath( context );
763     CGContextMoveToPoint(context, 0, 0);
764     NSRect bounds = [self bounds];
765     CGContextAddLineToPoint(context, 10, 0);
766     CGContextMoveToPoint(context, 0, 0);
767     CGContextAddLineToPoint(context, 0, 10);
768     CGContextMoveToPoint(context, bounds.size.width, bounds.size.height);
769     CGContextAddLineToPoint(context, bounds.size.width, bounds.size.height-10);
770     CGContextMoveToPoint(context, bounds.size.width, bounds.size.height);
771     CGContextAddLineToPoint(context, bounds.size.width-10, bounds.size.height);
772     CGContextClosePath( context );
773     CGContextStrokePath(context);
774 #endif
775
776     if ( !m_isFlipped )
777     {
778         CGContextTranslateCTM( context, 0,  [m_osxView bounds].size.height );
779         CGContextScaleCTM( context, 1, -1 );
780     }
781     
782     wxRegion updateRgn;
783     const NSRect *rects;
784     NSInteger count;
785
786     [slf getRectsBeingDrawn:&rects count:&count];
787     for ( int i = 0 ; i < count ; ++i )
788     {
789         updateRgn.Union(wxFromNSRect(slf, rects[i]) );
790     }
791
792     wxWindow* wxpeer = GetWXPeer();
793     wxpeer->GetUpdateRegion() = updateRgn;
794     wxpeer->MacSetCGContextRef( context );
795     
796     bool handled = wxpeer->MacDoRedraw( 0 );
797             
798     CGContextRestoreGState( context );
799
800     CGContextSaveGState( context );
801     if ( !handled )
802     {
803         // call super
804         SEL _cmd = @selector(drawRect:);
805         wxOSX_DrawRectHandlerPtr superimpl = (wxOSX_DrawRectHandlerPtr) [[slf superclass] instanceMethodForSelector:_cmd];
806         superimpl(slf, _cmd, *(NSRect*)rect);
807         CGContextRestoreGState( context );
808         CGContextSaveGState( context );
809     }
810     wxpeer->MacPaintChildrenBorders();
811     wxpeer->MacSetCGContextRef( NULL );
812     CGContextRestoreGState( context );
813 }
814
815 void wxWidgetCocoaImpl::controlAction( WXWidget slf, void *_cmd, void *sender)
816 {
817     wxWindow* wxpeer = (wxWindow*) GetWXPeer();
818     if ( wxpeer )
819         wxpeer->OSXHandleClicked(0);
820 }
821
822 void wxWidgetCocoaImpl::controlDoubleAction( WXWidget slf, void *_cmd, void *sender)
823 {
824 }
825
826 // 
827
828 #if OBJC_API_VERSION >= 2
829
830 #define wxOSX_CLASS_ADD_METHOD( c, s, i, t ) \
831     class_addMethod(c, s, i, t );
832
833 #else
834
835 #define wxOSX_CLASS_ADD_METHOD( c, s, i, t ) \
836     { s, t, i },
837
838 #endif
839
840 void wxOSXCocoaClassAddWXMethods(Class c)
841 {
842
843 #if OBJC_API_VERSION < 2
844     static objc_method wxmethods[] =
845     {
846 #endif
847
848     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
849     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
850     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseDown:), (IMP) wxOSX_mouseEvent, "v@:@" )
851
852     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
853     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
854     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseUp:), (IMP) wxOSX_mouseEvent, "v@:@" )
855
856     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseMoved:), (IMP) wxOSX_mouseEvent, "v@:@" )
857
858     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
859     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
860     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
861
862     wxOSX_CLASS_ADD_METHOD(c, @selector(scrollWheel:), (IMP) wxOSX_mouseEvent, "v@:@" )
863     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseEntered:), (IMP) wxOSX_mouseEvent, "v@:@" )
864     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseExited:), (IMP) wxOSX_mouseEvent, "v@:@" )
865     
866     wxOSX_CLASS_ADD_METHOD(c, @selector(keyDown:), (IMP) wxOSX_keyEvent, "v@:@" )
867     wxOSX_CLASS_ADD_METHOD(c, @selector(keyUp:), (IMP) wxOSX_keyEvent, "v@:@" )
868     wxOSX_CLASS_ADD_METHOD(c, @selector(flagsChanged:), (IMP) wxOSX_keyEvent, "v@:@" )
869     
870     wxOSX_CLASS_ADD_METHOD(c, @selector(insertText:), (IMP) wxOSX_insertText, "v@:@" )
871
872     wxOSX_CLASS_ADD_METHOD(c, @selector(performKeyEquivalent:), (IMP) wxOSX_performKeyEquivalent, "v@:@" )
873
874
875     wxOSX_CLASS_ADD_METHOD(c, @selector(becomeFirstResponder), (IMP) wxOSX_becomeFirstResponder, "c@:" )
876     wxOSX_CLASS_ADD_METHOD(c, @selector(resignFirstResponder), (IMP) wxOSX_resignFirstResponder, "c@:" )
877     wxOSX_CLASS_ADD_METHOD(c, @selector(resetCursorRects), (IMP) wxOSX_resetCursorRects, "v@:" )
878
879     wxOSX_CLASS_ADD_METHOD(c, @selector(isFlipped), (IMP) wxOSX_isFlipped, "c@:" )
880     wxOSX_CLASS_ADD_METHOD(c, @selector(drawRect:), (IMP) wxOSX_drawRect, "v@:{_NSRect={_NSPoint=ff}{_NSSize=ff}}" )
881
882     wxOSX_CLASS_ADD_METHOD(c, @selector(controlAction:), (IMP) wxOSX_controlAction, "v@:@" )
883     wxOSX_CLASS_ADD_METHOD(c, @selector(controlDoubleAction:), (IMP) wxOSX_controlDoubleAction, "v@:@" )
884
885 #if wxUSE_DRAG_AND_DROP
886     wxOSX_CLASS_ADD_METHOD(c, @selector(draggingEntered:), (IMP) wxOSX_draggingEntered, "I@:@" )
887     wxOSX_CLASS_ADD_METHOD(c, @selector(draggingUpdated:), (IMP) wxOSX_draggingUpdated, "I@:@" )
888     wxOSX_CLASS_ADD_METHOD(c, @selector(draggingExited:), (IMP) wxOSX_draggingExited, "v@:@" )
889     wxOSX_CLASS_ADD_METHOD(c, @selector(performDragOperation:), (IMP) wxOSX_performDragOperation, "c@:@" )
890 #endif     
891         
892 #if OBJC_API_VERSION < 2
893     } ;
894     static int method_count = WXSIZEOF( wxmethods );
895     static objc_method_list *wxmethodlist = NULL;
896     if ( wxmethodlist == NULL )
897     {
898         wxmethodlist = (objc_method_list*) malloc(sizeof(objc_method_list) + sizeof(wxmethods) );
899         memcpy( &wxmethodlist->method_list[0], &wxmethods[0], sizeof(wxmethods) );
900         wxmethodlist->method_count = method_count;
901         wxmethodlist->obsolete = 0;
902     }
903     class_addMethods( c, wxmethodlist );
904 #endif
905 }
906
907 //
908 // C++ implementation class
909 //
910
911 IMPLEMENT_DYNAMIC_CLASS( wxWidgetCocoaImpl , wxWidgetImpl )
912
913 wxWidgetCocoaImpl::wxWidgetCocoaImpl( wxWindowMac* peer , WXWidget w, bool isRootControl ) :
914     wxWidgetImpl( peer, isRootControl )
915 {
916     Init();
917     m_osxView = w;
918 }
919
920 wxWidgetCocoaImpl::wxWidgetCocoaImpl() 
921 {
922     Init();
923 }
924
925 void wxWidgetCocoaImpl::Init()
926 {
927     m_osxView = NULL;
928     m_isFlipped = true;
929     m_lastKeyDownEvent = NULL;
930 }
931
932 wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
933 {
934     RemoveAssociations( this );
935
936     if ( !IsRootControl() )
937     {
938         NSView *sv = [m_osxView superview];
939         if ( sv != nil )
940             [m_osxView removeFromSuperview];
941     }
942     [m_osxView release];
943 }
944     
945 bool wxWidgetCocoaImpl::IsVisible() const 
946 {
947     return [m_osxView isHiddenOrHasHiddenAncestor] == NO;
948 }
949
950 void wxWidgetCocoaImpl::SetVisibility( bool visible )
951 {
952     [m_osxView setHidden:(visible ? NO:YES)];
953 }
954
955 void wxWidgetCocoaImpl::Raise()
956 {
957 }
958     
959 void wxWidgetCocoaImpl::Lower()
960 {
961 }
962
963 void wxWidgetCocoaImpl::ScrollRect( const wxRect *rect, int dx, int dy )
964 {
965 #if 1
966     SetNeedsDisplay() ;
967 #else
968     // We should do something like this, but it wasn't working in 10.4.
969     if (GetNeedsDisplay() )
970     {
971         SetNeedsDisplay() ;
972     }
973     NSRect r = wxToNSRect( [m_osxView superview], *rect );
974     NSSize offset = NSMakeSize((float)dx, (float)dy);
975     [m_osxView scrollRect:r by:offset];
976 #endif
977 }
978
979 void wxWidgetCocoaImpl::Move(int x, int y, int width, int height)
980 {
981     wxWindowMac* parent = GetWXPeer()->GetParent();
982     // under Cocoa we might have a contentView in the wxParent to which we have to 
983     // adjust the coordinates
984     if (parent)
985     {
986         int cx = 0,cy = 0,cw = 0,ch = 0;
987         if ( parent->GetPeer() )
988         {
989             parent->GetPeer()->GetContentArea(cx, cy, cw, ch);
990             x -= cx;
991             y -= cy;
992         }
993     }
994     NSRect r = wxToNSRect( [m_osxView superview], wxRect(x,y,width, height) );
995     [m_osxView setFrame:r];
996     
997     if ([m_osxView respondsToSelector:@selector(trackingTag)] )
998     {
999         if ( [(wxNSView*)m_osxView trackingTag] )
1000             [m_osxView removeTrackingRect: [(wxNSView*)m_osxView trackingTag]];
1001         
1002         [(wxNSView*)m_osxView setTrackingTag: [m_osxView addTrackingRect: [m_osxView bounds] owner: m_osxView userData: nil assumeInside: NO]];
1003     }
1004 }
1005
1006 void wxWidgetCocoaImpl::GetPosition( int &x, int &y ) const
1007 {
1008     wxRect r = wxFromNSRect( [m_osxView superview], [m_osxView frame] );
1009     x = r.GetLeft();
1010     y = r.GetTop();
1011 }
1012
1013 void wxWidgetCocoaImpl::GetSize( int &width, int &height ) const
1014 {
1015     NSRect rect = [m_osxView frame];
1016     width = rect.size.width;
1017     height = rect.size.height;
1018 }
1019
1020 void wxWidgetCocoaImpl::GetContentArea( int&left, int &top, int &width, int &height ) const
1021 {
1022     if ( [m_osxView respondsToSelector:@selector(contentView) ] )
1023     {
1024         NSView* cv = [m_osxView contentView];
1025      
1026         NSRect bounds = [m_osxView bounds];
1027         NSRect rect = [cv frame];
1028         
1029         int y = rect.origin.y;
1030         int x = rect.origin.x;
1031         if ( ![ m_osxView isFlipped ] )
1032             y = bounds.size.height - (rect.origin.y + rect.size.height);
1033         left = x;
1034         top = y;
1035         width = rect.size.width;
1036         height = rect.size.height;
1037     }
1038     else
1039     {
1040         left = top = 0;
1041         GetSize( width, height );
1042     }
1043 }
1044
1045 void wxWidgetCocoaImpl::SetNeedsDisplay( const wxRect* where )
1046 {
1047     if ( where )
1048         [m_osxView setNeedsDisplayInRect:wxToNSRect(m_osxView, *where )];
1049     else
1050         [m_osxView setNeedsDisplay:YES];
1051 }
1052
1053 bool wxWidgetCocoaImpl::GetNeedsDisplay() const
1054 {
1055     return [m_osxView needsDisplay];
1056 }
1057
1058 bool wxWidgetCocoaImpl::CanFocus() const
1059 {
1060     return [m_osxView canBecomeKeyView] == YES;
1061 }
1062
1063 bool wxWidgetCocoaImpl::HasFocus() const
1064 {
1065     return ( [[m_osxView window] firstResponder] == m_osxView );
1066 }
1067
1068 bool wxWidgetCocoaImpl::SetFocus() 
1069 {
1070     if ( [m_osxView canBecomeKeyView] == NO )
1071         return false;
1072         
1073     [[m_osxView window] makeFirstResponder: m_osxView] ;
1074     return true;
1075 }
1076
1077
1078 void wxWidgetCocoaImpl::RemoveFromParent()
1079 {
1080     [m_osxView removeFromSuperview];
1081 }
1082
1083 void wxWidgetCocoaImpl::Embed( wxWidgetImpl *parent )
1084 {
1085     NSView* container = parent->GetWXWidget() ;
1086     wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
1087     [container addSubview:m_osxView];
1088 }
1089
1090 void wxWidgetCocoaImpl::SetBackgroundColour( const wxColour &WXUNUSED(col) )
1091 {
1092     // m_osxView.backgroundColor = [[UIColor alloc] initWithCGColor:col.GetCGColor()];
1093 }
1094
1095 void wxWidgetCocoaImpl::SetLabel( const wxString& title, wxFontEncoding encoding )
1096 {
1097     if ( [m_osxView respondsToSelector:@selector(setTitle:) ] )
1098     {
1099         wxCFStringRef cf( title , m_wxPeer->GetFont().GetEncoding() );
1100         [m_osxView setTitle:cf.AsNSString()];
1101     }
1102     else if ( [m_osxView respondsToSelector:@selector(setStringValue:) ] )
1103     {
1104         wxCFStringRef cf( title , m_wxPeer->GetFont().GetEncoding() );
1105         [m_osxView setStringValue:cf.AsNSString()];
1106     }
1107 }
1108     
1109
1110 void  wxWidgetImpl::Convert( wxPoint *pt , wxWidgetImpl *from , wxWidgetImpl *to )
1111 {
1112     NSPoint p = wxToNSPoint( from->GetWXWidget(), *pt );
1113     p = [from->GetWXWidget() convertPoint:p toView:to->GetWXWidget() ]; 
1114     *pt = wxFromNSPoint( to->GetWXWidget(), p );
1115 }
1116
1117 wxInt32 wxWidgetCocoaImpl::GetValue() const 
1118 {
1119     return [(NSControl*)m_osxView intValue];
1120 }
1121
1122 void wxWidgetCocoaImpl::SetValue( wxInt32 v ) 
1123 {
1124     if (  [m_osxView respondsToSelector:@selector(setIntValue:)] )
1125     {
1126         [m_osxView setIntValue:v];
1127     }
1128     else if (  [m_osxView respondsToSelector:@selector(setFloatValue:)] )
1129     {
1130         [m_osxView setFloatValue:(double)v];
1131     }
1132     else if (  [m_osxView respondsToSelector:@selector(setDoubleValue:)] )
1133     {
1134         [m_osxView setDoubleValue:(double)v];
1135     }
1136 }
1137
1138 void wxWidgetCocoaImpl::SetMinimum( wxInt32 v ) 
1139 {
1140     if (  [m_osxView respondsToSelector:@selector(setMinValue:)] )
1141     {
1142         [m_osxView setMinValue:(double)v];
1143     }
1144 }
1145
1146 void wxWidgetCocoaImpl::SetMaximum( wxInt32 v ) 
1147 {
1148     if (  [m_osxView respondsToSelector:@selector(setMaxValue:)] )
1149     {
1150         [m_osxView setMaxValue:(double)v];
1151     }
1152 }
1153
1154 wxInt32 wxWidgetCocoaImpl::GetMinimum() const 
1155 {
1156     if (  [m_osxView respondsToSelector:@selector(getMinValue:)] )
1157     {
1158         return [m_osxView minValue];
1159     }
1160     return 0;
1161 }
1162
1163 wxInt32 wxWidgetCocoaImpl::GetMaximum() const 
1164 {
1165     if (  [m_osxView respondsToSelector:@selector(getMaxValue:)] )
1166     {
1167         return [m_osxView maxValue];
1168     }
1169     return 0;
1170 }
1171
1172 void wxWidgetCocoaImpl::SetBitmap( const wxBitmap& bitmap )
1173 {
1174     if (  [m_osxView respondsToSelector:@selector(setImage:)] )
1175     {
1176         [m_osxView setImage:bitmap.GetNSImage()];
1177     }
1178 }
1179
1180 void wxWidgetCocoaImpl::SetupTabs( const wxNotebook& notebook)
1181 {
1182     // implementation in subclass
1183 }
1184
1185 void wxWidgetCocoaImpl::GetBestRect( wxRect *r ) const
1186 {
1187     r->x = r->y = r->width = r->height = 0;
1188 //    if (  [m_osxView isKindOfClass:[NSControl class]] )
1189     if (  [m_osxView respondsToSelector:@selector(sizeToFit)] )
1190     {
1191         NSRect former = [m_osxView frame];
1192         [m_osxView sizeToFit];
1193         NSRect best = [m_osxView frame];
1194         [m_osxView setFrame:former];
1195         r->width = best.size.width;
1196         r->height = best.size.height;
1197     }
1198 }
1199
1200 bool wxWidgetCocoaImpl::IsEnabled() const
1201 {
1202     if ( [m_osxView respondsToSelector:@selector(isEnabled) ] )
1203         return [m_osxView isEnabled];
1204     return true;
1205 }
1206
1207 void wxWidgetCocoaImpl::Enable( bool enable )
1208 {
1209     if ( [m_osxView respondsToSelector:@selector(setEnabled:) ] )
1210         [m_osxView setEnabled:enable];
1211 }
1212
1213 void wxWidgetCocoaImpl::PulseGauge()
1214 {
1215 }
1216
1217 void wxWidgetCocoaImpl::SetScrollThumb( wxInt32 val, wxInt32 view )
1218 {
1219 }
1220
1221 void wxWidgetCocoaImpl::SetControlSize( wxWindowVariant variant ) 
1222 {
1223     NSControlSize size = NSRegularControlSize;
1224     
1225     switch ( variant )
1226     {
1227         case wxWINDOW_VARIANT_NORMAL :
1228             size = NSRegularControlSize;
1229             break ;
1230
1231         case wxWINDOW_VARIANT_SMALL :
1232             size = NSSmallControlSize;
1233             break ;
1234
1235         case wxWINDOW_VARIANT_MINI :
1236             size = NSMiniControlSize;
1237             break ;
1238
1239         case wxWINDOW_VARIANT_LARGE :
1240             size = NSRegularControlSize;
1241             break ;
1242
1243         default:
1244             wxFAIL_MSG(_T("unexpected window variant"));
1245             break ;
1246     }
1247     if ( [m_osxView respondsToSelector:@selector(setControlSize:)] )
1248         [m_osxView setControlSize:size];
1249 }
1250
1251 void wxWidgetCocoaImpl::SetFont(wxFont const&, wxColour const&, long, bool)
1252 {
1253     // TODO
1254 }
1255
1256 void wxWidgetCocoaImpl::InstallEventHandler( WXWidget control )
1257 {
1258     WXWidget c =  control ? control : (WXWidget) m_osxView;
1259     wxWidgetImpl::Associate( c, this ) ;
1260     if ([c respondsToSelector:@selector(setAction:)])
1261     {
1262         [c setTarget: c];
1263         [c setAction: @selector(controlAction:)];
1264         if ([c respondsToSelector:@selector(setDoubleAction:)])
1265         {
1266             [c setDoubleAction: @selector(controlDoubleAction:)];
1267         }
1268         
1269     }
1270 }
1271
1272 static bool g_inKeyEvent = false;
1273
1274 bool wxWidgetCocoaImpl::DoHandleCharEvent(NSEvent *event, NSString *text)
1275 {
1276     wxKeyEvent wxevent(wxEVT_KEY_DOWN);
1277     SetupKeyEvent( wxevent, event, text );
1278     
1279     wxevent.SetEventType(wxEVT_CHAR);
1280
1281     return GetWXPeer()->OSXHandleKeyEvent(wxevent);
1282 }
1283
1284 bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event)
1285 {
1286     wxASSERT_MSG(!g_inKeyEvent, "Re-entering key handler...\n");
1287     g_inKeyEvent = true;
1288     wxKeyEvent wxevent(wxEVT_KEY_DOWN);
1289     SetupKeyEvent( wxevent, event );
1290     
1291     bool result = GetWXPeer()->OSXHandleKeyEvent(wxevent);
1292
1293     // this will fire higher level events, like insertText, to help
1294     // us handle EVT_CHAR, etc.
1295     if ([event type] == NSKeyDown)
1296     {
1297         m_lastKeyDownEvent = event;
1298         [m_osxView interpretKeyEvents:[NSArray arrayWithObject:event]];
1299     }
1300     g_inKeyEvent = false;
1301     return result;
1302 }
1303
1304 bool wxWidgetCocoaImpl::DoHandleMouseEvent(NSEvent *event)
1305 {
1306     NSPoint clickLocation; 
1307     clickLocation = [m_osxView convertPoint:[event locationInWindow] fromView:nil]; 
1308     wxPoint pt = wxFromNSPoint( m_osxView, clickLocation );
1309     wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
1310     SetupMouseEvent( wxevent , event ) ;
1311     wxevent.m_x = pt.x;
1312     wxevent.m_y = pt.y;
1313
1314     return GetWXPeer()->HandleWindowEvent(wxevent);
1315 }
1316
1317 void wxWidgetCocoaImpl::DoNotifyFocusEvent(bool receivedFocus)
1318 {
1319     wxWindow* thisWindow = GetWXPeer();
1320     if ( thisWindow->MacGetTopLevelWindow() && NeedsFocusRect() )
1321     {
1322         thisWindow->MacInvalidateBorders();
1323     }
1324
1325     if ( receivedFocus )
1326     {
1327         wxLogTrace(_T("Focus"), _T("focus set(%p)"), static_cast<void*>(thisWindow));
1328         wxChildFocusEvent eventFocus((wxWindow*)thisWindow);
1329         thisWindow->HandleWindowEvent(eventFocus);
1330
1331 #if wxUSE_CARET
1332         if ( thisWindow->GetCaret() )
1333             thisWindow->GetCaret()->OnSetFocus();
1334 #endif
1335
1336         wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId());
1337         event.SetEventObject(thisWindow);
1338         // TODO how to find out the targetFocusWindow ?
1339         // event.SetWindow(targetFocusWindow);
1340         thisWindow->HandleWindowEvent(event) ;
1341     }
1342     else // !receivedFocuss
1343     {
1344 #if wxUSE_CARET
1345         if ( thisWindow->GetCaret() )
1346             thisWindow->GetCaret()->OnKillFocus();
1347 #endif
1348
1349         wxLogTrace(_T("Focus"), _T("focus lost(%p)"), static_cast<void*>(thisWindow));
1350                     
1351         wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId());
1352         event.SetEventObject(thisWindow);
1353         // TODO how to find out the targetFocusWindow ?
1354         // event.SetWindow(targetFocusWindow);
1355         thisWindow->HandleWindowEvent(event) ;
1356     }
1357 }
1358
1359 void wxWidgetCocoaImpl::SetCursor(const wxCursor& cursor)
1360 {
1361     NSPoint location = [NSEvent mouseLocation];
1362     location = [[m_osxView window] convertScreenToBase:location];
1363     NSPoint locationInView = [m_osxView convertPoint:location fromView:nil];
1364
1365     if( NSMouseInRect(locationInView, [m_osxView bounds], YES) )
1366     {
1367         [(NSCursor*)cursor.GetHCURSOR() set];
1368     }
1369     [[m_osxView window] invalidateCursorRectsForView:m_osxView];
1370 }
1371
1372 void wxWidgetCocoaImpl::CaptureMouse()
1373 {
1374     [[m_osxView window] disableCursorRects];
1375 }
1376
1377 void wxWidgetCocoaImpl::ReleaseMouse()
1378 {
1379     [[m_osxView window] enableCursorRects];
1380 }
1381
1382 void wxWidgetCocoaImpl::SetFlipped(bool flipped)
1383 {
1384     m_isFlipped = flipped;
1385 }
1386
1387 //
1388 // Factory methods
1389 //
1390
1391 wxWidgetImpl* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, wxWindowMac* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
1392                             long style, long extraStyle)
1393 {
1394     NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
1395     wxNSView* v = [[wxNSView alloc] initWithFrame:r];
1396
1397     // temporary hook for dnd
1398     [v registerForDraggedTypes:[NSArray arrayWithObjects:
1399         NSStringPboardType, NSFilenamesPboardType, NSTIFFPboardType, NSPICTPboardType, NSPDFPboardType, nil]];
1400         
1401     wxWidgetCocoaImpl* c = new wxWidgetCocoaImpl( wxpeer, v );
1402     return c;
1403 }
1404
1405 wxWidgetImpl* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now ) 
1406 {
1407     NSWindow* tlw = now->GetWXWindow();
1408     wxNSView* v = [[wxNSView alloc] initWithFrame:[[tlw contentView] frame]];
1409     wxWidgetCocoaImpl* c = new wxWidgetCocoaImpl( now, v, true );
1410     c->InstallEventHandler();
1411     [tlw setContentView:v];
1412     return c;
1413 }