зеркало из https://github.com/mozilla/pjs.git
Make labels actually fire a click on the thing they're labeling when they're
clicked, instead of just redirecting their own event. Bug 146066, also fixes bugs 271740 and 276279. r=bryner, sr=jst
This commit is contained in:
Родитель
27d21949cf
Коммит
1091c7b77a
|
@ -1373,6 +1373,65 @@ IsArea(nsIContent *aContent)
|
|||
aContent->IsContentOfType(nsIContent::eHTML));
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsGenericHTMLElement::DispatchEvent(nsPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIContent* aTarget,
|
||||
PRBool aFullDispatch,
|
||||
nsEventStatus* aStatus)
|
||||
{
|
||||
NS_PRECONDITION(aTarget, "Must have target");
|
||||
NS_PRECONDITION(aEvent, "Must have source event");
|
||||
NS_PRECONDITION(aStatus, "Null out param?");
|
||||
|
||||
if (!aPresContext) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPresShell *shell = aPresContext->GetPresShell();
|
||||
if (!shell) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aFullDispatch) {
|
||||
return shell->HandleEventWithTarget(aEvent, nsnull, aTarget, NS_EVENT_FLAG_INIT,
|
||||
aStatus);
|
||||
}
|
||||
|
||||
return shell->HandleDOMEventWithTarget(aTarget, aEvent, aStatus);
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsGenericHTMLElement::DispatchClickEvent(nsPresContext* aPresContext,
|
||||
nsInputEvent* aSourceEvent,
|
||||
nsIContent* aTarget,
|
||||
PRBool aFullDispatch,
|
||||
nsEventStatus* aStatus)
|
||||
{
|
||||
NS_PRECONDITION(aTarget, "Must have target");
|
||||
NS_PRECONDITION(aSourceEvent, "Must have source event");
|
||||
NS_PRECONDITION(aStatus, "Null out param?");
|
||||
|
||||
nsMouseEvent event(NS_MOUSE_LEFT_CLICK, aSourceEvent->widget);
|
||||
event.point = aSourceEvent->point;
|
||||
event.refPoint = aSourceEvent->refPoint;
|
||||
PRUint32 clickCount = 1;
|
||||
if (aSourceEvent->eventStructType == NS_MOUSE_EVENT) {
|
||||
clickCount = NS_STATIC_CAST(nsMouseEvent*, aSourceEvent)->clickCount;
|
||||
}
|
||||
event.clickCount = clickCount;
|
||||
event.isShift = aSourceEvent->isShift;
|
||||
event.isControl = aSourceEvent->isControl;
|
||||
event.isAlt = aSourceEvent->isAlt;
|
||||
event.isMeta = aSourceEvent->isMeta;
|
||||
event.internalAppFlags |=
|
||||
aSourceEvent->internalAppFlags & NS_APP_EVENT_FLAG_TRUSTED;
|
||||
|
||||
return DispatchEvent(aPresContext, &event, aTarget, aFullDispatch, aStatus);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::HandleDOMEventForAnchors(nsPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
|
@ -1515,27 +1574,7 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsPresContext* aPresContext,
|
|||
nsKeyEvent* keyEvent = NS_STATIC_CAST(nsKeyEvent*, aEvent);
|
||||
if (keyEvent->keyCode == NS_VK_RETURN) {
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsCOMPtr<nsIContent> mouseContent;
|
||||
|
||||
//fire click
|
||||
nsGUIEvent* guiEvent = NS_STATIC_CAST(nsGUIEvent*, aEvent);
|
||||
nsMouseEvent event(NS_MOUSE_LEFT_CLICK, guiEvent->widget);
|
||||
event.point = aEvent->point;
|
||||
event.refPoint = aEvent->refPoint;
|
||||
event.clickCount = 1;
|
||||
event.isShift = keyEvent->isShift;
|
||||
event.isControl = keyEvent->isControl;
|
||||
event.isAlt = keyEvent->isAlt;
|
||||
event.isMeta = keyEvent->isMeta;
|
||||
event.internalAppFlags |=
|
||||
aEvent->internalAppFlags & NS_APP_EVENT_FLAG_TRUSTED;
|
||||
|
||||
nsIPresShell *presShell = aPresContext->GetPresShell();
|
||||
if (presShell) {
|
||||
ret = presShell->HandleDOMEventWithTarget(this, &event, &status);
|
||||
// presShell may no longer be alive, don't use it here
|
||||
// unless you keep a reference.
|
||||
}
|
||||
ret = DispatchClickEvent(aPresContext, keyEvent, this, PR_FALSE, &status);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -203,6 +203,26 @@ public:
|
|||
virtual void RemoveFocus(nsPresContext *aPresContext);
|
||||
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
||||
|
||||
/**
|
||||
* Method to create and dispatch a left-click event loosely based on aSourceEvent. If
|
||||
* aFullDispatch is true, the event will be dispatched in all event groups and so
|
||||
* forth; if it's false it will be dispatched only as a DOM event.
|
||||
*/
|
||||
static nsresult DispatchClickEvent(nsPresContext* aPresContext,
|
||||
nsInputEvent* aSourceEvent,
|
||||
nsIContent* aTarget,
|
||||
PRBool aFullDispatch,
|
||||
nsEventStatus* aStatus);
|
||||
|
||||
/**
|
||||
* Method to dispatch aEvent to aTarget without crashing and all.
|
||||
*/
|
||||
static nsresult DispatchEvent(nsPresContext* aPresContext,
|
||||
nsEvent* aEvent,
|
||||
nsIContent* aTarget,
|
||||
PRBool aFullDispatch,
|
||||
nsEventStatus* aStatus);
|
||||
|
||||
/**
|
||||
* Standard anchor HandleDOMEvent, used by A, AREA and LINK (parameters
|
||||
* are the same as HandleDOMEvent)
|
||||
|
|
|
@ -217,7 +217,8 @@ nsHTMLLabelElement::HandleDOMEvent(nsPresContext* aPresContext,
|
|||
*aEventStatus == nsEventStatus_eConsumeNoDefault ||
|
||||
(aEvent->message != NS_MOUSE_LEFT_CLICK &&
|
||||
aEvent->message != NS_FOCUS_CONTENT) ||
|
||||
aFlags & NS_EVENT_FLAG_CAPTURE)
|
||||
aFlags & NS_EVENT_FLAG_CAPTURE ||
|
||||
!(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIContent> content = GetForContent();
|
||||
|
@ -225,25 +226,23 @@ nsHTMLLabelElement::HandleDOMEvent(nsPresContext* aPresContext,
|
|||
mHandlingEvent = PR_TRUE;
|
||||
switch (aEvent->message) {
|
||||
case NS_MOUSE_LEFT_CLICK:
|
||||
if (ShouldFocus(this)) {
|
||||
// Focus the for content.
|
||||
content->SetFocus(aPresContext);
|
||||
}
|
||||
if (aEvent->eventStructType == NS_MOUSE_EVENT) {
|
||||
if (ShouldFocus(this)) {
|
||||
// Focus the for content.
|
||||
content->SetFocus(aPresContext);
|
||||
}
|
||||
|
||||
// This sends the event twice down parts of its path. Oh well.
|
||||
// This is needed for:
|
||||
// * Making radio buttons and checkboxes get checked.
|
||||
// * Triggering user event handlers. (For compatibility with IE,
|
||||
// we do only left click. If we wanted to interpret the HTML
|
||||
// spec very narrowly, we would do nothing. If we wanted to
|
||||
// do something sensible, we might send more events through
|
||||
// like this.) See bug 7554, bug 49897, and bug 96813.
|
||||
// XXX The event should probably have its target modified. See
|
||||
// bug 146066. (But what if |aDOMEvent| is null and it gets
|
||||
// created later? If we forced the existence of an event and
|
||||
// modified its target, we could replace |mHandlingEvent|.)
|
||||
rv = content->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
|
||||
aFlags, aEventStatus);
|
||||
// Dispatch a new click event to |content|
|
||||
// (For compatibility with IE, we do only left click. If
|
||||
// we wanted to interpret the HTML spec very narrowly, we
|
||||
// would do nothing. If we wanted to do something
|
||||
// sensible, we might send more events through like
|
||||
// this.) See bug 7554, bug 49897, and bug 96813.
|
||||
nsEventStatus status = *aEventStatus;
|
||||
rv = DispatchClickEvent(aPresContext, NS_STATIC_CAST(nsInputEvent*, aEvent),
|
||||
content, PR_TRUE, &status);
|
||||
// Do we care about the status this returned? I don't think we do...
|
||||
}
|
||||
break;
|
||||
case NS_FOCUS_CONTENT:
|
||||
// Since we don't have '-moz-user-focus: normal', the only time
|
||||
|
@ -252,8 +251,12 @@ nsHTMLLabelElement::HandleDOMEvent(nsPresContext* aPresContext,
|
|||
// case.
|
||||
// Since focus doesn't bubble, this is basically the second part
|
||||
// of redirecting |SetFocus|.
|
||||
rv = content->HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
|
||||
aFlags, aEventStatus);
|
||||
{
|
||||
nsEvent event(NS_FOCUS_CONTENT);
|
||||
nsEventStatus status = *aEventStatus;
|
||||
rv = DispatchEvent(aPresContext, &event, content, PR_TRUE, &status);
|
||||
// Do we care about the status this returned? I don't think we do...
|
||||
}
|
||||
break;
|
||||
}
|
||||
mHandlingEvent = PR_FALSE;
|
||||
|
|
Загрузка…
Ссылка в новой задаче