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