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