From 4578f06507f42adfa94303ba1325695a5b1bb595 Mon Sep 17 00:00:00 2001 From: "saari%netscape.com" Date: Fri, 20 Jul 2001 08:14:44 +0000 Subject: [PATCH] fixing 77675, windows stealing focus from each other. r=bryner, sr=hyatt git-svn-id: svn://10.0.0.236/trunk@99637 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/public/nsIDocument.h | 9 ++++ mozilla/content/base/src/nsDocument.cpp | 22 ++++++++- mozilla/content/base/src/nsDocument.h | 9 ++++ .../events/src/nsEventStateManager.cpp | 29 ++++++++---- .../xul/document/src/nsXULDocument.cpp | 47 ++++++++----------- .../content/xul/document/src/nsXULDocument.h | 6 ++- mozilla/dom/src/base/nsFocusController.cpp | 7 +-- mozilla/dom/src/base/nsFocusController.h | 4 +- mozilla/widget/src/mac/nsMacEventHandler.cpp | 2 +- 9 files changed, 89 insertions(+), 46 deletions(-) diff --git a/mozilla/content/base/public/nsIDocument.h b/mozilla/content/base/public/nsIDocument.h index 7258ac5b4cd..133411f7e80 100644 --- a/mozilla/content/base/public/nsIDocument.h +++ b/mozilla/content/base/public/nsIDocument.h @@ -64,6 +64,7 @@ class nsIObserver; class nsISupportsArray; class nsIScriptLoader; class nsString; +class nsIFocusController; // IID for the nsIDocument interface #define NS_IDOCUMENT_IID \ @@ -261,6 +262,14 @@ public: */ NS_IMETHOD GetScriptLoader(nsIScriptLoader** aScriptLoader) = 0; + /** + * Get the focus controller for this document + * This can usually be gotten through the ScriptGlobalObject, but + * it is set to null during document destruction, when we still might + * need to fire focus events. + */ + NS_IMETHOD GetFocusController(nsIFocusController** aFocusController) = 0; + //---------------------------------------------------------------------- // Document notification API's diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index 03ed75a611f..cbe8169183f 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -98,7 +98,8 @@ #include "nsIInterfaceRequestor.h" #include "nsIDOMWindowInternal.h" - +#include "nsPIDOMWindow.h" +#include "nsIFocusController.h" #include "nsIDOMElement.h" #include "nsIBoxObject.h" @@ -1410,12 +1411,31 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject) #endif mContentWrapperHash.Reset(); + } else if (aScriptGlobalObject != mScriptGlobalObject) { + // Update our weak ref to the focus controller + nsCOMPtr domPrivate = do_QueryInterface(aScriptGlobalObject); + if (domPrivate) { + nsCOMPtr fc; + domPrivate->GetRootFocusController(getter_AddRefs(fc)); + mFocusController = getter_AddRefs(NS_GetWeakReference(fc)); + } } mScriptGlobalObject = aScriptGlobalObject; return NS_OK; } +NS_IMETHODIMP +nsDocument::GetFocusController(nsIFocusController** aFocusController) +{ + NS_ENSURE_ARG_POINTER(aFocusController); + + nsCOMPtr fc = do_QueryReferent(mFocusController); + *aFocusController = fc; + NS_IF_ADDREF(*aFocusController); + return NS_OK; +} + NS_IMETHODIMP nsDocument::GetNameSpaceManager(nsINameSpaceManager*& aManager) { diff --git a/mozilla/content/base/src/nsDocument.h b/mozilla/content/base/src/nsDocument.h index 9e1b5e34046..f1e9b294711 100644 --- a/mozilla/content/base/src/nsDocument.h +++ b/mozilla/content/base/src/nsDocument.h @@ -392,6 +392,14 @@ public: */ NS_IMETHOD GetScriptLoader(nsIScriptLoader** aScriptLoader); + /** + * Get the focus controller for this document + * This can usually be gotten through the ScriptGlobalObject, but + * it is set to null during document destruction, when we still might + * need to fire focus events. + */ + NS_IMETHOD GetFocusController(nsIFocusController** aFocusController); + /** * Add a new observer of document change notifications. Whenever * content is changed, appended, inserted or removed the observers are @@ -572,6 +580,7 @@ protected: nsSupportsHashtable mContentWrapperHash; nsCOMPtr mCSSLoader; + nsWeakPtr mFocusController; private: // These are not implemented and not supported. diff --git a/mozilla/content/events/src/nsEventStateManager.cpp b/mozilla/content/events/src/nsEventStateManager.cpp index dd661d2d358..27127bf948f 100644 --- a/mozilla/content/events/src/nsEventStateManager.cpp +++ b/mozilla/content/events/src/nsEventStateManager.cpp @@ -624,9 +624,6 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, { EnsureDocument(aPresContext); - if (gLastFocusedDocument != mDocument) - break; - nsCOMPtr ourGlobal; mDocument->GetScriptGlobalObject(getter_AddRefs(ourGlobal)); @@ -635,22 +632,23 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, // focused sub-window and sub-element for this top-level // window. nsCOMPtr focusController; - nsCOMPtr rootWindow; - nsCOMPtr ourWindow = do_QueryInterface(ourGlobal); - if(ourWindow) { - ourWindow->GetRootFocusController(getter_AddRefs(focusController)); + mDocument->GetFocusController(getter_AddRefs(focusController)); if (focusController) { // Suppress the command dispatcher. focusController->SetSuppressFocus(PR_TRUE, "Deactivate Suppression"); } - } // Now fire blurs. We have to fire a blur on the focused window // and on the focused element if there is one. - if (gLastFocusedDocument && gLastFocusedPresContext) { + if (gLastFocusedDocument && gLastFocusedDocument == mDocument) { if (gLastFocusedContent) { // Blur the element. nsCOMPtr shell; + + nsCOMPtr focusedElement; + focusController->GetFocusedElement(getter_AddRefs(focusedElement)); + nsCOMPtr focusedContent = do_QueryInterface(focusedElement); + gLastFocusedDocument->GetShellAt(0, getter_AddRefs(shell)); if (shell) { nsCOMPtr oldPresContext; @@ -663,7 +661,8 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, nsCOMPtr esm; oldPresContext->GetEventStateManager(getter_AddRefs(esm)); esm->SetFocusedContent(gLastFocusedContent); - gLastFocusedContent->HandleDOMEvent(oldPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + if(focusedContent) + focusedContent->HandleDOMEvent(oldPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); esm->SetFocusedContent(nsnull); NS_IF_RELEASE(gLastFocusedContent); } @@ -678,6 +677,16 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, mDocument->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); if (ourGlobal) ourGlobal->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + else { + // If the document is being torn down, we can't fire a blur on + // the window, but we still need to tell the focus controller + // that it isn't active. + + nsCOMPtr fc; + gLastFocusedDocument->GetFocusController(getter_AddRefs(fc)); + if (fc) + fc->SetActive(PR_FALSE); + } // Now clear our our global variables mCurrentTarget = nsnull; diff --git a/mozilla/content/xul/document/src/nsXULDocument.cpp b/mozilla/content/xul/document/src/nsXULDocument.cpp index 55f9c683399..27d5d21d2fb 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.cpp +++ b/mozilla/content/xul/document/src/nsXULDocument.cpp @@ -1428,12 +1428,31 @@ nsXULDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject) #endif mContentWrapperHash.Reset(); + } else if (mScriptGlobalObject != aScriptGlobalObject) { + // Update our weak ref to the focus controller + nsCOMPtr domPrivate = do_QueryInterface(aScriptGlobalObject); + if (domPrivate) { + nsCOMPtr fc; + domPrivate->GetRootFocusController(getter_AddRefs(fc)); + mFocusController = getter_AddRefs(NS_GetWeakReference(fc)); + } } mScriptGlobalObject = aScriptGlobalObject; return NS_OK; } +NS_IMETHODIMP +nsXULDocument::GetFocusController(nsIFocusController** aFocusController) +{ + NS_ENSURE_ARG_POINTER(aFocusController); + + nsCOMPtr fc = do_QueryReferent(mFocusController); + *aFocusController = fc; + NS_IF_ADDREF(*aFocusController); + return NS_OK; +} + NS_IMETHODIMP nsXULDocument::GetNameSpaceManager(nsINameSpaceManager*& aManager) { @@ -6315,31 +6334,3 @@ XULElementFactoryImpl::CreateInstanceByTag(nsINodeInfo *aNodeInfo, return nsXULElement::Create(aNodeInfo, aResult); } - - -nsresult nsXULDocument::GetFocusController(nsIFocusController** aController) -{ - NS_ENSURE_ARG_POINTER(aController); - - nsresult rv; - - // get the script global object - nsCOMPtr global; - rv = GetScriptGlobalObject(getter_AddRefs(global)); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(global, NS_ERROR_FAILURE); - // get the internal dom window - nsCOMPtr internalWin(do_QueryInterface(global, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(internalWin, NS_ERROR_FAILURE); - // get the private dom window - nsCOMPtr privateWin(do_QueryInterface(internalWin, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(privateWin, NS_ERROR_FAILURE); - // get the focus controller - rv = privateWin->GetRootFocusController(aController); // addref is here - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(*aController, NS_ERROR_FAILURE); - - return rv; -} diff --git a/mozilla/content/xul/document/src/nsXULDocument.h b/mozilla/content/xul/document/src/nsXULDocument.h index c8dd1195fde..1e4429728b0 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.h +++ b/mozilla/content/xul/document/src/nsXULDocument.h @@ -231,6 +231,8 @@ public: NS_IMETHOD GetScriptLoader(nsIScriptLoader** aScriptLoader); + NS_IMETHOD GetFocusController(nsIFocusController** aFocusController); + virtual void AddObserver(nsIDocumentObserver* aObserver); virtual PRBool RemoveObserver(nsIDocumentObserver* aObserver); @@ -548,6 +550,8 @@ protected: nsCOMPtr mTooltipNode; // [OWNER] element triggering the tooltip nsCOMPtr mNodeInfoManager; // [OWNER] list of names in the document + nsWeakPtr mFocusController; + /** * Context stack, which maintains the state of the Builder and allows * it to be interrupted. @@ -794,8 +798,6 @@ protected: private: // helpers - nsresult GetFocusController(nsIFocusController** aController); - }; diff --git a/mozilla/dom/src/base/nsFocusController.cpp b/mozilla/dom/src/base/nsFocusController.cpp index 5bc2cb37c2d..424e45c67b8 100644 --- a/mozilla/dom/src/base/nsFocusController.cpp +++ b/mozilla/dom/src/base/nsFocusController.cpp @@ -59,7 +59,8 @@ nsFocusController::~nsFocusController(void) { } -NS_IMPL_ISUPPORTS3(nsFocusController, nsIFocusController, nsIDOMFocusListener, nsIDOMEventListener) +NS_IMPL_ISUPPORTS4(nsFocusController, nsIFocusController, + nsIDOMFocusListener, nsIDOMEventListener, nsSupportsWeakReference) NS_IMETHODIMP nsFocusController::Create(nsIFocusController** aResult) @@ -401,13 +402,13 @@ nsFocusController::SetSuppressFocus(PRBool aSuppressFocus, char* aReason) if(aSuppressFocus) { ++mSuppressFocus; #ifdef DEBUG_hyatt - printf("[%d] SuppressFocus incremented to %d. The reason is %s.\n", this, mSuppressFocus, aReason); + printf("[%p] SuppressFocus incremented to %d. The reason is %s.\n", this, mSuppressFocus, aReason); #endif } else if(mSuppressFocus > 0) { --mSuppressFocus; #ifdef DEBUG_hyatt - printf("[%d] SuppressFocus decremented to %d. The reason is %s.\n", this, mSuppressFocus, aReason); + printf("[%p] SuppressFocus decremented to %d. The reason is %s.\n", this, mSuppressFocus, aReason); #endif } else diff --git a/mozilla/dom/src/base/nsFocusController.h b/mozilla/dom/src/base/nsFocusController.h index 20a3d5501e1..9d607ffa72b 100644 --- a/mozilla/dom/src/base/nsFocusController.h +++ b/mozilla/dom/src/base/nsFocusController.h @@ -29,6 +29,7 @@ #include "nsIDOMFocusListener.h" #include "nsIDOMElement.h" #include "nsIDOMWindow.h" +#include "nsWeakReference.h" class nsIDOMElement; class nsIDOMWindow; @@ -36,7 +37,8 @@ class nsIController; class nsIControllers; class nsFocusController : public nsIFocusController, - public nsIDOMFocusListener + public nsIDOMFocusListener, + public nsSupportsWeakReference { public: static NS_IMETHODIMP Create(nsIFocusController** aResult); diff --git a/mozilla/widget/src/mac/nsMacEventHandler.cpp b/mozilla/widget/src/mac/nsMacEventHandler.cpp index 354fd7a3148..ef5419297a7 100644 --- a/mozilla/widget/src/mac/nsMacEventHandler.cpp +++ b/mozilla/widget/src/mac/nsMacEventHandler.cpp @@ -320,10 +320,10 @@ void nsMacEventDispatchHandler::SetDeactivated(nsWindow *aDeactivatedWidget) if (mActiveWidget) { //printf(" nsMacEventDispatchHandler::SetDeactivated sends NS_DEACTIVATE\n"); - DispatchGuiEvent(mActiveWidget, NS_DEACTIVATE); mActiveWidget->RemoveDeleteObserver(this); mActiveWidget = nsnull; } + DispatchGuiEvent(aDeactivatedWidget, NS_DEACTIVATE); } //-------------------------------------------------------------------------