]> git.saurik.com Git - wxWidgets.git/blob - src/mac/app.cpp
fix Alt-letter navigation with spin controls (bug 672974)
[wxWidgets.git] / src / mac / app.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: app.cpp
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 #ifdef __GNUG__
13 #pragma implementation "app.h"
14 #endif
15
16 #include "wx/defs.h"
17
18 #include "wx/window.h"
19 #include "wx/frame.h"
20 #include "wx/button.h"
21 #include "wx/app.h"
22 #include "wx/utils.h"
23 #include "wx/gdicmn.h"
24 #include "wx/pen.h"
25 #include "wx/brush.h"
26 #include "wx/cursor.h"
27 #include "wx/intl.h"
28 #include "wx/icon.h"
29 #include "wx/palette.h"
30 #include "wx/dc.h"
31 #include "wx/dialog.h"
32 #include "wx/msgdlg.h"
33 #include "wx/log.h"
34 #include "wx/module.h"
35 #include "wx/memory.h"
36 #include "wx/tooltip.h"
37 #include "wx/textctrl.h"
38 #include "wx/menu.h"
39 #include "wx/docview.h"
40
41 #if wxUSE_WX_RESOURCES
42 # include "wx/resource.h"
43 #endif
44
45 #include <string.h>
46
47 // mac
48
49 #ifndef __DARWIN__
50 #if __option(profile)
51 #include <profiler.h>
52 #endif
53 #endif
54
55 #include "apprsrc.h"
56
57 #include "wx/mac/uma.h"
58 #include "wx/mac/macnotfy.h"
59
60 #ifdef __DARWIN__
61 # include <CoreServices/CoreServices.h>
62 # if defined(WXMAKINGDLL)
63 # include <mach-o/dyld.h>
64 # endif
65 #else
66 # include <Sound.h>
67 # include <Threads.h>
68 # include <ToolUtils.h>
69 # include <DiskInit.h>
70 # include <Devices.h>
71 #endif
72
73 extern wxList wxPendingDelete;
74 extern wxList *wxWinMacWindowList;
75 extern wxList *wxWinMacControlList;
76
77 // statics for implementation
78
79 static bool s_inYield = FALSE;
80 static bool s_inOnIdle = FALSE;
81
82 #if TARGET_CARBON
83 static bool s_inReceiveEvent = FALSE ;
84 static EventTime sleepTime = kEventDurationNoWait ;
85 #else
86 static long sleepTime = 0 ;
87 #endif
88
89 wxApp *wxTheApp = NULL;
90
91 #if !USE_SHARED_LIBRARY
92 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
93 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
94 EVT_IDLE(wxApp::OnIdle)
95 EVT_END_SESSION(wxApp::OnEndSession)
96 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
97 END_EVENT_TABLE()
98 #endif
99
100
101 const short kMacMinHeap = (29 * 1024) ;
102 // platform specific static variables
103
104 const short kwxMacMenuBarResource = 1 ;
105 const short kwxMacAppleMenuId = 1 ;
106
107 WXHRGN wxApp::s_macCursorRgn = NULL;
108 wxWindow* wxApp::s_captureWindow = NULL ;
109 int wxApp::s_lastMouseDown = 0 ;
110 long wxApp::sm_lastMessageTime = 0;
111 long wxApp::s_lastModifiers = 0 ;
112
113
114 bool wxApp::s_macDefaultEncodingIsPC = true ;
115 bool wxApp::s_macSupportPCMenuShortcuts = true ;
116 long wxApp::s_macAboutMenuItemId = wxID_ABOUT ;
117 long wxApp::s_macPreferencesMenuItemId = 0 ;
118 long wxApp::s_macExitMenuItemId = wxID_EXIT ;
119 wxString wxApp::s_macHelpMenuTitleName = "&Help" ;
120
121 //----------------------------------------------------------------------
122 // Core Apple Event Support
123 //----------------------------------------------------------------------
124
125 pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , long refcon ) ;
126 pascal OSErr AEHandleOApp( const AppleEvent *event , AppleEvent *reply , long refcon ) ;
127 pascal OSErr AEHandlePDoc( const AppleEvent *event , AppleEvent *reply , long refcon ) ;
128 pascal OSErr AEHandleQuit( const AppleEvent *event , AppleEvent *reply , long refcon ) ;
129
130 pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , long WXUNUSED(refcon) )
131 {
132 return wxTheApp->MacHandleAEODoc( (AppleEvent*) event , reply) ;
133 }
134
135 pascal OSErr AEHandleOApp( const AppleEvent *event , AppleEvent *reply , long WXUNUSED(refcon) )
136 {
137 return wxTheApp->MacHandleAEOApp( (AppleEvent*) event , reply ) ;
138 }
139
140 pascal OSErr AEHandlePDoc( const AppleEvent *event , AppleEvent *reply , long WXUNUSED(refcon) )
141 {
142 return wxTheApp->MacHandleAEPDoc( (AppleEvent*) event , reply ) ;
143 }
144
145 pascal OSErr AEHandleQuit( const AppleEvent *event , AppleEvent *reply , long WXUNUSED(refcon) )
146 {
147 return wxTheApp->MacHandleAEQuit( (AppleEvent*) event , reply) ;
148 }
149
150 // AEODoc Calls MacOpenFile on each of the files passed
151
152 short wxApp::MacHandleAEODoc(const WXEVENTREF event, WXEVENTREF WXUNUSED(reply))
153 {
154 AEDescList docList;
155 AEKeyword keywd;
156 DescType returnedType;
157 Size actualSize;
158 long itemsInList;
159 FSSpec theSpec;
160 OSErr err;
161 short i;
162 err = AEGetParamDesc((AppleEvent *)event, keyDirectObject, typeAEList,&docList);
163 if (err != noErr)
164 return err;
165
166 err = AECountItems(&docList, &itemsInList);
167 if (err != noErr)
168 return err;
169
170 ProcessSerialNumber PSN ;
171 PSN.highLongOfPSN = 0 ;
172 PSN.lowLongOfPSN = kCurrentProcess ;
173 SetFrontProcess( &PSN ) ;
174
175 for (i = 1; i <= itemsInList; i++) {
176 AEGetNthPtr(&docList, i, typeFSS, &keywd, &returnedType,
177 (Ptr) & theSpec, sizeof(theSpec), &actualSize);
178 wxString fName = wxMacFSSpec2MacFilename(&theSpec);
179 MacOpenFile(fName);
180 }
181 return noErr;
182 }
183
184 // AEPDoc Calls MacPrintFile on each of the files passed
185
186 short wxApp::MacHandleAEPDoc(const WXEVENTREF event , WXEVENTREF WXUNUSED(reply))
187 {
188 AEDescList docList;
189 AEKeyword keywd;
190 DescType returnedType;
191 Size actualSize;
192 long itemsInList;
193 FSSpec theSpec;
194 OSErr err;
195 short i;
196 err = AEGetParamDesc((AppleEvent *)event, keyDirectObject, typeAEList,&docList);
197 if (err != noErr)
198 return err;
199
200 err = AECountItems(&docList, &itemsInList);
201 if (err != noErr)
202 return err;
203
204 ProcessSerialNumber PSN ;
205 PSN.highLongOfPSN = 0 ;
206 PSN.lowLongOfPSN = kCurrentProcess ;
207 SetFrontProcess( &PSN ) ;
208
209 for (i = 1; i <= itemsInList; i++) {
210 AEGetNthPtr(&docList, i, typeFSS, &keywd, &returnedType,
211 (Ptr) & theSpec, sizeof(theSpec), &actualSize);
212 wxString fName = wxMacFSSpec2MacFilename(&theSpec);
213 MacPrintFile(fName);
214 }
215 return noErr;
216 }
217
218 // AEOApp calls MacNewFile
219
220 short wxApp::MacHandleAEOApp(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
221 {
222 MacNewFile() ;
223 return noErr ;
224 }
225
226 // AEQuit attempts to quite the application
227
228 short wxApp::MacHandleAEQuit(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
229 {
230 /* wxWindow* win = GetTopWindow() ;
231 if ( win )
232 {
233 win->Close(TRUE ) ;
234 }
235 else
236 */
237 {
238 ExitMainLoop() ;
239 }
240 return noErr ;
241 }
242
243 //----------------------------------------------------------------------
244 // Support Routines linking the Mac...File Calls to the Document Manager
245 //----------------------------------------------------------------------
246
247 void wxApp::MacOpenFile(const wxString & fileName )
248 {
249 wxDocManager* dm = wxDocManager::GetDocumentManager() ;
250 if ( dm )
251 dm->CreateDocument(fileName , wxDOC_SILENT ) ;
252 }
253
254 void wxApp::MacPrintFile(const wxString & fileName )
255 {
256 wxDocManager* dm = wxDocManager::GetDocumentManager() ;
257 if ( dm )
258 {
259 wxDocument *doc = dm->CreateDocument(fileName , wxDOC_SILENT ) ;
260 if ( doc )
261 {
262 wxView* view = doc->GetFirstView() ;
263 if( view )
264 {
265 wxPrintout *printout = view->OnCreatePrintout();
266 if (printout)
267 {
268 wxPrinter printer;
269 printer.Print(view->GetFrame(), printout, TRUE);
270 delete printout;
271 }
272 }
273 if (doc->Close())
274 {
275 doc->DeleteAllViews();
276 dm->RemoveDocument(doc) ;
277 }
278 }
279 }
280 }
281
282 void wxApp::MacNewFile()
283 {
284 }
285
286 //----------------------------------------------------------------------
287 // Carbon Event Handler
288 //----------------------------------------------------------------------
289
290 #if TARGET_CARBON
291
292 static const EventTypeSpec eventList[] =
293 {
294 { kEventClassCommand, kEventProcessCommand } ,
295 { kEventClassCommand, kEventCommandUpdateStatus } ,
296
297 { kEventClassApplication , kEventAppActivated } ,
298 { kEventClassApplication , kEventAppDeactivated } ,
299 // handling the quit event is not recommended by apple
300 // rather using the quit apple event - which we do
301
302 { kEventClassAppleEvent , kEventAppleEvent } ,
303
304 { kEventClassMouse , kEventMouseDown } ,
305 { 'WXMC' , 'WXMC' }
306 } ;
307
308 static pascal OSStatus MenuEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
309 {
310 OSStatus result = eventNotHandledErr ;
311 UInt32 kind = GetEventKind( event ) ;
312
313 return result ;
314 }
315
316 // due to the rather low-level event API of wxWindows, we cannot use RunApplicationEventLoop
317 // but have to use ReceiveNextEvent dealing with events manually, therefore we also have
318 // deal with clicks in the menu bar explicitely
319
320 static pascal OSStatus MouseEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
321 {
322 OSStatus result = eventNotHandledErr ;
323
324 switch( GetEventKind(event) )
325 {
326 case kEventMouseDown :
327 {
328 Point point ;
329 WindowRef window ;
330
331 GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL,
332 sizeof( Point ), NULL, &point );
333 short windowPart = ::FindWindow(point, &window);
334
335 if ( windowPart == inMenuBar )
336 {
337 MenuSelect( point ) ;
338 result = noErr ;
339 }
340 }
341 break ;
342 }
343
344 return result ;
345 }
346
347 static pascal OSStatus CommandEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
348 {
349 OSStatus result = eventNotHandledErr ;
350
351 HICommand command ;
352
353 GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL,
354 sizeof( HICommand ), NULL, &command );
355
356 MenuCommand id = command.commandID ;
357 if ( id == kHICommandPreferences )
358 id = wxApp::s_macPreferencesMenuItemId ;
359
360 wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
361 wxMenu* menu = NULL ;
362 wxMenuItem* item = NULL ;
363
364 if ( mbar )
365 item = mbar->FindItem( id , &menu ) ;
366
367 if ( item == NULL || menu == NULL || mbar == NULL )
368 return result ;
369
370 switch( GetEventKind( event ) )
371 {
372 case kEventProcessCommand :
373 {
374 if (item->IsCheckable())
375 {
376 item->Check( !item->IsChecked() ) ;
377 }
378
379 menu->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ;
380 result = noErr ;
381 }
382 break ;
383 case kEventCommandUpdateStatus:
384 // eventually trigger an updateui round
385 result = noErr ;
386 break ;
387 default :
388 break ;
389 }
390
391 return result ;
392 }
393
394 static pascal OSStatus ApplicationEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
395 {
396 OSStatus result = eventNotHandledErr ;
397 switch ( GetEventKind( event ) )
398 {
399 case kEventAppActivated :
400 {
401 wxTheApp->MacResume( true ) ;
402 result = noErr ;
403 }
404 break ;
405 case kEventAppDeactivated :
406 {
407 wxTheApp->MacSuspend( true ) ;
408 result = noErr ;
409 }
410 break ;
411 default :
412 break ;
413 }
414 return result ;
415 }
416
417 pascal OSStatus wxAppEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
418 {
419 OSStatus result = eventNotHandledErr ;
420 switch( GetEventClass( event ) )
421 {
422 case kEventClassCommand :
423 result = CommandEventHandler( handler , event , data ) ;
424 break ;
425 case kEventClassApplication :
426 result = ApplicationEventHandler( handler , event , data ) ;
427 break ;
428 case kEventClassMenu :
429 result = MenuEventHandler( handler , event , data ) ;
430 break ;
431 case kEventClassMouse :
432 result = MouseEventHandler( handler , event , data ) ;
433 break ;
434 case kEventClassAppleEvent :
435 {
436 EventRecord rec ;
437 wxMacConvertEventToRecord( event , &rec ) ;
438 result = AEProcessAppleEvent( &rec ) ;
439 }
440 break ;
441 default :
442 break ;
443 }
444
445 return result ;
446 }
447
448 DEFINE_ONE_SHOT_HANDLER_GETTER( wxAppEventHandler )
449
450 #endif
451
452 #if defined(WXMAKINGDLL) && !defined(__DARWIN__)
453 // we know it's there ;-)
454 WXIMPORT char std::__throws_bad_alloc ;
455 #endif
456
457 bool wxApp::Initialize()
458 {
459 int error = 0 ;
460
461 // Mac-specific
462
463 UMAInitToolbox( 4 ) ;
464 SetEventMask( everyEvent ) ;
465 UMAShowWatchCursor() ;
466
467 #if defined(WXMAKINGDLL) && defined(__DARWIN__)
468 // open shared library resources from here since we don't have
469 // __wxinitialize in Mach-O shared libraries
470 wxStAppResource::OpenSharedLibraryResource(NULL);
471 #endif
472
473 #ifndef __DARWIN__
474 // test the minimal configuration necessary
475
476 # if !TARGET_CARBON
477 long theSystem ;
478 long theMachine;
479
480 if (Gestalt(gestaltMachineType, &theMachine) != noErr)
481 {
482 error = kMacSTRWrongMachine;
483 }
484 else if (theMachine < gestaltMacPlus)
485 {
486 error = kMacSTRWrongMachine;
487 }
488 else if (Gestalt(gestaltSystemVersion, &theSystem) != noErr )
489 {
490 error = kMacSTROldSystem ;
491 }
492 else if ( theSystem < 0x0860 )
493 {
494 error = kMacSTROldSystem ;
495 }
496 else if ((long)GetApplLimit() - (long)ApplicationZone() < kMacMinHeap)
497 {
498 error = kMacSTRSmallSize;
499 }
500 # endif
501 /*
502 else
503 {
504 if ( !UMAHasAppearance() )
505 {
506 error = kMacSTRNoPre8Yet ;
507 }
508 }
509 */
510 #endif
511
512 // if we encountered any problems so far, give the error code and exit immediately
513
514 if ( error )
515 {
516 wxStAppResource resload ;
517 short itemHit;
518 Str255 message;
519
520 GetIndString(message, 128, error);
521 UMAShowArrowCursor() ;
522 ParamText("\pFatal Error", message, (ConstStr255Param)"\p", (ConstStr255Param)"\p");
523 itemHit = Alert(128, nil);
524 return FALSE ;
525 }
526
527 #ifndef __DARWIN__
528 # if __option(profile)
529 ProfilerInit( collectDetailed, bestTimeBase , 20000 , 40 ) ;
530 # endif
531 #endif
532
533 #ifndef __DARWIN__
534 // now avoid exceptions thrown for new (bad_alloc)
535 // FIXME CS for some changes outside wxMac does not compile anymore
536 #if 0
537 std::__throws_bad_alloc = 0 ;
538 #endif
539
540 #endif
541
542 s_macCursorRgn = ::NewRgn() ;
543
544 wxClassInfo::InitializeClasses();
545
546 #if wxUSE_RESOURCES
547 // wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
548 #endif
549
550 #if wxUSE_THREADS
551 wxPendingEventsLocker = new wxCriticalSection;
552 #endif
553
554 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
555 wxTheColourDatabase->Initialize();
556
557 #ifdef __WXDEBUG__
558 #if wxUSE_LOG
559 // flush the logged messages if any and install a 'safer' log target: the
560 // default one (wxLogGui) can't be used after the resources are freed just
561 // below and the user suppliedo ne might be even more unsafe (using any
562 // wxWindows GUI function is unsafe starting from now)
563 wxLog::DontCreateOnDemand();
564
565 // this will flush the old messages if any
566 delete wxLog::SetActiveTarget(new wxLogStderr);
567 #endif // wxUSE_LOG
568 #endif
569
570 wxWinMacWindowList = new wxList(wxKEY_INTEGER);
571 wxWinMacControlList = new wxList(wxKEY_INTEGER);
572
573 wxInitializeStockLists();
574 wxInitializeStockObjects();
575
576 #if wxUSE_WX_RESOURCES
577 wxInitializeResourceSystem();
578 #endif
579
580 wxBitmap::InitStandardHandlers();
581
582 wxModule::RegisterModules();
583 if (!wxModule::InitializeModules()) {
584 return FALSE;
585 }
586
587 wxMacCreateNotifierTable() ;
588
589 UMAShowArrowCursor() ;
590
591 return TRUE;
592 }
593
594 bool wxApp::OnInitGui()
595 {
596 if( !wxAppBase::OnInitGui() )
597 return false ;
598
599 #if TARGET_CARBON
600 InstallStandardEventHandler( GetApplicationEventTarget() ) ;
601
602 InstallApplicationEventHandler(
603 GetwxAppEventHandlerUPP(),
604 GetEventTypeCount(eventList), eventList, wxTheApp, &((EventHandlerRef)wxTheApp->m_macEventHandler));
605 #endif
606
607 #if defined(UNIVERSAL_INTERFACES_VERSION) && (UNIVERSAL_INTERFACES_VERSION >= 0x0340)
608 AEInstallEventHandler( kCoreEventClass , kAEOpenDocuments ,
609 NewAEEventHandlerUPP(AEHandleODoc) ,
610 0 , FALSE ) ;
611 AEInstallEventHandler( kCoreEventClass , kAEOpenApplication ,
612 NewAEEventHandlerUPP(AEHandleOApp) ,
613 0 , FALSE ) ;
614 AEInstallEventHandler( kCoreEventClass , kAEPrintDocuments ,
615 NewAEEventHandlerUPP(AEHandlePDoc) ,
616 0 , FALSE ) ;
617 AEInstallEventHandler( kCoreEventClass , kAEQuitApplication ,
618 NewAEEventHandlerUPP(AEHandleQuit) ,
619 0 , FALSE ) ;
620 #else
621 AEInstallEventHandler( kCoreEventClass , kAEOpenDocuments ,
622 NewAEEventHandlerProc(AEHandleODoc) ,
623 0 , FALSE ) ;
624 AEInstallEventHandler( kCoreEventClass , kAEOpenApplication ,
625 NewAEEventHandlerProc(AEHandleOApp) ,
626 0 , FALSE ) ;
627 AEInstallEventHandler( kCoreEventClass , kAEPrintDocuments ,
628 NewAEEventHandlerProc(AEHandlePDoc) ,
629 0 , FALSE ) ;
630 AEInstallEventHandler( kCoreEventClass , kAEQuitApplication ,
631 NewAEEventHandlerProc(AEHandleQuit) ,
632 0 , FALSE ) ;
633 #endif
634
635 return TRUE ;
636 }
637
638 void wxApp::CleanUp()
639 {
640 wxToolTip::RemoveToolTips() ;
641 #if wxUSE_LOG
642 // flush the logged messages if any and install a 'safer' log target: the
643 // default one (wxLogGui) can't be used after the resources are freed just
644 // below and the user suppliedo ne might be even more unsafe (using any
645 // wxWindows GUI function is unsafe starting from now)
646 wxLog::DontCreateOnDemand();
647
648 // this will flush the old messages if any
649 delete wxLog::SetActiveTarget(new wxLogStderr);
650 #endif // wxUSE_LOG
651
652 // One last chance for pending objects to be cleaned up
653 wxTheApp->DeletePendingObjects();
654
655 wxModule::CleanUpModules();
656
657 #if wxUSE_WX_RESOURCES
658 wxCleanUpResourceSystem();
659 #endif
660
661 wxDeleteStockObjects() ;
662
663 // Destroy all GDI lists, etc.
664 wxDeleteStockLists();
665
666 delete wxTheColourDatabase;
667 wxTheColourDatabase = NULL;
668
669 wxBitmap::CleanUpHandlers();
670
671 wxMacDestroyNotifierTable() ;
672 if (wxWinMacWindowList) {
673 delete wxWinMacWindowList ;
674 }
675 if (wxWinMacControlList) {
676 delete wxWinMacControlList ;
677 }
678 delete wxPendingEvents;
679
680 #if wxUSE_THREADS
681 delete wxPendingEventsLocker;
682 // If we don't do the following, we get an apparent memory leak.
683 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
684 #endif
685
686 wxClassInfo::CleanUpClasses();
687
688 #ifndef __DARWIN__
689 # if __option(profile)
690 ProfilerDump( "\papp.prof" ) ;
691 ProfilerTerm() ;
692 # endif
693 #endif
694
695 delete wxTheApp;
696 wxTheApp = NULL;
697
698 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
699 // At this point we want to check if there are any memory
700 // blocks that aren't part of the wxDebugContext itself,
701 // as a special case. Then when dumping we need to ignore
702 // wxDebugContext, too.
703 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
704 {
705 wxLogDebug(wxT("There were memory leaks."));
706 wxDebugContext::Dump();
707 wxDebugContext::PrintStatistics();
708 }
709 // wxDebugContext::SetStream(NULL, NULL);
710 #endif
711
712 #if wxUSE_LOG
713 // do it as the very last thing because everything else can log messages
714 delete wxLog::SetActiveTarget(NULL);
715 #endif // wxUSE_LOG
716
717 #if defined(WXMAKINGDLL) && defined(__DARWIN__)
718 // close shared library resources from here since we don't have
719 // __wxterminate in Mach-O shared libraries
720 wxStAppResource::CloseSharedLibraryResource();
721 #endif
722
723 UMACleanupToolbox() ;
724 if (s_macCursorRgn) {
725 ::DisposeRgn((RgnHandle)s_macCursorRgn);
726 }
727
728 #if 0
729 TerminateAE() ;
730 #endif
731 }
732
733 //----------------------------------------------------------------------
734 // wxEntry
735 //----------------------------------------------------------------------
736
737 // extern variable for shared library resource id
738 // need to be able to find it with NSLookupAndBindSymbol
739 short gSharedLibraryResource = kResFileNotOpened ;
740
741 #if defined(WXMAKINGDLL) && defined(__DARWIN__)
742 CFBundleRef gSharedLibraryBundle = NULL;
743 #endif /* WXMAKINGDLL && __DARWIN__ */
744
745 wxStAppResource::wxStAppResource()
746 {
747 m_currentRefNum = CurResFile() ;
748 if ( gSharedLibraryResource != kResFileNotOpened )
749 {
750 UseResFile( gSharedLibraryResource ) ;
751 }
752 }
753
754 wxStAppResource::~wxStAppResource()
755 {
756 if ( m_currentRefNum != kResFileNotOpened )
757 {
758 UseResFile( m_currentRefNum ) ;
759 }
760 }
761
762 void wxStAppResource::OpenSharedLibraryResource(const void *initBlock)
763 {
764 gSharedLibraryResource = kResFileNotOpened;
765
766 #ifdef WXMAKINGDLL
767 if ( initBlock != NULL ) {
768 const CFragInitBlock *theInitBlock = (const CFragInitBlock *)initBlock;
769 FSSpec *fileSpec = NULL;
770
771 if (theInitBlock->fragLocator.where == kDataForkCFragLocator) {
772 fileSpec = theInitBlock->fragLocator.u.onDisk.fileSpec;
773 }
774 else if (theInitBlock->fragLocator.where == kResourceCFragLocator) {
775 fileSpec = theInitBlock->fragLocator.u.inSegs.fileSpec;
776 }
777
778 if (fileSpec != NULL) {
779 gSharedLibraryResource = FSpOpenResFile(fileSpec, fsRdPerm);
780 }
781 }
782 else {
783 #ifdef __DARWIN__
784 // Open the shared library resource file if it is not yet open
785 NSSymbol theSymbol;
786 NSModule theModule;
787 const char *theLibPath;
788
789 gSharedLibraryBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.wxwindows.wxWindows"));
790 if (gSharedLibraryBundle != NULL) {
791 // wxWindows has been bundled into a framework
792 // load the framework resources
793
794 gSharedLibraryResource = CFBundleOpenBundleResourceMap(gSharedLibraryBundle);
795 }
796 else {
797 // wxWindows is a simple dynamic shared library
798 // load the resources from the data fork of a separate resource file
799 char *theResPath;
800 char *theName;
801 char *theExt;
802 FSRef theResRef;
803 OSErr theErr = noErr;
804
805 // get the library path
806 theSymbol = NSLookupAndBindSymbol("_gSharedLibraryResource");
807 theModule = NSModuleForSymbol(theSymbol);
808 theLibPath = NSLibraryNameForModule(theModule);
809
810 wxLogDebug( wxT("wxMac library installation name is '%s'"),
811 theLibPath );
812
813 // allocate copy to replace .dylib.* extension with .rsrc
814 theResPath = strdup(theLibPath);
815 if (theResPath != NULL) {
816 theName = strrchr(theResPath, '/');
817 if (theName == NULL) {
818 // no directory elements in path
819 theName = theResPath;
820 }
821 // find ".dylib" shared library extension
822 theExt = strstr(theName, ".dylib");
823 // overwrite extension with ".rsrc"
824 strcpy(theExt, ".rsrc");
825
826 wxLogDebug( wxT("wxMac resources file name is '%s'"),
827 theResPath );
828
829 theErr = FSPathMakeRef((UInt8 *) theResPath, &theResRef, false);
830 if (theErr != noErr) {
831 // try in current directory (using name only)
832 theErr = FSPathMakeRef((UInt8 *) theName, &theResRef, false);
833 }
834
835 // open the resource file
836 if (theErr == noErr) {
837 theErr = FSOpenResourceFile( &theResRef, 0, NULL, fsRdPerm,
838 &gSharedLibraryResource);
839 }
840 if (theErr != noErr) {
841 wxLogDebug( wxT("unable to open wxMac resource file '%s'"),
842 theResPath );
843 }
844
845 // free duplicated resource file path
846 free(theResPath);
847 }
848 }
849 #endif /* __DARWIN__ */
850 }
851 #endif /* WXMAKINGDLL */
852 }
853
854 void wxStAppResource::CloseSharedLibraryResource()
855 {
856 #ifdef WXMAKINGDLL
857 // Close the shared library resource file
858 if (gSharedLibraryResource != kResFileNotOpened) {
859 #ifdef __DARWIN__
860 if (gSharedLibraryBundle != NULL) {
861 CFBundleCloseBundleResourceMap(gSharedLibraryBundle,
862 gSharedLibraryResource);
863 gSharedLibraryBundle = NULL;
864 }
865 else
866 #endif /* __DARWIN__ */
867 {
868 CloseResFile(gSharedLibraryResource);
869 }
870 gSharedLibraryResource = kResFileNotOpened;
871 }
872 #endif /* WXMAKINGDLL */
873 }
874
875 #if defined(WXMAKINGDLL) && !defined(__DARWIN__)
876
877 // for shared libraries we have to manually get the correct resource
878 // ref num upon initializing and releasing when terminating, therefore
879 // the __wxinitialize and __wxterminate must be used
880
881 extern "C" {
882 void __sinit(void); /* (generated by linker) */
883 pascal OSErr __initialize(const CFragInitBlock *theInitBlock);
884 pascal void __terminate(void);
885 }
886
887 pascal OSErr __wxinitialize(const CFragInitBlock *theInitBlock)
888 {
889 wxStAppResource::OpenSharedLibraryResource( theInitBlock ) ;
890 return __initialize( theInitBlock ) ;
891 }
892
893 pascal void __wxterminate(void)
894 {
895 wxStAppResource::CloseSharedLibraryResource() ;
896 __terminate() ;
897 }
898
899 #endif /* WXMAKINGDLL && !__DARWIN__ */
900
901 int WXDLLEXPORT wxEntryStart( int WXUNUSED(argc), char *WXUNUSED(argv)[] )
902 {
903 return wxApp::Initialize();
904 }
905
906 int WXDLLEXPORT wxEntryInitGui()
907 {
908 return wxTheApp->OnInitGui();
909 }
910
911 void WXDLLEXPORT wxEntryCleanup()
912 {
913 wxApp::CleanUp();
914 }
915
916 int wxEntry( int argc, char *argv[] , bool enterLoop )
917 {
918 #ifdef __MWERKS__
919 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
920 // This seems to be necessary since there are 'rogue'
921 // objects present at this point (perhaps global objects?)
922 // Setting a checkpoint will ignore them as far as the
923 // memory checking facility is concerned.
924 // Of course you may argue that memory allocated in globals should be
925 // checked, but this is a reasonable compromise.
926 wxDebugContext::SetCheckpoint();
927 #endif
928 #endif
929 if (!wxEntryStart(argc, argv)) {
930 return 0;
931 }
932 // create the application object or ensure that one already exists
933 if (!wxTheApp)
934 {
935 // The app may have declared a global application object, but we recommend
936 // the IMPLEMENT_APP macro is used instead, which sets an initializer
937 // function for delayed, dynamic app object construction.
938 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
939 wxT("No initializer - use IMPLEMENT_APP macro.") );
940
941 wxTheApp = (wxApp*) (*wxApp::GetInitializerFunction()) ();
942 }
943
944 wxCHECK_MSG( wxTheApp, 0, wxT("You have to define an instance of wxApp!") );
945
946 #ifdef __DARWIN__
947 // Mac OS X passes a process serial number command line argument when
948 // the application is launched from the Finder. This argument must be
949 // removed from the command line arguments before being handled by the
950 // application (otherwise applications would need to handle it)
951
952 if (argc > 1) {
953 if (strncmp(argv[1], "-psn_", 5) == 0) {
954 // assume the argument is always the only one and remove it
955 --argc;
956 }
957 }
958 #else
959 argc = 0 ; // currently we don't support files as parameters
960 #endif
961 // we could try to get the open apple events here to adjust argc and argv better
962
963 wxTheApp->argc = argc;
964 wxTheApp->argv = argv;
965
966 // GUI-specific initialization, such as creating an app context.
967 wxEntryInitGui();
968
969 // Here frames insert themselves automatically
970 // into wxTopLevelWindows by getting created
971 // in OnInit().
972
973 int retValue = 0;
974
975 if ( wxTheApp->OnInit() )
976 {
977 if ( enterLoop )
978 {
979 retValue = wxTheApp->OnRun();
980 }
981 else
982 // We want to initialize, but not run or exit immediately.
983 return 1;
984 }
985 //else: app initialization failed, so we skipped OnRun()
986
987 wxWindow *topWindow = wxTheApp->GetTopWindow();
988 if ( topWindow )
989 {
990 // Forcibly delete the window.
991 if ( topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
992 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
993 {
994 topWindow->Close(TRUE);
995 wxTheApp->DeletePendingObjects();
996 }
997 else
998 {
999 delete topWindow;
1000 wxTheApp->SetTopWindow(NULL);
1001 }
1002 }
1003
1004 wxTheApp->OnExit();
1005
1006 wxEntryCleanup();
1007
1008 return retValue;
1009 }
1010
1011 #if TARGET_CARBON
1012
1013 bool wxMacConvertEventToRecord( EventRef event , EventRecord *rec)
1014 {
1015 bool converted = ConvertEventRefToEventRecord( event,rec) ;
1016 OSStatus err = noErr ;
1017 if ( !converted )
1018 {
1019 switch( GetEventClass( event ) )
1020 {
1021 case kEventClassKeyboard :
1022 {
1023 converted = true ;
1024 switch( GetEventKind(event) )
1025 {
1026 case kEventRawKeyDown :
1027 rec->what = keyDown ;
1028 break ;
1029 case kEventRawKeyRepeat :
1030 rec->what = autoKey ;
1031 break ;
1032 case kEventRawKeyUp :
1033 rec->what = keyUp ;
1034 break ;
1035 case kEventRawKeyModifiersChanged :
1036 rec->what = nullEvent ;
1037 break ;
1038 default :
1039 converted = false ;
1040 break ;
1041 }
1042 if ( converted )
1043 {
1044 UInt32 keyCode ;
1045 unsigned char charCode ;
1046 UInt32 modifiers ;
1047 GetMouse( &rec->where) ;
1048
1049 err = GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, 4, NULL, &modifiers);
1050 err = GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, 4, NULL, &keyCode);
1051 err = GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, 1, NULL, &charCode);
1052 rec->modifiers = modifiers ;
1053 rec->message = (keyCode << 8 ) + charCode ;
1054 }
1055 }
1056 break ;
1057 case kEventClassTextInput :
1058 {
1059 switch( GetEventKind( event ) )
1060 {
1061 case kEventTextInputUnicodeForKeyEvent :
1062 {
1063 EventRef rawEvent ;
1064 err = GetEventParameter( event , kEventParamTextInputSendKeyboardEvent ,typeEventRef,NULL,sizeof(rawEvent),NULL,&rawEvent ) ;
1065 converted = true ;
1066 {
1067 UInt32 keyCode ;
1068 unsigned char charCode ;
1069 UInt32 modifiers ;
1070 GetMouse( &rec->where) ;
1071 rec->what = keyDown ;
1072 err = GetEventParameter(rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, 4, NULL, &modifiers);
1073 err = GetEventParameter(rawEvent, kEventParamKeyCode, typeUInt32, NULL, 4, NULL, &keyCode);
1074 err = GetEventParameter(rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, 1, NULL, &charCode);
1075 rec->modifiers = modifiers ;
1076 rec->message = (keyCode << 8 ) + charCode ;
1077 }
1078 }
1079 break ;
1080 default :
1081 break ;
1082 }
1083 }
1084 break ;
1085 }
1086 }
1087
1088 return converted ;
1089 }
1090
1091 /*
1092 pascal OSStatus wxMacApplicationEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
1093 {
1094 OSStatus result = eventNotHandledErr ;
1095
1096 EventRecord rec ;
1097 switch ( GetEventClass( event ) )
1098 {
1099 case kEventClassKeyboard :
1100 if ( wxMacConvertEventToRecord( event , &rec ) )
1101 {
1102 wxTheApp->MacHandleModifierEvents( &rec ) ;
1103 wxTheApp->MacHandleOneEvent( &rec ) ;
1104 result = noErr ;
1105 }
1106 break ;
1107 case kEventClassTextInput :
1108 if ( wxMacConvertEventToRecord( event , &rec ) )
1109 {
1110 wxTheApp->MacHandleModifierEvents( &rec ) ;
1111 wxTheApp->MacHandleOneEvent( &rec ) ;
1112 result = noErr ;
1113 }
1114 break ;
1115 default :
1116 break ;
1117 }
1118 return result ;
1119 }
1120 */
1121 #endif
1122
1123 // Static member initialization
1124 wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
1125
1126 wxApp::wxApp()
1127 {
1128 m_topWindow = NULL;
1129 wxTheApp = this;
1130
1131 #if WXWIN_COMPATIBILITY_2_2
1132 m_wantDebugOutput = TRUE;
1133 #endif
1134
1135 argc = 0;
1136 argv = NULL;
1137
1138 m_printMode = wxPRINT_WINDOWS;
1139 m_auto3D = TRUE;
1140 }
1141
1142 bool wxApp::Initialized()
1143 {
1144 if (GetTopWindow())
1145 return TRUE;
1146 else
1147 return FALSE;
1148 }
1149
1150 int wxApp::MainLoop()
1151 {
1152 m_keepGoing = TRUE;
1153
1154 while (m_keepGoing)
1155 {
1156 MacDoOneEvent() ;
1157 }
1158
1159 return 0;
1160 }
1161
1162 // Returns TRUE if more time is needed.
1163 bool wxApp::ProcessIdle()
1164 {
1165 wxIdleEvent event;
1166 event.SetEventObject(this);
1167 ProcessEvent(event);
1168
1169 return event.MoreRequested();
1170 }
1171
1172 void wxApp::ExitMainLoop()
1173 {
1174 m_keepGoing = FALSE;
1175 }
1176
1177 // Is a message/event pending?
1178 bool wxApp::Pending()
1179 {
1180 #if TARGET_CARBON
1181 return GetNumEventsInQueue( GetMainEventQueue() ) > 0 ;
1182 #else
1183 EventRecord event ;
1184
1185 return EventAvail( everyEvent , &event ) ;
1186 #endif
1187 }
1188
1189 // Dispatch a message.
1190 void wxApp::Dispatch()
1191 {
1192 MacDoOneEvent() ;
1193 }
1194
1195 void wxApp::OnIdle(wxIdleEvent& event)
1196 {
1197 // Avoid recursion (via ProcessEvent default case)
1198 if ( s_inOnIdle )
1199 return;
1200
1201
1202 s_inOnIdle = TRUE;
1203
1204 // 'Garbage' collection of windows deleted with Close().
1205 DeletePendingObjects();
1206
1207 // flush the logged messages if any
1208 wxLog *pLog = wxLog::GetActiveTarget();
1209 if ( pLog != NULL && pLog->HasPendingMessages() )
1210 pLog->Flush();
1211
1212 // Send OnIdle events to all windows
1213 bool needMore = SendIdleEvents();
1214
1215 if (needMore)
1216 event.RequestMore(TRUE);
1217
1218 // If they are pending events, we must process them: pending events are
1219 // either events to the threads other than main or events posted with
1220 // wxPostEvent() functions
1221 wxMacProcessNotifierAndPendingEvents();
1222
1223 s_inOnIdle = FALSE;
1224 }
1225
1226 void wxWakeUpIdle()
1227 {
1228 wxMacWakeUp() ;
1229 }
1230
1231 // Send idle event to all top-level windows
1232 bool wxApp::SendIdleEvents()
1233 {
1234 bool needMore = FALSE;
1235 wxWindowListNode* node = wxTopLevelWindows.GetFirst();
1236 while (node)
1237 {
1238 wxWindow* win = node->GetData();
1239 if (SendIdleEvents(win))
1240 needMore = TRUE;
1241
1242 node = node->GetNext();
1243 }
1244 return needMore;
1245 }
1246
1247 // Send idle event to window and all subwindows
1248 bool wxApp::SendIdleEvents(wxWindow* win)
1249 {
1250 bool needMore = FALSE;
1251
1252 wxIdleEvent event;
1253 event.SetEventObject(win);
1254 win->ProcessEvent(event);
1255
1256 if (event.MoreRequested())
1257 needMore = TRUE;
1258
1259 wxWindowListNode* node = win->GetChildren().GetFirst();
1260 while (node)
1261 {
1262 wxWindow* win = node->GetData();
1263 if (SendIdleEvents(win))
1264 needMore = TRUE;
1265
1266 node = node->GetNext();
1267 }
1268 return needMore ;
1269 }
1270
1271 void wxApp::DeletePendingObjects()
1272 {
1273 wxNode *node = wxPendingDelete.GetFirst();
1274 while (node)
1275 {
1276 wxObject *obj = (wxObject *)node->GetData();
1277
1278 delete obj;
1279
1280 if (wxPendingDelete.Member(obj))
1281 delete node;
1282
1283 // Deleting one object may have deleted other pending
1284 // objects, so start from beginning of list again.
1285 node = wxPendingDelete.GetFirst();
1286 }
1287 }
1288
1289 void wxExit()
1290 {
1291 wxLogError(_("Fatal error: exiting"));
1292
1293 wxApp::CleanUp();
1294 ::ExitToShell() ;
1295 }
1296
1297 void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
1298 {
1299 if (GetTopWindow())
1300 GetTopWindow()->Close(TRUE);
1301 }
1302
1303 // Default behaviour: close the application with prompts. The
1304 // user can veto the close, and therefore the end session.
1305 void wxApp::OnQueryEndSession(wxCloseEvent& event)
1306 {
1307 if (GetTopWindow())
1308 {
1309 if (!GetTopWindow()->Close(!event.CanVeto()))
1310 event.Veto(TRUE);
1311 }
1312 }
1313
1314 extern "C" void wxCYield() ;
1315 void wxCYield()
1316 {
1317 wxYield() ;
1318 }
1319
1320 // Yield to other processes
1321
1322 bool wxApp::Yield(bool onlyIfNeeded)
1323 {
1324 if (s_inYield)
1325 {
1326 if ( !onlyIfNeeded )
1327 {
1328 wxFAIL_MSG( wxT("wxYield called recursively" ) );
1329 }
1330
1331 return FALSE;
1332 }
1333
1334 s_inYield = TRUE;
1335
1336 #if wxUSE_THREADS
1337 YieldToAnyThread() ;
1338 #endif
1339 // by definition yield should handle all non-processed events
1340 #if TARGET_CARBON
1341 EventRef theEvent;
1342
1343 OSStatus status = noErr ;
1344 do
1345 {
1346 s_inReceiveEvent = true ;
1347 status = ReceiveNextEvent(0, NULL,kEventDurationNoWait,true,&theEvent) ;
1348 s_inReceiveEvent = false ;
1349
1350 if ( status == eventLoopTimedOutErr )
1351 {
1352 // make sure next time the event loop will trigger idle events
1353 sleepTime = kEventDurationNoWait ;
1354 }
1355 else if ( status == eventLoopQuitErr )
1356 {
1357 // according to QA1061 this may also occur when a WakeUp Process
1358 // is executed
1359 }
1360 else
1361 {
1362 MacHandleOneEvent( theEvent ) ;
1363 ReleaseEvent(theEvent);
1364 }
1365 } while( status == noErr ) ;
1366 #else
1367 EventRecord event ;
1368
1369 // having a larger value here leads to large performance slowdowns
1370 // so we cannot give background apps more processor time here
1371 // we do so however having a large sleep value in the main event loop
1372 sleepTime = 0 ;
1373
1374 while ( !IsExiting() && WaitNextEvent(everyEvent, &event,sleepTime, (RgnHandle) wxApp::s_macCursorRgn))
1375 {
1376 MacHandleModifierEvents( &event ) ;
1377 MacHandleOneEvent( &event );
1378 if ( event.what != kHighLevelEvent )
1379 SetRectRgn( (RgnHandle) wxApp::s_macCursorRgn , event.where.h , event.where.v , event.where.h + 1 , event.where.v + 1 ) ;
1380 }
1381 MacHandleModifierEvents( &event ) ;
1382 #endif
1383
1384 wxMacProcessNotifierAndPendingEvents() ;
1385 s_inYield = FALSE;
1386
1387 return TRUE;
1388 }
1389
1390 // platform specifics
1391
1392 void wxApp::MacSuspend( bool convertClipboard )
1393 {
1394 #if !TARGET_CARBON
1395 // we have to deactive the top level windows manually
1396
1397 wxWindowListNode* node = wxTopLevelWindows.GetFirst();
1398 while (node)
1399 {
1400 wxTopLevelWindow* win = (wxTopLevelWindow*) node->Data();
1401 win->MacActivate( ((EventRecord*) MacGetCurrentEvent())->when , false ) ;
1402
1403 node = node->GetNext();
1404 }
1405
1406 ::HideFloatingWindows() ;
1407 #endif
1408 s_lastMouseDown = 0 ;
1409
1410 if( convertClipboard )
1411 {
1412 MacConvertPrivateToPublicScrap() ;
1413 }
1414 }
1415
1416 extern wxList wxModalDialogs;
1417
1418 void wxApp::MacResume( bool convertClipboard )
1419 {
1420 s_lastMouseDown = 0 ;
1421 if( convertClipboard )
1422 {
1423 MacConvertPublicToPrivateScrap() ;
1424 }
1425
1426 #if !TARGET_CARBON
1427 ::ShowFloatingWindows() ;
1428 // raise modal dialogs in case a non modal window was selected to activate the app
1429
1430 wxNode* node = wxModalDialogs.GetFirst();
1431 while (node)
1432 {
1433 wxDialog* dialog = (wxDialog *) node->GetData();
1434 dialog->Raise();
1435
1436 node = node->GetNext();
1437 }
1438 #endif
1439 }
1440
1441 void wxApp::MacConvertPrivateToPublicScrap()
1442 {
1443 }
1444
1445 void wxApp::MacConvertPublicToPrivateScrap()
1446 {
1447 }
1448
1449 void wxApp::MacDoOneEvent()
1450 {
1451 #if TARGET_CARBON
1452 EventRef theEvent;
1453
1454 s_inReceiveEvent = true ;
1455 OSStatus status = ReceiveNextEvent(0, NULL,sleepTime,true,&theEvent) ;
1456 s_inReceiveEvent = false ;
1457 if ( status == eventLoopTimedOutErr )
1458 {
1459 if ( wxTheApp->ProcessIdle() )
1460 sleepTime = kEventDurationNoWait ;
1461 else
1462 sleepTime = kEventDurationForever ;
1463 }
1464 else if ( status == eventLoopQuitErr )
1465 {
1466 // according to QA1061 this may also occur when a WakeUp Process
1467 // is executed
1468 }
1469 else
1470 {
1471 MacHandleOneEvent( theEvent ) ;
1472 ReleaseEvent(theEvent);
1473 }
1474 #else
1475 EventRecord event ;
1476
1477 EventMask eventMask = everyEvent ;
1478
1479 if (WaitNextEvent(eventMask, &event, sleepTime, (RgnHandle) s_macCursorRgn))
1480 {
1481 MacHandleModifierEvents( &event ) ;
1482 MacHandleOneEvent( &event );
1483 }
1484 else
1485 {
1486 MacHandleModifierEvents( &event ) ;
1487 // idlers
1488 WindowPtr window = ::FrontWindow() ;
1489 if ( window )
1490 ::IdleControls( window ) ;
1491
1492 if ( wxTheApp->ProcessIdle() )
1493 sleepTime = 0 ;
1494 else
1495 sleepTime = GetCaretTime() / 2 ;
1496 }
1497 if ( event.what != kHighLevelEvent )
1498 SetRectRgn( (RgnHandle) s_macCursorRgn , event.where.h , event.where.v , event.where.h + 1 , event.where.v + 1 ) ;
1499 #endif
1500 // repeaters
1501
1502 DeletePendingObjects() ;
1503 wxMacProcessNotifierAndPendingEvents() ;
1504 }
1505
1506 void wxApp::MacHandleOneEvent( WXEVENTREF evr )
1507 {
1508 #if TARGET_CARBON
1509 EventTargetRef theTarget;
1510 theTarget = GetEventDispatcherTarget();
1511 m_macCurrentEvent = evr ;
1512 SendEventToEventTarget ((EventRef) evr , theTarget);
1513 #else
1514 EventRecord* ev = (EventRecord*) evr ;
1515 m_macCurrentEvent = ev ;
1516
1517 wxApp::sm_lastMessageTime = ev->when ;
1518
1519 switch (ev->what)
1520 {
1521 case mouseDown:
1522 MacHandleMouseDownEvent( ev ) ;
1523 if ( ev->modifiers & controlKey )
1524 s_lastMouseDown = 2;
1525 else
1526 s_lastMouseDown = 1;
1527 break;
1528 case mouseUp:
1529 if ( s_lastMouseDown == 2 )
1530 {
1531 ev->modifiers |= controlKey ;
1532 }
1533 else
1534 {
1535 ev->modifiers &= ~controlKey ;
1536 }
1537 MacHandleMouseUpEvent( ev ) ;
1538 s_lastMouseDown = 0;
1539 break;
1540 case activateEvt:
1541 MacHandleActivateEvent( ev ) ;
1542 break;
1543 case updateEvt:
1544 MacHandleUpdateEvent( ev ) ;
1545 break;
1546 case keyDown:
1547 case autoKey:
1548 MacHandleKeyDownEvent( ev ) ;
1549 break;
1550 case keyUp:
1551 MacHandleKeyUpEvent( ev ) ;
1552 break;
1553 case diskEvt:
1554 MacHandleDiskEvent( ev ) ;
1555 break;
1556 case osEvt:
1557 MacHandleOSEvent( ev ) ;
1558 break;
1559 case kHighLevelEvent:
1560 MacHandleHighLevelEvent( ev ) ;
1561 break;
1562 default:
1563 break;
1564 }
1565 #endif
1566 wxMacProcessNotifierAndPendingEvents() ;
1567 }
1568
1569 #if !TARGET_CARBON
1570 bool s_macIsInModalLoop = false ;
1571
1572 void wxApp::MacHandleModifierEvents( WXEVENTREF evr )
1573 {
1574 EventRecord* ev = (EventRecord*) evr ;
1575 if ( ev->modifiers != s_lastModifiers && wxWindow::FindFocus() != NULL )
1576 {
1577 wxKeyEvent event(wxEVT_KEY_DOWN);
1578
1579 event.m_shiftDown = ev->modifiers & shiftKey;
1580 event.m_controlDown = ev->modifiers & controlKey;
1581 event.m_altDown = ev->modifiers & optionKey;
1582 event.m_metaDown = ev->modifiers & cmdKey;
1583
1584 event.m_x = ev->where.h;
1585 event.m_y = ev->where.v;
1586 event.m_timeStamp = ev->when;
1587 wxWindow* focus = wxWindow::FindFocus() ;
1588 event.SetEventObject(focus);
1589
1590 if ( (ev->modifiers ^ s_lastModifiers ) & controlKey )
1591 {
1592 event.m_keyCode = WXK_CONTROL ;
1593 event.SetEventType( ( ev->modifiers & controlKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
1594 focus->GetEventHandler()->ProcessEvent( event ) ;
1595 }
1596 if ( (ev->modifiers ^ s_lastModifiers ) & shiftKey )
1597 {
1598 event.m_keyCode = WXK_SHIFT ;
1599 event.SetEventType( ( ev->modifiers & shiftKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
1600 focus->GetEventHandler()->ProcessEvent( event ) ;
1601 }
1602 if ( (ev->modifiers ^ s_lastModifiers ) & optionKey )
1603 {
1604 event.m_keyCode = WXK_ALT ;
1605 event.SetEventType( ( ev->modifiers & optionKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
1606 focus->GetEventHandler()->ProcessEvent( event ) ;
1607 }
1608 s_lastModifiers = ev->modifiers ;
1609 }
1610 }
1611
1612 void wxApp::MacHandleHighLevelEvent( WXEVENTREF evr )
1613 {
1614 // we must avoid reentrancy problems when processing high level events eg printing
1615 bool former = s_inYield ;
1616 s_inYield = TRUE ;
1617 EventRecord* ev = (EventRecord*) evr ;
1618 ::AEProcessAppleEvent( ev ) ;
1619 s_inYield = former ;
1620 }
1621
1622 void wxApp::MacHandleMouseDownEvent( WXEVENTREF evr )
1623 {
1624 EventRecord* ev = (EventRecord*) evr ;
1625 wxToolTip::RemoveToolTips() ;
1626
1627 WindowRef window;
1628 WindowRef frontWindow = ::FrontNonFloatingWindow() ;
1629 WindowAttributes frontWindowAttributes = NULL ;
1630 if ( frontWindow )
1631 ::GetWindowAttributes( frontWindow , &frontWindowAttributes ) ;
1632
1633 short windowPart = ::FindWindow(ev->where, &window);
1634 wxTopLevelWindowMac* win = wxFindWinFromMacWindow( window ) ;
1635 if ( wxPendingDelete.Member(win) )
1636 return ;
1637
1638 BitMap screenBits;
1639 GetQDGlobalsScreenBits( &screenBits );
1640
1641 switch (windowPart)
1642 {
1643 case inMenuBar :
1644 if ( s_macIsInModalLoop )
1645 {
1646 SysBeep ( 30 ) ;
1647 }
1648 else
1649 {
1650 UInt32 menuresult = MenuSelect(ev->where) ;
1651 MacHandleMenuSelect( HiWord( menuresult ) , LoWord( menuresult ) );
1652 s_lastMouseDown = 0;
1653 }
1654 break ;
1655 case inSysWindow :
1656 SystemClick( ev , window ) ;
1657 s_lastMouseDown = 0;
1658 break ;
1659 case inDrag :
1660 if ( window != frontWindow && s_macIsInModalLoop && !(ev->modifiers & cmdKey ) )
1661 {
1662 SysBeep ( 30 ) ;
1663 }
1664 else
1665 {
1666 DragWindow(window, ev->where, &screenBits.bounds);
1667 if (win)
1668 {
1669 GrafPtr port ;
1670 GetPort( &port ) ;
1671 Point pt = { 0, 0 } ;
1672 SetPortWindowPort(window) ;
1673 LocalToGlobal( &pt ) ;
1674 SetPort( port ) ;
1675 win->SetSize( pt.h , pt.v , -1 ,
1676 -1 , wxSIZE_USE_EXISTING);
1677 }
1678 s_lastMouseDown = 0;
1679 }
1680 break ;
1681 case inGoAway:
1682 if (TrackGoAway(window, ev->where))
1683 {
1684 if ( win )
1685 win->Close() ;
1686 }
1687 s_lastMouseDown = 0;
1688 break;
1689 case inGrow:
1690 {
1691 Rect newContentRect ;
1692 Rect constraintRect ;
1693 constraintRect.top = win->GetMinHeight() ;
1694 if ( constraintRect.top == -1 )
1695 constraintRect.top = 0 ;
1696 constraintRect.left = win->GetMinWidth() ;
1697 if ( constraintRect.left == -1 )
1698 constraintRect.left = 0 ;
1699 constraintRect.right = win->GetMaxWidth() ;
1700 if ( constraintRect.right == -1 )
1701 constraintRect.right = 32000 ;
1702 constraintRect.bottom = win->GetMaxHeight() ;
1703 if ( constraintRect.bottom == -1 )
1704 constraintRect.bottom = 32000 ;
1705
1706 Boolean growResult = ResizeWindow( window , ev->where ,
1707 &constraintRect , &newContentRect ) ;
1708 if ( growResult )
1709 {
1710 win->SetSize( newContentRect.left , newContentRect.top ,
1711 newContentRect.right - newContentRect.left ,
1712 newContentRect.bottom - newContentRect.top, wxSIZE_USE_EXISTING);
1713 }
1714 s_lastMouseDown = 0;
1715 }
1716 break;
1717 case inZoomIn:
1718 case inZoomOut:
1719 if (TrackBox(window, ev->where, windowPart))
1720 {
1721 // TODO setup size event
1722 ZoomWindow( window , windowPart , false ) ;
1723 if (win)
1724 {
1725 Rect tempRect ;
1726 GrafPtr port ;
1727 GetPort( &port ) ;
1728 Point pt = { 0, 0 } ;
1729 SetPortWindowPort(window) ;
1730 LocalToGlobal( &pt ) ;
1731 SetPort( port ) ;
1732
1733 GetWindowPortBounds(window, &tempRect ) ;
1734 win->SetSize( pt.h , pt.v , tempRect.right-tempRect.left ,
1735 tempRect.bottom-tempRect.top, wxSIZE_USE_EXISTING);
1736 }
1737 }
1738 s_lastMouseDown = 0;
1739 break;
1740 case inCollapseBox :
1741 // TODO setup size event
1742 s_lastMouseDown = 0;
1743 break ;
1744
1745 case inContent :
1746 {
1747 GrafPtr port ;
1748 GetPort( &port ) ;
1749 SetPortWindowPort(window) ;
1750 SetPort( port ) ;
1751 }
1752 if ( window != frontWindow && wxTheApp->s_captureWindow == NULL )
1753 {
1754 if ( s_macIsInModalLoop )
1755 {
1756 SysBeep ( 30 ) ;
1757 }
1758 else if ( UMAIsWindowFloating( window ) )
1759 {
1760 if ( win )
1761 win->MacMouseDown( ev , windowPart ) ;
1762 }
1763 else
1764 {
1765 if ( win )
1766 win->MacMouseDown( ev , windowPart ) ;
1767 ::SelectWindow( window ) ;
1768 }
1769 }
1770 else
1771 {
1772 if ( win )
1773 win->MacMouseDown( ev , windowPart ) ;
1774 }
1775 break ;
1776 default:
1777 break;
1778 }
1779 }
1780
1781 void wxApp::MacHandleMouseUpEvent( WXEVENTREF evr )
1782 {
1783 EventRecord* ev = (EventRecord*) evr ;
1784 WindowRef window;
1785
1786 short windowPart = inNoWindow ;
1787 if ( wxTheApp->s_captureWindow )
1788 {
1789 window = (WindowRef) s_captureWindow->MacGetRootWindow() ;
1790 windowPart = inContent ;
1791 }
1792 else
1793 {
1794 windowPart = ::FindWindow(ev->where, &window) ;
1795 }
1796
1797 switch (windowPart)
1798 {
1799 case inMenuBar :
1800 break ;
1801 case inSysWindow :
1802 break ;
1803 default:
1804 {
1805 wxTopLevelWindowMac* win = wxFindWinFromMacWindow( window ) ;
1806 if ( win )
1807 win->MacMouseUp( ev , windowPart ) ;
1808 }
1809 break;
1810 }
1811 }
1812
1813 #endif
1814
1815 long wxMacTranslateKey(unsigned char key, unsigned char code) ;
1816 long wxMacTranslateKey(unsigned char key, unsigned char code)
1817 {
1818 long retval = key ;
1819 switch (key)
1820 {
1821 case kHomeCharCode :
1822 retval = WXK_HOME;
1823 break;
1824 case kEnterCharCode :
1825 retval = WXK_RETURN;
1826 break;
1827 case kEndCharCode :
1828 retval = WXK_END;
1829 break;
1830 case kHelpCharCode :
1831 retval = WXK_HELP;
1832 break;
1833 case kBackspaceCharCode :
1834 retval = WXK_BACK;
1835 break;
1836 case kTabCharCode :
1837 retval = WXK_TAB;
1838 break;
1839 case kPageUpCharCode :
1840 retval = WXK_PAGEUP;
1841 break;
1842 case kPageDownCharCode :
1843 retval = WXK_PAGEDOWN;
1844 break;
1845 case kReturnCharCode :
1846 retval = WXK_RETURN;
1847 break;
1848 case kFunctionKeyCharCode :
1849 {
1850 switch( code )
1851 {
1852 case 0x7a :
1853 retval = WXK_F1 ;
1854 break;
1855 case 0x78 :
1856 retval = WXK_F2 ;
1857 break;
1858 case 0x63 :
1859 retval = WXK_F3 ;
1860 break;
1861 case 0x76 :
1862 retval = WXK_F4 ;
1863 break;
1864 case 0x60 :
1865 retval = WXK_F5 ;
1866 break;
1867 case 0x61 :
1868 retval = WXK_F6 ;
1869 break;
1870 case 0x62:
1871 retval = WXK_F7 ;
1872 break;
1873 case 0x64 :
1874 retval = WXK_F8 ;
1875 break;
1876 case 0x65 :
1877 retval = WXK_F9 ;
1878 break;
1879 case 0x6D :
1880 retval = WXK_F10 ;
1881 break;
1882 case 0x67 :
1883 retval = WXK_F11 ;
1884 break;
1885 case 0x6F :
1886 retval = WXK_F12 ;
1887 break;
1888 case 0x69 :
1889 retval = WXK_F13 ;
1890 break;
1891 case 0x6B :
1892 retval = WXK_F14 ;
1893 break;
1894 case 0x71 :
1895 retval = WXK_F15 ;
1896 break;
1897 }
1898 }
1899 break ;
1900 case kEscapeCharCode :
1901 retval = WXK_ESCAPE ;
1902 break ;
1903 case kLeftArrowCharCode :
1904 retval = WXK_LEFT ;
1905 break ;
1906 case kRightArrowCharCode :
1907 retval = WXK_RIGHT ;
1908 break ;
1909 case kUpArrowCharCode :
1910 retval = WXK_UP ;
1911 break ;
1912 case kDownArrowCharCode :
1913 retval = WXK_DOWN ;
1914 break ;
1915 case kDeleteCharCode :
1916 retval = WXK_DELETE ;
1917 default:
1918 break ;
1919 } // end switch
1920
1921 return retval;
1922 }
1923
1924 #if !TARGET_CARBON
1925 void wxApp::MacHandleKeyDownEvent( WXEVENTREF evr )
1926 {
1927 EventRecord* ev = (EventRecord*) evr ;
1928 wxToolTip::RemoveToolTips() ;
1929
1930 UInt32 menuresult = UMAMenuEvent(ev) ;
1931 if ( HiWord( menuresult ) )
1932 {
1933 if ( !s_macIsInModalLoop )
1934 MacHandleMenuSelect( HiWord( menuresult ) , LoWord( menuresult ) ) ;
1935 }
1936 else
1937 {
1938 wxWindow* focus = wxWindow::FindFocus() ;
1939
1940 if ( MacSendKeyDownEvent( focus , ev->message , ev->modifiers , ev->when , ev->where.h , ev->where.v ) == false )
1941 {
1942 // has not been handled -> perform default
1943 wxControl* control = wxDynamicCast( focus , wxControl ) ;
1944 if ( control && control->GetMacControl() != NULL )
1945 {
1946 short keycode ;
1947 short keychar ;
1948 keychar = short(ev->message & charCodeMask);
1949 keycode = short(ev->message & keyCodeMask) >> 8 ;
1950 ::HandleControlKey( (ControlHandle) control->GetMacControl() , keycode , keychar , ev->modifiers ) ;
1951 }
1952 }
1953 }
1954 }
1955
1956 void wxApp::MacHandleKeyUpEvent( WXEVENTREF evr )
1957 {
1958 EventRecord* ev = (EventRecord*) evr ;
1959 wxToolTip::RemoveToolTips() ;
1960
1961 UInt32 menuresult = UMAMenuEvent(ev) ;
1962 if ( HiWord( menuresult ) )
1963 {
1964 }
1965 else
1966 {
1967 MacSendKeyUpEvent( wxWindow::FindFocus() , ev->message , ev->modifiers , ev->when , ev->where.h , ev->where.v ) ;
1968 }
1969 }
1970
1971 #endif
1972
1973 bool wxApp::MacSendKeyDownEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey )
1974 {
1975 if ( !focus )
1976 return false ;
1977
1978 short keycode ;
1979 short keychar ;
1980 keychar = short(keymessage & charCodeMask);
1981 keycode = short(keymessage & keyCodeMask) >> 8 ;
1982
1983 if ( modifiers & ( controlKey|shiftKey|optionKey ) )
1984 {
1985 // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
1986 // and look at the character after
1987 UInt32 state = 0;
1988 UInt32 keyInfo = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache), ( modifiers & (~(controlKey|shiftKey|optionKey))) | keycode, &state);
1989 keychar = short(keyInfo & charCodeMask);
1990 keycode = short(keyInfo & keyCodeMask) >> 8 ;
1991 }
1992 long keyval = wxMacTranslateKey(keychar, keycode) ;
1993 long realkeyval = keyval ;
1994 if ( keyval == keychar )
1995 {
1996 // we are not on a special character combo -> pass the real os event-value to EVT_CHAR, but not to EVT_KEY (make upper first)
1997 realkeyval = short(keymessage & charCodeMask) ;
1998 keyval = wxToupper( keyval ) ;
1999 }
2000
2001 wxKeyEvent event(wxEVT_KEY_DOWN);
2002 bool handled = false ;
2003 event.m_shiftDown = modifiers & shiftKey;
2004 event.m_controlDown = modifiers & controlKey;
2005 event.m_altDown = modifiers & optionKey;
2006 event.m_metaDown = modifiers & cmdKey;
2007 event.m_keyCode = keyval ;
2008
2009 event.m_x = wherex;
2010 event.m_y = wherey;
2011 event.m_timeStamp = when;
2012 event.SetEventObject(focus);
2013 handled = focus->GetEventHandler()->ProcessEvent( event ) ;
2014 if ( handled && event.GetSkipped() )
2015 handled = false ;
2016 if ( !handled )
2017 {
2018 #if wxUSE_ACCEL
2019 if (!handled)
2020 {
2021 wxWindow *ancestor = focus;
2022 while (ancestor)
2023 {
2024 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
2025 if (command != -1)
2026 {
2027 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
2028 handled = ancestor->GetEventHandler()->ProcessEvent( command_event );
2029 break;
2030 }
2031 if (ancestor->IsTopLevel())
2032 break;
2033 ancestor = ancestor->GetParent();
2034 }
2035 }
2036 #endif // wxUSE_ACCEL
2037 }
2038 if (!handled)
2039 {
2040 event.Skip( FALSE ) ;
2041 event.SetEventType( wxEVT_CHAR ) ;
2042 // raw value again
2043 event.m_keyCode = realkeyval ;
2044
2045 handled = focus->GetEventHandler()->ProcessEvent( event ) ;
2046 if ( handled && event.GetSkipped() )
2047 handled = false ;
2048 }
2049 if ( !handled &&
2050 (keyval == WXK_TAB) &&
2051 // CS: copied the change below from wxGTK
2052 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
2053 // have this style, yet choose not to process this particular TAB in which
2054 // case TAB must still work as a navigational character
2055 #if 0
2056 (!focus->HasFlag(wxTE_PROCESS_TAB)) &&
2057 #endif
2058 (focus->GetParent()) &&
2059 (focus->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
2060 {
2061 wxNavigationKeyEvent new_event;
2062 new_event.SetEventObject( focus );
2063 new_event.SetDirection( !event.ShiftDown() );
2064 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
2065 new_event.SetWindowChange( event.ControlDown() );
2066 new_event.SetCurrentFocus( focus );
2067 handled = focus->GetEventHandler()->ProcessEvent( new_event );
2068 if ( handled && new_event.GetSkipped() )
2069 handled = false ;
2070 }
2071 // backdoor handler for default return and command escape
2072 if ( !handled && (!focus->IsKindOf(CLASSINFO(wxControl) ) || !focus->MacCanFocus() ) )
2073 {
2074 // if window is not having a focus still testing for default enter or cancel
2075 // TODO add the UMA version for ActiveNonFloatingWindow
2076 wxWindow* focus = wxFindWinFromMacWindow( FrontWindow() ) ;
2077 if ( focus )
2078 {
2079 if ( keyval == WXK_RETURN )
2080 {
2081 wxButton *def = wxDynamicCast(focus->GetDefaultItem(),
2082 wxButton);
2083 if ( def && def->IsEnabled() )
2084 {
2085 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
2086 event.SetEventObject(def);
2087 def->Command(event);
2088 return true ;
2089 }
2090 }
2091 /* generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs) */
2092 else if (keyval == WXK_ESCAPE || (keyval == '.' && modifiers & cmdKey ) )
2093 {
2094 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
2095 new_event.SetEventObject( focus );
2096 handled = focus->GetEventHandler()->ProcessEvent( new_event );
2097 }
2098 }
2099 }
2100 return handled ;
2101 }
2102
2103 bool wxApp::MacSendKeyUpEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey )
2104 {
2105 if ( !focus )
2106 return false ;
2107
2108 short keycode ;
2109 short keychar ;
2110 keychar = short(keymessage & charCodeMask);
2111 keycode = short(keymessage & keyCodeMask) >> 8 ;
2112 if ( modifiers & ( controlKey|shiftKey|optionKey ) )
2113 {
2114 // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier
2115 // and look at the character after
2116 UInt32 state = 0;
2117 UInt32 keyInfo = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache), ( modifiers & (~(controlKey|shiftKey|optionKey))) | keycode, &state);
2118 keychar = short(keyInfo & charCodeMask);
2119 keycode = short(keyInfo & keyCodeMask) >> 8 ;
2120 }
2121 long keyval = wxMacTranslateKey(keychar, keycode) ;
2122
2123 if ( keyval == keychar )
2124 {
2125 keyval = wxToupper( keyval ) ;
2126 }
2127 bool handled = false ;
2128
2129 wxKeyEvent event(wxEVT_KEY_UP);
2130 event.m_shiftDown = modifiers & shiftKey;
2131 event.m_controlDown = modifiers & controlKey;
2132 event.m_altDown = modifiers & optionKey;
2133 event.m_metaDown = modifiers & cmdKey;
2134 event.m_keyCode = keyval ;
2135
2136 event.m_x = wherex;
2137 event.m_y = wherey;
2138 event.m_timeStamp = when;
2139 event.SetEventObject(focus);
2140 handled = focus->GetEventHandler()->ProcessEvent( event ) ;
2141
2142 return handled ;
2143 }
2144
2145 #if !TARGET_CARBON
2146 void wxApp::MacHandleActivateEvent( WXEVENTREF evr )
2147 {
2148 EventRecord* ev = (EventRecord*) evr ;
2149 WindowRef window = (WindowRef) ev->message ;
2150 if ( window )
2151 {
2152 bool activate = (ev->modifiers & activeFlag ) ;
2153 WindowClass wclass ;
2154 ::GetWindowClass ( window , &wclass ) ;
2155 if ( wclass == kFloatingWindowClass )
2156 {
2157 // if it is a floater we activate/deactivate the front non-floating window instead
2158 window = ::FrontNonFloatingWindow() ;
2159 }
2160 wxTopLevelWindowMac* win = wxFindWinFromMacWindow( window ) ;
2161 if ( win )
2162 win->MacActivate( ev->when , activate ) ;
2163 }
2164 }
2165
2166 void wxApp::MacHandleUpdateEvent( WXEVENTREF evr )
2167 {
2168 EventRecord* ev = (EventRecord*) evr ;
2169 WindowRef window = (WindowRef) ev->message ;
2170 wxTopLevelWindowMac * win = wxFindWinFromMacWindow( window ) ;
2171 if ( win )
2172 {
2173 if ( !wxPendingDelete.Member(win) )
2174 win->MacUpdate( ev->when ) ;
2175 }
2176 else
2177 {
2178 // since there is no way of telling this foreign window to update itself
2179 // we have to invalidate the update region otherwise we keep getting the same
2180 // event over and over again
2181 BeginUpdate( window ) ;
2182 EndUpdate( window ) ;
2183 }
2184 }
2185
2186 void wxApp::MacHandleDiskEvent( WXEVENTREF evr )
2187 {
2188 EventRecord* ev = (EventRecord*) evr ;
2189 if ( HiWord( ev->message ) != noErr )
2190 {
2191 OSErr err ;
2192 Point point ;
2193 SetPt( &point , 100 , 100 ) ;
2194
2195 err = DIBadMount( point , ev->message ) ;
2196 wxASSERT( err == noErr ) ;
2197 }
2198 }
2199
2200 void wxApp::MacHandleOSEvent( WXEVENTREF evr )
2201 {
2202 EventRecord* ev = (EventRecord*) evr ;
2203 switch( ( ev->message & osEvtMessageMask ) >> 24 )
2204 {
2205 case suspendResumeMessage :
2206 {
2207 bool isResuming = ev->message & resumeFlag ;
2208 bool convertClipboard = ev->message & convertClipboardFlag ;
2209
2210 bool doesActivate = UMAGetProcessModeDoesActivateOnFGSwitch() ;
2211 if ( isResuming )
2212 {
2213 WindowRef oldFrontWindow = NULL ;
2214 WindowRef newFrontWindow = NULL ;
2215
2216 // in case we don't take care of activating ourselves, we have to synchronize
2217 // our idea of the active window with the process manager's - which it already activated
2218
2219 if ( !doesActivate )
2220 oldFrontWindow = ::FrontNonFloatingWindow() ;
2221
2222 MacResume( convertClipboard ) ;
2223
2224 newFrontWindow = ::FrontNonFloatingWindow() ;
2225
2226 if ( oldFrontWindow )
2227 {
2228 wxTopLevelWindowMac* win = wxFindWinFromMacWindow( oldFrontWindow ) ;
2229 if ( win )
2230 win->MacActivate( ev->when , false ) ;
2231 }
2232 if ( newFrontWindow )
2233 {
2234 wxTopLevelWindowMac* win = wxFindWinFromMacWindow( newFrontWindow ) ;
2235 if ( win )
2236 win->MacActivate( ev->when , true ) ;
2237 }
2238 }
2239 else
2240 {
2241 MacSuspend( convertClipboard ) ;
2242 }
2243 }
2244 break ;
2245 case mouseMovedMessage :
2246 {
2247 WindowRef window;
2248
2249 wxWindow* currentMouseWindow = NULL ;
2250
2251 if (s_captureWindow )
2252 {
2253 currentMouseWindow = s_captureWindow ;
2254 }
2255 else
2256 {
2257 wxWindow::MacGetWindowFromPoint( wxPoint( ev->where.h , ev->where.v ) ,
2258 &currentMouseWindow ) ;
2259 }
2260
2261 if ( currentMouseWindow != wxWindow::s_lastMouseWindow )
2262 {
2263 wxMouseEvent event ;
2264
2265 bool isDown = !(ev->modifiers & btnState) ; // 1 is for up
2266 bool controlDown = ev->modifiers & controlKey ; // for simulating right mouse
2267
2268 event.m_leftDown = isDown && !controlDown;
2269 event.m_middleDown = FALSE;
2270 event.m_rightDown = isDown && controlDown;
2271 event.m_shiftDown = ev->modifiers & shiftKey;
2272 event.m_controlDown = ev->modifiers & controlKey;
2273 event.m_altDown = ev->modifiers & optionKey;
2274 event.m_metaDown = ev->modifiers & cmdKey;
2275 event.m_x = ev->where.h;
2276 event.m_y = ev->where.v;
2277 event.m_timeStamp = ev->when;
2278 event.SetEventObject(this);
2279
2280 if ( wxWindow::s_lastMouseWindow )
2281 {
2282 wxMouseEvent eventleave(event);
2283 eventleave.SetEventType( wxEVT_LEAVE_WINDOW );
2284 wxWindow::s_lastMouseWindow->ScreenToClient( &eventleave.m_x, &eventleave.m_y );
2285 eventleave.SetEventObject( wxWindow::s_lastMouseWindow ) ;
2286
2287 wxWindow::s_lastMouseWindow->GetEventHandler()->ProcessEvent(eventleave);
2288 }
2289 if ( currentMouseWindow )
2290 {
2291 wxMouseEvent evententer(event);
2292 evententer.SetEventType( wxEVT_ENTER_WINDOW );
2293 currentMouseWindow->ScreenToClient( &evententer.m_x, &evententer.m_y );
2294 evententer.SetEventObject( currentMouseWindow ) ;
2295 currentMouseWindow->GetEventHandler()->ProcessEvent(evententer);
2296 }
2297 wxWindow::s_lastMouseWindow = currentMouseWindow ;
2298 }
2299
2300 short windowPart = inNoWindow ;
2301
2302 if ( s_captureWindow )
2303 {
2304 window = (WindowRef) s_captureWindow->MacGetRootWindow() ;
2305 windowPart = inContent ;
2306 }
2307 else
2308 {
2309 windowPart = ::FindWindow(ev->where, &window);
2310 }
2311
2312 switch (windowPart)
2313 {
2314 case inContent :
2315 {
2316 wxTopLevelWindowMac* win = wxFindWinFromMacWindow( window ) ;
2317 if ( win )
2318 win->MacMouseMoved( ev , windowPart ) ;
2319 else
2320 {
2321 if ( wxIsBusy() )
2322 {
2323 }
2324 else
2325 UMAShowArrowCursor();
2326 }
2327 }
2328 break;
2329 default :
2330 {
2331 if ( wxIsBusy() )
2332 {
2333 }
2334 else
2335 UMAShowArrowCursor();
2336 }
2337 break ;
2338 }
2339 }
2340 break ;
2341
2342 }
2343 }
2344 #endif
2345
2346 void wxApp::MacHandleMenuCommand( wxUint32 id )
2347 {
2348 wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
2349 wxMenu* menu = NULL ;
2350 wxMenuItem* item = NULL ;
2351 if ( mbar )
2352 {
2353 item = mbar->FindItem( id , &menu ) ;
2354 }
2355 wxCHECK_RET( item != NULL && menu != NULL && mbar != NULL, wxT("error in menu item callback") );
2356
2357 if (item->IsCheckable())
2358 {
2359 item->Check( !item->IsChecked() ) ;
2360 }
2361
2362 menu->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ;
2363 }
2364
2365 #if !TARGET_CARBON
2366 void wxApp::MacHandleMenuSelect( int macMenuId , int macMenuItemNum )
2367 {
2368 if (macMenuId == 0)
2369 return; // no menu item selected
2370
2371 if (macMenuId == kwxMacAppleMenuId && macMenuItemNum > 1)
2372 {
2373 #if ! TARGET_CARBON
2374 Str255 deskAccessoryName ;
2375 GrafPtr savedPort ;
2376
2377 GetMenuItemText(GetMenuHandle(kwxMacAppleMenuId), macMenuItemNum, deskAccessoryName);
2378 GetPort(&savedPort);
2379 OpenDeskAcc(deskAccessoryName);
2380 SetPort(savedPort);
2381 #endif
2382 }
2383 else
2384 {
2385 MenuCommand id ;
2386 GetMenuItemCommandID( GetMenuHandle(macMenuId) , macMenuItemNum , &id ) ;
2387 MacHandleMenuCommand( id ) ;
2388 }
2389 HiliteMenu(0);
2390 }
2391 #endif