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