]> git.saurik.com Git - wxWidgets.git/blame - src/osx/carbon/app.cpp
Fix crash in wxDC::GetMultiLineTextExtent() after last commit.
[wxWidgets.git] / src / osx / carbon / app.cpp
CommitLineData
489468fe 1/////////////////////////////////////////////////////////////////////////////
524c47aa 2// Name: src/osx/carbon/app.cpp
489468fe
SC
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"
524c47aa 43#include "wx/evtloop.h"
489468fe
SC
44
45#include <string.h>
46
47// mac
b2680ced 48#if wxOSX_USE_CARBON
1f0c8f31 49#include "wx/osx/uma.h"
b2680ced
SC
50#else
51#include "wx/osx/private.h"
52#endif
489468fe 53
b2680ced
SC
54#if defined(WXMAKINGDLL_CORE)
55# include <mach-o/dyld.h>
489468fe
SC
56#endif
57
58// Keep linker from discarding wxStockGDIMac
59wxFORCE_LINK_MODULE(gdiobj)
60
489468fe
SC
61IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
62BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
63 EVT_IDLE(wxApp::OnIdle)
64 EVT_END_SESSION(wxApp::OnEndSession)
65 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
66END_EVENT_TABLE()
67
68
69// platform specific static variables
70static const short kwxMacAppleMenuId = 1 ;
71
72wxWindow* wxApp::s_captureWindow = NULL ;
73long wxApp::s_lastModifiers = 0 ;
74
75long wxApp::s_macAboutMenuItemId = wxID_ABOUT ;
76long wxApp::s_macPreferencesMenuItemId = wxID_PREFERENCES ;
77long wxApp::s_macExitMenuItemId = wxID_EXIT ;
78wxString wxApp::s_macHelpMenuTitleName = wxT("&Help") ;
79
80bool wxApp::sm_isEmbedded = false; // Normally we're not a plugin
81
f93849e6 82#if wxOSX_USE_CARBON
b2680ced 83
489468fe
SC
84//----------------------------------------------------------------------
85// Core Apple Event Support
86//----------------------------------------------------------------------
87
b2680ced
SC
88AEEventHandlerUPP sODocHandler = NULL ;
89AEEventHandlerUPP sGURLHandler = NULL ;
90AEEventHandlerUPP sOAppHandler = NULL ;
91AEEventHandlerUPP sPDocHandler = NULL ;
92AEEventHandlerUPP sRAppHandler = NULL ;
93AEEventHandlerUPP sQuitHandler = NULL ;
94
489468fe
SC
95pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
96pascal OSErr AEHandleOApp( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
97pascal OSErr AEHandlePDoc( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
98pascal OSErr AEHandleQuit( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
99pascal OSErr AEHandleRApp( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
b2680ced 100pascal OSErr AEHandleGURL( const AppleEvent *event , AppleEvent *reply , SRefCon refcon ) ;
489468fe
SC
101
102pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
103{
104 return wxTheApp->MacHandleAEODoc( (AppleEvent*) event , reply) ;
105}
106
107pascal OSErr AEHandleOApp( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
108{
109 return wxTheApp->MacHandleAEOApp( (AppleEvent*) event , reply ) ;
110}
111
112pascal OSErr AEHandlePDoc( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
113{
114 return wxTheApp->MacHandleAEPDoc( (AppleEvent*) event , reply ) ;
115}
116
117pascal OSErr AEHandleQuit( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
118{
119 return wxTheApp->MacHandleAEQuit( (AppleEvent*) event , reply) ;
120}
121
122pascal OSErr AEHandleRApp( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
123{
124 return wxTheApp->MacHandleAERApp( (AppleEvent*) event , reply) ;
125}
126
127pascal OSErr AEHandleGURL( const AppleEvent *event , AppleEvent *reply , SRefCon WXUNUSED(refcon) )
128{
129 return wxTheApp->MacHandleAEGURL((WXEVENTREF *)event , reply) ;
130}
131
132
ee7553e9 133// AEODoc Calls MacOpenFiles with all of the files passed
489468fe
SC
134
135short 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
ee7553e9 161 wxArrayString fileNames;
489468fe
SC
162 for (i = 1; i <= itemsInList; i++)
163 {
0161592b 164 err = AEGetNthPtr(
489468fe
SC
165 &docList, i, typeFSRef, &keywd, &returnedType,
166 (Ptr)&theRef, sizeof(theRef), &actualSize);
0161592b
SC
167
168 if ( err != noErr)
169 return err;
170
489468fe
SC
171 fName = wxMacFSRefToPath( &theRef ) ;
172
ee7553e9 173 fileNames.Add(fName);
489468fe
SC
174 }
175
ee7553e9
DS
176 MacOpenFiles(fileNames);
177
489468fe
SC
178 return noErr;
179}
180
181// AEODoc Calls MacOpenURL on the url passed
182
183short 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
d181e877 194 url[actualSize] = '\0'; // Terminate the C string
489468fe
SC
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
208short 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 {
9c841f84 236 err = AEGetNthPtr(
489468fe
SC
237 &docList, i, typeFSRef, &keywd, &returnedType,
238 (Ptr)&theRef, sizeof(theRef), &actualSize);
9c841f84
SC
239
240 if ( err != noErr)
241 return err;
242
489468fe
SC
243 fName = wxMacFSRefToPath( &theRef ) ;
244
245 MacPrintFile(fName);
246 }
247
248 return noErr;
249}
250
251// AEOApp calls MacNewFile
252
253short 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
261short wxApp::MacHandleAEQuit(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
262{
2680ddc6
SC
263 wxCloseEvent event;
264 wxTheApp->OnQueryEndSession(event);
265 if ( !event.GetVeto() )
489468fe 266 {
2680ddc6
SC
267 wxCloseEvent event;
268 wxTheApp->OnEndSession(event);
489468fe 269 }
489468fe
SC
270 return noErr ;
271}
272
273// AEROApp calls MacReopenApp
274
275short wxApp::MacHandleAERApp(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
276{
277 MacReopenApp() ;
278
279 return noErr ;
280}
281
b2680ced
SC
282#endif
283
489468fe
SC
284//----------------------------------------------------------------------
285// Support Routines linking the Mac...File Calls to the Document Manager
286//----------------------------------------------------------------------
287
ee7553e9
DS
288void 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
489468fe
SC
298void 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
307void wxApp::MacOpenURL(const wxString & WXUNUSED(url) )
308{
309}
310
311void 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
348void wxApp::MacNewFile()
349{
350}
351
352void 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();
4b1d0dbe 360 if ( !node )
489468fe
SC
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 ;
d181e877 376 }
489468fe 377 else if ( win->IsIconized() )
d181e877 378 {
489468fe
SC
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
b2680ced
SC
404#if wxOSX_USE_CARBON
405
489468fe
SC
406struct IdPair
407{
408 UInt32 macId ;
409 int wxId ;
410} ;
411
412IdPair 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
423int 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
461UInt32 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
489wxMenu* 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 ) ) ||
d181e877 518 ( helpMenuHandle != NULL && command.menu.menuRef == helpMenuHandle ) ||
489468fe
SC
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 {
8f2a8de6 527 URefCon refCon = 0 ;
489468fe
SC
528
529 GetMenuItemRefCon( command.menu.menuRef , command.menu.menuItemIndex , &refCon ) ;
530 itemMenu = wxFindMenuFromMacMenu( command.menu.menuRef ) ;
524c47aa 531 if ( itemMenu != NULL && refCon != 0)
0ee6e449 532 item = (wxMenuItem*) refCon;
489468fe
SC
533 }
534 }
535#endif
536 return itemMenu ;
537}
538
b2680ced
SC
539#endif
540
489468fe
SC
541//----------------------------------------------------------------------
542// Carbon Event Handler
543//----------------------------------------------------------------------
544
b2680ced
SC
545#if wxOSX_USE_CARBON
546
489468fe
SC
547static 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
570static pascal OSStatus
571wxMacAppMenuEventHandler( 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 {
489468fe
SC
582 switch (GetEventKind(event))
583 {
584 case kEventMenuOpening:
524c47aa 585 menu->HandleMenuOpened();
489468fe
SC
586 break;
587
588 case kEventMenuClosed:
524c47aa 589 menu->HandleMenuClosed();
489468fe
SC
590 break;
591
592 case kEventMenuTargetItem:
524c47aa
SC
593 {
594 HICommand command ;
d181e877 595
524c47aa
SC
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 }
489468fe
SC
607 break;
608
609 default:
610 wxFAIL_MSG(wxT("Unexpected menu event kind"));
611 break;
612 }
613
489468fe
SC
614 }
615#endif
616 return eventNotHandledErr;
617}
618
489468fe
SC
619static pascal OSStatus
620wxMacAppCommandEventHandler( 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 ) ;
489468fe
SC
633
634 if ( item )
635 {
636 wxASSERT( itemMenu != NULL ) ;
637
638 switch ( cEvent.GetKind() )
639 {
640 case kEventProcessCommand :
524c47aa
SC
641 if ( itemMenu->HandleCommandProcess( item ) )
642 result = noErr;
489468fe
SC
643 break ;
644
645 case kEventCommandUpdateStatus:
524c47aa
SC
646 if ( itemMenu->HandleCommandUpdateStatus( item ) )
647 result = noErr;
489468fe
SC
648 break ;
649
650 default :
651 break ;
652 }
653 }
654 return result ;
655}
489468fe
SC
656
657static pascal OSStatus
658wxMacAppApplicationEventHandler( 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
684pascal 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 :
4f134f0c 721 result = AEProcessEvent(event);
489468fe
SC
722 break ;
723
724 default :
725 break ;
726 }
727
728 wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ;
729
730 return result ;
731}
732
733DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacAppEventHandler )
b2680ced 734#endif
489468fe 735
4b6a582b 736#if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
489468fe
SC
737
738pascal static void
739wxMacAssertOutputHandler(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
4b6a582b 782#endif // wxDEBUG_LEVEL
489468fe 783
489468fe
SC
784bool wxApp::Initialize(int& argc, wxChar **argv)
785{
786 // Mac-specific
787
4b6a582b 788#if wxDEBUG_LEVEL && wxOSX_USE_COCOA_OR_CARBON
489468fe
SC
789 InstallDebugAssertOutputHandler( NewDebugAssertOutputHandlerUPP( wxMacAssertOutputHandler ) );
790#endif
791
489468fe
SC
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 {
9a83f860 798 static const wxChar *ARG_PSN = wxT("-psn_");
489468fe
SC
799 if ( wxStrncmp(argv[1], ARG_PSN, wxStrlen(ARG_PSN)) == 0 )
800 {
801 // remove this argument
802 --argc;
815acb8e 803 memmove(argv + 1, argv + 2, argc * sizeof(wxChar*));
489468fe
SC
804 }
805 }
806
46447d1a
SC
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 {
815acb8e 828 memmove(argv + i, argv + i + 2, (argc-i-1)*sizeof(wxChar*));
46447d1a 829 argc -= 2;
46447d1a
SC
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
489468fe
SC
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
489468fe
SC
857 return true;
858}
859
88695e9a 860#if wxOSX_USE_COCOA_OR_CARBON
524c47aa
SC
861bool wxApp::CallOnInit()
862{
863 wxMacAutoreleasePool autoreleasepool;
864 return OnInit();
865}
cf4ce62c 866#endif
524c47aa 867
489468fe
SC
868bool wxApp::OnInitGui()
869{
870 if ( !wxAppBase::OnInitGui() )
871 return false ;
524c47aa
SC
872
873 if ( !DoInitGui() )
874 return false;
875
876 return true ;
877}
878
879bool wxApp::ProcessIdle()
880{
881 wxMacAutoreleasePool autoreleasepool;
882 return wxAppBase::ProcessIdle();
883}
884
ada17583
SC
885int wxApp::OnRun()
886{
887 wxMacAutoreleasePool pool;
888 return wxAppBase::OnRun();
889}
890
b2680ced 891#if wxOSX_USE_CARBON
524c47aa
SC
892bool wxApp::DoInitGui()
893{
489468fe
SC
894 InstallStandardEventHandler( GetApplicationEventTarget() ) ;
895 if (!sm_isEmbedded)
896 {
897 InstallApplicationEventHandler(
898 GetwxMacAppEventHandlerUPP(),
899 GetEventTypeCount(eventList), eventList, wxTheApp, (EventHandlerRef *)&(wxTheApp->m_macEventHandler));
900 }
489468fe
SC
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 }
524c47aa 924
489468fe
SC
925 if ( !wxMacInitCocoa() )
926 return false;
d181e877 927
524c47aa 928 return true;
489468fe
SC
929}
930
524c47aa 931void wxApp::DoCleanUp()
489468fe 932{
489468fe
SC
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 }
524c47aa 958}
489468fe 959
b2680ced
SC
960#endif
961
524c47aa
SC
962void wxApp::CleanUp()
963{
ada17583 964 wxMacAutoreleasePool autoreleasepool;
524c47aa
SC
965#if wxUSE_TOOLTIPS
966 wxToolTip::RemoveToolTips() ;
967#endif
968
524c47aa
SC
969 DoCleanUp();
970
489468fe
SC
971 wxAppBase::CleanUp();
972}
973
974//----------------------------------------------------------------------
975// misc initialization stuff
976//----------------------------------------------------------------------
977
489468fe
SC
978wxApp::wxApp()
979{
980 m_printMode = wxPRINT_WINDOWS;
981
982 m_macCurrentEvent = NULL ;
983 m_macCurrentEventHandlerCallRef = NULL ;
32e806fe
KO
984 m_macPool = new wxMacAutoreleasePool();
985}
986
987wxApp::~wxApp()
988{
989 if (m_macPool)
990 delete m_macPool;
489468fe
SC
991}
992
524c47aa
SC
993CFMutableArrayRef GetAutoReleaseArray()
994{
995 static CFMutableArrayRef array = 0;
996 if ( array == 0)
997 array= CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
998 return array;
999}
1000
1001void wxApp::MacAddToAutorelease( void* cfrefobj )
1002{
1003 CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj );
1004}
1005
32e806fe
KO
1006void wxApp::MacReleaseAutoreleasePool()
1007{
1008 if (m_macPool)
1009 delete m_macPool;
1010 m_macPool = new wxMacAutoreleasePool();
1011}
1012
489468fe
SC
1013void 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__
a2dd520d 1019#if wxUSE_MENUS
489468fe
SC
1020 if (!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar())
1021 wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar();
1022#endif
524c47aa
SC
1023#endif
1024 CFArrayRemoveAllValues( GetAutoReleaseArray() );
489468fe
SC
1025}
1026
1027void wxApp::WakeUpIdle()
1028{
cc96f525 1029 wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
489468fe 1030
cc96f525
SC
1031 if ( loop )
1032 loop->WakeUp();
489468fe
SC
1033}
1034
1035void 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.
1043void wxApp::OnQueryEndSession(wxCloseEvent& event)
1044{
2680ddc6
SC
1045 if ( !wxDialog::OSXHasModalDialogsOpen() )
1046 {
1047 if (GetTopWindow())
1048 {
1049 if (!GetTopWindow()->Close(!event.CanVeto()))
1050 event.Veto(true);
1051 }
1052 }
1053 else
489468fe 1054 {
2680ddc6 1055 event.Veto(true);
489468fe
SC
1056 }
1057}
1058
1059extern "C" void wxCYield() ;
1060void wxCYield()
1061{
1062 wxYield() ;
1063}
1064
489468fe
SC
1065// virtual
1066void wxApp::MacHandleUnhandledEvent( WXEVENTREF WXUNUSED(evr) )
1067{
1068 // Override to process unhandled events as you please
1069}
1070
c1313b54
SC
1071#if wxOSX_USE_COCOA_OR_CARBON
1072
c1313b54
SC
1073CGKeyCode wxCharCodeWXToOSX(wxKeyCode code)
1074{
1075 CGKeyCode keycode;
1076
1077 switch (code)
1078 {
11716cbe
VZ
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
c1313b54
SC
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;
11716cbe
VZ
1125
1126#ifdef __clang__
1127 #pragma clang diagnostic pop
1128#endif // __clang__
c1313b54
SC
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;
4983b80d
SC
1139 case WXK_RAW_CONTROL: keycode = kVK_Control; break;
1140 case WXK_CONTROL: keycode = kVK_Command; break;
c1313b54
SC
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}
b2680ced 1202
489468fe
SC
1203long 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
1344int wxMacKeyCodeToModifier(wxKeyCode key)
1345{
1346 switch (key)
1347 {
1348 case WXK_START:
1349 case WXK_MENU:
4983b80d 1350 case WXK_COMMAND:
489468fe
SC
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
4983b80d 1362 case WXK_RAW_CONTROL:
489468fe
SC
1363 return controlKey;
1364
1365 default:
1366 return 0;
1367 }
1368}
b2680ced 1369#endif
489468fe 1370
36b96006
SC
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
f3769d53 1376
489468fe
SC
1377wxMouseState 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();
dd9ec596 1391 ms.SetRawControlDown(modifiers & controlKey);
489468fe
SC
1392 ms.SetShiftDown(modifiers & shiftKey);
1393 ms.SetAltDown(modifiers & optionKey);
dd9ec596 1394 ms.SetControlDown(modifiers & cmdKey);
f3769d53 1395
489468fe
SC
1396 return ms;
1397}
1398
f3769d53
SC
1399#endif
1400
489468fe
SC
1401// TODO : once the new key/char handling is tested, move all the code to wxWindow
1402
2f7baaec 1403bool wxApp::MacSendKeyDownEvent( wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
489468fe
SC
1404{
1405 if ( !focus )
1406 return false ;
1407
489468fe 1408 wxKeyEvent event(wxEVT_KEY_DOWN) ;
2f7baaec 1409 MacCreateKeyEvent( event, focus , keymessage , modifiers , when , uniChar ) ;
489468fe 1410
4eb5a0ec 1411 return focus->OSXHandleKeyEvent(event);
489468fe
SC
1412}
1413
2f7baaec 1414bool wxApp::MacSendKeyUpEvent( wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
489468fe
SC
1415{
1416 if ( !focus )
1417 return false ;
1418
489468fe 1419 wxKeyEvent event( wxEVT_KEY_UP ) ;
2f7baaec 1420 MacCreateKeyEvent( event, focus , keymessage , modifiers , when , uniChar ) ;
489468fe 1421
4eb5a0ec 1422 return focus->OSXHandleKeyEvent(event) ;
489468fe
SC
1423}
1424
2f7baaec 1425bool wxApp::MacSendCharEvent( wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
489468fe
SC
1426{
1427 if ( !focus )
1428 return false ;
489468fe 1429 wxKeyEvent event(wxEVT_CHAR) ;
2f7baaec 1430 MacCreateKeyEvent( event, focus , keymessage , modifiers , when , uniChar ) ;
489468fe
SC
1431
1432 bool handled = false ;
1433
b2680ced 1434#if wxOSX_USE_CARBON
2c2fafe9 1435 long keyval = event.m_keyCode ;
489468fe 1436
489468fe 1437 {
3a95f73c
VZ
1438 wxKeyEvent eventCharHook(wxEVT_CHAR_HOOK, event);
1439 handled = focus->HandleWindowEvent( eventCharHook );
4cf1a9bf 1440 if ( handled && eventCharHook.IsNextEventAllowed() )
489468fe
SC
1441 handled = false ;
1442 }
1443
1444 if ( !handled )
1445 {
489468fe
SC
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
b2680ced 1472 if ( !handled && (!focus->IsKindOf(CLASSINFO(wxControl) ) || !focus->AcceptsFocus() ) )
489468fe
SC
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__
b2680ced 1477 wxWindow* focus = wxNonOwnedWindow::GetFromWXWindow( (WXWindow) FrontWindow() ) ;
489468fe
SC
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 }
b2680ced 1506#endif
489468fe
SC
1507 return handled ;
1508}
1509
1510// This method handles common code for SendKeyDown, SendKeyUp, and SendChar events.
2f7baaec 1511void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar )
489468fe 1512{
c1313b54
SC
1513#if wxOSX_USE_COCOA_OR_CARBON
1514
489468fe
SC
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__
03647350 1524 // TODO new implementation using TextInputSources
489468fe
SC
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 }
d181e877 1545 else if (keycode >= 65 && keycode <= 81)
489468fe
SC
1546 {
1547 switch (keycode)
1548 {
1549 case 76 :
1550 keyval = WXK_NUMPAD_ENTER;
1551 break;
d181e877 1552
489468fe
SC
1553 case 81:
1554 keyval = WXK_NUMPAD_EQUAL;
1555 break;
d181e877 1556
489468fe
SC
1557 case 67:
1558 keyval = WXK_NUMPAD_MULTIPLY;
1559 break;
d181e877 1560
489468fe
SC
1561 case 75:
1562 keyval = WXK_NUMPAD_DIVIDE;
1563 break;
d181e877 1564
489468fe
SC
1565 case 78:
1566 keyval = WXK_NUMPAD_SUBTRACT;
1567 break;
d181e877 1568
489468fe
SC
1569 case 69:
1570 keyval = WXK_NUMPAD_ADD;
1571 break;
d181e877 1572
489468fe
SC
1573 case 65:
1574 keyval = WXK_NUMPAD_DECIMAL;
1575 break;
1576 default:
1577 break;
1578 }
1579 }
1580 }
d181e877 1581
489468fe 1582 event.m_shiftDown = modifiers & shiftKey;
dd9ec596 1583 event.m_rawControlDown = modifiers & controlKey;
489468fe 1584 event.m_altDown = modifiers & optionKey;
dd9ec596 1585 event.m_controlDown = modifiers & cmdKey;
489468fe
SC
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;
489468fe
SC
1593 event.SetTimestamp(when);
1594 event.SetEventObject(focus);
de0d2095
SC
1595#else
1596 wxUnusedVar(event);
1597 wxUnusedVar(focus);
1598 wxUnusedVar(keymessage);
1599 wxUnusedVar(modifiers);
1600 wxUnusedVar(when);
de0d2095 1601 wxUnusedVar(uniChar);
b2680ced 1602#endif
489468fe
SC
1603}
1604
1605
1606void wxApp::MacHideApp()
1607{
b2680ced 1608#if wxOSX_USE_CARBON
489468fe
SC
1609 wxMacCarbonEvent event( kEventClassCommand , kEventCommandProcess );
1610 HICommand command;
1611 memset( &command, 0 , sizeof(command) );
1612 command.commandID = kHICommandHide ;
d181e877 1613 event.SetParameter<HICommand>(kEventParamDirectObject, command );
489468fe 1614 SendEventToApplication( event );
b2680ced 1615#endif
489468fe 1616}