Bug 924692 - Part 1: Add touch caret rendering support; r=roc

This commit is contained in:
Phoebe Chang 2014-06-03 15:08:25 +08:00
parent 90fde7deef
commit a37fc5efe4
14 changed files with 200 additions and 7 deletions

View File

@ -671,6 +671,9 @@
@BINPATH@/res/table-remove-row-active.gif
@BINPATH@/res/table-remove-row-hover.gif
@BINPATH@/res/table-remove-row.gif
@BINPATH@/res/text_selection_handle.png
@BINPATH@/res/text_selection_handle@1.5.png
@BINPATH@/res/text_selection_handle@2.png
@BINPATH@/res/grabber.gif
#ifdef XP_MACOSX
@BINPATH@/res/cursors/*

View File

@ -39,4 +39,7 @@ RESOURCE_FILES += [
'res/table-remove-row-active.gif',
'res/table-remove-row-hover.gif',
'res/table-remove-row.gif',
'res/text_selection_handle.png',
'res/text_selection_handle@1.5.png',
'res/text_selection_handle@2.png',
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -29,6 +29,7 @@
#include "nsTableCellFrame.h"
#include "nsIDOMHTMLDocument.h"
#include "nsHTMLParts.h"
#include "nsPresShell.h"
#include "nsIPresShell.h"
#include "nsUnicharUtils.h"
#include "nsStyleSet.h"
@ -2597,6 +2598,12 @@ nsCSSFrameConstructor::ConstructDocElementFrame(Element* aDocEle
SetInitialSingleChild(mDocElementContainingBlock, newFrame);
// Create touch caret frame if there is a canvas frame
if (mDocElementContainingBlock->GetType() == nsGkAtoms::canvasFrame) {
ConstructAnonymousContentForCanvas(state, mDocElementContainingBlock,
aDocElement);
}
return newFrame;
}
@ -2852,6 +2859,29 @@ nsCSSFrameConstructor::SetUpDocElementContainingBlock(nsIContent* aDocElement)
}
}
void
nsCSSFrameConstructor::ConstructAnonymousContentForCanvas(nsFrameConstructorState& aState,
nsIFrame* aFrame,
nsIContent* aDocElement)
{
NS_ASSERTION(aFrame->GetType() == nsGkAtoms::canvasFrame, "aFrame should be canvas frame!");
nsAutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
GetAnonymousContent(aDocElement, aFrame, anonymousItems);
if (anonymousItems.IsEmpty()) {
// Touch caret is not enabled.
return;
}
FrameConstructionItemList itemsToConstruct;
nsContainerFrame* frameAsContainer = do_QueryFrame(aFrame);
AddFCItemsForAnonymousContent(aState, frameAsContainer, anonymousItems, itemsToConstruct);
nsFrameItems frameItems;
ConstructFramesFromItemList(aState, itemsToConstruct, frameAsContainer, frameItems);
frameAsContainer->AppendFrames(kPrincipalList, frameItems);
}
nsContainerFrame*
nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell* aPresShell,
nsPresContext* aPresContext,

View File

@ -1769,6 +1769,10 @@ private:
nsIContent* aContent,
nsStyleContext* aStyleContext,
bool aIsGeneratedContent);
// Create touch caret frame.
void ConstructAnonymousContentForCanvas(nsFrameConstructorState& aState,
nsIFrame* aFrame,
nsIContent* aDocElement);
public:

View File

@ -53,6 +53,7 @@ class nsViewManager;
class nsView;
class nsRenderingContext;
class nsIPageSequenceFrame;
class nsCanvasFrame;
class nsAString;
class nsCaret;
class nsFrameSelection;
@ -467,6 +468,12 @@ public:
*/
virtual nsIPageSequenceFrame* GetPageSequenceFrame() const = 0;
/**
* Returns the canvas frame associated with the frame hierarchy.
* Returns nullptr if is XUL document.
*/
virtual nsCanvasFrame* GetCanvasFrame() const = 0;
/**
* Gets the real primary frame associated with the content object.
*
@ -735,6 +742,11 @@ public:
*/
virtual void NotifyDestroyingFrame(nsIFrame* aFrame) = 0;
/**
* Returns the touch caret element of the presshell.
*/
virtual mozilla::dom::Element* GetTouchCaretElement() const = 0;
/**
* Get the caret, if it exists. AddRefs it.
*/

View File

@ -701,6 +701,18 @@ nsIPresShell::FrameSelection()
static bool sSynthMouseMove = true;
static uint32_t sNextPresShellId;
static bool sPointerEventEnabled = true;
static bool sTouchCaretEnabled = false;
/* static */ bool
PresShell::TouchCaretPrefEnabled()
{
static bool initialized = false;
if (!initialized) {
Preferences::AddBoolVarCache(&sTouchCaretEnabled, "touchcaret.enabled");
initialized = true;
}
return sTouchCaretEnabled;
}
PresShell::PresShell()
: mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)
@ -2472,6 +2484,19 @@ PresShell::GetPageSequenceFrame() const
return do_QueryFrame(frame);
}
nsCanvasFrame*
PresShell::GetCanvasFrame() const
{
nsIFrame* frame = mFrameConstructor->GetDocElementContainingBlock();
return do_QueryFrame(frame);
}
Element*
PresShell::GetTouchCaretElement() const
{
return GetCanvasFrame() ? GetCanvasFrame()->GetTouchCaretElement() : nullptr;
}
void
PresShell::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
{

View File

@ -67,6 +67,9 @@ public:
// nsISupports
NS_DECL_ISUPPORTS
// Touch caret preference
static bool TouchCaretPrefEnabled();
void Init(nsIDocument* aDocument, nsPresContext* aPresContext,
nsViewManager* aViewManager, nsStyleSet* aStyleSet,
nsCompatibility aCompatMode);
@ -90,6 +93,7 @@ public:
virtual nsresult ResizeReflow(nscoord aWidth, nscoord aHeight) MOZ_OVERRIDE;
virtual nsresult ResizeReflowOverride(nscoord aWidth, nscoord aHeight) MOZ_OVERRIDE;
virtual nsIPageSequenceFrame* GetPageSequenceFrame() const MOZ_OVERRIDE;
virtual nsCanvasFrame* GetCanvasFrame() const MOZ_OVERRIDE;
virtual nsIFrame* GetRealPrimaryFrameFor(nsIContent* aContent) const MOZ_OVERRIDE;
virtual nsIFrame* GetPlaceholderFrameFor(nsIFrame* aFrame) const MOZ_OVERRIDE;
@ -207,6 +211,8 @@ public:
virtual void ClearMouseCaptureOnView(nsView* aView) MOZ_OVERRIDE;
virtual bool IsVisible() MOZ_OVERRIDE;
// touch caret
virtual mozilla::dom::Element* GetTouchCaretElement() const MOZ_OVERRIDE;
// caret handling
virtual already_AddRefed<nsCaret> GetCaret() const MOZ_OVERRIDE;
virtual void MaybeInvalidateCaretPosition() MOZ_OVERRIDE;

View File

@ -12,12 +12,17 @@
#include "nsStyleContext.h"
#include "nsRenderingContext.h"
#include "nsGkAtoms.h"
#include "nsPresShell.h"
#include "nsIPresShell.h"
#include "nsDisplayList.h"
#include "nsCSSFrameConstructor.h"
#include "nsFrameManager.h"
#include "gfxPlatform.h"
// for touchcaret
#include "nsContentList.h"
#include "nsContentCreatorFunctions.h"
#include "nsContentUtils.h"
#include "nsStyleSet.h"
// for focus
#include "nsIScrollableFrame.h"
#ifdef DEBUG_CANVAS_FOCUS
@ -40,8 +45,53 @@ NS_IMPL_FRAMEARENA_HELPERS(nsCanvasFrame)
NS_QUERYFRAME_HEAD(nsCanvasFrame)
NS_QUERYFRAME_ENTRY(nsCanvasFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
nsresult
nsCanvasFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
{
// We won't create touch caret element if preference is not enabled.
if (!PresShell::TouchCaretPrefEnabled()) {
return NS_OK;
}
nsCOMPtr<nsIDocument> doc = mContent->OwnerDoc();
nsCOMPtr<nsINodeInfo> nodeInfo;
// Create and append touch caret frame.
nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::div, nullptr,
kNameSpaceID_XHTML,
nsIDOMNode::ELEMENT_NODE);
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = NS_NewHTMLElement(getter_AddRefs(mTouchCaretElement), nodeInfo.forget(),
mozilla::dom::NOT_FROM_PARSER);
NS_ENSURE_SUCCESS(rv, rv);
aElements.AppendElement(mTouchCaretElement);
// Add a _moz_anonclass attribute as touch caret selector.
ErrorResult er;
mTouchCaretElement->SetAttribute(NS_LITERAL_STRING("_moz_anonclass"),
NS_LITERAL_STRING("mozTouchCaret"), er);
NS_ENSURE_SUCCESS(er.ErrorCode(), er.ErrorCode());
// Set touch caret to visibility: hidden by default.
nsAutoString classValue;
classValue.AppendLiteral("moz-touchcaret hidden");
rv = mTouchCaretElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
classValue, true);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
void
nsCanvasFrame::AppendAnonymousContentTo(nsBaseContentList& aElements, uint32_t aFilter)
{
aElements.MaybeAppendElement(mTouchCaretElement);
}
void
nsCanvasFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
@ -51,6 +101,7 @@ nsCanvasFrame::DestroyFrom(nsIFrame* aDestructRoot)
sf->RemoveScrollPositionListener(this);
}
nsContentUtils::DestroyAnonymousContent(&mTouchCaretElement);
nsContainerFrame::DestroyFrom(aDestructRoot);
}
@ -98,9 +149,14 @@ nsCanvasFrame::AppendFrames(ChildListID aListID,
nsFrameList& aFrameList)
{
MOZ_ASSERT(aListID == kPrincipalList, "unexpected child list");
MOZ_ASSERT(mFrames.IsEmpty(), "already have a child frame");
MOZ_ASSERT(aFrameList.FirstChild() == aFrameList.LastChild(),
"Only one principal child frame allowed");
if (!mFrames.IsEmpty()) {
for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
// We only allow native anonymous child frame for touch caret,
// which its placeholder is added to the Principal child lists.
MOZ_ASSERT(e.get()->GetContent()->IsInNativeAnonymousSubtree(),
"invalid child list");
}
}
nsFrame::VerifyDirtyBitSet(aFrameList);
nsContainerFrame::AppendFrames(aListID, aFrameList);
}
@ -121,7 +177,6 @@ nsCanvasFrame::RemoveFrame(ChildListID aListID,
nsIFrame* aOldFrame)
{
MOZ_ASSERT(aListID == kPrincipalList, "unexpected child list");
MOZ_ASSERT(aOldFrame == mFrames.FirstChild(), "unknown aOldFrame");
nsContainerFrame::RemoveFrame(aListID, aOldFrame);
}
#endif

View File

@ -13,6 +13,7 @@
#include "nsContainerFrame.h"
#include "nsIScrollPositionListener.h"
#include "nsDisplayList.h"
#include "nsIAnonymousContentCreator.h"
class nsPresContext;
class nsRenderingContext;
@ -25,7 +26,8 @@ class nsRenderingContext;
* frame
*/
class nsCanvasFrame : public nsContainerFrame,
public nsIScrollPositionListener
public nsIScrollPositionListener,
public nsIAnonymousContentCreator
{
public:
nsCanvasFrame(nsStyleContext* aContext)
@ -64,6 +66,16 @@ public:
~(nsIFrame::eCanContainOverflowContainers));
}
// nsIAnonymousContentCreator
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) MOZ_OVERRIDE;
virtual void AppendAnonymousContentTo(nsBaseContentList& aElements, uint32_t aFilter) MOZ_OVERRIDE;
// Touch caret handle function
mozilla::dom::Element* GetTouchCaretElement() const
{
return mTouchCaretElement;
}
/** SetHasFocus tells the CanvasFrame to draw with focus ring
* @param aHasFocus true to show focus ring, false to hide it
*/
@ -111,6 +123,8 @@ protected:
// Data members
bool mDoPaintFocus;
bool mAddedScrollPositionListener;
nsCOMPtr<mozilla::dom::Element> mTouchCaretElement;
};
/**

View File

@ -283,3 +283,41 @@ parsererror|sourcetext {
font-weight: bold;
font-size: 12pt;
}
div[\_moz_anonclass="mozTouchCaret"].moz-touchcaret {
background-image: url("resource://gre/res/text_selection_handle.png");
position: absolute;
width: 19px;
height: 24px;
margin-left: -10px;
background-position: center center;
z-index: 2147483647;
}
@media (min-resolution: 1.5dppx) {
div[\_moz_anonclass="mozTouchCaret"].moz-touchcaret {
background-image: url("resource://gre/res/text_selection_handle@1.5.png");
position: absolute;
width: 29px;
height: 36px;
margin-left: -15px;
background-position: center center;
z-index: 2147483647;
}
}
@media (min-resolution: 2dppx) {
div[\_moz_anonclass="mozTouchCaret"].moz-touchcaret {
background-image: url("resource://gre/res/text_selection_handle@2.png");
position: absolute;
width: 38px;
height: 48px;
margin-left: -19px;
background-position: center center;
z-index: 2147483647;
}
}
div[\_moz_anonclass="mozTouchCaret"].moz-touchcaret.hidden {
visibility: hidden;
}

View File

@ -2087,7 +2087,7 @@ pref("svg.svg-iframe.enabled", false);
pref("svg.svg-iframe.enabled", false);
#endif
// Is support for the new getBBox method from SVG 2 enabled?
// Is support for the new getBBox method from SVG 2 enabled?
// See https://svgwg.org/svg2-draft/single-page.html#types-SVGBoundingBoxOptions
#ifdef RELEASE_BUILD
pref("svg.new-getBBox.enabled", false);
@ -4148,6 +4148,9 @@ pref("urlclassifier.disallow_completions", "test-malware-simple,test-phish-simpl
// Turn off Spatial navigation by default.
pref("snav.enabled", false);
// Turn off touch caret by default.
pref("touchcaret.enabled", false);
// Wakelock is disabled by default.
pref("dom.wakelock.enabled", false);