]> git.saurik.com Git - wxWidgets.git/blame - src/osx/carbon/app.cpp
changing to allow for 2x ramping up NSApp run
[wxWidgets.git] / src / osx / carbon / app.cpp
CommitLineData
489468fe 1/////////////////////////////////////////////////////////////////////////////
524c47aa 2// Name: src/osx/carbon/app.cpp
489468fe
SC
3// Purpose: wxApp
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
489468fe
SC
7// Copyright: (c) Stefan Csomor
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#include "wx/wxprec.h"
12
13#include "wx/app.h"
14
15#ifndef WX_PRECOMP
16 #include "wx/intl.h"
17 #include "wx/log.h"
18 #include "wx/utils.h"
19 #include "wx/window.h"
20 #include "wx/frame.h"
21 #include "wx/dc.h"
22 #include "wx/button.h"
23 #include "wx/menu.h"
24 #include "wx/pen.h"
25 #include "wx/brush.h"
26 #include "wx/palette.h"
27 #include "wx/icon.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"
35#endif
36
37#include "wx/tooltip.h"
38#include "wx/docview.h"
39#include "wx/filename.h"
40#include "wx/link.h"
41#include "wx/thread.h"
524c47aa 42#include "wx/evtloop.h"
489468fe
SC
43
44#include <string.h>
45
46// mac
b2680ced 47#if wxOSX_USE_CARBON
1f0c8f31 48#include "wx/osx/uma.h"
b2680ced
SC
49#else
50#include "wx/osx/private.h"
51#endif
489468fe 52
b2680ced
SC
53#if defined(WXMAKINGDLL_CORE)
54# include <mach-o/dyld.h>
489468fe
SC
55#endif
56
57// Keep linker from discarding wxStockGDIMac
58wxFORCE_LINK_MODULE(gdiobj)
59
489468fe
SC
60IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
61BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
62 EVT_IDLE(wxApp::OnIdle)
63 EVT_END_SESSION(wxApp::OnEndSession)
64 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
65END_EVENT_TABLE()
66
67
68// platform specific static variables
69static const short kwxMacAppleMenuId = 1 ;
70
71wxWindow* wxApp::s_captureWindow = NULL ;
72long wxApp::s_lastModifiers = 0 ;
73
74long wxApp::s_macAboutMenuItemId = wxID_ABOUT ;
75long wxApp::s_macPreferencesMenuItemId = wxID_PREFERENCES ;
76long wxApp::s_macExitMenuItemId = wxID_EXIT ;
77wxString wxApp::s_macHelpMenuTitleName = wxT("&Help") ;
78
79bool wxApp::sm_isEmbedded = false; // Normally we're not a plugin
80
f93849e6 81#if wxOSX_USE_CARBON
b2680ced 82
489468fe
SC
83//----------------------------------------------------------------------
84// Core Apple Event Support
85//----------------------------------------------------------------------
86
b2680ced
SC
87AEEventHandlerUPP sODocHandler = NULL ;
88AEEventHandlerUPP sGURLHandler = NULL ;
89AEEventHandlerUPP sOAppHandler = NULL ;
90AEEventHandlerUPP sPDocHandler = NULL ;
91AEEventHandlerUPP sRAppHandler = NULL ;
92AEEventHandlerUPP sQuitHandler = NULL ;
93
489468fe
SC
94pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
95pascal OSErr AEHandleOApp( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
96pascal OSErr AEHandlePDoc( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
97pascal OSErr AEHandleQuit( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
98pascal OSErr AEHandleRApp( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
b2680ced 99pascal OSErr AEHandleGURL( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
489468fe
SC
100
101pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
102{
103 return wxTheApp->MacHandleAEODoc( (AppleEvent*) event , reply) ;
104}
105
106pascal OSErr AEHandleOApp( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
107{
108 return wxTheApp->MacHandleAEOApp( (AppleEvent*) event , reply ) ;
109}
110
111pascal OSErr AEHandlePDoc( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
112{
113 return wxTheApp->MacHandleAEPDoc( (AppleEvent*) event , reply ) ;
114}
115
116pascal OSErr AEHandleQuit( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
117{
118 return wxTheApp->MacHandleAEQuit( (AppleEvent*) event , reply) ;
119}
120
121pascal OSErr AEHandleRApp( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
122{
123 return wxTheApp->MacHandleAERApp( (AppleEvent*) event , reply) ;
124}
125
126pascal OSErr AEHandleGURL( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
127{
128 return wxTheApp->MacHandleAEGURL((WXEVENTREF *)event , reply) ;
129}
130
131
ee7553e9 132// AEODoc Calls MacOpenFiles with all of the files passed
489468fe
SC
133
134short wxApp::MacHandleAEODoc(const WXEVENTREF event, WXEVENTREF WXUNUSED(reply))
135{
136 AEDescList docList;
137 AEKeyword keywd;
138 DescType returnedType;
139 Size actualSize;
140 long itemsInList;
141 OSErr err;
142 short i;
143
144 err = AEGetParamDesc((AppleEvent *)event, keyDirectObject, typeAEList,&docList);
145 if (err != noErr)
146 return err;
147
148 err = AECountItems(&docList, &itemsInList);
149 if (err != noErr)
150 return err;
151
152 ProcessSerialNumber PSN ;
153 PSN.highLongOfPSN = 0 ;
154 PSN.lowLongOfPSN = kCurrentProcess ;
155 SetFrontProcess( &PSN ) ;
156
157 wxString fName ;
158 FSRef theRef ;
159
ee7553e9 160 wxArrayString fileNames;
489468fe
SC
161 for (i = 1; i <= itemsInList; i++)
162 {
0161592b 163 err = AEGetNthPtr(
489468fe
SC
164 &docList, i, typeFSRef, &keywd, &returnedType,
165 (Ptr)&theRef, sizeof(theRef), &actualSize);
0161592b
SC
166
167 if ( err != noErr)
168 return err;
169
489468fe
SC
170 fName = wxMacFSRefToPath( &theRef ) ;
171
ee7553e9 172 fileNames.Add(fName);
489468fe
SC
173 }
174
ee7553e9
DS
175 MacOpenFiles(fileNames);
176
489468fe
SC
177 return noErr;
178}
179
180// AEODoc Calls MacOpenURL on the url passed
181
182short wxApp::MacHandleAEGURL(const WXEVENTREF event, WXEVENTREF WXUNUSED(reply))
183{
184 DescType returnedType;
185 Size actualSize;
186 char url[255];
187 OSErr err = AEGetParamPtr((AppleEvent *)event, keyDirectObject, typeChar,
188 &returnedType, url, sizeof(url)-1,
189 &actualSize);
190 if (err != noErr)
191 return err;
192
d181e877 193 url[actualSize] = '\0'; // Terminate the C string
489468fe
SC
194
195 ProcessSerialNumber PSN ;
196 PSN.highLongOfPSN = 0 ;
197 PSN.lowLongOfPSN = kCurrentProcess ;
198 SetFrontProcess( &PSN ) ;
199
200 MacOpenURL(wxString(url, wxConvUTF8));
201
202 return noErr;
203}
204
205// AEPDoc Calls MacPrintFile on each of the files passed
206
207short wxApp::MacHandleAEPDoc(const WXEVENTREF event , WXEVENTREF WXUNUSED(reply))
208{
209 AEDescList docList;
210 AEKeyword keywd;
211 DescType returnedType;
212 Size actualSize;
213 long itemsInList;
214 OSErr err;
215 short i;
216
217 err = AEGetParamDesc((AppleEvent *)event, keyDirectObject, typeAEList,&docList);
218 if (err != noErr)
219 return err;
220
221 err = AECountItems(&docList, &itemsInList);
222 if (err != noErr)
223 return err;
224
225 ProcessSerialNumber PSN ;
226 PSN.highLongOfPSN = 0 ;
227 PSN.lowLongOfPSN = kCurrentProcess ;
228 SetFrontProcess( &PSN ) ;
229
230 wxString fName ;
231 FSRef theRef ;
232
233 for (i = 1; i <= itemsInList; i++)
234 {
9c841f84 235 err = AEGetNthPtr(
489468fe
SC
236 &docList, i, typeFSRef, &keywd, &returnedType,
237 (Ptr)&theRef, sizeof(theRef), &actualSize);
9c841f84
SC
238
239 if ( err != noErr)
240 return err;
241
489468fe
SC
242 fName = wxMacFSRefToPath( &theRef ) ;
243
244 MacPrintFile(fName);
245 }
246
247 return noErr;
248}
249
250// AEOApp calls MacNewFile
251
252short wxApp::MacHandleAEOApp(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
253{
254 MacNewFile() ;
255 return noErr ;
256}
257
258// AEQuit attempts to quit the application
259
260short wxApp::MacHandleAEQuit(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
261{
2680ddc6
SC
262 wxCloseEvent event;
263 wxTheApp->OnQueryEndSession(event);
264 if ( !event.GetVeto() )
489468fe 265 {
2680ddc6
SC
266 wxCloseEvent event;
267 wxTheApp->OnEndSession(event);
489468fe 268 }
489468fe
SC
269 return noErr ;
270}
271
272// AEROApp calls MacReopenApp
273
274short wxApp::MacHandleAERApp(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
275{
276 MacReopenApp() ;
277
278 return noErr ;
279}
280
b2680ced
SC
281#endif
282
489468fe
SC
283//----------------------------------------------------------------------
284// Support Routines linking the Mac...File Calls to the Document Manager
285//----------------------------------------------------------------------
286
ee7553e9
DS
287void wxApp::MacOpenFiles(const wxArrayString & fileNames )
288{
289 size_t i;
290 const size_t fileCount = fileNames.GetCount();
291 for (i = 0; i < fileCount; i++)
292 {
293 MacOpenFile(fileNames[i]);
294 }
295}
296
489468fe
SC
297void wxApp::MacOpenFile(const wxString & fileName )
298{
299#if wxUSE_DOC_VIEW_ARCHITECTURE
300 wxDocManager* dm = wxDocManager::GetDocumentManager() ;
301 if ( dm )
302 dm->CreateDocument(fileName , wxDOC_SILENT ) ;
303#endif
304}
305
306void wxApp::MacOpenURL(const wxString & WXUNUSED(url) )
307{
308}
309
310void wxApp::MacPrintFile(const wxString & fileName )
311{
312#if wxUSE_DOC_VIEW_ARCHITECTURE
313
314#if wxUSE_PRINTING_ARCHITECTURE
315 wxDocManager* dm = wxDocManager::GetDocumentManager() ;
316 if ( dm )
317 {
318 wxDocument *doc = dm->CreateDocument(fileName , wxDOC_SILENT ) ;
319 if ( doc )
320 {
321 wxView* view = doc->GetFirstView() ;
322 if ( view )
323 {
324 wxPrintout *printout = view->OnCreatePrintout();
325 if (printout)
326 {
327 wxPrinter printer;
328 printer.Print(view->GetFrame(), printout, true);
329 delete printout;
330 }
331 }
332
333 if (doc->Close())
334 {
335 doc->DeleteAllViews();
336 dm->RemoveDocument(doc) ;
337 }
338 }
339 }
340#endif //print
341
342#endif //docview
343}
344
345
346
347void wxApp::MacNewFile()
348{
349}
350
351void wxApp::MacReopenApp()
352{
353 // HIG says :
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
357
358 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
4b1d0dbe 359 if ( !node )
489468fe
SC
360 {
361 MacNewFile() ;
362 }
363 else
364 {
365 wxTopLevelWindow* firstIconized = NULL ;
366 wxTopLevelWindow* firstHidden = NULL ;
367 while (node)
368 {
369 wxTopLevelWindow* win = (wxTopLevelWindow*) node->GetData();
370 if ( !win->IsShown() )
371 {
372 // make sure we don't show 'virtual toplevel windows' like wxTaskBarIconWindow
373 if ( firstHidden == NULL && ( wxDynamicCast( win, wxFrame ) || wxDynamicCast( win, wxDialog ) ) )
374 firstHidden = win ;
d181e877 375 }
489468fe 376 else if ( win->IsIconized() )
d181e877 377 {
489468fe
SC
378 if ( firstIconized == NULL )
379 firstIconized = win ;
380 }
381 else
382 {
383 // we do have a visible, non-iconized toplevelwindow -> do nothing
384 return;
385 }
386
387 node = node->GetNext();
388 }
389
390 if ( firstIconized )
391 firstIconized->Iconize( false ) ;
50f403a5
SC
392
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 ...
396#if 0
489468fe
SC
397 else if ( firstHidden )
398 firstHidden->Show( true );
50f403a5 399#endif
489468fe
SC
400 }
401}
402
b0ae6049 403#if wxOSX_USE_COCOA_OR_IPHONE
038c9947
SC
404void wxApp::OSXOnWillFinishLaunching()
405{
b0ae6049 406 wxTheApp->OnInit();
038c9947
SC
407}
408
409void wxApp::OSXOnDidFinishLaunching()
410{
b0ae6049 411 wxTheApp->OnLaunched();
fb5cb867 412 wxEventLoopBase::SetActive(GetMainLoop());
15160da2
SC
413}
414
415void wxApp::OSXOnWillTerminate()
416{
417 wxCloseEvent event;
418 event.SetCanVeto(false);
419 wxTheApp->OnEndSession(event);
b0ae6049 420
fb5cb867
SC
421 wxGUIEventLoop* mainloop = dynamic_cast<wxGUIEventLoop*>(GetMainLoop());
422 if ( mainloop )
423 mainloop->OSXOnWillTerminate();
424 wxEventLoopBase::SetActive(NULL);
425
b0ae6049 426 wxTheApp->OnExit();
15160da2
SC
427}
428
429bool wxApp::OSXOnShouldTerminate()
430{
431 wxCloseEvent event;
432 wxTheApp->OnQueryEndSession(event);
433 return !event.GetVeto();
038c9947 434}
b0ae6049 435#endif
038c9947 436
489468fe
SC
437//----------------------------------------------------------------------
438// Macintosh CommandID support - converting between native and wx IDs
439//----------------------------------------------------------------------
440
441// if no native match they just return the passed-in id
442
b2680ced
SC
443#if wxOSX_USE_CARBON
444
489468fe
SC
445struct IdPair
446{
447 UInt32 macId ;
448 int wxId ;
449} ;
450
451IdPair gCommandIds [] =
452{
453 { kHICommandCut , wxID_CUT } ,
454 { kHICommandCopy , wxID_COPY } ,
455 { kHICommandPaste , wxID_PASTE } ,
456 { kHICommandSelectAll , wxID_SELECTALL } ,
457 { kHICommandClear , wxID_CLEAR } ,
458 { kHICommandUndo , wxID_UNDO } ,
459 { kHICommandRedo , wxID_REDO } ,
460} ;
461
462int wxMacCommandToId( UInt32 macCommandId )
463{
464 int wxid = 0 ;
465
466 switch ( macCommandId )
467 {
468 case kHICommandPreferences :
469 wxid = wxApp::s_macPreferencesMenuItemId ;
470 break ;
471
472 case kHICommandQuit :
473 wxid = wxApp::s_macExitMenuItemId ;
474 break ;
475
476 case kHICommandAbout :
477 wxid = wxApp::s_macAboutMenuItemId ;
478 break ;
479
480 default :
481 {
482 for ( size_t i = 0 ; i < WXSIZEOF(gCommandIds) ; ++i )
483 {
484 if ( gCommandIds[i].macId == macCommandId )
485 {
486 wxid = gCommandIds[i].wxId ;
487 break ;
488 }
489 }
490 }
491 break ;
492 }
493
494 if ( wxid == 0 )
495 wxid = (int) macCommandId ;
496
497 return wxid ;
498}
499
500UInt32 wxIdToMacCommand( int wxId )
501{
502 UInt32 macId = 0 ;
503
504 if ( wxId == wxApp::s_macPreferencesMenuItemId )
505 macId = kHICommandPreferences ;
506 else if (wxId == wxApp::s_macExitMenuItemId)
507 macId = kHICommandQuit ;
508 else if (wxId == wxApp::s_macAboutMenuItemId)
509 macId = kHICommandAbout ;
510 else
511 {
512 for ( size_t i = 0 ; i < WXSIZEOF(gCommandIds) ; ++i )
513 {
514 if ( gCommandIds[i].wxId == wxId )
515 {
516 macId = gCommandIds[i].macId ;
517 break ;
518 }
519 }
520 }
521
522 if ( macId == 0 )
523 macId = (int) wxId ;
524
525 return macId ;
526}
527
528wxMenu* wxFindMenuFromMacCommand( const HICommand &command , wxMenuItem* &item )
529{
530 wxMenu* itemMenu = NULL ;
531#ifndef __WXUNIVERSAL__
532 int id = 0 ;
533
534 // for 'standard' commands which don't have a wx-menu
535 if ( command.commandID == kHICommandPreferences || command.commandID == kHICommandQuit || command.commandID == kHICommandAbout )
536 {
537 id = wxMacCommandToId( command.commandID ) ;
538
539 wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
540 if ( mbar )
541 item = mbar->FindItem( id , &itemMenu ) ;
542 }
543 else if ( command.commandID != 0 && command.menu.menuRef != 0 && command.menu.menuItemIndex != 0 )
544 {
545 id = wxMacCommandToId( command.commandID ) ;
546 // make sure it is one of our own menus, or of the 'synthetic' apple and help menus , otherwise don't touch
547 MenuItemIndex firstUserHelpMenuItem ;
548 static MenuHandle helpMenuHandle = NULL ;
549 if ( helpMenuHandle == NULL )
550 {
551 if ( UMAGetHelpMenuDontCreate( &helpMenuHandle , &firstUserHelpMenuItem) != noErr )
552 helpMenuHandle = NULL ;
553 }
554
555 // is it part of the application or the Help menu, then look for the id directly
556 if ( ( GetMenuHandle( kwxMacAppleMenuId ) != NULL && command.menu.menuRef == GetMenuHandle( kwxMacAppleMenuId ) ) ||
d181e877 557 ( helpMenuHandle != NULL && command.menu.menuRef == helpMenuHandle ) ||
489468fe
SC
558 wxMenuBar::MacGetWindowMenuHMenu() != NULL && command.menu.menuRef == wxMenuBar::MacGetWindowMenuHMenu() )
559 {
560 wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
561 if ( mbar )
562 item = mbar->FindItem( id , &itemMenu ) ;
563 }
564 else
565 {
8f2a8de6 566 URefCon refCon = 0 ;
489468fe
SC
567
568 GetMenuItemRefCon( command.menu.menuRef , command.menu.menuItemIndex , &refCon ) ;
569 itemMenu = wxFindMenuFromMacMenu( command.menu.menuRef ) ;
524c47aa 570 if ( itemMenu != NULL && refCon != 0)
0ee6e449 571 item = (wxMenuItem*) refCon;
489468fe
SC
572 }
573 }
574#endif
575 return itemMenu ;
576}
577
b2680ced
SC
578#endif
579
489468fe
SC
580//----------------------------------------------------------------------
581// Carbon Event Handler
582//----------------------------------------------------------------------
583
b2680ced
SC
584#if wxOSX_USE_CARBON
585
489468fe
SC
586static const EventTypeSpec eventList[] =
587{
588 { kEventClassCommand, kEventProcessCommand } ,
589 { kEventClassCommand, kEventCommandUpdateStatus } ,
590
591 { kEventClassMenu, kEventMenuOpening },
592 { kEventClassMenu, kEventMenuClosed },
593 { kEventClassMenu, kEventMenuTargetItem },
594
595 { kEventClassApplication , kEventAppActivated } ,
596 { kEventClassApplication , kEventAppDeactivated } ,
597 // handling the quit event is not recommended by apple
598 // rather using the quit apple event - which we do
599
600 { kEventClassAppleEvent , kEventAppleEvent } ,
601
602 { kEventClassMouse , kEventMouseDown } ,
603 { kEventClassMouse , kEventMouseMoved } ,
604 { kEventClassMouse , kEventMouseUp } ,
605 { kEventClassMouse , kEventMouseDragged } ,
606 { 'WXMC' , 'WXMC' }
607} ;
608
609static pascal OSStatus
610wxMacAppMenuEventHandler( EventHandlerCallRef WXUNUSED(handler),
611 EventRef event,
612 void *WXUNUSED(data) )
613{
614 wxMacCarbonEvent cEvent( event ) ;
615 MenuRef menuRef = cEvent.GetParameter<MenuRef>(kEventParamDirectObject) ;
616#ifndef __WXUNIVERSAL__
617 wxMenu* menu = wxFindMenuFromMacMenu( menuRef ) ;
618
619 if ( menu )
620 {
489468fe
SC
621 switch (GetEventKind(event))
622 {
623 case kEventMenuOpening:
524c47aa 624 menu->HandleMenuOpened();
489468fe
SC
625 break;
626
627 case kEventMenuClosed:
524c47aa 628 menu->HandleMenuClosed();
489468fe
SC
629 break;
630
631 case kEventMenuTargetItem:
524c47aa
SC
632 {
633 HICommand command ;
d181e877 634
524c47aa
SC
635 command.menu.menuRef = menuRef;
636 command.menu.menuItemIndex = cEvent.GetParameter<MenuItemIndex>(kEventParamMenuItemIndex,typeMenuItemIndex) ;
637 command.commandID = cEvent.GetParameter<MenuCommand>(kEventParamMenuCommand,typeMenuCommand) ;
638 if (command.commandID != 0)
639 {
640 wxMenuItem* item = NULL ;
641 wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ;
642 if ( itemMenu && item )
643 itemMenu->HandleMenuItemHighlighted( item );
644 }
645 }
489468fe
SC
646 break;
647
648 default:
649 wxFAIL_MSG(wxT("Unexpected menu event kind"));
650 break;
651 }
652
489468fe
SC
653 }
654#endif
655 return eventNotHandledErr;
656}
657
489468fe
SC
658static pascal OSStatus
659wxMacAppCommandEventHandler( EventHandlerCallRef WXUNUSED(handler) ,
660 EventRef event ,
661 void *WXUNUSED(data) )
662{
663 OSStatus result = eventNotHandledErr ;
664
665 HICommand command ;
666
667 wxMacCarbonEvent cEvent( event ) ;
668 cEvent.GetParameter<HICommand>(kEventParamDirectObject,typeHICommand,&command) ;
669
670 wxMenuItem* item = NULL ;
671 wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ;
489468fe
SC
672
673 if ( item )
674 {
675 wxASSERT( itemMenu != NULL ) ;
676
677 switch ( cEvent.GetKind() )
678 {
679 case kEventProcessCommand :
524c47aa
SC
680 if ( itemMenu->HandleCommandProcess( item ) )
681 result = noErr;
489468fe
SC
682 break ;
683
684 case kEventCommandUpdateStatus:
524c47aa
SC
685 if ( itemMenu->HandleCommandUpdateStatus( item ) )
686 result = noErr;
489468fe
SC
687 break ;
688
689 default :
690 break ;
691 }
692 }
693 return result ;
694}
489468fe
SC
695
696static pascal OSStatus
697wxMacAppApplicationEventHandler( EventHandlerCallRef WXUNUSED(handler) ,
698 EventRef event ,
699 void *WXUNUSED(data) )
700{
701 OSStatus result = eventNotHandledErr ;
702 switch ( GetEventKind( event ) )
703 {
704 case kEventAppActivated :
705 if ( wxTheApp )
706 wxTheApp->SetActive( true , NULL ) ;
707 result = noErr ;
708 break ;
709
710 case kEventAppDeactivated :
711 if ( wxTheApp )
712 wxTheApp->SetActive( false , NULL ) ;
713 result = noErr ;
714 break ;
715
716 default :
717 break ;
718 }
719
720 return result ;
721}
722
723pascal OSStatus wxMacAppEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
724{
725 EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ;
726 EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ;
727 wxTheApp->MacSetCurrentEvent( event , handler ) ;
728
729 OSStatus result = eventNotHandledErr ;
730 switch ( GetEventClass( event ) )
731 {
732#ifndef __LP64__
733 case kEventClassCommand :
734 result = wxMacAppCommandEventHandler( handler , event , data ) ;
735 break ;
736#endif
737 case kEventClassApplication :
738 result = wxMacAppApplicationEventHandler( handler , event , data ) ;
739 break ;
740#ifndef __LP64__
741 case kEventClassMenu :
742 result = wxMacAppMenuEventHandler( handler , event , data ) ;
743 break ;
744
745 case kEventClassMouse :
746 {
747 wxMacCarbonEvent cEvent( event ) ;
748
749 WindowRef window ;
750 Point screenMouseLocation = cEvent.GetParameter<Point>(kEventParamMouseLocation) ;
751 ::FindWindow(screenMouseLocation, &window);
752 // only send this event in case it had not already been sent to a tlw, as we get
753 // double events otherwise (in case event.skip) was called
754 if ( window == NULL )
755 result = wxMacTopLevelMouseEventHandler( handler , event , NULL ) ;
756 }
757 break ;
758#endif
759 case kEventClassAppleEvent :
4f134f0c 760 result = AEProcessEvent(event);
489468fe
SC
761 break ;
762
763 default :
764 break ;
765 }
766
767 wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ;
768
769 return result ;
770}
771
772DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacAppEventHandler )
b2680ced 773#endif
489468fe 774
4b6a582b 775#if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
489468fe
SC
776
777pascal static void
778wxMacAssertOutputHandler(OSType WXUNUSED(componentSignature),
779 UInt32 WXUNUSED(options),
780 const char *assertionString,
781 const char *exceptionLabelString,
782 const char *errorString,
783 const char *fileName,
784 long lineNumber,
785 void *value,
786 ConstStr255Param WXUNUSED(outputMsg))
787{
788 // flow into assert handling
789 wxString fileNameStr ;
790 wxString assertionStr ;
791 wxString exceptionStr ;
792 wxString errorStr ;
793
794#if wxUSE_UNICODE
795 fileNameStr = wxString(fileName, wxConvLocal);
796 assertionStr = wxString(assertionString, wxConvLocal);
797 exceptionStr = wxString((exceptionLabelString!=0) ? exceptionLabelString : "", wxConvLocal) ;
798 errorStr = wxString((errorString!=0) ? errorString : "", wxConvLocal) ;
799#else
800 fileNameStr = fileName;
801 assertionStr = assertionString;
802 exceptionStr = (exceptionLabelString!=0) ? exceptionLabelString : "" ;
803 errorStr = (errorString!=0) ? errorString : "" ;
804#endif
805
806#if 1
807 // flow into log
808 wxLogDebug( wxT("AssertMacros: %s %s %s file: %s, line: %ld (value %p)\n"),
809 assertionStr.c_str() ,
810 exceptionStr.c_str() ,
811 errorStr.c_str(),
812 fileNameStr.c_str(), lineNumber ,
813 value ) ;
814#else
815
816 wxOnAssert(fileNameStr, lineNumber , assertionStr ,
817 wxString::Format( wxT("%s %s value (%p)") , exceptionStr, errorStr , value ) ) ;
818#endif
819}
820
4b6a582b 821#endif // wxDEBUG_LEVEL
489468fe 822
489468fe
SC
823bool wxApp::Initialize(int& argc, wxChar **argv)
824{
825 // Mac-specific
826
4b6a582b 827#if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
489468fe
SC
828 InstallDebugAssertOutputHandler( NewDebugAssertOutputHandlerUPP( wxMacAssertOutputHandler ) );
829#endif
830
489468fe
SC
831 // Mac OS X passes a process serial number command line argument when
832 // the application is launched from the Finder. This argument must be
833 // removed from the command line arguments before being handled by the
834 // application (otherwise applications would need to handle it)
835 if ( argc > 1 )
836 {
9a83f860 837 static const wxChar *ARG_PSN = wxT("-psn_");
489468fe
SC
838 if ( wxStrncmp(argv[1], ARG_PSN, wxStrlen(ARG_PSN)) == 0 )
839 {
840 // remove this argument
841 --argc;
815acb8e 842 memmove(argv + 1, argv + 2, argc * sizeof(wxChar*));
489468fe
SC
843 }
844 }
845
46447d1a
SC
846 /*
847 Cocoa supports -Key value options which set the user defaults key "Key"
848 to the value "value" Some of them are very handy for debugging like
849 -NSShowAllViews YES. Cocoa picks these up from the real argv so
850 our removal of them from the wx copy of it does not affect Cocoa's
851 ability to see them.
852
853 We basically just assume that any "-NS" option and its following
854 argument needs to be removed from argv. We hope that user code does
855 not expect to see -NS options and indeed it's probably a safe bet
856 since most user code accepting options is probably using the
857 double-dash GNU-style syntax.
858 */
859 for(int i=1; i < argc; ++i)
860 {
861 static const wxChar *ARG_NS = wxT("-NS");
862 if( wxStrncmp(argv[i], ARG_NS, wxStrlen(ARG_NS)) == 0 )
863 {
864 // Only eat this option if it has an argument
865 if( (i + 1) < argc )
866 {
815acb8e 867 memmove(argv + i, argv + i + 2, (argc-i-1)*sizeof(wxChar*));
46447d1a 868 argc -= 2;
46447d1a
SC
869 // drop back one position so the next run through the loop
870 // reprocesses the argument at our current index.
871 --i;
872 }
873 }
874 }
875
489468fe
SC
876 if ( !wxAppBase::Initialize(argc, argv) )
877 return false;
878
879#if wxUSE_INTL
880 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
881#endif
882
883 // these might be the startup dirs, set them to the 'usual' dir containing the app bundle
884 wxString startupCwd = wxGetCwd() ;
885 if ( startupCwd == wxT("/") || startupCwd.Right(15) == wxT("/Contents/MacOS") )
886 {
887 CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle() ) ;
888 CFURLRef urlParent = CFURLCreateCopyDeletingLastPathComponent( kCFAllocatorDefault , url ) ;
889 CFRelease( url ) ;
890 CFStringRef path = CFURLCopyFileSystemPath ( urlParent , kCFURLPOSIXPathStyle ) ;
891 CFRelease( urlParent ) ;
892 wxString cwd = wxCFStringRef(path).AsString(wxLocale::GetSystemEncoding());
893 wxSetWorkingDirectory( cwd ) ;
894 }
895
489468fe
SC
896 return true;
897}
898
88695e9a 899#if wxOSX_USE_COCOA_OR_CARBON
524c47aa
SC
900bool wxApp::CallOnInit()
901{
902 wxMacAutoreleasePool autoreleasepool;
903 return OnInit();
904}
cf4ce62c 905#endif
524c47aa 906
489468fe
SC
907bool wxApp::OnInitGui()
908{
909 if ( !wxAppBase::OnInitGui() )
910 return false ;
524c47aa
SC
911
912 if ( !DoInitGui() )
913 return false;
914
915 return true ;
916}
917
918bool wxApp::ProcessIdle()
919{
920 wxMacAutoreleasePool autoreleasepool;
921 return wxAppBase::ProcessIdle();
922}
923
ada17583
SC
924int wxApp::OnRun()
925{
926 wxMacAutoreleasePool pool;
927 return wxAppBase::OnRun();
928}
929
b2680ced 930#if wxOSX_USE_CARBON
524c47aa
SC
931bool wxApp::DoInitGui()
932{
489468fe
SC
933 InstallStandardEventHandler( GetApplicationEventTarget() ) ;
934 if (!sm_isEmbedded)
935 {
936 InstallApplicationEventHandler(
937 GetwxMacAppEventHandlerUPP(),
938 GetEventTypeCount(eventList), eventList, wxTheApp, (EventHandlerRef *)&(wxTheApp->m_macEventHandler));
939 }
489468fe
SC
940
941 if (!sm_isEmbedded)
942 {
943 sODocHandler = NewAEEventHandlerUPP(AEHandleODoc) ;
944 sGURLHandler = NewAEEventHandlerUPP(AEHandleGURL) ;
945 sOAppHandler = NewAEEventHandlerUPP(AEHandleOApp) ;
946 sPDocHandler = NewAEEventHandlerUPP(AEHandlePDoc) ;
947 sRAppHandler = NewAEEventHandlerUPP(AEHandleRApp) ;
948 sQuitHandler = NewAEEventHandlerUPP(AEHandleQuit) ;
949
950 AEInstallEventHandler( kCoreEventClass , kAEOpenDocuments ,
951 sODocHandler , 0 , FALSE ) ;
952 AEInstallEventHandler( kInternetEventClass, kAEGetURL,
953 sGURLHandler , 0 , FALSE ) ;
954 AEInstallEventHandler( kCoreEventClass , kAEOpenApplication ,
955 sOAppHandler , 0 , FALSE ) ;
956 AEInstallEventHandler( kCoreEventClass , kAEPrintDocuments ,
957 sPDocHandler , 0 , FALSE ) ;
958 AEInstallEventHandler( kCoreEventClass , kAEReopenApplication ,
959 sRAppHandler , 0 , FALSE ) ;
960 AEInstallEventHandler( kCoreEventClass , kAEQuitApplication ,
961 sQuitHandler , 0 , FALSE ) ;
962 }
524c47aa 963
489468fe
SC
964 if ( !wxMacInitCocoa() )
965 return false;
d181e877 966
524c47aa 967 return true;
489468fe
SC
968}
969
524c47aa 970void wxApp::DoCleanUp()
489468fe 971{
489468fe
SC
972 if (!sm_isEmbedded)
973 RemoveEventHandler( (EventHandlerRef)(wxTheApp->m_macEventHandler) );
974
975 if (!sm_isEmbedded)
976 {
977 AERemoveEventHandler( kCoreEventClass , kAEOpenDocuments ,
978 sODocHandler , FALSE ) ;
979 AERemoveEventHandler( kInternetEventClass, kAEGetURL,
980 sGURLHandler , FALSE ) ;
981 AERemoveEventHandler( kCoreEventClass , kAEOpenApplication ,
982 sOAppHandler , FALSE ) ;
983 AERemoveEventHandler( kCoreEventClass , kAEPrintDocuments ,
984 sPDocHandler , FALSE ) ;
985 AERemoveEventHandler( kCoreEventClass , kAEReopenApplication ,
986 sRAppHandler , FALSE ) ;
987 AERemoveEventHandler( kCoreEventClass , kAEQuitApplication ,
988 sQuitHandler , FALSE ) ;
989
990 DisposeAEEventHandlerUPP( sODocHandler ) ;
991 DisposeAEEventHandlerUPP( sGURLHandler ) ;
992 DisposeAEEventHandlerUPP( sOAppHandler ) ;
993 DisposeAEEventHandlerUPP( sPDocHandler ) ;
994 DisposeAEEventHandlerUPP( sRAppHandler ) ;
995 DisposeAEEventHandlerUPP( sQuitHandler ) ;
996 }
524c47aa 997}
489468fe 998
b2680ced
SC
999#endif
1000
524c47aa
SC
1001void wxApp::CleanUp()
1002{
ada17583 1003 wxMacAutoreleasePool autoreleasepool;
524c47aa
SC
1004#if wxUSE_TOOLTIPS
1005 wxToolTip::RemoveToolTips() ;
1006#endif
1007
524c47aa
SC
1008 DoCleanUp();
1009
489468fe
SC
1010 wxAppBase::CleanUp();
1011}
1012
1013//----------------------------------------------------------------------
1014// misc initialization stuff
1015//----------------------------------------------------------------------
1016
489468fe
SC
1017wxApp::wxApp()
1018{
1019 m_printMode = wxPRINT_WINDOWS;
1020
1021 m_macCurrentEvent = NULL ;
1022 m_macCurrentEventHandlerCallRef = NULL ;
32e806fe
KO
1023 m_macPool = new wxMacAutoreleasePool();
1024}
1025
1026wxApp::~wxApp()
1027{
1028 if (m_macPool)
1029 delete m_macPool;
489468fe
SC
1030}
1031
524c47aa
SC
1032CFMutableArrayRef GetAutoReleaseArray()
1033{
1034 static CFMutableArrayRef array = 0;
1035 if ( array == 0)
1036 array= CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
1037 return array;
1038}
1039
1040void wxApp::MacAddToAutorelease( void* cfrefobj )
1041{
1042 CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj );
1043}
1044
32e806fe
KO
1045void wxApp::MacReleaseAutoreleasePool()
1046{
1047 if (m_macPool)
1048 delete m_macPool;
1049 m_macPool = new wxMacAutoreleasePool();
1050}
1051
489468fe
SC
1052void wxApp::OnIdle(wxIdleEvent& WXUNUSED(event))
1053{
1054 // If they are pending events, we must process them: pending events are
1055 // either events to the threads other than main or events posted with
1056 // wxPostEvent() functions
1057#ifndef __WXUNIVERSAL__
a2dd520d 1058#if wxUSE_MENUS
489468fe
SC
1059 if (!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar())
1060 wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar();
1061#endif
524c47aa
SC
1062#endif
1063 CFArrayRemoveAllValues( GetAutoReleaseArray() );
489468fe
SC
1064}
1065
1066void wxApp::WakeUpIdle()
1067{
cc96f525 1068 wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
489468fe 1069
cc96f525
SC
1070 if ( loop )
1071 loop->WakeUp();
489468fe
SC
1072}
1073
1074void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
1075{
1076 if (GetTopWindow())
1077 GetTopWindow()->Close(true);
1078}
1079
1080// Default behaviour: close the application with prompts. The
1081// user can veto the close, and therefore the end session.
1082void wxApp::OnQueryEndSession(wxCloseEvent& event)
1083{
2680ddc6
SC
1084 if ( !wxDialog::OSXHasModalDialogsOpen() )
1085 {
1086 if (GetTopWindow())
1087 {
1088 if (!GetTopWindow()->Close(!event.CanVeto()))
1089 event.Veto(true);
1090 }
1091 }
1092 else
489468fe 1093 {
2680ddc6 1094 event.Veto(true);
489468fe
SC
1095 }
1096}
1097
1098extern "C" void wxCYield() ;
1099void wxCYield()
1100{
1101 wxYield() ;
1102}
1103
489468fe
SC
1104// virtual
1105void wxApp::MacHandleUnhandledEvent( WXEVENTREF WXUNUSED(evr) )
1106{
1107 // Override to process unhandled events as you please
1108}
1109
c1313b54
SC
1110#if wxOSX_USE_COCOA_OR_CARBON
1111
c1313b54
SC
1112CGKeyCode wxCharCodeWXToOSX(wxKeyCode code)
1113{
1114 CGKeyCode keycode;
1115
1116 switch (code)
1117 {
11716cbe
VZ
1118 // Clang warns about switch values not of the same type as (enumerated)
1119 // switch controlling expression. This is generally useful but here we
1120 // really want to be able to use letters and digits without making them
1121 // part of wxKeyCode enum.
1122#ifdef __clang__
1123 #pragma clang diagnostic push
1124 #pragma clang diagnostic ignored "-Wswitch"
1125#endif // __clang__
1126
c1313b54
SC
1127 case 'a': case 'A': keycode = kVK_ANSI_A; break;
1128 case 'b': case 'B': keycode = kVK_ANSI_B; break;
1129 case 'c': case 'C': keycode = kVK_ANSI_C; break;
1130 case 'd': case 'D': keycode = kVK_ANSI_D; break;
1131 case 'e': case 'E': keycode = kVK_ANSI_E; break;
1132 case 'f': case 'F': keycode = kVK_ANSI_F; break;
1133 case 'g': case 'G': keycode = kVK_ANSI_G; break;
1134 case 'h': case 'H': keycode = kVK_ANSI_H; break;
1135 case 'i': case 'I': keycode = kVK_ANSI_I; break;
1136 case 'j': case 'J': keycode = kVK_ANSI_J; break;
1137 case 'k': case 'K': keycode = kVK_ANSI_K; break;
1138 case 'l': case 'L': keycode = kVK_ANSI_L; break;
1139 case 'm': case 'M': keycode = kVK_ANSI_M; break;
1140 case 'n': case 'N': keycode = kVK_ANSI_N; break;
1141 case 'o': case 'O': keycode = kVK_ANSI_O; break;
1142 case 'p': case 'P': keycode = kVK_ANSI_P; break;
1143 case 'q': case 'Q': keycode = kVK_ANSI_Q; break;
1144 case 'r': case 'R': keycode = kVK_ANSI_R; break;
1145 case 's': case 'S': keycode = kVK_ANSI_S; break;
1146 case 't': case 'T': keycode = kVK_ANSI_T; break;
1147 case 'u': case 'U': keycode = kVK_ANSI_U; break;
1148 case 'v': case 'V': keycode = kVK_ANSI_V; break;
1149 case 'w': case 'W': keycode = kVK_ANSI_W; break;
1150 case 'x': case 'X': keycode = kVK_ANSI_X; break;
1151 case 'y': case 'Y': keycode = kVK_ANSI_Y; break;
1152 case 'z': case 'Z': keycode = kVK_ANSI_Z; break;
1153
1154 case '0': keycode = kVK_ANSI_0; break;
1155 case '1': keycode = kVK_ANSI_1; break;
1156 case '2': keycode = kVK_ANSI_2; break;
1157 case '3': keycode = kVK_ANSI_3; break;
1158 case '4': keycode = kVK_ANSI_4; break;
1159 case '5': keycode = kVK_ANSI_5; break;
1160 case '6': keycode = kVK_ANSI_6; break;
1161 case '7': keycode = kVK_ANSI_7; break;
1162 case '8': keycode = kVK_ANSI_8; break;
1163 case '9': keycode = kVK_ANSI_9; break;
11716cbe
VZ
1164
1165#ifdef __clang__
1166 #pragma clang diagnostic pop
1167#endif // __clang__
c1313b54
SC
1168
1169 case WXK_BACK: keycode = kVK_Delete; break;
1170 case WXK_TAB: keycode = kVK_Tab; break;
1171 case WXK_RETURN: keycode = kVK_Return; break;
1172 case WXK_ESCAPE: keycode = kVK_Escape; break;
1173 case WXK_SPACE: keycode = kVK_Space; break;
7422ea95 1174 case WXK_DELETE: keycode = kVK_ForwardDelete; break;
c1313b54
SC
1175
1176 case WXK_SHIFT: keycode = kVK_Shift; break;
1177 case WXK_ALT: keycode = kVK_Option; break;
4983b80d
SC
1178 case WXK_RAW_CONTROL: keycode = kVK_Control; break;
1179 case WXK_CONTROL: keycode = kVK_Command; break;
c1313b54
SC
1180
1181 case WXK_CAPITAL: keycode = kVK_CapsLock; break;
1182 case WXK_END: keycode = kVK_End; break;
1183 case WXK_HOME: keycode = kVK_Home; break;
1184 case WXK_LEFT: keycode = kVK_LeftArrow; break;
1185 case WXK_UP: keycode = kVK_UpArrow; break;
1186 case WXK_RIGHT: keycode = kVK_RightArrow; break;
1187 case WXK_DOWN: keycode = kVK_DownArrow; break;
1188
1189 case WXK_HELP: keycode = kVK_Help; break;
1190
1191
1192 case WXK_NUMPAD0: keycode = kVK_ANSI_Keypad0; break;
1193 case WXK_NUMPAD1: keycode = kVK_ANSI_Keypad1; break;
1194 case WXK_NUMPAD2: keycode = kVK_ANSI_Keypad2; break;
1195 case WXK_NUMPAD3: keycode = kVK_ANSI_Keypad3; break;
1196 case WXK_NUMPAD4: keycode = kVK_ANSI_Keypad4; break;
1197 case WXK_NUMPAD5: keycode = kVK_ANSI_Keypad5; break;
1198 case WXK_NUMPAD6: keycode = kVK_ANSI_Keypad6; break;
1199 case WXK_NUMPAD7: keycode = kVK_ANSI_Keypad7; break;
1200 case WXK_NUMPAD8: keycode = kVK_ANSI_Keypad8; break;
1201 case WXK_NUMPAD9: keycode = kVK_ANSI_Keypad9; break;
1202 case WXK_F1: keycode = kVK_F1; break;
1203 case WXK_F2: keycode = kVK_F2; break;
1204 case WXK_F3: keycode = kVK_F3; break;
1205 case WXK_F4: keycode = kVK_F4; break;
1206 case WXK_F5: keycode = kVK_F5; break;
1207 case WXK_F6: keycode = kVK_F6; break;
1208 case WXK_F7: keycode = kVK_F7; break;
1209 case WXK_F8: keycode = kVK_F8; break;
1210 case WXK_F9: keycode = kVK_F9; break;
1211 case WXK_F10: keycode = kVK_F10; break;
1212 case WXK_F11: keycode = kVK_F11; break;
1213 case WXK_F12: keycode = kVK_F12; break;
1214 case WXK_F13: keycode = kVK_F13; break;
1215 case WXK_F14: keycode = kVK_F14; break;
1216 case WXK_F15: keycode = kVK_F15; break;
1217 case WXK_F16: keycode = kVK_F16; break;
1218 case WXK_F17: keycode = kVK_F17; break;
1219 case WXK_F18: keycode = kVK_F18; break;
1220 case WXK_F19: keycode = kVK_F19; break;
1221 case WXK_F20: keycode = kVK_F20; break;
1222
1223 case WXK_PAGEUP: keycode = kVK_PageUp; break;
1224 case WXK_PAGEDOWN: keycode = kVK_PageDown; break;
1225
1226 case WXK_NUMPAD_DELETE: keycode = kVK_ANSI_KeypadClear; break;
1227 case WXK_NUMPAD_EQUAL: keycode = kVK_ANSI_KeypadEquals; break;
1228 case WXK_NUMPAD_MULTIPLY: keycode = kVK_ANSI_KeypadMultiply; break;
1229 case WXK_NUMPAD_ADD: keycode = kVK_ANSI_KeypadPlus; break;
1230 case WXK_NUMPAD_SUBTRACT: keycode = kVK_ANSI_KeypadMinus; break;
1231 case WXK_NUMPAD_DECIMAL: keycode = kVK_ANSI_KeypadDecimal; break;
1232 case WXK_NUMPAD_DIVIDE: keycode = kVK_ANSI_KeypadDivide; break;
1233
1234 default:
1235 wxLogDebug( "Unrecognised keycode %d", code );
1236 keycode = static_cast<CGKeyCode>(-1);
1237 }
1238
1239 return keycode;
1240}
b2680ced 1241
489468fe
SC
1242long wxMacTranslateKey(unsigned char key, unsigned char code)
1243{
1244 long retval = key ;
1245 switch (key)
1246 {
1247 case kHomeCharCode :
1248 retval = WXK_HOME;
1249 break;
1250
1251 case kEnterCharCode :
1252 retval = WXK_RETURN;
1253 break;
1254 case kEndCharCode :
1255 retval = WXK_END;
1256 break;
1257
1258 case kHelpCharCode :
1259 retval = WXK_HELP;
1260 break;
1261
1262 case kBackspaceCharCode :
1263 retval = WXK_BACK;
1264 break;
1265
1266 case kTabCharCode :
1267 retval = WXK_TAB;
1268 break;
1269
1270 case kPageUpCharCode :
1271 retval = WXK_PAGEUP;
1272 break;
1273
1274 case kPageDownCharCode :
1275 retval = WXK_PAGEDOWN;
1276 break;
1277
1278 case kReturnCharCode :
1279 retval = WXK_RETURN;
1280 break;
1281
1282 case kFunctionKeyCharCode :
1283 {
1284 switch ( code )
1285 {
1286 case 0x7a :
1287 retval = WXK_F1 ;
1288 break;
1289
1290 case 0x78 :
1291 retval = WXK_F2 ;
1292 break;
1293
1294 case 0x63 :
1295 retval = WXK_F3 ;
1296 break;
1297
1298 case 0x76 :
1299 retval = WXK_F4 ;
1300 break;
1301
1302 case 0x60 :
1303 retval = WXK_F5 ;
1304 break;
1305
1306 case 0x61 :
1307 retval = WXK_F6 ;
1308 break;
1309
1310 case 0x62:
1311 retval = WXK_F7 ;
1312 break;
1313
1314 case 0x64 :
1315 retval = WXK_F8 ;
1316 break;
1317
1318 case 0x65 :
1319 retval = WXK_F9 ;
1320 break;
1321
1322 case 0x6D :
1323 retval = WXK_F10 ;
1324 break;
1325
1326 case 0x67 :
1327 retval = WXK_F11 ;
1328 break;
1329
1330 case 0x6F :
1331 retval = WXK_F12 ;
1332 break;
1333
1334 case 0x69 :
1335 retval = WXK_F13 ;
1336 break;
1337
1338 case 0x6B :
1339 retval = WXK_F14 ;
1340 break;
1341
1342 case 0x71 :
1343 retval = WXK_F15 ;
1344 break;
1345
1346 default:
1347 break;
1348 }
1349 }
1350 break ;
1351
1352 case kEscapeCharCode :
1353 retval = WXK_ESCAPE ;
1354 break ;
1355
1356 case kLeftArrowCharCode :
1357 retval = WXK_LEFT ;
1358 break ;
1359
1360 case kRightArrowCharCode :
1361 retval = WXK_RIGHT ;
1362 break ;
1363
1364 case kUpArrowCharCode :
1365 retval = WXK_UP ;
1366 break ;
1367
1368 case kDownArrowCharCode :
1369 retval = WXK_DOWN ;
1370 break ;
1371
1372 case kDeleteCharCode :
1373 retval = WXK_DELETE ;
1374 break ;
1375
1376 default:
1377 break ;
1378 } // end switch
1379
1380 return retval;
1381}
1382
1383int wxMacKeyCodeToModifier(wxKeyCode key)
1384{
1385 switch (key)
1386 {
1387 case WXK_START:
1388 case WXK_MENU:
4983b80d 1389 case WXK_COMMAND:
489468fe
SC
1390 return cmdKey;
1391
1392 case WXK_SHIFT:
1393 return shiftKey;
1394
1395 case WXK_CAPITAL:
1396 return alphaLock;
1397
1398 case WXK_ALT:
1399 return optionKey;
1400
4983b80d 1401 case WXK_RAW_CONTROL:
489468fe
SC
1402 return controlKey;
1403
1404 default:
1405 return 0;
1406 }
1407}
b2680ced 1408#endif
489468fe 1409
36b96006
SC
1410#if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
1411
1412// defined in utils.mm
1413
1414#elif wxOSX_USE_COCOA_OR_CARBON
f3769d53 1415
489468fe
SC
1416wxMouseState wxGetMouseState()
1417{
1418 wxMouseState ms;
1419
1420 wxPoint pt = wxGetMousePosition();
1421 ms.SetX(pt.x);
1422 ms.SetY(pt.y);
1423
1424 UInt32 buttons = GetCurrentButtonState();
1425 ms.SetLeftDown( (buttons & 0x01) != 0 );
1426 ms.SetMiddleDown( (buttons & 0x04) != 0 );
1427 ms.SetRightDown( (buttons & 0x02) != 0 );
1428
1429 UInt32 modifiers = GetCurrentKeyModifiers();
dd9ec596 1430 ms.SetRawControlDown(modifiers & controlKey);
489468fe
SC
1431 ms.SetShiftDown(modifiers & shiftKey);
1432 ms.SetAltDown(modifiers & optionKey);
dd9ec596 1433 ms.SetControlDown(modifiers & cmdKey);
f3769d53 1434
489468fe
SC
1435 return ms;
1436}
1437
f3769d53
SC
1438#endif
1439
489468fe
SC
1440// TODO : once the new key/char handling is tested, move all the code to wxWindow
1441
2f7baaec 1442bool wxApp::MacSendKeyDownEvent( wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
489468fe
SC
1443{
1444 if ( !focus )
1445 return false ;
1446
489468fe 1447 wxKeyEvent event(wxEVT_KEY_DOWN) ;
2f7baaec 1448 MacCreateKeyEvent( event, focus , keymessage , modifiers , when , uniChar ) ;
489468fe 1449
4eb5a0ec 1450 return focus->OSXHandleKeyEvent(event);
489468fe
SC
1451}
1452
2f7baaec 1453bool wxApp::MacSendKeyUpEvent( wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
489468fe
SC
1454{
1455 if ( !focus )
1456 return false ;
1457
489468fe 1458 wxKeyEvent event( wxEVT_KEY_UP ) ;
2f7baaec 1459 MacCreateKeyEvent( event, focus , keymessage , modifiers , when , uniChar ) ;
489468fe 1460
4eb5a0ec 1461 return focus->OSXHandleKeyEvent(event) ;
489468fe
SC
1462}
1463
2f7baaec 1464bool wxApp::MacSendCharEvent( wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
489468fe
SC
1465{
1466 if ( !focus )
1467 return false ;
489468fe 1468 wxKeyEvent event(wxEVT_CHAR) ;
2f7baaec 1469 MacCreateKeyEvent( event, focus , keymessage , modifiers , when , uniChar ) ;
489468fe
SC
1470
1471 bool handled = false ;
1472
b2680ced 1473#if wxOSX_USE_CARBON
2c2fafe9 1474 long keyval = event.m_keyCode ;
489468fe 1475
489468fe 1476 {
3a95f73c
VZ
1477 wxKeyEvent eventCharHook(wxEVT_CHAR_HOOK, event);
1478 handled = focus->HandleWindowEvent( eventCharHook );
4cf1a9bf 1479 if ( handled && eventCharHook.IsNextEventAllowed() )
489468fe
SC
1480 handled = false ;
1481 }
1482
1483 if ( !handled )
1484 {
489468fe
SC
1485 handled = focus->HandleWindowEvent( event ) ;
1486 }
1487
1488 if ( !handled && (keyval == WXK_TAB) )
1489 {
1490 wxWindow* iter = focus->GetParent() ;
1491 while ( iter && !handled )
1492 {
1493 if ( iter->HasFlag( wxTAB_TRAVERSAL ) )
1494 {
1495 wxNavigationKeyEvent new_event;
1496 new_event.SetEventObject( focus );
1497 new_event.SetDirection( !event.ShiftDown() );
1498 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1499 new_event.SetWindowChange( event.ControlDown() );
1500 new_event.SetCurrentFocus( focus );
1501 handled = focus->GetParent()->HandleWindowEvent( new_event );
1502 if ( handled && new_event.GetSkipped() )
1503 handled = false ;
1504 }
1505
1506 iter = iter->GetParent() ;
1507 }
1508 }
1509
1510 // backdoor handler for default return and command escape
b2680ced 1511 if ( !handled && (!focus->IsKindOf(CLASSINFO(wxControl) ) || !focus->AcceptsFocus() ) )
489468fe
SC
1512 {
1513 // if window is not having a focus still testing for default enter or cancel
1514 // TODO: add the UMA version for ActiveNonFloatingWindow
1515#ifndef __LP64__
b2680ced 1516 wxWindow* focus = wxNonOwnedWindow::GetFromWXWindow( (WXWindow) FrontWindow() ) ;
489468fe
SC
1517 if ( focus )
1518 {
1519 if ( keyval == WXK_RETURN || keyval == WXK_NUMPAD_ENTER )
1520 {
1521 wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(focus), wxTopLevelWindow);
1522 if ( tlw && tlw->GetDefaultItem() )
1523 {
1524 wxButton *def = wxDynamicCast(tlw->GetDefaultItem(), wxButton);
1525 if ( def && def->IsEnabled() )
1526 {
ce7fe42e 1527 wxCommandEvent event(wxEVT_BUTTON, def->GetId() );
489468fe
SC
1528 event.SetEventObject(def);
1529 def->Command(event);
1530
1531 return true ;
1532 }
1533 }
1534 }
1535 else if (keyval == WXK_ESCAPE || (keyval == '.' && modifiers & cmdKey ) )
1536 {
1537 // generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs)
ce7fe42e 1538 wxCommandEvent new_event(wxEVT_BUTTON,wxID_CANCEL);
489468fe
SC
1539 new_event.SetEventObject( focus );
1540 handled = focus->HandleWindowEvent( new_event );
1541 }
1542 }
1543#endif
1544 }
b2680ced 1545#endif
489468fe
SC
1546 return handled ;
1547}
1548
1549// This method handles common code for SendKeyDown, SendKeyUp, and SendChar events.
2f7baaec 1550void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
489468fe 1551{
c1313b54
SC
1552#if wxOSX_USE_COCOA_OR_CARBON
1553
489468fe
SC
1554 short keycode, keychar ;
1555
1556 keychar = short(keymessage & charCodeMask);
1557 keycode = short(keymessage & keyCodeMask) >> 8 ;
1558 if ( !(event.GetEventType() == wxEVT_CHAR) && (modifiers & (controlKey | shiftKey | optionKey) ) )
1559 {
1560 // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
1561 // and look at the character after
1562#ifdef __LP64__
03647350 1563 // TODO new implementation using TextInputSources
489468fe
SC
1564#else
1565 UInt32 state = 0;
1566 UInt32 keyInfo = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache), ( modifiers & (~(controlKey | shiftKey | optionKey))) | keycode, &state);
1567 keychar = short(keyInfo & charCodeMask);
1568#endif
1569 }
1570
1571 long keyval = wxMacTranslateKey(keychar, keycode) ;
1572 if ( keyval == keychar && ( event.GetEventType() == wxEVT_KEY_UP || event.GetEventType() == wxEVT_KEY_DOWN ) )
1573 keyval = wxToupper( keyval ) ;
1574
1575 // Check for NUMPAD keys. For KEY_UP/DOWN events we need to use the
1576 // WXK_NUMPAD constants, but for the CHAR event we want to use the
1577 // standard ascii values
1578 if ( event.GetEventType() != wxEVT_CHAR )
1579 {
1580 if (keyval >= '0' && keyval <= '9' && keycode >= 82 && keycode <= 92)
1581 {
1582 keyval = (keyval - '0') + WXK_NUMPAD0;
1583 }
d181e877 1584 else if (keycode >= 65 && keycode <= 81)
489468fe
SC
1585 {
1586 switch (keycode)
1587 {
1588 case 76 :
1589 keyval = WXK_NUMPAD_ENTER;
1590 break;
d181e877 1591
489468fe
SC
1592 case 81:
1593 keyval = WXK_NUMPAD_EQUAL;
1594 break;
d181e877 1595
489468fe
SC
1596 case 67:
1597 keyval = WXK_NUMPAD_MULTIPLY;
1598 break;
d181e877 1599
489468fe
SC
1600 case 75:
1601 keyval = WXK_NUMPAD_DIVIDE;
1602 break;
d181e877 1603
489468fe
SC
1604 case 78:
1605 keyval = WXK_NUMPAD_SUBTRACT;
1606 break;
d181e877 1607
489468fe
SC
1608 case 69:
1609 keyval = WXK_NUMPAD_ADD;
1610 break;
d181e877 1611
489468fe
SC
1612 case 65:
1613 keyval = WXK_NUMPAD_DECIMAL;
1614 break;
1615 default:
1616 break;
1617 }
1618 }
1619 }
d181e877 1620
489468fe 1621 event.m_shiftDown = modifiers & shiftKey;
dd9ec596 1622 event.m_rawControlDown = modifiers & controlKey;
489468fe 1623 event.m_altDown = modifiers & optionKey;
dd9ec596 1624 event.m_controlDown = modifiers & cmdKey;
489468fe
SC
1625 event.m_keyCode = keyval ;
1626#if wxUSE_UNICODE
1627 event.m_uniChar = uniChar ;
1628#endif
1629
1630 event.m_rawCode = keymessage;
1631 event.m_rawFlags = modifiers;
489468fe
SC
1632 event.SetTimestamp(when);
1633 event.SetEventObject(focus);
de0d2095
SC
1634#else
1635 wxUnusedVar(event);
1636 wxUnusedVar(focus);
1637 wxUnusedVar(keymessage);
1638 wxUnusedVar(modifiers);
1639 wxUnusedVar(when);
de0d2095 1640 wxUnusedVar(uniChar);
b2680ced 1641#endif
489468fe
SC
1642}
1643
1644
1645void wxApp::MacHideApp()
1646{
b2680ced 1647#if wxOSX_USE_CARBON
489468fe
SC
1648 wxMacCarbonEvent event( kEventClassCommand , kEventCommandProcess );
1649 HICommand command;
1650 memset( &command, 0 , sizeof(command) );
1651 command.commandID = kHICommandHide ;
d181e877 1652 event.SetParameter<HICommand>(kEventParamDirectObject, command );
489468fe 1653 SendEventToApplication( event );
b2680ced 1654#endif
489468fe 1655}