1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/app.cpp
4 // Author: Stefan Csomor
7 // Copyright: (c) Stefan Csomor
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 #include "wx/wxprec.h"
19 #include "wx/window.h"
22 #include "wx/button.h"
26 #include "wx/palette.h"
28 #include "wx/cursor.h"
29 #include "wx/dialog.h"
30 #include "wx/msgdlg.h"
31 #include "wx/textctrl.h"
32 #include "wx/memory.h"
33 #include "wx/gdicmn.h"
34 #include "wx/module.h"
37 #include "wx/tooltip.h"
38 #include "wx/docview.h"
39 #include "wx/filename.h"
41 #include "wx/thread.h"
42 #include "wx/evtloop.h"
48 #include "wx/osx/uma.h"
50 #include "wx/osx/private.h"
53 #if defined(WXMAKINGDLL_CORE)
54 # include <mach-o/dyld.h>
57 // Keep linker from discarding wxStockGDIMac
58 wxFORCE_LINK_MODULE(gdiobj
)
60 IMPLEMENT_DYNAMIC_CLASS(wxApp
, wxEvtHandler
)
61 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
)
62 EVT_IDLE(wxApp::OnIdle
)
63 EVT_END_SESSION(wxApp::OnEndSession
)
64 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession
)
68 // platform specific static variables
69 static const short kwxMacAppleMenuId
= 1 ;
71 wxWindow
* wxApp::s_captureWindow
= NULL
;
72 long wxApp::s_lastModifiers
= 0 ;
74 long wxApp::s_macAboutMenuItemId
= wxID_ABOUT
;
75 long wxApp::s_macPreferencesMenuItemId
= wxID_PREFERENCES
;
76 long wxApp::s_macExitMenuItemId
= wxID_EXIT
;
77 wxString
wxApp::s_macHelpMenuTitleName
= wxT("&Help") ;
79 bool wxApp::sm_isEmbedded
= false; // Normally we're not a plugin
83 //----------------------------------------------------------------------
84 // Core Apple Event Support
85 //----------------------------------------------------------------------
87 AEEventHandlerUPP sODocHandler
= NULL
;
88 AEEventHandlerUPP sGURLHandler
= NULL
;
89 AEEventHandlerUPP sOAppHandler
= NULL
;
90 AEEventHandlerUPP sPDocHandler
= NULL
;
91 AEEventHandlerUPP sRAppHandler
= NULL
;
92 AEEventHandlerUPP sQuitHandler
= NULL
;
94 pascal OSErr
AEHandleODoc( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon refcon
) ;
95 pascal OSErr
AEHandleOApp( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon refcon
) ;
96 pascal OSErr
AEHandlePDoc( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon refcon
) ;
97 pascal OSErr
AEHandleQuit( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon refcon
) ;
98 pascal OSErr
AEHandleRApp( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon refcon
) ;
99 pascal OSErr
AEHandleGURL( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon refcon
) ;
101 pascal OSErr
AEHandleODoc( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon
WXUNUSED(refcon
) )
103 return wxTheApp
->MacHandleAEODoc( (AppleEvent
*) event
, reply
) ;
106 pascal OSErr
AEHandleOApp( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon
WXUNUSED(refcon
) )
108 return wxTheApp
->MacHandleAEOApp( (AppleEvent
*) event
, reply
) ;
111 pascal OSErr
AEHandlePDoc( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon
WXUNUSED(refcon
) )
113 return wxTheApp
->MacHandleAEPDoc( (AppleEvent
*) event
, reply
) ;
116 pascal OSErr
AEHandleQuit( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon
WXUNUSED(refcon
) )
118 return wxTheApp
->MacHandleAEQuit( (AppleEvent
*) event
, reply
) ;
121 pascal OSErr
AEHandleRApp( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon
WXUNUSED(refcon
) )
123 return wxTheApp
->MacHandleAERApp( (AppleEvent
*) event
, reply
) ;
126 pascal OSErr
AEHandleGURL( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon
WXUNUSED(refcon
) )
128 return wxTheApp
->MacHandleAEGURL((WXEVENTREF
*)event
, reply
) ;
132 // AEODoc Calls MacOpenFiles with all of the files passed
134 short wxApp::MacHandleAEODoc(const WXEVENTREF event
, WXEVENTREF
WXUNUSED(reply
))
138 DescType returnedType
;
144 err
= AEGetParamDesc((AppleEvent
*)event
, keyDirectObject
, typeAEList
,&docList
);
148 err
= AECountItems(&docList
, &itemsInList
);
152 ProcessSerialNumber PSN
;
153 PSN
.highLongOfPSN
= 0 ;
154 PSN
.lowLongOfPSN
= kCurrentProcess
;
155 SetFrontProcess( &PSN
) ;
160 wxArrayString fileNames
;
161 for (i
= 1; i
<= itemsInList
; i
++)
164 &docList
, i
, typeFSRef
, &keywd
, &returnedType
,
165 (Ptr
)&theRef
, sizeof(theRef
), &actualSize
);
170 fName
= wxMacFSRefToPath( &theRef
) ;
172 fileNames
.Add(fName
);
175 MacOpenFiles(fileNames
);
180 // AEODoc Calls MacOpenURL on the url passed
182 short wxApp::MacHandleAEGURL(const WXEVENTREF event
, WXEVENTREF
WXUNUSED(reply
))
184 DescType returnedType
;
187 OSErr err
= AEGetParamPtr((AppleEvent
*)event
, keyDirectObject
, typeChar
,
188 &returnedType
, url
, sizeof(url
)-1,
193 url
[actualSize
] = '\0'; // Terminate the C string
195 ProcessSerialNumber PSN
;
196 PSN
.highLongOfPSN
= 0 ;
197 PSN
.lowLongOfPSN
= kCurrentProcess
;
198 SetFrontProcess( &PSN
) ;
200 MacOpenURL(wxString(url
, wxConvUTF8
));
205 // AEPDoc Calls MacPrintFile on each of the files passed
207 short wxApp::MacHandleAEPDoc(const WXEVENTREF event
, WXEVENTREF
WXUNUSED(reply
))
211 DescType returnedType
;
217 err
= AEGetParamDesc((AppleEvent
*)event
, keyDirectObject
, typeAEList
,&docList
);
221 err
= AECountItems(&docList
, &itemsInList
);
225 ProcessSerialNumber PSN
;
226 PSN
.highLongOfPSN
= 0 ;
227 PSN
.lowLongOfPSN
= kCurrentProcess
;
228 SetFrontProcess( &PSN
) ;
233 for (i
= 1; i
<= itemsInList
; i
++)
236 &docList
, i
, typeFSRef
, &keywd
, &returnedType
,
237 (Ptr
)&theRef
, sizeof(theRef
), &actualSize
);
242 fName
= wxMacFSRefToPath( &theRef
) ;
250 // AEOApp calls MacNewFile
252 short wxApp::MacHandleAEOApp(const WXEVENTREF
WXUNUSED(event
) , WXEVENTREF
WXUNUSED(reply
))
258 // AEQuit attempts to quit the application
260 short wxApp::MacHandleAEQuit(const WXEVENTREF
WXUNUSED(event
) , WXEVENTREF
WXUNUSED(reply
))
263 wxTheApp
->OnQueryEndSession(event
);
264 if ( !event
.GetVeto() )
267 wxTheApp
->OnEndSession(event
);
272 // AEROApp calls MacReopenApp
274 short wxApp::MacHandleAERApp(const WXEVENTREF
WXUNUSED(event
) , WXEVENTREF
WXUNUSED(reply
))
283 //----------------------------------------------------------------------
284 // Support Routines linking the Mac...File Calls to the Document Manager
285 //----------------------------------------------------------------------
287 void wxApp::MacOpenFiles(const wxArrayString
& fileNames
)
290 const size_t fileCount
= fileNames
.GetCount();
291 for (i
= 0; i
< fileCount
; i
++)
293 MacOpenFile(fileNames
[i
]);
297 void wxApp::MacOpenFile(const wxString
& fileName
)
299 #if wxUSE_DOC_VIEW_ARCHITECTURE
300 wxDocManager
* dm
= wxDocManager::GetDocumentManager() ;
302 dm
->CreateDocument(fileName
, wxDOC_SILENT
) ;
306 void wxApp::MacOpenURL(const wxString
& WXUNUSED(url
) )
310 void wxApp::MacPrintFile(const wxString
& fileName
)
312 #if wxUSE_DOC_VIEW_ARCHITECTURE
314 #if wxUSE_PRINTING_ARCHITECTURE
315 wxDocManager
* dm
= wxDocManager::GetDocumentManager() ;
318 wxDocument
*doc
= dm
->CreateDocument(fileName
, wxDOC_SILENT
) ;
321 wxView
* view
= doc
->GetFirstView() ;
324 wxPrintout
*printout
= view
->OnCreatePrintout();
328 printer
.Print(view
->GetFrame(), printout
, true);
335 doc
->DeleteAllViews();
336 dm
->RemoveDocument(doc
) ;
347 void wxApp::MacNewFile()
351 void wxApp::MacReopenApp()
354 // if there is no open window -> create a new one
355 // if all windows are hidden -> show the first
356 // if some windows are not hidden -> do nothing
358 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetFirst();
365 wxTopLevelWindow
* firstIconized
= NULL
;
366 wxTopLevelWindow
* firstHidden
= NULL
;
369 wxTopLevelWindow
* win
= (wxTopLevelWindow
*) node
->GetData();
370 if ( !win
->IsShown() )
372 // make sure we don't show 'virtual toplevel windows' like wxTaskBarIconWindow
373 if ( firstHidden
== NULL
&& ( wxDynamicCast( win
, wxFrame
) || wxDynamicCast( win
, wxDialog
) ) )
376 else if ( win
->IsIconized() )
378 if ( firstIconized
== NULL
)
379 firstIconized
= win
;
383 // we do have a visible, non-iconized toplevelwindow -> do nothing
387 node
= node
->GetNext();
391 firstIconized
->Iconize( false ) ;
393 // showing hidden windows is not really always a good solution, also non-modal dialogs when closed end up
394 // as hidden tlws, we don't want to reshow those, so let's just reopen the minimized a.k.a. iconized tlws
395 // unless we find a regression ...
397 else if ( firstHidden
)
398 firstHidden
->Show( true );
403 #if wxOSX_USE_COCOA_OR_IPHONE
404 void wxApp::OSXOnWillFinishLaunching()
407 m_onInitResult
= OnInit();
411 void wxApp::OSXOnDidFinishLaunching()
415 void wxApp::OSXOnWillTerminate()
418 event
.SetCanVeto(false);
419 wxTheApp
->OnEndSession(event
);
422 bool wxApp::OSXOnShouldTerminate()
425 wxTheApp
->OnQueryEndSession(event
);
426 return !event
.GetVeto();
430 //----------------------------------------------------------------------
431 // Macintosh CommandID support - converting between native and wx IDs
432 //----------------------------------------------------------------------
434 // if no native match they just return the passed-in id
444 IdPair gCommandIds
[] =
446 { kHICommandCut
, wxID_CUT
} ,
447 { kHICommandCopy
, wxID_COPY
} ,
448 { kHICommandPaste
, wxID_PASTE
} ,
449 { kHICommandSelectAll
, wxID_SELECTALL
} ,
450 { kHICommandClear
, wxID_CLEAR
} ,
451 { kHICommandUndo
, wxID_UNDO
} ,
452 { kHICommandRedo
, wxID_REDO
} ,
455 int wxMacCommandToId( UInt32 macCommandId
)
459 switch ( macCommandId
)
461 case kHICommandPreferences
:
462 wxid
= wxApp::s_macPreferencesMenuItemId
;
465 case kHICommandQuit
:
466 wxid
= wxApp::s_macExitMenuItemId
;
469 case kHICommandAbout
:
470 wxid
= wxApp::s_macAboutMenuItemId
;
475 for ( size_t i
= 0 ; i
< WXSIZEOF(gCommandIds
) ; ++i
)
477 if ( gCommandIds
[i
].macId
== macCommandId
)
479 wxid
= gCommandIds
[i
].wxId
;
488 wxid
= (int) macCommandId
;
493 UInt32
wxIdToMacCommand( int wxId
)
497 if ( wxId
== wxApp::s_macPreferencesMenuItemId
)
498 macId
= kHICommandPreferences
;
499 else if (wxId
== wxApp::s_macExitMenuItemId
)
500 macId
= kHICommandQuit
;
501 else if (wxId
== wxApp::s_macAboutMenuItemId
)
502 macId
= kHICommandAbout
;
505 for ( size_t i
= 0 ; i
< WXSIZEOF(gCommandIds
) ; ++i
)
507 if ( gCommandIds
[i
].wxId
== wxId
)
509 macId
= gCommandIds
[i
].macId
;
521 wxMenu
* wxFindMenuFromMacCommand( const HICommand
&command
, wxMenuItem
* &item
)
523 wxMenu
* itemMenu
= NULL
;
524 #ifndef __WXUNIVERSAL__
527 // for 'standard' commands which don't have a wx-menu
528 if ( command
.commandID
== kHICommandPreferences
|| command
.commandID
== kHICommandQuit
|| command
.commandID
== kHICommandAbout
)
530 id
= wxMacCommandToId( command
.commandID
) ;
532 wxMenuBar
* mbar
= wxMenuBar::MacGetInstalledMenuBar() ;
534 item
= mbar
->FindItem( id
, &itemMenu
) ;
536 else if ( command
.commandID
!= 0 && command
.menu
.menuRef
!= 0 && command
.menu
.menuItemIndex
!= 0 )
538 id
= wxMacCommandToId( command
.commandID
) ;
539 // make sure it is one of our own menus, or of the 'synthetic' apple and help menus , otherwise don't touch
540 MenuItemIndex firstUserHelpMenuItem
;
541 static MenuHandle helpMenuHandle
= NULL
;
542 if ( helpMenuHandle
== NULL
)
544 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
545 helpMenuHandle
= NULL
;
548 // is it part of the application or the Help menu, then look for the id directly
549 if ( ( GetMenuHandle( kwxMacAppleMenuId
) != NULL
&& command
.menu
.menuRef
== GetMenuHandle( kwxMacAppleMenuId
) ) ||
550 ( helpMenuHandle
!= NULL
&& command
.menu
.menuRef
== helpMenuHandle
) ||
551 wxMenuBar::MacGetWindowMenuHMenu() != NULL
&& command
.menu
.menuRef
== wxMenuBar::MacGetWindowMenuHMenu() )
553 wxMenuBar
* mbar
= wxMenuBar::MacGetInstalledMenuBar() ;
555 item
= mbar
->FindItem( id
, &itemMenu
) ;
561 GetMenuItemRefCon( command
.menu
.menuRef
, command
.menu
.menuItemIndex
, &refCon
) ;
562 itemMenu
= wxFindMenuFromMacMenu( command
.menu
.menuRef
) ;
563 if ( itemMenu
!= NULL
&& refCon
!= 0)
564 item
= (wxMenuItem
*) refCon
;
573 //----------------------------------------------------------------------
574 // Carbon Event Handler
575 //----------------------------------------------------------------------
579 static const EventTypeSpec eventList
[] =
581 { kEventClassCommand
, kEventProcessCommand
} ,
582 { kEventClassCommand
, kEventCommandUpdateStatus
} ,
584 { kEventClassMenu
, kEventMenuOpening
},
585 { kEventClassMenu
, kEventMenuClosed
},
586 { kEventClassMenu
, kEventMenuTargetItem
},
588 { kEventClassApplication
, kEventAppActivated
} ,
589 { kEventClassApplication
, kEventAppDeactivated
} ,
590 // handling the quit event is not recommended by apple
591 // rather using the quit apple event - which we do
593 { kEventClassAppleEvent
, kEventAppleEvent
} ,
595 { kEventClassMouse
, kEventMouseDown
} ,
596 { kEventClassMouse
, kEventMouseMoved
} ,
597 { kEventClassMouse
, kEventMouseUp
} ,
598 { kEventClassMouse
, kEventMouseDragged
} ,
602 static pascal OSStatus
603 wxMacAppMenuEventHandler( EventHandlerCallRef
WXUNUSED(handler
),
605 void *WXUNUSED(data
) )
607 wxMacCarbonEvent
cEvent( event
) ;
608 MenuRef menuRef
= cEvent
.GetParameter
<MenuRef
>(kEventParamDirectObject
) ;
609 #ifndef __WXUNIVERSAL__
610 wxMenu
* menu
= wxFindMenuFromMacMenu( menuRef
) ;
614 switch (GetEventKind(event
))
616 case kEventMenuOpening
:
617 menu
->HandleMenuOpened();
620 case kEventMenuClosed
:
621 menu
->HandleMenuClosed();
624 case kEventMenuTargetItem
:
628 command
.menu
.menuRef
= menuRef
;
629 command
.menu
.menuItemIndex
= cEvent
.GetParameter
<MenuItemIndex
>(kEventParamMenuItemIndex
,typeMenuItemIndex
) ;
630 command
.commandID
= cEvent
.GetParameter
<MenuCommand
>(kEventParamMenuCommand
,typeMenuCommand
) ;
631 if (command
.commandID
!= 0)
633 wxMenuItem
* item
= NULL
;
634 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
635 if ( itemMenu
&& item
)
636 itemMenu
->HandleMenuItemHighlighted( item
);
642 wxFAIL_MSG(wxT("Unexpected menu event kind"));
648 return eventNotHandledErr
;
651 static pascal OSStatus
652 wxMacAppCommandEventHandler( EventHandlerCallRef
WXUNUSED(handler
) ,
654 void *WXUNUSED(data
) )
656 OSStatus result
= eventNotHandledErr
;
660 wxMacCarbonEvent
cEvent( event
) ;
661 cEvent
.GetParameter
<HICommand
>(kEventParamDirectObject
,typeHICommand
,&command
) ;
663 wxMenuItem
* item
= NULL
;
664 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
668 wxASSERT( itemMenu
!= NULL
) ;
670 switch ( cEvent
.GetKind() )
672 case kEventProcessCommand
:
673 if ( itemMenu
->HandleCommandProcess( item
) )
677 case kEventCommandUpdateStatus
:
678 if ( itemMenu
->HandleCommandUpdateStatus( item
) )
689 static pascal OSStatus
690 wxMacAppApplicationEventHandler( EventHandlerCallRef
WXUNUSED(handler
) ,
692 void *WXUNUSED(data
) )
694 OSStatus result
= eventNotHandledErr
;
695 switch ( GetEventKind( event
) )
697 case kEventAppActivated
:
699 wxTheApp
->SetActive( true , NULL
) ;
703 case kEventAppDeactivated
:
705 wxTheApp
->SetActive( false , NULL
) ;
716 pascal OSStatus
wxMacAppEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
718 EventRef formerEvent
= (EventRef
) wxTheApp
->MacGetCurrentEvent() ;
719 EventHandlerCallRef formerEventHandlerCallRef
= (EventHandlerCallRef
) wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
720 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
722 OSStatus result
= eventNotHandledErr
;
723 switch ( GetEventClass( event
) )
726 case kEventClassCommand
:
727 result
= wxMacAppCommandEventHandler( handler
, event
, data
) ;
730 case kEventClassApplication
:
731 result
= wxMacAppApplicationEventHandler( handler
, event
, data
) ;
734 case kEventClassMenu
:
735 result
= wxMacAppMenuEventHandler( handler
, event
, data
) ;
738 case kEventClassMouse
:
740 wxMacCarbonEvent
cEvent( event
) ;
743 Point screenMouseLocation
= cEvent
.GetParameter
<Point
>(kEventParamMouseLocation
) ;
744 ::FindWindow(screenMouseLocation
, &window
);
745 // only send this event in case it had not already been sent to a tlw, as we get
746 // double events otherwise (in case event.skip) was called
747 if ( window
== NULL
)
748 result
= wxMacTopLevelMouseEventHandler( handler
, event
, NULL
) ;
752 case kEventClassAppleEvent
:
753 result
= AEProcessEvent(event
);
760 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerEventHandlerCallRef
) ;
765 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacAppEventHandler
)
768 #if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
771 wxMacAssertOutputHandler(OSType
WXUNUSED(componentSignature
),
772 UInt32
WXUNUSED(options
),
773 const char *assertionString
,
774 const char *exceptionLabelString
,
775 const char *errorString
,
776 const char *fileName
,
779 ConstStr255Param
WXUNUSED(outputMsg
))
781 // flow into assert handling
782 wxString fileNameStr
;
783 wxString assertionStr
;
784 wxString exceptionStr
;
788 fileNameStr
= wxString(fileName
, wxConvLocal
);
789 assertionStr
= wxString(assertionString
, wxConvLocal
);
790 exceptionStr
= wxString((exceptionLabelString
!=0) ? exceptionLabelString
: "", wxConvLocal
) ;
791 errorStr
= wxString((errorString
!=0) ? errorString
: "", wxConvLocal
) ;
793 fileNameStr
= fileName
;
794 assertionStr
= assertionString
;
795 exceptionStr
= (exceptionLabelString
!=0) ? exceptionLabelString
: "" ;
796 errorStr
= (errorString
!=0) ? errorString
: "" ;
801 wxLogDebug( wxT("AssertMacros: %s %s %s file: %s, line: %ld (value %p)\n"),
802 assertionStr
.c_str() ,
803 exceptionStr
.c_str() ,
805 fileNameStr
.c_str(), lineNumber
,
809 wxOnAssert(fileNameStr
, lineNumber
, assertionStr
,
810 wxString::Format( wxT("%s %s value (%p)") , exceptionStr
, errorStr
, value
) ) ;
814 #endif // wxDEBUG_LEVEL
816 bool wxApp::Initialize(int& argc
, wxChar
**argv
)
820 #if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
821 InstallDebugAssertOutputHandler( NewDebugAssertOutputHandlerUPP( wxMacAssertOutputHandler
) );
825 Cocoa supports -Key value options which set the user defaults key "Key"
826 to the value "value" Some of them are very handy for debugging like
827 -NSShowAllViews YES. Cocoa picks these up from the real argv so
828 our removal of them from the wx copy of it does not affect Cocoa's
831 We basically just assume that any "-NS" option and its following
832 argument needs to be removed from argv. We hope that user code does
833 not expect to see -NS options and indeed it's probably a safe bet
834 since most user code accepting options is probably using the
835 double-dash GNU-style syntax.
837 for(int i
=1; i
< argc
; ++i
)
839 static const wxChar
*ARG_NS
= wxT("-NS");
840 if( wxStrncmp(argv
[i
], ARG_NS
, wxStrlen(ARG_NS
)) == 0 )
842 // Only eat this option if it has an argument
845 memmove(argv
+ i
, argv
+ i
+ 2, (argc
-i
-1)*sizeof(wxChar
*));
847 // drop back one position so the next run through the loop
848 // reprocesses the argument at our current index.
854 if ( !wxAppBase::Initialize(argc
, argv
) )
858 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
861 // these might be the startup dirs, set them to the 'usual' dir containing the app bundle
862 wxString startupCwd
= wxGetCwd() ;
863 if ( startupCwd
== wxT("/") || startupCwd
.Right(15) == wxT("/Contents/MacOS") )
865 CFURLRef url
= CFBundleCopyBundleURL(CFBundleGetMainBundle() ) ;
866 CFURLRef urlParent
= CFURLCreateCopyDeletingLastPathComponent( kCFAllocatorDefault
, url
) ;
868 CFStringRef path
= CFURLCopyFileSystemPath ( urlParent
, kCFURLPOSIXPathStyle
) ;
869 CFRelease( urlParent
) ;
870 wxString cwd
= wxCFStringRef(path
).AsString(wxLocale::GetSystemEncoding());
871 wxSetWorkingDirectory( cwd
) ;
878 bool wxApp::CallOnInit()
880 wxMacAutoreleasePool autoreleasepool
;
885 bool wxApp::OnInitGui()
887 if ( !wxAppBase::OnInitGui() )
896 bool wxApp::ProcessIdle()
898 wxMacAutoreleasePool autoreleasepool
;
899 return wxAppBase::ProcessIdle();
904 wxMacAutoreleasePool pool
;
905 return wxAppBase::OnRun();
909 bool wxApp::DoInitGui()
911 InstallStandardEventHandler( GetApplicationEventTarget() ) ;
914 InstallApplicationEventHandler(
915 GetwxMacAppEventHandlerUPP(),
916 GetEventTypeCount(eventList
), eventList
, wxTheApp
, (EventHandlerRef
*)&(wxTheApp
->m_macEventHandler
));
921 sODocHandler
= NewAEEventHandlerUPP(AEHandleODoc
) ;
922 sGURLHandler
= NewAEEventHandlerUPP(AEHandleGURL
) ;
923 sOAppHandler
= NewAEEventHandlerUPP(AEHandleOApp
) ;
924 sPDocHandler
= NewAEEventHandlerUPP(AEHandlePDoc
) ;
925 sRAppHandler
= NewAEEventHandlerUPP(AEHandleRApp
) ;
926 sQuitHandler
= NewAEEventHandlerUPP(AEHandleQuit
) ;
928 AEInstallEventHandler( kCoreEventClass
, kAEOpenDocuments
,
929 sODocHandler
, 0 , FALSE
) ;
930 AEInstallEventHandler( kInternetEventClass
, kAEGetURL
,
931 sGURLHandler
, 0 , FALSE
) ;
932 AEInstallEventHandler( kCoreEventClass
, kAEOpenApplication
,
933 sOAppHandler
, 0 , FALSE
) ;
934 AEInstallEventHandler( kCoreEventClass
, kAEPrintDocuments
,
935 sPDocHandler
, 0 , FALSE
) ;
936 AEInstallEventHandler( kCoreEventClass
, kAEReopenApplication
,
937 sRAppHandler
, 0 , FALSE
) ;
938 AEInstallEventHandler( kCoreEventClass
, kAEQuitApplication
,
939 sQuitHandler
, 0 , FALSE
) ;
942 if ( !wxMacInitCocoa() )
948 void wxApp::DoCleanUp()
951 RemoveEventHandler( (EventHandlerRef
)(wxTheApp
->m_macEventHandler
) );
955 AERemoveEventHandler( kCoreEventClass
, kAEOpenDocuments
,
956 sODocHandler
, FALSE
) ;
957 AERemoveEventHandler( kInternetEventClass
, kAEGetURL
,
958 sGURLHandler
, FALSE
) ;
959 AERemoveEventHandler( kCoreEventClass
, kAEOpenApplication
,
960 sOAppHandler
, FALSE
) ;
961 AERemoveEventHandler( kCoreEventClass
, kAEPrintDocuments
,
962 sPDocHandler
, FALSE
) ;
963 AERemoveEventHandler( kCoreEventClass
, kAEReopenApplication
,
964 sRAppHandler
, FALSE
) ;
965 AERemoveEventHandler( kCoreEventClass
, kAEQuitApplication
,
966 sQuitHandler
, FALSE
) ;
968 DisposeAEEventHandlerUPP( sODocHandler
) ;
969 DisposeAEEventHandlerUPP( sGURLHandler
) ;
970 DisposeAEEventHandlerUPP( sOAppHandler
) ;
971 DisposeAEEventHandlerUPP( sPDocHandler
) ;
972 DisposeAEEventHandlerUPP( sRAppHandler
) ;
973 DisposeAEEventHandlerUPP( sQuitHandler
) ;
979 void wxApp::CleanUp()
981 wxMacAutoreleasePool autoreleasepool
;
983 wxToolTip::RemoveToolTips() ;
988 wxAppBase::CleanUp();
991 //----------------------------------------------------------------------
992 // misc initialization stuff
993 //----------------------------------------------------------------------
997 m_printMode
= wxPRINT_WINDOWS
;
999 m_macCurrentEvent
= NULL
;
1000 m_macCurrentEventHandlerCallRef
= NULL
;
1001 m_macPool
= new wxMacAutoreleasePool();
1010 CFMutableArrayRef
GetAutoReleaseArray()
1012 static CFMutableArrayRef array
= 0;
1014 array
= CFArrayCreateMutable(kCFAllocatorDefault
,0,&kCFTypeArrayCallBacks
);
1018 void wxApp::MacAddToAutorelease( void* cfrefobj
)
1020 CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj
);
1023 void wxApp::MacReleaseAutoreleasePool()
1027 m_macPool
= new wxMacAutoreleasePool();
1030 void wxApp::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1032 // If they are pending events, we must process them: pending events are
1033 // either events to the threads other than main or events posted with
1034 // wxPostEvent() functions
1035 #ifndef __WXUNIVERSAL__
1037 if (!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar())
1038 wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar();
1041 CFArrayRemoveAllValues( GetAutoReleaseArray() );
1044 void wxApp::WakeUpIdle()
1046 wxEventLoopBase
* const loop
= wxEventLoopBase::GetActive();
1052 void wxApp::OnEndSession(wxCloseEvent
& WXUNUSED(event
))
1055 GetTopWindow()->Close(true);
1058 // Default behaviour: close the application with prompts. The
1059 // user can veto the close, and therefore the end session.
1060 void wxApp::OnQueryEndSession(wxCloseEvent
& event
)
1062 if ( !wxDialog::OSXHasModalDialogsOpen() )
1066 if (!GetTopWindow()->Close(!event
.CanVeto()))
1076 extern "C" void wxCYield() ;
1083 void wxApp::MacHandleUnhandledEvent( WXEVENTREF
WXUNUSED(evr
) )
1085 // Override to process unhandled events as you please
1088 #if wxOSX_USE_COCOA_OR_CARBON
1090 CGKeyCode
wxCharCodeWXToOSX(wxKeyCode code
)
1096 // Clang warns about switch values not of the same type as (enumerated)
1097 // switch controlling expression. This is generally useful but here we
1098 // really want to be able to use letters and digits without making them
1099 // part of wxKeyCode enum.
1101 #pragma clang diagnostic push
1102 #pragma clang diagnostic ignored "-Wswitch"
1105 case 'a': case 'A': keycode
= kVK_ANSI_A
; break;
1106 case 'b': case 'B': keycode
= kVK_ANSI_B
; break;
1107 case 'c': case 'C': keycode
= kVK_ANSI_C
; break;
1108 case 'd': case 'D': keycode
= kVK_ANSI_D
; break;
1109 case 'e': case 'E': keycode
= kVK_ANSI_E
; break;
1110 case 'f': case 'F': keycode
= kVK_ANSI_F
; break;
1111 case 'g': case 'G': keycode
= kVK_ANSI_G
; break;
1112 case 'h': case 'H': keycode
= kVK_ANSI_H
; break;
1113 case 'i': case 'I': keycode
= kVK_ANSI_I
; break;
1114 case 'j': case 'J': keycode
= kVK_ANSI_J
; break;
1115 case 'k': case 'K': keycode
= kVK_ANSI_K
; break;
1116 case 'l': case 'L': keycode
= kVK_ANSI_L
; break;
1117 case 'm': case 'M': keycode
= kVK_ANSI_M
; break;
1118 case 'n': case 'N': keycode
= kVK_ANSI_N
; break;
1119 case 'o': case 'O': keycode
= kVK_ANSI_O
; break;
1120 case 'p': case 'P': keycode
= kVK_ANSI_P
; break;
1121 case 'q': case 'Q': keycode
= kVK_ANSI_Q
; break;
1122 case 'r': case 'R': keycode
= kVK_ANSI_R
; break;
1123 case 's': case 'S': keycode
= kVK_ANSI_S
; break;
1124 case 't': case 'T': keycode
= kVK_ANSI_T
; break;
1125 case 'u': case 'U': keycode
= kVK_ANSI_U
; break;
1126 case 'v': case 'V': keycode
= kVK_ANSI_V
; break;
1127 case 'w': case 'W': keycode
= kVK_ANSI_W
; break;
1128 case 'x': case 'X': keycode
= kVK_ANSI_X
; break;
1129 case 'y': case 'Y': keycode
= kVK_ANSI_Y
; break;
1130 case 'z': case 'Z': keycode
= kVK_ANSI_Z
; break;
1132 case '0': keycode
= kVK_ANSI_0
; break;
1133 case '1': keycode
= kVK_ANSI_1
; break;
1134 case '2': keycode
= kVK_ANSI_2
; break;
1135 case '3': keycode
= kVK_ANSI_3
; break;
1136 case '4': keycode
= kVK_ANSI_4
; break;
1137 case '5': keycode
= kVK_ANSI_5
; break;
1138 case '6': keycode
= kVK_ANSI_6
; break;
1139 case '7': keycode
= kVK_ANSI_7
; break;
1140 case '8': keycode
= kVK_ANSI_8
; break;
1141 case '9': keycode
= kVK_ANSI_9
; break;
1144 #pragma clang diagnostic pop
1147 case WXK_BACK
: keycode
= kVK_Delete
; break;
1148 case WXK_TAB
: keycode
= kVK_Tab
; break;
1149 case WXK_RETURN
: keycode
= kVK_Return
; break;
1150 case WXK_ESCAPE
: keycode
= kVK_Escape
; break;
1151 case WXK_SPACE
: keycode
= kVK_Space
; break;
1152 case WXK_DELETE
: keycode
= kVK_ForwardDelete
; break;
1154 case WXK_SHIFT
: keycode
= kVK_Shift
; break;
1155 case WXK_ALT
: keycode
= kVK_Option
; break;
1156 case WXK_RAW_CONTROL
: keycode
= kVK_Control
; break;
1157 case WXK_CONTROL
: keycode
= kVK_Command
; break;
1159 case WXK_CAPITAL
: keycode
= kVK_CapsLock
; break;
1160 case WXK_END
: keycode
= kVK_End
; break;
1161 case WXK_HOME
: keycode
= kVK_Home
; break;
1162 case WXK_LEFT
: keycode
= kVK_LeftArrow
; break;
1163 case WXK_UP
: keycode
= kVK_UpArrow
; break;
1164 case WXK_RIGHT
: keycode
= kVK_RightArrow
; break;
1165 case WXK_DOWN
: keycode
= kVK_DownArrow
; break;
1167 case WXK_HELP
: keycode
= kVK_Help
; break;
1170 case WXK_NUMPAD0
: keycode
= kVK_ANSI_Keypad0
; break;
1171 case WXK_NUMPAD1
: keycode
= kVK_ANSI_Keypad1
; break;
1172 case WXK_NUMPAD2
: keycode
= kVK_ANSI_Keypad2
; break;
1173 case WXK_NUMPAD3
: keycode
= kVK_ANSI_Keypad3
; break;
1174 case WXK_NUMPAD4
: keycode
= kVK_ANSI_Keypad4
; break;
1175 case WXK_NUMPAD5
: keycode
= kVK_ANSI_Keypad5
; break;
1176 case WXK_NUMPAD6
: keycode
= kVK_ANSI_Keypad6
; break;
1177 case WXK_NUMPAD7
: keycode
= kVK_ANSI_Keypad7
; break;
1178 case WXK_NUMPAD8
: keycode
= kVK_ANSI_Keypad8
; break;
1179 case WXK_NUMPAD9
: keycode
= kVK_ANSI_Keypad9
; break;
1180 case WXK_F1
: keycode
= kVK_F1
; break;
1181 case WXK_F2
: keycode
= kVK_F2
; break;
1182 case WXK_F3
: keycode
= kVK_F3
; break;
1183 case WXK_F4
: keycode
= kVK_F4
; break;
1184 case WXK_F5
: keycode
= kVK_F5
; break;
1185 case WXK_F6
: keycode
= kVK_F6
; break;
1186 case WXK_F7
: keycode
= kVK_F7
; break;
1187 case WXK_F8
: keycode
= kVK_F8
; break;
1188 case WXK_F9
: keycode
= kVK_F9
; break;
1189 case WXK_F10
: keycode
= kVK_F10
; break;
1190 case WXK_F11
: keycode
= kVK_F11
; break;
1191 case WXK_F12
: keycode
= kVK_F12
; break;
1192 case WXK_F13
: keycode
= kVK_F13
; break;
1193 case WXK_F14
: keycode
= kVK_F14
; break;
1194 case WXK_F15
: keycode
= kVK_F15
; break;
1195 case WXK_F16
: keycode
= kVK_F16
; break;
1196 case WXK_F17
: keycode
= kVK_F17
; break;
1197 case WXK_F18
: keycode
= kVK_F18
; break;
1198 case WXK_F19
: keycode
= kVK_F19
; break;
1199 case WXK_F20
: keycode
= kVK_F20
; break;
1201 case WXK_PAGEUP
: keycode
= kVK_PageUp
; break;
1202 case WXK_PAGEDOWN
: keycode
= kVK_PageDown
; break;
1204 case WXK_NUMPAD_DELETE
: keycode
= kVK_ANSI_KeypadClear
; break;
1205 case WXK_NUMPAD_EQUAL
: keycode
= kVK_ANSI_KeypadEquals
; break;
1206 case WXK_NUMPAD_MULTIPLY
: keycode
= kVK_ANSI_KeypadMultiply
; break;
1207 case WXK_NUMPAD_ADD
: keycode
= kVK_ANSI_KeypadPlus
; break;
1208 case WXK_NUMPAD_SUBTRACT
: keycode
= kVK_ANSI_KeypadMinus
; break;
1209 case WXK_NUMPAD_DECIMAL
: keycode
= kVK_ANSI_KeypadDecimal
; break;
1210 case WXK_NUMPAD_DIVIDE
: keycode
= kVK_ANSI_KeypadDivide
; break;
1213 wxLogDebug( "Unrecognised keycode %d", code
);
1214 keycode
= static_cast<CGKeyCode
>(-1);
1220 long wxMacTranslateKey(unsigned char key
, unsigned char code
)
1225 case kHomeCharCode
:
1229 case kEnterCharCode
:
1230 retval
= WXK_RETURN
;
1236 case kHelpCharCode
:
1240 case kBackspaceCharCode
:
1248 case kPageUpCharCode
:
1249 retval
= WXK_PAGEUP
;
1252 case kPageDownCharCode
:
1253 retval
= WXK_PAGEDOWN
;
1256 case kReturnCharCode
:
1257 retval
= WXK_RETURN
;
1260 case kFunctionKeyCharCode
:
1330 case kEscapeCharCode
:
1331 retval
= WXK_ESCAPE
;
1334 case kLeftArrowCharCode
:
1338 case kRightArrowCharCode
:
1339 retval
= WXK_RIGHT
;
1342 case kUpArrowCharCode
:
1346 case kDownArrowCharCode
:
1350 case kDeleteCharCode
:
1351 retval
= WXK_DELETE
;
1361 int wxMacKeyCodeToModifier(wxKeyCode key
)
1379 case WXK_RAW_CONTROL
:
1388 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
1390 // defined in utils.mm
1392 #elif wxOSX_USE_COCOA_OR_CARBON
1394 wxMouseState
wxGetMouseState()
1398 wxPoint pt
= wxGetMousePosition();
1402 UInt32 buttons
= GetCurrentButtonState();
1403 ms
.SetLeftDown( (buttons
& 0x01) != 0 );
1404 ms
.SetMiddleDown( (buttons
& 0x04) != 0 );
1405 ms
.SetRightDown( (buttons
& 0x02) != 0 );
1407 UInt32 modifiers
= GetCurrentKeyModifiers();
1408 ms
.SetRawControlDown(modifiers
& controlKey
);
1409 ms
.SetShiftDown(modifiers
& shiftKey
);
1410 ms
.SetAltDown(modifiers
& optionKey
);
1411 ms
.SetControlDown(modifiers
& cmdKey
);
1418 // TODO : once the new key/char handling is tested, move all the code to wxWindow
1420 bool wxApp::MacSendKeyDownEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1425 wxKeyEvent
event(wxEVT_KEY_DOWN
) ;
1426 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, uniChar
) ;
1428 return focus
->OSXHandleKeyEvent(event
);
1431 bool wxApp::MacSendKeyUpEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1436 wxKeyEvent
event( wxEVT_KEY_UP
) ;
1437 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, uniChar
) ;
1439 return focus
->OSXHandleKeyEvent(event
) ;
1442 bool wxApp::MacSendCharEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1446 wxKeyEvent
event(wxEVT_CHAR
) ;
1447 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, uniChar
) ;
1449 bool handled
= false ;
1451 #if wxOSX_USE_CARBON
1452 long keyval
= event
.m_keyCode
;
1455 wxKeyEvent
eventCharHook(wxEVT_CHAR_HOOK
, event
);
1456 handled
= focus
->HandleWindowEvent( eventCharHook
);
1457 if ( handled
&& eventCharHook
.IsNextEventAllowed() )
1463 handled
= focus
->HandleWindowEvent( event
) ;
1466 if ( !handled
&& (keyval
== WXK_TAB
) )
1468 wxWindow
* iter
= focus
->GetParent() ;
1469 while ( iter
&& !handled
)
1471 if ( iter
->HasFlag( wxTAB_TRAVERSAL
) )
1473 wxNavigationKeyEvent new_event
;
1474 new_event
.SetEventObject( focus
);
1475 new_event
.SetDirection( !event
.ShiftDown() );
1476 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1477 new_event
.SetWindowChange( event
.ControlDown() );
1478 new_event
.SetCurrentFocus( focus
);
1479 handled
= focus
->GetParent()->HandleWindowEvent( new_event
);
1480 if ( handled
&& new_event
.GetSkipped() )
1484 iter
= iter
->GetParent() ;
1488 // backdoor handler for default return and command escape
1489 if ( !handled
&& (!focus
->IsKindOf(CLASSINFO(wxControl
) ) || !focus
->AcceptsFocus() ) )
1491 // if window is not having a focus still testing for default enter or cancel
1492 // TODO: add the UMA version for ActiveNonFloatingWindow
1494 wxWindow
* focus
= wxNonOwnedWindow::GetFromWXWindow( (WXWindow
) FrontWindow() ) ;
1497 if ( keyval
== WXK_RETURN
|| keyval
== WXK_NUMPAD_ENTER
)
1499 wxTopLevelWindow
*tlw
= wxDynamicCast(wxGetTopLevelParent(focus
), wxTopLevelWindow
);
1500 if ( tlw
&& tlw
->GetDefaultItem() )
1502 wxButton
*def
= wxDynamicCast(tlw
->GetDefaultItem(), wxButton
);
1503 if ( def
&& def
->IsEnabled() )
1505 wxCommandEvent
event(wxEVT_BUTTON
, def
->GetId() );
1506 event
.SetEventObject(def
);
1507 def
->Command(event
);
1513 else if (keyval
== WXK_ESCAPE
|| (keyval
== '.' && modifiers
& cmdKey
) )
1515 // generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs)
1516 wxCommandEvent
new_event(wxEVT_BUTTON
,wxID_CANCEL
);
1517 new_event
.SetEventObject( focus
);
1518 handled
= focus
->HandleWindowEvent( new_event
);
1527 // This method handles common code for SendKeyDown, SendKeyUp, and SendChar events.
1528 void wxApp::MacCreateKeyEvent( wxKeyEvent
& event
, wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1530 #if wxOSX_USE_COCOA_OR_CARBON
1532 short keycode
, keychar
;
1534 keychar
= short(keymessage
& charCodeMask
);
1535 keycode
= short(keymessage
& keyCodeMask
) >> 8 ;
1536 if ( !(event
.GetEventType() == wxEVT_CHAR
) && (modifiers
& (controlKey
| shiftKey
| optionKey
) ) )
1538 // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
1539 // and look at the character after
1541 // TODO new implementation using TextInputSources
1544 UInt32 keyInfo
= KeyTranslate((Ptr
)GetScriptManagerVariable(smKCHRCache
), ( modifiers
& (~(controlKey
| shiftKey
| optionKey
))) | keycode
, &state
);
1545 keychar
= short(keyInfo
& charCodeMask
);
1549 long keyval
= wxMacTranslateKey(keychar
, keycode
) ;
1550 if ( keyval
== keychar
&& ( event
.GetEventType() == wxEVT_KEY_UP
|| event
.GetEventType() == wxEVT_KEY_DOWN
) )
1551 keyval
= wxToupper( keyval
) ;
1553 // Check for NUMPAD keys. For KEY_UP/DOWN events we need to use the
1554 // WXK_NUMPAD constants, but for the CHAR event we want to use the
1555 // standard ascii values
1556 if ( event
.GetEventType() != wxEVT_CHAR
)
1558 if (keyval
>= '0' && keyval
<= '9' && keycode
>= 82 && keycode
<= 92)
1560 keyval
= (keyval
- '0') + WXK_NUMPAD0
;
1562 else if (keycode
>= 65 && keycode
<= 81)
1567 keyval
= WXK_NUMPAD_ENTER
;
1571 keyval
= WXK_NUMPAD_EQUAL
;
1575 keyval
= WXK_NUMPAD_MULTIPLY
;
1579 keyval
= WXK_NUMPAD_DIVIDE
;
1583 keyval
= WXK_NUMPAD_SUBTRACT
;
1587 keyval
= WXK_NUMPAD_ADD
;
1591 keyval
= WXK_NUMPAD_DECIMAL
;
1599 event
.m_shiftDown
= modifiers
& shiftKey
;
1600 event
.m_rawControlDown
= modifiers
& controlKey
;
1601 event
.m_altDown
= modifiers
& optionKey
;
1602 event
.m_controlDown
= modifiers
& cmdKey
;
1603 event
.m_keyCode
= keyval
;
1605 event
.m_uniChar
= uniChar
;
1608 event
.m_rawCode
= keymessage
;
1609 event
.m_rawFlags
= modifiers
;
1610 event
.SetTimestamp(when
);
1611 event
.SetEventObject(focus
);
1615 wxUnusedVar(keymessage
);
1616 wxUnusedVar(modifiers
);
1618 wxUnusedVar(uniChar
);
1623 void wxApp::MacHideApp()
1625 #if wxOSX_USE_CARBON
1626 wxMacCarbonEvent
event( kEventClassCommand
, kEventCommandProcess
);
1628 memset( &command
, 0 , sizeof(command
) );
1629 command
.commandID
= kHICommandHide
;
1630 event
.SetParameter
<HICommand
>(kEventParamDirectObject
, command
);
1631 SendEventToApplication( event
);