]> git.saurik.com Git - wxWidgets.git/blobdiff - src/cocoa/mbarman.mm
When Cocoa sends [tabView:didSelectTabViewItem:] create a page changed event
[wxWidgets.git] / src / cocoa / mbarman.mm
index 81930b9135f9c29f69b32c45ad5a924cd1f03ee6..4a1cdec7fbf850b49552a83ae78ab8975a200984 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "wx/cocoa/mbarman.h"
 #include "wx/cocoa/autorelease.h"
+#include "wx/cocoa/objc/objc_uniquifying.h"
 
 #import <Foundation/NSString.h>
 #import <Foundation/NSNotification.h>
 #import <AppKit/NSApplication.h>
 #import <AppKit/NSWindow.h>
 
+#ifndef wxUSE_FSCRIPT
+#define wxUSE_FSCRIPT 0
+#endif
+
+#if wxUSE_FSCRIPT
+    #import <FScript/FScriptMenuItem.h>
+#endif
+
 // Declare setAppleMenu: in an NSApplication category since Tiger and later
 // releases support it but don't declare it as it's considered deprecated.
 @interface NSApplication(wxDeprecatedMethodsWeWantToUse)
@@ -51,6 +60,7 @@
 - (void)windowWillClose: (NSNotification *)notification;
 #endif // 0
 @end // interface wxMenuBarManagerObserver : NSObject
+WX_DECLARE_GET_OBJC_CLASS(wxMenuBarManagerObserver,NSObject)
 
 @implementation wxMenuBarManagerObserver : NSObject
 - (id)init
 #endif // 0
 
 @end // implementation wxMenuBarManagerObserver : NSObject
+WX_IMPLEMENT_GET_OBJC_CLASS(wxMenuBarManagerObserver,NSObject)
 
 // ============================================================================
 // wxMenuBarManager
 // ============================================================================
 wxMenuBarManager *wxMenuBarManager::sm_mbarmanInstance = NULL;
 
+static void AddFScriptItem(NSMenu *menu)
+#if wxUSE_FSCRIPT
+{
+    NSMenuItem *item = [[FScriptMenuItem alloc] init];
+    [menu addItem: item];
+    [item release];
+}
+#else
+{}
+#endif
+
 wxMenuBarManager::wxMenuBarManager()
 {
-    m_observer = [[wxMenuBarManagerObserver alloc]
+    m_observer = [[WX_GET_OBJC_CLASS(wxMenuBarManagerObserver) alloc]
             initWithWxMenuBarManager:this];
     [[NSNotificationCenter defaultCenter] addObserver:m_observer
             selector:@selector(windowDidBecomeKey:)
             name:NSWindowDidBecomeKeyNotification object:nil];
+
+    // HACK: Reuse the same selector and eventual C++ method and make it
+    // check for whether the notification is to become key or main.
+    [[NSNotificationCenter defaultCenter] addObserver:m_observer
+            selector:@selector(windowDidBecomeKey:)
+            name:NSWindowDidBecomeMainNotification object:nil];
 #if 0
     [[NSNotificationCenter defaultCenter] addObserver:m_observer
             selector:@selector(windowDidResignKey:)
@@ -146,6 +174,7 @@ wxMenuBarManager::wxMenuBarManager()
 
 /**/[m_menuApp addItemWithTitle:@"Preferences..." action:nil keyEquivalent:@""];
 /**/[m_menuApp addItem: [NSMenuItem separatorItem]];
+/**/AddFScriptItem(m_menuApp);
 /**/menuitem = [[NSMenuItem alloc] initWithTitle: @"Services" action:nil keyEquivalent:@""];
     [menuitem setSubmenu:m_menuServices];
     [m_menuApp addItem: menuitem];
@@ -251,6 +280,78 @@ void wxMenuBarManager::WindowDidBecomeKey(NSNotification *notification)
 {
     /* NOTE: m_currentNSWindow might be destroyed but we only ever use it
        to look it up in the hash table.  Do not send messages to it. */
+
+    /*  Update m_currentNSWindow only if we really should.  For instance,
+        if a non-wx window is becoming key but a wx window remains main
+        then don't change out the menubar.  However, if a non-wx window
+        (whether the same window or not) is main, then switch to the
+        generic menubar so the wx window that last installed a menubar
+        doesn't get menu events it doesn't expect.
+
+        If a wx window is becoming main then check to see if the key
+        window is a wx window and if so do nothing because that
+        is what would have been done before.
+
+        If a non-wx window is becoming main and 
+     */
+    NSString *notificationName = [notification name];
+    if(NULL == notificationName)
+        return;
+    else if([NSWindowDidBecomeKeyNotification isEqualTo:notificationName])
+    {   // This is the only one that was handled in 2.8 as shipped
+        // Generally the key window can change without the main window changing.
+        // The user can do this simply by clicking on something in a palette window
+        // that needs to become key.
+        NSWindow *newKeyWindow = [notification object];
+        wxCocoaNSWindow *theWxKeyWindow = wxCocoaNSWindow::GetFromCocoa(newKeyWindow);
+        if(theWxKeyWindow != NULL)
+        {   // If the new key window is a wx window, handle it as before
+            // even if it has not actually changed.
+            m_currentNSWindow = newKeyWindow;
+        }
+        else
+        {   // If the new key window is not wx then check the main window.
+            NSWindow *mainWindow = [[NSApplication sharedApplication] mainWindow];
+            if(m_currentNSWindow == mainWindow)
+                // Don't reset if the menubar doesn't need to change.
+                return;
+            else
+                // This is strange because theoretically we should have picked this up
+                // already in the main window notification but it's possible that
+                // we simply haven't gotten it yet and will about as soon as we return.
+                // We already know that the key window isn't wx so fall back to this
+                // one and let the code go ahead and set the wx menubar if it is
+                // a wx window and set the generic one if it isn't.
+                m_currentNSWindow = mainWindow;
+        }
+    }
+    else if([NSWindowDidBecomeMainNotification isEqualTo:notificationName])
+    {   // Handling this is new
+        // Generally the main window cannot change without the key window changing
+        // because if the user clicks on a window that can become main then the
+        // window will also become key.
+        // However, it's possible that when it becomes main it automatically makes
+        // some palette the key window.
+        NSWindow *newMainWindow = [notification object];
+        // If we already know about the window, bail.
+        if(newMainWindow == m_currentNSWindow)
+            return;
+        else
+        {
+            NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow];
+            if(keyWindow == m_currentNSWindow)
+                // if we already know about the key window, bail
+                return;
+            else
+            {   // As above, sort of strange.  Neither one is current.  Prefer key over main.
+                wxCocoaNSWindow *theWxMainWindow = wxCocoaNSWindow::GetFromCocoa(keyWindow);
+                if(theWxMainWindow != NULL)
+                    m_currentNSWindow = keyWindow;
+                else
+                    m_currentNSWindow = newMainWindow;
+            }
+        }
+    }
     m_currentNSWindow = [notification object];
     wxCocoaNSWindow *win = wxCocoaNSWindow::GetFromCocoa(m_currentNSWindow);
     if(win)