Backed out changeset 9f30d3caa231 (bug 1221459)

This commit is contained in:
Nigel Babu 2015-12-22 14:03:21 +05:30
parent 0d84c3e091
commit 1a8c45a533
36 changed files with 3601 additions and 34 deletions

View File

@ -813,6 +813,18 @@
@RESPATH@/res/accessiblecaret_tilt_right@1.5x.png
@RESPATH@/res/accessiblecaret_tilt_right@2.25x.png
@RESPATH@/res/accessiblecaret_tilt_right@2x.png
@RESPATH@/res/text_caret.png
@RESPATH@/res/text_caret@1.5x.png
@RESPATH@/res/text_caret@2.25x.png
@RESPATH@/res/text_caret@2x.png
@RESPATH@/res/text_caret_tilt_left.png
@RESPATH@/res/text_caret_tilt_left@1.5x.png
@RESPATH@/res/text_caret_tilt_left@2.25x.png
@RESPATH@/res/text_caret_tilt_left@2x.png
@RESPATH@/res/text_caret_tilt_right.png
@RESPATH@/res/text_caret_tilt_right@1.5x.png
@RESPATH@/res/text_caret_tilt_right@2.25x.png
@RESPATH@/res/text_caret_tilt_right@2x.png
@RESPATH@/res/grabber.gif
#ifdef XP_MACOSX
@RESPATH@/res/cursors/*

View File

@ -751,6 +751,18 @@
@RESPATH@/res/accessiblecaret_tilt_right@1.5x.png
@RESPATH@/res/accessiblecaret_tilt_right@2.25x.png
@RESPATH@/res/accessiblecaret_tilt_right@2x.png
@RESPATH@/res/text_caret.png
@RESPATH@/res/text_caret@1.5x.png
@RESPATH@/res/text_caret@2.25x.png
@RESPATH@/res/text_caret@2x.png
@RESPATH@/res/text_caret_tilt_left.png
@RESPATH@/res/text_caret_tilt_left@1.5x.png
@RESPATH@/res/text_caret_tilt_left@2.25x.png
@RESPATH@/res/text_caret_tilt_left@2x.png
@RESPATH@/res/text_caret_tilt_right.png
@RESPATH@/res/text_caret_tilt_right@1.5x.png
@RESPATH@/res/text_caret_tilt_right@2.25x.png
@RESPATH@/res/text_caret_tilt_right@2x.png
@RESPATH@/res/grabber.gif
#ifdef XP_MACOSX
@RESPATH@/res/cursors/*

View File

@ -41,6 +41,7 @@
#include "nsIObjectFrame.h"
#include "nsBindingManager.h"
#include "nsStyleCoord.h"
#include "SelectionCarets.h"
#include "TabChild.h"
#include "nsFrameLoader.h"
@ -1691,6 +1692,11 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear,
SetCaretVisible(presShell, false, nullptr);
}
RefPtr<SelectionCarets> selectionCarets = presShell->GetSelectionCarets();
if (selectionCarets) {
selectionCarets->NotifyBlur(aIsLeavingDocument || !mActiveWindow);
}
RefPtr<AccessibleCaretEventHub> eventHub = presShell->GetAccessibleCaretEventHub();
if (eventHub) {
eventHub->NotifyBlur(aIsLeavingDocument || !mActiveWindow);

View File

@ -207,6 +207,7 @@
#include "prrng.h"
#include "nsSandboxFlags.h"
#include "TimeChangeObserver.h"
#include "TouchCaret.h"
#include "mozilla/dom/AudioContext.h"
#include "mozilla/dom/BrowserElementDictionariesBinding.h"
#include "mozilla/dom/cache/CacheStorage.h"

View File

@ -59,4 +59,16 @@ RESOURCE_FILES += [
'res/table-remove-row-active.gif',
'res/table-remove-row-hover.gif',
'res/table-remove-row.gif',
'res/text_caret.png',
'res/text_caret@1.5x.png',
'res/text_caret@2.25x.png',
'res/text_caret@2x.png',
'res/text_caret_tilt_left.png',
'res/text_caret_tilt_left@1.5x.png',
'res/text_caret_tilt_left@2.25x.png',
'res/text_caret_tilt_left@2x.png',
'res/text_caret_tilt_right.png',
'res/text_caret_tilt_right@1.5x.png',
'res/text_caret_tilt_right@2.25x.png',
'res/text_caret_tilt_right@2x.png',
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,277 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 et tw=78: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef SelectionCarets_h__
#define SelectionCarets_h__
#include "nsDirection.h"
#include "nsIReflowObserver.h"
#include "nsIScrollObserver.h"
#include "nsISelectionListener.h"
#include "nsWeakPtr.h"
#include "nsWeakReference.h"
#include "Units.h"
#include "mozilla/dom/SelectionStateChangedEvent.h"
#include "mozilla/EventForwards.h"
#include "mozilla/WeakPtr.h"
class nsDocShell;
class nsFrameSelection;
class nsIContent;
class nsIPresShell;
class nsITimer;
namespace mozilla {
namespace dom {
class Selection;
} // namespace dom
/**
* NOTE: SelectionCarets was obsoleted by AccessibleCaret, and is no longer used
* on B2G. This file is going to be removed in bug 1221459. Please see the wiki
* page for more information. https://wiki.mozilla.org/Copy_n_Paste
*
* The SelectionCarets draw a pair of carets when the selection is not
* collapsed, one at each end of the selection.
* SelectionCarets also handle visibility, dragging caret and selecting word
* when long tap event fired.
*
* The DOM structure is 2 div elements for showing start and end caret.
* Each div element has a child div element. That is, each caret consist of
* outer div and inner div. Outer div takes responsibility for detecting two
* carets are overlapping. Inner div is for actual appearance.
*
* Here is an explanation of the html class names:
* .moz-selectioncaret-left: Indicates start DIV.
* .moz-selectioncaret-right: Indicates end DIV.
* .hidden: This class name is set by SetVisibility,
* SetStartFrameVisibility and SetEndFrameVisibility. Element
* with this class name become hidden.
* .tilt: This class name is set by SetTilted. According to the
* UX spec, when selection carets are overlapping, the image of
* caret becomes tilt.
*/
class SelectionCarets final : public nsIReflowObserver,
public nsISelectionListener,
public nsIScrollObserver,
public nsSupportsWeakReference
{
public:
/**
* Indicate which part of caret we are dragging at.
*/
enum DragMode {
NONE,
START_FRAME,
END_FRAME
};
explicit SelectionCarets(nsIPresShell *aPresShell);
NS_DECL_ISUPPORTS
NS_DECL_NSIREFLOWOBSERVER
NS_DECL_NSISELECTIONLISTENER
// Notify selection carets about the blur event to hidden itself
void NotifyBlur(bool aIsLeavingDocument);
// nsIScrollObserver
virtual void ScrollPositionChanged() override;
// AsyncPanZoom started/stopped callbacks from nsIScrollObserver
virtual void AsyncPanZoomStarted() override;
virtual void AsyncPanZoomStopped() override;
void Init();
void Terminate();
nsEventStatus HandleEvent(WidgetEvent* aEvent);
bool GetVisibility() const
{
return mVisible;
}
/**
* Get from pref "selectioncaret.inflatesize.threshold". This will inflate size of
* caret frame when we checking if user click on caret or not. In app units.
*/
static int32_t SelectionCaretsInflateSize()
{
return sSelectionCaretsInflateSize;
}
/**
* Set visibility for selection caret.
*/
void SetVisibility(bool aVisible);
/**
* Update selection caret position base on current selection range.
*/
void UpdateSelectionCarets();
private:
virtual ~SelectionCarets();
SelectionCarets() = delete;
/**
* Select a word base on current position, which activates only if element is
* selectable. Triggered by long tap event.
*/
nsresult SelectWord();
/**
* Move selection base on current touch/mouse point
*/
nsEventStatus DragSelection(const nsPoint &movePoint);
/**
* Get the vertical center position of selection caret relative to root
* frame.
*/
nscoord GetCaretYCenterPosition();
/**
* Simulate drag state when we change the selection range.
* Hence, the selection change event will fire normally.
*/
void SetSelectionDragState(bool aState);
void SetSelectionDirection(nsDirection aDir);
/**
* Move start frame of selection caret based on current caret pos.
* In app units.
*/
void SetStartFramePos(const nsRect& aCaretRect);
/**
* Move end frame of selection caret based on current caret pos.
* In app units.
*/
void SetEndFramePos(const nsRect& aCaretRect);
/**
* Check if aPosition is on the start or end frame of the
* selection caret's inner div element.
*
* @param aPosition should be relative to document's root frame
* in app units
*/
bool IsOnStartFrameInner(const nsPoint& aPosition);
bool IsOnEndFrameInner(const nsPoint& aPosition);
/**
* Get rect of selection caret's outer div element relative
* to document's root frame, in app units.
*/
nsRect GetStartFrameRect();
nsRect GetEndFrameRect();
/**
* Get rect of selection caret's inner div element relative
* to document's root frame, in app units.
*/
nsRect GetStartFrameRectInner();
nsRect GetEndFrameRectInner();
/**
* Set visibility for start part of selection caret, this function
* only affects css property of start frame. So it doesn't change
* mVisible member. When caret overflows element's box we'll hide
* it by calling this function.
*/
void SetStartFrameVisibility(bool aVisible);
/**
* Same as above function but for end frame of selection caret.
*/
void SetEndFrameVisibility(bool aVisible);
/**
* Set tilt class name to start and end frame of selection caret.
*/
void SetTilted(bool aIsTilt);
// Utility functions
dom::Selection* GetSelection();
already_AddRefed<nsFrameSelection> GetFrameSelection();
nsIContent* GetFocusedContent();
void DispatchSelectionStateChangedEvent(dom::Selection* aSelection,
dom::SelectionState aState);
void DispatchSelectionStateChangedEvent(dom::Selection* aSelection,
const dom::Sequence<dom::SelectionState>& aStates);
void DispatchCustomEvent(const nsAString& aEvent);
/**
* Detecting long tap using timer
*/
void LaunchLongTapDetector();
void CancelLongTapDetector();
static void FireLongTap(nsITimer* aTimer, void* aSelectionCarets);
void LaunchScrollEndDetector();
void CancelScrollEndDetector();
static void FireScrollEnd(nsITimer* aTimer, void* aSelectionCarets);
nsIPresShell* mPresShell;
WeakPtr<nsDocShell> mDocShell;
// This timer is used for detecting long tap fire. If content process
// has APZC, we'll use APZC for long tap detecting. Otherwise, we use this
// timer to detect long tap.
nsCOMPtr<nsITimer> mLongTapDetectorTimer;
// This timer is used for detecting scroll end. We don't have
// scroll end event now, so we will fire this event with a
// const time when we scroll. So when timer triggers, we treat it
// as scroll end event.
nsCOMPtr<nsITimer> mScrollEndDetectorTimer;
// When touch or mouse down, we save the position for detecting
// drag distance
nsPoint mDownPoint;
// For filter multitouch event
int32_t mActiveTouchId;
nscoord mCaretCenterToDownPointOffsetY;
// The horizontal boundary is defined by the first selected frame which
// determines the start-caret position. When users drag the end-caret up,
// the touch input(pos.y) will be changed to not cross this boundary.
// Otherwise, the selection range changes to one character only
// which causes the bad user experience.
nscoord mDragUpYBoundary;
// The horizontal boundary is defined by the last selected frame which
// determines the end-caret position. When users drag the start-caret down,
// the touch input(pos.y) will be changed to not cross this boundary.
// Otherwise, the selection range changes to one character only
// which causes the bad user experience.
nscoord mDragDownYBoundary;
DragMode mDragMode;
// True if async-pan-zoom should be used for selection carets.
bool mUseAsyncPanZoom;
// True if AsyncPanZoom is started
bool mInAsyncPanZoomGesture;
bool mEndCaretVisible;
bool mStartCaretVisible;
bool mSelectionVisibleInScrollFrames;
bool mVisible;
// Preference
static int32_t sSelectionCaretsInflateSize;
};
} // namespace mozilla
#endif //SelectionCarets_h__

1110
layout/base/TouchCaret.cpp Normal file

File diff suppressed because it is too large Load Diff

321
layout/base/TouchCaret.h Normal file
View File

@ -0,0 +1,321 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 et tw=78: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_TouchCaret_h__
#define mozilla_TouchCaret_h__
#include "nsISelectionListener.h"
#include "nsIScrollObserver.h"
#include "nsIWeakReferenceUtils.h"
#include "nsITimer.h"
#include "mozilla/EventForwards.h"
#include "mozilla/TouchEvents.h"
#include "Units.h"
class nsCanvasFrame;
class nsIFrame;
class nsIPresShell;
namespace mozilla {
/**
* NOTE: TouchCaret was obsoleted by AccessibleCaret, and is no longer used on
* B2G. This file is going to be removed in bug 1221459. Please see the wiki
* page for more information. https://wiki.mozilla.org/Copy_n_Paste
*
* The TouchCaret places a touch caret according to caret position when the
* caret is shown.
* TouchCaret is also responsible for touch caret visibility. Touch caret
* won't be shown when timer expires or while key event causes selection change.
*/
class TouchCaret final : public nsISelectionListener,
public nsIScrollObserver,
public nsSupportsWeakReference
{
public:
explicit TouchCaret(nsIPresShell* aPresShell);
NS_DECL_ISUPPORTS
NS_DECL_NSISELECTIONLISTENER
void Init();
void Terminate();
// nsIScrollObserver
virtual void ScrollPositionChanged() override;
// AsyncPanZoom started/stopped callbacks from nsIScrollObserver
virtual void AsyncPanZoomStarted() override;
virtual void AsyncPanZoomStopped() override;
/**
* Handle mouse and touch event only.
* Depends on visibility and position of touch caret, HandleEvent may consume
* that input event and return nsEventStatus_eConsumeNoDefault to the caller.
* In that case, caller should stop bubble up that input event.
*/
nsEventStatus HandleEvent(WidgetEvent* aEvent);
void SyncVisibilityWithCaret();
void UpdatePositionIfNeeded();
/**
* GetVisibility will get the visibility of the touch caret.
*/
bool GetVisibility() const
{
return mVisible;
}
/**
* Open or close the Android TextSelection ActionBar based on visibility.
*/
static void UpdateAndroidActionBarVisibility(bool aVisibility, uint32_t& aViewID);
private:
// Hide default constructor.
TouchCaret() = delete;
~TouchCaret();
bool IsDisplayable();
void UpdatePosition();
/**
* SetVisibility will set the visibility of the touch caret.
* SetVisibility performs an attribute-changed notification which could, in
* theory, destroy frames.
*/
void SetVisibility(bool aVisible);
/**
* Helper function to get caret's focus frame and caret's bounding rect.
*/
nsIFrame* GetCaretFocusFrame(nsRect* aOutRect = nullptr);
/**
* Find the nsCanvasFrame which holds the touch caret.
*/
nsCanvasFrame* GetCanvasFrame();
/**
* Find the root frame to update the touch caret's position.
*/
nsIFrame* GetRootFrame();
/**
* Retrieve the bounding rectangle of the touch caret.
*
* @returns A nsRect representing the bounding rectangle of this touch caret.
* The returned offset is relative to the canvas frame.
*/
nsRect GetTouchFrameRect();
/**
* Retrieve the bounding rectangle where the caret can be positioned.
* If we're positioning a caret in an input field, make sure the touch caret
* stays within the bounds of the field.
*
* @returns A nsRect representing the bounding rectangle of this valid area.
* The returned offset is relative to the canvas frame.
*/
nsRect GetContentBoundary();
/**
* Retrieve the center y position of the caret.
* The returned point is relative to the canvas frame.
*/
nscoord GetCaretYCenterPosition();
/**
* Retrieve the rect of the touch caret.
* The returned rect is relative to the canvas frame.
*/
nsRect GetTouchCaretRect();
/**
* Clamp the position of the touch caret to the scroll frame boundary.
* The returned rect is relative to the canvas frame.
*/
nsRect ClampRectToScrollFrame(const nsRect& aRect);
/**
* Set the position of the touch caret.
* Touch caret is an absolute positioned div.
*/
void SetTouchFramePos(const nsRect& aRect);
void LaunchExpirationTimer();
void CancelExpirationTimer();
static void DisableTouchCaretCallback(nsITimer* aTimer, void* aPresShell);
/**
* Move the caret to movePoint which is relative to the canvas frame.
* Caret will be scrolled into view.
*
* @param movePoint tap location relative to the canvas frame.
*/
void MoveCaret(const nsPoint& movePoint);
/**
* Check if aPoint is inside the touch caret frame.
*
* @param aPoint tap location relative to the canvas frame.
*/
bool IsOnTouchCaret(const nsPoint& aPoint);
/**
* These Handle* functions comprise input alphabet of the TouchCaret
* finite-state machine triggering state transitions.
*/
nsEventStatus HandleMouseMoveEvent(WidgetMouseEvent* aEvent);
nsEventStatus HandleMouseUpEvent(WidgetMouseEvent* aEvent);
nsEventStatus HandleMouseDownEvent(WidgetMouseEvent* aEvent);
nsEventStatus HandleTouchMoveEvent(WidgetTouchEvent* aEvent);
nsEventStatus HandleTouchUpEvent(WidgetTouchEvent* aEvent);
nsEventStatus HandleTouchDownEvent(WidgetTouchEvent* aEvent);
/**
* Get the coordinates of a given touch event, relative to canvas frame.
* @param aEvent the event
* @param aIdentifier the mIdentifier of the touch which is to be converted.
* @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
* for some reason the coordinates for the touch are not known (e.g.,
* the mIdentifier touch is not found).
*/
nsPoint GetEventPosition(WidgetTouchEvent* aEvent, int32_t aIdentifier);
/**
* Set mouse down state in nsFrameSelection, we'll set state to true when
* user start dragging caret and set state to false when user release the
* caret. The reason for setting this state is it will fire drag reason
* when moving caret and fire mouseup reason when releasing caret. So that
* the display behavior of copy/paste menu becomes more reasonable.
*/
void SetSelectionDragState(bool aState);
/**
* Get the coordinates of a given mouse event, relative to canvas frame.
* @param aEvent the event
* @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if
* for some reason the coordinates for the mouse are not known.
*/
nsPoint GetEventPosition(WidgetMouseEvent* aEvent);
/**
* States of TouchCaret finite-state machine.
*/
enum TouchCaretState {
// In this state, either there is no touch/mouse event going on, or the
// first stroke does not hit the touch caret.
// Will enter TOUCHCARET_TOUCHDRAG_ACTIVE state if the first touch stroke
// hits the touch caret. Will enter TOUCHCARET_MOUSEDRAG_ACTIVE state if
// mouse (left button) down hits the touch caret.
// Allowed next state: TOUCHCARET_MOUSEDRAG_ACTIVE,
// TOUCHCARET_TOUCHDRAG_ACTIVE.
TOUCHCARET_NONE,
// The first (left button) mouse down hits on the touch caret and is
// alive. Will enter TOUCHCARET_NONE state if the left button is release.
// Allowed next states: TOUCHCARET_NONE.
TOUCHCARET_MOUSEDRAG_ACTIVE,
// The first touch start event hits on touch caret and is alive.
// Will enter TOUCHCARET_NONE state if the finger on touch caret is
// removed and there are no more fingers on the screen; will enter
// TOUCHCARET_TOUCHDRAG_INACTIVE state if the finger on touch caret is
// removed but still has fingers touching on the screen.
// Allowed next states: TOUCHCARET_NONE, TOUCHCARET_TOUCHDRAG_INACTIVE.
TOUCHCARET_TOUCHDRAG_ACTIVE,
// The first touch stroke, which hit on touch caret, is dead, but still has
// fingers touching on the screen.
// Will enter TOUCHCARET_NONE state if all the fingers are removed from the
// screen.
// Allowed next state: TOUCHCARET_NONE.
TOUCHCARET_TOUCHDRAG_INACTIVE,
};
/**
* Do actual state transition and reset substates.
*/
void SetState(TouchCaretState aState);
/**
* Dispatch touch caret tap event to chrome.
*/
void DispatchTapEvent();
/**
* Current state we're dealing with.
*/
TouchCaretState mState;
/**
* Array containing all active touch IDs. When a touch happens, it gets added
* to this array, even if we choose not to handle it. When it ends, we remove
* it. We need to maintain this array in order to detect the end of the
* "multitouch" states because touch start events contain all current touches,
* but touch end events contain only those touches that have gone.
*/
nsTArray<int32_t> mTouchesId;
/**
* The mIdentifier of the touch which is on the touch caret.
*/
int32_t mActiveTouchId;
/**
* The offset between the tap location and the center of caret along y axis.
*/
nscoord mCaretCenterToDownPointOffsetY;
/**
* Get from pref "touchcaret.inflatesize.threshold". This will inflate the
* size of the touch caret frame when checking if user clicks on the caret
* or not. In app units.
*/
static int32_t TouchCaretInflateSize() { return sTouchCaretInflateSize; }
static int32_t TouchCaretExpirationTime()
{
return sTouchCaretExpirationTime;
}
void LaunchScrollEndDetector();
void CancelScrollEndDetector();
static void FireScrollEnd(nsITimer* aTimer, void* aSelectionCarets);
// This timer is used for detecting scroll end. We don't have
// scroll end event now, so we will fire this event with a
// const time when we scroll. So when timer triggers, we treat it
// as scroll end event.
nsCOMPtr<nsITimer> mScrollEndDetectorTimer;
nsWeakPtr mPresShell;
WeakPtr<nsDocShell> mDocShell;
// True if AsyncPanZoom is started
bool mInAsyncPanZoomGesture;
// Touch caret visibility
bool mVisible;
// Use for detecting single tap on touch caret.
bool mIsValidTap;
// Touch caret timer
nsCOMPtr<nsITimer> mTouchCaretExpirationTimer;
// Preference
static int32_t sTouchCaretInflateSize;
static int32_t sTouchCaretExpirationTime;
// The auto scroll timer's interval in miliseconds.
friend class SelectionCarets;
static const int32_t sAutoScrollTimerDelay = 30;
// Time for trigger scroll end event, in miliseconds.
static const int32_t sScrollEndTimerDelay = 300;
};
} //namespace mozilla
#endif //mozilla_TouchCaret_h__

View File

@ -6,16 +6,7 @@
*/
#include "TouchManager.h"
#include "mozilla/TouchEvents.h"
#include "mozilla/dom/EventTarget.h"
#include "nsIFrame.h"
#include "nsPresShell.h"
#include "nsView.h"
namespace mozilla {
using EventTarget = ::mozilla::dom::EventTarget;
nsRefPtrHashtable<nsUint32HashKey, dom::Touch>* TouchManager::gCaptureTouchList;
@ -231,5 +222,3 @@ TouchManager::PreHandleEvent(WidgetEvent* aEvent,
}
return true;
}
} // namespace mozilla

View File

@ -15,8 +15,6 @@
class PresShell;
class nsIDocument;
namespace mozilla {
class TouchManager {
public:
// Initialize and release static variables
@ -41,6 +39,4 @@ private:
nsCOMPtr<nsIDocument> mDocument;
};
} // namespace mozilla
#endif /* !defined(TouchManager_h_) */

View File

@ -7,10 +7,8 @@
#include <inttypes.h>
#include "FrameMetrics.h"
#include "gfxPrefs.h"
#include "LayersLogging.h"
#include "mozilla/layers/APZCCallbackHelper.h"
#include "mozilla/Preferences.h"
#include "nsDocument.h"
#include "nsIFrame.h"
#include "nsLayoutUtils.h"

View File

@ -40,8 +40,9 @@ with Files('nsChangeHint.h'):
with Files('nsBidi*'):
BUG_COMPONENT = ('Core', 'Layout: Text')
with Files('AccessibleCaret*'):
BUG_COMPONENT = ('Core', 'Selection')
for caret_file in ('AccessibleCaret*', 'TouchCaret*', 'SelectionCarets*'):
with Files(caret_file):
BUG_COMPONENT = ('Core', 'Selection')
XPIDL_SOURCES += [
'nsIStyleSheetService.idl',
@ -146,7 +147,9 @@ UNIFIED_SOURCES += [
'RestyleManager.cpp',
'RestyleTracker.cpp',
'ScrollbarStyles.cpp',
'SelectionCarets.cpp',
'StackArena.cpp',
'TouchCaret.cpp',
'TouchManager.cpp',
'ZoomConstraintsClient.cpp',
]

View File

@ -63,6 +63,8 @@ class nsCaret;
namespace mozilla {
class AccessibleCaretEventHub;
class CSSStyleSheet;
class TouchCaret;
class SelectionCarets;
} // namespace mozilla
class nsFrameSelection;
class nsFrameManager;
@ -805,6 +807,31 @@ public:
*/
virtual void NotifyDestroyingFrame(nsIFrame* aFrame) = 0;
/**
* Get the touch caret, if it exists. AddRefs it.
*/
virtual already_AddRefed<mozilla::TouchCaret> GetTouchCaret() const = 0;
/**
* Returns the touch caret element of the presshell.
*/
virtual mozilla::dom::Element* GetTouchCaretElement() const = 0;
/**
* Get the selection caret, if it exists. AddRefs it.
*/
virtual already_AddRefed<mozilla::SelectionCarets> GetSelectionCarets() const = 0;
/**
* Returns the start part of selection caret element of the presshell.
*/
virtual mozilla::dom::Element* GetSelectionCaretsStartElement() const = 0;
/**
* Returns the end part of selection caret element of the presshell.
*/
virtual mozilla::dom::Element* GetSelectionCaretsEndElement() const = 0;
/**
* Get the AccessibleCaretEventHub, if it exists. AddRefs it.
*/

View File

@ -78,6 +78,8 @@
#include "nsIMozBrowserFrame.h"
#include "nsCaret.h"
#include "AccessibleCaretEventHub.h"
#include "TouchCaret.h"
#include "SelectionCarets.h"
#include "nsIDOMHTMLDocument.h"
#include "nsFrameManager.h"
#include "nsXPCOM.h"
@ -703,9 +705,33 @@ nsIPresShell::FrameSelection()
static bool sSynthMouseMove = true;
static uint32_t sNextPresShellId;
static bool sPointerEventEnabled = true;
static bool sTouchCaretEnabled = false;
static bool sSelectionCaretEnabled = false;
static bool sAccessibleCaretEnabled = false;
static bool sBeforeAfterKeyboardEventEnabled = false;
/* static */ bool
PresShell::TouchCaretPrefEnabled()
{
static bool initialized = false;
if (!initialized) {
Preferences::AddBoolVarCache(&sTouchCaretEnabled, "touchcaret.enabled");
initialized = true;
}
return sTouchCaretEnabled;
}
/* static */ bool
PresShell::SelectionCaretPrefEnabled()
{
static bool initialized = false;
if (!initialized) {
Preferences::AddBoolVarCache(&sSelectionCaretEnabled, "selectioncaret.enabled");
initialized = true;
}
return sSelectionCaretEnabled;
}
/* static */ bool
PresShell::AccessibleCaretEnabled()
{
@ -856,6 +882,18 @@ PresShell::Init(nsIDocument* aDocument,
// Add the preference style sheet.
UpdatePreferenceStyles();
if (TouchCaretPrefEnabled() && !AccessibleCaretEnabled()) {
// Create touch caret handle
mTouchCaret = new TouchCaret(this);
mTouchCaret->Init();
}
if (SelectionCaretPrefEnabled() && !AccessibleCaretEnabled()) {
// Create selection caret handle
mSelectionCarets = new SelectionCarets(this);
mSelectionCarets->Init();
}
if (AccessibleCaretEnabled()) {
// Need to happen before nsFrameSelection has been set up.
mAccessibleCaretEventHub = new AccessibleCaretEventHub(this);
@ -1157,6 +1195,16 @@ PresShell::Destroy()
mSelection->DisconnectFromPresShell();
}
if (mTouchCaret) {
mTouchCaret->Terminate();
mTouchCaret = nullptr;
}
if (mSelectionCarets) {
mSelectionCarets->Terminate();
mSelectionCarets = nullptr;
}
if (mAccessibleCaretEventHub) {
mAccessibleCaretEventHub->Terminate();
mAccessibleCaretEventHub = nullptr;
@ -1943,6 +1991,19 @@ already_AddRefed<nsCaret> PresShell::GetCaret() const
return caret.forget();
}
// TouchCaret
already_AddRefed<TouchCaret> PresShell::GetTouchCaret() const
{
RefPtr<TouchCaret> touchCaret = mTouchCaret;
return touchCaret.forget();
}
already_AddRefed<SelectionCarets> PresShell::GetSelectionCarets() const
{
RefPtr<SelectionCarets> selectionCaret = mSelectionCarets;
return selectionCaret.forget();
}
already_AddRefed<AccessibleCaretEventHub> PresShell::GetAccessibleCaretEventHub() const
{
RefPtr<AccessibleCaretEventHub> eventHub = mAccessibleCaretEventHub;
@ -1973,6 +2034,12 @@ NS_IMETHODIMP PresShell::SetCaretEnabled(bool aInEnable)
}
}
// We should sync touch caret's visibility with caret every time since touch
// caret might be hidden due to timeout while caret is enabled.
if (mTouchCaret) {
mTouchCaret->SyncVisibilityWithCaret();
}
return NS_OK;
}
@ -2303,6 +2370,24 @@ PresShell::GetCanvasFrame() const
return do_QueryFrame(frame);
}
Element*
PresShell::GetTouchCaretElement() const
{
return GetCanvasFrame() ? GetCanvasFrame()->GetTouchCaretElement() : nullptr;
}
Element*
PresShell::GetSelectionCaretsStartElement() const
{
return GetCanvasFrame() ? GetCanvasFrame()->GetSelectionCaretsStartElement() : nullptr;
}
Element*
PresShell::GetSelectionCaretsEndElement() const
{
return GetCanvasFrame() ? GetCanvasFrame()->GetSelectionCaretsEndElement() : nullptr;
}
void
PresShell::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
{
@ -3701,6 +3786,10 @@ PresShell::UnsuppressAndInvalidate()
if (rootFrame) {
// let's assume that outline on a root frame is not supported
rootFrame->InvalidateFrame();
if (mTouchCaret) {
mTouchCaret->SyncVisibilityWithCaret();
}
}
// now that painting is unsuppressed, focus may be set on the document
@ -6891,6 +6980,47 @@ PresShell::HandleEvent(nsIFrame* aFrame,
RecordMouseLocation(aEvent);
// Determine whether event need to be consumed by touch caret or not.
if (TouchCaretPrefEnabled() || SelectionCaretPrefEnabled()) {
// We have to target the focus window because regardless of where the
// touch goes, we want to access the touch caret when user is typing on an
// editable element.
nsCOMPtr<nsPIDOMWindow> window = GetFocusedDOMWindowInOurWindow();
nsCOMPtr<nsIDocument> retargetEventDoc = window ? window->GetExtantDoc() : nullptr;
nsCOMPtr<nsIPresShell> presShell = retargetEventDoc ?
retargetEventDoc->GetShell() :
nullptr;
// Bug 1057256: Touch caret should handle the event before selection carets.
// Otherwise, a long tap on touch caret will be incorrectly handled by
// selection carets which makes moving touch caret failed.
RefPtr<TouchCaret> touchCaret = presShell ?
presShell->GetTouchCaret() :
nullptr;
if (touchCaret) {
*aEventStatus = touchCaret->HandleEvent(aEvent);
if (*aEventStatus == nsEventStatus_eConsumeNoDefault) {
// If the event is consumed by the touch caret, cancel APZC panning by
// setting mMultipleActionsPrevented.
aEvent->mFlags.mMultipleActionsPrevented = true;
return NS_OK;
}
}
RefPtr<SelectionCarets> selectionCaret = presShell ?
presShell->GetSelectionCarets() :
nullptr;
if (selectionCaret) {
*aEventStatus = selectionCaret->HandleEvent(aEvent);
if (*aEventStatus == nsEventStatus_eConsumeNoDefault) {
// If the event is consumed by the selection carets, cancel APZC panning by
// setting mMultipleActionsPrevented.
aEvent->mFlags.mMultipleActionsPrevented = true;
return NS_OK;
}
}
}
if (AccessibleCaretEnabled()) {
// We have to target the focus window because regardless of where the
// touch goes, we want to access the copy paste manager.
@ -8711,6 +8841,10 @@ PresShell::DidDoReflow(bool aInterruptible)
SynthesizeMouseMove(false);
}
if (mTouchCaret) {
mTouchCaret->UpdatePositionIfNeeded();
}
mPresContext->NotifyMissingFonts();
}

View File

@ -73,6 +73,12 @@ public:
// nsISupports
NS_DECL_ISUPPORTS
// Touch caret preference
static bool TouchCaretPrefEnabled();
// Selection caret preference
static bool SelectionCaretPrefEnabled();
static bool AccessibleCaretEnabled();
// BeforeAfterKeyboardEvent preference
@ -240,6 +246,14 @@ public:
virtual void ClearMouseCaptureOnView(nsView* aView) override;
virtual bool IsVisible() override;
// touch caret
virtual already_AddRefed<mozilla::TouchCaret> GetTouchCaret() const override;
virtual mozilla::dom::Element* GetTouchCaretElement() const override;
// selection caret
virtual already_AddRefed<mozilla::SelectionCarets> GetSelectionCarets() const override;
virtual mozilla::dom::Element* GetSelectionCaretsStartElement() const override;
virtual mozilla::dom::Element* GetSelectionCaretsEndElement() const override;
virtual already_AddRefed<mozilla::AccessibleCaretEventHub> GetAccessibleCaretEventHub() const override;
// caret handling
@ -802,11 +816,15 @@ protected:
nsCallbackEventRequest* mFirstCallbackEventRequest;
nsCallbackEventRequest* mLastCallbackEventRequest;
mozilla::TouchManager mTouchManager;
// TouchManager
TouchManager mTouchManager;
RefPtr<ZoomConstraintsClient> mZoomConstraintsClient;
RefPtr<MobileViewportManager> mMobileViewportManager;
// TouchCaret
RefPtr<mozilla::TouchCaret> mTouchCaret;
RefPtr<mozilla::SelectionCarets> mSelectionCarets;
RefPtr<mozilla::AccessibleCaretEventHub> mAccessibleCaretEventHub;
// This timer controls painting suppression. Until it fires

View File

@ -23,6 +23,11 @@
#include "gfxPlatform.h"
#include "nsPrintfCString.h"
#include "mozilla/dom/AnonymousContent.h"
// for touchcaret
#include "nsContentList.h"
#include "nsContentCreatorFunctions.h"
#include "nsContentUtils.h"
#include "nsStyleSet.h"
// for focus
#include "nsIScrollableFrame.h"
#ifdef DEBUG_CANVAS_FOCUS
@ -49,6 +54,8 @@ NS_QUERYFRAME_HEAD(nsCanvasFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
NS_IMPL_ISUPPORTS(nsCanvasFrame::DummyTouchListener, nsIDOMEventListener)
void
nsCanvasFrame::ShowCustomContentContainer()
{
@ -76,6 +83,66 @@ nsCanvasFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
nsCOMPtr<nsIDocument> doc = mContent->OwnerDoc();
nsresult rv = NS_OK;
ErrorResult er;
// We won't create touch caret element if preference is not enabled.
if (PresShell::TouchCaretPrefEnabled()) {
RefPtr<NodeInfo> 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);
rv = NS_NewHTMLElement(getter_AddRefs(mTouchCaretElement), nodeInfo.forget(),
NOT_FROM_PARSER);
NS_ENSURE_SUCCESS(rv, rv);
aElements.AppendElement(mTouchCaretElement);
// Set touch caret to visibility: hidden by default.
nsAutoString classValue;
classValue.AppendLiteral("moz-touchcaret hidden");
rv = mTouchCaretElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
classValue, true);
if (!mDummyTouchListener) {
mDummyTouchListener = new DummyTouchListener();
}
mTouchCaretElement->AddEventListener(NS_LITERAL_STRING("touchstart"),
mDummyTouchListener, false);
NS_ENSURE_SUCCESS(rv, rv);
}
if (PresShell::SelectionCaretPrefEnabled()) {
// Selection caret
mSelectionCaretsStartElement = doc->CreateHTMLElement(nsGkAtoms::div);
aElements.AppendElement(mSelectionCaretsStartElement);
nsCOMPtr<mozilla::dom::Element> selectionCaretsStartElementInner = doc->CreateHTMLElement(nsGkAtoms::div);
mSelectionCaretsStartElement->AppendChildTo(selectionCaretsStartElementInner, false);
mSelectionCaretsEndElement = doc->CreateHTMLElement(nsGkAtoms::div);
aElements.AppendElement(mSelectionCaretsEndElement);
nsCOMPtr<mozilla::dom::Element> selectionCaretsEndElementInner = doc->CreateHTMLElement(nsGkAtoms::div);
mSelectionCaretsEndElement->AppendChildTo(selectionCaretsEndElementInner, false);
rv = mSelectionCaretsStartElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
NS_LITERAL_STRING("moz-selectioncaret-left hidden"),
true);
NS_ENSURE_SUCCESS(rv, rv);
rv = mSelectionCaretsEndElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
NS_LITERAL_STRING("moz-selectioncaret-right hidden"),
true);
if (!mDummyTouchListener) {
mDummyTouchListener = new DummyTouchListener();
}
mSelectionCaretsStartElement->AddEventListener(NS_LITERAL_STRING("touchstart"),
mDummyTouchListener, false);
mSelectionCaretsEndElement->AddEventListener(NS_LITERAL_STRING("touchstart"),
mDummyTouchListener, false);
NS_ENSURE_SUCCESS(rv, rv);
}
// Create the custom content container.
mCustomContentContainer = doc->CreateHTMLElement(nsGkAtoms::div);
@ -121,6 +188,18 @@ nsCanvasFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
void
nsCanvasFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements, uint32_t aFilter)
{
if (mTouchCaretElement) {
aElements.AppendElement(mTouchCaretElement);
}
if (mSelectionCaretsStartElement) {
aElements.AppendElement(mSelectionCaretsStartElement);
}
if (mSelectionCaretsEndElement) {
aElements.AppendElement(mSelectionCaretsEndElement);
}
aElements.AppendElement(mCustomContentContainer);
}
@ -133,6 +212,25 @@ nsCanvasFrame::DestroyFrom(nsIFrame* aDestructRoot)
sf->RemoveScrollPositionListener(this);
}
if (mTouchCaretElement) {
mTouchCaretElement->RemoveEventListener(NS_LITERAL_STRING("touchstart"),
mDummyTouchListener, false);
}
if (mSelectionCaretsStartElement) {
mSelectionCaretsStartElement->RemoveEventListener(NS_LITERAL_STRING("touchstart"),
mDummyTouchListener, false);
}
if (mSelectionCaretsEndElement) {
mSelectionCaretsEndElement->RemoveEventListener(NS_LITERAL_STRING("touchstart"),
mDummyTouchListener, false);
}
nsContentUtils::DestroyAnonymousContent(&mTouchCaretElement);
nsContentUtils::DestroyAnonymousContent(&mSelectionCaretsStartElement);
nsContentUtils::DestroyAnonymousContent(&mSelectionCaretsEndElement);
// Elements inserted in the custom content container have the same lifetime as
// the document, so before destroying the container, make sure to keep a clone
// of each of them at document level so they can be re-appended on reframe.
@ -199,8 +297,8 @@ nsCanvasFrame::AppendFrames(ChildListID aListID,
MOZ_ASSERT(aListID == kPrincipalList, "unexpected child list");
if (!mFrames.IsEmpty()) {
for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
// We only allow native anonymous child frames to be in principal child
// list in canvas frame.
// 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");
}
@ -429,6 +527,15 @@ nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsIFrame* kid;
for (kid = GetFirstPrincipalChild(); kid; kid = kid->GetNextSibling()) {
// Skip touch/selection caret frame if we do not build caret.
if (!aBuilder->IsBuildingCaret()) {
if(kid->GetContent() == mTouchCaretElement ||
kid->GetContent() == mSelectionCaretsStartElement||
kid->GetContent() == mSelectionCaretsEndElement) {
continue;
}
}
// Put our child into its own pseudo-stack.
BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
}

View File

@ -14,6 +14,7 @@
#include "nsIScrollPositionListener.h"
#include "nsDisplayList.h"
#include "nsIAnonymousContentCreator.h"
#include "nsIDOMEventListener.h"
class nsPresContext;
class nsRenderingContext;
@ -82,6 +83,23 @@ public:
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements, uint32_t aFilter) override;
// Touch caret handle function
mozilla::dom::Element* GetTouchCaretElement() const
{
return mTouchCaretElement;
}
// Selection Caret Handle function
mozilla::dom::Element* GetSelectionCaretsStartElement() const
{
return mSelectionCaretsStartElement;
}
mozilla::dom::Element* GetSelectionCaretsEndElement() const
{
return mSelectionCaretsEndElement;
}
mozilla::dom::Element* GetCustomContentContainer() const
{
return mCustomContentContainer;
@ -147,7 +165,28 @@ protected:
bool mDoPaintFocus;
bool mAddedScrollPositionListener;
nsCOMPtr<mozilla::dom::Element> mTouchCaretElement;
nsCOMPtr<mozilla::dom::Element> mSelectionCaretsStartElement;
nsCOMPtr<mozilla::dom::Element> mSelectionCaretsEndElement;
nsCOMPtr<mozilla::dom::Element> mCustomContentContainer;
class DummyTouchListener final : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) override
{
return NS_OK;
}
private:
~DummyTouchListener() {}
};
/**
* A no-op touch-listener used for APZ purposes.
*/
RefPtr<DummyTouchListener> mDummyTouchListener;
};
/**

View File

@ -51,6 +51,9 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
#include "nsPresContext.h"
#include "nsIPresShell.h"
#include "nsCaret.h"
#include "TouchCaret.h"
#include "SelectionCarets.h"
#include "AccessibleCaretEventHub.h"
#include "mozilla/MouseEvents.h"
@ -820,6 +823,24 @@ nsFrameSelection::Init(nsIPresShell *aShell, nsIContent *aLimiter)
"dom.select_events.enabled", false);
}
// Set touch caret as selection listener
RefPtr<TouchCaret> touchCaret = mShell->GetTouchCaret();
if (touchCaret) {
int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (mDomSelections[index]) {
mDomSelections[index]->AddSelectionListener(touchCaret);
}
}
// Set selection caret as selection listener
RefPtr<SelectionCarets> selectionCarets = mShell->GetSelectionCarets();
if (selectionCarets) {
int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
if (mDomSelections[index]) {
mDomSelections[index]->AddSelectionListener(selectionCarets);
}
}
RefPtr<AccessibleCaretEventHub> eventHub = mShell->GetAccessibleCaretEventHub();
if (eventHub) {
int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
@ -3269,6 +3290,19 @@ nsFrameSelection::SetDelayedCaretData(WidgetMouseEvent* aMouseEvent)
void
nsFrameSelection::DisconnectFromPresShell()
{
// Remove touch caret as selection listener
RefPtr<TouchCaret> touchCaret = mShell->GetTouchCaret();
if (touchCaret) {
int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
mDomSelections[index]->RemoveSelectionListener(touchCaret);
}
RefPtr<SelectionCarets> selectionCarets = mShell->GetSelectionCarets();
if (selectionCarets) {
int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
mDomSelections[index]->RemoveSelectionListener(selectionCarets);
}
RefPtr<AccessibleCaretEventHub> eventHub = mShell->GetAccessibleCaretEventHub();
if (eventHub) {
int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);

View File

@ -417,6 +417,114 @@ div:-moz-native-anonymous.moz-accessiblecaret.none {
}
}
div:-moz-native-anonymous.moz-touchcaret,
div:-moz-native-anonymous.moz-selectioncaret-left,
div:-moz-native-anonymous.moz-selectioncaret-right {
position: fixed;
width: 44px;
height: 47px;
}
div:-moz-native-anonymous.moz-selectioncaret-left > div,
div:-moz-native-anonymous.moz-selectioncaret-right > div {
position: absolute;
width: 100%;
height: 100%;
bottom: 0;
}
div:-moz-native-anonymous.moz-touchcaret,
div:-moz-native-anonymous.moz-selectioncaret-left,
div:-moz-native-anonymous.moz-selectioncaret-right,
div:-moz-native-anonymous.moz-selectioncaret-left > div,
div:-moz-native-anonymous.moz-selectioncaret-right > div {
background-position: center bottom;
background-size: 100%;
background-repeat: no-repeat;
z-index: 2147483647;
}
div:-moz-native-anonymous.moz-touchcaret,
div:-moz-native-anonymous.moz-selectioncaret-left > div,
div:-moz-native-anonymous.moz-selectioncaret-right > div {
background-image: url("resource://gre/res/text_caret.png");
}
div:-moz-native-anonymous.moz-touchcaret,
div:-moz-native-anonymous.moz-selectioncaret-left,
div:-moz-native-anonymous.moz-selectioncaret-right {
margin-left: -23px;
}
div:-moz-native-anonymous.moz-selectioncaret-left.tilt > div {
background-image: url("resource://gre/res/text_caret_tilt_left.png");
margin-left: -17px;
}
div:-moz-native-anonymous.moz-selectioncaret-right.tilt > div {
background-image: url("resource://gre/res/text_caret_tilt_right.png");
margin-left: 18px;
}
@media (min-resolution: 1.5dppx) {
div:-moz-native-anonymous.moz-touchcaret,
div:-moz-native-anonymous.moz-selectioncaret-left > div,
div:-moz-native-anonymous.moz-selectioncaret-right > div {
background-image: url("resource://gre/res/text_caret@1.5x.png");
}
div:-moz-native-anonymous.moz-selectioncaret-left.tilt > div {
background-image: url("resource://gre/res/text_caret_tilt_left@1.5x.png");
}
div:-moz-native-anonymous.moz-selectioncaret-right.tilt > div {
background-image: url("resource://gre/res/text_caret_tilt_right@1.5x.png");
}
}
@media (min-resolution: 2dppx) {
div:-moz-native-anonymous.moz-touchcaret,
div:-moz-native-anonymous.moz-selectioncaret-left > div,
div:-moz-native-anonymous.moz-selectioncaret-right > div {
background-image: url("resource://gre/res/text_caret@2x.png");
}
div:-moz-native-anonymous.moz-selectioncaret-left.tilt > div {
background-image: url("resource://gre/res/text_caret_tilt_left@2x.png");
}
div:-moz-native-anonymous.moz-selectioncaret-right.tilt > div {
background-image: url("resource://gre/res/text_caret_tilt_right@2x.png");
}
}
@media (min-resolution: 2.25dppx) {
div:-moz-native-anonymous.moz-touchcaret,
div:-moz-native-anonymous.moz-selectioncaret-left > div,
div:-moz-native-anonymous.moz-selectioncaret-right > div {
background-image: url("resource://gre/res/text_caret@2.25x.png");
}
div:-moz-native-anonymous.moz-selectioncaret-left.tilt > div {
background-image: url("resource://gre/res/text_caret_tilt_left@2.25x.png");
}
div:-moz-native-anonymous.moz-selectioncaret-right.tilt > div {
background-image: url("resource://gre/res/text_caret_tilt_right@2.25x.png");
}
}
div:-moz-native-anonymous.moz-touchcaret.hidden,
div:-moz-native-anonymous.moz-selectioncaret-left.hidden,
div:-moz-native-anonymous.moz-selectioncaret-right.hidden,
div:-moz-native-anonymous.moz-selectioncaret-left.hidden > div,
div:-moz-native-anonymous.moz-selectioncaret-right.hidden > div {
width: 0px;
height: 0px;
margin: 0px;
visibility: hidden;
}
/* Custom content container in the CanvasFrame, fixed positioned on top of
everything else, not reacting to pointer events. */
div:-moz-native-anonymous.moz-custom-content-container {

View File

@ -51,6 +51,9 @@
// reflow so that that rare edge case doesn't lead to reftest
// failures.
branch.setBoolPref("layout.interruptible-reflow.enabled", false);
// Disable the auto-hide feature of touch caret to avoid potential
// intermittent issues.
branch.setIntPref("touchcaret.expiration.time", 0);
// Tell the search service we are running in the US. This also has the
// desired side-effect of preventing our geoip lookup.

View File

@ -543,18 +543,18 @@
@BINPATH@/res/language.properties
@BINPATH@/res/entityTables/*
#ifdef NIGHTLY_BUILD
@BINPATH@/res/accessiblecaret.png
@BINPATH@/res/accessiblecaret@1.5x.png
@BINPATH@/res/accessiblecaret@2.25x.png
@BINPATH@/res/accessiblecaret@2x.png
@BINPATH@/res/accessiblecaret_tilt_left.png
@BINPATH@/res/accessiblecaret_tilt_left@1.5x.png
@BINPATH@/res/accessiblecaret_tilt_left@2.25x.png
@BINPATH@/res/accessiblecaret_tilt_left@2x.png
@BINPATH@/res/accessiblecaret_tilt_right.png
@BINPATH@/res/accessiblecaret_tilt_right@1.5x.png
@BINPATH@/res/accessiblecaret_tilt_right@2.25x.png
@BINPATH@/res/accessiblecaret_tilt_right@2x.png
@BINPATH@/res/text_caret.png
@BINPATH@/res/text_caret@1.5x.png
@BINPATH@/res/text_caret@2.25x.png
@BINPATH@/res/text_caret@2x.png
@BINPATH@/res/text_caret_tilt_left.png
@BINPATH@/res/text_caret_tilt_left@1.5x.png
@BINPATH@/res/text_caret_tilt_left@2.25x.png
@BINPATH@/res/text_caret_tilt_left@2x.png
@BINPATH@/res/text_caret_tilt_right.png
@BINPATH@/res/text_caret_tilt_right@1.5x.png
@BINPATH@/res/text_caret_tilt_right@2.25x.png
@BINPATH@/res/text_caret_tilt_right@2x.png
#endif
#ifndef MOZ_ANDROID_EXCLUDE_FONTS

View File

@ -4856,6 +4856,25 @@ pref("browser.safebrowsing.allowOverride", true);
// Turn off Spatial navigation by default.
pref("snav.enabled", false);
// Original caret implementation on collapsed selection.
pref("touchcaret.enabled", false);
// This will inflate the size of the touch caret frame when checking if user
// clicks on the caret or not. In app units.
pref("touchcaret.inflatesize.threshold", 40);
// We'll start to increment time when user release the control of touch caret.
// When time exceed this expiration time, we'll hide touch caret.
// In milliseconds. (0 means disable this feature)
pref("touchcaret.expiration.time", 3000);
// Original caret implementation on non-collapsed selection.
pref("selectioncaret.enabled", false);
// This will inflate size of selection caret frame when we checking if
// user click on selection caret or not. In app units.
pref("selectioncaret.inflatesize.threshold", 40);
// New implementation to unify touch-caret and selection-carets.
pref("layout.accessiblecaret.enabled", false);

View File

@ -9,3 +9,4 @@ user_pref("dom.mozBrowserFramesEnabled", "%(OOP)s");
user_pref("dom.mozBrowserFramesWhitelist","app://test-container.gaiamobile.org,http://mochi.test:8888");
user_pref("dom.testing.datastore_enabled_for_hosted_apps", true);
user_pref("marionette.force-local", true);
user_pref("touchcaret.expiration.time", 0);