--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2768,16 +2768,28 @@ nsDocument::MatchClassNames(nsIContent*
// static
void
nsDocument::DestroyClassNameArray(void* aData)
{
ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(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)
{
nsresult rv = NS_OK;
if (aURI) {
rv = nsContentUtils::GetSecurityManager()->
CheckLoadURIWithPrincipal(NodePrincipal(), aURI,
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1079,16 +1079,39 @@ nsNSElementTearoff::GetClassList(nsIDOMD
NS_ENSURE_TRUE(slots->mClassList, NS_ERROR_OUT_OF_MEMORY);
}
NS_ADDREF(*aResult = slots->mClassList);
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;
+}
+
//----------------------------------------------------------------------
NS_IMPL_CYCLE_COLLECTION_1(nsNSElementTearoff, mContent)
NS_INTERFACE_MAP_BEGIN(nsNSElementTearoff)
NS_INTERFACE_MAP_ENTRY(nsIDOMNSElement)
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsNSElementTearoff)
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -2736,29 +2736,19 @@ nsEventStateManager::PostHandleEvent(nsP
nsRefPtr<nsPresContext> presContext = aPresContext;
nsresult ret = NS_OK;
switch (aEvent->message) {
case NS_MOUSE_BUTTON_DOWN:
{
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;
}
if (nsEventStatus_eConsumeNoDefault != *aStatus) {
nsCOMPtr<nsIContent> newFocus;
nsIContent* activeContent = nsnull;
PRBool suppressBlur = PR_FALSE;
if (mCurrentTarget) {
@@ -2853,27 +2843,19 @@ nsEventStateManager::PostHandleEvent(nsP
if (!mCurrentTarget) {
nsIFrame* targ;
GetEventTarget(&targ);
}
if (mCurrentTarget) {
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);
}
}
break;
case NS_MOUSE_SCROLL:
case NS_MOUSE_PIXEL_SCROLL:
{
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -406,37 +406,48 @@ protected:
static void sClickHoldCallback ( nsITimer* aTimer, void* aESM ) ;
nsCOMPtr<nsITimer> mClickHoldTimer;
#endif
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);
+ }
}
}
~nsAutoHandlingUserInputStatePusher()
{
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
static void* operator new(size_t /*size*/) CPP_THROW_NEW { return nsnull; }
static void operator delete(void* /*memory*/) {}
};
#endif // nsEventStateManager_h__
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -1134,17 +1134,17 @@ nsHTMLFormElement::SubmitSubmission(nsIF
//
// Submit
//
nsCOMPtr<nsIDocShell> docShell;
{
nsAutoPopupStatePusher popupStatePusher(mSubmitPopupState);
- nsAutoHandlingUserInputStatePusher userInpStatePusher(mSubmitInitiatedFromUserInput);
+ nsAutoHandlingUserInputStatePusher userInpStatePusher(mSubmitInitiatedFromUserInput, PR_FALSE);
rv = aFormSubmission->SubmitTo(actionURI, target, this, linkHandler,
getter_AddRefs(docShell),
getter_AddRefs(mSubmittingRequest));
}
NS_ENSURE_SUBMIT_SUCCESS(rv);
--- a/dom/interfaces/core/nsIDOMNSDocument.idl
+++ b/dom/interfaces/core/nsIDOMNSDocument.idl
@@ -38,17 +38,17 @@
*
* ***** END LICENSE BLOCK ***** */
#include "domstubs.idl"
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;
attribute DOMString dir;
readonly attribute nsIDOMLocation location;
attribute DOMString title;
@@ -86,9 +86,15 @@ interface nsIDOMNSDocument : nsISupports
*
* Callers from XUL documents should wait until the onload event has fired
* before calling this method.
*
* <a href="http://dev.w3.org/cvsweb/~checkout~/csswg/cssom/Overview.html?content-type=text/html;%20charset=utf-8#documentlayout-elementfrompoint">preliminary spec</a>
*/
nsIDOMElement elementFromPoint(in long x, in long y);
+ /**
+ * Release the current mouse capture if it is on an element within this
+ * document.
+ */
+ void releaseCapture();
+
};
--- a/dom/interfaces/core/nsIDOMNSElement.idl
+++ b/dom/interfaces/core/nsIDOMNSElement.idl
@@ -34,17 +34,17 @@
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "domstubs.idl"
-[scriptable, uuid(df86b1a8-02c3-47be-a76b-856620f925df)]
+[scriptable, uuid(FA8D7AF8-C208-4564-A0CD-346C345711F0)]
interface nsIDOMNSElement : nsISupports
{
/*
* Retrieve elements matching all classes listed in a
* space-separated string.
*
* See <http://whatwg.org/specs/web-apps/current-work/>
*/
@@ -147,9 +147,25 @@ interface nsIDOMNSElement : nsISupports
* Returns a live nsIDOMNodeList of the current child elements.
*/
readonly attribute nsIDOMNodeList children;
/**
* 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();
};
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -99,16 +99,33 @@ class gfxContext;
class nsPIDOMEventTarget;
class nsIDOMEvent;
class nsDisplayList;
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, \
{ 0xa5, 0x7b, 0xdc, 0x1a, 0x27, 0x04, 0xde, 0x87 } }
// Constants for ScrollContentIntoView() function
#define NS_PRESSHELL_SCROLL_TOP 0
#define NS_PRESSHELL_SCROLL_BOTTOM 100
@@ -852,16 +869,52 @@ public:
{
mObservesMutationsForPrint = aObserve;
}
PRBool ObservesNativeAnonMutationsForPrint()
{
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,
// please make the ownership explicit (pinkerton, scc).
// these are the same Document and PresContext owned by the DocViewer.
// we must share ownership.
nsIDocument* mDocument; // [STRONG]
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -203,16 +203,17 @@
#include "imgIEncoder.h"
#include "gfxPlatform.h"
#include "nsContentCID.h"
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
static void ColorToString(nscolor aColor, nsAutoString &aString);
// Class ID's
static NS_DEFINE_CID(kFrameSelectionCID, NS_FRAMESELECTION_CID);
@@ -792,16 +793,17 @@ public:
nsIDOMEvent* aEvent,
nsEventStatus* aStatus);
NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight);
NS_IMETHOD_(PRBool) IsVisible();
NS_IMETHOD_(void) WillPaint();
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);
NS_IMETHOD_(void) MaybeInvalidateCaretPosition();
NS_IMETHOD SetCaretEnabled(PRBool aInEnable);
NS_IMETHOD SetCaretReadOnly(PRBool aReadOnly);
NS_IMETHOD GetCaretEnabled(PRBool *aOutEnabled);
NS_IMETHOD SetCaretVisibilityDuringSelection(PRBool aVisibility);
@@ -4372,16 +4374,51 @@ PresShell::DispatchSynthMouseMove(nsGUIE
if (aFlushOnHoverChange &&
hoverGenerationBefore != mFrameConstructor->GetHoverGeneration()) {
// Flush so that the resulting reflow happens now so that our caller
// can suppress any synthesized mouse moves caused by that reflow.
FlushPendingNotifications(Flush_Layout);
}
}
+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)
{
aOutValue.Truncate();
if (!mDocument) return NS_ERROR_FAILURE;
nsresult rv;
@@ -5696,16 +5733,32 @@ PresShell::PaintDefaultBackground(nsIVie
nscolor bgcolor = NS_ComposeColors(ComputeBackstopColor(aView),
mCanvasBackgroundColor);
aRenderingContext->SetColor(bgcolor);
aRenderingContext->FillRect(aDirtyRect);
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()
{
if (NS_UNLIKELY(mIsDestroying)) {
return nsnull;
}
if (!mCurrentEventFrame && mCurrentEventContent) {
@@ -5852,50 +5905,59 @@ PresShell::HandleEvent(nsIView *
#ifdef ACCESSIBILITY
if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT) {
// Accessibility events come through OS requests and not from scripts,
// so it is safe to handle here
return HandleEventInternal(aEvent, aView, aEventStatus);
}
#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;
-
- 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;
-
- nsCOMPtr<nsIDocument> doc(do_QueryInterface(piWindow->GetExtantDocument()));
- if (!doc)
- 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;
-
- nsIView *view;
- presShell->GetViewManager()->GetRootView(view);
- sDontRetargetEvents = PR_TRUE;
- nsresult rv = viewObserver->HandleEvent(view, aEvent, aEventStatus);
- sDontRetargetEvents = PR_FALSE;
- return rv;
+ if (!sDontRetargetEvents) {
+ if (NS_IsEventTargetedAtFocusedWindow(aEvent)) {
+ nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+ if (!fm)
+ return NS_ERROR_FAILURE;
+
+ 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;
+
+ 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();
+ }
+
+ if (retargetEventDoc) {
+ nsIPresShell* presShell = retargetEventDoc->GetPrimaryShell();
+ if (!presShell)
+ return NS_OK;
+
+ 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;
+ }
}
}
// Check for a theme change up front, since the frame type is irrelevant
if (aEvent->message == NS_THEMECHANGED && mPresContext) {
mPresContext->ThemeChanged();
return NS_OK;
}
@@ -5936,18 +5998,51 @@ PresShell::HandleEvent(nsIView *
}
}
if (event && !mDelayedEvents.AppendElement(event)) {
delete event;
}
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
// view that has a frame.
if (!frame &&
(dispatchUsingCoordinates || NS_IS_KEY_EVENT(aEvent) ||
NS_IS_IME_EVENT(aEvent))) {
nsIView* targetView = aView;
@@ -5990,27 +6085,29 @@ PresShell::HandleEvent(nsIView *
frame = popup;
break;
}
}
}
#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) {
PresShell* shell =
static_cast<PresShell*>(targetFrame->PresContext()->PresShell());
if (shell != this) {
// Handle the event in the correct shell.
// Prevent deletion until we're done with event handling (bug 336582).
@@ -6280,17 +6377,18 @@ PresShell::HandleEventInternal(nsEvent*
return NS_OK;
}
if (me->context == nsMouseEvent::eContextMenuKey &&
!AdjustContextMenuKeyEvent(me)) {
return NS_OK;
}
}
- nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput);
+ nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput,
+ aEvent->message == NS_MOUSE_BUTTON_DOWN);
nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
// FIXME. If the event was reused, we need to clear the old target,
// bug 329430
aEvent->target = nsnull;
nsWeakView weakView(aView);
@@ -6326,16 +6424,21 @@ PresShell::HandleEventInternal(nsEvent*
// 3. Give event to event manager for post event state changes and
// generation of synthetic events.
if (!mIsDestroying && NS_SUCCEEDED(rv)) {
rv = manager->PostHandleEvent(mPresContext, aEvent,
GetCurrentEventFrame(), aStatus,
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;
}
// Dispatch event to content only (NOT full processing)
// See also HandleEventWithTarget which does full event processing.
NS_IMETHODIMP
PresShell::HandleDOMEventWithTarget(nsIContent* aTargetContent, nsEvent* aEvent,
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -1028,38 +1028,33 @@ nsListControlFrame::CaptureMouseEvents(P
return;
nsIView* view = GetScrolledFrame()->GetView();
NS_ASSERTION(view, "no view???");
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);
}
}
}
//---------------------------------------------------------
NS_IMETHODIMP
nsListControlFrame::HandleEvent(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
@@ -2117,21 +2112,17 @@ nsListControlFrame::FireMenuItemActiveEv
nsresult
nsListControlFrame::GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent,
PRInt32& aCurIndex)
{
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();
if (!borderInnerEdge.Contains(pt)) {
return NS_ERROR_FAILURE;
}
}
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -50,16 +50,17 @@
#include "nsIContent.h"
#include "nsContentUtils.h"
#include "nsIAtom.h"
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsStyleContext.h"
#include "nsIView.h"
#include "nsIViewManager.h"
+#include "nsIScrollableView.h"
#include "nsIScrollableFrame.h"
#include "nsPresContext.h"
#include "nsCRT.h"
#include "nsGUIEvent.h"
#include "nsIDOMEvent.h"
#include "nsPLDOMEvent.h"
#include "nsStyleConsts.h"
#include "nsIPresShell.h"
@@ -738,28 +739,27 @@ nsFrame::GetAdditionalChildListName(PRIn
nsFrameList
nsFrame::GetChildList(nsIAtom* aListName) const
{
return nsFrameList::EmptyList();
}
static nsIFrame*
-GetActiveSelectionFrame(nsIFrame* aFrame)
-{
- nsIView* mouseGrabber;
- aFrame->PresContext()->GetPresShell()->
- GetViewManager()->GetMouseEventGrabber(mouseGrabber);
- if (mouseGrabber) {
- nsIFrame* activeFrame = nsLayoutUtils::GetFrameFor(mouseGrabber);
- if (activeFrame) {
- return activeFrame;
+GetActiveSelectionFrame(nsPresContext* aPresContext, nsIFrame* aFrame)
+{
+ nsIPresShell* shell = aPresContext->GetPresShell();
+ if (shell) {
+ nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
+ if (capturingContent) {
+ nsIFrame* activeFrame = shell->GetPrimaryFrameFor(capturingContent);
+ return activeFrame ? activeFrame : aFrame;
}
}
-
+
return aFrame;
}
PRInt16
nsFrame::DisplaySelection(nsPresContext* aPresContext, PRBool isOkToTurnOn)
{
PRInt16 selType = nsISelectionController::SELECTION_OFF;
@@ -1902,18 +1902,33 @@ nsFrame::HandlePress(nsPresContext* aPre
// check for select: none
if (!selectable)
return NS_OK;
// When implementing NS_STYLE_USER_SELECT_ELEMENT, NS_STYLE_USER_SELECT_ELEMENTS and
// 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
const nsFrameSelection* frameselection = nsnull;
if (useFrameSelection)
frameselection = GetConstFrameSelection();
else
frameselection = shell->ConstFrameSelection();
@@ -2178,39 +2193,16 @@ nsFrame::PeekBackwardAndForward(nsSelect
nsFrameSelection::HINTLEFT);
if (NS_FAILED(rv))
return rv;
// maintain selection
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)
{
PRBool selectable;
PRUint8 selectStyle;
IsSelectable(&selectable, &selectStyle);
// XXX Do we really need to exclude non-selectable content here?
@@ -2225,23 +2217,16 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPres
nsCOMPtr<nsFrameSelection> frameselection = GetFrameSelection();
PRBool mouseDown = frameselection->GetMouseDownState();
if (!mouseDown)
return NS_OK;
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;
PRInt32 target;
nsMouseEvent *me = (nsMouseEvent *)aEvent;
nsresult result;
result = GetDataForTableSelection(frameselection, presShell, me,
getter_AddRefs(parentContent),
@@ -2249,32 +2234,39 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPres
if (NS_SUCCEEDED(result) && parentContent) {
frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
} else {
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
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;
}
/**
* This static method handles part of the nsFrame::HandleRelease in a way
* which doesn't rely on the nsFrame object to stay alive.
*/
static nsresult
@@ -2337,21 +2329,21 @@ HandleFrameSelection(nsFrameSelection*
return NS_OK;
}
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);
nsRefPtr<nsFrameSelection> frameselection;
ContentOffsets offsets;
nsCOMPtr<nsIContent> parentContent;
PRInt32 contentOffsetForTableSel = 0;
@@ -5926,61 +5918,16 @@ nsFrame::GetFirstLeaf(nsPresContext* aPr
while (1){
child = child->GetFirstChild(nsnull);
if (!child)
return;//nothing to do
*aFrame = child;
}
}
-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,
NSPropertyDtorFunc aPropDtorFunc,
void* aDtorData)
{
return PresContext()->PropertyTable()->
SetProperty(this, aPropName, aPropValue, aPropDtorFunc, aDtorData);
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -210,24 +210,16 @@ public:
static nsresult GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
nsPeekOffsetStruct *aPos,
nsIFrame *aBlockFrame,
PRInt32 aLineStart,
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,
PRInt32 aModType);
virtual nsSplittableType GetSplittableType() const;
virtual nsIFrame* GetPrevContinuation() const;
NS_IMETHOD SetPrevContinuation(nsIFrame*);
virtual nsIFrame* GetNextContinuation() const;
@@ -410,20 +402,16 @@ public:
nsIFrame** aProviderFrame,
PRBool* aIsChild);
// incorporate the child overflow area into the parent overflow area
// if the child does not have a overflow use the child area
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;
#ifdef NS_DEBUG
/**
* Tracing method that writes a method enter/exit routine to the
* nspr log using the nsIFrame log module. The tracing is only
* done when the NS_FRAME_TRACE_CALLS bit is set in the log module's
--- a/layout/generic/nsFrameSetFrame.cpp
+++ b/layout/generic/nsFrameSetFrame.cpp
@@ -313,29 +313,16 @@ nsHTMLFramesetFrame::Init(nsIContent*
} else {
break;
}
}
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();
// Get the rows= cols= data
nsCOMPtr<nsIFrameSetElement> ourContent(do_QueryInterface(mContent));
NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
const nsFramesetSpec* rowSpecs = nsnull;
@@ -810,38 +797,16 @@ NS_METHOD nsHTMLFramesetFrame::HandleEve
}
*aEventStatus = nsEventStatus_eConsumeNoDefault;
} else {
*aEventStatus = nsEventStatus_eIgnore;
}
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)
{
if (mDragger) {
aCursor.mCursor = (mDragger->mVertical) ? NS_STYLE_CURSOR_EW_RESIZE : NS_STYLE_CURSOR_NS_RESIZE;
} else {
aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT;
@@ -1476,38 +1441,33 @@ nsHTMLFramesetFrame::StartMouseDrag(nsPr
nsHTMLFramesetBorderFrame* aBorder,
nsGUIEvent* aEvent)
{
#if 0
PRInt32 index;
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;
+
+ nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
- mFirstDragPoint = aEvent->refPoint;
+ mDragger = aBorder;
+
+ 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];
- }
+ // 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;
- }
- }
+ gDragInProgress = PR_TRUE;
}
void
nsHTMLFramesetFrame::MouseDrag(nsPresContext* aPresContext,
nsGUIEvent* aEvent)
{
PRInt32 change; // measured positive from left-to-right or top-to-bottom
@@ -1578,27 +1538,20 @@ nsHTMLFramesetFrame::MouseDrag(nsPresCon
}
}
}
}
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)
{
#ifdef DEBUG
const nsStyleDisplay* disp = aContext->GetStyleDisplay();
NS_ASSERTION(!disp->IsAbsolutelyPositioned() && !disp->IsFloating(),
"Framesets should not be positioned and should not float");
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -305,20 +305,16 @@ public:
virtual nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const {
return mInner.GetParentViewForChildFrame(aFrame);
}
virtual nsIFrame* GetContentInsertionFrame() {
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);
virtual PRBool NeedsView() { return PR_TRUE; }
virtual PRBool DoesClipChildren() { return PR_TRUE; }
virtual nsSplittableType GetSplittableType() const;
@@ -473,20 +469,16 @@ public:
virtual nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const {
return mInner.GetParentViewForChildFrame(aFrame);
}
virtual nsIFrame* GetContentInsertionFrame() {
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);
virtual PRBool NeedsView() { return PR_TRUE; }
virtual PRBool DoesClipChildren() { return PR_TRUE; }
virtual nsSplittableType GetSplittableType() const;
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -102,19 +102,20 @@ struct nsPeekOffsetStruct;
struct nsPoint;
struct nsRect;
struct nsSize;
struct nsMargin;
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
* of floats, and when pulling up child frames from a next-in-flow.
*
* The choices are splittable, not splittable at all, and splittable in
* a non-rectangular fashion. This last type only applies to block-level
* elements, and indicates whether splitting can be used when doing runaround.
@@ -1728,24 +1729,16 @@ public:
* have kids. It could still have kids created via
* nsIAnonymousContentCreator. Returning true indicates that "normal"
* (non-anonymous, XBL-bound, CSS generated content, etc) children should not
* be constructed.
*/
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
*/
void InvalidateWithFlags(const nsRect& aDamageRect, PRUint32 aFlags);
/**
* Invalidate part of the frame by asking the view manager to repaint.
* aDamageRect is allowed to extend outside the frame's bounds. We'll do the right
* thing.
@@ -1950,24 +1943,16 @@ public:
* example in nsIFrame code.
*/
const nsFrameSelection* GetConstFrameSelection();
/** 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
* uses frame's begin selection state to start. if no selection on this frame will
* return NS_ERROR_FAILURE
* @param aPOS is defined in nsFrameSelection
*/
NS_IMETHOD PeekOffset(nsPeekOffsetStruct *aPos);
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -409,54 +409,25 @@ public:
}
virtual ~nsAutoScrollTimer()
{
if (mTimer)
mTimer->Cancel();
}
- nsresult Start(nsPresContext *aPresContext, nsIView *aView, nsPoint &aPoint)
+ nsresult Start(nsPresContext *aPresContext, nsPoint &aPoint)
{
mPoint = aPoint;
// Store the presentation context. The timer will be
// 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)
{
nsresult result;
mTimer = do_CreateInstance("@mozilla.org/timer;1", &result);
if (NS_FAILED(result))
return result;
@@ -489,56 +460,24 @@ public:
mDelay = aDelay;
return NS_OK;
}
NS_IMETHOD Notify(nsITimer *timer)
{
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;
}
private:
nsFrameSelection *mFrameSelection;
nsTypedSelection *mSelection;
nsPresContext *mPresContext;
@@ -5000,17 +4939,17 @@ nsTypedSelection::DoAutoScrollView(nsPre
// Map the globalPoint back into aView's coordinate system. We
// have to get the globalOffsets again because aView's
// window and its parents may have changed their offsets.
//
result = GetViewAncestorOffset(aView, nsnull, &globalOffset.x, &globalOffset.y);
NS_ENSURE_SUCCESS(result, result);
nsPoint svPoint = globalPoint - globalOffset;
- mAutoScrollTimer->Start(aPresContext, aView, svPoint);
+ mAutoScrollTimer->Start(aPresContext, svPoint);
}
return NS_OK;
}
NS_IMETHODIMP
nsTypedSelection::GetEnumerator(nsIEnumerator **aIterator)
{
--- a/layout/generic/test/test_bug470212.html
+++ b/layout/generic/test/test_bug470212.html
@@ -23,16 +23,17 @@ function doShiftDrag(){
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
wu.sendMouseEvent('mousedown', 0, 50, 0, 1, 4);
wu.sendMouseEvent('mousemove', 70, 70, 0, 0, 4);
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);
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doShiftDrag);
</script>
--- a/layout/xul/base/src/nsResizerFrame.cpp
+++ b/layout/xul/base/src/nsResizerFrame.cpp
@@ -106,18 +106,17 @@ nsResizerFrame::HandleEvent(nsPresContex
if (rv == NS_ERROR_NOT_IMPLEMENTED) {
// there's no native resize support,
// we need to window resizing ourselves
// we're tracking.
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;
aEvent->widget->GetScreenBounds(mWidgetRect);
}
*aEventStatus = nsEventStatus_eConsumeNoDefault;
doDefault = PR_FALSE;
@@ -131,18 +130,17 @@ nsResizerFrame::HandleEvent(nsPresContex
if(mTrackingMouseMove && aEvent->eventStructType == NS_MOUSE_EVENT &&
static_cast<nsMouseEvent*>(aEvent)->button ==
nsMouseEvent::eLeftButton)
{
// we're done tracking.
mTrackingMouseMove = PR_FALSE;
// end capture
- aEvent->widget->CaptureMouse(PR_FALSE);
- CaptureMouseEvents(aPresContext,PR_FALSE);
+ nsIPresShell::SetCapturingContent(nsnull, 0);
*aEventStatus = nsEventStatus_eConsumeNoDefault;
doDefault = PR_FALSE;
}
}
break;
case NS_MOUSE_MOVE: {
--- a/layout/xul/base/src/nsSliderFrame.cpp
+++ b/layout/xul/base/src/nsSliderFrame.cpp
@@ -50,17 +50,16 @@
#include "nsIContent.h"
#include "nsCOMPtr.h"
#include "nsINameSpaceManager.h"
#include "nsGkAtoms.h"
#include "nsHTMLParts.h"
#include "nsIPresShell.h"
#include "nsCSSRendering.h"
#include "nsIDOMEventTarget.h"
-#include "nsIViewManager.h"
#include "nsIDOMMouseEvent.h"
#include "nsIDocument.h"
#include "nsScrollbarButtonFrame.h"
#include "nsISliderListener.h"
#include "nsIScrollbarMediator.h"
#include "nsIScrollbarFrame.h"
#include "nsILookAndFeel.h"
#include "nsRepeatService.h"
@@ -119,17 +118,16 @@ nsSliderFrame::Init(nsIContent* aCo
gotPrefs = PR_TRUE;
gMiddlePref = nsContentUtils::GetBoolPref("middlemouse.scrollbarPosition");
gSnapMultiplier = nsContentUtils::GetIntPref("slider.snapMultiplier");
}
mCurPos = GetCurrentPosition(aContent);
- CreateViewForFrame(PresContext(), this, GetStyleContext(), PR_TRUE);
return rv;
}
NS_IMETHODIMP
nsSliderFrame::RemoveFrame(nsIAtom* aListName,
nsIFrame* aOldFrame)
{
nsresult rv = nsBoxFrame::RemoveFrame(aListName, aOldFrame);
@@ -974,52 +972,24 @@ nsSliderFrame::DragThumb(PRBool aGrabMou
if (parent) {
nsCOMPtr<nsISliderListener> sliderListener = do_QueryInterface(parent->GetContent());
if (sliderListener) {
nsContentUtils::AddScriptRunner(
new nsDragStateChangedRunnable(sliderListener, 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
nsSliderFrame::AddListener()
{
if (!mMediator) {
mMediator = new nsSliderMediator(this);
}
--- a/layout/xul/base/src/nsSliderFrame.h
+++ b/layout/xul/base/src/nsSliderFrame.h
@@ -181,18 +181,16 @@ public:
static PRInt32 GetCurrentPosition(nsIContent* content);
static PRInt32 GetMinPosition(nsIContent* content);
static PRInt32 GetMaxPosition(nsIContent* content);
static PRInt32 GetIncrement(nsIContent* content);
static PRInt32 GetPageIncrement(nsIContent* content);
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);
NS_IMETHOD HandleMultiplePress(nsPresContext* aPresContext,
nsGUIEvent * aEvent,
nsEventStatus* aEventStatus,
PRBool aControlHeld) { return NS_OK; }
--- a/layout/xul/base/src/nsSplitterFrame.cpp
+++ b/layout/xul/base/src/nsSplitterFrame.cpp
@@ -50,19 +50,16 @@
#include "nsIDOMDocument.h"
#include "nsPresContext.h"
#include "nsIDocument.h"
#include "nsINameSpaceManager.h"
#include "nsScrollbarButtonFrame.h"
#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"
#include "nsHTMLParts.h"
#include "nsILookAndFeel.h"
#include "nsStyleContext.h"
#include "nsBoxLayoutState.h"
#include "nsIXBLService.h"
@@ -142,18 +139,16 @@ public:
enum ResizeType { Closest, Farthest, Flex, Grow };
enum State { Open, CollapsedBefore, CollapsedAfter, Dragging };
enum CollapseDirection { Before, After };
ResizeType GetResizeBefore();
ResizeType GetResizeAfter();
State GetState();
- //nsresult CaptureMouse(nsPresContext* aPresContext, PRBool aGrabMouseEvents);
- //PRBool IsMouseCaptured(nsPresContext* aPresContext);
void Reverse(nsSplitterInfo*& aIndexes, PRInt32 aCount);
PRBool SupportsCollapseDirection(CollapseDirection aDirection);
void EnsureOrient();
void SetPreferredSize(nsBoxLayoutState& aState, nsIBox* aChildBox, nscoord aOnePixel, PRBool aIsHorizontal, nscoord* aSize);
nsSplitterFrame* mOuter;
PRBool mDidDrag;
@@ -162,17 +157,16 @@ public:
nsIBox* mParentBox;
PRBool mPressed;
nsSplitterInfo* mChildInfosBefore;
nsSplitterInfo* mChildInfosAfter;
PRInt32 mChildInfosBeforeCount;
PRInt32 mChildInfosAfterCount;
State mState;
nscoord mSplitterPos;
- nscoord mSplitterViewPos;
PRBool mDragging;
};
NS_IMPL_ADDREF(nsSplitterFrameInner)
NS_IMPL_RELEASE(nsSplitterFrameInner)
NS_INTERFACE_MAP_BEGIN(nsSplitterFrameInner)
@@ -348,19 +342,16 @@ nsSplitterFrame::Init(nsIContent* a
SetStyleContextWithoutNotification(newContext);
}
}
}
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;
return rv;
}
NS_IMETHODIMP
nsSplitterFrame::DoLayout(nsBoxLayoutState& aState)
@@ -469,17 +460,17 @@ nsSplitterFrame::HandleEvent(nsPresConte
}
void
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.
if (newState == Dragging)
mOuter->mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::state, EmptyString(), PR_TRUE);
mPressed = PR_FALSE;
@@ -583,30 +574,16 @@ nsSplitterFrameInner::MouseDrag(nsPresCo
} else {
// if we are not in a collapsed position and we are not dragging make sure
// we are dragging.
if (currentState != Dragging)
mOuter->mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::state, NS_LITERAL_STRING("dragging"), PR_TRUE);
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;
}
}
void
nsSplitterFrameInner::AddListener(nsPresContext* aPresContext)
{
mOuter->GetContent()->
@@ -624,72 +601,23 @@ nsSplitterFrameInner::RemoveListener()
mOuter->GetContent()->
RemoveEventListenerByIID(static_cast<nsIDOMMouseListener*>(this),
NS_GET_IID(nsIDOMMouseListener));
mOuter->GetContent()->
RemoveEventListenerByIID(static_cast<nsIDOMMouseMotionListener*>(this),
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;
}
nsresult
nsSplitterFrameInner::MouseDown(nsIDOMEvent* aMouseEvent)
{
NS_ENSURE_TRUE(mOuter, NS_OK);
@@ -840,36 +768,32 @@ nsSplitterFrameInner::MouseDown(nsIDOMEv
if (resizeAfter == Farthest)
Reverse(mChildInfosAfter, mChildInfosAfterCount);
// grow only applys to the children after. If grow is set then no space should be taken out of any children after
// us. To do this we just set the size of that list to be 0.
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;
}
nsresult
nsSplitterFrameInner::MouseMove(nsIDOMEvent* aMouseEvent)
{
NS_ENSURE_TRUE(mOuter, NS_OK);
--- a/layout/xul/base/src/nsSplitterFrame.h
+++ b/layout/xul/base/src/nsSplitterFrame.h
@@ -99,18 +99,16 @@ public:
nsEventStatus* aEventStatus);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
virtual void GetInitialOrientation(PRBool& aIsHorizontal);
- virtual nsIView* GetMouseCapturer() const { return GetView(); }
-
private:
friend class nsSplitterFrameInner;
nsSplitterFrameInner* mInner;
}; // class nsSplitterFrame
#endif
--- a/layout/xul/base/src/nsTitleBarFrame.cpp
+++ b/layout/xul/base/src/nsTitleBarFrame.cpp
@@ -43,17 +43,16 @@
#include "nsIDOMXULDocument.h"
#include "nsIDOMNodeList.h"
#include "nsGkAtoms.h"
#include "nsIWidget.h"
#include "nsMenuPopupFrame.h"
#include "nsPresContext.h"
#include "nsIDocShellTreeItem.h"
#include "nsPIDOMWindow.h"
-#include "nsIViewManager.h"
#include "nsGUIEvent.h"
#include "nsEventDispatcher.h"
#include "nsDisplayList.h"
#include "nsContentUtils.h"
//
// NS_NewTitleBarFrame
//
@@ -68,30 +67,16 @@ NS_NewTitleBarFrame(nsIPresShell* aPresS
NS_IMPL_FRAMEARENA_HELPERS(nsTitleBarFrame)
nsTitleBarFrame::nsTitleBarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
:nsBoxFrame(aPresShell, aContext, PR_FALSE)
{
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,
const nsDisplayListSet& aLists)
{
// override, since we don't want children to get events
if (aBuilder->IsForEventDelivery()) {
if (!mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allowevents,
@@ -126,17 +111,17 @@ nsTitleBarFrame::HandleEvent(nsPresConte
if (dsti) {
PRInt32 type = -1;
if (NS_SUCCEEDED(dsti->GetItemType(&type)) &&
type == nsIDocShellTreeItem::typeChrome) {
// we're tracking.
mTrackingMouseMove = PR_TRUE;
// start capture.
- CaptureMouseEvents(aPresContext,PR_TRUE);
+ nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
// remember current mouse coordinates.
mLastPoint = aEvent->refPoint;
}
}
*aEventStatus = nsEventStatus_eConsumeNoDefault;
doDefault = PR_FALSE;
@@ -149,17 +134,17 @@ nsTitleBarFrame::HandleEvent(nsPresConte
if(mTrackingMouseMove && aEvent->eventStructType == NS_MOUSE_EVENT &&
static_cast<nsMouseEvent*>(aEvent)->button ==
nsMouseEvent::eLeftButton)
{
// we're done tracking.
mTrackingMouseMove = PR_FALSE;
// end capture
- CaptureMouseEvents(aPresContext,PR_FALSE);
+ nsIPresShell::SetCapturingContent(nsnull, 0);
*aEventStatus = nsEventStatus_eConsumeNoDefault;
doDefault = PR_FALSE;
}
}
break;
case NS_MOUSE_MOVE: {
@@ -207,45 +192,16 @@ nsTitleBarFrame::HandleEvent(nsPresConte
}
if ( doDefault )
return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
else
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)
{
// Execute the oncommand event handler.
nsContentUtils::DispatchXULCommand(mContent,
aEvent ?
NS_IS_TRUSTED_EVENT(aEvent) : PR_FALSE);
}
--- a/layout/xul/base/src/nsTitleBarFrame.h
+++ b/layout/xul/base/src/nsTitleBarFrame.h
@@ -44,36 +44,28 @@ class nsTitleBarFrame : public nsBoxFram
{
public:
NS_DECL_FRAMEARENA_HELPERS
friend nsIFrame* NS_NewTitleBarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
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);
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
virtual PRBool GetMouseThrough() const { return PR_FALSE; }
virtual void MouseClicked(nsPresContext* aPresContext, nsGUIEvent* aEvent);
protected:
-
- NS_IMETHOD CaptureMouseEvents(nsPresContext* aPresContext,PRBool aGrabMouseEvents);
-
-protected:
PRBool mTrackingMouseMove;
nsIntPoint mLastPoint;
}; // class nsTitleBarFrame
#endif /* nsTitleBarFrame_h___ */
--- a/layout/xul/base/src/nsXULPopupManager.cpp
+++ b/layout/xul/base/src/nsXULPopupManager.cpp
@@ -2096,17 +2096,17 @@ nsXULMenuCommandEvent::Run()
nsPresContext* presContext = menuFrame->PresContext();
nsCOMPtr<nsIPresShell> shell = presContext->PresShell();
nsCOMPtr<nsIViewManager> kungFuDeathGrip = shell->GetViewManager();
// Deselect ourselves.
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);
}
if (popup && mCloseMenuMode != CloseMenuMode_None)
pm->HidePopup(popup, mCloseMenuMode == CloseMenuMode_Auto, PR_TRUE, PR_FALSE);
return NS_OK;
--- a/toolkit/content/tests/widgets/Makefile.in
+++ b/toolkit/content/tests/widgets/Makefile.in
@@ -98,16 +98,17 @@ include $(topsrcdir)/config/rules.mk
test_popuphidden.xul \
test_popup_scaled.xul \
test_popupremoving.xul \
test_popupremoving_frame.xul \
frame_popupremoving_frame.xul \
test_position.xul \
test_menu.xul \
test_menu_hide.xul \
+ test_mousecapture.xul \
test_focus.xul \
test_focus_anons.xul \
test_tabindex.xul \
test_mousescroll.xul \
test_scrollbar.xul \
test_sorttemplate.xul \
test_contextmenu_list.xul \
test_videocontrols.html \
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/widgets/test_mousecapture.xul
@@ -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>
--- a/toolkit/content/tests/widgets/test_scale.xul
+++ b/toolkit/content/tests/widgets/test_scale.xul
@@ -207,16 +207,40 @@ function testtag_scale_UI_Mouse(element,
var rect = element.getBoundingClientRect();
synthesizeMouseExpectEvent(element, rect.right - rect.left - hmove,
rect.bottom - rect.top - vmove, { },
element, "change", testid + " mouse on right movetoclick=false");
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)
{
is(element.getAttribute("value"), evalueattr, testid + " value attribute");
is(element.value, evalue, testid + " value");
is(element.min, emin, testid + " min");
is(element.max, emax, testid + " max");
--- a/view/public/nsIViewManager.h
+++ b/view/public/nsIViewManager.h
@@ -55,18 +55,18 @@ enum nsRectVisibility {
nsRectVisibility_kAboveViewport,
nsRectVisibility_kBelowViewport,
nsRectVisibility_kLeftOfViewport,
nsRectVisibility_kRightOfViewport,
nsRectVisibility_kZeroAreaRect
};
#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
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IVIEWMANAGER_IID)
/**
* Initialize the ViewManager
@@ -183,31 +183,16 @@ public:
* @param aEvent event to dispatch
* @param aViewTarget dispatch the event to this view
* @param aStatus event handling status
*/
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.
* If aSibling is null, the view is inserted at the end of the document order
* if aAfter is PR_TRUE, otherwise it is inserted at the beginning.
* If aSibling is non-null, then if aAfter is PR_TRUE, the view is inserted
* after the sibling in document order (appearing above the sibling unless
* overriden by z-order).
* If it is PR_FALSE, the view is inserted before the sibling.
--- a/view/public/nsIViewObserver.h
+++ b/view/public/nsIViewObserver.h
@@ -41,20 +41,20 @@
#include "nsISupports.h"
#include "nsEvent.h"
#include "nsColor.h"
#include "nsRect.h"
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
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IVIEWOBSERVER_IID)
/* called when the observer needs to paint. This paints the entire
@@ -145,13 +145,20 @@ public:
/**
* Dispatch the given synthesized mouse move event, and if
* aFlushOnHoverChange is true, flush layout if :hover changes cause
* any restyles.
*/
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)
#endif
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -180,23 +180,21 @@ nsView::nsView(nsViewManager* aViewManag
// should make this promise explicitly by calling
// SetViewContentTransparency.
mVFlags = 0;
mViewManager = aViewManager;
mDirtyRegion = nsnull;
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);
}
}
nsView::~nsView()
{
MOZ_COUNT_DTOR(nsView);
while (GetFirstChild())
@@ -490,25 +488,16 @@ NS_IMETHODIMP nsView::SetFloating(PRBool
}
#endif
return NS_OK;
}
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();
for (nsView *child = mFirstChild; child; child = child->GetNextSibling())
child->InvalidateHierarchy(aViewManagerParent);
}
void nsView::InsertChild(nsView *aChild, nsView *aSibling)
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -258,18 +258,16 @@ NS_IMETHODIMP nsViewManager::Init(nsIDev
}
if (nsnull != mContext) {
return NS_ERROR_ALREADY_INITIALIZED;
}
mContext = aContext;
mRefreshEnabled = PR_TRUE;
- mMouseGrabber = nsnull;
-
return NS_OK;
}
NS_IMETHODIMP_(nsIView *)
nsViewManager::CreateView(const nsRect& aBounds,
const nsIView* aParent,
nsViewVisibility aVisibilityFlag)
{
@@ -1072,41 +1070,34 @@ NS_IMETHODIMP nsViewManager::DispatchEve
aEvent->message != NS_MOUSE_ENTER) ||
NS_IS_KEY_EVENT(aEvent) ||
NS_IS_IME_EVENT(aEvent) ||
NS_IS_PLUGIN_EVENT(aEvent)) {
gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow());
}
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();
if ((aEvent->message == NS_MOUSE_MOVE &&
static_cast<nsMouseEvent*>(aEvent)->reason ==
nsMouseEvent::eReal) ||
aEvent->message == NS_MOUSE_ENTER ||
aEvent->message == NS_MOUSE_BUTTON_DOWN ||
@@ -1166,74 +1157,43 @@ NS_IMETHODIMP nsViewManager::DispatchEve
nsPoint pt;
pt.x = baseViewDimensions.x +
NSFloatPixelsToAppUnits(float(aEvent->refPoint.x) + 0.5f, p2a);
pt.y = baseViewDimensions.y +
NSFloatPixelsToAppUnits(float(aEvent->refPoint.y) + 0.5f, p2a);
pt += offset;
- *aStatus = HandleEvent(view, pt, aEvent, capturedEvent);
+ *aStatus = HandleEvent(view, pt, aEvent);
}
break;
}
}
return NS_OK;
}
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);
// Hold a refcount to the observer. The continued existence of the observer will
// delay deletion of this view hierarchy should the event want to cause its
// destruction in, say, some JavaScript event handler.
nsCOMPtr<nsIViewObserver> obs = aView->GetViewManager()->GetViewObserver();
nsEventStatus status = nsEventStatus_eIgnore;
if (obs) {
obs->HandleEvent(aView, aEvent, &status);
}
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)
{
if (aView->HasWidget()) {
// Check to see if the parent widget is the
// same as the new parent. If not then reparent
// the widget, otherwise there is nothing more
--- a/view/src/nsViewManager.h
+++ b/view/src/nsViewManager.h
@@ -123,20 +123,16 @@ public:
NS_IMETHOD UpdateView(nsIView *aView, PRUint32 aUpdateFlags);
NS_IMETHOD UpdateView(nsIView *aView, const nsRect &aRect, PRUint32 aUpdateFlags);
NS_IMETHOD UpdateAllViews(PRUint32 aUpdateFlags);
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);
NS_IMETHOD InsertChild(nsIView *parent, nsIView *child,
PRInt32 zindex);
NS_IMETHOD RemoveChild(nsIView *parent);
@@ -300,24 +296,20 @@ private:
}
void SetPainting(PRBool aPainting) {
RootViewManager()->mPainting = aPainting;
}
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.
* @param aView the view that will bit-blit
* @param aScrollAmount how much aView will scroll by
* @return always returns NS_OK
* @note
* This method used to return void, but MSVC 6.0 SP5 (without the
@@ -385,18 +377,16 @@ private:
nsRevocableEventPtr<nsViewManagerEvent> mSynthMouseMoveEvent;
nsRevocableEventPtr<nsViewManagerEvent> mInvalidateEvent;
// The following members should not be accessed directly except by
// 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;
PRInt32 mUpdateBatchCnt;
PRUint32 mUpdateBatchFlags;
PRInt32 mScrollCnt;
// Use IsRefreshEnabled() to check the value of mRefreshEnabled.
PRPackedBool mRefreshEnabled;
--- a/widget/src/xpwidgets/nsBaseDragService.cpp
+++ b/widget/src/xpwidgets/nsBaseDragService.cpp
@@ -222,30 +222,22 @@ nsBaseDragService::InvokeDragSession(nsI
// stash the document of the dom node
aDOMNode->GetOwnerDocument(getter_AddRefs(mSourceDocument));
mSourceNode = aDOMNode;
mEndDragPoint = nsIntPoint(0, 0);
// 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);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsBaseDragService::InvokeDragSessionWithImage(nsIDOMNode* aDOMNode,