X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/489468feaa08b8f504735eecca522fb8d0f825d2..c7e94140cd436c6c234a382ad4e16ec5da65830c:/src/osx/carbon/app.cpp diff --git a/src/osx/carbon/app.cpp b/src/osx/carbon/app.cpp index a75a511279..cf1e53b104 100644 --- a/src/osx/carbon/app.cpp +++ b/src/osx/carbon/app.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: src/mac/carbon/app.cpp +// Name: src/osx/carbon/app.cpp // Purpose: wxApp // Author: Stefan Csomor // Modified by: @@ -40,29 +40,24 @@ #include "wx/filename.h" #include "wx/link.h" #include "wx/thread.h" +#include "wx/evtloop.h" #include // mac +#if wxOSX_USE_CARBON +#include "wx/osx/uma.h" +#else +#include "wx/osx/private.h" +#endif -#include "wx/mac/uma.h" - -#ifdef __DARWIN__ -# include -# if defined(WXMAKINGDLL_CORE) -# include -# endif +#if defined(WXMAKINGDLL_CORE) +# include #endif // Keep linker from discarding wxStockGDIMac wxFORCE_LINK_MODULE(gdiobj) -// statics for implementation -static bool s_inYield = false; -static bool s_inReceiveEvent = false ; -static EventTime sleepTime = kEventDurationNoWait ; - - IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler) BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) EVT_IDLE(wxApp::OnIdle) @@ -84,15 +79,25 @@ wxString wxApp::s_macHelpMenuTitleName = wxT("&Help") ; bool wxApp::sm_isEmbedded = false; // Normally we're not a plugin +#if wxOSX_USE_CARBON + //---------------------------------------------------------------------- // Core Apple Event Support //---------------------------------------------------------------------- +AEEventHandlerUPP sODocHandler = NULL ; +AEEventHandlerUPP sGURLHandler = NULL ; +AEEventHandlerUPP sOAppHandler = NULL ; +AEEventHandlerUPP sPDocHandler = NULL ; +AEEventHandlerUPP sRAppHandler = NULL ; +AEEventHandlerUPP sQuitHandler = NULL ; + pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ; pascal OSErr AEHandleOApp( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ; pascal OSErr AEHandlePDoc( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ; pascal OSErr AEHandleQuit( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ; pascal OSErr AEHandleRApp( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ; +pascal OSErr AEHandleGURL( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ; pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) ) { @@ -179,7 +184,7 @@ short wxApp::MacHandleAEGURL(const WXEVENTREF event, WXEVENTREF WXUNUSED(reply)) if (err != noErr) return err; - url[actualSize] = '\0'; // Terminate the C string + url[actualSize] = '\0'; // Terminate the C string ProcessSerialNumber PSN ; PSN.highLongOfPSN = 0 ; @@ -244,18 +249,13 @@ short wxApp::MacHandleAEOApp(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNU short wxApp::MacHandleAEQuit(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply)) { - wxWindow* win = GetTopWindow() ; - if ( win ) + wxCloseEvent event; + wxTheApp->OnQueryEndSession(event); + if ( !event.GetVeto() ) { - wxCommandEvent exitEvent(wxEVT_COMMAND_MENU_SELECTED, s_macExitMenuItemId); - if (!win->ProcessEvent(exitEvent)) - win->Close(true) ; + wxCloseEvent event; + wxTheApp->OnEndSession(event); } - else - { - ExitMainLoop() ; - } - return noErr ; } @@ -268,6 +268,8 @@ short wxApp::MacHandleAERApp(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNU return noErr ; } +#endif + //---------------------------------------------------------------------- // Support Routines linking the Mac...File Calls to the Document Manager //---------------------------------------------------------------------- @@ -334,7 +336,7 @@ void wxApp::MacReopenApp() // if some windows are not hidden -> do nothing wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst(); - if ( node == NULL ) + if ( !node ) { MacNewFile() ; } @@ -350,9 +352,9 @@ void wxApp::MacReopenApp() // make sure we don't show 'virtual toplevel windows' like wxTaskBarIconWindow if ( firstHidden == NULL && ( wxDynamicCast( win, wxFrame ) || wxDynamicCast( win, wxDialog ) ) ) firstHidden = win ; - } + } else if ( win->IsIconized() ) - { + { if ( firstIconized == NULL ) firstIconized = win ; } @@ -378,6 +380,8 @@ void wxApp::MacReopenApp() // if no native match they just return the passed-in id +#if wxOSX_USE_CARBON + struct IdPair { UInt32 macId ; @@ -490,7 +494,7 @@ wxMenu* wxFindMenuFromMacCommand( const HICommand &command , wxMenuItem* &item ) // is it part of the application or the Help menu, then look for the id directly if ( ( GetMenuHandle( kwxMacAppleMenuId ) != NULL && command.menu.menuRef == GetMenuHandle( kwxMacAppleMenuId ) ) || - ( helpMenuHandle != NULL && command.menu.menuRef == helpMenuHandle ) || + ( helpMenuHandle != NULL && command.menu.menuRef == helpMenuHandle ) || wxMenuBar::MacGetWindowMenuHMenu() != NULL && command.menu.menuRef == wxMenuBar::MacGetWindowMenuHMenu() ) { wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ; @@ -499,22 +503,26 @@ wxMenu* wxFindMenuFromMacCommand( const HICommand &command , wxMenuItem* &item ) } else { - URefCon refCon ; + URefCon refCon = 0 ; GetMenuItemRefCon( command.menu.menuRef , command.menu.menuItemIndex , &refCon ) ; itemMenu = wxFindMenuFromMacMenu( command.menu.menuRef ) ; - if ( itemMenu != NULL ) - item = (wxMenuItem*) refCon ; + if ( itemMenu != NULL && refCon != 0) + item = (wxMenuItem*) refCon; } } #endif return itemMenu ; } +#endif + //---------------------------------------------------------------------- // Carbon Event Handler //---------------------------------------------------------------------- +#if wxOSX_USE_CARBON + static const EventTypeSpec eventList[] = { { kEventClassCommand, kEventProcessCommand } , @@ -550,22 +558,31 @@ wxMacAppMenuEventHandler( EventHandlerCallRef WXUNUSED(handler), if ( menu ) { - wxEventType type=0; - MenuCommand cmd=0; switch (GetEventKind(event)) { case kEventMenuOpening: - type = wxEVT_MENU_OPEN; + menu->HandleMenuOpened(); break; case kEventMenuClosed: - type = wxEVT_MENU_CLOSE; + menu->HandleMenuClosed(); break; case kEventMenuTargetItem: - cmd = cEvent.GetParameter(kEventParamMenuCommand,typeMenuCommand) ; - if (cmd != 0) - type = wxEVT_MENU_HIGHLIGHT; + { + HICommand command ; + + command.menu.menuRef = menuRef; + command.menu.menuItemIndex = cEvent.GetParameter(kEventParamMenuItemIndex,typeMenuItemIndex) ; + command.commandID = cEvent.GetParameter(kEventParamMenuCommand,typeMenuCommand) ; + if (command.commandID != 0) + { + wxMenuItem* item = NULL ; + wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ; + if ( itemMenu && item ) + itemMenu->HandleMenuItemHighlighted( item ); + } + } break; default: @@ -573,29 +590,11 @@ wxMacAppMenuEventHandler( EventHandlerCallRef WXUNUSED(handler), break; } - if ( type ) - { - wxMenuEvent wxevent(type, cmd, menu); - wxevent.SetEventObject(menu); - - wxEvtHandler* handler = menu->GetEventHandler(); - if (handler && handler->ProcessEvent(wxevent)) - { - // handled - } - else - { - wxWindow *win = menu->GetInvokingWindow(); - if (win) - win->HandleWindowEvent(wxevent); - } - } } #endif return eventNotHandledErr; } -#ifndef __LP64__ static pascal OSStatus wxMacAppCommandEventHandler( EventHandlerCallRef WXUNUSED(handler) , EventRef event , @@ -610,7 +609,6 @@ wxMacAppCommandEventHandler( EventHandlerCallRef WXUNUSED(handler) , wxMenuItem* item = NULL ; wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ; - int id = wxMacCommandToId( command.commandID ) ; if ( item ) { @@ -619,11 +617,13 @@ wxMacAppCommandEventHandler( EventHandlerCallRef WXUNUSED(handler) , switch ( cEvent.GetKind() ) { case kEventProcessCommand : - result = itemMenu->MacHandleCommandProcess( item, id ); + if ( itemMenu->HandleCommandProcess( item ) ) + result = noErr; break ; case kEventCommandUpdateStatus: - result = itemMenu->MacHandleCommandUpdateStatus( item, id ); + if ( itemMenu->HandleCommandUpdateStatus( item ) ) + result = noErr; break ; default : @@ -632,7 +632,6 @@ wxMacAppCommandEventHandler( EventHandlerCallRef WXUNUSED(handler) , } return result ; } -#endif static pascal OSStatus wxMacAppApplicationEventHandler( EventHandlerCallRef WXUNUSED(handler) , @@ -726,8 +725,9 @@ pascal OSStatus wxMacAppEventHandler( EventHandlerCallRef handler , EventRef eve } DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacAppEventHandler ) +#endif -#ifdef __WXDEBUG__ +#if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON pascal static void wxMacAssertOutputHandler(OSType WXUNUSED(componentSignature), @@ -773,31 +773,23 @@ wxMacAssertOutputHandler(OSType WXUNUSED(componentSignature), #endif } -#endif //__WXDEBUG__ - -extern "C" void macPostedEventCallback(void *WXUNUSED(unused)) -{ - wxTheApp->ProcessPendingEvents(); -} +#endif // wxDEBUG_LEVEL bool wxApp::Initialize(int& argc, wxChar **argv) { // Mac-specific -#ifdef __WXDEBUG__ +#if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON InstallDebugAssertOutputHandler( NewDebugAssertOutputHandlerUPP( wxMacAssertOutputHandler ) ); #endif - UMAInitToolbox( 4, sm_isEmbedded ) ; -// TODO CHECK Can Be Removed SetEventMask( everyEvent ) ; - // Mac OS X passes a process serial number command line argument when // the application is launched from the Finder. This argument must be // removed from the command line arguments before being handled by the // application (otherwise applications would need to handle it) if ( argc > 1 ) { - static const wxChar *ARG_PSN = _T("-psn_"); + static const wxChar *ARG_PSN = wxT("-psn_"); if ( wxStrncmp(argv[1], ARG_PSN, wxStrlen(ARG_PSN)) == 0 ) { // remove this argument @@ -826,30 +818,43 @@ bool wxApp::Initialize(int& argc, wxChar **argv) wxSetWorkingDirectory( cwd ) ; } - /* connect posted events to common-mode run loop so that wxPostEvent events - are handled even while we're in the menu or on a scrollbar */ - CFRunLoopSourceContext event_posted_context = {0}; - event_posted_context.perform = macPostedEventCallback; - m_macEventPosted = CFRunLoopSourceCreate(NULL,0,&event_posted_context); - CFRunLoopAddSource(CFRunLoopGetCurrent(), m_macEventPosted, kCFRunLoopCommonModes); - // run loop takes ownership - CFRelease(m_macEventPosted); - return true; } -AEEventHandlerUPP sODocHandler = NULL ; -AEEventHandlerUPP sGURLHandler = NULL ; -AEEventHandlerUPP sOAppHandler = NULL ; -AEEventHandlerUPP sPDocHandler = NULL ; -AEEventHandlerUPP sRAppHandler = NULL ; -AEEventHandlerUPP sQuitHandler = NULL ; +#if wxOSX_USE_COCOA_OR_CARBON +bool wxApp::CallOnInit() +{ + wxMacAutoreleasePool autoreleasepool; + return OnInit(); +} +#endif bool wxApp::OnInitGui() { if ( !wxAppBase::OnInitGui() ) return false ; -#ifndef __LP64__ + + if ( !DoInitGui() ) + return false; + + return true ; +} + +bool wxApp::ProcessIdle() +{ + wxMacAutoreleasePool autoreleasepool; + return wxAppBase::ProcessIdle(); +} + +int wxApp::OnRun() +{ + wxMacAutoreleasePool pool; + return wxAppBase::OnRun(); +} + +#if wxOSX_USE_CARBON +bool wxApp::DoInitGui() +{ InstallStandardEventHandler( GetApplicationEventTarget() ) ; if (!sm_isEmbedded) { @@ -857,7 +862,6 @@ bool wxApp::OnInitGui() GetwxMacAppEventHandlerUPP(), GetEventTypeCount(eventList), eventList, wxTheApp, (EventHandlerRef *)&(wxTheApp->m_macEventHandler)); } -#endif if (!sm_isEmbedded) { @@ -885,24 +889,11 @@ bool wxApp::OnInitGui() if ( !wxMacInitCocoa() ) return false; - return true ; + return true; } -void wxApp::CleanUp() +void wxApp::DoCleanUp() { -#if wxUSE_TOOLTIPS - wxToolTip::RemoveToolTips() ; -#endif - - if (m_macEventPosted) - { - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_macEventPosted, kCFRunLoopCommonModes); - m_macEventPosted = NULL; - } - - // One last chance for pending objects to be cleaned up - wxTheApp->DeletePendingObjects(); - if (!sm_isEmbedded) RemoveEventHandler( (EventHandlerRef)(wxTheApp->m_macEventHandler) ); @@ -928,6 +919,18 @@ void wxApp::CleanUp() DisposeAEEventHandlerUPP( sRAppHandler ) ; DisposeAEEventHandlerUPP( sQuitHandler ) ; } +} + +#endif + +void wxApp::CleanUp() +{ + wxMacAutoreleasePool autoreleasepool; +#if wxUSE_TOOLTIPS + wxToolTip::RemoveToolTips() ; +#endif + + DoCleanUp(); wxAppBase::CleanUp(); } @@ -936,7 +939,7 @@ void wxApp::CleanUp() // misc initialization stuff //---------------------------------------------------------------------- -#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 +#if wxOSX_USE_CARBON && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 bool wxMacConvertEventToRecord( EventRef event , EventRecord *rec) { OSStatus err = noErr ; @@ -1034,7 +1037,33 @@ wxApp::wxApp() m_macCurrentEvent = NULL ; m_macCurrentEventHandlerCallRef = NULL ; - m_macEventPosted = NULL ; + m_macPool = new wxMacAutoreleasePool(); +} + +wxApp::~wxApp() +{ + if (m_macPool) + delete m_macPool; +} + +CFMutableArrayRef GetAutoReleaseArray() +{ + static CFMutableArrayRef array = 0; + if ( array == 0) + array= CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks); + return array; +} + +void wxApp::MacAddToAutorelease( void* cfrefobj ) +{ + CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj ); +} + +void wxApp::MacReleaseAutoreleasePool() +{ + if (m_macPool) + delete m_macPool; + m_macPool = new wxMacAutoreleasePool(); } void wxApp::OnIdle(wxIdleEvent& WXUNUSED(event)) @@ -1043,19 +1072,20 @@ void wxApp::OnIdle(wxIdleEvent& WXUNUSED(event)) // either events to the threads other than main or events posted with // wxPostEvent() functions #ifndef __WXUNIVERSAL__ +#if wxUSE_MENUS if (!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar()) wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar(); #endif +#endif + CFArrayRemoveAllValues( GetAutoReleaseArray() ); } void wxApp::WakeUpIdle() { - if (m_macEventPosted) - { - CFRunLoopSourceSignal(m_macEventPosted); - } + wxEventLoopBase * const loop = wxEventLoopBase::GetActive(); - wxMacWakeUp() ; + if ( loop ) + loop->WakeUp(); } void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event)) @@ -1068,110 +1098,24 @@ void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event)) // user can veto the close, and therefore the end session. void wxApp::OnQueryEndSession(wxCloseEvent& event) { - if (GetTopWindow()) + if ( !wxDialog::OSXHasModalDialogsOpen() ) { - if (!GetTopWindow()->Close(!event.CanVeto())) - event.Veto(true); - } -} - -extern "C" void wxCYield() ; -void wxCYield() -{ - wxYield() ; -} - -// Yield to other processes - -bool wxApp::Yield(bool onlyIfNeeded) -{ - if (s_inYield) - { - if ( !onlyIfNeeded ) + if (GetTopWindow()) { - wxFAIL_MSG( wxT("wxYield called recursively" ) ); + if (!GetTopWindow()->Close(!event.CanVeto())) + event.Veto(true); } - - return false; } - -#if wxUSE_THREADS - // Yielding from a non-gui thread needs to bail out, otherwise we end up - // possibly sending events in the thread too. - if ( !wxThread::IsMain() ) - { - return true; - } -#endif // wxUSE_THREADS - - s_inYield = true; - - // by definition yield should handle all non-processed events - - EventRef theEvent; - - OSStatus status = noErr ; - - while ( status == noErr ) + else { - s_inReceiveEvent = true ; - status = ReceiveNextEvent(0, NULL,kEventDurationNoWait,true,&theEvent) ; - s_inReceiveEvent = false ; - - if ( status == eventLoopTimedOutErr ) - { - // make sure next time the event loop will trigger idle events - sleepTime = kEventDurationNoWait ; - } - else if ( status == eventLoopQuitErr ) - { - // according to QA1061 this may also occur when a WakeUp Process - // is executed - } - else - { - MacHandleOneEvent( theEvent ) ; - ReleaseEvent(theEvent); - } + event.Veto(true); } - - s_inYield = false; - - return true; } -void wxApp::MacDoOneEvent() +extern "C" void wxCYield() ; +void wxCYield() { - wxMacAutoreleasePool autoreleasepool; - EventRef theEvent; - - s_inReceiveEvent = true ; - OSStatus status = ReceiveNextEvent(0, NULL, sleepTime, true, &theEvent) ; - s_inReceiveEvent = false ; - - switch (status) - { - case eventLoopTimedOutErr : - if ( wxTheApp->ProcessIdle() ) - sleepTime = kEventDurationNoWait ; - else - sleepTime = kEventDurationSecond; - break; - - case eventLoopQuitErr : - // according to QA1061 this may also occur - // when a WakeUp Process is executed - break; - - default: - MacHandleOneEvent( theEvent ) ; - ReleaseEvent( theEvent ); - sleepTime = kEventDurationNoWait ; - break; - } - // repeaters - - DeletePendingObjects() ; + wxYield() ; } // virtual @@ -1180,34 +1124,250 @@ void wxApp::MacHandleUnhandledEvent( WXEVENTREF WXUNUSED(evr) ) // Override to process unhandled events as you please } -CFMutableArrayRef GetAutoReleaseArray() +#if wxOSX_USE_COCOA_OR_CARBON + +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 + +// adding forward compatible defines for keys that are different on different keyboard layouts +// see Inside Mac Volume V + +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +// defines for keys that are the same on all layouts + +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +#endif + +CGKeyCode wxCharCodeWXToOSX(wxKeyCode code) { - static CFMutableArrayRef array = 0; - if ( array == 0) - array= CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks); - return array; -} - -void wxApp::MacHandleOneEvent( WXEVENTREF evr ) -{ - EventTargetRef theTarget; - theTarget = GetEventDispatcherTarget(); - m_macCurrentEvent = evr ; - - OSStatus status = SendEventToEventTarget((EventRef) evr , theTarget); - if (status == eventNotHandledErr) - MacHandleUnhandledEvent(evr); - -#if wxUSE_THREADS - wxMutexGuiLeaveOrEnter(); -#endif // wxUSE_THREADS - - CFArrayRemoveAllValues( GetAutoReleaseArray() ); -} - -void wxApp::MacAddToAutorelease( void* cfrefobj ) -{ - CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj ); + CGKeyCode keycode; + + switch (code) + { + case 'a': case 'A': keycode = kVK_ANSI_A; break; + case 'b': case 'B': keycode = kVK_ANSI_B; break; + case 'c': case 'C': keycode = kVK_ANSI_C; break; + case 'd': case 'D': keycode = kVK_ANSI_D; break; + case 'e': case 'E': keycode = kVK_ANSI_E; break; + case 'f': case 'F': keycode = kVK_ANSI_F; break; + case 'g': case 'G': keycode = kVK_ANSI_G; break; + case 'h': case 'H': keycode = kVK_ANSI_H; break; + case 'i': case 'I': keycode = kVK_ANSI_I; break; + case 'j': case 'J': keycode = kVK_ANSI_J; break; + case 'k': case 'K': keycode = kVK_ANSI_K; break; + case 'l': case 'L': keycode = kVK_ANSI_L; break; + case 'm': case 'M': keycode = kVK_ANSI_M; break; + case 'n': case 'N': keycode = kVK_ANSI_N; break; + case 'o': case 'O': keycode = kVK_ANSI_O; break; + case 'p': case 'P': keycode = kVK_ANSI_P; break; + case 'q': case 'Q': keycode = kVK_ANSI_Q; break; + case 'r': case 'R': keycode = kVK_ANSI_R; break; + case 's': case 'S': keycode = kVK_ANSI_S; break; + case 't': case 'T': keycode = kVK_ANSI_T; break; + case 'u': case 'U': keycode = kVK_ANSI_U; break; + case 'v': case 'V': keycode = kVK_ANSI_V; break; + case 'w': case 'W': keycode = kVK_ANSI_W; break; + case 'x': case 'X': keycode = kVK_ANSI_X; break; + case 'y': case 'Y': keycode = kVK_ANSI_Y; break; + case 'z': case 'Z': keycode = kVK_ANSI_Z; break; + + case '0': keycode = kVK_ANSI_0; break; + case '1': keycode = kVK_ANSI_1; break; + case '2': keycode = kVK_ANSI_2; break; + case '3': keycode = kVK_ANSI_3; break; + case '4': keycode = kVK_ANSI_4; break; + case '5': keycode = kVK_ANSI_5; break; + case '6': keycode = kVK_ANSI_6; break; + case '7': keycode = kVK_ANSI_7; break; + case '8': keycode = kVK_ANSI_8; break; + case '9': keycode = kVK_ANSI_9; break; + + case WXK_BACK: keycode = kVK_Delete; break; + case WXK_TAB: keycode = kVK_Tab; break; + case WXK_RETURN: keycode = kVK_Return; break; + case WXK_ESCAPE: keycode = kVK_Escape; break; + case WXK_SPACE: keycode = kVK_Space; break; + case WXK_DELETE: keycode = kVK_Delete; break; + + case WXK_SHIFT: keycode = kVK_Shift; break; + case WXK_ALT: keycode = kVK_Option; break; + case WXK_CONTROL: keycode = kVK_Control; break; + case WXK_COMMAND: keycode = kVK_Command; break; + + case WXK_CAPITAL: keycode = kVK_CapsLock; break; + case WXK_END: keycode = kVK_End; break; + case WXK_HOME: keycode = kVK_Home; break; + case WXK_LEFT: keycode = kVK_LeftArrow; break; + case WXK_UP: keycode = kVK_UpArrow; break; + case WXK_RIGHT: keycode = kVK_RightArrow; break; + case WXK_DOWN: keycode = kVK_DownArrow; break; + + case WXK_HELP: keycode = kVK_Help; break; + + + case WXK_NUMPAD0: keycode = kVK_ANSI_Keypad0; break; + case WXK_NUMPAD1: keycode = kVK_ANSI_Keypad1; break; + case WXK_NUMPAD2: keycode = kVK_ANSI_Keypad2; break; + case WXK_NUMPAD3: keycode = kVK_ANSI_Keypad3; break; + case WXK_NUMPAD4: keycode = kVK_ANSI_Keypad4; break; + case WXK_NUMPAD5: keycode = kVK_ANSI_Keypad5; break; + case WXK_NUMPAD6: keycode = kVK_ANSI_Keypad6; break; + case WXK_NUMPAD7: keycode = kVK_ANSI_Keypad7; break; + case WXK_NUMPAD8: keycode = kVK_ANSI_Keypad8; break; + case WXK_NUMPAD9: keycode = kVK_ANSI_Keypad9; break; + case WXK_F1: keycode = kVK_F1; break; + case WXK_F2: keycode = kVK_F2; break; + case WXK_F3: keycode = kVK_F3; break; + case WXK_F4: keycode = kVK_F4; break; + case WXK_F5: keycode = kVK_F5; break; + case WXK_F6: keycode = kVK_F6; break; + case WXK_F7: keycode = kVK_F7; break; + case WXK_F8: keycode = kVK_F8; break; + case WXK_F9: keycode = kVK_F9; break; + case WXK_F10: keycode = kVK_F10; break; + case WXK_F11: keycode = kVK_F11; break; + case WXK_F12: keycode = kVK_F12; break; + case WXK_F13: keycode = kVK_F13; break; + case WXK_F14: keycode = kVK_F14; break; + case WXK_F15: keycode = kVK_F15; break; + case WXK_F16: keycode = kVK_F16; break; + case WXK_F17: keycode = kVK_F17; break; + case WXK_F18: keycode = kVK_F18; break; + case WXK_F19: keycode = kVK_F19; break; + case WXK_F20: keycode = kVK_F20; break; + + case WXK_PAGEUP: keycode = kVK_PageUp; break; + case WXK_PAGEDOWN: keycode = kVK_PageDown; break; + + case WXK_NUMPAD_DELETE: keycode = kVK_ANSI_KeypadClear; break; + case WXK_NUMPAD_EQUAL: keycode = kVK_ANSI_KeypadEquals; break; + case WXK_NUMPAD_MULTIPLY: keycode = kVK_ANSI_KeypadMultiply; break; + case WXK_NUMPAD_ADD: keycode = kVK_ANSI_KeypadPlus; break; + case WXK_NUMPAD_SUBTRACT: keycode = kVK_ANSI_KeypadMinus; break; + case WXK_NUMPAD_DECIMAL: keycode = kVK_ANSI_KeypadDecimal; break; + case WXK_NUMPAD_DIVIDE: keycode = kVK_ANSI_KeypadDivide; break; + + default: + wxLogDebug( "Unrecognised keycode %d", code ); + keycode = static_cast(-1); + } + + return keycode; } long wxMacTranslateKey(unsigned char key, unsigned char code) @@ -1375,6 +1535,13 @@ int wxMacKeyCodeToModifier(wxKeyCode key) return 0; } } +#endif + +#if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 + +// defined in utils.mm + +#elif wxOSX_USE_COCOA_OR_CARBON wxMouseState wxGetMouseState() { @@ -1398,6 +1565,8 @@ wxMouseState wxGetMouseState() return ms; } +#endif + // TODO : once the new key/char handling is tested, move all the code to wxWindow bool wxApp::MacSendKeyDownEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar ) @@ -1405,47 +1574,10 @@ bool wxApp::MacSendKeyDownEvent( wxWindow* focus , long keymessage , long modifi if ( !focus ) return false ; - bool handled; wxKeyEvent event(wxEVT_KEY_DOWN) ; MacCreateKeyEvent( event, focus , keymessage , modifiers , when , wherex , wherey , uniChar ) ; - handled = focus->HandleWindowEvent( event ) ; - if ( handled && event.GetSkipped() ) - handled = false ; - -#if wxUSE_ACCEL - if ( !handled ) - { - wxWindow *ancestor = focus; - while (ancestor) - { - int command = ancestor->GetAcceleratorTable()->GetCommand( event ); - if (command != -1) - { - wxEvtHandler * const handler = ancestor->GetEventHandler(); - - wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command ); - handled = handler->ProcessEvent( command_event ); - - if ( !handled ) - { - // accelerators can also be used with buttons, try them too - command_event.SetEventType(wxEVT_COMMAND_BUTTON_CLICKED); - handled = handler->ProcessEvent( command_event ); - } - - break; - } - - if (ancestor->IsTopLevel()) - break; - - ancestor = ancestor->GetParent(); - } - } -#endif // wxUSE_ACCEL - - return handled ; + return focus->OSXHandleKeyEvent(event); } bool wxApp::MacSendKeyUpEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar ) @@ -1453,25 +1585,23 @@ bool wxApp::MacSendKeyUpEvent( wxWindow* focus , long keymessage , long modifier if ( !focus ) return false ; - bool handled; wxKeyEvent event( wxEVT_KEY_UP ) ; MacCreateKeyEvent( event, focus , keymessage , modifiers , when , wherex , wherey , uniChar ) ; - handled = focus->HandleWindowEvent( event ) ; - return handled ; + return focus->OSXHandleKeyEvent(event) ; } bool wxApp::MacSendCharEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar ) { if ( !focus ) return false ; - wxKeyEvent event(wxEVT_CHAR) ; MacCreateKeyEvent( event, focus , keymessage , modifiers , when , wherex , wherey , uniChar ) ; - long keyval = event.m_keyCode ; bool handled = false ; +#if wxOSX_USE_CARBON + long keyval = event.m_keyCode ; wxNonOwnedWindow *tlw = focus->MacGetTopLevelWindow() ; if (tlw) @@ -1512,12 +1642,12 @@ bool wxApp::MacSendCharEvent( wxWindow* focus , long keymessage , long modifiers } // backdoor handler for default return and command escape - if ( !handled && (!focus->IsKindOf(CLASSINFO(wxControl) ) || !focus->MacCanFocus() ) ) + if ( !handled && (!focus->IsKindOf(CLASSINFO(wxControl) ) || !focus->AcceptsFocus() ) ) { // if window is not having a focus still testing for default enter or cancel // TODO: add the UMA version for ActiveNonFloatingWindow #ifndef __LP64__ - wxWindow* focus = wxFindWinFromMacWindow( FrontWindow() ) ; + wxWindow* focus = wxNonOwnedWindow::GetFromWXWindow( (WXWindow) FrontWindow() ) ; if ( focus ) { if ( keyval == WXK_RETURN || keyval == WXK_NUMPAD_ENTER ) @@ -1546,12 +1676,15 @@ bool wxApp::MacSendCharEvent( wxWindow* focus , long keymessage , long modifiers } #endif } +#endif return handled ; } // This method handles common code for SendKeyDown, SendKeyUp, and SendChar events. void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar ) { +#if wxOSX_USE_COCOA_OR_CARBON + short keycode, keychar ; keychar = short(keymessage & charCodeMask); @@ -1561,7 +1694,7 @@ void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymess // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier // and look at the character after #ifdef __LP64__ - // TODO new implementation using TextInputSources + // TODO new implementation using TextInputSources #else UInt32 state = 0; UInt32 keyInfo = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache), ( modifiers & (~(controlKey | shiftKey | optionKey))) | keycode, &state); @@ -1582,34 +1715,34 @@ void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymess { keyval = (keyval - '0') + WXK_NUMPAD0; } - else if (keycode >= 65 && keycode <= 81) + else if (keycode >= 65 && keycode <= 81) { switch (keycode) { case 76 : keyval = WXK_NUMPAD_ENTER; break; - + case 81: keyval = WXK_NUMPAD_EQUAL; break; - + case 67: keyval = WXK_NUMPAD_MULTIPLY; break; - + case 75: keyval = WXK_NUMPAD_DIVIDE; break; - + case 78: keyval = WXK_NUMPAD_SUBTRACT; break; - + case 69: keyval = WXK_NUMPAD_ADD; break; - + case 65: keyval = WXK_NUMPAD_DECIMAL; break; @@ -1618,7 +1751,7 @@ void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymess } } } - + event.m_shiftDown = modifiers & shiftKey; event.m_controlDown = modifiers & controlKey; event.m_altDown = modifiers & optionKey; @@ -1634,15 +1767,27 @@ void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymess event.m_y = wherey; event.SetTimestamp(when); event.SetEventObject(focus); +#else + wxUnusedVar(event); + wxUnusedVar(focus); + wxUnusedVar(keymessage); + wxUnusedVar(modifiers); + wxUnusedVar(when); + wxUnusedVar(wherex); + wxUnusedVar(wherey); + wxUnusedVar(uniChar); +#endif } void wxApp::MacHideApp() { +#if wxOSX_USE_CARBON wxMacCarbonEvent event( kEventClassCommand , kEventCommandProcess ); HICommand command; memset( &command, 0 , sizeof(command) ); command.commandID = kHICommandHide ; - event.SetParameter(kEventParamDirectObject, command ); + event.SetParameter(kEventParamDirectObject, command ); SendEventToApplication( event ); +#endif }