]> git.saurik.com Git - wxWidgets.git/blame - src/mac/app.cpp
bug fixes
[wxWidgets.git] / src / mac / app.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: app.cpp
3// Purpose: wxApp
4// Author: AUTHOR
5// Modified by:
6// Created: ??/??/98
7// RCS-ID: $Id$
8// Copyright: (c) AUTHOR
8461e4c2 9// Licence: wxWindows licence
e9576ca5
SC
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "app.h"
14#endif
15
df06d1a4
GD
16#include "wx/defs.h"
17
03e11df5 18#include "wx/window.h"
e9576ca5 19#include "wx/frame.h"
e8566d35 20#include "wx/button.h"
e9576ca5
SC
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"
ed5b9811 27#include "wx/intl.h"
e9576ca5
SC
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"
2f1ae414 36#include "wx/tooltip.h"
b3c406a5 37#include "wx/textctrl.h"
03e11df5 38#include "wx/menu.h"
738a6daa
SC
39#include "wx/docview.h"
40
e9576ca5 41#if wxUSE_WX_RESOURCES
df06d1a4 42# include "wx/resource.h"
e9576ca5
SC
43#endif
44
45#include <string.h>
46
8be97d65
SC
47// mac
48
f5c6eb5c 49#ifndef __DARWIN__
03e11df5 50 #if __option(profile)
8461e4c2 51 #include <profiler.h>
03e11df5 52 #endif
9779893b 53#endif
519cb848 54
8be97d65
SC
55#include "apprsrc.h"
56
03e11df5
GD
57#include "wx/mac/uma.h"
58#include "wx/mac/macnotfy.h"
2f1ae414 59
df06d1a4
GD
60#ifdef __DARWIN__
61# include <CoreServices/CoreServices.h>
ed581ee2
GD
62# if defined(WXMAKINGDLL)
63# include <mach-o/dyld.h>
64# endif
df06d1a4
GD
65#else
66# include <Sound.h>
67# include <Threads.h>
68# include <ToolUtils.h>
69# include <DiskInit.h>
70# include <Devices.h>
2f1ae414 71#endif
519cb848 72
e9576ca5 73extern wxList wxPendingDelete;
519cb848
SC
74extern wxList *wxWinMacWindowList;
75extern wxList *wxWinMacControlList;
e9576ca5 76
c5c9378c
SC
77// statics for implementation
78
738a6daa 79static bool s_inYield = FALSE;
c5c9378c
SC
80static bool s_inOnIdle = FALSE;
81
82#if TARGET_CARBON
83static bool s_inReceiveEvent = FALSE ;
84static EventTime sleepTime = kEventDurationNoWait ;
85#else
86static long sleepTime = 0 ;
87#endif
738a6daa 88
6418cb93 89wxApp *wxTheApp = NULL;
e9576ca5 90
2f1ae414 91#if !USE_SHARED_LIBRARY
e9576ca5
SC
92IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
93BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
94 EVT_IDLE(wxApp::OnIdle)
15b41e90
SC
95 EVT_END_SESSION(wxApp::OnEndSession)
96 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
e9576ca5 97END_EVENT_TABLE()
2f1ae414 98#endif
e9576ca5 99
169935ad 100
8461e4c2 101const short kMacMinHeap = (29 * 1024) ;
8be97d65 102// platform specific static variables
169935ad 103
519cb848
SC
104const short kwxMacMenuBarResource = 1 ;
105const short kwxMacAppleMenuId = 1 ;
106
fbbdb7cd
GD
107WXHRGN wxApp::s_macCursorRgn = NULL;
108wxWindow* wxApp::s_captureWindow = NULL ;
109int wxApp::s_lastMouseDown = 0 ;
110long wxApp::sm_lastMessageTime = 0;
41d368a4
SC
111long wxApp::s_lastModifiers = 0 ;
112
519cb848 113
fbbdb7cd
GD
114bool wxApp::s_macDefaultEncodingIsPC = true ;
115bool wxApp::s_macSupportPCMenuShortcuts = true ;
116long wxApp::s_macAboutMenuItemId = wxID_ABOUT ;
2b5f62a0
VZ
117long wxApp::s_macPreferencesMenuItemId = 0 ;
118long wxApp::s_macExitMenuItemId = wxID_EXIT ;
fbbdb7cd 119wxString wxApp::s_macHelpMenuTitleName = "&Help" ;
519cb848 120
15b41e90
SC
121//----------------------------------------------------------------------
122// Core Apple Event Support
123//----------------------------------------------------------------------
124
72055702
SC
125pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , long refcon ) ;
126pascal OSErr AEHandleOApp( const AppleEvent *event , AppleEvent *reply , long refcon ) ;
127pascal OSErr AEHandlePDoc( const AppleEvent *event , AppleEvent *reply , long refcon ) ;
128pascal OSErr AEHandleQuit( const AppleEvent *event , AppleEvent *reply , long refcon ) ;
72055702 129
2a294857 130pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , long WXUNUSED(refcon) )
519cb848 131{
8461e4c2 132 return wxTheApp->MacHandleAEODoc( (AppleEvent*) event , reply) ;
519cb848
SC
133}
134
2a294857 135pascal OSErr AEHandleOApp( const AppleEvent *event , AppleEvent *reply , long WXUNUSED(refcon) )
519cb848 136{
8461e4c2 137 return wxTheApp->MacHandleAEOApp( (AppleEvent*) event , reply ) ;
519cb848
SC
138}
139
2a294857 140pascal OSErr AEHandlePDoc( const AppleEvent *event , AppleEvent *reply , long WXUNUSED(refcon) )
519cb848 141{
8461e4c2 142 return wxTheApp->MacHandleAEPDoc( (AppleEvent*) event , reply ) ;
519cb848
SC
143}
144
2a294857 145pascal OSErr AEHandleQuit( const AppleEvent *event , AppleEvent *reply , long WXUNUSED(refcon) )
519cb848 146{
8461e4c2 147 return wxTheApp->MacHandleAEQuit( (AppleEvent*) event , reply) ;
519cb848
SC
148}
149
15b41e90 150// AEODoc Calls MacOpenFile on each of the files passed
5ab6aab8 151
2072fbbb
SC
152short 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
8461e4c2
VZ
170 ProcessSerialNumber PSN ;
171 PSN.highLongOfPSN = 0 ;
172 PSN.lowLongOfPSN = kCurrentProcess ;
173 SetFrontProcess( &PSN ) ;
2072fbbb
SC
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;
519cb848
SC
182}
183
15b41e90
SC
184// AEPDoc Calls MacPrintFile on each of the files passed
185
2072fbbb 186short wxApp::MacHandleAEPDoc(const WXEVENTREF event , WXEVENTREF WXUNUSED(reply))
519cb848 187{
2072fbbb
SC
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;
519cb848
SC
216}
217
15b41e90
SC
218// AEOApp calls MacNewFile
219
2a294857 220short wxApp::MacHandleAEOApp(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
519cb848 221{
2072fbbb 222 MacNewFile() ;
8461e4c2 223 return noErr ;
519cb848
SC
224}
225
15b41e90
SC
226// AEQuit attempts to quite the application
227
2a294857 228short wxApp::MacHandleAEQuit(const WXEVENTREF WXUNUSED(event) , WXEVENTREF WXUNUSED(reply))
519cb848 229{
c5c9378c 230 /* wxWindow* win = GetTopWindow() ;
8461e4c2
VZ
231 if ( win )
232 {
233 win->Close(TRUE ) ;
234 }
235 else
c5c9378c 236 */
8461e4c2
VZ
237 {
238 ExitMainLoop() ;
239 }
240 return noErr ;
519cb848
SC
241}
242
15b41e90
SC
243//----------------------------------------------------------------------
244// Support Routines linking the Mac...File Calls to the Document Manager
245//----------------------------------------------------------------------
246
247void wxApp::MacOpenFile(const wxString & fileName )
248{
249 wxDocManager* dm = wxDocManager::GetDocumentManager() ;
250 if ( dm )
251 dm->CreateDocument(fileName , wxDOC_SILENT ) ;
252}
253
254void 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
282void wxApp::MacNewFile()
283{
284}
285
c5c9378c
SC
286//----------------------------------------------------------------------
287// Carbon Event Handler
288//----------------------------------------------------------------------
9779893b 289
c5c9378c 290#if TARGET_CARBON
519cb848 291
c5c9378c
SC
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
597a3d06
SC
302 { kEventClassAppleEvent , kEventAppleEvent } ,
303
c5c9378c 304 { kEventClassMouse , kEventMouseDown } ,
d8e9da78 305 { 'WXMC' , 'WXMC' }
c5c9378c 306 } ;
519cb848 307
c5c9378c 308static pascal OSStatus MenuEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
519cb848 309{
c5c9378c
SC
310 OSStatus result = eventNotHandledErr ;
311 UInt32 kind = GetEventKind( event ) ;
312
8461e4c2 313 return result ;
519cb848
SC
314}
315
c5c9378c
SC
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
519cb848 319
c5c9378c 320static pascal OSStatus MouseEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
519cb848 321{
c5c9378c
SC
322 OSStatus result = eventNotHandledErr ;
323
324 switch( GetEventKind(event) )
8461e4c2 325 {
c5c9378c
SC
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);
8461e4c2 334
c5c9378c
SC
335 if ( windowPart == inMenuBar )
336 {
337 MenuSelect( point ) ;
338 result = noErr ;
339 }
340 }
341 break ;
342 }
8461e4c2 343
8461e4c2 344 return result ;
519cb848 345}
169935ad 346
15b41e90
SC
347static 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
394static 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
417pascal 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 ;
c5c9378c
SC
428 case kEventClassMenu :
429 result = MenuEventHandler( handler , event , data ) ;
430 break ;
431 case kEventClassMouse :
432 result = MouseEventHandler( handler , event , data ) ;
433 break ;
597a3d06
SC
434 case kEventClassAppleEvent :
435 {
436 EventRecord rec ;
437 wxMacConvertEventToRecord( event , &rec ) ;
438 result = AEProcessAppleEvent( &rec ) ;
439 }
440 break ;
15b41e90
SC
441 default :
442 break ;
443 }
444
445 return result ;
446}
447
448DEFINE_ONE_SHOT_HANDLER_GETTER( wxAppEventHandler )
449
450#endif
451
ed581ee2 452#if defined(WXMAKINGDLL) && !defined(__DARWIN__)
53fd991c
SC
453// we know it's there ;-)
454WXIMPORT char std::__throws_bad_alloc ;
455#endif
456
e9576ca5
SC
457bool wxApp::Initialize()
458{
fbbdb7cd 459 int error = 0 ;
9779893b 460
fbbdb7cd 461 // Mac-specific
9779893b 462
fbbdb7cd
GD
463 UMAInitToolbox( 4 ) ;
464 SetEventMask( everyEvent ) ;
8461e4c2 465 UMAShowWatchCursor() ;
8be97d65 466
fbbdb7cd
GD
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
84c1ffa9 472
f5c6eb5c 473#ifndef __DARWIN__
fbbdb7cd 474 // test the minimal configuration necessary
8be97d65 475
fbbdb7cd 476# if !TARGET_CARBON
8461e4c2
VZ
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 }
72055702 492 else if ( theSystem < 0x0860 )
8461e4c2
VZ
493 {
494 error = kMacSTROldSystem ;
495 }
496 else if ((long)GetApplLimit() - (long)ApplicationZone() < kMacMinHeap)
497 {
498 error = kMacSTRSmallSize;
499 }
fbbdb7cd 500# endif
8461e4c2
VZ
501 /*
502 else
503 {
504 if ( !UMAHasAppearance() )
505 {
506 error = kMacSTRNoPre8Yet ;
507 }
508 }
509 */
ed5b9811 510#endif
8be97d65 511
8461e4c2 512 // if we encountered any problems so far, give the error code and exit immediately
9779893b 513
169935ad 514 if ( error )
9779893b 515 {
53fd991c 516 wxStAppResource resload ;
8461e4c2
VZ
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 ;
9779893b 525 }
519cb848 526
f5c6eb5c 527#ifndef __DARWIN__
fbbdb7cd 528# if __option(profile)
8461e4c2 529 ProfilerInit( collectDetailed, bestTimeBase , 20000 , 40 ) ;
fbbdb7cd 530# endif
9779893b 531#endif
519cb848 532
f5c6eb5c 533#ifndef __DARWIN__
ed581ee2 534 // now avoid exceptions thrown for new (bad_alloc)
15b41e90
SC
535 // FIXME CS for some changes outside wxMac does not compile anymore
536#if 0
537 std::__throws_bad_alloc = 0 ;
538#endif
539
03e11df5 540#endif
9779893b 541
8461e4c2 542 s_macCursorRgn = ::NewRgn() ;
8be97d65 543
ed581ee2 544 wxClassInfo::InitializeClasses();
e9576ca5 545
2f1ae414
SC
546#if wxUSE_RESOURCES
547// wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
e9576ca5 548#endif
e9576ca5 549
2f1ae414
SC
550#if wxUSE_THREADS
551 wxPendingEventsLocker = new wxCriticalSection;
552#endif
84c1ffa9 553
ed581ee2
GD
554 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
555 wxTheColourDatabase->Initialize();
e9576ca5 556
fc0daf84 557#ifdef __WXDEBUG__
0a67a93b
SC
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
fc0daf84 568#endif
0a67a93b 569
0a6cce3b
SC
570 wxWinMacWindowList = new wxList(wxKEY_INTEGER);
571 wxWinMacControlList = new wxList(wxKEY_INTEGER);
572
e9576ca5
SC
573 wxInitializeStockLists();
574 wxInitializeStockObjects();
575
576#if wxUSE_WX_RESOURCES
577 wxInitializeResourceSystem();
578#endif
579
580 wxBitmap::InitStandardHandlers();
581
582 wxModule::RegisterModules();
03e11df5 583 if (!wxModule::InitializeModules()) {
519cb848 584 return FALSE;
03e11df5 585 }
e9576ca5 586
2f1ae414 587 wxMacCreateNotifierTable() ;
9779893b 588
2f1ae414 589 UMAShowArrowCursor() ;
8461e4c2 590
e9576ca5
SC
591 return TRUE;
592}
593
15b41e90
SC
594bool wxApp::OnInitGui()
595{
596 if( !wxAppBase::OnInitGui() )
597 return false ;
598
599#if TARGET_CARBON
c5c9378c
SC
600 InstallStandardEventHandler( GetApplicationEventTarget() ) ;
601
15b41e90
SC
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
e9576ca5
SC
638void wxApp::CleanUp()
639{
12cd5f34 640 wxToolTip::RemoveToolTips() ;
2f1ae414
SC
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
fbbdb7cd 655 wxModule::CleanUpModules();
e9576ca5
SC
656
657#if wxUSE_WX_RESOURCES
fbbdb7cd 658 wxCleanUpResourceSystem();
e9576ca5
SC
659#endif
660
fbbdb7cd 661 wxDeleteStockObjects() ;
e9576ca5 662
2f1ae414
SC
663 // Destroy all GDI lists, etc.
664 wxDeleteStockLists();
e9576ca5 665
fbbdb7cd
GD
666 delete wxTheColourDatabase;
667 wxTheColourDatabase = NULL;
e9576ca5 668
fbbdb7cd 669 wxBitmap::CleanUpHandlers();
519cb848 670
fbbdb7cd
GD
671 wxMacDestroyNotifierTable() ;
672 if (wxWinMacWindowList) {
673 delete wxWinMacWindowList ;
674 }
675 if (wxWinMacControlList) {
676 delete wxWinMacControlList ;
677 }
2f1ae414 678 delete wxPendingEvents;
84c1ffa9 679
2f1ae414
SC
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
fbbdb7cd 686 wxClassInfo::CleanUpClasses();
e9576ca5 687
f5c6eb5c 688#ifndef __DARWIN__
fbbdb7cd
GD
689# if __option(profile)
690 ProfilerDump( "\papp.prof" ) ;
691 ProfilerTerm() ;
692# endif
9779893b 693#endif
519cb848 694
fbbdb7cd
GD
695 delete wxTheApp;
696 wxTheApp = NULL;
9779893b 697
e9576ca5 698#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
2f1ae414
SC
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);
e9576ca5 710#endif
9779893b 711
2f1ae414
SC
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
169935ad 716
fbbdb7cd
GD
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
84c1ffa9 722
8461e4c2 723 UMACleanupToolbox() ;
fbbdb7cd 724 if (s_macCursorRgn) {
76a5e5d2 725 ::DisposeRgn((RgnHandle)s_macCursorRgn);
fbbdb7cd 726 }
84c1ffa9 727
8461e4c2
VZ
728 #if 0
729 TerminateAE() ;
730 #endif
e9576ca5
SC
731}
732
92b002a4
RD
733//----------------------------------------------------------------------
734// wxEntry
735//----------------------------------------------------------------------
736
fbbdb7cd
GD
737// extern variable for shared library resource id
738// need to be able to find it with NSLookupAndBindSymbol
739short gSharedLibraryResource = kResFileNotOpened ;
740
ed581ee2 741#if defined(WXMAKINGDLL) && defined(__DARWIN__)
fbbdb7cd 742CFBundleRef gSharedLibraryBundle = NULL;
ed581ee2 743#endif /* WXMAKINGDLL && __DARWIN__ */
53fd991c
SC
744
745wxStAppResource::wxStAppResource()
746{
fbbdb7cd
GD
747 m_currentRefNum = CurResFile() ;
748 if ( gSharedLibraryResource != kResFileNotOpened )
749 {
750 UseResFile( gSharedLibraryResource ) ;
751 }
752}
753
754wxStAppResource::~wxStAppResource()
755{
756 if ( m_currentRefNum != kResFileNotOpened )
757 {
758 UseResFile( m_currentRefNum ) ;
759 }
760}
761
762void 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;
84c1ffa9 770
fbbdb7cd
GD
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 }
84c1ffa9 777
fbbdb7cd
GD
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
ed581ee2
GD
785 NSSymbol theSymbol;
786 NSModule theModule;
787 const char *theLibPath;
84c1ffa9 788
fbbdb7cd
GD
789 gSharedLibraryBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.wxwindows.wxWindows"));
790 if (gSharedLibraryBundle != NULL) {
ed581ee2
GD
791 // wxWindows has been bundled into a framework
792 // load the framework resources
84c1ffa9 793
fbbdb7cd 794 gSharedLibraryResource = CFBundleOpenBundleResourceMap(gSharedLibraryBundle);
ed581ee2
GD
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;
84c1ffa9 804
ed581ee2 805 // get the library path
fbbdb7cd 806 theSymbol = NSLookupAndBindSymbol("_gSharedLibraryResource");
ed581ee2
GD
807 theModule = NSModuleForSymbol(theSymbol);
808 theLibPath = NSLibraryNameForModule(theModule);
ed581ee2 809
f346733b
GD
810 wxLogDebug( wxT("wxMac library installation name is '%s'"),
811 theLibPath );
812
ed581ee2
GD
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");
84c1ffa9 825
f346733b
GD
826 wxLogDebug( wxT("wxMac resources file name is '%s'"),
827 theResPath );
ed581ee2
GD
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 }
84c1ffa9 834
ed581ee2
GD
835 // open the resource file
836 if (theErr == noErr) {
837 theErr = FSOpenResourceFile( &theResRef, 0, NULL, fsRdPerm,
fbbdb7cd 838 &gSharedLibraryResource);
ed581ee2 839 }
f346733b
GD
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);
ed581ee2
GD
847 }
848 }
fbbdb7cd 849#endif /* __DARWIN__ */
53fd991c 850 }
fbbdb7cd 851#endif /* WXMAKINGDLL */
53fd991c
SC
852}
853
fbbdb7cd 854void wxStAppResource::CloseSharedLibraryResource()
53fd991c 855{
fbbdb7cd 856#ifdef WXMAKINGDLL
ed581ee2 857 // Close the shared library resource file
fbbdb7cd
GD
858 if (gSharedLibraryResource != kResFileNotOpened) {
859#ifdef __DARWIN__
860 if (gSharedLibraryBundle != NULL) {
861 CFBundleCloseBundleResourceMap(gSharedLibraryBundle,
862 gSharedLibraryResource);
863 gSharedLibraryBundle = NULL;
ed581ee2 864 }
fbbdb7cd
GD
865 else
866#endif /* __DARWIN__ */
867 {
868 CloseResFile(gSharedLibraryResource);
ed581ee2 869 }
fbbdb7cd 870 gSharedLibraryResource = kResFileNotOpened;
84c1ffa9 871 }
fbbdb7cd 872#endif /* WXMAKINGDLL */
53fd991c
SC
873}
874
ed581ee2 875#if defined(WXMAKINGDLL) && !defined(__DARWIN__)
53fd991c 876
ed581ee2
GD
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
53fd991c 880
53fd991c 881extern "C" {
fbbdb7cd
GD
882 void __sinit(void); /* (generated by linker) */
883 pascal OSErr __initialize(const CFragInitBlock *theInitBlock);
884 pascal void __terminate(void);
53fd991c 885}
53fd991c
SC
886
887pascal OSErr __wxinitialize(const CFragInitBlock *theInitBlock)
888{
fbbdb7cd
GD
889 wxStAppResource::OpenSharedLibraryResource( theInitBlock ) ;
890 return __initialize( theInitBlock ) ;
53fd991c
SC
891}
892
893pascal void __wxterminate(void)
894{
fbbdb7cd 895 wxStAppResource::CloseSharedLibraryResource() ;
53fd991c
SC
896 __terminate() ;
897}
ed581ee2
GD
898
899#endif /* WXMAKINGDLL && !__DARWIN__ */
53fd991c 900
2a294857 901int WXDLLEXPORT wxEntryStart( int WXUNUSED(argc), char *WXUNUSED(argv)[] )
92b002a4
RD
902{
903 return wxApp::Initialize();
904}
905
53fd991c 906int WXDLLEXPORT wxEntryInitGui()
92b002a4
RD
907{
908 return wxTheApp->OnInitGui();
909}
910
53fd991c 911void WXDLLEXPORT wxEntryCleanup()
92b002a4
RD
912{
913 wxApp::CleanUp();
914}
915
2f1ae414 916int wxEntry( int argc, char *argv[] , bool enterLoop )
e9576ca5 917{
7c551d95
SC
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
92b002a4 929 if (!wxEntryStart(argc, argv)) {
2f1ae414 930 return 0;
03e11df5 931 }
2f1ae414
SC
932 // create the application object or ensure that one already exists
933 if (!wxTheApp)
e9576ca5 934 {
2f1ae414
SC
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.") );
9779893b 940
2f1ae414
SC
941 wxTheApp = (wxApp*) (*wxApp::GetInitializerFunction()) ();
942 }
9779893b 943
2f1ae414 944 wxCHECK_MSG( wxTheApp, 0, wxT("You have to define an instance of wxApp!") );
e9576ca5 945
e94e53ac
GD
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) {
2b5f62a0 953 if (strncmp(argv[1], "-psn_", 5) == 0) {
e94e53ac
GD
954 // assume the argument is always the only one and remove it
955 --argc;
956 }
84c1ffa9 957 }
e94e53ac 958#else
89ebf1c9 959 argc = 0 ; // currently we don't support files as parameters
519cb848 960#endif
89ebf1c9 961 // we could try to get the open apple events here to adjust argc and argv better
519cb848 962
89ebf1c9
RR
963 wxTheApp->argc = argc;
964 wxTheApp->argv = argv;
9779893b 965
89ebf1c9
RR
966 // GUI-specific initialization, such as creating an app context.
967 wxEntryInitGui();
9779893b 968
89ebf1c9
RR
969 // Here frames insert themselves automatically
970 // into wxTopLevelWindows by getting created
971 // in OnInit().
9779893b 972
89ebf1c9 973 int retValue = 0;
9779893b 974
8461e4c2
VZ
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
92b002a4 1006 wxEntryCleanup();
8461e4c2
VZ
1007
1008 return retValue;
03e11df5 1009}
e9576ca5 1010
b4efa069
SC
1011#if TARGET_CARBON
1012
1013bool 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 ;
84c1ffa9 1024 switch( GetEventKind(event) )
b4efa069
SC
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 }
84c1ffa9 1087
b4efa069
SC
1088 return converted ;
1089}
1090
15b41e90 1091/*
b4efa069
SC
1092pascal OSStatus wxMacApplicationEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
1093{
1094 OSStatus result = eventNotHandledErr ;
84c1ffa9 1095
b4efa069
SC
1096 EventRecord rec ;
1097 switch ( GetEventClass( event ) )
1098 {
1099 case kEventClassKeyboard :
1100 if ( wxMacConvertEventToRecord( event , &rec ) )
1101 {
41d368a4 1102 wxTheApp->MacHandleModifierEvents( &rec ) ;
b4efa069
SC
1103 wxTheApp->MacHandleOneEvent( &rec ) ;
1104 result = noErr ;
1105 }
1106 break ;
1107 case kEventClassTextInput :
1108 if ( wxMacConvertEventToRecord( event , &rec ) )
1109 {
41d368a4 1110 wxTheApp->MacHandleModifierEvents( &rec ) ;
b4efa069
SC
1111 wxTheApp->MacHandleOneEvent( &rec ) ;
1112 result = noErr ;
1113 }
1114 break ;
1115 default :
1116 break ;
1117 }
1118 return result ;
1119}
15b41e90 1120*/
b4efa069
SC
1121#endif
1122
e9576ca5 1123// Static member initialization
2f1ae414 1124wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
e9576ca5
SC
1125
1126wxApp::wxApp()
1127{
1128 m_topWindow = NULL;
1129 wxTheApp = this;
2f1ae414 1130
1b21409b
JS
1131#if WXWIN_COMPATIBILITY_2_2
1132 m_wantDebugOutput = TRUE;
1133#endif
2f1ae414 1134
e9576ca5
SC
1135 argc = 0;
1136 argv = NULL;
519cb848 1137
e9576ca5 1138 m_printMode = wxPRINT_WINDOWS;
e9576ca5
SC
1139 m_auto3D = TRUE;
1140}
1141
1142bool wxApp::Initialized()
1143{
519cb848 1144 if (GetTopWindow())
e9576ca5 1145 return TRUE;
519cb848
SC
1146 else
1147 return FALSE;
e9576ca5
SC
1148}
1149
1150int wxApp::MainLoop()
1151{
5ab6aab8 1152 m_keepGoing = TRUE;
e9576ca5 1153
5ab6aab8
SC
1154 while (m_keepGoing)
1155 {
1156 MacDoOneEvent() ;
1157 }
e9576ca5 1158
5ab6aab8 1159 return 0;
e9576ca5
SC
1160}
1161
1162// Returns TRUE if more time is needed.
1163bool wxApp::ProcessIdle()
1164{
1165 wxIdleEvent event;
1166 event.SetEventObject(this);
1167 ProcessEvent(event);
1168
1169 return event.MoreRequested();
1170}
1171
1172void wxApp::ExitMainLoop()
1173{
c5c9378c 1174 m_keepGoing = FALSE;
e9576ca5
SC
1175}
1176
1177// Is a message/event pending?
1178bool wxApp::Pending()
1179{
c5c9378c
SC
1180#if TARGET_CARBON
1181 return GetNumEventsInQueue( GetMainEventQueue() ) > 0 ;
1182#else
8461e4c2 1183 EventRecord event ;
519cb848 1184
c5c9378c
SC
1185 return EventAvail( everyEvent , &event ) ;
1186#endif
e9576ca5
SC
1187}
1188
1189// Dispatch a message.
1190void wxApp::Dispatch()
1191{
8461e4c2 1192 MacDoOneEvent() ;
e9576ca5
SC
1193}
1194
1195void wxApp::OnIdle(wxIdleEvent& event)
1196{
2f1ae414
SC
1197 // Avoid recursion (via ProcessEvent default case)
1198 if ( s_inOnIdle )
1199 return;
e9576ca5 1200
2f1ae414
SC
1201
1202 s_inOnIdle = TRUE;
e9576ca5
SC
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
2f1ae414
SC
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;
e9576ca5
SC
1224}
1225
9779893b
RD
1226void wxWakeUpIdle()
1227{
8461e4c2 1228 wxMacWakeUp() ;
9779893b
RD
1229}
1230
e9576ca5
SC
1231// Send idle event to all top-level windows
1232bool wxApp::SendIdleEvents()
1233{
1234 bool needMore = FALSE;
8461e4c2
VZ
1235 wxNode* node = wxTopLevelWindows.First();
1236 while (node)
1237 {
1238 wxWindow* win = (wxWindow*) node->Data();
1239 if (SendIdleEvents(win))
e9576ca5
SC
1240 needMore = TRUE;
1241
8461e4c2
VZ
1242 node = node->Next();
1243 }
e9576ca5
SC
1244 return needMore;
1245}
1246
1247// Send idle event to window and all subwindows
1248bool wxApp::SendIdleEvents(wxWindow* win)
1249{
1250 bool needMore = FALSE;
1251
8461e4c2
VZ
1252 wxIdleEvent event;
1253 event.SetEventObject(win);
1254 win->ProcessEvent(event);
e9576ca5
SC
1255
1256 if (event.MoreRequested())
1257 needMore = TRUE;
1258
8461e4c2
VZ
1259 wxNode* node = win->GetChildren().First();
1260 while (node)
1261 {
1262 wxWindow* win = (wxWindow*) node->Data();
1263 if (SendIdleEvents(win))
e9576ca5
SC
1264 needMore = TRUE;
1265
8461e4c2
VZ
1266 node = node->Next();
1267 }
e9576ca5
SC
1268 return needMore ;
1269}
1270
1271void wxApp::DeletePendingObjects()
1272{
1273 wxNode *node = wxPendingDelete.First();
1274 while (node)
1275 {
1276 wxObject *obj = (wxObject *)node->Data();
9779893b 1277
e9576ca5
SC
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.First();
1286 }
1287}
1288
e9576ca5
SC
1289void wxExit()
1290{
2f1ae414
SC
1291 wxLogError(_("Fatal error: exiting"));
1292
1293 wxApp::CleanUp();
8461e4c2 1294 ::ExitToShell() ;
e9576ca5
SC
1295}
1296
2f1ae414
SC
1297void 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.
1305void wxApp::OnQueryEndSession(wxCloseEvent& event)
1306{
1307 if (GetTopWindow())
1308 {
1309 if (!GetTopWindow()->Close(!event.CanVeto()))
1310 event.Veto(TRUE);
1311 }
1312}
1313
1314extern "C" void wxCYield() ;
1315void wxCYield()
1316{
8461e4c2 1317 wxYield() ;
2f1ae414
SC
1318}
1319
e9576ca5 1320// Yield to other processes
cb2713bf 1321
8461e4c2 1322bool wxApp::Yield(bool onlyIfNeeded)
e9576ca5 1323{
8461e4c2
VZ
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;
cb2713bf 1335
2f1ae414 1336#if wxUSE_THREADS
cb2713bf 1337 YieldToAnyThread() ;
2f1ae414 1338#endif
c5c9378c
SC
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 {
d8e9da78
SC
1357 // according to QA1061 this may also occur when a WakeUp Process
1358 // is executed
c5c9378c
SC
1359 }
1360 else
1361 {
1362 MacHandleOneEvent( theEvent ) ;
1363 ReleaseEvent(theEvent);
1364 }
1365 } while( status == noErr ) ;
1366#else
cb2713bf 1367 EventRecord event ;
2f1ae414 1368
c5c9378c
SC
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
d8e9da78 1372 sleepTime = 0 ;
2f1ae414 1373
c5c9378c 1374 while ( !IsExiting() && WaitNextEvent(everyEvent, &event,sleepTime, (RgnHandle) wxApp::s_macCursorRgn))
8461e4c2 1375 {
c5c9378c
SC
1376 MacHandleModifierEvents( &event ) ;
1377 MacHandleOneEvent( &event );
8461e4c2 1378 if ( event.what != kHighLevelEvent )
76a5e5d2 1379 SetRectRgn( (RgnHandle) wxApp::s_macCursorRgn , event.where.h , event.where.v , event.where.h + 1 , event.where.v + 1 ) ;
8461e4c2 1380 }
c5c9378c
SC
1381 MacHandleModifierEvents( &event ) ;
1382#endif
2f1ae414 1383
8461e4c2 1384 wxMacProcessNotifierAndPendingEvents() ;
8461e4c2 1385 s_inYield = FALSE;
cb2713bf 1386
8461e4c2 1387 return TRUE;
169935ad
SC
1388}
1389
9779893b 1390// platform specifics
169935ad 1391
519cb848
SC
1392void wxApp::MacSuspend( bool convertClipboard )
1393{
15b41e90 1394#if !TARGET_CARBON
1c469f7f 1395 // we have to deactive the top level windows manually
8461e4c2 1396
1c469f7f
SC
1397 wxNode* node = wxTopLevelWindows.First();
1398 while (node)
1399 {
1400 wxTopLevelWindow* win = (wxTopLevelWindow*) node->Data();
15b41e90 1401 win->MacActivate( ((EventRecord*) MacGetCurrentEvent())->when , false ) ;
8461e4c2 1402
1c469f7f
SC
1403 node = node->Next();
1404 }
84c1ffa9 1405
15b41e90
SC
1406 ::HideFloatingWindows() ;
1407#endif
2a294857 1408 s_lastMouseDown = 0 ;
15b41e90 1409
2a294857
GD
1410 if( convertClipboard )
1411 {
1412 MacConvertPrivateToPublicScrap() ;
1413 }
519cb848
SC
1414}
1415
2a294857
GD
1416extern wxList wxModalDialogs;
1417
519cb848
SC
1418void wxApp::MacResume( bool convertClipboard )
1419{
2a294857
GD
1420 s_lastMouseDown = 0 ;
1421 if( convertClipboard )
1422 {
1423 MacConvertPublicToPrivateScrap() ;
1424 }
84c1ffa9 1425
15b41e90 1426#if !TARGET_CARBON
2a294857 1427 ::ShowFloatingWindows() ;
2a294857 1428 // raise modal dialogs in case a non modal window was selected to activate the app
9779893b 1429
2a294857
GD
1430 wxNode* node = wxModalDialogs.First();
1431 while (node)
1432 {
1433 wxDialog* dialog = (wxDialog *) node->Data();
1434 dialog->Raise();
84c1ffa9 1435
2a294857
GD
1436 node = node->Next();
1437 }
15b41e90 1438#endif
519cb848
SC
1439}
1440
1441void wxApp::MacConvertPrivateToPublicScrap()
1442{
519cb848
SC
1443}
1444
1445void wxApp::MacConvertPublicToPrivateScrap()
1446{
519cb848
SC
1447}
1448
9779893b 1449void wxApp::MacDoOneEvent()
169935ad 1450{
c5c9378c
SC
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 {
d8e9da78
SC
1466 // according to QA1061 this may also occur when a WakeUp Process
1467 // is executed
c5c9378c
SC
1468 }
1469 else
1470 {
1471 MacHandleOneEvent( theEvent ) ;
1472 ReleaseEvent(theEvent);
1473 }
1474#else
1475 EventRecord event ;
169935ad 1476
c5c9378c 1477 EventMask eventMask = everyEvent ;
169935ad 1478
c5c9378c 1479 if (WaitNextEvent(eventMask, &event, sleepTime, (RgnHandle) s_macCursorRgn))
8461e4c2 1480 {
41d368a4 1481 MacHandleModifierEvents( &event ) ;
6264b550 1482 MacHandleOneEvent( &event );
8461e4c2
VZ
1483 }
1484 else
1485 {
41d368a4 1486 MacHandleModifierEvents( &event ) ;
8461e4c2 1487 // idlers
72055702 1488 WindowPtr window = ::FrontWindow() ;
8461e4c2 1489 if ( window )
72055702 1490 ::IdleControls( window ) ;
9779893b 1491
c5c9378c
SC
1492 if ( wxTheApp->ProcessIdle() )
1493 sleepTime = 0 ;
1494 else
1495 sleepTime = GetCaretTime() / 2 ;
8461e4c2
VZ
1496 }
1497 if ( event.what != kHighLevelEvent )
76a5e5d2 1498 SetRectRgn( (RgnHandle) s_macCursorRgn , event.where.h , event.where.v , event.where.h + 1 , event.where.v + 1 ) ;
c5c9378c 1499#endif
8461e4c2 1500 // repeaters
519cb848 1501
6264b550 1502 DeletePendingObjects() ;
8461e4c2 1503 wxMacProcessNotifierAndPendingEvents() ;
169935ad
SC
1504}
1505
76a5e5d2 1506void wxApp::MacHandleOneEvent( WXEVENTREF evr )
169935ad 1507{
c5c9378c
SC
1508#if TARGET_CARBON
1509 EventTargetRef theTarget;
1510 theTarget = GetEventDispatcherTarget();
1511 m_macCurrentEvent = evr ;
1512 SendEventToEventTarget ((EventRef) evr , theTarget);
1513#else
76a5e5d2 1514 EventRecord* ev = (EventRecord*) evr ;
8461e4c2
VZ
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 }
c5c9378c 1565#endif
8461e4c2 1566 wxMacProcessNotifierAndPendingEvents() ;
169935ad
SC
1567}
1568
c5c9378c
SC
1569#if !TARGET_CARBON
1570bool s_macIsInModalLoop = false ;
1571
1572void 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
76a5e5d2 1612void wxApp::MacHandleHighLevelEvent( WXEVENTREF evr )
169935ad 1613{
738a6daa
SC
1614 // we must avoid reentrancy problems when processing high level events eg printing
1615 bool former = s_inYield ;
1616 s_inYield = TRUE ;
76a5e5d2 1617 EventRecord* ev = (EventRecord*) evr ;
8461e4c2 1618 ::AEProcessAppleEvent( ev ) ;
738a6daa 1619 s_inYield = former ;
169935ad
SC
1620}
1621
76a5e5d2 1622void wxApp::MacHandleMouseDownEvent( WXEVENTREF evr )
169935ad 1623{
76a5e5d2 1624 EventRecord* ev = (EventRecord*) evr ;
8461e4c2 1625 wxToolTip::RemoveToolTips() ;
2f1ae414 1626
8461e4c2 1627 WindowRef window;
72055702 1628 WindowRef frontWindow = ::FrontNonFloatingWindow() ;
8461e4c2
VZ
1629 WindowAttributes frontWindowAttributes = NULL ;
1630 if ( frontWindow )
72055702 1631 ::GetWindowAttributes( frontWindow , &frontWindowAttributes ) ;
9779893b 1632
8461e4c2 1633 short windowPart = ::FindWindow(ev->where, &window);
a3722eeb 1634 wxTopLevelWindowMac* win = wxFindWinFromMacWindow( window ) ;
0a67a93b
SC
1635 if ( wxPendingDelete.Member(win) )
1636 return ;
9779893b 1637
8461e4c2
VZ
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) ;
15b41e90 1651 MacHandleMenuSelect( HiWord( menuresult ) , LoWord( menuresult ) );
8461e4c2
VZ
1652 s_lastMouseDown = 0;
1653 }
1654 break ;
8461e4c2
VZ
1655 case inSysWindow :
1656 SystemClick( ev , window ) ;
1657 s_lastMouseDown = 0;
1658 break ;
8461e4c2
VZ
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 } ;
66a09d47 1672 SetPortWindowPort(window) ;
8461e4c2
VZ
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 {
2b5f62a0
VZ
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 )
8461e4c2 1709 {
2b5f62a0
VZ
1710 win->SetSize( newContentRect.left , newContentRect.top ,
1711 newContentRect.right - newContentRect.left ,
1712 newContentRect.bottom - newContentRect.top, wxSIZE_USE_EXISTING);
8461e4c2
VZ
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 ;
0f493093
SC
1726 GrafPtr port ;
1727 GetPort( &port ) ;
1728 Point pt = { 0, 0 } ;
1729 SetPortWindowPort(window) ;
1730 LocalToGlobal( &pt ) ;
1731 SetPort( port ) ;
8461e4c2
VZ
1732
1733 GetWindowPortBounds(window, &tempRect ) ;
0f493093 1734 win->SetSize( pt.h , pt.v , tempRect.right-tempRect.left ,
8461e4c2
VZ
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 ) ;
66a09d47 1749 SetPortWindowPort(window) ;
8461e4c2
VZ
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 ) ;
72055702 1767 ::SelectWindow( window ) ;
8461e4c2
VZ
1768 }
1769 }
1770 else
1771 {
1772 if ( win )
1773 win->MacMouseDown( ev , windowPart ) ;
1774 }
1775 break ;
8461e4c2
VZ
1776 default:
1777 break;
1778 }
169935ad
SC
1779}
1780
76a5e5d2 1781void wxApp::MacHandleMouseUpEvent( WXEVENTREF evr )
169935ad 1782{
76a5e5d2 1783 EventRecord* ev = (EventRecord*) evr ;
8461e4c2
VZ
1784 WindowRef window;
1785
4f5a3250
SC
1786 short windowPart = inNoWindow ;
1787 if ( wxTheApp->s_captureWindow )
1788 {
1789 window = (WindowRef) s_captureWindow->MacGetRootWindow() ;
1790 windowPart = inContent ;
84c1ffa9 1791 }
4f5a3250
SC
1792 else
1793 {
1794 windowPart = ::FindWindow(ev->where, &window) ;
1795 }
8461e4c2
VZ
1796
1797 switch (windowPart)
1798 {
1799 case inMenuBar :
1800 break ;
1801 case inSysWindow :
1802 break ;
1803 default:
1804 {
a3722eeb 1805 wxTopLevelWindowMac* win = wxFindWinFromMacWindow( window ) ;
8461e4c2
VZ
1806 if ( win )
1807 win->MacMouseUp( ev , windowPart ) ;
1808 }
1809 break;
1810 }
169935ad
SC
1811}
1812
15b41e90
SC
1813#endif
1814
72055702 1815long wxMacTranslateKey(unsigned char key, unsigned char code) ;
7c551d95 1816long wxMacTranslateKey(unsigned char key, unsigned char code)
9779893b 1817{
8461e4c2 1818 long retval = key ;
9779893b 1819 switch (key)
519cb848 1820 {
12e049f6 1821 case kHomeCharCode :
8461e4c2
VZ
1822 retval = WXK_HOME;
1823 break;
12e049f6 1824 case kEnterCharCode :
8461e4c2
VZ
1825 retval = WXK_RETURN;
1826 break;
12e049f6 1827 case kEndCharCode :
8461e4c2
VZ
1828 retval = WXK_END;
1829 break;
12e049f6 1830 case kHelpCharCode :
8461e4c2
VZ
1831 retval = WXK_HELP;
1832 break;
12e049f6 1833 case kBackspaceCharCode :
8461e4c2
VZ
1834 retval = WXK_BACK;
1835 break;
12e049f6 1836 case kTabCharCode :
8461e4c2
VZ
1837 retval = WXK_TAB;
1838 break;
12e049f6 1839 case kPageUpCharCode :
8461e4c2
VZ
1840 retval = WXK_PAGEUP;
1841 break;
12e049f6 1842 case kPageDownCharCode :
8461e4c2
VZ
1843 retval = WXK_PAGEDOWN;
1844 break;
12e049f6 1845 case kReturnCharCode :
8461e4c2
VZ
1846 retval = WXK_RETURN;
1847 break;
12e049f6 1848 case kFunctionKeyCharCode :
8461e4c2
VZ
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 ;
12e049f6 1900 case kEscapeCharCode :
8461e4c2
VZ
1901 retval = WXK_ESCAPE ;
1902 break ;
12e049f6 1903 case kLeftArrowCharCode :
8461e4c2
VZ
1904 retval = WXK_LEFT ;
1905 break ;
12e049f6 1906 case kRightArrowCharCode :
8461e4c2
VZ
1907 retval = WXK_RIGHT ;
1908 break ;
12e049f6 1909 case kUpArrowCharCode :
8461e4c2
VZ
1910 retval = WXK_UP ;
1911 break ;
12e049f6 1912 case kDownArrowCharCode :
8461e4c2
VZ
1913 retval = WXK_DOWN ;
1914 break ;
12e049f6 1915 case kDeleteCharCode :
8461e4c2
VZ
1916 retval = WXK_DELETE ;
1917 default:
1918 break ;
1919 } // end switch
1920
1921 return retval;
169935ad
SC
1922}
1923
c5c9378c 1924#if !TARGET_CARBON
76a5e5d2 1925void wxApp::MacHandleKeyDownEvent( WXEVENTREF evr )
169935ad 1926{
76a5e5d2 1927 EventRecord* ev = (EventRecord*) evr ;
8461e4c2
VZ
1928 wxToolTip::RemoveToolTips() ;
1929
1930 UInt32 menuresult = UMAMenuEvent(ev) ;
1931 if ( HiWord( menuresult ) )
1932 {
1933 if ( !s_macIsInModalLoop )
ac2d1ca6 1934 MacHandleMenuSelect( HiWord( menuresult ) , LoWord( menuresult ) ) ;
8461e4c2
VZ
1935 }
1936 else
1937 {
12e049f6
SC
1938 wxWindow* focus = wxWindow::FindFocus() ;
1939
1940 if ( MacSendKeyDownEvent( focus , ev->message , ev->modifiers , ev->when , ev->where.h , ev->where.v ) == false )
ac2d1ca6
SC
1941 {
1942 // has not been handled -> perform default
1943 wxControl* control = wxDynamicCast( focus , wxControl ) ;
1944 if ( control && control->GetMacControl() != NULL )
8461e4c2 1945 {
12e049f6
SC
1946 short keycode ;
1947 short keychar ;
1948 keychar = short(ev->message & charCodeMask);
1949 keycode = short(ev->message & keyCodeMask) >> 8 ;
ac2d1ca6
SC
1950 ::HandleControlKey( (ControlHandle) control->GetMacControl() , keycode , keychar , ev->modifiers ) ;
1951 }
1952 }
1953 }
1954}
1955
c5c9378c
SC
1956void 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
12e049f6 1973bool wxApp::MacSendKeyDownEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey )
ac2d1ca6 1974{
ba12463b
SC
1975 if ( !focus )
1976 return false ;
1977
12e049f6
SC
1978 short keycode ;
1979 short keychar ;
1980 keychar = short(keymessage & charCodeMask);
1981 keycode = short(keymessage & keyCodeMask) >> 8 ;
1982
ef08713a 1983 if ( modifiers & ( controlKey|shiftKey|optionKey ) )
12e049f6
SC
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;
ef08713a 1988 UInt32 keyInfo = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache), ( modifiers & (~(controlKey|shiftKey|optionKey))) | keycode, &state);
12e049f6
SC
1989 keychar = short(keyInfo & charCodeMask);
1990 keycode = short(keyInfo & keyCodeMask) >> 8 ;
1991 }
1992 long keyval = wxMacTranslateKey(keychar, keycode) ;
ef08713a
SC
1993 long realkeyval = keyval ;
1994 if ( keyval == keychar )
1995 {
b96a8bdb 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)
ef08713a 1997 realkeyval = short(keymessage & charCodeMask) ;
b96a8bdb 1998 keyval = wxToupper( keyval ) ;
ef08713a
SC
1999 }
2000
ac2d1ca6 2001 wxKeyEvent event(wxEVT_KEY_DOWN);
41d368a4 2002 bool handled = false ;
ac2d1ca6
SC
2003 event.m_shiftDown = modifiers & shiftKey;
2004 event.m_controlDown = modifiers & controlKey;
2005 event.m_altDown = modifiers & optionKey;
2006 event.m_metaDown = modifiers & cmdKey;
ef08713a 2007 event.m_keyCode = keyval ;
ac2d1ca6
SC
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 {
ba2928c6 2018#if wxUSE_ACCEL
ac2d1ca6
SC
2019 if (!handled)
2020 {
2021 wxWindow *ancestor = focus;
2022 while (ancestor)
2023 {
2024 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
2025 if (command != -1)
8461e4c2 2026 {
ac2d1ca6
SC
2027 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
2028 handled = ancestor->GetEventHandler()->ProcessEvent( command_event );
2029 break;
8461e4c2 2030 }
ac2d1ca6
SC
2031 if (ancestor->IsTopLevel())
2032 break;
2033 ancestor = ancestor->GetParent();
8461e4c2 2034 }
ac2d1ca6
SC
2035 }
2036#endif // wxUSE_ACCEL
2037 }
2038 if (!handled)
2039 {
2040 event.Skip( FALSE ) ;
2041 event.SetEventType( wxEVT_CHAR ) ;
12e049f6 2042 // raw value again
ef08713a 2043 event.m_keyCode = realkeyval ;
ac2d1ca6
SC
2044
2045 handled = focus->GetEventHandler()->ProcessEvent( event ) ;
2046 if ( handled && event.GetSkipped() )
2047 handled = false ;
2048 }
2049 if ( !handled &&
2050 (keyval == WXK_TAB) &&
35a8698b
SC
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
ac2d1ca6 2056 (!focus->HasFlag(wxTE_PROCESS_TAB)) &&
35a8698b 2057#endif
ac2d1ca6
SC
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() ) ;
e562df9b
SC
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);
ac2d1ca6 2088 return true ;
e562df9b
SC
2089 }
2090 }
8461e4c2 2091 /* generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs) */
ac2d1ca6 2092 else if (keyval == WXK_ESCAPE || (keyval == '.' && modifiers & cmdKey ) )
8461e4c2 2093 {
e562df9b
SC
2094 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
2095 new_event.SetEventObject( focus );
2096 handled = focus->GetEventHandler()->ProcessEvent( new_event );
8461e4c2 2097 }
e562df9b 2098 }
8461e4c2 2099 }
ac2d1ca6 2100 return handled ;
169935ad
SC
2101}
2102
12e049f6 2103bool wxApp::MacSendKeyUpEvent( wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey )
ac2d1ca6 2104{
ba12463b
SC
2105 if ( !focus )
2106 return false ;
2107
12e049f6
SC
2108 short keycode ;
2109 short keychar ;
2110 keychar = short(keymessage & charCodeMask);
2111 keycode = short(keymessage & keyCodeMask) >> 8 ;
ef08713a 2112 if ( modifiers & ( controlKey|shiftKey|optionKey ) )
12e049f6
SC
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;
ef08713a 2117 UInt32 keyInfo = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache), ( modifiers & (~(controlKey|shiftKey|optionKey))) | keycode, &state);
12e049f6
SC
2118 keychar = short(keyInfo & charCodeMask);
2119 keycode = short(keyInfo & keyCodeMask) >> 8 ;
2120 }
2121 long keyval = wxMacTranslateKey(keychar, keycode) ;
2122
b96a8bdb
SC
2123 if ( keyval == keychar )
2124 {
2125 keyval = wxToupper( keyval ) ;
2126 }
ac2d1ca6 2127 bool handled = false ;
ac2d1ca6 2128
ba12463b
SC
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;
ef08713a 2134 event.m_keyCode = keyval ;
ba12463b
SC
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
ac2d1ca6
SC
2142 return handled ;
2143}
c5c9378c 2144
15b41e90 2145#if !TARGET_CARBON
76a5e5d2 2146void wxApp::MacHandleActivateEvent( WXEVENTREF evr )
169935ad 2147{
76a5e5d2 2148 EventRecord* ev = (EventRecord*) evr ;
8461e4c2
VZ
2149 WindowRef window = (WindowRef) ev->message ;
2150 if ( window )
2151 {
2152 bool activate = (ev->modifiers & activeFlag ) ;
2153 WindowClass wclass ;
72055702 2154 ::GetWindowClass ( window , &wclass ) ;
8461e4c2
VZ
2155 if ( wclass == kFloatingWindowClass )
2156 {
2157 // if it is a floater we activate/deactivate the front non-floating window instead
72055702 2158 window = ::FrontNonFloatingWindow() ;
8461e4c2 2159 }
a3722eeb 2160 wxTopLevelWindowMac* win = wxFindWinFromMacWindow( window ) ;
8461e4c2 2161 if ( win )
15b41e90 2162 win->MacActivate( ev->when , activate ) ;
8461e4c2 2163 }
169935ad
SC
2164}
2165
76a5e5d2 2166void wxApp::MacHandleUpdateEvent( WXEVENTREF evr )
169935ad 2167{
76a5e5d2 2168 EventRecord* ev = (EventRecord*) evr ;
8461e4c2 2169 WindowRef window = (WindowRef) ev->message ;
a3722eeb 2170 wxTopLevelWindowMac * win = wxFindWinFromMacWindow( window ) ;
8461e4c2
VZ
2171 if ( win )
2172 {
0a67a93b 2173 if ( !wxPendingDelete.Member(win) )
a3722eeb 2174 win->MacUpdate( ev->when ) ;
8461e4c2
VZ
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 }
169935ad
SC
2184}
2185
76a5e5d2 2186void wxApp::MacHandleDiskEvent( WXEVENTREF evr )
169935ad 2187{
76a5e5d2 2188 EventRecord* ev = (EventRecord*) evr ;
8461e4c2 2189 if ( HiWord( ev->message ) != noErr )
519cb848 2190 {
8461e4c2
VZ
2191 OSErr err ;
2192 Point point ;
2193 SetPt( &point , 100 , 100 ) ;
9779893b 2194
8461e4c2
VZ
2195 err = DIBadMount( point , ev->message ) ;
2196 wxASSERT( err == noErr ) ;
8461e4c2 2197 }
169935ad
SC
2198}
2199
76a5e5d2 2200void wxApp::MacHandleOSEvent( WXEVENTREF evr )
169935ad 2201{
76a5e5d2 2202 EventRecord* ev = (EventRecord*) evr ;
8461e4c2
VZ
2203 switch( ( ev->message & osEvtMessageMask ) >> 24 )
2204 {
2205 case suspendResumeMessage :
2206 {
2207 bool isResuming = ev->message & resumeFlag ;
8461e4c2 2208 bool convertClipboard = ev->message & convertClipboardFlag ;
15b41e90 2209
8461e4c2
VZ
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 )
72055702 2220 oldFrontWindow = ::FrontNonFloatingWindow() ;
8461e4c2
VZ
2221
2222 MacResume( convertClipboard ) ;
2223
72055702 2224 newFrontWindow = ::FrontNonFloatingWindow() ;
8461e4c2
VZ
2225
2226 if ( oldFrontWindow )
2227 {
a3722eeb 2228 wxTopLevelWindowMac* win = wxFindWinFromMacWindow( oldFrontWindow ) ;
8461e4c2 2229 if ( win )
15b41e90 2230 win->MacActivate( ev->when , false ) ;
8461e4c2
VZ
2231 }
2232 if ( newFrontWindow )
2233 {
a3722eeb 2234 wxTopLevelWindowMac* win = wxFindWinFromMacWindow( newFrontWindow ) ;
8461e4c2 2235 if ( win )
15b41e90 2236 win->MacActivate( ev->when , true ) ;
8461e4c2
VZ
2237 }
2238 }
2239 else
2240 {
2241 MacSuspend( convertClipboard ) ;
8461e4c2
VZ
2242 }
2243 }
2244 break ;
2245 case mouseMovedMessage :
2246 {
2247 WindowRef window;
2248
2249 wxWindow* currentMouseWindow = NULL ;
2250
12e049f6
SC
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
8461e4c2
VZ
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);
84c1ffa9 2279
8461e4c2
VZ
2280 if ( wxWindow::s_lastMouseWindow )
2281 {
ed60b502
RR
2282 wxMouseEvent eventleave(event);
2283 eventleave.SetEventType( wxEVT_LEAVE_WINDOW );
2284 wxWindow::s_lastMouseWindow->ScreenToClient( &eventleave.m_x, &eventleave.m_y );
d1bdc41d 2285 eventleave.SetEventObject( wxWindow::s_lastMouseWindow ) ;
84c1ffa9 2286
8461e4c2
VZ
2287 wxWindow::s_lastMouseWindow->GetEventHandler()->ProcessEvent(eventleave);
2288 }
2289 if ( currentMouseWindow )
2290 {
ed60b502
RR
2291 wxMouseEvent evententer(event);
2292 evententer.SetEventType( wxEVT_ENTER_WINDOW );
2293 currentMouseWindow->ScreenToClient( &evententer.m_x, &evententer.m_y );
d1bdc41d 2294 evententer.SetEventObject( currentMouseWindow ) ;
8461e4c2
VZ
2295 currentMouseWindow->GetEventHandler()->ProcessEvent(evententer);
2296 }
2297 wxWindow::s_lastMouseWindow = currentMouseWindow ;
2298 }
2299
12e049f6
SC
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
8461e4c2
VZ
2312 switch (windowPart)
2313 {
49a9ce1b 2314 case inContent :
8461e4c2 2315 {
a3722eeb 2316 wxTopLevelWindowMac* win = wxFindWinFromMacWindow( window ) ;
8461e4c2
VZ
2317 if ( win )
2318 win->MacMouseMoved( ev , windowPart ) ;
2319 else
49a9ce1b
SC
2320 {
2321 if ( wxIsBusy() )
2322 {
2323 }
2324 else
2325 UMAShowArrowCursor();
2326 }
8461e4c2
VZ
2327 }
2328 break;
49a9ce1b
SC
2329 default :
2330 {
2331 if ( wxIsBusy() )
2332 {
2333 }
2334 else
2335 UMAShowArrowCursor();
2336 }
2337 break ;
8461e4c2
VZ
2338 }
2339 }
2340 break ;
2341
2342 }
169935ad 2343}
15b41e90
SC
2344#endif
2345
2346void 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}
169935ad 2364
15b41e90 2365#if !TARGET_CARBON
519cb848 2366void wxApp::MacHandleMenuSelect( int macMenuId , int macMenuItemNum )
169935ad 2367{
8461e4c2
VZ
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 {
2b5f62a0
VZ
2385 MenuCommand id ;
2386 GetMenuItemCommandID( GetMenuHandle(macMenuId) , macMenuItemNum , &id ) ;
15b41e90 2387 MacHandleMenuCommand( id ) ;
8461e4c2
VZ
2388 }
2389 HiliteMenu(0);
169935ad 2390}
15b41e90 2391#endif