]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/app.cpp
fixed wxScreenDC for X
[wxWidgets.git] / src / mac / app.cpp
index 76ab2b8675c852d5da0d547675045e584035ad2d..7e83eb254a1b770d7a7330751d519f35ef097eef 100644 (file)
@@ -57,6 +57,9 @@
 
 #ifdef __DARWIN__
 #  include <CoreServices/CoreServices.h>
+#  if defined(WXMAKINGDLL)
+#    include <mach-o/dyld.h>
+#  endif
 #else
 #  include <Sound.h>
 #  include <Threads.h>
@@ -88,15 +91,15 @@ const short    kMacMinHeap = (29 * 1024) ;
 const short kwxMacMenuBarResource = 1 ;
 const short kwxMacAppleMenuId = 1 ;
 
-WXHRGN            wxApp::s_macCursorRgn = NULL;
-wxWindow*            wxApp::s_captureWindow = NULL ;
-int                    wxApp::s_lastMouseDown = 0 ;
-long                     wxApp::sm_lastMessageTime = 0;
+WXHRGN    wxApp::s_macCursorRgn = NULL;
+wxWindow* wxApp::s_captureWindow = NULL ;
+int       wxApp::s_lastMouseDown = 0 ;
+long      wxApp::sm_lastMessageTime = 0;
 
-bool    wxApp::s_macDefaultEncodingIsPC = true ;
-bool wxApp::s_macSupportPCMenuShortcuts = true ;
-long wxApp::s_macAboutMenuItemId = wxID_ABOUT ;
-wxString wxApp::s_macHelpMenuTitleName = "&Help" ;
+bool      wxApp::s_macDefaultEncodingIsPC = true ;
+bool      wxApp::s_macSupportPCMenuShortcuts = true ;
+long      wxApp::s_macAboutMenuItemId = wxID_ABOUT ;
+wxString  wxApp::s_macHelpMenuTitleName = "&Help" ;
 
 pascal OSErr AEHandleODoc( const AppleEvent *event , AppleEvent *reply , long refcon ) ;
 pascal OSErr AEHandleOApp( const AppleEvent *event , AppleEvent *reply , long refcon ) ;
@@ -373,48 +376,60 @@ void wxMacStringToPascal( const char * from , StringPtr to , bool pc2macEncoding
       CopyCStringToPascal( from , to ) ;
     }
 }
-#ifdef WXMAKINGDLL
-#ifndef __DARWIN__
+
+#if defined(WXMAKINGDLL) && !defined(__DARWIN__)
 // we know it's there ;-)
 WXIMPORT char std::__throws_bad_alloc ;
 #endif
-#endif
 
 bool wxApp::Initialize()
 {
-  int error = 0 ;
+    int error = 0 ;
 
-  // Mac-specific
+    // Mac-specific
 
-  UMAInitToolbox( 4 ) ;
-  SetEventMask( everyEvent ) ;
+    UMAInitToolbox( 4 ) ;
+    SetEventMask( everyEvent ) ;
     UMAShowWatchCursor() ;
 
+#if defined(WXMAKINGDLL) && defined(__DARWIN__)
+    // open shared library resources from here since we don't have
+    //   __wxinitialize in Mach-O shared libraries
+    wxStAppResource::OpenSharedLibraryResource(NULL);
+#endif
+    
 #if defined(UNIVERSAL_INTERFACES_VERSION) && (UNIVERSAL_INTERFACES_VERSION >= 0x0340)
-    AEInstallEventHandler( kCoreEventClass , kAEOpenDocuments ,   NewAEEventHandlerUPP(AEHandleODoc) ,
+    AEInstallEventHandler( kCoreEventClass , kAEOpenDocuments ,
+                           NewAEEventHandlerUPP(AEHandleODoc) ,
                            (long) wxTheApp , FALSE ) ;
-    AEInstallEventHandler( kCoreEventClass , kAEOpenApplication , NewAEEventHandlerUPP(AEHandleOApp) ,
+    AEInstallEventHandler( kCoreEventClass , kAEOpenApplication ,
+                           NewAEEventHandlerUPP(AEHandleOApp) ,
                            (long) wxTheApp , FALSE ) ;
-    AEInstallEventHandler( kCoreEventClass , kAEPrintDocuments ,  NewAEEventHandlerUPP(AEHandlePDoc) ,
+    AEInstallEventHandler( kCoreEventClass , kAEPrintDocuments ,
+                           NewAEEventHandlerUPP(AEHandlePDoc) ,
                            (long) wxTheApp , FALSE ) ;
-    AEInstallEventHandler( kCoreEventClass , kAEQuitApplication , NewAEEventHandlerUPP(AEHandleQuit) ,
+    AEInstallEventHandler( kCoreEventClass , kAEQuitApplication ,
+                           NewAEEventHandlerUPP(AEHandleQuit) ,
                            (long) wxTheApp , FALSE ) ;
 #else
-    AEInstallEventHandler( kCoreEventClass , kAEOpenDocuments ,   NewAEEventHandlerProc(AEHandleODoc) ,
-                   (long) wxTheApp , FALSE ) ;
-    AEInstallEventHandler( kCoreEventClass , kAEOpenApplication , NewAEEventHandlerProc(AEHandleOApp) ,
-                   (long) wxTheApp , FALSE ) ;
-    AEInstallEventHandler( kCoreEventClass , kAEPrintDocuments ,  NewAEEventHandlerProc(AEHandlePDoc) ,
-                   (long) wxTheApp , FALSE ) ;
-    AEInstallEventHandler( kCoreEventClass , kAEQuitApplication , NewAEEventHandlerProc(AEHandleQuit) ,
-                   (long) wxTheApp , FALSE ) ;
+    AEInstallEventHandler( kCoreEventClass , kAEOpenDocuments ,
+                           NewAEEventHandlerProc(AEHandleODoc) ,
+                           (long) wxTheApp , FALSE ) ;
+    AEInstallEventHandler( kCoreEventClass , kAEOpenApplication ,
+                           NewAEEventHandlerProc(AEHandleOApp) ,
+                           (long) wxTheApp , FALSE ) ;
+    AEInstallEventHandler( kCoreEventClass , kAEPrintDocuments ,
+                           NewAEEventHandlerProc(AEHandlePDoc) ,
+                           (long) wxTheApp , FALSE ) ;
+    AEInstallEventHandler( kCoreEventClass , kAEQuitApplication ,
+                           NewAEEventHandlerProc(AEHandleQuit) ,
+                           (long) wxTheApp , FALSE ) ;
 #endif
 
-
 #ifndef __DARWIN__
-  // test the minimal configuration necessary
+    // test the minimal configuration necessary
 
-    #if !TARGET_CARBON
+#  if !TARGET_CARBON
     long theSystem ;
     long theMachine;
 
@@ -438,7 +453,7 @@ bool wxApp::Initialize()
     {
         error = kMacSTRSmallSize;
     }
-    #endif
+#  endif
     /*
     else
     {
@@ -466,26 +481,21 @@ bool wxApp::Initialize()
   }
 
 #ifndef __DARWIN__
-  #if __option(profile)
+#  if __option(profile)
     ProfilerInit( collectDetailed, bestTimeBase , 20000 , 40 ) ;
-  #endif
+#  endif
 #endif
 
-  // now avoid exceptions thrown for new (bad_alloc)
-
 #ifndef __DARWIN__
-  std::__throws_bad_alloc = FALSE ;
+    // now avoid exceptions thrown for new (bad_alloc)
+    std::__throws_bad_alloc = FALSE ;
 #endif
 
     s_macCursorRgn = ::NewRgn() ;
 
-#ifdef __WXMSW__
-  wxBuffer = new char[1500];
-#else
-  wxBuffer = new char[BUFSIZ + 512];
-#endif
-
-  wxClassInfo::InitializeClasses();
+    wxBuffer = new char[BUFSIZ + 512];
+  
+    wxClassInfo::InitializeClasses();
 
 #if wxUSE_RESOURCES
 //    wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
@@ -494,8 +504,9 @@ bool wxApp::Initialize()
 #if wxUSE_THREADS
     wxPendingEventsLocker = new wxCriticalSection;
 #endif
-  wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
-  wxTheColourDatabase->Initialize();
+    
+    wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
+    wxTheColourDatabase->Initialize();
 
 #ifdef __WXDEBUG__
 #if wxUSE_LOG
@@ -551,50 +562,51 @@ void wxApp::CleanUp()
     // One last chance for pending objects to be cleaned up
     wxTheApp->DeletePendingObjects();
 
-  wxModule::CleanUpModules();
+    wxModule::CleanUpModules();
 
 #if wxUSE_WX_RESOURCES
-  wxCleanUpResourceSystem();
+    wxCleanUpResourceSystem();
 #endif
 
-  wxDeleteStockObjects() ;
+    wxDeleteStockObjects() ;
 
     // Destroy all GDI lists, etc.
     wxDeleteStockLists();
 
-  delete wxTheColourDatabase;
-  wxTheColourDatabase = NULL;
+    delete wxTheColourDatabase;
+    wxTheColourDatabase = NULL;
 
-  wxBitmap::CleanUpHandlers();
+    wxBitmap::CleanUpHandlers();
 
-  delete[] wxBuffer;
-  wxBuffer = NULL;
-
-  wxMacDestroyNotifierTable() ;
-  if (wxWinMacWindowList)
-    delete wxWinMacWindowList ;
-
-  if (wxWinMacControlList)
-    delete wxWinMacControlList ;
+    delete[] wxBuffer;
+    wxBuffer = NULL;
 
+    wxMacDestroyNotifierTable() ;
+    if (wxWinMacWindowList) {
+        delete wxWinMacWindowList ;
+    }
+    if (wxWinMacControlList) {
+        delete wxWinMacControlList ;
+    }
     delete wxPendingEvents;
+    
 #if wxUSE_THREADS
     delete wxPendingEventsLocker;
     // If we don't do the following, we get an apparent memory leak.
     ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
 #endif
 
-  wxClassInfo::CleanUpClasses();
+    wxClassInfo::CleanUpClasses();
 
 #ifndef __DARWIN__
-  #if __option(profile)
-  ProfilerDump( "\papp.prof" ) ;
-  ProfilerTerm() ;
-  #endif
+#  if __option(profile)
+    ProfilerDump( "\papp.prof" ) ;
+    ProfilerTerm() ;
+#  endif
 #endif
 
-  delete wxTheApp;
-  wxTheApp = NULL;
+    delete wxTheApp;
+    wxTheApp = NULL;
 
 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
     // At this point we want to check if there are any memory
@@ -615,10 +627,17 @@ void wxApp::CleanUp()
     delete wxLog::SetActiveTarget(NULL);
 #endif // wxUSE_LOG
 
+#if defined(WXMAKINGDLL) && defined(__DARWIN__)
+    // close shared library resources from here since we don't have
+    //   __wxterminate in Mach-O shared libraries
+    wxStAppResource::CloseSharedLibraryResource();
+#endif
+    
     UMACleanupToolbox() ;
-    if (s_macCursorRgn)
+    if (s_macCursorRgn) {
         ::DisposeRgn((RgnHandle)s_macCursorRgn);
-
+    }
+    
     #if 0
         TerminateAE() ;
     #endif
@@ -628,62 +647,161 @@ void wxApp::CleanUp()
 // wxEntry
 //----------------------------------------------------------------------
 
-short gCurrentResource = -1 ;
+// extern variable for shared library resource id
+// need to be able to find it with NSLookupAndBindSymbol
+short gSharedLibraryResource = kResFileNotOpened ;
+
+#if defined(WXMAKINGDLL) && defined(__DARWIN__)
+CFBundleRef gSharedLibraryBundle = NULL;
+#endif /* WXMAKINGDLL && __DARWIN__ */
 
 wxStAppResource::wxStAppResource()
 {
     m_currentRefNum = CurResFile() ;
-    if ( gCurrentResource != -1 )
+    if ( gSharedLibraryResource != kResFileNotOpened )
     {
-        UseResFile( gCurrentResource ) ;
+        UseResFile( gSharedLibraryResource ) ;
     }
 }
 
 wxStAppResource::~wxStAppResource()
 {
-    if ( m_currentRefNum != -1 )
+    if ( m_currentRefNum != kResFileNotOpened )
     {
         UseResFile( m_currentRefNum ) ;
     }
 }
 
+void wxStAppResource::OpenSharedLibraryResource(const void *initBlock)
+{
+    gSharedLibraryResource = kResFileNotOpened;
+
 #ifdef WXMAKINGDLL
+    if ( initBlock != NULL ) {
+        const CFragInitBlock *theInitBlock = (const CFragInitBlock *)initBlock;
+        FSSpec *fileSpec = NULL;
+        
+        if (theInitBlock->fragLocator.where == kDataForkCFragLocator) {
+            fileSpec = theInitBlock->fragLocator.u.onDisk.fileSpec;
+        }
+        else if (theInitBlock->fragLocator.where == kResourceCFragLocator) {
+            fileSpec = theInitBlock->fragLocator.u.inSegs.fileSpec;
+        }
+        
+        if (fileSpec != NULL) {
+            gSharedLibraryResource =  FSpOpenResFile(fileSpec, fsRdPerm);
+        }
+    }
+    else {
+#ifdef __DARWIN__
+        // Open the shared library resource file if it is not yet open
+        NSSymbol    theSymbol;
+        NSModule    theModule;
+        const char *theLibPath;
+        
+        gSharedLibraryBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.wxwindows.wxWindows"));
+        if (gSharedLibraryBundle != NULL) {
+            // wxWindows has been bundled into a framework
+            //   load the framework resources
+            
+            gSharedLibraryResource = CFBundleOpenBundleResourceMap(gSharedLibraryBundle);
+        }
+        else {
+            // wxWindows is a simple dynamic shared library
+            //   load the resources from the data fork of a separate resource file
+            char  *theResPath;
+            char  *theName;
+            char  *theExt;
+            FSRef  theResRef;
+            OSErr  theErr = noErr;
+            
+            // get the library path
+            theSymbol = NSLookupAndBindSymbol("_gSharedLibraryResource");
+            theModule = NSModuleForSymbol(theSymbol);
+            theLibPath = NSLibraryNameForModule(theModule);
+
+            // allocate copy to replace .dylib.* extension with .rsrc
+            theResPath = strdup(theLibPath);
+            if (theResPath != NULL) {
+                theName = strrchr(theResPath, '/');
+                if (theName == NULL) {
+                    // no directory elements in path
+                    theName = theResPath;
+                }
+                // find ".dylib" shared library extension
+                theExt = strstr(theName, ".dylib");
+                // overwrite extension with ".rsrc"
+                strcpy(theExt, ".rsrc");
+                
+                wxLogDebug( theResPath );
+
+                theErr = FSPathMakeRef((UInt8 *) theResPath, &theResRef, false);
+                if (theErr != noErr) {
+                    // try in current directory (using name only)
+                    theErr = FSPathMakeRef((UInt8 *) theName, &theResRef, false);
+                }
+                
+                // free duplicated resource file path
+                free(theResPath);
+
+                // open the resource file
+                if (theErr == noErr) {
+                    theErr = FSOpenResourceFile( &theResRef, 0, NULL, fsRdPerm,
+                                                 &gSharedLibraryResource);
+                }
+            }
+        }
+#endif /* __DARWIN__ */
+    }
+#endif /* WXMAKINGDLL */
+}
 
-// for shared libraries we have to manually get the correct resource ref num upon
-// initializing and releasing when terminating, therefore the __wxinitialize and __wxterminate
-// must be used
+void wxStAppResource::CloseSharedLibraryResource()
+{
+#ifdef WXMAKINGDLL
+    // Close the shared library resource file
+    if (gSharedLibraryResource != kResFileNotOpened) {
+#ifdef __DARWIN__
+        if (gSharedLibraryBundle != NULL) {
+            CFBundleCloseBundleResourceMap(gSharedLibraryBundle,
+                                           gSharedLibraryResource);
+            gSharedLibraryBundle = NULL;
+        }
+        else
+#endif /* __DARWIN__ */
+        {
+            CloseResFile(gSharedLibraryResource);
+        }
+        gSharedLibraryResource = kResFileNotOpened;
+    }    
+#endif /* WXMAKINGDLL */
+}
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#if defined(WXMAKINGDLL) && !defined(__DARWIN__)
 
-void __sinit(void);    /*      (generated by linker)   */
-pascal OSErr __initialize(const CFragInitBlock *theInitBlock);
-pascal void __terminate(void);
+// for shared libraries we have to manually get the correct resource
+// ref num upon initializing and releasing when terminating, therefore
+// the __wxinitialize and __wxterminate must be used
 
-#ifdef __cplusplus
+extern "C" {
+    void __sinit(void);        /*      (generated by linker)   */
+    pascal OSErr __initialize(const CFragInitBlock *theInitBlock);
+    pascal void __terminate(void);
 }
-#endif
 
 pascal OSErr __wxinitialize(const CFragInitBlock *theInitBlock)
 {
-   gCurrentResource = -1;
-   
-   if (theInitBlock->fragLocator.where == kDataForkCFragLocator) {
-      gCurrentResource = 
-         FSpOpenResFile(theInitBlock->fragLocator.u.onDisk.fileSpec, 
-                              fsRdPerm);
-   }
-   return __initialize( theInitBlock ) ;
+    wxStAppResource::OpenSharedLibraryResource( theInitBlock ) ;
+    return __initialize( theInitBlock ) ;
 }
 
 pascal void __wxterminate(void)
 {
-    if (gCurrentResource != -1)
-      CloseResFile(gCurrentResource);
+    wxStAppResource::CloseSharedLibraryResource() ;
     __terminate() ;
 }
-#endif
+
+#endif /* WXMAKINGDLL && !__DARWIN__ */
 
 int WXDLLEXPORT wxEntryStart( int argc, char *argv[] )
 {
@@ -702,7 +820,6 @@ void WXDLLEXPORT wxEntryCleanup()
 
 int wxEntry( int argc, char *argv[] , bool enterLoop )
 {
-    gCurrentResource = CurResFile() ;
 #ifdef __MWERKS__
 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
     // This seems to be necessary since there are 'rogue'
@@ -738,10 +855,10 @@ int wxEntry( int argc, char *argv[] , bool enterLoop )
     // application (otherwise applications would need to handle it)
 
     if (argc > 1) {
-        char buf[6] = "";
-        strncpy(buf, argv[1], 5);
+        char theArg[6] = "";
+        strncpy(theArg, argv[1], 5);
         
-        if (strcmp(buf, "-psn_") == 0) {
+        if (strcmp(theArg, "-psn_") == 0) {
             // assume the argument is always the only one and remove it
             --argc;
         }
@@ -1478,6 +1595,11 @@ void wxApp::MacHandleKeyDownEvent( WXEVENTREF evr )
         short keychar ;
         keychar = short(ev->message & charCodeMask);
         keycode = short(ev->message & keyCodeMask) >> 8 ;
+        // it is wxWindows Convention to have Ctrl Key Combinations at ASCII char value
+        if ( ev->modifiers & controlKey && keychar >= 0 && keychar < 0x20 )
+        {
+            keychar += 0x40 ;
+        }
         long keyval = wxMacTranslateKey(keychar, keycode) ;
         bool handled = false ;
         wxWindow* focus = wxWindow::FindFocus() ;
@@ -1495,12 +1617,13 @@ void wxApp::MacHandleKeyDownEvent( WXEVENTREF evr )
             event.m_timeStamp = ev->when;
             event.SetEventObject(focus);
             handled = focus->GetEventHandler()->ProcessEvent( event ) ;
+            if ( handled && event.GetSkipped() )
+                handled = false ;
             if ( !handled )
             {
 #if wxUSE_ACCEL
                 if (!handled)
                 {
-                    /*
                     wxWindow *ancestor = focus;
                     while (ancestor)
                     {
@@ -1511,11 +1634,10 @@ void wxApp::MacHandleKeyDownEvent( WXEVENTREF evr )
                             handled = ancestor->GetEventHandler()->ProcessEvent( command_event );
                             break;
                         }
-                        if (ancestor->m_isFrame)
+                        if (ancestor->IsTopLevel())
                             break;
                         ancestor = ancestor->GetParent();
                     }
-                    */
                 }
 #endif // wxUSE_ACCEL
             }
@@ -1532,10 +1654,18 @@ void wxApp::MacHandleKeyDownEvent( WXEVENTREF evr )
                 event.m_timeStamp = ev->when;
                 event.SetEventObject(focus);
                 handled = focus->GetEventHandler()->ProcessEvent( event ) ;
+                if ( handled && event.GetSkipped() )
+                    handled = false ;
             }
             if ( !handled &&
                  (keyval == WXK_TAB) &&
+// CS: copied the change below from wxGTK
+// VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
+//     have this style, yet choose not to process this particular TAB in which
+//     case TAB must still work as a navigational character
+#if 0
                  (!focus->HasFlag(wxTE_PROCESS_TAB)) &&
+#endif
                  (focus->GetParent()) &&
                  (focus->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
             {
@@ -1546,6 +1676,8 @@ void wxApp::MacHandleKeyDownEvent( WXEVENTREF evr )
                 new_event.SetWindowChange( event.ControlDown() );
                 new_event.SetCurrentFocus( focus );
                 handled = focus->GetEventHandler()->ProcessEvent( new_event );
+                if ( handled && new_event.GetSkipped() )
+                    handled = false ;
             }
         }
         if ( !handled )
@@ -1764,6 +1896,7 @@ void wxApp::MacHandleOSEvent( WXEVENTREF evr )
                         wxMouseEvent eventleave(event);
                         eventleave.SetEventType( wxEVT_LEAVE_WINDOW );
                         wxWindow::s_lastMouseWindow->ScreenToClient( &eventleave.m_x, &eventleave.m_y );
+                        eventleave.SetEventObject( wxWindow::s_lastMouseWindow ) ;
                         
                         wxWindow::s_lastMouseWindow->GetEventHandler()->ProcessEvent(eventleave);
                     }
@@ -1772,7 +1905,7 @@ void wxApp::MacHandleOSEvent( WXEVENTREF evr )
                         wxMouseEvent evententer(event);
                         evententer.SetEventType( wxEVT_ENTER_WINDOW );
                         currentMouseWindow->ScreenToClient( &evententer.m_x, &evententer.m_y );
-                        
+                        evententer.SetEventObject( currentMouseWindow ) ;
                         currentMouseWindow->GetEventHandler()->ProcessEvent(evententer);
                     }
                     wxWindow::s_lastMouseWindow = currentMouseWindow ;