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