mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 550434 Clicking in an empty contenteditable element that has focus causes the caret to disappear (alternative approach) r=roc
This commit is contained in:
parent
94442dd89e
commit
6e00300d75
@ -371,8 +371,6 @@ nsEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||
return rv;
|
||||
}
|
||||
|
||||
EnsureSelectionInEditor(aMouseEvent, PR_FALSE);
|
||||
|
||||
// If we got a mouse down inside the editing area, we should force the
|
||||
// IME to commit before we change the cursor position
|
||||
mEditor->ForceCompositionEnd();
|
||||
@ -857,21 +855,14 @@ nsEditorEventListener::Focus(nsIDOMEvent* aEvent)
|
||||
NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
|
||||
NS_ENSURE_ARG(aEvent);
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
|
||||
// turn on selection and caret
|
||||
if (mEditor->IsDisabled()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
EnsureSelectionInEditor(aEvent, PR_TRUE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsEditorEventListener::EnsureSelectionInEditor(nsIDOMEvent* aEvent, PRBool aOnFocus)
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(target);
|
||||
|
||||
PRBool targetIsEditableDoc = PR_FALSE;
|
||||
@ -889,12 +880,12 @@ nsEditorEventListener::EnsureSelectionInEditor(nsIDOMEvent* aEvent, PRBool aOnFo
|
||||
// listener in the chain changed the focus.
|
||||
if (editableRoot) {
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
NS_ENSURE_TRUE(fm, );
|
||||
NS_ENSURE_TRUE(fm, NS_OK);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
fm->GetFocusedElement(getter_AddRefs(element));
|
||||
if (!SameCOMIdentity(element, target))
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -910,24 +901,22 @@ nsEditorEventListener::EnsureSelectionInEditor(nsIDOMEvent* aEvent, PRBool aOnFo
|
||||
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||
getter_AddRefs(selection));
|
||||
|
||||
if (aOnFocus) {
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
if (presShell) {
|
||||
nsRefPtr<nsCaret> caret = presShell->GetCaret();
|
||||
if (caret) {
|
||||
caret->SetIgnoreUserModify(PR_FALSE);
|
||||
if (selection) {
|
||||
caret->SetCaretDOMSelection(selection);
|
||||
}
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
if (presShell) {
|
||||
nsRefPtr<nsCaret> caret = presShell->GetCaret();
|
||||
if (caret) {
|
||||
caret->SetIgnoreUserModify(PR_FALSE);
|
||||
if (selection) {
|
||||
caret->SetCaretDOMSelection(selection);
|
||||
}
|
||||
}
|
||||
|
||||
selCon->SetCaretReadOnly(mEditor->IsReadonly());
|
||||
selCon->SetCaretEnabled(PR_TRUE);
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
||||
selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
|
||||
}
|
||||
|
||||
selCon->SetCaretReadOnly(mEditor->IsReadonly());
|
||||
selCon->SetCaretEnabled(PR_TRUE);
|
||||
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
||||
selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> selectionPrivate =
|
||||
do_QueryInterface(selection);
|
||||
if (selectionPrivate)
|
||||
@ -935,7 +924,7 @@ nsEditorEventListener::EnsureSelectionInEditor(nsIDOMEvent* aEvent, PRBool aOnFo
|
||||
selectionPrivate->SetAncestorLimiter(editableRoot);
|
||||
}
|
||||
|
||||
if (aOnFocus && selection && !editableRoot) {
|
||||
if (selection && !editableRoot) {
|
||||
PRInt32 rangeCount;
|
||||
selection->GetRangeCount(&rangeCount);
|
||||
if (rangeCount == 0) {
|
||||
@ -943,6 +932,7 @@ nsEditorEventListener::EnsureSelectionInEditor(nsIDOMEvent* aEvent, PRBool aOnFo
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -107,8 +107,6 @@ protected:
|
||||
nsresult DragGesture(nsIDOMDragEvent* aDragEvent);
|
||||
already_AddRefed<nsIPresShell> GetPresShell();
|
||||
|
||||
void EnsureSelectionInEditor(nsIDOMEvent* aEvent, PRBool aOnFocus);
|
||||
|
||||
protected:
|
||||
nsEditor* mEditor; // weak
|
||||
nsRefPtr<nsCaret> mCaret;
|
||||
|
@ -2460,8 +2460,10 @@ static FrameContentRange GetRangeForFrame(nsIFrame* aFrame) {
|
||||
// frame is the result (in which case different handling is needed), and
|
||||
// afterFrame says which end is repersented if frameEdge is true
|
||||
struct FrameTarget {
|
||||
FrameTarget(nsIFrame* aFrame, PRBool aFrameEdge, PRBool aAfterFrame) :
|
||||
frame(aFrame), frameEdge(aFrameEdge), afterFrame(aAfterFrame) { }
|
||||
FrameTarget(nsIFrame* aFrame, PRBool aFrameEdge, PRBool aAfterFrame,
|
||||
PRBool aEmptyBlock = PR_FALSE) :
|
||||
frame(aFrame), frameEdge(aFrameEdge), afterFrame(aAfterFrame),
|
||||
emptyBlock(aEmptyBlock) { }
|
||||
static FrameTarget Null() {
|
||||
return FrameTarget(nsnull, PR_FALSE, PR_FALSE);
|
||||
}
|
||||
@ -2471,6 +2473,7 @@ struct FrameTarget {
|
||||
nsIFrame* frame;
|
||||
PRPackedBool frameEdge;
|
||||
PRPackedBool afterFrame;
|
||||
PRPackedBool emptyBlock;
|
||||
};
|
||||
|
||||
// See function implementation for information
|
||||
@ -2596,7 +2599,7 @@ static FrameTarget GetSelectionClosestFrameForLine(
|
||||
// special because they represent paragraphs and because they are organized
|
||||
// into lines, which have bounds that are not stored elsewhere in the
|
||||
// frame tree. Returns a null FrameTarget for frames which are not
|
||||
// blocks or blocks with no lines.
|
||||
// blocks or blocks with no lines except editable one.
|
||||
static FrameTarget GetSelectionClosestFrameForBlock(nsIFrame* aFrame,
|
||||
nsPoint aPoint)
|
||||
{
|
||||
@ -2607,8 +2610,15 @@ static FrameTarget GetSelectionClosestFrameForBlock(nsIFrame* aFrame,
|
||||
// This code searches for the correct line
|
||||
nsBlockFrame::line_iterator firstLine = bf->begin_lines();
|
||||
nsBlockFrame::line_iterator end = bf->end_lines();
|
||||
if (firstLine == end)
|
||||
if (firstLine == end) {
|
||||
nsIContent *blockContent = aFrame->GetContent();
|
||||
if (blockContent && blockContent->IsEditable()) {
|
||||
// If the frame is ediable empty block, we should return it with empty
|
||||
// flag.
|
||||
return FrameTarget(aFrame, PR_FALSE, PR_FALSE, PR_TRUE);
|
||||
}
|
||||
return FrameTarget::Null();
|
||||
}
|
||||
nsBlockFrame::line_iterator curLine = firstLine;
|
||||
nsBlockFrame::line_iterator closestLine = end;
|
||||
while (curLine != end) {
|
||||
@ -2825,6 +2835,17 @@ nsIFrame::ContentOffsets nsIFrame::GetContentOffsetsFromPoint(nsPoint aPoint,
|
||||
|
||||
FrameTarget closest = GetSelectionClosestFrame(adjustedFrame, adjustedPoint);
|
||||
|
||||
if (closest.emptyBlock) {
|
||||
ContentOffsets offsets;
|
||||
NS_ASSERTION(closest.frame,
|
||||
"closest.frame must not be null when it's empty");
|
||||
offsets.content = closest.frame->GetContent();
|
||||
offsets.offset = 0;
|
||||
offsets.secondaryOffset = 0;
|
||||
offsets.associateWithNext = PR_TRUE;
|
||||
return offsets;
|
||||
}
|
||||
|
||||
// If the correct offset is at one end of a frame, use offset-based
|
||||
// calculation method
|
||||
if (closest.frameEdge) {
|
||||
|
Loading…
Reference in New Issue
Block a user