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