diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index d077508bfdec..30d59b56c132 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -409,7 +409,7 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, break; case NS_MOUSE_MOVE: GenerateDragGesture(aPresContext, aEvent); - UpdateCursor(aPresContext, aEvent->point, aTargetFrame, aStatus); + UpdateCursor(aPresContext, aEvent, aTargetFrame, aStatus); GenerateMouseEnterExit(aPresContext, aEvent); break; case NS_MOUSE_EXIT: @@ -470,7 +470,7 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, case NS_ACTIVATE: { nsIContent* newFocus; - mCurrentTarget->GetContent(&newFocus); + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, &newFocus); if (newFocus) { nsIFocusableContent *focusChange; if (NS_SUCCEEDED(newFocus->QueryInterface(NS_GET_IID(nsIFocusableContent), @@ -517,7 +517,7 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, case NS_DEACTIVATE: { nsIContent* newFocus; - mCurrentTarget->GetContent(&newFocus); + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, &newFocus); if (newFocus) { nsIFocusableContent *focusChange; if (NS_SUCCEEDED(newFocus->QueryInterface(NS_GET_IID(nsIFocusableContent), @@ -655,7 +655,7 @@ nsEventStateManager :: GenerateDragGesture ( nsIPresContext* aPresContext, nsGUI // dispatch to the DOM nsCOMPtr lastContent; if ( mGestureDownFrame ) { - mGestureDownFrame->GetContent(getter_AddRefs(lastContent)); + mGestureDownFrame->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(lastContent)); if ( lastContent ) lastContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); } @@ -700,7 +700,7 @@ nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext, if (nsEventStatus_eConsumeNoDefault != *aStatus) { nsCOMPtr newFocus; - mCurrentTarget->GetContent(getter_AddRefs(newFocus)); + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(newFocus)); nsCOMPtr focusable; if (newFocus) { @@ -1090,7 +1090,7 @@ nsEventStateManager::CheckDisabled(nsIContent* aContent) } void -nsEventStateManager::UpdateCursor(nsIPresContext* aPresContext, nsPoint& aPoint, nsIFrame* aTargetFrame, +nsEventStateManager::UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus) { PRInt32 cursor; @@ -1107,7 +1107,7 @@ nsEventStateManager::UpdateCursor(nsIPresContext* aPresContext, nsPoint& aPoint, } //If not disabled, check for the right cursor. else { - aTargetFrame->GetCursor(aPresContext, aPoint, cursor); + aTargetFrame->GetCursor(aPresContext, aEvent->point, cursor); } switch (cursor) { @@ -1169,13 +1169,12 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE switch(aEvent->message) { case NS_MOUSE_MOVE: { - if (mLastMouseOverFrame != mCurrentTarget) { - //We'll need the content, too, to check if it changed separately from the frames. - nsCOMPtr lastContent; - nsCOMPtr targetContent; + nsCOMPtr targetContent; + if (mCurrentTarget) { + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(targetContent)); + } - if ( mCurrentTarget ) - mCurrentTarget->GetContent(getter_AddRefs(targetContent)); + if (mLastMouseOverContent.get() != targetContent.get()) { if (mLastMouseOverFrame) { //fire mouseout @@ -1192,19 +1191,14 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE event.isAlt = ((nsMouseEvent*)aEvent)->isAlt; event.isMeta = ((nsMouseEvent*)aEvent)->isMeta; - //The frame has change but the content may not have. Check before dispatching to content - mLastMouseOverFrame->GetContent(getter_AddRefs(lastContent)); - - mCurrentTargetContent = lastContent; + mCurrentTargetContent = mLastMouseOverContent; NS_IF_ADDREF(mCurrentTargetContent); mCurrentRelatedContent = targetContent; NS_IF_ADDREF(mCurrentRelatedContent); - if (lastContent != targetContent) { - //XXX This event should still go somewhere!! - if (nsnull != lastContent) { - lastContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); - } + //XXX This event should still go somewhere!! + if (nsnull != mLastMouseOverContent) { + mLastMouseOverContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); } //Now dispatch to the frame @@ -1233,19 +1227,16 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE mCurrentTargetContent = targetContent; NS_IF_ADDREF(mCurrentTargetContent); - mCurrentRelatedContent = lastContent; + mCurrentRelatedContent = mLastMouseOverContent; NS_IF_ADDREF(mCurrentRelatedContent); - //The frame has change but the content may not have. Check before dispatching to content - if (lastContent != targetContent) { - //XXX This event should still go somewhere!! - if (targetContent) { - targetContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); - } - - if (nsEventStatus_eConsumeNoDefault != status) { - SetContentState(targetContent, NS_EVENT_STATE_HOVER); - } + //XXX This event should still go somewhere!! + if (targetContent) { + targetContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + } + + if (nsEventStatus_eConsumeNoDefault != status) { + SetContentState(targetContent, NS_EVENT_STATE_HOVER); } //Now dispatch to the frame @@ -1257,6 +1248,7 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE NS_IF_RELEASE(mCurrentTargetContent); NS_IF_RELEASE(mCurrentRelatedContent); mLastMouseOverFrame = mCurrentTarget; + mLastMouseOverContent = targetContent; } } break; @@ -1278,15 +1270,12 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE event.isAlt = ((nsMouseEvent*)aEvent)->isAlt; event.isMeta = ((nsMouseEvent*)aEvent)->isMeta; - nsCOMPtr lastContent; - mLastMouseOverFrame->GetContent(getter_AddRefs(lastContent)); - - mCurrentTargetContent = lastContent; + mCurrentTargetContent = mLastMouseOverContent; NS_IF_ADDREF(mCurrentTargetContent); mCurrentRelatedContent = nsnull; - if (lastContent) { - lastContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + if (mLastMouseOverContent) { + mLastMouseOverContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); if (nsEventStatus_eConsumeNoDefault != status) { SetContentState(nsnull, NS_EVENT_STATE_HOVER); @@ -1299,6 +1288,7 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE //XXX Get the new frame mLastMouseOverFrame->HandleEvent(aPresContext, &event, &status); mLastMouseOverFrame = nsnull; + mLastMouseOverContent = nsnull; } NS_IF_RELEASE(mCurrentTargetContent); @@ -1324,7 +1314,7 @@ nsEventStateManager::GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsG //We'll need the content, too, to check if it changed separately from the frames. nsCOMPtr lastContent; nsCOMPtr targetContent; - mCurrentTarget->GetContent(getter_AddRefs(targetContent)); + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(targetContent)); if ( mLastDragOverFrame ) { //fire drag exit @@ -1342,7 +1332,7 @@ nsEventStateManager::GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsG event.isMeta = ((nsMouseEvent*)aEvent)->isMeta; //The frame has change but the content may not have. Check before dispatching to content - mLastDragOverFrame->GetContent(getter_AddRefs(lastContent)); + mLastDragOverFrame->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(lastContent)); mCurrentTargetContent = lastContent; NS_IF_ADDREF(mCurrentTargetContent); @@ -1434,7 +1424,7 @@ nsEventStateManager::GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsG // dispatch to content via DOM nsCOMPtr lastContent; - mLastDragOverFrame->GetContent(getter_AddRefs(lastContent)); + mLastDragOverFrame->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(lastContent)); mCurrentTargetContent = lastContent; NS_IF_ADDREF(mCurrentTargetContent); @@ -1471,7 +1461,7 @@ nsEventStateManager::SetClickCount(nsIPresContext* aPresContext, nsresult ret = NS_OK; nsCOMPtr mouseContent; - mCurrentTarget->GetContent(getter_AddRefs(mouseContent)); + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(mouseContent)); switch (aEvent->message) { case NS_MOUSE_LEFT_BUTTON_DOWN: @@ -1538,7 +1528,7 @@ nsEventStateManager::CheckForAndDispatchClick(nsIPresContext* aPresContext, nsMouseEvent event; nsCOMPtr mouseContent; - mCurrentTarget->GetContent(getter_AddRefs(mouseContent)); + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(mouseContent)); //If mouse is still over same element, clickcount will be > 1. //If it has moved it will be zero, so no click. @@ -1955,7 +1945,7 @@ nsEventStateManager::GetEventTargetContent(nsEvent* aEvent, nsIContent** aConten } if (mCurrentTarget) { - mCurrentTarget->GetContent(aContent); + mCurrentTarget->GetContentForEvent(mPresContext, aEvent, aContent); return NS_OK; } @@ -2171,6 +2161,7 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo // Go ahead and fire a blur on the window. nsCOMPtr globalObject; + gLastFocusedDocument->GetScriptGlobalObject(getter_AddRefs(globalObject)); if (!mDocument) { diff --git a/content/events/src/nsEventStateManager.h b/content/events/src/nsEventStateManager.h index 99eeffc678c2..8009212532ec 100644 --- a/content/events/src/nsEventStateManager.h +++ b/content/events/src/nsEventStateManager.h @@ -91,7 +91,7 @@ public: NS_IMETHOD UnregisterAccessKey(nsIFrame * aFrame); protected: - void UpdateCursor(nsIPresContext* aPresContext, nsPoint& aPoint, nsIFrame* aTargetFrame, nsEventStatus* aStatus); + void UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus); void GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIEvent* aEvent); void GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsGUIEvent* aEvent); NS_IMETHOD SetClickCount(nsIPresContext* aPresContext, nsMouseEvent *aEvent, nsEventStatus* aStatus); @@ -127,6 +127,7 @@ protected: nsIContent* mCurrentTargetContent; nsIContent* mCurrentRelatedContent; nsIFrame* mLastMouseOverFrame; + nsCOMPtr mLastMouseOverContent; nsIFrame* mLastDragOverFrame; // member variables for the d&d gesture state machine diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 2f3e85575a2e..14d72b0a3615 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -584,6 +584,121 @@ nsGenericHTMLElement::SetDocumentForFormControls(nsIDocument* aDocument, return result; } +nsresult +nsGenericHTMLElement::HandleDOMEventForAnchors(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIDOMEvent** aDOMEvent, + PRUint32 aFlags, + nsEventStatus* aEventStatus) +{ + NS_ENSURE_ARG(aPresContext); + NS_ENSURE_ARG_POINTER(aEventStatus); + // Try script event handlers first + nsresult ret = HandleDOMEvent(aPresContext, aEvent, aDOMEvent, + aFlags, aEventStatus); + + if ((NS_OK == ret) && (nsEventStatus_eIgnore == *aEventStatus) && + !(aFlags & NS_EVENT_FLAG_CAPTURE)) { + // If this anchor element has an HREF then it is sensitive to + // mouse events (otherwise ignore them). + nsAutoString href; + nsresult result = GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, href); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + switch (aEvent->message) { + case NS_MOUSE_LEFT_BUTTON_DOWN: + { + // don't make the link grab the focus if there is no link handler + nsILinkHandler* handler; + nsresult rv = aPresContext->GetLinkHandler(&handler); + if (NS_SUCCEEDED(rv) && (nsnull != handler)) { + nsIEventStateManager *stateManager; + if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) { + stateManager->SetContentState(mContent, NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS); + NS_RELEASE(stateManager); + } + NS_RELEASE(handler); + *aEventStatus = nsEventStatus_eConsumeNoDefault; + } + } + break; + + case NS_MOUSE_LEFT_CLICK: + case NS_KEY_PRESS: + { + if (nsEventStatus_eConsumeNoDefault != *aEventStatus) { + + nsKeyEvent * keyEvent; + if (aEvent->eventStructType == NS_KEY_EVENT) { + //Handle key commands from keys with char representation here, not on KeyDown + keyEvent = (nsKeyEvent *)aEvent; + } + + //Click or return key + if (aEvent->message == NS_MOUSE_LEFT_CLICK || keyEvent->keyCode == NS_VK_RETURN) { + nsAutoString target; + nsIURI* baseURL = nsnull; + GetBaseURL(baseURL); + GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::target, target); + if (target.Length() == 0) { + GetBaseTarget(target); + } + ret = TriggerLink(aPresContext, eLinkVerb_Replace, + baseURL, href, target, PR_TRUE); + NS_IF_RELEASE(baseURL); + *aEventStatus = nsEventStatus_eConsumeDoDefault; + } + } + } + break; + + case NS_MOUSE_RIGHT_BUTTON_DOWN: + // XXX Bring up a contextual menu provided by the application + break; + + case NS_MOUSE_ENTER: + { + nsIEventStateManager *stateManager; + if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) { + stateManager->SetContentState(mContent, NS_EVENT_STATE_HOVER); + NS_RELEASE(stateManager); + } + + nsAutoString target; + nsIURI* baseURL = nsnull; + GetBaseURL(baseURL); + GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::target, target); + if (target.Length() == 0) { + GetBaseTarget(target); + } + ret = TriggerLink(aPresContext, eLinkVerb_Replace, + baseURL, href, target, PR_FALSE); + NS_IF_RELEASE(baseURL); + *aEventStatus = nsEventStatus_eConsumeNoDefault; + } + break; + + case NS_MOUSE_EXIT: + { + nsIEventStateManager *stateManager; + if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) { + stateManager->SetContentState(nsnull, NS_EVENT_STATE_HOVER); + NS_RELEASE(stateManager); + } + + nsAutoString empty; + ret = TriggerLink(aPresContext, eLinkVerb_Replace, nsnull, empty, empty, PR_FALSE); + *aEventStatus = nsEventStatus_eConsumeNoDefault; + } + break; + + default: + break; + } + } + } + return ret; +} + nsresult nsGenericHTMLElement::GetNameSpaceID(PRInt32& aID) const { diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 5fa1da186e6b..260fcab9aca1 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -117,6 +117,11 @@ public: PRBool aDeep, nsIFormControl* aControl, nsIForm* aForm); + nsresult HandleDOMEventForAnchors(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIDOMEvent** aDOMEvent, + PRUint32 aFlags, + nsEventStatus* aEventStatus); // Implementation for nsIHTMLContent nsresult Compact(); diff --git a/content/html/content/src/nsHTMLAnchorElement.cpp b/content/html/content/src/nsHTMLAnchorElement.cpp index 9512a8ea5330..24979aec6e72 100644 --- a/content/html/content/src/nsHTMLAnchorElement.cpp +++ b/content/html/content/src/nsHTMLAnchorElement.cpp @@ -334,112 +334,11 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext* aPresContext, PRUint32 aFlags, nsEventStatus* aEventStatus) { - NS_ENSURE_ARG(aPresContext); - NS_ENSURE_ARG_POINTER(aEventStatus); - // Try script event handlers first - nsresult ret = mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, - aFlags, aEventStatus); - - if ((NS_OK == ret) && (nsEventStatus_eIgnore == *aEventStatus) && - !(aFlags & NS_EVENT_FLAG_CAPTURE)) { - // If this anchor element has an HREF then it is sensitive to - // mouse events (otherwise ignore them). - nsAutoString href; - nsresult result = GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, href); - if (NS_CONTENT_ATTR_HAS_VALUE == result) { - switch (aEvent->message) { - case NS_MOUSE_LEFT_BUTTON_DOWN: - { - // don't make the link grab the focus if there is no link handler - nsILinkHandler* handler; - nsresult rv = aPresContext->GetLinkHandler(&handler); - if (NS_SUCCEEDED(rv) && (nsnull != handler)) { - nsIEventStateManager *stateManager; - if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) { - stateManager->SetContentState(this, NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS); - NS_RELEASE(stateManager); - } - NS_RELEASE(handler); - *aEventStatus = nsEventStatus_eConsumeNoDefault; - } - } - break; - - case NS_MOUSE_LEFT_CLICK: - case NS_KEY_PRESS: - { - if (nsEventStatus_eConsumeNoDefault != *aEventStatus) { - - nsKeyEvent * keyEvent; - if (aEvent->eventStructType == NS_KEY_EVENT) { - //Handle key commands from keys with char representation here, not on KeyDown - keyEvent = (nsKeyEvent *)aEvent; - } - - //Click or return key - if (aEvent->message == NS_MOUSE_LEFT_CLICK || keyEvent->keyCode == NS_VK_RETURN) { - nsAutoString target; - nsIURI* baseURL = nsnull; - GetBaseURL(baseURL); - GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::target, target); - if (target.Length() == 0) { - GetBaseTarget(target); - } - ret = mInner.TriggerLink(aPresContext, eLinkVerb_Replace, - baseURL, href, target, PR_TRUE); - NS_IF_RELEASE(baseURL); - *aEventStatus = nsEventStatus_eConsumeDoDefault; - } - } - } - break; - - case NS_MOUSE_RIGHT_BUTTON_DOWN: - // XXX Bring up a contextual menu provided by the application - break; - - case NS_MOUSE_ENTER: - { - nsIEventStateManager *stateManager; - if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) { - stateManager->SetContentState(this, NS_EVENT_STATE_HOVER); - NS_RELEASE(stateManager); - } - - nsAutoString target; - nsIURI* baseURL = nsnull; - GetBaseURL(baseURL); - GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::target, target); - if (target.Length() == 0) { - GetBaseTarget(target); - } - ret = mInner.TriggerLink(aPresContext, eLinkVerb_Replace, - baseURL, href, target, PR_FALSE); - NS_IF_RELEASE(baseURL); - *aEventStatus = nsEventStatus_eConsumeNoDefault; - } - break; - - case NS_MOUSE_EXIT: - { - nsIEventStateManager *stateManager; - if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) { - stateManager->SetContentState(nsnull, NS_EVENT_STATE_HOVER); - NS_RELEASE(stateManager); - } - - nsAutoString empty; - ret = mInner.TriggerLink(aPresContext, eLinkVerb_Replace, nsnull, empty, empty, PR_FALSE); - *aEventStatus = nsEventStatus_eConsumeNoDefault; - } - break; - - default: - break; - } - } - } - return ret; + return mInner.HandleDOMEventForAnchors(aPresContext, + aEvent, + aDOMEvent, + aFlags, + aEventStatus); } NS_IMETHODIMP diff --git a/content/html/content/src/nsHTMLAreaElement.cpp b/content/html/content/src/nsHTMLAreaElement.cpp index 24047da8322d..71e162b80f84 100644 --- a/content/html/content/src/nsHTMLAreaElement.cpp +++ b/content/html/content/src/nsHTMLAreaElement.cpp @@ -226,8 +226,11 @@ nsHTMLAreaElement::HandleDOMEvent(nsIPresContext* aPresContext, PRUint32 aFlags, nsEventStatus* aEventStatus) { - return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, - aFlags, aEventStatus); + return mInner.HandleDOMEventForAnchors(aPresContext, + aEvent, + aDOMEvent, + aFlags, + aEventStatus); } NS_IMETHODIMP diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index dfe7f3ad8176..c86e11728432 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -2869,7 +2869,7 @@ PresShell::HandleEvent(nsIView *aView, } else { nsIContent* targetContent; - if (NS_OK == mCurrentEventFrame->GetContent(&targetContent) && nsnull != 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); diff --git a/layout/base/public/nsIFrame.h b/layout/base/public/nsIFrame.h index b845c5200433..efdbb432f7c2 100644 --- a/layout/base/public/nsIFrame.h +++ b/layout/base/public/nsIFrame.h @@ -678,6 +678,10 @@ public: nsGUIEvent* aEvent, nsEventStatus* aEventStatus) = 0; + NS_IMETHOD GetContentForEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIContent** aContent) = 0; + NS_IMETHOD GetContentAndOffsetsFromPoint(nsIPresContext* aCX, const nsPoint& aPoint, nsIContent ** aNewContent, diff --git a/layout/events/src/nsEventStateManager.cpp b/layout/events/src/nsEventStateManager.cpp index d077508bfdec..30d59b56c132 100644 --- a/layout/events/src/nsEventStateManager.cpp +++ b/layout/events/src/nsEventStateManager.cpp @@ -409,7 +409,7 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, break; case NS_MOUSE_MOVE: GenerateDragGesture(aPresContext, aEvent); - UpdateCursor(aPresContext, aEvent->point, aTargetFrame, aStatus); + UpdateCursor(aPresContext, aEvent, aTargetFrame, aStatus); GenerateMouseEnterExit(aPresContext, aEvent); break; case NS_MOUSE_EXIT: @@ -470,7 +470,7 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, case NS_ACTIVATE: { nsIContent* newFocus; - mCurrentTarget->GetContent(&newFocus); + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, &newFocus); if (newFocus) { nsIFocusableContent *focusChange; if (NS_SUCCEEDED(newFocus->QueryInterface(NS_GET_IID(nsIFocusableContent), @@ -517,7 +517,7 @@ nsEventStateManager::PreHandleEvent(nsIPresContext* aPresContext, case NS_DEACTIVATE: { nsIContent* newFocus; - mCurrentTarget->GetContent(&newFocus); + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, &newFocus); if (newFocus) { nsIFocusableContent *focusChange; if (NS_SUCCEEDED(newFocus->QueryInterface(NS_GET_IID(nsIFocusableContent), @@ -655,7 +655,7 @@ nsEventStateManager :: GenerateDragGesture ( nsIPresContext* aPresContext, nsGUI // dispatch to the DOM nsCOMPtr lastContent; if ( mGestureDownFrame ) { - mGestureDownFrame->GetContent(getter_AddRefs(lastContent)); + mGestureDownFrame->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(lastContent)); if ( lastContent ) lastContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); } @@ -700,7 +700,7 @@ nsEventStateManager::PostHandleEvent(nsIPresContext* aPresContext, if (nsEventStatus_eConsumeNoDefault != *aStatus) { nsCOMPtr newFocus; - mCurrentTarget->GetContent(getter_AddRefs(newFocus)); + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(newFocus)); nsCOMPtr focusable; if (newFocus) { @@ -1090,7 +1090,7 @@ nsEventStateManager::CheckDisabled(nsIContent* aContent) } void -nsEventStateManager::UpdateCursor(nsIPresContext* aPresContext, nsPoint& aPoint, nsIFrame* aTargetFrame, +nsEventStateManager::UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus) { PRInt32 cursor; @@ -1107,7 +1107,7 @@ nsEventStateManager::UpdateCursor(nsIPresContext* aPresContext, nsPoint& aPoint, } //If not disabled, check for the right cursor. else { - aTargetFrame->GetCursor(aPresContext, aPoint, cursor); + aTargetFrame->GetCursor(aPresContext, aEvent->point, cursor); } switch (cursor) { @@ -1169,13 +1169,12 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE switch(aEvent->message) { case NS_MOUSE_MOVE: { - if (mLastMouseOverFrame != mCurrentTarget) { - //We'll need the content, too, to check if it changed separately from the frames. - nsCOMPtr lastContent; - nsCOMPtr targetContent; + nsCOMPtr targetContent; + if (mCurrentTarget) { + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(targetContent)); + } - if ( mCurrentTarget ) - mCurrentTarget->GetContent(getter_AddRefs(targetContent)); + if (mLastMouseOverContent.get() != targetContent.get()) { if (mLastMouseOverFrame) { //fire mouseout @@ -1192,19 +1191,14 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE event.isAlt = ((nsMouseEvent*)aEvent)->isAlt; event.isMeta = ((nsMouseEvent*)aEvent)->isMeta; - //The frame has change but the content may not have. Check before dispatching to content - mLastMouseOverFrame->GetContent(getter_AddRefs(lastContent)); - - mCurrentTargetContent = lastContent; + mCurrentTargetContent = mLastMouseOverContent; NS_IF_ADDREF(mCurrentTargetContent); mCurrentRelatedContent = targetContent; NS_IF_ADDREF(mCurrentRelatedContent); - if (lastContent != targetContent) { - //XXX This event should still go somewhere!! - if (nsnull != lastContent) { - lastContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); - } + //XXX This event should still go somewhere!! + if (nsnull != mLastMouseOverContent) { + mLastMouseOverContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); } //Now dispatch to the frame @@ -1233,19 +1227,16 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE mCurrentTargetContent = targetContent; NS_IF_ADDREF(mCurrentTargetContent); - mCurrentRelatedContent = lastContent; + mCurrentRelatedContent = mLastMouseOverContent; NS_IF_ADDREF(mCurrentRelatedContent); - //The frame has change but the content may not have. Check before dispatching to content - if (lastContent != targetContent) { - //XXX This event should still go somewhere!! - if (targetContent) { - targetContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); - } - - if (nsEventStatus_eConsumeNoDefault != status) { - SetContentState(targetContent, NS_EVENT_STATE_HOVER); - } + //XXX This event should still go somewhere!! + if (targetContent) { + targetContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + } + + if (nsEventStatus_eConsumeNoDefault != status) { + SetContentState(targetContent, NS_EVENT_STATE_HOVER); } //Now dispatch to the frame @@ -1257,6 +1248,7 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE NS_IF_RELEASE(mCurrentTargetContent); NS_IF_RELEASE(mCurrentRelatedContent); mLastMouseOverFrame = mCurrentTarget; + mLastMouseOverContent = targetContent; } } break; @@ -1278,15 +1270,12 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE event.isAlt = ((nsMouseEvent*)aEvent)->isAlt; event.isMeta = ((nsMouseEvent*)aEvent)->isMeta; - nsCOMPtr lastContent; - mLastMouseOverFrame->GetContent(getter_AddRefs(lastContent)); - - mCurrentTargetContent = lastContent; + mCurrentTargetContent = mLastMouseOverContent; NS_IF_ADDREF(mCurrentTargetContent); mCurrentRelatedContent = nsnull; - if (lastContent) { - lastContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + if (mLastMouseOverContent) { + mLastMouseOverContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); if (nsEventStatus_eConsumeNoDefault != status) { SetContentState(nsnull, NS_EVENT_STATE_HOVER); @@ -1299,6 +1288,7 @@ nsEventStateManager::GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIE //XXX Get the new frame mLastMouseOverFrame->HandleEvent(aPresContext, &event, &status); mLastMouseOverFrame = nsnull; + mLastMouseOverContent = nsnull; } NS_IF_RELEASE(mCurrentTargetContent); @@ -1324,7 +1314,7 @@ nsEventStateManager::GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsG //We'll need the content, too, to check if it changed separately from the frames. nsCOMPtr lastContent; nsCOMPtr targetContent; - mCurrentTarget->GetContent(getter_AddRefs(targetContent)); + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(targetContent)); if ( mLastDragOverFrame ) { //fire drag exit @@ -1342,7 +1332,7 @@ nsEventStateManager::GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsG event.isMeta = ((nsMouseEvent*)aEvent)->isMeta; //The frame has change but the content may not have. Check before dispatching to content - mLastDragOverFrame->GetContent(getter_AddRefs(lastContent)); + mLastDragOverFrame->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(lastContent)); mCurrentTargetContent = lastContent; NS_IF_ADDREF(mCurrentTargetContent); @@ -1434,7 +1424,7 @@ nsEventStateManager::GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsG // dispatch to content via DOM nsCOMPtr lastContent; - mLastDragOverFrame->GetContent(getter_AddRefs(lastContent)); + mLastDragOverFrame->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(lastContent)); mCurrentTargetContent = lastContent; NS_IF_ADDREF(mCurrentTargetContent); @@ -1471,7 +1461,7 @@ nsEventStateManager::SetClickCount(nsIPresContext* aPresContext, nsresult ret = NS_OK; nsCOMPtr mouseContent; - mCurrentTarget->GetContent(getter_AddRefs(mouseContent)); + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(mouseContent)); switch (aEvent->message) { case NS_MOUSE_LEFT_BUTTON_DOWN: @@ -1538,7 +1528,7 @@ nsEventStateManager::CheckForAndDispatchClick(nsIPresContext* aPresContext, nsMouseEvent event; nsCOMPtr mouseContent; - mCurrentTarget->GetContent(getter_AddRefs(mouseContent)); + mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(mouseContent)); //If mouse is still over same element, clickcount will be > 1. //If it has moved it will be zero, so no click. @@ -1955,7 +1945,7 @@ nsEventStateManager::GetEventTargetContent(nsEvent* aEvent, nsIContent** aConten } if (mCurrentTarget) { - mCurrentTarget->GetContent(aContent); + mCurrentTarget->GetContentForEvent(mPresContext, aEvent, aContent); return NS_OK; } @@ -2171,6 +2161,7 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo // Go ahead and fire a blur on the window. nsCOMPtr globalObject; + gLastFocusedDocument->GetScriptGlobalObject(getter_AddRefs(globalObject)); if (!mDocument) { diff --git a/layout/events/src/nsEventStateManager.h b/layout/events/src/nsEventStateManager.h index 99eeffc678c2..8009212532ec 100644 --- a/layout/events/src/nsEventStateManager.h +++ b/layout/events/src/nsEventStateManager.h @@ -91,7 +91,7 @@ public: NS_IMETHOD UnregisterAccessKey(nsIFrame * aFrame); protected: - void UpdateCursor(nsIPresContext* aPresContext, nsPoint& aPoint, nsIFrame* aTargetFrame, nsEventStatus* aStatus); + void UpdateCursor(nsIPresContext* aPresContext, nsEvent* aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus); void GenerateMouseEnterExit(nsIPresContext* aPresContext, nsGUIEvent* aEvent); void GenerateDragDropEnterExit(nsIPresContext* aPresContext, nsGUIEvent* aEvent); NS_IMETHOD SetClickCount(nsIPresContext* aPresContext, nsMouseEvent *aEvent, nsEventStatus* aStatus); @@ -127,6 +127,7 @@ protected: nsIContent* mCurrentTargetContent; nsIContent* mCurrentRelatedContent; nsIFrame* mLastMouseOverFrame; + nsCOMPtr mLastMouseOverContent; nsIFrame* mLastDragOverFrame; // member variables for the d&d gesture state machine diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index bc83e1d6a391..f6581003f1c9 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -746,6 +746,17 @@ nsFrame::Paint(nsIPresContext* aPresContext, return NS_OK; } +/** + * + */ +NS_IMETHODIMP +nsFrame::GetContentForEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIContent** aContent) +{ + return GetContent(aContent); +} + /** * */ diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h index 8efd96dea17a..5e194f9994fc 100644 --- a/layout/generic/nsFrame.h +++ b/layout/generic/nsFrame.h @@ -195,6 +195,9 @@ public: NS_IMETHOD HandleEvent(nsIPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus); + NS_IMETHOD GetContentForEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIContent** aContent); NS_IMETHOD GetCursor(nsIPresContext* aPresContext, nsPoint& aPoint, PRInt32& aCursor); diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index b845c5200433..efdbb432f7c2 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -678,6 +678,10 @@ public: nsGUIEvent* aEvent, nsEventStatus* aEventStatus) = 0; + NS_IMETHOD GetContentForEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIContent** aContent) = 0; + NS_IMETHOD GetContentAndOffsetsFromPoint(nsIPresContext* aCX, const nsPoint& aPoint, nsIContent ** aNewContent, diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 09d57f7a7dce..2d2f75532129 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -686,6 +686,35 @@ nsImageFrame::GetAnchorHREF(nsString& aResult) return status; } +NS_IMETHODIMP +nsImageFrame::GetContentForEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIContent** aContent) +{ + NS_ENSURE_ARG_POINTER(aContent); + nsImageMap* map; + map = GetImageMap(); + + if (nsnull != map) { + nsPoint p; + TranslateEventCoords(aPresContext, aEvent->point, p); + nsAutoString absURL, target, altText; + PRBool suppress; + PRBool inside = PR_FALSE; + nsCOMPtr area; + inside = map->IsInside(p.x, p.y, getter_AddRefs(area), + absURL, target, altText, + &suppress); + if (inside && area) { + *aContent = area; + NS_ADDREF(*aContent); + return NS_OK; + } + } + + return GetContent(aContent); +} + // XXX what should clicks on transparent pixels do? NS_METHOD nsImageFrame::HandleEvent(nsIPresContext* aPresContext, @@ -707,30 +736,15 @@ nsImageFrame::HandleEvent(nsIPresContext* aPresContext, nsAutoString absURL, target, altText; PRBool suppress; PRBool inside = PR_FALSE; + // Even though client-side image map triggering happens + // through content, we need to make sure we're not inside + // (in case we deal with a case of both client-side and + // sever-side on the same image - it happens!) if (nsnull != map) { - nsIDocument* doc = nsnull; - mContent->GetDocument(doc); - nsIURI* docURL = nsnull; - if (doc) { - docURL = doc->GetDocumentURL(); - NS_RELEASE(doc); - } - - if (docURL) { - inside = map->IsInside(p.x, p.y, docURL, absURL, target, altText, - &suppress); - NS_RELEASE(docURL); - } - - if (inside) { - // We hit a clickable area. Time to go somewhere... - PRBool clicked = PR_FALSE; - if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) { - *aEventStatus = nsEventStatus_eConsumeDoDefault; - clicked = PR_TRUE; - } - TriggerLink(aPresContext, absURL, target, clicked); - } + nsCOMPtr area; + inside = map->IsInside(p.x, p.y, getter_AddRefs(area), + absURL, target, altText, + &suppress); } if (!inside && isServerMap) { diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index d70ba42af17b..203556bc46fc 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -53,6 +53,9 @@ public: nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + NS_IMETHOD GetContentForEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIContent** aContent); NS_METHOD HandleEvent(nsIPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus); diff --git a/layout/generic/nsImageMap.cpp b/layout/generic/nsImageMap.cpp index 2afaff7ab161..f3facac842f0 100644 --- a/layout/generic/nsImageMap.cpp +++ b/layout/generic/nsImageMap.cpp @@ -46,9 +46,7 @@ class Area { public: - Area(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL); + Area(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL); virtual ~Area(); void ParseCoords(const nsString& aSpec); @@ -71,21 +69,18 @@ public: virtual void FinishConvertToXIF(nsXIFConverter& aConverter) const; - - const nsString& GetBase() const { return mBase; } - const nsString& GetHREF() const { return mHREF; } - const nsString& GetTarget() const { return mTarget; } - const nsString& GetAltText() const { return mAltText; } + void GetHREF(nsString& aHref) const; + void GetTarget(nsString& aTarget) const; + void GetAltText(nsString& aAltText) const; PRBool GetSuppress() const { return mSuppressFeedback; } + PRBool GetHasURL() const { return mHasURL; } + void GetArea(nsIContent** aArea) const; #ifdef DEBUG virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; #endif - nsString mBase; - nsString mHREF; - nsString mTarget; - nsString mAltText; + nsCOMPtr mArea; nscoord* mCoords; PRInt32 mNumCoords; PRBool mSuppressFeedback; @@ -94,11 +89,9 @@ public: MOZ_DECL_CTOR_COUNTER(Area); -Area::Area(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, +Area::Area(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL) - : mBase(aBaseURL), mHREF(aHREF), mTarget(aTarget), mAltText(aAltText), - mSuppressFeedback(aSuppress), mHasURL(aHasURL) + : mArea(aArea), mSuppressFeedback(aSuppress), mHasURL(aHasURL) { MOZ_COUNT_CTOR(Area); mCoords = nsnull; @@ -111,17 +104,46 @@ Area::~Area() delete [] mCoords; } +void +Area::GetHREF(nsString& aHref) const +{ + aHref.Truncate(); + if (mArea) { + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, aHref); + } +} + +void +Area::GetTarget(nsString& aTarget) const +{ + aTarget.Truncate(); + if (mArea) { + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::target, aTarget); + } +} + +void +Area::GetAltText(nsString& aAltText) const +{ + aAltText.Truncate(); + if (mArea) { + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::alt, aAltText); + } +} + +void +Area::GetArea(nsIContent** aArea) const +{ + *aArea = mArea; + NS_IF_ADDREF(*aArea); +} + #ifdef DEBUG void Area::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const { if (aResult) { PRUint32 sum = sizeof(*this); - PRUint32 s; - mBase.SizeOf(aHandler, &s); sum += s; - mHREF.SizeOf(aHandler, &s); sum += s; - mTarget.SizeOf(aHandler, &s); sum += s; - mAltText.SizeOf(aHandler, &s); sum += s; sum += mNumCoords * sizeof(nscoord); *aResult = sum; } @@ -296,6 +318,14 @@ void Area::ParseCoords(const nsString& aSpec) void Area::ToHTML(nsString& aResult) { + nsAutoString href, target, altText; + + if (mArea) { + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, href); + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::target, target); + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::alt, altText); + } + aResult.Truncate(); aResult.Append("\"");GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, href); + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::target, target); + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::alt, altText); + } + nsAutoString tag("area"); aConverter.BeginStartTag(tag); @@ -362,16 +400,16 @@ void Area::BeginConvertToXIF(nsXIFConverter& aConverter) const aConverter.AddAttribute(name,coords); name.SetString("href"); - aConverter.AddAttribute(name,mHREF); + aConverter.AddAttribute(name,href); - if (0 < mTarget.Length()) { + if (0 < target.Length()) { name.SetString("target"); - aConverter.AddAttribute(name,mTarget); + aConverter.AddAttribute(name,target); } - if (0 < mAltText.Length()) { + if (0 < altText.Length()) { name.SetString("alt"); - aConverter.AddAttribute(name,mTarget); + aConverter.AddAttribute(name,altText); } if (mSuppressFeedback) { name.SetString("suppress"); @@ -397,9 +435,7 @@ void Area::ConvertContentToXIF(nsXIFConverter& aConverter) const class DefaultArea : public Area { public: - DefaultArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL); + DefaultArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL); ~DefaultArea(); virtual PRBool IsInside(nscoord x, nscoord y); @@ -408,10 +444,8 @@ public: virtual void GetShapeName(nsString& aResult) const; }; -DefaultArea::DefaultArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL) - : Area(aBaseURL, aHREF, aTarget, aAltText, aSuppress, aHasURL) +DefaultArea::DefaultArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL) + : Area(aArea, aSuppress, aHasURL) { } @@ -437,9 +471,7 @@ void DefaultArea::GetShapeName(nsString& aResult) const class RectArea : public Area { public: - RectArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL); + RectArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL); ~RectArea(); virtual PRBool IsInside(nscoord x, nscoord y); @@ -448,10 +480,8 @@ public: virtual void GetShapeName(nsString& aResult) const; }; -RectArea::RectArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL) - : Area(aBaseURL, aHREF, aTarget, aAltText, aSuppress, aHasURL) +RectArea::RectArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL) + : Area(aArea, aSuppress, aHasURL) { } @@ -502,9 +532,7 @@ void RectArea::GetShapeName(nsString& aResult) const class PolyArea : public Area { public: - PolyArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL); + PolyArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL); ~PolyArea(); virtual PRBool IsInside(nscoord x, nscoord y); @@ -513,10 +541,8 @@ public: virtual void GetShapeName(nsString& aResult) const; }; -PolyArea::PolyArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL) - : Area(aBaseURL, aHREF, aTarget, aAltText, aSuppress, aHasURL) +PolyArea::PolyArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL) + : Area(aArea, aSuppress, aHasURL) { } @@ -616,9 +642,7 @@ void PolyArea::GetShapeName(nsString& aResult) const class CircleArea : public Area { public: - CircleArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL); + CircleArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL); ~CircleArea(); virtual PRBool IsInside(nscoord x, nscoord y); @@ -627,10 +651,8 @@ public: virtual void GetShapeName(nsString& aResult) const; }; -CircleArea::CircleArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL) - : Area(aBaseURL, aHREF, aTarget, aAltText, aSuppress, aHasURL) +CircleArea::CircleArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL) + : Area(aArea, aSuppress, aHasURL) { } @@ -830,31 +852,28 @@ nsImageMap::UpdateAreas() nsresult nsImageMap::AddArea(nsIContent* aArea) { - nsAutoString shape, coords, baseURL, href, target, altText, noHref; - aArea->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::shape, shape); - aArea->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::coords, coords); - aArea->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, href); - aArea->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::target, target); - aArea->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::alt, altText); - PRBool hasURL = (PRBool)(NS_CONTENT_ATTR_HAS_VALUE != aArea->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::nohref, noHref)); + nsAutoString shape, coords, baseURL, noHref; + aArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::shape, shape); + aArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::coords, coords); + PRBool hasURL = (PRBool)(NS_CONTENT_ATTR_HAS_VALUE != aArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::nohref, noHref)); PRBool suppress = PR_FALSE;/* XXX */ Area* area; if ((0 == shape.Length()) || shape.EqualsIgnoreCase("rect") || shape.EqualsIgnoreCase("rectangle")) { - area = new RectArea(baseURL, href, target, altText, suppress, hasURL); + area = new RectArea(aArea, suppress, hasURL); } else if (shape.EqualsIgnoreCase("poly") || shape.EqualsIgnoreCase("polygon")) { - area = new PolyArea(baseURL, href, target, altText, suppress, hasURL); + area = new PolyArea(aArea, suppress, hasURL); } else if (shape.EqualsIgnoreCase("circle") || shape.EqualsIgnoreCase("circ")) { - area = new CircleArea(baseURL, href, target, altText, suppress, hasURL); + area = new CircleArea(aArea, suppress, hasURL); } else { - area = new DefaultArea(baseURL, href, target, altText, suppress, hasURL); + area = new DefaultArea(aArea, suppress, hasURL); } area->ParseCoords(coords); mAreas.AppendElement(area); @@ -863,7 +882,7 @@ nsImageMap::AddArea(nsIContent* aArea) PRBool nsImageMap::IsInside(nscoord aX, nscoord aY, - nsIURI* aDocURL, + nsIContent** aContent, nsString& aAbsURL, nsString& aTarget, nsString& aAltText, @@ -872,32 +891,37 @@ nsImageMap::IsInside(nscoord aX, nscoord aY, PRInt32 i, n = mAreas.Count(); for (i = 0; i < n; i++) { Area* area = (Area*) mAreas.ElementAt(i); - if (area->IsInside(aX, aY) && area->mHasURL) { - nsresult rv; - // Set the image loader's source URL and base URL - nsIURI* baseUri = nsnull; - nsIHTMLContent* htmlContent; - if (mMap) { - rv = mMap->QueryInterface(kIHTMLContentIID, (void**)&htmlContent); - if (NS_SUCCEEDED(rv)) { - htmlContent->GetBaseURL(baseUri); - NS_RELEASE(htmlContent); - } - else { - nsIDocument* doc; - rv = mMap->GetDocument(doc); + if (area->IsInside(aX, aY)) { + if (area->GetHasURL()) { + nsresult rv; + // Set the image loader's source URL and base URL + nsIURI* baseUri = nsnull; + nsIHTMLContent* htmlContent; + if (mMap) { + rv = mMap->QueryInterface(kIHTMLContentIID, (void**)&htmlContent); if (NS_SUCCEEDED(rv)) { - doc->GetBaseURL(baseUri); // Could just use mDocument here... - NS_RELEASE(doc); + htmlContent->GetBaseURL(baseUri); + NS_RELEASE(htmlContent); + } + else { + nsIDocument* doc; + rv = mMap->GetDocument(doc); + if (NS_SUCCEEDED(rv)) { + doc->GetBaseURL(baseUri); // Could just use mDocument here... + NS_RELEASE(doc); + } } } + if (NS_FAILED(rv)) return PR_FALSE; + + nsAutoString href; + area->GetHREF(href); + NS_MakeAbsoluteURI(href, baseUri, aAbsURL); + + NS_RELEASE(baseUri); } - if (NS_FAILED(rv)) return PR_FALSE; - NS_MakeAbsoluteURI(area->mHREF, baseUri, aAbsURL); - - NS_RELEASE(baseUri); - aTarget = area->mTarget; + area->GetTarget(aTarget); if (mMap && (aTarget.Length() == 0)) { nsIHTMLContent* content = nsnull; nsresult result = mMap->QueryInterface(kIHTMLContentIID, (void**)&content); @@ -906,8 +930,9 @@ nsImageMap::IsInside(nscoord aX, nscoord aY, NS_RELEASE(content); } } - aAltText = area->mAltText; + area->GetAltText(aAltText); *aSuppress = area->mSuppressFeedback; + area->GetArea(aContent); return PR_TRUE; } } @@ -921,7 +946,9 @@ nsImageMap::IsInside(nscoord aX, nscoord aY) for (i = 0; i < n; i++) { Area* area = (Area*) mAreas.ElementAt(i); if (area->IsInside(aX, aY)) { - if ((area->mHREF).Length() > 0) { + nsAutoString href; + area->GetHREF(href); + if (href.Length() > 0) { return PR_TRUE; } } diff --git a/layout/generic/nsImageMap.h b/layout/generic/nsImageMap.h index 34758e47ef42..0cd8951c7b47 100644 --- a/layout/generic/nsImageMap.h +++ b/layout/generic/nsImageMap.h @@ -51,7 +51,7 @@ public: * then NS_NOT_INSIDE is returned. */ PRBool IsInside(nscoord aX, nscoord aY, - nsIURI* aDocURL, + nsIContent** aContent, nsString& aAbsURL, nsString& aTarget, nsString& aAltText, diff --git a/layout/html/base/src/nsFrame.cpp b/layout/html/base/src/nsFrame.cpp index bc83e1d6a391..f6581003f1c9 100644 --- a/layout/html/base/src/nsFrame.cpp +++ b/layout/html/base/src/nsFrame.cpp @@ -746,6 +746,17 @@ nsFrame::Paint(nsIPresContext* aPresContext, return NS_OK; } +/** + * + */ +NS_IMETHODIMP +nsFrame::GetContentForEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIContent** aContent) +{ + return GetContent(aContent); +} + /** * */ diff --git a/layout/html/base/src/nsFrame.h b/layout/html/base/src/nsFrame.h index 8efd96dea17a..5e194f9994fc 100644 --- a/layout/html/base/src/nsFrame.h +++ b/layout/html/base/src/nsFrame.h @@ -195,6 +195,9 @@ public: NS_IMETHOD HandleEvent(nsIPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus); + NS_IMETHOD GetContentForEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIContent** aContent); NS_IMETHOD GetCursor(nsIPresContext* aPresContext, nsPoint& aPoint, PRInt32& aCursor); diff --git a/layout/html/base/src/nsImageFrame.cpp b/layout/html/base/src/nsImageFrame.cpp index 09d57f7a7dce..2d2f75532129 100644 --- a/layout/html/base/src/nsImageFrame.cpp +++ b/layout/html/base/src/nsImageFrame.cpp @@ -686,6 +686,35 @@ nsImageFrame::GetAnchorHREF(nsString& aResult) return status; } +NS_IMETHODIMP +nsImageFrame::GetContentForEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIContent** aContent) +{ + NS_ENSURE_ARG_POINTER(aContent); + nsImageMap* map; + map = GetImageMap(); + + if (nsnull != map) { + nsPoint p; + TranslateEventCoords(aPresContext, aEvent->point, p); + nsAutoString absURL, target, altText; + PRBool suppress; + PRBool inside = PR_FALSE; + nsCOMPtr area; + inside = map->IsInside(p.x, p.y, getter_AddRefs(area), + absURL, target, altText, + &suppress); + if (inside && area) { + *aContent = area; + NS_ADDREF(*aContent); + return NS_OK; + } + } + + return GetContent(aContent); +} + // XXX what should clicks on transparent pixels do? NS_METHOD nsImageFrame::HandleEvent(nsIPresContext* aPresContext, @@ -707,30 +736,15 @@ nsImageFrame::HandleEvent(nsIPresContext* aPresContext, nsAutoString absURL, target, altText; PRBool suppress; PRBool inside = PR_FALSE; + // Even though client-side image map triggering happens + // through content, we need to make sure we're not inside + // (in case we deal with a case of both client-side and + // sever-side on the same image - it happens!) if (nsnull != map) { - nsIDocument* doc = nsnull; - mContent->GetDocument(doc); - nsIURI* docURL = nsnull; - if (doc) { - docURL = doc->GetDocumentURL(); - NS_RELEASE(doc); - } - - if (docURL) { - inside = map->IsInside(p.x, p.y, docURL, absURL, target, altText, - &suppress); - NS_RELEASE(docURL); - } - - if (inside) { - // We hit a clickable area. Time to go somewhere... - PRBool clicked = PR_FALSE; - if (aEvent->message == NS_MOUSE_LEFT_BUTTON_UP) { - *aEventStatus = nsEventStatus_eConsumeDoDefault; - clicked = PR_TRUE; - } - TriggerLink(aPresContext, absURL, target, clicked); - } + nsCOMPtr area; + inside = map->IsInside(p.x, p.y, getter_AddRefs(area), + absURL, target, altText, + &suppress); } if (!inside && isServerMap) { diff --git a/layout/html/base/src/nsImageFrame.h b/layout/html/base/src/nsImageFrame.h index d70ba42af17b..203556bc46fc 100644 --- a/layout/html/base/src/nsImageFrame.h +++ b/layout/html/base/src/nsImageFrame.h @@ -53,6 +53,9 @@ public: nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + NS_IMETHOD GetContentForEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIContent** aContent); NS_METHOD HandleEvent(nsIPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus); diff --git a/layout/html/base/src/nsImageMap.cpp b/layout/html/base/src/nsImageMap.cpp index 2afaff7ab161..f3facac842f0 100644 --- a/layout/html/base/src/nsImageMap.cpp +++ b/layout/html/base/src/nsImageMap.cpp @@ -46,9 +46,7 @@ class Area { public: - Area(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL); + Area(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL); virtual ~Area(); void ParseCoords(const nsString& aSpec); @@ -71,21 +69,18 @@ public: virtual void FinishConvertToXIF(nsXIFConverter& aConverter) const; - - const nsString& GetBase() const { return mBase; } - const nsString& GetHREF() const { return mHREF; } - const nsString& GetTarget() const { return mTarget; } - const nsString& GetAltText() const { return mAltText; } + void GetHREF(nsString& aHref) const; + void GetTarget(nsString& aTarget) const; + void GetAltText(nsString& aAltText) const; PRBool GetSuppress() const { return mSuppressFeedback; } + PRBool GetHasURL() const { return mHasURL; } + void GetArea(nsIContent** aArea) const; #ifdef DEBUG virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const; #endif - nsString mBase; - nsString mHREF; - nsString mTarget; - nsString mAltText; + nsCOMPtr mArea; nscoord* mCoords; PRInt32 mNumCoords; PRBool mSuppressFeedback; @@ -94,11 +89,9 @@ public: MOZ_DECL_CTOR_COUNTER(Area); -Area::Area(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, +Area::Area(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL) - : mBase(aBaseURL), mHREF(aHREF), mTarget(aTarget), mAltText(aAltText), - mSuppressFeedback(aSuppress), mHasURL(aHasURL) + : mArea(aArea), mSuppressFeedback(aSuppress), mHasURL(aHasURL) { MOZ_COUNT_CTOR(Area); mCoords = nsnull; @@ -111,17 +104,46 @@ Area::~Area() delete [] mCoords; } +void +Area::GetHREF(nsString& aHref) const +{ + aHref.Truncate(); + if (mArea) { + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, aHref); + } +} + +void +Area::GetTarget(nsString& aTarget) const +{ + aTarget.Truncate(); + if (mArea) { + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::target, aTarget); + } +} + +void +Area::GetAltText(nsString& aAltText) const +{ + aAltText.Truncate(); + if (mArea) { + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::alt, aAltText); + } +} + +void +Area::GetArea(nsIContent** aArea) const +{ + *aArea = mArea; + NS_IF_ADDREF(*aArea); +} + #ifdef DEBUG void Area::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const { if (aResult) { PRUint32 sum = sizeof(*this); - PRUint32 s; - mBase.SizeOf(aHandler, &s); sum += s; - mHREF.SizeOf(aHandler, &s); sum += s; - mTarget.SizeOf(aHandler, &s); sum += s; - mAltText.SizeOf(aHandler, &s); sum += s; sum += mNumCoords * sizeof(nscoord); *aResult = sum; } @@ -296,6 +318,14 @@ void Area::ParseCoords(const nsString& aSpec) void Area::ToHTML(nsString& aResult) { + nsAutoString href, target, altText; + + if (mArea) { + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, href); + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::target, target); + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::alt, altText); + } + aResult.Truncate(); aResult.Append("\"");GetAttribute(kNameSpaceID_None, nsHTMLAtoms::href, href); + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::target, target); + mArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::alt, altText); + } + nsAutoString tag("area"); aConverter.BeginStartTag(tag); @@ -362,16 +400,16 @@ void Area::BeginConvertToXIF(nsXIFConverter& aConverter) const aConverter.AddAttribute(name,coords); name.SetString("href"); - aConverter.AddAttribute(name,mHREF); + aConverter.AddAttribute(name,href); - if (0 < mTarget.Length()) { + if (0 < target.Length()) { name.SetString("target"); - aConverter.AddAttribute(name,mTarget); + aConverter.AddAttribute(name,target); } - if (0 < mAltText.Length()) { + if (0 < altText.Length()) { name.SetString("alt"); - aConverter.AddAttribute(name,mTarget); + aConverter.AddAttribute(name,altText); } if (mSuppressFeedback) { name.SetString("suppress"); @@ -397,9 +435,7 @@ void Area::ConvertContentToXIF(nsXIFConverter& aConverter) const class DefaultArea : public Area { public: - DefaultArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL); + DefaultArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL); ~DefaultArea(); virtual PRBool IsInside(nscoord x, nscoord y); @@ -408,10 +444,8 @@ public: virtual void GetShapeName(nsString& aResult) const; }; -DefaultArea::DefaultArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL) - : Area(aBaseURL, aHREF, aTarget, aAltText, aSuppress, aHasURL) +DefaultArea::DefaultArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL) + : Area(aArea, aSuppress, aHasURL) { } @@ -437,9 +471,7 @@ void DefaultArea::GetShapeName(nsString& aResult) const class RectArea : public Area { public: - RectArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL); + RectArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL); ~RectArea(); virtual PRBool IsInside(nscoord x, nscoord y); @@ -448,10 +480,8 @@ public: virtual void GetShapeName(nsString& aResult) const; }; -RectArea::RectArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL) - : Area(aBaseURL, aHREF, aTarget, aAltText, aSuppress, aHasURL) +RectArea::RectArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL) + : Area(aArea, aSuppress, aHasURL) { } @@ -502,9 +532,7 @@ void RectArea::GetShapeName(nsString& aResult) const class PolyArea : public Area { public: - PolyArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL); + PolyArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL); ~PolyArea(); virtual PRBool IsInside(nscoord x, nscoord y); @@ -513,10 +541,8 @@ public: virtual void GetShapeName(nsString& aResult) const; }; -PolyArea::PolyArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL) - : Area(aBaseURL, aHREF, aTarget, aAltText, aSuppress, aHasURL) +PolyArea::PolyArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL) + : Area(aArea, aSuppress, aHasURL) { } @@ -616,9 +642,7 @@ void PolyArea::GetShapeName(nsString& aResult) const class CircleArea : public Area { public: - CircleArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL); + CircleArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL); ~CircleArea(); virtual PRBool IsInside(nscoord x, nscoord y); @@ -627,10 +651,8 @@ public: virtual void GetShapeName(nsString& aResult) const; }; -CircleArea::CircleArea(const nsString& aBaseURL, const nsString& aHREF, - const nsString& aTarget, const nsString& aAltText, - PRBool aSuppress, PRBool aHasURL) - : Area(aBaseURL, aHREF, aTarget, aAltText, aSuppress, aHasURL) +CircleArea::CircleArea(nsIContent* aArea, PRBool aSuppress, PRBool aHasURL) + : Area(aArea, aSuppress, aHasURL) { } @@ -830,31 +852,28 @@ nsImageMap::UpdateAreas() nsresult nsImageMap::AddArea(nsIContent* aArea) { - nsAutoString shape, coords, baseURL, href, target, altText, noHref; - aArea->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::shape, shape); - aArea->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::coords, coords); - aArea->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, href); - aArea->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::target, target); - aArea->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::alt, altText); - PRBool hasURL = (PRBool)(NS_CONTENT_ATTR_HAS_VALUE != aArea->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::nohref, noHref)); + nsAutoString shape, coords, baseURL, noHref; + aArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::shape, shape); + aArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::coords, coords); + PRBool hasURL = (PRBool)(NS_CONTENT_ATTR_HAS_VALUE != aArea->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::nohref, noHref)); PRBool suppress = PR_FALSE;/* XXX */ Area* area; if ((0 == shape.Length()) || shape.EqualsIgnoreCase("rect") || shape.EqualsIgnoreCase("rectangle")) { - area = new RectArea(baseURL, href, target, altText, suppress, hasURL); + area = new RectArea(aArea, suppress, hasURL); } else if (shape.EqualsIgnoreCase("poly") || shape.EqualsIgnoreCase("polygon")) { - area = new PolyArea(baseURL, href, target, altText, suppress, hasURL); + area = new PolyArea(aArea, suppress, hasURL); } else if (shape.EqualsIgnoreCase("circle") || shape.EqualsIgnoreCase("circ")) { - area = new CircleArea(baseURL, href, target, altText, suppress, hasURL); + area = new CircleArea(aArea, suppress, hasURL); } else { - area = new DefaultArea(baseURL, href, target, altText, suppress, hasURL); + area = new DefaultArea(aArea, suppress, hasURL); } area->ParseCoords(coords); mAreas.AppendElement(area); @@ -863,7 +882,7 @@ nsImageMap::AddArea(nsIContent* aArea) PRBool nsImageMap::IsInside(nscoord aX, nscoord aY, - nsIURI* aDocURL, + nsIContent** aContent, nsString& aAbsURL, nsString& aTarget, nsString& aAltText, @@ -872,32 +891,37 @@ nsImageMap::IsInside(nscoord aX, nscoord aY, PRInt32 i, n = mAreas.Count(); for (i = 0; i < n; i++) { Area* area = (Area*) mAreas.ElementAt(i); - if (area->IsInside(aX, aY) && area->mHasURL) { - nsresult rv; - // Set the image loader's source URL and base URL - nsIURI* baseUri = nsnull; - nsIHTMLContent* htmlContent; - if (mMap) { - rv = mMap->QueryInterface(kIHTMLContentIID, (void**)&htmlContent); - if (NS_SUCCEEDED(rv)) { - htmlContent->GetBaseURL(baseUri); - NS_RELEASE(htmlContent); - } - else { - nsIDocument* doc; - rv = mMap->GetDocument(doc); + if (area->IsInside(aX, aY)) { + if (area->GetHasURL()) { + nsresult rv; + // Set the image loader's source URL and base URL + nsIURI* baseUri = nsnull; + nsIHTMLContent* htmlContent; + if (mMap) { + rv = mMap->QueryInterface(kIHTMLContentIID, (void**)&htmlContent); if (NS_SUCCEEDED(rv)) { - doc->GetBaseURL(baseUri); // Could just use mDocument here... - NS_RELEASE(doc); + htmlContent->GetBaseURL(baseUri); + NS_RELEASE(htmlContent); + } + else { + nsIDocument* doc; + rv = mMap->GetDocument(doc); + if (NS_SUCCEEDED(rv)) { + doc->GetBaseURL(baseUri); // Could just use mDocument here... + NS_RELEASE(doc); + } } } + if (NS_FAILED(rv)) return PR_FALSE; + + nsAutoString href; + area->GetHREF(href); + NS_MakeAbsoluteURI(href, baseUri, aAbsURL); + + NS_RELEASE(baseUri); } - if (NS_FAILED(rv)) return PR_FALSE; - NS_MakeAbsoluteURI(area->mHREF, baseUri, aAbsURL); - - NS_RELEASE(baseUri); - aTarget = area->mTarget; + area->GetTarget(aTarget); if (mMap && (aTarget.Length() == 0)) { nsIHTMLContent* content = nsnull; nsresult result = mMap->QueryInterface(kIHTMLContentIID, (void**)&content); @@ -906,8 +930,9 @@ nsImageMap::IsInside(nscoord aX, nscoord aY, NS_RELEASE(content); } } - aAltText = area->mAltText; + area->GetAltText(aAltText); *aSuppress = area->mSuppressFeedback; + area->GetArea(aContent); return PR_TRUE; } } @@ -921,7 +946,9 @@ nsImageMap::IsInside(nscoord aX, nscoord aY) for (i = 0; i < n; i++) { Area* area = (Area*) mAreas.ElementAt(i); if (area->IsInside(aX, aY)) { - if ((area->mHREF).Length() > 0) { + nsAutoString href; + area->GetHREF(href); + if (href.Length() > 0) { return PR_TRUE; } } diff --git a/layout/html/base/src/nsImageMap.h b/layout/html/base/src/nsImageMap.h index 34758e47ef42..0cd8951c7b47 100644 --- a/layout/html/base/src/nsImageMap.h +++ b/layout/html/base/src/nsImageMap.h @@ -51,7 +51,7 @@ public: * then NS_NOT_INSIDE is returned. */ PRBool IsInside(nscoord aX, nscoord aY, - nsIURI* aDocURL, + nsIContent** aContent, nsString& aAbsURL, nsString& aTarget, nsString& aAltText, diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp index dfe7f3ad8176..c86e11728432 100644 --- a/layout/html/base/src/nsPresShell.cpp +++ b/layout/html/base/src/nsPresShell.cpp @@ -2869,7 +2869,7 @@ PresShell::HandleEvent(nsIView *aView, } else { nsIContent* targetContent; - if (NS_OK == mCurrentEventFrame->GetContent(&targetContent) && nsnull != 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); diff --git a/layout/html/content/src/nsGenericHTMLElement.cpp b/layout/html/content/src/nsGenericHTMLElement.cpp index 2f3e85575a2e..14d72b0a3615 100644 --- a/layout/html/content/src/nsGenericHTMLElement.cpp +++ b/layout/html/content/src/nsGenericHTMLElement.cpp @@ -584,6 +584,121 @@ nsGenericHTMLElement::SetDocumentForFormControls(nsIDocument* aDocument, return result; } +nsresult +nsGenericHTMLElement::HandleDOMEventForAnchors(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIDOMEvent** aDOMEvent, + PRUint32 aFlags, + nsEventStatus* aEventStatus) +{ + NS_ENSURE_ARG(aPresContext); + NS_ENSURE_ARG_POINTER(aEventStatus); + // Try script event handlers first + nsresult ret = HandleDOMEvent(aPresContext, aEvent, aDOMEvent, + aFlags, aEventStatus); + + if ((NS_OK == ret) && (nsEventStatus_eIgnore == *aEventStatus) && + !(aFlags & NS_EVENT_FLAG_CAPTURE)) { + // If this anchor element has an HREF then it is sensitive to + // mouse events (otherwise ignore them). + nsAutoString href; + nsresult result = GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, href); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + switch (aEvent->message) { + case NS_MOUSE_LEFT_BUTTON_DOWN: + { + // don't make the link grab the focus if there is no link handler + nsILinkHandler* handler; + nsresult rv = aPresContext->GetLinkHandler(&handler); + if (NS_SUCCEEDED(rv) && (nsnull != handler)) { + nsIEventStateManager *stateManager; + if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) { + stateManager->SetContentState(mContent, NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS); + NS_RELEASE(stateManager); + } + NS_RELEASE(handler); + *aEventStatus = nsEventStatus_eConsumeNoDefault; + } + } + break; + + case NS_MOUSE_LEFT_CLICK: + case NS_KEY_PRESS: + { + if (nsEventStatus_eConsumeNoDefault != *aEventStatus) { + + nsKeyEvent * keyEvent; + if (aEvent->eventStructType == NS_KEY_EVENT) { + //Handle key commands from keys with char representation here, not on KeyDown + keyEvent = (nsKeyEvent *)aEvent; + } + + //Click or return key + if (aEvent->message == NS_MOUSE_LEFT_CLICK || keyEvent->keyCode == NS_VK_RETURN) { + nsAutoString target; + nsIURI* baseURL = nsnull; + GetBaseURL(baseURL); + GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::target, target); + if (target.Length() == 0) { + GetBaseTarget(target); + } + ret = TriggerLink(aPresContext, eLinkVerb_Replace, + baseURL, href, target, PR_TRUE); + NS_IF_RELEASE(baseURL); + *aEventStatus = nsEventStatus_eConsumeDoDefault; + } + } + } + break; + + case NS_MOUSE_RIGHT_BUTTON_DOWN: + // XXX Bring up a contextual menu provided by the application + break; + + case NS_MOUSE_ENTER: + { + nsIEventStateManager *stateManager; + if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) { + stateManager->SetContentState(mContent, NS_EVENT_STATE_HOVER); + NS_RELEASE(stateManager); + } + + nsAutoString target; + nsIURI* baseURL = nsnull; + GetBaseURL(baseURL); + GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::target, target); + if (target.Length() == 0) { + GetBaseTarget(target); + } + ret = TriggerLink(aPresContext, eLinkVerb_Replace, + baseURL, href, target, PR_FALSE); + NS_IF_RELEASE(baseURL); + *aEventStatus = nsEventStatus_eConsumeNoDefault; + } + break; + + case NS_MOUSE_EXIT: + { + nsIEventStateManager *stateManager; + if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) { + stateManager->SetContentState(nsnull, NS_EVENT_STATE_HOVER); + NS_RELEASE(stateManager); + } + + nsAutoString empty; + ret = TriggerLink(aPresContext, eLinkVerb_Replace, nsnull, empty, empty, PR_FALSE); + *aEventStatus = nsEventStatus_eConsumeNoDefault; + } + break; + + default: + break; + } + } + } + return ret; +} + nsresult nsGenericHTMLElement::GetNameSpaceID(PRInt32& aID) const { diff --git a/layout/html/content/src/nsGenericHTMLElement.h b/layout/html/content/src/nsGenericHTMLElement.h index 5fa1da186e6b..260fcab9aca1 100644 --- a/layout/html/content/src/nsGenericHTMLElement.h +++ b/layout/html/content/src/nsGenericHTMLElement.h @@ -117,6 +117,11 @@ public: PRBool aDeep, nsIFormControl* aControl, nsIForm* aForm); + nsresult HandleDOMEventForAnchors(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIDOMEvent** aDOMEvent, + PRUint32 aFlags, + nsEventStatus* aEventStatus); // Implementation for nsIHTMLContent nsresult Compact(); diff --git a/layout/html/content/src/nsHTMLAnchorElement.cpp b/layout/html/content/src/nsHTMLAnchorElement.cpp index 9512a8ea5330..24979aec6e72 100644 --- a/layout/html/content/src/nsHTMLAnchorElement.cpp +++ b/layout/html/content/src/nsHTMLAnchorElement.cpp @@ -334,112 +334,11 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext* aPresContext, PRUint32 aFlags, nsEventStatus* aEventStatus) { - NS_ENSURE_ARG(aPresContext); - NS_ENSURE_ARG_POINTER(aEventStatus); - // Try script event handlers first - nsresult ret = mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, - aFlags, aEventStatus); - - if ((NS_OK == ret) && (nsEventStatus_eIgnore == *aEventStatus) && - !(aFlags & NS_EVENT_FLAG_CAPTURE)) { - // If this anchor element has an HREF then it is sensitive to - // mouse events (otherwise ignore them). - nsAutoString href; - nsresult result = GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, href); - if (NS_CONTENT_ATTR_HAS_VALUE == result) { - switch (aEvent->message) { - case NS_MOUSE_LEFT_BUTTON_DOWN: - { - // don't make the link grab the focus if there is no link handler - nsILinkHandler* handler; - nsresult rv = aPresContext->GetLinkHandler(&handler); - if (NS_SUCCEEDED(rv) && (nsnull != handler)) { - nsIEventStateManager *stateManager; - if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) { - stateManager->SetContentState(this, NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS); - NS_RELEASE(stateManager); - } - NS_RELEASE(handler); - *aEventStatus = nsEventStatus_eConsumeNoDefault; - } - } - break; - - case NS_MOUSE_LEFT_CLICK: - case NS_KEY_PRESS: - { - if (nsEventStatus_eConsumeNoDefault != *aEventStatus) { - - nsKeyEvent * keyEvent; - if (aEvent->eventStructType == NS_KEY_EVENT) { - //Handle key commands from keys with char representation here, not on KeyDown - keyEvent = (nsKeyEvent *)aEvent; - } - - //Click or return key - if (aEvent->message == NS_MOUSE_LEFT_CLICK || keyEvent->keyCode == NS_VK_RETURN) { - nsAutoString target; - nsIURI* baseURL = nsnull; - GetBaseURL(baseURL); - GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::target, target); - if (target.Length() == 0) { - GetBaseTarget(target); - } - ret = mInner.TriggerLink(aPresContext, eLinkVerb_Replace, - baseURL, href, target, PR_TRUE); - NS_IF_RELEASE(baseURL); - *aEventStatus = nsEventStatus_eConsumeDoDefault; - } - } - } - break; - - case NS_MOUSE_RIGHT_BUTTON_DOWN: - // XXX Bring up a contextual menu provided by the application - break; - - case NS_MOUSE_ENTER: - { - nsIEventStateManager *stateManager; - if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) { - stateManager->SetContentState(this, NS_EVENT_STATE_HOVER); - NS_RELEASE(stateManager); - } - - nsAutoString target; - nsIURI* baseURL = nsnull; - GetBaseURL(baseURL); - GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::target, target); - if (target.Length() == 0) { - GetBaseTarget(target); - } - ret = mInner.TriggerLink(aPresContext, eLinkVerb_Replace, - baseURL, href, target, PR_FALSE); - NS_IF_RELEASE(baseURL); - *aEventStatus = nsEventStatus_eConsumeNoDefault; - } - break; - - case NS_MOUSE_EXIT: - { - nsIEventStateManager *stateManager; - if (NS_OK == aPresContext->GetEventStateManager(&stateManager)) { - stateManager->SetContentState(nsnull, NS_EVENT_STATE_HOVER); - NS_RELEASE(stateManager); - } - - nsAutoString empty; - ret = mInner.TriggerLink(aPresContext, eLinkVerb_Replace, nsnull, empty, empty, PR_FALSE); - *aEventStatus = nsEventStatus_eConsumeNoDefault; - } - break; - - default: - break; - } - } - } - return ret; + return mInner.HandleDOMEventForAnchors(aPresContext, + aEvent, + aDOMEvent, + aFlags, + aEventStatus); } NS_IMETHODIMP diff --git a/layout/html/content/src/nsHTMLAreaElement.cpp b/layout/html/content/src/nsHTMLAreaElement.cpp index 24047da8322d..71e162b80f84 100644 --- a/layout/html/content/src/nsHTMLAreaElement.cpp +++ b/layout/html/content/src/nsHTMLAreaElement.cpp @@ -226,8 +226,11 @@ nsHTMLAreaElement::HandleDOMEvent(nsIPresContext* aPresContext, PRUint32 aFlags, nsEventStatus* aEventStatus) { - return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, - aFlags, aEventStatus); + return mInner.HandleDOMEventForAnchors(aPresContext, + aEvent, + aDOMEvent, + aFlags, + aEventStatus); } NS_IMETHODIMP