Make command= event retargeting dispatch a new event rather than reusing the old one. Add a new interface for command events that supports a sourceEvent property for accessing the original event. Bug 336696, r=neil sr=jst.

This commit is contained in:
bryner%brianryner.com 2006-05-22 16:18:45 +00:00
parent 69aa263848
commit 87831f25b1
17 changed files with 364 additions and 13 deletions

View File

@ -95,5 +95,7 @@ NS_NewDOMSVGEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsEv
nsresult
NS_NewDOMSVGZoomEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsGUIEvent* aEvent);
#endif // MOZ_SVG
nsresult
NS_NewDOMXULCommandEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsXULCommandEvent* aEvent);
#endif // nsIPrivateDOMEvent_h__

View File

@ -76,6 +76,7 @@ CPPSRCS = \
nsDOMPopupBlockedEvent.cpp \
nsDOMBeforeUnloadEvent.cpp \
nsDOMPageTransitionEvent.cpp \
nsDOMXULCommandEvent.cpp \
nsPrivateTextRange.cpp \
nsDOMEventGroup.cpp \
nsXMLEventsManager.cpp \

View File

@ -649,6 +649,11 @@ NS_METHOD nsDOMEvent::DuplicatePrivateData()
newEvent->eventStructType = NS_SVGZOOM_EVENT;
break;
#endif // MOZ_SVG
case NS_XUL_COMMAND_EVENT:
newEvent = new nsXULCommandEvent(PR_FALSE, msg, nsnull);
NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
newEvent->eventStructType = NS_XUL_COMMAND_EVENT;
break;
default:
NS_WARNING("Unknown event type!!!");
return NS_ERROR_FAILURE;

View File

@ -0,0 +1,148 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* 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 Gecko.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsDOMXULCommandEvent.h"
#include "nsContentUtils.h"
nsDOMXULCommandEvent::nsDOMXULCommandEvent(nsPresContext* aPresContext,
nsXULCommandEvent* aEvent)
: nsDOMUIEvent(aPresContext,
aEvent ? aEvent : new nsXULCommandEvent(PR_FALSE, 0, nsnull))
{
if (aEvent) {
mEventIsInternal = PR_FALSE;
}
else {
mEventIsInternal = PR_TRUE;
mEvent->time = PR_Now();
}
}
nsDOMXULCommandEvent::~nsDOMXULCommandEvent()
{
}
NS_IMPL_ADDREF_INHERITED(nsDOMXULCommandEvent, nsDOMUIEvent)
NS_IMPL_RELEASE_INHERITED(nsDOMXULCommandEvent, nsDOMUIEvent)
NS_INTERFACE_MAP_BEGIN(nsDOMXULCommandEvent)
NS_INTERFACE_MAP_ENTRY(nsIDOMXULCommandEvent)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XULCommandEvent)
NS_INTERFACE_MAP_END_INHERITING(nsDOMUIEvent)
NS_IMETHODIMP
nsDOMXULCommandEvent::GetAltKey(PRBool* aIsDown)
{
NS_ENSURE_ARG_POINTER(aIsDown);
*aIsDown = Event()->isAlt;
return NS_OK;
}
NS_IMETHODIMP
nsDOMXULCommandEvent::GetCtrlKey(PRBool* aIsDown)
{
NS_ENSURE_ARG_POINTER(aIsDown);
*aIsDown = Event()->isControl;
return NS_OK;
}
NS_IMETHODIMP
nsDOMXULCommandEvent::GetShiftKey(PRBool* aIsDown)
{
NS_ENSURE_ARG_POINTER(aIsDown);
*aIsDown = Event()->isShift;
return NS_OK;
}
NS_IMETHODIMP
nsDOMXULCommandEvent::GetMetaKey(PRBool* aIsDown)
{
NS_ENSURE_ARG_POINTER(aIsDown);
*aIsDown = Event()->isMeta;
return NS_OK;
}
NS_IMETHODIMP
nsDOMXULCommandEvent::GetSourceNode(nsIDOMEventTarget** aSourceNode)
{
NS_ENSURE_ARG_POINTER(aSourceNode);
nsISupports *sourceNode = Event()->sourceNode;
if (sourceNode) {
return CallQueryInterface(sourceNode, aSourceNode);
}
// There was no explicit sourceNode, so return the originalTarget.
return GetOriginalTarget(aSourceNode);
}
NS_IMETHODIMP
nsDOMXULCommandEvent::InitCommandEvent(const nsAString& aType,
PRBool aCanBubble, PRBool aCancelable,
nsIDOMAbstractView *aView,
PRInt32 aDetail,
PRBool aCtrlKey, PRBool aAltKey,
PRBool aShiftKey, PRBool aMetaKey,
nsIDOMEventTarget* aSourceNode)
{
nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable,
aView, aDetail);
NS_ENSURE_SUCCESS(rv, rv);
nsXULCommandEvent *event = Event();
event->isControl = aCtrlKey;
event->isAlt = aAltKey;
event->isShift = aShiftKey;
event->isMeta = aMetaKey;
event->sourceNode = aSourceNode;
return NS_OK;
}
nsresult NS_NewDOMXULCommandEvent(nsIDOMEvent** aInstancePtrResult,
nsPresContext* aPresContext,
nsXULCommandEvent *aEvent)
{
nsDOMXULCommandEvent* it = new nsDOMXULCommandEvent(aPresContext, aEvent);
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
return CallQueryInterface(it, aInstancePtrResult);
}

View File

@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* 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 Gecko.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// This class implements a XUL "command" event. See nsIDOMXULCommandEvent.idl
#ifndef nsDOMXULCommandEvent_h_
#define nsDOMXULCommandEvent_h_
#include "nsDOMUIEvent.h"
#include "nsIDOMXULCommandEvent.h"
class nsDOMXULCommandEvent : public nsDOMUIEvent,
public nsIDOMXULCommandEvent
{
public:
nsDOMXULCommandEvent(nsPresContext* aPresContext, nsXULCommandEvent* aEvent);
virtual ~nsDOMXULCommandEvent();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMXULCOMMANDEVENT
// Forward our inherited virtual methods to the base class
NS_FORWARD_TO_NSDOMUIEVENT
private:
// Convenience accessor for the event
nsXULCommandEvent* Event() {
return NS_STATIC_CAST(nsXULCommandEvent*, mEvent);
}
};
#endif // nsDOMXULCommandEvent_h_

View File

@ -688,6 +688,11 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsGUIEvent*,aEvent));
#endif // MOZ_SVG
case NS_XUL_COMMAND_EVENT:
return NS_NewDOMXULCommandEvent(aDOMEvent, aPresContext,
NS_STATIC_CAST(nsXULCommandEvent*,
aEvent));
}
// For all other types of events, create a vanilla event object.
@ -727,6 +732,9 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
aEventType.LowerCaseEqualsLiteral("svgzoomevents"))
return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext, nsnull);
#endif // MOZ_SVG
if (aEventType.LowerCaseEqualsLiteral("xulcommandevent") ||
aEventType.LowerCaseEqualsLiteral("xulcommandevents"))
return NS_NewDOMXULCommandEvent(aDOMEvent, aPresContext, nsnull);
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}

View File

@ -363,7 +363,7 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver,
aEvent->PreventDefault();
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(PR_TRUE, NS_XUL_COMMAND, nsnull, nsMouseEvent::eReal);
nsXULCommandEvent event(PR_TRUE, NS_XUL_COMMAND, nsnull);
// Copy the modifiers from the key event.
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);

View File

@ -1701,6 +1701,15 @@ nsXULElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
~NS_EVENT_FLAG_STOP_DISPATCH_IMMEDIATELY;
// Dispatch will set the right target.
aVisitor.mEvent->target = nsnull;
if (aVisitor.mEvent->eventStructType == NS_XUL_COMMAND_EVENT) {
// Set the source node to this element
NS_STATIC_CAST(nsXULCommandEvent*, aVisitor.mEvent)->
sourceNode = NS_STATIC_CAST(nsIContent*, this);
} else {
NS_WARNING("Incorrect eventStructType for command event");
}
nsEventDispatcher::Dispatch(commandContent,
aVisitor.mPresContext,
aVisitor.mEvent,
@ -2210,8 +2219,7 @@ nsXULElement::DoCommand()
context = shell->GetPresContext();
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(PR_TRUE, NS_XUL_COMMAND, nsnull,
nsMouseEvent::eReal);
nsXULCommandEvent event(PR_TRUE, NS_XUL_COMMAND, nsnull);
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this),
context, &event, nsnull, &status);
}

View File

@ -50,6 +50,7 @@ XPIDLSRCS = \
nsIDOMXULButtonElement.idl \
nsIDOMXULCheckboxElement.idl \
nsIDOMXULCommandDispatcher.idl \
nsIDOMXULCommandEvent.idl \
nsIDOMXULControlElement.idl \
nsIDOMXULDescriptionElement.idl \
nsIDOMXULDocument.idl \

View File

@ -0,0 +1,79 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* 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 Gecko.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Ryner <bryner@brianryner.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* This interface is supported by command events, which are dispatched to
* XUL elements as a result of mouse or keyboard activation.
*/
#include "nsIDOMUIEvent.idl"
[scriptable, uuid(f9fa8205-a988-4828-9228-f3332d5475ac)]
interface nsIDOMXULCommandEvent : nsIDOMUIEvent
{
/**
* Command events support the same set of modifier keys as mouse and key
* events.
*/
readonly attribute boolean ctrlKey;
readonly attribute boolean shiftKey;
readonly attribute boolean altKey;
readonly attribute boolean metaKey;
/**
* If the command event was retargeted because of a command= attribute
* on the original target, sourceNode will be set to the old target.
* If no retargeting has taken place, then sourceNode will be the same
* as originalTarget.
*/
readonly attribute nsIDOMEventTarget sourceNode;
/**
* Creates a new command event with the given attributes.
*/
void initCommandEvent(in DOMString typeArg,
in boolean canBubbleArg,
in boolean cancelableArg,
in nsIDOMAbstractView viewArg,
in long detailArg,
in boolean ctrlKeyArg,
in boolean altKeyArg,
in boolean shiftKeyArg,
in boolean metaKeyArg,
in nsIDOMEventTarget sourceNodeArg);
};

View File

@ -383,6 +383,8 @@ enum nsDOMClassInfoID {
eDOMClassInfo_SVGForeignObjectElement_id,
#endif
eDOMClassInfo_XULCommandEvent_id,
// This one better be the last one in this list
eDOMClassInfoIDCount
};

View File

@ -223,6 +223,7 @@
#include "nsIDOMBeforeUnloadEvent.h"
#include "nsIDOMMutationEvent.h"
#include "nsIDOMSmartCardEvent.h"
#include "nsIDOMXULCommandEvent.h"
#include "nsIDOMPageTransitionEvent.h"
#include "nsIDOMNSDocumentStyle.h"
#include "nsIDOMDocumentRange.h"
@ -1139,6 +1140,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(SVGForeignObjectElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
#endif
NS_DEFINE_CLASSINFO_DATA(XULCommandEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
};
// Objects that shuld be constructable through |new Name();|
@ -3042,6 +3046,11 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_END
#endif
DOM_CLASSINFO_MAP_BEGIN(XULCommandEvent, nsIDOMXULCommandEvent)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULCommandEvent)
DOM_CLASSINFO_UI_EVENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
#ifdef NS_DEBUG
{
PRUint32 i = NS_ARRAY_LENGTH(sClassInfoData);

View File

@ -151,8 +151,8 @@ nsButtonBoxFrame::DoMouseClick(nsGUIEvent* aEvent, PRBool aTrustEvent)
// Execute the oncommand event handler.
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(aEvent ? NS_IS_TRUSTED_EVENT(aEvent) : aTrustEvent,
NS_XUL_COMMAND, nsnull, nsMouseEvent::eReal);
nsXULCommandEvent event(aEvent ? NS_IS_TRUSTED_EVENT(aEvent) : aTrustEvent,
NS_XUL_COMMAND, nsnull);
if(aEvent) {
event.isShift = ((nsInputEvent*)(aEvent))->isShift;
event.isControl = ((nsInputEvent*)(aEvent))->isControl;

View File

@ -1629,9 +1629,9 @@ nsMenuFrame::Execute(nsGUIEvent *aEvent)
// Create a trusted event if the triggering event was trusted, or if
// we're called from chrome code (since at least one of our caller
// passes in a null event).
nsMouseEvent event(aEvent ? NS_IS_TRUSTED_EVENT(aEvent) :
nsContentUtils::IsCallerChrome(), NS_XUL_COMMAND, nsnull,
nsMouseEvent::eReal);
nsXULCommandEvent event(aEvent ? NS_IS_TRUSTED_EVENT(aEvent) :
nsContentUtils::IsCallerChrome(),
NS_XUL_COMMAND, nsnull);
if (aEvent && (aEvent->eventStructType == NS_MOUSE_EVENT ||
aEvent->eventStructType == NS_KEY_EVENT ||
aEvent->eventStructType == NS_ACCESSIBLE_EVENT)) {

View File

@ -332,8 +332,8 @@ nsResizerFrame::MouseClicked(nsPresContext* aPresContext, nsGUIEvent *aEvent)
// Execute the oncommand event handler.
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(aEvent ? NS_IS_TRUSTED_EVENT(aEvent) : PR_FALSE,
NS_XUL_COMMAND, nsnull, nsMouseEvent::eReal);
nsXULCommandEvent event(aEvent ? NS_IS_TRUSTED_EVENT(aEvent) : PR_FALSE,
NS_XUL_COMMAND, nsnull);
nsEventDispatcher::Dispatch(mContent, aPresContext, &event, nsnull, &status);
}

View File

@ -216,8 +216,8 @@ nsTitleBarFrame::MouseClicked(nsPresContext* aPresContext, nsGUIEvent* aEvent)
// Execute the oncommand event handler.
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(aEvent ? NS_IS_TRUSTED_EVENT(aEvent) : PR_FALSE,
NS_XUL_COMMAND, nsnull, nsMouseEvent::eReal);
nsXULCommandEvent event(aEvent ? NS_IS_TRUSTED_EVENT(aEvent) : PR_FALSE,
NS_XUL_COMMAND, nsnull);
nsEventDispatcher::Dispatch(mContent, aPresContext, &event, nsnull, &status);
}

View File

@ -99,6 +99,7 @@ class nsIDOMEventTarget;
#define NS_SVG_EVENT 30
#define NS_SVGZOOM_EVENT 31
#endif // MOZ_SVG
#define NS_XUL_COMMAND_EVENT 32
// These flags are sort of a mess. They're sort of shared between event
// listener flags and event flags, but only some of them. You've been
@ -267,7 +268,7 @@ class nsIDOMEventTarget;
#define NS_XUL_POPUP_SHOWN (NS_XUL_EVENT_START+1)
#define NS_XUL_POPUP_HIDING (NS_XUL_EVENT_START+2)
#define NS_XUL_POPUP_HIDDEN (NS_XUL_EVENT_START+3)
#define NS_XUL_COMMAND (NS_XUL_EVENT_START+4)
// NS_XUL_COMMAND used to be here (NS_XUL_EVENT_START+4)
#define NS_XUL_BROADCAST (NS_XUL_EVENT_START+5)
#define NS_XUL_COMMAND_UPDATE (NS_XUL_EVENT_START+6)
//@}
@ -345,6 +346,10 @@ class nsIDOMEventTarget;
#define NS_SVG_ZOOM (NS_SVGZOOM_EVENT_START)
#endif // MOZ_SVG
// XUL command events
#define NS_XULCOMMAND_EVENT_START 3000
#define NS_XUL_COMMAND (NS_XULCOMMAND_EVENT_START)
/**
* Return status for event processors, nsEventStatus, is defined in
* nsEvent.h.
@ -916,6 +921,22 @@ public:
PRBool persisted;
};
/**
* XUL command event
*/
class nsXULCommandEvent : public nsInputEvent
{
public:
nsXULCommandEvent(PRBool isTrusted, PRUint32 msg, nsIWidget *w)
: nsInputEvent(isTrusted, msg, w, NS_XUL_COMMAND_EVENT)
{
}
// Using nsISupports, not nsIDOMEventTarget because in some cases
// nsIDOMEventTarget is implemented as a tearoff.
nsCOMPtr<nsISupports> sourceNode;
};
/**
* Event status for D&D Event
*/