Bug 988143 - Enable Gecko Touch in Fennec, TouchCaret mods, r=ehsan

* * *
Bug 988143 - Enable Gecko Touch in Fennec, TouchCaret mods, r=ehsan
This commit is contained in:
Mark Capella 2015-05-14 22:06:13 -04:00
parent 16f6e4d712
commit 9549c6e21f
4 changed files with 120 additions and 7 deletions

View File

@ -60,13 +60,18 @@ NS_IMPL_ISUPPORTS(TouchCaret, nsISelectionListener)
/*static*/ int32_t TouchCaret::sTouchCaretInflateSize = 0;
/*static*/ int32_t TouchCaret::sTouchCaretExpirationTime = 0;
/*static*/ bool TouchCaret::sCaretManagesAndroidActionbar = false;
/*static*/ bool TouchCaret::sTouchcaretExtendedvisibility = false;
/*static*/ uint32_t TouchCaret::sActionBarViewCount = 0;
TouchCaret::TouchCaret(nsIPresShell* aPresShell)
: mState(TOUCHCARET_NONE),
mActiveTouchId(-1),
mCaretCenterToDownPointOffsetY(0),
mVisible(false),
mIsValidTap(false)
mIsValidTap(false),
mActionBarViewID(0)
{
MOZ_ASSERT(NS_IsMainThread());
@ -82,6 +87,10 @@ TouchCaret::TouchCaret(nsIPresShell* aPresShell)
"touchcaret.inflatesize.threshold");
Preferences::AddIntVarCache(&sTouchCaretExpirationTime,
"touchcaret.expiration.time");
Preferences::AddBoolVarCache(&sCaretManagesAndroidActionbar,
"caret.manages-android-actionbar");
Preferences::AddBoolVarCache(&sTouchcaretExtendedvisibility,
"touchcaret.extendedvisibility");
addedTouchCaretPref = true;
}
@ -174,6 +183,38 @@ TouchCaret::SetVisibility(bool aVisible)
// Set touch caret expiration time.
mVisible ? LaunchExpirationTimer() : CancelExpirationTimer();
// If after a TouchCaret visibility change we become hidden, ensure
// the Android ActionBar handler is notified to close the current view.
if (!mVisible && sCaretManagesAndroidActionbar) {
UpdateAndroidActionBarVisibility(false, mActionBarViewID);
}
}
/**
* Open or close the Android TextSelection ActionBar, based on visibility.
* Each time we're called to open the actionbar, we increment / assign a
* unique view ID and return it to the caller. The ID is returned on calls
* to close the actionbar to ensure we don't close the shared view if it
* was already force closed by a subsequent callers open request.
*/
/* static */void
TouchCaret::UpdateAndroidActionBarVisibility(bool aVisibility, uint32_t& aViewID)
{
// Are we openning a new view?
if (aVisibility) {
// Assign a new view ID.
aViewID = ++sActionBarViewCount;
}
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
nsString topic = (aVisibility) ?
NS_LITERAL_STRING("ActionBar:OpenNew") : NS_LITERAL_STRING("ActionBar:Close");
nsAutoString viewCount;
viewCount.AppendInt(aViewID);
os->NotifyObservers(nullptr, NS_ConvertUTF16toUTF8(topic).get(), viewCount.get());
}
}
nsRect
@ -362,6 +403,25 @@ TouchCaret::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection* aSel,
SetVisibility(false);
} else {
SyncVisibilityWithCaret();
// Is the TouchCaret visible and we're showing/hiding the actionbar?
if (mVisible && sCaretManagesAndroidActionbar) {
// A selection change due to touch tap opens the actionbar.
if (aReason & nsISelectionListener::MOUSEUP_REASON) {
UpdateAndroidActionBarVisibility(true, mActionBarViewID);
} else {
// Update the ActionBar state for caret-specific selection changes.
// Ignore transient selection composition changes that occur while
// the TouchCaret is also visible.
bool isCollapsed;
if (NS_SUCCEEDED(aSel->GetIsCollapsed(&isCollapsed)) && isCollapsed) {
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
os->NotifyObservers(nullptr, "ActionBar:UpdateState", nullptr);
}
}
}
}
}
return NS_OK;
@ -447,10 +507,6 @@ TouchCaret::IsDisplayable()
TOUCHCARET_LOG("Focus frame is not valid!");
return false;
}
if (focusRect.IsEmpty()) {
TOUCHCARET_LOG("Focus rect is empty!");
return false;
}
dom::Element* editingHost = focusFrame->GetContent()->GetEditingHost();
if (!editingHost) {
@ -458,6 +514,16 @@ TouchCaret::IsDisplayable()
return false;
}
// No further checks required if extended TouchCaret visibility.
if (sTouchcaretExtendedvisibility) {
return true;
}
if (focusRect.IsEmpty()) {
TOUCHCARET_LOG("Focus rect is empty!");
return false;
}
if (!nsContentUtils::HasNonEmptyTextContent(
editingHost, nsContentUtils::eRecurseIntoChildren)) {
TOUCHCARET_LOG("The content is empty!");
@ -837,6 +903,12 @@ TouchCaret::HandleMouseDownEvent(WidgetMouseEvent* aEvent)
CancelExpirationTimer();
status = nsEventStatus_eConsumeNoDefault;
} else {
// Mousedown events that miss HitTest can be caused by soft-keyboard
// auto-suggestions. If extended visibility, update the caret position.
if (sTouchcaretExtendedvisibility) {
UpdatePositionIfNeeded();
break;
}
// Set touch caret invisible if HisTest fails. Bypass event.
SetVisibility(false);
status = nsEventStatus_eIgnore;
@ -897,8 +969,14 @@ TouchCaret::HandleTouchDownEvent(WidgetTouchEvent* aEvent)
// No touch is on the touch caret. Set touch caret invisible, and bypass
// the event.
if (mActiveTouchId == -1) {
SetVisibility(false);
status = nsEventStatus_eIgnore;
// Check touch caret visibility style.
if (sTouchcaretExtendedvisibility) {
// Update position on events associated with scroll and pan-zoom.
UpdatePositionIfNeeded();
} else {
SetVisibility(false);
status = nsEventStatus_eIgnore;
}
}
}
break;

View File

@ -60,6 +60,11 @@ public:
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;
@ -280,10 +285,16 @@ private:
// Preference
static int32_t sTouchCaretInflateSize;
static int32_t sTouchCaretExpirationTime;
static bool sCaretManagesAndroidActionbar;
static bool sTouchcaretExtendedvisibility;
// The auto scroll timer's interval in miliseconds.
friend class SelectionCarets;
static const int32_t sAutoScrollTimerDelay = 30;
// Unique ID of current Mobile ActionBar view.
static uint32_t sActionBarViewCount;
uint32_t mActionBarViewID;
};
} //namespace mozilla
#endif //mozilla_TouchCaret_h__

View File

@ -882,3 +882,18 @@ pref("selectioncaret.detects.longtap", false);
// Selection carets override caret visibility.
pref("selectioncaret.visibility.affectscaret", true);
// Turn off touch caret by default.
pref("touchcaret.enabled", false);
// TouchCaret never auto-hides.
pref("touchcaret.expiration.time", 0);
// Touch caret stays visible under a wider range of conditions
// than the default b2g. We can display the caret in empty editables
// for example, and do not auto-hide until loss of focus.
pref("touchcaret.extendedvisibility", true);
// The TouchCaret and the SelectionCarets will indicate when the
// TextSelection actionbar is to be openned or closed.
pref("caret.manages-android-actionbar", true);

View File

@ -4563,6 +4563,15 @@ pref("selectioncaret.detects.longtap", true);
// Selection carets do not affect caret visibility.
pref("selectioncaret.visibility.affectscaret", false);
// The Touch caret by default observes the b2g visibility rules, and
// not the extended Android visibility rules that allow for touchcaret
// display in empty editable fields, for example.
pref("touchcaret.extendedvisibility", false);
// Desktop and b2g don't need to open or close the Android
// TextSelection (Actionbar) utility.
pref("caret.manages-android-actionbar", false);
// New implementation to unify touch-caret and selection-carets.
pref("layout.accessiblecaret.enabled", false);