adding pane/frameset/frame/iframe navigation

Bug 24423 r=joki,saari a=hyatt
This commit is contained in:
rods%netscape.com 2001-05-22 23:52:17 +00:00
Родитель e919fcd1d2
Коммит ade2376885
16 изменённых файлов: 2100 добавлений и 23 удалений

Просмотреть файл

@ -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 {