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