Mousewheel bugs 29244, 50339, 42313, 33733, and 57598. r=rods,pavlov. sr=hyatt.

This commit is contained in:
bryner%uiuc.edu 2000-12-09 07:28:19 +00:00
Родитель 4597daa244
Коммит e3a92267ce
21 изменённых файлов: 589 добавлений и 192 удалений

Просмотреть файл

@ -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<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
// Otherwise, check for a focused content element
nsCOMPtr<nsIContent> 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<nsIScrollableViewProvider> 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<nsIPresContext> 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<nsISupports> shell;
aPresContext->GetContainer(getter_AddRefs(shell));
if (!shell) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(shell);
if (!treeItem) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShellTreeItem> parent;
treeItem->GetParent(getter_AddRefs(parent));
if (!parent) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShell> pDocShell = do_QueryInterface(parent);
if (!pDocShell) return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresShell> 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<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
// Otherwise, check for a focused content element
nsCOMPtr<nsIContent> 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;

Просмотреть файл

@ -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);

Просмотреть файл

@ -62,3 +62,4 @@ nsIScrollableFrame.h
nsIPrivateDOMImplementation.h
nsIContentSerializer.h
nsIHTMLToTextSink.h
nsIScrollableViewProvider.h

Просмотреть файл

@ -91,6 +91,7 @@ nsIScrollableFrame.h \
nsIPrivateDOMImplementation.h \
nsIContentSerializer.h \
nsIHTMLToTextSink.h \
nsIScrollableViewProvider.h \
$(NULL)
XPIDLSRCS = \

Просмотреть файл

@ -83,6 +83,7 @@ EXPORTS = \
nsIPrivateDOMImplementation.h \
nsIContentSerializer.h \
nsIHTMLToTextSink.h \
nsIScrollableViewProvider.h \
$(NULL)
MODULE=layout_base

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
// Otherwise, check for a focused content element
nsCOMPtr<nsIContent> 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<nsIScrollableViewProvider> 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<nsIPresContext> 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<nsISupports> shell;
aPresContext->GetContainer(getter_AddRefs(shell));
if (!shell) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(shell);
if (!treeItem) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShellTreeItem> parent;
treeItem->GetParent(getter_AddRefs(parent));
if (!parent) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShell> pDocShell = do_QueryInterface(parent);
if (!pDocShell) return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresShell> 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<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
// Otherwise, check for a focused content element
nsCOMPtr<nsIContent> 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;

Просмотреть файл

@ -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);

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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);

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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);

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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; };

Просмотреть файл

@ -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

Просмотреть файл

@ -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<nsIWidget> 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<nsIMenuRollup> 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.

Просмотреть файл

@ -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

Просмотреть файл

@ -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) {