Modifying view event flow to always start processing from top view, not enter at children

This commit is contained in:
joki%netscape.com 1999-02-01 22:45:59 +00:00
parent 2e680185ec
commit 4513eb2392
5 changed files with 82 additions and 14 deletions

View File

@ -421,6 +421,13 @@ public:
*/
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const = 0;
/**
* Set flags on view to allow customization of view behavior during
* event handling
* @param aFlags flags to be added to view
*/
NS_IMETHOD SetViewFlags(PRInt32 aFlags) = 0;
private:
NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
NS_IMETHOD_(nsrefcnt) Release(void) = 0;
@ -455,4 +462,8 @@ private:
//while in the front to back pass
#define NS_VIEW_FLAG_FRONT_TO_BACK 0x0040
//Flag to determine whether the view will check if events can be handled
//by its children or just handle the events itself
#define NS_VIEW_FLAG_DONT_CHECK_CHILDREN 0x0001
#endif

View File

@ -711,9 +711,9 @@ NS_IMETHODIMP nsScrollingView :: HandleEvent(nsGUIEvent *aEvent, PRUint32 aEvent
} // switch
} break;
#if 0
case NS_MOUSE_MOVE:
{
#if 0
nsRect brect;
nscoord lx, ly;
@ -751,7 +751,6 @@ NS_IMETHODIMP nsScrollingView :: HandleEvent(nsGUIEvent *aEvent, PRUint32 aEvent
mScrollingTimer->Cancel();
NS_RELEASE(mScrollingTimer);
}
#endif
break;
}
@ -799,6 +798,7 @@ NS_IMETHODIMP nsScrollingView :: HandleEvent(nsGUIEvent *aEvent, PRUint32 aEvent
}
break;
}
#endif
default:
break;

View File

@ -72,6 +72,7 @@ nsView :: nsView()
mVis = nsViewVisibility_kShow;
mXForm = nsnull;
mVFlags = ~ALL_VIEW_FLAGS;
mEventFlags = 0;
mOpacity = 1.0f;
}
@ -740,9 +741,10 @@ NS_IMETHODIMP nsView :: HandleEvent(nsGUIEvent *event, PRUint32 aEventFlags,
//printf(" %d %d %d %d (%d,%d) \n", this, event->widget, event->widgetSupports,
// event->message, event->point.x, event->point.y);
aStatus = nsEventStatus_eIgnore;
PRBool handledByChild = PR_FALSE;
//see if any of this view's children can process the event
if (aStatus == nsEventStatus_eIgnore) {
if (aStatus == nsEventStatus_eIgnore && !(mEventFlags & NS_VIEW_FLAG_DONT_CHECK_CHILDREN)) {
PRInt32 numkids;
nsRect trect;
nscoord x, y;
@ -760,6 +762,7 @@ NS_IMETHODIMP nsView :: HandleEvent(nsGUIEvent *event, PRUint32 aEventFlags,
if (trect.Contains(x, y))
{
handledByChild = PR_TRUE;
//the x, y position of the event in question
//is inside this child view, so give it the
//opportunity to handle the event
@ -778,8 +781,8 @@ NS_IMETHODIMP nsView :: HandleEvent(nsGUIEvent *event, PRUint32 aEventFlags,
}
}
//if the view's children didn't take the event, check the view itself.
if ((aStatus == nsEventStatus_eIgnore) && (nsnull != mClientData))
//if no child's bounds matched the event, check the view itself.
if (!handledByChild && nsnull != mClientData)
{
nsIViewObserver *obs;
@ -1252,6 +1255,12 @@ void nsView :: List(FILE* out, PRInt32 aIndent) const
fputs(">\n", out);
}
NS_IMETHODIMP nsView :: SetViewFlags(PRInt32 aFlags)
{
mVFlags &= aFlags;
return NS_OK;
}
NS_IMETHODIMP nsView :: GetOffsetFromWidget(nscoord *aDx, nscoord *aDy, nsIWidget *&aWidget)
{
nsIView *ancestor;

View File

@ -98,6 +98,7 @@ public:
NS_IMETHOD SetWidget(nsIWidget *aWidget);
NS_IMETHOD GetWidget(nsIWidget *&aWidget);
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
NS_IMETHOD SetViewFlags(PRInt32 aFlags);
// Helper function to get the view that's associated with a widget
static nsIView* GetViewFor(nsIWidget* aWidget);
@ -125,6 +126,7 @@ protected:
float mOpacity;
PRInt32 mVFlags;
nsIRegion* mDirtyRegion;
PRInt32 mEventFlags;
private:
NS_IMETHOD_(nsrefcnt) AddRef(void);

View File

@ -25,8 +25,10 @@
#include "nsIScrollableView.h"
#include "nsIRegion.h"
#include "nsView.h"
#include "nsIScrollbar.h"
static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID);
static NS_DEFINE_IID(kIScrollbarIID, NS_ISCROLLBAR_IID);
static const PRBool gsDebug = PR_FALSE;
@ -793,33 +795,77 @@ NS_IMETHODIMP nsViewManager :: DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &
default:
{
nsIView* baseView;
nsIView* view;
nsPoint offset;
nsIScrollbar* sb;
//Find the view whose coordinates system we're in.
baseView = nsView::GetViewFor(aEvent->widget);
if (nsnull != mMouseGrabber && NS_IS_MOUSE_EVENT(aEvent))
//Find the view to which we're initially going to send the event
//for hittesting.
if (nsnull != mMouseGrabber && NS_IS_MOUSE_EVENT(aEvent)) {
view = mMouseGrabber;
else if (nsnull != mKeyGrabber && NS_IS_KEY_EVENT(aEvent))
}
else if (nsnull != mKeyGrabber && NS_IS_KEY_EVENT(aEvent)) {
view = mKeyGrabber;
else
view = nsView::GetViewFor(aEvent->widget);
}
else if (NS_OK == aEvent->widget->QueryInterface(kIScrollbarIID, (void**)&sb)) {
view = baseView;
NS_RELEASE(sb);
}
else {
view = mRootView;
}
if (nsnull != view)
{
if (nsnull != view) {
//Calculate the proper offset for the view we're going to
offset.x = offset.y = 0;
if (baseView != view) {
//Get offset from root of baseView
nsIView *parent;
nsRect bounds;
parent = baseView;
while (nsnull != parent) {
parent->GetBounds(bounds);
offset.x += bounds.x;
offset.y += bounds.y;
parent->GetParent(parent);
}
//Subtract back offset from root of view
parent = view;
while (nsnull != parent) {
parent->GetBounds(bounds);
offset.x -= bounds.x;
offset.y -= bounds.y;
parent->GetParent(parent);
}
}
//Dispatch the event
float p2t, t2p;
// pass on to view somewhere else to deal with
mContext->GetDevUnitsToAppUnits(p2t);
mContext->GetAppUnitsToDevUnits(t2p);
aEvent->point.x = NSIntPixelsToTwips(aEvent->point.x, p2t);
aEvent->point.y = NSIntPixelsToTwips(aEvent->point.y, p2t);
aEvent->point.x += offset.x;
aEvent->point.y += offset.y;
view->HandleEvent(aEvent, NS_VIEW_FLAG_CHECK_CHILDREN |
NS_VIEW_FLAG_CHECK_PARENT |
NS_VIEW_FLAG_CHECK_SIBLINGS,
aStatus);
aEvent->point.x -= offset.x;
aEvent->point.y -= offset.y;
aEvent->point.x = NSTwipsToIntPixels(aEvent->point.x, t2p);
aEvent->point.y = NSTwipsToIntPixels(aEvent->point.y, t2p);
}