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