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