зеркало из https://github.com/mozilla/gecko-dev.git
Partial fix for bug 141900 (Text entry fields in forms excruciatingly slow.)
mozilla/content/base/public/nsISelectionController.idl mozilla/content/base/src/nsSelection.cpp mozilla/editor/composer/src/nsEditorShell.cpp mozilla/editor/idl/nsIPlaintextEditor.idl mozilla/editor/libeditor/base/nsEditor.cpp mozilla/editor/libeditor/base/nsEditor.h mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp mozilla/editor/libeditor/html/nsHTMLEditor.cpp mozilla/editor/libeditor/text/nsEditorEventListeners.cpp mozilla/editor/libeditor/text/nsPlaintextDataTransfer.cpp mozilla/editor/libeditor/text/nsPlaintextEditor.cpp mozilla/editor/txtsvc/src/nsTextServicesDocument.cpp mozilla/editor/ui/dialogs/content/EdTableProps.js mozilla/embedding/components/find/src/nsWebBrowserFind.cpp mozilla/extensions/xmlterm/base/mozXMLTermSession.cpp mozilla/layout/base/public/nsIFrameSelection.h mozilla/layout/html/base/src/nsPresShell.cpp mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp mozilla/mailnews/compose/src/nsMsgCompose.cpp mozilla/xpfe/browser/resources/content/viewPartialSource.js - Added aIsSynchronous arg to the ScrollSelectionIntoView() method of nsISelectionController and nsIFrameSelection. Updated all callers to pass new arg. - Modified selection to post a plevent to call which does the call to ScrollIntoView() in the async ScrollIntoView() case. - Edits in text widgets now use asynchronous reflow, paint, and scroll processing full time. - Removed redundant ScrollSelectionIntoView() calls in the editor event listeners. - Editor IME code now forced to flush reflows and paints before getting caret coordinates. r=jfrancis@netscape.com sr=waterson@netscape.com
This commit is contained in:
Родитель
2cc8934aad
Коммит
8996b9ec1c
|
@ -83,8 +83,11 @@ interface nsISelectionController : nsISelectionDisplay
|
|||
*
|
||||
* @param aType the selection to scroll into view. //SelectionType
|
||||
* @param aRegion the region inside the selection to scroll into view. //SelectionRegion
|
||||
* @param aIsSynchronous when true, scrolls the selection into view
|
||||
* before returning. If false, posts a request which is processed
|
||||
* at some point after the method returns.
|
||||
*/
|
||||
void scrollSelectionIntoView(in short type, in short region);
|
||||
void scrollSelectionIntoView(in short type, in short region, in boolean isSynchronous);
|
||||
/**
|
||||
* RepaintSelection repaints the selection specified by aType.
|
||||
*
|
||||
|
|
|
@ -98,6 +98,8 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
|
|||
#include "nsITimerCallback.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIAutoCopy.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
|
||||
//nodtifications
|
||||
#include "nsIDOMDocument.h"
|
||||
|
@ -138,6 +140,7 @@ static NS_DEFINE_IID(kCSubtreeIteratorCID, NS_SUBTREEITERATOR_CID);
|
|||
class nsSelectionIterator;
|
||||
class nsSelection;
|
||||
class nsAutoScrollTimer;
|
||||
struct nsScrollSelectionIntoViewEvent;
|
||||
|
||||
PRBool IsValidSelectionPoint(nsSelection *aFrameSel, nsIContent *aContent);
|
||||
PRBool IsValidSelectionPoint(nsSelection *aFrameSel, nsIDOMNode *aDomNode);
|
||||
|
@ -223,7 +226,8 @@ public:
|
|||
nsresult GetSelectionRegionRectAndScrollableView(SelectionRegion aRegion, nsRect *aRect, nsIScrollableView **aScrollableView);
|
||||
nsresult ScrollRectIntoView(nsIScrollableView *aScrollableView, nsRect& aRect, PRIntn aVPercent, PRIntn aHPercent, PRBool aScrollParentViews);
|
||||
|
||||
NS_IMETHOD ScrollIntoView(SelectionRegion aRegion=nsISelectionController::SELECTION_FOCUS_REGION);
|
||||
nsresult PostScrollSelectionIntoViewEvent(SelectionRegion aRegion);
|
||||
NS_IMETHOD ScrollIntoView(SelectionRegion aRegion=nsISelectionController::SELECTION_FOCUS_REGION, PRBool aIsSynchronous=PR_TRUE);
|
||||
nsresult AddItem(nsIDOMRange *aRange);
|
||||
nsresult RemoveItem(nsIDOMRange *aRange);
|
||||
|
||||
|
@ -277,6 +281,7 @@ public:
|
|||
|
||||
private:
|
||||
friend class nsSelectionIterator;
|
||||
friend struct nsScrollSelectionIntoViewEvent;
|
||||
|
||||
|
||||
void setAnchorFocusRange(PRInt32 aIndex); //pass in index into FrameSelection
|
||||
|
@ -304,6 +309,8 @@ private:
|
|||
#ifdef IBMBIDI
|
||||
PRBool mTrueDirection;
|
||||
#endif
|
||||
nsCOMPtr<nsIEventQueue> mEventQueue;
|
||||
PRBool mScrollEventPosted;
|
||||
};
|
||||
|
||||
// Stack-class to turn on/off selection batching for table selection
|
||||
|
@ -354,7 +361,7 @@ public:
|
|||
NS_IMETHOD ClearTableCellSelection(){mSelectingTableCellMode = 0; return NS_OK;}
|
||||
|
||||
NS_IMETHOD GetSelection(SelectionType aType, nsISelection **aDomSelection);
|
||||
NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion);
|
||||
NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous);
|
||||
NS_IMETHOD RepaintSelection(nsIPresContext* aPresContext, SelectionType aType);
|
||||
NS_IMETHOD GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffset, HINT aHint, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset);
|
||||
|
||||
|
@ -2931,7 +2938,7 @@ nsSelection::GetSelection(SelectionType aType, nsISelection **aDomSelection)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion)
|
||||
nsSelection::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous)
|
||||
{
|
||||
PRInt8 index = GetIndexFromSelectionType(aType);
|
||||
if (index < 0)
|
||||
|
@ -2940,7 +2947,7 @@ nsSelection::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegio
|
|||
if (!mDomSelections[index])
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
return mDomSelections[index]->ScrollIntoView(aRegion);
|
||||
return mDomSelections[index]->ScrollIntoView(aRegion, aIsSynchronous);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -4488,6 +4495,7 @@ nsTypedSelection::nsTypedSelection(nsSelection *aList)
|
|||
mAutoScrollTimer = nsnull;
|
||||
NS_NewISupportsArray(getter_AddRefs(mSelectionListeners));
|
||||
NS_INIT_REFCNT();
|
||||
mScrollEventPosted = PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4500,6 +4508,7 @@ nsTypedSelection::nsTypedSelection()
|
|||
mAutoScrollTimer = nsnull;
|
||||
NS_NewISupportsArray(getter_AddRefs(mSelectionListeners));
|
||||
NS_INIT_REFCNT();
|
||||
mScrollEventPosted = PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4512,6 +4521,11 @@ nsTypedSelection::~nsTypedSelection()
|
|||
mAutoScrollTimer->Stop();
|
||||
NS_RELEASE(mAutoScrollTimer);
|
||||
}
|
||||
|
||||
if (mEventQueue && mScrollEventPosted) {
|
||||
mEventQueue->RevokeEvents(this);
|
||||
mScrollEventPosted = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -7548,8 +7562,89 @@ nsTypedSelection::ScrollRectIntoView(nsIScrollableView *aScrollableView,
|
|||
return rv;
|
||||
}
|
||||
|
||||
static void PR_CALLBACK HandlePLEvent(nsScrollSelectionIntoViewEvent* aEvent);
|
||||
static void PR_CALLBACK DestroyPLEvent(nsScrollSelectionIntoViewEvent* aEvent);
|
||||
|
||||
struct nsScrollSelectionIntoViewEvent : public PLEvent {
|
||||
nsScrollSelectionIntoViewEvent(nsTypedSelection *aTypedSelection, SelectionRegion aRegion) {
|
||||
if (!aTypedSelection)
|
||||
return;
|
||||
|
||||
mTypedSelection = aTypedSelection;
|
||||
mRegion = aRegion;
|
||||
|
||||
PL_InitEvent(this, aTypedSelection,
|
||||
(PLHandleEventProc) ::HandlePLEvent,
|
||||
(PLDestroyEventProc) ::DestroyPLEvent);
|
||||
}
|
||||
|
||||
~nsScrollSelectionIntoViewEvent() {}
|
||||
|
||||
void HandleEvent() {
|
||||
mTypedSelection->mScrollEventPosted = PR_FALSE;
|
||||
|
||||
if (!mTypedSelection)
|
||||
return;
|
||||
|
||||
mTypedSelection->ScrollIntoView(mRegion, PR_TRUE);
|
||||
}
|
||||
|
||||
nsTypedSelection *mTypedSelection;
|
||||
SelectionRegion mRegion;
|
||||
};
|
||||
|
||||
static void PR_CALLBACK HandlePLEvent(nsScrollSelectionIntoViewEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aEvent,"Event is null");
|
||||
aEvent->HandleEvent();
|
||||
}
|
||||
|
||||
static void PR_CALLBACK DestroyPLEvent(nsScrollSelectionIntoViewEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aEvent,"Event is null");
|
||||
delete aEvent;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTypedSelection::PostScrollSelectionIntoViewEvent(SelectionRegion aRegion)
|
||||
{
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
if (!mEventQueue) {
|
||||
nsresult rv;
|
||||
|
||||
// Cache the event queue of the current UI thread
|
||||
nsCOMPtr<nsIEventQueueService> eventService = do_GetService(kEventQueueServiceCID, &rv);
|
||||
if (NS_SUCCEEDED(rv) && (nsnull != eventService)) { // XXX this implies that the UI is the current thread.
|
||||
rv = eventService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(mEventQueue));
|
||||
}
|
||||
}
|
||||
|
||||
if (mEventQueue) {
|
||||
if (mScrollEventPosted) {
|
||||
// We've already posted an event, revoke it and
|
||||
// place a new one at the end of the queue to make
|
||||
// sure that any new pending reflow events are processed
|
||||
// before we scroll. This will insure that we scroll
|
||||
// to the correct place on screen.
|
||||
|
||||
mEventQueue->RevokeEvents(this);
|
||||
mScrollEventPosted = PR_FALSE;
|
||||
}
|
||||
|
||||
nsScrollSelectionIntoViewEvent *ev = new nsScrollSelectionIntoViewEvent(this, aRegion);
|
||||
if (ev) {
|
||||
mEventQueue->PostEvent(ev);
|
||||
mScrollEventPosted = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTypedSelection::ScrollIntoView(SelectionRegion aRegion)
|
||||
nsTypedSelection::ScrollIntoView(SelectionRegion aRegion, PRBool aIsSynchronous)
|
||||
{
|
||||
nsresult result;
|
||||
if (!mFrameSelection)
|
||||
|
@ -7558,6 +7653,9 @@ nsTypedSelection::ScrollIntoView(SelectionRegion aRegion)
|
|||
if (mFrameSelection->GetBatching())
|
||||
return NS_OK;
|
||||
|
||||
if (!aIsSynchronous)
|
||||
return PostScrollSelectionIntoViewEvent(aRegion);
|
||||
|
||||
//
|
||||
// Shut the caret off before scrolling to avoid
|
||||
// leaving caret turds on the screen!
|
||||
|
|
|
@ -98,6 +98,8 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
|
|||
#include "nsITimerCallback.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIAutoCopy.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
|
||||
//nodtifications
|
||||
#include "nsIDOMDocument.h"
|
||||
|
@ -138,6 +140,7 @@ static NS_DEFINE_IID(kCSubtreeIteratorCID, NS_SUBTREEITERATOR_CID);
|
|||
class nsSelectionIterator;
|
||||
class nsSelection;
|
||||
class nsAutoScrollTimer;
|
||||
struct nsScrollSelectionIntoViewEvent;
|
||||
|
||||
PRBool IsValidSelectionPoint(nsSelection *aFrameSel, nsIContent *aContent);
|
||||
PRBool IsValidSelectionPoint(nsSelection *aFrameSel, nsIDOMNode *aDomNode);
|
||||
|
@ -223,7 +226,8 @@ public:
|
|||
nsresult GetSelectionRegionRectAndScrollableView(SelectionRegion aRegion, nsRect *aRect, nsIScrollableView **aScrollableView);
|
||||
nsresult ScrollRectIntoView(nsIScrollableView *aScrollableView, nsRect& aRect, PRIntn aVPercent, PRIntn aHPercent, PRBool aScrollParentViews);
|
||||
|
||||
NS_IMETHOD ScrollIntoView(SelectionRegion aRegion=nsISelectionController::SELECTION_FOCUS_REGION);
|
||||
nsresult PostScrollSelectionIntoViewEvent(SelectionRegion aRegion);
|
||||
NS_IMETHOD ScrollIntoView(SelectionRegion aRegion=nsISelectionController::SELECTION_FOCUS_REGION, PRBool aIsSynchronous=PR_TRUE);
|
||||
nsresult AddItem(nsIDOMRange *aRange);
|
||||
nsresult RemoveItem(nsIDOMRange *aRange);
|
||||
|
||||
|
@ -277,6 +281,7 @@ public:
|
|||
|
||||
private:
|
||||
friend class nsSelectionIterator;
|
||||
friend struct nsScrollSelectionIntoViewEvent;
|
||||
|
||||
|
||||
void setAnchorFocusRange(PRInt32 aIndex); //pass in index into FrameSelection
|
||||
|
@ -304,6 +309,8 @@ private:
|
|||
#ifdef IBMBIDI
|
||||
PRBool mTrueDirection;
|
||||
#endif
|
||||
nsCOMPtr<nsIEventQueue> mEventQueue;
|
||||
PRBool mScrollEventPosted;
|
||||
};
|
||||
|
||||
// Stack-class to turn on/off selection batching for table selection
|
||||
|
@ -354,7 +361,7 @@ public:
|
|||
NS_IMETHOD ClearTableCellSelection(){mSelectingTableCellMode = 0; return NS_OK;}
|
||||
|
||||
NS_IMETHOD GetSelection(SelectionType aType, nsISelection **aDomSelection);
|
||||
NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion);
|
||||
NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous);
|
||||
NS_IMETHOD RepaintSelection(nsIPresContext* aPresContext, SelectionType aType);
|
||||
NS_IMETHOD GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffset, HINT aHint, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset);
|
||||
|
||||
|
@ -2931,7 +2938,7 @@ nsSelection::GetSelection(SelectionType aType, nsISelection **aDomSelection)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion)
|
||||
nsSelection::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous)
|
||||
{
|
||||
PRInt8 index = GetIndexFromSelectionType(aType);
|
||||
if (index < 0)
|
||||
|
@ -2940,7 +2947,7 @@ nsSelection::ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegio
|
|||
if (!mDomSelections[index])
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
return mDomSelections[index]->ScrollIntoView(aRegion);
|
||||
return mDomSelections[index]->ScrollIntoView(aRegion, aIsSynchronous);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -4488,6 +4495,7 @@ nsTypedSelection::nsTypedSelection(nsSelection *aList)
|
|||
mAutoScrollTimer = nsnull;
|
||||
NS_NewISupportsArray(getter_AddRefs(mSelectionListeners));
|
||||
NS_INIT_REFCNT();
|
||||
mScrollEventPosted = PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4500,6 +4508,7 @@ nsTypedSelection::nsTypedSelection()
|
|||
mAutoScrollTimer = nsnull;
|
||||
NS_NewISupportsArray(getter_AddRefs(mSelectionListeners));
|
||||
NS_INIT_REFCNT();
|
||||
mScrollEventPosted = PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4512,6 +4521,11 @@ nsTypedSelection::~nsTypedSelection()
|
|||
mAutoScrollTimer->Stop();
|
||||
NS_RELEASE(mAutoScrollTimer);
|
||||
}
|
||||
|
||||
if (mEventQueue && mScrollEventPosted) {
|
||||
mEventQueue->RevokeEvents(this);
|
||||
mScrollEventPosted = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -7548,8 +7562,89 @@ nsTypedSelection::ScrollRectIntoView(nsIScrollableView *aScrollableView,
|
|||
return rv;
|
||||
}
|
||||
|
||||
static void PR_CALLBACK HandlePLEvent(nsScrollSelectionIntoViewEvent* aEvent);
|
||||
static void PR_CALLBACK DestroyPLEvent(nsScrollSelectionIntoViewEvent* aEvent);
|
||||
|
||||
struct nsScrollSelectionIntoViewEvent : public PLEvent {
|
||||
nsScrollSelectionIntoViewEvent(nsTypedSelection *aTypedSelection, SelectionRegion aRegion) {
|
||||
if (!aTypedSelection)
|
||||
return;
|
||||
|
||||
mTypedSelection = aTypedSelection;
|
||||
mRegion = aRegion;
|
||||
|
||||
PL_InitEvent(this, aTypedSelection,
|
||||
(PLHandleEventProc) ::HandlePLEvent,
|
||||
(PLDestroyEventProc) ::DestroyPLEvent);
|
||||
}
|
||||
|
||||
~nsScrollSelectionIntoViewEvent() {}
|
||||
|
||||
void HandleEvent() {
|
||||
mTypedSelection->mScrollEventPosted = PR_FALSE;
|
||||
|
||||
if (!mTypedSelection)
|
||||
return;
|
||||
|
||||
mTypedSelection->ScrollIntoView(mRegion, PR_TRUE);
|
||||
}
|
||||
|
||||
nsTypedSelection *mTypedSelection;
|
||||
SelectionRegion mRegion;
|
||||
};
|
||||
|
||||
static void PR_CALLBACK HandlePLEvent(nsScrollSelectionIntoViewEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aEvent,"Event is null");
|
||||
aEvent->HandleEvent();
|
||||
}
|
||||
|
||||
static void PR_CALLBACK DestroyPLEvent(nsScrollSelectionIntoViewEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aEvent,"Event is null");
|
||||
delete aEvent;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTypedSelection::PostScrollSelectionIntoViewEvent(SelectionRegion aRegion)
|
||||
{
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
if (!mEventQueue) {
|
||||
nsresult rv;
|
||||
|
||||
// Cache the event queue of the current UI thread
|
||||
nsCOMPtr<nsIEventQueueService> eventService = do_GetService(kEventQueueServiceCID, &rv);
|
||||
if (NS_SUCCEEDED(rv) && (nsnull != eventService)) { // XXX this implies that the UI is the current thread.
|
||||
rv = eventService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(mEventQueue));
|
||||
}
|
||||
}
|
||||
|
||||
if (mEventQueue) {
|
||||
if (mScrollEventPosted) {
|
||||
// We've already posted an event, revoke it and
|
||||
// place a new one at the end of the queue to make
|
||||
// sure that any new pending reflow events are processed
|
||||
// before we scroll. This will insure that we scroll
|
||||
// to the correct place on screen.
|
||||
|
||||
mEventQueue->RevokeEvents(this);
|
||||
mScrollEventPosted = PR_FALSE;
|
||||
}
|
||||
|
||||
nsScrollSelectionIntoViewEvent *ev = new nsScrollSelectionIntoViewEvent(this, aRegion);
|
||||
if (ev) {
|
||||
mEventQueue->PostEvent(ev);
|
||||
mScrollEventPosted = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTypedSelection::ScrollIntoView(SelectionRegion aRegion)
|
||||
nsTypedSelection::ScrollIntoView(SelectionRegion aRegion, PRBool aIsSynchronous)
|
||||
{
|
||||
nsresult result;
|
||||
if (!mFrameSelection)
|
||||
|
@ -7558,6 +7653,9 @@ nsTypedSelection::ScrollIntoView(SelectionRegion aRegion)
|
|||
if (mFrameSelection->GetBatching())
|
||||
return NS_OK;
|
||||
|
||||
if (!aIsSynchronous)
|
||||
return PostScrollSelectionIntoViewEvent(aRegion);
|
||||
|
||||
//
|
||||
// Shut the caret off before scrolling to avoid
|
||||
// leaving caret turds on the screen!
|
||||
|
|
Загрузка…
Ссылка в новой задаче