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()
406 m_onInitResult
= OnInit();
409 void wxApp::OSXOnDidFinishLaunching()
413 void wxApp::OSXOnWillTerminate()
416 event
.SetCanVeto(false);
417 wxTheApp
->OnEndSession(event
);
420 bool wxApp::OSXOnShouldTerminate()
423 wxTheApp
->OnQueryEndSession(event
);
424 return !event
.GetVeto();
428 //----------------------------------------------------------------------
429 // Macintosh CommandID support - converting between native and wx IDs
430 //----------------------------------------------------------------------
432 // if no native match they just return the passed-in id
442 IdPair gCommandIds
[] =
444 { kHICommandCut
, wxID_CUT
} ,
445 { kHICommandCopy
, wxID_COPY
} ,
446 { kHICommandPaste
, wxID_PASTE
} ,
447 { kHICommandSelectAll
, wxID_SELECTALL
} ,
448 { kHICommandClear
, wxID_CLEAR
} ,
449 { kHICommandUndo
, wxID_UNDO
} ,
450 { kHICommandRedo
, wxID_REDO
} ,
453 int wxMacCommandToId( UInt32 macCommandId
)
457 switch ( macCommandId
)
459 case kHICommandPreferences
:
460 wxid
= wxApp::s_macPreferencesMenuItemId
;
463 case kHICommandQuit
:
464 wxid
= wxApp::s_macExitMenuItemId
;
467 case kHICommandAbout
:
468 wxid
= wxApp::s_macAboutMenuItemId
;
473 for ( size_t i
= 0 ; i
< WXSIZEOF(gCommandIds
) ; ++i
)
475 if ( gCommandIds
[i
].macId
== macCommandId
)
477 wxid
= gCommandIds
[i
].wxId
;
486 wxid
= (int) macCommandId
;
491 UInt32
wxIdToMacCommand( int wxId
)
495 if ( wxId
== wxApp::s_macPreferencesMenuItemId
)
496 macId
= kHICommandPreferences
;
497 else if (wxId
== wxApp::s_macExitMenuItemId
)
498 macId
= kHICommandQuit
;
499 else if (wxId
== wxApp::s_macAboutMenuItemId
)
500 macId
= kHICommandAbout
;
503 for ( size_t i
= 0 ; i
< WXSIZEOF(gCommandIds
) ; ++i
)
505 if ( gCommandIds
[i
].wxId
== wxId
)
507 macId
= gCommandIds
[i
].macId
;
519 wxMenu
* wxFindMenuFromMacCommand( const HICommand
&command
, wxMenuItem
* &item
)
521 wxMenu
* itemMenu
= NULL
;
522 #ifndef __WXUNIVERSAL__
525 // for 'standard' commands which don't have a wx-menu
526 if ( command
.commandID
== kHICommandPreferences
|| command
.commandID
== kHICommandQuit
|| command
.commandID
== kHICommandAbout
)
528 id
= wxMacCommandToId( command
.commandID
) ;
530 wxMenuBar
* mbar
= wxMenuBar::MacGetInstalledMenuBar() ;
532 item
= mbar
->FindItem( id
, &itemMenu
) ;
534 else if ( command
.commandID
!= 0 && command
.menu
.menuRef
!= 0 && command
.menu
.menuItemIndex
!= 0 )
536 id
= wxMacCommandToId( command
.commandID
) ;
537 // make sure it is one of our own menus, or of the 'synthetic' apple and help menus , otherwise don't touch
538 MenuItemIndex firstUserHelpMenuItem
;
539 static MenuHandle helpMenuHandle
= NULL
;
540 if ( helpMenuHandle
== NULL
)
542 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
543 helpMenuHandle
= NULL
;
546 // is it part of the application or the Help menu, then look for the id directly
547 if ( ( GetMenuHandle( kwxMacAppleMenuId
) != NULL
&& command
.menu
.menuRef
== GetMenuHandle( kwxMacAppleMenuId
) ) ||
548 ( helpMenuHandle
!= NULL
&& command
.menu
.menuRef
== helpMenuHandle
) ||
549 wxMenuBar::MacGetWindowMenuHMenu() != NULL
&& command
.menu
.menuRef
== wxMenuBar::MacGetWindowMenuHMenu() )
551 wxMenuBar
* mbar
= wxMenuBar::MacGetInstalledMenuBar() ;
553 item
= mbar
->FindItem( id
, &itemMenu
) ;
559 GetMenuItemRefCon( command
.menu
.menuRef
, command
.menu
.menuItemIndex
, &refCon
) ;
560 itemMenu
= wxFindMenuFromMacMenu( command
.menu
.menuRef
) ;
561 if ( itemMenu
!= NULL
&& refCon
!= 0)
562 item
= (wxMenuItem
*) refCon
;
571 //----------------------------------------------------------------------
572 // Carbon Event Handler
573 //----------------------------------------------------------------------
577 static const EventTypeSpec eventList
[] =
579 { kEventClassCommand
, kEventProcessCommand
} ,
580 { kEventClassCommand
, kEventCommandUpdateStatus
} ,
582 { kEventClassMenu
, kEventMenuOpening
},
583 { kEventClassMenu
, kEventMenuClosed
},
584 { kEventClassMenu
, kEventMenuTargetItem
},
586 { kEventClassApplication
, kEventAppActivated
} ,
587 { kEventClassApplication
, kEventAppDeactivated
} ,
588 // handling the quit event is not recommended by apple
589 // rather using the quit apple event - which we do
591 { kEventClassAppleEvent
, kEventAppleEvent
} ,
593 { kEventClassMouse
, kEventMouseDown
} ,
594 { kEventClassMouse
, kEventMouseMoved
} ,
595 { kEventClassMouse
, kEventMouseUp
} ,
596 { kEventClassMouse
, kEventMouseDragged
} ,
600 static pascal OSStatus
601 wxMacAppMenuEventHandler( EventHandlerCallRef
WXUNUSED(handler
),
603 void *WXUNUSED(data
) )
605 wxMacCarbonEvent
cEvent( event
) ;
606 MenuRef menuRef
= cEvent
.GetParameter
<MenuRef
>(kEventParamDirectObject
) ;
607 #ifndef __WXUNIVERSAL__
608 wxMenu
* menu
= wxFindMenuFromMacMenu( menuRef
) ;
612 switch (GetEventKind(event
))
614 case kEventMenuOpening
:
615 menu
->HandleMenuOpened();
618 case kEventMenuClosed
:
619 menu
->HandleMenuClosed();
622 case kEventMenuTargetItem
:
626 command
.menu
.menuRef
= menuRef
;
627 command
.menu
.menuItemIndex
= cEvent
.GetParameter
<MenuItemIndex
>(kEventParamMenuItemIndex
,typeMenuItemIndex
) ;
628 command
.commandID
= cEvent
.GetParameter
<MenuCommand
>(kEventParamMenuCommand
,typeMenuCommand
) ;
629 if (command
.commandID
!= 0)
631 wxMenuItem
* item
= NULL
;
632 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
633 if ( itemMenu
&& item
)
634 itemMenu
->HandleMenuItemHighlighted( item
);
640 wxFAIL_MSG(wxT("Unexpected menu event kind"));
646 return eventNotHandledErr
;
649 static pascal OSStatus
650 wxMacAppCommandEventHandler( EventHandlerCallRef
WXUNUSED(handler
) ,
652 void *WXUNUSED(data
) )
654 OSStatus result
= eventNotHandledErr
;
658 wxMacCarbonEvent
cEvent( event
) ;
659 cEvent
.GetParameter
<HICommand
>(kEventParamDirectObject
,typeHICommand
,&command
) ;
661 wxMenuItem
* item
= NULL
;
662 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
666 wxASSERT( itemMenu
!= NULL
) ;
668 switch ( cEvent
.GetKind() )
670 case kEventProcessCommand
:
671 if ( itemMenu
->HandleCommandProcess( item
) )
675 case kEventCommandUpdateStatus
:
676 if ( itemMenu
->HandleCommandUpdateStatus( item
) )
687 static pascal OSStatus
688 wxMacAppApplicationEventHandler( EventHandlerCallRef
WXUNUSED(handler
) ,
690 void *WXUNUSED(data
) )
692 OSStatus result
= eventNotHandledErr
;
693 switch ( GetEventKind( event
) )
695 case kEventAppActivated
:
697 wxTheApp
->SetActive( true , NULL
) ;
701 case kEventAppDeactivated
:
703 wxTheApp
->SetActive( false , NULL
) ;
714 pascal OSStatus
wxMacAppEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
716 EventRef formerEvent
= (EventRef
) wxTheApp
->MacGetCurrentEvent() ;
717 EventHandlerCallRef formerEventHandlerCallRef
= (EventHandlerCallRef
) wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
718 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
720 OSStatus result
= eventNotHandledErr
;
721 switch ( GetEventClass( event
) )
724 case kEventClassCommand
:
725 result
= wxMacAppCommandEventHandler( handler
, event
, data
) ;
728 case kEventClassApplication
:
729 result
= wxMacAppApplicationEventHandler( handler
, event
, data
) ;
732 case kEventClassMenu
:
733 result
= wxMacAppMenuEventHandler( handler
, event
, data
) ;
736 case kEventClassMouse
:
738 wxMacCarbonEvent
cEvent( event
) ;
741 Point screenMouseLocation
= cEvent
.GetParameter
<Point
>(kEventParamMouseLocation
) ;
742 ::FindWindow(screenMouseLocation
, &window
);
743 // only send this event in case it had not already been sent to a tlw, as we get
744 // double events otherwise (in case event.skip) was called
745 if ( window
== NULL
)
746 result
= wxMacTopLevelMouseEventHandler( handler
, event
, NULL
) ;
750 case kEventClassAppleEvent
:
751 result
= AEProcessEvent(event
);
758 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerEventHandlerCallRef
) ;
763 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacAppEventHandler
)
766 #if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
769 wxMacAssertOutputHandler(OSType
WXUNUSED(componentSignature
),
770 UInt32
WXUNUSED(options
),
771 const char *assertionString
,
772 const char *exceptionLabelString
,
773 const char *errorString
,
774 const char *fileName
,
777 ConstStr255Param
WXUNUSED(outputMsg
))
779 // flow into assert handling
780 wxString fileNameStr
;
781 wxString assertionStr
;
782 wxString exceptionStr
;
786 fileNameStr
= wxString(fileName
, wxConvLocal
);
787 assertionStr
= wxString(assertionString
, wxConvLocal
);
788 exceptionStr
= wxString((exceptionLabelString
!=0) ? exceptionLabelString
: "", wxConvLocal
) ;
789 errorStr
= wxString((errorString
!=0) ? errorString
: "", wxConvLocal
) ;
791 fileNameStr
= fileName
;
792 assertionStr
= assertionString
;
793 exceptionStr
= (exceptionLabelString
!=0) ? exceptionLabelString
: "" ;
794 errorStr
= (errorString
!=0) ? errorString
: "" ;
799 wxLogDebug( wxT("AssertMacros: %s %s %s file: %s, line: %ld (value %p)\n"),
800 assertionStr
.c_str() ,
801 exceptionStr
.c_str() ,
803 fileNameStr
.c_str(), lineNumber
,
807 wxOnAssert(fileNameStr
, lineNumber
, assertionStr
,
808 wxString::Format( wxT("%s %s value (%p)") , exceptionStr
, errorStr
, value
) ) ;
812 #endif // wxDEBUG_LEVEL
814 bool wxApp::Initialize(int& argc
, wxChar
**argv
)
818 #if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
819 InstallDebugAssertOutputHandler( NewDebugAssertOutputHandlerUPP( wxMacAssertOutputHandler
) );
823 Cocoa supports -Key value options which set the user defaults key "Key"
824 to the value "value" Some of them are very handy for debugging like
825 -NSShowAllViews YES. Cocoa picks these up from the real argv so
826 our removal of them from the wx copy of it does not affect Cocoa's
829 We basically just assume that any "-NS" option and its following
830 argument needs to be removed from argv. We hope that user code does
831 not expect to see -NS options and indeed it's probably a safe bet
832 since most user code accepting options is probably using the
833 double-dash GNU-style syntax.
835 for(int i
=1; i
< argc
; ++i
)
837 static const wxChar
*ARG_NS
= wxT("-NS");
838 if( wxStrncmp(argv
[i
], ARG_NS
, wxStrlen(ARG_NS
)) == 0 )
840 // Only eat this option if it has an argument
843 memmove(argv
+ i
, argv
+ i
+ 2, (argc
-i
-1)*sizeof(wxChar
*));
845 // drop back one position so the next run through the loop
846 // reprocesses the argument at our current index.
852 if ( !wxAppBase::Initialize(argc
, argv
) )
856 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
859 // these might be the startup dirs, set them to the 'usual' dir containing the app bundle
860 wxString startupCwd
= wxGetCwd() ;
861 if ( startupCwd
== wxT("/") || startupCwd
.Right(15) == wxT("/Contents/MacOS") )
863 CFURLRef url
= CFBundleCopyBundleURL(CFBundleGetMainBundle() ) ;
864 CFURLRef urlParent
= CFURLCreateCopyDeletingLastPathComponent( kCFAllocatorDefault
, url
) ;
866 CFStringRef path
= CFURLCopyFileSystemPath ( urlParent
, kCFURLPOSIXPathStyle
) ;
867 CFRelease( urlParent
) ;
868 wxString cwd
= wxCFStringRef(path
).AsString(wxLocale::GetSystemEncoding());
869 wxSetWorkingDirectory( cwd
) ;
876 bool wxApp::CallOnInit()
878 wxMacAutoreleasePool autoreleasepool
;
883 bool wxApp::OnInitGui()
885 if ( !wxAppBase::OnInitGui() )
894 bool wxApp::ProcessIdle()
896 wxMacAutoreleasePool autoreleasepool
;
897 return wxAppBase::ProcessIdle();
902 wxMacAutoreleasePool pool
;
903 return wxAppBase::OnRun();
907 bool wxApp::DoInitGui()
909 InstallStandardEventHandler( GetApplicationEventTarget() ) ;
912 InstallApplicationEventHandler(
913 GetwxMacAppEventHandlerUPP(),
914 GetEventTypeCount(eventList
), eventList
, wxTheApp
, (EventHandlerRef
*)&(wxTheApp
->m_macEventHandler
));
919 sODocHandler
= NewAEEventHandlerUPP(AEHandleODoc
) ;
920 sGURLHandler
= NewAEEventHandlerUPP(AEHandleGURL
) ;
921 sOAppHandler
= NewAEEventHandlerUPP(AEHandleOApp
) ;
922 sPDocHandler
= NewAEEventHandlerUPP(AEHandlePDoc
) ;
923 sRAppHandler
= NewAEEventHandlerUPP(AEHandleRApp
) ;
924 sQuitHandler
= NewAEEventHandlerUPP(AEHandleQuit
) ;
926 AEInstallEventHandler( kCoreEventClass
, kAEOpenDocuments
,
927 sODocHandler
, 0 , FALSE
) ;
928 AEInstallEventHandler( kInternetEventClass
, kAEGetURL
,
929 sGURLHandler
, 0 , FALSE
) ;
930 AEInstallEventHandler( kCoreEventClass
, kAEOpenApplication
,
931 sOAppHandler
, 0 , FALSE
) ;
932 AEInstallEventHandler( kCoreEventClass
, kAEPrintDocuments
,
933 sPDocHandler
, 0 , FALSE
) ;
934 AEInstallEventHandler( kCoreEventClass
, kAEReopenApplication
,
935 sRAppHandler
, 0 , FALSE
) ;
936 AEInstallEventHandler( kCoreEventClass
, kAEQuitApplication
,
937 sQuitHandler
, 0 , FALSE
) ;
940 if ( !wxMacInitCocoa() )
946 void wxApp::DoCleanUp()
949 RemoveEventHandler( (EventHandlerRef
)(wxTheApp
->m_macEventHandler
) );
953 AERemoveEventHandler( kCoreEventClass
, kAEOpenDocuments
,
954 sODocHandler
, FALSE
) ;
955 AERemoveEventHandler( kInternetEventClass
, kAEGetURL
,
956 sGURLHandler
, FALSE
) ;
957 AERemoveEventHandler( kCoreEventClass
, kAEOpenApplication
,
958 sOAppHandler
, FALSE
) ;
959 AERemoveEventHandler( kCoreEventClass
, kAEPrintDocuments
,
960 sPDocHandler
, FALSE
) ;
961 AERemoveEventHandler( kCoreEventClass
, kAEReopenApplication
,
962 sRAppHandler
, FALSE
) ;
963 AERemoveEventHandler( kCoreEventClass
, kAEQuitApplication
,
964 sQuitHandler
, FALSE
) ;
966 DisposeAEEventHandlerUPP( sODocHandler
) ;
967 DisposeAEEventHandlerUPP( sGURLHandler
) ;
968 DisposeAEEventHandlerUPP( sOAppHandler
) ;
969 DisposeAEEventHandlerUPP( sPDocHandler
) ;
970 DisposeAEEventHandlerUPP( sRAppHandler
) ;
971 DisposeAEEventHandlerUPP( sQuitHandler
) ;
977 void wxApp::CleanUp()
979 wxMacAutoreleasePool autoreleasepool
;
981 wxToolTip::RemoveToolTips() ;
986 wxAppBase::CleanUp();
989 //----------------------------------------------------------------------
990 // misc initialization stuff
991 //----------------------------------------------------------------------
995 m_printMode
= wxPRINT_WINDOWS
;
997 m_macCurrentEvent
= NULL
;
998 m_macCurrentEventHandlerCallRef
= NULL
;
999 m_macPool
= new wxMacAutoreleasePool();
1008 CFMutableArrayRef
GetAutoReleaseArray()
1010 static CFMutableArrayRef array
= 0;
1012 array
= CFArrayCreateMutable(kCFAllocatorDefault
,0,&kCFTypeArrayCallBacks
);
1016 void wxApp::MacAddToAutorelease( void* cfrefobj
)
1018 CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj
);
1021 void wxApp::MacReleaseAutoreleasePool()
1025 m_macPool
= new wxMacAutoreleasePool();
1028 void wxApp::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1030 // If they are pending events, we must process them: pending events are
1031 // either events to the threads other than main or events posted with
1032 // wxPostEvent() functions
1033 #ifndef __WXUNIVERSAL__
1035 if (!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar())
1036 wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar();
1039 CFArrayRemoveAllValues( GetAutoReleaseArray() );
1042 void wxApp::WakeUpIdle()
1044 wxEventLoopBase
* const loop
= wxEventLoopBase::GetActive();
1050 void wxApp::OnEndSession(wxCloseEvent
& WXUNUSED(event
))
1053 GetTopWindow()->Close(true);
1056 // Default behaviour: close the application with prompts. The
1057 // user can veto the close, and therefore the end session.
1058 void wxApp::OnQueryEndSession(wxCloseEvent
& event
)
1060 if ( !wxDialog::OSXHasModalDialogsOpen() )
1064 if (!GetTopWindow()->Close(!event
.CanVeto()))
1074 extern "C" void wxCYield() ;
1081 void wxApp::MacHandleUnhandledEvent( WXEVENTREF
WXUNUSED(evr
) )
1083 // Override to process unhandled events as you please
1086 #if wxOSX_USE_COCOA_OR_CARBON
1088 CGKeyCode
wxCharCodeWXToOSX(wxKeyCode code
)
1094 // Clang warns about switch values not of the same type as (enumerated)
1095 // switch controlling expression. This is generally useful but here we
1096 // really want to be able to use letters and digits without making them
1097 // part of wxKeyCode enum.
1099 #pragma clang diagnostic push
1100 #pragma clang diagnostic ignored "-Wswitch"
1103 case 'a': case 'A': keycode
= kVK_ANSI_A
; break;
1104 case 'b': case 'B': keycode
= kVK_ANSI_B
; break;
1105 case 'c': case 'C': keycode
= kVK_ANSI_C
; break;
1106 case 'd': case 'D': keycode
= kVK_ANSI_D
; break;
1107 case 'e': case 'E': keycode
= kVK_ANSI_E
; break;
1108 case 'f': case 'F': keycode
= kVK_ANSI_F
; break;
1109 case 'g': case 'G': keycode
= kVK_ANSI_G
; break;
1110 case 'h': case 'H': keycode
= kVK_ANSI_H
; break;
1111 case 'i': case 'I': keycode
= kVK_ANSI_I
; break;
1112 case 'j': case 'J': keycode
= kVK_ANSI_J
; break;
1113 case 'k': case 'K': keycode
= kVK_ANSI_K
; break;
1114 case 'l': case 'L': keycode
= kVK_ANSI_L
; break;
1115 case 'm': case 'M': keycode
= kVK_ANSI_M
; break;
1116 case 'n': case 'N': keycode
= kVK_ANSI_N
; break;
1117 case 'o': case 'O': keycode
= kVK_ANSI_O
; break;
1118 case 'p': case 'P': keycode
= kVK_ANSI_P
; break;
1119 case 'q': case 'Q': keycode
= kVK_ANSI_Q
; break;
1120 case 'r': case 'R': keycode
= kVK_ANSI_R
; break;
1121 case 's': case 'S': keycode
= kVK_ANSI_S
; break;
1122 case 't': case 'T': keycode
= kVK_ANSI_T
; break;
1123 case 'u': case 'U': keycode
= kVK_ANSI_U
; break;
1124 case 'v': case 'V': keycode
= kVK_ANSI_V
; break;
1125 case 'w': case 'W': keycode
= kVK_ANSI_W
; break;
1126 case 'x': case 'X': keycode
= kVK_ANSI_X
; break;
1127 case 'y': case 'Y': keycode
= kVK_ANSI_Y
; break;
1128 case 'z': case 'Z': keycode
= kVK_ANSI_Z
; break;
1130 case '0': keycode
= kVK_ANSI_0
; break;
1131 case '1': keycode
= kVK_ANSI_1
; break;
1132 case '2': keycode
= kVK_ANSI_2
; break;
1133 case '3': keycode
= kVK_ANSI_3
; break;
1134 case '4': keycode
= kVK_ANSI_4
; break;
1135 case '5': keycode
= kVK_ANSI_5
; break;
1136 case '6': keycode
= kVK_ANSI_6
; break;
1137 case '7': keycode
= kVK_ANSI_7
; break;
1138 case '8': keycode
= kVK_ANSI_8
; break;
1139 case '9': keycode
= kVK_ANSI_9
; break;
1142 #pragma clang diagnostic pop
1145 case WXK_BACK
: keycode
= kVK_Delete
; break;
1146 case WXK_TAB
: keycode
= kVK_Tab
; break;
1147 case WXK_RETURN
: keycode
= kVK_Return
; break;
1148 case WXK_ESCAPE
: keycode
= kVK_Escape
; break;
1149 case WXK_SPACE
: keycode
= kVK_Space
; break;
1150 case WXK_DELETE
: keycode
= kVK_ForwardDelete
; break;
1152 case WXK_SHIFT
: keycode
= kVK_Shift
; break;
1153 case WXK_ALT
: keycode
= kVK_Option
; break;
1154 case WXK_RAW_CONTROL
: keycode
= kVK_Control
; break;
1155 case WXK_CONTROL
: keycode
= kVK_Command
; break;
1157 case WXK_CAPITAL
: keycode
= kVK_CapsLock
; break;
1158 case WXK_END
: keycode
= kVK_End
; break;
1159 case WXK_HOME
: keycode
= kVK_Home
; break;
1160 case WXK_LEFT
: keycode
= kVK_LeftArrow
; break;
1161 case WXK_UP
: keycode
= kVK_UpArrow
; break;
1162 case WXK_RIGHT
: keycode
= kVK_RightArrow
; break;
1163 case WXK_DOWN
: keycode
= kVK_DownArrow
; break;
1165 case WXK_HELP
: keycode
= kVK_Help
; break;
1168 case WXK_NUMPAD0
: keycode
= kVK_ANSI_Keypad0
; break;
1169 case WXK_NUMPAD1
: keycode
= kVK_ANSI_Keypad1
; break;
1170 case WXK_NUMPAD2
: keycode
= kVK_ANSI_Keypad2
; break;
1171 case WXK_NUMPAD3
: keycode
= kVK_ANSI_Keypad3
; break;
1172 case WXK_NUMPAD4
: keycode
= kVK_ANSI_Keypad4
; break;
1173 case WXK_NUMPAD5
: keycode
= kVK_ANSI_Keypad5
; break;
1174 case WXK_NUMPAD6
: keycode
= kVK_ANSI_Keypad6
; break;
1175 case WXK_NUMPAD7
: keycode
= kVK_ANSI_Keypad7
; break;
1176 case WXK_NUMPAD8
: keycode
= kVK_ANSI_Keypad8
; break;
1177 case WXK_NUMPAD9
: keycode
= kVK_ANSI_Keypad9
; break;
1178 case WXK_F1
: keycode
= kVK_F1
; break;
1179 case WXK_F2
: keycode
= kVK_F2
; break;
1180 case WXK_F3
: keycode
= kVK_F3
; break;
1181 case WXK_F4
: keycode
= kVK_F4
; break;
1182 case WXK_F5
: keycode
= kVK_F5
; break;
1183 case WXK_F6
: keycode
= kVK_F6
; break;
1184 case WXK_F7
: keycode
= kVK_F7
; break;
1185 case WXK_F8
: keycode
= kVK_F8
; break;
1186 case WXK_F9
: keycode
= kVK_F9
; break;
1187 case WXK_F10
: keycode
= kVK_F10
; break;
1188 case WXK_F11
: keycode
= kVK_F11
; break;
1189 case WXK_F12
: keycode
= kVK_F12
; break;
1190 case WXK_F13
: keycode
= kVK_F13
; break;
1191 case WXK_F14
: keycode
= kVK_F14
; break;
1192 case WXK_F15
: keycode
= kVK_F15
; break;
1193 case WXK_F16
: keycode
= kVK_F16
; break;
1194 case WXK_F17
: keycode
= kVK_F17
; break;
1195 case WXK_F18
: keycode
= kVK_F18
; break;
1196 case WXK_F19
: keycode
= kVK_F19
; break;
1197 case WXK_F20
: keycode
= kVK_F20
; break;
1199 case WXK_PAGEUP
: keycode
= kVK_PageUp
; break;
1200 case WXK_PAGEDOWN
: keycode
= kVK_PageDown
; break;
1202 case WXK_NUMPAD_DELETE
: keycode
= kVK_ANSI_KeypadClear
; break;
1203 case WXK_NUMPAD_EQUAL
: keycode
= kVK_ANSI_KeypadEquals
; break;
1204 case WXK_NUMPAD_MULTIPLY
: keycode
= kVK_ANSI_KeypadMultiply
; break;
1205 case WXK_NUMPAD_ADD
: keycode
= kVK_ANSI_KeypadPlus
; break;
1206 case WXK_NUMPAD_SUBTRACT
: keycode
= kVK_ANSI_KeypadMinus
; break;
1207 case WXK_NUMPAD_DECIMAL
: keycode
= kVK_ANSI_KeypadDecimal
; break;
1208 case WXK_NUMPAD_DIVIDE
: keycode
= kVK_ANSI_KeypadDivide
; break;
1211 wxLogDebug( "Unrecognised keycode %d", code
);
1212 keycode
= static_cast<CGKeyCode
>(-1);
1218 long wxMacTranslateKey(unsigned char key
, unsigned char code
)
1223 case kHomeCharCode
:
1227 case kEnterCharCode
:
1228 retval
= WXK_RETURN
;
1234 case kHelpCharCode
:
1238 case kBackspaceCharCode
:
1246 case kPageUpCharCode
:
1247 retval
= WXK_PAGEUP
;
1250 case kPageDownCharCode
:
1251 retval
= WXK_PAGEDOWN
;
1254 case kReturnCharCode
:
1255 retval
= WXK_RETURN
;
1258 case kFunctionKeyCharCode
:
1328 case kEscapeCharCode
:
1329 retval
= WXK_ESCAPE
;
1332 case kLeftArrowCharCode
:
1336 case kRightArrowCharCode
:
1337 retval
= WXK_RIGHT
;
1340 case kUpArrowCharCode
:
1344 case kDownArrowCharCode
:
1348 case kDeleteCharCode
:
1349 retval
= WXK_DELETE
;
1359 int wxMacKeyCodeToModifier(wxKeyCode key
)
1377 case WXK_RAW_CONTROL
:
1386 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
1388 // defined in utils.mm
1390 #elif wxOSX_USE_COCOA_OR_CARBON
1392 wxMouseState
wxGetMouseState()
1396 wxPoint pt
= wxGetMousePosition();
1400 UInt32 buttons
= GetCurrentButtonState();
1401 ms
.SetLeftDown( (buttons
& 0x01) != 0 );
1402 ms
.SetMiddleDown( (buttons
& 0x04) != 0 );
1403 ms
.SetRightDown( (buttons
& 0x02) != 0 );
1405 UInt32 modifiers
= GetCurrentKeyModifiers();
1406 ms
.SetRawControlDown(modifiers
& controlKey
);
1407 ms
.SetShiftDown(modifiers
& shiftKey
);
1408 ms
.SetAltDown(modifiers
& optionKey
);
1409 ms
.SetControlDown(modifiers
& cmdKey
);
1416 // TODO : once the new key/char handling is tested, move all the code to wxWindow
1418 bool wxApp::MacSendKeyDownEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1423 wxKeyEvent
event(wxEVT_KEY_DOWN
) ;
1424 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, uniChar
) ;
1426 return focus
->OSXHandleKeyEvent(event
);
1429 bool wxApp::MacSendKeyUpEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1434 wxKeyEvent
event( wxEVT_KEY_UP
) ;
1435 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, uniChar
) ;
1437 return focus
->OSXHandleKeyEvent(event
) ;
1440 bool wxApp::MacSendCharEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1444 wxKeyEvent
event(wxEVT_CHAR
) ;
1445 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, uniChar
) ;
1447 bool handled
= false ;
1449 #if wxOSX_USE_CARBON
1450 long keyval
= event
.m_keyCode
;
1453 wxKeyEvent
eventCharHook(wxEVT_CHAR_HOOK
, event
);
1454 handled
= focus
->HandleWindowEvent( eventCharHook
);
1455 if ( handled
&& eventCharHook
.IsNextEventAllowed() )
1461 handled
= focus
->HandleWindowEvent( event
) ;
1464 if ( !handled
&& (keyval
== WXK_TAB
) )
1466 wxWindow
* iter
= focus
->GetParent() ;
1467 while ( iter
&& !handled
)
1469 if ( iter
->HasFlag( wxTAB_TRAVERSAL
) )
1471 wxNavigationKeyEvent new_event
;
1472 new_event
.SetEventObject( focus
);
1473 new_event
.SetDirection( !event
.ShiftDown() );
1474 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1475 new_event
.SetWindowChange( event
.ControlDown() );
1476 new_event
.SetCurrentFocus( focus
);
1477 handled
= focus
->GetParent()->HandleWindowEvent( new_event
);
1478 if ( handled
&& new_event
.GetSkipped() )
1482 iter
= iter
->GetParent() ;
1486 // backdoor handler for default return and command escape
1487 if ( !handled
&& (!focus
->IsKindOf(CLASSINFO(wxControl
) ) || !focus
->AcceptsFocus() ) )
1489 // if window is not having a focus still testing for default enter or cancel
1490 // TODO: add the UMA version for ActiveNonFloatingWindow
1492 wxWindow
* focus
= wxNonOwnedWindow::GetFromWXWindow( (WXWindow
) FrontWindow() ) ;
1495 if ( keyval
== WXK_RETURN
|| keyval
== WXK_NUMPAD_ENTER
)
1497 wxTopLevelWindow
*tlw
= wxDynamicCast(wxGetTopLevelParent(focus
), wxTopLevelWindow
);
1498 if ( tlw
&& tlw
->GetDefaultItem() )
1500 wxButton
*def
= wxDynamicCast(tlw
->GetDefaultItem(), wxButton
);
1501 if ( def
&& def
->IsEnabled() )
1503 wxCommandEvent
event(wxEVT_BUTTON
, def
->GetId() );
1504 event
.SetEventObject(def
);
1505 def
->Command(event
);
1511 else if (keyval
== WXK_ESCAPE
|| (keyval
== '.' && modifiers
& cmdKey
) )
1513 // generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs)
1514 wxCommandEvent
new_event(wxEVT_BUTTON
,wxID_CANCEL
);
1515 new_event
.SetEventObject( focus
);
1516 handled
= focus
->HandleWindowEvent( new_event
);
1525 // This method handles common code for SendKeyDown, SendKeyUp, and SendChar events.
1526 void wxApp::MacCreateKeyEvent( wxKeyEvent
& event
, wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1528 #if wxOSX_USE_COCOA_OR_CARBON
1530 short keycode
, keychar
;
1532 keychar
= short(keymessage
& charCodeMask
);
1533 keycode
= short(keymessage
& keyCodeMask
) >> 8 ;
1534 if ( !(event
.GetEventType() == wxEVT_CHAR
) && (modifiers
& (controlKey
| shiftKey
| optionKey
) ) )
1536 // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
1537 // and look at the character after
1539 // TODO new implementation using TextInputSources
1542 UInt32 keyInfo
= KeyTranslate((Ptr
)GetScriptManagerVariable(smKCHRCache
), ( modifiers
& (~(controlKey
| shiftKey
| optionKey
))) | keycode
, &state
);
1543 keychar
= short(keyInfo
& charCodeMask
);
1547 long keyval
= wxMacTranslateKey(keychar
, keycode
) ;
1548 if ( keyval
== keychar
&& ( event
.GetEventType() == wxEVT_KEY_UP
|| event
.GetEventType() == wxEVT_KEY_DOWN
) )
1549 keyval
= wxToupper( keyval
) ;
1551 // Check for NUMPAD keys. For KEY_UP/DOWN events we need to use the
1552 // WXK_NUMPAD constants, but for the CHAR event we want to use the
1553 // standard ascii values
1554 if ( event
.GetEventType() != wxEVT_CHAR
)
1556 if (keyval
>= '0' && keyval
<= '9' && keycode
>= 82 && keycode
<= 92)
1558 keyval
= (keyval
- '0') + WXK_NUMPAD0
;
1560 else if (keycode
>= 65 && keycode
<= 81)
1565 keyval
= WXK_NUMPAD_ENTER
;
1569 keyval
= WXK_NUMPAD_EQUAL
;
1573 keyval
= WXK_NUMPAD_MULTIPLY
;
1577 keyval
= WXK_NUMPAD_DIVIDE
;
1581 keyval
= WXK_NUMPAD_SUBTRACT
;
1585 keyval
= WXK_NUMPAD_ADD
;
1589 keyval
= WXK_NUMPAD_DECIMAL
;
1597 event
.m_shiftDown
= modifiers
& shiftKey
;
1598 event
.m_rawControlDown
= modifiers
& controlKey
;
1599 event
.m_altDown
= modifiers
& optionKey
;
1600 event
.m_controlDown
= modifiers
& cmdKey
;
1601 event
.m_keyCode
= keyval
;
1603 event
.m_uniChar
= uniChar
;
1606 event
.m_rawCode
= keymessage
;
1607 event
.m_rawFlags
= modifiers
;
1608 event
.SetTimestamp(when
);
1609 event
.SetEventObject(focus
);
1613 wxUnusedVar(keymessage
);
1614 wxUnusedVar(modifiers
);
1616 wxUnusedVar(uniChar
);
1621 void wxApp::MacHideApp()
1623 #if wxOSX_USE_CARBON
1624 wxMacCarbonEvent
event( kEventClassCommand
, kEventCommandProcess
);
1626 memset( &command
, 0 , sizeof(command
) );
1627 command
.commandID
= kHICommandHide
;
1628 event
.SetParameter
<HICommand
>(kEventParamDirectObject
, command
);
1629 SendEventToApplication( event
);