From aae64e984b47da646cabffbc84655b1ca881101f Mon Sep 17 00:00:00 2001 From: "bryner%uiuc.edu" Date: Sat, 9 Dec 2000 07:28:19 +0000 Subject: [PATCH] Mousewheel bugs 29244, 50339, 42313, 33733, and 57598. r=rods,pavlov. sr=hyatt. git-svn-id: svn://10.0.0.236/trunk@83448 18797224-902f-48f8-a5cc-f745e15eee43 --- .../events/src/nsEventStateManager.cpp | 253 ++++++++++++------ .../content/events/src/nsEventStateManager.h | 8 + mozilla/layout/base/public/MANIFEST | 1 + mozilla/layout/base/public/Makefile.in | 1 + mozilla/layout/base/public/makefile.win | 1 + .../base/public/nsIScrollableViewProvider.h | 43 +++ .../layout/events/src/nsEventStateManager.cpp | 253 ++++++++++++------ .../layout/events/src/nsEventStateManager.h | 8 + .../layout/forms/nsComboboxControlFrame.cpp | 20 ++ mozilla/layout/forms/nsComboboxControlFrame.h | 13 +- .../generic/nsIScrollableViewProvider.h | 43 +++ .../html/forms/src/nsComboboxControlFrame.cpp | 20 ++ .../html/forms/src/nsComboboxControlFrame.h | 13 +- .../html/forms/src/nsGfxTextControlFrame2.cpp | 11 + .../html/forms/src/nsGfxTextControlFrame2.h | 6 +- mozilla/layout/xul/base/src/nsMenuFrame.cpp | 21 ++ mozilla/layout/xul/base/src/nsMenuFrame.h | 9 +- .../layout/xul/base/src/nsMenuPopupFrame.h | 5 +- mozilla/widget/src/gtk/nsWidget.cpp | 10 +- mozilla/widget/src/gtk/nsWidget.h | 2 +- mozilla/widget/src/windows/nsWindow.cpp | 40 +-- 21 files changed, 589 insertions(+), 192 deletions(-) create mode 100644 mozilla/layout/base/public/nsIScrollableViewProvider.h create mode 100644 mozilla/layout/generic/nsIScrollableViewProvider.h diff --git a/mozilla/content/events/src/nsEventStateManager.cpp b/mozilla/content/events/src/nsEventStateManager.cpp index 402a0934dcc..7134eae1185 100644 --- a/mozilla/content/events/src/nsEventStateManager.cpp +++ b/mozilla/content/events/src/nsEventStateManager.cpp @@ -71,6 +71,7 @@ #include "nsIDocShell.h" #include "nsIMarkupDocumentViewer.h" #include "nsITreeFrame.h" +#include "nsIScrollableViewProvider.h" //we will use key binding by default now. this wil lbreak viewer for now #define NON_KEYBINDING 0 @@ -806,6 +807,179 @@ nsEventStateManager::ChangeTextSize(PRInt32 change) return NS_OK; } +nsresult +nsEventStateManager::DoWheelScroll(nsIPresContext* aPresContext, + nsIFrame* aTargetFrame, + nsMouseScrollEvent* msEvent, + PRInt32 numLines, PRBool scrollPage, + PRBool aUseTargetFrame) +{ + nsIView* focusView = nsnull; + nsIScrollableView* sv = nsnull; + nsIFrame* focusFrame = nsnull; + + // Special case for tree/list frames - they handle their own scrolling + nsITreeFrame* treeFrame = nsnull; + nsIFrame* curFrame = aTargetFrame; + + while (curFrame) { + if (NS_OK == curFrame->QueryInterface(NS_GET_IID(nsITreeFrame), + (void**) &treeFrame)) + break; + curFrame->GetParent(&curFrame); + } + + if (treeFrame) { + PRInt32 scrollIndex, visibleRows; + treeFrame->GetIndexOfFirstVisibleRow(&scrollIndex); + treeFrame->GetNumberOfVisibleRows(&visibleRows); + + if (scrollPage) + scrollIndex += ((numLines > 0) ? visibleRows : -visibleRows); + else + scrollIndex += numLines; + + if (scrollIndex < 0) + scrollIndex = 0; + else { + PRInt32 numRows, lastPageTopRow; + treeFrame->GetRowCount(&numRows); + lastPageTopRow = numRows - visibleRows; + if (scrollIndex > lastPageTopRow) + scrollIndex = lastPageTopRow; + } + + treeFrame->ScrollToIndex(scrollIndex); + return NS_OK; + } + + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + + // Otherwise, check for a focused content element + nsCOMPtr focusContent; + if (mCurrentFocus) { + focusContent = mCurrentFocus; + } + else { + // If there is no focused content, get the document content + EnsureDocument(presShell); + focusContent = dont_AddRef(mDocument->GetRootContent()); + } + + if (!focusContent) + return NS_ERROR_FAILURE; + + if (aUseTargetFrame) + focusFrame = aTargetFrame; + else + presShell->GetPrimaryFrameFor(focusContent, &focusFrame); + + if (!focusFrame) + return NS_ERROR_FAILURE; + + // Now check whether this frame wants to provide us with an + // nsIScrollableView to use for scrolling. + + nsCOMPtr svp = do_QueryInterface(focusFrame); + if (svp) { + svp->GetScrollableView(&sv); + sv->QueryInterface(NS_GET_IID(nsIView), (void**) &focusView); + } else { + focusFrame->GetView(aPresContext, &focusView); + if (!focusView) { + nsIFrame* frameWithView; + focusFrame->GetParentWithView(aPresContext, &frameWithView); + if (frameWithView) + frameWithView->GetView(aPresContext, &focusView); + else + return NS_ERROR_FAILURE; + } + + sv = GetNearestScrollingView(focusView); + } + + if (sv) { + if (scrollPage) + sv->ScrollByPages((numLines > 0) ? 1 : -1); + else + sv->ScrollByLines(0, numLines); + + if (focusView) + ForceViewUpdate(focusView); + } else { + nsresult rv; + nsIFrame* newFrame = nsnull; + nsCOMPtr newPresContext; + + rv = GetParentScrollingView(msEvent, aPresContext, newFrame, + *getter_AddRefs(newPresContext)); + if (NS_SUCCEEDED(rv)) + return DoWheelScroll(newPresContext, newFrame, msEvent, numLines, + scrollPage, PR_TRUE); + else + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +nsresult +nsEventStateManager::GetParentScrollingView(nsMouseScrollEvent *aEvent, + nsIPresContext* aPresContext, + nsIFrame* &targetOuterFrame, + nsIPresContext* &presCtxOuter) +{ + if (!aEvent) return NS_ERROR_FAILURE; + if (!aPresContext) return NS_ERROR_FAILURE; + + nsCOMPtr shell; + aPresContext->GetContainer(getter_AddRefs(shell)); + if (!shell) return NS_ERROR_FAILURE; + + nsCOMPtr treeItem = do_QueryInterface(shell); + if (!treeItem) return NS_ERROR_FAILURE; + + nsCOMPtr parent; + treeItem->GetParent(getter_AddRefs(parent)); + if (!parent) return NS_ERROR_FAILURE; + + nsCOMPtr pDocShell = do_QueryInterface(parent); + if (!pDocShell) return NS_ERROR_FAILURE; + + nsCOMPtr presShell; + pDocShell->GetPresShell(getter_AddRefs(presShell)); + if (!presShell) return NS_ERROR_FAILURE; + + nsIFrame* rootFrame = nsnull; + presShell->GetRootFrame(&rootFrame); + if (!rootFrame) return NS_ERROR_FAILURE; + + presShell->GetPresContext(&presCtxOuter); //addrefs + + nsPoint eventPoint; + rootFrame->GetOrigin(eventPoint); + eventPoint += aEvent->point; + + nsresult rv; + rv = rootFrame->GetFrameForPoint(presCtxOuter, eventPoint, + NS_FRAME_PAINT_LAYER_FOREGROUND, + &targetOuterFrame); + if (rv != NS_OK) { + rv = rootFrame->GetFrameForPoint(presCtxOuter, eventPoint, + NS_FRAME_PAINT_LAYER_FLOATERS, + &targetOuterFrame); + if (rv != NS_OK) { + rv = rootFrame->GetFrameForPoint(presCtxOuter, eventPoint, + NS_FRAME_PAINT_LAYER_BACKGROUND, + &targetOuterFrame); + if (rv != NS_OK) return NS_ERROR_FAILURE; + } + } + + return NS_OK; +} + NS_IMETHODIMP nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext, nsEvent *aEvent, @@ -976,82 +1150,11 @@ nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext, case MOUSE_SCROLL_N_LINES: case MOUSE_SCROLL_PAGE: { - nsIView* focusView = nsnull; - nsIScrollableView* sv = nsnull; - nsIFrame* focusFrame = nsnull; + nsresult rv = DoWheelScroll(aPresContext, aTargetFrame, msEvent, + numLines, + (action == MOUSE_SCROLL_PAGE), + PR_FALSE); - // Special case for tree frames - they handle their own scrolling - nsITreeFrame* treeFrame = nsnull; - nsIFrame* curFrame = aTargetFrame; - - while (curFrame) { - if (NS_OK == curFrame->QueryInterface(NS_GET_IID(nsITreeFrame), (void**) &treeFrame)) - break; - curFrame->GetParent(&curFrame); - } - - if (treeFrame) { - PRInt32 scrollIndex, visibleRows; - treeFrame->GetIndexOfFirstVisibleRow(&scrollIndex); - treeFrame->GetNumberOfVisibleRows(&visibleRows); - - if (action == MOUSE_SCROLL_N_LINES) - scrollIndex += numLines; - else - scrollIndex += ((numLines > 0) ? visibleRows : -visibleRows); - - if (scrollIndex < 0) - scrollIndex = 0; - else { - PRInt32 numRows, lastPageTopRow; - treeFrame->GetRowCount(&numRows); - lastPageTopRow = numRows - visibleRows; - if (scrollIndex > lastPageTopRow) - scrollIndex = lastPageTopRow; - } - - treeFrame->ScrollToIndex(scrollIndex); - break; - } - - nsCOMPtr presShell; - aPresContext->GetShell(getter_AddRefs(presShell)); - - // Otherwise, check for a focused content element - nsCOMPtr focusContent; - if (mCurrentFocus) - focusContent = mCurrentFocus; - else { - // If there is no focused content, get the document content - EnsureDocument(presShell); - focusContent = dont_AddRef(mDocument->GetRootContent()); - } - - if (!focusContent) - break; - - presShell->GetPrimaryFrameFor(focusContent, &focusFrame); - if (!focusFrame) - break; - - focusFrame->GetView(aPresContext, &focusView); - if (!focusView) { - nsIFrame* frameWithView; - focusFrame->GetParentWithView(aPresContext, &frameWithView); - if (frameWithView) - frameWithView->GetView(aPresContext, &focusView); - else - break; - } - - sv = GetNearestScrollingView(focusView); - if (sv) { - if (action == MOUSE_SCROLL_N_LINES) - sv->ScrollByLines(0, numLines); - else - sv->ScrollByPages((numLines > 0) ? 1 : -1); - ForceViewUpdate(focusView); - } } break; diff --git a/mozilla/content/events/src/nsEventStateManager.h b/mozilla/content/events/src/nsEventStateManager.h index 357896a0e5c..7f0765a3af6 100644 --- a/mozilla/content/events/src/nsEventStateManager.h +++ b/mozilla/content/events/src/nsEventStateManager.h @@ -119,6 +119,14 @@ protected: // These functions are for mousewheel scrolling nsIScrollableView* GetNearestScrollingView(nsIView* aView); + nsresult GetParentScrollingView(nsMouseScrollEvent* aEvent, + nsIPresContext* aPresContext, + nsIFrame* &targetOuterFrame, + nsIPresContext* &presCtxOuter); + nsresult DoWheelScroll(nsIPresContext* aPresContext, + nsIFrame* aTargetFrame, + nsMouseScrollEvent* msEvent, PRInt32 numLines, + PRBool scrollPage, PRBool aUseTargetFrame); void ForceViewUpdate(nsIView* aView); nsresult getPrefService(); nsresult ChangeTextSize(PRInt32 change); diff --git a/mozilla/layout/base/public/MANIFEST b/mozilla/layout/base/public/MANIFEST index d3b48dd6a5b..e4ab7a685b2 100644 --- a/mozilla/layout/base/public/MANIFEST +++ b/mozilla/layout/base/public/MANIFEST @@ -62,3 +62,4 @@ nsIScrollableFrame.h nsIPrivateDOMImplementation.h nsIContentSerializer.h nsIHTMLToTextSink.h +nsIScrollableViewProvider.h diff --git a/mozilla/layout/base/public/Makefile.in b/mozilla/layout/base/public/Makefile.in index c3eeddc7968..3c8d078faea 100644 --- a/mozilla/layout/base/public/Makefile.in +++ b/mozilla/layout/base/public/Makefile.in @@ -91,6 +91,7 @@ nsIScrollableFrame.h \ nsIPrivateDOMImplementation.h \ nsIContentSerializer.h \ nsIHTMLToTextSink.h \ +nsIScrollableViewProvider.h \ $(NULL) XPIDLSRCS = \ diff --git a/mozilla/layout/base/public/makefile.win b/mozilla/layout/base/public/makefile.win index 7fd361f3636..96851826cd8 100644 --- a/mozilla/layout/base/public/makefile.win +++ b/mozilla/layout/base/public/makefile.win @@ -83,6 +83,7 @@ EXPORTS = \ nsIPrivateDOMImplementation.h \ nsIContentSerializer.h \ nsIHTMLToTextSink.h \ + nsIScrollableViewProvider.h \ $(NULL) MODULE=layout_base diff --git a/mozilla/layout/base/public/nsIScrollableViewProvider.h b/mozilla/layout/base/public/nsIScrollableViewProvider.h new file mode 100644 index 00000000000..622a7cacbf6 --- /dev/null +++ b/mozilla/layout/base/public/nsIScrollableViewProvider.h @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#ifndef _nsIScrollableViewProvider_h +#define _nsIScrollableViewProvider_h + +#include "nsISupports.h" + +#define NS_ISCROLLABLEVIEWPROVIDER_IID_STR "2b2e0d30-1dd2-11b2-9169-eb82b04f6775" + +#define NS_ISCROLLABLEVIEWPROVIDER_IID \ +{0x2b2e0d30, 0x1dd2, 0x11b2, \ +{0x91, 0x69, 0xeb, 0x82, 0xb0, 0x4f, 0x67, 0x75}} + +class nsIScrollableView; + +class nsIScrollableViewProvider : public nsISupports { + public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISCROLLABLEVIEWPROVIDER_IID) + + NS_IMETHOD GetScrollableView(nsIScrollableView** aView)=0; +}; + +#endif /* _nsIScrollableViewProvider_h */ diff --git a/mozilla/layout/events/src/nsEventStateManager.cpp b/mozilla/layout/events/src/nsEventStateManager.cpp index 402a0934dcc..7134eae1185 100644 --- a/mozilla/layout/events/src/nsEventStateManager.cpp +++ b/mozilla/layout/events/src/nsEventStateManager.cpp @@ -71,6 +71,7 @@ #include "nsIDocShell.h" #include "nsIMarkupDocumentViewer.h" #include "nsITreeFrame.h" +#include "nsIScrollableViewProvider.h" //we will use key binding by default now. this wil lbreak viewer for now #define NON_KEYBINDING 0 @@ -806,6 +807,179 @@ nsEventStateManager::ChangeTextSize(PRInt32 change) return NS_OK; } +nsresult +nsEventStateManager::DoWheelScroll(nsIPresContext* aPresContext, + nsIFrame* aTargetFrame, + nsMouseScrollEvent* msEvent, + PRInt32 numLines, PRBool scrollPage, + PRBool aUseTargetFrame) +{ + nsIView* focusView = nsnull; + nsIScrollableView* sv = nsnull; + nsIFrame* focusFrame = nsnull; + + // Special case for tree/list frames - they handle their own scrolling + nsITreeFrame* treeFrame = nsnull; + nsIFrame* curFrame = aTargetFrame; + + while (curFrame) { + if (NS_OK == curFrame->QueryInterface(NS_GET_IID(nsITreeFrame), + (void**) &treeFrame)) + break; + curFrame->GetParent(&curFrame); + } + + if (treeFrame) { + PRInt32 scrollIndex, visibleRows; + treeFrame->GetIndexOfFirstVisibleRow(&scrollIndex); + treeFrame->GetNumberOfVisibleRows(&visibleRows); + + if (scrollPage) + scrollIndex += ((numLines > 0) ? visibleRows : -visibleRows); + else + scrollIndex += numLines; + + if (scrollIndex < 0) + scrollIndex = 0; + else { + PRInt32 numRows, lastPageTopRow; + treeFrame->GetRowCount(&numRows); + lastPageTopRow = numRows - visibleRows; + if (scrollIndex > lastPageTopRow) + scrollIndex = lastPageTopRow; + } + + treeFrame->ScrollToIndex(scrollIndex); + return NS_OK; + } + + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + + // Otherwise, check for a focused content element + nsCOMPtr focusContent; + if (mCurrentFocus) { + focusContent = mCurrentFocus; + } + else { + // If there is no focused content, get the document content + EnsureDocument(presShell); + focusContent = dont_AddRef(mDocument->GetRootContent()); + } + + if (!focusContent) + return NS_ERROR_FAILURE; + + if (aUseTargetFrame) + focusFrame = aTargetFrame; + else + presShell->GetPrimaryFrameFor(focusContent, &focusFrame); + + if (!focusFrame) + return NS_ERROR_FAILURE; + + // Now check whether this frame wants to provide us with an + // nsIScrollableView to use for scrolling. + + nsCOMPtr svp = do_QueryInterface(focusFrame); + if (svp) { + svp->GetScrollableView(&sv); + sv->QueryInterface(NS_GET_IID(nsIView), (void**) &focusView); + } else { + focusFrame->GetView(aPresContext, &focusView); + if (!focusView) { + nsIFrame* frameWithView; + focusFrame->GetParentWithView(aPresContext, &frameWithView); + if (frameWithView) + frameWithView->GetView(aPresContext, &focusView); + else + return NS_ERROR_FAILURE; + } + + sv = GetNearestScrollingView(focusView); + } + + if (sv) { + if (scrollPage) + sv->ScrollByPages((numLines > 0) ? 1 : -1); + else + sv->ScrollByLines(0, numLines); + + if (focusView) + ForceViewUpdate(focusView); + } else { + nsresult rv; + nsIFrame* newFrame = nsnull; + nsCOMPtr newPresContext; + + rv = GetParentScrollingView(msEvent, aPresContext, newFrame, + *getter_AddRefs(newPresContext)); + if (NS_SUCCEEDED(rv)) + return DoWheelScroll(newPresContext, newFrame, msEvent, numLines, + scrollPage, PR_TRUE); + else + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +nsresult +nsEventStateManager::GetParentScrollingView(nsMouseScrollEvent *aEvent, + nsIPresContext* aPresContext, + nsIFrame* &targetOuterFrame, + nsIPresContext* &presCtxOuter) +{ + if (!aEvent) return NS_ERROR_FAILURE; + if (!aPresContext) return NS_ERROR_FAILURE; + + nsCOMPtr shell; + aPresContext->GetContainer(getter_AddRefs(shell)); + if (!shell) return NS_ERROR_FAILURE; + + nsCOMPtr treeItem = do_QueryInterface(shell); + if (!treeItem) return NS_ERROR_FAILURE; + + nsCOMPtr parent; + treeItem->GetParent(getter_AddRefs(parent)); + if (!parent) return NS_ERROR_FAILURE; + + nsCOMPtr pDocShell = do_QueryInterface(parent); + if (!pDocShell) return NS_ERROR_FAILURE; + + nsCOMPtr presShell; + pDocShell->GetPresShell(getter_AddRefs(presShell)); + if (!presShell) return NS_ERROR_FAILURE; + + nsIFrame* rootFrame = nsnull; + presShell->GetRootFrame(&rootFrame); + if (!rootFrame) return NS_ERROR_FAILURE; + + presShell->GetPresContext(&presCtxOuter); //addrefs + + nsPoint eventPoint; + rootFrame->GetOrigin(eventPoint); + eventPoint += aEvent->point; + + nsresult rv; + rv = rootFrame->GetFrameForPoint(presCtxOuter, eventPoint, + NS_FRAME_PAINT_LAYER_FOREGROUND, + &targetOuterFrame); + if (rv != NS_OK) { + rv = rootFrame->GetFrameForPoint(presCtxOuter, eventPoint, + NS_FRAME_PAINT_LAYER_FLOATERS, + &targetOuterFrame); + if (rv != NS_OK) { + rv = rootFrame->GetFrameForPoint(presCtxOuter, eventPoint, + NS_FRAME_PAINT_LAYER_BACKGROUND, + &targetOuterFrame); + if (rv != NS_OK) return NS_ERROR_FAILURE; + } + } + + return NS_OK; +} + NS_IMETHODIMP nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext, nsEvent *aEvent, @@ -976,82 +1150,11 @@ nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext, case MOUSE_SCROLL_N_LINES: case MOUSE_SCROLL_PAGE: { - nsIView* focusView = nsnull; - nsIScrollableView* sv = nsnull; - nsIFrame* focusFrame = nsnull; + nsresult rv = DoWheelScroll(aPresContext, aTargetFrame, msEvent, + numLines, + (action == MOUSE_SCROLL_PAGE), + PR_FALSE); - // Special case for tree frames - they handle their own scrolling - nsITreeFrame* treeFrame = nsnull; - nsIFrame* curFrame = aTargetFrame; - - while (curFrame) { - if (NS_OK == curFrame->QueryInterface(NS_GET_IID(nsITreeFrame), (void**) &treeFrame)) - break; - curFrame->GetParent(&curFrame); - } - - if (treeFrame) { - PRInt32 scrollIndex, visibleRows; - treeFrame->GetIndexOfFirstVisibleRow(&scrollIndex); - treeFrame->GetNumberOfVisibleRows(&visibleRows); - - if (action == MOUSE_SCROLL_N_LINES) - scrollIndex += numLines; - else - scrollIndex += ((numLines > 0) ? visibleRows : -visibleRows); - - if (scrollIndex < 0) - scrollIndex = 0; - else { - PRInt32 numRows, lastPageTopRow; - treeFrame->GetRowCount(&numRows); - lastPageTopRow = numRows - visibleRows; - if (scrollIndex > lastPageTopRow) - scrollIndex = lastPageTopRow; - } - - treeFrame->ScrollToIndex(scrollIndex); - break; - } - - nsCOMPtr presShell; - aPresContext->GetShell(getter_AddRefs(presShell)); - - // Otherwise, check for a focused content element - nsCOMPtr focusContent; - if (mCurrentFocus) - focusContent = mCurrentFocus; - else { - // If there is no focused content, get the document content - EnsureDocument(presShell); - focusContent = dont_AddRef(mDocument->GetRootContent()); - } - - if (!focusContent) - break; - - presShell->GetPrimaryFrameFor(focusContent, &focusFrame); - if (!focusFrame) - break; - - focusFrame->GetView(aPresContext, &focusView); - if (!focusView) { - nsIFrame* frameWithView; - focusFrame->GetParentWithView(aPresContext, &frameWithView); - if (frameWithView) - frameWithView->GetView(aPresContext, &focusView); - else - break; - } - - sv = GetNearestScrollingView(focusView); - if (sv) { - if (action == MOUSE_SCROLL_N_LINES) - sv->ScrollByLines(0, numLines); - else - sv->ScrollByPages((numLines > 0) ? 1 : -1); - ForceViewUpdate(focusView); - } } break; diff --git a/mozilla/layout/events/src/nsEventStateManager.h b/mozilla/layout/events/src/nsEventStateManager.h index 357896a0e5c..7f0765a3af6 100644 --- a/mozilla/layout/events/src/nsEventStateManager.h +++ b/mozilla/layout/events/src/nsEventStateManager.h @@ -119,6 +119,14 @@ protected: // These functions are for mousewheel scrolling nsIScrollableView* GetNearestScrollingView(nsIView* aView); + nsresult GetParentScrollingView(nsMouseScrollEvent* aEvent, + nsIPresContext* aPresContext, + nsIFrame* &targetOuterFrame, + nsIPresContext* &presCtxOuter); + nsresult DoWheelScroll(nsIPresContext* aPresContext, + nsIFrame* aTargetFrame, + nsMouseScrollEvent* msEvent, PRInt32 numLines, + PRBool scrollPage, PRBool aUseTargetFrame); void ForceViewUpdate(nsIView* aView); nsresult getPrefService(); nsresult ChangeTextSize(PRInt32 change); diff --git a/mozilla/layout/forms/nsComboboxControlFrame.cpp b/mozilla/layout/forms/nsComboboxControlFrame.cpp index 4460a44522c..f5a6c7bd8bd 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.cpp +++ b/mozilla/layout/forms/nsComboboxControlFrame.cpp @@ -299,6 +299,9 @@ nsComboboxControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) } else if (aIID.Equals(NS_GET_IID(nsIRollupListener))) { *aInstancePtr = (void*)(nsIRollupListener*)this; return NS_OK; + } else if (aIID.Equals(NS_GET_IID(nsIScrollableViewProvider))) { + *aInstancePtr = (void*)(nsIScrollableViewProvider*)this; + return NS_OK; } return nsAreaFrame::QueryInterface(aIID, aInstancePtr); } @@ -2485,4 +2488,21 @@ nsComboboxControlFrame::Paint(nsIPresContext* aPresContext, return nsFrame::Paint(aPresContext,aRenderingContext,aDirtyRect,aWhichLayer); } +//---------------------------------------------------------------------- + //nsIScrollableViewProvider +//---------------------------------------------------------------------- +NS_METHOD +nsComboboxControlFrame::GetScrollableView(nsIScrollableView** aView) +{ + *aView = nsnull; + nsIView* view = nsnull; + mDropdownFrame->GetView(mPresContext, &view); + if (view) { + nsIScrollableView* sv = nsnull; + nsresult rv = view->QueryInterface(NS_GET_IID(nsIScrollableView), (void**) &sv); + if (NS_SUCCEEDED(rv) && sv) + *aView = sv; + } + return NS_OK; +} diff --git a/mozilla/layout/forms/nsComboboxControlFrame.h b/mozilla/layout/forms/nsComboboxControlFrame.h index 53cf8f6f24a..4584222a836 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.h +++ b/mozilla/layout/forms/nsComboboxControlFrame.h @@ -46,12 +46,14 @@ #include "nsIPresState.h" #include "nsCSSFrameConstructor.h" #include "nsITextContent.h" +#include "nsIScrollableViewProvider.h" class nsFormFrame; class nsIView; class nsStyleContext; class nsIHTMLContent; class nsIListControlFrame; +class nsIScrollableView; /** * Child list name indices @@ -65,7 +67,8 @@ class nsComboboxControlFrame : public nsAreaFrame, public nsIAnonymousContentCreator, public nsISelectControlFrame, public nsIStatefulFrame, - public nsIRollupListener + public nsIRollupListener, + public nsIScrollableViewProvider { public: friend nsresult NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags); @@ -180,7 +183,10 @@ public: //nsIRollupListener // NS_DECL_NSIROLLUPLISTENER NS_IMETHOD Rollup(); - NS_IMETHOD ShouldRollupOnMouseWheelEvent(PRBool *aShouldRollup) { *aShouldRollup = PR_FALSE; return NS_OK;} + // a combobox should roll up if a mousewheel event happens outside of + // the popup area + NS_IMETHOD ShouldRollupOnMouseWheelEvent(PRBool *aShouldRollup) + { *aShouldRollup = PR_TRUE; return NS_OK;} //NS_IMETHOD ShouldRollupOnMouseWheelEvent(nsIWidget *aWidget, PRBool *aShouldRollup) //{ *aShouldRollup = PR_FALSE; return NS_OK;} @@ -188,6 +194,9 @@ public: NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor) { mFrameConstructor = aConstructor; return NS_OK;} // not owner - do not addref! + // nsIScrollableViewProvider + NS_IMETHOD GetScrollableView(nsIScrollableView** aView); + protected: NS_IMETHOD CreateDisplayFrame(nsIPresContext* aPresContext); diff --git a/mozilla/layout/generic/nsIScrollableViewProvider.h b/mozilla/layout/generic/nsIScrollableViewProvider.h new file mode 100644 index 00000000000..622a7cacbf6 --- /dev/null +++ b/mozilla/layout/generic/nsIScrollableViewProvider.h @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#ifndef _nsIScrollableViewProvider_h +#define _nsIScrollableViewProvider_h + +#include "nsISupports.h" + +#define NS_ISCROLLABLEVIEWPROVIDER_IID_STR "2b2e0d30-1dd2-11b2-9169-eb82b04f6775" + +#define NS_ISCROLLABLEVIEWPROVIDER_IID \ +{0x2b2e0d30, 0x1dd2, 0x11b2, \ +{0x91, 0x69, 0xeb, 0x82, 0xb0, 0x4f, 0x67, 0x75}} + +class nsIScrollableView; + +class nsIScrollableViewProvider : public nsISupports { + public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISCROLLABLEVIEWPROVIDER_IID) + + NS_IMETHOD GetScrollableView(nsIScrollableView** aView)=0; +}; + +#endif /* _nsIScrollableViewProvider_h */ diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp index 4460a44522c..f5a6c7bd8bd 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -299,6 +299,9 @@ nsComboboxControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) } else if (aIID.Equals(NS_GET_IID(nsIRollupListener))) { *aInstancePtr = (void*)(nsIRollupListener*)this; return NS_OK; + } else if (aIID.Equals(NS_GET_IID(nsIScrollableViewProvider))) { + *aInstancePtr = (void*)(nsIScrollableViewProvider*)this; + return NS_OK; } return nsAreaFrame::QueryInterface(aIID, aInstancePtr); } @@ -2485,4 +2488,21 @@ nsComboboxControlFrame::Paint(nsIPresContext* aPresContext, return nsFrame::Paint(aPresContext,aRenderingContext,aDirtyRect,aWhichLayer); } +//---------------------------------------------------------------------- + //nsIScrollableViewProvider +//---------------------------------------------------------------------- +NS_METHOD +nsComboboxControlFrame::GetScrollableView(nsIScrollableView** aView) +{ + *aView = nsnull; + nsIView* view = nsnull; + mDropdownFrame->GetView(mPresContext, &view); + if (view) { + nsIScrollableView* sv = nsnull; + nsresult rv = view->QueryInterface(NS_GET_IID(nsIScrollableView), (void**) &sv); + if (NS_SUCCEEDED(rv) && sv) + *aView = sv; + } + return NS_OK; +} diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h index 53cf8f6f24a..4584222a836 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.h +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.h @@ -46,12 +46,14 @@ #include "nsIPresState.h" #include "nsCSSFrameConstructor.h" #include "nsITextContent.h" +#include "nsIScrollableViewProvider.h" class nsFormFrame; class nsIView; class nsStyleContext; class nsIHTMLContent; class nsIListControlFrame; +class nsIScrollableView; /** * Child list name indices @@ -65,7 +67,8 @@ class nsComboboxControlFrame : public nsAreaFrame, public nsIAnonymousContentCreator, public nsISelectControlFrame, public nsIStatefulFrame, - public nsIRollupListener + public nsIRollupListener, + public nsIScrollableViewProvider { public: friend nsresult NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags); @@ -180,7 +183,10 @@ public: //nsIRollupListener // NS_DECL_NSIROLLUPLISTENER NS_IMETHOD Rollup(); - NS_IMETHOD ShouldRollupOnMouseWheelEvent(PRBool *aShouldRollup) { *aShouldRollup = PR_FALSE; return NS_OK;} + // a combobox should roll up if a mousewheel event happens outside of + // the popup area + NS_IMETHOD ShouldRollupOnMouseWheelEvent(PRBool *aShouldRollup) + { *aShouldRollup = PR_TRUE; return NS_OK;} //NS_IMETHOD ShouldRollupOnMouseWheelEvent(nsIWidget *aWidget, PRBool *aShouldRollup) //{ *aShouldRollup = PR_FALSE; return NS_OK;} @@ -188,6 +194,9 @@ public: NS_IMETHOD SetFrameConstructor(nsCSSFrameConstructor *aConstructor) { mFrameConstructor = aConstructor; return NS_OK;} // not owner - do not addref! + // nsIScrollableViewProvider + NS_IMETHOD GetScrollableView(nsIScrollableView** aView); + protected: NS_IMETHOD CreateDisplayFrame(nsIPresContext* aPresContext); diff --git a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp index d403cc3117d..54b8d5466bd 100644 --- a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp +++ b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp @@ -1072,6 +1072,10 @@ nsGfxTextControlFrame2::QueryInterface(const nsIID& aIID, void** aInstancePtr) *aInstancePtr = (void*)(nsIStatefulFrame*) this; return NS_OK; } + if (aIID.Equals(NS_GET_IID(nsIScrollableViewProvider))) { + *aInstancePtr = (void*)(nsIScrollableViewProvider*) this; + return NS_OK; + } return nsBoxFrame::QueryInterface(aIID, aInstancePtr); } @@ -3178,4 +3182,11 @@ nsGfxTextControlFrame2::RestoreState(nsIPresContext* aPresContext, nsIPresState* return res; } +NS_IMETHODIMP +nsGfxTextControlFrame2::GetScrollableView(nsIScrollableView** aView) +{ + *aView = mScrollableView; + return NS_OK; +} + #endif diff --git a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.h b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.h index 33a6382561e..9da3e3151f6 100644 --- a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.h +++ b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.h @@ -35,6 +35,7 @@ #include "nsHTMLValue.h" //for nsHTMLValue #include "nsIFontMetrics.h" #include "nsWeakReference.h" //for service and presshell pointers +#include "nsIScrollableViewProvider.h" class nsIPresState; class nsGfxTextControlFrame; @@ -53,7 +54,8 @@ class nsGfxTextControlFrame2 : public nsStackFrame, public nsIAnonymousContentCreator, public nsIFormControlFrame, public nsIGfxTextControlFrame2, - public nsIStatefulFrame + public nsIStatefulFrame, + public nsIScrollableViewProvider { public: @@ -220,6 +222,8 @@ protected: NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState); NS_IMETHOD RestoreState(nsIPresContext* aPresContext, nsIPresState* aState); + // nsIScrollableViewProvider + NS_IMETHOD GetScrollableView(nsIScrollableView** aView); private: //helper methods diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.cpp b/mozilla/layout/xul/base/src/nsMenuFrame.cpp index f6da405b8ae..523a7533a79 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuFrame.cpp @@ -64,6 +64,7 @@ #include "nsCSSFrameConstructor.h" #include "nsIDOMKeyEvent.h" #include "nsIPref.h" +#include "nsIScrollableView.h" #define NS_MENU_POPUP_LIST_INDEX 0 @@ -115,6 +116,7 @@ nsMenuFrame::Release(void) NS_INTERFACE_MAP_BEGIN(nsMenuFrame) NS_INTERFACE_MAP_ENTRY(nsITimerCallback) NS_INTERFACE_MAP_ENTRY(nsIMenuFrame) + NS_INTERFACE_MAP_ENTRY(nsIScrollableViewProvider) NS_INTERFACE_MAP_END_INHERITING(nsBoxFrame) // @@ -1638,6 +1640,25 @@ nsMenuFrame::SetActiveChild(nsIDOMElement* aChild) return NS_OK; } +NS_IMETHODIMP +nsMenuFrame::GetScrollableView(nsIScrollableView** aView) +{ + *aView = nsnull; + if (!mPopupFrames.FirstChild()) + return NS_OK; + + nsMenuPopupFrame* popup = (nsMenuPopupFrame*) mPopupFrames.FirstChild(); + nsIFrame* childFrame = nsnull; + popup->FirstChild(mPresContext, nsnull, &childFrame); + if (childFrame) { + *aView = popup->GetScrollableView(childFrame); + nsRect itemRect; + childFrame->GetRect(itemRect); + (*aView)->SetLineHeight(itemRect.height); + } + + return NS_OK; +} /* Need to figure out what this does. NS_IMETHODIMP diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.h b/mozilla/layout/xul/base/src/nsMenuFrame.h index cf0b0f36d0d..439f8111234 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.h +++ b/mozilla/layout/xul/base/src/nsMenuFrame.h @@ -43,16 +43,19 @@ #include "nsISupportsArray.h" #include "nsIDOMText.h" #include "nsIContent.h" +#include "nsIScrollableViewProvider.h" nsresult NS_NewMenuFrame(nsIPresShell* aPresShell, nsIFrame** aResult, PRUint32 aFlags) ; class nsMenuBarFrame; class nsMenuPopupFrame; class nsCSSFrameConstructor; +class nsIScrollableView; class nsMenuFrame : public nsBoxFrame, public nsIMenuFrame, - public nsITimerCallback + public nsITimerCallback, + public nsIScrollableViewProvider { public: nsMenuFrame(nsIPresShell* aShell); @@ -145,6 +148,10 @@ public: NS_IMETHOD MarkChildrenStyleChange(); NS_IMETHOD MarkAsGenerated(); + // nsIScrollableViewProvider methods + + NS_IMETHOD GetScrollableView(nsIScrollableView** aView); + // nsMenuFrame methods PRBool IsOpen() { return mMenuOpen; }; diff --git a/mozilla/layout/xul/base/src/nsMenuPopupFrame.h b/mozilla/layout/xul/base/src/nsMenuPopupFrame.h index 40bba7a4a7b..869eb7704d7 100644 --- a/mozilla/layout/xul/base/src/nsMenuPopupFrame.h +++ b/mozilla/layout/xul/base/src/nsMenuPopupFrame.h @@ -137,7 +137,8 @@ public: } void EnsureMenuItemIsVisible(nsIMenuFrame* aMenuFrame); - + nsIScrollableView* GetScrollableView(nsIFrame* aStart); + protected: // redefine to tell the box system not to move the // views. @@ -164,8 +165,6 @@ protected: const nsRect & inScreenParentFrameRect, PRInt32 inScreenTopTwips, PRInt32 inScreenLeftTwips, PRInt32 inScreenBottomTwips, PRInt32 inScreenRightTwips ) ; - nsIScrollableView* GetScrollableView(nsIFrame* aStart); - nsIMenuFrame* mCurrentMenu; // The current menu that is active. PRBool mIsCapturingMouseEvents; // Whether or not we're grabbing the mouse events. // XXX Hack diff --git a/mozilla/widget/src/gtk/nsWidget.cpp b/mozilla/widget/src/gtk/nsWidget.cpp index 28fec839120..b970a808d7e 100644 --- a/mozilla/widget/src/gtk/nsWidget.cpp +++ b/mozilla/widget/src/gtk/nsWidget.cpp @@ -1850,7 +1850,7 @@ nsWidget :: IsMouseInWindow ( GdkWindow* inWindow, PRInt32 inMouseX, PRInt32 inM // Deal with rollup of popups (xpmenus, etc) // PRBool -nsWidget :: HandlePopup ( PRInt32 inMouseX, PRInt32 inMouseY ) +nsWidget::HandlePopup(PRInt32 inMouseX, PRInt32 inMouseY, PRBool isWheel) { PRBool retVal = PR_FALSE; nsCOMPtr rollupWidget = do_QueryReferent(gRollupWidget); @@ -1859,6 +1859,10 @@ nsWidget :: HandlePopup ( PRInt32 inMouseX, PRInt32 inMouseY ) GdkWindow *currentPopup = (GdkWindow *)rollupWidget->GetNativeData(NS_NATIVE_WINDOW); if ( !IsMouseInWindow(currentPopup, inMouseX, inMouseY) ) { PRBool rollup = PR_TRUE; + if (isWheel) { + gRollupListener->ShouldRollupOnMouseWheelEvent(&rollup); + retVal = PR_TRUE; + } // if we're dealing with menus, we probably have submenus and we don't // want to rollup if the clickis in a parent menu of the current submenu nsCOMPtr menuRollup ( do_QueryInterface(gRollupListener) ); @@ -1906,7 +1910,9 @@ nsWidget::OnButtonPressSignal(GdkEventButton * aGdkButtonEvent) nsMouseScrollEvent scrollEvent; PRUint32 eventType = 0; - if ( HandlePopup(aGdkButtonEvent->x_root, aGdkButtonEvent->y_root) ) + PRBool isWheel = (aGdkButtonEvent->button == 4 || + aGdkButtonEvent->button == 5); + if (HandlePopup(aGdkButtonEvent->x_root, aGdkButtonEvent->y_root, isWheel)) return; // Switch on single, double, triple click. diff --git a/mozilla/widget/src/gtk/nsWidget.h b/mozilla/widget/src/gtk/nsWidget.h index 77356d08d01..ab8718c58a8 100644 --- a/mozilla/widget/src/gtk/nsWidget.h +++ b/mozilla/widget/src/gtk/nsWidget.h @@ -305,7 +305,7 @@ protected: static void SuppressModality(PRBool aSuppress); // Deal with rollup for popups - PRBool HandlePopup ( PRInt32 inMouseX, PRInt32 inMouseY ) ; + PRBool HandlePopup(PRInt32 inMouseX, PRInt32 inMouseY, PRBool isWheel); PRBool IsMouseInWindow ( GdkWindow* inWindow, PRInt32 inMouseX, PRInt32 inMouseY ) ; #ifdef USE_XIM diff --git a/mozilla/widget/src/windows/nsWindow.cpp b/mozilla/widget/src/windows/nsWindow.cpp index 3cab3d449a5..c3329b1670d 100644 --- a/mozilla/widget/src/windows/nsWindow.cpp +++ b/mozilla/widget/src/windows/nsWindow.cpp @@ -829,40 +829,20 @@ nsWindow :: DealWithPopups ( UINT inMsg, LRESULT* outResult ) { if ( gRollupListener && gRollupWidget) { - // All mouse wheel events cause the popup to rollup. - // XXX: Need something more reliable then WM_MOUSEWHEEL. - // This event is not always generated. The mouse wheel - // is plugged into the scrollbar scrolling in odd ways - // which make it difficult to find a message which will - // reliably be generated when the mouse wheel changes position - if ((inMsg == WM_MOUSEWHEEL) || (inMsg == uMSH_MOUSEWHEEL)) { - - // XXX Turn on ifdef or remove the "else" part of this ifdef when - // Bug 33733 is fixed -#if 0 - PRBool doRollup; - gRollupListener->ShouldRollupOnMouseWheelEvent(&doRollup); - if (!doRollup) { - *outResult = FALSE; - return FALSE; - } else { - gRollupListener->Rollup(); - *outResult = TRUE; - return TRUE; - } -#else - gRollupListener->Rollup(); - *outResult = TRUE; - return TRUE; -#endif - } - if (inMsg == WM_ACTIVATE || inMsg == WM_NCLBUTTONDOWN || inMsg == WM_LBUTTONDOWN || inMsg == WM_RBUTTONDOWN || inMsg == WM_MBUTTONDOWN || - inMsg == WM_NCMBUTTONDOWN || inMsg == WM_NCRBUTTONDOWN || inMsg == WM_MOUSEACTIVATE) { + inMsg == WM_NCMBUTTONDOWN || inMsg == WM_NCRBUTTONDOWN || inMsg == WM_MOUSEACTIVATE || + inMsg == WM_MOUSEWHEEL || inMsg == uMSH_MOUSEWHEEL) + { // Rollup if the event is outside the popup. PRBool rollup = !nsWindow::EventIsInsideWindow((nsWindow*)gRollupWidget); - + + if (rollup && (inMsg == WM_MOUSEWHEEL || inMsg == uMSH_MOUSEWHEEL)) + { + gRollupListener->ShouldRollupOnMouseWheelEvent(&rollup); + *outResult = PR_TRUE; + } + // If we're dealing with menus, we probably have submenus and we don't // want to rollup if the click is in a parent menu of the current submenu. if (rollup) {