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()
409 void wxApp::OSXOnDidFinishLaunching()
411 wxTheApp
->OnLaunched();
414 void wxApp::OSXOnWillTerminate()
417 event
.SetCanVeto(false);
418 wxTheApp
->OnEndSession(event
);
423 bool wxApp::OSXOnShouldTerminate()
426 wxTheApp
->OnQueryEndSession(event
);
427 return !event
.GetVeto();
431 //----------------------------------------------------------------------
432 // Macintosh CommandID support - converting between native and wx IDs
433 //----------------------------------------------------------------------
435 // if no native match they just return the passed-in id
445 IdPair gCommandIds
[] =
447 { kHICommandCut
, wxID_CUT
} ,
448 { kHICommandCopy
, wxID_COPY
} ,
449 { kHICommandPaste
, wxID_PASTE
} ,
450 { kHICommandSelectAll
, wxID_SELECTALL
} ,
451 { kHICommandClear
, wxID_CLEAR
} ,
452 { kHICommandUndo
, wxID_UNDO
} ,
453 { kHICommandRedo
, wxID_REDO
} ,
456 int wxMacCommandToId( UInt32 macCommandId
)
460 switch ( macCommandId
)
462 case kHICommandPreferences
:
463 wxid
= wxApp::s_macPreferencesMenuItemId
;
466 case kHICommandQuit
:
467 wxid
= wxApp::s_macExitMenuItemId
;
470 case kHICommandAbout
:
471 wxid
= wxApp::s_macAboutMenuItemId
;
476 for ( size_t i
= 0 ; i
< WXSIZEOF(gCommandIds
) ; ++i
)
478 if ( gCommandIds
[i
].macId
== macCommandId
)
480 wxid
= gCommandIds
[i
].wxId
;
489 wxid
= (int) macCommandId
;
494 UInt32
wxIdToMacCommand( int wxId
)
498 if ( wxId
== wxApp::s_macPreferencesMenuItemId
)
499 macId
= kHICommandPreferences
;
500 else if (wxId
== wxApp::s_macExitMenuItemId
)
501 macId
= kHICommandQuit
;
502 else if (wxId
== wxApp::s_macAboutMenuItemId
)
503 macId
= kHICommandAbout
;
506 for ( size_t i
= 0 ; i
< WXSIZEOF(gCommandIds
) ; ++i
)
508 if ( gCommandIds
[i
].wxId
== wxId
)
510 macId
= gCommandIds
[i
].macId
;
522 wxMenu
* wxFindMenuFromMacCommand( const HICommand
&command
, wxMenuItem
* &item
)
524 wxMenu
* itemMenu
= NULL
;
525 #ifndef __WXUNIVERSAL__
528 // for 'standard' commands which don't have a wx-menu
529 if ( command
.commandID
== kHICommandPreferences
|| command
.commandID
== kHICommandQuit
|| command
.commandID
== kHICommandAbout
)
531 id
= wxMacCommandToId( command
.commandID
) ;
533 wxMenuBar
* mbar
= wxMenuBar::MacGetInstalledMenuBar() ;
535 item
= mbar
->FindItem( id
, &itemMenu
) ;
537 else if ( command
.commandID
!= 0 && command
.menu
.menuRef
!= 0 && command
.menu
.menuItemIndex
!= 0 )
539 id
= wxMacCommandToId( command
.commandID
) ;
540 // make sure it is one of our own menus, or of the 'synthetic' apple and help menus , otherwise don't touch
541 MenuItemIndex firstUserHelpMenuItem
;
542 static MenuHandle helpMenuHandle
= NULL
;
543 if ( helpMenuHandle
== NULL
)
545 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle
, &firstUserHelpMenuItem
) != noErr
)
546 helpMenuHandle
= NULL
;
549 // is it part of the application or the Help menu, then look for the id directly
550 if ( ( GetMenuHandle( kwxMacAppleMenuId
) != NULL
&& command
.menu
.menuRef
== GetMenuHandle( kwxMacAppleMenuId
) ) ||
551 ( helpMenuHandle
!= NULL
&& command
.menu
.menuRef
== helpMenuHandle
) ||
552 wxMenuBar::MacGetWindowMenuHMenu() != NULL
&& command
.menu
.menuRef
== wxMenuBar::MacGetWindowMenuHMenu() )
554 wxMenuBar
* mbar
= wxMenuBar::MacGetInstalledMenuBar() ;
556 item
= mbar
->FindItem( id
, &itemMenu
) ;
562 GetMenuItemRefCon( command
.menu
.menuRef
, command
.menu
.menuItemIndex
, &refCon
) ;
563 itemMenu
= wxFindMenuFromMacMenu( command
.menu
.menuRef
) ;
564 if ( itemMenu
!= NULL
&& refCon
!= 0)
565 item
= (wxMenuItem
*) refCon
;
574 //----------------------------------------------------------------------
575 // Carbon Event Handler
576 //----------------------------------------------------------------------
580 static const EventTypeSpec eventList
[] =
582 { kEventClassCommand
, kEventProcessCommand
} ,
583 { kEventClassCommand
, kEventCommandUpdateStatus
} ,
585 { kEventClassMenu
, kEventMenuOpening
},
586 { kEventClassMenu
, kEventMenuClosed
},
587 { kEventClassMenu
, kEventMenuTargetItem
},
589 { kEventClassApplication
, kEventAppActivated
} ,
590 { kEventClassApplication
, kEventAppDeactivated
} ,
591 // handling the quit event is not recommended by apple
592 // rather using the quit apple event - which we do
594 { kEventClassAppleEvent
, kEventAppleEvent
} ,
596 { kEventClassMouse
, kEventMouseDown
} ,
597 { kEventClassMouse
, kEventMouseMoved
} ,
598 { kEventClassMouse
, kEventMouseUp
} ,
599 { kEventClassMouse
, kEventMouseDragged
} ,
603 static pascal OSStatus
604 wxMacAppMenuEventHandler( EventHandlerCallRef
WXUNUSED(handler
),
606 void *WXUNUSED(data
) )
608 wxMacCarbonEvent
cEvent( event
) ;
609 MenuRef menuRef
= cEvent
.GetParameter
<MenuRef
>(kEventParamDirectObject
) ;
610 #ifndef __WXUNIVERSAL__
611 wxMenu
* menu
= wxFindMenuFromMacMenu( menuRef
) ;
615 switch (GetEventKind(event
))
617 case kEventMenuOpening
:
618 menu
->HandleMenuOpened();
621 case kEventMenuClosed
:
622 menu
->HandleMenuClosed();
625 case kEventMenuTargetItem
:
629 command
.menu
.menuRef
= menuRef
;
630 command
.menu
.menuItemIndex
= cEvent
.GetParameter
<MenuItemIndex
>(kEventParamMenuItemIndex
,typeMenuItemIndex
) ;
631 command
.commandID
= cEvent
.GetParameter
<MenuCommand
>(kEventParamMenuCommand
,typeMenuCommand
) ;
632 if (command
.commandID
!= 0)
634 wxMenuItem
* item
= NULL
;
635 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
636 if ( itemMenu
&& item
)
637 itemMenu
->HandleMenuItemHighlighted( item
);
643 wxFAIL_MSG(wxT("Unexpected menu event kind"));
649 return eventNotHandledErr
;
652 static pascal OSStatus
653 wxMacAppCommandEventHandler( EventHandlerCallRef
WXUNUSED(handler
) ,
655 void *WXUNUSED(data
) )
657 OSStatus result
= eventNotHandledErr
;
661 wxMacCarbonEvent
cEvent( event
) ;
662 cEvent
.GetParameter
<HICommand
>(kEventParamDirectObject
,typeHICommand
,&command
) ;
664 wxMenuItem
* item
= NULL
;
665 wxMenu
* itemMenu
= wxFindMenuFromMacCommand( command
, item
) ;
669 wxASSERT( itemMenu
!= NULL
) ;
671 switch ( cEvent
.GetKind() )
673 case kEventProcessCommand
:
674 if ( itemMenu
->HandleCommandProcess( item
) )
678 case kEventCommandUpdateStatus
:
679 if ( itemMenu
->HandleCommandUpdateStatus( item
) )
690 static pascal OSStatus
691 wxMacAppApplicationEventHandler( EventHandlerCallRef
WXUNUSED(handler
) ,
693 void *WXUNUSED(data
) )
695 OSStatus result
= eventNotHandledErr
;
696 switch ( GetEventKind( event
) )
698 case kEventAppActivated
:
700 wxTheApp
->SetActive( true , NULL
) ;
704 case kEventAppDeactivated
:
706 wxTheApp
->SetActive( false , NULL
) ;
717 pascal OSStatus
wxMacAppEventHandler( EventHandlerCallRef handler
, EventRef event
, void *data
)
719 EventRef formerEvent
= (EventRef
) wxTheApp
->MacGetCurrentEvent() ;
720 EventHandlerCallRef formerEventHandlerCallRef
= (EventHandlerCallRef
) wxTheApp
->MacGetCurrentEventHandlerCallRef() ;
721 wxTheApp
->MacSetCurrentEvent( event
, handler
) ;
723 OSStatus result
= eventNotHandledErr
;
724 switch ( GetEventClass( event
) )
727 case kEventClassCommand
:
728 result
= wxMacAppCommandEventHandler( handler
, event
, data
) ;
731 case kEventClassApplication
:
732 result
= wxMacAppApplicationEventHandler( handler
, event
, data
) ;
735 case kEventClassMenu
:
736 result
= wxMacAppMenuEventHandler( handler
, event
, data
) ;
739 case kEventClassMouse
:
741 wxMacCarbonEvent
cEvent( event
) ;
744 Point screenMouseLocation
= cEvent
.GetParameter
<Point
>(kEventParamMouseLocation
) ;
745 ::FindWindow(screenMouseLocation
, &window
);
746 // only send this event in case it had not already been sent to a tlw, as we get
747 // double events otherwise (in case event.skip) was called
748 if ( window
== NULL
)
749 result
= wxMacTopLevelMouseEventHandler( handler
, event
, NULL
) ;
753 case kEventClassAppleEvent
:
754 result
= AEProcessEvent(event
);
761 wxTheApp
->MacSetCurrentEvent( formerEvent
, formerEventHandlerCallRef
) ;
766 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacAppEventHandler
)
769 #if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
772 wxMacAssertOutputHandler(OSType
WXUNUSED(componentSignature
),
773 UInt32
WXUNUSED(options
),
774 const char *assertionString
,
775 const char *exceptionLabelString
,
776 const char *errorString
,
777 const char *fileName
,
780 ConstStr255Param
WXUNUSED(outputMsg
))
782 // flow into assert handling
783 wxString fileNameStr
;
784 wxString assertionStr
;
785 wxString exceptionStr
;
789 fileNameStr
= wxString(fileName
, wxConvLocal
);
790 assertionStr
= wxString(assertionString
, wxConvLocal
);
791 exceptionStr
= wxString((exceptionLabelString
!=0) ? exceptionLabelString
: "", wxConvLocal
) ;
792 errorStr
= wxString((errorString
!=0) ? errorString
: "", wxConvLocal
) ;
794 fileNameStr
= fileName
;
795 assertionStr
= assertionString
;
796 exceptionStr
= (exceptionLabelString
!=0) ? exceptionLabelString
: "" ;
797 errorStr
= (errorString
!=0) ? errorString
: "" ;
802 wxLogDebug( wxT("AssertMacros: %s %s %s file: %s, line: %ld (value %p)\n"),
803 assertionStr
.c_str() ,
804 exceptionStr
.c_str() ,
806 fileNameStr
.c_str(), lineNumber
,
810 wxOnAssert(fileNameStr
, lineNumber
, assertionStr
,
811 wxString::Format( wxT("%s %s value (%p)") , exceptionStr
, errorStr
, value
) ) ;
815 #endif // wxDEBUG_LEVEL
817 bool wxApp::Initialize(int& argc
, wxChar
**argv
)
821 #if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
822 InstallDebugAssertOutputHandler( NewDebugAssertOutputHandlerUPP( wxMacAssertOutputHandler
) );
825 // Mac OS X passes a process serial number command line argument when
826 // the application is launched from the Finder. This argument must be
827 // removed from the command line arguments before being handled by the
828 // application (otherwise applications would need to handle it)
831 static const wxChar
*ARG_PSN
= wxT("-psn_");
832 if ( wxStrncmp(argv
[1], ARG_PSN
, wxStrlen(ARG_PSN
)) == 0 )
834 // remove this argument
836 memmove(argv
+ 1, argv
+ 2, argc
* sizeof(wxChar
*));
841 Cocoa supports -Key value options which set the user defaults key "Key"
842 to the value "value" Some of them are very handy for debugging like
843 -NSShowAllViews YES. Cocoa picks these up from the real argv so
844 our removal of them from the wx copy of it does not affect Cocoa's
847 We basically just assume that any "-NS" option and its following
848 argument needs to be removed from argv. We hope that user code does
849 not expect to see -NS options and indeed it's probably a safe bet
850 since most user code accepting options is probably using the
851 double-dash GNU-style syntax.
853 for(int i
=1; i
< argc
; ++i
)
855 static const wxChar
*ARG_NS
= wxT("-NS");
856 if( wxStrncmp(argv
[i
], ARG_NS
, wxStrlen(ARG_NS
)) == 0 )
858 // Only eat this option if it has an argument
861 memmove(argv
+ i
, argv
+ i
+ 2, (argc
-i
-1)*sizeof(wxChar
*));
863 // drop back one position so the next run through the loop
864 // reprocesses the argument at our current index.
870 if ( !wxAppBase::Initialize(argc
, argv
) )
874 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
877 // these might be the startup dirs, set them to the 'usual' dir containing the app bundle
878 wxString startupCwd
= wxGetCwd() ;
879 if ( startupCwd
== wxT("/") || startupCwd
.Right(15) == wxT("/Contents/MacOS") )
881 CFURLRef url
= CFBundleCopyBundleURL(CFBundleGetMainBundle() ) ;
882 CFURLRef urlParent
= CFURLCreateCopyDeletingLastPathComponent( kCFAllocatorDefault
, url
) ;
884 CFStringRef path
= CFURLCopyFileSystemPath ( urlParent
, kCFURLPOSIXPathStyle
) ;
885 CFRelease( urlParent
) ;
886 wxString cwd
= wxCFStringRef(path
).AsString(wxLocale::GetSystemEncoding());
887 wxSetWorkingDirectory( cwd
) ;
893 #if wxOSX_USE_COCOA_OR_CARBON
894 bool wxApp::CallOnInit()
896 wxMacAutoreleasePool autoreleasepool
;
901 bool wxApp::OnInitGui()
903 if ( !wxAppBase::OnInitGui() )
912 bool wxApp::ProcessIdle()
914 wxMacAutoreleasePool autoreleasepool
;
915 return wxAppBase::ProcessIdle();
920 wxMacAutoreleasePool pool
;
921 return wxAppBase::OnRun();
925 bool wxApp::DoInitGui()
927 InstallStandardEventHandler( GetApplicationEventTarget() ) ;
930 InstallApplicationEventHandler(
931 GetwxMacAppEventHandlerUPP(),
932 GetEventTypeCount(eventList
), eventList
, wxTheApp
, (EventHandlerRef
*)&(wxTheApp
->m_macEventHandler
));
937 sODocHandler
= NewAEEventHandlerUPP(AEHandleODoc
) ;
938 sGURLHandler
= NewAEEventHandlerUPP(AEHandleGURL
) ;
939 sOAppHandler
= NewAEEventHandlerUPP(AEHandleOApp
) ;
940 sPDocHandler
= NewAEEventHandlerUPP(AEHandlePDoc
) ;
941 sRAppHandler
= NewAEEventHandlerUPP(AEHandleRApp
) ;
942 sQuitHandler
= NewAEEventHandlerUPP(AEHandleQuit
) ;
944 AEInstallEventHandler( kCoreEventClass
, kAEOpenDocuments
,
945 sODocHandler
, 0 , FALSE
) ;
946 AEInstallEventHandler( kInternetEventClass
, kAEGetURL
,
947 sGURLHandler
, 0 , FALSE
) ;
948 AEInstallEventHandler( kCoreEventClass
, kAEOpenApplication
,
949 sOAppHandler
, 0 , FALSE
) ;
950 AEInstallEventHandler( kCoreEventClass
, kAEPrintDocuments
,
951 sPDocHandler
, 0 , FALSE
) ;
952 AEInstallEventHandler( kCoreEventClass
, kAEReopenApplication
,
953 sRAppHandler
, 0 , FALSE
) ;
954 AEInstallEventHandler( kCoreEventClass
, kAEQuitApplication
,
955 sQuitHandler
, 0 , FALSE
) ;
958 if ( !wxMacInitCocoa() )
964 void wxApp::DoCleanUp()
967 RemoveEventHandler( (EventHandlerRef
)(wxTheApp
->m_macEventHandler
) );
971 AERemoveEventHandler( kCoreEventClass
, kAEOpenDocuments
,
972 sODocHandler
, FALSE
) ;
973 AERemoveEventHandler( kInternetEventClass
, kAEGetURL
,
974 sGURLHandler
, FALSE
) ;
975 AERemoveEventHandler( kCoreEventClass
, kAEOpenApplication
,
976 sOAppHandler
, FALSE
) ;
977 AERemoveEventHandler( kCoreEventClass
, kAEPrintDocuments
,
978 sPDocHandler
, FALSE
) ;
979 AERemoveEventHandler( kCoreEventClass
, kAEReopenApplication
,
980 sRAppHandler
, FALSE
) ;
981 AERemoveEventHandler( kCoreEventClass
, kAEQuitApplication
,
982 sQuitHandler
, FALSE
) ;
984 DisposeAEEventHandlerUPP( sODocHandler
) ;
985 DisposeAEEventHandlerUPP( sGURLHandler
) ;
986 DisposeAEEventHandlerUPP( sOAppHandler
) ;
987 DisposeAEEventHandlerUPP( sPDocHandler
) ;
988 DisposeAEEventHandlerUPP( sRAppHandler
) ;
989 DisposeAEEventHandlerUPP( sQuitHandler
) ;
995 void wxApp::CleanUp()
997 wxMacAutoreleasePool autoreleasepool
;
999 wxToolTip::RemoveToolTips() ;
1004 wxAppBase::CleanUp();
1007 //----------------------------------------------------------------------
1008 // misc initialization stuff
1009 //----------------------------------------------------------------------
1013 m_printMode
= wxPRINT_WINDOWS
;
1015 m_macCurrentEvent
= NULL
;
1016 m_macCurrentEventHandlerCallRef
= NULL
;
1017 m_macPool
= new wxMacAutoreleasePool();
1026 CFMutableArrayRef
GetAutoReleaseArray()
1028 static CFMutableArrayRef array
= 0;
1030 array
= CFArrayCreateMutable(kCFAllocatorDefault
,0,&kCFTypeArrayCallBacks
);
1034 void wxApp::MacAddToAutorelease( void* cfrefobj
)
1036 CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj
);
1039 void wxApp::MacReleaseAutoreleasePool()
1043 m_macPool
= new wxMacAutoreleasePool();
1046 void wxApp::OnIdle(wxIdleEvent
& WXUNUSED(event
))
1048 // If they are pending events, we must process them: pending events are
1049 // either events to the threads other than main or events posted with
1050 // wxPostEvent() functions
1051 #ifndef __WXUNIVERSAL__
1053 if (!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar())
1054 wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar();
1057 CFArrayRemoveAllValues( GetAutoReleaseArray() );
1060 void wxApp::WakeUpIdle()
1062 wxEventLoopBase
* const loop
= wxEventLoopBase::GetActive();
1068 void wxApp::OnEndSession(wxCloseEvent
& WXUNUSED(event
))
1071 GetTopWindow()->Close(true);
1074 // Default behaviour: close the application with prompts. The
1075 // user can veto the close, and therefore the end session.
1076 void wxApp::OnQueryEndSession(wxCloseEvent
& event
)
1078 if ( !wxDialog::OSXHasModalDialogsOpen() )
1082 if (!GetTopWindow()->Close(!event
.CanVeto()))
1092 extern "C" void wxCYield() ;
1099 void wxApp::MacHandleUnhandledEvent( WXEVENTREF
WXUNUSED(evr
) )
1101 // Override to process unhandled events as you please
1104 #if wxOSX_USE_COCOA_OR_CARBON
1106 CGKeyCode
wxCharCodeWXToOSX(wxKeyCode code
)
1112 // Clang warns about switch values not of the same type as (enumerated)
1113 // switch controlling expression. This is generally useful but here we
1114 // really want to be able to use letters and digits without making them
1115 // part of wxKeyCode enum.
1117 #pragma clang diagnostic push
1118 #pragma clang diagnostic ignored "-Wswitch"
1121 case 'a': case 'A': keycode
= kVK_ANSI_A
; break;
1122 case 'b': case 'B': keycode
= kVK_ANSI_B
; break;
1123 case 'c': case 'C': keycode
= kVK_ANSI_C
; break;
1124 case 'd': case 'D': keycode
= kVK_ANSI_D
; break;
1125 case 'e': case 'E': keycode
= kVK_ANSI_E
; break;
1126 case 'f': case 'F': keycode
= kVK_ANSI_F
; break;
1127 case 'g': case 'G': keycode
= kVK_ANSI_G
; break;
1128 case 'h': case 'H': keycode
= kVK_ANSI_H
; break;
1129 case 'i': case 'I': keycode
= kVK_ANSI_I
; break;
1130 case 'j': case 'J': keycode
= kVK_ANSI_J
; break;
1131 case 'k': case 'K': keycode
= kVK_ANSI_K
; break;
1132 case 'l': case 'L': keycode
= kVK_ANSI_L
; break;
1133 case 'm': case 'M': keycode
= kVK_ANSI_M
; break;
1134 case 'n': case 'N': keycode
= kVK_ANSI_N
; break;
1135 case 'o': case 'O': keycode
= kVK_ANSI_O
; break;
1136 case 'p': case 'P': keycode
= kVK_ANSI_P
; break;
1137 case 'q': case 'Q': keycode
= kVK_ANSI_Q
; break;
1138 case 'r': case 'R': keycode
= kVK_ANSI_R
; break;
1139 case 's': case 'S': keycode
= kVK_ANSI_S
; break;
1140 case 't': case 'T': keycode
= kVK_ANSI_T
; break;
1141 case 'u': case 'U': keycode
= kVK_ANSI_U
; break;
1142 case 'v': case 'V': keycode
= kVK_ANSI_V
; break;
1143 case 'w': case 'W': keycode
= kVK_ANSI_W
; break;
1144 case 'x': case 'X': keycode
= kVK_ANSI_X
; break;
1145 case 'y': case 'Y': keycode
= kVK_ANSI_Y
; break;
1146 case 'z': case 'Z': keycode
= kVK_ANSI_Z
; break;
1148 case '0': keycode
= kVK_ANSI_0
; break;
1149 case '1': keycode
= kVK_ANSI_1
; break;
1150 case '2': keycode
= kVK_ANSI_2
; break;
1151 case '3': keycode
= kVK_ANSI_3
; break;
1152 case '4': keycode
= kVK_ANSI_4
; break;
1153 case '5': keycode
= kVK_ANSI_5
; break;
1154 case '6': keycode
= kVK_ANSI_6
; break;
1155 case '7': keycode
= kVK_ANSI_7
; break;
1156 case '8': keycode
= kVK_ANSI_8
; break;
1157 case '9': keycode
= kVK_ANSI_9
; break;
1160 #pragma clang diagnostic pop
1163 case WXK_BACK
: keycode
= kVK_Delete
; break;
1164 case WXK_TAB
: keycode
= kVK_Tab
; break;
1165 case WXK_RETURN
: keycode
= kVK_Return
; break;
1166 case WXK_ESCAPE
: keycode
= kVK_Escape
; break;
1167 case WXK_SPACE
: keycode
= kVK_Space
; break;
1168 case WXK_DELETE
: keycode
= kVK_ForwardDelete
; break;
1170 case WXK_SHIFT
: keycode
= kVK_Shift
; break;
1171 case WXK_ALT
: keycode
= kVK_Option
; break;
1172 case WXK_RAW_CONTROL
: keycode
= kVK_Control
; break;
1173 case WXK_CONTROL
: keycode
= kVK_Command
; break;
1175 case WXK_CAPITAL
: keycode
= kVK_CapsLock
; break;
1176 case WXK_END
: keycode
= kVK_End
; break;
1177 case WXK_HOME
: keycode
= kVK_Home
; break;
1178 case WXK_LEFT
: keycode
= kVK_LeftArrow
; break;
1179 case WXK_UP
: keycode
= kVK_UpArrow
; break;
1180 case WXK_RIGHT
: keycode
= kVK_RightArrow
; break;
1181 case WXK_DOWN
: keycode
= kVK_DownArrow
; break;
1183 case WXK_HELP
: keycode
= kVK_Help
; break;
1186 case WXK_NUMPAD0
: keycode
= kVK_ANSI_Keypad0
; break;
1187 case WXK_NUMPAD1
: keycode
= kVK_ANSI_Keypad1
; break;
1188 case WXK_NUMPAD2
: keycode
= kVK_ANSI_Keypad2
; break;
1189 case WXK_NUMPAD3
: keycode
= kVK_ANSI_Keypad3
; break;
1190 case WXK_NUMPAD4
: keycode
= kVK_ANSI_Keypad4
; break;
1191 case WXK_NUMPAD5
: keycode
= kVK_ANSI_Keypad5
; break;
1192 case WXK_NUMPAD6
: keycode
= kVK_ANSI_Keypad6
; break;
1193 case WXK_NUMPAD7
: keycode
= kVK_ANSI_Keypad7
; break;
1194 case WXK_NUMPAD8
: keycode
= kVK_ANSI_Keypad8
; break;
1195 case WXK_NUMPAD9
: keycode
= kVK_ANSI_Keypad9
; break;
1196 case WXK_F1
: keycode
= kVK_F1
; break;
1197 case WXK_F2
: keycode
= kVK_F2
; break;
1198 case WXK_F3
: keycode
= kVK_F3
; break;
1199 case WXK_F4
: keycode
= kVK_F4
; break;
1200 case WXK_F5
: keycode
= kVK_F5
; break;
1201 case WXK_F6
: keycode
= kVK_F6
; break;
1202 case WXK_F7
: keycode
= kVK_F7
; break;
1203 case WXK_F8
: keycode
= kVK_F8
; break;
1204 case WXK_F9
: keycode
= kVK_F9
; break;
1205 case WXK_F10
: keycode
= kVK_F10
; break;
1206 case WXK_F11
: keycode
= kVK_F11
; break;
1207 case WXK_F12
: keycode
= kVK_F12
; break;
1208 case WXK_F13
: keycode
= kVK_F13
; break;
1209 case WXK_F14
: keycode
= kVK_F14
; break;
1210 case WXK_F15
: keycode
= kVK_F15
; break;
1211 case WXK_F16
: keycode
= kVK_F16
; break;
1212 case WXK_F17
: keycode
= kVK_F17
; break;
1213 case WXK_F18
: keycode
= kVK_F18
; break;
1214 case WXK_F19
: keycode
= kVK_F19
; break;
1215 case WXK_F20
: keycode
= kVK_F20
; break;
1217 case WXK_PAGEUP
: keycode
= kVK_PageUp
; break;
1218 case WXK_PAGEDOWN
: keycode
= kVK_PageDown
; break;
1220 case WXK_NUMPAD_DELETE
: keycode
= kVK_ANSI_KeypadClear
; break;
1221 case WXK_NUMPAD_EQUAL
: keycode
= kVK_ANSI_KeypadEquals
; break;
1222 case WXK_NUMPAD_MULTIPLY
: keycode
= kVK_ANSI_KeypadMultiply
; break;
1223 case WXK_NUMPAD_ADD
: keycode
= kVK_ANSI_KeypadPlus
; break;
1224 case WXK_NUMPAD_SUBTRACT
: keycode
= kVK_ANSI_KeypadMinus
; break;
1225 case WXK_NUMPAD_DECIMAL
: keycode
= kVK_ANSI_KeypadDecimal
; break;
1226 case WXK_NUMPAD_DIVIDE
: keycode
= kVK_ANSI_KeypadDivide
; break;
1229 wxLogDebug( "Unrecognised keycode %d", code
);
1230 keycode
= static_cast<CGKeyCode
>(-1);
1236 long wxMacTranslateKey(unsigned char key
, unsigned char code
)
1241 case kHomeCharCode
:
1245 case kEnterCharCode
:
1246 retval
= WXK_RETURN
;
1252 case kHelpCharCode
:
1256 case kBackspaceCharCode
:
1264 case kPageUpCharCode
:
1265 retval
= WXK_PAGEUP
;
1268 case kPageDownCharCode
:
1269 retval
= WXK_PAGEDOWN
;
1272 case kReturnCharCode
:
1273 retval
= WXK_RETURN
;
1276 case kFunctionKeyCharCode
:
1346 case kEscapeCharCode
:
1347 retval
= WXK_ESCAPE
;
1350 case kLeftArrowCharCode
:
1354 case kRightArrowCharCode
:
1355 retval
= WXK_RIGHT
;
1358 case kUpArrowCharCode
:
1362 case kDownArrowCharCode
:
1366 case kDeleteCharCode
:
1367 retval
= WXK_DELETE
;
1377 int wxMacKeyCodeToModifier(wxKeyCode key
)
1395 case WXK_RAW_CONTROL
:
1404 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
1406 // defined in utils.mm
1408 #elif wxOSX_USE_COCOA_OR_CARBON
1410 wxMouseState
wxGetMouseState()
1414 wxPoint pt
= wxGetMousePosition();
1418 UInt32 buttons
= GetCurrentButtonState();
1419 ms
.SetLeftDown( (buttons
& 0x01) != 0 );
1420 ms
.SetMiddleDown( (buttons
& 0x04) != 0 );
1421 ms
.SetRightDown( (buttons
& 0x02) != 0 );
1423 UInt32 modifiers
= GetCurrentKeyModifiers();
1424 ms
.SetRawControlDown(modifiers
& controlKey
);
1425 ms
.SetShiftDown(modifiers
& shiftKey
);
1426 ms
.SetAltDown(modifiers
& optionKey
);
1427 ms
.SetControlDown(modifiers
& cmdKey
);
1434 // TODO : once the new key/char handling is tested, move all the code to wxWindow
1436 bool wxApp::MacSendKeyDownEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1441 wxKeyEvent
event(wxEVT_KEY_DOWN
) ;
1442 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, uniChar
) ;
1444 return focus
->OSXHandleKeyEvent(event
);
1447 bool wxApp::MacSendKeyUpEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1452 wxKeyEvent
event( wxEVT_KEY_UP
) ;
1453 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, uniChar
) ;
1455 return focus
->OSXHandleKeyEvent(event
) ;
1458 bool wxApp::MacSendCharEvent( wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1462 wxKeyEvent
event(wxEVT_CHAR
) ;
1463 MacCreateKeyEvent( event
, focus
, keymessage
, modifiers
, when
, uniChar
) ;
1465 bool handled
= false ;
1467 #if wxOSX_USE_CARBON
1468 long keyval
= event
.m_keyCode
;
1471 wxKeyEvent
eventCharHook(wxEVT_CHAR_HOOK
, event
);
1472 handled
= focus
->HandleWindowEvent( eventCharHook
);
1473 if ( handled
&& eventCharHook
.IsNextEventAllowed() )
1479 handled
= focus
->HandleWindowEvent( event
) ;
1482 if ( !handled
&& (keyval
== WXK_TAB
) )
1484 wxWindow
* iter
= focus
->GetParent() ;
1485 while ( iter
&& !handled
)
1487 if ( iter
->HasFlag( wxTAB_TRAVERSAL
) )
1489 wxNavigationKeyEvent new_event
;
1490 new_event
.SetEventObject( focus
);
1491 new_event
.SetDirection( !event
.ShiftDown() );
1492 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1493 new_event
.SetWindowChange( event
.ControlDown() );
1494 new_event
.SetCurrentFocus( focus
);
1495 handled
= focus
->GetParent()->HandleWindowEvent( new_event
);
1496 if ( handled
&& new_event
.GetSkipped() )
1500 iter
= iter
->GetParent() ;
1504 // backdoor handler for default return and command escape
1505 if ( !handled
&& (!focus
->IsKindOf(CLASSINFO(wxControl
) ) || !focus
->AcceptsFocus() ) )
1507 // if window is not having a focus still testing for default enter or cancel
1508 // TODO: add the UMA version for ActiveNonFloatingWindow
1510 wxWindow
* focus
= wxNonOwnedWindow::GetFromWXWindow( (WXWindow
) FrontWindow() ) ;
1513 if ( keyval
== WXK_RETURN
|| keyval
== WXK_NUMPAD_ENTER
)
1515 wxTopLevelWindow
*tlw
= wxDynamicCast(wxGetTopLevelParent(focus
), wxTopLevelWindow
);
1516 if ( tlw
&& tlw
->GetDefaultItem() )
1518 wxButton
*def
= wxDynamicCast(tlw
->GetDefaultItem(), wxButton
);
1519 if ( def
&& def
->IsEnabled() )
1521 wxCommandEvent
event(wxEVT_BUTTON
, def
->GetId() );
1522 event
.SetEventObject(def
);
1523 def
->Command(event
);
1529 else if (keyval
== WXK_ESCAPE
|| (keyval
== '.' && modifiers
& cmdKey
) )
1531 // generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs)
1532 wxCommandEvent
new_event(wxEVT_BUTTON
,wxID_CANCEL
);
1533 new_event
.SetEventObject( focus
);
1534 handled
= focus
->HandleWindowEvent( new_event
);
1543 // This method handles common code for SendKeyDown, SendKeyUp, and SendChar events.
1544 void wxApp::MacCreateKeyEvent( wxKeyEvent
& event
, wxWindow
* focus
, long keymessage
, long modifiers
, long when
, wxChar uniChar
)
1546 #if wxOSX_USE_COCOA_OR_CARBON
1548 short keycode
, keychar
;
1550 keychar
= short(keymessage
& charCodeMask
);
1551 keycode
= short(keymessage
& keyCodeMask
) >> 8 ;
1552 if ( !(event
.GetEventType() == wxEVT_CHAR
) && (modifiers
& (controlKey
| shiftKey
| optionKey
) ) )
1554 // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
1555 // and look at the character after
1557 // TODO new implementation using TextInputSources
1560 UInt32 keyInfo
= KeyTranslate((Ptr
)GetScriptManagerVariable(smKCHRCache
), ( modifiers
& (~(controlKey
| shiftKey
| optionKey
))) | keycode
, &state
);
1561 keychar
= short(keyInfo
& charCodeMask
);
1565 long keyval
= wxMacTranslateKey(keychar
, keycode
) ;
1566 if ( keyval
== keychar
&& ( event
.GetEventType() == wxEVT_KEY_UP
|| event
.GetEventType() == wxEVT_KEY_DOWN
) )
1567 keyval
= wxToupper( keyval
) ;
1569 // Check for NUMPAD keys. For KEY_UP/DOWN events we need to use the
1570 // WXK_NUMPAD constants, but for the CHAR event we want to use the
1571 // standard ascii values
1572 if ( event
.GetEventType() != wxEVT_CHAR
)
1574 if (keyval
>= '0' && keyval
<= '9' && keycode
>= 82 && keycode
<= 92)
1576 keyval
= (keyval
- '0') + WXK_NUMPAD0
;
1578 else if (keycode
>= 65 && keycode
<= 81)
1583 keyval
= WXK_NUMPAD_ENTER
;
1587 keyval
= WXK_NUMPAD_EQUAL
;
1591 keyval
= WXK_NUMPAD_MULTIPLY
;
1595 keyval
= WXK_NUMPAD_DIVIDE
;
1599 keyval
= WXK_NUMPAD_SUBTRACT
;
1603 keyval
= WXK_NUMPAD_ADD
;
1607 keyval
= WXK_NUMPAD_DECIMAL
;
1615 event
.m_shiftDown
= modifiers
& shiftKey
;
1616 event
.m_rawControlDown
= modifiers
& controlKey
;
1617 event
.m_altDown
= modifiers
& optionKey
;
1618 event
.m_controlDown
= modifiers
& cmdKey
;
1619 event
.m_keyCode
= keyval
;
1621 event
.m_uniChar
= uniChar
;
1624 event
.m_rawCode
= keymessage
;
1625 event
.m_rawFlags
= modifiers
;
1626 event
.SetTimestamp(when
);
1627 event
.SetEventObject(focus
);
1631 wxUnusedVar(keymessage
);
1632 wxUnusedVar(modifiers
);
1634 wxUnusedVar(uniChar
);
1639 void wxApp::MacHideApp()
1641 #if wxOSX_USE_CARBON
1642 wxMacCarbonEvent
event( kEventClassCommand
, kEventCommandProcess
);
1644 memset( &command
, 0 , sizeof(command
) );
1645 command
.commandID
= kHICommandHide
;
1646 event
.SetParameter
<HICommand
>(kEventParamDirectObject
, command
);
1647 SendEventToApplication( event
);