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 ) ;
394 // showing hidden windows is not really always a good solution, also non-modal dialogs when closed end up
395 // as hidden tlws, we don't want to reshow those, so let's just reopen the minimized a.k.a. iconized tlws
396 // unless we find a regression ...
398 else if ( firstHidden
)
399 firstHidden
->Show( true );
404 void wxApp::OSXOnWillFinishLaunching()
408 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();
427 //----------------------------------------------------------------------
428 // Macintosh CommandID support - converting between native and wx IDs
429 //----------------------------------------------------------------------
431 // if no native match they just return the passed-in id
441 IdPair gCommandIds
[] =
443 { kHICommandCut
, wxID_CUT
} ,
444 { kHICommandCopy
, wxID_COPY
} ,
445 { kHICommandPaste
, wxID_PASTE
} ,
446 { kHICommandSelectAll
, wxID_SELECTALL
} ,
447 { kHICommandClear
, wxID_CLEAR
} ,
448 { kHICommandUndo
, wxID_UNDO
} ,
449 { kHICommandRedo
, wxID_REDO
} ,
452 int wxMacCommandToId( UInt32 macCommandId
)
456 switch ( macCommandId
)
458 case kHICommandPreferences
:
459 wxid
= wxApp::s_macPreferencesMenuItemId
;
462 case kHICommandQuit
:
463 wxid
= wxApp::s_macExitMenuItemId
;
466 case kHICommandAbout
:
467 wxid
= wxApp::s_macAboutMenuItemId
;
472 for ( size_t i
= 0 ; i
< WXSIZEOF(gCommandIds
) ; ++i
)
474 if ( gCommandIds
[i
].macId
== macCommandId
)
476 wxid
= gCommandIds
[i
].wxId
;
485 wxid
= (int) macCommandId
;
490 UInt32
wxIdToMacCommand( int wxId
)
494 if ( wxId
== wxApp::s_macPreferencesMenuItemId
)
495 macId
= kHICommandPreferences
;
496 else if (wxId
== wxApp::s_macExitMenuItemId
)
497 macId
= kHICommandQuit
;
498 else if (wxId
== wxApp::s_macAboutMenuItemId
)
499 macId
= kHICommandAbout
;
502 for ( size_t i
= 0 ; i
< WXSIZEOF(gCommandIds
) ; ++i
)
504 if ( gCommandIds
[i
].wxId
== wxId
)
506 macId
= gCommandIds
[i
].macId
;
518 wxMenu
* wxFindMenuFromMacCommand( const HICommand
&command
, wxMenuItem
* &item
)
520 wxMenu
* itemMenu
= NULL
;
521 #ifndef __WXUNIVERSAL__
524 // for 'standard' commands which don't have a wx-menu
525 if ( command
.commandID
== kHICommandPreferences
|| command
.commandID
== kHICommandQuit
|| command
.commandID
== kHICommandAbout
)
527 id
= wxMacCommandToId( command
.commandID
) ;
529 wxMenuBar
* mbar
= wxMenuBar::MacGetInstalledMenuBar() ;
531 item
= mbar
->FindItem( id
, &itemMenu
) ;
533 else if ( command
.commandID
!= 0 && command
.menu
.menuRef
!= 0 && command
.menu
.menuItemIndex
!= 0 )
535 id
= wxMacCommandToId( command
.commandID
) ;
536 // make sure it is one of our own menus, or of the 'synthetic' apple and help menus , otherwise don't touch
537 MenuItemIndex firstUserHelpMenuItem
;
538 static MenuHandle helpMenuHandle
= NULL
;
539 if ( helpMenuHandle
== NULL
)
541 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
542 helpMenuHandle
= NULL
;
545 // is it part of the application or the Help menu, then look for the id directly
546 if ( ( GetMenuHandle( kwxMacAppleMenuId
) != NULL
&& command
.menu
.menuRef
== GetMenuHandle( kwxMacAppleMenuId
) ) ||
547 ( helpMenuHandle
!= NULL
&& command
.menu
.menuRef
== helpMenuHandle
) ||
548 wxMenuBar::MacGetWindowMenuHMenu() != NULL
&& command
.menu
.menuRef
== wxMenuBar::MacGetWindowMenuHMenu() )
550 wxMenuBar
* mbar
= wxMenuBar::MacGetInstalledMenuBar() ;
552 item
= mbar
->FindItem( id
, &itemMenu
) ;
558 GetMenuItemRefCon( command
.menu
.menuRef
, command
.menu
.menuItemIndex
, &refCon
) ;
559 itemMenu
= wxFindMenuFromMacMenu( command
.menu
.menuRef
) ;
560 if ( itemMenu
!= NULL
&& refCon
!= 0)
561 item
= (wxMenuItem
*) refCon
;
570 //----------------------------------------------------------------------
571 // Carbon Event Handler
572 //----------------------------------------------------------------------
576 static const EventTypeSpec eventList
[] =
578 { kEventClassCommand
, kEventProcessCommand
} ,
579 { kEventClassCommand
, kEventCommandUpdateStatus
} ,
581 { kEventClassMenu
, kEventMenuOpening
},
582 { kEventClassMenu
, kEventMenuClosed
},
583 { kEventClassMenu
, kEventMenuTargetItem
},
585 { kEventClassApplication
, kEventAppActivated
} ,
586 { kEventClassApplication
, kEventAppDeactivated
} ,
587 // handling the quit event is not recommended by apple
588 // rather using the quit apple event - which we do
590 { kEventClassAppleEvent
, kEventAppleEvent
} ,
592 { kEventClassMouse
, kEventMouseDown
} ,
593 { kEventClassMouse
, kEventMouseMoved
} ,
594 { kEventClassMouse
, kEventMouseUp
} ,
595 { kEventClassMouse
, kEventMouseDragged
} ,
599 static pascal OSStatus
600 wxMacAppMenuEventHandler( EventHandlerCallRef
WXUNUSED(handler
),
602 void *WXUNUSED(data
) )
604 wxMacCarbonEvent
cEvent( event
) ;
605 MenuRef menuRef
= cEvent
.GetParameter
<MenuRef
>(kEventParamDirectObject
) ;
606 #ifndef __WXUNIVERSAL__
607 wxMenu
* menu
= wxFindMenuFromMacMenu( menuRef
) ;
611 switch (GetEventKind(event
))
613 case kEventMenuOpening
:
614 menu
->HandleMenuOpened();
617 case kEventMenuClosed
:
618 menu
->HandleMenuClosed();
621 case kEventMenuTargetItem
:
625 command
.menu
.menuRef
= menuRef
;
626 command
.menu
.menuItemIndex
= cEvent
.GetParameter
<MenuItemIndex
>(kEventParamMenuItemIndex
,typeMenuItemIndex
) ;
627 command
.commandID
= cEvent
.GetParameter
<MenuCommand
>(kEventParamMenuCommand
,typeMenuCommand
) ;
628 if (command
.commandID
!= 0)
630 wxMenuItem
* item
= NULL
;
631 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
632 if ( itemMenu
&& item
)
633 itemMenu
->HandleMenuItemHighlighted( item
);
639 wxFAIL_MSG(wxT("Unexpected menu event kind"));
645 return eventNotHandledErr
;
648 static pascal OSStatus
649 wxMacAppCommandEventHandler( EventHandlerCallRef
WXUNUSED(handler
) ,
651 void *WXUNUSED(data
) )
653 OSStatus result
= eventNotHandledErr
;
657 wxMacCarbonEvent
cEvent( event
) ;
658 cEvent
.GetParameter
<HICommand
>(kEventParamDirectObject
,typeHICommand
,&command
) ;
660 wxMenuItem
* item
= NULL
;
661 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
665 wxASSERT( itemMenu
!= NULL
) ;
667 switch ( cEvent
.GetKind() )
669 case kEventProcessCommand
:
670 if ( itemMenu
->HandleCommandProcess( item
) )
674 case kEventCommandUpdateStatus
:
675 if ( itemMenu
->HandleCommandUpdateStatus( item
) )
686 static pascal OSStatus
687 wxMacAppApplicationEventHandler( EventHandlerCallRef
WXUNUSED(handler
) ,
689 void *WXUNUSED(data
) )
691 OSStatus result
= eventNotHandledErr
;
692 switch ( GetEventKind( event
) )
694 case kEventAppActivated
:
696 wxTheApp
->SetActive( true , NULL
) ;
700 case kEventAppDeactivated
:
702 wxTheApp
->SetActive( false , NULL
) ;
713 pascal OSStatus
wxMacAppEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
715 EventRef formerEvent
= (EventRef
) wxTheApp
->MacGetCurrentEvent() ;
716 EventHandlerCallRef formerEventHandlerCallRef
= (EventHandlerCallRef
) wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
717 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
719 OSStatus result
= eventNotHandledErr
;
720 switch ( GetEventClass( event
) )
723 case kEventClassCommand
:
724 result
= wxMacAppCommandEventHandler( handler
, event
, data
) ;
727 case kEventClassApplication
:
728 result
= wxMacAppApplicationEventHandler( handler
, event
, data
) ;
731 case kEventClassMenu
:
732 result
= wxMacAppMenuEventHandler( handler
, event
, data
) ;
735 case kEventClassMouse
:
737 wxMacCarbonEvent
cEvent( event
) ;
740 Point screenMouseLocation
= cEvent
.GetParameter
<Point
>(kEventParamMouseLocation
) ;
741 ::FindWindow(screenMouseLocation
, &window
);
742 // only send this event in case it had not already been sent to a tlw, as we get
743 // double events otherwise (in case event.skip) was called
744 if ( window
== NULL
)
745 result
= wxMacTopLevelMouseEventHandler( handler
, event
, NULL
) ;
749 case kEventClassAppleEvent
:
750 result
= AEProcessEvent(event
);
757 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerEventHandlerCallRef
) ;
762 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacAppEventHandler
)
765 #if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
768 wxMacAssertOutputHandler(OSType
WXUNUSED(componentSignature
),
769 UInt32
WXUNUSED(options
),
770 const char *assertionString
,
771 const char *exceptionLabelString
,
772 const char *errorString
,
773 const char *fileName
,
776 ConstStr255Param
WXUNUSED(outputMsg
))
778 // flow into assert handling
779 wxString fileNameStr
;
780 wxString assertionStr
;
781 wxString exceptionStr
;
785 fileNameStr
= wxString(fileName
, wxConvLocal
);
786 assertionStr
= wxString(assertionString
, wxConvLocal
);
787 exceptionStr
= wxString((exceptionLabelString
!=0) ? exceptionLabelString
: "", wxConvLocal
) ;
788 errorStr
= wxString((errorString
!=0) ? errorString
: "", wxConvLocal
) ;
790 fileNameStr
= fileName
;
791 assertionStr
= assertionString
;
792 exceptionStr
= (exceptionLabelString
!=0) ? exceptionLabelString
: "" ;
793 errorStr
= (errorString
!=0) ? errorString
: "" ;
798 wxLogDebug( wxT("AssertMacros: %s %s %s file: %s, line: %ld (value %p)\n"),
799 assertionStr
.c_str() ,
800 exceptionStr
.c_str() ,
802 fileNameStr
.c_str(), lineNumber
,
806 wxOnAssert(fileNameStr
, lineNumber
, assertionStr
,
807 wxString::Format( wxT("%s %s value (%p)") , exceptionStr
, errorStr
, value
) ) ;
811 #endif // wxDEBUG_LEVEL
813 bool wxApp::Initialize(int& argc
, wxChar
**argv
)
817 #if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
818 InstallDebugAssertOutputHandler( NewDebugAssertOutputHandlerUPP( wxMacAssertOutputHandler
) );
821 // Mac OS X passes a process serial number command line argument when
822 // the application is launched from the Finder. This argument must be
823 // removed from the command line arguments before being handled by the
824 // application (otherwise applications would need to handle it)
827 static const wxChar
*ARG_PSN
= wxT("-psn_");
828 if ( wxStrncmp(argv
[1], ARG_PSN
, wxStrlen(ARG_PSN
)) == 0 )
830 // remove this argument
832 memmove(argv
+ 1, argv
+ 2, argc
* sizeof(wxChar
*));
837 Cocoa supports -Key value options which set the user defaults key "Key"
838 to the value "value" Some of them are very handy for debugging like
839 -NSShowAllViews YES. Cocoa picks these up from the real argv so
840 our removal of them from the wx copy of it does not affect Cocoa's
843 We basically just assume that any "-NS" option and its following
844 argument needs to be removed from argv. We hope that user code does
845 not expect to see -NS options and indeed it's probably a safe bet
846 since most user code accepting options is probably using the
847 double-dash GNU-style syntax.
849 for(int i
=1; i
< argc
; ++i
)
851 static const wxChar
*ARG_NS
= wxT("-NS");
852 if( wxStrncmp(argv
[i
], ARG_NS
, wxStrlen(ARG_NS
)) == 0 )
854 // Only eat this option if it has an argument
857 memmove(argv
+ i
, argv
+ i
+ 2, (argc
-i
-1)*sizeof(wxChar
*));
859 // drop back one position so the next run through the loop
860 // reprocesses the argument at our current index.
866 if ( !wxAppBase::Initialize(argc
, argv
) )
870 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
873 // these might be the startup dirs, set them to the 'usual' dir containing the app bundle
874 wxString startupCwd
= wxGetCwd() ;
875 if ( startupCwd
== wxT("/") || startupCwd
.Right(15) == wxT("/Contents/MacOS") )
877 CFURLRef url
= CFBundleCopyBundleURL(CFBundleGetMainBundle() ) ;
878 CFURLRef urlParent
= CFURLCreateCopyDeletingLastPathComponent( kCFAllocatorDefault
, url
) ;
880 CFStringRef path
= CFURLCopyFileSystemPath ( urlParent
, kCFURLPOSIXPathStyle
) ;
881 CFRelease( urlParent
) ;
882 wxString cwd
= wxCFStringRef(path
).AsString(wxLocale::GetSystemEncoding());
883 wxSetWorkingDirectory( cwd
) ;
889 #if wxOSX_USE_COCOA_OR_CARBON
890 bool wxApp::CallOnInit()
892 wxMacAutoreleasePool autoreleasepool
;
897 bool wxApp::OnInitGui()
899 if ( !wxAppBase::OnInitGui() )
908 bool wxApp::ProcessIdle()
910 wxMacAutoreleasePool autoreleasepool
;
911 return wxAppBase::ProcessIdle();
916 wxMacAutoreleasePool pool
;
917 return wxAppBase::OnRun();
921 bool wxApp::DoInitGui()
923 InstallStandardEventHandler( GetApplicationEventTarget() ) ;
926 InstallApplicationEventHandler(
927 GetwxMacAppEventHandlerUPP(),
928 GetEventTypeCount(eventList
), eventList
, wxTheApp
, (EventHandlerRef
*)&(wxTheApp
->m_macEventHandler
));
933 sODocHandler
= NewAEEventHandlerUPP(AEHandleODoc
) ;
934 sGURLHandler
= NewAEEventHandlerUPP(AEHandleGURL
) ;
935 sOAppHandler
= NewAEEventHandlerUPP(AEHandleOApp
) ;
936 sPDocHandler
= NewAEEventHandlerUPP(AEHandlePDoc
) ;
937 sRAppHandler
= NewAEEventHandlerUPP(AEHandleRApp
) ;
938 sQuitHandler
= NewAEEventHandlerUPP(AEHandleQuit
) ;
940 AEInstallEventHandler( kCoreEventClass
, kAEOpenDocuments
,
941 sODocHandler
, 0 , FALSE
) ;
942 AEInstallEventHandler( kInternetEventClass
, kAEGetURL
,
943 sGURLHandler
, 0 , FALSE
) ;
944 AEInstallEventHandler( kCoreEventClass
, kAEOpenApplication
,
945 sOAppHandler
, 0 , FALSE
) ;
946 AEInstallEventHandler( kCoreEventClass
, kAEPrintDocuments
,
947 sPDocHandler
, 0 , FALSE
) ;
948 AEInstallEventHandler( kCoreEventClass
, kAEReopenApplication
,
949 sRAppHandler
, 0 , FALSE
) ;
950 AEInstallEventHandler( kCoreEventClass
, kAEQuitApplication
,
951 sQuitHandler
, 0 , FALSE
) ;
954 if ( !wxMacInitCocoa() )
960 void wxApp::DoCleanUp()
963 RemoveEventHandler( (EventHandlerRef
)(wxTheApp
->m_macEventHandler
) );
967 AERemoveEventHandler( kCoreEventClass
, kAEOpenDocuments
,
968 sODocHandler
, FALSE
) ;
969 AERemoveEventHandler( kInternetEventClass
, kAEGetURL
,
970 sGURLHandler
, FALSE
) ;
971 AERemoveEventHandler( kCoreEventClass
, kAEOpenApplication
,
972 sOAppHandler
, FALSE
) ;
973 AERemoveEventHandler( kCoreEventClass
, kAEPrintDocuments
,
974 sPDocHandler
, FALSE
) ;
975 AERemoveEventHandler( kCoreEventClass
, kAEReopenApplication
,
976 sRAppHandler
, FALSE
) ;
977 AERemoveEventHandler( kCoreEventClass
, kAEQuitApplication
,
978 sQuitHandler
, FALSE
) ;
980 DisposeAEEventHandlerUPP( sODocHandler
) ;
981 DisposeAEEventHandlerUPP( sGURLHandler
) ;
982 DisposeAEEventHandlerUPP( sOAppHandler
) ;
983 DisposeAEEventHandlerUPP( sPDocHandler
) ;
984 DisposeAEEventHandlerUPP( sRAppHandler
) ;
985 DisposeAEEventHandlerUPP( sQuitHandler
) ;
991 void wxApp::CleanUp()
993 wxMacAutoreleasePool autoreleasepool
;
995 wxToolTip::RemoveToolTips() ;
1000 wxAppBase::CleanUp();
1003 //----------------------------------------------------------------------
1004 // misc initialization stuff
1005 //----------------------------------------------------------------------
1009 m_printMode
= wxPRINT_WINDOWS
;
1011 m_macCurrentEvent
= NULL
;
1012 m_macCurrentEventHandlerCallRef
= NULL
;
1013 m_macPool
= new wxMacAutoreleasePool();
1022 CFMutableArrayRef
GetAutoReleaseArray()
1024 static CFMutableArrayRef array
= 0;
1026 array
= CFArrayCreateMutable(kCFAllocatorDefault
,0,&kCFTypeArrayCallBacks
);
1030 void wxApp::MacAddToAutorelease( void* cfrefobj
)
1032 CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj
);
1035 void wxApp::MacReleaseAutoreleasePool()
1039 m_macPool
= new wxMacAutoreleasePool();
1042 void wxApp::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1044 // If they are pending events, we must process them: pending events are
1045 // either events to the threads other than main or events posted with
1046 // wxPostEvent() functions
1047 #ifndef __WXUNIVERSAL__
1049 if (!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar())
1050 wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar();
1053 CFArrayRemoveAllValues( GetAutoReleaseArray() );
1056 void wxApp::WakeUpIdle()
1058 wxEventLoopBase
* const loop
= wxEventLoopBase::GetActive();
1064 void wxApp::OnEndSession(wxCloseEvent
& WXUNUSED(event
))
1067 GetTopWindow()->Close(true);
1070 // Default behaviour: close the application with prompts. The
1071 // user can veto the close, and therefore the end session.
1072 void wxApp::OnQueryEndSession(wxCloseEvent
& event
)
1074 if ( !wxDialog::OSXHasModalDialogsOpen() )
1078 if (!GetTopWindow()->Close(!event
.CanVeto()))
1088 extern "C" void wxCYield() ;
1095 void wxApp::MacHandleUnhandledEvent( WXEVENTREF
WXUNUSED(evr
) )
1097 // Override to process unhandled events as you please
1100 #if wxOSX_USE_COCOA_OR_CARBON
1102 CGKeyCode
wxCharCodeWXToOSX(wxKeyCode code
)
1108 // Clang warns about switch values not of the same type as (enumerated)
1109 // switch controlling expression. This is generally useful but here we
1110 // really want to be able to use letters and digits without making them
1111 // part of wxKeyCode enum.
1113 #pragma clang diagnostic push
1114 #pragma clang diagnostic ignored "-Wswitch"
1117 case 'a': case 'A': keycode
= kVK_ANSI_A
; break;
1118 case 'b': case 'B': keycode
= kVK_ANSI_B
; break;
1119 case 'c': case 'C': keycode
= kVK_ANSI_C
; break;
1120 case 'd': case 'D': keycode
= kVK_ANSI_D
; break;
1121 case 'e': case 'E': keycode
= kVK_ANSI_E
; break;
1122 case 'f': case 'F': keycode
= kVK_ANSI_F
; break;
1123 case 'g': case 'G': keycode
= kVK_ANSI_G
; break;
1124 case 'h': case 'H': keycode
= kVK_ANSI_H
; break;
1125 case 'i': case 'I': keycode
= kVK_ANSI_I
; break;
1126 case 'j': case 'J': keycode
= kVK_ANSI_J
; break;
1127 case 'k': case 'K': keycode
= kVK_ANSI_K
; break;
1128 case 'l': case 'L': keycode
= kVK_ANSI_L
; break;
1129 case 'm': case 'M': keycode
= kVK_ANSI_M
; break;
1130 case 'n': case 'N': keycode
= kVK_ANSI_N
; break;
1131 case 'o': case 'O': keycode
= kVK_ANSI_O
; break;
1132 case 'p': case 'P': keycode
= kVK_ANSI_P
; break;
1133 case 'q': case 'Q': keycode
= kVK_ANSI_Q
; break;
1134 case 'r': case 'R': keycode
= kVK_ANSI_R
; break;
1135 case 's': case 'S': keycode
= kVK_ANSI_S
; break;
1136 case 't': case 'T': keycode
= kVK_ANSI_T
; break;
1137 case 'u': case 'U': keycode
= kVK_ANSI_U
; break;
1138 case 'v': case 'V': keycode
= kVK_ANSI_V
; break;
1139 case 'w': case 'W': keycode
= kVK_ANSI_W
; break;
1140 case 'x': case 'X': keycode
= kVK_ANSI_X
; break;
1141 case 'y': case 'Y': keycode
= kVK_ANSI_Y
; break;
1142 case 'z': case 'Z': keycode
= kVK_ANSI_Z
; break;
1144 case '0': keycode
= kVK_ANSI_0
; break;
1145 case '1': keycode
= kVK_ANSI_1
; break;
1146 case '2': keycode
= kVK_ANSI_2
; break;
1147 case '3': keycode
= kVK_ANSI_3
; break;
1148 case '4': keycode
= kVK_ANSI_4
; break;
1149 case '5': keycode
= kVK_ANSI_5
; break;
1150 case '6': keycode
= kVK_ANSI_6
; break;
1151 case '7': keycode
= kVK_ANSI_7
; break;
1152 case '8': keycode
= kVK_ANSI_8
; break;
1153 case '9': keycode
= kVK_ANSI_9
; break;
1156 #pragma clang diagnostic pop
1159 case WXK_BACK
: keycode
= kVK_Delete
; break;
1160 case WXK_TAB
: keycode
= kVK_Tab
; break;
1161 case WXK_RETURN
: keycode
= kVK_Return
; break;
1162 case WXK_ESCAPE
: keycode
= kVK_Escape
; break;
1163 case WXK_SPACE
: keycode
= kVK_Space
; break;
1164 case WXK_DELETE
: keycode
= kVK_ForwardDelete
; break;
1166 case WXK_SHIFT
: keycode
= kVK_Shift
; break;
1167 case WXK_ALT
: keycode
= kVK_Option
; break;
1168 case WXK_RAW_CONTROL
: keycode
= kVK_Control
; break;
1169 case WXK_CONTROL
: keycode
= kVK_Command
; break;
1171 case WXK_CAPITAL
: keycode
= kVK_CapsLock
; break;
1172 case WXK_END
: keycode
= kVK_End
; break;
1173 case WXK_HOME
: keycode
= kVK_Home
; break;
1174 case WXK_LEFT
: keycode
= kVK_LeftArrow
; break;
1175 case WXK_UP
: keycode
= kVK_UpArrow
; break;
1176 case WXK_RIGHT
: keycode
= kVK_RightArrow
; break;
1177 case WXK_DOWN
: keycode
= kVK_DownArrow
; break;
1179 case WXK_HELP
: keycode
= kVK_Help
; break;
1182 case WXK_NUMPAD0
: keycode
= kVK_ANSI_Keypad0
; break;
1183 case WXK_NUMPAD1
: keycode
= kVK_ANSI_Keypad1
; break;
1184 case WXK_NUMPAD2
: keycode
= kVK_ANSI_Keypad2
; break;
1185 case WXK_NUMPAD3
: keycode
= kVK_ANSI_Keypad3
; break;
1186 case WXK_NUMPAD4
: keycode
= kVK_ANSI_Keypad4
; break;
1187 case WXK_NUMPAD5
: keycode
= kVK_ANSI_Keypad5
; break;
1188 case WXK_NUMPAD6
: keycode
= kVK_ANSI_Keypad6
; break;
1189 case WXK_NUMPAD7
: keycode
= kVK_ANSI_Keypad7
; break;
1190 case WXK_NUMPAD8
: keycode
= kVK_ANSI_Keypad8
; break;
1191 case WXK_NUMPAD9
: keycode
= kVK_ANSI_Keypad9
; break;
1192 case WXK_F1
: keycode
= kVK_F1
; break;
1193 case WXK_F2
: keycode
= kVK_F2
; break;
1194 case WXK_F3
: keycode
= kVK_F3
; break;
1195 case WXK_F4
: keycode
= kVK_F4
; break;
1196 case WXK_F5
: keycode
= kVK_F5
; break;
1197 case WXK_F6
: keycode
= kVK_F6
; break;
1198 case WXK_F7
: keycode
= kVK_F7
; break;
1199 case WXK_F8
: keycode
= kVK_F8
; break;
1200 case WXK_F9
: keycode
= kVK_F9
; break;
1201 case WXK_F10
: keycode
= kVK_F10
; break;
1202 case WXK_F11
: keycode
= kVK_F11
; break;
1203 case WXK_F12
: keycode
= kVK_F12
; break;
1204 case WXK_F13
: keycode
= kVK_F13
; break;
1205 case WXK_F14
: keycode
= kVK_F14
; break;
1206 case WXK_F15
: keycode
= kVK_F15
; break;
1207 case WXK_F16
: keycode
= kVK_F16
; break;
1208 case WXK_F17
: keycode
= kVK_F17
; break;
1209 case WXK_F18
: keycode
= kVK_F18
; break;
1210 case WXK_F19
: keycode
= kVK_F19
; break;
1211 case WXK_F20
: keycode
= kVK_F20
; break;
1213 case WXK_PAGEUP
: keycode
= kVK_PageUp
; break;
1214 case WXK_PAGEDOWN
: keycode
= kVK_PageDown
; break;
1216 case WXK_NUMPAD_DELETE
: keycode
= kVK_ANSI_KeypadClear
; break;
1217 case WXK_NUMPAD_EQUAL
: keycode
= kVK_ANSI_KeypadEquals
; break;
1218 case WXK_NUMPAD_MULTIPLY
: keycode
= kVK_ANSI_KeypadMultiply
; break;
1219 case WXK_NUMPAD_ADD
: keycode
= kVK_ANSI_KeypadPlus
; break;
1220 case WXK_NUMPAD_SUBTRACT
: keycode
= kVK_ANSI_KeypadMinus
; break;
1221 case WXK_NUMPAD_DECIMAL
: keycode
= kVK_ANSI_KeypadDecimal
; break;
1222 case WXK_NUMPAD_DIVIDE
: keycode
= kVK_ANSI_KeypadDivide
; break;
1225 wxLogDebug( "Unrecognised keycode %d", code
);
1226 keycode
= static_cast<CGKeyCode
>(-1);
1232 long wxMacTranslateKey(unsigned char key
, unsigned char code
)
1237 case kHomeCharCode
:
1241 case kEnterCharCode
:
1242 retval
= WXK_RETURN
;
1248 case kHelpCharCode
:
1252 case kBackspaceCharCode
:
1260 case kPageUpCharCode
:
1261 retval
= WXK_PAGEUP
;
1264 case kPageDownCharCode
:
1265 retval
= WXK_PAGEDOWN
;
1268 case kReturnCharCode
:
1269 retval
= WXK_RETURN
;
1272 case kFunctionKeyCharCode
:
1342 case kEscapeCharCode
:
1343 retval
= WXK_ESCAPE
;
1346 case kLeftArrowCharCode
:
1350 case kRightArrowCharCode
:
1351 retval
= WXK_RIGHT
;
1354 case kUpArrowCharCode
:
1358 case kDownArrowCharCode
:
1362 case kDeleteCharCode
:
1363 retval
= WXK_DELETE
;
1373 int wxMacKeyCodeToModifier(wxKeyCode key
)
1391 case WXK_RAW_CONTROL
:
1400 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
1402 // defined in utils.mm
1404 #elif wxOSX_USE_COCOA_OR_CARBON
1406 wxMouseState
wxGetMouseState()
1410 wxPoint pt
= wxGetMousePosition();
1414 UInt32 buttons
= GetCurrentButtonState();
1415 ms
.SetLeftDown( (buttons
& 0x01) != 0 );
1416 ms
.SetMiddleDown( (buttons
& 0x04) != 0 );
1417 ms
.SetRightDown( (buttons
& 0x02) != 0 );
1419 UInt32 modifiers
= GetCurrentKeyModifiers();
1420 ms
.SetRawControlDown(modifiers
& controlKey
);
1421 ms
.SetShiftDown(modifiers
& shiftKey
);
1422 ms
.SetAltDown(modifiers
& optionKey
);
1423 ms
.SetControlDown(modifiers
& cmdKey
);
1430 // TODO : once the new key/char handling is tested, move all the code to wxWindow
1432 bool wxApp::MacSendKeyDownEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1437 wxKeyEvent
event(wxEVT_KEY_DOWN
) ;
1438 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, uniChar
) ;
1440 return focus
->OSXHandleKeyEvent(event
);
1443 bool wxApp::MacSendKeyUpEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1448 wxKeyEvent
event( wxEVT_KEY_UP
) ;
1449 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, uniChar
) ;
1451 return focus
->OSXHandleKeyEvent(event
) ;
1454 bool wxApp::MacSendCharEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1458 wxKeyEvent
event(wxEVT_CHAR
) ;
1459 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, uniChar
) ;
1461 bool handled
= false ;
1463 #if wxOSX_USE_CARBON
1464 long keyval
= event
.m_keyCode
;
1467 wxKeyEvent
eventCharHook(wxEVT_CHAR_HOOK
, event
);
1468 handled
= focus
->HandleWindowEvent( eventCharHook
);
1469 if ( handled
&& eventCharHook
.IsNextEventAllowed() )
1475 handled
= focus
->HandleWindowEvent( event
) ;
1478 if ( !handled
&& (keyval
== WXK_TAB
) )
1480 wxWindow
* iter
= focus
->GetParent() ;
1481 while ( iter
&& !handled
)
1483 if ( iter
->HasFlag( wxTAB_TRAVERSAL
) )
1485 wxNavigationKeyEvent new_event
;
1486 new_event
.SetEventObject( focus
);
1487 new_event
.SetDirection( !event
.ShiftDown() );
1488 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1489 new_event
.SetWindowChange( event
.ControlDown() );
1490 new_event
.SetCurrentFocus( focus
);
1491 handled
= focus
->GetParent()->HandleWindowEvent( new_event
);
1492 if ( handled
&& new_event
.GetSkipped() )
1496 iter
= iter
->GetParent() ;
1500 // backdoor handler for default return and command escape
1501 if ( !handled
&& (!focus
->IsKindOf(CLASSINFO(wxControl
) ) || !focus
->AcceptsFocus() ) )
1503 // if window is not having a focus still testing for default enter or cancel
1504 // TODO: add the UMA version for ActiveNonFloatingWindow
1506 wxWindow
* focus
= wxNonOwnedWindow::GetFromWXWindow( (WXWindow
) FrontWindow() ) ;
1509 if ( keyval
== WXK_RETURN
|| keyval
== WXK_NUMPAD_ENTER
)
1511 wxTopLevelWindow
*tlw
= wxDynamicCast(wxGetTopLevelParent(focus
), wxTopLevelWindow
);
1512 if ( tlw
&& tlw
->GetDefaultItem() )
1514 wxButton
*def
= wxDynamicCast(tlw
->GetDefaultItem(), wxButton
);
1515 if ( def
&& def
->IsEnabled() )
1517 wxCommandEvent
event(wxEVT_BUTTON
, def
->GetId() );
1518 event
.SetEventObject(def
);
1519 def
->Command(event
);
1525 else if (keyval
== WXK_ESCAPE
|| (keyval
== '.' && modifiers
& cmdKey
) )
1527 // generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs)
1528 wxCommandEvent
new_event(wxEVT_BUTTON
,wxID_CANCEL
);
1529 new_event
.SetEventObject( focus
);
1530 handled
= focus
->HandleWindowEvent( new_event
);
1539 // This method handles common code for SendKeyDown, SendKeyUp, and SendChar events.
1540 void wxApp::MacCreateKeyEvent( wxKeyEvent
& event
, wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1542 #if wxOSX_USE_COCOA_OR_CARBON
1544 short keycode
, keychar
;
1546 keychar
= short(keymessage
& charCodeMask
);
1547 keycode
= short(keymessage
& keyCodeMask
) >> 8 ;
1548 if ( !(event
.GetEventType() == wxEVT_CHAR
) && (modifiers
& (controlKey
| shiftKey
| optionKey
) ) )
1550 // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
1551 // and look at the character after
1553 // TODO new implementation using TextInputSources
1556 UInt32 keyInfo
= KeyTranslate((Ptr
)GetScriptManagerVariable(smKCHRCache
), ( modifiers
& (~(controlKey
| shiftKey
| optionKey
))) | keycode
, &state
);
1557 keychar
= short(keyInfo
& charCodeMask
);
1561 long keyval
= wxMacTranslateKey(keychar
, keycode
) ;
1562 if ( keyval
== keychar
&& ( event
.GetEventType() == wxEVT_KEY_UP
|| event
.GetEventType() == wxEVT_KEY_DOWN
) )
1563 keyval
= wxToupper( keyval
) ;
1565 // Check for NUMPAD keys. For KEY_UP/DOWN events we need to use the
1566 // WXK_NUMPAD constants, but for the CHAR event we want to use the
1567 // standard ascii values
1568 if ( event
.GetEventType() != wxEVT_CHAR
)
1570 if (keyval
>= '0' && keyval
<= '9' && keycode
>= 82 && keycode
<= 92)
1572 keyval
= (keyval
- '0') + WXK_NUMPAD0
;
1574 else if (keycode
>= 65 && keycode
<= 81)
1579 keyval
= WXK_NUMPAD_ENTER
;
1583 keyval
= WXK_NUMPAD_EQUAL
;
1587 keyval
= WXK_NUMPAD_MULTIPLY
;
1591 keyval
= WXK_NUMPAD_DIVIDE
;
1595 keyval
= WXK_NUMPAD_SUBTRACT
;
1599 keyval
= WXK_NUMPAD_ADD
;
1603 keyval
= WXK_NUMPAD_DECIMAL
;
1611 event
.m_shiftDown
= modifiers
& shiftKey
;
1612 event
.m_rawControlDown
= modifiers
& controlKey
;
1613 event
.m_altDown
= modifiers
& optionKey
;
1614 event
.m_controlDown
= modifiers
& cmdKey
;
1615 event
.m_keyCode
= keyval
;
1617 event
.m_uniChar
= uniChar
;
1620 event
.m_rawCode
= keymessage
;
1621 event
.m_rawFlags
= modifiers
;
1622 event
.SetTimestamp(when
);
1623 event
.SetEventObject(focus
);
1627 wxUnusedVar(keymessage
);
1628 wxUnusedVar(modifiers
);
1630 wxUnusedVar(uniChar
);
1635 void wxApp::MacHideApp()
1637 #if wxOSX_USE_CARBON
1638 wxMacCarbonEvent
event( kEventClassCommand
, kEventCommandProcess
);
1640 memset( &command
, 0 , sizeof(command
) );
1641 command
.commandID
= kHICommandHide
;
1642 event
.SetParameter
<HICommand
>(kEventParamDirectObject
, command
);
1643 SendEventToApplication( event
);