From 4bd197233d0b125f1ec2442f8c245a2290db1ed9 Mon Sep 17 00:00:00 2001 From: "reed%reedloden.com" Date: Wed, 27 Feb 2008 01:49:47 +0000 Subject: [PATCH] Bug 394473 - "caret/cursor in View Source is invisible since 20070628 {not rendered, seen, can't, cannot, shown, displayed}" [p=chris@pearce.org.nz (Chris Pearce [cpearce]) r=peterv r+sr=roc a1.9=beltzner] --- content/base/src/nsGkAtomList.h | 1 + content/events/src/nsEventStateManager.cpp | 64 +++++++++++++++---- layout/base/nsCaret.cpp | 24 +++++-- layout/base/nsCaret.h | 4 +- suite/browser/viewSource.xul | 2 +- suite/browser/viewsource.js | 2 - .../viewsource/content/viewSource.js | 2 - .../viewsource/content/viewSource.xul | 2 +- 8 files changed, 76 insertions(+), 25 deletions(-) diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index 2adad746a5a..e0303fb4e62 100755 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -761,6 +761,7 @@ GK_ATOM(setcookie, "set-cookie") GK_ATOM(setter, "setter") GK_ATOM(shape, "shape") GK_ATOM(show, "show") +GK_ATOM(showcaret, "showcaret") GK_ATOM(simple, "simple") GK_ATOM(single, "single") GK_ATOM(size, "size") diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 09a1710b9fd..4c4c86972d1 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -226,6 +226,8 @@ enum { #define NS_MODIFIER_ALT 4 #define NS_MODIFIER_META 8 +static PRBool GetWindowShowCaret(nsIDocument *aDocument); + static nsIDocument * GetDocumentFromWindow(nsIDOMWindow *aWindow) { @@ -1041,11 +1043,20 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext, case NS_LOSTFOCUS: { - // Hide the caret used in "browse with caret mode" - if (mBrowseWithCaret && mPresContext) { + // Hide the caret if it's visible. + if (mPresContext) { nsIPresShell *presShell = mPresContext->GetPresShell(); - if (presShell) - SetContentCaretVisible(presShell, mCurrentFocus, PR_FALSE); + if (presShell) { + nsCOMPtr caret; + presShell->GetCaret(getter_AddRefs(caret)); + if (caret) { + PRBool caretVisible = PR_FALSE; + caret->GetCaretVisible(&caretVisible); + if (caretVisible) { + SetContentCaretVisible(presShell, mCurrentFocus, PR_FALSE); + } + } + } } // If focus is going to another mozilla window, we wait for the @@ -4714,7 +4725,7 @@ nsEventStateManager::SendFocusBlur(nsPresContext* aPresContext, } } - if (mBrowseWithCaret) + if (mBrowseWithCaret || GetWindowShowCaret(mDocument)) SetContentCaretVisible(presShell, aContent, PR_TRUE); return NS_OK; @@ -5342,6 +5353,7 @@ nsEventStateManager::SetCaretEnabled(nsIPresShell *aPresShell, PRBool aEnabled) selCon->SetCaretEnabled(aEnabled); caret->SetCaretVisible(aEnabled); + caret->SetIgnoreUserModify(aEnabled); return NS_OK; } @@ -5373,9 +5385,6 @@ nsEventStateManager::SetContentCaretVisible(nsIPresShell* aPresShell, // First, tell the caret which selection to use caret->SetCaretDOMSelection(domSelection); - // Ignore user-modify status of nodes when browsing with caret - caret->SetIgnoreUserModify(aVisible); - // In content, we need to set the caret // the only other case is edit fields, where they have a different frame selection from the doc's // in that case they'll take care of making the caret visible themselves @@ -5388,13 +5397,32 @@ nsEventStateManager::SetContentCaretVisible(nsIPresShell* aPresShell, return NS_OK; } - PRBool nsEventStateManager::GetBrowseWithCaret() { return mBrowseWithCaret; } +// Checks if the window corresponding to |aDocument| has the +// showcaret="true" attribute set. +static PRBool +GetWindowShowCaret(nsIDocument *aDocument) +{ + if (!aDocument) return PR_FALSE; + + nsPIDOMWindow* window = aDocument->GetWindow(); + if (!window) return PR_FALSE; + + nsCOMPtr docContent = + do_QueryInterface(window->GetFrameElementInternal()); + if (!docContent) return PR_FALSE; + + return docContent->AttrValueIs(kNameSpaceID_None, + nsGkAtoms::showcaret, + NS_LITERAL_STRING("true"), + eCaseMatters); +} + void nsEventStateManager::ResetBrowseWithCaret() { @@ -5436,12 +5464,20 @@ nsEventStateManager::ResetBrowseWithCaret() mBrowseWithCaret = browseWithCaret; - - // Make caret visible or not, depending on what's appropriate - // Set caret visibility for focused document only - // Others will be set when they get focused again + // Make caret visible or not, depending on what's appropriate. + // Set caret visibility for focused document only, + // others will be set when they get focused again if (presShell && gLastFocusedDocument && gLastFocusedDocument == mDocument) { - SetContentCaretVisible(presShell, mCurrentFocus, browseWithCaret); + + // Contenteditable nodes should always have a caret. + PRBool isFocusEditable = + (mCurrentFocus) ? mCurrentFocus->HasFlag(NODE_IS_EDITABLE) : PR_FALSE; + + PRBool caretShouldBeVisible = isFocusEditable || + browseWithCaret || + GetWindowShowCaret(mDocument); + + SetContentCaretVisible(presShell, mCurrentFocus, caretShouldBeVisible); } } diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp index f802dfe0846..ed81bb1e479 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -224,11 +224,14 @@ NS_IMETHODIMP nsCaret::SetCaretVisible(PRBool inMakeVisible) { mVisible = inMakeVisible; nsresult err = NS_OK; - if (mVisible) + if (mVisible) { err = StartBlinking(); - else + SetIgnoreUserModify(PR_TRUE); + } else { err = StopBlinking(); - + SetIgnoreUserModify(PR_FALSE); + } + return err; } @@ -546,7 +549,7 @@ nsresult nsCaret::StopBlinking() if (mDrawn) // erase the caret if necessary DrawCaret(PR_TRUE); - NS_ASSERTION(!mDrawn, "We just erased ourselves"); + NS_ASSERTION(!mDrawn, "Caret still drawn after StopBlinking()."); KillTimer(); return NS_OK; @@ -1217,6 +1220,19 @@ nsCaret::GetFrameSelection() void nsCaret::SetIgnoreUserModify(PRBool aIgnoreUserModify) { + if (!aIgnoreUserModify && mIgnoreUserModify && mDrawn) { + // We're turning off mIgnoreUserModify. If the caret's drawn + // in a read-only node we must erase it, else the next call + // to DrawCaret() won't erase the old caret, due to the new + // mIgnoreUserModify value. + nsIFrame *frame = GetCaretFrame(); + if (frame) { + const nsStyleUserInterface* userinterface = frame->GetStyleUserInterface(); + if (userinterface->mUserModify == NS_STYLE_USER_MODIFY_READ_ONLY) { + StopBlinking(); + } + } + } mIgnoreUserModify = aIgnoreUserModify; } diff --git a/layout/base/nsCaret.h b/layout/base/nsCaret.h index 8907165baff..1841fb77ecb 100644 --- a/layout/base/nsCaret.h +++ b/layout/base/nsCaret.h @@ -171,7 +171,9 @@ protected: nscoord mBidiIndicatorSize; // width and height of bidi indicator PRPackedBool mVisible; // is the caret blinking - PRPackedBool mDrawn; // this should be mutable + + PRPackedBool mDrawn; // Denotes when the caret is physically drawn on the screen. + PRPackedBool mReadOnly; // it the caret in readonly state (draws differently) PRPackedBool mShowDuringSelection; // show when text is selected diff --git a/suite/browser/viewSource.xul b/suite/browser/viewSource.xul index 35f6f78d15f..fe106eacdd0 100644 --- a/suite/browser/viewSource.xul +++ b/suite/browser/viewSource.xul @@ -100,7 +100,7 @@ + context="viewSourceContextMenu" showcaret="true"/> diff --git a/suite/browser/viewsource.js b/suite/browser/viewsource.js index b66fbde4ce7..2f0050fcef0 100644 --- a/suite/browser/viewsource.js +++ b/suite/browser/viewsource.js @@ -362,7 +362,6 @@ function goToLine(line) var selCon = getSelectionController(); selCon.setDisplaySelection(nsISelectionController.SELECTION_ON); - selCon.setCaretEnabled(true); selCon.setCaretVisibilityDuringSelection(true); // Scroll the beginning of the line into view. @@ -397,7 +396,6 @@ function updateStatusBar() var selCon = getSelectionController(); selCon.setDisplaySelection(nsISelectionController.SELECTION_ON); - selCon.setCaretEnabled(true); selCon.setCaretVisibilityDuringSelection(true); var interlinePosition = selection diff --git a/toolkit/components/viewsource/content/viewSource.js b/toolkit/components/viewsource/content/viewSource.js index 7943404119b..f37038ebecc 100644 --- a/toolkit/components/viewsource/content/viewSource.js +++ b/toolkit/components/viewsource/content/viewSource.js @@ -399,7 +399,6 @@ function goToLine(line) var selCon = getSelectionController(); selCon.setDisplaySelection(nsISelectionController.SELECTION_ON); - selCon.setCaretEnabled(true); selCon.setCaretVisibilityDuringSelection(true); // Scroll the beginning of the line into view. @@ -434,7 +433,6 @@ function updateStatusBar() var selCon = getSelectionController(); selCon.setDisplaySelection(nsISelectionController.SELECTION_ON); - selCon.setCaretEnabled(true); selCon.setCaretVisibilityDuringSelection(true); var interlinePosition = selection diff --git a/toolkit/components/viewsource/content/viewSource.xul b/toolkit/components/viewsource/content/viewSource.xul index 7a0e34ad1c7..5808bf4f750 100644 --- a/toolkit/components/viewsource/content/viewSource.xul +++ b/toolkit/components/viewsource/content/viewSource.xul @@ -203,7 +203,7 @@ ondragdrop="nsDragAndDrop.drop(event, contentAreaDNDObserver);"> + disablehistory="true" context="viewSourceContextMenu" showcaret="true"/>