From f77a66da83cbcdb6d070d2da5e1a85532d633aee Mon Sep 17 00:00:00 2001 From: "mats.palmgren%bredband.net" Date: Thu, 21 Jul 2005 00:15:27 +0000 Subject: [PATCH] Prevent having kbd focus inside the content document in Print Preview. b=244128 r=bryner sr=bzbarsky a=asa git-svn-id: svn://10.0.0.236/trunk@176372 18797224-902f-48f8-a5cc-f745e15eee43 --- .../events/src/nsEventStateManager.cpp | 24 +++-- mozilla/layout/base/nsDocumentViewer.cpp | 33 +++++++ .../printing/nsPrintPreviewListener.cpp | 89 ++++++++++++++----- 3 files changed, 117 insertions(+), 29 deletions(-) diff --git a/mozilla/content/events/src/nsEventStateManager.cpp b/mozilla/content/events/src/nsEventStateManager.cpp index d406cf9297d..177ced284db 100644 --- a/mozilla/content/events/src/nsEventStateManager.cpp +++ b/mozilla/content/events/src/nsEventStateManager.cpp @@ -5128,12 +5128,20 @@ nsEventStateManager::TabIntoDocument(nsIDocShell* aDocShell, nsCOMPtr treeItem = do_QueryInterface(aDocShell); treeItem->GetItemType(&itemType); + nsCOMPtr presContext; + aDocShell->GetPresContext(getter_AddRefs(presContext)); PRBool focusDocument; - if (!aForward || (itemType == nsIDocShellTreeItem::typeChrome)) - focusDocument = PR_FALSE; - else { - // Check for a frameset document - focusDocument = !(IsFrameSetDoc(aDocShell)); + if (presContext && + presContext->Type() == nsPresContext::eContext_PrintPreview) { + // Don't focus any content in print preview mode, bug 244128. + focusDocument = PR_TRUE; + } else { + if (!aForward || (itemType == nsIDocShellTreeItem::typeChrome)) + focusDocument = PR_FALSE; + else { + // Check for a frameset document + focusDocument = !(IsFrameSetDoc(aDocShell)); + } } if (focusDocument) { @@ -5143,10 +5151,8 @@ nsEventStateManager::TabIntoDocument(nsIDocShell* aDocShell, else { aDocShell->SetHasFocus(PR_FALSE); - nsCOMPtr pc; - aDocShell->GetPresContext(getter_AddRefs(pc)); - if (pc) { - nsIEventStateManager *docESM = pc->EventStateManager(); + if (presContext) { + nsIEventStateManager *docESM = presContext->EventStateManager(); // we are about to shift focus to aDocShell // keep track of the document, so we don't try to go back into it. diff --git a/mozilla/layout/base/nsDocumentViewer.cpp b/mozilla/layout/base/nsDocumentViewer.cpp index 926ebd3b789..3be86555e54 100644 --- a/mozilla/layout/base/nsDocumentViewer.cpp +++ b/mozilla/layout/base/nsDocumentViewer.cpp @@ -52,6 +52,7 @@ #include "nsIDocument.h" #include "nsPresContext.h" #include "nsIPresShell.h" +#include "nsIEventStateManager.h" #include "nsStyleSet.h" #include "nsIStyleSheet.h" #include "nsICSSStyleSheet.h" @@ -3948,6 +3949,37 @@ DocumentViewerImpl::ReturnToGalleyPresentation() #endif // NS_PRINTING && NS_PRINT_PREVIEW } +//------------------------------------------------------------ +// Reset ESM focus for all descendent doc shells. +static void +ResetFocusState(nsIDocShell* aDocShell) +{ + nsCOMPtr docShellEnumerator; + aDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent, + nsIDocShell::ENUMERATE_FORWARDS, + getter_AddRefs(docShellEnumerator)); + + nsCOMPtr currentDocShell; + nsCOMPtr currentContainer; + PRBool hasMoreDocShells; + while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMoreDocShells)) + && hasMoreDocShells) { + docShellEnumerator->GetNext(getter_AddRefs(currentContainer)); + currentDocShell = do_QueryInterface(currentContainer); + if (!currentDocShell) { + break; + } + nsCOMPtr presContext; + currentDocShell->GetPresContext(getter_AddRefs(presContext)); + nsIEventStateManager* esm = + presContext ? presContext->EventStateManager() : nsnull; + if (esm) { + esm->SetContentState(nsnull, NS_EVENT_STATE_FOCUS); + esm->SetFocusedContent(nsnull); + } + } +} + //------------------------------------------------------------ void DocumentViewerImpl::InstallNewPresentation() @@ -3966,6 +3998,7 @@ DocumentViewerImpl::InstallNewPresentation() nsCOMPtr docShell(do_QueryInterface(dstParentItem)); if (docShell) { docShell->SetHasFocus(PR_TRUE); + ::ResetFocusState(docShell); } } diff --git a/mozilla/layout/printing/nsPrintPreviewListener.cpp b/mozilla/layout/printing/nsPrintPreviewListener.cpp index 09fc1b99425..b086bcff241 100644 --- a/mozilla/layout/printing/nsPrintPreviewListener.cpp +++ b/mozilla/layout/printing/nsPrintPreviewListener.cpp @@ -21,6 +21,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Mats Palmgren * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -40,6 +41,11 @@ #include "nsIContent.h" #include "nsIDOMKeyEvent.h" #include "nsIDOMNSEvent.h" +#include "nsIDocument.h" +#include "nsIPresShell.h" +#include "nsIDocShell.h" +#include "nsPresContext.h" +#include "nsIEventStateManager.h" #include "nsLiteralString.h" NS_IMPL_ISUPPORTS1(nsPrintPreviewListener, nsIDOMEventListener) @@ -108,50 +114,93 @@ nsPrintPreviewListener::RemoveListeners() //------------------------------------------------------- // -// IsKeyOK +// GetActionForEvent // // Helper function to let certain key events thru // -static PRBool IsKeyOK(nsIDOMEvent* aEvent) +enum eEventAction { + eEventAction_Tab, eEventAction_ShiftTab, + eEventAction_Propagate, eEventAction_Suppress +}; + +static eEventAction +GetActionForEvent(nsIDOMEvent* aEvent) { - const PRUint32 kOKKeyCodes[] = {nsIDOMKeyEvent::DOM_VK_PAGE_UP, nsIDOMKeyEvent::DOM_VK_PAGE_DOWN, - nsIDOMKeyEvent::DOM_VK_UP, nsIDOMKeyEvent::DOM_VK_DOWN, - nsIDOMKeyEvent::DOM_VK_HOME, nsIDOMKeyEvent::DOM_VK_END, - nsIDOMKeyEvent::DOM_VK_TAB, 0}; + static const PRUint32 kOKKeyCodes[] = { + nsIDOMKeyEvent::DOM_VK_PAGE_UP, nsIDOMKeyEvent::DOM_VK_PAGE_DOWN, + nsIDOMKeyEvent::DOM_VK_UP, nsIDOMKeyEvent::DOM_VK_DOWN, + nsIDOMKeyEvent::DOM_VK_HOME, nsIDOMKeyEvent::DOM_VK_END + }; nsCOMPtr keyEvent(do_QueryInterface(aEvent)); if (keyEvent) { PRBool b; keyEvent->GetAltKey(&b); - if (b) return PR_FALSE; + if (b) return eEventAction_Suppress; keyEvent->GetCtrlKey(&b); - if (b) return PR_FALSE; + if (b) return eEventAction_Suppress; + keyEvent->GetShiftKey(&b); - if (b) return PR_FALSE; PRUint32 keyCode; keyEvent->GetKeyCode(&keyCode); - PRInt32 i = 0; - while (kOKKeyCodes[i] != 0) { + if (keyCode == nsIDOMKeyEvent::DOM_VK_TAB) + return b ? eEventAction_ShiftTab : eEventAction_Tab; + + if (b) return eEventAction_Suppress; + + for (PRUint32 i = 0; i < sizeof(kOKKeyCodes)/sizeof(kOKKeyCodes[0]); ++i) { if (keyCode == kOKKeyCodes[i]) { - return PR_TRUE; + return eEventAction_Propagate; } - i++; } } - return PR_FALSE; + return eEventAction_Suppress; } -NS_IMETHODIMP nsPrintPreviewListener::HandleEvent(nsIDOMEvent* aKeyEvent) -{ +NS_IMETHODIMP +nsPrintPreviewListener::HandleEvent(nsIDOMEvent* aEvent) +{ nsCOMPtr target; - nsCOMPtr nsEvent = do_QueryInterface(aKeyEvent); + nsCOMPtr nsEvent = do_QueryInterface(aEvent); if (nsEvent) nsEvent->GetOriginalTarget(getter_AddRefs(target)); nsCOMPtr content(do_QueryInterface(target)); - if (content && !content->IsContentOfType(nsIContent::eXUL) && !IsKeyOK(aKeyEvent)) { - aKeyEvent->StopPropagation(); - aKeyEvent->PreventDefault(); + if (content && !content->IsContentOfType(nsIContent::eXUL)) { + eEventAction action = ::GetActionForEvent(aEvent); + switch (action) { + case eEventAction_Tab: + case eEventAction_ShiftTab: + { + nsAutoString eventString; + aEvent->GetType(eventString); + if (eventString == NS_LITERAL_STRING("keydown")) { + // Handle tabbing explicitly here since we don't want focus ending up + // inside the content document, bug 244128. + nsIDocument* doc = content->GetCurrentDoc(); + NS_ASSERTION(doc, "no document"); + + nsIDocument* parentDoc = doc->GetParentDocument(); + NS_ASSERTION(parentDoc, "no parent document"); + nsIEventStateManager* esm = + parentDoc->GetShellAt(0)->GetPresContext()->EventStateManager(); + if (esm) { + esm->SetContentState(nsnull, NS_EVENT_STATE_FOCUS); + PRBool forward = (action == eEventAction_Tab); + esm->ShiftFocus(forward, + forward ? nsnull : parentDoc->FindContentForSubDocument(doc)); + } + } + } + // fall-through + case eEventAction_Suppress: + aEvent->StopPropagation(); + aEvent->PreventDefault(); + break; + case eEventAction_Propagate: + // intentionally empty + break; + } } return NS_OK; }