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