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