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