From 2bd5264d46c0c252f115cf88cf215fa77ca4e9c8 Mon Sep 17 00:00:00 2001 From: "smfr%smfr.org" Date: Wed, 12 Oct 2005 17:38:29 +0000 Subject: [PATCH] Fix camino bug 311683. The earlier fix for bug 297343 introduced a short delay before the dispatch of focus/activate events on window activation. It turns out that this was bad, as you could end up with two windows which continually each come to the front ("duelling windows"). This patch makes things synchronous again, but fixes the original bug by exposing a category on NSWindow in the widget code that allows the embedder to know if a SetFocus() call is coming as a result of window activation. r=mento git-svn-id: svn://10.0.0.236/trunk@182094 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/camino/src/browser/BrowserWindow.h | 4 ++ mozilla/camino/src/browser/BrowserWindow.mm | 1 + .../src/browser/BrowserWindowController.mm | 15 +++++--- .../camino/src/embedding/CHBrowserListener.mm | 2 + mozilla/widget/src/cocoa/mozView.h | 15 ++++++++ mozilla/widget/src/cocoa/nsChildView.mm | 38 +++++++------------ 6 files changed, 45 insertions(+), 30 deletions(-) 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