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