Bug 1003934 - Forward NS_MOUSE_EXIT events to content processes so they know the mouse has exited their frame. r=smaug

This commit is contained in:
Jim Mathies 2014-05-27 20:12:26 -05:00
parent 2f9e87d09a
commit 8bad3b3fe7
2 changed files with 75 additions and 44 deletions

View File

@ -1144,6 +1144,7 @@ CrossProcessSafeEvent(const WidgetEvent& aEvent)
case NS_MOUSE_BUTTON_UP:
case NS_MOUSE_MOVE:
case NS_CONTEXTMENU:
case NS_MOUSE_EXIT:
return true;
default:
return false;
@ -1165,7 +1166,6 @@ CrossProcessSafeEvent(const WidgetEvent& aEvent)
bool
EventStateManager::HandleCrossProcessEvent(WidgetEvent* aEvent,
nsIFrame* aTargetFrame,
nsEventStatus *aStatus) {
if (*aStatus == nsEventStatus_eConsumeNoDefault ||
aEvent->mFlags.mNoCrossProcessBoundaryForwarding ||
@ -2655,7 +2655,6 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
NS_ENSURE_ARG_POINTER(aStatus);
bool dispatchedToContentProcess = HandleCrossProcessEvent(aEvent,
aTargetFrame,
aStatus);
mCurrentTarget = aTargetFrame;
@ -3542,6 +3541,44 @@ EventStateManager::IsHandlingUserInput()
(TimeStamp::Now() - sHandlingInputStart) <= timeout;
}
static void
CreateMouseOrPointerWidgetEvent(WidgetMouseEvent* aMouseEvent,
uint32_t aMessage,
nsIContent* aRelatedContent,
nsAutoPtr<WidgetMouseEvent>& aNewEvent)
{
WidgetPointerEvent* sourcePointer = aMouseEvent->AsPointerEvent();
if (sourcePointer) {
PROFILER_LABEL("Input", "DispatchPointerEvent");
nsAutoPtr<WidgetPointerEvent> newPointerEvent;
newPointerEvent =
new WidgetPointerEvent(aMouseEvent->mFlags.mIsTrusted, aMessage,
aMouseEvent->widget);
newPointerEvent->isPrimary = sourcePointer->isPrimary;
newPointerEvent->pointerId = sourcePointer->pointerId;
newPointerEvent->width = sourcePointer->width;
newPointerEvent->height = sourcePointer->height;
newPointerEvent->inputSource = sourcePointer->inputSource;
newPointerEvent->relatedTarget =
nsIPresShell::GetPointerCapturingContent(sourcePointer->pointerId)
? nullptr
: aRelatedContent;
aNewEvent = newPointerEvent.forget();
} else {
aNewEvent =
new WidgetMouseEvent(aMouseEvent->mFlags.mIsTrusted, aMessage,
aMouseEvent->widget, WidgetMouseEvent::eReal);
aNewEvent->relatedTarget = aRelatedContent;
}
aNewEvent->refPoint = aMouseEvent->refPoint;
aNewEvent->modifiers = aMouseEvent->modifiers;
aNewEvent->button = aMouseEvent->button;
aNewEvent->buttons = aMouseEvent->buttons;
aNewEvent->pressure = aMouseEvent->pressure;
aNewEvent->pluginEvent = aMouseEvent->pluginEvent;
aNewEvent->inputSource = aMouseEvent->inputSource;
}
nsIFrame*
EventStateManager::DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent,
uint32_t aMessage,
@ -3567,54 +3604,49 @@ EventStateManager::DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent,
return mPresContext->GetPrimaryFrameFor(content);
}
nsEventStatus status = nsEventStatus_eIgnore;
nsAutoPtr<WidgetMouseEvent> event;
WidgetPointerEvent* sourcePointer = aMouseEvent->AsPointerEvent();
if (sourcePointer) {
PROFILER_LABEL("Input", "DispatchPointerEvent");
nsAutoPtr<WidgetPointerEvent> newPointerEvent;
newPointerEvent =
new WidgetPointerEvent(aMouseEvent->mFlags.mIsTrusted, aMessage,
aMouseEvent->widget);
newPointerEvent->isPrimary = sourcePointer->isPrimary;
newPointerEvent->pointerId = sourcePointer->pointerId;
newPointerEvent->width = sourcePointer->width;
newPointerEvent->height = sourcePointer->height;
newPointerEvent->inputSource = sourcePointer->inputSource;
newPointerEvent->relatedTarget = nsIPresShell::GetPointerCapturingContent(sourcePointer->pointerId)
? nullptr
: aRelatedContent;
event = newPointerEvent.forget();
} else {
PROFILER_LABEL("Input", "DispatchMouseEvent");
event =
new WidgetMouseEvent(aMouseEvent->mFlags.mIsTrusted, aMessage,
aMouseEvent->widget, WidgetMouseEvent::eReal);
event->relatedTarget = aRelatedContent;
mCurrentTargetContent = nullptr;
if (!aTargetContent) {
return nullptr;
}
event->refPoint = aMouseEvent->refPoint;
event->modifiers = aMouseEvent->modifiers;
event->button = aMouseEvent->button;
event->buttons = aMouseEvent->buttons;
event->pressure = aMouseEvent->pressure;
event->pluginEvent = aMouseEvent->pluginEvent;
event->inputSource = aMouseEvent->inputSource;
nsAutoPtr<WidgetMouseEvent> dispatchEvent;
CreateMouseOrPointerWidgetEvent(aMouseEvent, aMessage,
aRelatedContent, dispatchEvent);
nsWeakFrame previousTarget = mCurrentTarget;
mCurrentTargetContent = aTargetContent;
nsIFrame* targetFrame = nullptr;
if (aTargetContent) {
ESMEventCB callback(aTargetContent);
EventDispatcher::Dispatch(aTargetContent, mPresContext, event, nullptr,
&status, &callback);
// Although the primary frame was checked in event callback,
// it may not be the same object after event dispatching and handling.
// So we need to refetch it.
if (mPresContext) {
targetFrame = mPresContext->GetPrimaryFrameFor(aTargetContent);
if (aMouseEvent->AsMouseEvent()) {
PROFILER_LABEL("Input", "DispatchMouseEvent");
}
nsEventStatus status = nsEventStatus_eIgnore;
ESMEventCB callback(aTargetContent);
EventDispatcher::Dispatch(aTargetContent, mPresContext, dispatchEvent, nullptr,
&status, &callback);
if (mPresContext) {
// Although the primary frame was checked in event callback, it may not be
// the same object after event dispatch and handling, so refetch it.
targetFrame = mPresContext->GetPrimaryFrameFor(aTargetContent);
// If we are leaving remote content, dispatch a mouse exit event to the
// remote frame.
if (aMessage == NS_MOUSE_EXIT_SYNTH && IsRemoteTarget(aTargetContent)) {
// For remote content, send a normal widget mouse exit event.
nsAutoPtr<WidgetMouseEvent> remoteEvent;
CreateMouseOrPointerWidgetEvent(aMouseEvent, NS_MOUSE_EXIT,
aRelatedContent, remoteEvent);
// mCurrentTarget is set to the new target, so we must reset it to the
// old target and then dispatch a cross-process event. (mCurrentTarget
// will be set back below.) HandleCrossProcessEvent will query for the
// proper target via GetEventTarget which will return mCurrentTarget.
mCurrentTarget = targetFrame;
HandleCrossProcessEvent(remoteEvent, &status);
}
}

View File

@ -783,7 +783,6 @@ protected:
nsFrameLoader* aRemote,
nsEventStatus *aStatus);
bool HandleCrossProcessEvent(WidgetEvent* aEvent,
nsIFrame* aTargetFrame,
nsEventStatus* aStatus);
void ReleaseCurrentIMEContentObserver();