diff --git a/mozilla/camino/src/browser/BrowserWindow.h b/mozilla/camino/src/browser/BrowserWindow.h index d15228cb72c..178962ca303 100644 --- a/mozilla/camino/src/browser/BrowserWindow.h +++ b/mozilla/camino/src/browser/BrowserWindow.h @@ -38,6 +38,8 @@ #import +// this implements the mozWindow protocol (see mozView.h) + @interface BrowserWindow : NSWindow { IBOutlet id mAutoCompleteTextField; @@ -50,9 +52,11 @@ - (BOOL)makeFirstResponder:(NSResponder*) responder; +// mozWindow protocol - (BOOL)suppressMakeKeyFront; - (void)setSuppressMakeKeyFront:(BOOL)inSuppress; +// scripting - (NSString*)getURL; @end diff --git a/mozilla/camino/src/browser/BrowserWindow.mm b/mozilla/camino/src/browser/BrowserWindow.mm index 0e3bf6f2c67..e03c7126ced 100644 --- a/mozilla/camino/src/browser/BrowserWindow.mm +++ b/mozilla/camino/src/browser/BrowserWindow.mm @@ -36,6 +36,7 @@ * * ***** END LICENSE BLOCK ***** */ +#import "mozView.h" #import "BrowserWindow.h" #import "BrowserWindowController.h" #import "AutoCompleteTextField.h" diff --git a/mozilla/camino/src/browser/BrowserWindowController.mm b/mozilla/camino/src/browser/BrowserWindowController.mm index 4cbccf34b7e..52f23209afc 100644 --- a/mozilla/camino/src/browser/BrowserWindowController.mm +++ b/mozilla/camino/src/browser/BrowserWindowController.mm @@ -421,7 +421,7 @@ enum BWCOpenDest { - (BrowserTabViewItem*)openNewTab:(BOOL)aLoadInBG; - (void)setupToolbar; -- (void)delayedSetActive:(NSNumber*)inActive; // NSNumber with bool +- (void)setGeckoActive:(BOOL)inActive; - (NSString*)getContextMenuNodeDocumentURL; - (void)loadSourceOfURL:(NSString*)urlStr; - (void)transformFormatString:(NSMutableString*)inFormat domain:(NSString*)inDomain search:(NSString*)inSearch; @@ -495,7 +495,7 @@ enum BWCOpenDest { // the widget code (via -viewsWindowDidBecomeKey) takes care // of sending focus and activate events to gecko, // but we still need to call the embedding activate API - [self performSelector:@selector(delayedSetActive:) withObject:[NSNumber numberWithBool:YES] afterDelay:0]; + [self setGeckoActive:YES]; } - (void)windowDidResignKey:(NSNotification *)notification @@ -508,13 +508,18 @@ enum BWCOpenDest { // the widget code (via -viewsWindowDidResignKey) takes care // of sending focus and activate events to gecko, // but we still need to call the embedding activate API - [self performSelector:@selector(delayedSetActive:) withObject:[NSNumber numberWithBool:NO] afterDelay:0]; + [self setGeckoActive:NO]; } -- (void)delayedSetActive:(NSNumber*)inActive +- (void)setGeckoActive:(BOOL)inActive { if ([self isResponderGeckoView:[[self window] firstResponder]]) - [mBrowserView setBrowserActive:[inActive boolValue]]; + { + BrowserWindow* browserWin = (BrowserWindow*)[self window]; + [browserWin setSuppressMakeKeyFront:YES]; // prevent gecko focus bringing the window to the front + [mBrowserView setBrowserActive:inActive]; + [browserWin setSuppressMakeKeyFront:NO]; + } } - (void)windowDidBecomeMain:(NSNotification *)notification diff --git a/mozilla/camino/src/embedding/CHBrowserListener.mm b/mozilla/camino/src/embedding/CHBrowserListener.mm index ad7aa3482b3..bc0908bb02a 100644 --- a/mozilla/camino/src/embedding/CHBrowserListener.mm +++ b/mozilla/camino/src/embedding/CHBrowserListener.mm @@ -39,6 +39,8 @@ #import "NSString+Utils.h" +#import "mozView.h" + // Embedding includes #include "nsIWebNavigation.h" #include "nsIWebProgress.h" diff --git a/mozilla/widget/src/cocoa/mozView.h b/mozilla/widget/src/cocoa/mozView.h index afd520711b1..62a002b29ec 100644 --- a/mozilla/widget/src/cocoa/mozView.h +++ b/mozilla/widget/src/cocoa/mozView.h @@ -75,3 +75,18 @@ class nsIWidget; @end + +// +// An informal protocol implemented by the NSWindow of the host application. +// +// It's used to prevent re-entrant calls to -makeKeyAndOrderFront: when gecko +// focus/activate events propagate out to the embedder's +// nsIEmbeddingSiteWindow::SetFocus implementation. +// + +@interface NSObject(mozWindow) + +- (BOOL)suppressMakeKeyFront; +- (void)setSuppressMakeKeyFront:(BOOL)inSuppress; + +@end diff --git a/mozilla/widget/src/cocoa/nsChildView.mm b/mozilla/widget/src/cocoa/nsChildView.mm index 671398fbba2..7790c2494bf 100644 --- a/mozilla/widget/src/cocoa/nsChildView.mm +++ b/mozilla/widget/src/cocoa/nsChildView.mm @@ -111,9 +111,6 @@ - (void)flushRect:(NSRect)inRect; - (BOOL)isRectObscuredBySubview:(NSRect)inRect; -- (void)sendActivateEvent; -- (void)sendDeactivateEvent; - #if USE_CLICK_HOLD_CONTEXTMENU // called on a timer two seconds after a mouse down to see if we should display // a context menu (click-hold) @@ -3451,38 +3448,29 @@ static void ConvertCocoaKeyEventToMacEvent(NSEvent* cocoaEvent, EventRecord& mac } - (void)viewsWindowDidBecomeKey -{ - // When unhiding the app, -windowBecameKey: gets called when two bits of window - // state are incorrect (on Tiger): - // - // 1. [window isVisible] returns YES even though it's not on the screen - // 2. [NSApp keyWindow] is not the right window yet - // - // Because this state is not correct at this time, we postpone sending - // the events into gecko (which in turn propagate into the host app) - // until the next time through the event loop, when we're off this stack - // and Cocoa has got its story straight. - [self performSelector:@selector(sendActivateEvent) withObject:nil afterDelay:0]; -} - -- (void)viewsWindowDidResignKey -{ - [self performSelector:@selector(sendDeactivateEvent) withObject:nil afterDelay:0]; -} - -- (void)sendActivateEvent { if (!mGeckoChild) - return; // we've been destroyed + return; // we've been destroyed (paranoia) + // check to see if the window implements the mozWindow protocol. This + // allows embedders to avoid re-entrant calls to -makeKeyAndOrderFront, + // which can happen because these activate/focus calls propagate out + // to the embedder via nsIEmbeddingSiteWindow::SetFocus(). + BOOL isMozWindow = [[self window] respondsToSelector:@selector(setSuppressMakeKeyFront:)]; + if (isMozWindow) + [[self window] setSuppressMakeKeyFront:YES]; + nsFocusEvent focusEvent(PR_TRUE, NS_GOTFOCUS, mGeckoChild); mGeckoChild->DispatchWindowEvent(focusEvent); nsFocusEvent activateEvent(PR_TRUE, NS_ACTIVATE, mGeckoChild); mGeckoChild->DispatchWindowEvent(activateEvent); + + if (isMozWindow) + [[self window] setSuppressMakeKeyFront:NO]; } -- (void)sendDeactivateEvent +- (void)viewsWindowDidResignKey { if (!mGeckoChild) return; // we've been destroyed