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