1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/app.cpp
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
20 #include "wx/window.h"
23 #include "wx/button.h"
27 #include "wx/palette.h"
29 #include "wx/cursor.h"
30 #include "wx/dialog.h"
31 #include "wx/msgdlg.h"
32 #include "wx/textctrl.h"
33 #include "wx/memory.h"
34 #include "wx/gdicmn.h"
35 #include "wx/module.h"
38 #include "wx/tooltip.h"
39 #include "wx/docview.h"
40 #include "wx/filename.h"
42 #include "wx/thread.h"
43 #include "wx/evtloop.h"
49 #include "wx/osx/uma.h"
51 #include "wx/osx/private.h"
54 #if defined(WXMAKINGDLL_CORE)
55 # include <mach-o/dyld.h>
58 // Keep linker from discarding wxStockGDIMac
59 wxFORCE_LINK_MODULE(gdiobj
)
61 IMPLEMENT_DYNAMIC_CLASS(wxApp
, wxEvtHandler
)
62 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
)
63 EVT_IDLE(wxApp::OnIdle
)
64 EVT_END_SESSION(wxApp::OnEndSession
)
65 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession
)
69 // platform specific static variables
70 static const short kwxMacAppleMenuId
= 1 ;
72 wxWindow
* wxApp::s_captureWindow
= NULL
;
73 long wxApp::s_lastModifiers
= 0 ;
75 long wxApp::s_macAboutMenuItemId
= wxID_ABOUT
;
76 long wxApp::s_macPreferencesMenuItemId
= wxID_PREFERENCES
;
77 long wxApp::s_macExitMenuItemId
= wxID_EXIT
;
78 wxString
wxApp::s_macHelpMenuTitleName
= wxT("&Help") ;
80 bool wxApp::sm_isEmbedded
= false; // Normally we're not a plugin
84 //----------------------------------------------------------------------
85 // Core Apple Event Support
86 //----------------------------------------------------------------------
88 AEEventHandlerUPP sODocHandler
= NULL
;
89 AEEventHandlerUPP sGURLHandler
= NULL
;
90 AEEventHandlerUPP sOAppHandler
= NULL
;
91 AEEventHandlerUPP sPDocHandler
= NULL
;
92 AEEventHandlerUPP sRAppHandler
= NULL
;
93 AEEventHandlerUPP sQuitHandler
= NULL
;
95 pascal OSErr
AEHandleODoc( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon refcon
) ;
96 pascal OSErr
AEHandleOApp( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon refcon
) ;
97 pascal OSErr
AEHandlePDoc( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon refcon
) ;
98 pascal OSErr
AEHandleQuit( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon refcon
) ;
99 pascal OSErr
AEHandleRApp( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon refcon
) ;
100 pascal OSErr
AEHandleGURL( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon refcon
) ;
102 pascal OSErr
AEHandleODoc( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon
WXUNUSED(refcon
) )
104 return wxTheApp
->MacHandleAEODoc( (AppleEvent
*) event
, reply
) ;
107 pascal OSErr
AEHandleOApp( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon
WXUNUSED(refcon
) )
109 return wxTheApp
->MacHandleAEOApp( (AppleEvent
*) event
, reply
) ;
112 pascal OSErr
AEHandlePDoc( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon
WXUNUSED(refcon
) )
114 return wxTheApp
->MacHandleAEPDoc( (AppleEvent
*) event
, reply
) ;
117 pascal OSErr
AEHandleQuit( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon
WXUNUSED(refcon
) )
119 return wxTheApp
->MacHandleAEQuit( (AppleEvent
*) event
, reply
) ;
122 pascal OSErr
AEHandleRApp( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon
WXUNUSED(refcon
) )
124 return wxTheApp
->MacHandleAERApp( (AppleEvent
*) event
, reply
) ;
127 pascal OSErr
AEHandleGURL( const AppleEvent
*event
, AppleEvent
*reply
, SRefCon
WXUNUSED(refcon
) )
129 return wxTheApp
->MacHandleAEGURL((WXEVENTREF
*)event
, reply
) ;
133 // AEODoc Calls MacOpenFiles with all of the files passed
135 short wxApp::MacHandleAEODoc(const WXEVENTREF event
, WXEVENTREF
WXUNUSED(reply
))
139 DescType returnedType
;
145 err
= AEGetParamDesc((AppleEvent
*)event
, keyDirectObject
, typeAEList
,&docList
);
149 err
= AECountItems(&docList
, &itemsInList
);
153 ProcessSerialNumber PSN
;
154 PSN
.highLongOfPSN
= 0 ;
155 PSN
.lowLongOfPSN
= kCurrentProcess
;
156 SetFrontProcess( &PSN
) ;
161 wxArrayString fileNames
;
162 for (i
= 1; i
<= itemsInList
; i
++)
165 &docList
, i
, typeFSRef
, &keywd
, &returnedType
,
166 (Ptr
)&theRef
, sizeof(theRef
), &actualSize
);
171 fName
= wxMacFSRefToPath( &theRef
) ;
173 fileNames
.Add(fName
);
176 MacOpenFiles(fileNames
);
181 // AEODoc Calls MacOpenURL on the url passed
183 short wxApp::MacHandleAEGURL(const WXEVENTREF event
, WXEVENTREF
WXUNUSED(reply
))
185 DescType returnedType
;
188 OSErr err
= AEGetParamPtr((AppleEvent
*)event
, keyDirectObject
, typeChar
,
189 &returnedType
, url
, sizeof(url
)-1,
194 url
[actualSize
] = '\0'; // Terminate the C string
196 ProcessSerialNumber PSN
;
197 PSN
.highLongOfPSN
= 0 ;
198 PSN
.lowLongOfPSN
= kCurrentProcess
;
199 SetFrontProcess( &PSN
) ;
201 MacOpenURL(wxString(url
, wxConvUTF8
));
206 // AEPDoc Calls MacPrintFile on each of the files passed
208 short wxApp::MacHandleAEPDoc(const WXEVENTREF event
, WXEVENTREF
WXUNUSED(reply
))
212 DescType returnedType
;
218 err
= AEGetParamDesc((AppleEvent
*)event
, keyDirectObject
, typeAEList
,&docList
);
222 err
= AECountItems(&docList
, &itemsInList
);
226 ProcessSerialNumber PSN
;
227 PSN
.highLongOfPSN
= 0 ;
228 PSN
.lowLongOfPSN
= kCurrentProcess
;
229 SetFrontProcess( &PSN
) ;
234 for (i
= 1; i
<= itemsInList
; i
++)
237 &docList
, i
, typeFSRef
, &keywd
, &returnedType
,
238 (Ptr
)&theRef
, sizeof(theRef
), &actualSize
);
243 fName
= wxMacFSRefToPath( &theRef
) ;
251 // AEOApp calls MacNewFile
253 short wxApp::MacHandleAEOApp(const WXEVENTREF
WXUNUSED(event
) , WXEVENTREF
WXUNUSED(reply
))
259 // AEQuit attempts to quit the application
261 short wxApp::MacHandleAEQuit(const WXEVENTREF
WXUNUSED(event
) , WXEVENTREF
WXUNUSED(reply
))
264 wxTheApp
->OnQueryEndSession(event
);
265 if ( !event
.GetVeto() )
268 wxTheApp
->OnEndSession(event
);
273 // AEROApp calls MacReopenApp
275 short wxApp::MacHandleAERApp(const WXEVENTREF
WXUNUSED(event
) , WXEVENTREF
WXUNUSED(reply
))
284 //----------------------------------------------------------------------
285 // Support Routines linking the Mac...File Calls to the Document Manager
286 //----------------------------------------------------------------------
288 void wxApp::MacOpenFiles(const wxArrayString
& fileNames
)
291 const size_t fileCount
= fileNames
.GetCount();
292 for (i
= 0; i
< fileCount
; i
++)
294 MacOpenFile(fileNames
[i
]);
298 void wxApp::MacOpenFile(const wxString
& fileName
)
300 #if wxUSE_DOC_VIEW_ARCHITECTURE
301 wxDocManager
* dm
= wxDocManager::GetDocumentManager() ;
303 dm
->CreateDocument(fileName
, wxDOC_SILENT
) ;
307 void wxApp::MacOpenURL(const wxString
& WXUNUSED(url
) )
311 void wxApp::MacPrintFile(const wxString
& fileName
)
313 #if wxUSE_DOC_VIEW_ARCHITECTURE
315 #if wxUSE_PRINTING_ARCHITECTURE
316 wxDocManager
* dm
= wxDocManager::GetDocumentManager() ;
319 wxDocument
*doc
= dm
->CreateDocument(fileName
, wxDOC_SILENT
) ;
322 wxView
* view
= doc
->GetFirstView() ;
325 wxPrintout
*printout
= view
->OnCreatePrintout();
329 printer
.Print(view
->GetFrame(), printout
, true);
336 doc
->DeleteAllViews();
337 dm
->RemoveDocument(doc
) ;
348 void wxApp::MacNewFile()
352 void wxApp::MacReopenApp()
355 // if there is no open window -> create a new one
356 // if all windows are hidden -> show the first
357 // if some windows are not hidden -> do nothing
359 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetFirst();
366 wxTopLevelWindow
* firstIconized
= NULL
;
367 wxTopLevelWindow
* firstHidden
= NULL
;
370 wxTopLevelWindow
* win
= (wxTopLevelWindow
*) node
->GetData();
371 if ( !win
->IsShown() )
373 // make sure we don't show 'virtual toplevel windows' like wxTaskBarIconWindow
374 if ( firstHidden
== NULL
&& ( wxDynamicCast( win
, wxFrame
) || wxDynamicCast( win
, wxDialog
) ) )
377 else if ( win
->IsIconized() )
379 if ( firstIconized
== NULL
)
380 firstIconized
= win
;
384 // we do have a visible, non-iconized toplevelwindow -> do nothing
388 node
= node
->GetNext();
392 firstIconized
->Iconize( false ) ;
393 else if ( firstHidden
)
394 firstHidden
->Show( true );
398 //----------------------------------------------------------------------
399 // Macintosh CommandID support - converting between native and wx IDs
400 //----------------------------------------------------------------------
402 // if no native match they just return the passed-in id
412 IdPair gCommandIds
[] =
414 { kHICommandCut
, wxID_CUT
} ,
415 { kHICommandCopy
, wxID_COPY
} ,
416 { kHICommandPaste
, wxID_PASTE
} ,
417 { kHICommandSelectAll
, wxID_SELECTALL
} ,
418 { kHICommandClear
, wxID_CLEAR
} ,
419 { kHICommandUndo
, wxID_UNDO
} ,
420 { kHICommandRedo
, wxID_REDO
} ,
423 int wxMacCommandToId( UInt32 macCommandId
)
427 switch ( macCommandId
)
429 case kHICommandPreferences
:
430 wxid
= wxApp::s_macPreferencesMenuItemId
;
433 case kHICommandQuit
:
434 wxid
= wxApp::s_macExitMenuItemId
;
437 case kHICommandAbout
:
438 wxid
= wxApp::s_macAboutMenuItemId
;
443 for ( size_t i
= 0 ; i
< WXSIZEOF(gCommandIds
) ; ++i
)
445 if ( gCommandIds
[i
].macId
== macCommandId
)
447 wxid
= gCommandIds
[i
].wxId
;
456 wxid
= (int) macCommandId
;
461 UInt32
wxIdToMacCommand( int wxId
)
465 if ( wxId
== wxApp::s_macPreferencesMenuItemId
)
466 macId
= kHICommandPreferences
;
467 else if (wxId
== wxApp::s_macExitMenuItemId
)
468 macId
= kHICommandQuit
;
469 else if (wxId
== wxApp::s_macAboutMenuItemId
)
470 macId
= kHICommandAbout
;
473 for ( size_t i
= 0 ; i
< WXSIZEOF(gCommandIds
) ; ++i
)
475 if ( gCommandIds
[i
].wxId
== wxId
)
477 macId
= gCommandIds
[i
].macId
;
489 wxMenu
* wxFindMenuFromMacCommand( const HICommand
&command
, wxMenuItem
* &item
)
491 wxMenu
* itemMenu
= NULL
;
492 #ifndef __WXUNIVERSAL__
495 // for 'standard' commands which don't have a wx-menu
496 if ( command
.commandID
== kHICommandPreferences
|| command
.commandID
== kHICommandQuit
|| command
.commandID
== kHICommandAbout
)
498 id
= wxMacCommandToId( command
.commandID
) ;
500 wxMenuBar
* mbar
= wxMenuBar::MacGetInstalledMenuBar() ;
502 item
= mbar
->FindItem( id
, &itemMenu
) ;
504 else if ( command
.commandID
!= 0 && command
.menu
.menuRef
!= 0 && command
.menu
.menuItemIndex
!= 0 )
506 id
= wxMacCommandToId( command
.commandID
) ;
507 // make sure it is one of our own menus, or of the 'synthetic' apple and help menus , otherwise don't touch
508 MenuItemIndex firstUserHelpMenuItem
;
509 static MenuHandle helpMenuHandle
= NULL
;
510 if ( helpMenuHandle
== NULL
)
512 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
513 helpMenuHandle
= NULL
;
516 // is it part of the application or the Help menu, then look for the id directly
517 if ( ( GetMenuHandle( kwxMacAppleMenuId
) != NULL
&& command
.menu
.menuRef
== GetMenuHandle( kwxMacAppleMenuId
) ) ||
518 ( helpMenuHandle
!= NULL
&& command
.menu
.menuRef
== helpMenuHandle
) ||
519 wxMenuBar::MacGetWindowMenuHMenu() != NULL
&& command
.menu
.menuRef
== wxMenuBar::MacGetWindowMenuHMenu() )
521 wxMenuBar
* mbar
= wxMenuBar::MacGetInstalledMenuBar() ;
523 item
= mbar
->FindItem( id
, &itemMenu
) ;
529 GetMenuItemRefCon( command
.menu
.menuRef
, command
.menu
.menuItemIndex
, &refCon
) ;
530 itemMenu
= wxFindMenuFromMacMenu( command
.menu
.menuRef
) ;
531 if ( itemMenu
!= NULL
&& refCon
!= 0)
532 item
= (wxMenuItem
*) refCon
;
541 //----------------------------------------------------------------------
542 // Carbon Event Handler
543 //----------------------------------------------------------------------
547 static const EventTypeSpec eventList
[] =
549 { kEventClassCommand
, kEventProcessCommand
} ,
550 { kEventClassCommand
, kEventCommandUpdateStatus
} ,
552 { kEventClassMenu
, kEventMenuOpening
},
553 { kEventClassMenu
, kEventMenuClosed
},
554 { kEventClassMenu
, kEventMenuTargetItem
},
556 { kEventClassApplication
, kEventAppActivated
} ,
557 { kEventClassApplication
, kEventAppDeactivated
} ,
558 // handling the quit event is not recommended by apple
559 // rather using the quit apple event - which we do
561 { kEventClassAppleEvent
, kEventAppleEvent
} ,
563 { kEventClassMouse
, kEventMouseDown
} ,
564 { kEventClassMouse
, kEventMouseMoved
} ,
565 { kEventClassMouse
, kEventMouseUp
} ,
566 { kEventClassMouse
, kEventMouseDragged
} ,
570 static pascal OSStatus
571 wxMacAppMenuEventHandler( EventHandlerCallRef
WXUNUSED(handler
),
573 void *WXUNUSED(data
) )
575 wxMacCarbonEvent
cEvent( event
) ;
576 MenuRef menuRef
= cEvent
.GetParameter
<MenuRef
>(kEventParamDirectObject
) ;
577 #ifndef __WXUNIVERSAL__
578 wxMenu
* menu
= wxFindMenuFromMacMenu( menuRef
) ;
582 switch (GetEventKind(event
))
584 case kEventMenuOpening
:
585 menu
->HandleMenuOpened();
588 case kEventMenuClosed
:
589 menu
->HandleMenuClosed();
592 case kEventMenuTargetItem
:
596 command
.menu
.menuRef
= menuRef
;
597 command
.menu
.menuItemIndex
= cEvent
.GetParameter
<MenuItemIndex
>(kEventParamMenuItemIndex
,typeMenuItemIndex
) ;
598 command
.commandID
= cEvent
.GetParameter
<MenuCommand
>(kEventParamMenuCommand
,typeMenuCommand
) ;
599 if (command
.commandID
!= 0)
601 wxMenuItem
* item
= NULL
;
602 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
603 if ( itemMenu
&& item
)
604 itemMenu
->HandleMenuItemHighlighted( item
);
610 wxFAIL_MSG(wxT("Unexpected menu event kind"));
616 return eventNotHandledErr
;
619 static pascal OSStatus
620 wxMacAppCommandEventHandler( EventHandlerCallRef
WXUNUSED(handler
) ,
622 void *WXUNUSED(data
) )
624 OSStatus result
= eventNotHandledErr
;
628 wxMacCarbonEvent
cEvent( event
) ;
629 cEvent
.GetParameter
<HICommand
>(kEventParamDirectObject
,typeHICommand
,&command
) ;
631 wxMenuItem
* item
= NULL
;
632 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
636 wxASSERT( itemMenu
!= NULL
) ;
638 switch ( cEvent
.GetKind() )
640 case kEventProcessCommand
:
641 if ( itemMenu
->HandleCommandProcess( item
) )
645 case kEventCommandUpdateStatus
:
646 if ( itemMenu
->HandleCommandUpdateStatus( item
) )
657 static pascal OSStatus
658 wxMacAppApplicationEventHandler( EventHandlerCallRef
WXUNUSED(handler
) ,
660 void *WXUNUSED(data
) )
662 OSStatus result
= eventNotHandledErr
;
663 switch ( GetEventKind( event
) )
665 case kEventAppActivated
:
667 wxTheApp
->SetActive( true , NULL
) ;
671 case kEventAppDeactivated
:
673 wxTheApp
->SetActive( false , NULL
) ;
684 pascal OSStatus
wxMacAppEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
686 EventRef formerEvent
= (EventRef
) wxTheApp
->MacGetCurrentEvent() ;
687 EventHandlerCallRef formerEventHandlerCallRef
= (EventHandlerCallRef
) wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
688 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
690 OSStatus result
= eventNotHandledErr
;
691 switch ( GetEventClass( event
) )
694 case kEventClassCommand
:
695 result
= wxMacAppCommandEventHandler( handler
, event
, data
) ;
698 case kEventClassApplication
:
699 result
= wxMacAppApplicationEventHandler( handler
, event
, data
) ;
702 case kEventClassMenu
:
703 result
= wxMacAppMenuEventHandler( handler
, event
, data
) ;
706 case kEventClassMouse
:
708 wxMacCarbonEvent
cEvent( event
) ;
711 Point screenMouseLocation
= cEvent
.GetParameter
<Point
>(kEventParamMouseLocation
) ;
712 ::FindWindow(screenMouseLocation
, &window
);
713 // only send this event in case it had not already been sent to a tlw, as we get
714 // double events otherwise (in case event.skip) was called
715 if ( window
== NULL
)
716 result
= wxMacTopLevelMouseEventHandler( handler
, event
, NULL
) ;
720 case kEventClassAppleEvent
:
721 result
= AEProcessEvent(event
);
728 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerEventHandlerCallRef
) ;
733 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacAppEventHandler
)
736 #if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
739 wxMacAssertOutputHandler(OSType
WXUNUSED(componentSignature
),
740 UInt32
WXUNUSED(options
),
741 const char *assertionString
,
742 const char *exceptionLabelString
,
743 const char *errorString
,
744 const char *fileName
,
747 ConstStr255Param
WXUNUSED(outputMsg
))
749 // flow into assert handling
750 wxString fileNameStr
;
751 wxString assertionStr
;
752 wxString exceptionStr
;
756 fileNameStr
= wxString(fileName
, wxConvLocal
);
757 assertionStr
= wxString(assertionString
, wxConvLocal
);
758 exceptionStr
= wxString((exceptionLabelString
!=0) ? exceptionLabelString
: "", wxConvLocal
) ;
759 errorStr
= wxString((errorString
!=0) ? errorString
: "", wxConvLocal
) ;
761 fileNameStr
= fileName
;
762 assertionStr
= assertionString
;
763 exceptionStr
= (exceptionLabelString
!=0) ? exceptionLabelString
: "" ;
764 errorStr
= (errorString
!=0) ? errorString
: "" ;
769 wxLogDebug( wxT("AssertMacros: %s %s %s file: %s, line: %ld (value %p)\n"),
770 assertionStr
.c_str() ,
771 exceptionStr
.c_str() ,
773 fileNameStr
.c_str(), lineNumber
,
777 wxOnAssert(fileNameStr
, lineNumber
, assertionStr
,
778 wxString::Format( wxT("%s %s value (%p)") , exceptionStr
, errorStr
, value
) ) ;
782 #endif // wxDEBUG_LEVEL
784 bool wxApp::Initialize(int& argc
, wxChar
**argv
)
788 #if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
789 InstallDebugAssertOutputHandler( NewDebugAssertOutputHandlerUPP( wxMacAssertOutputHandler
) );
792 // Mac OS X passes a process serial number command line argument when
793 // the application is launched from the Finder. This argument must be
794 // removed from the command line arguments before being handled by the
795 // application (otherwise applications would need to handle it)
798 static const wxChar
*ARG_PSN
= wxT("-psn_");
799 if ( wxStrncmp(argv
[1], ARG_PSN
, wxStrlen(ARG_PSN
)) == 0 )
801 // remove this argument
803 memmove(argv
+ 1, argv
+ 2, argc
* sizeof(wxChar
*));
808 Cocoa supports -Key value options which set the user defaults key "Key"
809 to the value "value" Some of them are very handy for debugging like
810 -NSShowAllViews YES. Cocoa picks these up from the real argv so
811 our removal of them from the wx copy of it does not affect Cocoa's
814 We basically just assume that any "-NS" option and its following
815 argument needs to be removed from argv. We hope that user code does
816 not expect to see -NS options and indeed it's probably a safe bet
817 since most user code accepting options is probably using the
818 double-dash GNU-style syntax.
820 for(int i
=1; i
< argc
; ++i
)
822 static const wxChar
*ARG_NS
= wxT("-NS");
823 if( wxStrncmp(argv
[i
], ARG_NS
, wxStrlen(ARG_NS
)) == 0 )
825 // Only eat this option if it has an argument
828 memmove(argv
+ i
, argv
+ i
+ 2, (argc
-i
-1)*sizeof(wxChar
*));
830 // drop back one position so the next run through the loop
831 // reprocesses the argument at our current index.
837 if ( !wxAppBase::Initialize(argc
, argv
) )
841 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
844 // these might be the startup dirs, set them to the 'usual' dir containing the app bundle
845 wxString startupCwd
= wxGetCwd() ;
846 if ( startupCwd
== wxT("/") || startupCwd
.Right(15) == wxT("/Contents/MacOS") )
848 CFURLRef url
= CFBundleCopyBundleURL(CFBundleGetMainBundle() ) ;
849 CFURLRef urlParent
= CFURLCreateCopyDeletingLastPathComponent( kCFAllocatorDefault
, url
) ;
851 CFStringRef path
= CFURLCopyFileSystemPath ( urlParent
, kCFURLPOSIXPathStyle
) ;
852 CFRelease( urlParent
) ;
853 wxString cwd
= wxCFStringRef(path
).AsString(wxLocale::GetSystemEncoding());
854 wxSetWorkingDirectory( cwd
) ;
860 #if wxOSX_USE_COCOA_OR_CARBON
861 bool wxApp::CallOnInit()
863 wxMacAutoreleasePool autoreleasepool
;
868 bool wxApp::OnInitGui()
870 if ( !wxAppBase::OnInitGui() )
879 bool wxApp::ProcessIdle()
881 wxMacAutoreleasePool autoreleasepool
;
882 return wxAppBase::ProcessIdle();
887 wxMacAutoreleasePool pool
;
888 return wxAppBase::OnRun();
892 bool wxApp::DoInitGui()
894 InstallStandardEventHandler( GetApplicationEventTarget() ) ;
897 InstallApplicationEventHandler(
898 GetwxMacAppEventHandlerUPP(),
899 GetEventTypeCount(eventList
), eventList
, wxTheApp
, (EventHandlerRef
*)&(wxTheApp
->m_macEventHandler
));
904 sODocHandler
= NewAEEventHandlerUPP(AEHandleODoc
) ;
905 sGURLHandler
= NewAEEventHandlerUPP(AEHandleGURL
) ;
906 sOAppHandler
= NewAEEventHandlerUPP(AEHandleOApp
) ;
907 sPDocHandler
= NewAEEventHandlerUPP(AEHandlePDoc
) ;
908 sRAppHandler
= NewAEEventHandlerUPP(AEHandleRApp
) ;
909 sQuitHandler
= NewAEEventHandlerUPP(AEHandleQuit
) ;
911 AEInstallEventHandler( kCoreEventClass
, kAEOpenDocuments
,
912 sODocHandler
, 0 , FALSE
) ;
913 AEInstallEventHandler( kInternetEventClass
, kAEGetURL
,
914 sGURLHandler
, 0 , FALSE
) ;
915 AEInstallEventHandler( kCoreEventClass
, kAEOpenApplication
,
916 sOAppHandler
, 0 , FALSE
) ;
917 AEInstallEventHandler( kCoreEventClass
, kAEPrintDocuments
,
918 sPDocHandler
, 0 , FALSE
) ;
919 AEInstallEventHandler( kCoreEventClass
, kAEReopenApplication
,
920 sRAppHandler
, 0 , FALSE
) ;
921 AEInstallEventHandler( kCoreEventClass
, kAEQuitApplication
,
922 sQuitHandler
, 0 , FALSE
) ;
925 if ( !wxMacInitCocoa() )
931 void wxApp::DoCleanUp()
934 RemoveEventHandler( (EventHandlerRef
)(wxTheApp
->m_macEventHandler
) );
938 AERemoveEventHandler( kCoreEventClass
, kAEOpenDocuments
,
939 sODocHandler
, FALSE
) ;
940 AERemoveEventHandler( kInternetEventClass
, kAEGetURL
,
941 sGURLHandler
, FALSE
) ;
942 AERemoveEventHandler( kCoreEventClass
, kAEOpenApplication
,
943 sOAppHandler
, FALSE
) ;
944 AERemoveEventHandler( kCoreEventClass
, kAEPrintDocuments
,
945 sPDocHandler
, FALSE
) ;
946 AERemoveEventHandler( kCoreEventClass
, kAEReopenApplication
,
947 sRAppHandler
, FALSE
) ;
948 AERemoveEventHandler( kCoreEventClass
, kAEQuitApplication
,
949 sQuitHandler
, FALSE
) ;
951 DisposeAEEventHandlerUPP( sODocHandler
) ;
952 DisposeAEEventHandlerUPP( sGURLHandler
) ;
953 DisposeAEEventHandlerUPP( sOAppHandler
) ;
954 DisposeAEEventHandlerUPP( sPDocHandler
) ;
955 DisposeAEEventHandlerUPP( sRAppHandler
) ;
956 DisposeAEEventHandlerUPP( sQuitHandler
) ;
962 void wxApp::CleanUp()
964 wxMacAutoreleasePool autoreleasepool
;
966 wxToolTip::RemoveToolTips() ;
971 wxAppBase::CleanUp();
974 //----------------------------------------------------------------------
975 // misc initialization stuff
976 //----------------------------------------------------------------------
980 m_printMode
= wxPRINT_WINDOWS
;
982 m_macCurrentEvent
= NULL
;
983 m_macCurrentEventHandlerCallRef
= NULL
;
984 m_macPool
= new wxMacAutoreleasePool();
993 CFMutableArrayRef
GetAutoReleaseArray()
995 static CFMutableArrayRef array
= 0;
997 array
= CFArrayCreateMutable(kCFAllocatorDefault
,0,&kCFTypeArrayCallBacks
);
1001 void wxApp::MacAddToAutorelease( void* cfrefobj
)
1003 CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj
);
1006 void wxApp::MacReleaseAutoreleasePool()
1010 m_macPool
= new wxMacAutoreleasePool();
1013 void wxApp::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1015 // If they are pending events, we must process them: pending events are
1016 // either events to the threads other than main or events posted with
1017 // wxPostEvent() functions
1018 #ifndef __WXUNIVERSAL__
1020 if (!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar())
1021 wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar();
1024 CFArrayRemoveAllValues( GetAutoReleaseArray() );
1027 void wxApp::WakeUpIdle()
1029 wxEventLoopBase
* const loop
= wxEventLoopBase::GetActive();
1035 void wxApp::OnEndSession(wxCloseEvent
& WXUNUSED(event
))
1038 GetTopWindow()->Close(true);
1041 // Default behaviour: close the application with prompts. The
1042 // user can veto the close, and therefore the end session.
1043 void wxApp::OnQueryEndSession(wxCloseEvent
& event
)
1045 if ( !wxDialog::OSXHasModalDialogsOpen() )
1049 if (!GetTopWindow()->Close(!event
.CanVeto()))
1059 extern "C" void wxCYield() ;
1066 void wxApp::MacHandleUnhandledEvent( WXEVENTREF
WXUNUSED(evr
) )
1068 // Override to process unhandled events as you please
1071 #if wxOSX_USE_COCOA_OR_CARBON
1073 CGKeyCode
wxCharCodeWXToOSX(wxKeyCode code
)
1079 // Clang warns about switch values not of the same type as (enumerated)
1080 // switch controlling expression. This is generally useful but here we
1081 // really want to be able to use letters and digits without making them
1082 // part of wxKeyCode enum.
1084 #pragma clang diagnostic push
1085 #pragma clang diagnostic ignored "-Wswitch"
1088 case 'a': case 'A': keycode
= kVK_ANSI_A
; break;
1089 case 'b': case 'B': keycode
= kVK_ANSI_B
; break;
1090 case 'c': case 'C': keycode
= kVK_ANSI_C
; break;
1091 case 'd': case 'D': keycode
= kVK_ANSI_D
; break;
1092 case 'e': case 'E': keycode
= kVK_ANSI_E
; break;
1093 case 'f': case 'F': keycode
= kVK_ANSI_F
; break;
1094 case 'g': case 'G': keycode
= kVK_ANSI_G
; break;
1095 case 'h': case 'H': keycode
= kVK_ANSI_H
; break;
1096 case 'i': case 'I': keycode
= kVK_ANSI_I
; break;
1097 case 'j': case 'J': keycode
= kVK_ANSI_J
; break;
1098 case 'k': case 'K': keycode
= kVK_ANSI_K
; break;
1099 case 'l': case 'L': keycode
= kVK_ANSI_L
; break;
1100 case 'm': case 'M': keycode
= kVK_ANSI_M
; break;
1101 case 'n': case 'N': keycode
= kVK_ANSI_N
; break;
1102 case 'o': case 'O': keycode
= kVK_ANSI_O
; break;
1103 case 'p': case 'P': keycode
= kVK_ANSI_P
; break;
1104 case 'q': case 'Q': keycode
= kVK_ANSI_Q
; break;
1105 case 'r': case 'R': keycode
= kVK_ANSI_R
; break;
1106 case 's': case 'S': keycode
= kVK_ANSI_S
; break;
1107 case 't': case 'T': keycode
= kVK_ANSI_T
; break;
1108 case 'u': case 'U': keycode
= kVK_ANSI_U
; break;
1109 case 'v': case 'V': keycode
= kVK_ANSI_V
; break;
1110 case 'w': case 'W': keycode
= kVK_ANSI_W
; break;
1111 case 'x': case 'X': keycode
= kVK_ANSI_X
; break;
1112 case 'y': case 'Y': keycode
= kVK_ANSI_Y
; break;
1113 case 'z': case 'Z': keycode
= kVK_ANSI_Z
; break;
1115 case '0': keycode
= kVK_ANSI_0
; break;
1116 case '1': keycode
= kVK_ANSI_1
; break;
1117 case '2': keycode
= kVK_ANSI_2
; break;
1118 case '3': keycode
= kVK_ANSI_3
; break;
1119 case '4': keycode
= kVK_ANSI_4
; break;
1120 case '5': keycode
= kVK_ANSI_5
; break;
1121 case '6': keycode
= kVK_ANSI_6
; break;
1122 case '7': keycode
= kVK_ANSI_7
; break;
1123 case '8': keycode
= kVK_ANSI_8
; break;
1124 case '9': keycode
= kVK_ANSI_9
; break;
1127 #pragma clang diagnostic pop
1130 case WXK_BACK
: keycode
= kVK_Delete
; break;
1131 case WXK_TAB
: keycode
= kVK_Tab
; break;
1132 case WXK_RETURN
: keycode
= kVK_Return
; break;
1133 case WXK_ESCAPE
: keycode
= kVK_Escape
; break;
1134 case WXK_SPACE
: keycode
= kVK_Space
; break;
1135 case WXK_DELETE
: keycode
= kVK_Delete
; break;
1137 case WXK_SHIFT
: keycode
= kVK_Shift
; break;
1138 case WXK_ALT
: keycode
= kVK_Option
; break;
1139 case WXK_RAW_CONTROL
: keycode
= kVK_Control
; break;
1140 case WXK_CONTROL
: keycode
= kVK_Command
; break;
1142 case WXK_CAPITAL
: keycode
= kVK_CapsLock
; break;
1143 case WXK_END
: keycode
= kVK_End
; break;
1144 case WXK_HOME
: keycode
= kVK_Home
; break;
1145 case WXK_LEFT
: keycode
= kVK_LeftArrow
; break;
1146 case WXK_UP
: keycode
= kVK_UpArrow
; break;
1147 case WXK_RIGHT
: keycode
= kVK_RightArrow
; break;
1148 case WXK_DOWN
: keycode
= kVK_DownArrow
; break;
1150 case WXK_HELP
: keycode
= kVK_Help
; break;
1153 case WXK_NUMPAD0
: keycode
= kVK_ANSI_Keypad0
; break;
1154 case WXK_NUMPAD1
: keycode
= kVK_ANSI_Keypad1
; break;
1155 case WXK_NUMPAD2
: keycode
= kVK_ANSI_Keypad2
; break;
1156 case WXK_NUMPAD3
: keycode
= kVK_ANSI_Keypad3
; break;
1157 case WXK_NUMPAD4
: keycode
= kVK_ANSI_Keypad4
; break;
1158 case WXK_NUMPAD5
: keycode
= kVK_ANSI_Keypad5
; break;
1159 case WXK_NUMPAD6
: keycode
= kVK_ANSI_Keypad6
; break;
1160 case WXK_NUMPAD7
: keycode
= kVK_ANSI_Keypad7
; break;
1161 case WXK_NUMPAD8
: keycode
= kVK_ANSI_Keypad8
; break;
1162 case WXK_NUMPAD9
: keycode
= kVK_ANSI_Keypad9
; break;
1163 case WXK_F1
: keycode
= kVK_F1
; break;
1164 case WXK_F2
: keycode
= kVK_F2
; break;
1165 case WXK_F3
: keycode
= kVK_F3
; break;
1166 case WXK_F4
: keycode
= kVK_F4
; break;
1167 case WXK_F5
: keycode
= kVK_F5
; break;
1168 case WXK_F6
: keycode
= kVK_F6
; break;
1169 case WXK_F7
: keycode
= kVK_F7
; break;
1170 case WXK_F8
: keycode
= kVK_F8
; break;
1171 case WXK_F9
: keycode
= kVK_F9
; break;
1172 case WXK_F10
: keycode
= kVK_F10
; break;
1173 case WXK_F11
: keycode
= kVK_F11
; break;
1174 case WXK_F12
: keycode
= kVK_F12
; break;
1175 case WXK_F13
: keycode
= kVK_F13
; break;
1176 case WXK_F14
: keycode
= kVK_F14
; break;
1177 case WXK_F15
: keycode
= kVK_F15
; break;
1178 case WXK_F16
: keycode
= kVK_F16
; break;
1179 case WXK_F17
: keycode
= kVK_F17
; break;
1180 case WXK_F18
: keycode
= kVK_F18
; break;
1181 case WXK_F19
: keycode
= kVK_F19
; break;
1182 case WXK_F20
: keycode
= kVK_F20
; break;
1184 case WXK_PAGEUP
: keycode
= kVK_PageUp
; break;
1185 case WXK_PAGEDOWN
: keycode
= kVK_PageDown
; break;
1187 case WXK_NUMPAD_DELETE
: keycode
= kVK_ANSI_KeypadClear
; break;
1188 case WXK_NUMPAD_EQUAL
: keycode
= kVK_ANSI_KeypadEquals
; break;
1189 case WXK_NUMPAD_MULTIPLY
: keycode
= kVK_ANSI_KeypadMultiply
; break;
1190 case WXK_NUMPAD_ADD
: keycode
= kVK_ANSI_KeypadPlus
; break;
1191 case WXK_NUMPAD_SUBTRACT
: keycode
= kVK_ANSI_KeypadMinus
; break;
1192 case WXK_NUMPAD_DECIMAL
: keycode
= kVK_ANSI_KeypadDecimal
; break;
1193 case WXK_NUMPAD_DIVIDE
: keycode
= kVK_ANSI_KeypadDivide
; break;
1196 wxLogDebug( "Unrecognised keycode %d", code
);
1197 keycode
= static_cast<CGKeyCode
>(-1);
1203 long wxMacTranslateKey(unsigned char key
, unsigned char code
)
1208 case kHomeCharCode
:
1212 case kEnterCharCode
:
1213 retval
= WXK_RETURN
;
1219 case kHelpCharCode
:
1223 case kBackspaceCharCode
:
1231 case kPageUpCharCode
:
1232 retval
= WXK_PAGEUP
;
1235 case kPageDownCharCode
:
1236 retval
= WXK_PAGEDOWN
;
1239 case kReturnCharCode
:
1240 retval
= WXK_RETURN
;
1243 case kFunctionKeyCharCode
:
1313 case kEscapeCharCode
:
1314 retval
= WXK_ESCAPE
;
1317 case kLeftArrowCharCode
:
1321 case kRightArrowCharCode
:
1322 retval
= WXK_RIGHT
;
1325 case kUpArrowCharCode
:
1329 case kDownArrowCharCode
:
1333 case kDeleteCharCode
:
1334 retval
= WXK_DELETE
;
1344 int wxMacKeyCodeToModifier(wxKeyCode key
)
1362 case WXK_RAW_CONTROL
:
1371 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
1373 // defined in utils.mm
1375 #elif wxOSX_USE_COCOA_OR_CARBON
1377 wxMouseState
wxGetMouseState()
1381 wxPoint pt
= wxGetMousePosition();
1385 UInt32 buttons
= GetCurrentButtonState();
1386 ms
.SetLeftDown( (buttons
& 0x01) != 0 );
1387 ms
.SetMiddleDown( (buttons
& 0x04) != 0 );
1388 ms
.SetRightDown( (buttons
& 0x02) != 0 );
1390 UInt32 modifiers
= GetCurrentKeyModifiers();
1391 ms
.SetRawControlDown(modifiers
& controlKey
);
1392 ms
.SetShiftDown(modifiers
& shiftKey
);
1393 ms
.SetAltDown(modifiers
& optionKey
);
1394 ms
.SetControlDown(modifiers
& cmdKey
);
1401 // TODO : once the new key/char handling is tested, move all the code to wxWindow
1403 bool wxApp::MacSendKeyDownEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, short wherex
, short wherey
, wxChar uniChar
)
1408 wxKeyEvent
event(wxEVT_KEY_DOWN
) ;
1409 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, wherex
, wherey
, uniChar
) ;
1411 return focus
->OSXHandleKeyEvent(event
);
1414 bool wxApp::MacSendKeyUpEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, short wherex
, short wherey
, wxChar uniChar
)
1419 wxKeyEvent
event( wxEVT_KEY_UP
) ;
1420 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, wherex
, wherey
, uniChar
) ;
1422 return focus
->OSXHandleKeyEvent(event
) ;
1425 bool wxApp::MacSendCharEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, short wherex
, short wherey
, wxChar uniChar
)
1429 wxKeyEvent
event(wxEVT_CHAR
) ;
1430 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, wherex
, wherey
, uniChar
) ;
1432 bool handled
= false ;
1434 #if wxOSX_USE_CARBON
1435 long keyval
= event
.m_keyCode
;
1438 wxKeyEvent
eventCharHook(wxEVT_CHAR_HOOK
, event
);
1439 handled
= focus
->HandleWindowEvent( eventCharHook
);
1440 if ( handled
&& eventCharHook
.IsNextEventAllowed() )
1446 handled
= focus
->HandleWindowEvent( event
) ;
1449 if ( !handled
&& (keyval
== WXK_TAB
) )
1451 wxWindow
* iter
= focus
->GetParent() ;
1452 while ( iter
&& !handled
)
1454 if ( iter
->HasFlag( wxTAB_TRAVERSAL
) )
1456 wxNavigationKeyEvent new_event
;
1457 new_event
.SetEventObject( focus
);
1458 new_event
.SetDirection( !event
.ShiftDown() );
1459 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1460 new_event
.SetWindowChange( event
.ControlDown() );
1461 new_event
.SetCurrentFocus( focus
);
1462 handled
= focus
->GetParent()->HandleWindowEvent( new_event
);
1463 if ( handled
&& new_event
.GetSkipped() )
1467 iter
= iter
->GetParent() ;
1471 // backdoor handler for default return and command escape
1472 if ( !handled
&& (!focus
->IsKindOf(CLASSINFO(wxControl
) ) || !focus
->AcceptsFocus() ) )
1474 // if window is not having a focus still testing for default enter or cancel
1475 // TODO: add the UMA version for ActiveNonFloatingWindow
1477 wxWindow
* focus
= wxNonOwnedWindow::GetFromWXWindow( (WXWindow
) FrontWindow() ) ;
1480 if ( keyval
== WXK_RETURN
|| keyval
== WXK_NUMPAD_ENTER
)
1482 wxTopLevelWindow
*tlw
= wxDynamicCast(wxGetTopLevelParent(focus
), wxTopLevelWindow
);
1483 if ( tlw
&& tlw
->GetDefaultItem() )
1485 wxButton
*def
= wxDynamicCast(tlw
->GetDefaultItem(), wxButton
);
1486 if ( def
&& def
->IsEnabled() )
1488 wxCommandEvent
event(wxEVT_COMMAND_BUTTON_CLICKED
, def
->GetId() );
1489 event
.SetEventObject(def
);
1490 def
->Command(event
);
1496 else if (keyval
== WXK_ESCAPE
|| (keyval
== '.' && modifiers
& cmdKey
) )
1498 // generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs)
1499 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1500 new_event
.SetEventObject( focus
);
1501 handled
= focus
->HandleWindowEvent( new_event
);
1510 // This method handles common code for SendKeyDown, SendKeyUp, and SendChar events.
1511 void wxApp::MacCreateKeyEvent( wxKeyEvent
& event
, wxWindow
* focus
, long keymessage
, long modifiers
, long when
, short wherex
, short wherey
, wxChar uniChar
)
1513 #if wxOSX_USE_COCOA_OR_CARBON
1515 short keycode
, keychar
;
1517 keychar
= short(keymessage
& charCodeMask
);
1518 keycode
= short(keymessage
& keyCodeMask
) >> 8 ;
1519 if ( !(event
.GetEventType() == wxEVT_CHAR
) && (modifiers
& (controlKey
| shiftKey
| optionKey
) ) )
1521 // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
1522 // and look at the character after
1524 // TODO new implementation using TextInputSources
1527 UInt32 keyInfo
= KeyTranslate((Ptr
)GetScriptManagerVariable(smKCHRCache
), ( modifiers
& (~(controlKey
| shiftKey
| optionKey
))) | keycode
, &state
);
1528 keychar
= short(keyInfo
& charCodeMask
);
1532 long keyval
= wxMacTranslateKey(keychar
, keycode
) ;
1533 if ( keyval
== keychar
&& ( event
.GetEventType() == wxEVT_KEY_UP
|| event
.GetEventType() == wxEVT_KEY_DOWN
) )
1534 keyval
= wxToupper( keyval
) ;
1536 // Check for NUMPAD keys. For KEY_UP/DOWN events we need to use the
1537 // WXK_NUMPAD constants, but for the CHAR event we want to use the
1538 // standard ascii values
1539 if ( event
.GetEventType() != wxEVT_CHAR
)
1541 if (keyval
>= '0' && keyval
<= '9' && keycode
>= 82 && keycode
<= 92)
1543 keyval
= (keyval
- '0') + WXK_NUMPAD0
;
1545 else if (keycode
>= 65 && keycode
<= 81)
1550 keyval
= WXK_NUMPAD_ENTER
;
1554 keyval
= WXK_NUMPAD_EQUAL
;
1558 keyval
= WXK_NUMPAD_MULTIPLY
;
1562 keyval
= WXK_NUMPAD_DIVIDE
;
1566 keyval
= WXK_NUMPAD_SUBTRACT
;
1570 keyval
= WXK_NUMPAD_ADD
;
1574 keyval
= WXK_NUMPAD_DECIMAL
;
1582 event
.m_shiftDown
= modifiers
& shiftKey
;
1583 event
.m_rawControlDown
= modifiers
& controlKey
;
1584 event
.m_altDown
= modifiers
& optionKey
;
1585 event
.m_controlDown
= modifiers
& cmdKey
;
1586 event
.m_keyCode
= keyval
;
1588 event
.m_uniChar
= uniChar
;
1591 event
.m_rawCode
= keymessage
;
1592 event
.m_rawFlags
= modifiers
;
1595 event
.SetTimestamp(when
);
1596 event
.SetEventObject(focus
);
1600 wxUnusedVar(keymessage
);
1601 wxUnusedVar(modifiers
);
1603 wxUnusedVar(wherex
);
1604 wxUnusedVar(wherey
);
1605 wxUnusedVar(uniChar
);
1610 void wxApp::MacHideApp()
1612 #if wxOSX_USE_CARBON
1613 wxMacCarbonEvent
event( kEventClassCommand
, kEventCommandProcess
);
1615 memset( &command
, 0 , sizeof(command
) );
1616 command
.commandID
= kHICommandHide
;
1617 event
.SetParameter
<HICommand
>(kEventParamDirectObject
, command
);
1618 SendEventToApplication( event
);