From 51156271b7da5ce58cc2a69d90dcf4fbb8bac0aa Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Wed, 21 Nov 2007 10:51:20 +0000 Subject: [PATCH] focus fixes for 10.5 git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH@50127 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/mac/carbon/window.cpp | 142 ++++++++++++++++++++++++++++++-------- 1 file changed, 114 insertions(+), 28 deletions(-) diff --git a/src/mac/carbon/window.cpp b/src/mac/carbon/window.cpp index f8654518d2..8588d1ab97 100644 --- a/src/mac/carbon/window.cpp +++ b/src/mac/carbon/window.cpp @@ -162,6 +162,12 @@ enum }; #endif +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 +enum { + kEventControlFocusPartChanged = 164 +}; +#endif + #endif static const EventTypeSpec eventList[] = @@ -184,8 +190,8 @@ static const EventTypeSpec eventList[] = { kEventClassControl , kEventControlActivate } , { kEventClassControl , kEventControlDeactivate } , #endif - { kEventClassControl , kEventControlGetFocusPart } , { kEventClassControl , kEventControlSetFocusPart } , + { kEventClassControl , kEventControlFocusPartChanged } , { kEventClassService , kEventServiceGetTypes }, { kEventClassService , kEventServiceCopy }, @@ -326,38 +332,27 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl break ; #endif // TARGET_API_MAC_OSX - // we emulate this event under Carbon CFM - case kEventControlGetFocusPart : - if ( thisWindow->MacIsUserPane() ) + // + // focus handling + // different handling on OS X + // + + case kEventControlFocusPartChanged : + // the event is emulated by wxmac for systems lower than 10.5 { - // kHIViewEntireView and kHIViewNoPart have the same code, needed for Leopard - cEvent.SetParameter(kEventParamControlPart , kHIViewEntireView ); - result = noErr ; - } - break ; - case kEventControlSetFocusPart : - { - Boolean focusEverything = false ; - ControlPartCode controlPart = cEvent.GetParameter(kEventParamControlPart , typeControlPartCode ); - -#ifdef __WXMAC_OSX__ - if ( cEvent.GetParameter(kEventParamControlFocusEverything , &focusEverything ) == noErr ) - { - } -#endif - - if ( thisWindow->MacIsUserPane() ) - result = noErr ; - - if ( controlPart == kControlFocusNoPart ) + ControlPartCode previousControlPart = cEvent.GetParameter(kEventParamControlPreviousPart , typeControlPartCode ); + ControlPartCode currentControlPart = cEvent.GetParameter(kEventParamControlCurrentPart , typeControlPartCode ); + if ( currentControlPart == 0 ) { + // kill focus #if wxUSE_CARET if ( thisWindow->GetCaret() ) thisWindow->GetCaret()->OnKillFocus(); #endif - + wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow)); + // remove this as soon as posting the synthesized event works properly static bool inKillFocusEvent = false ; if ( !inKillFocusEvent ) @@ -369,23 +364,114 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl inKillFocusEvent = false ; } } - else + else if ( previousControlPart == 0 ) { + // set focus // panel wants to track the window which was the last to have focus in it wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow)); wxChildFocusEvent eventFocus((wxWindow*)thisWindow); thisWindow->GetEventHandler()->ProcessEvent(eventFocus); - + #if wxUSE_CARET if ( thisWindow->GetCaret() ) thisWindow->GetCaret()->OnSetFocus(); #endif - + wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId()); event.SetEventObject(thisWindow); thisWindow->GetEventHandler()->ProcessEvent(event) ; } } + break; + case kEventControlSetFocusPart : + { +#ifdef __WXMAC_OSX__ + Boolean focusEverything = false ; + if ( cEvent.GetParameter(kEventParamControlFocusEverything , &focusEverything ) == noErr ) + { + // put a breakpoint here to catch focus everything events + } +#endif + ControlPartCode controlPart = cEvent.GetParameter(kEventParamControlPart , typeControlPartCode ); + + ControlPartCode previousControlPart = 0; + verify_noerr( HIViewGetFocusPart(controlRef, &previousControlPart)); + + if ( thisWindow->MacIsUserPane() ) + { + if ( controlPart != kControlFocusNoPart ) + cEvent.SetParameter( kEventParamControlPart, typeControlPartCode, 1 ) ; + result = noErr ; + } + else + result = CallNextEventHandler(handler, event); + + if ( UMAGetSystemVersion() < 0x1050 ) + { +// set back to 0 if problems arise +#if 1 + ControlPartCode currentControlPart = cEvent.GetParameter(kEventParamControlPart , typeControlPartCode ); + // synthesize the event focus changed event + EventRef evRef = NULL ; + + OSStatus err = MacCreateEvent( + NULL , kEventClassControl , kEventControlFocusPartChanged , TicksToEventTime( TickCount() ) , + kEventAttributeUserEvent , &evRef ); + verify_noerr( err ); + + wxMacCarbonEvent iEvent( evRef ) ; + iEvent.SetParameter( kEventParamDirectObject , controlRef ) ; + iEvent.SetParameter( kEventParamControlPreviousPart, typeControlPartCode, previousControlPart ) ; + iEvent.SetParameter( kEventParamControlCurrentPart, typeControlPartCode, currentControlPart ) ; + +#if 0 + // TODO test this first, avoid double posts etc... + PostEventToQueue( GetMainEventQueue(), evRef , kEventPriorityHigh ); +#else + wxMacWindowControlEventHandler( NULL , evRef , data ) ; +#endif + ReleaseEvent( evRef ) ; +#else + // old implementation, to be removed if the new one works + if ( controlPart == kControlFocusNoPart ) + { +#if wxUSE_CARET + if ( thisWindow->GetCaret() ) + thisWindow->GetCaret()->OnKillFocus(); +#endif + + wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow)); + + static bool inKillFocusEvent = false ; + + if ( !inKillFocusEvent ) + { + inKillFocusEvent = true ; + wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId()); + event.SetEventObject(thisWindow); + thisWindow->GetEventHandler()->ProcessEvent(event) ; + inKillFocusEvent = false ; + } + } + else + { + // panel wants to track the window which was the last to have focus in it + wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow)); + wxChildFocusEvent eventFocus((wxWindow*)thisWindow); + thisWindow->GetEventHandler()->ProcessEvent(eventFocus); + + #if wxUSE_CARET + if ( thisWindow->GetCaret() ) + thisWindow->GetCaret()->OnSetFocus(); + #endif + + wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId()); + event.SetEventObject(thisWindow); + thisWindow->GetEventHandler()->ProcessEvent(event) ; + } +#endif + } + } break ; case kEventControlHit :