mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 503943, add mouse capturing api to elements, remove capturing from views, r=roc,sr=smaug
This commit is contained in:
parent
83b480a7fb
commit
51b0e867e6
@ -2773,6 +2773,18 @@ nsDocument::DestroyClassNameArray(void* aData)
|
||||
delete info;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::ReleaseCapture()
|
||||
{
|
||||
// only release the capture if the caller can access it. This prevents a
|
||||
// page from stopping a scrollbar grab for example.
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(nsIPresShell::GetCapturingContent());
|
||||
if (node && nsContentUtils::CanCallerAccess(node)) {
|
||||
nsIPresShell::SetCapturingContent(nsnull, 0);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::SetBaseURI(nsIURI* aURI)
|
||||
{
|
||||
|
@ -1084,6 +1084,29 @@ nsNSElementTearoff::GetClassList(nsIDOMDOMTokenList** aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSElementTearoff::SetCapture(PRBool aRetargetToElement)
|
||||
{
|
||||
// If there is already an active capture, ignore this request. This would
|
||||
// occur if a splitter, frame resizer, etc had already captured and we don't
|
||||
// want to override those.
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(nsIPresShell::GetCapturingContent());
|
||||
if (node)
|
||||
return NS_OK;
|
||||
|
||||
nsIPresShell::SetCapturingContent(mContent, aRetargetToElement ? CAPTURE_RETARGETTOELEMENT : 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSElementTearoff::ReleaseCapture()
|
||||
{
|
||||
if (nsIPresShell::GetCapturingContent() == mContent) {
|
||||
nsIPresShell::SetCapturingContent(nsnull, 0);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -2741,19 +2741,9 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
{
|
||||
if (static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton &&
|
||||
!mNormalLMouseEventInProcess) {
|
||||
//Our state is out of whack. We got a mouseup while still processing
|
||||
//the mousedown. Kill View-level mouse capture or it'll stay stuck
|
||||
if (aView) {
|
||||
nsIViewManager* viewMan = aView->GetViewManager();
|
||||
if (viewMan) {
|
||||
nsIView* grabbingView;
|
||||
viewMan->GetMouseEventGrabber(grabbingView);
|
||||
if (grabbingView == aView) {
|
||||
PRBool result;
|
||||
viewMan->GrabMouseEvents(nsnull, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
// We got a mouseup event while a mousedown event was being processed.
|
||||
// Make sure that the capturing content is cleared.
|
||||
nsIPresShell::SetCapturingContent(nsnull, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2858,17 +2848,9 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
ret =
|
||||
CheckForAndDispatchClick(presContext, (nsMouseEvent*)aEvent, aStatus);
|
||||
}
|
||||
|
||||
nsIPresShell *shell = presContext->GetPresShell();
|
||||
if (shell) {
|
||||
nsIViewManager* viewMan = shell->GetViewManager();
|
||||
if (viewMan) {
|
||||
nsIView* grabbingView = nsnull;
|
||||
viewMan->GetMouseEventGrabber(grabbingView);
|
||||
if (grabbingView == aView) {
|
||||
PRBool result;
|
||||
viewMan->GrabMouseEvents(nsnull, result);
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsFrameSelection> frameSelection = shell->FrameSelection();
|
||||
frameSelection->SetMouseDownState(PR_FALSE);
|
||||
}
|
||||
|
@ -411,15 +411,22 @@ protected:
|
||||
static PRInt32 sUserInputEventDepth;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This class is used while processing real user input. During this time, popups
|
||||
* are allowed. For mousedown events, mouse capturing is also permitted.
|
||||
*/
|
||||
class nsAutoHandlingUserInputStatePusher
|
||||
{
|
||||
public:
|
||||
nsAutoHandlingUserInputStatePusher(PRBool aIsHandlingUserInput)
|
||||
: mIsHandlingUserInput(aIsHandlingUserInput)
|
||||
nsAutoHandlingUserInputStatePusher(PRBool aIsHandlingUserInput, PRBool aIsMouseDown)
|
||||
: mIsHandlingUserInput(aIsHandlingUserInput), mIsMouseDown(aIsMouseDown)
|
||||
{
|
||||
if (aIsHandlingUserInput) {
|
||||
nsEventStateManager::StartHandlingUserInput();
|
||||
if (aIsMouseDown) {
|
||||
nsIPresShell::SetCapturingContent(nsnull, 0);
|
||||
nsIPresShell::AllowMouseCapture(PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,11 +434,15 @@ public:
|
||||
{
|
||||
if (mIsHandlingUserInput) {
|
||||
nsEventStateManager::StopHandlingUserInput();
|
||||
if (mIsMouseDown) {
|
||||
nsIPresShell::AllowMouseCapture(PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
PRBool mIsHandlingUserInput;
|
||||
PRBool mIsMouseDown;
|
||||
|
||||
private:
|
||||
// Hide so that this class can only be stack-allocated
|
||||
|
@ -1139,7 +1139,7 @@ nsHTMLFormElement::SubmitSubmission(nsIFormSubmission* aFormSubmission)
|
||||
{
|
||||
nsAutoPopupStatePusher popupStatePusher(mSubmitPopupState);
|
||||
|
||||
nsAutoHandlingUserInputStatePusher userInpStatePusher(mSubmitInitiatedFromUserInput);
|
||||
nsAutoHandlingUserInputStatePusher userInpStatePusher(mSubmitInitiatedFromUserInput, PR_FALSE);
|
||||
|
||||
rv = aFormSubmission->SubmitTo(actionURI, target, this, linkHandler,
|
||||
getter_AddRefs(docShell),
|
||||
|
@ -43,7 +43,7 @@
|
||||
interface nsIBoxObject;
|
||||
interface nsIDOMLocation;
|
||||
|
||||
[scriptable, uuid(09a439ad-4079-46d5-a050-4d7015d1a108)]
|
||||
[scriptable, uuid(B7E9211B-F29F-4E2D-9762-6BCBC64E5C05)]
|
||||
interface nsIDOMNSDocument : nsISupports
|
||||
{
|
||||
readonly attribute DOMString characterSet;
|
||||
@ -91,4 +91,10 @@ interface nsIDOMNSDocument : nsISupports
|
||||
*/
|
||||
nsIDOMElement elementFromPoint(in long x, in long y);
|
||||
|
||||
/**
|
||||
* Release the current mouse capture if it is on an element within this
|
||||
* document.
|
||||
*/
|
||||
void releaseCapture();
|
||||
|
||||
};
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(df86b1a8-02c3-47be-a76b-856620f925df)]
|
||||
[scriptable, uuid(FA8D7AF8-C208-4564-A0CD-346C345711F0)]
|
||||
interface nsIDOMNSElement : nsISupports
|
||||
{
|
||||
/*
|
||||
@ -152,4 +152,20 @@ interface nsIDOMNSElement : nsISupports
|
||||
* Returns a DOMTokenList object reflecting the class attribute.
|
||||
*/
|
||||
readonly attribute nsIDOMDOMTokenList classList;
|
||||
|
||||
/**
|
||||
* Set this during a mousedown event to grab and retarget all mouse events
|
||||
* to this element until the mouse button is released or releaseCapture is
|
||||
* called. If retargetToElement is true, then all events are targetted at
|
||||
* this element. If false, events can also fire at descendants of this
|
||||
* element.
|
||||
*
|
||||
*/
|
||||
void setCapture([optional] in boolean retargetToElement);
|
||||
|
||||
/**
|
||||
* If this element has captured the mouse, release the capture. If another
|
||||
* element has captured the mouse, this method has no effect.
|
||||
*/
|
||||
void releaseCapture();
|
||||
};
|
||||
|
@ -104,6 +104,23 @@ class nsDisplayListBuilder;
|
||||
typedef short SelectionType;
|
||||
typedef PRUint32 nsFrameState;
|
||||
|
||||
// Flags to pass to SetCapturingContent
|
||||
//
|
||||
// when assigning capture, ignore whether capture is allowed or not
|
||||
#define CAPTURE_IGNOREALLOWED 1
|
||||
// true if events should be targeted at the capturing content or its children
|
||||
#define CAPTURE_RETARGETTOELEMENT 2
|
||||
|
||||
typedef struct CapturingContentInfo {
|
||||
// capture should only be allowed during a mousedown event
|
||||
PRPackedBool mAllowed;
|
||||
PRPackedBool mRetargetToElement;
|
||||
nsIContent* mContent;
|
||||
|
||||
CapturingContentInfo() :
|
||||
mAllowed(PR_FALSE), mRetargetToElement(PR_FALSE), mContent(nsnull) { }
|
||||
} CapturingContentInfo;
|
||||
|
||||
// eba51d41-68db-4dab-a57b-dc1a2704de87
|
||||
#define NS_IPRESSHELL_IID \
|
||||
{ 0xeba51d41, 0x68db, 0x4dab, \
|
||||
@ -857,6 +874,42 @@ public:
|
||||
return mObservesMutationsForPrint;
|
||||
}
|
||||
|
||||
// mouse capturing
|
||||
|
||||
static CapturingContentInfo gCaptureInfo;
|
||||
|
||||
/**
|
||||
* When capturing content is set, it traps all mouse events and retargets
|
||||
* them at this content node. If capturing is not allowed
|
||||
* (gCaptureInfo.mAllowed is false), then capturing is not set. However, if
|
||||
* the CAPTURE_IGNOREALLOWED flag is set, the allowed state is ignored and
|
||||
* capturing is set regardless. To disable capture, pass null for the value
|
||||
* of aContent.
|
||||
*
|
||||
* If CAPTURE_RETARGETTOELEMENT is set, all mouse events are targeted at
|
||||
* aContent only. Otherwise, mouse events are targeted at aContent or its
|
||||
* descendants. That is, descendants of aContent receive mouse events as
|
||||
* they normally would, but mouse events outside of aContent are retargeted
|
||||
* to aContent.
|
||||
*/
|
||||
static void SetCapturingContent(nsIContent* aContent, PRUint8 aFlags);
|
||||
|
||||
/**
|
||||
* Return the active content currently capturing the mouse if any.
|
||||
*/
|
||||
static nsIContent* GetCapturingContent()
|
||||
{
|
||||
return gCaptureInfo.mContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow or disallow mouse capturing.
|
||||
*/
|
||||
static void AllowMouseCapture(PRBool aAllowed)
|
||||
{
|
||||
gCaptureInfo.mAllowed = aAllowed;
|
||||
}
|
||||
|
||||
protected:
|
||||
// IMPORTANT: The ownership implicit in the following member variables
|
||||
// has been explicitly checked. If you add any members to this class,
|
||||
|
@ -208,6 +208,7 @@ static NS_DEFINE_CID(kCSSStyleSheetCID, NS_CSS_STYLESHEET_CID);
|
||||
static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
|
||||
|
||||
PRBool nsIPresShell::gIsAccessibilityActive = PR_FALSE;
|
||||
CapturingContentInfo nsIPresShell::gCaptureInfo;
|
||||
|
||||
// convert a color value to a string, in the CSS format #RRGGBB
|
||||
// * - initially created for bugs 31816, 20760, 22963
|
||||
@ -797,6 +798,7 @@ public:
|
||||
NS_IMETHOD_(void) InvalidateFrameForView(nsIView *view);
|
||||
NS_IMETHOD_(void) DispatchSynthMouseMove(nsGUIEvent *aEvent,
|
||||
PRBool aFlushOnHoverChange);
|
||||
NS_IMETHOD_(void) ClearMouseCapture(nsIView* aView);
|
||||
|
||||
// caret handling
|
||||
NS_IMETHOD GetCaret(nsCaret **aOutCaret);
|
||||
@ -4377,6 +4379,41 @@ PresShell::DispatchSynthMouseMove(nsGUIEvent *aEvent,
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
PresShell::ClearMouseCapture(nsIView* aView)
|
||||
{
|
||||
if (gCaptureInfo.mContent) {
|
||||
if (aView) {
|
||||
// if a view was specified, ensure that the captured content
|
||||
// is within this view
|
||||
nsIFrame* frame = GetPrimaryFrameFor(gCaptureInfo.mContent);
|
||||
if (frame) {
|
||||
nsIView* view = frame->GetClosestView();
|
||||
while (view) {
|
||||
if (view == aView) {
|
||||
NS_RELEASE(gCaptureInfo.mContent);
|
||||
// the view containing the captured content likely disappeared so
|
||||
// disable capture for now.
|
||||
gCaptureInfo.mAllowed = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
view = view->GetParent();
|
||||
}
|
||||
// return if the view wasn't found
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NS_RELEASE(gCaptureInfo.mContent);
|
||||
}
|
||||
|
||||
// disable mouse capture until the next mousedown as a dialog has opened
|
||||
// or a drag has started. Otherwise, someone could start capture during
|
||||
// the modal dialog or drag.
|
||||
gCaptureInfo.mAllowed = PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::DoGetContents(const nsACString& aMimeType, PRUint32 aFlags, PRBool aSelectionOnly, nsAString& aOutValue)
|
||||
{
|
||||
@ -5701,6 +5738,22 @@ PresShell::PaintDefaultBackground(nsIView* aView,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsIPresShell::SetCapturingContent(nsIContent* aContent, PRUint8 aFlags)
|
||||
{
|
||||
NS_IF_RELEASE(gCaptureInfo.mContent);
|
||||
|
||||
// only set capturing content if allowed or the CAPTURE_IGNOREALLOWED flag
|
||||
// is used
|
||||
if ((aFlags & CAPTURE_IGNOREALLOWED) || gCaptureInfo.mAllowed) {
|
||||
if (aContent) {
|
||||
NS_ADDREF(gCaptureInfo.mContent = aContent);
|
||||
}
|
||||
gCaptureInfo.mRetargetToElement = (aFlags & CAPTURE_RETARGETTOELEMENT) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
PresShell::GetCurrentEventFrame()
|
||||
{
|
||||
@ -5857,40 +5910,49 @@ PresShell::HandleEvent(nsIView *aView,
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIDocument> retargetEventDoc;
|
||||
// key and IME events must be targeted at the presshell for the focused frame
|
||||
if (!sDontRetargetEvents && NS_IsEventTargetedAtFocusedWindow(aEvent)) {
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (!fm)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (!sDontRetargetEvents) {
|
||||
if (NS_IsEventTargetedAtFocusedWindow(aEvent)) {
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (!fm)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> window;
|
||||
fm->GetFocusedWindow(getter_AddRefs(window));
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> window;
|
||||
fm->GetFocusedWindow(getter_AddRefs(window));
|
||||
// if there is no focused frame, there isn't anything to fire a key event
|
||||
// at so just return
|
||||
nsCOMPtr<nsPIDOMWindow> piWindow = do_QueryInterface(window);
|
||||
if (!piWindow)
|
||||
return NS_OK;
|
||||
|
||||
// if there is no focused frame, there isn't anything to fire a key event
|
||||
// at so just return
|
||||
nsCOMPtr<nsPIDOMWindow> piWindow = do_QueryInterface(window);
|
||||
if (!piWindow)
|
||||
return NS_OK;
|
||||
retargetEventDoc = do_QueryInterface(piWindow->GetExtantDocument());
|
||||
if (!retargetEventDoc)
|
||||
return NS_OK;
|
||||
} else if (NS_IS_MOUSE_EVENT(aEvent) && GetCapturingContent()) {
|
||||
// if the mouse is being captured then retarget the mouse event at the
|
||||
// document that is being captured.
|
||||
retargetEventDoc = gCaptureInfo.mContent->GetCurrentDoc();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(piWindow->GetExtantDocument()));
|
||||
if (!doc)
|
||||
return NS_OK;
|
||||
if (retargetEventDoc) {
|
||||
nsIPresShell* presShell = retargetEventDoc->GetPrimaryShell();
|
||||
if (!presShell)
|
||||
return NS_OK;
|
||||
|
||||
nsIPresShell *presShell = doc->GetPrimaryShell();
|
||||
if (!presShell)
|
||||
return NS_OK;
|
||||
if (presShell != this) {
|
||||
nsCOMPtr<nsIViewObserver> viewObserver = do_QueryInterface(presShell);
|
||||
if (!viewObserver)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (presShell != this) {
|
||||
nsCOMPtr<nsIViewObserver> viewObserver = do_QueryInterface(presShell);
|
||||
if (!viewObserver)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIView *view;
|
||||
presShell->GetViewManager()->GetRootView(view);
|
||||
sDontRetargetEvents = PR_TRUE;
|
||||
nsresult rv = viewObserver->HandleEvent(view, aEvent, aEventStatus);
|
||||
sDontRetargetEvents = PR_FALSE;
|
||||
return rv;
|
||||
nsIView *view;
|
||||
presShell->GetViewManager()->GetRootView(view);
|
||||
sDontRetargetEvents = PR_TRUE;
|
||||
nsresult rv = viewObserver->HandleEvent(view, aEvent, aEventStatus);
|
||||
sDontRetargetEvents = PR_FALSE;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5941,8 +6003,41 @@ PresShell::HandleEvent(nsIView *aView,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool getDescendantPoint = PR_TRUE;
|
||||
nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
|
||||
|
||||
if (NS_IS_MOUSE_EVENT(aEvent) && GetCapturingContent()) {
|
||||
// if a node is capturing the mouse, get the frame for the capturing
|
||||
// content and use that instead. However, if the content has no parent,
|
||||
// such as the root frame, get the parent canvas frame instead. This
|
||||
// ensures that positioned frames are included when hit-testing.
|
||||
nsIContent* capturingContent = gCaptureInfo.mContent;
|
||||
frame = GetPrimaryFrameFor(capturingContent);
|
||||
if (frame) {
|
||||
getDescendantPoint = !gCaptureInfo.mRetargetToElement;
|
||||
if (!capturingContent->GetParent()) {
|
||||
frame = frame->GetParent();
|
||||
}
|
||||
else {
|
||||
// special case for <select> as it needs to capture on the dropdown list.
|
||||
if (capturingContent->Tag() == nsGkAtoms::select &&
|
||||
capturingContent->IsNodeOfType(nsINode::eHTML)) {
|
||||
nsIFrame* childframe = frame->GetChildList(nsGkAtoms::selectPopupList).FirstChild();
|
||||
if (childframe) {
|
||||
frame = childframe;
|
||||
}
|
||||
}
|
||||
|
||||
// if the frame is a scrolling frame, get the inner scrolled frame instead.
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(frame);
|
||||
if (scrollFrame) {
|
||||
frame = scrollFrame->GetScrolledFrame();
|
||||
}
|
||||
}
|
||||
aView = frame->GetClosestView();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool dispatchUsingCoordinates = NS_IsEventUsingCoordinates(aEvent);
|
||||
|
||||
// if this event has no frame, we need to retarget it at a parent
|
||||
@ -5995,17 +6090,19 @@ PresShell::HandleEvent(nsIView *aView,
|
||||
#endif
|
||||
}
|
||||
|
||||
nsPoint eventPoint
|
||||
= nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
|
||||
nsIFrame* targetFrame;
|
||||
{
|
||||
nsAutoDisableGetUsedXAssertions disableAssert;
|
||||
PRBool ignoreRootScrollFrame = PR_FALSE;
|
||||
if (aEvent->eventStructType == NS_MOUSE_EVENT) {
|
||||
ignoreRootScrollFrame = static_cast<nsMouseEvent*>(aEvent)->ignoreRootScrollFrame;
|
||||
nsIFrame* targetFrame = nsnull;
|
||||
if (getDescendantPoint) {
|
||||
nsPoint eventPoint
|
||||
= nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
|
||||
{
|
||||
nsAutoDisableGetUsedXAssertions disableAssert;
|
||||
PRBool ignoreRootScrollFrame = PR_FALSE;
|
||||
if (aEvent->eventStructType == NS_MOUSE_EVENT) {
|
||||
ignoreRootScrollFrame = static_cast<nsMouseEvent*>(aEvent)->ignoreRootScrollFrame;
|
||||
}
|
||||
targetFrame = nsLayoutUtils::GetFrameForPoint(frame, eventPoint,
|
||||
PR_FALSE, ignoreRootScrollFrame);
|
||||
}
|
||||
targetFrame = nsLayoutUtils::GetFrameForPoint(frame, eventPoint,
|
||||
PR_FALSE, ignoreRootScrollFrame);
|
||||
}
|
||||
|
||||
if (targetFrame) {
|
||||
@ -6285,7 +6382,8 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView,
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput);
|
||||
nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput,
|
||||
aEvent->message == NS_MOUSE_BUTTON_DOWN);
|
||||
|
||||
nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
|
||||
|
||||
@ -6331,6 +6429,11 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView,
|
||||
weakView.GetView());
|
||||
}
|
||||
}
|
||||
|
||||
if (aEvent->message == NS_MOUSE_BUTTON_UP) {
|
||||
// reset the capturing content now that the mouse button is up
|
||||
SetCapturingContent(nsnull, 0);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -1033,28 +1033,23 @@ nsListControlFrame::CaptureMouseEvents(PRBool aGrabMouseEvents)
|
||||
if (NS_UNLIKELY(!view))
|
||||
return;
|
||||
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
if (viewMan) {
|
||||
PRBool result;
|
||||
// It's not clear why we don't have the widget capture mouse events here.
|
||||
if (aGrabMouseEvents) {
|
||||
viewMan->GrabMouseEvents(view, result);
|
||||
} else {
|
||||
nsIView* curGrabber;
|
||||
viewMan->GetMouseEventGrabber(curGrabber);
|
||||
PRBool dropDownIsHidden = PR_FALSE;
|
||||
if (IsInDropDownMode()) {
|
||||
dropDownIsHidden = !mComboboxFrame->IsDroppedDown();
|
||||
}
|
||||
if (curGrabber == view || dropDownIsHidden) {
|
||||
// only unset the grabber if *we* are the ones doing the grabbing
|
||||
// (or if the dropdown is hidden, in which case NO-ONE should be
|
||||
// grabbing anything
|
||||
// it could be a scrollbar inside this listbox which is actually grabbing
|
||||
// This shouldn't be necessary. We should simply ensure that events targeting
|
||||
// scrollbars are never visible to DOM consumers.
|
||||
viewMan->GrabMouseEvents(nsnull, result);
|
||||
}
|
||||
if (aGrabMouseEvents) {
|
||||
nsIPresShell::SetCapturingContent(mContent, CAPTURE_IGNOREALLOWED);
|
||||
} else {
|
||||
nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
|
||||
|
||||
PRBool dropDownIsHidden = PR_FALSE;
|
||||
if (IsInDropDownMode()) {
|
||||
dropDownIsHidden = !mComboboxFrame->IsDroppedDown();
|
||||
}
|
||||
if (capturingContent == mContent || dropDownIsHidden) {
|
||||
// only clear the capturing content if *we* are the ones doing the
|
||||
// capturing (or if the dropdown is hidden, in which case NO-ONE should
|
||||
// be capturing anything - it could be a scrollbar inside this listbox
|
||||
// which is actually grabbing
|
||||
// This shouldn't be necessary. We should simply ensure that events targeting
|
||||
// scrollbars are never visible to DOM consumers.
|
||||
nsIPresShell::SetCapturingContent(nsnull, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2122,11 +2117,7 @@ nsListControlFrame::GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent,
|
||||
if (IgnoreMouseEventForSelection(aMouseEvent))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIView* view = GetScrolledFrame()->GetView();
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
nsIView* curGrabber;
|
||||
viewMan->GetMouseEventGrabber(curGrabber);
|
||||
if (curGrabber != view) {
|
||||
if (nsIPresShell::GetCapturingContent() != mContent) {
|
||||
// If we're not capturing, then ignore movement in the border
|
||||
nsPoint pt = nsLayoutUtils::GetDOMEventCoordinatesRelativeTo(aMouseEvent, this);
|
||||
nsRect borderInnerEdge = GetScrollableView()->View()->GetBounds();
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "nsStyleContext.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsCRT.h"
|
||||
@ -743,18 +744,17 @@ nsFrame::GetChildList(nsIAtom* aListName) const
|
||||
}
|
||||
|
||||
static nsIFrame*
|
||||
GetActiveSelectionFrame(nsIFrame* aFrame)
|
||||
GetActiveSelectionFrame(nsPresContext* aPresContext, nsIFrame* aFrame)
|
||||
{
|
||||
nsIView* mouseGrabber;
|
||||
aFrame->PresContext()->GetPresShell()->
|
||||
GetViewManager()->GetMouseEventGrabber(mouseGrabber);
|
||||
if (mouseGrabber) {
|
||||
nsIFrame* activeFrame = nsLayoutUtils::GetFrameFor(mouseGrabber);
|
||||
if (activeFrame) {
|
||||
return activeFrame;
|
||||
nsIPresShell* shell = aPresContext->GetPresShell();
|
||||
if (shell) {
|
||||
nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
|
||||
if (capturingContent) {
|
||||
nsIFrame* activeFrame = shell->GetPrimaryFrameFor(capturingContent);
|
||||
return activeFrame ? activeFrame : aFrame;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return aFrame;
|
||||
}
|
||||
|
||||
@ -1907,8 +1907,23 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
||||
// NS_STYLE_USER_SELECT_TOGGLE, need to change this logic
|
||||
PRBool useFrameSelection = (selectStyle == NS_STYLE_USER_SELECT_TEXT);
|
||||
|
||||
if (!IsMouseCaptured(aPresContext))
|
||||
CaptureMouse(aPresContext, PR_TRUE);
|
||||
// If the mouse is dragged outside the nearest enclosing scrollable area
|
||||
// while making a selection, the area will be scrolled. To do this, capture
|
||||
// the mouse on the nearest scrollable frame. If there isn't a scrollable
|
||||
// frame, or something else is already capturing the mouse, there's no
|
||||
// reason to capture.
|
||||
if (!nsIPresShell::GetCapturingContent()) {
|
||||
nsIFrame* checkFrame = this;
|
||||
nsIScrollableFrame *scrollFrame = nsnull;
|
||||
while (checkFrame) {
|
||||
scrollFrame = do_QueryFrame(checkFrame);
|
||||
if (scrollFrame) {
|
||||
nsIPresShell::SetCapturingContent(checkFrame->GetContent(), CAPTURE_IGNOREALLOWED);
|
||||
break;
|
||||
}
|
||||
checkFrame = checkFrame->GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX This is screwy; it really should use the selection frame, not the
|
||||
// event frame
|
||||
@ -2183,29 +2198,6 @@ nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack,
|
||||
return frameSelection->MaintainSelection(aAmountBack);
|
||||
}
|
||||
|
||||
// Figure out which view we should point capturing at, given that drag started
|
||||
// in this frame.
|
||||
static nsIView* GetNearestCapturingView(nsIFrame* aFrame) {
|
||||
nsIView* view = nsnull;
|
||||
while (!(view = aFrame->GetMouseCapturer()) && aFrame->GetParent()) {
|
||||
aFrame = aFrame->GetParent();
|
||||
}
|
||||
if (!view) {
|
||||
// Use the root view. The root frame always has the root view.
|
||||
view = aFrame->GetView();
|
||||
}
|
||||
NS_ASSERTION(view, "No capturing view found");
|
||||
return view;
|
||||
}
|
||||
|
||||
nsIFrame* nsFrame::GetNearestCapturingFrame(nsIFrame* aFrame) {
|
||||
nsIFrame* captureFrame = aFrame;
|
||||
while (captureFrame && !captureFrame->GetMouseCapturer()) {
|
||||
captureFrame = captureFrame->GetParent();
|
||||
}
|
||||
return captureFrame;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFrame::HandleDrag(nsPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus)
|
||||
@ -2230,13 +2222,6 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPresContext* aPresContext,
|
||||
|
||||
frameselection->StopAutoScrollTimer();
|
||||
|
||||
// If we have capturing view, it must be ensured that |this| doesn't
|
||||
// get deleted during HandleDrag.
|
||||
nsWeakFrame weakFrame = GetNearestCapturingView(this) ? this : nsnull;
|
||||
#ifdef NS_DEBUG
|
||||
PRBool frameAlive = weakFrame.IsAlive();
|
||||
#endif
|
||||
|
||||
// Check if we are dragging in a table cell
|
||||
nsCOMPtr<nsIContent> parentContent;
|
||||
PRInt32 contentOffset;
|
||||
@ -2254,22 +2239,29 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPresContext* aPresContext,
|
||||
frameselection->HandleDrag(this, pt);
|
||||
}
|
||||
|
||||
if (weakFrame) {
|
||||
nsIView* captureView = GetNearestCapturingView(this);
|
||||
if (captureView) {
|
||||
// get the nearest scrollframe
|
||||
nsIFrame* checkFrame = this;
|
||||
nsIScrollableFrame *scrollFrame = nsnull;
|
||||
while (checkFrame) {
|
||||
scrollFrame = do_QueryFrame(checkFrame);
|
||||
if (scrollFrame) {
|
||||
break;
|
||||
}
|
||||
checkFrame = checkFrame->GetParent();
|
||||
}
|
||||
|
||||
if (scrollFrame) {
|
||||
nsIView* capturingView = scrollFrame->GetScrollableView()->View();
|
||||
if (capturingView) {
|
||||
// Get the view that aEvent->point is relative to. This is disgusting.
|
||||
nsIView* eventView = nsnull;
|
||||
nsPoint pt = nsLayoutUtils::GetEventCoordinatesForNearestView(aEvent, this,
|
||||
&eventView);
|
||||
nsPoint capturePt = pt + eventView->GetOffsetTo(captureView);
|
||||
frameselection->StartAutoScrollTimer(captureView, capturePt, 30);
|
||||
nsPoint capturePt = pt + eventView->GetOffsetTo(capturingView);
|
||||
frameselection->StartAutoScrollTimer(capturingView, capturePt, 30);
|
||||
}
|
||||
}
|
||||
#ifdef NS_DEBUG
|
||||
if (frameAlive && !weakFrame.IsAlive()) {
|
||||
NS_WARNING("nsFrame deleted during nsFrame::HandleDrag.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2342,11 +2334,11 @@ NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
nsIFrame* activeFrame = GetActiveSelectionFrame(this);
|
||||
nsIFrame* activeFrame = GetActiveSelectionFrame(aPresContext, this);
|
||||
|
||||
// We can unconditionally stop capturing because
|
||||
// we should never be capturing when the mouse button is up
|
||||
CaptureMouse(aPresContext, PR_FALSE);
|
||||
nsIPresShell::SetCapturingContent(nsnull, 0);
|
||||
|
||||
PRBool selectionOff =
|
||||
(DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF);
|
||||
@ -5931,51 +5923,6 @@ nsFrame::GetFirstLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrame::CaptureMouse(nsPresContext* aPresContext, PRBool aGrabMouseEvents)
|
||||
{
|
||||
// get its view
|
||||
nsIView* view = GetNearestCapturingView(this);
|
||||
if (!view) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
if (!viewMan) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (aGrabMouseEvents) {
|
||||
PRBool result;
|
||||
viewMan->GrabMouseEvents(view, result);
|
||||
} else {
|
||||
PRBool result;
|
||||
viewMan->GrabMouseEvents(nsnull, result);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsFrame::IsMouseCaptured(nsPresContext* aPresContext)
|
||||
{
|
||||
// get its view
|
||||
nsIView* view = GetNearestCapturingView(this);
|
||||
|
||||
if (view) {
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
|
||||
if (viewMan) {
|
||||
nsIView* grabbingView;
|
||||
viewMan->GetMouseEventGrabber(grabbingView);
|
||||
if (grabbingView == view)
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsIFrame::SetProperty(nsIAtom* aPropName,
|
||||
void* aPropValue,
|
||||
|
@ -215,14 +215,6 @@ public:
|
||||
PRInt8 aOutSideLimit
|
||||
);
|
||||
|
||||
/**
|
||||
* Find the nearest frame with a mouse capturer. If no
|
||||
* parent has mouse capture this will return null.
|
||||
* @param aFrame Frame drag began in.
|
||||
* @return Nearest capturing frame.
|
||||
*/
|
||||
static nsIFrame* GetNearestCapturingFrame(nsIFrame* aFrame);
|
||||
|
||||
NS_IMETHOD CharacterDataChanged(CharacterDataChangeInfo* aInfo);
|
||||
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
@ -415,10 +407,6 @@ public:
|
||||
void ConsiderChildOverflow(nsRect& aOverflowArea,
|
||||
nsIFrame* aChildFrame);
|
||||
|
||||
//Mouse Capturing code used by the frames to tell the view to capture all the following events
|
||||
NS_IMETHOD CaptureMouse(nsPresContext* aPresContext, PRBool aGrabMouseEvents);
|
||||
PRBool IsMouseCaptured(nsPresContext* aPresContext);
|
||||
|
||||
virtual const void* GetStyleDataExternal(nsStyleStructID aSID) const;
|
||||
|
||||
|
||||
|
@ -318,19 +318,6 @@ nsHTMLFramesetFrame::Init(nsIContent* aContent,
|
||||
nsPresContext* presContext = PresContext();
|
||||
nsIPresShell* shell = presContext->PresShell();
|
||||
|
||||
// create the view. a view is needed since it needs to be a mouse grabber
|
||||
nsIViewManager* viewMan = shell->GetViewManager();
|
||||
|
||||
nsIView *parView = GetAncestorWithView()->GetView();
|
||||
nsRect boundBox(0, 0, 0, 0);
|
||||
nsIView* view = viewMan->CreateView(boundBox, parView);
|
||||
if (!view)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// XXX Put it last in document order until we can do better
|
||||
viewMan->InsertChild(parView, view, nsnull, PR_TRUE);
|
||||
SetView(view);
|
||||
|
||||
nsFrameborder frameborder = GetFrameBorder();
|
||||
PRInt32 borderWidth = GetBorderWidth(presContext, PR_FALSE);
|
||||
nscolor borderColor = GetBorderColor();
|
||||
@ -815,28 +802,6 @@ NS_METHOD nsHTMLFramesetFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
PRBool
|
||||
nsHTMLFramesetFrame::IsGrabbingMouse()
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
nsIView* view = GetView();
|
||||
if (view) {
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
if (viewMan) {
|
||||
nsIView* grabber;
|
||||
viewMan->GetMouseEventGrabber(grabber);
|
||||
if (grabber == view) {
|
||||
// the nsFramesetBorderFrame has captured NS_MOUSE_DOWN
|
||||
result = PR_TRUE;
|
||||
}
|
||||
NS_RELEASE(viewMan);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFramesetFrame::GetCursor(const nsPoint& aPoint,
|
||||
nsIFrame::Cursor& aCursor)
|
||||
@ -1481,28 +1446,23 @@ nsHTMLFramesetFrame::StartMouseDrag(nsPresContext* aPresContext,
|
||||
IndexOf(aBorder, index);
|
||||
NS_ASSERTION((nsnull != aBorder) && (index >= 0), "invalid dragger");
|
||||
#endif
|
||||
nsIView* view = GetView();
|
||||
if (view) {
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
if (viewMan) {
|
||||
PRBool ignore;
|
||||
viewMan->GrabMouseEvents(view, ignore);
|
||||
mDragger = aBorder;
|
||||
|
||||
mFirstDragPoint = aEvent->refPoint;
|
||||
nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
|
||||
|
||||
// Store the original frame sizes
|
||||
if (mDragger->mVertical) {
|
||||
mPrevNeighborOrigSize = mColSizes[mDragger->mPrevNeighbor];
|
||||
mNextNeighborOrigSize = mColSizes[mDragger->mNextNeighbor];
|
||||
} else {
|
||||
mPrevNeighborOrigSize = mRowSizes[mDragger->mPrevNeighbor];
|
||||
mNextNeighborOrigSize = mRowSizes[mDragger->mNextNeighbor];
|
||||
}
|
||||
mDragger = aBorder;
|
||||
|
||||
gDragInProgress = PR_TRUE;
|
||||
}
|
||||
mFirstDragPoint = aEvent->refPoint;
|
||||
|
||||
// Store the original frame sizes
|
||||
if (mDragger->mVertical) {
|
||||
mPrevNeighborOrigSize = mColSizes[mDragger->mPrevNeighbor];
|
||||
mNextNeighborOrigSize = mColSizes[mDragger->mNextNeighbor];
|
||||
} else {
|
||||
mPrevNeighborOrigSize = mRowSizes[mDragger->mPrevNeighbor];
|
||||
mNextNeighborOrigSize = mRowSizes[mDragger->mNextNeighbor];
|
||||
}
|
||||
|
||||
gDragInProgress = PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
@ -1583,17 +1543,10 @@ nsHTMLFramesetFrame::MouseDrag(nsPresContext* aPresContext,
|
||||
void
|
||||
nsHTMLFramesetFrame::EndMouseDrag(nsPresContext* aPresContext)
|
||||
{
|
||||
nsIView* view = GetView();
|
||||
if (view) {
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
if (viewMan) {
|
||||
mDragger = nsnull;
|
||||
PRBool ignore;
|
||||
viewMan->GrabMouseEvents(nsnull, ignore);
|
||||
}
|
||||
}
|
||||
nsIPresShell::SetCapturingContent(nsnull, 0);
|
||||
mDragger = nsnull;
|
||||
gDragInProgress = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
NS_NewHTMLFramesetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||
|
@ -310,10 +310,6 @@ public:
|
||||
return mInner.GetScrolledFrame()->GetContentInsertionFrame();
|
||||
}
|
||||
|
||||
virtual nsIView* GetMouseCapturer() const {
|
||||
return mInner.GetScrolledFrame()->GetView();
|
||||
}
|
||||
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRUint32 aFlags);
|
||||
@ -478,10 +474,6 @@ public:
|
||||
return mInner.GetScrolledFrame()->GetContentInsertionFrame();
|
||||
}
|
||||
|
||||
virtual nsIView* GetMouseCapturer() const {
|
||||
return mInner.GetScrolledFrame()->GetView();
|
||||
}
|
||||
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRUint32 aFlags);
|
||||
|
@ -107,9 +107,10 @@ struct CharacterDataChangeInfo;
|
||||
|
||||
typedef class nsIFrame nsIBox;
|
||||
|
||||
// 87F5B42A-507D-4707-976C-46819867BC63
|
||||
#define NS_IFRAME_IID \
|
||||
{ 0x7e9018b5, 0x5405, 0x4e2b, \
|
||||
{ 0x87, 0x67, 0xe2, 0xb4, 0xb1, 0x3e, 0xc1, 0x69 } }
|
||||
{ 0x87f5b42a, 0x507d, 0x4707, \
|
||||
{ 0x97, 0x6c, 0x46, 0x81, 0x98, 0x67, 0xbc, 0x63 } }
|
||||
|
||||
/**
|
||||
* Indication of how the frame can be split. This is used when doing runaround
|
||||
@ -1732,14 +1733,6 @@ public:
|
||||
*/
|
||||
virtual PRBool IsLeaf() const;
|
||||
|
||||
/**
|
||||
* Does this frame want to capture the mouse when the user clicks in
|
||||
* it or its children? If so, return the view which should be
|
||||
* targeted for mouse capture. The view need not be this frame's view,
|
||||
* it could be the view on a child.
|
||||
*/
|
||||
virtual nsIView* GetMouseCapturer() const { return nsnull; }
|
||||
|
||||
/**
|
||||
* @param aFlags see InvalidateInternal below
|
||||
*/
|
||||
@ -1954,14 +1947,6 @@ public:
|
||||
/** EndSelection related calls
|
||||
*/
|
||||
|
||||
/**
|
||||
* Call to turn on/off mouseCapture at the view level. Needed by the ESM so
|
||||
* it must be in the public interface.
|
||||
* @param aPresContext presContext associated with the frame
|
||||
* @param aGrabMouseEvents PR_TRUE to enable capture, PR_FALSE to disable
|
||||
*/
|
||||
NS_IMETHOD CaptureMouse(nsPresContext* aPresContext, PRBool aGrabMouseEvents) = 0;
|
||||
|
||||
/**
|
||||
* called to find the previous/next character, word, or line returns the actual
|
||||
* nsIFrame and the frame offset. THIS DOES NOT CHANGE SELECTION STATE
|
||||
|
@ -414,7 +414,7 @@ public:
|
||||
mTimer->Cancel();
|
||||
}
|
||||
|
||||
nsresult Start(nsPresContext *aPresContext, nsIView *aView, nsPoint &aPoint)
|
||||
nsresult Start(nsPresContext *aPresContext, nsPoint &aPoint)
|
||||
{
|
||||
mPoint = aPoint;
|
||||
|
||||
@ -422,36 +422,7 @@ public:
|
||||
// stopped by the selection if the prescontext is destroyed.
|
||||
mPresContext = aPresContext;
|
||||
|
||||
// Store the content from the nearest capturing frame. If this returns null
|
||||
// the capturing frame is the root.
|
||||
nsIFrame* clientFrame = static_cast<nsIFrame*>(aView->GetClientData());
|
||||
NS_ASSERTION(clientFrame, "Missing client frame");
|
||||
|
||||
nsIFrame* capturingFrame = nsFrame::GetNearestCapturingFrame(clientFrame);
|
||||
NS_ASSERTION(!capturingFrame || capturingFrame->GetMouseCapturer(),
|
||||
"Capturing frame should have a mouse capturer" );
|
||||
|
||||
NS_ASSERTION(!capturingFrame || mPresContext == capturingFrame->PresContext(),
|
||||
"Shouldn't have different pres contexts");
|
||||
|
||||
NS_ASSERTION(capturingFrame != mPresContext->PresShell()->FrameManager()->GetRootFrame(),
|
||||
"Capturing frame should not be the root frame");
|
||||
|
||||
if (capturingFrame)
|
||||
{
|
||||
mContent = capturingFrame->GetContent();
|
||||
NS_ASSERTION(mContent, "Need content");
|
||||
|
||||
NS_ASSERTION(mContent != mPresContext->PresShell()->FrameManager()->GetRootFrame()->GetContent(),
|
||||
"We didn't want the root content!");
|
||||
|
||||
NS_ASSERTION(capturingFrame == nsFrame::GetNearestCapturingFrame(
|
||||
mPresContext->PresShell()->GetPrimaryFrameFor(mContent)),
|
||||
"Mapping of frame to content failed.");
|
||||
}
|
||||
|
||||
// Check that if there was no capturing frame the content is null.
|
||||
NS_ASSERTION(capturingFrame || !mContent, "Content not cleared correctly.");
|
||||
mContent = nsIPresShell::GetCapturingContent();
|
||||
|
||||
if (!mTimer)
|
||||
{
|
||||
@ -494,46 +465,14 @@ public:
|
||||
{
|
||||
if (mSelection && mPresContext)
|
||||
{
|
||||
// If the content is null the capturing frame must be the root frame.
|
||||
nsIFrame* capturingFrame;
|
||||
if (mContent)
|
||||
{
|
||||
nsIFrame* contentFrame = mPresContext->PresShell()->GetPrimaryFrameFor(mContent);
|
||||
if (contentFrame)
|
||||
{
|
||||
capturingFrame = nsFrame::GetNearestCapturingFrame(contentFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
capturingFrame = nsnull;
|
||||
}
|
||||
NS_ASSERTION(!capturingFrame || capturingFrame->GetMouseCapturer(),
|
||||
"Capturing frame should have a mouse capturer" );
|
||||
}
|
||||
else
|
||||
{
|
||||
capturingFrame = mPresContext->PresShell()->FrameManager()->GetRootFrame();
|
||||
}
|
||||
|
||||
// Clear the content reference now that the frame has been found.
|
||||
nsWeakFrame frame = mPresContext->PresShell()->GetPrimaryFrameFor(mContent);
|
||||
mContent = nsnull;
|
||||
|
||||
// This could happen for a frame with style changed to display:none or a frame
|
||||
// that was destroyed.
|
||||
if (!capturingFrame) {
|
||||
NS_WARNING("Frame destroyed or set to display:none before scroll timer fired.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIView* captureView = capturingFrame->GetMouseCapturer();
|
||||
|
||||
nsWeakFrame viewFrame = static_cast<nsIFrame*>(captureView->GetClientData());
|
||||
NS_ASSERTION(viewFrame.GetFrame(), "View must have a client frame");
|
||||
|
||||
mFrameSelection->HandleDrag(viewFrame, mPoint);
|
||||
mFrameSelection->HandleDrag(frame, mPoint);
|
||||
|
||||
nsPoint pnt;
|
||||
mSelection->DoAutoScrollView(mPresContext,
|
||||
viewFrame.IsAlive() ? captureView : nsnull,
|
||||
frame.IsAlive() ? frame->GetClosestView(&pnt) : nsnull,
|
||||
mPoint, PR_TRUE);
|
||||
}
|
||||
return NS_OK;
|
||||
@ -5005,7 +4944,7 @@ nsTypedSelection::DoAutoScrollView(nsPresContext *aPresContext,
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
|
||||
nsPoint svPoint = globalPoint - globalOffset;
|
||||
mAutoScrollTimer->Start(aPresContext, aView, svPoint);
|
||||
mAutoScrollTimer->Start(aPresContext, svPoint);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -28,6 +28,7 @@ function doShiftDrag(){
|
||||
wu.sendMouseEvent('mousemove', 80, 500, 0, 0, 4);
|
||||
|
||||
is(window.getSelection().rangeCount, 0, "rangeCount should be 0");
|
||||
wu.sendMouseEvent('mouseup', 80, 500, 0, 0, 4);
|
||||
|
||||
SimpleTest.finish();
|
||||
}, 0);
|
||||
|
@ -111,8 +111,7 @@ nsResizerFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
mTrackingMouseMove = PR_TRUE;
|
||||
|
||||
// start capture.
|
||||
aEvent->widget->CaptureMouse(PR_TRUE);
|
||||
CaptureMouseEvents(aPresContext,PR_TRUE);
|
||||
nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
|
||||
|
||||
// remember current mouse coordinates.
|
||||
mLastPoint = aEvent->refPoint;
|
||||
@ -136,8 +135,7 @@ nsResizerFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
mTrackingMouseMove = PR_FALSE;
|
||||
|
||||
// end capture
|
||||
aEvent->widget->CaptureMouse(PR_FALSE);
|
||||
CaptureMouseEvents(aPresContext,PR_FALSE);
|
||||
nsIPresShell::SetCapturingContent(nsnull, 0);
|
||||
|
||||
*aEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
doDefault = PR_FALSE;
|
||||
|
@ -55,7 +55,6 @@
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsScrollbarButtonFrame.h"
|
||||
@ -124,7 +123,6 @@ nsSliderFrame::Init(nsIContent* aContent,
|
||||
|
||||
mCurPos = GetCurrentPosition(aContent);
|
||||
|
||||
CreateViewForFrame(PresContext(), this, GetStyleContext(), PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -979,42 +977,14 @@ nsSliderFrame::DragThumb(PRBool aGrabMouseEvents)
|
||||
}
|
||||
}
|
||||
|
||||
// get its view
|
||||
nsIView* view = GetView();
|
||||
|
||||
if (view) {
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
|
||||
if (viewMan) {
|
||||
PRBool result;
|
||||
|
||||
if (aGrabMouseEvents) {
|
||||
viewMan->GrabMouseEvents(view,result);
|
||||
} else {
|
||||
viewMan->GrabMouseEvents(nsnull,result);
|
||||
}
|
||||
}
|
||||
}
|
||||
nsIPresShell::SetCapturingContent(aGrabMouseEvents ? GetContent() : nsnull,
|
||||
aGrabMouseEvents ? CAPTURE_IGNOREALLOWED : 0);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSliderFrame::isDraggingThumb()
|
||||
{
|
||||
// get its view
|
||||
nsIView* view = GetView();
|
||||
|
||||
if (view) {
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
|
||||
if (viewMan) {
|
||||
nsIView* grabbingView;
|
||||
viewMan->GetMouseEventGrabber(grabbingView);
|
||||
if (grabbingView == view)
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
return (nsIPresShell::GetCapturingContent() == GetContent());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -186,8 +186,6 @@ public:
|
||||
static PRInt32 GetIntegerAttribute(nsIContent* content, nsIAtom* atom, PRInt32 defaultValue);
|
||||
void EnsureOrient();
|
||||
|
||||
virtual nsIView* GetMouseCapturer() const { return GetView(); }
|
||||
|
||||
NS_IMETHOD HandlePress(nsPresContext* aPresContext,
|
||||
nsGUIEvent * aEvent,
|
||||
nsEventStatus* aEventStatus);
|
||||
|
@ -55,9 +55,6 @@
|
||||
#include "nsIDOMMouseListener.h"
|
||||
#include "nsIDOMMouseMotionListener.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsFrameList.h"
|
||||
@ -147,8 +144,6 @@ public:
|
||||
ResizeType GetResizeAfter();
|
||||
State GetState();
|
||||
|
||||
//nsresult CaptureMouse(nsPresContext* aPresContext, PRBool aGrabMouseEvents);
|
||||
//PRBool IsMouseCaptured(nsPresContext* aPresContext);
|
||||
void Reverse(nsSplitterInfo*& aIndexes, PRInt32 aCount);
|
||||
PRBool SupportsCollapseDirection(CollapseDirection aDirection);
|
||||
|
||||
@ -167,7 +162,6 @@ public:
|
||||
PRInt32 mChildInfosAfterCount;
|
||||
State mState;
|
||||
nscoord mSplitterPos;
|
||||
nscoord mSplitterViewPos;
|
||||
PRBool mDragging;
|
||||
|
||||
};
|
||||
@ -353,9 +347,6 @@ nsSplitterFrame::Init(nsIContent* aContent,
|
||||
nsresult rv = nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = nsHTMLContainerFrame::CreateViewForFrame(this, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mInner->mState = nsSplitterFrameInner::Open;
|
||||
mInner->AddListener(PresContext());
|
||||
mInner->mParentBox = nsnull;
|
||||
@ -474,7 +465,7 @@ nsSplitterFrameInner::MouseUp(nsPresContext* aPresContext, nsGUIEvent* aEvent)
|
||||
if (mDragging && mOuter) {
|
||||
AdjustChildren(aPresContext);
|
||||
AddListener(aPresContext);
|
||||
mOuter->CaptureMouse(aPresContext, PR_FALSE);
|
||||
nsIPresShell::SetCapturingContent(nsnull, 0); // XXXndeakin is this needed?
|
||||
mDragging = PR_FALSE;
|
||||
State newState = GetState();
|
||||
// if the state is dragging then make it Open.
|
||||
@ -588,20 +579,6 @@ nsSplitterFrameInner::MouseDrag(nsPresContext* aPresContext, nsGUIEvent* aEvent)
|
||||
AdjustChildren(aPresContext);
|
||||
}
|
||||
|
||||
// printf("----- resize ----- ");
|
||||
/*
|
||||
for (i=0; i < mChildInfosBeforeCount; i++)
|
||||
printf("before, index=%d, current=%d, changed=%d\n", mChildInfosBefore[i].index, mChildInfosBefore[i].current, mChildInfosBefore[i].changed);
|
||||
for (i=0; i < mChildInfosAfterCount; i++)
|
||||
printf("after, index=%d, current=%d, changed=%d\n", mChildInfosAfter[i].index, mChildInfosAfter[i].current, mChildInfosAfter[i].changed);
|
||||
*/
|
||||
|
||||
/*
|
||||
nsIPresShell *shell = aPresContext->PresShell();
|
||||
|
||||
shell->FrameNeedsReflow(mOuter, nsIPresShell::eStyleChange,
|
||||
NS_FRAME_IS_DIRTY);
|
||||
*/
|
||||
mDidDrag = PR_TRUE;
|
||||
}
|
||||
}
|
||||
@ -629,62 +606,13 @@ nsSplitterFrameInner::RemoveListener()
|
||||
NS_GET_IID(nsIDOMMouseMotionListener));
|
||||
}
|
||||
|
||||
/*
|
||||
nsresult
|
||||
nsSplitterFrameInner :: CaptureMouse(nsPresContext* aPresContext, PRBool aGrabMouseEvents)
|
||||
{
|
||||
// get its view
|
||||
nsIView* view = mOuter->GetView();
|
||||
PRBool result;
|
||||
|
||||
if (view) {
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
if (viewMan) {
|
||||
// nsIWidget* widget = view->GetWidget();
|
||||
if (aGrabMouseEvents) {
|
||||
viewMan->GrabMouseEvents(view,result);
|
||||
// if (widget)
|
||||
// widget->CaptureMouse(PR_TRUE);
|
||||
} else {
|
||||
viewMan->GrabMouseEvents(nsnull,result);
|
||||
// if (widget)
|
||||
// widget->CaptureMouse(PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsSplitterFrameInner :: IsMouseCaptured(nsPresContext* aPresContext)
|
||||
{
|
||||
// get its view
|
||||
nsIView* view = mOuter->GetView();
|
||||
|
||||
if (view) {
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
|
||||
if (viewMan) {
|
||||
nsIView* grabbingView;
|
||||
viewMan->GetMouseEventGrabber(grabbingView);
|
||||
if (grabbingView == view)
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
*/
|
||||
|
||||
nsresult
|
||||
nsSplitterFrameInner::MouseUp(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
NS_ENSURE_TRUE(mOuter, NS_OK);
|
||||
mPressed = PR_FALSE;
|
||||
|
||||
mOuter->CaptureMouse(mOuter->PresContext(), PR_FALSE);
|
||||
nsIPresShell::SetCapturingContent(nsnull, 0);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -845,26 +773,22 @@ nsSplitterFrameInner::MouseDown(nsIDOMEvent* aMouseEvent)
|
||||
if (resizeAfter == Grow)
|
||||
mChildInfosAfterCount = 0;
|
||||
|
||||
nsRect vr = mOuter->GetView()->GetBounds();
|
||||
|
||||
PRInt32 c;
|
||||
nsPoint pt = nsLayoutUtils::GetDOMEventCoordinatesRelativeTo(mouseEvent,
|
||||
mParentBox);
|
||||
if (isHorizontal) {
|
||||
c = pt.x;
|
||||
mSplitterPos = mOuter->mRect.x;
|
||||
mSplitterViewPos = vr.x;
|
||||
} else {
|
||||
c = pt.y;
|
||||
mSplitterPos = mOuter->mRect.y;
|
||||
mSplitterViewPos = vr.y;
|
||||
}
|
||||
|
||||
mDragStart = c;
|
||||
|
||||
//printf("Pressed mDragStart=%d\n",mDragStart);
|
||||
|
||||
mOuter->CaptureMouse(outerPresContext, PR_TRUE);
|
||||
nsIPresShell::SetCapturingContent(mOuter->GetContent(), CAPTURE_IGNOREALLOWED);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -104,8 +104,6 @@ public:
|
||||
|
||||
virtual void GetInitialOrientation(PRBool& aIsHorizontal);
|
||||
|
||||
virtual nsIView* GetMouseCapturer() const { return GetView(); }
|
||||
|
||||
private:
|
||||
|
||||
friend class nsSplitterFrameInner;
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsDisplayList.h"
|
||||
@ -73,20 +72,6 @@ nsTitleBarFrame::nsTitleBarFrame(nsIPresShell* aPresShell, nsStyleContext* aCont
|
||||
mTrackingMouseMove = PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTitleBarFrame::Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIFrame* asPrevInFlow)
|
||||
{
|
||||
nsresult rv = nsBoxFrame::Init(aContent, aParent, asPrevInFlow);
|
||||
|
||||
CreateViewForFrame(PresContext(), this, GetStyleContext(), PR_TRUE);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTitleBarFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
@ -131,7 +116,7 @@ nsTitleBarFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
mTrackingMouseMove = PR_TRUE;
|
||||
|
||||
// start capture.
|
||||
CaptureMouseEvents(aPresContext,PR_TRUE);
|
||||
nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
|
||||
|
||||
// remember current mouse coordinates.
|
||||
mLastPoint = aEvent->refPoint;
|
||||
@ -154,7 +139,7 @@ nsTitleBarFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
mTrackingMouseMove = PR_FALSE;
|
||||
|
||||
// end capture
|
||||
CaptureMouseEvents(aPresContext,PR_FALSE);
|
||||
nsIPresShell::SetCapturingContent(nsnull, 0);
|
||||
|
||||
*aEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
doDefault = PR_FALSE;
|
||||
@ -212,35 +197,6 @@ nsTitleBarFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTitleBarFrame::CaptureMouseEvents(nsPresContext* aPresContext,PRBool aGrabMouseEvents)
|
||||
{
|
||||
// get its view
|
||||
nsIView* view = GetView();
|
||||
PRBool result;
|
||||
|
||||
if (view) {
|
||||
nsIViewManager* viewMan = view->GetViewManager();
|
||||
if (viewMan) {
|
||||
// nsIWidget* widget = view->GetWidget();
|
||||
if (aGrabMouseEvents) {
|
||||
viewMan->GrabMouseEvents(view,result);
|
||||
//mIsCapturingMouseEvents = PR_TRUE;
|
||||
//widget->CaptureMouse(PR_TRUE);
|
||||
} else {
|
||||
viewMan->GrabMouseEvents(nsnull,result);
|
||||
//mIsCapturingMouseEvents = PR_FALSE;
|
||||
//widget->CaptureMouse(PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
nsTitleBarFrame::MouseClicked(nsPresContext* aPresContext, nsGUIEvent* aEvent)
|
||||
{
|
||||
|
@ -49,10 +49,6 @@ public:
|
||||
|
||||
nsTitleBarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
|
||||
|
||||
NS_IMETHOD Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIFrame* asPrevInFlow);
|
||||
|
||||
NS_IMETHOD BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
@ -65,10 +61,6 @@ public:
|
||||
|
||||
virtual void MouseClicked(nsPresContext* aPresContext, nsGUIEvent* aEvent);
|
||||
|
||||
protected:
|
||||
|
||||
NS_IMETHOD CaptureMouseEvents(nsPresContext* aPresContext,PRBool aGrabMouseEvents);
|
||||
|
||||
protected:
|
||||
PRBool mTrackingMouseMove;
|
||||
nsIntPoint mLastPoint;
|
||||
|
@ -2101,7 +2101,7 @@ nsXULMenuCommandEvent::Run()
|
||||
if (mCloseMenuMode != CloseMenuMode_None)
|
||||
menuFrame->SelectMenu(PR_FALSE);
|
||||
|
||||
nsAutoHandlingUserInputStatePusher userInpStatePusher(mUserInput);
|
||||
nsAutoHandlingUserInputStatePusher userInpStatePusher(mUserInput, PR_FALSE);
|
||||
nsContentUtils::DispatchXULCommand(mMenu, mIsTrusted, nsnull, shell,
|
||||
mControl, mAlt, mShift, mMeta);
|
||||
}
|
||||
|
@ -103,6 +103,7 @@ _TEST_FILES = test_bug360220.xul \
|
||||
test_position.xul \
|
||||
test_menu.xul \
|
||||
test_menu_hide.xul \
|
||||
test_mousecapture.xul \
|
||||
test_focus.xul \
|
||||
test_focus_anons.xul \
|
||||
test_tabindex.xul \
|
||||
|
191
toolkit/content/tests/widgets/test_mousecapture.xul
Normal file
191
toolkit/content/tests/widgets/test_mousecapture.xul
Normal file
@ -0,0 +1,191 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>
|
||||
|
||||
<window title="Mouse Capture Tests" align="start"
|
||||
onload="setTimeout(runTests, 0);"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script>
|
||||
<![CDATA[
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var captureRetargetMode = false;
|
||||
var cachedMouseDown = null;
|
||||
var previousWidth = 0, originalWidth = 0;
|
||||
|
||||
function splitterCallback(adjustment)
|
||||
{
|
||||
var newWidth = Number($("leftbox").width); // getBoundingClientRect().width;
|
||||
var expectedWidth = previousWidth + adjustment;
|
||||
if (expectedWidth > $("splitterbox").getBoundingClientRect().width)
|
||||
expectedWidth = $("splitterbox").getBoundingClientRect().width - $("splitter").getBoundingClientRect().width;
|
||||
is(newWidth, expectedWidth, "splitter left box size (" + adjustment + ")");
|
||||
previousWidth = newWidth;
|
||||
}
|
||||
|
||||
function selectionCallback(adjustment)
|
||||
{
|
||||
if (adjustment == 4000) {
|
||||
is(frames[0].getSelection().toString(), "This is some text", "selection after drag (" + adjustment + ")");
|
||||
ok(frames[0].scrollY > 40, "selection caused scroll down (" + adjustment + ")");
|
||||
}
|
||||
else {
|
||||
if (adjustment == 0) {
|
||||
is(frames[0].getSelection().toString(), ".", "selection after drag (" + adjustment + ")");
|
||||
}
|
||||
is(frames[0].scrollY, 0, "selection scrollY (" + adjustment + ")");
|
||||
}
|
||||
}
|
||||
|
||||
function framesetCallback(adjustment)
|
||||
{
|
||||
var newWidth = frames[1].frames[0].document.documentElement.clientWidth;
|
||||
var expectedWidth = originalWidth + adjustment;
|
||||
if (adjustment == 0)
|
||||
expectedWidth = originalWidth - 12;
|
||||
else if (expectedWidth >= 4000)
|
||||
expectedWidth = originalWidth * 2 - 2;
|
||||
|
||||
is(newWidth, expectedWidth, "frameset after drag (" + adjustment + ")");
|
||||
}
|
||||
|
||||
function runTests()
|
||||
{
|
||||
previousWidth = $("leftbox").getBoundingClientRect().width;
|
||||
runCaptureTest($("splitter"), splitterCallback);
|
||||
|
||||
var custom = document.getElementById("custom");
|
||||
runCaptureTest(custom);
|
||||
|
||||
synthesizeMouseExpectEvent($("rightbox"), 2, 2, { type: "mousemove" },
|
||||
$("rightbox"), "mousemove", "setCapture and releaseCapture");
|
||||
|
||||
custom.setCapture();
|
||||
synthesizeMouseExpectEvent($("leftbox"), 2, 2, { type: "mousemove" },
|
||||
$("leftbox"), "mousemove", "setCapture fails on non mousedown");
|
||||
|
||||
var custom2 = document.getElementById("custom2");
|
||||
synthesizeMouse(custom2, 2, 2, { type: "mousedown" });
|
||||
synthesizeMouseExpectEvent($("leftbox"), 2, 2, { type: "mousemove" },
|
||||
$("leftbox"), "mousemove", "document.releaseCapture releases capture");
|
||||
|
||||
var custom3 = document.getElementById("custom3");
|
||||
synthesizeMouse(custom3, 2, 2, { type: "mousedown" });
|
||||
synthesizeMouseExpectEvent($("leftbox"), 2, 2, { type: "mousemove" },
|
||||
$("leftbox"), "mousemove", "element.releaseCapture releases capture");
|
||||
|
||||
var custom4 = document.getElementById("custom4");
|
||||
synthesizeMouse(custom4, 2, 2, { type: "mousedown" });
|
||||
synthesizeMouseExpectEvent($("leftbox"), 2, 2, { type: "mousemove" },
|
||||
custom4, "mousemove", "element.releaseCapture during mousemove before releaseCapture");
|
||||
synthesizeMouseExpectEvent($("leftbox"), 2, 2, { type: "mousemove" },
|
||||
$("leftbox"), "mousemove", "element.releaseCapture during mousemove after releaseCapture");
|
||||
|
||||
var custom5 = document.getElementById("custom5");
|
||||
runCaptureTest(custom5);
|
||||
captureRetargetMode = true;
|
||||
runCaptureTest(custom5);
|
||||
captureRetargetMode = false;
|
||||
|
||||
var b = frames[0].document.getElementById("b");
|
||||
runCaptureTest(b, selectionCallback);
|
||||
|
||||
previousWidth = frames[1].frames[0].document.documentElement.clientWidth;
|
||||
originalWidth = previousWidth;
|
||||
runCaptureTest(frames[1].document.documentElement.lastChild, framesetCallback);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function runCaptureTest(element, callback)
|
||||
{
|
||||
var expectedTarget = null;
|
||||
|
||||
var win = element.ownerDocument.defaultView;
|
||||
|
||||
function mouseMoved(event) {
|
||||
is(event.originalTarget, expectedTarget,
|
||||
expectedTarget.id + " target for point " + event.clientX + "," + event.clientY);
|
||||
}
|
||||
win.addEventListener("mousemove", mouseMoved, false);
|
||||
|
||||
expectedTarget = element;
|
||||
|
||||
var basepoint = element.localName == "frameset" ? 50 : 2;
|
||||
synthesizeMouse(element, basepoint, basepoint, { type: "mousedown" }, win);
|
||||
|
||||
// in setCapture(true) mode, all events should fire on custom5. In
|
||||
// setCapture(false) mode, events can fire at a descendant
|
||||
if (expectedTarget == $("custom5") && !captureRetargetMode)
|
||||
expectedTarget = $("custom5spacer");
|
||||
|
||||
// releaseCapture should do nothing for an element which isn't capturing
|
||||
$("splitterbox").releaseCapture();
|
||||
|
||||
synthesizeMouse(element, basepoint + 2, basepoint + 2, { type: "mousemove" }, win);
|
||||
if (callback)
|
||||
callback(2);
|
||||
|
||||
if (expectedTarget == $("custom5spacer") && !captureRetargetMode)
|
||||
expectedTarget = $("custom5inner");
|
||||
|
||||
synthesizeMouse(element, basepoint + 25, basepoint + 25, { type: "mousemove" }, win);
|
||||
if (callback)
|
||||
callback(25);
|
||||
|
||||
expectedTarget = element.localName == "b" ? win.document.documentElement : element;
|
||||
synthesizeMouse(element, basepoint + 4000, basepoint + 4000, { type: "mousemove" }, win);
|
||||
if (callback)
|
||||
callback(4000);
|
||||
synthesizeMouse(element, basepoint - 12, basepoint - 12, { type: "mousemove" }, win);
|
||||
if (callback)
|
||||
callback(-12);
|
||||
|
||||
expectedTarget = element.localName == "frameset" ? element : win.document.documentElement;
|
||||
synthesizeMouse(element, basepoint + 30, basepoint + 30, { type: "mouseup" }, win);
|
||||
synthesizeMouse(win.document.documentElement, 2, 2, { type: "mousemove" }, win);
|
||||
if (callback)
|
||||
callback(0);
|
||||
|
||||
win.removeEventListener("mousemove", mouseMoved, false);
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<hbox id="splitterbox" style="margin-top: 5px;" onmousedown="this.setCapture()">
|
||||
<hbox id="leftbox" width="100" flex="1"/>
|
||||
<splitter id="splitter" height="5"/>
|
||||
<hbox id="rightbox" width="100" flex="1"/>
|
||||
</hbox>
|
||||
|
||||
<vbox id="custom" width="10" height="10" onmousedown="this.setCapture(); cachedMouseDown = event;"/>
|
||||
<vbox id="custom2" width="10" height="10" onmousedown="this.setCapture(); document.releaseCapture();"/>
|
||||
<vbox id="custom3" width="10" height="10" onmousedown="this.setCapture(); this.releaseCapture();"/>
|
||||
<vbox id="custom4" width="10" height="10" onmousedown="this.setCapture();"
|
||||
onmousemove="this.releaseCapture();"/>
|
||||
<hbox id="custom5" width="40" height="40"
|
||||
onmousedown="this.setCapture(captureRetargetMode);">
|
||||
<spacer id="custom5spacer" width="5"/>
|
||||
<hbox id="custom5inner" width="35" height="35"/>
|
||||
</hbox>
|
||||
|
||||
<hbox>
|
||||
<iframe width="100" height="100"
|
||||
src="data:text/html,%3Cbody style%3D'font-size%3A 40pt%3B'%3E.%3Cb id%3D'b'%3EThis%3C/b%3E is some text%3C/body%3E"/>
|
||||
|
||||
<iframe width="100" height="100"
|
||||
src="data:text/html,%3Cframeset cols='50%, 50%'%3E%3Cframe src='about:blank'%3E%3Cframe src='about:blank'%3E%3C/frameset%3E"/>
|
||||
</hbox>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display"/><div id="content" style="display: none"/><pre id="test"/>
|
||||
</body>
|
||||
|
||||
</window>
|
@ -212,6 +212,30 @@ function testtag_scale_UI_Mouse(element, testid, horiz, reverse, pinc)
|
||||
is(element.value, endval, testid + " mouse on right movetoclick=false");
|
||||
|
||||
element.removeAttribute("movetoclick");
|
||||
|
||||
element.value = reverse ? element.max : element.min;
|
||||
|
||||
synthesizeMouse(element, 8, 8, { type: "mousedown" });
|
||||
synthesizeMouse(element, horiz ? 2000 : 8, horiz ? 8 : 2000, { type: "mousemove" });
|
||||
is(element.value, reverse ? element.min : element.max, testid + " move mouse too far after end");
|
||||
synthesizeMouse(element, 2, 2, { type: "mouseup" });
|
||||
|
||||
synthesizeMouse(element, rect.width - 8, rect.height - 8, { type: "mousedown" });
|
||||
synthesizeMouse(element, horiz ? -2000 : rect.width - 8, horiz ? rect.height - 8 : -2000, { type: "mousemove" });
|
||||
is(element.value, reverse ? element.max : element.min, testid + " move mouse too far before start");
|
||||
|
||||
synthesizeMouse(element, 2, 2, { type: "mouseup" });
|
||||
|
||||
// now check if moving outside in both directions works. On Windows,
|
||||
// it should snap back to the original location.
|
||||
element.value = reverse ? element.max : element.min;
|
||||
|
||||
var expected = (navigator.platform.indexOf("Win") >= 0) ? element.value :
|
||||
(reverse ? element.min : element.max);
|
||||
synthesizeMouse(element, 7, 7, { type: "mousedown" });
|
||||
synthesizeMouse(element, 2000, 2000, { type: "mousemove" });
|
||||
is(element.value, expected, testid + " move mouse ouside in both directions");
|
||||
synthesizeMouse(element, 2, 2, { type: "mouseup" });
|
||||
}
|
||||
|
||||
function testtag_scale_States(element, evalue, evalueattr, emin, emax, testid)
|
||||
|
@ -60,8 +60,8 @@ enum nsRectVisibility {
|
||||
};
|
||||
|
||||
#define NS_IVIEWMANAGER_IID \
|
||||
{ 0x739bbc2b, 0x5c45, 0x40bb, \
|
||||
{ 0xb0, 0xbc, 0xe3, 0x1c, 0xe0, 0xf2, 0x19, 0xc2 } }
|
||||
{ 0xe1f3095c, 0x65cd, 0x46e1, \
|
||||
{ 0x9d, 0x70, 0x88, 0xcf, 0x54, 0x19, 0x9d, 0x05 } }
|
||||
|
||||
class nsIViewManager : public nsISupports
|
||||
{
|
||||
@ -187,21 +187,6 @@ public:
|
||||
NS_IMETHOD DispatchEvent(nsGUIEvent *aEvent,
|
||||
nsIView* aViewTarget, nsEventStatus* aStatus) = 0;
|
||||
|
||||
/**
|
||||
* Used to grab/capture all mouse events for a specific view,
|
||||
* irrespective of the cursor position at which the
|
||||
* event occurred.
|
||||
* @param aView view to capture mouse events
|
||||
* @result event handling status
|
||||
*/
|
||||
NS_IMETHOD GrabMouseEvents(nsIView *aView, PRBool& aResult) = 0;
|
||||
|
||||
/**
|
||||
* Get the current view, if any, that's capturing mouse events.
|
||||
* @result view that is capturing mouse events or nsnull
|
||||
*/
|
||||
NS_IMETHOD GetMouseEventGrabber(nsIView *&aView) = 0;
|
||||
|
||||
/**
|
||||
* Given a parent view, insert another view as its child.
|
||||
* aSibling and aAbove control the "document order" for the insertion.
|
||||
|
@ -46,10 +46,10 @@
|
||||
class nsIRenderingContext;
|
||||
class nsGUIEvent;
|
||||
|
||||
// 52b3b616-23a9-4516-a8d3-452b4126eb2b
|
||||
// 8D7AE493-1EB1-4D38-89DA-9EEEAA29FD79
|
||||
#define NS_IVIEWOBSERVER_IID \
|
||||
{ 0x52b3b616, 0x23a9, 0x4516, \
|
||||
{ 0xa8, 0xd3, 0x45, 0x2b, 0x41, 0x26, 0xeb, 0x2b } }
|
||||
{ 0x8d7ae493, 0x1eb1, 0x4d38, \
|
||||
{ 0x89, 0xda, 0x9e, 0xee, 0xaa, 0x29, 0xfd, 0x79 } }
|
||||
|
||||
class nsIViewObserver : public nsISupports
|
||||
{
|
||||
@ -150,6 +150,13 @@ public:
|
||||
*/
|
||||
NS_IMETHOD_(void) DispatchSynthMouseMove(nsGUIEvent *aEvent,
|
||||
PRBool aFlushOnHoverChange) = 0;
|
||||
|
||||
/**
|
||||
* If something within aView is capturing the mouse, clear the capture.
|
||||
* if aView is null, clear the mouse capture no matter what is capturing it.
|
||||
*/
|
||||
NS_IMETHOD_(void) ClearMouseCapture(nsIView* aView) = 0;
|
||||
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIViewObserver, NS_IVIEWOBSERVER_IID)
|
||||
|
@ -185,13 +185,11 @@ nsView::nsView(nsViewManager* aViewManager, nsViewVisibility aVisibility)
|
||||
mDeletionObserver = nsnull;
|
||||
}
|
||||
|
||||
void nsView::DropMouseGrabbing() {
|
||||
// check to see if we are grabbing events
|
||||
if (mViewManager->GetMouseEventGrabber() == this) {
|
||||
// we are grabbing events. Move the grab to the parent if we can.
|
||||
PRBool boolResult; //not used
|
||||
// if GetParent() returns null, then we release the grab, which is the best we can do
|
||||
mViewManager->GrabMouseEvents(GetParent(), boolResult);
|
||||
void nsView::DropMouseGrabbing()
|
||||
{
|
||||
nsCOMPtr<nsIViewObserver> viewObserver = mViewManager->GetViewObserver();
|
||||
if (viewObserver) {
|
||||
viewObserver->ClearMouseCapture(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,15 +493,6 @@ NS_IMETHODIMP nsView::SetFloating(PRBool aFloatingView)
|
||||
|
||||
void nsView::InvalidateHierarchy(nsViewManager *aViewManagerParent)
|
||||
{
|
||||
if (aViewManagerParent) {
|
||||
// We're removed from the view hierarchy of aRemovalPoint, so make sure
|
||||
// we're not still grabbing mouse events.
|
||||
if (aViewManagerParent->GetMouseEventGrabber() == this) {
|
||||
PRBool res;
|
||||
aViewManagerParent->GrabMouseEvents(nsnull, res);
|
||||
}
|
||||
}
|
||||
|
||||
if (mViewManager->GetRootView() == this)
|
||||
mViewManager->InvalidateHierarchy();
|
||||
|
||||
|
@ -263,8 +263,6 @@ NS_IMETHODIMP nsViewManager::Init(nsIDeviceContext* aContext)
|
||||
|
||||
mRefreshEnabled = PR_TRUE;
|
||||
|
||||
mMouseGrabber = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1077,31 +1075,24 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
|
||||
}
|
||||
|
||||
if (aEvent->message == NS_DEACTIVATE) {
|
||||
PRBool result;
|
||||
GrabMouseEvents(nsnull, result);
|
||||
// if a window is deactivated, clear the mouse capture regardless
|
||||
// of what is capturing
|
||||
nsIViewObserver* viewObserver = GetViewObserver();
|
||||
if (viewObserver) {
|
||||
viewObserver->ClearMouseCapture(nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
//Find the view whose coordinates system we're in.
|
||||
nsView* baseView = static_cast<nsView*>(aView);
|
||||
nsView* view = baseView;
|
||||
PRBool capturedEvent = PR_FALSE;
|
||||
|
||||
|
||||
if (NS_IsEventUsingCoordinates(aEvent)) {
|
||||
// will dispatch using coordinates. Pretty bogus but it's consistent
|
||||
// with what presshell does.
|
||||
view = GetDisplayRootFor(baseView);
|
||||
}
|
||||
|
||||
//Find the view to which we're initially going to send the event
|
||||
//for hittesting.
|
||||
if (NS_IS_MOUSE_EVENT(aEvent) || NS_IS_DRAG_EVENT(aEvent)) {
|
||||
nsView* mouseGrabber = GetMouseEventGrabber();
|
||||
if (mouseGrabber) {
|
||||
view = mouseGrabber;
|
||||
capturedEvent = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (nsnull != view) {
|
||||
PRInt32 p2a = mContext->AppUnitsPerDevPixel();
|
||||
|
||||
@ -1171,7 +1162,7 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
|
||||
NSFloatPixelsToAppUnits(float(aEvent->refPoint.y) + 0.5f, p2a);
|
||||
pt += offset;
|
||||
|
||||
*aStatus = HandleEvent(view, pt, aEvent, capturedEvent);
|
||||
*aStatus = HandleEvent(view, pt, aEvent);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -1182,7 +1173,7 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
|
||||
}
|
||||
|
||||
nsEventStatus nsViewManager::HandleEvent(nsView* aView, nsPoint aPoint,
|
||||
nsGUIEvent* aEvent, PRBool aCaptured) {
|
||||
nsGUIEvent* aEvent) {
|
||||
//printf(" %d %d %d %d (%d,%d) \n", this, event->widget, event->widgetSupports,
|
||||
// event->message, event->point.x, event->point.y);
|
||||
|
||||
@ -1198,37 +1189,6 @@ nsEventStatus nsViewManager::HandleEvent(nsView* aView, nsPoint aPoint,
|
||||
return status;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsViewManager::GrabMouseEvents(nsIView *aView, PRBool &aResult)
|
||||
{
|
||||
if (!IsRootVM()) {
|
||||
return RootViewManager()->GrabMouseEvents(aView, aResult);
|
||||
}
|
||||
|
||||
// Along with nsView::SetVisibility, we enforce that the mouse grabber
|
||||
// can never be a hidden view.
|
||||
if (aView && !static_cast<nsView*>(aView)->IsEffectivelyVisible()) {
|
||||
aView = nsnull;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_mjudge
|
||||
if (aView)
|
||||
{
|
||||
printf("capturing mouse events for view %x\n",aView);
|
||||
}
|
||||
printf("removing mouse capture from view %x\n",mMouseGrabber);
|
||||
#endif
|
||||
|
||||
mMouseGrabber = static_cast<nsView*>(aView);
|
||||
aResult = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsViewManager::GetMouseEventGrabber(nsIView *&aView)
|
||||
{
|
||||
aView = GetMouseEventGrabber();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Recursively reparent widgets if necessary
|
||||
|
||||
void nsViewManager::ReparentChildWidgets(nsIView* aView, nsIWidget *aNewWidget)
|
||||
|
@ -128,10 +128,6 @@ public:
|
||||
NS_IMETHOD DispatchEvent(nsGUIEvent *aEvent,
|
||||
nsIView* aTargetView, nsEventStatus* aStatus);
|
||||
|
||||
NS_IMETHOD GrabMouseEvents(nsIView *aView, PRBool &aResult);
|
||||
|
||||
NS_IMETHOD GetMouseEventGrabber(nsIView *&aView);
|
||||
|
||||
NS_IMETHOD InsertChild(nsIView *parent, nsIView *child, nsIView *sibling,
|
||||
PRBool above);
|
||||
|
||||
@ -305,14 +301,10 @@ private:
|
||||
|
||||
public: // NOT in nsIViewManager, so private to the view module
|
||||
nsView* GetRootView() const { return mRootView; }
|
||||
nsView* GetMouseEventGrabber() const {
|
||||
return RootViewManager()->mMouseGrabber;
|
||||
}
|
||||
nsViewManager* RootViewManager() const { return mRootViewManager; }
|
||||
PRBool IsRootVM() const { return this == RootViewManager(); }
|
||||
|
||||
nsEventStatus HandleEvent(nsView* aView, nsPoint aPoint, nsGUIEvent* aEvent,
|
||||
PRBool aCaptured);
|
||||
nsEventStatus HandleEvent(nsView* aView, nsPoint aPoint, nsGUIEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Called to inform the view manager that a view is about to bit-blit.
|
||||
@ -390,8 +382,6 @@ private:
|
||||
// the root view manager. Some have accessor functions to enforce
|
||||
// this, as noted.
|
||||
|
||||
// Use GrabMouseEvents() and GetMouseEventGrabber() to access mMouseGrabber.
|
||||
nsView *mMouseGrabber;
|
||||
// Use IncrementUpdateCount(), DecrementUpdateCount(), UpdateCount(),
|
||||
// ClearUpdateCount() on the root viewmanager to access mUpdateCnt.
|
||||
PRInt32 mUpdateCnt;
|
||||
|
@ -227,20 +227,12 @@ nsBaseDragService::InvokeDragSession(nsIDOMNode *aDOMNode,
|
||||
// When the mouse goes down, the selection code starts a mouse
|
||||
// capture. However, this gets in the way of determining drag
|
||||
// feedback for things like trees because the event coordinates
|
||||
// are in the wrong coord system. Turn off mouse capture in
|
||||
// the associated view manager.
|
||||
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(aDOMNode);
|
||||
if (contentNode) {
|
||||
nsIDocument* doc = contentNode->GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsIPresShell* presShell = doc->GetPrimaryShell();
|
||||
if (presShell) {
|
||||
nsIViewManager* vm = presShell->GetViewManager();
|
||||
if (vm) {
|
||||
PRBool notUsed;
|
||||
vm->GrabMouseEvents(nsnull, notUsed);
|
||||
}
|
||||
}
|
||||
// are in the wrong coord system, so turn off mouse capture.
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mSourceDocument);
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIViewObserver> viewObserver = do_QueryInterface(doc->GetPrimaryShell());
|
||||
if (viewObserver) {
|
||||
viewObserver->ClearMouseCapture(nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user