X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0309327e97bfb8b7f3030c21eaf75109ee733d72..12ca260575f98426427464fbf8fcfad5f1ec7b61:/src/osx/cocoa/window.mm diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index 048117a2cd..46aa01527a 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -87,21 +87,13 @@ 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 + BOOL _hasToolTip; + NSTrackingRectTag _lastToolTipTrackTag; + id _lastToolTipOwner; + void* _lastUserData; + } -// 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) @@ -137,27 +129,6 @@ NSRect wxOSXGetFrameForControl( wxWindowMac* window , const wxPoint& pos , const - (void)setImagePosition:(NSCellImagePosition)aPosition; @end -// in case we want to use the native tooltip callbacks - -#if 0 - -@interface NSView(wxToolTip) -- (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(void *)userData; -@end - -@implementation NSView(wxToolTip) - -- (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(void *)userData { - wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( view ); - if (impl == NULL) - return nil; - - return @"Tag"; -} -@end - -#endif - // The following code is a combination of the code listed here: // http://lists.apple.com/archives/cocoa-dev/2008/Apr/msg01582.html // (which can't be used because KLGetCurrentKeyboardLayout etc aren't 64-bit) @@ -662,7 +633,7 @@ void wxWidgetCocoaImpl::SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEve if ( fabs(deltaX) > fabs(deltaY) ) { - wxevent.m_wheelAxis = 1; + wxevent.m_wheelAxis = wxMOUSE_WHEEL_HORIZONTAL; wxevent.m_wheelRotation = (int)deltaX; } else @@ -710,38 +681,87 @@ void wxWidgetCocoaImpl::SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEve } } -- (void) setTrackingTag: (NSTrackingRectTag)tag +/* idea taken from webkit sources: overwrite the methods that (private) NSToolTipManager will use to attach its tracking rectangle + * then when changing the tooltip send fake view-exit and view-enter methods which will lead to a tooltip refresh + */ + + +- (void)_sendToolTipMouseExited { - rectTag = tag; + // Nothing matters except window, trackingNumber, and userData. + NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseExited + location:NSMakePoint(0, 0) + modifierFlags:0 + timestamp:0 + windowNumber:[[self window] windowNumber] + context:NULL + eventNumber:0 + trackingNumber:_lastToolTipTrackTag + userData:_lastUserData]; + [_lastToolTipOwner mouseExited:fakeEvent]; } -- (NSTrackingRectTag) trackingTag +- (void)_sendToolTipMouseEntered { - return rectTag; + // Nothing matters except window, trackingNumber, and userData. + NSEvent *fakeEvent = [NSEvent enterExitEventWithType:NSMouseEntered + location:NSMakePoint(0, 0) + modifierFlags:0 + timestamp:0 + windowNumber:[[self window] windowNumber] + context:NULL + eventNumber:0 + trackingNumber:_lastToolTipTrackTag + userData:_lastUserData]; + [_lastToolTipOwner mouseEntered:fakeEvent]; } -#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 -- (void) updateTrackingArea +- (void)setToolTip:(NSString *)string; { - if (_trackingArea) + if (string) { - [self removeTrackingArea: _trackingArea]; - [_trackingArea release]; + if ( _hasToolTip ) + { + [self _sendToolTipMouseExited]; + } + + [super setToolTip:string]; + _hasToolTip = YES; + [self _sendToolTipMouseEntered]; } - - NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited|NSTrackingMouseMoved|NSTrackingActiveAlways; - - NSTrackingArea* area = [[NSTrackingArea alloc] initWithRect: [self bounds] options: options owner: self userInfo: nil]; - [self addTrackingArea: area]; + else + { + if ( _hasToolTip ) + { + [self _sendToolTipMouseExited]; + [super setToolTip:nil]; + _hasToolTip = NO; + } + } +} - _trackingArea = area; +- (NSTrackingRectTag)addTrackingRect:(NSRect)rect owner:(id)owner userData:(void *)data assumeInside:(BOOL)assumeInside +{ + NSTrackingRectTag tag = [super addTrackingRect:rect owner:owner userData:data assumeInside:assumeInside]; + if ( owner != self ) + { + _lastUserData = data; + _lastToolTipOwner = owner; + _lastToolTipTrackTag = tag; + } + return tag; } -- (NSTrackingArea*) trackingArea +- (void)removeTrackingRect:(NSTrackingRectTag)tag { - return _trackingArea; + if (tag == _lastToolTipTrackTag) + { + _lastUserData = NULL; + _lastToolTipOwner = nil; + _lastToolTipTrackTag = 0; + } + [super removeTrackingRect:tag]; } -#endif @end // wxNSView // @@ -800,6 +820,15 @@ void wxOSX_mouseEvent(NSView* self, SEL _cmd, NSEvent *event) impl->mouseEvent(event, self, _cmd); } +void wxOSX_cursorUpdate(NSView* self, SEL _cmd, NSEvent *event) +{ + wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); + if (impl == NULL) + return; + + impl->cursorUpdate(event, self, _cmd); +} + BOOL wxOSX_acceptsFirstMouse(NSView* WXUNUSED(self), SEL WXUNUSED(_cmd), NSEvent *WXUNUSED(event)) { // This is needed to support click through, otherwise the first click on a window @@ -861,15 +890,6 @@ BOOL wxOSX_resignFirstResponder(NSView* self, SEL _cmd) return impl->resignFirstResponder(self, _cmd); } -void wxOSX_resetCursorRects(NSView* self, SEL _cmd) -{ - wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); - if (impl == NULL) - return; - - impl->resetCursorRects(self, _cmd); -} - BOOL wxOSX_isFlipped(NSView* self, SEL _cmd) { wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); @@ -887,7 +907,7 @@ void wxOSX_drawRect(NSView* self, SEL _cmd, NSRect rect) if (impl == NULL) return; -#ifdef wxUSE_THREADS +#if wxUSE_THREADS // OS X starts a NSUIHeartBeatThread for animating the default button in a // dialog. This causes a drawRect of the active dialog from outside the // main UI thread. This causes an occasional crash since the wx drawing @@ -1096,7 +1116,6 @@ typedef void (*wxOSX_TextEventHandlerPtr)(NSView* self, SEL _cmd, NSString *even typedef void (*wxOSX_EventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event); typedef BOOL (*wxOSX_PerformKeyEventHandlerPtr)(NSView* self, SEL _cmd, NSEvent *event); typedef BOOL (*wxOSX_FocusHandlerPtr)(NSView* self, SEL _cmd); -typedef BOOL (*wxOSX_ResetCursorRectsHandlerPtr)(NSView* self, SEL _cmd); void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd) { @@ -1122,6 +1141,22 @@ void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd) } } +void wxWidgetCocoaImpl::cursorUpdate(WX_NSEvent event, WXWidget slf, void *_cmd) +{ + NSCursor *cursor = (NSCursor*)GetWXPeer()->GetCursor().GetHCURSOR(); + if (cursor == NULL) + { + wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd]; + superimpl(slf, (SEL)_cmd, event); + } + else + { + [cursor set]; + } +} + + + void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd) { if ( [event type] == NSKeyDown ) @@ -1241,25 +1276,6 @@ bool wxWidgetCocoaImpl::resignFirstResponder(WXWidget slf, void *_cmd) return r; } -void wxWidgetCocoaImpl::resetCursorRects(WXWidget slf, void *_cmd) -{ - wxWindow* wxpeer = GetWXPeer(); - if ( wxpeer ) - { - NSCursor *cursor = (NSCursor*)wxpeer->GetCursor().GetHCURSOR(); - if (cursor == NULL) - { - wxOSX_ResetCursorRectsHandlerPtr superimpl = (wxOSX_ResetCursorRectsHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd]; - superimpl(slf, (SEL)_cmd); - } - else - { - [slf addCursorRect: [slf bounds] - cursor: cursor]; - } - } -} - bool wxWidgetCocoaImpl::isFlipped(WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd)) { return m_isFlipped; @@ -1469,6 +1485,8 @@ void wxOSXCocoaClassAddWXMethods(Class c) wxOSX_CLASS_ADD_METHOD(c, @selector(mouseEntered:), (IMP) wxOSX_mouseEvent, "v@:@" ) wxOSX_CLASS_ADD_METHOD(c, @selector(mouseExited:), (IMP) wxOSX_mouseEvent, "v@:@" ) + wxOSX_CLASS_ADD_METHOD(c, @selector(cursorUpdate:), (IMP) wxOSX_cursorUpdate, "v@:@" ) + wxOSX_CLASS_ADD_METHOD(c, @selector(keyDown:), (IMP) wxOSX_keyEvent, "v@:@" ) wxOSX_CLASS_ADD_METHOD(c, @selector(keyUp:), (IMP) wxOSX_keyEvent, "v@:@" ) wxOSX_CLASS_ADD_METHOD(c, @selector(flagsChanged:), (IMP) wxOSX_keyEvent, "v@:@" ) @@ -1480,7 +1498,6 @@ void wxOSXCocoaClassAddWXMethods(Class c) wxOSX_CLASS_ADD_METHOD(c, @selector(acceptsFirstResponder), (IMP) wxOSX_acceptsFirstResponder, "c@:" ) wxOSX_CLASS_ADD_METHOD(c, @selector(becomeFirstResponder), (IMP) wxOSX_becomeFirstResponder, "c@:" ) wxOSX_CLASS_ADD_METHOD(c, @selector(resignFirstResponder), (IMP) wxOSX_resignFirstResponder, "c@:" ) - wxOSX_CLASS_ADD_METHOD(c, @selector(resetCursorRects), (IMP) wxOSX_resetCursorRects, "v@:" ) wxOSX_CLASS_ADD_METHOD(c, @selector(isFlipped), (IMP) wxOSX_isFlipped, "c@:" ) wxOSX_CLASS_ADD_METHOD(c, @selector(drawRect:), (IMP) wxOSX_drawRect, "v@:{_NSRect={_NSPoint=ff}{_NSSize=ff}}" ) @@ -1615,6 +1632,7 @@ void wxWidgetCocoaImpl::SetVisibility( bool visible ) wxUnusedVar(progress); m_win->SendSizeEvent(); + m_win->MacOnInternalSize(); } - (void)animationDidEnd:(NSAnimation*)animation @@ -1791,6 +1809,7 @@ wxWidgetCocoaImpl::ShowViewOrWindowWithEffect(wxWindow *win, // refresh it once again after the end to ensure that everything is in // place win->SendSizeEvent(); + win->MacOnInternalSize(); } [anim setDelegate:nil]; @@ -1964,20 +1983,6 @@ void wxWidgetCocoaImpl::Move(int x, int y, int width, int height) NSRect r = wxToNSRect( [m_osxView superview], wxRect(x,y,width, 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 ( [wxview trackingTag] ) - [wxview removeTrackingRect: [wxview trackingTag]]; - - [wxview setTrackingTag: [wxview addTrackingRect: [m_osxView bounds] owner: wxview userData: nil assumeInside: NO]]; - } -#endif } void wxWidgetCocoaImpl::GetPosition( int &x, int &y ) const @@ -2067,6 +2072,23 @@ bool wxWidgetCocoaImpl::SetFocus() return true; } +void wxWidgetCocoaImpl::SetDropTarget(wxDropTarget* target) +{ + [m_osxView unregisterDraggedTypes]; + + if ( target == NULL ) + return; + + wxDataObject* dobj = target->GetDataObject(); + + if( dobj ) + { + CFMutableArrayRef typesarray = CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks); + + [m_osxView registerForDraggedTypes:(NSArray*)typesarray]; + CFRelease(typesarray); + } +} void wxWidgetCocoaImpl::RemoveFromParent() { @@ -2338,32 +2360,17 @@ void wxWidgetCocoaImpl::SetFont(wxFont const& font, wxColour const&col, long, bo alpha:(CGFloat) (col.Alpha() / 255.0)]]; } -NSToolTipTag tt = 0; - void wxWidgetCocoaImpl::SetToolTip(wxToolTip* tooltip) { - if (tooltip) + if ( tooltip ) { - /* - if ( tt != 0 ) - { - [m_osxView removeToolTip:tt]; - tt = 0; - } - */ wxCFStringRef cf( tooltip->GetTip() , m_wxPeer->GetFont().GetEncoding() ); [m_osxView setToolTip: cf.AsNSString()]; - // tt = [m_osxView addToolTipRect:[m_osxView bounds] owner:m_osxView userData:nil]; } else { - if ( tt != 0 ) - { - [m_osxView removeToolTip:tt]; - tt = 0; - } + [m_osxView setToolTip:nil]; } - } void wxWidgetCocoaImpl::InstallEventHandler( WXWidget control ) @@ -2380,7 +2387,11 @@ void wxWidgetCocoaImpl::InstallEventHandler( WXWidget control ) } } -} + NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited|NSTrackingCursorUpdate|NSTrackingMouseMoved|NSTrackingActiveAlways|NSTrackingInVisibleRect; + NSTrackingArea* area = [[NSTrackingArea alloc] initWithRect: NSZeroRect options: options owner: m_osxView userInfo: nil]; + [m_osxView addTrackingArea: area]; + [area release]; + } bool wxWidgetCocoaImpl::DoHandleCharEvent(NSEvent *event, NSString *text) { @@ -2413,7 +2424,7 @@ bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event) if ( !result ) { - if ( IsUserPane() && [event type] == NSKeyDown) + if ( [event type] == NSKeyDown) { long keycode = wxOSXTranslateCocoaKey( event, wxEVT_CHAR ); @@ -2422,12 +2433,20 @@ bool wxWidgetCocoaImpl::DoHandleKeyEvent(NSEvent *event) // eventually we could setup a doCommandBySelector catcher and retransform this into the wx key chars wxKeyEvent wxevent2(wxevent) ; wxevent2.SetEventType(wxEVT_CHAR); + SetupKeyEvent( wxevent2, event ); wxevent2.m_keyCode = keycode; result = GetWXPeer()->OSXHandleKeyEvent(wxevent2); } + else if (wxevent.CmdDown()) + { + wxKeyEvent wxevent2(wxevent) ; + wxevent2.SetEventType(wxEVT_CHAR); + SetupKeyEvent( wxevent2, event ); + result = GetWXPeer()->OSXHandleKeyEvent(wxevent2); + } else { - if ( !wxevent.CmdDown() ) + if ( IsUserPane() && !wxevent.CmdDown() ) { if ( [m_osxView isKindOfClass:[NSScrollView class] ] ) [[(NSScrollView*)m_osxView documentView] interpretKeyEvents:[NSArray arrayWithObject:event]]; @@ -2446,7 +2465,6 @@ bool wxWidgetCocoaImpl::DoHandleMouseEvent(NSEvent *event) { wxMouseEvent wxevent(wxEVT_LEFT_DOWN); SetupMouseEvent(wxevent , event) ; - return GetWXPeer()->HandleWindowEvent(wxevent); } @@ -2505,7 +2523,6 @@ void wxWidgetCocoaImpl::SetCursor(const wxCursor& cursor) [(NSCursor*)cursor.GetHCURSOR() set]; } } - [[m_osxView window] invalidateCursorRectsForView:m_osxView]; } void wxWidgetCocoaImpl::CaptureMouse() @@ -2534,10 +2551,6 @@ wxWidgetImpl* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, wxWindowMac* WX NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ; wxNSView* v = [[wxNSView alloc] initWithFrame:r]; - // temporary hook for dnd - [v registerForDraggedTypes:[NSArray arrayWithObjects: - NSStringPboardType, NSFilenamesPboardType, NSTIFFPboardType, NSPICTPboardType, NSPDFPboardType, nil]]; - wxWidgetCocoaImpl* c = new wxWidgetCocoaImpl( wxpeer, v, false, true ); return c; }