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