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