1 /////////////////////////////////////////////////////////////////////////////
8 // Copyright: (c) AUTHOR
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "app.h"
18 #include "wx/window.h"
20 #include "wx/button.h"
23 #include "wx/gdicmn.h"
26 #include "wx/cursor.h"
29 #include "wx/palette.h"
31 #include "wx/dialog.h"
32 #include "wx/msgdlg.h"
34 #include "wx/module.h"
35 #include "wx/memory.h"
36 #include "wx/tooltip.h"
37 #include "wx/textctrl.h"
39 #if wxUSE_WX_RESOURCES
40 # include "wx/resource.h"
55 #include "wx/mac/uma.h"
56 #include "wx/mac/macnotfy.h"
59 # include <CoreServices/CoreServices.h>
63 # include <ToolUtils.h>
64 # include <DiskInit.h>
68 extern char *wxBuffer
;
69 extern wxList wxPendingDelete
;
70 extern wxList
*wxWinMacWindowList
;
71 extern wxList
*wxWinMacControlList
;
73 wxApp
*wxTheApp
= NULL
;
75 #if !USE_SHARED_LIBRARY
76 IMPLEMENT_DYNAMIC_CLASS(wxApp
, wxEvtHandler
)
77 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
)
78 EVT_IDLE(wxApp::OnIdle
)
79 EVT_END_SESSION(wxApp::OnEndSession
)
80 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession
)
85 const short kMacMinHeap
= (29 * 1024) ;
86 // platform specific static variables
88 const short kwxMacMenuBarResource
= 1 ;
89 const short kwxMacAppleMenuId
= 1 ;
91 WXHRGN
wxApp::s_macCursorRgn
= NULL
;
92 wxWindow
* wxApp::s_captureWindow
= NULL
;
93 int wxApp::s_lastMouseDown
= 0 ;
94 long wxApp::sm_lastMessageTime
= 0;
96 bool wxApp::s_macDefaultEncodingIsPC
= true ;
97 bool wxApp::s_macSupportPCMenuShortcuts
= true ;
98 long wxApp::s_macAboutMenuItemId
= wxID_ABOUT
;
99 wxString
wxApp::s_macHelpMenuTitleName
= "&Help" ;
101 pascal OSErr
AEHandleODoc( const AppleEvent
*event
, AppleEvent
*reply
, long refcon
) ;
102 pascal OSErr
AEHandleOApp( const AppleEvent
*event
, AppleEvent
*reply
, long refcon
) ;
103 pascal OSErr
AEHandlePDoc( const AppleEvent
*event
, AppleEvent
*reply
, long refcon
) ;
104 pascal OSErr
AEHandleQuit( const AppleEvent
*event
, AppleEvent
*reply
, long refcon
) ;
107 pascal OSErr
AEHandleODoc( const AppleEvent
*event
, AppleEvent
*reply
, long refcon
)
109 wxApp
* app
= (wxApp
*) refcon
;
110 return wxTheApp
->MacHandleAEODoc( (AppleEvent
*) event
, reply
) ;
113 pascal OSErr
AEHandleOApp( const AppleEvent
*event
, AppleEvent
*reply
, long refcon
)
115 wxApp
* app
= (wxApp
*) refcon
;
116 return wxTheApp
->MacHandleAEOApp( (AppleEvent
*) event
, reply
) ;
119 pascal OSErr
AEHandlePDoc( const AppleEvent
*event
, AppleEvent
*reply
, long refcon
)
121 wxApp
* app
= (wxApp
*) refcon
;
122 return wxTheApp
->MacHandleAEPDoc( (AppleEvent
*) event
, reply
) ;
125 pascal OSErr
AEHandleQuit( const AppleEvent
*event
, AppleEvent
*reply
, long refcon
)
127 wxApp
* app
= (wxApp
*) refcon
;
128 return wxTheApp
->MacHandleAEQuit( (AppleEvent
*) event
, reply
) ;
131 short wxApp::MacHandleAEODoc(const WXEVENTREF event
, WXEVENTREF reply
)
134 ProcessSerialNumber PSN
;
135 PSN
.highLongOfPSN
= 0 ;
136 PSN
.lowLongOfPSN
= kCurrentProcess
;
137 SetFrontProcess( &PSN
) ;
141 short wxApp::MacHandleAEPDoc(const WXEVENTREF event
, WXEVENTREF reply
)
146 short wxApp::MacHandleAEOApp(const WXEVENTREF event
, WXEVENTREF reply
)
151 short wxApp::MacHandleAEQuit(const WXEVENTREF event
, WXEVENTREF reply
)
153 wxWindow
* win
= GetTopWindow() ;
165 char StringMac
[] = "\x0d\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
166 "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
167 "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xae\xaf"
168 "\xb1\xb4\xb5\xb6\xbb\xbc\xbe\xbf"
169 "\xc0\xc1\xc2\xc4\xc7\xc8\xc9\xcb\xcc\xcd\xce\xcf"
170 "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd8\xca\xdb" ;
172 char StringANSI
[] = "\x0a\xC4\xC5\xC7\xC9\xD1\xD6\xDC\xE1\xE0\xE2\xE4\xE3\xE5\xE7\xE9\xE8"
173 "\xEA\xEB\xED\xEC\xEE\xEF\xF1\xF3\xF2\xF4\xF6\xF5\xFA\xF9\xFB\xFC"
174 "\x86\xBA\xA2\xA3\xA7\x95\xB6\xDF\xAE\xA9\x99\xB4\xA8\xC6\xD8"
175 "\xB1\xA5\xB5\xF0\xAA\xBA\xE6\xF8"
176 "\xBF\xA1\xAC\x83\xAB\xBB\x85\xC0\xC3\xD5\x8C\x9C"
177 "\x96\x97\x93\x94\x91\x92\xF7\xFF\xA0\x80" ;
179 void wxMacConvertFromPC( const char *from
, char *to
, int len
)
184 for( int i
= 0 ; i
< len
; ++ i
)
186 c
= strchr( StringANSI
, *from
) ;
189 *to
= StringMac
[ c
- StringANSI
] ;
197 for( int i
= 0 ; i
< len
; ++ i
)
199 c
= strchr( StringANSI
, *from
) ;
202 *to
= StringMac
[ c
- StringANSI
] ;
214 void wxMacConvertToPC( const char *from
, char *to
, int len
)
219 for( int i
= 0 ; i
< len
; ++ i
)
221 c
= strchr( StringMac
, *from
) ;
224 *to
= StringANSI
[ c
- StringMac
] ;
232 for( int i
= 0 ; i
< len
; ++ i
)
234 c
= strchr( StringMac
, *from
) ;
237 *to
= StringANSI
[ c
- StringMac
] ;
249 void wxMacConvertFromPC( char * p
)
252 int len
= strlen ( p
) ;
254 wxMacConvertFromPC( ptr
, ptr
, len
) ;
257 void wxMacConvertFromPCForControls( char * p
)
260 int len
= strlen ( p
) ;
262 wxMacConvertFromPC( ptr
, ptr
, len
) ;
263 for ( int i
= 0 ; i
< strlen ( ptr
) ; i
++ )
265 if ( ptr
[i
] == '&' && ptr
[i
]+1 != ' ' )
267 memmove( &ptr
[i
] , &ptr
[i
+1] , strlen( &ptr
[i
+1] ) + 1) ;
272 void wxMacConvertFromPC( unsigned char *p
)
274 char *ptr
= (char*) p
+ 1 ;
277 wxMacConvertFromPC( ptr
, ptr
, len
) ;
280 extern char *wxBuffer
;
282 wxString
wxMacMakeMacStringFromPC( const char * p
)
284 const char *ptr
= p
;
285 int len
= strlen ( p
) ;
286 char *buf
= wxBuffer
;
288 if ( len
>= BUFSIZ
+ 512 )
290 buf
= new char [len
+1] ;
293 wxMacConvertFromPC( ptr
, buf
, len
) ;
295 wxString
result( buf
) ;
296 if ( buf
!= wxBuffer
)
302 void wxMacConvertToPC( char * p
)
305 int len
= strlen ( p
) ;
307 wxMacConvertToPC( ptr
, ptr
, len
) ;
310 void wxMacConvertToPC( unsigned char *p
)
312 char *ptr
= (char*) p
+ 1 ;
315 wxMacConvertToPC( ptr
, ptr
, len
) ;
318 wxString
wxMacMakePCStringFromMac( const char * p
)
320 const char *ptr
= p
;
321 int len
= strlen ( p
) ;
322 char *buf
= wxBuffer
;
324 if ( len
>= BUFSIZ
+ 512 )
326 buf
= new char [len
+1] ;
329 wxMacConvertToPC( ptr
, buf
, len
) ;
332 wxString
result( buf
) ;
333 if ( buf
!= wxBuffer
)
338 wxString
wxMacMakeStringFromMacString( const char* from
, bool mac2pcEncoding
)
342 return wxMacMakePCStringFromMac( from
) ;
346 return wxString( from
) ;
350 wxString
wxMacMakeStringFromPascal( StringPtr from
, bool mac2pcEncoding
)
352 // this is safe since a pascal string can never be larger than 256 bytes
354 CopyPascalStringToC( from
, s
) ;
357 return wxMacMakePCStringFromMac( s
) ;
361 return wxString( s
) ;
365 void wxMacStringToPascal( const char * from
, StringPtr to
, bool pc2macEncoding
)
369 CopyCStringToPascal( wxMacMakeMacStringFromPC( from
) , to
) ;
373 CopyCStringToPascal( from
, to
) ;
378 // we know it's there ;-)
379 WXIMPORT
char std::__throws_bad_alloc
;
383 bool wxApp::Initialize()
389 UMAInitToolbox( 4 ) ;
390 SetEventMask( everyEvent
) ;
391 UMAShowWatchCursor() ;
393 #if defined(UNIVERSAL_INTERFACES_VERSION) && (UNIVERSAL_INTERFACES_VERSION >= 0x0340)
394 AEInstallEventHandler( kCoreEventClass
, kAEOpenDocuments
, NewAEEventHandlerUPP(AEHandleODoc
) ,
395 (long) wxTheApp
, FALSE
) ;
396 AEInstallEventHandler( kCoreEventClass
, kAEOpenApplication
, NewAEEventHandlerUPP(AEHandleOApp
) ,
397 (long) wxTheApp
, FALSE
) ;
398 AEInstallEventHandler( kCoreEventClass
, kAEPrintDocuments
, NewAEEventHandlerUPP(AEHandlePDoc
) ,
399 (long) wxTheApp
, FALSE
) ;
400 AEInstallEventHandler( kCoreEventClass
, kAEQuitApplication
, NewAEEventHandlerUPP(AEHandleQuit
) ,
401 (long) wxTheApp
, FALSE
) ;
403 AEInstallEventHandler( kCoreEventClass
, kAEOpenDocuments
, NewAEEventHandlerProc(AEHandleODoc
) ,
404 (long) wxTheApp
, FALSE
) ;
405 AEInstallEventHandler( kCoreEventClass
, kAEOpenApplication
, NewAEEventHandlerProc(AEHandleOApp
) ,
406 (long) wxTheApp
, FALSE
) ;
407 AEInstallEventHandler( kCoreEventClass
, kAEPrintDocuments
, NewAEEventHandlerProc(AEHandlePDoc
) ,
408 (long) wxTheApp
, FALSE
) ;
409 AEInstallEventHandler( kCoreEventClass
, kAEQuitApplication
, NewAEEventHandlerProc(AEHandleQuit
) ,
410 (long) wxTheApp
, FALSE
) ;
415 // test the minimal configuration necessary
421 if (Gestalt(gestaltMachineType
, &theMachine
) != noErr
)
423 error
= kMacSTRWrongMachine
;
425 else if (theMachine
< gestaltMacPlus
)
427 error
= kMacSTRWrongMachine
;
429 else if (Gestalt(gestaltSystemVersion
, &theSystem
) != noErr
)
431 error
= kMacSTROldSystem
;
433 else if ( theSystem
< 0x0860 )
435 error
= kMacSTROldSystem
;
437 else if ((long)GetApplLimit() - (long)ApplicationZone() < kMacMinHeap
)
439 error
= kMacSTRSmallSize
;
445 if ( !UMAHasAppearance() )
447 error = kMacSTRNoPre8Yet ;
453 // if we encountered any problems so far, give the error code and exit immediately
457 wxStAppResource resload
;
461 GetIndString(message
, 128, error
);
462 UMAShowArrowCursor() ;
463 ParamText("\pFatal Error", message
, (ConstStr255Param
)"\p", (ConstStr255Param
)"\p");
464 itemHit
= Alert(128, nil
);
469 #if __option(profile)
470 ProfilerInit( collectDetailed
, bestTimeBase
, 20000 , 40 ) ;
474 // now avoid exceptions thrown for new (bad_alloc)
477 std::__throws_bad_alloc
= FALSE
;
480 s_macCursorRgn
= ::NewRgn() ;
483 wxBuffer
= new char[1500];
485 wxBuffer
= new char[BUFSIZ
+ 512];
488 wxClassInfo::InitializeClasses();
491 // wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
495 wxPendingEventsLocker
= new wxCriticalSection
;
497 wxTheColourDatabase
= new wxColourDatabase(wxKEY_STRING
);
498 wxTheColourDatabase
->Initialize();
502 // flush the logged messages if any and install a 'safer' log target: the
503 // default one (wxLogGui) can't be used after the resources are freed just
504 // below and the user suppliedo ne might be even more unsafe (using any
505 // wxWindows GUI function is unsafe starting from now)
506 wxLog::DontCreateOnDemand();
508 // this will flush the old messages if any
509 delete wxLog::SetActiveTarget(new wxLogStderr
);
513 wxWinMacWindowList
= new wxList(wxKEY_INTEGER
);
514 wxWinMacControlList
= new wxList(wxKEY_INTEGER
);
516 wxInitializeStockLists();
517 wxInitializeStockObjects();
519 #if wxUSE_WX_RESOURCES
520 wxInitializeResourceSystem();
523 wxBitmap::InitStandardHandlers();
525 wxModule::RegisterModules();
526 if (!wxModule::InitializeModules()) {
530 wxMacCreateNotifierTable() ;
532 UMAShowArrowCursor() ;
537 void wxApp::CleanUp()
539 wxToolTip::RemoveToolTips() ;
541 // flush the logged messages if any and install a 'safer' log target: the
542 // default one (wxLogGui) can't be used after the resources are freed just
543 // below and the user suppliedo ne might be even more unsafe (using any
544 // wxWindows GUI function is unsafe starting from now)
545 wxLog::DontCreateOnDemand();
547 // this will flush the old messages if any
548 delete wxLog::SetActiveTarget(new wxLogStderr
);
551 // One last chance for pending objects to be cleaned up
552 wxTheApp
->DeletePendingObjects();
554 wxModule::CleanUpModules();
556 #if wxUSE_WX_RESOURCES
557 wxCleanUpResourceSystem();
560 wxDeleteStockObjects() ;
562 // Destroy all GDI lists, etc.
563 wxDeleteStockLists();
565 delete wxTheColourDatabase
;
566 wxTheColourDatabase
= NULL
;
568 wxBitmap::CleanUpHandlers();
573 wxMacDestroyNotifierTable() ;
574 if (wxWinMacWindowList
)
575 delete wxWinMacWindowList
;
577 if (wxWinMacControlList
)
578 delete wxWinMacControlList
;
580 delete wxPendingEvents
;
582 delete wxPendingEventsLocker
;
583 // If we don't do the following, we get an apparent memory leak.
584 ((wxEvtHandler
&) wxDefaultValidator
).ClearEventLocker();
587 wxClassInfo::CleanUpClasses();
590 #if __option(profile)
591 ProfilerDump( "\papp.prof" ) ;
599 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
600 // At this point we want to check if there are any memory
601 // blocks that aren't part of the wxDebugContext itself,
602 // as a special case. Then when dumping we need to ignore
603 // wxDebugContext, too.
604 if (wxDebugContext::CountObjectsLeft(TRUE
) > 0)
606 wxLogDebug(wxT("There were memory leaks."));
607 wxDebugContext::Dump();
608 wxDebugContext::PrintStatistics();
610 // wxDebugContext::SetStream(NULL, NULL);
614 // do it as the very last thing because everything else can log messages
615 delete wxLog::SetActiveTarget(NULL
);
618 UMACleanupToolbox() ;
620 ::DisposeRgn((RgnHandle
)s_macCursorRgn
);
627 //----------------------------------------------------------------------
629 //----------------------------------------------------------------------
631 short gCurrentResource
= -1 ;
633 wxStAppResource::wxStAppResource()
635 m_currentRefNum
= CurResFile() ;
636 if ( gCurrentResource
!= -1 )
638 UseResFile( gCurrentResource
) ;
642 wxStAppResource::~wxStAppResource()
644 if ( m_currentRefNum
!= -1 )
646 UseResFile( m_currentRefNum
) ;
652 // for shared libraries we have to manually get the correct resource ref num upon
653 // initializing and releasing when terminating, therefore the __wxinitialize and __wxterminate
660 void __sinit(void); /* (generated by linker) */
661 pascal OSErr
__initialize(const CFragInitBlock
*theInitBlock
);
662 pascal void __terminate(void);
668 pascal OSErr
__wxinitialize(const CFragInitBlock
*theInitBlock
)
670 gCurrentResource
= -1;
672 if (theInitBlock
->fragLocator
.where
== kDataForkCFragLocator
) {
674 FSpOpenResFile(theInitBlock
->fragLocator
.u
.onDisk
.fileSpec
,
677 return __initialize( theInitBlock
) ;
680 pascal void __wxterminate(void)
682 if (gCurrentResource
!= -1)
683 CloseResFile(gCurrentResource
);
688 int WXDLLEXPORT
wxEntryStart( int argc
, char *argv
[] )
690 return wxApp::Initialize();
694 int WXDLLEXPORT
wxEntryInitGui()
696 return wxTheApp
->OnInitGui();
700 void WXDLLEXPORT
wxEntryCleanup()
706 int wxEntry( int argc
, char *argv
[] , bool enterLoop
)
708 gCurrentResource
= CurResFile() ;
710 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
711 // This seems to be necessary since there are 'rogue'
712 // objects present at this point (perhaps global objects?)
713 // Setting a checkpoint will ignore them as far as the
714 // memory checking facility is concerned.
715 // Of course you may argue that memory allocated in globals should be
716 // checked, but this is a reasonable compromise.
717 wxDebugContext::SetCheckpoint();
720 if (!wxEntryStart(argc
, argv
)) {
723 // create the application object or ensure that one already exists
726 // The app may have declared a global application object, but we recommend
727 // the IMPLEMENT_APP macro is used instead, which sets an initializer
728 // function for delayed, dynamic app object construction.
729 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
730 wxT("No initializer - use IMPLEMENT_APP macro.") );
732 wxTheApp
= (wxApp
*) (*wxApp::GetInitializerFunction()) ();
735 wxCHECK_MSG( wxTheApp
, 0, wxT("You have to define an instance of wxApp!") );
738 argc
= 0 ; // currently we don't support files as parameters
740 // we could try to get the open apple events here to adjust argc and argv better
742 wxTheApp
->argc
= argc
;
743 wxTheApp
->argv
= argv
;
745 // GUI-specific initialization, such as creating an app context.
749 // Here frames insert themselves automatically
750 // into wxTopLevelWindows by getting created
755 if ( wxTheApp
->OnInit() )
759 retValue
= wxTheApp
->OnRun();
762 // We want to initialize, but not run or exit immediately.
765 //else: app initialization failed, so we skipped OnRun()
767 wxWindow
*topWindow
= wxTheApp
->GetTopWindow();
770 // Forcibly delete the window.
771 if ( topWindow
->IsKindOf(CLASSINFO(wxFrame
)) ||
772 topWindow
->IsKindOf(CLASSINFO(wxDialog
)) )
774 topWindow
->Close(TRUE
);
775 wxTheApp
->DeletePendingObjects();
780 wxTheApp
->SetTopWindow(NULL
);
791 // Static member initialization
792 wxAppInitializerFunction
wxAppBase::m_appInitFn
= (wxAppInitializerFunction
) NULL
;
799 #if WXWIN_COMPATIBILITY_2_2
800 m_wantDebugOutput
= TRUE
;
806 m_printMode
= wxPRINT_WINDOWS
;
807 m_exitOnFrameDelete
= TRUE
;
811 bool wxApp::Initialized()
819 int wxApp::MainLoop()
831 // Returns TRUE if more time is needed.
832 bool wxApp::ProcessIdle()
835 event
.SetEventObject(this);
838 return event
.MoreRequested();
841 void wxApp::ExitMainLoop()
846 // Is a message/event pending?
847 bool wxApp::Pending()
851 return EventAvail( everyEvent
, &event
) ;
854 // Dispatch a message.
855 void wxApp::Dispatch()
860 void wxApp::OnIdle(wxIdleEvent
& event
)
862 static bool s_inOnIdle
= FALSE
;
864 // Avoid recursion (via ProcessEvent default case)
871 // 'Garbage' collection of windows deleted with Close().
872 DeletePendingObjects();
874 // flush the logged messages if any
875 wxLog
*pLog
= wxLog::GetActiveTarget();
876 if ( pLog
!= NULL
&& pLog
->HasPendingMessages() )
879 // Send OnIdle events to all windows
880 bool needMore
= SendIdleEvents();
883 event
.RequestMore(TRUE
);
885 // If they are pending events, we must process them: pending events are
886 // either events to the threads other than main or events posted with
887 // wxPostEvent() functions
888 wxMacProcessNotifierAndPendingEvents();
898 // Send idle event to all top-level windows
899 bool wxApp::SendIdleEvents()
901 bool needMore
= FALSE
;
902 wxNode
* node
= wxTopLevelWindows
.First();
905 wxWindow
* win
= (wxWindow
*) node
->Data();
906 if (SendIdleEvents(win
))
914 // Send idle event to window and all subwindows
915 bool wxApp::SendIdleEvents(wxWindow
* win
)
917 bool needMore
= FALSE
;
920 event
.SetEventObject(win
);
921 win
->ProcessEvent(event
);
923 if (event
.MoreRequested())
926 wxNode
* node
= win
->GetChildren().First();
929 wxWindow
* win
= (wxWindow
*) node
->Data();
930 if (SendIdleEvents(win
))
938 void wxApp::DeletePendingObjects()
940 wxNode
*node
= wxPendingDelete
.First();
943 wxObject
*obj
= (wxObject
*)node
->Data();
947 if (wxPendingDelete
.Member(obj
))
950 // Deleting one object may have deleted other pending
951 // objects, so start from beginning of list again.
952 node
= wxPendingDelete
.First();
957 wxApp::GetStdIcon(int which
) const
961 case wxICON_INFORMATION
:
962 return wxIcon("wxICON_INFO");
964 case wxICON_QUESTION
:
965 return wxIcon("wxICON_QUESTION");
967 case wxICON_EXCLAMATION
:
968 return wxIcon("wxICON_WARNING");
971 wxFAIL_MSG(wxT("requested non existent standard icon"));
972 // still fall through
975 return wxIcon("wxICON_ERROR");
981 wxLogError(_("Fatal error: exiting"));
987 void wxApp::OnEndSession(wxCloseEvent
& WXUNUSED(event
))
990 GetTopWindow()->Close(TRUE
);
993 // Default behaviour: close the application with prompts. The
994 // user can veto the close, and therefore the end session.
995 void wxApp::OnQueryEndSession(wxCloseEvent
& event
)
999 if (!GetTopWindow()->Close(!event
.CanVeto()))
1004 extern "C" void wxCYield() ;
1010 // Yield to other processes
1012 bool wxApp::Yield(bool onlyIfNeeded
)
1014 static bool s_inYield
= FALSE
;
1018 if ( !onlyIfNeeded
)
1020 wxFAIL_MSG( wxT("wxYield called recursively" ) );
1029 YieldToAnyThread() ;
1033 long sleepTime
= 1 ; //::GetCaretTime();
1035 while ( !wxTheApp
->IsExiting() && WaitNextEvent(everyEvent
, &event
,sleepTime
, (RgnHandle
) wxApp::s_macCursorRgn
))
1037 wxTheApp
->MacHandleOneEvent( &event
);
1038 if ( event
.what
!= kHighLevelEvent
)
1039 SetRectRgn( (RgnHandle
) wxApp::s_macCursorRgn
, event
.where
.h
, event
.where
.v
, event
.where
.h
+ 1 , event
.where
.v
+ 1 ) ;
1042 wxMacProcessNotifierAndPendingEvents() ;
1049 // platform specifics
1051 void wxApp::MacSuspend( bool convertClipboard
)
1053 // we have to deactive the top level windows manually
1055 wxNode
* node
= wxTopLevelWindows
.First();
1058 wxTopLevelWindow
* win
= (wxTopLevelWindow
*) node
->Data();
1059 win
->MacActivate( MacGetCurrentEvent() , false ) ;
1061 node
= node
->Next();
1064 s_lastMouseDown
= 0 ;
1065 if( convertClipboard
)
1067 MacConvertPrivateToPublicScrap() ;
1070 ::HideFloatingWindows() ;
1073 void wxApp::MacResume( bool convertClipboard
)
1075 s_lastMouseDown
= 0 ;
1076 if( convertClipboard
)
1078 MacConvertPublicToPrivateScrap() ;
1081 ::ShowFloatingWindows() ;
1084 void wxApp::MacConvertPrivateToPublicScrap()
1088 void wxApp::MacConvertPublicToPrivateScrap()
1092 void wxApp::MacDoOneEvent()
1096 long sleepTime
= 1; // GetCaretTime() / 4 ;
1098 if (WaitNextEvent(everyEvent
, &event
, sleepTime
, (RgnHandle
) s_macCursorRgn
))
1100 MacHandleOneEvent( &event
);
1105 WindowPtr window
= ::FrontWindow() ;
1107 ::IdleControls( window
) ;
1109 wxTheApp
->ProcessIdle() ;
1111 if ( event
.what
!= kHighLevelEvent
)
1112 SetRectRgn( (RgnHandle
) s_macCursorRgn
, event
.where
.h
, event
.where
.v
, event
.where
.h
+ 1 , event
.where
.v
+ 1 ) ;
1116 DeletePendingObjects() ;
1117 wxMacProcessNotifierAndPendingEvents() ;
1120 void wxApp::MacHandleOneEvent( WXEVENTREF evr
)
1122 EventRecord
* ev
= (EventRecord
*) evr
;
1123 m_macCurrentEvent
= ev
;
1125 wxApp::sm_lastMessageTime
= ev
->when
;
1130 MacHandleMouseDownEvent( ev
) ;
1131 if ( ev
->modifiers
& controlKey
)
1132 s_lastMouseDown
= 2;
1134 s_lastMouseDown
= 1;
1137 if ( s_lastMouseDown
== 2 )
1139 ev
->modifiers
|= controlKey
;
1143 ev
->modifiers
&= ~controlKey
;
1145 MacHandleMouseUpEvent( ev
) ;
1146 s_lastMouseDown
= 0;
1149 MacHandleActivateEvent( ev
) ;
1152 MacHandleUpdateEvent( ev
) ;
1156 MacHandleKeyDownEvent( ev
) ;
1159 MacHandleKeyUpEvent( ev
) ;
1162 MacHandleDiskEvent( ev
) ;
1165 MacHandleOSEvent( ev
) ;
1167 case kHighLevelEvent
:
1168 MacHandleHighLevelEvent( ev
) ;
1173 wxMacProcessNotifierAndPendingEvents() ;
1176 void wxApp::MacHandleHighLevelEvent( WXEVENTREF evr
)
1178 EventRecord
* ev
= (EventRecord
*) evr
;
1179 ::AEProcessAppleEvent( ev
) ;
1182 bool s_macIsInModalLoop
= false ;
1184 void wxApp::MacHandleMouseDownEvent( WXEVENTREF evr
)
1186 EventRecord
* ev
= (EventRecord
*) evr
;
1187 wxToolTip::RemoveToolTips() ;
1190 WindowRef frontWindow
= ::FrontNonFloatingWindow() ;
1191 WindowAttributes frontWindowAttributes
= NULL
;
1193 ::GetWindowAttributes( frontWindow
, &frontWindowAttributes
) ;
1195 short windowPart
= ::FindWindow(ev
->where
, &window
);
1196 wxTopLevelWindowMac
* win
= wxFindWinFromMacWindow( window
) ;
1197 if ( wxPendingDelete
.Member(win
) )
1201 GetQDGlobalsScreenBits( &screenBits
);
1206 if ( s_macIsInModalLoop
)
1212 UInt32 menuresult
= MenuSelect(ev
->where
) ;
1213 MacHandleMenuSelect( HiWord( menuresult
) , LoWord( menuresult
) );
1214 s_lastMouseDown
= 0;
1219 SystemClick( ev
, window
) ;
1220 s_lastMouseDown
= 0;
1224 if ( window
!= frontWindow
&& s_macIsInModalLoop
&& !(ev
->modifiers
& cmdKey
) )
1230 DragWindow(window
, ev
->where
, &screenBits
.bounds
);
1235 Point pt
= { 0, 0 } ;
1236 SetPortWindowPort(window
) ;
1237 LocalToGlobal( &pt
) ;
1239 win
->SetSize( pt
.h
, pt
.v
, -1 ,
1240 -1 , wxSIZE_USE_EXISTING
);
1242 s_lastMouseDown
= 0;
1246 if (TrackGoAway(window
, ev
->where
))
1251 s_lastMouseDown
= 0;
1255 int growResult
= GrowWindow(window
, ev
->where
, &screenBits
.bounds
);
1256 if (growResult
!= 0)
1258 int newWidth
= LoWord(growResult
);
1259 int newHeight
= HiWord(growResult
);
1260 int oldWidth
, oldHeight
;
1265 win
->GetSize(&oldWidth
, &oldHeight
);
1267 newWidth
= oldWidth
;
1269 newHeight
= oldHeight
;
1270 win
->SetSize( -1, -1, newWidth
, newHeight
, wxSIZE_USE_EXISTING
);
1273 s_lastMouseDown
= 0;
1278 if (TrackBox(window
, ev
->where
, windowPart
))
1280 // TODO setup size event
1281 ZoomWindow( window
, windowPart
, false ) ;
1286 GetWindowPortBounds(window
, &tempRect
) ;
1287 win
->SetSize( -1, -1, tempRect
.right
-tempRect
.left
,
1288 tempRect
.bottom
-tempRect
.top
, wxSIZE_USE_EXISTING
);
1291 s_lastMouseDown
= 0;
1293 case inCollapseBox
:
1294 // TODO setup size event
1295 s_lastMouseDown
= 0;
1302 SetPortWindowPort(window
) ;
1305 if ( window
!= frontWindow
&& wxTheApp
->s_captureWindow
== NULL
)
1307 if ( s_macIsInModalLoop
)
1311 else if ( UMAIsWindowFloating( window
) )
1314 win
->MacMouseDown( ev
, windowPart
) ;
1319 win
->MacMouseDown( ev
, windowPart
) ;
1320 ::SelectWindow( window
) ;
1326 win
->MacMouseDown( ev
, windowPart
) ;
1335 void wxApp::MacHandleMouseUpEvent( WXEVENTREF evr
)
1337 EventRecord
* ev
= (EventRecord
*) evr
;
1340 short windowPart
= inNoWindow
;
1341 if ( wxTheApp
->s_captureWindow
)
1343 window
= (WindowRef
) s_captureWindow
->MacGetRootWindow() ;
1344 windowPart
= inContent
;
1348 windowPart
= ::FindWindow(ev
->where
, &window
) ;
1359 wxTopLevelWindowMac
* win
= wxFindWinFromMacWindow( window
) ;
1361 win
->MacMouseUp( ev
, windowPart
) ;
1367 long wxMacTranslateKey(unsigned char key
, unsigned char code
) ;
1368 long wxMacTranslateKey(unsigned char key
, unsigned char code
)
1377 retval
= WXK_RETURN
;
1392 retval
= WXK_PAGEUP
;
1395 retval
= WXK_PAGEDOWN
;
1398 retval
= WXK_RETURN
;
1453 retval
= WXK_ESCAPE
;
1459 retval
= WXK_RIGHT
;
1468 retval
= WXK_DELETE
;
1476 void wxApp::MacHandleKeyDownEvent( WXEVENTREF evr
)
1478 EventRecord
* ev
= (EventRecord
*) evr
;
1479 wxToolTip::RemoveToolTips() ;
1481 UInt32 menuresult
= UMAMenuEvent(ev
) ;
1482 if ( HiWord( menuresult
) )
1484 if ( !s_macIsInModalLoop
)
1485 MacHandleMenuSelect( HiWord( menuresult
) , LoWord( menuresult
) ) ;
1491 keychar
= short(ev
->message
& charCodeMask
);
1492 keycode
= short(ev
->message
& keyCodeMask
) >> 8 ;
1493 long keyval
= wxMacTranslateKey(keychar
, keycode
) ;
1494 bool handled
= false ;
1495 wxWindow
* focus
= wxWindow::FindFocus() ;
1499 wxKeyEvent
event(wxEVT_KEY_DOWN
);
1500 event
.m_shiftDown
= ev
->modifiers
& shiftKey
;
1501 event
.m_controlDown
= ev
->modifiers
& controlKey
;
1502 event
.m_altDown
= ev
->modifiers
& optionKey
;
1503 event
.m_metaDown
= ev
->modifiers
& cmdKey
;
1504 event
.m_keyCode
= keyval
;
1505 event
.m_x
= ev
->where
.h
;
1506 event
.m_y
= ev
->where
.v
;
1507 event
.m_timeStamp
= ev
->when
;
1508 event
.SetEventObject(focus
);
1509 handled
= focus
->GetEventHandler()->ProcessEvent( event
) ;
1515 wxWindow
*ancestor
= focus
;
1519 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
1522 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
1523 handled = ancestor->GetEventHandler()->ProcessEvent( command_event );
1526 if (ancestor->m_isFrame)
1528 ancestor = ancestor->GetParent();
1532 #endif // wxUSE_ACCEL
1536 wxKeyEvent
event(wxEVT_CHAR
);
1537 event
.m_shiftDown
= ev
->modifiers
& shiftKey
;
1538 event
.m_controlDown
= ev
->modifiers
& controlKey
;
1539 event
.m_altDown
= ev
->modifiers
& optionKey
;
1540 event
.m_metaDown
= ev
->modifiers
& cmdKey
;
1541 event
.m_keyCode
= keyval
;
1542 event
.m_x
= ev
->where
.h
;
1543 event
.m_y
= ev
->where
.v
;
1544 event
.m_timeStamp
= ev
->when
;
1545 event
.SetEventObject(focus
);
1546 handled
= focus
->GetEventHandler()->ProcessEvent( event
) ;
1549 (keyval
== WXK_TAB
) &&
1550 (!focus
->HasFlag(wxTE_PROCESS_TAB
)) &&
1551 (focus
->GetParent()) &&
1552 (focus
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1554 wxNavigationKeyEvent new_event
;
1555 new_event
.SetEventObject( focus
);
1556 new_event
.SetDirection( !event
.ShiftDown() );
1557 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1558 new_event
.SetWindowChange( event
.ControlDown() );
1559 new_event
.SetCurrentFocus( focus
);
1560 handled
= focus
->GetEventHandler()->ProcessEvent( new_event
);
1565 // if window is not having a focus still testing for default enter or cancel
1566 // TODO add the UMA version for ActiveNonFloatingWindow
1567 focus
= wxFindWinFromMacWindow( FrontWindow() ) ;
1570 if ( keyval
== WXK_RETURN
)
1572 wxButton
*def
= wxDynamicCast(focus
->GetDefaultItem(),
1574 if ( def
&& def
->IsEnabled() )
1576 wxCommandEvent
event(wxEVT_COMMAND_BUTTON_CLICKED
, def
->GetId() );
1577 event
.SetEventObject(def
);
1578 def
->Command(event
);
1582 /* generate wxID_CANCEL if command-. or <esc> has been pressed (typically in dialogs) */
1583 else if (keyval
== WXK_ESCAPE
|| (keyval
== '.' && ev
->modifiers
& cmdKey
) )
1585 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1586 new_event
.SetEventObject( focus
);
1587 handled
= focus
->GetEventHandler()->ProcessEvent( new_event
);
1594 void wxApp::MacHandleKeyUpEvent( WXEVENTREF evr
)
1596 EventRecord
* ev
= (EventRecord
*) evr
;
1597 wxToolTip::RemoveToolTips() ;
1599 UInt32 menuresult
= UMAMenuEvent(ev
) ;
1600 if ( HiWord( menuresult
) )
1607 keychar
= short(ev
->message
& charCodeMask
);
1608 keycode
= short(ev
->message
& keyCodeMask
) >> 8 ;
1610 wxWindow
* focus
= wxWindow::FindFocus() ;
1613 long keyval
= wxMacTranslateKey(keychar
, keycode
) ;
1615 wxKeyEvent
event(wxEVT_KEY_UP
);
1616 event
.m_shiftDown
= ev
->modifiers
& shiftKey
;
1617 event
.m_controlDown
= ev
->modifiers
& controlKey
;
1618 event
.m_altDown
= ev
->modifiers
& optionKey
;
1619 event
.m_metaDown
= ev
->modifiers
& cmdKey
;
1620 event
.m_keyCode
= keyval
;
1621 event
.m_x
= ev
->where
.h
;
1622 event
.m_y
= ev
->where
.v
;
1623 event
.m_timeStamp
= ev
->when
;
1624 event
.SetEventObject(focus
);
1625 bool handled
= focus
->GetEventHandler()->ProcessEvent( event
) ;
1630 void wxApp::MacHandleActivateEvent( WXEVENTREF evr
)
1632 EventRecord
* ev
= (EventRecord
*) evr
;
1633 WindowRef window
= (WindowRef
) ev
->message
;
1636 bool activate
= (ev
->modifiers
& activeFlag
) ;
1637 WindowClass wclass
;
1638 ::GetWindowClass ( window
, &wclass
) ;
1639 if ( wclass
== kFloatingWindowClass
)
1641 // if it is a floater we activate/deactivate the front non-floating window instead
1642 window
= ::FrontNonFloatingWindow() ;
1644 wxTopLevelWindowMac
* win
= wxFindWinFromMacWindow( window
) ;
1646 win
->MacActivate( ev
, activate
) ;
1650 void wxApp::MacHandleUpdateEvent( WXEVENTREF evr
)
1652 EventRecord
* ev
= (EventRecord
*) evr
;
1653 WindowRef window
= (WindowRef
) ev
->message
;
1654 wxTopLevelWindowMac
* win
= wxFindWinFromMacWindow( window
) ;
1657 if ( !wxPendingDelete
.Member(win
) )
1658 win
->MacUpdate( ev
->when
) ;
1662 // since there is no way of telling this foreign window to update itself
1663 // we have to invalidate the update region otherwise we keep getting the same
1664 // event over and over again
1665 BeginUpdate( window
) ;
1666 EndUpdate( window
) ;
1670 void wxApp::MacHandleDiskEvent( WXEVENTREF evr
)
1672 EventRecord
* ev
= (EventRecord
*) evr
;
1673 if ( HiWord( ev
->message
) != noErr
)
1678 SetPt( &point
, 100 , 100 ) ;
1680 err
= DIBadMount( point
, ev
->message
) ;
1681 wxASSERT( err
== noErr
) ;
1686 void wxApp::MacHandleOSEvent( WXEVENTREF evr
)
1688 EventRecord
* ev
= (EventRecord
*) evr
;
1689 switch( ( ev
->message
& osEvtMessageMask
) >> 24 )
1691 case suspendResumeMessage
:
1693 bool isResuming
= ev
->message
& resumeFlag
;
1695 bool convertClipboard
= ev
->message
& convertClipboardFlag
;
1697 bool convertClipboard
= false;
1699 bool doesActivate
= UMAGetProcessModeDoesActivateOnFGSwitch() ;
1702 WindowRef oldFrontWindow
= NULL
;
1703 WindowRef newFrontWindow
= NULL
;
1705 // in case we don't take care of activating ourselves, we have to synchronize
1706 // our idea of the active window with the process manager's - which it already activated
1708 if ( !doesActivate
)
1709 oldFrontWindow
= ::FrontNonFloatingWindow() ;
1711 MacResume( convertClipboard
) ;
1713 newFrontWindow
= ::FrontNonFloatingWindow() ;
1715 if ( oldFrontWindow
)
1717 wxTopLevelWindowMac
* win
= wxFindWinFromMacWindow( oldFrontWindow
) ;
1719 win
->MacActivate( ev
, false ) ;
1721 if ( newFrontWindow
)
1723 wxTopLevelWindowMac
* win
= wxFindWinFromMacWindow( newFrontWindow
) ;
1725 win
->MacActivate( ev
, true ) ;
1730 MacSuspend( convertClipboard
) ;
1732 // in case this suspending did close an active window, another one might
1733 // have surfaced -> lets deactivate that one
1735 /* TODO : find out what to do on systems < 10 , perhaps FrontNonFloatingWindow
1736 WindowRef newActiveWindow = ::ActiveNonFloatingWindow() ;
1737 if ( newActiveWindow )
1739 wxWindow* win = wxFindWinFromMacWindow( newActiveWindow ) ;
1741 win->MacActivate( ev , false ) ;
1747 case mouseMovedMessage
:
1751 wxWindow
* currentMouseWindow
= NULL
;
1753 wxWindow::MacGetWindowFromPoint( wxPoint( ev
->where
.h
, ev
->where
.v
) ,
1754 ¤tMouseWindow
) ;
1755 if ( currentMouseWindow
!= wxWindow::s_lastMouseWindow
)
1757 wxMouseEvent event
;
1759 bool isDown
= !(ev
->modifiers
& btnState
) ; // 1 is for up
1760 bool controlDown
= ev
->modifiers
& controlKey
; // for simulating right mouse
1762 event
.m_leftDown
= isDown
&& !controlDown
;
1763 event
.m_middleDown
= FALSE
;
1764 event
.m_rightDown
= isDown
&& controlDown
;
1765 event
.m_shiftDown
= ev
->modifiers
& shiftKey
;
1766 event
.m_controlDown
= ev
->modifiers
& controlKey
;
1767 event
.m_altDown
= ev
->modifiers
& optionKey
;
1768 event
.m_metaDown
= ev
->modifiers
& cmdKey
;
1769 event
.m_x
= ev
->where
.h
;
1770 event
.m_y
= ev
->where
.v
;
1771 event
.m_timeStamp
= ev
->when
;
1772 event
.SetEventObject(this);
1774 if ( wxWindow::s_lastMouseWindow
)
1776 wxMouseEvent
eventleave(event
);
1777 eventleave
.SetEventType( wxEVT_LEAVE_WINDOW
);
1778 wxWindow::s_lastMouseWindow
->ScreenToClient( &eventleave
.m_x
, &eventleave
.m_y
);
1780 wxWindow::s_lastMouseWindow
->GetEventHandler()->ProcessEvent(eventleave
);
1782 if ( currentMouseWindow
)
1784 wxMouseEvent
evententer(event
);
1785 evententer
.SetEventType( wxEVT_ENTER_WINDOW
);
1786 currentMouseWindow
->ScreenToClient( &evententer
.m_x
, &evententer
.m_y
);
1788 currentMouseWindow
->GetEventHandler()->ProcessEvent(evententer
);
1790 wxWindow::s_lastMouseWindow
= currentMouseWindow
;
1793 short windowPart
= ::FindWindow(ev
->where
, &window
);
1797 // fixes for setting the cursor back from dominic mazzoni
1799 UMAShowArrowCursor();
1802 UMAShowArrowCursor();
1806 // if ( s_lastMouseDown == 0 )
1807 // ev->modifiers |= btnState ;
1809 // Calling GetNextEvent with a zero event mask will always
1810 // pass back a null event. However, it fills the EventRecord
1811 // with the state of the modifier keys. This is needed since
1812 // the modifier state returned by WaitForNextEvent often is
1813 // wrong mouse move events. The attempt above to correct this
1814 // didn't always work (under OS X at least).
1817 ::GetNextEvent(0, &tmp
);
1818 ev
->modifiers
= tmp
.modifiers
;
1820 wxTopLevelWindowMac
* win
= wxFindWinFromMacWindow( window
) ;
1822 win
->MacMouseMoved( ev
, windowPart
) ;
1824 UMAShowArrowCursor();
1835 void wxApp::MacHandleMenuSelect( int macMenuId
, int macMenuItemNum
)
1838 return; // no menu item selected
1840 if (macMenuId
== kwxMacAppleMenuId
&& macMenuItemNum
> 1)
1843 Str255 deskAccessoryName
;
1846 GetMenuItemText(GetMenuHandle(kwxMacAppleMenuId
), macMenuItemNum
, deskAccessoryName
);
1847 GetPort(&savedPort
);
1848 OpenDeskAcc(deskAccessoryName
);
1854 wxWindow
* frontwindow
= wxFindWinFromMacWindow( ::FrontWindow() ) ;
1855 if ( frontwindow
&& wxMenuBar::MacGetInstalledMenuBar() )
1856 wxMenuBar::MacGetInstalledMenuBar()->MacMenuSelect( frontwindow
->GetEventHandler() , 0 , macMenuId
, macMenuItemNum
) ;
1862 long wxApp::MacTranslateKey(char key, int mods)
1866 void wxApp::MacAdjustCursor()
1873 wxApp::macAdjustCursor()
1875 if (ev->what != kHighLevelEvent)
1877 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(::FrontWindow());
1880 if (!theMacWxFrame->MacAdjustCursor(ev->where))
1881 ::SetCursor(&(qd.arrow));