]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/cocoa/window.mm
Since wxDialog::Show(false) only calls wxWindow::Show, we must explicitly hide the...
[wxWidgets.git] / src / osx / cocoa / window.mm
index fed5b07659fc780a6786835a482d8013a7756440..a2aea90d23c464a829abe7167a13cd2301428b27 100644 (file)
     #include "wx/dcclient.h"
     #include "wx/nonownedwnd.h"
     #include "wx/log.h"
+    #include "wx/textctrl.h"
 #endif
 
 #ifdef __WXMAC__
     #include "wx/osx/private.h"
 #endif
 
+#include "wx/evtloop.h"
+
 #if wxUSE_CARET
     #include "wx/caret.h"
 #endif
     #include "wx/dnd.h"
 #endif
 
+#if wxUSE_TOOLTIPS
+    #include "wx/tooltip.h"
+#endif
+
 #include <objc/objc-runtime.h>
 
 // Get the window with the focus
@@ -38,7 +45,7 @@ NSView* GetViewFromResponder( NSResponder* responder )
     NSView* view = nil;
     if ( [responder isKindOfClass:[NSTextView class]] )
     {
-        NSView* delegate =  [(NSTextView*)responder delegate];
+        NSView* delegate = (NSView*) [(NSTextView*)responder delegate];
         if ( [delegate isKindOfClass:[NSTextField class] ] )
             view = delegate;
         else
@@ -80,11 +87,20 @@ NSRect wxOSXGetFrameForControl( wxWindowMac* window , const wxPoint& pos , const
 @interface wxNSView : NSView
 {
     NSTrackingRectTag rectTag;
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
+    NSTrackingArea* _trackingArea;
+#endif
 }
 
 // the tracking tag is needed to track mouse enter / exit events
 - (void) setTrackingTag: (NSTrackingRectTag)tag;
 - (NSTrackingRectTag) trackingTag;
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
+// under 10.5 we can also track mouse moved events on non-focused windows if
+// we use the new NSTrackingArea APIs. 
+- (void) updateTrackingArea;
+- (NSTrackingArea*) trackingArea;
+#endif
 @end // wxNSView
 
 @interface NSView(PossibleMethods)
@@ -114,6 +130,8 @@ NSRect wxOSXGetFrameForControl( wxWindowMac* window , const wxPoint& pos , const
 - (void)setTarget:(id)anObject;
 - (void)setAction:(SEL)aSelector;
 - (void)setDoubleAction:(SEL)aSelector;
+- (void)setBackgroundColor:(NSColor*)aColor;
+- (void)setImagePosition:(NSCellImagePosition)aPosition;
 @end
 
 long wxOSXTranslateCocoaKey( NSEvent* event )
@@ -271,7 +289,7 @@ long wxOSXTranslateCocoaKey( NSEvent* event )
     return retval;
 }
 
-void SetupKeyEvent( wxKeyEvent &wxevent , NSEvent * nsEvent, NSString* charString = NULL )
+void wxWidgetCocoaImpl::SetupKeyEvent(wxKeyEvent &wxevent , NSEvent * nsEvent, NSString* charString)
 {
     UInt32 modifiers = [nsEvent modifierFlags] ;
     int eventType = [nsEvent type];
@@ -289,7 +307,7 @@ void SetupKeyEvent( wxKeyEvent &wxevent , NSEvent * nsEvent, NSString* charStrin
     wxString chars;
     if ( eventType != NSFlagsChanged )
     {
-        NSString* nschars = (wxevent.GetEventType() != wxEVT_CHAR) ? [nsEvent charactersIgnoringModifiers] : [nsEvent characters];
+        NSString* nschars = [nsEvent charactersIgnoringModifiers];
         if ( charString )
         {
             // if charString is set, it did not come from key up / key down
@@ -350,12 +368,27 @@ void SetupKeyEvent( wxKeyEvent &wxevent , NSEvent * nsEvent, NSString* charStrin
     wxevent.m_uniChar = aunichar;
 #endif
     wxevent.m_keyCode = keyval;
+
+    wxWindowMac* peer = GetWXPeer();
+    if ( peer )
+    {
+        wxevent.SetEventObject(peer);
+        wxevent.SetId(peer->GetId()) ;
+    }
 }
 
 UInt32 g_lastButton = 0 ;
 bool g_lastButtonWasFakeRight = false ;
 
-void SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
+// better scroll wheel support 
+// see http://lists.apple.com/archives/cocoa-dev/2007/Feb/msg00050.html
+
+@interface NSEvent (DeviceDelta)
+- (float)deviceDeltaX;
+- (float)deviceDeltaY;
+@end
+
+void wxWidgetCocoaImpl::SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
 {
     int eventType = [nsEvent type];
     UInt32 modifiers = [nsEvent modifierFlags] ;
@@ -488,19 +521,43 @@ void SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
 
      case NSScrollWheel :
         {
+            float deltaX = 0.0;
+            float deltaY = 0.0;
+
             wxevent.SetEventType( wxEVT_MOUSEWHEEL ) ;
+
+            // see http://developer.apple.com/qa/qa2005/qa1453.html
+            // for more details on why we have to look for the exact type
+            
+            const EventRef cEvent = (EventRef) [nsEvent eventRef];
+            bool isMouseScrollEvent = false;
+            if ( cEvent )
+                isMouseScrollEvent = ::GetEventKind(cEvent) == kEventMouseScroll;
+                
+            if ( isMouseScrollEvent )
+            {
+                deltaX = [nsEvent deviceDeltaX];
+                deltaY = [nsEvent deviceDeltaY];
+            }
+            else
+            {
+                deltaX = ([nsEvent deltaX] * 10);
+                deltaY = ([nsEvent deltaY] * 10);
+            }
+            
             wxevent.m_wheelDelta = 10;
             wxevent.m_linesPerAction = 1;
-
-            if ( fabs([nsEvent deltaX]) > fabs([nsEvent deltaY]) )
+                
+            if ( fabs(deltaX) > fabs(deltaY) )
             {
                 wxevent.m_wheelAxis = 1;
-                wxevent.m_wheelRotation = (int)([nsEvent deltaX] * 10);
+                wxevent.m_wheelRotation = (int)deltaX;
             }
             else
             {
-                wxevent.m_wheelRotation = (int)([nsEvent deltaY] * 10);
+                wxevent.m_wheelRotation = (int)deltaY;
             }
+
         }
         break ;
 
@@ -521,7 +578,12 @@ void SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
     }
 
     wxevent.m_clickCount = clickCount;
-
+    wxWindowMac* peer = GetWXPeer();
+    if ( peer )
+    {
+        wxevent.SetEventObject(peer);
+        wxevent.SetId(peer->GetId()) ;
+    }
 }
 
 @implementation wxNSView
@@ -546,6 +608,28 @@ void SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
     return rectTag;
 }
 
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
+- (void) updateTrackingArea
+{
+    if (_trackingArea)
+    {
+        [self removeTrackingArea: _trackingArea];
+        [_trackingArea release];
+    }
+    
+    NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited|NSTrackingMouseMoved|NSTrackingActiveAlways;
+        
+    NSTrackingArea* area = [[NSTrackingArea alloc] initWithRect: [self bounds] options: options owner: self userInfo: nil];
+    [self addTrackingArea: area];
+
+    _trackingArea = area;
+}
+
+- (NSTrackingArea*) trackingArea
+{
+    return _trackingArea;
+}
+#endif
 @end // wxNSView
 
 //
@@ -604,6 +688,13 @@ void wxOSX_mouseEvent(NSView* self, SEL _cmd, NSEvent *event)
     impl->mouseEvent(event, self, _cmd);
 }
 
+BOOL wxOSX_acceptsFirstMouse(NSView* self, SEL _cmd, NSEvent *event)
+{
+    // This is needed to support click through, otherwise the first click on a window
+    // will not do anything unless it is the active window already.
+    return YES;
+}
+
 void wxOSX_keyEvent(NSView* self, SEL _cmd, NSEvent *event)
 {
     wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
@@ -793,7 +884,7 @@ unsigned int wxWidgetCocoaImpl::draggingUpdated(void* s, WXWidget WXUNUSED(slf),
         result = wxDragCopy;
     else if ( sourceDragMask & NSDragOperationMove )
         result = wxDragMove;
-
+    
     PasteboardRef pboardRef;
     PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
     target->SetCurrentDragPasteboard(pboardRef);
@@ -869,11 +960,14 @@ void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
 
 void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
 {
+    if ( [event type] == NSKeyDown )
+        m_lastKeyDownEvent = event;
     if ( GetFocusedViewInWindow([slf window]) != slf || m_hasEditor || !DoHandleKeyEvent(event) )
     {
         wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
         superimpl(slf, (SEL)_cmd, event);
     }
+    m_lastKeyDownEvent = NULL;
 }
 
 void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd)
@@ -883,7 +977,6 @@ void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd)
         wxOSX_TextEventHandlerPtr superimpl = (wxOSX_TextEventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
         superimpl(slf, (SEL)_cmd, text);
     }
-    m_lastKeyDownEvent = NULL;
 }
 
 
@@ -1035,6 +1128,18 @@ void wxWidgetCocoaImpl::controlDoubleAction( WXWidget WXUNUSED(slf), void *WXUNU
 {
 }
 
+void wxWidgetCocoaImpl::controlTextDidChange()
+{
+    wxWindow* wxpeer = (wxWindow*)GetWXPeer();
+    if ( wxpeer ) 
+    {
+        wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, wxpeer->GetId());
+        event.SetEventObject( wxpeer );
+        event.SetString( static_cast<wxTextCtrl*>(wxpeer)->GetValue() );
+        wxpeer->HandleWindowEvent( event );
+    }
+}
+
 //
 
 #if OBJC_API_VERSION >= 2
@@ -1070,6 +1175,8 @@ void wxOSXCocoaClassAddWXMethods(Class c)
     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
     wxOSX_CLASS_ADD_METHOD(c, @selector(rightMouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
     wxOSX_CLASS_ADD_METHOD(c, @selector(otherMouseDragged:), (IMP) wxOSX_mouseEvent, "v@:@" )
+    
+    wxOSX_CLASS_ADD_METHOD(c, @selector(acceptsFirstMouse:), (IMP) wxOSX_acceptsFirstMouse, "v@:@" )
 
     wxOSX_CLASS_ADD_METHOD(c, @selector(scrollWheel:), (IMP) wxOSX_mouseEvent, "v@:@" )
     wxOSX_CLASS_ADD_METHOD(c, @selector(mouseEntered:), (IMP) wxOSX_mouseEvent, "v@:@" )
@@ -1127,6 +1234,11 @@ wxWidgetCocoaImpl::wxWidgetCocoaImpl( wxWindowMac* peer , WXWidget w, bool isRoo
 {
     Init();
     m_osxView = w;
+
+    // check if the user wants to create the control initially hidden
+    if ( !peer->IsShown() )
+        SetVisibility(false);
+
     // gc aware handling
     if ( m_osxView )
         CFRetain(m_osxView);
@@ -1171,6 +1283,242 @@ void wxWidgetCocoaImpl::SetVisibility( bool visible )
     [m_osxView setHidden:(visible ? NO:YES)];
 }
 
+// ----------------------------------------------------------------------------
+// window animation stuff
+// ----------------------------------------------------------------------------
+
+// define a delegate used to refresh the window during animation
+@interface wxNSAnimationDelegate : NSObject wxOSX_10_6_AND_LATER(<NSAnimationDelegate>)
+{
+    wxWindow *m_win;
+    bool m_isDone;
+}
+
+- (id)init:(wxWindow *)win;
+
+- (bool)isDone;
+
+// NSAnimationDelegate methods
+- (void)animationDidEnd:(NSAnimation*)animation;
+- (void)animation:(NSAnimation*)animation
+        didReachProgressMark:(NSAnimationProgress)progress;
+@end
+
+@implementation wxNSAnimationDelegate
+
+- (id)init:(wxWindow *)win
+{
+    [super init];
+
+    m_win = win;
+    m_isDone = false;
+
+    return self;
+}
+
+- (bool)isDone
+{
+    return m_isDone;
+}
+
+- (void)animation:(NSAnimation*)animation
+        didReachProgressMark:(NSAnimationProgress)progress
+{
+    wxUnusedVar(animation);
+    wxUnusedVar(progress);
+
+    m_win->SendSizeEvent();
+}
+
+- (void)animationDidEnd:(NSAnimation*)animation
+{
+    m_isDone = true;
+}
+
+@end
+
+/* static */
+bool
+wxWidgetCocoaImpl::ShowViewOrWindowWithEffect(wxWindow *win,
+                                              bool show,
+                                              wxShowEffect effect,
+                                              unsigned timeout)
+{
+    // create the dictionary describing the animation to perform on this view
+    NSObject * const
+        viewOrWin = static_cast<NSObject *>(win->OSXGetViewOrWindow());
+    NSMutableDictionary * const
+        dict = [NSMutableDictionary dictionaryWithCapacity:4];
+    [dict setObject:viewOrWin forKey:NSViewAnimationTargetKey];
+
+    // determine the start and end rectangles assuming we're hiding the window
+    const wxRect rectOrig = win->GetRect();
+    wxRect rectStart,
+           rectEnd;
+    rectStart =
+    rectEnd = rectOrig;
+
+    if ( show )
+    {
+        if ( effect == wxSHOW_EFFECT_ROLL_TO_LEFT ||
+                effect == wxSHOW_EFFECT_SLIDE_TO_LEFT )
+            effect = wxSHOW_EFFECT_ROLL_TO_RIGHT;
+        else if ( effect == wxSHOW_EFFECT_ROLL_TO_RIGHT ||
+                    effect == wxSHOW_EFFECT_SLIDE_TO_RIGHT )
+            effect = wxSHOW_EFFECT_ROLL_TO_LEFT;
+        else if ( effect == wxSHOW_EFFECT_ROLL_TO_TOP ||
+                    effect == wxSHOW_EFFECT_SLIDE_TO_TOP )
+            effect = wxSHOW_EFFECT_ROLL_TO_BOTTOM;
+        else if ( effect == wxSHOW_EFFECT_ROLL_TO_BOTTOM ||
+                    effect == wxSHOW_EFFECT_SLIDE_TO_BOTTOM )
+            effect = wxSHOW_EFFECT_ROLL_TO_TOP;
+    }
+
+    switch ( effect )
+    {
+        case wxSHOW_EFFECT_ROLL_TO_LEFT:
+        case wxSHOW_EFFECT_SLIDE_TO_LEFT:
+            rectEnd.width = 0;
+            break;
+
+        case wxSHOW_EFFECT_ROLL_TO_RIGHT:
+        case wxSHOW_EFFECT_SLIDE_TO_RIGHT:
+            rectEnd.x = rectStart.GetRight();
+            rectEnd.width = 0;
+            break;
+
+        case wxSHOW_EFFECT_ROLL_TO_TOP:
+        case wxSHOW_EFFECT_SLIDE_TO_TOP:
+            rectEnd.height = 0;
+            break;
+
+        case wxSHOW_EFFECT_ROLL_TO_BOTTOM:
+        case wxSHOW_EFFECT_SLIDE_TO_BOTTOM:
+            rectEnd.y = rectStart.GetBottom();
+            rectEnd.height = 0;
+            break;
+
+        case wxSHOW_EFFECT_EXPAND:
+            rectEnd.x = rectStart.x + rectStart.width / 2;
+            rectEnd.y = rectStart.y + rectStart.height / 2;
+            rectEnd.width =
+            rectEnd.height = 0;
+            break;
+
+        case wxSHOW_EFFECT_BLEND:
+            [dict setObject:(show ? NSViewAnimationFadeInEffect
+                                  : NSViewAnimationFadeOutEffect)
+                  forKey:NSViewAnimationEffectKey];
+            break;
+
+        case wxSHOW_EFFECT_NONE:
+        case wxSHOW_EFFECT_MAX:
+            wxFAIL_MSG( "unexpected animation effect" );
+            return false;
+
+        default:
+            wxFAIL_MSG( "unknown animation effect" );
+            return false;
+    };
+
+    if ( show )
+    {
+        // we need to restore it to the original rectangle instead of making it
+        // disappear
+        wxSwap(rectStart, rectEnd);
+
+        // and as the window is currently hidden, we need to show it for the
+        // animation to be visible at all (but don't restore it at its full
+        // rectangle as it shouldn't appear immediately)
+        win->SetSize(rectStart);
+        win->Show();
+    }
+
+    NSView * const parentView = [viewOrWin isKindOfClass:[NSView class]]
+                                    ? [(NSView *)viewOrWin superview]
+                                    : nil;
+    const NSRect rStart = wxToNSRect(parentView, rectStart);
+    const NSRect rEnd = wxToNSRect(parentView, rectEnd);
+
+    [dict setObject:[NSValue valueWithRect:rStart]
+          forKey:NSViewAnimationStartFrameKey];
+    [dict setObject:[NSValue valueWithRect:rEnd]
+          forKey:NSViewAnimationEndFrameKey];
+
+    // create an animation using the values in the above dictionary
+    NSViewAnimation * const
+        anim = [[NSViewAnimation alloc]
+                initWithViewAnimations:[NSArray arrayWithObject:dict]];
+
+    if ( !timeout )
+    {
+        // what is a good default duration? Windows uses 200ms, Web frameworks
+        // use anything from 250ms to 1s... choose something in the middle
+        timeout = 500;
+    }
+
+    [anim setDuration:timeout/1000.];   // duration is in seconds here
+
+    // if the window being animated changes its layout depending on its size
+    // (which is almost always the case) we need to redo it during animation
+    //
+    // the number of layouts here is arbitrary, but 10 seems like too few (e.g.
+    // controls in wxInfoBar visibly jump around)
+    const int NUM_LAYOUTS = 20;
+    for ( float f = 1./NUM_LAYOUTS; f < 1.; f += 1./NUM_LAYOUTS )
+        [anim addProgressMark:f];
+
+    wxNSAnimationDelegate * const
+        animDelegate = [[wxNSAnimationDelegate alloc] init:win];
+    [anim setDelegate:animDelegate];
+    [anim startAnimation];
+
+    // Cocoa is capable of doing animation asynchronously or even from separate
+    // thread but wx API doesn't provide any way to be notified about the
+    // animation end and without this we really must ensure that the window has
+    // the expected (i.e. the same as if a simple Show() had been used) size
+    // when we return, so block here until the animation finishes
+    //
+    // notice that because the default animation mode is NSAnimationBlocking,
+    // no user input events ought to be processed from here
+    {
+        wxEventLoopGuarantor ensureEventLoopExistence;
+        wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
+        while ( ![animDelegate isDone] )
+            loop->Dispatch();
+    }
+
+    if ( !show )
+    {
+        // NSViewAnimation is smart enough to hide the NSView being animated at
+        // the end but we also must ensure that it's hidden for wx too
+        win->Hide();
+
+        // and we must also restore its size because it isn't expected to
+        // change just because the window was hidden
+        win->SetSize(rectOrig);
+    }
+    else
+    {
+        // refresh it once again after the end to ensure that everything is in
+        // place
+        win->SendSizeEvent();
+    }
+
+    [anim setDelegate:nil];
+    [animDelegate release];
+    [anim release];
+
+    return true;
+}
+
+bool wxWidgetCocoaImpl::ShowWithEffect(bool show,
+                                       wxShowEffect effect,
+                                       unsigned timeout)
+{
+    return ShowViewOrWindowWithEffect(m_wxPeer, show, effect, timeout);
+}
+
 void wxWidgetCocoaImpl::Raise()
 {
     // Not implemented
@@ -1217,13 +1565,19 @@ void wxWidgetCocoaImpl::Move(int x, int y, int width, int height)
     [m_osxView setFrame:r];
     [[m_osxView superview] setNeedsDisplayInRect:r];
 
+    wxNSView* wxview = (wxNSView*)m_osxView;
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
+    if ([wxview respondsToSelector:@selector(updateTrackingArea)] )
+        [wxview updateTrackingArea]; 
+#else
     if ([m_osxView respondsToSelector:@selector(trackingTag)] )
     {
-        if ( [(wxNSView*)m_osxView trackingTag] )
-            [m_osxView removeTrackingRect: [(wxNSView*)m_osxView trackingTag]];
+        if ( [wxview trackingTag] )
+            [wxview removeTrackingRect: [wxview trackingTag]];
 
-        [(wxNSView*)m_osxView setTrackingTag: [m_osxView addTrackingRect: [m_osxView bounds] owner: m_osxView userData: nil assumeInside: NO]];
+        [wxview setTrackingTag: [wxview addTrackingRect: [m_osxView bounds] owner: wxview userData: nil assumeInside: NO]];
     }
+#endif
 }
 
 void wxWidgetCocoaImpl::GetPosition( int &x, int &y ) const
@@ -1311,9 +1665,19 @@ void wxWidgetCocoaImpl::Embed( wxWidgetImpl *parent )
     [container addSubview:m_osxView];
 }
 
-void wxWidgetCocoaImpl::SetBackgroundColour( const wxColour &WXUNUSED(col) )
+void wxWidgetCocoaImpl::SetBackgroundColour( const wxColour &col )
 {
-    // m_osxView.backgroundColor = [[UIColor alloc] initWithCGColor:col.GetCGColor()];
+    NSView* targetView = m_osxView;
+    if ( [m_osxView isKindOfClass:[NSScrollView class] ] )
+        targetView = [(NSScrollView*) m_osxView documentView];
+
+    if ( [targetView respondsToSelector:@selector(setBackgroundColor:) ] )
+    {
+        [targetView setBackgroundColor:[NSColor colorWithCalibratedRed:(CGFloat) (col.Red() / 255.0)
+                                                                green:(CGFloat) (col.Green() / 255.0)
+                                                                 blue:(CGFloat) (col.Blue() / 255.0)
+                                                                alpha:(CGFloat) (col.Alpha() / 255.0)]];
+    }
 }
 
 void wxWidgetCocoaImpl::SetLabel( const wxString& title, wxFontEncoding encoding )
@@ -1411,6 +1775,7 @@ void wxWidgetCocoaImpl::SetBitmap( const wxBitmap& bitmap )
     if (  [m_osxView respondsToSelector:@selector(setImage:)] )
     {
         [m_osxView setImage:bitmap.GetNSImage()];
+        [m_osxView setNeedsDisplay:YES];
     }
 }
 
@@ -1529,6 +1894,18 @@ void wxWidgetCocoaImpl::SetFont(wxFont const& font, wxColour const&, long, bool)
         [m_osxView setFont: font.OSXGetNSFont()];
 }
 
+void wxWidgetCocoaImpl::SetToolTip(wxToolTip* tooltip)
+{
+    if (tooltip)
+    {
+        wxCFStringRef cf( tooltip->GetTip() , m_wxPeer->GetFont().GetEncoding() );
+        [m_osxView setToolTip: cf.AsNSString()];
+    }
+    else 
+        [m_osxView setToolTip: nil];
+
+}
+
 void wxWidgetCocoaImpl::InstallEventHandler( WXWidget control )
 {
     WXWidget c =  control ? control : (WXWidget) m_osxView;
@@ -1549,7 +1926,6 @@ bool wxWidgetCocoaImpl::DoHandleCharEvent(NSEvent *event, NSString *text)
 {
     wxKeyEvent wxevent(wxEVT_CHAR);
     SetupKeyEvent( wxevent, event, text );
-    wxevent.SetEventObject(GetWXPeer());
 
     return GetWXPeer()->OSXHandleKeyEvent(wxevent);
 }
@@ -1558,14 +1934,13 @@ bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event)
 {
     wxKeyEvent wxevent(wxEVT_KEY_DOWN);
     SetupKeyEvent( wxevent, event );
-    wxevent.SetEventObject(GetWXPeer());
     bool result = GetWXPeer()->OSXHandleKeyEvent(wxevent);
 
     // this will fire higher level events, like insertText, to help
     // us handle EVT_CHAR, etc.
-    if ( !m_hasEditor && [event type] == NSKeyDown)
+
+    if ( m_wxPeer->MacIsUserPane() && [event type] == NSKeyDown)
     {
-        m_lastKeyDownEvent = event;
         if ( !result )
         {
             if ( [m_osxView isKindOfClass:[NSScrollView class] ] )
@@ -1575,6 +1950,7 @@ bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event)
             result = true;
         }
     }
+
     return result;
 }
 
@@ -1584,8 +1960,7 @@ bool wxWidgetCocoaImpl::DoHandleMouseEvent(NSEvent *event)
     clickLocation = [m_osxView convertPoint:[event locationInWindow] fromView:nil];
     wxPoint pt = wxFromNSPoint( m_osxView, clickLocation );
     wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
-    SetupMouseEvent( wxevent , event ) ;
-    wxevent.SetEventObject(GetWXPeer());
+    SetupMouseEvent(wxevent , event) ;
     wxevent.m_x = pt.x;
     wxevent.m_y = pt.y;