зеркало из https://github.com/mozilla/pjs.git
adding pane/frameset/frame/iframe navigation
Bug 24423 r=joki,saari a=hyatt
This commit is contained in:
Родитель
e919fcd1d2
Коммит
ade2376885
|
@ -33,6 +33,7 @@ class nsIDOMEvent;
|
|||
class nsIFrame;
|
||||
class nsIView;
|
||||
class nsIWidget;
|
||||
class nsIDocument;
|
||||
|
||||
/*
|
||||
* Event listener manager interface.
|
||||
|
@ -78,6 +79,14 @@ public:
|
|||
NS_IMETHOD GetNextTabbableContent(nsIContent* aRootContent, nsIFrame* aFrame,
|
||||
PRBool forward, nsIContent** aResult) = 0;
|
||||
|
||||
NS_IMETHOD GetNextTabbableIndexContent(nsIContent* aRootContent,
|
||||
PRBool forward,
|
||||
PRBool aStartOver,
|
||||
nsIContent** aResult) = 0;
|
||||
|
||||
NS_IMETHOD HasPositiveTabIndex(nsIContent* aContent,
|
||||
PRBool* aResult) = 0;
|
||||
|
||||
// This is an experiement and may be temporary
|
||||
NS_IMETHOD ConsumeFocusEvents(PRBool aDoConsume) = 0;
|
||||
|
||||
|
@ -92,6 +101,14 @@ public:
|
|||
|
||||
// Method for moving the focus forward/back.
|
||||
NS_IMETHOD MoveFocus(PRBool aDirection, nsIContent* aRoot)=0;
|
||||
|
||||
// Method for indicating that we are at top of a doc in a special situation
|
||||
NS_IMETHOD SetSpecialTopOfDoc(PRBool aIsAtTop)=0;
|
||||
|
||||
//-- Special Enums needed for DocShell Identification
|
||||
enum eDocType {eChrome = 0, eGenericContent, eFrameSet, eFrame, eIFrame};
|
||||
NS_IMETHOD FigureOutKindOfDoc(nsIDocument* aDoc, eDocType* aDocType) = 0;
|
||||
|
||||
};
|
||||
|
||||
#define NS_EVENT_STATE_UNSPECIFIED 0x0000
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -37,6 +37,7 @@ class nsIScrollableView;
|
|||
class nsIPresShell;
|
||||
class nsITreeFrame;
|
||||
class nsIFrameSelection;
|
||||
class nsIDocShell;
|
||||
|
||||
// mac uses click-hold context menus, a holdover from 4.x
|
||||
#ifdef XP_MAC
|
||||
|
@ -113,6 +114,10 @@ public:
|
|||
|
||||
NS_IMETHOD MoveFocus(PRBool aDirection, nsIContent* aRoot);
|
||||
|
||||
NS_IMETHOD SetSpecialTopOfDoc(PRBool aIsAtTop) { mSpecialTopOfDoc = aIsAtTop; return NS_OK; }
|
||||
|
||||
NS_IMETHOD FigureOutKindOfDoc(nsIDocument* aDoc, eDocType* aDocType);
|
||||
|
||||
protected:
|
||||
void UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus);
|
||||
void GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIEvent* aEvent);
|
||||
|
@ -122,6 +127,13 @@ protected:
|
|||
PRBool ChangeFocus(nsIContent* aFocus, nsIFrame* aFocusFrame, PRBool aSetFocus);
|
||||
void ShiftFocus(PRBool forward, nsIContent* aRoot=nsnull);
|
||||
NS_IMETHOD GetNextTabbableContent(nsIContent* aRootContent, nsIFrame* aFrame, PRBool forward, nsIContent** aResult);
|
||||
NS_IMETHOD GetNextTabbableIndexContent(nsIContent* aRootContent,
|
||||
PRBool forward,
|
||||
PRBool aStartOver,
|
||||
nsIContent** aResult);
|
||||
NS_IMETHOD HasPositiveTabIndex(nsIContent* aContent,
|
||||
PRBool* aResult);
|
||||
|
||||
PRInt32 GetNextTabIndex(nsIContent* aParent, PRBool foward);
|
||||
NS_IMETHOD SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aContent);
|
||||
PRBool CheckDisabled(nsIContent* aContent);
|
||||
|
@ -129,6 +141,26 @@ protected:
|
|||
void EnsureDocument(nsIPresContext* aPresContext);
|
||||
void FlushPendingEvents(nsIPresContext* aPresContext);
|
||||
|
||||
//---------------------------------------------
|
||||
// DocShell Focus Traversal Methods
|
||||
//---------------------------------------------
|
||||
|
||||
void ShiftFocusByDoc(PRBool forward, nsIContent* aRoot=nsnull);
|
||||
PRBool FocusAfterHTMLFrameDoc(nsIDocShell* aDocShell, nsIDocShell* aParentDocShell, PRBool aForward);
|
||||
PRBool FocusAfterHTMLIFrameDoc(nsIDocShell* aDocShell, nsIDocShell* aParentDocShell, PRBool aForward, PRBool& aFocusDoc);
|
||||
PRBool FocusWithinHTMLFrameDoc(nsIContent* aRootContent, nsIPresShell* aPresShell, PRBool aForward, PRBool& aDoFocusAvailDocShells);
|
||||
PRBool FocusWithinHTMLIFrameDoc(nsIContent* aNextContent, PRBool aForward);
|
||||
nsIContent* GetLastContent(nsIDocShell* aDocShell);
|
||||
nsIContent* GetLastContent(nsIContent* aRootContent);
|
||||
nsIDocShell* GetDocShellFromContent(nsIDocShell* aParentDocShell, nsIContent* aContent);
|
||||
nsIDocShell* GetNextDocShell(nsIDocShell* aParentDS, nsIDocShell* aCurrentDS, PRBool aForward);
|
||||
void ForceUpdate(nsIDocShell* aDocShell);
|
||||
nsresult GetDocShellsFromDoc(nsIDocument* aDocument, nsIDocShell** aDocShell, nsIDocShell** aParentDS);
|
||||
PRBool IsLastFrameInFrameSet(nsIContent* aLastFrameContent);
|
||||
nsIContent* FindContentForDocShell(nsIPresShell* aPresShell, nsIContent* aContent, nsIDocShell* aDocShell);
|
||||
PRBool IsFrameSetDoc(nsIContent* aContent);
|
||||
|
||||
|
||||
// These functions are for mousewheel scrolling
|
||||
nsIScrollableView* GetNearestScrollingView(nsIView* aView);
|
||||
nsresult GetParentScrollingView(nsMouseScrollEvent* aEvent,
|
||||
|
@ -188,6 +220,10 @@ protected:
|
|||
PRBool mConsumeFocusEvents;
|
||||
PRInt32 mLockCursor;
|
||||
|
||||
// DocShell Traversal Data Memebers
|
||||
PRPackedBool mSpecialTopOfDoc;
|
||||
nsCOMPtr<nsIContent> mLastContentFocus;
|
||||
|
||||
//Anti-recursive stack controls
|
||||
nsIContent* mFirstBlurEvent;
|
||||
nsIContent* mFirstFocusEvent;
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "nsISecurityEventSink.h"
|
||||
#include "nsScriptSecurityManager.h"
|
||||
#include "nsDocumentCharsetInfoCID.h"
|
||||
#include "nsICanvasFrame.h"
|
||||
|
||||
// Local Includes
|
||||
#include "nsDocShell.h"
|
||||
|
@ -117,6 +118,9 @@ static NS_DEFINE_CID(kPluginManagerCID, NS_PLUGINMANAGER_CID);
|
|||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
||||
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
#ifdef DEBUG_rods
|
||||
//#define DEBUG_DOCSHELL_FOCUS
|
||||
#endif
|
||||
//
|
||||
// Local function prototypes
|
||||
//
|
||||
|
@ -137,6 +141,31 @@ static NS_METHOD AHTC_WriteFunc(nsIInputStream * in,
|
|||
static PRLogModuleInfo* gDocShellLog;
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
//*** nsDocShellFocusController
|
||||
//*****************************************************************************
|
||||
|
||||
class nsDocShellFocusController
|
||||
{
|
||||
|
||||
public:
|
||||
static nsDocShellFocusController* GetInstance() { return &mDocShellFocusControllerSingleton; }
|
||||
virtual ~nsDocShellFocusController(){}
|
||||
|
||||
void Focus(nsIDocShell* aDS);
|
||||
void ClosingDown(nsIDocShell* aDS);
|
||||
|
||||
protected:
|
||||
nsDocShellFocusController(){}
|
||||
|
||||
nsIDocShell* mFocusedDocShell; // very weak reference
|
||||
|
||||
private:
|
||||
static nsDocShellFocusController mDocShellFocusControllerSingleton;
|
||||
};
|
||||
|
||||
nsDocShellFocusController nsDocShellFocusController::mDocShellFocusControllerSingleton;
|
||||
|
||||
//*****************************************************************************
|
||||
//*** nsDocShell: Object Management
|
||||
//*****************************************************************************
|
||||
|
@ -175,6 +204,10 @@ nsDocShell::nsDocShell():
|
|||
|
||||
nsDocShell::~nsDocShell()
|
||||
{
|
||||
nsDocShellFocusController* dsfc = nsDocShellFocusController::GetInstance();
|
||||
if (dsfc) {
|
||||
dsfc->ClosingDown(this);
|
||||
}
|
||||
Destroy();
|
||||
}
|
||||
|
||||
|
@ -1492,9 +1525,92 @@ nsDocShell::GetTreeOwner(nsIDocShellTreeOwner ** aTreeOwner)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DOCSHELL_FOCUS
|
||||
static void
|
||||
PrintDocTree(nsIDocShellTreeNode * aParentNode, int aLevel)
|
||||
{
|
||||
for (PRInt32 i=0;i<aLevel;i++) printf(" ");
|
||||
|
||||
PRInt32 childWebshellCount;
|
||||
aParentNode->GetChildCount(&childWebshellCount);
|
||||
nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(aParentNode));
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentAsItem(do_QueryInterface(aParentNode));
|
||||
PRInt32 type;
|
||||
parentAsItem->GetItemType(&type);
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
parentAsDocShell->GetPresShell(getter_AddRefs(presShell));
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
parentAsDocShell->GetPresContext(getter_AddRefs(presContext));
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
presShell->GetDocument(getter_AddRefs(doc));
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo;
|
||||
doc->GetScriptGlobalObject(getter_AddRefs(sgo));
|
||||
nsCOMPtr<nsIDOMWindowInternal> domwin(do_QueryInterface(sgo));
|
||||
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
nsCOMPtr<nsIViewManager> vm;
|
||||
presShell->GetViewManager(getter_AddRefs(vm));
|
||||
if (vm) {
|
||||
vm->GetWidget(getter_AddRefs(widget));
|
||||
}
|
||||
nsCOMPtr<nsIEventStateManager> esm;
|
||||
presContext->GetEventStateManager(getter_AddRefs(esm));
|
||||
nsCOMPtr<nsIContent>rootContent(getter_AddRefs(doc->GetRootContent()));
|
||||
|
||||
printf("DS %p Ty %s Doc %p DW %p EM %p CN %p\n",
|
||||
parentAsDocShell.get(),
|
||||
type==nsIDocShellTreeItem::typeChrome?"Chr":"Con",
|
||||
doc.get(), domwin.get(), esm.get(), rootContent.get());
|
||||
|
||||
if (childWebshellCount > 0) {
|
||||
for (PRInt32 i=0;i<childWebshellCount;i++) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> child;
|
||||
aParentNode->GetChildAt(i, getter_AddRefs(child));
|
||||
nsCOMPtr<nsIDocShellTreeNode> childAsNode(do_QueryInterface(child));
|
||||
PrintDocTree(childAsNode, aLevel+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PrintDocTree(nsIDocShellTreeNode * aParentNode)
|
||||
{
|
||||
NS_ASSERTION(aParentNode, "Pointer is null!");
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> item(do_QueryInterface(aParentNode));
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
item->GetParent(getter_AddRefs(parentItem));
|
||||
while (parentItem) {
|
||||
nsCOMPtr<nsIDocShellTreeItem>tmp;
|
||||
parentItem->GetParent(getter_AddRefs(tmp));
|
||||
if (!tmp) {
|
||||
break;
|
||||
}
|
||||
parentItem = tmp;
|
||||
}
|
||||
|
||||
if (!parentItem) {
|
||||
parentItem = do_QueryInterface(aParentNode);
|
||||
}
|
||||
|
||||
if (parentItem) {
|
||||
nsCOMPtr<nsIDocShellTreeNode> parentAsNode(do_QueryInterface(parentItem));
|
||||
PrintDocTree(parentAsNode, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetTreeOwner(nsIDocShellTreeOwner * aTreeOwner)
|
||||
{
|
||||
#ifdef DEBUG_DOCSHELL_FOCUS
|
||||
nsCOMPtr<nsIDocShellTreeNode> node(do_QueryInterface(aTreeOwner));
|
||||
if (node) {
|
||||
PrintDocTree(node);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Don't automatically set the progress based on the tree owner for frames
|
||||
if (!IsFrame()) {
|
||||
nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(mLoadCookie));
|
||||
|
@ -2480,9 +2596,31 @@ nsDocShell::GetMainWidget(nsIWidget ** aMainWidget)
|
|||
return GetParentWidget(aMainWidget);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocShell::ForceUpdate(nsIDocShell* aDocShell)
|
||||
{
|
||||
NS_ASSERTION(aDocShell, "DocShell is null!");
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
aDocShell->GetPresShell(getter_AddRefs(presShell));
|
||||
|
||||
nsCOMPtr<nsIViewManager> vm;
|
||||
presShell->GetViewManager(getter_AddRefs(vm));
|
||||
if (vm) {
|
||||
vm->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
|
||||
#ifdef DEBUG_DOCSHELL_FOCUS
|
||||
printf("nsDocShell::ForceUpdate - DS: %p **********\n", aDocShell);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetFocus()
|
||||
{
|
||||
#ifdef DEBUG_DOCSHELL_FOCUS
|
||||
printf("nsDocShell::SetFocus %p\n", (nsIDocShell*)this);
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
GetPresShell(getter_AddRefs(presShell));
|
||||
|
@ -2522,25 +2660,185 @@ nsDocShell::SetFocus()
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIContent> focusContent;
|
||||
esm->GetNextTabbableContent(rootContent, nsnull, PR_TRUE,
|
||||
getter_AddRefs(focusContent));
|
||||
|
||||
// Figure out what type of document this is
|
||||
// if parent doc is content then set focus to document itself
|
||||
// and set the "special" flag so it knows we are at the beginning
|
||||
// of the document
|
||||
PRBool doFocusDoc = PR_FALSE;
|
||||
nsIDocShellTreeItem* treeItem = NS_STATIC_CAST(nsIDocShellTreeItem *, this);
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
treeItem->GetParent(getter_AddRefs(parentItem));
|
||||
if (parentItem) {
|
||||
PRInt32 type;
|
||||
parentItem->GetItemType(&type);
|
||||
doFocusDoc = type == nsIDocShellTreeItem::typeContent;
|
||||
}
|
||||
|
||||
// Tell itself (and the DocShellFocusController) who has focus
|
||||
// this way focus gets removed from the currently focused DocShell
|
||||
SetHasFocus(PR_TRUE);
|
||||
|
||||
// Either focus the document or the "first" piece of content
|
||||
if (doFocusDoc) {
|
||||
esm->SetContentState(nsnull, NS_EVENT_STATE_FOCUS);
|
||||
esm->SetSpecialTopOfDoc(PR_TRUE);
|
||||
} else {
|
||||
nsCOMPtr<nsIContent> content;
|
||||
esm->GetNextTabbableIndexContent(rootContent, PR_TRUE, PR_TRUE, getter_AddRefs(content));
|
||||
if (!content) {
|
||||
esm->GetNextTabbableContent(rootContent, nsnull, PR_TRUE,
|
||||
getter_AddRefs(focusContent));
|
||||
} else {
|
||||
focusContent = content;
|
||||
}
|
||||
}
|
||||
|
||||
if (focusContent) {
|
||||
nsIFrame *focusFrame = nsnull;
|
||||
presShell->GetPrimaryFrameFor(focusContent, &focusFrame);
|
||||
esm->ChangeFocus(focusContent, focusFrame, PR_TRUE);
|
||||
SetCanvasHasFocus(PR_FALSE);
|
||||
} else {
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo;
|
||||
document->GetScriptGlobalObject(getter_AddRefs(sgo));
|
||||
if (sgo) {
|
||||
nsCOMPtr<nsIDOMWindowInternal> domwin(do_QueryInterface(sgo));
|
||||
if (domwin)
|
||||
if (domwin) {
|
||||
domwin->Focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// Finds the very next DocShell after the arg aNode
|
||||
nsresult
|
||||
nsDocShell::FindNextChildDoc(nsIDocShellTreeNode* aNode, PRBool aForward, nsIDocShell** aDocShell)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNode);
|
||||
*aDocShell = nsnull;
|
||||
|
||||
PRInt32 count;
|
||||
aNode->GetChildCount(&count);
|
||||
if (count > 0) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> child;
|
||||
aNode->GetChildAt(aForward?0:count-1, getter_AddRefs(child));
|
||||
NS_ASSERTION(child, "Child can't be null!");
|
||||
nsCOMPtr<nsIDocShell>ds = do_QueryInterface(child);
|
||||
*aDocShell = ds.get();
|
||||
NS_ADDREF(*aDocShell);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// Finds the very next DocShell after the arg aNode
|
||||
PRBool
|
||||
nsDocShell::FocusNextChild(nsIBaseWindow * aCurrentFocus, PRBool aForward)
|
||||
{
|
||||
// Make sure the current focused item is content
|
||||
// and if so find the next content DS and give it focus
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(aCurrentFocus));
|
||||
if (treeItem) {
|
||||
PRInt32 type;
|
||||
treeItem->GetItemType(&type);
|
||||
if (type == nsIDocShellTreeItem::typeContent) {
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aCurrentFocus));
|
||||
if (!docShell) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeNode> treeNode(do_QueryInterface(aCurrentFocus));
|
||||
if (!treeNode) return PR_FALSE;
|
||||
PRInt32 childCount;
|
||||
treeNode->GetChildCount(&childCount);
|
||||
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
docShell->GetPresContext(getter_AddRefs(presContext));
|
||||
if (!presContext) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIEventStateManager> esm;
|
||||
presContext->GetEventStateManager(getter_AddRefs(esm));
|
||||
if (!esm) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
docShell->GetPresShell(getter_AddRefs(presShell));
|
||||
if (!presShell) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
presShell->GetDocument(getter_AddRefs(document));
|
||||
if (!document) return PR_FALSE;
|
||||
|
||||
nsIEventStateManager::eDocType docType;
|
||||
if (NS_FAILED(esm->FigureOutKindOfDoc(document, &docType))) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIContent> rootContent = getter_AddRefs(document->GetRootContent());
|
||||
if (!rootContent) return PR_FALSE;
|
||||
|
||||
PRBool hasTabIndexes;
|
||||
esm->HasPositiveTabIndex(rootContent, &hasTabIndexes); // ignoring return code
|
||||
|
||||
nsIDocShell* thisDS = NS_STATIC_CAST(nsIDocShell *, this);
|
||||
// leave printf for debugging
|
||||
//printf("DS: %p TBI: %s chld: %s DSE: %s\n", docShell.get(), hasTabIndexes?"Y":"N", childCount > 0?"Y":"N", docShell.get() != thisDS?"Y":"N");
|
||||
if (docType == nsIEventStateManager::eFrameSet ||
|
||||
(docShell.get() != thisDS && !hasTabIndexes && childCount > 0)) {
|
||||
nsCOMPtr<nsIDocShell> childDS;
|
||||
if (NS_SUCCEEDED(FindNextChildDoc(treeNode, aForward, getter_AddRefs(childDS)))) {
|
||||
nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(childDS));
|
||||
if (NS_SUCCEEDED(baseWin->SetFocus())) {
|
||||
MakeSureOfSetFocus(baseWin);
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else if (docShell.get() != thisDS) {
|
||||
nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(docShell));
|
||||
if (NS_SUCCEEDED(baseWin->SetFocus())) {
|
||||
MakeSureOfSetFocus(baseWin);
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
// This is just in case we run into a window that
|
||||
// isn't implemented nsDocShell, because if it is implemented
|
||||
// by this class then all this will have already been done.
|
||||
void
|
||||
nsDocShell::MakeSureOfSetFocus(nsIBaseWindow * aCurrentFocus, nsIDocShell* aDocShell)
|
||||
{
|
||||
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(aCurrentFocus);
|
||||
if (!docShell) {
|
||||
if (aDocShell != nsnull) {
|
||||
docShell = aDocShell;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool hasFocus;
|
||||
docShell->GetHasFocus(&hasFocus);
|
||||
|
||||
// leave printf for debugging purposes
|
||||
//printf(">>>>>>>>>> nsDocShell::SetHasFocus: %p %s\n", docShell.get(), hasFocus?"Yes":"No");
|
||||
|
||||
if (!hasFocus) {
|
||||
docShell->SetHasFocus(PR_TRUE);
|
||||
|
||||
nsDocShellFocusController* dsfc = nsDocShellFocusController::GetInstance();
|
||||
if (dsfc) {
|
||||
dsfc->Focus(docShell);
|
||||
}
|
||||
ForceUpdate(docShell);// Force Paint Here
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::FocusAvailable(nsIBaseWindow * aCurrentFocus,
|
||||
PRBool aForward, PRBool * aTookFocus)
|
||||
|
@ -2561,9 +2859,20 @@ nsDocShell::FocusAvailable(nsIBaseWindow * aCurrentFocus,
|
|||
ret = chromeFocus->FocusNextElement();
|
||||
else
|
||||
ret = chromeFocus->FocusPrevElement();
|
||||
|
||||
// For DocShell's not implemented by this class
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(chromeFocus));
|
||||
MakeSureOfSetFocus(nsnull, docShell);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DOCSHELL_FOCUS
|
||||
nsIDocShellTreeNode* node = NS_STATIC_CAST(nsIDocShellTreeNode *, this);
|
||||
if (node) {
|
||||
PrintDocTree(node);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Otherwise, first person we should call is the parent, or the
|
||||
// docshell tree owner.
|
||||
nsCOMPtr<nsIBaseWindow> nextCallWin(do_QueryInterface(mParent));
|
||||
|
@ -2573,6 +2882,14 @@ nsDocShell::FocusAvailable(nsIBaseWindow * aCurrentFocus,
|
|||
//If the current focus is us, offer it to the next owner.
|
||||
if (aCurrentFocus == NS_STATIC_CAST(nsIBaseWindow *, this)) {
|
||||
if (nextCallWin) {
|
||||
|
||||
// Make sure the current focused item is content
|
||||
// and if so find the next content DS and give it focus
|
||||
if (FocusNextChild(aCurrentFocus, aForward)) {
|
||||
*aTookFocus = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ret = nextCallWin->FocusAvailable(aCurrentFocus,
|
||||
aForward, aTookFocus);
|
||||
if (NS_SUCCEEDED(ret) && *aTookFocus)
|
||||
|
@ -2595,9 +2912,18 @@ nsDocShell::FocusAvailable(nsIBaseWindow * aCurrentFocus,
|
|||
child(do_QueryInterface((nsISupports *) mChildren.ElementAt(i)));
|
||||
//If we have focus we offer it to our first child.
|
||||
if (aCurrentFocus == NS_STATIC_CAST(nsIBaseWindow *, this)) {
|
||||
// Make sure the current focused item is content
|
||||
// and if so find the next content DS and give it focus
|
||||
if (FocusNextChild(child, aForward)) {
|
||||
*aTookFocus = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(child->SetFocus())) {
|
||||
*aTookFocus = PR_TRUE;
|
||||
return NS_OK;
|
||||
// For DocShell's not implemented by this class
|
||||
MakeSureOfSetFocus(child);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
//If we don't have focus, find the child that does then
|
||||
|
@ -2608,6 +2934,8 @@ nsDocShell::FocusAvailable(nsIBaseWindow * aCurrentFocus,
|
|||
do_QueryInterface((nsISupports *) mChildren.ElementAt(i));
|
||||
if (NS_SUCCEEDED(child->SetFocus())) {
|
||||
*aTookFocus = PR_TRUE;
|
||||
// For DocShell's not implemented by this class
|
||||
MakeSureOfSetFocus(child);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
@ -5375,6 +5703,78 @@ nsDocShell::IsFrame()
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetHasFocus(PRBool *aHasFocus)
|
||||
{
|
||||
*aHasFocus = mHasFocus;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetHasFocus(PRBool aHasFocus)
|
||||
{
|
||||
if (mParent != nsnull) {
|
||||
PRInt32 type;
|
||||
mParent->GetItemType(&type);
|
||||
if (type != nsIDocShellTreeItem::typeContent) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// leave printf for debgging purposes
|
||||
//printf(">>>>>>>>>> nsDocShell::SetHasFocus: %p %s\n", this, aHasFocus?"Yes":"No");
|
||||
|
||||
mHasFocus = aHasFocus;
|
||||
|
||||
nsDocShellFocusController* dsfc = nsDocShellFocusController::GetInstance();
|
||||
if (dsfc && aHasFocus) {
|
||||
dsfc->Focus(this);
|
||||
}
|
||||
|
||||
SetCanvasHasFocus(aHasFocus);
|
||||
|
||||
// Force Paint Here
|
||||
ForceUpdate(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Tells the HTMLFrame/CanvasFrame that is now has focus
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetCanvasHasFocus(PRBool aCanvasHasFocus)
|
||||
{
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
GetPresShell(getter_AddRefs(presShell));
|
||||
if (!presShell) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
presShell->GetDocument(getter_AddRefs(doc));
|
||||
if (!doc) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIContent> rootContent = getter_AddRefs(doc->GetRootContent());
|
||||
if (!rootContent) return NS_ERROR_FAILURE;
|
||||
|
||||
nsIFrame* frame;
|
||||
presShell->GetPrimaryFrameFor(rootContent, &frame);
|
||||
if (frame != nsnull) {
|
||||
frame->GetParent(&frame);
|
||||
if (frame != nsnull) {
|
||||
nsICanvasFrame* canvasFrame;
|
||||
if (NS_SUCCEEDED(frame->QueryInterface(NS_GET_IID(nsICanvasFrame), (void**)&canvasFrame))) {
|
||||
canvasFrame->SetHasFocus(aCanvasHasFocus);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetCanvasHasFocus(PRBool *aCanvasHasFocus)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*** nsRefreshTimer: Object Management
|
||||
//*****************************************************************************
|
||||
|
@ -5458,3 +5858,32 @@ nsRefreshTimer::Notify(nsITimer * aTimer)
|
|||
mDocShell->LoadURI(mURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
//*** nsDocShellFocusController: Object Management
|
||||
//*****************************************************************************
|
||||
void
|
||||
nsDocShellFocusController::Focus(nsIDocShell* aDocShell)
|
||||
{
|
||||
#ifdef DEBUG_DOCSHELL_FOCUS
|
||||
printf("****** nsDocShellFocusController Focus To: %p Blur To: %p\n", aDocShell, mFocusedDocShell);
|
||||
#endif
|
||||
|
||||
if (aDocShell != mFocusedDocShell) {
|
||||
if (mFocusedDocShell) {
|
||||
mFocusedDocShell->SetHasFocus(PR_FALSE);
|
||||
}
|
||||
mFocusedDocShell = aDocShell;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// This is need for when the document with focus goes away
|
||||
void
|
||||
nsDocShellFocusController::ClosingDown(nsIDocShell* aDocShell)
|
||||
{
|
||||
if (aDocShell == mFocusedDocShell) {
|
||||
mFocusedDocShell = nsnull;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -261,6 +261,12 @@ protected:
|
|||
|
||||
PRBool IsFrame();
|
||||
|
||||
// DocShell Focus helpers
|
||||
void ForceUpdate(nsIDocShell* aDocShell);
|
||||
nsresult FindNextChildDoc(nsIDocShellTreeNode* aNode, PRBool aForward, nsIDocShell** aDocShell);
|
||||
PRBool FocusNextChild(nsIBaseWindow * aCurrentFocus, PRBool aForward);
|
||||
void MakeSureOfSetFocus(nsIBaseWindow * aCurrentFocus, nsIDocShell* aDocShell = nsnull);
|
||||
|
||||
//
|
||||
// Helper method that is called when a new document (including any
|
||||
// sub-documents - ie. frames) has been completely loaded.
|
||||
|
@ -306,6 +312,8 @@ protected:
|
|||
PRUint32 mAppType;
|
||||
PRInt32 mChildOffset; // Offset in the parent's child list.
|
||||
PRUint32 mBusyFlags;
|
||||
PRPackedBool mHasFocus;
|
||||
|
||||
// Reference to the SHEntry for this docshell until the page is destroyed.
|
||||
// Somebody give me better name
|
||||
nsCOMPtr<nsISHEntry> OSHE;
|
||||
|
|
|
@ -237,6 +237,16 @@ interface nsIDocShell : nsISupports
|
|||
*/
|
||||
attribute long marginHeight;
|
||||
|
||||
/*
|
||||
* Tells the DocShell that it now has focus or has lost focus
|
||||
*/
|
||||
attribute boolean hasFocus;
|
||||
|
||||
/*
|
||||
* Tells the docshell whether the canvas should have focus
|
||||
*/
|
||||
attribute boolean canvasHasFocus;
|
||||
|
||||
/**
|
||||
* Current busy state for DocShell
|
||||
*/
|
||||
|
|
|
@ -1719,8 +1719,9 @@ NS_IMETHODIMP GlobalWindowImpl::Focus()
|
|||
treeOwnerAsWin->SetVisibility(PR_TRUE);
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
if (mDocShell)
|
||||
if (mDocShell) {
|
||||
mDocShell->GetPresShell(getter_AddRefs(presShell));
|
||||
}
|
||||
|
||||
nsresult result = NS_OK;
|
||||
if (presShell) {
|
||||
|
@ -1761,6 +1762,10 @@ NS_IMETHODIMP GlobalWindowImpl::Blur()
|
|||
newFocusWin->SetFocus();
|
||||
}
|
||||
|
||||
if (mDocShell) {
|
||||
mDocShell->SetHasFocus(PR_FALSE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,3 +39,4 @@ nsIFrameTraversal.h
|
|||
nsIObjectFrame.h
|
||||
nsIImageFrame.h
|
||||
nsITextFrame.h
|
||||
nsICanvasFrame.h
|
||||
|
|
|
@ -67,6 +67,7 @@ nsILayoutHistoryState.h \
|
|||
nsIStatefulFrame.h \
|
||||
nsIScrollableFrame.h \
|
||||
nsIScrollableViewProvider.h \
|
||||
nsICanvasFrame.h \
|
||||
$(NULL)
|
||||
|
||||
ifdef IBMBIDI
|
||||
|
|
|
@ -60,6 +60,7 @@ EXPORTS = \
|
|||
nsIScrollableFrame.h \
|
||||
nsIScrollableViewProvider.h \
|
||||
nsIPrintContext.h \
|
||||
nsICanvasFrame.h \
|
||||
!ifdef IBMBIDI
|
||||
nsBidiPresUtils.h \
|
||||
nsITextFrame.h \
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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):
|
||||
*/
|
||||
|
||||
#ifndef nsICanvasFrame_h__
|
||||
#define nsICanvasFrame_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
// IID for the nsICanvasFrame interface
|
||||
#define NS_ICANVASFRAME_IID \
|
||||
{ 0x9df7db77, 0x49a2, 0x11d5, {0x97, 0x92, 0x0, 0x60, 0xb0, 0xfb, 0x99, 0x56} }
|
||||
|
||||
class nsICanvasFrame : public nsISupports
|
||||
{
|
||||
public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_ICANVASFRAME_IID; return iid; }
|
||||
|
||||
/** SetHasFocus tells the CanvasFrame to draw with focus ring
|
||||
* @param aHasFocus PR_TRUE to show focus ring, PR_FALSE to hide it
|
||||
*/
|
||||
NS_IMETHOD SetHasFocus(PRBool aHasFocus) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // nsICanvasFrame_h__
|
||||
|
|
@ -43,6 +43,23 @@
|
|||
#include "nsIScrollableView.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIScrollPositionListener.h"
|
||||
|
||||
// for focus
|
||||
#include "nsIDOMWindowInternal.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIFocusController.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsICanvasFrame.h"
|
||||
#include "nsIPref.h"
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
|
||||
#ifdef DEBUG_rods
|
||||
//#define DEBUG_CANVAS_FOCUS
|
||||
#endif
|
||||
|
||||
// Interface IDs
|
||||
|
||||
|
@ -53,8 +70,21 @@
|
|||
* It only supports having a single child frame which must be an area
|
||||
* frame
|
||||
*/
|
||||
class CanvasFrame : public nsHTMLContainerFrame {
|
||||
class CanvasFrame : public nsHTMLContainerFrame,
|
||||
public nsIScrollPositionListener,
|
||||
public nsICanvasFrame {
|
||||
public:
|
||||
CanvasFrame() : mDoPaintFocus(PR_FALSE) {}
|
||||
|
||||
// nsISupports
|
||||
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
||||
|
||||
NS_IMETHOD Init(nsIPresContext* aPresContext,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIStyleContext* aContext,
|
||||
nsIFrame* aPrevInFlow);
|
||||
|
||||
NS_IMETHOD AppendFrames(nsIPresContext* aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
|
@ -90,6 +120,13 @@ public:
|
|||
const nsRect& aDirtyRect,
|
||||
nsFramePaintLayer aWhichLayer);
|
||||
|
||||
// nsIScrollPositionListener
|
||||
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
||||
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
||||
|
||||
// nsICanvasFrame
|
||||
NS_IMETHOD SetHasFocus(PRBool aHasFocus) { mDoPaintFocus = aHasFocus; return NS_OK; }
|
||||
|
||||
/**
|
||||
* Get the "type" of the frame
|
||||
*
|
||||
|
@ -113,8 +150,24 @@ public:
|
|||
|
||||
protected:
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
void DrawDottedRect(nsIRenderingContext& aRenderingContext, nsRect& aRect);
|
||||
|
||||
// Data members
|
||||
PRPackedBool mDoPaintFocus;
|
||||
nsCOMPtr<nsIPresContext> mPresContext;
|
||||
|
||||
// static members
|
||||
static PRBool mShowFocusPrefOn;
|
||||
|
||||
|
||||
private:
|
||||
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
|
||||
NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
|
||||
};
|
||||
|
||||
PRBool CanvasFrame::mShowFocusPrefOn = PR_TRUE;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
|
@ -132,6 +185,102 @@ NS_NewCanvasFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Frames are not refcounted, no need to AddRef
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
NS_PRECONDITION(0 != aInstancePtr, "null ptr");
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (aIID.Equals(NS_GET_IID(nsIScrollPositionListener))) {
|
||||
*aInstancePtr = (void*) ((nsIScrollPositionListener*) this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aIID.Equals(NS_GET_IID(nsICanvasFrame))) {
|
||||
*aInstancePtr = (void*) ((nsICanvasFrame*) this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::Init(nsIPresContext* aPresContext,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIStyleContext* aContext,
|
||||
nsIFrame* aPrevInFlow)
|
||||
{
|
||||
nsresult rv = nsHTMLContainerFrame::Init(aPresContext,aContent,aParent,aContext,aPrevInFlow);
|
||||
|
||||
mPresContext = aPresContext;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
aPresContext->GetShell(getter_AddRefs(presShell));
|
||||
nsCOMPtr<nsIViewManager> vm;
|
||||
presShell->GetViewManager(getter_AddRefs(vm));
|
||||
|
||||
nsIScrollableView* scrollingView = nsnull;
|
||||
vm->GetRootScrollableView(&scrollingView);
|
||||
|
||||
if (scrollingView) {
|
||||
scrollingView->AddScrollPositionListener((nsIScrollPositionListener *)this);
|
||||
}
|
||||
|
||||
// Get the prefs service
|
||||
nsresult result;
|
||||
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &result);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
prefs->GetBoolPref("layout.reflow.showframecounts", &mShowFocusPrefOn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
|
||||
{
|
||||
#ifdef DEBUG_CANVAS_FOCUS
|
||||
{
|
||||
PRBool hasFocus = PR_FALSE;
|
||||
nsCOMPtr<nsISupports> container;
|
||||
mPresContext->GetContainer(getter_AddRefs(container));
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (docShell) {
|
||||
docShell->GetHasFocus(&hasFocus);
|
||||
}
|
||||
printf("SPWC: %p HF: %s mDoPaintFocus: %s\n", docShell.get(), hasFocus?"Y":"N", mDoPaintFocus?"Y":"N");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mDoPaintFocus) {
|
||||
mDoPaintFocus = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
mPresContext->GetShell(getter_AddRefs(presShell));
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIViewManager> vm;
|
||||
presShell->GetViewManager(getter_AddRefs(vm));
|
||||
if (vm) {
|
||||
vm->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::AppendFrames(nsIPresContext* aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
|
@ -228,6 +377,26 @@ CanvasFrame::RemoveFrame(nsIPresContext* aPresContext,
|
|||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
CanvasFrame::DrawDottedRect(nsIRenderingContext& aRenderingContext, nsRect& aRect)
|
||||
{
|
||||
#ifdef DEBUG_CANVAS_FOCUS
|
||||
printf("** DrawDottedRect: %d,%d,%d,%d\n",aRect.x, aRect.y, aRect.width, aRect.height);
|
||||
#endif
|
||||
|
||||
aRenderingContext.DrawLine(aRect.x, aRect.y,
|
||||
aRect.x+aRect.width, aRect.y);
|
||||
aRenderingContext.DrawLine(aRect.x+aRect.width, aRect.y,
|
||||
aRect.x+aRect.width, aRect.y+aRect.height);
|
||||
aRenderingContext.DrawLine(aRect.x+aRect.width, aRect.y+aRect.height,
|
||||
aRect.x, aRect.y+aRect.height);
|
||||
aRenderingContext.DrawLine(aRect.x, aRect.y+aRect.height,
|
||||
aRect.x, aRect.y);
|
||||
aRenderingContext.DrawLine(aRect.x, aRect.y+aRect.height,
|
||||
aRect.x, aRect.y);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::Paint(nsIPresContext* aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
|
@ -237,7 +406,90 @@ CanvasFrame::Paint(nsIPresContext* aPresContext,
|
|||
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
|
||||
SetDefaultBackgroundColor(aPresContext);
|
||||
}
|
||||
return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
|
||||
nsresult rv = nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
|
||||
|
||||
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
|
||||
|
||||
#ifdef DEBUG_CANVAS_FOCUS
|
||||
nsCOMPtr<nsIContent> focusContent;
|
||||
nsCOMPtr<nsIEventStateManager> esm;
|
||||
aPresContext->GetEventStateManager(getter_AddRefs(esm));
|
||||
if (esm) {
|
||||
esm->GetFocusedContent(getter_AddRefs(focusContent));
|
||||
}
|
||||
|
||||
PRBool hasFocus = PR_FALSE;
|
||||
nsCOMPtr<nsISupports> container;
|
||||
aPresContext->GetContainer(getter_AddRefs(container));
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (docShell) {
|
||||
docShell->GetHasFocus(&hasFocus);
|
||||
printf("%p - CanvasFrame::Paint R:%d,%d,%d,%d DR: %d,%d,%d,%d\n", this,
|
||||
mRect.x, mRect.y, mRect.width, mRect.height,
|
||||
aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
|
||||
}
|
||||
printf("%p - Focus: %s c: %p DoPaint:%s\n", docShell.get(), hasFocus?"Y":"N",
|
||||
focusContent.get(), mDoPaintFocus?"Y":"N");
|
||||
#endif
|
||||
|
||||
if (mDoPaintFocus) {
|
||||
aRenderingContext.PushState();
|
||||
PRBool clipEmpty;
|
||||
nsRect focusRect;
|
||||
GetRect(focusRect);
|
||||
/////////////////////
|
||||
// draw focus
|
||||
// XXX This is only temporary
|
||||
const nsStyleDisplay* disp = (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
|
||||
// Only paint the focus if we're visible
|
||||
if (disp->IsVisible()) {
|
||||
nsCOMPtr<nsIEventStateManager> stateManager;
|
||||
nsresult rv = aPresContext->GetEventStateManager(getter_AddRefs(stateManager));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsIFrame * parentFrame;
|
||||
GetParent(&parentFrame);
|
||||
nsIScrollableFrame* scrollableFrame;
|
||||
if (NS_SUCCEEDED(parentFrame->QueryInterface(NS_GET_IID(nsIScrollableFrame), (void**)&scrollableFrame))) {
|
||||
nscoord width, height;
|
||||
scrollableFrame->GetClipSize(aPresContext, &width, &height);
|
||||
}
|
||||
nsIView* parentView;
|
||||
parentFrame->GetView(aPresContext, &parentView);
|
||||
|
||||
nsIScrollableView* scrollableView;
|
||||
if (NS_SUCCEEDED(parentView->QueryInterface(NS_GET_IID(nsIScrollableView), (void**)&scrollableView))) {
|
||||
nscoord width, height;
|
||||
scrollableView->GetContainerSize(&width, &height);
|
||||
const nsIView* clippedView;
|
||||
scrollableView->GetClipView(&clippedView);
|
||||
nsRect vcr;
|
||||
clippedView->GetBounds(vcr);
|
||||
focusRect.height = vcr.height;
|
||||
nscoord x,y;
|
||||
scrollableView->GetScrollPosition(x, y);
|
||||
focusRect.x += x;
|
||||
focusRect.y += y;
|
||||
}
|
||||
aRenderingContext.SetLineStyle(nsLineStyle_kDotted);
|
||||
aRenderingContext.SetColor(NS_RGB(0,0,0));
|
||||
|
||||
float p2t;
|
||||
aPresContext->GetPixelsToTwips(&p2t);
|
||||
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
|
||||
|
||||
focusRect.width -= onePixel;
|
||||
focusRect.height -= onePixel;
|
||||
|
||||
DrawDottedRect(aRenderingContext, focusRect);
|
||||
|
||||
focusRect.Deflate(onePixel, onePixel);
|
||||
DrawDottedRect(aRenderingContext, focusRect);
|
||||
}
|
||||
}
|
||||
aRenderingContext.PopState(clipEmpty);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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):
|
||||
*/
|
||||
|
||||
#ifndef nsICanvasFrame_h__
|
||||
#define nsICanvasFrame_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
// IID for the nsICanvasFrame interface
|
||||
#define NS_ICANVASFRAME_IID \
|
||||
{ 0x9df7db77, 0x49a2, 0x11d5, {0x97, 0x92, 0x0, 0x60, 0xb0, 0xfb, 0x99, 0x56} }
|
||||
|
||||
class nsICanvasFrame : public nsISupports
|
||||
{
|
||||
public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_ICANVASFRAME_IID; return iid; }
|
||||
|
||||
/** SetHasFocus tells the CanvasFrame to draw with focus ring
|
||||
* @param aHasFocus PR_TRUE to show focus ring, PR_FALSE to hide it
|
||||
*/
|
||||
NS_IMETHOD SetHasFocus(PRBool aHasFocus) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // nsICanvasFrame_h__
|
||||
|
|
@ -43,6 +43,23 @@
|
|||
#include "nsIScrollableView.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIScrollPositionListener.h"
|
||||
|
||||
// for focus
|
||||
#include "nsIDOMWindowInternal.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIFocusController.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsICanvasFrame.h"
|
||||
#include "nsIPref.h"
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
|
||||
#ifdef DEBUG_rods
|
||||
//#define DEBUG_CANVAS_FOCUS
|
||||
#endif
|
||||
|
||||
// Interface IDs
|
||||
|
||||
|
@ -53,8 +70,21 @@
|
|||
* It only supports having a single child frame which must be an area
|
||||
* frame
|
||||
*/
|
||||
class CanvasFrame : public nsHTMLContainerFrame {
|
||||
class CanvasFrame : public nsHTMLContainerFrame,
|
||||
public nsIScrollPositionListener,
|
||||
public nsICanvasFrame {
|
||||
public:
|
||||
CanvasFrame() : mDoPaintFocus(PR_FALSE) {}
|
||||
|
||||
// nsISupports
|
||||
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
||||
|
||||
NS_IMETHOD Init(nsIPresContext* aPresContext,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIStyleContext* aContext,
|
||||
nsIFrame* aPrevInFlow);
|
||||
|
||||
NS_IMETHOD AppendFrames(nsIPresContext* aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
|
@ -90,6 +120,13 @@ public:
|
|||
const nsRect& aDirtyRect,
|
||||
nsFramePaintLayer aWhichLayer);
|
||||
|
||||
// nsIScrollPositionListener
|
||||
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
||||
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
||||
|
||||
// nsICanvasFrame
|
||||
NS_IMETHOD SetHasFocus(PRBool aHasFocus) { mDoPaintFocus = aHasFocus; return NS_OK; }
|
||||
|
||||
/**
|
||||
* Get the "type" of the frame
|
||||
*
|
||||
|
@ -113,8 +150,24 @@ public:
|
|||
|
||||
protected:
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
void DrawDottedRect(nsIRenderingContext& aRenderingContext, nsRect& aRect);
|
||||
|
||||
// Data members
|
||||
PRPackedBool mDoPaintFocus;
|
||||
nsCOMPtr<nsIPresContext> mPresContext;
|
||||
|
||||
// static members
|
||||
static PRBool mShowFocusPrefOn;
|
||||
|
||||
|
||||
private:
|
||||
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
|
||||
NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
|
||||
};
|
||||
|
||||
PRBool CanvasFrame::mShowFocusPrefOn = PR_TRUE;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
|
@ -132,6 +185,102 @@ NS_NewCanvasFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Frames are not refcounted, no need to AddRef
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
{
|
||||
NS_PRECONDITION(0 != aInstancePtr, "null ptr");
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (aIID.Equals(NS_GET_IID(nsIScrollPositionListener))) {
|
||||
*aInstancePtr = (void*) ((nsIScrollPositionListener*) this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aIID.Equals(NS_GET_IID(nsICanvasFrame))) {
|
||||
*aInstancePtr = (void*) ((nsICanvasFrame*) this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::Init(nsIPresContext* aPresContext,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIStyleContext* aContext,
|
||||
nsIFrame* aPrevInFlow)
|
||||
{
|
||||
nsresult rv = nsHTMLContainerFrame::Init(aPresContext,aContent,aParent,aContext,aPrevInFlow);
|
||||
|
||||
mPresContext = aPresContext;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
aPresContext->GetShell(getter_AddRefs(presShell));
|
||||
nsCOMPtr<nsIViewManager> vm;
|
||||
presShell->GetViewManager(getter_AddRefs(vm));
|
||||
|
||||
nsIScrollableView* scrollingView = nsnull;
|
||||
vm->GetRootScrollableView(&scrollingView);
|
||||
|
||||
if (scrollingView) {
|
||||
scrollingView->AddScrollPositionListener((nsIScrollPositionListener *)this);
|
||||
}
|
||||
|
||||
// Get the prefs service
|
||||
nsresult result;
|
||||
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &result);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
prefs->GetBoolPref("layout.reflow.showframecounts", &mShowFocusPrefOn);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
|
||||
{
|
||||
#ifdef DEBUG_CANVAS_FOCUS
|
||||
{
|
||||
PRBool hasFocus = PR_FALSE;
|
||||
nsCOMPtr<nsISupports> container;
|
||||
mPresContext->GetContainer(getter_AddRefs(container));
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (docShell) {
|
||||
docShell->GetHasFocus(&hasFocus);
|
||||
}
|
||||
printf("SPWC: %p HF: %s mDoPaintFocus: %s\n", docShell.get(), hasFocus?"Y":"N", mDoPaintFocus?"Y":"N");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mDoPaintFocus) {
|
||||
mDoPaintFocus = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
mPresContext->GetShell(getter_AddRefs(presShell));
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIViewManager> vm;
|
||||
presShell->GetViewManager(getter_AddRefs(vm));
|
||||
if (vm) {
|
||||
vm->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::AppendFrames(nsIPresContext* aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
|
@ -228,6 +377,26 @@ CanvasFrame::RemoveFrame(nsIPresContext* aPresContext,
|
|||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
CanvasFrame::DrawDottedRect(nsIRenderingContext& aRenderingContext, nsRect& aRect)
|
||||
{
|
||||
#ifdef DEBUG_CANVAS_FOCUS
|
||||
printf("** DrawDottedRect: %d,%d,%d,%d\n",aRect.x, aRect.y, aRect.width, aRect.height);
|
||||
#endif
|
||||
|
||||
aRenderingContext.DrawLine(aRect.x, aRect.y,
|
||||
aRect.x+aRect.width, aRect.y);
|
||||
aRenderingContext.DrawLine(aRect.x+aRect.width, aRect.y,
|
||||
aRect.x+aRect.width, aRect.y+aRect.height);
|
||||
aRenderingContext.DrawLine(aRect.x+aRect.width, aRect.y+aRect.height,
|
||||
aRect.x, aRect.y+aRect.height);
|
||||
aRenderingContext.DrawLine(aRect.x, aRect.y+aRect.height,
|
||||
aRect.x, aRect.y);
|
||||
aRenderingContext.DrawLine(aRect.x, aRect.y+aRect.height,
|
||||
aRect.x, aRect.y);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::Paint(nsIPresContext* aPresContext,
|
||||
nsIRenderingContext& aRenderingContext,
|
||||
|
@ -237,7 +406,90 @@ CanvasFrame::Paint(nsIPresContext* aPresContext,
|
|||
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
|
||||
SetDefaultBackgroundColor(aPresContext);
|
||||
}
|
||||
return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
|
||||
nsresult rv = nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
|
||||
|
||||
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
|
||||
|
||||
#ifdef DEBUG_CANVAS_FOCUS
|
||||
nsCOMPtr<nsIContent> focusContent;
|
||||
nsCOMPtr<nsIEventStateManager> esm;
|
||||
aPresContext->GetEventStateManager(getter_AddRefs(esm));
|
||||
if (esm) {
|
||||
esm->GetFocusedContent(getter_AddRefs(focusContent));
|
||||
}
|
||||
|
||||
PRBool hasFocus = PR_FALSE;
|
||||
nsCOMPtr<nsISupports> container;
|
||||
aPresContext->GetContainer(getter_AddRefs(container));
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (docShell) {
|
||||
docShell->GetHasFocus(&hasFocus);
|
||||
printf("%p - CanvasFrame::Paint R:%d,%d,%d,%d DR: %d,%d,%d,%d\n", this,
|
||||
mRect.x, mRect.y, mRect.width, mRect.height,
|
||||
aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
|
||||
}
|
||||
printf("%p - Focus: %s c: %p DoPaint:%s\n", docShell.get(), hasFocus?"Y":"N",
|
||||
focusContent.get(), mDoPaintFocus?"Y":"N");
|
||||
#endif
|
||||
|
||||
if (mDoPaintFocus) {
|
||||
aRenderingContext.PushState();
|
||||
PRBool clipEmpty;
|
||||
nsRect focusRect;
|
||||
GetRect(focusRect);
|
||||
/////////////////////
|
||||
// draw focus
|
||||
// XXX This is only temporary
|
||||
const nsStyleDisplay* disp = (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
|
||||
// Only paint the focus if we're visible
|
||||
if (disp->IsVisible()) {
|
||||
nsCOMPtr<nsIEventStateManager> stateManager;
|
||||
nsresult rv = aPresContext->GetEventStateManager(getter_AddRefs(stateManager));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsIFrame * parentFrame;
|
||||
GetParent(&parentFrame);
|
||||
nsIScrollableFrame* scrollableFrame;
|
||||
if (NS_SUCCEEDED(parentFrame->QueryInterface(NS_GET_IID(nsIScrollableFrame), (void**)&scrollableFrame))) {
|
||||
nscoord width, height;
|
||||
scrollableFrame->GetClipSize(aPresContext, &width, &height);
|
||||
}
|
||||
nsIView* parentView;
|
||||
parentFrame->GetView(aPresContext, &parentView);
|
||||
|
||||
nsIScrollableView* scrollableView;
|
||||
if (NS_SUCCEEDED(parentView->QueryInterface(NS_GET_IID(nsIScrollableView), (void**)&scrollableView))) {
|
||||
nscoord width, height;
|
||||
scrollableView->GetContainerSize(&width, &height);
|
||||
const nsIView* clippedView;
|
||||
scrollableView->GetClipView(&clippedView);
|
||||
nsRect vcr;
|
||||
clippedView->GetBounds(vcr);
|
||||
focusRect.height = vcr.height;
|
||||
nscoord x,y;
|
||||
scrollableView->GetScrollPosition(x, y);
|
||||
focusRect.x += x;
|
||||
focusRect.y += y;
|
||||
}
|
||||
aRenderingContext.SetLineStyle(nsLineStyle_kDotted);
|
||||
aRenderingContext.SetColor(NS_RGB(0,0,0));
|
||||
|
||||
float p2t;
|
||||
aPresContext->GetPixelsToTwips(&p2t);
|
||||
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
|
||||
|
||||
focusRect.width -= onePixel;
|
||||
focusRect.height -= onePixel;
|
||||
|
||||
DrawDottedRect(aRenderingContext, focusRect);
|
||||
|
||||
focusRect.Deflate(onePixel, onePixel);
|
||||
DrawDottedRect(aRenderingContext, focusRect);
|
||||
}
|
||||
}
|
||||
aRenderingContext.PopState(clipEmpty);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -374,6 +374,7 @@ frame {
|
|||
iframe {
|
||||
background-color: transparent ! important; /* (b=49779) */
|
||||
border: 2px inset;
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
noframes {
|
||||
|
|
|
@ -374,6 +374,7 @@ frame {
|
|||
iframe {
|
||||
background-color: transparent ! important; /* (b=49779) */
|
||||
border: 2px inset;
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
noframes {
|
||||
|
|
Загрузка…
Ссылка в новой задаче