mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 1016184 - Part 3b: Revise touch caret visibility logic. f=pchang, r=ehsan
* Refactor UpdateTouchCaret() into smaller functions. * Update touch caret in PresShell::DidDoReflow() and PresShell::UnsuppressAndInvalidate() if needed.
This commit is contained in:
parent
ac20b2f613
commit
4099ebe260
@ -58,7 +58,7 @@ TouchCaret::TouchCaret(nsIPresShell* aPresShell)
|
||||
mCaretCenterToDownPointOffsetY(0),
|
||||
mVisible(false)
|
||||
{
|
||||
TOUCHCARET_LOG("Constructor");
|
||||
TOUCHCARET_LOG("Constructor, PresShell=%p", aPresShell);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
static bool addedTouchCaretPref = false;
|
||||
@ -100,27 +100,29 @@ void
|
||||
TouchCaret::SetVisibility(bool aVisible)
|
||||
{
|
||||
if (mVisible == aVisible) {
|
||||
TOUCHCARET_LOG("Visibility not changed");
|
||||
TOUCHCARET_LOG("Set visibility %s, same as the old one",
|
||||
(aVisible ? "shown" : "hidden"));
|
||||
return;
|
||||
}
|
||||
|
||||
mVisible = aVisible;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
||||
if (!presShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::dom::Element* touchCaretElement = presShell->GetTouchCaretElement();
|
||||
if (!touchCaretElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
mVisible = aVisible;
|
||||
|
||||
// Set touch caret visibility.
|
||||
ErrorResult err;
|
||||
touchCaretElement->ClassList()->Toggle(NS_LITERAL_STRING("hidden"),
|
||||
dom::Optional<bool>(!mVisible),
|
||||
err);
|
||||
TOUCHCARET_LOG("Visibility %s", (mVisible ? "shown" : "hidden"));
|
||||
TOUCHCARET_LOG("Set visibility %s", (mVisible ? "shown" : "hidden"));
|
||||
|
||||
// Set touch caret expiration time.
|
||||
mVisible ? LaunchExpirationTimer() : CancelExpirationTimer();
|
||||
@ -331,6 +333,8 @@ nsresult
|
||||
TouchCaret::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection* aSel,
|
||||
int16_t aReason)
|
||||
{
|
||||
TOUCHCARET_LOG("Reason=%d", aReason);
|
||||
|
||||
// Hide touch caret while no caret exists.
|
||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
||||
if (!presShell) {
|
||||
@ -349,52 +353,110 @@ TouchCaret::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection* aSel,
|
||||
// If this notification is for a selection that is not the one the
|
||||
// the caret is currently interested in , then there is nothing to do!
|
||||
if (aSel != caret->GetCaretDOMSelection()) {
|
||||
TOUCHCARET_LOG("Return for selection mismatch!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Update touch caret position and visibility.
|
||||
// Hide touch caret while key event causes selection change.
|
||||
if ((aReason == nsISelectionListener::NO_REASON) ||
|
||||
(aReason & nsISelectionListener::KEYPRESS_REASON)) {
|
||||
UpdateTouchCaret(false);
|
||||
if (aReason & nsISelectionListener::KEYPRESS_REASON) {
|
||||
TOUCHCARET_LOG("KEYPRESS_REASON");
|
||||
SetVisibility(false);
|
||||
} else {
|
||||
UpdateTouchCaret(true);
|
||||
SyncVisibilityWithCaret();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
TouchCaret::UpdateTouchCaret(bool aVisible)
|
||||
TouchCaret::SyncVisibilityWithCaret()
|
||||
{
|
||||
TOUCHCARET_LOG("SyncVisibilityWithCaret");
|
||||
if (IsDisplayable()) {
|
||||
SetVisibility(true);
|
||||
UpdatePosition();
|
||||
} else {
|
||||
SetVisibility(false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TouchCaret::UpdatePositionIfNeeded()
|
||||
{
|
||||
TOUCHCARET_LOG("UpdatePositionIfNeeded");
|
||||
if (IsDisplayable()) {
|
||||
if (mVisible) {
|
||||
UpdatePosition();
|
||||
}
|
||||
} else {
|
||||
SetVisibility(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TouchCaret::IsDisplayable()
|
||||
{
|
||||
// Hide touch caret while no caret exists.
|
||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
||||
if (!presShell) {
|
||||
return;
|
||||
TOUCHCARET_LOG("PresShell is nullptr!");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRefPtr<nsCaret> caret = presShell->GetCaret();
|
||||
if (!caret) {
|
||||
SetVisibility(false);
|
||||
return;
|
||||
TOUCHCARET_LOG("Caret is nullptr!");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIFrame* canvasFrame = GetCanvasFrame();
|
||||
if (!canvasFrame) {
|
||||
TOUCHCARET_LOG("No canvas frame!");
|
||||
return false;
|
||||
}
|
||||
|
||||
dom::Element* touchCaretElement = presShell->GetTouchCaretElement();
|
||||
if (!touchCaretElement) {
|
||||
TOUCHCARET_LOG("No touch caret frame element!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hide touch caret while caret is not visible.
|
||||
bool caretVisible = false;
|
||||
caret->GetCaretVisible(&caretVisible);
|
||||
if (!caretVisible) {
|
||||
TOUCHCARET_LOG("Caret is not visible");
|
||||
SetVisibility(false);
|
||||
return;
|
||||
TOUCHCARET_LOG("Caret is not visible!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Caret is visible and shown, update touch caret.
|
||||
nsISelection* caretSelection = caret->GetCaretDOMSelection();
|
||||
nsRect focusRect;
|
||||
nsIFrame* focusFrame = caret->GetGeometry(caretSelection, &focusRect);
|
||||
if (!focusFrame) {
|
||||
TOUCHCARET_LOG("Focus frame is not valid!");
|
||||
return false;
|
||||
}
|
||||
if (focusRect.IsEmpty()) {
|
||||
TOUCHCARET_LOG("Focus rect is empty!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TouchCaret::UpdatePosition()
|
||||
{
|
||||
MOZ_ASSERT(mVisible);
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
||||
if (!presShell) {
|
||||
return;
|
||||
}
|
||||
nsRefPtr<nsCaret> caret = presShell->GetCaret();
|
||||
nsISelection* caretSelection = caret->GetCaretDOMSelection();
|
||||
nsRect focusRect;
|
||||
nsIFrame* focusFrame = caret->GetGeometry(caretSelection, &focusRect);
|
||||
if (!focusFrame || focusRect.IsEmpty()) {
|
||||
TOUCHCARET_LOG("Focus frame not valid");
|
||||
SetVisibility(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -415,6 +477,7 @@ TouchCaret::UpdateTouchCaret(bool aVisible)
|
||||
while (closestScrollFrame) {
|
||||
nsIScrollableFrame* sf = do_QueryFrame(closestScrollFrame);
|
||||
nsRect visualRect = sf->GetScrollPortRect();
|
||||
|
||||
// Clamp the touch caret in the scroll port.
|
||||
nsLayoutUtils::TransformRect(closestScrollFrame, canvasFrame, visualRect);
|
||||
pos = visualRect.ClampPoint(pos);
|
||||
@ -426,7 +489,6 @@ TouchCaret::UpdateTouchCaret(bool aVisible)
|
||||
}
|
||||
|
||||
SetTouchFramePos(pos);
|
||||
SetVisibility(aVisible);
|
||||
}
|
||||
|
||||
/* static */void
|
||||
|
@ -45,18 +45,9 @@ public:
|
||||
*/
|
||||
nsEventStatus HandleEvent(WidgetEvent* aEvent);
|
||||
|
||||
/**
|
||||
* By calling this function, touch caret recalculate touch frame position and
|
||||
* update accordingly.
|
||||
*/
|
||||
void UpdateTouchCaret(bool aVisible);
|
||||
void SyncVisibilityWithCaret();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
void UpdatePositionIfNeeded();
|
||||
|
||||
/**
|
||||
* GetVisibility will get the visibility of the touch caret.
|
||||
@ -72,6 +63,17 @@ private:
|
||||
|
||||
~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);
|
||||
|
||||
/**
|
||||
* Find the nsCanvasFrame which holds the touch caret.
|
||||
*/
|
||||
|
@ -2245,7 +2245,7 @@ NS_IMETHODIMP PresShell::SetCaretEnabled(bool aInEnable)
|
||||
mCaret->SetCaretVisible(mCaretEnabled);
|
||||
}
|
||||
if (mTouchCaret) {
|
||||
mTouchCaret->UpdateTouchCaret(mCaretEnabled);
|
||||
mTouchCaret->SyncVisibilityWithCaret();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3932,6 +3932,9 @@ PresShell::UnsuppressAndInvalidate()
|
||||
if (mCaretEnabled && mCaret) {
|
||||
mCaret->CheckCaretDrawingState();
|
||||
}
|
||||
if (mTouchCaret) {
|
||||
mTouchCaret->UpdatePositionIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
// now that painting is unsuppressed, focus may be set on the document
|
||||
@ -5805,7 +5808,7 @@ PresShell::MarkImagesInSubtreeVisible(nsIFrame* aFrame, const nsRect& aRect)
|
||||
if (usingDisplayport) {
|
||||
rect = displayPort;
|
||||
} else {
|
||||
rect = rect.Intersect(scrollFrame->GetScrollPortRect());
|
||||
rect = rect.Intersect(scrollFrame->GetScrollPortRect());
|
||||
}
|
||||
rect = scrollFrame->ExpandRectToNearlyVisible(rect);
|
||||
}
|
||||
@ -8649,6 +8652,7 @@ PresShell::DidDoReflow(bool aInterruptible, bool aWasInterrupted)
|
||||
if (sSynthMouseMove) {
|
||||
SynthesizeMouseMove(false);
|
||||
}
|
||||
|
||||
if (mCaret) {
|
||||
// Update the caret's position now to account for any changes created by
|
||||
// the reflow.
|
||||
@ -8656,6 +8660,10 @@ PresShell::DidDoReflow(bool aInterruptible, bool aWasInterrupted)
|
||||
mCaret->UpdateCaretPosition();
|
||||
}
|
||||
|
||||
if (mTouchCaret) {
|
||||
mTouchCaret->UpdatePositionIfNeeded();
|
||||
}
|
||||
|
||||
if (!aWasInterrupted) {
|
||||
ClearReflowOnZoomPending();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user