Part 1 of fix for bug #39821: Drag and Drop interferes with selection.
layout/base/public/nsIFrameSelection.h layout/base/src/nsSelection.cpp layout/events/src/nsEventStateManager.cpp layout/html/base/src/nsFrame.cpp layout/html/forms/src/nsGfxTextControlFrame2.cpp xpfe/browser/resources/content/navigatorDD.js r=brade@netscape.com,cmanske@netscape.com a=beppe@netscape.com,waterson@netscape.com
This commit is contained in:
Родитель
da27f7fefd
Коммит
2303aabdcb
|
@ -291,6 +291,10 @@ public:
|
|||
NS_IMETHOD SelectAll();
|
||||
NS_IMETHOD SetDisplaySelection(PRInt16 aState);
|
||||
NS_IMETHOD GetDisplaySelection(PRInt16 *aState);
|
||||
NS_IMETHOD SetDelayCaretOverExistingSelection(PRBool aDelay);
|
||||
NS_IMETHOD GetDelayCaretOverExistingSelection(PRBool *aDelay);
|
||||
NS_IMETHOD SetDelayedCaretData(nsMouseEvent *aMouseEvent);
|
||||
NS_IMETHOD GetDelayedCaretData(nsMouseEvent **aMouseEvent);
|
||||
/*END nsIFrameSelection interfacse*/
|
||||
|
||||
|
||||
|
@ -372,6 +376,11 @@ private:
|
|||
PRBool mDesiredXSet;
|
||||
enum HINT {HINTLEFT=0,HINTRIGHT=1}mHint;//end of this line or beginning of next
|
||||
nsIScrollableView *mScrollView;
|
||||
|
||||
PRBool mDelayCaretOverExistingSelection;
|
||||
PRBool mDelayedMouseEventValid;
|
||||
nsMouseEvent mDelayedMouseEvent;
|
||||
|
||||
public:
|
||||
static nsIAtom *sTableAtom;
|
||||
static nsIAtom *sCellAtom;
|
||||
|
@ -798,6 +807,9 @@ nsSelection::nsSelection()
|
|||
autoCopyService->Listen(mDomSelections[index]);
|
||||
}
|
||||
mDisplaySelection = nsISelectionController::SELECTION_OFF;
|
||||
|
||||
mDelayCaretOverExistingSelection = PR_TRUE;
|
||||
mDelayedMouseEventValid = PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2783,6 +2795,61 @@ nsSelection::GetDisplaySelection(PRInt16 *aToggle)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::SetDelayCaretOverExistingSelection(PRBool aDelay)
|
||||
{
|
||||
mDelayCaretOverExistingSelection = aDelay;
|
||||
|
||||
if (! aDelay)
|
||||
mDelayedMouseEventValid = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::GetDelayCaretOverExistingSelection(PRBool *aDelay)
|
||||
{
|
||||
if (!aDelay)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aDelay = mDelayCaretOverExistingSelection;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::SetDelayedCaretData(nsMouseEvent *aMouseEvent)
|
||||
{
|
||||
if (aMouseEvent)
|
||||
{
|
||||
mDelayedMouseEventValid = PR_TRUE;
|
||||
mDelayedMouseEvent = *aMouseEvent;
|
||||
|
||||
// XXX: Hmmm, should we AddRef mDelayedMouseEvent->widget?
|
||||
// Doing so might introduce a leak if things in the app
|
||||
// are not released in the correct order though, so for now
|
||||
// don't do anything.
|
||||
}
|
||||
else
|
||||
mDelayedMouseEventValid = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::GetDelayedCaretData(nsMouseEvent **aMouseEvent)
|
||||
{
|
||||
if (!aMouseEvent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (mDelayedMouseEventValid)
|
||||
*aMouseEvent = &mDelayedMouseEvent;
|
||||
else
|
||||
*aMouseEvent = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//END nsIDOMSelection interface implementations
|
||||
|
||||
#ifdef XP_MAC
|
||||
|
|
|
@ -686,6 +686,25 @@ nsEventStateManager :: GenerateDragGesture ( nsIPresContext* aPresContext, nsGUI
|
|||
{
|
||||
NS_WARN_IF_FALSE(aPresContext, "This shouldn't happen.");
|
||||
if ( IsTrackingDragGesture() ) {
|
||||
|
||||
// Check if selection is tracking drag gestures, if so
|
||||
// don't interfere!
|
||||
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
nsresult rv = aPresContext->GetShell(getter_AddRefs(shell));
|
||||
if (NS_SUCCEEDED(rv) && shell){
|
||||
nsCOMPtr<nsIFrameSelection> frameSel;
|
||||
rv = shell->GetFrameSelection(getter_AddRefs(frameSel));
|
||||
if (NS_SUCCEEDED(rv) && frameSel){
|
||||
PRBool mouseDownState = PR_TRUE;
|
||||
frameSel->GetMouseDownState(&mouseDownState);
|
||||
if (mouseDownState) {
|
||||
StopTrackingDragGesture();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// figure out the delta in twips, since that is how it is in the event.
|
||||
// Do we need to do this conversion every time? Will the pres context really change on
|
||||
// us or can we cache it?
|
||||
|
|
|
@ -309,6 +309,46 @@ public:
|
|||
NS_IMETHOD SetDisplaySelection(PRInt16 aState)=0;
|
||||
NS_IMETHOD GetDisplaySelection(PRInt16 *aState)=0;
|
||||
|
||||
/** Allow applications to specify how we should place the caret
|
||||
* when the user clicks over an existing selection. A aDelay
|
||||
* value of PR_TRUE means delay clearing the selection and
|
||||
* placing the caret until MouseUp, when the user clicks over
|
||||
* an existing selection. This is especially usefull when applications
|
||||
* want to support Drag & Drop of the current selection. A value
|
||||
* of PR_FALSE means place the caret immediately. If the application
|
||||
* never calls this method, the nsIFrameSelection implementation
|
||||
* assumes the default value is PR_TRUE.
|
||||
* @param aDelay PR_TRUE if we should delay caret placement.
|
||||
*/
|
||||
NS_IMETHOD SetDelayCaretOverExistingSelection(PRBool aDelay)=0;
|
||||
|
||||
/** Get the current delay caret setting. If aDelay contains
|
||||
* a return value of PR_TRUE, the caret is placed on MouseUp
|
||||
* when clicking over an existing selection. If PR_FALSE,
|
||||
* the selection is cleared and caret is placed immediately
|
||||
* in all cases.
|
||||
* @param aDelay will contain the return value.
|
||||
*/
|
||||
NS_IMETHOD GetDelayCaretOverExistingSelection(PRBool *aDelay)=0;
|
||||
|
||||
/** If we are delaying caret placement til MouseUp (see
|
||||
* Set/GetDelayCaretOverExistingSelection()), this method
|
||||
* can be used to store the data received during the MouseDown
|
||||
* so that we can place the caret during the MouseUp event.
|
||||
* @aMouseEvent the event received by the selection MouseDown
|
||||
* handling method. A NULL value can be use to tell this method
|
||||
* that any data is storing is no longer valid.
|
||||
*/
|
||||
NS_IMETHOD SetDelayedCaretData(nsMouseEvent *aMouseEvent)=0;
|
||||
|
||||
/** Get the delayed MouseDown event data neccessary to place the
|
||||
* caret during MouseUp processing.
|
||||
* @aMouseEvent will contain a pointer to the event received
|
||||
* by the selection during MouseDown processing. It can be NULL
|
||||
* if the data is no longer valid.
|
||||
*/
|
||||
NS_IMETHOD GetDelayedCaretData(nsMouseEvent **aMouseEvent)=0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -309,6 +309,46 @@ public:
|
|||
NS_IMETHOD SetDisplaySelection(PRInt16 aState)=0;
|
||||
NS_IMETHOD GetDisplaySelection(PRInt16 *aState)=0;
|
||||
|
||||
/** Allow applications to specify how we should place the caret
|
||||
* when the user clicks over an existing selection. A aDelay
|
||||
* value of PR_TRUE means delay clearing the selection and
|
||||
* placing the caret until MouseUp, when the user clicks over
|
||||
* an existing selection. This is especially usefull when applications
|
||||
* want to support Drag & Drop of the current selection. A value
|
||||
* of PR_FALSE means place the caret immediately. If the application
|
||||
* never calls this method, the nsIFrameSelection implementation
|
||||
* assumes the default value is PR_TRUE.
|
||||
* @param aDelay PR_TRUE if we should delay caret placement.
|
||||
*/
|
||||
NS_IMETHOD SetDelayCaretOverExistingSelection(PRBool aDelay)=0;
|
||||
|
||||
/** Get the current delay caret setting. If aDelay contains
|
||||
* a return value of PR_TRUE, the caret is placed on MouseUp
|
||||
* when clicking over an existing selection. If PR_FALSE,
|
||||
* the selection is cleared and caret is placed immediately
|
||||
* in all cases.
|
||||
* @param aDelay will contain the return value.
|
||||
*/
|
||||
NS_IMETHOD GetDelayCaretOverExistingSelection(PRBool *aDelay)=0;
|
||||
|
||||
/** If we are delaying caret placement til MouseUp (see
|
||||
* Set/GetDelayCaretOverExistingSelection()), this method
|
||||
* can be used to store the data received during the MouseDown
|
||||
* so that we can place the caret during the MouseUp event.
|
||||
* @aMouseEvent the event received by the selection MouseDown
|
||||
* handling method. A NULL value can be use to tell this method
|
||||
* that any data is storing is no longer valid.
|
||||
*/
|
||||
NS_IMETHOD SetDelayedCaretData(nsMouseEvent *aMouseEvent)=0;
|
||||
|
||||
/** Get the delayed MouseDown event data neccessary to place the
|
||||
* caret during MouseUp processing.
|
||||
* @aMouseEvent will contain a pointer to the event received
|
||||
* by the selection during MouseDown processing. It can be NULL
|
||||
* if the data is no longer valid.
|
||||
*/
|
||||
NS_IMETHOD GetDelayedCaretData(nsMouseEvent **aMouseEvent)=0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -291,6 +291,10 @@ public:
|
|||
NS_IMETHOD SelectAll();
|
||||
NS_IMETHOD SetDisplaySelection(PRInt16 aState);
|
||||
NS_IMETHOD GetDisplaySelection(PRInt16 *aState);
|
||||
NS_IMETHOD SetDelayCaretOverExistingSelection(PRBool aDelay);
|
||||
NS_IMETHOD GetDelayCaretOverExistingSelection(PRBool *aDelay);
|
||||
NS_IMETHOD SetDelayedCaretData(nsMouseEvent *aMouseEvent);
|
||||
NS_IMETHOD GetDelayedCaretData(nsMouseEvent **aMouseEvent);
|
||||
/*END nsIFrameSelection interfacse*/
|
||||
|
||||
|
||||
|
@ -372,6 +376,11 @@ private:
|
|||
PRBool mDesiredXSet;
|
||||
enum HINT {HINTLEFT=0,HINTRIGHT=1}mHint;//end of this line or beginning of next
|
||||
nsIScrollableView *mScrollView;
|
||||
|
||||
PRBool mDelayCaretOverExistingSelection;
|
||||
PRBool mDelayedMouseEventValid;
|
||||
nsMouseEvent mDelayedMouseEvent;
|
||||
|
||||
public:
|
||||
static nsIAtom *sTableAtom;
|
||||
static nsIAtom *sCellAtom;
|
||||
|
@ -798,6 +807,9 @@ nsSelection::nsSelection()
|
|||
autoCopyService->Listen(mDomSelections[index]);
|
||||
}
|
||||
mDisplaySelection = nsISelectionController::SELECTION_OFF;
|
||||
|
||||
mDelayCaretOverExistingSelection = PR_TRUE;
|
||||
mDelayedMouseEventValid = PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2783,6 +2795,61 @@ nsSelection::GetDisplaySelection(PRInt16 *aToggle)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::SetDelayCaretOverExistingSelection(PRBool aDelay)
|
||||
{
|
||||
mDelayCaretOverExistingSelection = aDelay;
|
||||
|
||||
if (! aDelay)
|
||||
mDelayedMouseEventValid = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::GetDelayCaretOverExistingSelection(PRBool *aDelay)
|
||||
{
|
||||
if (!aDelay)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aDelay = mDelayCaretOverExistingSelection;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::SetDelayedCaretData(nsMouseEvent *aMouseEvent)
|
||||
{
|
||||
if (aMouseEvent)
|
||||
{
|
||||
mDelayedMouseEventValid = PR_TRUE;
|
||||
mDelayedMouseEvent = *aMouseEvent;
|
||||
|
||||
// XXX: Hmmm, should we AddRef mDelayedMouseEvent->widget?
|
||||
// Doing so might introduce a leak if things in the app
|
||||
// are not released in the correct order though, so for now
|
||||
// don't do anything.
|
||||
}
|
||||
else
|
||||
mDelayedMouseEventValid = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::GetDelayedCaretData(nsMouseEvent **aMouseEvent)
|
||||
{
|
||||
if (!aMouseEvent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (mDelayedMouseEventValid)
|
||||
*aMouseEvent = &mDelayedMouseEvent;
|
||||
else
|
||||
*aMouseEvent = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//END nsIDOMSelection interface implementations
|
||||
|
||||
#ifdef XP_MAC
|
||||
|
|
|
@ -686,6 +686,25 @@ nsEventStateManager :: GenerateDragGesture ( nsIPresContext* aPresContext, nsGUI
|
|||
{
|
||||
NS_WARN_IF_FALSE(aPresContext, "This shouldn't happen.");
|
||||
if ( IsTrackingDragGesture() ) {
|
||||
|
||||
// Check if selection is tracking drag gestures, if so
|
||||
// don't interfere!
|
||||
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
nsresult rv = aPresContext->GetShell(getter_AddRefs(shell));
|
||||
if (NS_SUCCEEDED(rv) && shell){
|
||||
nsCOMPtr<nsIFrameSelection> frameSel;
|
||||
rv = shell->GetFrameSelection(getter_AddRefs(frameSel));
|
||||
if (NS_SUCCEEDED(rv) && frameSel){
|
||||
PRBool mouseDownState = PR_TRUE;
|
||||
frameSel->GetMouseDownState(&mouseDownState);
|
||||
if (mouseDownState) {
|
||||
StopTrackingDragGesture();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// figure out the delta in twips, since that is how it is in the event.
|
||||
// Do we need to do this conversion every time? Will the pres context really change on
|
||||
// us or can we cache it?
|
||||
|
|
|
@ -1007,57 +1007,65 @@ nsFrame::HandlePress(nsIPresContext* aPresContext,
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
#ifdef DRAG_AND_DROP_FRIENDLY_SELECTION
|
||||
PRBool supportsDelay = PR_FALSE;
|
||||
|
||||
// Check if any part of this frame is selected, and if the
|
||||
// user clicked inside the selected region. If so, we delay
|
||||
// starting a new selection since the user may be trying to
|
||||
// drag the selected region to some other app.
|
||||
frameselection->GetDelayCaretOverExistingSelection(&supportsDelay);
|
||||
frameselection->SetDelayedCaretData(0);
|
||||
|
||||
SelectionDetails *details = 0;
|
||||
nsFrameState frameState;
|
||||
GetFrameState(&frameState);
|
||||
PRBool isSelected = ((frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT);
|
||||
|
||||
if (isSelected)
|
||||
if (supportsDelay)
|
||||
{
|
||||
rv = frameselection->LookUpSelection(content, 0, endOffset, &details, PR_FALSE);
|
||||
// Check if any part of this frame is selected, and if the
|
||||
// user clicked inside the selected region. If so, we delay
|
||||
// starting a new selection since the user may be trying to
|
||||
// drag the selected region to some other app.
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
SelectionDetails *details = 0;
|
||||
nsFrameState frameState;
|
||||
GetFrameState(&frameState);
|
||||
PRBool isSelected = ((frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT);
|
||||
|
||||
//
|
||||
// If there are any details, check to see if the user clicked
|
||||
// within any selected region of the frame.
|
||||
//
|
||||
|
||||
if (details)
|
||||
if (isSelected)
|
||||
{
|
||||
SelectionDetails *curDetail = details;
|
||||
rv = frameselection->LookUpSelection(content, 0, endOffset, &details, PR_FALSE);
|
||||
|
||||
while (curDetail)
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
//
|
||||
// If there are any details, check to see if the user clicked
|
||||
// within any selected region of the frame.
|
||||
//
|
||||
|
||||
if (details)
|
||||
{
|
||||
//
|
||||
// If the user clicked inside a selection, then just
|
||||
// return without doing anything. We will handle placing
|
||||
// the caret later on when the mouse is released.
|
||||
//
|
||||
if (curDetail->mStart <= startOffset && endOffset <= curDetail->mEnd)
|
||||
SelectionDetails *curDetail = details;
|
||||
|
||||
while (curDetail)
|
||||
{
|
||||
delete details;
|
||||
rv = frameselection->SetMouseDownState( PR_FALSE );
|
||||
return NS_OK;
|
||||
//
|
||||
// If the user clicked inside a selection, then just
|
||||
// return without doing anything. We will handle placing
|
||||
// the caret later on when the mouse is released.
|
||||
//
|
||||
if (curDetail->mStart <= startOffset && endOffset <= curDetail->mEnd)
|
||||
{
|
||||
delete details;
|
||||
rv = frameselection->SetMouseDownState( PR_FALSE );
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return frameselection->SetDelayedCaretData(me);
|
||||
}
|
||||
|
||||
curDetail = curDetail->mNext;
|
||||
}
|
||||
|
||||
curDetail = curDetail->mNext;
|
||||
delete details;
|
||||
}
|
||||
|
||||
delete details;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DRAG_AND_DROP_FRIENDLY_SELECTION
|
||||
|
||||
rv = frameselection->SetMouseDownState( PR_TRUE );
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
|
@ -1311,46 +1319,56 @@ NS_IMETHODIMP nsFrame::HandleRelease(nsIPresContext* aPresContext,
|
|||
if (!frameselection)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
#ifdef DRAG_AND_DROP_FRIENDLY_SELECTION
|
||||
PRBool supportsDelay = PR_FALSE;
|
||||
|
||||
// Check if the frameselection recorded the mouse going down.
|
||||
// If not, the user must have clicked in a part of the selection.
|
||||
// Place the caret before continuing!
|
||||
frameselection->GetDelayCaretOverExistingSelection(&supportsDelay);
|
||||
|
||||
PRBool mouseDown = PR_FALSE;
|
||||
|
||||
result = frameselection->GetMouseDownState(&mouseDown);
|
||||
|
||||
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
||||
|
||||
if (NS_SUCCEEDED(result) && me->clickCount < 2 && !mouseDown)
|
||||
if (supportsDelay)
|
||||
{
|
||||
result = frameselection->SetMouseDownState( PR_TRUE );
|
||||
// Check if the frameselection recorded the mouse going down.
|
||||
// If not, the user must have clicked in a part of the selection.
|
||||
// Place the caret before continuing!
|
||||
|
||||
nsCOMPtr<nsIContent>parentContent;
|
||||
PRInt32 contentOffset;
|
||||
PRUint32 target;
|
||||
PRBool mouseDown = PR_FALSE;
|
||||
|
||||
result = GetDataForTableSelection(me, getter_AddRefs(parentContent), &contentOffset, &target);
|
||||
result = frameselection->GetMouseDownState(&mouseDown);
|
||||
|
||||
if (NS_SUCCEEDED(result) && parentContent)
|
||||
result = frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
|
||||
else
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
nsMouseEvent *me = 0;
|
||||
|
||||
result = frameselection->GetDelayedCaretData(&me);
|
||||
|
||||
if (NS_SUCCEEDED(result) && !mouseDown && me && me->clickCount < 2)
|
||||
{
|
||||
nsCOMPtr<nsIContent> content;
|
||||
PRInt32 startOffset = 0, endOffset = 0;
|
||||
PRBool beginFrameContent = PR_FALSE;
|
||||
result = frameselection->SetMouseDownState( PR_TRUE );
|
||||
|
||||
result = GetContentAndOffsetsFromPoint(aPresContext, aEvent->point, getter_AddRefs(content), startOffset, endOffset, beginFrameContent);
|
||||
nsCOMPtr<nsIContent>parentContent;
|
||||
PRInt32 contentOffset;
|
||||
PRUint32 target;
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
result = GetDataForTableSelection(me, getter_AddRefs(parentContent), &contentOffset, &target);
|
||||
|
||||
result = frameselection->HandleClick(content, startOffset , endOffset, me->isShift, PR_FALSE, beginFrameContent);
|
||||
if (NS_SUCCEEDED(result) && parentContent)
|
||||
result = frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIContent> content;
|
||||
PRInt32 startOffset = 0, endOffset = 0;
|
||||
PRBool beginFrameContent = PR_FALSE;
|
||||
|
||||
result = GetContentAndOffsetsFromPoint(aPresContext, me->point, getter_AddRefs(content), startOffset, endOffset, beginFrameContent);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
result = frameselection->HandleClick(content, startOffset , endOffset, me->isShift, PR_FALSE, beginFrameContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DRAG_AND_DROP_FRIENDLY_SELECTION
|
||||
result = frameselection->SetDelayedCaretData(0);
|
||||
}
|
||||
|
||||
// Now handle the normal HandleRelase business.
|
||||
|
||||
|
|
|
@ -291,6 +291,10 @@ public:
|
|||
NS_IMETHOD SelectAll();
|
||||
NS_IMETHOD SetDisplaySelection(PRInt16 aState);
|
||||
NS_IMETHOD GetDisplaySelection(PRInt16 *aState);
|
||||
NS_IMETHOD SetDelayCaretOverExistingSelection(PRBool aDelay);
|
||||
NS_IMETHOD GetDelayCaretOverExistingSelection(PRBool *aDelay);
|
||||
NS_IMETHOD SetDelayedCaretData(nsMouseEvent *aMouseEvent);
|
||||
NS_IMETHOD GetDelayedCaretData(nsMouseEvent **aMouseEvent);
|
||||
/*END nsIFrameSelection interfacse*/
|
||||
|
||||
|
||||
|
@ -372,6 +376,11 @@ private:
|
|||
PRBool mDesiredXSet;
|
||||
enum HINT {HINTLEFT=0,HINTRIGHT=1}mHint;//end of this line or beginning of next
|
||||
nsIScrollableView *mScrollView;
|
||||
|
||||
PRBool mDelayCaretOverExistingSelection;
|
||||
PRBool mDelayedMouseEventValid;
|
||||
nsMouseEvent mDelayedMouseEvent;
|
||||
|
||||
public:
|
||||
static nsIAtom *sTableAtom;
|
||||
static nsIAtom *sCellAtom;
|
||||
|
@ -798,6 +807,9 @@ nsSelection::nsSelection()
|
|||
autoCopyService->Listen(mDomSelections[index]);
|
||||
}
|
||||
mDisplaySelection = nsISelectionController::SELECTION_OFF;
|
||||
|
||||
mDelayCaretOverExistingSelection = PR_TRUE;
|
||||
mDelayedMouseEventValid = PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2783,6 +2795,61 @@ nsSelection::GetDisplaySelection(PRInt16 *aToggle)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::SetDelayCaretOverExistingSelection(PRBool aDelay)
|
||||
{
|
||||
mDelayCaretOverExistingSelection = aDelay;
|
||||
|
||||
if (! aDelay)
|
||||
mDelayedMouseEventValid = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::GetDelayCaretOverExistingSelection(PRBool *aDelay)
|
||||
{
|
||||
if (!aDelay)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aDelay = mDelayCaretOverExistingSelection;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::SetDelayedCaretData(nsMouseEvent *aMouseEvent)
|
||||
{
|
||||
if (aMouseEvent)
|
||||
{
|
||||
mDelayedMouseEventValid = PR_TRUE;
|
||||
mDelayedMouseEvent = *aMouseEvent;
|
||||
|
||||
// XXX: Hmmm, should we AddRef mDelayedMouseEvent->widget?
|
||||
// Doing so might introduce a leak if things in the app
|
||||
// are not released in the correct order though, so for now
|
||||
// don't do anything.
|
||||
}
|
||||
else
|
||||
mDelayedMouseEventValid = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::GetDelayedCaretData(nsMouseEvent **aMouseEvent)
|
||||
{
|
||||
if (!aMouseEvent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (mDelayedMouseEventValid)
|
||||
*aMouseEvent = &mDelayedMouseEvent;
|
||||
else
|
||||
*aMouseEvent = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//END nsIDOMSelection interface implementations
|
||||
|
||||
#ifdef XP_MAC
|
||||
|
|
|
@ -1007,57 +1007,65 @@ nsFrame::HandlePress(nsIPresContext* aPresContext,
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
#ifdef DRAG_AND_DROP_FRIENDLY_SELECTION
|
||||
PRBool supportsDelay = PR_FALSE;
|
||||
|
||||
// Check if any part of this frame is selected, and if the
|
||||
// user clicked inside the selected region. If so, we delay
|
||||
// starting a new selection since the user may be trying to
|
||||
// drag the selected region to some other app.
|
||||
frameselection->GetDelayCaretOverExistingSelection(&supportsDelay);
|
||||
frameselection->SetDelayedCaretData(0);
|
||||
|
||||
SelectionDetails *details = 0;
|
||||
nsFrameState frameState;
|
||||
GetFrameState(&frameState);
|
||||
PRBool isSelected = ((frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT);
|
||||
|
||||
if (isSelected)
|
||||
if (supportsDelay)
|
||||
{
|
||||
rv = frameselection->LookUpSelection(content, 0, endOffset, &details, PR_FALSE);
|
||||
// Check if any part of this frame is selected, and if the
|
||||
// user clicked inside the selected region. If so, we delay
|
||||
// starting a new selection since the user may be trying to
|
||||
// drag the selected region to some other app.
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
SelectionDetails *details = 0;
|
||||
nsFrameState frameState;
|
||||
GetFrameState(&frameState);
|
||||
PRBool isSelected = ((frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT);
|
||||
|
||||
//
|
||||
// If there are any details, check to see if the user clicked
|
||||
// within any selected region of the frame.
|
||||
//
|
||||
|
||||
if (details)
|
||||
if (isSelected)
|
||||
{
|
||||
SelectionDetails *curDetail = details;
|
||||
rv = frameselection->LookUpSelection(content, 0, endOffset, &details, PR_FALSE);
|
||||
|
||||
while (curDetail)
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
//
|
||||
// If there are any details, check to see if the user clicked
|
||||
// within any selected region of the frame.
|
||||
//
|
||||
|
||||
if (details)
|
||||
{
|
||||
//
|
||||
// If the user clicked inside a selection, then just
|
||||
// return without doing anything. We will handle placing
|
||||
// the caret later on when the mouse is released.
|
||||
//
|
||||
if (curDetail->mStart <= startOffset && endOffset <= curDetail->mEnd)
|
||||
SelectionDetails *curDetail = details;
|
||||
|
||||
while (curDetail)
|
||||
{
|
||||
delete details;
|
||||
rv = frameselection->SetMouseDownState( PR_FALSE );
|
||||
return NS_OK;
|
||||
//
|
||||
// If the user clicked inside a selection, then just
|
||||
// return without doing anything. We will handle placing
|
||||
// the caret later on when the mouse is released.
|
||||
//
|
||||
if (curDetail->mStart <= startOffset && endOffset <= curDetail->mEnd)
|
||||
{
|
||||
delete details;
|
||||
rv = frameselection->SetMouseDownState( PR_FALSE );
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return frameselection->SetDelayedCaretData(me);
|
||||
}
|
||||
|
||||
curDetail = curDetail->mNext;
|
||||
}
|
||||
|
||||
curDetail = curDetail->mNext;
|
||||
delete details;
|
||||
}
|
||||
|
||||
delete details;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DRAG_AND_DROP_FRIENDLY_SELECTION
|
||||
|
||||
rv = frameselection->SetMouseDownState( PR_TRUE );
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
|
@ -1311,46 +1319,56 @@ NS_IMETHODIMP nsFrame::HandleRelease(nsIPresContext* aPresContext,
|
|||
if (!frameselection)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
#ifdef DRAG_AND_DROP_FRIENDLY_SELECTION
|
||||
PRBool supportsDelay = PR_FALSE;
|
||||
|
||||
// Check if the frameselection recorded the mouse going down.
|
||||
// If not, the user must have clicked in a part of the selection.
|
||||
// Place the caret before continuing!
|
||||
frameselection->GetDelayCaretOverExistingSelection(&supportsDelay);
|
||||
|
||||
PRBool mouseDown = PR_FALSE;
|
||||
|
||||
result = frameselection->GetMouseDownState(&mouseDown);
|
||||
|
||||
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
||||
|
||||
if (NS_SUCCEEDED(result) && me->clickCount < 2 && !mouseDown)
|
||||
if (supportsDelay)
|
||||
{
|
||||
result = frameselection->SetMouseDownState( PR_TRUE );
|
||||
// Check if the frameselection recorded the mouse going down.
|
||||
// If not, the user must have clicked in a part of the selection.
|
||||
// Place the caret before continuing!
|
||||
|
||||
nsCOMPtr<nsIContent>parentContent;
|
||||
PRInt32 contentOffset;
|
||||
PRUint32 target;
|
||||
PRBool mouseDown = PR_FALSE;
|
||||
|
||||
result = GetDataForTableSelection(me, getter_AddRefs(parentContent), &contentOffset, &target);
|
||||
result = frameselection->GetMouseDownState(&mouseDown);
|
||||
|
||||
if (NS_SUCCEEDED(result) && parentContent)
|
||||
result = frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
|
||||
else
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
nsMouseEvent *me = 0;
|
||||
|
||||
result = frameselection->GetDelayedCaretData(&me);
|
||||
|
||||
if (NS_SUCCEEDED(result) && !mouseDown && me && me->clickCount < 2)
|
||||
{
|
||||
nsCOMPtr<nsIContent> content;
|
||||
PRInt32 startOffset = 0, endOffset = 0;
|
||||
PRBool beginFrameContent = PR_FALSE;
|
||||
result = frameselection->SetMouseDownState( PR_TRUE );
|
||||
|
||||
result = GetContentAndOffsetsFromPoint(aPresContext, aEvent->point, getter_AddRefs(content), startOffset, endOffset, beginFrameContent);
|
||||
nsCOMPtr<nsIContent>parentContent;
|
||||
PRInt32 contentOffset;
|
||||
PRUint32 target;
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
result = GetDataForTableSelection(me, getter_AddRefs(parentContent), &contentOffset, &target);
|
||||
|
||||
result = frameselection->HandleClick(content, startOffset , endOffset, me->isShift, PR_FALSE, beginFrameContent);
|
||||
if (NS_SUCCEEDED(result) && parentContent)
|
||||
result = frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIContent> content;
|
||||
PRInt32 startOffset = 0, endOffset = 0;
|
||||
PRBool beginFrameContent = PR_FALSE;
|
||||
|
||||
result = GetContentAndOffsetsFromPoint(aPresContext, me->point, getter_AddRefs(content), startOffset, endOffset, beginFrameContent);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
result = frameselection->HandleClick(content, startOffset , endOffset, me->isShift, PR_FALSE, beginFrameContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DRAG_AND_DROP_FRIENDLY_SELECTION
|
||||
result = frameselection->SetDelayedCaretData(0);
|
||||
}
|
||||
|
||||
// Now handle the normal HandleRelase business.
|
||||
|
||||
|
|
|
@ -134,6 +134,10 @@ public:
|
|||
SelectionDetails **aReturnDetails, PRBool aSlowCheck);
|
||||
NS_IMETHOD SetMouseDownState(PRBool aState);
|
||||
NS_IMETHOD GetMouseDownState(PRBool *aState);
|
||||
NS_IMETHOD SetDelayCaretOverExistingSelection(PRBool aDelay);
|
||||
NS_IMETHOD GetDelayCaretOverExistingSelection(PRBool *aDelay);
|
||||
NS_IMETHOD SetDelayedCaretData(nsMouseEvent *aMouseEvent);
|
||||
NS_IMETHOD GetDelayedCaretData(nsMouseEvent **aMouseEvent);
|
||||
NS_IMETHOD GetTableCellSelection(PRBool *aState);
|
||||
NS_IMETHOD GetTableCellSelectionStyleColor(const nsStyleColor **aStyleColor);
|
||||
NS_IMETHOD GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffset, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset);
|
||||
|
@ -418,6 +422,29 @@ nsTextAreaSelectionImpl::GetMouseDownState(PRBool *aState)
|
|||
return mFrameSelection->GetMouseDownState(aState);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextAreaSelectionImpl::SetDelayCaretOverExistingSelection(PRBool aDelay)
|
||||
{
|
||||
return mFrameSelection->SetDelayCaretOverExistingSelection(aDelay);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextAreaSelectionImpl::GetDelayCaretOverExistingSelection(PRBool *aDelay)
|
||||
{
|
||||
return mFrameSelection->GetDelayCaretOverExistingSelection(aDelay);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextAreaSelectionImpl::SetDelayedCaretData(nsMouseEvent *aMouseEvent)
|
||||
{
|
||||
return mFrameSelection->SetDelayedCaretData(aMouseEvent);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextAreaSelectionImpl::GetDelayedCaretData(nsMouseEvent **aMouseEvent)
|
||||
{
|
||||
return mFrameSelection->GetDelayedCaretData(aMouseEvent);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextAreaSelectionImpl::GetTableCellSelection(PRBool *aState)
|
||||
|
|
|
@ -302,12 +302,6 @@ function BeginDragContentArea ( event )
|
|||
// dump(domselection);
|
||||
htmlstring = domselection.toString("text/html", 128+256, 0);
|
||||
textstring = domselection.toString("text/plain", 0, 0);
|
||||
|
||||
// The following return disables the ability to drag & drop
|
||||
// the current selection. This temporarily fixes bug #39821
|
||||
// so that others are unblocked. Remove it when drag & drop and
|
||||
// selection cooperate better.
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче