From e0c292d77e98ed35e7799e0634fc2f1e25e0bfb0 Mon Sep 17 00:00:00 2001 From: "hyatt%netscape.com" Date: Sat, 4 Nov 2000 08:21:20 +0000 Subject: [PATCH] Fix for 54203. r=saari, a=brendan --- content/events/src/nsEventStateManager.cpp | 141 ++-- content/xbl/src/nsXBLPrototypeHandler.cpp | 64 +- content/xbl/src/nsXBLWindowKeyHandler.cpp | 15 +- .../document/src/nsXULCommandDispatcher.cpp | 672 ++++++----------- .../xul/document/src/nsXULCommandDispatcher.h | 60 +- content/xul/document/src/nsXULDocument.cpp | 16 +- docshell/base/nsDocShell.cpp | 56 +- dom/public/base/MANIFEST | 2 + dom/public/base/Makefile.in | 2 + dom/public/base/makefile.win | 4 +- dom/public/base/nsIFocusController.h | 60 ++ dom/public/base/nsPIDOMWindow.h | 6 +- dom/public/base/nsPIWindowRoot.h | 41 ++ dom/public/idl/xul/XULCommandDispatcher.idl | 4 - dom/public/xul/nsIDOMXULCommandDispatcher.h | 21 - dom/src/base/Makefile.in | 2 + dom/src/base/makefile.win | 4 + dom/src/base/nsFocusController.cpp | 369 ++++++++++ dom/src/base/nsFocusController.h | 91 +++ dom/src/base/nsGlobalWindow.cpp | 118 ++- dom/src/base/nsGlobalWindow.h | 6 +- dom/src/base/nsWindowRoot.cpp | 229 ++++++ dom/src/base/nsWindowRoot.h | 72 ++ dom/src/xul/nsJSXULCommandDispatcher.cpp | 89 +-- editor/base/nsEditorShell.cpp | 9 +- editor/composer/src/nsEditorShell.cpp | 9 +- layout/base/nsPresShell.cpp | 163 ++--- layout/events/src/nsEventStateManager.cpp | 141 ++-- layout/html/base/src/nsPresShell.cpp | 163 ++--- layout/xbl/src/nsXBLPrototypeHandler.cpp | 64 +- layout/xbl/src/nsXBLWindowKeyHandler.cpp | 15 +- .../public/idl/XULCommandDispatcher.idl | 4 - .../public/nsIDOMXULCommandDispatcher.h | 21 - rdf/content/src/nsJSXULCommandDispatcher.cpp | 674 ------------------ rdf/content/src/nsXULCommandDispatcher.cpp | 665 ----------------- rdf/content/src/nsXULCommandDispatcher.h | 119 ---- rdf/content/src/nsXULDocument.cpp | 16 +- 37 files changed, 1540 insertions(+), 2667 deletions(-) create mode 100644 dom/public/base/nsIFocusController.h create mode 100644 dom/public/base/nsPIWindowRoot.h create mode 100644 dom/src/base/nsFocusController.cpp create mode 100644 dom/src/base/nsFocusController.h create mode 100644 dom/src/base/nsWindowRoot.cpp create mode 100644 dom/src/base/nsWindowRoot.h diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 9a65b1b3728..ca164786f4c 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -62,9 +62,11 @@ #include "nsIServiceManager.h" #include "nsIPref.h" +#include "nsIChromeEventHandler.h" +#include "nsIFocusController.h" + #include "nsXULAtoms.h" #include "nsIDOMXULDocument.h" -#include "nsIDOMXULCommandDispatcher.h" #include "nsIObserverService.h" #include "nsIDocShell.h" #include "nsIMarkupDocumentViewer.h" @@ -333,16 +335,16 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, blurevent.message = NS_BLUR_CONTENT; if(gLastFocusedPresContext) { - nsCOMPtr commandDispatcher; + nsCOMPtr focusController; nsCOMPtr ourGlobal; gLastFocusedDocument->GetScriptGlobalObject(getter_AddRefs(ourGlobal)); nsCOMPtr rootWindow; nsCOMPtr ourWindow = do_QueryInterface(ourGlobal); if(ourWindow) { - ourWindow->GetRootCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) - commandDispatcher->SetSuppressFocus(PR_TRUE); + ourWindow->GetRootFocusController(getter_AddRefs(focusController)); + if (focusController) + focusController->SetSuppressFocus(PR_TRUE); } gLastFocusedDocument->HandleDOMEvent(gLastFocusedPresContext, &blurevent, nsnull, NS_EVENT_FLAG_INIT, &blurstatus); @@ -350,8 +352,8 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, gLastFocusedContent->HandleDOMEvent(gLastFocusedPresContext, &blurevent, nsnull, NS_EVENT_FLAG_INIT, &blurstatus); - if (commandDispatcher) { - commandDispatcher->SetSuppressFocus(PR_FALSE); + if (focusController) { + focusController->SetSuppressFocus(PR_FALSE); } } } @@ -399,56 +401,30 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, // objects. EnsureDocument(aPresContext); - nsCOMPtr commandDispatcher; + nsCOMPtr focusController; nsCOMPtr focusedElement; nsCOMPtr focusedWindow; nsCOMPtr xulDoc = do_QueryInterface(mDocument); - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - // Obtain focus info from the command dispatcher. - commandDispatcher->GetFocusedWindow(getter_AddRefs(focusedWindow)); - commandDispatcher->GetFocusedElement(getter_AddRefs(focusedElement)); - - commandDispatcher->SetSuppressFocusScroll(PR_TRUE); - } + nsCOMPtr globalObj; + mDocument->GetScriptGlobalObject(getter_AddRefs(globalObj)); + nsCOMPtr win(do_QueryInterface(globalObj)); + win->GetRootFocusController(getter_AddRefs(focusController)); + + if (focusController) { + // Obtain focus info from the command dispatcher. + focusController->GetFocusedWindow(getter_AddRefs(focusedWindow)); + focusController->GetFocusedElement(getter_AddRefs(focusedElement)); + + focusController->SetSuppressFocusScroll(PR_TRUE); } if (!focusedWindow) { - nsCOMPtr globalObject; - mDocument->GetScriptGlobalObject(getter_AddRefs(globalObject)); - focusedWindow = do_QueryInterface(globalObject); + nsCOMPtr globalObject; + mDocument->GetScriptGlobalObject(getter_AddRefs(globalObject)); + focusedWindow = do_QueryInterface(globalObject); } - // Sill no focused XULDocument, that is bad - if(!xulDoc && focusedWindow) - { - nsCOMPtr privateWindow = do_QueryInterface(focusedWindow); - if(privateWindow){ - nsCOMPtr privateRootWindow; - privateWindow->GetPrivateRoot(getter_AddRefs(privateRootWindow)); - if(privateRootWindow) { - nsCOMPtr privateParentDoc; - privateRootWindow->GetDocument(getter_AddRefs(privateParentDoc)); - xulDoc = do_QueryInterface(privateParentDoc); - } - } - - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - // Obtain focus info from the command dispatcher. - commandDispatcher->GetFocusedWindow(getter_AddRefs(focusedWindow)); - commandDispatcher->GetFocusedElement(getter_AddRefs(focusedElement)); - - commandDispatcher->SetSuppressFocusScroll(PR_TRUE); - } - } - } - // Focus the DOM window. NS_WARN_IF_FALSE(focusedWindow,"check why focusedWindow is null!!!"); if(focusedWindow) { @@ -470,16 +446,16 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, } } - if (commandDispatcher) { - commandDispatcher->SetActive(PR_TRUE); + if (focusController) { + focusController->SetActive(PR_TRUE); PRBool isSuppressed; - commandDispatcher->GetSuppressFocus(&isSuppressed); + focusController->GetSuppressFocus(&isSuppressed); while(isSuppressed){ - commandDispatcher->SetSuppressFocus(PR_FALSE); // Unsuppress and let the command dispatcher listen again. - commandDispatcher->GetSuppressFocus(&isSuppressed); + focusController->SetSuppressFocus(PR_FALSE); // Unsuppress and let the command dispatcher listen again. + focusController->GetSuppressFocus(&isSuppressed); } - commandDispatcher->SetSuppressFocusScroll(PR_FALSE); + focusController->SetSuppressFocusScroll(PR_FALSE); } } break; @@ -508,24 +484,14 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, // de-activation. This will cause it to remember the last // focused sub-window and sub-element for this top-level // window. - nsCOMPtr commandDispatcher; + nsCOMPtr focusController; nsCOMPtr rootWindow; nsCOMPtr ourWindow = do_QueryInterface(ourGlobal); if(ourWindow) { - ourWindow->GetPrivateRoot(getter_AddRefs(rootWindow)); - if(rootWindow) { - nsCOMPtr rootDocument; - rootWindow->GetDocument(getter_AddRefs(rootDocument)); - - nsCOMPtr xulDoc = do_QueryInterface(rootDocument); - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - // Suppress the command dispatcher. - commandDispatcher->SetSuppressFocus(PR_TRUE); - } - } + ourWindow->GetRootFocusController(getter_AddRefs(focusController)); + if (focusController) { + // Suppress the command dispatcher. + focusController->SetSuppressFocus(PR_TRUE); } } @@ -577,9 +543,9 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, gLastFocusedPresContext = nsnull; } - if (commandDispatcher) { - commandDispatcher->SetActive(PR_FALSE); - //commandDispatcher->SetSuppressFocus(PR_FALSE); + if (focusController) { + focusController->SetActive(PR_FALSE); + //focusController->SetSuppressFocus(PR_FALSE); } } @@ -955,7 +921,6 @@ nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext, PRInt32 action = 0; PRInt32 numLines = 0; PRBool aBool; - if (msEvent->isShift) { mPrefService->GetIntPref("mousewheel.withshiftkey.action", &action); mPrefService->GetBoolPref("mousewheel.withshiftkey.sysnumlines", @@ -2687,8 +2652,8 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo // Make sure we're not switching command dispatchers, if so, surpress the blurred one if(gLastFocusedDocument && mDocument) { - nsCOMPtr newCommandDispatcher; - nsCOMPtr oldCommandDispatcher; + nsCOMPtr newFocusController; + nsCOMPtr oldFocusController; nsCOMPtr oldPIDOMWindow; nsCOMPtr newPIDOMWindow; nsCOMPtr oldGlobal; @@ -2698,11 +2663,11 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo nsCOMPtr newWindow = do_QueryInterface(newGlobal); nsCOMPtr oldWindow = do_QueryInterface(oldGlobal); if(newWindow) - newWindow->GetRootCommandDispatcher(getter_AddRefs(newCommandDispatcher)); + newWindow->GetRootFocusController(getter_AddRefs(newFocusController)); if(oldWindow) - oldWindow->GetRootCommandDispatcher(getter_AddRefs(oldCommandDispatcher)); - if(oldCommandDispatcher && oldCommandDispatcher != newCommandDispatcher) - oldCommandDispatcher->SetSuppressFocus(PR_TRUE); + oldWindow->GetRootFocusController(getter_AddRefs(oldFocusController)); + if(oldFocusController && oldFocusController != newFocusController) + oldFocusController->SetSuppressFocus(PR_TRUE); } nsCOMPtr esm; @@ -2737,8 +2702,8 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo // Make sure we're not switching command dispatchers, if so, surpress the blurred one if(mDocument) { - nsCOMPtr newCommandDispatcher; - nsCOMPtr oldCommandDispatcher; + nsCOMPtr newFocusController; + nsCOMPtr oldFocusController; nsCOMPtr oldPIDOMWindow; nsCOMPtr newPIDOMWindow; nsCOMPtr oldGlobal; @@ -2748,10 +2713,10 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo nsCOMPtr newWindow = do_QueryInterface(newGlobal); nsCOMPtr oldWindow = do_QueryInterface(oldGlobal); - newWindow->GetRootCommandDispatcher(getter_AddRefs(newCommandDispatcher)); - oldWindow->GetRootCommandDispatcher(getter_AddRefs(oldCommandDispatcher)); - if(oldCommandDispatcher && oldCommandDispatcher != newCommandDispatcher) - oldCommandDispatcher->SetSuppressFocus(PR_TRUE); + newWindow->GetRootFocusController(getter_AddRefs(newFocusController)); + oldWindow->GetRootFocusController(getter_AddRefs(oldFocusController)); + if(oldFocusController && oldFocusController != newFocusController) + oldFocusController->SetSuppressFocus(PR_TRUE); } nsCOMPtr esm; @@ -2963,6 +2928,12 @@ nsEventStateManager::DispatchNewEvent(nsISupports* aTarget, nsIDOMEvent* aEvent) if (target) { ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent, NS_EVENT_FLAG_INIT, &status); } + else { + nsCOMPtr target(do_QueryInterface(aTarget)); + if (target) { + ret = target->HandleChromeEvent(mPresContext, innerEvent, &aEvent, NS_EVENT_FLAG_INIT, &status); + } + } } } } diff --git a/content/xbl/src/nsXBLPrototypeHandler.cpp b/content/xbl/src/nsXBLPrototypeHandler.cpp index 7bd6ea4f732..211057b02fe 100644 --- a/content/xbl/src/nsXBLPrototypeHandler.cpp +++ b/content/xbl/src/nsXBLPrototypeHandler.cpp @@ -42,12 +42,13 @@ #include "nsIDOMNSHTMLTextAreaElement.h" #include "nsIDOMNSHTMLInputElement.h" #include "nsIDOMText.h" -#include "nsIDOMXULCommandDispatcher.h" +#include "nsIFocusController.h" #include "nsIEventListenerManager.h" #include "nsIDOMEventReceiver.h" #include "nsIDOMEventListener.h" #include "nsIPrivateDOMEvent.h" #include "nsPIDOMWindow.h" +#include "nsPIWindowRoot.h" #include "nsIDOMWindowInternal.h" #include "nsIPref.h" #include "nsIServiceManager.h" @@ -218,29 +219,36 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, nsIDOMEven // Instead of executing JS, let's get the controller for the bound // element and call doCommand on it. nsCOMPtr controller; + nsCOMPtr focusController; - nsCOMPtr privateWindow(do_QueryInterface(aReceiver)); - if (!privateWindow) { - nsCOMPtr elt(do_QueryInterface(aReceiver)); - nsCOMPtr doc; - if (elt) - elt->GetDocument(*getter_AddRefs(doc)); + nsCOMPtr windowRoot(do_QueryInterface(aReceiver)); + if (windowRoot) { + windowRoot->GetFocusController(getter_AddRefs(focusController)); + } + else { + nsCOMPtr privateWindow(do_QueryInterface(aReceiver)); + if (!privateWindow) { + nsCOMPtr elt(do_QueryInterface(aReceiver)); + nsCOMPtr doc; + if (elt) + elt->GetDocument(*getter_AddRefs(doc)); - if (!doc) - doc = do_QueryInterface(aReceiver); + if (!doc) + doc = do_QueryInterface(aReceiver); - if (!doc) - return NS_ERROR_FAILURE; + if (!doc) + return NS_ERROR_FAILURE; - nsCOMPtr globalObject; - doc->GetScriptGlobalObject(getter_AddRefs(globalObject)); - privateWindow = do_QueryInterface(globalObject); + nsCOMPtr globalObject; + doc->GetScriptGlobalObject(getter_AddRefs(globalObject)); + privateWindow = do_QueryInterface(globalObject); + } + + privateWindow->GetRootFocusController(getter_AddRefs(focusController)); } - nsCOMPtr commandDispatcher; - privateWindow->GetRootCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) - commandDispatcher->GetControllerForCommand(command, getter_AddRefs(controller)); + if (focusController) + focusController->GetControllerForCommand(command, getter_AddRefs(controller)); else GetController(aReceiver, getter_AddRefs(controller)); // We're attached to the receiver possibly. if (controller) @@ -271,12 +279,25 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, nsIDOMEven mHandlerElement->GetAttribute(kNameSpaceID_None, kOnCommandAtom, handlerText); if (handlerText.IsEmpty()) return NS_ERROR_FAILURE; // For whatever reason, they didn't give us anything to do. - aEvent->PreventDefault(); // Preventing default for XUL key handlers + aEvent->PreventDefault(); // Preventing default for XUL key handlers } } // Compile the handler and bind it to the element. - nsCOMPtr boundGlobal(do_QueryInterface(aReceiver)); + nsCOMPtr boundGlobal; + nsCOMPtr winRoot(do_QueryInterface(aReceiver)); + if (winRoot) { + nsCOMPtr focusController; + winRoot->GetFocusController(getter_AddRefs(focusController)); + nsCOMPtr win; + focusController->GetFocusedWindow(getter_AddRefs(win)); + nsCOMPtr piWin(do_QueryInterface(win)); + nsCOMPtr rootWin; + piWin->GetPrivateRoot(getter_AddRefs(rootWin)); + boundGlobal = do_QueryInterface(rootWin); + } + else boundGlobal = do_QueryInterface(aReceiver); + if (!boundGlobal) { nsCOMPtr boundDocument(do_QueryInterface(aReceiver)); if (!boundDocument) { @@ -293,7 +314,8 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, nsIDOMEven nsCOMPtr boundContext; boundGlobal->GetContext(getter_AddRefs(boundContext)); - nsCOMPtr owner(do_QueryInterface(aReceiver)); + nsCOMPtr owner(do_QueryInterface(winRoot ? boundGlobal : aReceiver)); + void* scriptObject; owner->GetScriptObject(boundContext, &scriptObject); diff --git a/content/xbl/src/nsXBLWindowKeyHandler.cpp b/content/xbl/src/nsXBLWindowKeyHandler.cpp index ede299c0f22..69ff45d174c 100644 --- a/content/xbl/src/nsXBLWindowKeyHandler.cpp +++ b/content/xbl/src/nsXBLWindowKeyHandler.cpp @@ -39,12 +39,13 @@ #include "nsIScriptGlobalObject.h" #include "nsIDOMWindowInternal.h" #include "nsPIDOMWindow.h" -#include "nsIDOMXULCommandDispatcher.h" +#include "nsIFocusController.h" #include "nsIDocShell.h" #include "nsIPresShell.h" #include "nsIDOMDocument.h" #include "nsIDocument.h" #include "nsIDOMElement.h" +#include "nsPIWindowRoot.h" PRUint32 nsXBLWindowKeyHandler::gRefCnt = 0; nsIAtom* nsXBLWindowKeyHandler::kKeyDownAtom = nsnull; @@ -90,16 +91,16 @@ NS_IMPL_ISUPPORTS1(nsXBLWindowKeyHandler, nsIDOMKeyListener) PRBool nsXBLWindowKeyHandler::IsEditor() { - nsCOMPtr privateWindow(do_QueryInterface(mReceiver)); - nsCOMPtr commandDispatcher; - privateWindow->GetRootCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (!commandDispatcher) { - NS_WARNING("********* Problem for embedding. They have no command dispatcher!!!\n"); + nsCOMPtr windowRoot(do_QueryInterface(mReceiver)); + nsCOMPtr focusController; + windowRoot->GetFocusController(getter_AddRefs(focusController)); + if (!focusController) { + NS_WARNING("********* Something went wrong! No focus controller on the root!!!\n"); return PR_FALSE; } nsCOMPtr focusedWindow; - commandDispatcher->GetFocusedWindow(getter_AddRefs(focusedWindow)); + focusController->GetFocusedWindow(getter_AddRefs(focusedWindow)); if (!focusedWindow) return PR_FALSE; diff --git a/content/xul/document/src/nsXULCommandDispatcher.cpp b/content/xul/document/src/nsXULCommandDispatcher.cpp index 9bc1d1ade42..30416f5ad7a 100644 --- a/content/xul/document/src/nsXULCommandDispatcher.cpp +++ b/content/xul/document/src/nsXULCommandDispatcher.cpp @@ -29,6 +29,7 @@ */ #include "nsIContent.h" +#include "nsIFocusController.h" #include "nsIControllers.h" #include "nsIDOMDocument.h" #include "nsIDOMXULDocument.h" @@ -55,19 +56,18 @@ static PRLogModuleInfo* gLog; //////////////////////////////////////////////////////////////////////// -nsXULCommandDispatcher::nsXULCommandDispatcher(void) - : mScriptObject(nsnull), mSuppressFocus(0), - mActive(PR_FALSE), mFocusInitialized(PR_FALSE), mUpdaters(nsnull) +nsXULCommandDispatcher::nsXULCommandDispatcher(nsIDocument* aDocument) + : mScriptObject(nsnull), mDocument(aDocument), mFocusController(nsnull), mUpdaters(nsnull) { NS_INIT_REFCNT(); #ifdef PR_LOGGING - if (! gLog) - gLog = PR_NewLogModule("nsXULCommandDispatcher"); + if (! gLog) + gLog = PR_NewLogModule("nsXULCommandDispatcher"); #endif } -nsXULCommandDispatcher::~nsXULCommandDispatcher(void) +nsXULCommandDispatcher::~nsXULCommandDispatcher() { while (mUpdaters) { Updater* doomed = mUpdaters; @@ -82,45 +82,58 @@ NS_IMPL_RELEASE(nsXULCommandDispatcher) NS_IMETHODIMP nsXULCommandDispatcher::QueryInterface(REFNSIID iid, void** result) { - if (! result) - return NS_ERROR_NULL_POINTER; + if (! result) + return NS_ERROR_NULL_POINTER; - *result = nsnull; - if (iid.Equals(NS_GET_IID(nsISupports)) || - iid.Equals(NS_GET_IID(nsIDOMXULCommandDispatcher))) { - *result = NS_STATIC_CAST(nsIDOMXULCommandDispatcher*, this); - } - else if (iid.Equals(NS_GET_IID(nsIDOMFocusListener)) || - iid.Equals(NS_GET_IID(nsIDOMEventListener))) { - *result = NS_STATIC_CAST(nsIDOMFocusListener*, this); - } - else if (iid.Equals(NS_GET_IID(nsIScriptObjectOwner))) { - *result = NS_STATIC_CAST(nsIScriptObjectOwner*, this); - } - else if (iid.Equals(NS_GET_IID(nsISupportsWeakReference))) { - *result = NS_STATIC_CAST(nsISupportsWeakReference*, this); - } - else { - return NS_NOINTERFACE; - } + *result = nsnull; + if (iid.Equals(NS_GET_IID(nsISupports)) || + iid.Equals(NS_GET_IID(nsIDOMXULCommandDispatcher))) { + *result = NS_STATIC_CAST(nsIDOMXULCommandDispatcher*, this); + } + else if (iid.Equals(NS_GET_IID(nsIScriptObjectOwner))) { + *result = NS_STATIC_CAST(nsIScriptObjectOwner*, this); + } + else if (iid.Equals(NS_GET_IID(nsISupportsWeakReference))) { + *result = NS_STATIC_CAST(nsISupportsWeakReference*, this); + } + else { + return NS_NOINTERFACE; + } - NS_ADDREF_THIS(); - return NS_OK; + NS_ADDREF_THIS(); + return NS_OK; } NS_IMETHODIMP -nsXULCommandDispatcher::Create(nsIDOMXULCommandDispatcher** aResult) +nsXULCommandDispatcher::Create(nsIDocument* aDoc, nsIDOMXULCommandDispatcher** aResult) { - nsXULCommandDispatcher* dispatcher = new nsXULCommandDispatcher(); - if (! dispatcher) - return NS_ERROR_OUT_OF_MEMORY; + nsXULCommandDispatcher* dispatcher = new nsXULCommandDispatcher(aDoc); + if (!dispatcher) + return NS_ERROR_OUT_OF_MEMORY; - *aResult = dispatcher; - NS_ADDREF(*aResult); - return NS_OK; + *aResult = dispatcher; + NS_ADDREF(*aResult); + return NS_OK; } +void +nsXULCommandDispatcher::EnsureFocusController() +{ + if (!mFocusController) { + nsCOMPtr global; + mDocument->GetScriptGlobalObject(getter_AddRefs(global)); + nsCOMPtr win(do_QueryInterface(global)); + + // An inelegant way to retrieve this to be sure, but we are + // guaranteed that the focus controller outlives us, so it + // is safe to hold on to it (since we can't die until it has + // died). + nsCOMPtr focus; + win->GetRootFocusController(getter_AddRefs(focus)); + mFocusController = focus; // Store as a weak ptr. + } +} //////////////////////////////////////////////////////////////// // nsIDOMXULTracker Interface @@ -128,35 +141,31 @@ nsXULCommandDispatcher::Create(nsIDOMXULCommandDispatcher** aResult) NS_IMETHODIMP nsXULCommandDispatcher::GetFocusedElement(nsIDOMElement** aElement) { - *aElement = mCurrentElement; - NS_IF_ADDREF(*aElement); - return NS_OK; + EnsureFocusController(); + return mFocusController->GetFocusedElement(aElement); } NS_IMETHODIMP nsXULCommandDispatcher::GetFocusedWindow(nsIDOMWindowInternal** aWindow) { - *aWindow = mCurrentWindow; - NS_IF_ADDREF(*aWindow); - return NS_OK; + EnsureFocusController(); + return mFocusController->GetFocusedWindow(aWindow); } NS_IMETHODIMP nsXULCommandDispatcher::SetFocusedElement(nsIDOMElement* aElement) { - mCurrentElement = aElement; - // Need to update focus commands when focus switches from - // an element to no element, so don't test mCurrentElement - // before updating. - UpdateCommands(NS_LITERAL_STRING("focus")); - return NS_OK; + EnsureFocusController(); + return mFocusController->SetFocusedElement(aElement); } NS_IMETHODIMP nsXULCommandDispatcher::SetFocusedWindow(nsIDOMWindowInternal* aWindow) { - mCurrentWindow = aWindow; - return NS_OK; + EnsureFocusController(); + if (mFocusController) + return mFocusController->SetFocusedWindow(aWindow); + return NS_ERROR_FAILURE; } NS_IMETHODIMP @@ -164,110 +173,114 @@ nsXULCommandDispatcher::AddCommandUpdater(nsIDOMElement* aElement, const nsAReadableString& aEvents, const nsAReadableString& aTargets) { - NS_PRECONDITION(aElement != nsnull, "null ptr"); - if (! aElement) - return NS_ERROR_NULL_POINTER; + NS_PRECONDITION(aElement != nsnull, "null ptr"); + if (! aElement) + return NS_ERROR_NULL_POINTER; - Updater* updater = mUpdaters; - Updater** link = &mUpdaters; + Updater* updater = mUpdaters; + Updater** link = &mUpdaters; - while (updater) { - if (updater->mElement == aElement) { + while (updater) { + if (updater->mElement == aElement) { #ifdef NS_DEBUG - nsCAutoString eventsC, targetsC, aeventsC, atargetsC; - eventsC.AssignWithConversion(updater->mEvents); - targetsC.AssignWithConversion(updater->mTargets); - aeventsC.Assign(NS_ConvertUCS2toUTF8(aEvents)); - atargetsC.Assign(NS_ConvertUCS2toUTF8(aTargets)); - PR_LOG(gLog, PR_LOG_ALWAYS, - ("xulcmd[%p] replace %p(events=%s targets=%s) with (events=%s targets=%s)", - this, aElement, - (const char*) eventsC, - (const char*) targetsC, - (const char*) aeventsC, - (const char*) atargetsC)); + nsCAutoString eventsC, targetsC, aeventsC, atargetsC; + eventsC.AssignWithConversion(updater->mEvents); + targetsC.AssignWithConversion(updater->mTargets); + aeventsC.Assign(NS_ConvertUCS2toUTF8(aEvents)); + atargetsC.Assign(NS_ConvertUCS2toUTF8(aTargets)); + PR_LOG(gLog, PR_LOG_ALWAYS, + ("xulcmd[%p] replace %p(events=%s targets=%s) with (events=%s targets=%s)", + this, aElement, + (const char*) eventsC, + (const char*) targetsC, + (const char*) aeventsC, + (const char*) atargetsC)); #endif - // If the updater was already in the list, then replace - // (?) the 'events' and 'targets' filters with the new - // specification. - updater->mEvents = aEvents; - updater->mTargets = aTargets; - return NS_OK; - } - - link = &(updater->mNext); - updater = updater->mNext; + // If the updater was already in the list, then replace + // (?) the 'events' and 'targets' filters with the new + // specification. + updater->mEvents = aEvents; + updater->mTargets = aTargets; + return NS_OK; } -#ifdef NS_DEBUG - nsCAutoString aeventsC, atargetsC; - aeventsC.Assign(NS_ConvertUCS2toUTF8(aEvents)); - atargetsC.Assign(NS_ConvertUCS2toUTF8(aTargets)); - PR_LOG(gLog, PR_LOG_ALWAYS, - ("xulcmd[%p] add %p(events=%s targets=%s)", - this, aElement, - (const char*) aeventsC, - (const char*) atargetsC)); + link = &(updater->mNext); + updater = updater->mNext; + } +#ifdef NS_DEBUG + nsCAutoString aeventsC, atargetsC; + aeventsC.Assign(NS_ConvertUCS2toUTF8(aEvents)); + atargetsC.Assign(NS_ConvertUCS2toUTF8(aTargets)); + + PR_LOG(gLog, PR_LOG_ALWAYS, + ("xulcmd[%p] add %p(events=%s targets=%s)", + this, aElement, + (const char*) aeventsC, + (const char*) atargetsC)); #endif - // If we get here, this is a new updater. Append it to the list. - updater = new Updater(aElement, aEvents, aTargets); - if (! updater) - return NS_ERROR_OUT_OF_MEMORY; + // If we get here, this is a new updater. Append it to the list. + updater = new Updater(aElement, aEvents, aTargets); + if (! updater) + return NS_ERROR_OUT_OF_MEMORY; - *link = updater; - return NS_OK; + *link = updater; + return NS_OK; } NS_IMETHODIMP nsXULCommandDispatcher::RemoveCommandUpdater(nsIDOMElement* aElement) { - NS_PRECONDITION(aElement != nsnull, "null ptr"); - if (! aElement) - return NS_ERROR_NULL_POINTER; + NS_PRECONDITION(aElement != nsnull, "null ptr"); + if (! aElement) + return NS_ERROR_NULL_POINTER; - Updater* updater = mUpdaters; - Updater** link = &mUpdaters; + Updater* updater = mUpdaters; + Updater** link = &mUpdaters; - while (updater) { - if (updater->mElement == aElement) { + while (updater) { + if (updater->mElement == aElement) { #ifdef NS_DEBUG - nsCAutoString eventsC, targetsC; - eventsC.AssignWithConversion(updater->mEvents); - targetsC.AssignWithConversion(updater->mTargets); - PR_LOG(gLog, PR_LOG_ALWAYS, - ("xulcmd[%p] remove %p(events=%s targets=%s)", - this, aElement, - (const char*) eventsC, - (const char*) targetsC)); + nsCAutoString eventsC, targetsC; + eventsC.AssignWithConversion(updater->mEvents); + targetsC.AssignWithConversion(updater->mTargets); + PR_LOG(gLog, PR_LOG_ALWAYS, + ("xulcmd[%p] remove %p(events=%s targets=%s)", + this, aElement, + (const char*) eventsC, + (const char*) targetsC)); #endif - *link = updater->mNext; - delete updater; - return NS_OK; - } - - link = &(updater->mNext); - updater = updater->mNext; + *link = updater->mNext; + delete updater; + return NS_OK; } - // Hmm. Not found. Oh well. - return NS_OK; + link = &(updater->mNext); + updater = updater->mNext; + } + + // Hmm. Not found. Oh well. + return NS_OK; } NS_IMETHODIMP nsXULCommandDispatcher::UpdateCommands(const nsAReadableString& aEventName) { - nsresult rv; + nsresult rv; - nsAutoString id; - if (mCurrentElement) { - rv = mCurrentElement->GetAttribute(NS_ConvertASCIItoUCS2("id"), id); - NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get element's id"); - if (NS_FAILED(rv)) return rv; - } + EnsureFocusController(); + + nsAutoString id; + nsCOMPtr element; + mFocusController->GetFocusedElement(getter_AddRefs(element)); + if (element) { + rv = element->GetAttribute(NS_ConvertASCIItoUCS2("id"), id); + NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get element's id"); + if (NS_FAILED(rv)) return rv; + } #if 0 { @@ -277,226 +290,84 @@ nsXULCommandDispatcher::UpdateCommands(const nsAReadableString& aEventName) } #endif - for (Updater* updater = mUpdaters; updater != nsnull; updater = updater->mNext) { - // Skip any nodes that don't match our 'events' or 'targets' - // filters. - if (! Matches(updater->mEvents, aEventName)) - continue; + for (Updater* updater = mUpdaters; updater != nsnull; updater = updater->mNext) { + // Skip any nodes that don't match our 'events' or 'targets' + // filters. + if (! Matches(updater->mEvents, aEventName)) + continue; - if (! Matches(updater->mTargets, id)) - continue; + if (! Matches(updater->mTargets, id)) + continue; - nsCOMPtr content = do_QueryInterface(updater->mElement); - NS_ASSERTION(content != nsnull, "not an nsIContent"); - if (! content) - return NS_ERROR_UNEXPECTED; + nsCOMPtr content = do_QueryInterface(updater->mElement); + NS_ASSERTION(content != nsnull, "not an nsIContent"); + if (! content) + return NS_ERROR_UNEXPECTED; - nsCOMPtr document; - rv = content->GetDocument(*getter_AddRefs(document)); - NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get document"); - if (NS_FAILED(rv)) return rv; + nsCOMPtr document; + rv = content->GetDocument(*getter_AddRefs(document)); + NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get document"); + if (NS_FAILED(rv)) return rv; - NS_ASSERTION(document != nsnull, "element has no document"); - if (! document) - continue; + NS_ASSERTION(document != nsnull, "element has no document"); + if (! document) + continue; #ifdef NS_DEBUG - nsCAutoString aeventnameC; - aeventnameC.Assign(NS_ConvertUCS2toUTF8(aEventName)); - PR_LOG(gLog, PR_LOG_ALWAYS, - ("xulcmd[%p] update %p event=%s", - this, updater->mElement, - (const char*) aeventnameC)); + nsCAutoString aeventnameC; + aeventnameC.Assign(NS_ConvertUCS2toUTF8(aEventName)); + PR_LOG(gLog, PR_LOG_ALWAYS, + ("xulcmd[%p] update %p event=%s", + this, updater->mElement, + (const char*) aeventnameC)); #endif - PRInt32 count = document->GetNumberOfShells(); - for (PRInt32 i = 0; i < count; i++) { - nsCOMPtr shell = dont_AddRef(document->GetShellAt(i)); - if (! shell) - continue; - - // Retrieve the context in which our DOM event will fire. - nsCOMPtr context; - rv = shell->GetPresContext(getter_AddRefs(context)); - if (NS_FAILED(rv)) return rv; + PRInt32 count = document->GetNumberOfShells(); + for (PRInt32 i = 0; i < count; i++) { + nsCOMPtr shell = dont_AddRef(document->GetShellAt(i)); + if (! shell) + continue; + + // Retrieve the context in which our DOM event will fire. + nsCOMPtr context; + rv = shell->GetPresContext(getter_AddRefs(context)); + if (NS_FAILED(rv)) return rv; - // Handle the DOM event - nsEventStatus status = nsEventStatus_eIgnore; - nsEvent event; - event.eventStructType = NS_EVENT; - event.message = NS_XUL_COMMAND_UPDATE; - content->HandleDOMEvent(context, &event, nsnull, NS_EVENT_FLAG_INIT, &status); - } + // Handle the DOM event + nsEventStatus status = nsEventStatus_eIgnore; + nsEvent event; + event.eventStructType = NS_EVENT; + event.message = NS_XUL_COMMAND_UPDATE; + content->HandleDOMEvent(context, &event, nsnull, NS_EVENT_FLAG_INIT, &status); } - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::GetControllers(nsIControllers** aResult) -{ - //XXX: we should fix this so there's a generic interface that describes controllers, - // so this code would have no special knowledge of what object might have controllers. - if (mCurrentElement) { - nsCOMPtr xulElement = do_QueryInterface(mCurrentElement); - if (xulElement) - return xulElement->GetControllers(aResult); - - nsCOMPtr htmlTextArea = do_QueryInterface(mCurrentElement); - if (htmlTextArea) - return htmlTextArea->GetControllers(aResult); - - nsCOMPtr htmlInputElement = do_QueryInterface(mCurrentElement); - if (htmlInputElement) - return htmlInputElement->GetControllers(aResult); } - else if (mCurrentWindow) { - nsCOMPtr domWindow = do_QueryInterface(mCurrentWindow); - if (domWindow) - return domWindow->GetControllers(aResult); - } - - *aResult = nsnull; return NS_OK; } -///// -// nsIDOMFocusListener -///// - -nsresult -nsXULCommandDispatcher::Focus(nsIDOMEvent* aEvent) -{ - if (mSuppressFocus) - return NS_OK; - - nsCOMPtr t; - aEvent->GetOriginalTarget(getter_AddRefs(t)); - -#if 0 - printf("%d : Focus occurred on: ", this); - nsCOMPtr domDebugElement = do_QueryInterface(t); - if (domDebugElement) { - printf("A Focusable DOM Element"); - } - nsCOMPtr domDebugDocument = do_QueryInterface(t); - if (domDebugDocument) { - nsCOMPtr htmlDoc = do_QueryInterface(t); - if (htmlDoc) { - printf("Window with an HTML doc (happens twice)"); - } - else printf("Window with a XUL doc (happens twice)"); - } - printf("\n"); -#endif /* DEBUG_hyatt */ - - nsCOMPtr domElement = do_QueryInterface(t); - if (domElement && (domElement != mCurrentElement)) { - SetFocusedElement(domElement); - - // Also set focus to our innermost window. - // XXX Must be done for the Ender case, since ender causes a blur, - // but we don't hear the subsequent focus to the Ender window. - nsCOMPtr ownerDoc; - domElement->GetOwnerDocument(getter_AddRefs(ownerDoc)); - nsCOMPtr domWindow; - GetParentWindowFromDocument(ownerDoc, getter_AddRefs(domWindow)); - if (domWindow) - SetFocusedWindow(domWindow); - } - else { - // We're focusing a window. We only want to do an update commands - // if no element is focused. - nsCOMPtr domWindow; - nsCOMPtr domDoc = do_QueryInterface(t); - if (domDoc) { - GetParentWindowFromDocument(domDoc, getter_AddRefs(domWindow)); - if (domWindow) { - SetFocusedWindow(domWindow); - if (mCurrentElement) { - // Make sure this element is in our window. If not, we - // should clear this field. - nsCOMPtr ownerDoc; - mCurrentElement->GetOwnerDocument(getter_AddRefs(ownerDoc)); - nsCOMPtr windowDoc; - mCurrentWindow->GetDocument(getter_AddRefs(windowDoc)); - if (ownerDoc != windowDoc) - mCurrentElement = nsnull; - } - - if (!mCurrentElement) - UpdateCommands(NS_LITERAL_STRING("focus")); - } - } - } - - return NS_OK; -} - -nsresult -nsXULCommandDispatcher::Blur(nsIDOMEvent* aEvent) -{ - if (mSuppressFocus) - return NS_OK; - - nsCOMPtr t; - aEvent->GetOriginalTarget(getter_AddRefs(t)); - -#if 0 - printf("%d : Blur occurred on: ", this); - nsCOMPtr domDebugElement = do_QueryInterface(t); - if (domDebugElement) { - printf("A Focusable DOM Element"); - } - nsCOMPtr domDebugDocument = do_QueryInterface(t); - if (domDebugDocument) { - nsCOMPtr htmlDoc = do_QueryInterface(t); - if (htmlDoc) { - printf("Window with an HTML doc (happens twice)"); - } - else printf("Window with a XUL doc (happens twice)"); - } - printf("\n"); -#endif /* DEBUG_hyatt */ - - nsCOMPtr domElement = do_QueryInterface(t); - if (domElement) { - SetFocusedElement(nsnull); - } - - nsCOMPtr domWindow; - nsCOMPtr domDoc = do_QueryInterface(t); - if (domDoc) { - GetParentWindowFromDocument(domDoc, getter_AddRefs(domWindow)); - if (domWindow) - SetFocusedWindow(nsnull); - } - - return NS_OK; -} //////////////////////////////////////////////////////////////////////// // nsIScriptObjectOwner interface NS_IMETHODIMP nsXULCommandDispatcher::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject) { - nsresult res = NS_OK; - nsIScriptGlobalObject *global = aContext->GetGlobalObject(); + nsresult res = NS_OK; + nsIScriptGlobalObject *global = aContext->GetGlobalObject(); - if (nsnull == mScriptObject) { - res = NS_NewScriptXULCommandDispatcher(aContext, (nsISupports *)(nsIDOMXULCommandDispatcher*)this, global, (void**)&mScriptObject); - } - *aScriptObject = mScriptObject; + if (nsnull == mScriptObject) { + res = NS_NewScriptXULCommandDispatcher(aContext, (nsISupports *)(nsIDOMXULCommandDispatcher*)this, global, (void**)&mScriptObject); + } + *aScriptObject = mScriptObject; - NS_RELEASE(global); - return res; + NS_RELEASE(global); + return res; } NS_IMETHODIMP nsXULCommandDispatcher::SetScriptObject(void *aScriptObject) { - mScriptObject = aScriptObject; - return NS_OK; + mScriptObject = aScriptObject; + return NS_OK; } @@ -504,162 +375,41 @@ PRBool nsXULCommandDispatcher::Matches(const nsString& aList, const nsAReadableString& aElement) { - if (aList.Equals(NS_LITERAL_STRING("*"))) - return PR_TRUE; // match _everything_! + if (aList.Equals(NS_LITERAL_STRING("*"))) + return PR_TRUE; // match _everything_! - PRInt32 indx = aList.Find((const PRUnichar *)nsPromiseFlatString(aElement).get()); - if (indx == -1) - return PR_FALSE; // not in the list at all + PRInt32 indx = aList.Find((const PRUnichar *)nsPromiseFlatString(aElement).get()); + if (indx == -1) + return PR_FALSE; // not in the list at all - // okay, now make sure it's not a substring snafu; e.g., 'ur' - // found inside of 'blur'. - if (indx > 0) { - PRUnichar ch = aList[indx - 1]; - if (! nsCRT::IsAsciiSpace(ch) && ch != PRUnichar(',')) - return PR_FALSE; - } + // okay, now make sure it's not a substring snafu; e.g., 'ur' + // found inside of 'blur'. + if (indx > 0) { + PRUnichar ch = aList[indx - 1]; + if (! nsCRT::IsAsciiSpace(ch) && ch != PRUnichar(',')) + return PR_FALSE; + } - if (indx + aElement.Length() < aList.Length()) { - PRUnichar ch = aList[indx + aElement.Length()]; - if (! nsCRT::IsAsciiSpace(ch) && ch != PRUnichar(',')) - return PR_FALSE; - } + if (indx + aElement.Length() < aList.Length()) { + PRUnichar ch = aList[indx + aElement.Length()]; + if (! nsCRT::IsAsciiSpace(ch) && ch != PRUnichar(',')) + return PR_FALSE; + } - return PR_TRUE; + return PR_TRUE; } - -nsresult -nsXULCommandDispatcher::GetParentWindowFromDocument(nsIDOMDocument* aDocument, nsIDOMWindowInternal** aWindow) +NS_IMETHODIMP +nsXULCommandDispatcher::GetControllers(nsIControllers** aResult) { - nsCOMPtr objectOwner = do_QueryInterface(aDocument); - if(!objectOwner) return NS_OK; - - nsCOMPtr globalObject; - objectOwner->GetScriptGlobalObject(getter_AddRefs(globalObject)); - if(!globalObject) return NS_OK; - - nsCOMPtr domWindow = do_QueryInterface(globalObject); - *aWindow = domWindow; - NS_IF_ADDREF(*aWindow); - return NS_OK; + EnsureFocusController(); + return mFocusController->GetControllers(aResult); } NS_IMETHODIMP nsXULCommandDispatcher::GetControllerForCommand(const nsAReadableString& aCommand, nsIController** _retval) { - nsPromiseFlatString flatCommand(aCommand); - const PRUnichar *command = flatCommand.get(); - *_retval = nsnull; - - nsCOMPtr controllers; - GetControllers(getter_AddRefs(controllers)); - if(controllers) { - nsCOMPtr controller; - controllers->GetControllerForCommand(command, getter_AddRefs(controller)); - if(controller) { - *_retval = controller; - NS_ADDREF(*_retval); - return NS_OK; - } - } - - nsCOMPtr currentWindow; - if (mCurrentElement) { - // Move up to the window. - nsCOMPtr domDoc; - mCurrentElement->GetOwnerDocument(getter_AddRefs(domDoc)); - nsCOMPtr domWindow; - GetParentWindowFromDocument(domDoc, getter_AddRefs(domWindow)); - currentWindow = do_QueryInterface(domWindow); - } - else if (mCurrentWindow) { - nsCOMPtr privateWin = do_QueryInterface(mCurrentWindow); - privateWin->GetPrivateParent(getter_AddRefs(currentWindow)); - } - else return NS_OK; - - while(currentWindow) { - nsCOMPtr domWindow = do_QueryInterface(currentWindow); - if(domWindow) { - nsCOMPtr controllers2; - domWindow->GetControllers(getter_AddRefs(controllers2)); - if(controllers2) { - nsCOMPtr controller; - controllers2->GetControllerForCommand(command, getter_AddRefs(controller)); - if(controller) { - *_retval = controller; - NS_ADDREF(*_retval); - return NS_OK; - } - } - } - nsCOMPtr parentPWindow = currentWindow; - parentPWindow->GetPrivateParent(getter_AddRefs(currentWindow)); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::GetSuppressFocusScroll(PRBool* aSuppressFocusScroll) -{ - *aSuppressFocusScroll = mSuppressFocusScroll; - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::SetSuppressFocusScroll(PRBool aSuppressFocusScroll) -{ - mSuppressFocusScroll = aSuppressFocusScroll; - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::GetSuppressFocus(PRBool* aSuppressFocus) -{ - if(mSuppressFocus) - *aSuppressFocus = PR_TRUE; - else - *aSuppressFocus = PR_FALSE; - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::SetSuppressFocus(PRBool aSuppressFocus) -{ - if(aSuppressFocus) - ++mSuppressFocus; - else if(mSuppressFocus > 0) - --mSuppressFocus; - - //printf("mSuppressFocus == %d\n", mSuppressFocus); - - // we are unsuppressing after activating, so update focus-related commands - // we need this to update commands in the case where an element is focussed. - if (!mSuppressFocus && mCurrentElement) - UpdateCommands(NS_LITERAL_STRING("focus")); - - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::GetActive(PRBool* aActive) -{ - //if(!mFocusInitialized) - // return PR_TRUE; - - *aActive = mActive; - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::SetActive(PRBool aActive) -{ - if(!mFocusInitialized) - mFocusInitialized = PR_TRUE; - - mActive = aActive; - return NS_OK; + EnsureFocusController(); + return mFocusController->GetControllerForCommand(aCommand, _retval); } diff --git a/content/xul/document/src/nsXULCommandDispatcher.h b/content/xul/document/src/nsXULCommandDispatcher.h index 537d3c7befb..a53338240da 100644 --- a/content/xul/document/src/nsXULCommandDispatcher.h +++ b/content/xul/document/src/nsXULCommandDispatcher.h @@ -42,21 +42,22 @@ class nsIDOMElement; class nsPIDOMWindow; - +class nsIFocusController; class nsXULCommandDispatcher : public nsIDOMXULCommandDispatcher, - public nsIDOMFocusListener, public nsIScriptObjectOwner, public nsSupportsWeakReference { protected: - nsXULCommandDispatcher(void); - virtual ~nsXULCommandDispatcher(void); + nsXULCommandDispatcher(nsIDocument* aDocument); + virtual ~nsXULCommandDispatcher(); + + void EnsureFocusController(); public: static NS_IMETHODIMP - Create(nsIDOMXULCommandDispatcher** aResult); + Create(nsIDocument* aDocument, nsIDOMXULCommandDispatcher** aResult); // nsISupports NS_DECL_ISUPPORTS @@ -64,50 +65,31 @@ public: // nsIDOMXULCommandDispatcher interface NS_DECL_IDOMXULCOMMANDDISPATCHER - // nsIDOMFocusListener - virtual nsresult Focus(nsIDOMEvent* aEvent); - virtual nsresult Blur(nsIDOMEvent* aEvent); - - // nsIDOMEventListener - virtual nsresult HandleEvent(nsIDOMEvent* anEvent) { return NS_OK; }; - // nsIScriptObjectOwner interface NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject); NS_IMETHOD SetScriptObject(void *aScriptObject); -public: - static nsresult GetParentWindowFromDocument(nsIDOMDocument* aElement, nsIDOMWindowInternal** aWindow); - protected: - void* mScriptObject; // ???? + nsIFocusController* mFocusController; // Weak. We always die before the focus controller does. + nsIDocument* mDocument; // Weak. - // XXX THis was supposed to be WEAK, but c'mon, that's an accident - // waiting to happen! If somebody deletes the node, then asks us - // for the focus, we'll get killed! - nsCOMPtr mCurrentElement; // [OWNER] - nsCOMPtr mCurrentWindow; // [OWNER] - - //PRBool mSuppressFocus; - PRUint32 mSuppressFocus; - PRBool mSuppressFocusScroll; - PRBool mActive; - PRBool mFocusInitialized; + void* mScriptObject; class Updater { public: - Updater(nsIDOMElement* aElement, - const nsAReadableString& aEvents, - const nsAReadableString& aTargets) - : mElement(aElement), - mEvents(aEvents), - mTargets(aTargets), - mNext(nsnull) - {} + Updater(nsIDOMElement* aElement, + const nsAReadableString& aEvents, + const nsAReadableString& aTargets) + : mElement(aElement), + mEvents(aEvents), + mTargets(aTargets), + mNext(nsnull) + {} - nsIDOMElement* mElement; // [WEAK] - nsString mEvents; - nsString mTargets; - Updater* mNext; + nsIDOMElement* mElement; // [WEAK] + nsString mEvents; + nsString mTargets; + Updater* mNext; }; Updater* mUpdaters; diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index 98e7132361f..5887459fa7b 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -1413,11 +1413,6 @@ nsXULDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject) if (mRootContent) mRootContent->SetDocument(nsnull, PR_TRUE, PR_TRUE); - // Break circular reference for the case where the currently - // focused window is ourself. - if (mCommandDispatcher) - mCommandDispatcher->SetFocusedWindow(nsnull); - // set all builder references to document to nsnull -- out of band notification // to break ownership cycle if (mBuilders) { @@ -3828,18 +3823,9 @@ nsXULDocument::Init() mNodeInfoManager->Init(mNameSpaceManager); // Create our command dispatcher and hook it up. - rv = nsXULCommandDispatcher::Create(getter_AddRefs(mCommandDispatcher)); + rv = nsXULCommandDispatcher::Create(this, getter_AddRefs(mCommandDispatcher)); NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a focus tracker"); if (NS_FAILED(rv)) return rv; - - nsCOMPtr commandDispatcher = - do_QueryInterface(mCommandDispatcher); - - if (commandDispatcher) { - // Take the focus tracker and add it as an event listener for focus and blur events. - AddEventListener(NS_LITERAL_STRING("focus"), commandDispatcher, PR_TRUE); - AddEventListener(NS_LITERAL_STRING("blur"), commandDispatcher, PR_TRUE); - } // Get the local store. Yeah, I know. I wish GetService() used a // 'void**', too. diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index a541127d8a1..12b8a8d79c3 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -81,11 +81,7 @@ #include "nsCExternalHandlerService.h" #include "nsIExternalProtocolService.h" -// XXX Very unfortunate dependencies. These are required to fix -// some serious focus bugs. Please read my comment in -// SetupNewViewer. -- hyatt -#include "nsIDOMXULDocument.h" -#include "nsIDOMXULCommandDispatcher.h" +#include "nsIFocusController.h" static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID); static NS_DEFINE_CID(kPlatformCharsetCID, NS_PLATFORMCHARSET_CID); @@ -1681,6 +1677,15 @@ NS_IMETHODIMP nsDocShell::Destroy() if(docShellParentAsNode) docShellParentAsNode->RemoveChild(this); + if (mScriptGlobal) { + nsCOMPtr focusController; + nsCOMPtr ourWindow = do_QueryInterface(mScriptGlobal); + ourWindow->GetRootFocusController(getter_AddRefs(focusController)); + if (focusController) { + focusController->SetFocusedWindow(nsnull); + } + } + mContentViewer = nsnull; DestroyChildren(); @@ -2811,39 +2816,24 @@ NS_IMETHODIMP nsDocShell::SetupNewViewer(nsIContentViewer* aNewViewer) } } - // XXX The command dispatcher is the only object that understands - // focus in our system truly, madly, and deeply. Right now it is attached to - // XUL documents, but eventually it will move into the embedding layer and be - // divorced from XUL. - // - // For 6.0, however, this isn't going to happen. - // - // It is necessary to obtain the command dispatcher to utilize its ability + // It is necessary to obtain the focus controller to utilize its ability // to suppress focus. This is necessary to fix Win32-only bugs related to // a loss of focus when mContentViewer is set to null. The internal window // is destroyed, and the OS focuses the parent window. This call ends up - // notifying the command dispatcher that the outer window should focus + // notifying the focus controller that the outer window should focus // and this hoses us on any link traversal. // - // Please do not touch any of the command dispatcher code here without + // Please do not touch any of the focus controller code here without // testing bugs #28580 and 50509. These are immensely important bugs, // so PLEASE take care not to regress them if you decide to alter this // code later -- hyatt - nsCOMPtr commandDispatcher; + nsCOMPtr focusController; if (mScriptGlobal) { - nsCOMPtr rootWindow; nsCOMPtr ourWindow = do_QueryInterface(mScriptGlobal); - ourWindow->GetPrivateRoot(getter_AddRefs(rootWindow)); - nsCOMPtr rootDocument; - rootWindow->GetDocument(getter_AddRefs(rootDocument)); - nsCOMPtr xulDoc = do_QueryInterface(rootDocument); - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - // Suppress the command dispatcher. - commandDispatcher->SetSuppressFocus(PR_TRUE); - } + ourWindow->GetRootFocusController(getter_AddRefs(focusController)); + if (focusController) { + // Suppress the command dispatcher. + focusController->SetSuppressFocus(PR_TRUE); } } @@ -2856,12 +2846,10 @@ NS_IMETHODIMP nsDocShell::SetupNewViewer(nsIContentViewer* aNewViewer) mContentViewer = nsnull; // End copying block (Don't hold content/document viewer ref beyond here!!) - // See the book I wrote above regarding why the command dispatcher is - // being used here. I reiterate that this object is not really a XUL - // object and will move post-6.0, so please don't come into my cube - // and beat me for checking this in. -- hyatt - if (commandDispatcher) - commandDispatcher->SetSuppressFocus(PR_FALSE); + // See the book I wrote above regarding why the focus controller is + // being used here. -- hyatt + if (focusController) + focusController->SetSuppressFocus(PR_FALSE); mContentViewer = aNewViewer; diff --git a/dom/public/base/MANIFEST b/dom/public/base/MANIFEST index 59fcf451c4e..a9076e8575b 100644 --- a/dom/public/base/MANIFEST +++ b/dom/public/base/MANIFEST @@ -35,6 +35,8 @@ nsIDOMPluginArray.h nsIDOMBarProp.h nsIDOMDOMException.h nsPIDOMWindow.h +nsPIWindowRoot.h +nsIFocusController.h nsIDOMAbstractView.h nsIDOMCrypto.h nsIDOMCRMFObject.h diff --git a/dom/public/base/Makefile.in b/dom/public/base/Makefile.in index ec2bc1db506..3226cf967b3 100644 --- a/dom/public/base/Makefile.in +++ b/dom/public/base/Makefile.in @@ -44,6 +44,8 @@ EXPORTS = \ nsIDOMBarProp.h \ nsIDOMDOMException.h \ nsPIDOMWindow.h \ + nsPIWindowRoot.h \ + nsIFocusController.h \ nsIDOMAbstractView.h \ nsIDOMViewCSS.h \ nsIDOMCRMFObject.h \ diff --git a/dom/public/base/makefile.win b/dom/public/base/makefile.win index 9092bc4f5b7..eca794d1288 100644 --- a/dom/public/base/makefile.win +++ b/dom/public/base/makefile.win @@ -28,9 +28,9 @@ EXPORTS=nsIDOMWindow.h nsIDOMWindowInternal.h nsIDOMNavigator.h \ nsIDOMWindowCollection.h nsIDOMScreen.h nsIDOMHistory.h \ nsIDOMMimeType.h nsIDOMMimeTypeArray.h \ nsIDOMPlugin.h nsIDOMPluginArray.h nsIDOMBarProp.h \ - nsIDOMDOMException.h nsPIDOMWindow.h nsIDOMAbstractView.h \ + nsIDOMDOMException.h nsPIDOMWindow.h nsPIWindowRoot.h nsIDOMAbstractView.h \ nsIDOMViewCSS.h nsIDOMCRMFObject.h nsIDOMCrypto.h nsIDOMPkcs11.h \ - nsIDOMWindowEventOwner.h + nsIDOMWindowEventOwner.h nsIFocusController.h MODULE=dom diff --git a/dom/public/base/nsIFocusController.h b/dom/public/base/nsIFocusController.h new file mode 100644 index 00000000000..6803eeaf86a --- /dev/null +++ b/dom/public/base/nsIFocusController.h @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is Netscape + * Communications, Inc. Portions created by Netscape are + * Copyright (C) 1999, Mozilla. All Rights Reserved. + * + * Contributor(s): + * David W. Hyatt (Original Author) + */ + +#ifndef nsIFocusController_h__ +#define nsIFocusController_h__ + +#include "nsISupports.h" + +class nsIDOMElement; +class nsIDOMWindowInternal; +class nsIController; +class nsIControllers; + +// {AC71F479-17E1-4ee0-8EFD-0ECF2AA2F827} +#define NS_IFOCUSCONTROLLER_IID \ +{ 0xac71f479, 0x17e1, 0x4ee0, { 0x8e, 0xfd, 0xe, 0xcf, 0x2a, 0xa2, 0xf8, 0x27 } } + +class nsIFocusController : public nsISupports { +public: + static const nsIID& GetIID() { static nsIID iid = NS_IFOCUSCONTROLLER_IID; return iid; } + + NS_IMETHOD GetFocusedElement(nsIDOMElement** aResult)=0; + NS_IMETHOD SetFocusedElement(nsIDOMElement* aElement)=0; + + NS_IMETHOD GetFocusedWindow(nsIDOMWindowInternal** aResult)=0; + NS_IMETHOD SetFocusedWindow(nsIDOMWindowInternal* aResult)=0; + + NS_IMETHOD GetSuppressFocus(PRBool* aSuppressFlag)=0; + NS_IMETHOD SetSuppressFocus(PRBool aSuppressFlag)=0; + + NS_IMETHOD GetSuppressFocusScroll(PRBool* aSuppressFlag)=0; + NS_IMETHOD SetSuppressFocusScroll(PRBool aSuppressFlag)=0; + + NS_IMETHOD GetActive(PRBool* aActive)=0; + NS_IMETHOD SetActive(PRBool aActive)=0; + + NS_IMETHOD GetControllerForCommand(const nsAReadableString& aCommand, nsIController** aResult)=0; + NS_IMETHOD GetControllers(nsIControllers** aResult)=0; +}; + +#endif // nsIFocusController_h__ diff --git a/dom/public/base/nsPIDOMWindow.h b/dom/public/base/nsPIDOMWindow.h index 585ca5525d6..097febd4650 100644 --- a/dom/public/base/nsPIDOMWindow.h +++ b/dom/public/base/nsPIDOMWindow.h @@ -34,6 +34,8 @@ class nsIDocShell; class nsIDOMWindowInternal; +class nsIChromeEventHandler; +class nsIFocusController; #define NS_PIDOMWINDOW_IID \ { 0x3aa80781, 0x7e6a, 0x11d3, { 0xbf, 0x87, 0x0, 0x10, 0x5a, 0x1b, 0x6, 0x27 } } @@ -55,7 +57,9 @@ public: NS_IMETHOD Activate() = 0; NS_IMETHOD Deactivate() = 0; - NS_IMETHOD GetRootCommandDispatcher(nsIDOMXULCommandDispatcher ** aDispatcher)=0; + NS_IMETHOD GetChromeEventHandler(nsIChromeEventHandler** aHandler)=0; + + NS_IMETHOD GetRootFocusController(nsIFocusController** aResult)=0; /* from nsIBaseWindow */ /* void setPositionAndSize (in long x, in long y, in long cx, in long cy, in boolean fRepaint); */ diff --git a/dom/public/base/nsPIWindowRoot.h b/dom/public/base/nsPIWindowRoot.h new file mode 100644 index 00000000000..510e6f6e9e6 --- /dev/null +++ b/dom/public/base/nsPIWindowRoot.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is Netscape + * Communications, Inc. Portions created by Netscape are + * Copyright (C) 1999, Mozilla. All Rights Reserved. + * + * Contributor(s): + * David W. Hyatt (Original Author) + */ + +#ifndef nsPIWindowRoot_h__ +#define nsPIWindowRoot_h__ + +#include "nsISupports.h" + +class nsIFocusController; + +// {575CB0E1-E6C4-484a-99F8-C47B06C0E521} +#define NS_IWINDOWROOT_IID \ +{ 0x575cb0e1, 0xe6c4, 0x484a, { 0x99, 0xf8, 0xc4, 0x7b, 0x6, 0xc0, 0xe5, 0x21 } } + +class nsPIWindowRoot : public nsISupports { +public: + static const nsIID& GetIID() { static nsIID iid = NS_IWINDOWROOT_IID; return iid; } + + NS_IMETHOD GetFocusController(nsIFocusController** aResult)=0; +}; + +#endif // nsPIWindowRoot_h__ diff --git a/dom/public/idl/xul/XULCommandDispatcher.idl b/dom/public/idl/xul/XULCommandDispatcher.idl index 07ee3349dc1..19e6d886009 100644 --- a/dom/public/idl/xul/XULCommandDispatcher.idl +++ b/dom/public/idl/xul/XULCommandDispatcher.idl @@ -5,9 +5,6 @@ interface XULCommandDispatcher { attribute Element focusedElement; attribute WindowInternal focusedWindow; - attribute boolean suppressFocus; - attribute boolean suppressFocusScroll; - attribute boolean active; void addCommandUpdater(in Element updater, in DOMString events, in DOMString targets); void removeCommandUpdater(in Element updater); @@ -15,6 +12,5 @@ interface XULCommandDispatcher { void updateCommands(in DOMString eventName); xpidl nsIController getControllerForCommand(in DOMString command); - xpidl nsIControllers getControllers(); }; diff --git a/dom/public/xul/nsIDOMXULCommandDispatcher.h b/dom/public/xul/nsIDOMXULCommandDispatcher.h index 3153278e4a2..6fbedb13750 100644 --- a/dom/public/xul/nsIDOMXULCommandDispatcher.h +++ b/dom/public/xul/nsIDOMXULCommandDispatcher.h @@ -47,15 +47,6 @@ public: NS_IMETHOD GetFocusedWindow(nsIDOMWindowInternal** aFocusedWindow)=0; NS_IMETHOD SetFocusedWindow(nsIDOMWindowInternal* aFocusedWindow)=0; - NS_IMETHOD GetSuppressFocus(PRBool* aSuppressFocus)=0; - NS_IMETHOD SetSuppressFocus(PRBool aSuppressFocus)=0; - - NS_IMETHOD GetSuppressFocusScroll(PRBool* aSuppressFocusScroll)=0; - NS_IMETHOD SetSuppressFocusScroll(PRBool aSuppressFocusScroll)=0; - - NS_IMETHOD GetActive(PRBool* aActive)=0; - NS_IMETHOD SetActive(PRBool aActive)=0; - NS_IMETHOD AddCommandUpdater(nsIDOMElement* aUpdater, const nsAReadableString& aEvents, const nsAReadableString& aTargets)=0; NS_IMETHOD RemoveCommandUpdater(nsIDOMElement* aUpdater)=0; @@ -73,12 +64,6 @@ public: NS_IMETHOD SetFocusedElement(nsIDOMElement* aFocusedElement); \ NS_IMETHOD GetFocusedWindow(nsIDOMWindowInternal** aFocusedWindow); \ NS_IMETHOD SetFocusedWindow(nsIDOMWindowInternal* aFocusedWindow); \ - NS_IMETHOD GetSuppressFocus(PRBool* aSuppressFocus); \ - NS_IMETHOD SetSuppressFocus(PRBool aSuppressFocus); \ - NS_IMETHOD GetSuppressFocusScroll(PRBool* aSuppressFocusScroll); \ - NS_IMETHOD SetSuppressFocusScroll(PRBool aSuppressFocusScroll); \ - NS_IMETHOD GetActive(PRBool* aActive); \ - NS_IMETHOD SetActive(PRBool aActive); \ NS_IMETHOD AddCommandUpdater(nsIDOMElement* aUpdater, const nsAReadableString& aEvents, const nsAReadableString& aTargets); \ NS_IMETHOD RemoveCommandUpdater(nsIDOMElement* aUpdater); \ NS_IMETHOD UpdateCommands(const nsAReadableString& aEventName); \ @@ -92,12 +77,6 @@ public: NS_IMETHOD SetFocusedElement(nsIDOMElement* aFocusedElement) { return _to SetFocusedElement(aFocusedElement); } \ NS_IMETHOD GetFocusedWindow(nsIDOMWindowInternal** aFocusedWindow) { return _to GetFocusedWindow(aFocusedWindow); } \ NS_IMETHOD SetFocusedWindow(nsIDOMWindowInternal* aFocusedWindow) { return _to SetFocusedWindow(aFocusedWindow); } \ - NS_IMETHOD GetSuppressFocus(PRBool* aSuppressFocus) { return _to GetSuppressFocus(aSuppressFocus); } \ - NS_IMETHOD SetSuppressFocus(PRBool aSuppressFocus) { return _to SetSuppressFocus(aSuppressFocus); } \ - NS_IMETHOD GetSuppressFocusScroll(PRBool* aSuppressFocusScroll) { return _to GetSuppressFocusScroll(aSuppressFocusScroll); } \ - NS_IMETHOD SetSuppressFocusScroll(PRBool aSuppressFocusScroll) { return _to SetSuppressFocusScroll(aSuppressFocusScroll); } \ - NS_IMETHOD GetActive(PRBool* aActive) { return _to GetActive(aActive); } \ - NS_IMETHOD SetActive(PRBool aActive) { return _to SetActive(aActive); } \ NS_IMETHOD AddCommandUpdater(nsIDOMElement* aUpdater, const nsAReadableString& aEvents, const nsAReadableString& aTargets) { return _to AddCommandUpdater(aUpdater, aEvents, aTargets); } \ NS_IMETHOD RemoveCommandUpdater(nsIDOMElement* aUpdater) { return _to RemoveCommandUpdater(aUpdater); } \ NS_IMETHOD UpdateCommands(const nsAReadableString& aEventName) { return _to UpdateCommands(aEventName); } \ diff --git a/dom/src/base/Makefile.in b/dom/src/base/Makefile.in index aae31a00ad4..00807221e95 100644 --- a/dom/src/base/Makefile.in +++ b/dom/src/base/Makefile.in @@ -40,6 +40,7 @@ CPPSRCS = \ nsJSNavigator.cpp \ nsJSLocation.cpp \ nsJSWindowCollection.cpp \ + nsFocusController.cpp \ nsGlobalWindow.cpp \ nsLocation.cpp \ nsDOMWindowList.cpp \ @@ -57,6 +58,7 @@ CPPSRCS = \ nsJSCRMFObject.cpp \ nsJSCrypto.cpp \ nsJSPkcs11.cpp \ + nsWindowRoot.cpp \ $(NULL) EXPORTS = nsJSUtils.h diff --git a/dom/src/base/makefile.win b/dom/src/base/makefile.win index 74f77231f47..6a64c8d8e99 100644 --- a/dom/src/base/makefile.win +++ b/dom/src/base/makefile.win @@ -36,6 +36,7 @@ CPPSRCS = \ nsJSNavigator.cpp \ nsJSLocation.cpp \ nsJSWindowCollection.cpp \ + nsFocusController.cpp \ nsGlobalWindow.cpp \ nsLocation.cpp \ nsDOMWindowList.cpp \ @@ -53,6 +54,7 @@ CPPSRCS = \ nsJSCrypto.cpp \ nsJSCMRFObject.cpp \ nsJSPkcs11.cpp \ + nsWindowRoot.cpp \ $(NULL) EXPORTS=nsJSUtils.h @@ -67,6 +69,7 @@ CPP_OBJS= \ .\$(OBJDIR)\nsJSDOMException.obj \ .\$(OBJDIR)\nsJSEnvironment.obj \ .\$(OBJDIR)\nsJSWindow.obj \ + .\$(OBJDIR)\nsFocusController.obj \ .\$(OBJDIR)\nsGlobalWindow.obj \ .\$(OBJDIR)\nsJSNavigator.obj \ .\$(OBJDIR)\nsLocation.obj \ @@ -87,6 +90,7 @@ CPP_OBJS= \ .\$(OBJDIR)\nsJSCrypto.obj \ .\$(OBJDIR)\nsJSCRMFObject.obj \ .\$(OBJDIR)\nsJSPkcs11.obj \ + .\$(OBJDIR)\nsWindowRoot.obj \ $(NULL) LINCS=-I$(XPDIST)\public\xpcom -I$(XPDIST)\public\raptor \ diff --git a/dom/src/base/nsFocusController.cpp b/dom/src/base/nsFocusController.cpp new file mode 100644 index 00000000000..98195adeaf4 --- /dev/null +++ b/dom/src/base/nsFocusController.cpp @@ -0,0 +1,369 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is Netscape + * Communications, Inc. Portions created by Netscape are + * Copyright (C) 1999, Mozilla. All Rights Reserved. + * + * Contributor(s): + * David W. Hyatt (Original Author) + */ + +#include "nsIContent.h" +#include "nsIControllers.h" +#include "nsIDOMDocument.h" +#include "nsIDOMHTMLDocument.h" +#include "nsIDOMElement.h" +#include "nsIDOMNSHTMLInputElement.h" +#include "nsIDOMNSHTMLTextAreaElement.h" +#include "nsIDOMUIEvent.h" +#include "nsIDOMWindowInternal.h" +#include "nsIDocument.h" +#include "nsIPresContext.h" +#include "nsIPresShell.h" +#include "nsIScriptGlobalObject.h" +#include "nsPIDOMWindow.h" +#include "nsFocusController.h" +#include "prlog.h" +#include "nsIDOMEventTarget.h" + +#ifdef INCLUDE_XUL +#include "nsIDOMXULDocument.h" +#include "nsIDOMXULElement.h" +#endif + +//////////////////////////////////////////////////////////////////////// + +nsFocusController::nsFocusController(void) +: mSuppressFocus(0), + mSuppressFocusScroll(PR_FALSE), + mActive(PR_FALSE) +{ + NS_INIT_REFCNT(); +} + +nsFocusController::~nsFocusController(void) +{ +} + +NS_IMPL_ISUPPORTS3(nsFocusController, nsIFocusController, nsIDOMFocusListener, nsIDOMEventListener) + +NS_IMETHODIMP +nsFocusController::Create(nsIFocusController** aResult) +{ + nsFocusController* controller = new nsFocusController(); + if (!controller) + return NS_ERROR_OUT_OF_MEMORY; + + *aResult = controller; + NS_ADDREF(*aResult); + return NS_OK; +} + + +//////////////////////////////////////////////////////////////// +// nsIFocusController Interface + +NS_IMETHODIMP +nsFocusController::GetFocusedElement(nsIDOMElement** aElement) +{ + *aElement = mCurrentElement; + NS_IF_ADDREF(*aElement); + return NS_OK; +} + +NS_IMETHODIMP +nsFocusController::GetFocusedWindow(nsIDOMWindowInternal** aWindow) +{ + *aWindow = mCurrentWindow; + NS_IF_ADDREF(*aWindow); + return NS_OK; +} + +NS_IMETHODIMP +nsFocusController::SetFocusedElement(nsIDOMElement* aElement) +{ + mCurrentElement = aElement; + + // Need to update focus commands when focus switches from + // an element to no element, so don't test mCurrentElement + // before updating. + UpdateCommands(NS_LITERAL_STRING("focus")); + return NS_OK; +} + +NS_IMETHODIMP +nsFocusController::SetFocusedWindow(nsIDOMWindowInternal* aWindow) +{ + mCurrentWindow = aWindow; + return NS_OK; +} + + +NS_IMETHODIMP +nsFocusController::UpdateCommands(const nsAReadableString& aEventName) +{ + if (mCurrentWindow) { + mCurrentWindow->UpdateCommands(aEventName); + } + else if (mCurrentElement) { + nsCOMPtr domDoc; + mCurrentElement->GetOwnerDocument(getter_AddRefs(domDoc)); + nsCOMPtr doc(do_QueryInterface(domDoc)); + + nsCOMPtr global; + doc->GetScriptGlobalObject(getter_AddRefs(global)); + + nsCOMPtr window(do_QueryInterface(global)); + window->UpdateCommands(aEventName); + } + return NS_OK; +} + + +NS_IMETHODIMP +nsFocusController::GetControllers(nsIControllers** aResult) +{ + //XXX: we should fix this so there's a generic interface that describes controllers, + // so this code would have no special knowledge of what object might have controllers. + if (mCurrentElement) { + +#ifdef INCLUDE_XUL + nsCOMPtr xulElement(do_QueryInterface(mCurrentElement)); + if (xulElement) + return xulElement->GetControllers(aResult); +#endif + + nsCOMPtr htmlTextArea(do_QueryInterface(mCurrentElement)); + if (htmlTextArea) + return htmlTextArea->GetControllers(aResult); + + nsCOMPtr htmlInputElement(do_QueryInterface(mCurrentElement)); + if (htmlInputElement) + return htmlInputElement->GetControllers(aResult); + } + else if (mCurrentWindow) { + nsCOMPtr domWindow(do_QueryInterface(mCurrentWindow)); + if (domWindow) + return domWindow->GetControllers(aResult); + } + + *aResult = nsnull; + return NS_OK; +} + +///// +// nsIDOMFocusListener +///// + +nsresult +nsFocusController::Focus(nsIDOMEvent* aEvent) +{ + if (mSuppressFocus) + return NS_OK; + + nsCOMPtr t; + aEvent->GetOriginalTarget(getter_AddRefs(t)); + + nsCOMPtr domElement = do_QueryInterface(t); + if (domElement && (domElement != mCurrentElement)) { + SetFocusedElement(domElement); + + // Also set focus to our innermost window. + // XXX Must be done for the Ender case, since ender causes a blur, + // but we don't hear the subsequent focus to the Ender window. + nsCOMPtr ownerDoc; + domElement->GetOwnerDocument(getter_AddRefs(ownerDoc)); + nsCOMPtr domWindow; + GetParentWindowFromDocument(ownerDoc, getter_AddRefs(domWindow)); + if (domWindow) + SetFocusedWindow(domWindow); + } + else { + // We're focusing a window. We only want to do an update commands + // if no element is focused. + nsCOMPtr domWindow; + nsCOMPtr domDoc = do_QueryInterface(t); + if (domDoc) { + GetParentWindowFromDocument(domDoc, getter_AddRefs(domWindow)); + if (domWindow) { + SetFocusedWindow(domWindow); + if (mCurrentElement) { + // Make sure this element is in our window. If not, we + // should clear this field. + nsCOMPtr ownerDoc; + mCurrentElement->GetOwnerDocument(getter_AddRefs(ownerDoc)); + nsCOMPtr windowDoc; + mCurrentWindow->GetDocument(getter_AddRefs(windowDoc)); + if (ownerDoc != windowDoc) + mCurrentElement = nsnull; + } + + if (!mCurrentElement) + UpdateCommands(NS_LITERAL_STRING("focus")); + } + } + } + + return NS_OK; +} + +nsresult +nsFocusController::Blur(nsIDOMEvent* aEvent) +{ + if (mSuppressFocus) + return NS_OK; + + nsCOMPtr t; + aEvent->GetOriginalTarget(getter_AddRefs(t)); + + nsCOMPtr domElement = do_QueryInterface(t); + if (domElement) { + SetFocusedElement(nsnull); + } + + nsCOMPtr domWindow; + nsCOMPtr domDoc = do_QueryInterface(t); + if (domDoc) { + GetParentWindowFromDocument(domDoc, getter_AddRefs(domWindow)); + if (domWindow) + SetFocusedWindow(nsnull); + } + + return NS_OK; +} + +nsresult +nsFocusController::GetParentWindowFromDocument(nsIDOMDocument* aDocument, nsIDOMWindowInternal** aWindow) +{ + nsCOMPtr objectOwner = do_QueryInterface(aDocument); + if(!objectOwner) return NS_OK; + + nsCOMPtr globalObject; + objectOwner->GetScriptGlobalObject(getter_AddRefs(globalObject)); + if(!globalObject) return NS_OK; + + nsCOMPtr domWindow = do_QueryInterface(globalObject); + *aWindow = domWindow; + NS_IF_ADDREF(*aWindow); + return NS_OK; +} + +NS_IMETHODIMP +nsFocusController::GetControllerForCommand(const nsAReadableString& aCommand, nsIController** _retval) +{ + nsPromiseFlatString flatCommand(aCommand); + const PRUnichar *command = flatCommand.get(); + *_retval = nsnull; + + nsCOMPtr controllers; + GetControllers(getter_AddRefs(controllers)); + if(controllers) { + nsCOMPtr controller; + controllers->GetControllerForCommand(command, getter_AddRefs(controller)); + if(controller) { + *_retval = controller; + NS_ADDREF(*_retval); + return NS_OK; + } + } + + nsCOMPtr currentWindow; + if (mCurrentElement) { + // Move up to the window. + nsCOMPtr domDoc; + mCurrentElement->GetOwnerDocument(getter_AddRefs(domDoc)); + nsCOMPtr domWindow; + GetParentWindowFromDocument(domDoc, getter_AddRefs(domWindow)); + currentWindow = do_QueryInterface(domWindow); + } + else if (mCurrentWindow) { + nsCOMPtr privateWin = do_QueryInterface(mCurrentWindow); + privateWin->GetPrivateParent(getter_AddRefs(currentWindow)); + } + else return NS_OK; + + while(currentWindow) { + nsCOMPtr domWindow = do_QueryInterface(currentWindow); + if(domWindow) { + nsCOMPtr controllers2; + domWindow->GetControllers(getter_AddRefs(controllers2)); + if(controllers2) { + nsCOMPtr controller; + controllers2->GetControllerForCommand(command, getter_AddRefs(controller)); + if(controller) { + *_retval = controller; + NS_ADDREF(*_retval); + return NS_OK; + } + } + } + nsCOMPtr parentPWindow = currentWindow; + parentPWindow->GetPrivateParent(getter_AddRefs(currentWindow)); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsFocusController::GetSuppressFocusScroll(PRBool* aSuppressFocusScroll) +{ + *aSuppressFocusScroll = mSuppressFocusScroll; + return NS_OK; +} + +NS_IMETHODIMP +nsFocusController::SetSuppressFocusScroll(PRBool aSuppressFocusScroll) +{ + mSuppressFocusScroll = aSuppressFocusScroll; + return NS_OK; +} + +NS_IMETHODIMP +nsFocusController::GetSuppressFocus(PRBool* aSuppressFocus) +{ + *aSuppressFocus = (mSuppressFocus > 0); + return NS_OK; +} + +NS_IMETHODIMP +nsFocusController::SetSuppressFocus(PRBool aSuppressFocus) +{ + if(aSuppressFocus) + ++mSuppressFocus; + else if(mSuppressFocus > 0) + --mSuppressFocus; + + // we are unsuppressing after activating, so update focus-related commands + // we need this to update commands in the case where an element is focused. + if (!mSuppressFocus && mCurrentElement) + UpdateCommands(NS_LITERAL_STRING("focus")); + + return NS_OK; +} + +NS_IMETHODIMP +nsFocusController::GetActive(PRBool* aActive) +{ + *aActive = mActive; + return NS_OK; +} + +NS_IMETHODIMP +nsFocusController::SetActive(PRBool aActive) +{ + mActive = aActive; + return NS_OK; +} + diff --git a/dom/src/base/nsFocusController.h b/dom/src/base/nsFocusController.h new file mode 100644 index 00000000000..f431551f504 --- /dev/null +++ b/dom/src/base/nsFocusController.h @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is Netscape + * Communications, Inc. Portions created by Netscape are + * Copyright (C) 1999, Mozilla. All Rights Reserved. + * + * Contributor(s): + * David W. Hyatt (Original Author) + */ + +#ifndef nsFocusController_h__ +#define nsFocusController_h__ + +#include "nsCOMPtr.h" +#include "nsIFocusController.h" +#include "nsIDOMFocusListener.h" +#include "nsIDOMElement.h" +#include "nsIDOMWindow.h" + +class nsIDOMElement; +class nsIDOMWindow; +class nsIController; +class nsIControllers; + +class nsFocusController : public nsIFocusController, + public nsIDOMFocusListener +{ +public: + static NS_IMETHODIMP Create(nsIFocusController** aResult); + +protected: + nsFocusController(void); + virtual ~nsFocusController(void); + +public: + NS_DECL_ISUPPORTS + + NS_IMETHOD GetFocusedElement(nsIDOMElement** aResult); + NS_IMETHOD SetFocusedElement(nsIDOMElement* aElement); + + NS_IMETHOD GetFocusedWindow(nsIDOMWindowInternal** aResult); + NS_IMETHOD SetFocusedWindow(nsIDOMWindowInternal* aResult); + + NS_IMETHOD GetSuppressFocus(PRBool* aSuppressFlag); + NS_IMETHOD SetSuppressFocus(PRBool aSuppressFlag); + + NS_IMETHOD GetSuppressFocusScroll(PRBool* aSuppressFlag); + NS_IMETHOD SetSuppressFocusScroll(PRBool aSuppressFlag); + + NS_IMETHOD GetActive(PRBool* aActive); + NS_IMETHOD SetActive(PRBool aActive); + + NS_IMETHOD GetControllerForCommand(const nsAReadableString& aCommand, nsIController** aResult); + NS_IMETHOD GetControllers(nsIControllers** aResult); + + // nsIDOMFocusListener + virtual nsresult Focus(nsIDOMEvent* aEvent); + virtual nsresult Blur(nsIDOMEvent* aEvent); + + // nsIDOMEventListener + virtual nsresult HandleEvent(nsIDOMEvent* anEvent) { return NS_OK; }; + +protected: + NS_IMETHOD UpdateCommands(const nsAReadableString& aEventName); + +public: + static nsresult GetParentWindowFromDocument(nsIDOMDocument* aElement, nsIDOMWindowInternal** aWindow); + +// Members +protected: + nsCOMPtr mCurrentElement; // [OWNER] + nsCOMPtr mCurrentWindow; // [OWNER] + + PRUint32 mSuppressFocus; + PRBool mSuppressFocusScroll; + PRBool mActive; +}; + +#endif // nsFocusController_h__ diff --git a/dom/src/base/nsGlobalWindow.cpp b/dom/src/base/nsGlobalWindow.cpp index 1d9c431c2b3..cb2035d9971 100644 --- a/dom/src/base/nsGlobalWindow.cpp +++ b/dom/src/base/nsGlobalWindow.cpp @@ -102,6 +102,8 @@ #include "nsDOMCID.h" #include "nsDOMError.h" +#include "nsWindowRoot.h" + // XXX An unfortunate dependency exists here (two XUL files). #include "nsIDOMXULDocument.h" #include "nsIDOMXULCommandDispatcher.h" @@ -306,12 +308,12 @@ NS_IMETHODIMP GlobalWindowImpl::SetNewDocument(nsIDOMDocument* aDocument) // browser scrolling and other browser commands. nsCOMPtr internal; GetPrivateRoot(getter_AddRefs(internal)); - nsCOMPtr us(do_QueryInterface((nsIDOMWindow*)this)); + nsCOMPtr us(do_QueryInterface(NS_STATIC_CAST(nsIDOMWindow*,this))); if (internal == us) { nsresult rv; NS_WITH_SERVICE(nsIXBLService, xblService, "@mozilla.org/xbl;1", &rv); if (xblService) { - nsCOMPtr rec(do_QueryInterface(internal)); + nsCOMPtr rec(do_QueryInterface(mChromeEventHandler)); xblService->AttachGlobalKeyHandler(rec); } } @@ -434,10 +436,23 @@ NS_IMETHODIMP GlobalWindowImpl::SetDocShell(nsIDocShell* aDocShell) // Get our enclosing chrome shell and retrieve its global window impl, so // that we can do some forwarding to the chrome document. - nsCOMPtr chromeEventHandler; - mDocShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler)); - if (chromeEventHandler) - mChromeEventHandler = chromeEventHandler.get(); // ref + mDocShell->GetChromeEventHandler(getter_AddRefs(mChromeEventHandler)); + if (!mChromeEventHandler) { + // We have no chrome event handler. If we have a parent, + // get our chrome event handler from the parent. If + // we don't have a parent, then we need to make a new + // window root object that will function as a chrome event + // handler and receive all events that occur anywhere inside + // our window. + nsCOMPtr parentWindow; + GetParent(getter_AddRefs(parentWindow)); + if (parentWindow.get() != NS_STATIC_CAST(nsIDOMWindow*,this)) { + nsCOMPtr piWindow(do_QueryInterface(parentWindow)); + nsCOMPtr handler; + piWindow->GetChromeEventHandler(getter_AddRefs(mChromeEventHandler)); + } + else NS_NewWindowRoot(this, getter_AddRefs(mChromeEventHandler)); + } } return NS_OK; } @@ -2098,48 +2113,23 @@ NS_IMETHODIMP GlobalWindowImpl::Close(JSContext* cx, jsval* argv, PRUint32 argc) NS_IMETHODIMP GlobalWindowImpl::UpdateCommands(const nsAReadableString& anAction) { - if (mChromeEventHandler) { - // Just jump out to the chrome event handler. - nsCOMPtr content = do_QueryInterface(mChromeEventHandler); - if (content) { - // Cross the chrome/content boundary and get the nearest enclosing - // chrome window. - nsCOMPtr doc; - content->GetDocument(*getter_AddRefs(doc)); - nsCOMPtr global; - if (!doc) - return NS_ERROR_NULL_POINTER; - doc->GetScriptGlobalObject(getter_AddRefs(global)); - nsCOMPtr domWindow = do_QueryInterface(global); - return domWindow->UpdateCommands(anAction); - } - else { - // XXX Handle the embedding case. The chrome handler could be told - // to poke menu items/update commands etc. This can be used by - // embedders if we set it up right and lets them know all sorts of - // interesting things about Ender text fields. - } + nsCOMPtr rootWindow; + GetPrivateRoot(getter_AddRefs(rootWindow)); + if (!rootWindow) + return NS_OK; - } - else { + nsCOMPtr document; + rootWindow->GetDocument(getter_AddRefs(document)); + + if (document) { // See if we contain a XUL document. - nsCOMPtr xulDoc = do_QueryInterface(mDocument); + nsCOMPtr xulDoc = do_QueryInterface(document); if (xulDoc) { // Retrieve the command dispatcher and call updateCommands on it. nsCOMPtr xulCommandDispatcher; xulDoc->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher)); xulCommandDispatcher->UpdateCommands(anAction); } - - // Now call UpdateCommands on our parent window. - nsCOMPtr parent; - GetParent(getter_AddRefs(parent)); - // GetParent returns self at the top - if (NS_STATIC_CAST(nsIDOMWindow *, this) == parent.get()) - return NS_OK; - - nsCOMPtr parentInternal = do_QueryInterface(parent); - return parentInternal->UpdateCommands(anAction); } return NS_OK; @@ -2597,6 +2587,10 @@ NS_IMETHODIMP GlobalWindowImpl::GetPrivateRoot(nsIDOMWindowInternal ** aParent) if(parentTop == nsnull) return NS_ERROR_FAILURE; parentTop->GetDocShell(getter_AddRefs(docShell)); + + // Get the chrome event handler from the doc shell, since we only + // want to deal with XUL chrome handlers and not the new kind of + // window root handler. nsCOMPtr chromeEventHandler; docShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler)); @@ -2806,31 +2800,35 @@ NS_IMETHODIMP GlobalWindowImpl::Deactivate() } NS_IMETHODIMP -GlobalWindowImpl::GetRootCommandDispatcher(nsIDOMXULCommandDispatcher ** - aDispatcher) +GlobalWindowImpl::GetChromeEventHandler(nsIChromeEventHandler** aHandler) { - if (!aDispatcher) - return NS_ERROR_FAILURE; - - *aDispatcher = nsnull; - - nsCOMPtr commandDispatcher; - nsCOMPtr rootWindow; - - GetPrivateRoot(getter_AddRefs(rootWindow)); - if (rootWindow) { - nsCOMPtr rootDocument; - rootWindow->GetDocument(getter_AddRefs(rootDocument)); - - nsCOMPtr xulDoc = do_QueryInterface(rootDocument); - if (xulDoc) { - xulDoc->GetCommandDispatcher(aDispatcher); - } - } + *aHandler = mChromeEventHandler; + NS_IF_ADDREF(*aHandler); return NS_OK; } +NS_IMETHODIMP +GlobalWindowImpl::GetRootFocusController(nsIFocusController** aController) +{ + *aController = nsnull; + nsCOMPtr rootWindow; + GetPrivateRoot(getter_AddRefs(rootWindow)); + if (rootWindow) { + // Obtain the chrome event handler. + nsCOMPtr chromeHandler; + nsCOMPtr piWin(do_QueryInterface(rootWindow)); + piWin->GetChromeEventHandler(getter_AddRefs(chromeHandler)); + if (chromeHandler) { + nsCOMPtr windowRoot(do_QueryInterface(chromeHandler)); + if (windowRoot) { + windowRoot->GetFocusController(getter_AddRefs(aController)); + } + } + } + + return NS_OK; +} NS_IMETHODIMP GlobalWindowImpl::SetPositionAndSize(PRInt32 x, PRInt32 y, PRInt32 cx, diff --git a/dom/src/base/nsGlobalWindow.h b/dom/src/base/nsGlobalWindow.h index 8361db6b91d..8dc25856b95 100644 --- a/dom/src/base/nsGlobalWindow.h +++ b/dom/src/base/nsGlobalWindow.h @@ -159,7 +159,9 @@ public: NS_IMETHOD Activate(); NS_IMETHOD Deactivate(); - NS_IMETHOD GetRootCommandDispatcher(nsIDOMXULCommandDispatcher ** aDispatcher); + NS_IMETHOD GetChromeEventHandler(nsIChromeEventHandler** aHandler); + + NS_IMETHOD GetRootFocusController(nsIFocusController** aResult); NS_IMETHOD SetPositionAndSize(PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy, PRBool fRepaint); @@ -252,7 +254,7 @@ protected: nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // Weak Reference nsIDocShell* mDocShell; // Weak Reference - nsIChromeEventHandler* mChromeEventHandler; // Weak Reference + nsCOMPtr mChromeEventHandler; // [Strong] We break it when we get torn down. nsCOMPtr mCrypto; nsCOMPtr mPkcs11; nsCOMPtr mDocumentPrincipal; diff --git a/dom/src/base/nsWindowRoot.cpp b/dom/src/base/nsWindowRoot.cpp new file mode 100644 index 00000000000..a09f1530563 --- /dev/null +++ b/dom/src/base/nsWindowRoot.cpp @@ -0,0 +1,229 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is Netscape + * Communications, Inc. Portions created by Netscape are + * Copyright (C) 1999, Mozilla. All Rights Reserved. + * + * Contributor(s): + * David W. Hyatt (Original Author) + */ + +#include "nsCOMPtr.h" +#include "nsWindowRoot.h" +#include "nsIDOMWindow.h" +#include "nsIDOMDocument.h" +#include "nsIDocument.h" +#include "nsIEventListenerManager.h" +#include "nsIPresShell.h" +#include "nsIPresContext.h" +#include "nsLayoutCID.h" +#include "nsIEventStateManager.h" +#include "nsIPrivateDOMEvent.h" +#include "nsIDOMWindowInternal.h" +#include "nsFocusController.h" + +static NS_DEFINE_CID(kEventListenerManagerCID, NS_EVENTLISTENERMANAGER_CID); + +nsWindowRoot::nsWindowRoot(nsIDOMWindow* aWindow) +{ + NS_INIT_ISUPPORTS(); + mWindow = aWindow; + + // Create and init our focus controller. + nsFocusController::Create(getter_AddRefs(mFocusController)); + + nsCOMPtr focusListener(do_QueryInterface(mFocusController)); + AddEventListener(NS_LITERAL_STRING("focus"), focusListener, PR_TRUE); + AddEventListener(NS_LITERAL_STRING("blur"), focusListener, PR_TRUE); +} + +nsWindowRoot::~nsWindowRoot() +{ +} + +NS_IMPL_ISUPPORTS3(nsWindowRoot, nsIDOMEventReceiver, nsIChromeEventHandler, nsPIWindowRoot) + +NS_IMETHODIMP +nsWindowRoot::AddEventListener(const nsAReadableString& aType, nsIDOMEventListener* aListener, PRBool aUseCapture) +{ + nsCOMPtr manager; + GetListenerManager(getter_AddRefs(manager)); + if (manager) { + PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE; + manager->AddEventListenerByType(aListener, aType, flags); + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWindowRoot::RemoveEventListener(const nsAReadableString& aType, nsIDOMEventListener* aListener, PRBool aUseCapture) +{ + nsCOMPtr manager; + GetListenerManager(getter_AddRefs(manager)); + if (manager) { + PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE; + manager->RemoveEventListenerByType(aListener, aType, flags); + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWindowRoot::DispatchEvent(nsIDOMEvent* aEvt) +{ + // Obtain a presentation context + nsCOMPtr domDoc; + mWindow->GetDocument(getter_AddRefs(domDoc)); + if (!domDoc) + return NS_OK; + nsCOMPtr doc(do_QueryInterface(domDoc)); + + PRInt32 count = doc->GetNumberOfShells(); + if (count == 0) + return NS_OK; + + nsCOMPtr shell = getter_AddRefs(doc->GetShellAt(0)); + + // Retrieve the context + nsCOMPtr aPresContext; + shell->GetPresContext(getter_AddRefs(aPresContext)); + + nsCOMPtr esm; + if (NS_SUCCEEDED(aPresContext->GetEventStateManager(getter_AddRefs(esm)))) { + return esm->DispatchNewEvent(NS_STATIC_CAST(nsIDOMEventReceiver*,this), aEvt); + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWindowRoot::AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID) +{ + nsCOMPtr manager; + GetListenerManager(getter_AddRefs(manager)); + if (manager) { + manager->AddEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE); + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWindowRoot::RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID) +{ + nsCOMPtr manager; + GetListenerManager(getter_AddRefs(manager)); + if (manager) { + manager->AddEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE); + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsWindowRoot::GetListenerManager(nsIEventListenerManager** aResult) +{ + if (!mListenerManager) { + nsresult rv; + mListenerManager = do_CreateInstance(kEventListenerManagerCID, &rv); + if (NS_FAILED(rv)) return rv; + } + + *aResult = mListenerManager; + NS_ADDREF(*aResult); + return NS_OK; +} + +NS_IMETHODIMP +nsWindowRoot::GetNewListenerManager(nsIEventListenerManager **aResult) +{ + return nsComponentManager::CreateInstance(kEventListenerManagerCID, + nsnull, + NS_GET_IID(nsIEventListenerManager), + (void**) aResult); +} + +NS_IMETHODIMP +nsWindowRoot::HandleEvent(nsIDOMEvent *aEvent) +{ + return DispatchEvent(aEvent); +} + +NS_IMETHODIMP nsWindowRoot::HandleChromeEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, nsIDOMEvent** aDOMEvent, PRUint32 aFlags, + nsEventStatus* aEventStatus) +{ + // Prevent the world from going + // away until after we've finished handling the event. + nsCOMPtr kungFuDeathGrip(mWindow); + + nsresult ret = NS_OK; + nsIDOMEvent* domEvent = nsnull; + + // We're at the top, so there's no bubbling or capturing here. + if (NS_EVENT_FLAG_INIT & aFlags) { + aDOMEvent = &domEvent; + aEvent->flags = aFlags; + aFlags &= ~(NS_EVENT_FLAG_CANT_BUBBLE | NS_EVENT_FLAG_CANT_CANCEL); + } + + //Local handling stage + if (mListenerManager && !(aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH)) { + aEvent->flags |= aFlags; + mListenerManager->HandleEvent(aPresContext, aEvent, aDOMEvent, this, aFlags, aEventStatus); + aEvent->flags &= ~aFlags; + } + + if (NS_EVENT_FLAG_INIT & aFlags) { + // We're leaving the DOM event loop so if we created a DOM event, release here. + if (nsnull != *aDOMEvent) { + nsrefcnt rc; + NS_RELEASE2(*aDOMEvent, rc); + if (0 != rc) { + //Okay, so someone in the DOM loop (a listener, JS object) still has a ref to the DOM Event but + //the internal data hasn't been malloc'd. Force a copy of the data here so the DOM Event is still valid. + nsIPrivateDOMEvent *privateEvent; + if (NS_OK == (*aDOMEvent)->QueryInterface(NS_GET_IID(nsIPrivateDOMEvent), (void**)&privateEvent)) { + privateEvent->DuplicatePrivateData(); + NS_RELEASE(privateEvent); + } + } + } + aDOMEvent = nsnull; + } + + return ret; +} + +NS_IMETHODIMP +nsWindowRoot::GetFocusController(nsIFocusController** aResult) +{ + *aResult = mFocusController; + NS_IF_ADDREF(*aResult); + return NS_OK; +} + +/////////////////////////////////////////////////////////////////////////////////// + +nsresult +NS_NewWindowRoot(nsIDOMWindow* aWindow, nsIChromeEventHandler** aResult) +{ + *aResult = new nsWindowRoot(aWindow); + if (!*aResult) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(*aResult); + return NS_OK; +} diff --git a/dom/src/base/nsWindowRoot.h b/dom/src/base/nsWindowRoot.h new file mode 100644 index 00000000000..874a4b12692 --- /dev/null +++ b/dom/src/base/nsWindowRoot.h @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is Netscape + * Communications, Inc. Portions created by Netscape are + * Copyright (C) 1999, Mozilla. All Rights Reserved. + * + * Contributor(s): + * David W. Hyatt (Original Author) + */ + +#ifndef nsWindowRoot_h__ +#define nsWindowRoot_h__ + +class nsIDOMWindow; +class nsIDOMEventListener; +class nsIEventListenerManager; +class nsIDOMEvent; + +#include "nsGUIEvent.h" +#include "nsIDOMEventReceiver.h" +#include "nsIChromeEventHandler.h" +#include "nsIEventListenerManager.h" +#include "nsPIWindowRoot.h" +#include "nsIFocusController.h" + +class nsWindowRoot : public nsIDOMEventReceiver, public nsIChromeEventHandler, public nsPIWindowRoot +{ +public: + nsWindowRoot(nsIDOMWindow* aWindow); + virtual ~nsWindowRoot(); + + NS_DECL_ISUPPORTS + NS_DECL_IDOMEVENTTARGET + + NS_IMETHOD HandleChromeEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, nsIDOMEvent** aDOMEvent, PRUint32 aFlags, + nsEventStatus* aEventStatus); + + NS_IMETHOD AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID); + NS_IMETHOD RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID); + NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult); + NS_IMETHOD GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult); + NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent); + + // nsPIWindowRoot + NS_IMETHOD GetFocusController(nsIFocusController** aResult); + +protected: + // Members + nsIDOMWindow* mWindow; // [Weak]. The window will hold on to us and let go when it dies. + nsCOMPtr mListenerManager; // [Strong]. We own the manager, which owns event listeners attached + // to us. + nsCOMPtr mFocusController; // The focus controller for the root. +}; + +extern nsresult +NS_NewWindowRoot(nsIDOMWindow* aWindow, + nsIChromeEventHandler** aResult); + +#endif diff --git a/dom/src/xul/nsJSXULCommandDispatcher.cpp b/dom/src/xul/nsJSXULCommandDispatcher.cpp index 529c38462b1..ae3868698fa 100644 --- a/dom/src/xul/nsJSXULCommandDispatcher.cpp +++ b/dom/src/xul/nsJSXULCommandDispatcher.cpp @@ -55,10 +55,7 @@ static NS_DEFINE_IID(kIControllersIID, NS_ICONTROLLERS_IID); // enum XULCommandDispatcher_slots { XULCOMMANDDISPATCHER_FOCUSEDELEMENT = -1, - XULCOMMANDDISPATCHER_FOCUSEDWINDOW = -2, - XULCOMMANDDISPATCHER_SUPPRESSFOCUS = -3, - XULCOMMANDDISPATCHER_SUPPRESSFOCUSSCROLL = -4, - XULCOMMANDDISPATCHER_ACTIVE = -5 + XULCOMMANDDISPATCHER_FOCUSEDWINDOW = -2 }; /***********************************************************************/ @@ -107,42 +104,6 @@ GetXULCommandDispatcherProperty(JSContext *cx, JSObject *obj, jsval id, jsval *v } break; } - case XULCOMMANDDISPATCHER_SUPPRESSFOCUS: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_SUPPRESSFOCUS, PR_FALSE); - if (NS_SUCCEEDED(rv)) { - PRBool prop; - rv = a->GetSuppressFocus(&prop); - if (NS_SUCCEEDED(rv)) { - *vp = BOOLEAN_TO_JSVAL(prop); - } - } - break; - } - case XULCOMMANDDISPATCHER_SUPPRESSFOCUSSCROLL: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_SUPPRESSFOCUSSCROLL, PR_FALSE); - if (NS_SUCCEEDED(rv)) { - PRBool prop; - rv = a->GetSuppressFocusScroll(&prop); - if (NS_SUCCEEDED(rv)) { - *vp = BOOLEAN_TO_JSVAL(prop); - } - } - break; - } - case XULCOMMANDDISPATCHER_ACTIVE: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_ACTIVE, PR_FALSE); - if (NS_SUCCEEDED(rv)) { - PRBool prop; - rv = a->GetActive(&prop); - if (NS_SUCCEEDED(rv)) { - *vp = BOOLEAN_TO_JSVAL(prop); - } - } - break; - } default: return nsJSUtils::nsCallJSScriptObjectGetProperty(a, cx, obj, id, vp); } @@ -210,51 +171,6 @@ SetXULCommandDispatcherProperty(JSContext *cx, JSObject *obj, jsval id, jsval *v } break; } - case XULCOMMANDDISPATCHER_SUPPRESSFOCUS: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_SUPPRESSFOCUS, PR_TRUE); - if (NS_SUCCEEDED(rv)) { - PRBool prop; - if (PR_FALSE == nsJSUtils::nsConvertJSValToBool(&prop, cx, *vp)) { - rv = NS_ERROR_DOM_NOT_BOOLEAN_ERR; - break; - } - - rv = a->SetSuppressFocus(prop); - - } - break; - } - case XULCOMMANDDISPATCHER_SUPPRESSFOCUSSCROLL: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_SUPPRESSFOCUSSCROLL, PR_TRUE); - if (NS_SUCCEEDED(rv)) { - PRBool prop; - if (PR_FALSE == nsJSUtils::nsConvertJSValToBool(&prop, cx, *vp)) { - rv = NS_ERROR_DOM_NOT_BOOLEAN_ERR; - break; - } - - rv = a->SetSuppressFocusScroll(prop); - - } - break; - } - case XULCOMMANDDISPATCHER_ACTIVE: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_ACTIVE, PR_TRUE); - if (NS_SUCCEEDED(rv)) { - PRBool prop; - if (PR_FALSE == nsJSUtils::nsConvertJSValToBool(&prop, cx, *vp)) { - rv = NS_ERROR_DOM_NOT_BOOLEAN_ERR; - break; - } - - rv = a->SetActive(prop); - - } - break; - } default: return nsJSUtils::nsCallJSScriptObjectSetProperty(a, cx, obj, id, vp); } @@ -276,9 +192,6 @@ static JSPropertySpec XULCommandDispatcherProperties[] = { {"focusedElement", XULCOMMANDDISPATCHER_FOCUSEDELEMENT, JSPROP_ENUMERATE}, {"focusedWindow", XULCOMMANDDISPATCHER_FOCUSEDWINDOW, JSPROP_ENUMERATE}, - {"suppressFocus", XULCOMMANDDISPATCHER_SUPPRESSFOCUS, JSPROP_ENUMERATE}, - {"suppressFocusScroll", XULCOMMANDDISPATCHER_SUPPRESSFOCUSSCROLL, JSPROP_ENUMERATE}, - {"active", XULCOMMANDDISPATCHER_ACTIVE, JSPROP_ENUMERATE}, {0} }; diff --git a/editor/base/nsEditorShell.cpp b/editor/base/nsEditorShell.cpp index 795ed91175d..236729ddc98 100644 --- a/editor/base/nsEditorShell.cpp +++ b/editor/base/nsEditorShell.cpp @@ -30,6 +30,7 @@ #include "prprf.h" #include "nsIComponentManager.h" +#include "nsIFocusController.h" #include "nsIScriptContext.h" #include "nsIScriptGlobalObject.h" #include "nsIScriptGlobalObjectOwner.h" @@ -635,13 +636,13 @@ nsEditorShell::PrepareDocumentForEditing(nsIDocumentLoader* aLoader, nsIURI *aUr if (privContent) { - nsCOMPtr commandDispatcher; - privContent->GetRootCommandDispatcher(getter_AddRefs(commandDispatcher)); + nsCOMPtr focusController; + privContent->GetRootFocusController(getter_AddRefs(focusController)); - if (commandDispatcher) + if (focusController) { nsCOMPtr focussedWindow; - commandDispatcher->GetFocusedWindow(getter_AddRefs(focussedWindow)); + focusController->GetFocusedWindow(getter_AddRefs(focussedWindow)); if (focussedWindow.get() == contentInternal.get()) // now see if we are focussed { diff --git a/editor/composer/src/nsEditorShell.cpp b/editor/composer/src/nsEditorShell.cpp index 795ed91175d..236729ddc98 100644 --- a/editor/composer/src/nsEditorShell.cpp +++ b/editor/composer/src/nsEditorShell.cpp @@ -30,6 +30,7 @@ #include "prprf.h" #include "nsIComponentManager.h" +#include "nsIFocusController.h" #include "nsIScriptContext.h" #include "nsIScriptGlobalObject.h" #include "nsIScriptGlobalObjectOwner.h" @@ -635,13 +636,13 @@ nsEditorShell::PrepareDocumentForEditing(nsIDocumentLoader* aLoader, nsIURI *aUr if (privContent) { - nsCOMPtr commandDispatcher; - privContent->GetRootCommandDispatcher(getter_AddRefs(commandDispatcher)); + nsCOMPtr focusController; + privContent->GetRootFocusController(getter_AddRefs(focusController)); - if (commandDispatcher) + if (focusController) { nsCOMPtr focussedWindow; - commandDispatcher->GetFocusedWindow(getter_AddRefs(focussedWindow)); + focusController->GetFocusedWindow(getter_AddRefs(focussedWindow)); if (focussedWindow.get() == contentInternal.get()) // now see if we are focussed { diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 8eb81e7f8db..4caf569e4a5 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -111,10 +111,7 @@ #include "nsIScriptGlobalObject.h" #include "nsIDOMWindowInternal.h" #include "nsPIDOMWindow.h" -#ifdef INCLUDE_XUL -#include "nsIDOMXULDocument.h" -#include "nsIDOMXULCommandDispatcher.h" -#endif // INCLUDE_XUL +#include "nsIFocusController.h" // Drag & Drop, Clipboard #include "nsWidgetsCID.h" @@ -2111,68 +2108,52 @@ PresShell::EndObservingDocument() char* nsPresShell_ReflowStackPointerTop; #endif -#ifdef INCLUDE_XUL static void CheckForFocus(nsIDocument* aDocument) { // Now that we have a root frame, set focus in to the presshell, but // only do this if our window is currently focused // Restore focus if we're the active window or a parent of a previously // active window. - // XXX The XUL dependency will go away when the focus tracking portion - // of the command dispatcher moves into the embedding layer. nsCOMPtr globalObject; aDocument->GetScriptGlobalObject(getter_AddRefs(globalObject)); - nsCOMPtr rootWindow; nsCOMPtr ourWindow = do_QueryInterface(globalObject); - ourWindow->GetPrivateRoot(getter_AddRefs(rootWindow)); - NS_ASSERTION(rootWindow , "cannot get rootWindow"); - if(nsnull == rootWindow) - return; - nsCOMPtr rootDocument; - rootWindow->GetDocument(getter_AddRefs(rootDocument)); + nsCOMPtr focusController; + ourWindow->GetRootFocusController(getter_AddRefs(focusController)); - nsCOMPtr commandDispatcher; - nsCOMPtr xulDoc = do_QueryInterface(rootDocument); - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - // Suppress the command dispatcher. - commandDispatcher->SetSuppressFocus(PR_TRUE); - nsCOMPtr focusedWindow; - commandDispatcher->GetFocusedWindow(getter_AddRefs(focusedWindow)); - - // See if the command dispatcher is holding on to an orphan window. - // This happens when you move from an inner frame to an outer frame - // (e.g., _parent, _top) - if (focusedWindow) { - nsCOMPtr domDoc; - focusedWindow->GetDocument(getter_AddRefs(domDoc)); - if (!domDoc) { - // We're pointing to garbage. Go ahead and let this - // presshell take the focus. - focusedWindow = do_QueryInterface(ourWindow); - commandDispatcher->SetFocusedWindow(focusedWindow); - } + if (focusController) { + // Suppress the command dispatcher. + focusController->SetSuppressFocus(PR_TRUE); + nsCOMPtr focusedWindow; + focusController->GetFocusedWindow(getter_AddRefs(focusedWindow)); + + // See if the command dispatcher is holding on to an orphan window. + // This happens when you move from an inner frame to an outer frame + // (e.g., _parent, _top) + if (focusedWindow) { + nsCOMPtr domDoc; + focusedWindow->GetDocument(getter_AddRefs(domDoc)); + if (!domDoc) { + // We're pointing to garbage. Go ahead and let this + // presshell take the focus. + focusedWindow = do_QueryInterface(ourWindow); + focusController->SetFocusedWindow(focusedWindow); } - - nsCOMPtr domWindow = do_QueryInterface(ourWindow); - if (domWindow == focusedWindow) { - PRBool active; - commandDispatcher->GetActive(&active); - commandDispatcher->SetFocusedElement(nsnull); - if(active) { - // We need to restore focus and make sure we null - // out the focused element. - domWindow->Focus(); - } - } - commandDispatcher->SetSuppressFocus(PR_FALSE); } + + nsCOMPtr domWindow = do_QueryInterface(ourWindow); + if (domWindow == focusedWindow) { + PRBool active; + focusController->GetActive(&active); + focusController->SetFocusedElement(nsnull); + if(active) { + // We need to restore focus and make sure we null + // out the focused element. + domWindow->Focus(); + } + } + focusController->SetSuppressFocus(PR_FALSE); } } -#endif - nsresult PresShell::NotifyReflowObservers(const char *aData) @@ -2294,9 +2275,7 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight) mFrameManager->SetRootFrame(rootFrame); } -#ifdef INCLUDE_XUL CheckForFocus(mDocument); -#endif // Have the style sheet processor construct frame for the root // content object down @@ -2516,8 +2495,7 @@ NS_IMETHODIMP PresShell::ScrollFrameIntoView(nsIFrame *aFrame){ if (!aFrame) return NS_ERROR_NULL_POINTER; - -#ifdef INCLUDE_XUL + // Before we scroll the frame into view, ask the command dispatcher // if we're resetting focus because a window just got an activate // event. If we are, we do not want to scroll the frame into view. @@ -2525,40 +2503,28 @@ PresShell::ScrollFrameIntoView(nsIFrame *aFrame){ // window. When they reactivate the window, the expected behavior // is not for the anchor link to scroll back into view. That is what // this check is preventing. - // XXX: The dependency on the command dispatcher needs to be fixed. nsCOMPtr content; aFrame->GetContent(getter_AddRefs(content)); if(content) { nsCOMPtr document; content->GetDocument(*getter_AddRefs(document)); if(document){ - nsCOMPtr commandDispatcher; - nsCOMPtr ourGlobal; - document->GetScriptGlobalObject(getter_AddRefs(ourGlobal)); - nsCOMPtr rootWindow; + nsCOMPtr focusController; + nsCOMPtr ourGlobal; + document->GetScriptGlobalObject(getter_AddRefs(ourGlobal)); nsCOMPtr ourWindow = do_QueryInterface(ourGlobal); if(ourWindow) { - ourWindow->GetPrivateRoot(getter_AddRefs(rootWindow)); - if(rootWindow) { - nsCOMPtr rootDocument; - rootWindow->GetDocument(getter_AddRefs(rootDocument)); - - nsCOMPtr xulDoc = do_QueryInterface(rootDocument); - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - PRBool dontScroll; - commandDispatcher->GetSuppressFocusScroll(&dontScroll); - if(dontScroll) - return NS_OK; - } - } - } - } + ourWindow->GetRootFocusController(getter_AddRefs(focusController)); + if (focusController) { + PRBool dontScroll; + focusController->GetSuppressFocusScroll(&dontScroll); + if(dontScroll) + return NS_OK; + } + } } } -#endif + if (IsScrollingEnabled()) return ScrollFrameIntoView(aFrame, NS_PRESSHELL_SCROLL_ANYWHERE, NS_PRESSHELL_SCROLL_ANYWHERE); @@ -3406,7 +3372,7 @@ PresShell::ScrollFrameIntoView(nsIFrame *aFrame, if (!aFrame) { return NS_ERROR_NULL_POINTER; } -#ifdef INCLUDE_XUL + // Before we scroll the frame into view, ask the command dispatcher // if we're resetting focus because a window just got an activate // event. If we are, we do not want to scroll the frame into view. @@ -3421,33 +3387,22 @@ PresShell::ScrollFrameIntoView(nsIFrame *aFrame, nsCOMPtr document; content->GetDocument(*getter_AddRefs(document)); if(document){ - nsCOMPtr commandDispatcher; - nsCOMPtr ourGlobal; - document->GetScriptGlobalObject(getter_AddRefs(ourGlobal)); - nsCOMPtr rootWindow; + nsCOMPtr focusController; + nsCOMPtr ourGlobal; + document->GetScriptGlobalObject(getter_AddRefs(ourGlobal)); nsCOMPtr ourWindow = do_QueryInterface(ourGlobal); if(ourWindow) { - ourWindow->GetPrivateRoot(getter_AddRefs(rootWindow)); - if(rootWindow) { - nsCOMPtr rootDocument; - rootWindow->GetDocument(getter_AddRefs(rootDocument)); - - nsCOMPtr xulDoc = do_QueryInterface(rootDocument); - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - PRBool dontScroll; - commandDispatcher->GetSuppressFocusScroll(&dontScroll); - if(dontScroll) - return NS_OK; - } - } - } - } + ourWindow->GetRootFocusController(getter_AddRefs(focusController)); + if (focusController) { + PRBool dontScroll; + focusController->GetSuppressFocusScroll(&dontScroll); + if(dontScroll) + return NS_OK; + } + } } } -#endif + if (mViewManager) { // Get the viewport scroller nsIScrollableView* scrollingView; diff --git a/layout/events/src/nsEventStateManager.cpp b/layout/events/src/nsEventStateManager.cpp index 9a65b1b3728..ca164786f4c 100644 --- a/layout/events/src/nsEventStateManager.cpp +++ b/layout/events/src/nsEventStateManager.cpp @@ -62,9 +62,11 @@ #include "nsIServiceManager.h" #include "nsIPref.h" +#include "nsIChromeEventHandler.h" +#include "nsIFocusController.h" + #include "nsXULAtoms.h" #include "nsIDOMXULDocument.h" -#include "nsIDOMXULCommandDispatcher.h" #include "nsIObserverService.h" #include "nsIDocShell.h" #include "nsIMarkupDocumentViewer.h" @@ -333,16 +335,16 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, blurevent.message = NS_BLUR_CONTENT; if(gLastFocusedPresContext) { - nsCOMPtr commandDispatcher; + nsCOMPtr focusController; nsCOMPtr ourGlobal; gLastFocusedDocument->GetScriptGlobalObject(getter_AddRefs(ourGlobal)); nsCOMPtr rootWindow; nsCOMPtr ourWindow = do_QueryInterface(ourGlobal); if(ourWindow) { - ourWindow->GetRootCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) - commandDispatcher->SetSuppressFocus(PR_TRUE); + ourWindow->GetRootFocusController(getter_AddRefs(focusController)); + if (focusController) + focusController->SetSuppressFocus(PR_TRUE); } gLastFocusedDocument->HandleDOMEvent(gLastFocusedPresContext, &blurevent, nsnull, NS_EVENT_FLAG_INIT, &blurstatus); @@ -350,8 +352,8 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, gLastFocusedContent->HandleDOMEvent(gLastFocusedPresContext, &blurevent, nsnull, NS_EVENT_FLAG_INIT, &blurstatus); - if (commandDispatcher) { - commandDispatcher->SetSuppressFocus(PR_FALSE); + if (focusController) { + focusController->SetSuppressFocus(PR_FALSE); } } } @@ -399,56 +401,30 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, // objects. EnsureDocument(aPresContext); - nsCOMPtr commandDispatcher; + nsCOMPtr focusController; nsCOMPtr focusedElement; nsCOMPtr focusedWindow; nsCOMPtr xulDoc = do_QueryInterface(mDocument); - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - // Obtain focus info from the command dispatcher. - commandDispatcher->GetFocusedWindow(getter_AddRefs(focusedWindow)); - commandDispatcher->GetFocusedElement(getter_AddRefs(focusedElement)); - - commandDispatcher->SetSuppressFocusScroll(PR_TRUE); - } + nsCOMPtr globalObj; + mDocument->GetScriptGlobalObject(getter_AddRefs(globalObj)); + nsCOMPtr win(do_QueryInterface(globalObj)); + win->GetRootFocusController(getter_AddRefs(focusController)); + + if (focusController) { + // Obtain focus info from the command dispatcher. + focusController->GetFocusedWindow(getter_AddRefs(focusedWindow)); + focusController->GetFocusedElement(getter_AddRefs(focusedElement)); + + focusController->SetSuppressFocusScroll(PR_TRUE); } if (!focusedWindow) { - nsCOMPtr globalObject; - mDocument->GetScriptGlobalObject(getter_AddRefs(globalObject)); - focusedWindow = do_QueryInterface(globalObject); + nsCOMPtr globalObject; + mDocument->GetScriptGlobalObject(getter_AddRefs(globalObject)); + focusedWindow = do_QueryInterface(globalObject); } - // Sill no focused XULDocument, that is bad - if(!xulDoc && focusedWindow) - { - nsCOMPtr privateWindow = do_QueryInterface(focusedWindow); - if(privateWindow){ - nsCOMPtr privateRootWindow; - privateWindow->GetPrivateRoot(getter_AddRefs(privateRootWindow)); - if(privateRootWindow) { - nsCOMPtr privateParentDoc; - privateRootWindow->GetDocument(getter_AddRefs(privateParentDoc)); - xulDoc = do_QueryInterface(privateParentDoc); - } - } - - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - // Obtain focus info from the command dispatcher. - commandDispatcher->GetFocusedWindow(getter_AddRefs(focusedWindow)); - commandDispatcher->GetFocusedElement(getter_AddRefs(focusedElement)); - - commandDispatcher->SetSuppressFocusScroll(PR_TRUE); - } - } - } - // Focus the DOM window. NS_WARN_IF_FALSE(focusedWindow,"check why focusedWindow is null!!!"); if(focusedWindow) { @@ -470,16 +446,16 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, } } - if (commandDispatcher) { - commandDispatcher->SetActive(PR_TRUE); + if (focusController) { + focusController->SetActive(PR_TRUE); PRBool isSuppressed; - commandDispatcher->GetSuppressFocus(&isSuppressed); + focusController->GetSuppressFocus(&isSuppressed); while(isSuppressed){ - commandDispatcher->SetSuppressFocus(PR_FALSE); // Unsuppress and let the command dispatcher listen again. - commandDispatcher->GetSuppressFocus(&isSuppressed); + focusController->SetSuppressFocus(PR_FALSE); // Unsuppress and let the command dispatcher listen again. + focusController->GetSuppressFocus(&isSuppressed); } - commandDispatcher->SetSuppressFocusScroll(PR_FALSE); + focusController->SetSuppressFocusScroll(PR_FALSE); } } break; @@ -508,24 +484,14 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, // de-activation. This will cause it to remember the last // focused sub-window and sub-element for this top-level // window. - nsCOMPtr commandDispatcher; + nsCOMPtr focusController; nsCOMPtr rootWindow; nsCOMPtr ourWindow = do_QueryInterface(ourGlobal); if(ourWindow) { - ourWindow->GetPrivateRoot(getter_AddRefs(rootWindow)); - if(rootWindow) { - nsCOMPtr rootDocument; - rootWindow->GetDocument(getter_AddRefs(rootDocument)); - - nsCOMPtr xulDoc = do_QueryInterface(rootDocument); - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - // Suppress the command dispatcher. - commandDispatcher->SetSuppressFocus(PR_TRUE); - } - } + ourWindow->GetRootFocusController(getter_AddRefs(focusController)); + if (focusController) { + // Suppress the command dispatcher. + focusController->SetSuppressFocus(PR_TRUE); } } @@ -577,9 +543,9 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, gLastFocusedPresContext = nsnull; } - if (commandDispatcher) { - commandDispatcher->SetActive(PR_FALSE); - //commandDispatcher->SetSuppressFocus(PR_FALSE); + if (focusController) { + focusController->SetActive(PR_FALSE); + //focusController->SetSuppressFocus(PR_FALSE); } } @@ -955,7 +921,6 @@ nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext, PRInt32 action = 0; PRInt32 numLines = 0; PRBool aBool; - if (msEvent->isShift) { mPrefService->GetIntPref("mousewheel.withshiftkey.action", &action); mPrefService->GetBoolPref("mousewheel.withshiftkey.sysnumlines", @@ -2687,8 +2652,8 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo // Make sure we're not switching command dispatchers, if so, surpress the blurred one if(gLastFocusedDocument && mDocument) { - nsCOMPtr newCommandDispatcher; - nsCOMPtr oldCommandDispatcher; + nsCOMPtr newFocusController; + nsCOMPtr oldFocusController; nsCOMPtr oldPIDOMWindow; nsCOMPtr newPIDOMWindow; nsCOMPtr oldGlobal; @@ -2698,11 +2663,11 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo nsCOMPtr newWindow = do_QueryInterface(newGlobal); nsCOMPtr oldWindow = do_QueryInterface(oldGlobal); if(newWindow) - newWindow->GetRootCommandDispatcher(getter_AddRefs(newCommandDispatcher)); + newWindow->GetRootFocusController(getter_AddRefs(newFocusController)); if(oldWindow) - oldWindow->GetRootCommandDispatcher(getter_AddRefs(oldCommandDispatcher)); - if(oldCommandDispatcher && oldCommandDispatcher != newCommandDispatcher) - oldCommandDispatcher->SetSuppressFocus(PR_TRUE); + oldWindow->GetRootFocusController(getter_AddRefs(oldFocusController)); + if(oldFocusController && oldFocusController != newFocusController) + oldFocusController->SetSuppressFocus(PR_TRUE); } nsCOMPtr esm; @@ -2737,8 +2702,8 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo // Make sure we're not switching command dispatchers, if so, surpress the blurred one if(mDocument) { - nsCOMPtr newCommandDispatcher; - nsCOMPtr oldCommandDispatcher; + nsCOMPtr newFocusController; + nsCOMPtr oldFocusController; nsCOMPtr oldPIDOMWindow; nsCOMPtr newPIDOMWindow; nsCOMPtr oldGlobal; @@ -2748,10 +2713,10 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo nsCOMPtr newWindow = do_QueryInterface(newGlobal); nsCOMPtr oldWindow = do_QueryInterface(oldGlobal); - newWindow->GetRootCommandDispatcher(getter_AddRefs(newCommandDispatcher)); - oldWindow->GetRootCommandDispatcher(getter_AddRefs(oldCommandDispatcher)); - if(oldCommandDispatcher && oldCommandDispatcher != newCommandDispatcher) - oldCommandDispatcher->SetSuppressFocus(PR_TRUE); + newWindow->GetRootFocusController(getter_AddRefs(newFocusController)); + oldWindow->GetRootFocusController(getter_AddRefs(oldFocusController)); + if(oldFocusController && oldFocusController != newFocusController) + oldFocusController->SetSuppressFocus(PR_TRUE); } nsCOMPtr esm; @@ -2963,6 +2928,12 @@ nsEventStateManager::DispatchNewEvent(nsISupports* aTarget, nsIDOMEvent* aEvent) if (target) { ret = target->HandleDOMEvent(mPresContext, innerEvent, &aEvent, NS_EVENT_FLAG_INIT, &status); } + else { + nsCOMPtr target(do_QueryInterface(aTarget)); + if (target) { + ret = target->HandleChromeEvent(mPresContext, innerEvent, &aEvent, NS_EVENT_FLAG_INIT, &status); + } + } } } } diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp index 8eb81e7f8db..4caf569e4a5 100644 --- a/layout/html/base/src/nsPresShell.cpp +++ b/layout/html/base/src/nsPresShell.cpp @@ -111,10 +111,7 @@ #include "nsIScriptGlobalObject.h" #include "nsIDOMWindowInternal.h" #include "nsPIDOMWindow.h" -#ifdef INCLUDE_XUL -#include "nsIDOMXULDocument.h" -#include "nsIDOMXULCommandDispatcher.h" -#endif // INCLUDE_XUL +#include "nsIFocusController.h" // Drag & Drop, Clipboard #include "nsWidgetsCID.h" @@ -2111,68 +2108,52 @@ PresShell::EndObservingDocument() char* nsPresShell_ReflowStackPointerTop; #endif -#ifdef INCLUDE_XUL static void CheckForFocus(nsIDocument* aDocument) { // Now that we have a root frame, set focus in to the presshell, but // only do this if our window is currently focused // Restore focus if we're the active window or a parent of a previously // active window. - // XXX The XUL dependency will go away when the focus tracking portion - // of the command dispatcher moves into the embedding layer. nsCOMPtr globalObject; aDocument->GetScriptGlobalObject(getter_AddRefs(globalObject)); - nsCOMPtr rootWindow; nsCOMPtr ourWindow = do_QueryInterface(globalObject); - ourWindow->GetPrivateRoot(getter_AddRefs(rootWindow)); - NS_ASSERTION(rootWindow , "cannot get rootWindow"); - if(nsnull == rootWindow) - return; - nsCOMPtr rootDocument; - rootWindow->GetDocument(getter_AddRefs(rootDocument)); + nsCOMPtr focusController; + ourWindow->GetRootFocusController(getter_AddRefs(focusController)); - nsCOMPtr commandDispatcher; - nsCOMPtr xulDoc = do_QueryInterface(rootDocument); - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - // Suppress the command dispatcher. - commandDispatcher->SetSuppressFocus(PR_TRUE); - nsCOMPtr focusedWindow; - commandDispatcher->GetFocusedWindow(getter_AddRefs(focusedWindow)); - - // See if the command dispatcher is holding on to an orphan window. - // This happens when you move from an inner frame to an outer frame - // (e.g., _parent, _top) - if (focusedWindow) { - nsCOMPtr domDoc; - focusedWindow->GetDocument(getter_AddRefs(domDoc)); - if (!domDoc) { - // We're pointing to garbage. Go ahead and let this - // presshell take the focus. - focusedWindow = do_QueryInterface(ourWindow); - commandDispatcher->SetFocusedWindow(focusedWindow); - } + if (focusController) { + // Suppress the command dispatcher. + focusController->SetSuppressFocus(PR_TRUE); + nsCOMPtr focusedWindow; + focusController->GetFocusedWindow(getter_AddRefs(focusedWindow)); + + // See if the command dispatcher is holding on to an orphan window. + // This happens when you move from an inner frame to an outer frame + // (e.g., _parent, _top) + if (focusedWindow) { + nsCOMPtr domDoc; + focusedWindow->GetDocument(getter_AddRefs(domDoc)); + if (!domDoc) { + // We're pointing to garbage. Go ahead and let this + // presshell take the focus. + focusedWindow = do_QueryInterface(ourWindow); + focusController->SetFocusedWindow(focusedWindow); } - - nsCOMPtr domWindow = do_QueryInterface(ourWindow); - if (domWindow == focusedWindow) { - PRBool active; - commandDispatcher->GetActive(&active); - commandDispatcher->SetFocusedElement(nsnull); - if(active) { - // We need to restore focus and make sure we null - // out the focused element. - domWindow->Focus(); - } - } - commandDispatcher->SetSuppressFocus(PR_FALSE); } + + nsCOMPtr domWindow = do_QueryInterface(ourWindow); + if (domWindow == focusedWindow) { + PRBool active; + focusController->GetActive(&active); + focusController->SetFocusedElement(nsnull); + if(active) { + // We need to restore focus and make sure we null + // out the focused element. + domWindow->Focus(); + } + } + focusController->SetSuppressFocus(PR_FALSE); } } -#endif - nsresult PresShell::NotifyReflowObservers(const char *aData) @@ -2294,9 +2275,7 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight) mFrameManager->SetRootFrame(rootFrame); } -#ifdef INCLUDE_XUL CheckForFocus(mDocument); -#endif // Have the style sheet processor construct frame for the root // content object down @@ -2516,8 +2495,7 @@ NS_IMETHODIMP PresShell::ScrollFrameIntoView(nsIFrame *aFrame){ if (!aFrame) return NS_ERROR_NULL_POINTER; - -#ifdef INCLUDE_XUL + // Before we scroll the frame into view, ask the command dispatcher // if we're resetting focus because a window just got an activate // event. If we are, we do not want to scroll the frame into view. @@ -2525,40 +2503,28 @@ PresShell::ScrollFrameIntoView(nsIFrame *aFrame){ // window. When they reactivate the window, the expected behavior // is not for the anchor link to scroll back into view. That is what // this check is preventing. - // XXX: The dependency on the command dispatcher needs to be fixed. nsCOMPtr content; aFrame->GetContent(getter_AddRefs(content)); if(content) { nsCOMPtr document; content->GetDocument(*getter_AddRefs(document)); if(document){ - nsCOMPtr commandDispatcher; - nsCOMPtr ourGlobal; - document->GetScriptGlobalObject(getter_AddRefs(ourGlobal)); - nsCOMPtr rootWindow; + nsCOMPtr focusController; + nsCOMPtr ourGlobal; + document->GetScriptGlobalObject(getter_AddRefs(ourGlobal)); nsCOMPtr ourWindow = do_QueryInterface(ourGlobal); if(ourWindow) { - ourWindow->GetPrivateRoot(getter_AddRefs(rootWindow)); - if(rootWindow) { - nsCOMPtr rootDocument; - rootWindow->GetDocument(getter_AddRefs(rootDocument)); - - nsCOMPtr xulDoc = do_QueryInterface(rootDocument); - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - PRBool dontScroll; - commandDispatcher->GetSuppressFocusScroll(&dontScroll); - if(dontScroll) - return NS_OK; - } - } - } - } + ourWindow->GetRootFocusController(getter_AddRefs(focusController)); + if (focusController) { + PRBool dontScroll; + focusController->GetSuppressFocusScroll(&dontScroll); + if(dontScroll) + return NS_OK; + } + } } } -#endif + if (IsScrollingEnabled()) return ScrollFrameIntoView(aFrame, NS_PRESSHELL_SCROLL_ANYWHERE, NS_PRESSHELL_SCROLL_ANYWHERE); @@ -3406,7 +3372,7 @@ PresShell::ScrollFrameIntoView(nsIFrame *aFrame, if (!aFrame) { return NS_ERROR_NULL_POINTER; } -#ifdef INCLUDE_XUL + // Before we scroll the frame into view, ask the command dispatcher // if we're resetting focus because a window just got an activate // event. If we are, we do not want to scroll the frame into view. @@ -3421,33 +3387,22 @@ PresShell::ScrollFrameIntoView(nsIFrame *aFrame, nsCOMPtr document; content->GetDocument(*getter_AddRefs(document)); if(document){ - nsCOMPtr commandDispatcher; - nsCOMPtr ourGlobal; - document->GetScriptGlobalObject(getter_AddRefs(ourGlobal)); - nsCOMPtr rootWindow; + nsCOMPtr focusController; + nsCOMPtr ourGlobal; + document->GetScriptGlobalObject(getter_AddRefs(ourGlobal)); nsCOMPtr ourWindow = do_QueryInterface(ourGlobal); if(ourWindow) { - ourWindow->GetPrivateRoot(getter_AddRefs(rootWindow)); - if(rootWindow) { - nsCOMPtr rootDocument; - rootWindow->GetDocument(getter_AddRefs(rootDocument)); - - nsCOMPtr xulDoc = do_QueryInterface(rootDocument); - if (xulDoc) { - // See if we have a command dispatcher attached. - xulDoc->GetCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) { - PRBool dontScroll; - commandDispatcher->GetSuppressFocusScroll(&dontScroll); - if(dontScroll) - return NS_OK; - } - } - } - } + ourWindow->GetRootFocusController(getter_AddRefs(focusController)); + if (focusController) { + PRBool dontScroll; + focusController->GetSuppressFocusScroll(&dontScroll); + if(dontScroll) + return NS_OK; + } + } } } -#endif + if (mViewManager) { // Get the viewport scroller nsIScrollableView* scrollingView; diff --git a/layout/xbl/src/nsXBLPrototypeHandler.cpp b/layout/xbl/src/nsXBLPrototypeHandler.cpp index 7bd6ea4f732..211057b02fe 100644 --- a/layout/xbl/src/nsXBLPrototypeHandler.cpp +++ b/layout/xbl/src/nsXBLPrototypeHandler.cpp @@ -42,12 +42,13 @@ #include "nsIDOMNSHTMLTextAreaElement.h" #include "nsIDOMNSHTMLInputElement.h" #include "nsIDOMText.h" -#include "nsIDOMXULCommandDispatcher.h" +#include "nsIFocusController.h" #include "nsIEventListenerManager.h" #include "nsIDOMEventReceiver.h" #include "nsIDOMEventListener.h" #include "nsIPrivateDOMEvent.h" #include "nsPIDOMWindow.h" +#include "nsPIWindowRoot.h" #include "nsIDOMWindowInternal.h" #include "nsIPref.h" #include "nsIServiceManager.h" @@ -218,29 +219,36 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, nsIDOMEven // Instead of executing JS, let's get the controller for the bound // element and call doCommand on it. nsCOMPtr controller; + nsCOMPtr focusController; - nsCOMPtr privateWindow(do_QueryInterface(aReceiver)); - if (!privateWindow) { - nsCOMPtr elt(do_QueryInterface(aReceiver)); - nsCOMPtr doc; - if (elt) - elt->GetDocument(*getter_AddRefs(doc)); + nsCOMPtr windowRoot(do_QueryInterface(aReceiver)); + if (windowRoot) { + windowRoot->GetFocusController(getter_AddRefs(focusController)); + } + else { + nsCOMPtr privateWindow(do_QueryInterface(aReceiver)); + if (!privateWindow) { + nsCOMPtr elt(do_QueryInterface(aReceiver)); + nsCOMPtr doc; + if (elt) + elt->GetDocument(*getter_AddRefs(doc)); - if (!doc) - doc = do_QueryInterface(aReceiver); + if (!doc) + doc = do_QueryInterface(aReceiver); - if (!doc) - return NS_ERROR_FAILURE; + if (!doc) + return NS_ERROR_FAILURE; - nsCOMPtr globalObject; - doc->GetScriptGlobalObject(getter_AddRefs(globalObject)); - privateWindow = do_QueryInterface(globalObject); + nsCOMPtr globalObject; + doc->GetScriptGlobalObject(getter_AddRefs(globalObject)); + privateWindow = do_QueryInterface(globalObject); + } + + privateWindow->GetRootFocusController(getter_AddRefs(focusController)); } - nsCOMPtr commandDispatcher; - privateWindow->GetRootCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (commandDispatcher) - commandDispatcher->GetControllerForCommand(command, getter_AddRefs(controller)); + if (focusController) + focusController->GetControllerForCommand(command, getter_AddRefs(controller)); else GetController(aReceiver, getter_AddRefs(controller)); // We're attached to the receiver possibly. if (controller) @@ -271,12 +279,25 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, nsIDOMEven mHandlerElement->GetAttribute(kNameSpaceID_None, kOnCommandAtom, handlerText); if (handlerText.IsEmpty()) return NS_ERROR_FAILURE; // For whatever reason, they didn't give us anything to do. - aEvent->PreventDefault(); // Preventing default for XUL key handlers + aEvent->PreventDefault(); // Preventing default for XUL key handlers } } // Compile the handler and bind it to the element. - nsCOMPtr boundGlobal(do_QueryInterface(aReceiver)); + nsCOMPtr boundGlobal; + nsCOMPtr winRoot(do_QueryInterface(aReceiver)); + if (winRoot) { + nsCOMPtr focusController; + winRoot->GetFocusController(getter_AddRefs(focusController)); + nsCOMPtr win; + focusController->GetFocusedWindow(getter_AddRefs(win)); + nsCOMPtr piWin(do_QueryInterface(win)); + nsCOMPtr rootWin; + piWin->GetPrivateRoot(getter_AddRefs(rootWin)); + boundGlobal = do_QueryInterface(rootWin); + } + else boundGlobal = do_QueryInterface(aReceiver); + if (!boundGlobal) { nsCOMPtr boundDocument(do_QueryInterface(aReceiver)); if (!boundDocument) { @@ -293,7 +314,8 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, nsIDOMEven nsCOMPtr boundContext; boundGlobal->GetContext(getter_AddRefs(boundContext)); - nsCOMPtr owner(do_QueryInterface(aReceiver)); + nsCOMPtr owner(do_QueryInterface(winRoot ? boundGlobal : aReceiver)); + void* scriptObject; owner->GetScriptObject(boundContext, &scriptObject); diff --git a/layout/xbl/src/nsXBLWindowKeyHandler.cpp b/layout/xbl/src/nsXBLWindowKeyHandler.cpp index ede299c0f22..69ff45d174c 100644 --- a/layout/xbl/src/nsXBLWindowKeyHandler.cpp +++ b/layout/xbl/src/nsXBLWindowKeyHandler.cpp @@ -39,12 +39,13 @@ #include "nsIScriptGlobalObject.h" #include "nsIDOMWindowInternal.h" #include "nsPIDOMWindow.h" -#include "nsIDOMXULCommandDispatcher.h" +#include "nsIFocusController.h" #include "nsIDocShell.h" #include "nsIPresShell.h" #include "nsIDOMDocument.h" #include "nsIDocument.h" #include "nsIDOMElement.h" +#include "nsPIWindowRoot.h" PRUint32 nsXBLWindowKeyHandler::gRefCnt = 0; nsIAtom* nsXBLWindowKeyHandler::kKeyDownAtom = nsnull; @@ -90,16 +91,16 @@ NS_IMPL_ISUPPORTS1(nsXBLWindowKeyHandler, nsIDOMKeyListener) PRBool nsXBLWindowKeyHandler::IsEditor() { - nsCOMPtr privateWindow(do_QueryInterface(mReceiver)); - nsCOMPtr commandDispatcher; - privateWindow->GetRootCommandDispatcher(getter_AddRefs(commandDispatcher)); - if (!commandDispatcher) { - NS_WARNING("********* Problem for embedding. They have no command dispatcher!!!\n"); + nsCOMPtr windowRoot(do_QueryInterface(mReceiver)); + nsCOMPtr focusController; + windowRoot->GetFocusController(getter_AddRefs(focusController)); + if (!focusController) { + NS_WARNING("********* Something went wrong! No focus controller on the root!!!\n"); return PR_FALSE; } nsCOMPtr focusedWindow; - commandDispatcher->GetFocusedWindow(getter_AddRefs(focusedWindow)); + focusController->GetFocusedWindow(getter_AddRefs(focusedWindow)); if (!focusedWindow) return PR_FALSE; diff --git a/rdf/content/public/idl/XULCommandDispatcher.idl b/rdf/content/public/idl/XULCommandDispatcher.idl index 07ee3349dc1..19e6d886009 100644 --- a/rdf/content/public/idl/XULCommandDispatcher.idl +++ b/rdf/content/public/idl/XULCommandDispatcher.idl @@ -5,9 +5,6 @@ interface XULCommandDispatcher { attribute Element focusedElement; attribute WindowInternal focusedWindow; - attribute boolean suppressFocus; - attribute boolean suppressFocusScroll; - attribute boolean active; void addCommandUpdater(in Element updater, in DOMString events, in DOMString targets); void removeCommandUpdater(in Element updater); @@ -15,6 +12,5 @@ interface XULCommandDispatcher { void updateCommands(in DOMString eventName); xpidl nsIController getControllerForCommand(in DOMString command); - xpidl nsIControllers getControllers(); }; diff --git a/rdf/content/public/nsIDOMXULCommandDispatcher.h b/rdf/content/public/nsIDOMXULCommandDispatcher.h index 3153278e4a2..6fbedb13750 100644 --- a/rdf/content/public/nsIDOMXULCommandDispatcher.h +++ b/rdf/content/public/nsIDOMXULCommandDispatcher.h @@ -47,15 +47,6 @@ public: NS_IMETHOD GetFocusedWindow(nsIDOMWindowInternal** aFocusedWindow)=0; NS_IMETHOD SetFocusedWindow(nsIDOMWindowInternal* aFocusedWindow)=0; - NS_IMETHOD GetSuppressFocus(PRBool* aSuppressFocus)=0; - NS_IMETHOD SetSuppressFocus(PRBool aSuppressFocus)=0; - - NS_IMETHOD GetSuppressFocusScroll(PRBool* aSuppressFocusScroll)=0; - NS_IMETHOD SetSuppressFocusScroll(PRBool aSuppressFocusScroll)=0; - - NS_IMETHOD GetActive(PRBool* aActive)=0; - NS_IMETHOD SetActive(PRBool aActive)=0; - NS_IMETHOD AddCommandUpdater(nsIDOMElement* aUpdater, const nsAReadableString& aEvents, const nsAReadableString& aTargets)=0; NS_IMETHOD RemoveCommandUpdater(nsIDOMElement* aUpdater)=0; @@ -73,12 +64,6 @@ public: NS_IMETHOD SetFocusedElement(nsIDOMElement* aFocusedElement); \ NS_IMETHOD GetFocusedWindow(nsIDOMWindowInternal** aFocusedWindow); \ NS_IMETHOD SetFocusedWindow(nsIDOMWindowInternal* aFocusedWindow); \ - NS_IMETHOD GetSuppressFocus(PRBool* aSuppressFocus); \ - NS_IMETHOD SetSuppressFocus(PRBool aSuppressFocus); \ - NS_IMETHOD GetSuppressFocusScroll(PRBool* aSuppressFocusScroll); \ - NS_IMETHOD SetSuppressFocusScroll(PRBool aSuppressFocusScroll); \ - NS_IMETHOD GetActive(PRBool* aActive); \ - NS_IMETHOD SetActive(PRBool aActive); \ NS_IMETHOD AddCommandUpdater(nsIDOMElement* aUpdater, const nsAReadableString& aEvents, const nsAReadableString& aTargets); \ NS_IMETHOD RemoveCommandUpdater(nsIDOMElement* aUpdater); \ NS_IMETHOD UpdateCommands(const nsAReadableString& aEventName); \ @@ -92,12 +77,6 @@ public: NS_IMETHOD SetFocusedElement(nsIDOMElement* aFocusedElement) { return _to SetFocusedElement(aFocusedElement); } \ NS_IMETHOD GetFocusedWindow(nsIDOMWindowInternal** aFocusedWindow) { return _to GetFocusedWindow(aFocusedWindow); } \ NS_IMETHOD SetFocusedWindow(nsIDOMWindowInternal* aFocusedWindow) { return _to SetFocusedWindow(aFocusedWindow); } \ - NS_IMETHOD GetSuppressFocus(PRBool* aSuppressFocus) { return _to GetSuppressFocus(aSuppressFocus); } \ - NS_IMETHOD SetSuppressFocus(PRBool aSuppressFocus) { return _to SetSuppressFocus(aSuppressFocus); } \ - NS_IMETHOD GetSuppressFocusScroll(PRBool* aSuppressFocusScroll) { return _to GetSuppressFocusScroll(aSuppressFocusScroll); } \ - NS_IMETHOD SetSuppressFocusScroll(PRBool aSuppressFocusScroll) { return _to SetSuppressFocusScroll(aSuppressFocusScroll); } \ - NS_IMETHOD GetActive(PRBool* aActive) { return _to GetActive(aActive); } \ - NS_IMETHOD SetActive(PRBool aActive) { return _to SetActive(aActive); } \ NS_IMETHOD AddCommandUpdater(nsIDOMElement* aUpdater, const nsAReadableString& aEvents, const nsAReadableString& aTargets) { return _to AddCommandUpdater(aUpdater, aEvents, aTargets); } \ NS_IMETHOD RemoveCommandUpdater(nsIDOMElement* aUpdater) { return _to RemoveCommandUpdater(aUpdater); } \ NS_IMETHOD UpdateCommands(const nsAReadableString& aEventName) { return _to UpdateCommands(aEventName); } \ diff --git a/rdf/content/src/nsJSXULCommandDispatcher.cpp b/rdf/content/src/nsJSXULCommandDispatcher.cpp index 529c38462b1..e69de29bb2d 100644 --- a/rdf/content/src/nsJSXULCommandDispatcher.cpp +++ b/rdf/content/src/nsJSXULCommandDispatcher.cpp @@ -1,674 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * The contents of this file are subject to the Netscape Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - */ -/* AUTO-GENERATED. DO NOT EDIT!!! */ - -#include "jsapi.h" -#include "nsJSUtils.h" -#include "nsDOMError.h" -#include "nscore.h" -#include "nsIServiceManager.h" -#include "nsIScriptContext.h" -#include "nsIScriptSecurityManager.h" -#include "nsIJSScriptObject.h" -#include "nsIScriptObjectOwner.h" -#include "nsIScriptGlobalObject.h" -#include "nsCOMPtr.h" -#include "nsDOMPropEnums.h" -#include "nsString.h" -#include "nsIController.h" -#include "nsIDOMElement.h" -#include "nsIDOMWindowInternal.h" -#include "nsIDOMXULCommandDispatcher.h" -#include "nsIControllers.h" - - -static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID); -static NS_DEFINE_IID(kIJSScriptObjectIID, NS_IJSSCRIPTOBJECT_IID); -static NS_DEFINE_IID(kIScriptGlobalObjectIID, NS_ISCRIPTGLOBALOBJECT_IID); -static NS_DEFINE_IID(kIControllerIID, NS_ICONTROLLER_IID); -static NS_DEFINE_IID(kIElementIID, NS_IDOMELEMENT_IID); -static NS_DEFINE_IID(kIWindowInternalIID, NS_IDOMWINDOWINTERNAL_IID); -static NS_DEFINE_IID(kIXULCommandDispatcherIID, NS_IDOMXULCOMMANDDISPATCHER_IID); -static NS_DEFINE_IID(kIControllersIID, NS_ICONTROLLERS_IID); - -// -// XULCommandDispatcher property ids -// -enum XULCommandDispatcher_slots { - XULCOMMANDDISPATCHER_FOCUSEDELEMENT = -1, - XULCOMMANDDISPATCHER_FOCUSEDWINDOW = -2, - XULCOMMANDDISPATCHER_SUPPRESSFOCUS = -3, - XULCOMMANDDISPATCHER_SUPPRESSFOCUSSCROLL = -4, - XULCOMMANDDISPATCHER_ACTIVE = -5 -}; - -/***********************************************************************/ -// -// XULCommandDispatcher Properties Getter -// -PR_STATIC_CALLBACK(JSBool) -GetXULCommandDispatcherProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - nsIDOMXULCommandDispatcher *a = (nsIDOMXULCommandDispatcher*)nsJSUtils::nsGetNativeThis(cx, obj); - - // If there's no private data, this must be the prototype, so ignore - if (nsnull == a) { - return JS_TRUE; - } - - nsresult rv = NS_OK; - if (JSVAL_IS_INT(id)) { - nsIScriptSecurityManager *secMan = nsJSUtils::nsGetSecurityManager(cx, obj); - if (!secMan) - return PR_FALSE; - switch(JSVAL_TO_INT(id)) { - case XULCOMMANDDISPATCHER_FOCUSEDELEMENT: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_FOCUSEDELEMENT, PR_FALSE); - if (NS_SUCCEEDED(rv)) { - nsIDOMElement* prop; - rv = a->GetFocusedElement(&prop); - if (NS_SUCCEEDED(rv)) { - // get the js object - nsJSUtils::nsConvertObjectToJSVal((nsISupports *)prop, cx, obj, vp); - } - } - break; - } - case XULCOMMANDDISPATCHER_FOCUSEDWINDOW: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_FOCUSEDWINDOW, PR_FALSE); - if (NS_SUCCEEDED(rv)) { - nsIDOMWindowInternal* prop; - rv = a->GetFocusedWindow(&prop); - if (NS_SUCCEEDED(rv)) { - // get the js object - nsJSUtils::nsConvertObjectToJSVal((nsISupports *)prop, cx, obj, vp); - } - } - break; - } - case XULCOMMANDDISPATCHER_SUPPRESSFOCUS: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_SUPPRESSFOCUS, PR_FALSE); - if (NS_SUCCEEDED(rv)) { - PRBool prop; - rv = a->GetSuppressFocus(&prop); - if (NS_SUCCEEDED(rv)) { - *vp = BOOLEAN_TO_JSVAL(prop); - } - } - break; - } - case XULCOMMANDDISPATCHER_SUPPRESSFOCUSSCROLL: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_SUPPRESSFOCUSSCROLL, PR_FALSE); - if (NS_SUCCEEDED(rv)) { - PRBool prop; - rv = a->GetSuppressFocusScroll(&prop); - if (NS_SUCCEEDED(rv)) { - *vp = BOOLEAN_TO_JSVAL(prop); - } - } - break; - } - case XULCOMMANDDISPATCHER_ACTIVE: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_ACTIVE, PR_FALSE); - if (NS_SUCCEEDED(rv)) { - PRBool prop; - rv = a->GetActive(&prop); - if (NS_SUCCEEDED(rv)) { - *vp = BOOLEAN_TO_JSVAL(prop); - } - } - break; - } - default: - return nsJSUtils::nsCallJSScriptObjectGetProperty(a, cx, obj, id, vp); - } - } - else { - return nsJSUtils::nsCallJSScriptObjectGetProperty(a, cx, obj, id, vp); - } - - if (NS_FAILED(rv)) - return nsJSUtils::nsReportError(cx, obj, rv); - return PR_TRUE; -} - -/***********************************************************************/ -// -// XULCommandDispatcher Properties Setter -// -PR_STATIC_CALLBACK(JSBool) -SetXULCommandDispatcherProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - nsIDOMXULCommandDispatcher *a = (nsIDOMXULCommandDispatcher*)nsJSUtils::nsGetNativeThis(cx, obj); - - // If there's no private data, this must be the prototype, so ignore - if (nsnull == a) { - return JS_TRUE; - } - - nsresult rv = NS_OK; - if (JSVAL_IS_INT(id)) { - nsIScriptSecurityManager *secMan = nsJSUtils::nsGetSecurityManager(cx, obj); - if (!secMan) - return PR_FALSE; - switch(JSVAL_TO_INT(id)) { - case XULCOMMANDDISPATCHER_FOCUSEDELEMENT: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_FOCUSEDELEMENT, PR_TRUE); - if (NS_SUCCEEDED(rv)) { - nsIDOMElement* prop; - if (PR_FALSE == nsJSUtils::nsConvertJSValToObject((nsISupports **)&prop, - kIElementIID, NS_ConvertASCIItoUCS2("Element"), - cx, *vp)) { - rv = NS_ERROR_DOM_NOT_OBJECT_ERR; - break; - } - - rv = a->SetFocusedElement(prop); - NS_IF_RELEASE(prop); - } - break; - } - case XULCOMMANDDISPATCHER_FOCUSEDWINDOW: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_FOCUSEDWINDOW, PR_TRUE); - if (NS_SUCCEEDED(rv)) { - nsIDOMWindowInternal* prop; - if (PR_FALSE == nsJSUtils::nsConvertJSValToObject((nsISupports **)&prop, - kIWindowInternalIID, NS_ConvertASCIItoUCS2("WindowInternal"), - cx, *vp)) { - rv = NS_ERROR_DOM_NOT_OBJECT_ERR; - break; - } - - rv = a->SetFocusedWindow(prop); - NS_IF_RELEASE(prop); - } - break; - } - case XULCOMMANDDISPATCHER_SUPPRESSFOCUS: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_SUPPRESSFOCUS, PR_TRUE); - if (NS_SUCCEEDED(rv)) { - PRBool prop; - if (PR_FALSE == nsJSUtils::nsConvertJSValToBool(&prop, cx, *vp)) { - rv = NS_ERROR_DOM_NOT_BOOLEAN_ERR; - break; - } - - rv = a->SetSuppressFocus(prop); - - } - break; - } - case XULCOMMANDDISPATCHER_SUPPRESSFOCUSSCROLL: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_SUPPRESSFOCUSSCROLL, PR_TRUE); - if (NS_SUCCEEDED(rv)) { - PRBool prop; - if (PR_FALSE == nsJSUtils::nsConvertJSValToBool(&prop, cx, *vp)) { - rv = NS_ERROR_DOM_NOT_BOOLEAN_ERR; - break; - } - - rv = a->SetSuppressFocusScroll(prop); - - } - break; - } - case XULCOMMANDDISPATCHER_ACTIVE: - { - rv = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_ACTIVE, PR_TRUE); - if (NS_SUCCEEDED(rv)) { - PRBool prop; - if (PR_FALSE == nsJSUtils::nsConvertJSValToBool(&prop, cx, *vp)) { - rv = NS_ERROR_DOM_NOT_BOOLEAN_ERR; - break; - } - - rv = a->SetActive(prop); - - } - break; - } - default: - return nsJSUtils::nsCallJSScriptObjectSetProperty(a, cx, obj, id, vp); - } - } - else { - return nsJSUtils::nsCallJSScriptObjectSetProperty(a, cx, obj, id, vp); - } - - if (NS_FAILED(rv)) - return nsJSUtils::nsReportError(cx, obj, rv); - return PR_TRUE; -} - - -// -// XULCommandDispatcher class properties -// -static JSPropertySpec XULCommandDispatcherProperties[] = -{ - {"focusedElement", XULCOMMANDDISPATCHER_FOCUSEDELEMENT, JSPROP_ENUMERATE}, - {"focusedWindow", XULCOMMANDDISPATCHER_FOCUSEDWINDOW, JSPROP_ENUMERATE}, - {"suppressFocus", XULCOMMANDDISPATCHER_SUPPRESSFOCUS, JSPROP_ENUMERATE}, - {"suppressFocusScroll", XULCOMMANDDISPATCHER_SUPPRESSFOCUSSCROLL, JSPROP_ENUMERATE}, - {"active", XULCOMMANDDISPATCHER_ACTIVE, JSPROP_ENUMERATE}, - {0} -}; - - -// -// XULCommandDispatcher finalizer -// -PR_STATIC_CALLBACK(void) -FinalizeXULCommandDispatcher(JSContext *cx, JSObject *obj) -{ - nsJSUtils::nsGenericFinalize(cx, obj); -} - - -// -// XULCommandDispatcher enumerate -// -PR_STATIC_CALLBACK(JSBool) -EnumerateXULCommandDispatcher(JSContext *cx, JSObject *obj) -{ - return nsJSUtils::nsGenericEnumerate(cx, obj, nsnull); -} - - -// -// XULCommandDispatcher resolve -// -PR_STATIC_CALLBACK(JSBool) -ResolveXULCommandDispatcher(JSContext *cx, JSObject *obj, jsval id) -{ - return nsJSUtils::nsGenericResolve(cx, obj, id, nsnull); -} - - -// -// Native method AddCommandUpdater -// -PR_STATIC_CALLBACK(JSBool) -XULCommandDispatcherAddCommandUpdater(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - nsIDOMXULCommandDispatcher *nativeThis = (nsIDOMXULCommandDispatcher*)nsJSUtils::nsGetNativeThis(cx, obj); - nsresult result = NS_OK; - nsCOMPtr b0; - nsAutoString b1; - nsAutoString b2; - // If there's no private data, this must be the prototype, so ignore - if (nsnull == nativeThis) { - return JS_TRUE; - } - - { - *rval = JSVAL_NULL; - nsIScriptSecurityManager *secMan = nsJSUtils::nsGetSecurityManager(cx, obj); - if (!secMan) - return PR_FALSE; - result = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_ADDCOMMANDUPDATER, PR_FALSE); - if (NS_FAILED(result)) { - return nsJSUtils::nsReportError(cx, obj, result); - } - if (argc < 3) { - return nsJSUtils::nsReportError(cx, obj, NS_ERROR_DOM_TOO_FEW_PARAMETERS_ERR); - } - - if (JS_FALSE == nsJSUtils::nsConvertJSValToObject((nsISupports **)(void**)getter_AddRefs(b0), - kIElementIID, - NS_ConvertASCIItoUCS2("Element"), - cx, - argv[0])) { - return nsJSUtils::nsReportError(cx, obj, NS_ERROR_DOM_NOT_OBJECT_ERR); - } - nsJSUtils::nsConvertJSValToString(b1, cx, argv[1]); - nsJSUtils::nsConvertJSValToString(b2, cx, argv[2]); - - result = nativeThis->AddCommandUpdater(b0, b1, b2); - if (NS_FAILED(result)) { - return nsJSUtils::nsReportError(cx, obj, result); - } - - *rval = JSVAL_VOID; - } - - return JS_TRUE; -} - - -// -// Native method RemoveCommandUpdater -// -PR_STATIC_CALLBACK(JSBool) -XULCommandDispatcherRemoveCommandUpdater(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - nsIDOMXULCommandDispatcher *nativeThis = (nsIDOMXULCommandDispatcher*)nsJSUtils::nsGetNativeThis(cx, obj); - nsresult result = NS_OK; - nsCOMPtr b0; - // If there's no private data, this must be the prototype, so ignore - if (nsnull == nativeThis) { - return JS_TRUE; - } - - { - *rval = JSVAL_NULL; - nsIScriptSecurityManager *secMan = nsJSUtils::nsGetSecurityManager(cx, obj); - if (!secMan) - return PR_FALSE; - result = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_REMOVECOMMANDUPDATER, PR_FALSE); - if (NS_FAILED(result)) { - return nsJSUtils::nsReportError(cx, obj, result); - } - if (argc < 1) { - return nsJSUtils::nsReportError(cx, obj, NS_ERROR_DOM_TOO_FEW_PARAMETERS_ERR); - } - - if (JS_FALSE == nsJSUtils::nsConvertJSValToObject((nsISupports **)(void**)getter_AddRefs(b0), - kIElementIID, - NS_ConvertASCIItoUCS2("Element"), - cx, - argv[0])) { - return nsJSUtils::nsReportError(cx, obj, NS_ERROR_DOM_NOT_OBJECT_ERR); - } - - result = nativeThis->RemoveCommandUpdater(b0); - if (NS_FAILED(result)) { - return nsJSUtils::nsReportError(cx, obj, result); - } - - *rval = JSVAL_VOID; - } - - return JS_TRUE; -} - - -// -// Native method UpdateCommands -// -PR_STATIC_CALLBACK(JSBool) -XULCommandDispatcherUpdateCommands(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - nsIDOMXULCommandDispatcher *nativeThis = (nsIDOMXULCommandDispatcher*)nsJSUtils::nsGetNativeThis(cx, obj); - nsresult result = NS_OK; - nsAutoString b0; - // If there's no private data, this must be the prototype, so ignore - if (nsnull == nativeThis) { - return JS_TRUE; - } - - { - *rval = JSVAL_NULL; - nsIScriptSecurityManager *secMan = nsJSUtils::nsGetSecurityManager(cx, obj); - if (!secMan) - return PR_FALSE; - result = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_UPDATECOMMANDS, PR_FALSE); - if (NS_FAILED(result)) { - return nsJSUtils::nsReportError(cx, obj, result); - } - if (argc < 1) { - return nsJSUtils::nsReportError(cx, obj, NS_ERROR_DOM_TOO_FEW_PARAMETERS_ERR); - } - - nsJSUtils::nsConvertJSValToString(b0, cx, argv[0]); - - result = nativeThis->UpdateCommands(b0); - if (NS_FAILED(result)) { - return nsJSUtils::nsReportError(cx, obj, result); - } - - *rval = JSVAL_VOID; - } - - return JS_TRUE; -} - - -// -// Native method GetControllerForCommand -// -PR_STATIC_CALLBACK(JSBool) -XULCommandDispatcherGetControllerForCommand(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - nsIDOMXULCommandDispatcher *nativeThis = (nsIDOMXULCommandDispatcher*)nsJSUtils::nsGetNativeThis(cx, obj); - nsresult result = NS_OK; - nsIController* nativeRet; - nsAutoString b0; - // If there's no private data, this must be the prototype, so ignore - if (nsnull == nativeThis) { - return JS_TRUE; - } - - { - *rval = JSVAL_NULL; - nsIScriptSecurityManager *secMan = nsJSUtils::nsGetSecurityManager(cx, obj); - if (!secMan) - return PR_FALSE; - result = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_GETCONTROLLERFORCOMMAND, PR_FALSE); - if (NS_FAILED(result)) { - return nsJSUtils::nsReportError(cx, obj, result); - } - if (argc < 1) { - return nsJSUtils::nsReportError(cx, obj, NS_ERROR_DOM_TOO_FEW_PARAMETERS_ERR); - } - - nsJSUtils::nsConvertJSValToString(b0, cx, argv[0]); - - result = nativeThis->GetControllerForCommand(b0, &nativeRet); - if (NS_FAILED(result)) { - return nsJSUtils::nsReportError(cx, obj, result); - } - - // n.b., this will release nativeRet - nsJSUtils::nsConvertXPCObjectToJSVal(nativeRet, NS_GET_IID(nsIController), cx, obj, rval); - } - - return JS_TRUE; -} - - -// -// Native method GetControllers -// -PR_STATIC_CALLBACK(JSBool) -XULCommandDispatcherGetControllers(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - nsIDOMXULCommandDispatcher *nativeThis = (nsIDOMXULCommandDispatcher*)nsJSUtils::nsGetNativeThis(cx, obj); - nsresult result = NS_OK; - nsIControllers* nativeRet; - // If there's no private data, this must be the prototype, so ignore - if (nsnull == nativeThis) { - return JS_TRUE; - } - - { - *rval = JSVAL_NULL; - nsIScriptSecurityManager *secMan = nsJSUtils::nsGetSecurityManager(cx, obj); - if (!secMan) - return PR_FALSE; - result = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_XULCOMMANDDISPATCHER_GETCONTROLLERS, PR_FALSE); - if (NS_FAILED(result)) { - return nsJSUtils::nsReportError(cx, obj, result); - } - - result = nativeThis->GetControllers(&nativeRet); - if (NS_FAILED(result)) { - return nsJSUtils::nsReportError(cx, obj, result); - } - - // n.b., this will release nativeRet - nsJSUtils::nsConvertXPCObjectToJSVal(nativeRet, NS_GET_IID(nsIControllers), cx, obj, rval); - } - - return JS_TRUE; -} - - -/***********************************************************************/ -// -// class for XULCommandDispatcher -// -JSClass XULCommandDispatcherClass = { - "XULCommandDispatcher", - JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS, - JS_PropertyStub, - JS_PropertyStub, - GetXULCommandDispatcherProperty, - SetXULCommandDispatcherProperty, - EnumerateXULCommandDispatcher, - ResolveXULCommandDispatcher, - JS_ConvertStub, - FinalizeXULCommandDispatcher, - nsnull, - nsJSUtils::nsCheckAccess -}; - - -// -// XULCommandDispatcher class methods -// -static JSFunctionSpec XULCommandDispatcherMethods[] = -{ - {"addCommandUpdater", XULCommandDispatcherAddCommandUpdater, 3}, - {"removeCommandUpdater", XULCommandDispatcherRemoveCommandUpdater, 1}, - {"updateCommands", XULCommandDispatcherUpdateCommands, 1}, - {"getControllerForCommand", XULCommandDispatcherGetControllerForCommand, 1}, - {"getControllers", XULCommandDispatcherGetControllers, 0}, - {0} -}; - - -// -// XULCommandDispatcher constructor -// -PR_STATIC_CALLBACK(JSBool) -XULCommandDispatcher(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - return JS_FALSE; -} - - -// -// XULCommandDispatcher class initialization -// -extern "C" NS_DOM nsresult NS_InitXULCommandDispatcherClass(nsIScriptContext *aContext, void **aPrototype) -{ - JSContext *jscontext = (JSContext *)aContext->GetNativeContext(); - JSObject *proto = nsnull; - JSObject *constructor = nsnull; - JSObject *parent_proto = nsnull; - JSObject *global = JS_GetGlobalObject(jscontext); - jsval vp; - - if ((PR_TRUE != JS_LookupProperty(jscontext, global, "XULCommandDispatcher", &vp)) || - !JSVAL_IS_OBJECT(vp) || - ((constructor = JSVAL_TO_OBJECT(vp)) == nsnull) || - (PR_TRUE != JS_LookupProperty(jscontext, JSVAL_TO_OBJECT(vp), "prototype", &vp)) || - !JSVAL_IS_OBJECT(vp)) { - - proto = JS_InitClass(jscontext, // context - global, // global object - parent_proto, // parent proto - &XULCommandDispatcherClass, // JSClass - XULCommandDispatcher, // JSNative ctor - 0, // ctor args - XULCommandDispatcherProperties, // proto props - XULCommandDispatcherMethods, // proto funcs - nsnull, // ctor props (static) - nsnull); // ctor funcs (static) - if (nsnull == proto) { - return NS_ERROR_FAILURE; - } - - } - else if ((nsnull != constructor) && JSVAL_IS_OBJECT(vp)) { - proto = JSVAL_TO_OBJECT(vp); - } - else { - return NS_ERROR_FAILURE; - } - - if (aPrototype) { - *aPrototype = proto; - } - return NS_OK; -} - - -// -// Method for creating a new XULCommandDispatcher JavaScript object -// -extern "C" NS_DOM nsresult NS_NewScriptXULCommandDispatcher(nsIScriptContext *aContext, nsISupports *aSupports, nsISupports *aParent, void **aReturn) -{ - NS_PRECONDITION(nsnull != aContext && nsnull != aSupports && nsnull != aReturn, "null argument to NS_NewScriptXULCommandDispatcher"); - JSObject *proto; - JSObject *parent; - nsIScriptObjectOwner *owner; - JSContext *jscontext = (JSContext *)aContext->GetNativeContext(); - nsresult result = NS_OK; - nsIDOMXULCommandDispatcher *aXULCommandDispatcher; - - if (nsnull == aParent) { - parent = nsnull; - } - else if (NS_OK == aParent->QueryInterface(kIScriptObjectOwnerIID, (void**)&owner)) { - if (NS_OK != owner->GetScriptObject(aContext, (void **)&parent)) { - NS_RELEASE(owner); - return NS_ERROR_FAILURE; - } - NS_RELEASE(owner); - } - else { - return NS_ERROR_FAILURE; - } - - if (NS_OK != NS_InitXULCommandDispatcherClass(aContext, (void **)&proto)) { - return NS_ERROR_FAILURE; - } - - result = aSupports->QueryInterface(kIXULCommandDispatcherIID, (void **)&aXULCommandDispatcher); - if (NS_OK != result) { - return result; - } - - // create a js object for this class - *aReturn = JS_NewObject(jscontext, &XULCommandDispatcherClass, proto, parent); - if (nsnull != *aReturn) { - // connect the native object to the js object - JS_SetPrivate(jscontext, (JSObject *)*aReturn, aXULCommandDispatcher); - } - else { - NS_RELEASE(aXULCommandDispatcher); - return NS_ERROR_FAILURE; - } - - return NS_OK; -} diff --git a/rdf/content/src/nsXULCommandDispatcher.cpp b/rdf/content/src/nsXULCommandDispatcher.cpp index 9bc1d1ade42..e69de29bb2d 100644 --- a/rdf/content/src/nsXULCommandDispatcher.cpp +++ b/rdf/content/src/nsXULCommandDispatcher.cpp @@ -1,665 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * The contents of this file are subject to the Netscape Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All - * Rights Reserved. - * - * Original Author: David W. Hyatt (hyatt@netscape.com) - * - * Contributor(s): - */ - -/* - - This file provides the implementation for the XUL Command Dispatcher. - - */ - -#include "nsIContent.h" -#include "nsIControllers.h" -#include "nsIDOMDocument.h" -#include "nsIDOMXULDocument.h" -#include "nsIDOMHTMLDocument.h" -#include "nsIDOMElement.h" -#include "nsIDOMNSHTMLInputElement.h" -#include "nsIDOMNSHTMLTextAreaElement.h" -#include "nsIDOMUIEvent.h" -#include "nsIDOMWindowInternal.h" -#include "nsIDOMXULElement.h" -#include "nsIDocument.h" -#include "nsIPresContext.h" -#include "nsIPresShell.h" -#include "nsIScriptGlobalObject.h" -#include "nsPIDOMWindow.h" -#include "nsRDFCID.h" -#include "nsXULCommandDispatcher.h" -#include "prlog.h" -#include "nsIDOMEventTarget.h" - -#ifdef PR_LOGGING -static PRLogModuleInfo* gLog; -#endif - -//////////////////////////////////////////////////////////////////////// - -nsXULCommandDispatcher::nsXULCommandDispatcher(void) - : mScriptObject(nsnull), mSuppressFocus(0), - mActive(PR_FALSE), mFocusInitialized(PR_FALSE), mUpdaters(nsnull) -{ - NS_INIT_REFCNT(); - -#ifdef PR_LOGGING - if (! gLog) - gLog = PR_NewLogModule("nsXULCommandDispatcher"); -#endif -} - -nsXULCommandDispatcher::~nsXULCommandDispatcher(void) -{ - while (mUpdaters) { - Updater* doomed = mUpdaters; - mUpdaters = mUpdaters->mNext; - delete doomed; - } -} - -NS_IMPL_ADDREF(nsXULCommandDispatcher) -NS_IMPL_RELEASE(nsXULCommandDispatcher) - -NS_IMETHODIMP -nsXULCommandDispatcher::QueryInterface(REFNSIID iid, void** result) -{ - if (! result) - return NS_ERROR_NULL_POINTER; - - *result = nsnull; - if (iid.Equals(NS_GET_IID(nsISupports)) || - iid.Equals(NS_GET_IID(nsIDOMXULCommandDispatcher))) { - *result = NS_STATIC_CAST(nsIDOMXULCommandDispatcher*, this); - } - else if (iid.Equals(NS_GET_IID(nsIDOMFocusListener)) || - iid.Equals(NS_GET_IID(nsIDOMEventListener))) { - *result = NS_STATIC_CAST(nsIDOMFocusListener*, this); - } - else if (iid.Equals(NS_GET_IID(nsIScriptObjectOwner))) { - *result = NS_STATIC_CAST(nsIScriptObjectOwner*, this); - } - else if (iid.Equals(NS_GET_IID(nsISupportsWeakReference))) { - *result = NS_STATIC_CAST(nsISupportsWeakReference*, this); - } - else { - return NS_NOINTERFACE; - } - - NS_ADDREF_THIS(); - return NS_OK; -} - - -NS_IMETHODIMP -nsXULCommandDispatcher::Create(nsIDOMXULCommandDispatcher** aResult) -{ - nsXULCommandDispatcher* dispatcher = new nsXULCommandDispatcher(); - if (! dispatcher) - return NS_ERROR_OUT_OF_MEMORY; - - *aResult = dispatcher; - NS_ADDREF(*aResult); - return NS_OK; -} - - -//////////////////////////////////////////////////////////////// -// nsIDOMXULTracker Interface - -NS_IMETHODIMP -nsXULCommandDispatcher::GetFocusedElement(nsIDOMElement** aElement) -{ - *aElement = mCurrentElement; - NS_IF_ADDREF(*aElement); - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::GetFocusedWindow(nsIDOMWindowInternal** aWindow) -{ - *aWindow = mCurrentWindow; - NS_IF_ADDREF(*aWindow); - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::SetFocusedElement(nsIDOMElement* aElement) -{ - mCurrentElement = aElement; - // Need to update focus commands when focus switches from - // an element to no element, so don't test mCurrentElement - // before updating. - UpdateCommands(NS_LITERAL_STRING("focus")); - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::SetFocusedWindow(nsIDOMWindowInternal* aWindow) -{ - mCurrentWindow = aWindow; - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::AddCommandUpdater(nsIDOMElement* aElement, - const nsAReadableString& aEvents, - const nsAReadableString& aTargets) -{ - NS_PRECONDITION(aElement != nsnull, "null ptr"); - if (! aElement) - return NS_ERROR_NULL_POINTER; - - Updater* updater = mUpdaters; - Updater** link = &mUpdaters; - - while (updater) { - if (updater->mElement == aElement) { - -#ifdef NS_DEBUG - nsCAutoString eventsC, targetsC, aeventsC, atargetsC; - eventsC.AssignWithConversion(updater->mEvents); - targetsC.AssignWithConversion(updater->mTargets); - aeventsC.Assign(NS_ConvertUCS2toUTF8(aEvents)); - atargetsC.Assign(NS_ConvertUCS2toUTF8(aTargets)); - PR_LOG(gLog, PR_LOG_ALWAYS, - ("xulcmd[%p] replace %p(events=%s targets=%s) with (events=%s targets=%s)", - this, aElement, - (const char*) eventsC, - (const char*) targetsC, - (const char*) aeventsC, - (const char*) atargetsC)); -#endif - - // If the updater was already in the list, then replace - // (?) the 'events' and 'targets' filters with the new - // specification. - updater->mEvents = aEvents; - updater->mTargets = aTargets; - return NS_OK; - } - - link = &(updater->mNext); - updater = updater->mNext; - } -#ifdef NS_DEBUG - nsCAutoString aeventsC, atargetsC; - aeventsC.Assign(NS_ConvertUCS2toUTF8(aEvents)); - atargetsC.Assign(NS_ConvertUCS2toUTF8(aTargets)); - - PR_LOG(gLog, PR_LOG_ALWAYS, - ("xulcmd[%p] add %p(events=%s targets=%s)", - this, aElement, - (const char*) aeventsC, - (const char*) atargetsC)); -#endif - - // If we get here, this is a new updater. Append it to the list. - updater = new Updater(aElement, aEvents, aTargets); - if (! updater) - return NS_ERROR_OUT_OF_MEMORY; - - *link = updater; - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::RemoveCommandUpdater(nsIDOMElement* aElement) -{ - NS_PRECONDITION(aElement != nsnull, "null ptr"); - if (! aElement) - return NS_ERROR_NULL_POINTER; - - Updater* updater = mUpdaters; - Updater** link = &mUpdaters; - - while (updater) { - if (updater->mElement == aElement) { -#ifdef NS_DEBUG - nsCAutoString eventsC, targetsC; - eventsC.AssignWithConversion(updater->mEvents); - targetsC.AssignWithConversion(updater->mTargets); - PR_LOG(gLog, PR_LOG_ALWAYS, - ("xulcmd[%p] remove %p(events=%s targets=%s)", - this, aElement, - (const char*) eventsC, - (const char*) targetsC)); -#endif - - *link = updater->mNext; - delete updater; - return NS_OK; - } - - link = &(updater->mNext); - updater = updater->mNext; - } - - // Hmm. Not found. Oh well. - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::UpdateCommands(const nsAReadableString& aEventName) -{ - nsresult rv; - - nsAutoString id; - if (mCurrentElement) { - rv = mCurrentElement->GetAttribute(NS_ConvertASCIItoUCS2("id"), id); - NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get element's id"); - if (NS_FAILED(rv)) return rv; - } - -#if 0 - { - char* actionString = aEventName.ToNewCString(); - printf("Doing UpdateCommands(\"%s\")\n", actionString); - free(actionString); - } -#endif - - for (Updater* updater = mUpdaters; updater != nsnull; updater = updater->mNext) { - // Skip any nodes that don't match our 'events' or 'targets' - // filters. - if (! Matches(updater->mEvents, aEventName)) - continue; - - if (! Matches(updater->mTargets, id)) - continue; - - nsCOMPtr content = do_QueryInterface(updater->mElement); - NS_ASSERTION(content != nsnull, "not an nsIContent"); - if (! content) - return NS_ERROR_UNEXPECTED; - - nsCOMPtr document; - rv = content->GetDocument(*getter_AddRefs(document)); - NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get document"); - if (NS_FAILED(rv)) return rv; - - NS_ASSERTION(document != nsnull, "element has no document"); - if (! document) - continue; - -#ifdef NS_DEBUG - nsCAutoString aeventnameC; - aeventnameC.Assign(NS_ConvertUCS2toUTF8(aEventName)); - PR_LOG(gLog, PR_LOG_ALWAYS, - ("xulcmd[%p] update %p event=%s", - this, updater->mElement, - (const char*) aeventnameC)); -#endif - - PRInt32 count = document->GetNumberOfShells(); - for (PRInt32 i = 0; i < count; i++) { - nsCOMPtr shell = dont_AddRef(document->GetShellAt(i)); - if (! shell) - continue; - - // Retrieve the context in which our DOM event will fire. - nsCOMPtr context; - rv = shell->GetPresContext(getter_AddRefs(context)); - if (NS_FAILED(rv)) return rv; - - // Handle the DOM event - nsEventStatus status = nsEventStatus_eIgnore; - nsEvent event; - event.eventStructType = NS_EVENT; - event.message = NS_XUL_COMMAND_UPDATE; - content->HandleDOMEvent(context, &event, nsnull, NS_EVENT_FLAG_INIT, &status); - } - } - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::GetControllers(nsIControllers** aResult) -{ - //XXX: we should fix this so there's a generic interface that describes controllers, - // so this code would have no special knowledge of what object might have controllers. - if (mCurrentElement) { - nsCOMPtr xulElement = do_QueryInterface(mCurrentElement); - if (xulElement) - return xulElement->GetControllers(aResult); - - nsCOMPtr htmlTextArea = do_QueryInterface(mCurrentElement); - if (htmlTextArea) - return htmlTextArea->GetControllers(aResult); - - nsCOMPtr htmlInputElement = do_QueryInterface(mCurrentElement); - if (htmlInputElement) - return htmlInputElement->GetControllers(aResult); - } - else if (mCurrentWindow) { - nsCOMPtr domWindow = do_QueryInterface(mCurrentWindow); - if (domWindow) - return domWindow->GetControllers(aResult); - } - - *aResult = nsnull; - return NS_OK; -} - -///// -// nsIDOMFocusListener -///// - -nsresult -nsXULCommandDispatcher::Focus(nsIDOMEvent* aEvent) -{ - if (mSuppressFocus) - return NS_OK; - - nsCOMPtr t; - aEvent->GetOriginalTarget(getter_AddRefs(t)); - -#if 0 - printf("%d : Focus occurred on: ", this); - nsCOMPtr domDebugElement = do_QueryInterface(t); - if (domDebugElement) { - printf("A Focusable DOM Element"); - } - nsCOMPtr domDebugDocument = do_QueryInterface(t); - if (domDebugDocument) { - nsCOMPtr htmlDoc = do_QueryInterface(t); - if (htmlDoc) { - printf("Window with an HTML doc (happens twice)"); - } - else printf("Window with a XUL doc (happens twice)"); - } - printf("\n"); -#endif /* DEBUG_hyatt */ - - nsCOMPtr domElement = do_QueryInterface(t); - if (domElement && (domElement != mCurrentElement)) { - SetFocusedElement(domElement); - - // Also set focus to our innermost window. - // XXX Must be done for the Ender case, since ender causes a blur, - // but we don't hear the subsequent focus to the Ender window. - nsCOMPtr ownerDoc; - domElement->GetOwnerDocument(getter_AddRefs(ownerDoc)); - nsCOMPtr domWindow; - GetParentWindowFromDocument(ownerDoc, getter_AddRefs(domWindow)); - if (domWindow) - SetFocusedWindow(domWindow); - } - else { - // We're focusing a window. We only want to do an update commands - // if no element is focused. - nsCOMPtr domWindow; - nsCOMPtr domDoc = do_QueryInterface(t); - if (domDoc) { - GetParentWindowFromDocument(domDoc, getter_AddRefs(domWindow)); - if (domWindow) { - SetFocusedWindow(domWindow); - if (mCurrentElement) { - // Make sure this element is in our window. If not, we - // should clear this field. - nsCOMPtr ownerDoc; - mCurrentElement->GetOwnerDocument(getter_AddRefs(ownerDoc)); - nsCOMPtr windowDoc; - mCurrentWindow->GetDocument(getter_AddRefs(windowDoc)); - if (ownerDoc != windowDoc) - mCurrentElement = nsnull; - } - - if (!mCurrentElement) - UpdateCommands(NS_LITERAL_STRING("focus")); - } - } - } - - return NS_OK; -} - -nsresult -nsXULCommandDispatcher::Blur(nsIDOMEvent* aEvent) -{ - if (mSuppressFocus) - return NS_OK; - - nsCOMPtr t; - aEvent->GetOriginalTarget(getter_AddRefs(t)); - -#if 0 - printf("%d : Blur occurred on: ", this); - nsCOMPtr domDebugElement = do_QueryInterface(t); - if (domDebugElement) { - printf("A Focusable DOM Element"); - } - nsCOMPtr domDebugDocument = do_QueryInterface(t); - if (domDebugDocument) { - nsCOMPtr htmlDoc = do_QueryInterface(t); - if (htmlDoc) { - printf("Window with an HTML doc (happens twice)"); - } - else printf("Window with a XUL doc (happens twice)"); - } - printf("\n"); -#endif /* DEBUG_hyatt */ - - nsCOMPtr domElement = do_QueryInterface(t); - if (domElement) { - SetFocusedElement(nsnull); - } - - nsCOMPtr domWindow; - nsCOMPtr domDoc = do_QueryInterface(t); - if (domDoc) { - GetParentWindowFromDocument(domDoc, getter_AddRefs(domWindow)); - if (domWindow) - SetFocusedWindow(nsnull); - } - - return NS_OK; -} - -//////////////////////////////////////////////////////////////////////// -// nsIScriptObjectOwner interface -NS_IMETHODIMP -nsXULCommandDispatcher::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject) -{ - nsresult res = NS_OK; - nsIScriptGlobalObject *global = aContext->GetGlobalObject(); - - if (nsnull == mScriptObject) { - res = NS_NewScriptXULCommandDispatcher(aContext, (nsISupports *)(nsIDOMXULCommandDispatcher*)this, global, (void**)&mScriptObject); - } - *aScriptObject = mScriptObject; - - NS_RELEASE(global); - return res; -} - - -NS_IMETHODIMP -nsXULCommandDispatcher::SetScriptObject(void *aScriptObject) -{ - mScriptObject = aScriptObject; - return NS_OK; -} - - -PRBool -nsXULCommandDispatcher::Matches(const nsString& aList, - const nsAReadableString& aElement) -{ - if (aList.Equals(NS_LITERAL_STRING("*"))) - return PR_TRUE; // match _everything_! - - PRInt32 indx = aList.Find((const PRUnichar *)nsPromiseFlatString(aElement).get()); - if (indx == -1) - return PR_FALSE; // not in the list at all - - // okay, now make sure it's not a substring snafu; e.g., 'ur' - // found inside of 'blur'. - if (indx > 0) { - PRUnichar ch = aList[indx - 1]; - if (! nsCRT::IsAsciiSpace(ch) && ch != PRUnichar(',')) - return PR_FALSE; - } - - if (indx + aElement.Length() < aList.Length()) { - PRUnichar ch = aList[indx + aElement.Length()]; - if (! nsCRT::IsAsciiSpace(ch) && ch != PRUnichar(',')) - return PR_FALSE; - } - - return PR_TRUE; -} - - -nsresult -nsXULCommandDispatcher::GetParentWindowFromDocument(nsIDOMDocument* aDocument, nsIDOMWindowInternal** aWindow) -{ - nsCOMPtr objectOwner = do_QueryInterface(aDocument); - if(!objectOwner) return NS_OK; - - nsCOMPtr globalObject; - objectOwner->GetScriptGlobalObject(getter_AddRefs(globalObject)); - if(!globalObject) return NS_OK; - - nsCOMPtr domWindow = do_QueryInterface(globalObject); - *aWindow = domWindow; - NS_IF_ADDREF(*aWindow); - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::GetControllerForCommand(const nsAReadableString& aCommand, nsIController** _retval) -{ - nsPromiseFlatString flatCommand(aCommand); - const PRUnichar *command = flatCommand.get(); - *_retval = nsnull; - - nsCOMPtr controllers; - GetControllers(getter_AddRefs(controllers)); - if(controllers) { - nsCOMPtr controller; - controllers->GetControllerForCommand(command, getter_AddRefs(controller)); - if(controller) { - *_retval = controller; - NS_ADDREF(*_retval); - return NS_OK; - } - } - - nsCOMPtr currentWindow; - if (mCurrentElement) { - // Move up to the window. - nsCOMPtr domDoc; - mCurrentElement->GetOwnerDocument(getter_AddRefs(domDoc)); - nsCOMPtr domWindow; - GetParentWindowFromDocument(domDoc, getter_AddRefs(domWindow)); - currentWindow = do_QueryInterface(domWindow); - } - else if (mCurrentWindow) { - nsCOMPtr privateWin = do_QueryInterface(mCurrentWindow); - privateWin->GetPrivateParent(getter_AddRefs(currentWindow)); - } - else return NS_OK; - - while(currentWindow) { - nsCOMPtr domWindow = do_QueryInterface(currentWindow); - if(domWindow) { - nsCOMPtr controllers2; - domWindow->GetControllers(getter_AddRefs(controllers2)); - if(controllers2) { - nsCOMPtr controller; - controllers2->GetControllerForCommand(command, getter_AddRefs(controller)); - if(controller) { - *_retval = controller; - NS_ADDREF(*_retval); - return NS_OK; - } - } - } - nsCOMPtr parentPWindow = currentWindow; - parentPWindow->GetPrivateParent(getter_AddRefs(currentWindow)); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::GetSuppressFocusScroll(PRBool* aSuppressFocusScroll) -{ - *aSuppressFocusScroll = mSuppressFocusScroll; - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::SetSuppressFocusScroll(PRBool aSuppressFocusScroll) -{ - mSuppressFocusScroll = aSuppressFocusScroll; - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::GetSuppressFocus(PRBool* aSuppressFocus) -{ - if(mSuppressFocus) - *aSuppressFocus = PR_TRUE; - else - *aSuppressFocus = PR_FALSE; - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::SetSuppressFocus(PRBool aSuppressFocus) -{ - if(aSuppressFocus) - ++mSuppressFocus; - else if(mSuppressFocus > 0) - --mSuppressFocus; - - //printf("mSuppressFocus == %d\n", mSuppressFocus); - - // we are unsuppressing after activating, so update focus-related commands - // we need this to update commands in the case where an element is focussed. - if (!mSuppressFocus && mCurrentElement) - UpdateCommands(NS_LITERAL_STRING("focus")); - - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::GetActive(PRBool* aActive) -{ - //if(!mFocusInitialized) - // return PR_TRUE; - - *aActive = mActive; - return NS_OK; -} - -NS_IMETHODIMP -nsXULCommandDispatcher::SetActive(PRBool aActive) -{ - if(!mFocusInitialized) - mFocusInitialized = PR_TRUE; - - mActive = aActive; - return NS_OK; -} - diff --git a/rdf/content/src/nsXULCommandDispatcher.h b/rdf/content/src/nsXULCommandDispatcher.h index 537d3c7befb..e69de29bb2d 100644 --- a/rdf/content/src/nsXULCommandDispatcher.h +++ b/rdf/content/src/nsXULCommandDispatcher.h @@ -1,119 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * The contents of this file are subject to the Netscape Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All - * Rights Reserved. - * - * Original Author: David W. Hyatt (hyatt@netscape.com) - * - * Contributor(s): - */ - - -/* - - This is the focus manager for XUL documents. - -*/ - -#ifndef nsXULCommandDispatcher_h__ -#define nsXULCommandDispatcher_h__ - -#include "nsCOMPtr.h" -#include "nsIDOMXULCommandDispatcher.h" -#include "nsIDOMFocusListener.h" -#include "nsIScriptObjectOwner.h" -#include "nsWeakReference.h" -#include "nsIDOMNode.h" -#include "nsString.h" - -class nsIDOMElement; -class nsPIDOMWindow; - - -class nsXULCommandDispatcher : public nsIDOMXULCommandDispatcher, - public nsIDOMFocusListener, - public nsIScriptObjectOwner, - public nsSupportsWeakReference -{ -protected: - nsXULCommandDispatcher(void); - virtual ~nsXULCommandDispatcher(void); - -public: - - static NS_IMETHODIMP - Create(nsIDOMXULCommandDispatcher** aResult); - - // nsISupports - NS_DECL_ISUPPORTS - - // nsIDOMXULCommandDispatcher interface - NS_DECL_IDOMXULCOMMANDDISPATCHER - - // nsIDOMFocusListener - virtual nsresult Focus(nsIDOMEvent* aEvent); - virtual nsresult Blur(nsIDOMEvent* aEvent); - - // nsIDOMEventListener - virtual nsresult HandleEvent(nsIDOMEvent* anEvent) { return NS_OK; }; - - // nsIScriptObjectOwner interface - NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject); - NS_IMETHOD SetScriptObject(void *aScriptObject); - -public: - static nsresult GetParentWindowFromDocument(nsIDOMDocument* aElement, nsIDOMWindowInternal** aWindow); - -protected: - void* mScriptObject; // ???? - - // XXX THis was supposed to be WEAK, but c'mon, that's an accident - // waiting to happen! If somebody deletes the node, then asks us - // for the focus, we'll get killed! - nsCOMPtr mCurrentElement; // [OWNER] - nsCOMPtr mCurrentWindow; // [OWNER] - - //PRBool mSuppressFocus; - PRUint32 mSuppressFocus; - PRBool mSuppressFocusScroll; - PRBool mActive; - PRBool mFocusInitialized; - - class Updater { - public: - Updater(nsIDOMElement* aElement, - const nsAReadableString& aEvents, - const nsAReadableString& aTargets) - : mElement(aElement), - mEvents(aEvents), - mTargets(aTargets), - mNext(nsnull) - {} - - nsIDOMElement* mElement; // [WEAK] - nsString mEvents; - nsString mTargets; - Updater* mNext; - }; - - Updater* mUpdaters; - - PRBool Matches(const nsString& aList, - const nsAReadableString& aElement); -}; - -#endif // nsXULCommandDispatcher_h__ diff --git a/rdf/content/src/nsXULDocument.cpp b/rdf/content/src/nsXULDocument.cpp index 98e7132361f..5887459fa7b 100644 --- a/rdf/content/src/nsXULDocument.cpp +++ b/rdf/content/src/nsXULDocument.cpp @@ -1413,11 +1413,6 @@ nsXULDocument::SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject) if (mRootContent) mRootContent->SetDocument(nsnull, PR_TRUE, PR_TRUE); - // Break circular reference for the case where the currently - // focused window is ourself. - if (mCommandDispatcher) - mCommandDispatcher->SetFocusedWindow(nsnull); - // set all builder references to document to nsnull -- out of band notification // to break ownership cycle if (mBuilders) { @@ -3828,18 +3823,9 @@ nsXULDocument::Init() mNodeInfoManager->Init(mNameSpaceManager); // Create our command dispatcher and hook it up. - rv = nsXULCommandDispatcher::Create(getter_AddRefs(mCommandDispatcher)); + rv = nsXULCommandDispatcher::Create(this, getter_AddRefs(mCommandDispatcher)); NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a focus tracker"); if (NS_FAILED(rv)) return rv; - - nsCOMPtr commandDispatcher = - do_QueryInterface(mCommandDispatcher); - - if (commandDispatcher) { - // Take the focus tracker and add it as an event listener for focus and blur events. - AddEventListener(NS_LITERAL_STRING("focus"), commandDispatcher, PR_TRUE); - AddEventListener(NS_LITERAL_STRING("blur"), commandDispatcher, PR_TRUE); - } // Get the local store. Yeah, I know. I wish GetService() used a // 'void**', too.