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