fixes for 5995, 7304, 10573, 22832, and 9668.

Changes to event handling to deal with reentrant events, cursor fixes, and return value fixes.
This commit is contained in:
joki%netscape.com 2000-04-24 04:41:27 +00:00
parent c938845535
commit bbb0086bfe
46 changed files with 639 additions and 293 deletions

View File

@ -32,6 +32,7 @@ class nsIPresContext;
class nsIDOMEvent;
class nsIFrame;
class nsIView;
class nsIWidget;
/*
* Event listener manager interface.
@ -49,13 +50,13 @@ public:
NS_IMETHOD Init() = 0;
NS_IMETHOD PreHandleEvent(nsIPresContext* aPresContext,
nsGUIEvent *aEvent,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView) = 0;
NS_IMETHOD PostHandleEvent(nsIPresContext* aPresContext,
nsGUIEvent *aEvent,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView) = 0;
@ -80,6 +81,8 @@ public:
NS_IMETHOD RegisterAccessKey(nsIFrame * aFrame, PRUint32 aKey) = 0;
NS_IMETHOD UnregisterAccessKey(nsIFrame * aFrame) = 0;
NS_IMETHOD SetCursor(PRInt32 aCursor, nsIWidget* aWidget, PRBool aLockCursor) = 0;
};
#define NS_EVENT_STATE_UNSPECIFIED 0x0000

View File

@ -807,9 +807,9 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
case NS_MOUSE_MIDDLE_DOUBLECLICK:
case NS_MOUSE_RIGHT_DOUBLECLICK:
return mEventNames[eDOMEvents_dblclick];
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
return mEventNames[eDOMEvents_mouseover];
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
return mEventNames[eDOMEvents_mouseout];
case NS_MOUSE_MOVE:
return mEventNames[eDOMEvents_mousemove];
@ -833,6 +833,7 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
case NS_IMAGE_ABORT:
return mEventNames[eDOMEvents_abort];
case NS_IMAGE_ERROR:
case NS_SCRIPT_ERROR:
return mEventNames[eDOMEvents_error];
case NS_FORM_SUBMIT:
return mEventNames[eDOMEvents_submit];
@ -860,9 +861,9 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return mEventNames[eDOMEvents_commandupdate];
case NS_DRAGDROP_ENTER:
return mEventNames[eDOMEvents_dragenter];
case NS_DRAGDROP_OVER:
case NS_DRAGDROP_OVER_SYNTH:
return mEventNames[eDOMEvents_dragover];
case NS_DRAGDROP_EXIT:
case NS_DRAGDROP_EXIT_SYNTH:
return mEventNames[eDOMEvents_dragexit];
case NS_DRAGDROP_DROP:
return mEventNames[eDOMEvents_dragdrop];

View File

@ -741,8 +741,8 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
case NS_MOUSE_LEFT_DOUBLECLICK:
case NS_MOUSE_MIDDLE_DOUBLECLICK:
case NS_MOUSE_RIGHT_DOUBLECLICK:
case NS_MOUSE_ENTER:
case NS_MOUSE_EXIT:
case NS_MOUSE_ENTER_SYNTH:
case NS_MOUSE_EXIT_SYNTH:
if (nsnull != mMouseListeners) {
if (nsnull == *aDOMEvent) {
ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, aEvent);
@ -777,10 +777,10 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
case NS_MOUSE_RIGHT_DOUBLECLICK:
ret = mMouseListener->MouseDblClick(*aDOMEvent);
break;
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
ret = mMouseListener->MouseOver(*aDOMEvent);
break;
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
ret = mMouseListener->MouseOut(*aDOMEvent);
break;
default:
@ -824,13 +824,13 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
correctSubType = PR_TRUE;
}
break;
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
subType = NS_EVENT_BITS_MOUSE_MOUSEOVER;
if (ls->mSubType & NS_EVENT_BITS_MOUSE_MOUSEOVER) {
correctSubType = PR_TRUE;
}
break;
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
subType = NS_EVENT_BITS_MOUSE_MOUSEOUT;
if (ls->mSubType & NS_EVENT_BITS_MOUSE_MOUSEOUT) {
correctSubType = PR_TRUE;
@ -1207,6 +1207,7 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
case NS_PAGE_UNLOAD:
case NS_IMAGE_LOAD:
case NS_IMAGE_ERROR:
case NS_SCRIPT_ERROR:
if (nsnull != mLoadListeners) {
if (nsnull == *aDOMEvent) {
@ -1230,6 +1231,7 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
ret = mLoadListener->Unload(*aDOMEvent);
break;
case NS_IMAGE_ERROR:
case NS_SCRIPT_ERROR:
ret = mLoadListener->Error(*aDOMEvent);
default:
break;
@ -1254,6 +1256,7 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
}
break;
case NS_IMAGE_ERROR:
case NS_SCRIPT_ERROR:
subType = NS_EVENT_BITS_LOAD_ERROR;
if (ls->mSubType & NS_EVENT_BITS_LOAD_ERROR) {
correctSubType = PR_TRUE;
@ -1307,8 +1310,8 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
break;
case NS_DRAGDROP_ENTER:
case NS_DRAGDROP_OVER:
case NS_DRAGDROP_EXIT:
case NS_DRAGDROP_OVER_SYNTH:
case NS_DRAGDROP_EXIT_SYNTH:
case NS_DRAGDROP_DROP:
case NS_DRAGDROP_GESTURE:
if (nsnull != mDragListeners) {
@ -1329,10 +1332,10 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
case NS_DRAGDROP_ENTER:
ret = dragListener->DragEnter(*aDOMEvent);
break;
case NS_DRAGDROP_OVER:
case NS_DRAGDROP_OVER_SYNTH:
ret = dragListener->DragOver(*aDOMEvent);
break;
case NS_DRAGDROP_EXIT:
case NS_DRAGDROP_EXIT_SYNTH:
ret = dragListener->DragExit(*aDOMEvent);
break;
case NS_DRAGDROP_DROP:
@ -1352,12 +1355,12 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
if (dragStruct->mSubType & NS_EVENT_BITS_DRAG_ENTER)
correctSubType = PR_TRUE;
break;
case NS_DRAGDROP_OVER:
case NS_DRAGDROP_OVER_SYNTH:
subType = NS_EVENT_BITS_DRAG_OVER;
if (dragStruct->mSubType & NS_EVENT_BITS_DRAG_OVER)
correctSubType = PR_TRUE;
break;
case NS_DRAGDROP_EXIT:
case NS_DRAGDROP_EXIT_SYNTH:
subType = NS_EVENT_BITS_DRAG_EXIT;
if (dragStruct->mSubType & NS_EVENT_BITS_DRAG_EXIT)
correctSubType = PR_TRUE;

View File

@ -100,6 +100,7 @@ nsEventStateManager::nsEventStateManager()
mLastRightMouseDownContent = nsnull;
mConsumeFocusEvents = PR_FALSE;
mLockCursor = 0;
// init d&d gesture state machine variables
mIsTrackingDragGesture = PR_FALSE;
@ -231,7 +232,7 @@ NS_IMPL_ISUPPORTS1(nsEventStateManager, nsIEventStateManager)
NS_IMETHODIMP
nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext,
nsGUIEvent *aEvent,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView)
@ -258,7 +259,7 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext,
switch (aEvent->message) {
case NS_MOUSE_LEFT_BUTTON_DOWN:
BeginTrackingDragGesture ( aEvent, aTargetFrame );
BeginTrackingDragGesture ( (nsGUIEvent*)aEvent, aTargetFrame );
mLClickCount = ((nsMouseEvent*)aEvent)->clickCount;
SetClickCount(aPresContext, (nsMouseEvent*)aEvent, aStatus);
break;
@ -282,17 +283,17 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext,
// If this is the case, however, we know that ClearFrameRefs() has been called
// and it cleared out |mCurrentTarget|. As a result, we should pass |mCurrentTarget|
// into UpdateCursor().
GenerateDragGesture(aPresContext, aEvent);
GenerateDragGesture(aPresContext, (nsGUIEvent*)aEvent);
UpdateCursor(aPresContext, aEvent, mCurrentTarget, aStatus);
GenerateMouseEnterExit(aPresContext, aEvent);
GenerateMouseEnterExit(aPresContext, (nsGUIEvent*)aEvent);
break;
case NS_MOUSE_EXIT:
GenerateMouseEnterExit(aPresContext, aEvent);
GenerateMouseEnterExit(aPresContext, (nsGUIEvent*)aEvent);
//This is a window level mouseenter event and should stop here
aEvent->message = 0;
break;
case NS_DRAGDROP_OVER:
GenerateDragDropEnterExit(aPresContext, aEvent);
GenerateDragDropEnterExit(aPresContext, (nsGUIEvent*)aEvent);
break;
case NS_GOTFOCUS:
{
@ -663,7 +664,7 @@ nsEventStateManager :: GenerateDragGesture ( nsIPresContext* aPresContext, nsGUI
NS_IMETHODIMP
nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext,
nsGUIEvent *aEvent,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView)
@ -869,7 +870,7 @@ nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext,
case NS_DRAGDROP_EXIT:
// clean up after ourselves. make sure we do this _after_ the event, else we'll
// clean up too early!
GenerateDragDropEnterExit(aPresContext, aEvent);
GenerateDragDropEnterExit(aPresContext, (nsGUIEvent*)aEvent);
break;
case NS_KEY_PRESS:
if (nsEventStatus_eConsumeNoDefault != *aStatus) {
@ -1055,24 +1056,57 @@ nsEventStateManager::UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent,
nsEventStatus* aStatus)
{
PRInt32 cursor;
nsCursor c;
nsCOMPtr<nsIContent> targetContent;
if (mCurrentTarget) {
mCurrentTarget->GetContent(getter_AddRefs(targetContent));
//If cursor is locked just use the locked one
if (mLockCursor) {
cursor = mLockCursor;
}
//Check if the current target is disabled. If so use the default pointer.
if (targetContent && CheckDisabled(targetContent)) {
cursor = NS_STYLE_CURSOR_DEFAULT;
}
//If not disabled, check for the right cursor.
//If not locked, look for correct cursor
else {
if ( aTargetFrame )
aTargetFrame->GetCursor(aPresContext, aEvent->point, cursor);
nsCOMPtr<nsIContent> targetContent;
if (mCurrentTarget) {
mCurrentTarget->GetContent(getter_AddRefs(targetContent));
}
//Check if the current target is disabled. If so use the default pointer.
if (targetContent && CheckDisabled(targetContent)) {
cursor = NS_STYLE_CURSOR_DEFAULT;
}
//If not disabled, check for the right cursor.
else {
if (aTargetFrame) {
aTargetFrame->GetCursor(aPresContext, aEvent->point, cursor);
}
}
}
switch (cursor) {
if (aTargetFrame) {
nsCOMPtr<nsIWidget> window;
aTargetFrame->GetWindow(aPresContext, getter_AddRefs(window));
SetCursor(cursor, window, PR_FALSE);
}
if (mLockCursor || NS_STYLE_CURSOR_AUTO != cursor) {
*aStatus = nsEventStatus_eConsumeDoDefault;
}
}
NS_IMETHODIMP
nsEventStateManager::SetCursor(PRInt32 aCursor, nsIWidget* aWidget, PRBool aLockCursor)
{
nsCursor c;
NS_ENSURE_TRUE(aWidget, NS_ERROR_FAILURE);
if (aLockCursor) {
if (NS_STYLE_CURSOR_AUTO != aCursor) {
mLockCursor = aCursor;
}
else {
//If cursor style is set to auto we unlock the cursor again.
mLockCursor = 0;
}
}
switch (aCursor) {
default:
case NS_STYLE_CURSOR_AUTO:
case NS_STYLE_CURSOR_DEFAULT:
@ -1104,7 +1138,7 @@ nsEventStateManager::UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent,
case NS_STYLE_CURSOR_E_RESIZE:
c = eCursor_sizeWE;
break;
//These aren't in the CSS2 spec. Don't know what to do with them.
//We don't have cursors defined for these in nsIWidget. Need them to fix this.
case NS_STYLE_CURSOR_NE_RESIZE:
case NS_STYLE_CURSOR_NW_RESIZE:
case NS_STYLE_CURSOR_SE_RESIZE:
@ -1113,15 +1147,9 @@ nsEventStateManager::UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent,
break;
}
if (NS_STYLE_CURSOR_AUTO != cursor) {
*aStatus = nsEventStatus_eConsumeDoDefault;
}
aWidget->SetCursor(c);
if ( aTargetFrame ) {
nsCOMPtr<nsIWidget> window;
aTargetFrame->GetWindow(aPresContext, getter_AddRefs(window));
window->SetCursor(c);
}
return NS_OK;
}
void
@ -1152,7 +1180,7 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_MOUSE_EXIT;
event.message = NS_MOUSE_EXIT_SYNTH;
event.widget = aEvent->widget;
event.clickCount = 0;
event.point = aEvent->point;
@ -1196,7 +1224,7 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_MOUSE_ENTER;
event.message = NS_MOUSE_ENTER_SYNTH;
event.widget = aEvent->widget;
event.clickCount = 0;
event.point = aEvent->point;
@ -1251,7 +1279,7 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_MOUSE_EXIT;
event.message = NS_MOUSE_EXIT_SYNTH;
event.widget = aEvent->widget;
event.clickCount = 0;
event.point = aEvent->point;
@ -1315,7 +1343,7 @@ nsEventStateManager::GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsG
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_DRAGDROP_EVENT;
event.message = NS_DRAGDROP_EXIT;
event.message = NS_DRAGDROP_EXIT_SYNTH;
event.widget = aEvent->widget;
event.clickCount = 0;
event.point = aEvent->point;
@ -1406,7 +1434,7 @@ nsEventStateManager::GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsG
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_DRAGDROP_EVENT;
event.message = NS_DRAGDROP_EXIT;
event.message = NS_DRAGDROP_EXIT_SYNTH;
event.widget = aEvent->widget;
event.clickCount = 0;
event.point = aEvent->point;
@ -1550,14 +1578,10 @@ nsEventStateManager::CheckForAndDispatchClick(nsIPresContext* aPresContext,
event.isAlt = aEvent->isAlt;
event.isMeta = aEvent->isMeta;
if (mouseContent) {
ret = mouseContent->HandleDOMEvent(aPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, aStatus);
NS_ASSERTION(NS_SUCCEEDED(ret), "HandleDOMEvent failed");
}
if (nsnull != mCurrentTarget) {
ret = mCurrentTarget->HandleEvent(aPresContext, &event, aStatus);
nsCOMPtr<nsIPresShell> presShell;
mPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
ret = presShell->HandleEventWithTarget(&event, mCurrentTarget, mouseContent, aStatus);
}
}
return ret;

View File

@ -62,7 +62,7 @@ public:
* DOM or frame event handling should occur here as well.
*/
NS_IMETHOD PreHandleEvent(nsIPresContext* aPresContext,
nsGUIEvent *aEvent,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView);
@ -73,7 +73,7 @@ public:
* DOM and frame processing.
*/
NS_IMETHOD PostHandleEvent(nsIPresContext* aPresContext,
nsGUIEvent *aEvent,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView);
@ -97,6 +97,8 @@ public:
NS_IMETHOD RegisterAccessKey(nsIFrame * aFrame, PRUint32 aKey);
NS_IMETHOD UnregisterAccessKey(nsIFrame * aFrame);
NS_IMETHOD SetCursor(PRInt32 aCursor, nsIWidget* aWidget, PRBool aLockCursor);
protected:
void UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus);
void GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIEvent* aEvent);
@ -171,6 +173,7 @@ protected:
PRInt32 mCurrentTabIndex;
nsIWidget * mLastWindowToHaveFocus; // last native window to get focus via the evs
PRBool mConsumeFocusEvents;
PRInt32 mLockCursor;
//Anti-recursive stack controls
nsIContent* mFirstBlurEvent;

View File

@ -925,7 +925,7 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsIPresContext* aPresContext,
// XXX Bring up a contextual menu provided by the application
break;
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
{
nsIEventStateManager *stateManager;
if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) {
@ -947,7 +947,7 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsIPresContext* aPresContext,
}
break;
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
{
nsIEventStateManager *stateManager;
if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) {

View File

@ -459,7 +459,7 @@ nsHTMLButtonElement::HandleDOMEvent(nsIPresContext* aPresContext,
// XXX Bring up a contextual menu provided by the application
break;
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
{
nsIEventStateManager *stateManager;
if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) {
@ -471,7 +471,7 @@ nsHTMLButtonElement::HandleDOMEvent(nsIPresContext* aPresContext,
break;
// XXX this doesn't seem to do anything yet
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
{
nsIEventStateManager *stateManager;
if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) {

View File

@ -295,7 +295,7 @@ nsXMLElement::HandleDOMEvent(nsIPresContext* aPresContext,
// XXX Bring up a contextual menu provided by the application
break;
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
{
nsAutoString href, target;
nsIURI* baseURL = nsnull;
@ -315,7 +315,7 @@ nsXMLElement::HandleDOMEvent(nsIPresContext* aPresContext,
break;
// XXX this doesn't seem to do anything yet
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
{
nsAutoString empty;
ret = mInner.TriggerLink(aPresContext, eLinkVerb_Replace, nsnull, empty, empty, PR_FALSE);

View File

@ -186,6 +186,8 @@ public:
NS_IMETHOD DisableExternalCapture()=0;
NS_IMETHOD SetCursor(const nsString& aCursor)=0;
NS_IMETHOD Open(JSContext* cx, jsval* argv, PRUint32 argc, nsIDOMWindow** aReturn)=0;
NS_IMETHOD OpenDialog(JSContext* cx, jsval* argv, PRUint32 argc, nsIDOMWindow** aReturn)=0;
@ -278,6 +280,7 @@ public:
NS_IMETHOD RouteEvent(nsIDOMEvent* aEvt); \
NS_IMETHOD EnableExternalCapture(); \
NS_IMETHOD DisableExternalCapture(); \
NS_IMETHOD SetCursor(const nsString& aCursor); \
NS_IMETHOD Open(JSContext* cx, jsval* argv, PRUint32 argc, nsIDOMWindow** aReturn); \
NS_IMETHOD OpenDialog(JSContext* cx, jsval* argv, PRUint32 argc, nsIDOMWindow** aReturn); \
NS_IMETHOD Close(); \
@ -364,6 +367,7 @@ public:
NS_IMETHOD RouteEvent(nsIDOMEvent* aEvt) { return _to RouteEvent(aEvt); } \
NS_IMETHOD EnableExternalCapture() { return _to EnableExternalCapture(); } \
NS_IMETHOD DisableExternalCapture() { return _to DisableExternalCapture(); } \
NS_IMETHOD SetCursor(const nsString& aCursor) { return _to SetCursor(aCursor); } \
NS_IMETHOD Open(JSContext* cx, jsval* argv, PRUint32 argc, nsIDOMWindow** aReturn) { return _to Open(cx, argv, argc, aReturn); } \
NS_IMETHOD OpenDialog(JSContext* cx, jsval* argv, PRUint32 argc, nsIDOMWindow** aReturn) { return _to OpenDialog(cx, argv, argc, aReturn); } \
NS_IMETHOD Close() { return _to Close(); } \

View File

@ -1,6 +1,7 @@
interface Window {
/* IID: { 0xa6cf906b, 0x15b3, 0x11d2, \
{ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 } } */
readonly attribute Window window;
readonly attribute Window self;
readonly attribute Document document;
@ -68,7 +69,8 @@
void routeEvent(in Event evt);
void enableExternalCapture();
void disableExternalCapture();
void setCursor(in DOMString cursor);
Window open(/* ... */);
Window openDialog(/* ... */);
noscript void close();

View File

@ -923,6 +923,7 @@ enum nsDOMProp {
NS_DOM_PROP_WINDOW_SCROLLX,
NS_DOM_PROP_WINDOW_SCROLLY,
NS_DOM_PROP_WINDOW_SELF,
NS_DOM_PROP_WINDOW_SETCURSOR,
NS_DOM_PROP_WINDOW_SETINTERVAL,
NS_DOM_PROP_WINDOW_SETTIMEOUT,
NS_DOM_PROP_WINDOW_SIDEBAR,

View File

@ -922,6 +922,7 @@
"window.scrollx", \
"window.scrolly", \
"window.self", \
"window.setcursor", \
"window.setinterval", \
"window.settimeout", \
"window.sidebar", \

View File

@ -174,7 +174,7 @@ public:
**/
NS_IMETHOD CallEventHandler(void* aTarget, void* aHandler,
PRUint32 argc, void* argv,
PRBool* aBoolResult) = 0;
PRBool* aBoolResult, PRBool aReverseReturnResult) = 0;
/**
* Bind an already-compiled event handler function to a name in the given

View File

@ -66,6 +66,7 @@
#include "nsIDOMMouseListener.h"
#include "nsIDOMPaintListener.h"
#include "nsIEventQueueService.h"
#include "nsIEventStateManager.h"
#include "nsIHTTPProtocolHandler.h"
#include "nsIInterfaceRequestor.h"
#include "nsIJSContextStack.h"
@ -79,6 +80,7 @@
#include "nsIScriptSecurityManager.h"
#include "nsISelectionController.h"
#include "nsISidebar.h" // XXX for sidebar HACK, see bug 20721
#include "nsIStyleContext.h"
#include "nsIWebNavigation.h"
#include "nsIWebBrowser.h"
#include "nsIWebBrowserChrome.h"
@ -1024,7 +1026,7 @@ NS_IMETHODIMP GlobalWindowImpl::SetScreenY(PRInt32 aScreenY)
NS_IMETHODIMP GlobalWindowImpl::GetPageXOffset(PRInt32* aPageXOffset)
{
return NS_OK;
return GetScrollX(aPageXOffset);
}
NS_IMETHODIMP GlobalWindowImpl::SetPageXOffset(PRInt32 aPageXOffset)
@ -1034,7 +1036,7 @@ NS_IMETHODIMP GlobalWindowImpl::SetPageXOffset(PRInt32 aPageXOffset)
NS_IMETHODIMP GlobalWindowImpl::GetPageYOffset(PRInt32* aPageYOffset)
{
return NS_OK;
return GetScrollY(aPageYOffset);
}
NS_IMETHODIMP GlobalWindowImpl::SetPageYOffset(PRInt32 aPageYOffset)
@ -1520,6 +1522,61 @@ NS_IMETHODIMP GlobalWindowImpl::DisableExternalCapture()
return NS_ERROR_FAILURE;
}
//Note: This call will lock the cursor, it will not change as it moves.
//To unlock, the cursor must be set back to CURSOR_AUTO.
NS_IMETHODIMP GlobalWindowImpl::SetCursor(const nsString& aCursor)
{
nsresult ret = NS_OK;
PRInt32 cursor;
if (aCursor == "auto") cursor = NS_STYLE_CURSOR_AUTO;
else if (aCursor == "default") cursor = NS_STYLE_CURSOR_DEFAULT;
else if (aCursor == "pointer") cursor = NS_STYLE_CURSOR_POINTER;
else if (aCursor == "crosshair") cursor = NS_STYLE_CURSOR_CROSSHAIR;
else if (aCursor == "move") cursor = NS_STYLE_CURSOR_MOVE;
else if (aCursor == "text") cursor = NS_STYLE_CURSOR_TEXT;
else if (aCursor == "wait") cursor = NS_STYLE_CURSOR_WAIT;
else if (aCursor == "help") cursor = NS_STYLE_CURSOR_HELP;
else if (aCursor == "n-resize") cursor = NS_STYLE_CURSOR_N_RESIZE;
else if (aCursor == "s-resize") cursor = NS_STYLE_CURSOR_S_RESIZE;
else if (aCursor == "w-resize") cursor = NS_STYLE_CURSOR_W_RESIZE;
else if (aCursor == "e-resize") cursor = NS_STYLE_CURSOR_E_RESIZE;
else if (aCursor == "ne-resize") cursor = NS_STYLE_CURSOR_NE_RESIZE;
else if (aCursor == "nw-resize") cursor = NS_STYLE_CURSOR_NW_RESIZE;
else if (aCursor == "se-resize") cursor = NS_STYLE_CURSOR_SE_RESIZE;
else if (aCursor == "sw-resize") cursor = NS_STYLE_CURSOR_SW_RESIZE;
else return NS_OK;
nsCOMPtr<nsIPresContext> presContext;
mDocShell->GetPresContext(getter_AddRefs(presContext));
if(presContext) {
nsCOMPtr<nsIEventStateManager> esm;
if (NS_SUCCEEDED(presContext->GetEventStateManager(getter_AddRefs(esm)))) {
//Need root widget.
nsCOMPtr<nsIPresShell> presShell;
mDocShell->GetPresShell(getter_AddRefs(presShell));
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
nsCOMPtr<nsIViewManager> vm;
presShell->GetViewManager(getter_AddRefs(vm));
NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE);
nsIView* rootView;
vm->GetRootView(rootView);
NS_ENSURE_TRUE(rootView, NS_ERROR_FAILURE);
nsCOMPtr<nsIWidget> widget;
rootView->GetWidget(*getter_AddRefs(widget));
NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
//call esm and set cursor
ret = esm->SetCursor(cursor, widget, PR_TRUE);
}
}
return ret;
}
NS_IMETHODIMP GlobalWindowImpl::Open(JSContext* cx, jsval* argv, PRUint32 argc,
nsIDOMWindow** aReturn)
{
@ -3135,7 +3192,7 @@ PRBool GlobalWindowImpl::RunTimeout(nsTimeoutImpl *aTimeout)
PRBool aBoolResult;
rv = mContext->CallEventHandler(mScriptObject, timeout->funobj,
timeout->argc + 1, timeout->argv,
&aBoolResult);
&aBoolResult, PR_FALSE);
}
--mTimeoutFiringDepth;

View File

@ -47,6 +47,8 @@
#include "nsIPref.h"
#include "nsCOMPtr.h"
#include "nsJSUtils.h"
#include "nsIDocShell.h"
#include "nsIPresContext.h"
// Force PR_LOGGING so we can get JS strict warnings even in release builds
#define FORCE_PR_LOG 1
@ -72,6 +74,7 @@ NS_ScriptErrorReporter(JSContext *cx,
JSErrorReport *report)
{
nsCOMPtr<nsIScriptContext> context;
nsEventStatus status = nsEventStatus_eIgnore;
// XXX this means we are not going to get error reports on non DOM contexts
nsJSUtils::nsGetDynamicScriptContext(cx, getter_AddRefs(context));
@ -86,37 +89,55 @@ NS_ScriptErrorReporter(JSContext *cx,
return;
}
// Make an nsIScriptError and populate it with information from
// this error.
nsCOMPtr<nsIScriptError>
errorObject(do_CreateInstance("mozilla.scripterror.1"));
//send error event first, then proceed
nsCOMPtr<nsIDocShell> docShell;
globalObject->GetDocShell(getter_AddRefs(docShell));
if (docShell) {
nsCOMPtr<nsIPresContext> presContext;
docShell->GetPresContext(getter_AddRefs(presContext));
if(presContext) {
nsEvent errorevent;
errorevent.eventStructType = NS_EVENT;
errorevent.message = NS_SCRIPT_ERROR;
// XXX possible here to distinguish between XUL and content js?
// or could just expose setCategory and twiddle it later.
const char *category = "XUL/Content JavaScript";
if (errorObject != nsnull) {
nsresult rv = NS_ERROR_FAILURE;
if (report) {
nsAutoString fileUni;
fileUni.AssignWithConversion(report->filename);
const PRUnichar *newFileUni = fileUni.ToNewUnicode();
PRUint32 column = report->uctokenptr - report->uclinebuf;
rv = errorObject->Init(report->ucmessage, newFileUni,
report->uclinebuf, report->lineno,
column, report->flags, category);
nsAllocator::Free((void *)newFileUni);
} else if (message) {
nsAutoString messageUni;
messageUni.AssignWithConversion(message);
const PRUnichar *newMessageUni = messageUni.ToNewUnicode();
rv = errorObject->Init(newMessageUni, nsnull, nsnull,
0, 0, 0, category);
nsAllocator::Free((void *)newMessageUni);
globalObject->HandleDOMEvent(presContext, &errorevent, nsnull, NS_EVENT_FLAG_INIT, &status);
}
}
if (status != nsEventStatus_eConsumeNoDefault) {
// Make an nsIScriptError and populate it with information from
// this error.
nsCOMPtr<nsIScriptError>
errorObject(do_CreateInstance("mozilla.scripterror.1"));
// XXX possible here to distinguish between XUL and content js?
// or could just expose setCategory and twiddle it later.
const char *category = "XUL/Content JavaScript";
if (errorObject != nsnull) {
nsresult rv = NS_ERROR_FAILURE;
if (report) {
nsAutoString fileUni;
fileUni.AssignWithConversion(report->filename);
const PRUnichar *newFileUni = fileUni.ToNewUnicode();
PRUint32 column = report->uctokenptr - report->uclinebuf;
rv = errorObject->Init(report->ucmessage, newFileUni,
report->uclinebuf, report->lineno,
column, report->flags, category);
nsAllocator::Free((void *)newFileUni);
} else if (message) {
nsAutoString messageUni;
messageUni.AssignWithConversion(message);
const PRUnichar *newMessageUni = messageUni.ToNewUnicode();
rv = errorObject->Init(newMessageUni, nsnull, nsnull,
0, 0, 0, category);
nsAllocator::Free((void *)newMessageUni);
}
if (NS_SUCCEEDED(rv))
owner->ReportScriptError(errorObject);
}
if (NS_SUCCEEDED(rv))
owner->ReportScriptError(errorObject);
}
}
}
@ -133,6 +154,8 @@ NS_ScriptErrorReporter(JSContext *cx,
error.AppendWithConversion(": ");
error.Append(report->ucmessage);
error.AppendWithConversion("\n");
if (status != nsEventStatus_eIgnore)
error.AppendWithConversion("Error was suppressed by event handler\n");
char *errorStr = error.ToNewCString();
if (errorStr) {
@ -729,7 +752,7 @@ nsJSContext::CompileFunction(void* aTarget,
NS_IMETHODIMP
nsJSContext::CallEventHandler(void *aTarget, void *aHandler, PRUint32 argc,
void *argv, PRBool *aBoolResult)
void *argv, PRBool *aBoolResult, PRBool aReverseReturnResult)
{
// This one's a lot easier than EvaluateString because we don't have to
// hassle with principals: they're already compiled into the JS function.
@ -764,7 +787,7 @@ nsJSContext::CallEventHandler(void *aTarget, void *aHandler, PRUint32 argc,
argc, (jsval *)argv, &val);
}
*aBoolResult = ok
? !JSVAL_IS_BOOLEAN(val) || JSVAL_TO_BOOLEAN(val)
? !JSVAL_IS_BOOLEAN(val) || (aReverseReturnResult ? !JSVAL_TO_BOOLEAN(val) : JSVAL_TO_BOOLEAN(val))
: JS_TRUE;
ScriptEvaluated();

View File

@ -90,7 +90,7 @@ public:
void** aHandler);
NS_IMETHOD CallEventHandler(void *aTarget, void *aHandler,
PRUint32 argc, void *argv,
PRBool *aBoolResult);
PRBool *aBoolResult, PRBool aReverseReturnResult);
NS_IMETHOD BindCompiledEventHandler(void *aTarget,
nsIAtom *aName,
void *aHandler);

View File

@ -2124,6 +2124,47 @@ WindowDisableExternalCapture(JSContext *cx, JSObject *obj, uintN argc, jsval *ar
}
//
// Native method SetCursor
//
PR_STATIC_CALLBACK(JSBool)
WindowSetCursor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsIDOMWindow *nativeThis = (nsIDOMWindow*)nsJSUtils::nsGetNativeThis(cx, obj);
nsresult result = NS_OK;
nsAutoString b0;
// If there's no private data, this must be the prototype, so ignore
if (nsnull == nativeThis) {
return JS_TRUE;
}
{
*rval = JSVAL_NULL;
nsIScriptSecurityManager *secMan = nsJSUtils::nsGetSecurityManager(cx, obj);
if (!secMan)
return PR_FALSE;
result = secMan->CheckScriptAccess(cx, obj, NS_DOM_PROP_WINDOW_SETCURSOR, PR_FALSE);
if (NS_FAILED(result)) {
return nsJSUtils::nsReportError(cx, obj, result);
}
if (argc < 1) {
return nsJSUtils::nsReportError(cx, obj, NS_ERROR_DOM_TOO_FEW_PARAMETERS_ERR);
}
nsJSUtils::nsConvertJSValToString(b0, cx, argv[0]);
result = nativeThis->SetCursor(b0);
if (NS_FAILED(result)) {
return nsJSUtils::nsReportError(cx, obj, result);
}
*rval = JSVAL_VOID;
}
return JS_TRUE;
}
//
// Native method Open
//
@ -2567,6 +2608,7 @@ static JSFunctionSpec WindowMethods[] =
{"routeEvent", WindowRouteEvent, 1},
{"enableExternalCapture", WindowEnableExternalCapture, 0},
{"disableExternalCapture", WindowDisableExternalCapture, 0},
{"setCursor", WindowSetCursor, 1},
{"open", WindowOpen, 0},
{"openDialog", WindowOpenDialog, 0},
{"close", WindowClose, 0},

View File

@ -91,7 +91,7 @@ nsresult nsJSDOMEventListener::HandleEvent(nsIDOMEvent* aEvent)
argv[0] = OBJECT_TO_JSVAL(eventObj);
PRBool jsBoolResult;
if (NS_FAILED(scriptCX->CallEventHandler(mTarget, mHandler, 1, argv, &jsBoolResult))) {
if (NS_FAILED(scriptCX->CallEventHandler(mTarget, mHandler, 1, argv, &jsBoolResult, PR_FALSE))) {
return NS_ERROR_FAILURE;
}
return jsBoolResult ? NS_OK : NS_ERROR_FAILURE;

View File

@ -45,6 +45,7 @@ nsJSEventListener::nsJSEventListener(nsIScriptContext *aContext,
// or the owner goes away.
mContext = aContext;
mOwner = aOwner;
mReturnResult = nsReturnResult_eNotSet;
}
nsJSEventListener::~nsJSEventListener()
@ -105,7 +106,14 @@ nsresult nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
//JS can't handle this event yet or can't handle it at all
return NS_OK;
}
if (mReturnResult == nsReturnResult_eNotSet) {
if (eventString == "error" || eventString == "mouseover") {
mReturnResult = nsReturnResult_eReverseReturnResult;
}
else {
mReturnResult = nsReturnResult_eDoNotReverseReturnResult;
}
}
eventString.InsertWithConversion("on", 0, 2);
}
else {
@ -137,7 +145,13 @@ nsresult nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
argv[0] = OBJECT_TO_JSVAL(eventObj);
PRBool jsBoolResult;
result = mContext->CallEventHandler(obj, (void*) JSVAL_TO_OBJECT(funval), 1, argv, &jsBoolResult);
PRBool returnResult = mReturnResult == nsReturnResult_eReverseReturnResult ? PR_TRUE : PR_FALSE;
result = mContext->CallEventHandler(obj,
(void*) JSVAL_TO_OBJECT(funval),
1,
argv,
&jsBoolResult,
returnResult);
if (NS_FAILED(result)) {
return result;
}

View File

@ -53,6 +53,14 @@ protected:
nsIScriptContext* mContext;
nsIScriptObjectOwner* mOwner;
nsCOMPtr<nsIAtom> mEventName;
enum nsReturnResult {
nsReturnResult_eNotSet,
nsReturnResult_eReverseReturnResult,
nsReturnResult_eDoNotReverseReturnResult
};
nsReturnResult mReturnResult;
};

View File

@ -27,6 +27,7 @@
#include "nsCoord.h"
#include "nsIDOMSelection.h"
#include "nsIReflowCommand.h"
#include "nsGUIEvent.h"
class nsIContent;
class nsIContentIterator;
@ -388,9 +389,14 @@ public:
*/
NS_IMETHOD GetDisplayNonTextSelection(PRBool *aOutEnabled) = 0;
// XXX events
// XXX selection
/**
* Interface to dispatch events via the presshell
*/
NS_IMETHOD HandleEventWithTarget(nsEvent* aEvent,
nsIFrame* aFrame,
nsIContent* aContent,
nsEventStatus* aStatus) = 0;
/**
* Get and set the history state for the current document
*/

View File

@ -610,6 +610,8 @@ public:
NS_IMETHOD GetGeneratedContentIterator(nsIContent* aContent,
GeneratedContentType aType,
nsIContentIterator** aIterator) const;
NS_IMETHOD HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame, nsIContent* aContent, nsEventStatus* aStatus);
NS_IMETHOD IsReflowLocked(PRBool* aIsLocked);
@ -745,6 +747,8 @@ protected:
nsIFrame* mCurrentEventFrame;
nsIContent* mCurrentEventContent;
nsVoidArray mCurrentEventFrameStack;
nsVoidArray mCurrentEventContentStack;
#ifdef NS_DEBUG
nsRect mCurrentTargetRect;
nsIView* mCurrentTargetView;
@ -784,8 +788,10 @@ private:
//helper funcs for event handling
nsIFrame* GetCurrentEventFrame();
void PushCurrentEventFrame();
void PopCurrentEventFrame();
void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
void PopCurrentEventInfo();
nsresult HandleEventInternal(nsEvent* aEvent, nsIView* aView, nsEventStatus *aStatus);
};
#ifdef NS_DEBUG
@ -983,8 +989,16 @@ PresShell::~PresShell()
mSubShellMap = nsnull;
}
// release current event content and any content on event stack
NS_IF_RELEASE(mCurrentEventContent);
PRInt32 i, count = mCurrentEventContentStack.Count();
nsIContent* currentEventContent;
for (i = 0; i < count; i++) {
currentEventContent = (nsIContent*)mCurrentEventContentStack.ElementAt(i);
NS_IF_RELEASE(currentEventContent);
}
if (mViewManager) {
// Disable paints during tear down of the frame tree
mViewManager->DisableRefresh();
@ -2202,12 +2216,17 @@ PresShell::ClearFrameRefs(nsIFrame* aFrame)
}
if (aFrame == mCurrentEventFrame) {
mCurrentEventFrame->GetContent(&mCurrentEventContent);
aFrame->GetContent(&mCurrentEventContent);
mCurrentEventFrame = nsnull;
}
for (int i=0; i<mCurrentEventFrameStack.Count(); i++) {
if (aFrame == (nsIFrame*)mCurrentEventFrameStack.ElementAt(i)) {
//One of our stack frames was deleted. Get its content so that when we
//pop it we can still get its new frame from its content
nsIContent *currentEventContent;
aFrame->GetContent(&currentEventContent);
mCurrentEventContentStack.ReplaceElementAt((void*)currentEventContent, i);
mCurrentEventFrameStack.ReplaceElementAt(nsnull, i);
}
}
@ -3172,21 +3191,28 @@ PresShell::GetCurrentEventFrame()
}
void
PresShell::PushCurrentEventFrame()
PresShell::PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent)
{
if (mCurrentEventFrame) {
if (mCurrentEventFrame || mCurrentEventContent) {
mCurrentEventFrameStack.InsertElementAt((void*)mCurrentEventFrame, 0);
mCurrentEventContentStack.InsertElementAt((void*)mCurrentEventContent, 0);
}
mCurrentEventFrame = aFrame;
mCurrentEventContent = aContent;
NS_IF_ADDREF(aContent);
}
void
PresShell::PopCurrentEventFrame()
PresShell::PopCurrentEventInfo()
{
mCurrentEventFrame = nsnull;
NS_IF_RELEASE(mCurrentEventContent);
if (0 != mCurrentEventFrameStack.Count()) {
mCurrentEventFrame = (nsIFrame*)mCurrentEventFrameStack.ElementAt(0);
mCurrentEventFrameStack.RemoveElementAt(0);
mCurrentEventContent = (nsIContent*)mCurrentEventContentStack.ElementAt(0);
mCurrentEventContentStack.RemoveElementAt(0);
}
}
@ -3220,16 +3246,15 @@ PresShell::HandleEvent(nsIView *aView,
}
*/
if (nsnull != frame) {
PushCurrentEventFrame();
PushCurrentEventInfo(nsnull, nsnull);
nsIEventStateManager *manager;
nsIContent* focusContent = nsnull;
if (NS_OK == mPresContext->GetEventStateManager(&manager)) {
if (NS_IS_KEY_EVENT(aEvent)) {
//Key events go to the focused frame, not point based.
manager->GetFocusedContent(&focusContent);
if (focusContent)
GetPrimaryFrameFor(focusContent, &mCurrentEventFrame);
manager->GetFocusedContent(&mCurrentEventContent);
if (mCurrentEventContent)
GetPrimaryFrameFor(mCurrentEventContent, &mCurrentEventFrame);
else {
// XXX This is the way key events seem to work? Why?????
// They spend time doing calls to GetFrameForPoint with the
@ -3284,42 +3309,10 @@ PresShell::HandleEvent(nsIView *aView,
}
}
}
NS_IF_RELEASE(mCurrentEventContent);
if (GetCurrentEventFrame() || focusContent) {
//Once we have the targetFrame, handle the event in this order
//1. Give event to event manager for pre event state changes and generation of synthetic events.
rv = manager->PreHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aEventStatus, aView);
//2. Give event to the DOM for third party and JS use.
if ((GetCurrentEventFrame() || focusContent) && NS_OK == rv) {
if (focusContent) {
rv = focusContent->HandleDOMEvent(mPresContext, (nsEvent*)aEvent, nsnull,
NS_EVENT_FLAG_INIT, aEventStatus);
}
else {
nsIContent* targetContent;
if (NS_OK == mCurrentEventFrame->GetContentForEvent(mPresContext, aEvent, &targetContent) && nsnull != targetContent) {
rv = targetContent->HandleDOMEvent(mPresContext, (nsEvent*)aEvent, nsnull,
NS_EVENT_FLAG_INIT, aEventStatus);
NS_RELEASE(targetContent);
}
}
//3. Give event to the Frames for browser default processing.
// XXX The event isn't translated into the local coordinate space
// of the frame...
if (GetCurrentEventFrame() && NS_OK == rv) {
rv = mCurrentEventFrame->HandleEvent(mPresContext, aEvent, aEventStatus);
}
//4. Give event to event manager for post event state changes and generation of synthetic events.
if ((GetCurrentEventFrame() || focusContent) && NS_OK == rv) {
rv = manager->PostHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aEventStatus, aView);
}
}
if (GetCurrentEventFrame()) {
rv = HandleEventInternal(aEvent, aView, aEventStatus);
}
NS_RELEASE(manager);
NS_IF_RELEASE(focusContent);
}
#ifdef NS_DEBUG
if ((nsIFrameDebug::GetShowEventTargetFrameBorder()) && (GetCurrentEventFrame())) {
@ -3347,7 +3340,7 @@ PresShell::HandleEvent(nsIView *aView,
}
}
#endif
PopCurrentEventFrame();
PopCurrentEventInfo();
}
else {
rv = NS_OK;
@ -3357,6 +3350,59 @@ PresShell::HandleEvent(nsIView *aView,
return rv;
}
NS_IMETHODIMP
PresShell::HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame, nsIContent* aContent, nsEventStatus* aStatus)
{
nsresult ret;
PushCurrentEventInfo(aFrame, aContent);
ret = HandleEventInternal(aEvent, nsnull, aStatus);
PopCurrentEventInfo();
return NS_OK;
}
nsresult
PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView, nsEventStatus* aStatus)
{
nsresult rv;
nsIEventStateManager *manager;
if (NS_OK == mPresContext->GetEventStateManager(&manager)) {
//1. Give event to event manager for pre event state changes and generation of synthetic events.
rv = manager->PreHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aStatus, aView);
//2. Give event to the DOM for third party and JS use.
if ((GetCurrentEventFrame()) && NS_OK == rv) {
if (mCurrentEventContent) {
rv = mCurrentEventContent->HandleDOMEvent(mPresContext, aEvent, nsnull,
NS_EVENT_FLAG_INIT, aStatus);
}
else {
nsIContent* targetContent;
if (NS_OK == mCurrentEventFrame->GetContentForEvent(mPresContext, aEvent, &targetContent) && nsnull != targetContent) {
rv = targetContent->HandleDOMEvent(mPresContext, aEvent, nsnull,
NS_EVENT_FLAG_INIT, aStatus);
NS_RELEASE(targetContent);
}
}
//3. Give event to the Frames for browser default processing.
// XXX The event isn't translated into the local coordinate space
// of the frame...
if (GetCurrentEventFrame() && NS_OK == rv && aEvent->eventStructType != NS_EVENT) {
rv = mCurrentEventFrame->HandleEvent(mPresContext, (nsGUIEvent*)aEvent, aStatus);
}
//4. Give event to event manager for post event state changes and generation of synthetic events.
if ((GetCurrentEventFrame()) && NS_OK == rv) {
rv = manager->PostHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aStatus, aView);
}
}
NS_RELEASE(manager);
}
return rv;
}
NS_IMETHODIMP
PresShell::Scrolled(nsIView *aView)
{

View File

@ -27,6 +27,7 @@
#include "nsCoord.h"
#include "nsIDOMSelection.h"
#include "nsIReflowCommand.h"
#include "nsGUIEvent.h"
class nsIContent;
class nsIContentIterator;
@ -388,9 +389,14 @@ public:
*/
NS_IMETHOD GetDisplayNonTextSelection(PRBool *aOutEnabled) = 0;
// XXX events
// XXX selection
/**
* Interface to dispatch events via the presshell
*/
NS_IMETHOD HandleEventWithTarget(nsEvent* aEvent,
nsIFrame* aFrame,
nsIContent* aContent,
nsEventStatus* aStatus) = 0;
/**
* Get and set the history state for the current document
*/

View File

@ -32,6 +32,7 @@ class nsIPresContext;
class nsIDOMEvent;
class nsIFrame;
class nsIView;
class nsIWidget;
/*
* Event listener manager interface.
@ -49,13 +50,13 @@ public:
NS_IMETHOD Init() = 0;
NS_IMETHOD PreHandleEvent(nsIPresContext* aPresContext,
nsGUIEvent *aEvent,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView) = 0;
NS_IMETHOD PostHandleEvent(nsIPresContext* aPresContext,
nsGUIEvent *aEvent,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView) = 0;
@ -80,6 +81,8 @@ public:
NS_IMETHOD RegisterAccessKey(nsIFrame * aFrame, PRUint32 aKey) = 0;
NS_IMETHOD UnregisterAccessKey(nsIFrame * aFrame) = 0;
NS_IMETHOD SetCursor(PRInt32 aCursor, nsIWidget* aWidget, PRBool aLockCursor) = 0;
};
#define NS_EVENT_STATE_UNSPECIFIED 0x0000

View File

@ -807,9 +807,9 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
case NS_MOUSE_MIDDLE_DOUBLECLICK:
case NS_MOUSE_RIGHT_DOUBLECLICK:
return mEventNames[eDOMEvents_dblclick];
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
return mEventNames[eDOMEvents_mouseover];
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
return mEventNames[eDOMEvents_mouseout];
case NS_MOUSE_MOVE:
return mEventNames[eDOMEvents_mousemove];
@ -833,6 +833,7 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
case NS_IMAGE_ABORT:
return mEventNames[eDOMEvents_abort];
case NS_IMAGE_ERROR:
case NS_SCRIPT_ERROR:
return mEventNames[eDOMEvents_error];
case NS_FORM_SUBMIT:
return mEventNames[eDOMEvents_submit];
@ -860,9 +861,9 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return mEventNames[eDOMEvents_commandupdate];
case NS_DRAGDROP_ENTER:
return mEventNames[eDOMEvents_dragenter];
case NS_DRAGDROP_OVER:
case NS_DRAGDROP_OVER_SYNTH:
return mEventNames[eDOMEvents_dragover];
case NS_DRAGDROP_EXIT:
case NS_DRAGDROP_EXIT_SYNTH:
return mEventNames[eDOMEvents_dragexit];
case NS_DRAGDROP_DROP:
return mEventNames[eDOMEvents_dragdrop];

View File

@ -741,8 +741,8 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
case NS_MOUSE_LEFT_DOUBLECLICK:
case NS_MOUSE_MIDDLE_DOUBLECLICK:
case NS_MOUSE_RIGHT_DOUBLECLICK:
case NS_MOUSE_ENTER:
case NS_MOUSE_EXIT:
case NS_MOUSE_ENTER_SYNTH:
case NS_MOUSE_EXIT_SYNTH:
if (nsnull != mMouseListeners) {
if (nsnull == *aDOMEvent) {
ret = NS_NewDOMUIEvent(aDOMEvent, aPresContext, aEvent);
@ -777,10 +777,10 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
case NS_MOUSE_RIGHT_DOUBLECLICK:
ret = mMouseListener->MouseDblClick(*aDOMEvent);
break;
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
ret = mMouseListener->MouseOver(*aDOMEvent);
break;
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
ret = mMouseListener->MouseOut(*aDOMEvent);
break;
default:
@ -824,13 +824,13 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
correctSubType = PR_TRUE;
}
break;
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
subType = NS_EVENT_BITS_MOUSE_MOUSEOVER;
if (ls->mSubType & NS_EVENT_BITS_MOUSE_MOUSEOVER) {
correctSubType = PR_TRUE;
}
break;
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
subType = NS_EVENT_BITS_MOUSE_MOUSEOUT;
if (ls->mSubType & NS_EVENT_BITS_MOUSE_MOUSEOUT) {
correctSubType = PR_TRUE;
@ -1207,6 +1207,7 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
case NS_PAGE_UNLOAD:
case NS_IMAGE_LOAD:
case NS_IMAGE_ERROR:
case NS_SCRIPT_ERROR:
if (nsnull != mLoadListeners) {
if (nsnull == *aDOMEvent) {
@ -1230,6 +1231,7 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
ret = mLoadListener->Unload(*aDOMEvent);
break;
case NS_IMAGE_ERROR:
case NS_SCRIPT_ERROR:
ret = mLoadListener->Error(*aDOMEvent);
default:
break;
@ -1254,6 +1256,7 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
}
break;
case NS_IMAGE_ERROR:
case NS_SCRIPT_ERROR:
subType = NS_EVENT_BITS_LOAD_ERROR;
if (ls->mSubType & NS_EVENT_BITS_LOAD_ERROR) {
correctSubType = PR_TRUE;
@ -1307,8 +1310,8 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
break;
case NS_DRAGDROP_ENTER:
case NS_DRAGDROP_OVER:
case NS_DRAGDROP_EXIT:
case NS_DRAGDROP_OVER_SYNTH:
case NS_DRAGDROP_EXIT_SYNTH:
case NS_DRAGDROP_DROP:
case NS_DRAGDROP_GESTURE:
if (nsnull != mDragListeners) {
@ -1329,10 +1332,10 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
case NS_DRAGDROP_ENTER:
ret = dragListener->DragEnter(*aDOMEvent);
break;
case NS_DRAGDROP_OVER:
case NS_DRAGDROP_OVER_SYNTH:
ret = dragListener->DragOver(*aDOMEvent);
break;
case NS_DRAGDROP_EXIT:
case NS_DRAGDROP_EXIT_SYNTH:
ret = dragListener->DragExit(*aDOMEvent);
break;
case NS_DRAGDROP_DROP:
@ -1352,12 +1355,12 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
if (dragStruct->mSubType & NS_EVENT_BITS_DRAG_ENTER)
correctSubType = PR_TRUE;
break;
case NS_DRAGDROP_OVER:
case NS_DRAGDROP_OVER_SYNTH:
subType = NS_EVENT_BITS_DRAG_OVER;
if (dragStruct->mSubType & NS_EVENT_BITS_DRAG_OVER)
correctSubType = PR_TRUE;
break;
case NS_DRAGDROP_EXIT:
case NS_DRAGDROP_EXIT_SYNTH:
subType = NS_EVENT_BITS_DRAG_EXIT;
if (dragStruct->mSubType & NS_EVENT_BITS_DRAG_EXIT)
correctSubType = PR_TRUE;

View File

@ -100,6 +100,7 @@ nsEventStateManager::nsEventStateManager()
mLastRightMouseDownContent = nsnull;
mConsumeFocusEvents = PR_FALSE;
mLockCursor = 0;
// init d&d gesture state machine variables
mIsTrackingDragGesture = PR_FALSE;
@ -231,7 +232,7 @@ NS_IMPL_ISUPPORTS1(nsEventStateManager, nsIEventStateManager)
NS_IMETHODIMP
nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext,
nsGUIEvent *aEvent,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView)
@ -258,7 +259,7 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext,
switch (aEvent->message) {
case NS_MOUSE_LEFT_BUTTON_DOWN:
BeginTrackingDragGesture ( aEvent, aTargetFrame );
BeginTrackingDragGesture ( (nsGUIEvent*)aEvent, aTargetFrame );
mLClickCount = ((nsMouseEvent*)aEvent)->clickCount;
SetClickCount(aPresContext, (nsMouseEvent*)aEvent, aStatus);
break;
@ -282,17 +283,17 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext,
// If this is the case, however, we know that ClearFrameRefs() has been called
// and it cleared out |mCurrentTarget|. As a result, we should pass |mCurrentTarget|
// into UpdateCursor().
GenerateDragGesture(aPresContext, aEvent);
GenerateDragGesture(aPresContext, (nsGUIEvent*)aEvent);
UpdateCursor(aPresContext, aEvent, mCurrentTarget, aStatus);
GenerateMouseEnterExit(aPresContext, aEvent);
GenerateMouseEnterExit(aPresContext, (nsGUIEvent*)aEvent);
break;
case NS_MOUSE_EXIT:
GenerateMouseEnterExit(aPresContext, aEvent);
GenerateMouseEnterExit(aPresContext, (nsGUIEvent*)aEvent);
//This is a window level mouseenter event and should stop here
aEvent->message = 0;
break;
case NS_DRAGDROP_OVER:
GenerateDragDropEnterExit(aPresContext, aEvent);
GenerateDragDropEnterExit(aPresContext, (nsGUIEvent*)aEvent);
break;
case NS_GOTFOCUS:
{
@ -663,7 +664,7 @@ nsEventStateManager :: GenerateDragGesture ( nsIPresContext* aPresContext, nsGUI
NS_IMETHODIMP
nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext,
nsGUIEvent *aEvent,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView)
@ -869,7 +870,7 @@ nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext,
case NS_DRAGDROP_EXIT:
// clean up after ourselves. make sure we do this _after_ the event, else we'll
// clean up too early!
GenerateDragDropEnterExit(aPresContext, aEvent);
GenerateDragDropEnterExit(aPresContext, (nsGUIEvent*)aEvent);
break;
case NS_KEY_PRESS:
if (nsEventStatus_eConsumeNoDefault != *aStatus) {
@ -1055,24 +1056,57 @@ nsEventStateManager::UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent,
nsEventStatus* aStatus)
{
PRInt32 cursor;
nsCursor c;
nsCOMPtr<nsIContent> targetContent;
if (mCurrentTarget) {
mCurrentTarget->GetContent(getter_AddRefs(targetContent));
//If cursor is locked just use the locked one
if (mLockCursor) {
cursor = mLockCursor;
}
//Check if the current target is disabled. If so use the default pointer.
if (targetContent && CheckDisabled(targetContent)) {
cursor = NS_STYLE_CURSOR_DEFAULT;
}
//If not disabled, check for the right cursor.
//If not locked, look for correct cursor
else {
if ( aTargetFrame )
aTargetFrame->GetCursor(aPresContext, aEvent->point, cursor);
nsCOMPtr<nsIContent> targetContent;
if (mCurrentTarget) {
mCurrentTarget->GetContent(getter_AddRefs(targetContent));
}
//Check if the current target is disabled. If so use the default pointer.
if (targetContent && CheckDisabled(targetContent)) {
cursor = NS_STYLE_CURSOR_DEFAULT;
}
//If not disabled, check for the right cursor.
else {
if (aTargetFrame) {
aTargetFrame->GetCursor(aPresContext, aEvent->point, cursor);
}
}
}
switch (cursor) {
if (aTargetFrame) {
nsCOMPtr<nsIWidget> window;
aTargetFrame->GetWindow(aPresContext, getter_AddRefs(window));
SetCursor(cursor, window, PR_FALSE);
}
if (mLockCursor || NS_STYLE_CURSOR_AUTO != cursor) {
*aStatus = nsEventStatus_eConsumeDoDefault;
}
}
NS_IMETHODIMP
nsEventStateManager::SetCursor(PRInt32 aCursor, nsIWidget* aWidget, PRBool aLockCursor)
{
nsCursor c;
NS_ENSURE_TRUE(aWidget, NS_ERROR_FAILURE);
if (aLockCursor) {
if (NS_STYLE_CURSOR_AUTO != aCursor) {
mLockCursor = aCursor;
}
else {
//If cursor style is set to auto we unlock the cursor again.
mLockCursor = 0;
}
}
switch (aCursor) {
default:
case NS_STYLE_CURSOR_AUTO:
case NS_STYLE_CURSOR_DEFAULT:
@ -1104,7 +1138,7 @@ nsEventStateManager::UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent,
case NS_STYLE_CURSOR_E_RESIZE:
c = eCursor_sizeWE;
break;
//These aren't in the CSS2 spec. Don't know what to do with them.
//We don't have cursors defined for these in nsIWidget. Need them to fix this.
case NS_STYLE_CURSOR_NE_RESIZE:
case NS_STYLE_CURSOR_NW_RESIZE:
case NS_STYLE_CURSOR_SE_RESIZE:
@ -1113,15 +1147,9 @@ nsEventStateManager::UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent,
break;
}
if (NS_STYLE_CURSOR_AUTO != cursor) {
*aStatus = nsEventStatus_eConsumeDoDefault;
}
aWidget->SetCursor(c);
if ( aTargetFrame ) {
nsCOMPtr<nsIWidget> window;
aTargetFrame->GetWindow(aPresContext, getter_AddRefs(window));
window->SetCursor(c);
}
return NS_OK;
}
void
@ -1152,7 +1180,7 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_MOUSE_EXIT;
event.message = NS_MOUSE_EXIT_SYNTH;
event.widget = aEvent->widget;
event.clickCount = 0;
event.point = aEvent->point;
@ -1196,7 +1224,7 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_MOUSE_ENTER;
event.message = NS_MOUSE_ENTER_SYNTH;
event.widget = aEvent->widget;
event.clickCount = 0;
event.point = aEvent->point;
@ -1251,7 +1279,7 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_MOUSE_EXIT;
event.message = NS_MOUSE_EXIT_SYNTH;
event.widget = aEvent->widget;
event.clickCount = 0;
event.point = aEvent->point;
@ -1315,7 +1343,7 @@ nsEventStateManager::GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsG
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_DRAGDROP_EVENT;
event.message = NS_DRAGDROP_EXIT;
event.message = NS_DRAGDROP_EXIT_SYNTH;
event.widget = aEvent->widget;
event.clickCount = 0;
event.point = aEvent->point;
@ -1406,7 +1434,7 @@ nsEventStateManager::GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsG
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_DRAGDROP_EVENT;
event.message = NS_DRAGDROP_EXIT;
event.message = NS_DRAGDROP_EXIT_SYNTH;
event.widget = aEvent->widget;
event.clickCount = 0;
event.point = aEvent->point;
@ -1550,14 +1578,10 @@ nsEventStateManager::CheckForAndDispatchClick(nsIPresContext* aPresContext,
event.isAlt = aEvent->isAlt;
event.isMeta = aEvent->isMeta;
if (mouseContent) {
ret = mouseContent->HandleDOMEvent(aPresContext, &event, nsnull,
NS_EVENT_FLAG_INIT, aStatus);
NS_ASSERTION(NS_SUCCEEDED(ret), "HandleDOMEvent failed");
}
if (nsnull != mCurrentTarget) {
ret = mCurrentTarget->HandleEvent(aPresContext, &event, aStatus);
nsCOMPtr<nsIPresShell> presShell;
mPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
ret = presShell->HandleEventWithTarget(&event, mCurrentTarget, mouseContent, aStatus);
}
}
return ret;

View File

@ -62,7 +62,7 @@ public:
* DOM or frame event handling should occur here as well.
*/
NS_IMETHOD PreHandleEvent(nsIPresContext* aPresContext,
nsGUIEvent *aEvent,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView);
@ -73,7 +73,7 @@ public:
* DOM and frame processing.
*/
NS_IMETHOD PostHandleEvent(nsIPresContext* aPresContext,
nsGUIEvent *aEvent,
nsEvent *aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus,
nsIView* aView);
@ -97,6 +97,8 @@ public:
NS_IMETHOD RegisterAccessKey(nsIFrame * aFrame, PRUint32 aKey);
NS_IMETHOD UnregisterAccessKey(nsIFrame * aFrame);
NS_IMETHOD SetCursor(PRInt32 aCursor, nsIWidget* aWidget, PRBool aLockCursor);
protected:
void UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus);
void GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIEvent* aEvent);
@ -171,6 +173,7 @@ protected:
PRInt32 mCurrentTabIndex;
nsIWidget * mLastWindowToHaveFocus; // last native window to get focus via the evs
PRBool mConsumeFocusEvents;
PRInt32 mLockCursor;
//Anti-recursive stack controls
nsIContent* mFirstBlurEvent;

View File

@ -641,7 +641,9 @@ nsGfxButtonControlFrame::HandleEvent(nsIPresContext* aPresContext,
// lets see if the button was clicked
switch (aEvent->message) {
case NS_MOUSE_LEFT_CLICK:
MouseClicked(aPresContext);
if (nsEventStatus_eConsumeNoDefault != *aEventStatus) {
MouseClicked(aPresContext);
}
break;
}

View File

@ -1308,8 +1308,8 @@ nsListControlFrame::HandleEvent(nsIPresContext* aPresContext,
"<NA>","<NA>","<NA>","<NA>","<NA>","<NA>","<NA>","<NA>",
"NS_MOUSE_RIGHT_BUTTON_UP",
"NS_MOUSE_RIGHT_BUTTON_DOWN",
"NS_MOUSE_ENTER",
"NS_MOUSE_EXIT",
"NS_MOUSE_ENTER_SYNTH",
"NS_MOUSE_EXIT_SYNTH",
"NS_MOUSE_LEFT_DOUBLECLICK",
"NS_MOUSE_MIDDLE_DOUBLECLICK",
"NS_MOUSE_RIGHT_DOUBLECLICK",

View File

@ -951,6 +951,10 @@ nsImageMap::IsInside(nscoord aX, nscoord aY)
if (href.Length() > 0) {
return PR_TRUE;
}
else {
//We need to return here so we don't hit an overlapping map area
return PR_FALSE;
}
}
}
return PR_FALSE;

View File

@ -951,6 +951,10 @@ nsImageMap::IsInside(nscoord aX, nscoord aY)
if (href.Length() > 0) {
return PR_TRUE;
}
else {
//We need to return here so we don't hit an overlapping map area
return PR_FALSE;
}
}
}
return PR_FALSE;

View File

@ -610,6 +610,8 @@ public:
NS_IMETHOD GetGeneratedContentIterator(nsIContent* aContent,
GeneratedContentType aType,
nsIContentIterator** aIterator) const;
NS_IMETHOD HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame, nsIContent* aContent, nsEventStatus* aStatus);
NS_IMETHOD IsReflowLocked(PRBool* aIsLocked);
@ -745,6 +747,8 @@ protected:
nsIFrame* mCurrentEventFrame;
nsIContent* mCurrentEventContent;
nsVoidArray mCurrentEventFrameStack;
nsVoidArray mCurrentEventContentStack;
#ifdef NS_DEBUG
nsRect mCurrentTargetRect;
nsIView* mCurrentTargetView;
@ -784,8 +788,10 @@ private:
//helper funcs for event handling
nsIFrame* GetCurrentEventFrame();
void PushCurrentEventFrame();
void PopCurrentEventFrame();
void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
void PopCurrentEventInfo();
nsresult HandleEventInternal(nsEvent* aEvent, nsIView* aView, nsEventStatus *aStatus);
};
#ifdef NS_DEBUG
@ -983,8 +989,16 @@ PresShell::~PresShell()
mSubShellMap = nsnull;
}
// release current event content and any content on event stack
NS_IF_RELEASE(mCurrentEventContent);
PRInt32 i, count = mCurrentEventContentStack.Count();
nsIContent* currentEventContent;
for (i = 0; i < count; i++) {
currentEventContent = (nsIContent*)mCurrentEventContentStack.ElementAt(i);
NS_IF_RELEASE(currentEventContent);
}
if (mViewManager) {
// Disable paints during tear down of the frame tree
mViewManager->DisableRefresh();
@ -2202,12 +2216,17 @@ PresShell::ClearFrameRefs(nsIFrame* aFrame)
}
if (aFrame == mCurrentEventFrame) {
mCurrentEventFrame->GetContent(&mCurrentEventContent);
aFrame->GetContent(&mCurrentEventContent);
mCurrentEventFrame = nsnull;
}
for (int i=0; i<mCurrentEventFrameStack.Count(); i++) {
if (aFrame == (nsIFrame*)mCurrentEventFrameStack.ElementAt(i)) {
//One of our stack frames was deleted. Get its content so that when we
//pop it we can still get its new frame from its content
nsIContent *currentEventContent;
aFrame->GetContent(&currentEventContent);
mCurrentEventContentStack.ReplaceElementAt((void*)currentEventContent, i);
mCurrentEventFrameStack.ReplaceElementAt(nsnull, i);
}
}
@ -3172,21 +3191,28 @@ PresShell::GetCurrentEventFrame()
}
void
PresShell::PushCurrentEventFrame()
PresShell::PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent)
{
if (mCurrentEventFrame) {
if (mCurrentEventFrame || mCurrentEventContent) {
mCurrentEventFrameStack.InsertElementAt((void*)mCurrentEventFrame, 0);
mCurrentEventContentStack.InsertElementAt((void*)mCurrentEventContent, 0);
}
mCurrentEventFrame = aFrame;
mCurrentEventContent = aContent;
NS_IF_ADDREF(aContent);
}
void
PresShell::PopCurrentEventFrame()
PresShell::PopCurrentEventInfo()
{
mCurrentEventFrame = nsnull;
NS_IF_RELEASE(mCurrentEventContent);
if (0 != mCurrentEventFrameStack.Count()) {
mCurrentEventFrame = (nsIFrame*)mCurrentEventFrameStack.ElementAt(0);
mCurrentEventFrameStack.RemoveElementAt(0);
mCurrentEventContent = (nsIContent*)mCurrentEventContentStack.ElementAt(0);
mCurrentEventContentStack.RemoveElementAt(0);
}
}
@ -3220,16 +3246,15 @@ PresShell::HandleEvent(nsIView *aView,
}
*/
if (nsnull != frame) {
PushCurrentEventFrame();
PushCurrentEventInfo(nsnull, nsnull);
nsIEventStateManager *manager;
nsIContent* focusContent = nsnull;
if (NS_OK == mPresContext->GetEventStateManager(&manager)) {
if (NS_IS_KEY_EVENT(aEvent)) {
//Key events go to the focused frame, not point based.
manager->GetFocusedContent(&focusContent);
if (focusContent)
GetPrimaryFrameFor(focusContent, &mCurrentEventFrame);
manager->GetFocusedContent(&mCurrentEventContent);
if (mCurrentEventContent)
GetPrimaryFrameFor(mCurrentEventContent, &mCurrentEventFrame);
else {
// XXX This is the way key events seem to work? Why?????
// They spend time doing calls to GetFrameForPoint with the
@ -3284,42 +3309,10 @@ PresShell::HandleEvent(nsIView *aView,
}
}
}
NS_IF_RELEASE(mCurrentEventContent);
if (GetCurrentEventFrame() || focusContent) {
//Once we have the targetFrame, handle the event in this order
//1. Give event to event manager for pre event state changes and generation of synthetic events.
rv = manager->PreHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aEventStatus, aView);
//2. Give event to the DOM for third party and JS use.
if ((GetCurrentEventFrame() || focusContent) && NS_OK == rv) {
if (focusContent) {
rv = focusContent->HandleDOMEvent(mPresContext, (nsEvent*)aEvent, nsnull,
NS_EVENT_FLAG_INIT, aEventStatus);
}
else {
nsIContent* targetContent;
if (NS_OK == mCurrentEventFrame->GetContentForEvent(mPresContext, aEvent, &targetContent) && nsnull != targetContent) {
rv = targetContent->HandleDOMEvent(mPresContext, (nsEvent*)aEvent, nsnull,
NS_EVENT_FLAG_INIT, aEventStatus);
NS_RELEASE(targetContent);
}
}
//3. Give event to the Frames for browser default processing.
// XXX The event isn't translated into the local coordinate space
// of the frame...
if (GetCurrentEventFrame() && NS_OK == rv) {
rv = mCurrentEventFrame->HandleEvent(mPresContext, aEvent, aEventStatus);
}
//4. Give event to event manager for post event state changes and generation of synthetic events.
if ((GetCurrentEventFrame() || focusContent) && NS_OK == rv) {
rv = manager->PostHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aEventStatus, aView);
}
}
if (GetCurrentEventFrame()) {
rv = HandleEventInternal(aEvent, aView, aEventStatus);
}
NS_RELEASE(manager);
NS_IF_RELEASE(focusContent);
}
#ifdef NS_DEBUG
if ((nsIFrameDebug::GetShowEventTargetFrameBorder()) && (GetCurrentEventFrame())) {
@ -3347,7 +3340,7 @@ PresShell::HandleEvent(nsIView *aView,
}
}
#endif
PopCurrentEventFrame();
PopCurrentEventInfo();
}
else {
rv = NS_OK;
@ -3357,6 +3350,59 @@ PresShell::HandleEvent(nsIView *aView,
return rv;
}
NS_IMETHODIMP
PresShell::HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame, nsIContent* aContent, nsEventStatus* aStatus)
{
nsresult ret;
PushCurrentEventInfo(aFrame, aContent);
ret = HandleEventInternal(aEvent, nsnull, aStatus);
PopCurrentEventInfo();
return NS_OK;
}
nsresult
PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView, nsEventStatus* aStatus)
{
nsresult rv;
nsIEventStateManager *manager;
if (NS_OK == mPresContext->GetEventStateManager(&manager)) {
//1. Give event to event manager for pre event state changes and generation of synthetic events.
rv = manager->PreHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aStatus, aView);
//2. Give event to the DOM for third party and JS use.
if ((GetCurrentEventFrame()) && NS_OK == rv) {
if (mCurrentEventContent) {
rv = mCurrentEventContent->HandleDOMEvent(mPresContext, aEvent, nsnull,
NS_EVENT_FLAG_INIT, aStatus);
}
else {
nsIContent* targetContent;
if (NS_OK == mCurrentEventFrame->GetContentForEvent(mPresContext, aEvent, &targetContent) && nsnull != targetContent) {
rv = targetContent->HandleDOMEvent(mPresContext, aEvent, nsnull,
NS_EVENT_FLAG_INIT, aStatus);
NS_RELEASE(targetContent);
}
}
//3. Give event to the Frames for browser default processing.
// XXX The event isn't translated into the local coordinate space
// of the frame...
if (GetCurrentEventFrame() && NS_OK == rv && aEvent->eventStructType != NS_EVENT) {
rv = mCurrentEventFrame->HandleEvent(mPresContext, (nsGUIEvent*)aEvent, aStatus);
}
//4. Give event to event manager for post event state changes and generation of synthetic events.
if ((GetCurrentEventFrame()) && NS_OK == rv) {
rv = manager->PostHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aStatus, aView);
}
}
NS_RELEASE(manager);
}
return rv;
}
NS_IMETHODIMP
PresShell::Scrolled(nsIView *aView)
{

View File

@ -925,7 +925,7 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsIPresContext* aPresContext,
// XXX Bring up a contextual menu provided by the application
break;
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
{
nsIEventStateManager *stateManager;
if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) {
@ -947,7 +947,7 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsIPresContext* aPresContext,
}
break;
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
{
nsIEventStateManager *stateManager;
if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) {

View File

@ -459,7 +459,7 @@ nsHTMLButtonElement::HandleDOMEvent(nsIPresContext* aPresContext,
// XXX Bring up a contextual menu provided by the application
break;
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
{
nsIEventStateManager *stateManager;
if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) {
@ -471,7 +471,7 @@ nsHTMLButtonElement::HandleDOMEvent(nsIPresContext* aPresContext,
break;
// XXX this doesn't seem to do anything yet
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
{
nsIEventStateManager *stateManager;
if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) {

View File

@ -641,7 +641,9 @@ nsGfxButtonControlFrame::HandleEvent(nsIPresContext* aPresContext,
// lets see if the button was clicked
switch (aEvent->message) {
case NS_MOUSE_LEFT_CLICK:
MouseClicked(aPresContext);
if (nsEventStatus_eConsumeNoDefault != *aEventStatus) {
MouseClicked(aPresContext);
}
break;
}

View File

@ -1442,8 +1442,8 @@ nsGfxListControlFrame::HandleEvent(nsIPresContext* aPresContext,
"<NA>","<NA>","<NA>","<NA>","<NA>","<NA>","<NA>","<NA>",
"NS_MOUSE_RIGHT_BUTTON_UP",
"NS_MOUSE_RIGHT_BUTTON_DOWN",
"NS_MOUSE_ENTER",
"NS_MOUSE_EXIT",
"NS_MOUSE_ENTER_SYNTH",
"NS_MOUSE_EXIT_SYNTH",
"NS_MOUSE_LEFT_DOUBLECLICK",
"NS_MOUSE_MIDDLE_DOUBLECLICK",
"NS_MOUSE_RIGHT_DOUBLECLICK",

View File

@ -924,9 +924,9 @@ NS_METHOD nsGfxTextControlFrame::HandleEvent(nsIPresContext* aPresContext,
break;
case NS_DRAGDROP_ENTER:
case NS_DRAGDROP_OVER:
case NS_DRAGDROP_OVER_SYNTH:
case NS_DRAGDROP_DROP:
case NS_DRAGDROP_EXIT:
case NS_DRAGDROP_EXIT_SYNTH:
// currently unused
break;

View File

@ -1308,8 +1308,8 @@ nsListControlFrame::HandleEvent(nsIPresContext* aPresContext,
"<NA>","<NA>","<NA>","<NA>","<NA>","<NA>","<NA>","<NA>",
"NS_MOUSE_RIGHT_BUTTON_UP",
"NS_MOUSE_RIGHT_BUTTON_DOWN",
"NS_MOUSE_ENTER",
"NS_MOUSE_EXIT",
"NS_MOUSE_ENTER_SYNTH",
"NS_MOUSE_EXIT_SYNTH",
"NS_MOUSE_LEFT_DOUBLECLICK",
"NS_MOUSE_MIDDLE_DOUBLECLICK",
"NS_MOUSE_RIGHT_DOUBLECLICK",

View File

@ -299,7 +299,7 @@ NS_METHOD nsNativeFormControlFrame::HandleEvent(nsIPresContext* aPresContext,
PRInt32 type;
GetType(&type);
switch (aEvent->message) {
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
mLastMouseState = eMouseEnter;
break;
@ -314,7 +314,7 @@ NS_METHOD nsNativeFormControlFrame::HandleEvent(nsIPresContext* aPresContext,
mLastMouseState = eMouseEnter;
break;
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
mLastMouseState = eMouseNone;
break;

View File

@ -295,7 +295,7 @@ nsXMLElement::HandleDOMEvent(nsIPresContext* aPresContext,
// XXX Bring up a contextual menu provided by the application
break;
case NS_MOUSE_ENTER:
case NS_MOUSE_ENTER_SYNTH:
{
nsAutoString href, target;
nsIURI* baseURL = nsnull;
@ -315,7 +315,7 @@ nsXMLElement::HandleDOMEvent(nsIPresContext* aPresContext,
break;
// XXX this doesn't seem to do anything yet
case NS_MOUSE_EXIT:
case NS_MOUSE_EXIT_SYNTH:
{
nsAutoString empty;
ret = mInner.TriggerLink(aPresContext, eLinkVerb_Replace, nsnull, empty, empty, PR_FALSE);

View File

@ -311,7 +311,7 @@ nsMenuFrame::HandleEvent(nsIPresContext* aPresContext,
// Execute the execute event handler.
Execute();
}
else if (aEvent->message == NS_MOUSE_EXIT) {
else if (aEvent->message == NS_MOUSE_EXIT_SYNTH) {
// Kill our timer if one is active.
if (mOpenTimer) {
mOpenTimer->Cancel();

View File

@ -88,7 +88,7 @@ nsScrollbarButtonFrame::HandleEvent(nsIPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
// XXX hack until handle release is actually called in nsframe.
if (aEvent->message == NS_MOUSE_EXIT|| aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP)
if (aEvent->message == NS_MOUSE_EXIT_SYNTH|| aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP)
HandleRelease(aPresContext, aEvent, aEventStatus);
return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);

View File

@ -467,7 +467,7 @@ nsSliderFrame::HandleEvent(nsIPresContext* aPresContext,
}
// XXX hack until handle release is actually called in nsframe.
if (aEvent->message == NS_MOUSE_EXIT|| aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP)
if (aEvent->message == NS_MOUSE_EXIT_SYNTH || aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP)
HandleRelease(aPresContext, aEvent, aEventStatus);
return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);

View File

@ -201,9 +201,9 @@ nsTreeCellFrame::HandleEvent(nsIPresContext* aPresContext,
else
HandleMouseDownEvent(aPresContext, aEvent, aEventStatus);
}
else if (aEvent->message == NS_MOUSE_ENTER)
else if (aEvent->message == NS_MOUSE_ENTER_SYNTH)
HandleMouseEnterEvent(aPresContext, aEvent, aEventStatus);
else if (aEvent->message == NS_MOUSE_EXIT)
else if (aEvent->message == NS_MOUSE_EXIT_SYNTH)
HandleMouseExitEvent(aPresContext, aEvent, aEventStatus);
else if (aEvent->message == NS_MOUSE_LEFT_DOUBLECLICK)
HandleDoubleClickEvent(aPresContext, aEvent, aEventStatus);

View File

@ -333,6 +333,8 @@ enum nsDragDropEventStatus {
// Indicates the display has changed depth
#define NS_DISPLAYCHANGED (NS_WINDOW_START + 40)
// Indicates a script error has occurred
#define NS_SCRIPT_ERROR (NS_WINDOW_START + 50)
#define NS_MOUSE_MESSAGE_START 300
#define NS_MOUSE_MOVE (NS_MOUSE_MESSAGE_START)
@ -351,6 +353,8 @@ enum nsDragDropEventStatus {
#define NS_MOUSE_MIDDLE_CLICK (NS_MOUSE_MESSAGE_START + 28)
#define NS_MOUSE_RIGHT_CLICK (NS_MOUSE_MESSAGE_START + 29)
#define NS_MOUSE_ACTIVATE (NS_MOUSE_MESSAGE_START + 30)
#define NS_MOUSE_ENTER_SYNTH (NS_MOUSE_MESSAGE_START + 31)
#define NS_MOUSE_EXIT_SYNTH (NS_MOUSE_MESSAGE_START + 32)
#define NS_SCROLLBAR_MESSAGE_START 1000
#define NS_SCROLLBAR_POS (NS_SCROLLBAR_MESSAGE_START)
@ -385,6 +389,8 @@ enum nsDragDropEventStatus {
#define NS_DRAGDROP_EXIT (NS_DRAGDROP_EVENT_START + 2)
#define NS_DRAGDROP_DROP (NS_DRAGDROP_EVENT_START + 3)
#define NS_DRAGDROP_GESTURE (NS_DRAGDROP_EVENT_START + 4)
#define NS_DRAGDROP_OVER_SYNTH (NS_DRAGDROP_EVENT_START + 1)
#define NS_DRAGDROP_EXIT_SYNTH (NS_DRAGDROP_EVENT_START + 2)
// Events for popups
#define NS_MENU_EVENT_START 1500
@ -414,6 +420,10 @@ enum nsDragDropEventStatus {
((evnt)->message == NS_MOUSE_RIGHT_DOUBLECLICK) || \
((evnt)->message == NS_MOUSE_ENTER) || \
((evnt)->message == NS_MOUSE_EXIT) || \
((evnt)->message == NS_MOUSE_ENTER) || \
((evnt)->message == NS_MOUSE_EXIT) || \
((evnt)->message == NS_MOUSE_ENTER_SYNTH) || \
((evnt)->message == NS_MOUSE_EXIT_SYNTH) || \
((evnt)->message == NS_MOUSE_MOVE))
#define NS_IS_KEY_EVENT(evnt) \