Bug 503943, back out mouse capture patch, CLOSED TREE
authorNeil Deakin <neil@mozilla.com>
Thu, 10 Sep 2009 12:11:41 -0400
changeset 32361 94b823431cc060e1aac0c495b3181851ef5c34be
parent 32360 394140c609d579a1a69527d4da37a8def9efa4af
child 32362 a1d8b365bc51644385689d22e8b0530ad72068f3
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs503943
milestone1.9.3a1pre
Bug 503943, back out mouse capture patch, CLOSED TREE
content/base/src/nsDocument.cpp
content/base/src/nsGenericElement.cpp
content/events/src/nsEventStateManager.cpp
content/events/src/nsEventStateManager.h
content/html/content/src/nsHTMLFormElement.cpp
dom/interfaces/core/nsIDOMNSDocument.idl
dom/interfaces/core/nsIDOMNSElement.idl
layout/base/nsIPresShell.h
layout/base/nsPresShell.cpp
layout/forms/nsListControlFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsFrameSetFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIFrame.h
layout/generic/nsSelection.cpp
layout/xul/base/src/nsResizerFrame.cpp
layout/xul/base/src/nsSliderFrame.cpp
layout/xul/base/src/nsSliderFrame.h
layout/xul/base/src/nsSplitterFrame.cpp
layout/xul/base/src/nsSplitterFrame.h
layout/xul/base/src/nsTitleBarFrame.cpp
layout/xul/base/src/nsTitleBarFrame.h
layout/xul/base/src/nsXULPopupManager.cpp
toolkit/content/tests/widgets/Makefile.in
toolkit/content/tests/widgets/test_mousecapture.xul
toolkit/content/tests/widgets/test_scale.xul
view/public/nsIViewManager.h
view/public/nsIViewObserver.h
view/src/nsView.cpp
view/src/nsViewManager.cpp
view/src/nsViewManager.h
widget/src/xpwidgets/nsBaseDragService.cpp
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2768,28 +2768,16 @@ 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,39 +1079,16 @@ 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,19 +2736,29 @@ 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) {
-        // We got a mouseup event while a mousedown event was being processed.
-        // Make sure that the capturing content is cleared.
-        nsIPresShell::SetCapturingContent(nsnull, 0);
+        //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);
+            }
+          }
+        }
         break;
       }
 
       if (nsEventStatus_eConsumeNoDefault != *aStatus) {
         nsCOMPtr<nsIContent> newFocus;
         nsIContent* activeContent = nsnull;
         PRBool suppressBlur = PR_FALSE;
         if (mCurrentTarget) {
@@ -2843,19 +2853,27 @@ 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,48 +406,37 @@ 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, PRBool aIsMouseDown)
-    : mIsHandlingUserInput(aIsHandlingUserInput), mIsMouseDown(aIsMouseDown)
+  nsAutoHandlingUserInputStatePusher(PRBool aIsHandlingUserInput)
+    : mIsHandlingUserInput(aIsHandlingUserInput)
   {
     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, PR_FALSE);
+    nsAutoHandlingUserInputStatePusher userInpStatePusher(mSubmitInitiatedFromUserInput);
 
     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(B7E9211B-F29F-4E2D-9762-6BCBC64E5C05)]
+[scriptable, uuid(09a439ad-4079-46d5-a050-4d7015d1a108)]
 interface nsIDOMNSDocument : nsISupports
 {
   readonly attribute DOMString      characterSet;
            attribute DOMString      dir;
 
   readonly attribute nsIDOMLocation location;
 
            attribute DOMString      title;
@@ -86,15 +86,9 @@ 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(FA8D7AF8-C208-4564-A0CD-346C345711F0)]
+[scriptable, uuid(df86b1a8-02c3-47be-a76b-856620f925df)]
 interface nsIDOMNSElement : nsISupports
 {
   /*
    * Retrieve elements matching all classes listed in a
    * space-separated string.
    *
    * See <http://whatwg.org/specs/web-apps/current-work/>
    */
@@ -147,25 +147,9 @@ 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,33 +99,16 @@ 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
@@ -868,52 +851,16 @@ 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,17 +203,16 @@
 #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);
 
@@ -793,17 +792,16 @@ 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);
@@ -4367,51 +4365,16 @@ 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;
@@ -5725,32 +5688,16 @@ 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) {
@@ -5897,59 +5844,50 @@ 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) {
-    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;
-      }
+  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;
     }
   }
 
   // Check for a theme change up front, since the frame type is irrelevant
   if (aEvent->message == NS_THEMECHANGED && mPresContext) {
     mPresContext->ThemeChanged();
     return NS_OK;
   }
@@ -5990,51 +5928,18 @@ 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;
@@ -6077,29 +5982,27 @@ PresShell::HandleEvent(nsIView         *
             frame = popup;
             break;
           }
         }
       }
 #endif
     }
 
-    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);
+    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;
       }
+      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).
@@ -6369,18 +6272,17 @@ PresShell::HandleEventInternal(nsEvent* 
         return NS_OK;
       }
       if (me->context == nsMouseEvent::eContextMenuKey &&
           !AdjustContextMenuKeyEvent(me)) {
         return NS_OK;
       }
     }                                
 
-    nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput,
-                                                          aEvent->message == NS_MOUSE_BUTTON_DOWN);
+    nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput);
 
     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);
@@ -6416,21 +6318,16 @@ 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
@@ -1026,33 +1026,38 @@ nsListControlFrame::CaptureMouseEvents(P
     return;
   
   nsIView* view = GetScrolledFrame()->GetView();
 
   NS_ASSERTION(view, "no view???");
   if (NS_UNLIKELY(!view))
     return;
 
-  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);
+  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);
+      }
     }
   }
 }
 
 //---------------------------------------------------------
 NS_IMETHODIMP 
 nsListControlFrame::HandleEvent(nsPresContext* aPresContext, 
                                 nsGUIEvent*    aEvent,
@@ -2110,17 +2115,21 @@ nsListControlFrame::FireMenuItemActiveEv
 
 nsresult
 nsListControlFrame::GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent, 
                                          PRInt32&     aCurIndex)
 {
   if (IgnoreMouseEventForSelection(aMouseEvent))
     return NS_ERROR_FAILURE;
 
-  if (nsIPresShell::GetCapturingContent() != mContent) {
+  nsIView* view = GetScrolledFrame()->GetView();
+  nsIViewManager* viewMan = view->GetViewManager();
+  nsIView* curGrabber;
+  viewMan->GetMouseEventGrabber(curGrabber);
+  if (curGrabber != view) {
     // 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,17 +50,16 @@
 #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"
@@ -747,27 +746,28 @@ nsFrame::GetAdditionalChildListName(PRIn
 
 nsFrameList
 nsFrame::GetChildList(nsIAtom* aListName) const
 {
   return nsFrameList::EmptyList();
 }
 
 static nsIFrame*
-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;
+GetActiveSelectionFrame(nsIFrame* aFrame)
+{
+  nsIView* mouseGrabber;
+  aFrame->PresContext()->GetPresShell()->
+    GetViewManager()->GetMouseEventGrabber(mouseGrabber);
+  if (mouseGrabber) {
+    nsIFrame* activeFrame = nsLayoutUtils::GetFrameFor(mouseGrabber);
+    if (activeFrame) {
+      return activeFrame;
     }
   }
-
+    
   return aFrame;
 }
 
 PRInt16
 nsFrame::DisplaySelection(nsPresContext* aPresContext, PRBool isOkToTurnOn)
 {
   PRInt16 selType = nsISelectionController::SELECTION_OFF;
 
@@ -1910,33 +1910,18 @@ 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 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();
-    }
-  }
+  if (!IsMouseCaptured(aPresContext))
+    CaptureMouse(aPresContext, PR_TRUE);
 
   // 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();
@@ -2201,16 +2186,39 @@ 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,16 +2233,23 @@ 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),
@@ -2242,39 +2257,32 @@ 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);
   }
 
-  // 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) {
+  if (weakFrame) {
+    nsIView* captureView = GetNearestCapturingView(this);
+    if (captureView) {
       // 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(capturingView);
-      frameselection->StartAutoScrollTimer(capturingView, capturePt, 30);
+      nsPoint capturePt = pt + eventView->GetOffsetTo(captureView);
+      frameselection->StartAutoScrollTimer(captureView, 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 +2345,21 @@ HandleFrameSelection(nsFrameSelection*  
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext,
                                      nsGUIEvent*    aEvent,
                                      nsEventStatus* aEventStatus)
 {
-  nsIFrame* activeFrame = GetActiveSelectionFrame(aPresContext, this);
+  nsIFrame* activeFrame = GetActiveSelectionFrame(this);
 
   // We can unconditionally stop capturing because
   // we should never be capturing when the mouse button is up
-  nsIPresShell::SetCapturingContent(nsnull, 0);
+  CaptureMouse(aPresContext, PR_FALSE);
 
   PRBool selectionOff =
     (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF);
 
   nsRefPtr<nsFrameSelection> frameselection;
   ContentOffsets offsets;
   nsCOMPtr<nsIContent> parentContent;
   PRInt32 contentOffsetForTableSel = 0;
@@ -5926,16 +5934,61 @@ 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
@@ -197,16 +197,24 @@ 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;
@@ -389,16 +397,20 @@ 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
@@ -309,16 +309,29 @@ 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;
@@ -793,16 +806,38 @@ 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;
@@ -1437,33 +1472,38 @@ nsHTMLFramesetFrame::StartMouseDrag(nsPr
                                     nsHTMLFramesetBorderFrame* aBorder, 
                                     nsGUIEvent*                aEvent)
 {
 #if 0
   PRInt32 index;
   IndexOf(aBorder, index);
   NS_ASSERTION((nsnull != aBorder) && (index >= 0), "invalid dragger");
 #endif
-
-  nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
+  nsIView* view = GetView();
+  if (view) {
+    nsIViewManager* viewMan = view->GetViewManager();
+    if (viewMan) {
+      PRBool ignore;
+      viewMan->GrabMouseEvents(view, ignore);
+      mDragger = aBorder;
 
-  mDragger = aBorder;
-
-  mFirstDragPoint = aEvent->refPoint;
+      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
@@ -1534,20 +1574,27 @@ nsHTMLFramesetFrame::MouseDrag(nsPresCon
       }
     }
   }
 }  
 
 void
 nsHTMLFramesetFrame::EndMouseDrag(nsPresContext* aPresContext)
 {
-  nsIPresShell::SetCapturingContent(nsnull, 0);
-  mDragger = nsnull;
+  nsIView* view = GetView();
+  if (view) {
+    nsIViewManager* viewMan = view->GetViewManager();
+    if (viewMan) {
+      mDragger = nsnull;
+      PRBool ignore;
+      viewMan->GrabMouseEvents(nsnull, ignore);
+    }
+  }
   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
@@ -304,16 +304,20 @@ 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;
 
@@ -467,16 +471,20 @@ 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,20 +102,19 @@ 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 \
-  { 0x87f5b42a, 0x507d, 0x4707, \
-    { 0x97, 0x6c, 0x46, 0x81, 0x98, 0x67, 0xbc, 0x63 } }
+  { 0x7e9018b5, 0x5405, 0x4e2b, \
+    { 0x87, 0x67, 0xe2, 0xb4, 0xb1, 0x3e, 0xc1, 0x69 } }
 
 /**
  * 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.
@@ -1729,16 +1728,24 @@ 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.
@@ -1943,16 +1950,24 @@ 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,25 +409,54 @@ public:
   }
 
   virtual ~nsAutoScrollTimer()
   {
    if (mTimer)
        mTimer->Cancel();
   }
 
-  nsresult Start(nsPresContext *aPresContext, nsPoint &aPoint)
+  nsresult Start(nsPresContext *aPresContext, nsIView *aView, nsPoint &aPoint)
   {
     mPoint = aPoint;
 
     // Store the presentation context. The timer will be
     // stopped by the selection if the prescontext is destroyed.
     mPresContext = aPresContext;
 
-    mContent = nsIPresShell::GetCapturingContent();
+    // 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.");
 
     if (!mTimer)
     {
       nsresult result;
       mTimer = do_CreateInstance("@mozilla.org/timer;1", &result);
 
       if (NS_FAILED(result))
         return result;
@@ -460,24 +489,56 @@ public:
     mDelay = aDelay;
     return NS_OK;
   }
 
   NS_IMETHOD Notify(nsITimer *timer)
   {
     if (mSelection && mPresContext)
     {
-      nsWeakFrame frame = mPresContext->PresShell()->GetPrimaryFrameFor(mContent);
+      // 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.
       mContent = nsnull;
 
-      mFrameSelection->HandleDrag(frame, mPoint);
-
-      nsPoint pnt;
+      // 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);
+
       mSelection->DoAutoScrollView(mPresContext,
-                                   frame.IsAlive() ? frame->GetClosestView(&pnt) : nsnull,
+                                   viewFrame.IsAlive() ? captureView : nsnull,
                                    mPoint, PR_TRUE);
     }
     return NS_OK;
   }
 private:
   nsFrameSelection *mFrameSelection;
   nsTypedSelection *mSelection;
   nsPresContext *mPresContext;
@@ -4939,17 +5000,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, svPoint);
+    mAutoScrollTimer->Start(aPresContext, aView, svPoint);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTypedSelection::GetEnumerator(nsIEnumerator **aIterator)
 {
--- a/layout/xul/base/src/nsResizerFrame.cpp
+++ b/layout/xul/base/src/nsResizerFrame.cpp
@@ -104,17 +104,18 @@ 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.
-           nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
+           aEvent->widget->CaptureMouse(PR_TRUE);
+           CaptureMouseEvents(aPresContext,PR_TRUE);
 
            // remember current mouse coordinates.
            mLastPoint = aEvent->refPoint;
            aEvent->widget->GetScreenBounds(mWidgetRect);
          }
 
          *aEventStatus = nsEventStatus_eConsumeNoDefault;
          doDefault = PR_FALSE;
@@ -128,17 +129,18 @@ 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
-         nsIPresShell::SetCapturingContent(nsnull, 0);
+         aEvent->widget->CaptureMouse(PR_FALSE);
+         CaptureMouseEvents(aPresContext,PR_FALSE);
 
          *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,16 +50,17 @@
 #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"
@@ -116,16 +117,17 @@ 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);
@@ -970,24 +972,52 @@ nsSliderFrame::DragThumb(PRBool aGrabMou
   if (parent) {
     nsCOMPtr<nsISliderListener> sliderListener = do_QueryInterface(parent->GetContent());
     if (sliderListener) {
       nsContentUtils::AddScriptRunner(
         new nsDragStateChangedRunnable(sliderListener, aGrabMouseEvents));
     }
   }
 
-  nsIPresShell::SetCapturingContent(aGrabMouseEvents ? GetContent() : nsnull,
-                                    aGrabMouseEvents ? CAPTURE_IGNOREALLOWED : 0);
+  // 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);
+      }
+    }
+  }
 }
 
 PRBool
 nsSliderFrame::isDraggingThumb()
 {
-  return (nsIPresShell::GetCapturingContent() == GetContent());
+  // 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;
 }
 
 void
 nsSliderFrame::AddListener()
 {
   if (!mMediator) {
     mMediator = new nsSliderMediator(this);
   }
--- a/layout/xul/base/src/nsSliderFrame.h
+++ b/layout/xul/base/src/nsSliderFrame.h
@@ -179,16 +179,18 @@ 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,16 +50,19 @@
 #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"
@@ -139,16 +142,18 @@ 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;
@@ -157,16 +162,17 @@ 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)
@@ -340,16 +346,19 @@ 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)
@@ -458,17 +467,17 @@ nsSplitterFrame::HandleEvent(nsPresConte
 }
 
 void
 nsSplitterFrameInner::MouseUp(nsPresContext* aPresContext, nsGUIEvent* aEvent)
 {
   if (mDragging && mOuter) {
     AdjustChildren(aPresContext);
     AddListener(aPresContext);
-    nsIPresShell::SetCapturingContent(nsnull, 0); // XXXndeakin is this needed?
+    mOuter->CaptureMouse(aPresContext, PR_FALSE);
     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;
 
@@ -572,16 +581,30 @@ 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()->
@@ -599,23 +622,72 @@ 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;
 
-  nsIPresShell::SetCapturingContent(nsnull, 0);
+  mOuter->CaptureMouse(mOuter->PresContext(), PR_FALSE);
 
   return NS_OK;
 }
 
 nsresult
 nsSplitterFrameInner::MouseDown(nsIDOMEvent* aMouseEvent)
 {  
   NS_ENSURE_TRUE(mOuter, NS_OK);
@@ -766,32 +838,36 @@ 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);
 
-  nsIPresShell::SetCapturingContent(mOuter->GetContent(), CAPTURE_IGNOREALLOWED);
+  mOuter->CaptureMouse(outerPresContext, PR_TRUE);
 
   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
@@ -97,16 +97,18 @@ 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,16 +43,17 @@
 #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
 //
@@ -65,16 +66,30 @@ NS_NewTitleBarFrame(nsIPresShell* aPresS
 } // NS_NewTitleBarFrame
 
 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,
@@ -109,17 +124,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.
-             nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
+             CaptureMouseEvents(aPresContext,PR_TRUE);
 
              // remember current mouse coordinates.
              mLastPoint = aEvent->refPoint;
            }
          }
 
          *aEventStatus = nsEventStatus_eConsumeNoDefault;
          doDefault = PR_FALSE;
@@ -132,17 +147,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
-         nsIPresShell::SetCapturingContent(nsnull, 0);
+         CaptureMouseEvents(aPresContext,PR_FALSE);
 
          *aEventStatus = nsEventStatus_eConsumeNoDefault;
          doDefault = PR_FALSE;
        }
      }
      break;
 
    case NS_MOUSE_MOVE: {
@@ -190,16 +205,45 @@ 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
@@ -43,28 +43,36 @@
 class nsTitleBarFrame : public nsBoxFrame  
 {
 
 public:
   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, PR_FALSE);
+    nsAutoHandlingUserInputStatePusher userInpStatePusher(mUserInput);
     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,17 +98,16 @@ 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 \
deleted file mode 100644
--- a/toolkit/content/tests/widgets/test_mousecapture.xul
+++ /dev/null
@@ -1,191 +0,0 @@
-<?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,27 +207,16 @@ 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, 7, 7, { type: "mousedown" });
-  synthesizeMouse(element, 2000, 2000, { type: "mousemove" });
-  is(element.value, reverse ? element.min : element.max, testid + " move mouse too far before start");
-  synthesizeMouse(element, 2000, 2000, { type: "mouseup" });
-
-  synthesizeMouse(element, rect.width - 7, rect.height - 7, { type: "mousedown" });
-  synthesizeMouse(element, -2000, -2000, { type: "mousemove" });
-  is(element.value, reverse ? element.max : element.min, testid + " move mouse too far before end");
-  synthesizeMouse(element, -2000, -2000, { 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   \
-  { 0xe1f3095c, 0x65cd, 0x46e1, \
-    { 0x9d, 0x70, 0x88, 0xcf, 0x54, 0x19, 0x9d, 0x05 } }
+  { 0x739bbc2b, 0x5c45, 0x40bb, \
+    { 0xb0, 0xbc, 0xe3, 0x1c, 0xe0, 0xf2, 0x19, 0xc2 } }
 
 class nsIViewManager : public nsISupports
 {
 public:
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IVIEWMANAGER_IID)
   /**
    * Initialize the ViewManager
@@ -183,16 +183,31 @@ 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;
 
-// 8D7AE493-1EB1-4D38-89DA-9EEEAA29FD79
+// 52b3b616-23a9-4516-a8d3-452b4126eb2b
 #define NS_IVIEWOBSERVER_IID  \
-{ 0x8d7ae493, 0x1eb1, 0x4d38, \
-  { 0x89, 0xda, 0x9e, 0xee, 0xaa, 0x29, 0xfd, 0x79 } }
+{ 0x52b3b616, 0x23a9, 0x4516, \
+  { 0xa8, 0xd3, 0x45, 0x2b, 0x41, 0x26, 0xeb, 0x2b } }
 
 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,20 +145,13 @@ 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,21 +180,23 @@ nsView::nsView(nsViewManager* aViewManag
   // should make this promise explicitly by calling
   // SetViewContentTransparency.
   mVFlags = 0;
   mViewManager = aViewManager;
   mDirtyRegion = nsnull;
   mDeletionObserver = nsnull;
 }
 
-void nsView::DropMouseGrabbing()
-{
-  nsCOMPtr<nsIViewObserver> viewObserver = mViewManager->GetViewObserver();
-  if (viewObserver) {
-    viewObserver->ClearMouseCapture(this);
+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);
   }
 }
 
 nsView::~nsView()
 {
   MOZ_COUNT_DTOR(nsView);
 
   while (GetFirstChild())
@@ -488,16 +490,25 @@ 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,16 +258,18 @@ 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)
 {
@@ -1070,34 +1072,41 @@ 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) {
-          // if a window is deactivated, clear the mouse capture regardless
-          // of what is capturing
-          nsIViewObserver* viewObserver = GetViewObserver();
-          if (viewObserver) {
-            viewObserver->ClearMouseCapture(nsnull);
-          }
+          PRBool result;
+          GrabMouseEvents(nsnull, result);
         }
 
         //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 ||
@@ -1157,43 +1166,74 @@ 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);
+          *aStatus = HandleEvent(view, pt, aEvent, capturedEvent);
         }
     
         break;
       }
     }
 
   return NS_OK;
 }
 
 nsEventStatus nsViewManager::HandleEvent(nsView* aView, nsPoint aPoint,
-                                         nsGUIEvent* aEvent) {
+                                         nsGUIEvent* aEvent, PRBool aCaptured) {
 //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,16 +123,20 @@ 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);
 
@@ -296,20 +300,24 @@ 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);
+  nsEventStatus HandleEvent(nsView* aView, nsPoint aPoint, nsGUIEvent* aEvent,
+                            PRBool aCaptured);
 
   /**
    * 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
@@ -377,16 +385,18 @@ 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,22 +222,30 @@ 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, 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);
+  // 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);
+        }
+      }
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseDragService::InvokeDragSessionWithImage(nsIDOMNode* aDOMNode,