X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/094fa9e9ef74842c293baf5e2596e1db173ac2c8..7c60222510bc5e197b12f153c4bf05db66cb0f4a:/src/osx/cocoa/window.mm diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index 351bfe1f53..3465cdbc40 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -17,6 +17,7 @@ #include "wx/log.h" #include "wx/textctrl.h" #include "wx/combobox.h" + #include "wx/radiobut.h" #endif #ifdef __WXMAC__ @@ -41,7 +42,7 @@ // Get the window with the focus -NSView* GetViewFromResponder( NSResponder* responder ) +NSView* wxOSXGetViewFromResponder( NSResponder* responder ) { NSView* view = nil; if ( [responder isKindOfClass:[NSTextView class]] ) @@ -64,16 +65,29 @@ NSView* GetFocusedViewInWindow( NSWindow* keyWindow ) { NSView* focusedView = nil; if ( keyWindow != nil ) - focusedView = GetViewFromResponder([keyWindow firstResponder]); + focusedView = wxOSXGetViewFromResponder([keyWindow firstResponder]); return focusedView; } WXWidget wxWidgetImpl::FindFocus() { - return GetFocusedViewInWindow( [NSApp keyWindow] ); + return GetFocusedViewInWindow( [NSApp keyWindow] );; } +wxWidgetImpl* wxWidgetImpl::FindBestFromWXWidget(WXWidget control) +{ + wxWidgetImpl* impl = FindFromWXWidget(control); + + // NSScrollViews can have their subviews like NSClipView + // therefore check and use the NSScrollView peer in that case + if ( impl == NULL && [[control superview] isKindOfClass:[NSScrollView class]]) + impl = FindFromWXWidget([control superview]); + + return impl; +} + + NSRect wxOSXGetFrameForControl( wxWindowMac* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin ) { int x, y, w, h ; @@ -293,59 +307,70 @@ long wxOSXTranslateCocoaKey( NSEvent* event, int eventType ) case 48: retval = WXK_TAB; break; - - case 75: // / - retval = WXK_NUMPAD_DIVIDE; - break; - case 67: // * - retval = WXK_NUMPAD_MULTIPLY; - break; - case 78: // - - retval = WXK_NUMPAD_SUBTRACT; - break; - case 69: // + - retval = WXK_NUMPAD_ADD; - break; - case 76: // Enter - retval = WXK_NUMPAD_ENTER; - break; - case 65: // . - retval = WXK_NUMPAD_DECIMAL; - break; - case 82: // 0 - retval = WXK_NUMPAD0; - break; - case 83: // 1 - retval = WXK_NUMPAD1; - break; - case 84: // 2 - retval = WXK_NUMPAD2; - break; - case 85: // 3 - retval = WXK_NUMPAD3; - break; - case 86: // 4 - retval = WXK_NUMPAD4; - break; - case 87: // 5 - retval = WXK_NUMPAD5; - break; - case 88: // 6 - retval = WXK_NUMPAD6; - break; - case 89: // 7 - retval = WXK_NUMPAD7; - break; - case 91: // 8 - retval = WXK_NUMPAD8; - break; - case 92: // 9 - retval = WXK_NUMPAD9; - break; default: - //retval = [event keyCode]; break; } + + // Check for NUMPAD keys. For KEY_UP/DOWN events we need to use the + // WXK_NUMPAD constants, but for the CHAR event we want to use the + // standard ascii values + if ( eventType != wxEVT_CHAR ) + { + switch( [event keyCode] ) + { + case 75: // / + retval = WXK_NUMPAD_DIVIDE; + break; + case 67: // * + retval = WXK_NUMPAD_MULTIPLY; + break; + case 78: // - + retval = WXK_NUMPAD_SUBTRACT; + break; + case 69: // + + retval = WXK_NUMPAD_ADD; + break; + case 76: // Enter + retval = WXK_NUMPAD_ENTER; + break; + case 65: // . + retval = WXK_NUMPAD_DECIMAL; + break; + case 82: // 0 + retval = WXK_NUMPAD0; + break; + case 83: // 1 + retval = WXK_NUMPAD1; + break; + case 84: // 2 + retval = WXK_NUMPAD2; + break; + case 85: // 3 + retval = WXK_NUMPAD3; + break; + case 86: // 4 + retval = WXK_NUMPAD4; + break; + case 87: // 5 + retval = WXK_NUMPAD5; + break; + case 88: // 6 + retval = WXK_NUMPAD6; + break; + case 89: // 7 + retval = WXK_NUMPAD7; + break; + case 91: // 8 + retval = WXK_NUMPAD8; + break; + case 92: // 9 + retval = WXK_NUMPAD9; + break; + default: + //retval = [event keyCode]; + break; + } + } return retval; } @@ -658,6 +683,7 @@ void wxWidgetCocoaImpl::SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEve wxevent.m_wheelDelta = 10; wxevent.m_linesPerAction = 1; + wxevent.m_columnsPerAction = 1; if ( fabs(deltaX) > fabs(deltaY) ) { @@ -798,6 +824,14 @@ void wxWidgetCocoaImpl::SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEve } #endif +- (BOOL) canBecomeKeyView +{ + wxWidgetCocoaImpl* viewimpl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); + if ( viewimpl && viewimpl->IsUserPane() && viewimpl->GetWXPeer() ) + return viewimpl->GetWXPeer()->AcceptsFocus(); + return NO; +} + @end // wxNSView // @@ -1152,17 +1186,22 @@ bool wxWidgetCocoaImpl::performDragOperation(void* s, WXWidget WXUNUSED(slf), vo return result != wxDragNone; } -typedef void (*wxOSX_TextEventHandlerPtr)(NSView* self, SEL _cmd, NSString *event); -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); - void wxWidgetCocoaImpl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd) { + // we are getting moved events for all windows in the hierarchy, not something wx expects + // therefore we only handle it for the deepest child in the hierarchy + if ( [event type] == NSMouseMoved ) + { + NSView* hitview = [[[slf window] contentView] hitTest:[event locationInWindow]]; + if ( hitview == NULL || hitview != slf) + return; + } + if ( !DoHandleMouseEvent(event) ) { // for plain NSView mouse events would propagate to parents otherwise - if (!IsUserPane()) + // scrollwheel events have to be propagated if not handled in all cases + if (!IsUserPane() || [event type] == NSScrollWheel ) { wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd]; superimpl(slf, (SEL)_cmd, event); @@ -1208,9 +1247,14 @@ bool wxWidgetCocoaImpl::SetupCursor(WX_NSEvent event) while ( cursorTarget && !cursorTarget->MacSetupCursor( cursorPoint ) ) { + // at least in GTK cursor events are not propagated either ... +#if 1 + cursorTarget = NULL; +#else cursorTarget = cursorTarget->GetParent() ; if ( cursorTarget ) cursorPoint += cursorTarget->GetPosition(); +#endif } return cursorTarget != NULL; @@ -1262,14 +1306,14 @@ bool wxWidgetCocoaImpl::performKeyEquivalent(WX_NSEvent event, WXWidget slf, voi { wxEvtHandler * const handler = m_wxPeer->GetEventHandler(); - wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command ); + wxCommandEvent command_event( wxEVT_MENU, command ); command_event.SetEventObject( wxevent.GetEventObject() ); handled = handler->ProcessEvent( command_event ); if ( !handled ) { // accelerators can also be used with buttons, try them too - command_event.SetEventType(wxEVT_COMMAND_BUTTON_CLICKED); + command_event.SetEventType(wxEVT_BUTTON); handled = handler->ProcessEvent( command_event ); } } @@ -1313,20 +1357,17 @@ bool wxWidgetCocoaImpl::resignFirstResponder(WXWidget slf, void *_cmd) { wxOSX_FocusHandlerPtr superimpl = (wxOSX_FocusHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd]; BOOL r = superimpl(slf, (SEL)_cmd); - // get the current focus after running resignFirstResponder - // note that this value isn't reliable, it might return the same view that - // is resigning - NSView* otherView = FindFocus(); - wxWidgetImpl* otherWindow = FindFromWXWidget(otherView); + + NSResponder * responder = wxNonOwnedWindowCocoaImpl::GetNextFirstResponder(); + NSView* otherView = wxOSXGetViewFromResponder(responder); - // It doesn't make sense to notify about the loss of focus if we're not - // really losing it and the window which has just gained focus is the same - // one as this window itself. Of course, this should never happen in the - // first place but somehow it does in wxGrid code and without this check we - // enter into an infinite recursion, see #12267. + wxWidgetImpl* otherWindow = FindBestFromWXWidget(otherView); + + // It doesn't make sense to notify about the loss of focus if it's the same + // control in the end, and just a different subview if ( otherWindow == this ) return r; - + // NSTextViews have an editor as true responder, therefore the might get the // resign notification if their editor takes over, don't trigger any event then if ( r && !m_hasEditor) @@ -1662,6 +1703,17 @@ void wxWidgetCocoaImpl::SetVisibility( bool visible ) [m_osxView setHidden:(visible ? NO:YES)]; } +double wxWidgetCocoaImpl::GetContentScaleFactor() const +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 + NSWindow* tlw = [m_osxView window]; + if ( [ tlw respondsToSelector:@selector(backingScaleFactor) ] ) + return [tlw backingScaleFactor]; + else +#endif + return 1.0; +} + // ---------------------------------------------------------------------------- // window animation stuff // ---------------------------------------------------------------------------- @@ -1707,7 +1759,6 @@ void wxWidgetCocoaImpl::SetVisibility( bool visible ) wxUnusedVar(progress); m_win->SendSizeEvent(); - m_win->MacOnInternalSize(); } - (void)animationDidEnd:(NSAnimation*)animation @@ -1884,7 +1935,6 @@ 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]; @@ -2481,7 +2531,13 @@ void wxWidgetCocoaImpl::InstallEventHandler( WXWidget control ) if ([c respondsToSelector:@selector(setAction:)]) { [c setTarget: c]; - [c setAction: @selector(controlAction:)]; + if ( dynamic_cast(GetWXPeer()) ) + { + // everything already set up + } + else + [c setAction: @selector(controlAction:)]; + if ([c respondsToSelector:@selector(setDoubleAction:)]) { [c setDoubleAction: @selector(controlDoubleAction:)]; @@ -2489,7 +2545,7 @@ 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]; + NSTrackingArea* area = [[NSTrackingArea alloc] initWithRect: NSZeroRect options: options owner: m_osxView userInfo: nil]; [m_osxView addTrackingArea: area]; [area release]; }