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