wxMessageBox off the main thread lost result code.
[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 /*
823 Cocoa supports -Key value options which set the user defaults key "Key"
824 to the value "value" Some of them are very handy for debugging like
825 -NSShowAllViews YES. Cocoa picks these up from the real argv so
826 our removal of them from the wx copy of it does not affect Cocoa's
827 ability to see them.
828
829 We basically just assume that any "-NS" option and its following
830 argument needs to be removed from argv. We hope that user code does
831 not expect to see -NS options and indeed it's probably a safe bet
832 since most user code accepting options is probably using the
833 double-dash GNU-style syntax.
834 */
835 for(int i=1; i < argc; ++i)
836 {
837 static const wxChar *ARG_NS = wxT("-NS");
838 if( wxStrncmp(argv[i], ARG_NS, wxStrlen(ARG_NS)) == 0 )
839 {
840 // Only eat this option if it has an argument
841 if( (i + 1) < argc )
842 {
843 memmove(argv + i, argv + i + 2, (argc-i-1)*sizeof(wxChar*));
844 argc -= 2;
845 // drop back one position so the next run through the loop
846 // reprocesses the argument at our current index.
847 --i;
848 }
849 }
850 }
851
852 if ( !wxAppBase::Initialize(argc, argv) )
853 return false;
854
855 #if wxUSE_INTL
856 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
857 #endif
858
859 // these might be the startup dirs, set them to the 'usual' dir containing the app bundle
860 wxString startupCwd = wxGetCwd() ;
861 if ( startupCwd == wxT("/") || startupCwd.Right(15) == wxT("/Contents/MacOS") )
862 {
863 CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle() ) ;
864 CFURLRef urlParent = CFURLCreateCopyDeletingLastPathComponent( kCFAllocatorDefault , url ) ;
865 CFRelease( url ) ;
866 CFStringRef path = CFURLCopyFileSystemPath ( urlParent , kCFURLPOSIXPathStyle ) ;
867 CFRelease( urlParent ) ;
868 wxString cwd = wxCFStringRef(path).AsString(wxLocale::GetSystemEncoding());
869 wxSetWorkingDirectory( cwd ) ;
870 }
871
872 return true;
873 }
874
875 #if wxOSX_USE_CARBON
876 bool wxApp::CallOnInit()
877 {
878 wxMacAutoreleasePool autoreleasepool;
879 return OnInit();
880 }
881 #endif
882
883 bool wxApp::OnInitGui()
884 {
885 if ( !wxAppBase::OnInitGui() )
886 return false ;
887
888 if ( !DoInitGui() )
889 return false;
890
891 return true ;
892 }
893
894 bool wxApp::ProcessIdle()
895 {
896 wxMacAutoreleasePool autoreleasepool;
897 return wxAppBase::ProcessIdle();
898 }
899
900 int wxApp::OnRun()
901 {
902 wxMacAutoreleasePool pool;
903 return wxAppBase::OnRun();
904 }
905
906 #if wxOSX_USE_CARBON
907 bool wxApp::DoInitGui()
908 {
909 InstallStandardEventHandler( GetApplicationEventTarget() ) ;
910 if (!sm_isEmbedded)
911 {
912 InstallApplicationEventHandler(
913 GetwxMacAppEventHandlerUPP(),
914 GetEventTypeCount(eventList), eventList, wxTheApp, (EventHandlerRef *)&(wxTheApp->m_macEventHandler));
915 }
916
917 if (!sm_isEmbedded)
918 {
919 sODocHandler = NewAEEventHandlerUPP(AEHandleODoc) ;
920 sGURLHandler = NewAEEventHandlerUPP(AEHandleGURL) ;
921 sOAppHandler = NewAEEventHandlerUPP(AEHandleOApp) ;
922 sPDocHandler = NewAEEventHandlerUPP(AEHandlePDoc) ;
923 sRAppHandler = NewAEEventHandlerUPP(AEHandleRApp) ;
924 sQuitHandler = NewAEEventHandlerUPP(AEHandleQuit) ;
925
926 AEInstallEventHandler( kCoreEventClass , kAEOpenDocuments ,
927 sODocHandler , 0 , FALSE ) ;
928 AEInstallEventHandler( kInternetEventClass, kAEGetURL,
929 sGURLHandler , 0 , FALSE ) ;
930 AEInstallEventHandler( kCoreEventClass , kAEOpenApplication ,
931 sOAppHandler , 0 , FALSE ) ;
932 AEInstallEventHandler( kCoreEventClass , kAEPrintDocuments ,
933 sPDocHandler , 0 , FALSE ) ;
934 AEInstallEventHandler( kCoreEventClass , kAEReopenApplication ,
935 sRAppHandler , 0 , FALSE ) ;
936 AEInstallEventHandler( kCoreEventClass , kAEQuitApplication ,
937 sQuitHandler , 0 , FALSE ) ;
938 }
939
940 if ( !wxMacInitCocoa() )
941 return false;
942
943 return true;
944 }
945
946 void wxApp::DoCleanUp()
947 {
948 if (!sm_isEmbedded)
949 RemoveEventHandler( (EventHandlerRef)(wxTheApp->m_macEventHandler) );
950
951 if (!sm_isEmbedded)
952 {
953 AERemoveEventHandler( kCoreEventClass , kAEOpenDocuments ,
954 sODocHandler , FALSE ) ;
955 AERemoveEventHandler( kInternetEventClass, kAEGetURL,
956 sGURLHandler , FALSE ) ;
957 AERemoveEventHandler( kCoreEventClass , kAEOpenApplication ,
958 sOAppHandler , FALSE ) ;
959 AERemoveEventHandler( kCoreEventClass , kAEPrintDocuments ,
960 sPDocHandler , FALSE ) ;
961 AERemoveEventHandler( kCoreEventClass , kAEReopenApplication ,
962 sRAppHandler , FALSE ) ;
963 AERemoveEventHandler( kCoreEventClass , kAEQuitApplication ,
964 sQuitHandler , FALSE ) ;
965
966 DisposeAEEventHandlerUPP( sODocHandler ) ;
967 DisposeAEEventHandlerUPP( sGURLHandler ) ;
968 DisposeAEEventHandlerUPP( sOAppHandler ) ;
969 DisposeAEEventHandlerUPP( sPDocHandler ) ;
970 DisposeAEEventHandlerUPP( sRAppHandler ) ;
971 DisposeAEEventHandlerUPP( sQuitHandler ) ;
972 }
973 }
974
975 #endif
976
977 void wxApp::CleanUp()
978 {
979 wxMacAutoreleasePool autoreleasepool;
980 #if wxUSE_TOOLTIPS
981 wxToolTip::RemoveToolTips() ;
982 #endif
983
984 DoCleanUp();
985
986 wxAppBase::CleanUp();
987 }
988
989 //----------------------------------------------------------------------
990 // misc initialization stuff
991 //----------------------------------------------------------------------
992
993 wxApp::wxApp()
994 {
995 m_printMode = wxPRINT_WINDOWS;
996
997 m_macCurrentEvent = NULL ;
998 m_macCurrentEventHandlerCallRef = NULL ;
999 m_macPool = new wxMacAutoreleasePool();
1000 }
1001
1002 wxApp::~wxApp()
1003 {
1004 if (m_macPool)
1005 delete m_macPool;
1006 }
1007
1008 CFMutableArrayRef GetAutoReleaseArray()
1009 {
1010 static CFMutableArrayRef array = 0;
1011 if ( array == 0)
1012 array= CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
1013 return array;
1014 }
1015
1016 void wxApp::MacAddToAutorelease( void* cfrefobj )
1017 {
1018 CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj );
1019 }
1020
1021 void wxApp::MacReleaseAutoreleasePool()
1022 {
1023 if (m_macPool)
1024 delete m_macPool;
1025 m_macPool = new wxMacAutoreleasePool();
1026 }
1027
1028 void wxApp::OnIdle(wxIdleEvent& WXUNUSED(event))
1029 {
1030 // If they are pending events, we must process them: pending events are
1031 // either events to the threads other than main or events posted with
1032 // wxPostEvent() functions
1033 #ifndef __WXUNIVERSAL__
1034 #if wxUSE_MENUS
1035 if (!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar())
1036 wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar();
1037 #endif
1038 #endif
1039 CFArrayRemoveAllValues( GetAutoReleaseArray() );
1040 }
1041
1042 void wxApp::WakeUpIdle()
1043 {
1044 wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
1045
1046 if ( loop )
1047 loop->WakeUp();
1048 }
1049
1050 void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
1051 {
1052 if (GetTopWindow())
1053 GetTopWindow()->Close(true);
1054 }
1055
1056 // Default behaviour: close the application with prompts. The
1057 // user can veto the close, and therefore the end session.
1058 void wxApp::OnQueryEndSession(wxCloseEvent& event)
1059 {
1060 if ( !wxDialog::OSXHasModalDialogsOpen() )
1061 {
1062 if (GetTopWindow())
1063 {
1064 if (!GetTopWindow()->Close(!event.CanVeto()))
1065 event.Veto(true);
1066 }
1067 }
1068 else
1069 {
1070 event.Veto(true);
1071 }
1072 }
1073
1074 extern "C" void wxCYield() ;
1075 void wxCYield()
1076 {
1077 wxYield() ;
1078 }
1079
1080 // virtual
1081 void wxApp::MacHandleUnhandledEvent( WXEVENTREF WXUNUSED(evr) )
1082 {
1083 // Override to process unhandled events as you please
1084 }
1085
1086 #if wxOSX_USE_COCOA_OR_CARBON
1087
1088 CGKeyCode wxCharCodeWXToOSX(wxKeyCode code)
1089 {
1090 CGKeyCode keycode;
1091
1092 switch (code)
1093 {
1094 // Clang warns about switch values not of the same type as (enumerated)
1095 // switch controlling expression. This is generally useful but here we
1096 // really want to be able to use letters and digits without making them
1097 // part of wxKeyCode enum.
1098 #ifdef __clang__
1099 #pragma clang diagnostic push
1100 #pragma clang diagnostic ignored "-Wswitch"
1101 #endif // __clang__
1102
1103 case 'a': case 'A': keycode = kVK_ANSI_A; break;
1104 case 'b': case 'B': keycode = kVK_ANSI_B; break;
1105 case 'c': case 'C': keycode = kVK_ANSI_C; break;
1106 case 'd': case 'D': keycode = kVK_ANSI_D; break;
1107 case 'e': case 'E': keycode = kVK_ANSI_E; break;
1108 case 'f': case 'F': keycode = kVK_ANSI_F; break;
1109 case 'g': case 'G': keycode = kVK_ANSI_G; break;
1110 case 'h': case 'H': keycode = kVK_ANSI_H; break;
1111 case 'i': case 'I': keycode = kVK_ANSI_I; break;
1112 case 'j': case 'J': keycode = kVK_ANSI_J; break;
1113 case 'k': case 'K': keycode = kVK_ANSI_K; break;
1114 case 'l': case 'L': keycode = kVK_ANSI_L; break;
1115 case 'm': case 'M': keycode = kVK_ANSI_M; break;
1116 case 'n': case 'N': keycode = kVK_ANSI_N; break;
1117 case 'o': case 'O': keycode = kVK_ANSI_O; break;
1118 case 'p': case 'P': keycode = kVK_ANSI_P; break;
1119 case 'q': case 'Q': keycode = kVK_ANSI_Q; break;
1120 case 'r': case 'R': keycode = kVK_ANSI_R; break;
1121 case 's': case 'S': keycode = kVK_ANSI_S; break;
1122 case 't': case 'T': keycode = kVK_ANSI_T; break;
1123 case 'u': case 'U': keycode = kVK_ANSI_U; break;
1124 case 'v': case 'V': keycode = kVK_ANSI_V; break;
1125 case 'w': case 'W': keycode = kVK_ANSI_W; break;
1126 case 'x': case 'X': keycode = kVK_ANSI_X; break;
1127 case 'y': case 'Y': keycode = kVK_ANSI_Y; break;
1128 case 'z': case 'Z': keycode = kVK_ANSI_Z; break;
1129
1130 case '0': keycode = kVK_ANSI_0; break;
1131 case '1': keycode = kVK_ANSI_1; break;
1132 case '2': keycode = kVK_ANSI_2; break;
1133 case '3': keycode = kVK_ANSI_3; break;
1134 case '4': keycode = kVK_ANSI_4; break;
1135 case '5': keycode = kVK_ANSI_5; break;
1136 case '6': keycode = kVK_ANSI_6; break;
1137 case '7': keycode = kVK_ANSI_7; break;
1138 case '8': keycode = kVK_ANSI_8; break;
1139 case '9': keycode = kVK_ANSI_9; break;
1140
1141 #ifdef __clang__
1142 #pragma clang diagnostic pop
1143 #endif // __clang__
1144
1145 case WXK_BACK: keycode = kVK_Delete; break;
1146 case WXK_TAB: keycode = kVK_Tab; break;
1147 case WXK_RETURN: keycode = kVK_Return; break;
1148 case WXK_ESCAPE: keycode = kVK_Escape; break;
1149 case WXK_SPACE: keycode = kVK_Space; break;
1150 case WXK_DELETE: keycode = kVK_ForwardDelete; break;
1151
1152 case WXK_SHIFT: keycode = kVK_Shift; break;
1153 case WXK_ALT: keycode = kVK_Option; break;
1154 case WXK_RAW_CONTROL: keycode = kVK_Control; break;
1155 case WXK_CONTROL: keycode = kVK_Command; break;
1156
1157 case WXK_CAPITAL: keycode = kVK_CapsLock; break;
1158 case WXK_END: keycode = kVK_End; break;
1159 case WXK_HOME: keycode = kVK_Home; break;
1160 case WXK_LEFT: keycode = kVK_LeftArrow; break;
1161 case WXK_UP: keycode = kVK_UpArrow; break;
1162 case WXK_RIGHT: keycode = kVK_RightArrow; break;
1163 case WXK_DOWN: keycode = kVK_DownArrow; break;
1164
1165 case WXK_HELP: keycode = kVK_Help; break;
1166
1167
1168 case WXK_NUMPAD0: keycode = kVK_ANSI_Keypad0; break;
1169 case WXK_NUMPAD1: keycode = kVK_ANSI_Keypad1; break;
1170 case WXK_NUMPAD2: keycode = kVK_ANSI_Keypad2; break;
1171 case WXK_NUMPAD3: keycode = kVK_ANSI_Keypad3; break;
1172 case WXK_NUMPAD4: keycode = kVK_ANSI_Keypad4; break;
1173 case WXK_NUMPAD5: keycode = kVK_ANSI_Keypad5; break;
1174 case WXK_NUMPAD6: keycode = kVK_ANSI_Keypad6; break;
1175 case WXK_NUMPAD7: keycode = kVK_ANSI_Keypad7; break;
1176 case WXK_NUMPAD8: keycode = kVK_ANSI_Keypad8; break;
1177 case WXK_NUMPAD9: keycode = kVK_ANSI_Keypad9; break;
1178 case WXK_F1: keycode = kVK_F1; break;
1179 case WXK_F2: keycode = kVK_F2; break;
1180 case WXK_F3: keycode = kVK_F3; break;
1181 case WXK_F4: keycode = kVK_F4; break;
1182 case WXK_F5: keycode = kVK_F5; break;
1183 case WXK_F6: keycode = kVK_F6; break;
1184 case WXK_F7: keycode = kVK_F7; break;
1185 case WXK_F8: keycode = kVK_F8; break;
1186 case WXK_F9: keycode = kVK_F9; break;
1187 case WXK_F10: keycode = kVK_F10; break;
1188 case WXK_F11: keycode = kVK_F11; break;
1189 case WXK_F12: keycode = kVK_F12; break;
1190 case WXK_F13: keycode = kVK_F13; break;
1191 case WXK_F14: keycode = kVK_F14; break;
1192 case WXK_F15: keycode = kVK_F15; break;
1193 case WXK_F16: keycode = kVK_F16; break;
1194 case WXK_F17: keycode = kVK_F17; break;
1195 case WXK_F18: keycode = kVK_F18; break;
1196 case WXK_F19: keycode = kVK_F19; break;
1197 case WXK_F20: keycode = kVK_F20; break;
1198
1199 case WXK_PAGEUP: keycode = kVK_PageUp; break;
1200 case WXK_PAGEDOWN: keycode = kVK_PageDown; break;
1201
1202 case WXK_NUMPAD_DELETE: keycode = kVK_ANSI_KeypadClear; break;
1203 case WXK_NUMPAD_EQUAL: keycode = kVK_ANSI_KeypadEquals; break;
1204 case WXK_NUMPAD_MULTIPLY: keycode = kVK_ANSI_KeypadMultiply; break;
1205 case WXK_NUMPAD_ADD: keycode = kVK_ANSI_KeypadPlus; break;
1206 case WXK_NUMPAD_SUBTRACT: keycode = kVK_ANSI_KeypadMinus; break;
1207 case WXK_NUMPAD_DECIMAL: keycode = kVK_ANSI_KeypadDecimal; break;
1208 case WXK_NUMPAD_DIVIDE: keycode = kVK_ANSI_KeypadDivide; break;
1209
1210 default:
1211 wxLogDebug( "Unrecognised keycode %d", code );
1212 keycode = static_cast<CGKeyCode>(-1);
1213 }
1214
1215 return keycode;
1216 }
1217
1218 long wxMacTranslateKey(unsigned char key, unsigned char code)
1219 {
1220 long retval = key ;
1221 switch (key)
1222 {
1223 case kHomeCharCode :
1224 retval = WXK_HOME;
1225 break;
1226
1227 case kEnterCharCode :
1228 retval = WXK_RETURN;
1229 break;
1230 case kEndCharCode :
1231 retval = WXK_END;
1232 break;
1233
1234 case kHelpCharCode :
1235 retval = WXK_HELP;
1236 break;
1237
1238 case kBackspaceCharCode :
1239 retval = WXK_BACK;
1240 break;
1241
1242 case kTabCharCode :
1243 retval = WXK_TAB;
1244 break;
1245
1246 case kPageUpCharCode :
1247 retval = WXK_PAGEUP;
1248 break;
1249
1250 case kPageDownCharCode :
1251 retval = WXK_PAGEDOWN;
1252 break;
1253
1254 case kReturnCharCode :
1255 retval = WXK_RETURN;
1256 break;
1257
1258 case kFunctionKeyCharCode :
1259 {
1260 switch ( code )
1261 {
1262 case 0x7a :
1263 retval = WXK_F1 ;
1264 break;
1265
1266 case 0x78 :
1267 retval = WXK_F2 ;
1268 break;
1269
1270 case 0x63 :
1271 retval = WXK_F3 ;
1272 break;
1273
1274 case 0x76 :
1275 retval = WXK_F4 ;
1276 break;
1277
1278 case 0x60 :
1279 retval = WXK_F5 ;
1280 break;
1281
1282 case 0x61 :
1283 retval = WXK_F6 ;
1284 break;
1285
1286 case 0x62:
1287 retval = WXK_F7 ;
1288 break;
1289
1290 case 0x64 :
1291 retval = WXK_F8 ;
1292 break;
1293
1294 case 0x65 :
1295 retval = WXK_F9 ;
1296 break;
1297
1298 case 0x6D :
1299 retval = WXK_F10 ;
1300 break;
1301
1302 case 0x67 :
1303 retval = WXK_F11 ;
1304 break;
1305
1306 case 0x6F :
1307 retval = WXK_F12 ;
1308 break;
1309
1310 case 0x69 :
1311 retval = WXK_F13 ;
1312 break;
1313
1314 case 0x6B :
1315 retval = WXK_F14 ;
1316 break;
1317
1318 case 0x71 :
1319 retval = WXK_F15 ;
1320 break;
1321
1322 default:
1323 break;
1324 }
1325 }
1326 break ;
1327
1328 case kEscapeCharCode :
1329 retval = WXK_ESCAPE ;
1330 break ;
1331
1332 case kLeftArrowCharCode :
1333 retval = WXK_LEFT ;
1334 break ;
1335
1336 case kRightArrowCharCode :
1337 retval = WXK_RIGHT ;
1338 break ;
1339
1340 case kUpArrowCharCode :
1341 retval = WXK_UP ;
1342 break ;
1343
1344 case kDownArrowCharCode :
1345 retval = WXK_DOWN ;
1346 break ;
1347
1348 case kDeleteCharCode :
1349 retval = WXK_DELETE ;
1350 break ;
1351
1352 default:
1353 break ;
1354 } // end switch
1355
1356 return retval;
1357 }
1358
1359 int wxMacKeyCodeToModifier(wxKeyCode key)
1360 {
1361 switch (key)
1362 {
1363 case WXK_START:
1364 case WXK_MENU:
1365 case WXK_COMMAND:
1366 return cmdKey;
1367
1368 case WXK_SHIFT:
1369 return shiftKey;
1370
1371 case WXK_CAPITAL:
1372 return alphaLock;
1373
1374 case WXK_ALT:
1375 return optionKey;
1376
1377 case WXK_RAW_CONTROL:
1378 return controlKey;
1379
1380 default:
1381 return 0;
1382 }
1383 }
1384 #endif
1385
1386 #if wxOSX_USE_COCOA && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
1387
1388 // defined in utils.mm
1389
1390 #elif wxOSX_USE_COCOA_OR_CARBON
1391
1392 wxMouseState wxGetMouseState()
1393 {
1394 wxMouseState ms;
1395
1396 wxPoint pt = wxGetMousePosition();
1397 ms.SetX(pt.x);
1398 ms.SetY(pt.y);
1399
1400 UInt32 buttons = GetCurrentButtonState();
1401 ms.SetLeftDown( (buttons & 0x01) != 0 );
1402 ms.SetMiddleDown( (buttons & 0x04) != 0 );
1403 ms.SetRightDown( (buttons & 0x02) != 0 );
1404
1405 UInt32 modifiers = GetCurrentKeyModifiers();
1406 ms.SetRawControlDown(modifiers & controlKey);
1407 ms.SetShiftDown(modifiers & shiftKey);
1408 ms.SetAltDown(modifiers & optionKey);
1409 ms.SetControlDown(modifiers & cmdKey);
1410
1411 return ms;
1412 }
1413
1414 #endif
1415
1416 // TODO : once the new key/char handling is tested, move all the code to wxWindow
1417
1418 bool wxApp::MacSendKeyDownEvent( wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
1419 {
1420 if ( !focus )
1421 return false ;
1422
1423 wxKeyEvent event(wxEVT_KEY_DOWN) ;
1424 MacCreateKeyEvent( event, focus , keymessage , modifiers , when , uniChar ) ;
1425
1426 return focus->OSXHandleKeyEvent(event);
1427 }
1428
1429 bool wxApp::MacSendKeyUpEvent( wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
1430 {
1431 if ( !focus )
1432 return false ;
1433
1434 wxKeyEvent event( wxEVT_KEY_UP ) ;
1435 MacCreateKeyEvent( event, focus , keymessage , modifiers , when , uniChar ) ;
1436
1437 return focus->OSXHandleKeyEvent(event) ;
1438 }
1439
1440 bool wxApp::MacSendCharEvent( wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
1441 {
1442 if ( !focus )
1443 return false ;
1444 wxKeyEvent event(wxEVT_CHAR) ;
1445 MacCreateKeyEvent( event, focus , keymessage , modifiers , when , uniChar ) ;
1446
1447 bool handled = false ;
1448
1449 #if wxOSX_USE_CARBON
1450 long keyval = event.m_keyCode ;
1451
1452 {
1453 wxKeyEvent eventCharHook(wxEVT_CHAR_HOOK, event);
1454 handled = focus->HandleWindowEvent( eventCharHook );
1455 if ( handled && eventCharHook.IsNextEventAllowed() )
1456 handled = false ;
1457 }
1458
1459 if ( !handled )
1460 {
1461 handled = focus->HandleWindowEvent( event ) ;
1462 }
1463
1464 if ( !handled && (keyval == WXK_TAB) )
1465 {
1466 wxWindow* iter = focus->GetParent() ;
1467 while ( iter && !handled )
1468 {
1469 if ( iter->HasFlag( wxTAB_TRAVERSAL ) )
1470 {
1471 wxNavigationKeyEvent new_event;
1472 new_event.SetEventObject( focus );
1473 new_event.SetDirection( !event.ShiftDown() );
1474 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1475 new_event.SetWindowChange( event.ControlDown() );
1476 new_event.SetCurrentFocus( focus );
1477 handled = focus->GetParent()->HandleWindowEvent( new_event );
1478 if ( handled && new_event.GetSkipped() )
1479 handled = false ;
1480 }
1481
1482 iter = iter->GetParent() ;
1483 }
1484 }
1485
1486 // backdoor handler for default return and command escape
1487 if ( !handled && (!focus->IsKindOf(CLASSINFO(wxControl) ) || !focus->AcceptsFocus() ) )
1488 {
1489 // if window is not having a focus still testing for default enter or cancel
1490 // TODO: add the UMA version for ActiveNonFloatingWindow
1491 #ifndef __LP64__
1492 wxWindow* focus = wxNonOwnedWindow::GetFromWXWindow( (WXWindow) FrontWindow() ) ;
1493 if ( focus )
1494 {
1495 if ( keyval == WXK_RETURN || keyval == WXK_NUMPAD_ENTER )
1496 {
1497 wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(focus), wxTopLevelWindow);
1498 if ( tlw && tlw->GetDefaultItem() )
1499 {
1500 wxButton *def = wxDynamicCast(tlw->GetDefaultItem(), wxButton);
1501 if ( def && def->IsEnabled() )
1502 {
1503 wxCommandEvent event(wxEVT_BUTTON, def->GetId() );
1504 event.SetEventObject(def);
1505 def->Command(event);
1506
1507 return true ;
1508 }
1509 }
1510 }
1511 else if (keyval == WXK_ESCAPE || (keyval == '.' && modifiers & cmdKey ) )
1512 {
1513 // generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs)
1514 wxCommandEvent new_event(wxEVT_BUTTON,wxID_CANCEL);
1515 new_event.SetEventObject( focus );
1516 handled = focus->HandleWindowEvent( new_event );
1517 }
1518 }
1519 #endif
1520 }
1521 #endif
1522 return handled ;
1523 }
1524
1525 // This method handles common code for SendKeyDown, SendKeyUp, and SendChar events.
1526 void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
1527 {
1528 #if wxOSX_USE_COCOA_OR_CARBON
1529
1530 short keycode, keychar ;
1531
1532 keychar = short(keymessage & charCodeMask);
1533 keycode = short(keymessage & keyCodeMask) >> 8 ;
1534 if ( !(event.GetEventType() == wxEVT_CHAR) && (modifiers & (controlKey | shiftKey | optionKey) ) )
1535 {
1536 // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
1537 // and look at the character after
1538 #ifdef __LP64__
1539 // TODO new implementation using TextInputSources
1540 #else
1541 UInt32 state = 0;
1542 UInt32 keyInfo = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache), ( modifiers & (~(controlKey | shiftKey | optionKey))) | keycode, &state);
1543 keychar = short(keyInfo & charCodeMask);
1544 #endif
1545 }
1546
1547 long keyval = wxMacTranslateKey(keychar, keycode) ;
1548 if ( keyval == keychar && ( event.GetEventType() == wxEVT_KEY_UP || event.GetEventType() == wxEVT_KEY_DOWN ) )
1549 keyval = wxToupper( keyval ) ;
1550
1551 // Check for NUMPAD keys. For KEY_UP/DOWN events we need to use the
1552 // WXK_NUMPAD constants, but for the CHAR event we want to use the
1553 // standard ascii values
1554 if ( event.GetEventType() != wxEVT_CHAR )
1555 {
1556 if (keyval >= '0' && keyval <= '9' && keycode >= 82 && keycode <= 92)
1557 {
1558 keyval = (keyval - '0') + WXK_NUMPAD0;
1559 }
1560 else if (keycode >= 65 && keycode <= 81)
1561 {
1562 switch (keycode)
1563 {
1564 case 76 :
1565 keyval = WXK_NUMPAD_ENTER;
1566 break;
1567
1568 case 81:
1569 keyval = WXK_NUMPAD_EQUAL;
1570 break;
1571
1572 case 67:
1573 keyval = WXK_NUMPAD_MULTIPLY;
1574 break;
1575
1576 case 75:
1577 keyval = WXK_NUMPAD_DIVIDE;
1578 break;
1579
1580 case 78:
1581 keyval = WXK_NUMPAD_SUBTRACT;
1582 break;
1583
1584 case 69:
1585 keyval = WXK_NUMPAD_ADD;
1586 break;
1587
1588 case 65:
1589 keyval = WXK_NUMPAD_DECIMAL;
1590 break;
1591 default:
1592 break;
1593 }
1594 }
1595 }
1596
1597 event.m_shiftDown = modifiers & shiftKey;
1598 event.m_rawControlDown = modifiers & controlKey;
1599 event.m_altDown = modifiers & optionKey;
1600 event.m_controlDown = modifiers & cmdKey;
1601 event.m_keyCode = keyval ;
1602 #if wxUSE_UNICODE
1603 event.m_uniChar = uniChar ;
1604 #endif
1605
1606 event.m_rawCode = keymessage;
1607 event.m_rawFlags = modifiers;
1608 event.SetTimestamp(when);
1609 event.SetEventObject(focus);
1610 #else
1611 wxUnusedVar(event);
1612 wxUnusedVar(focus);
1613 wxUnusedVar(keymessage);
1614 wxUnusedVar(modifiers);
1615 wxUnusedVar(when);
1616 wxUnusedVar(uniChar);
1617 #endif
1618 }
1619
1620
1621 void wxApp::MacHideApp()
1622 {
1623 #if wxOSX_USE_CARBON
1624 wxMacCarbonEvent event( kEventClassCommand , kEventCommandProcess );
1625 HICommand command;
1626 memset( &command, 0 , sizeof(command) );
1627 command.commandID = kHICommandHide ;
1628 event.SetParameter<HICommand>(kEventParamDirectObject, command );
1629 SendEventToApplication( event );
1630 #endif
1631 }