Added support for XLink - simple links and show=replace or new. Modified nsILinkHandler interface.

git-svn-id: svn://10.0.0.236/trunk@14640 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
vidur%netscape.com 1998-11-14 00:21:19 +00:00
parent e54ec51180
commit 19d3032d70
21 changed files with 552 additions and 75 deletions

View File

@ -279,7 +279,7 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext& aPresContext,
if (target.Length() == 0) {
GetAttribute(nsString(NS_HTML_BASE_TARGET), target);
}
mInner.TriggerLink(aPresContext, base, href, target, PR_TRUE);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, base, href, target, PR_TRUE);
aEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
@ -300,7 +300,7 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext& aPresContext,
if (target.Length() == 0) {
GetAttribute(nsString(NS_HTML_BASE_TARGET), target);
}
mInner.TriggerLink(aPresContext, base, href, target, PR_FALSE);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, base, href, target, PR_FALSE);
aEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;
@ -309,7 +309,7 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext& aPresContext,
case NS_MOUSE_EXIT:
{
nsAutoString empty;
mInner.TriggerLink(aPresContext, empty, empty, empty, PR_FALSE);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, empty, empty, empty, PR_FALSE);
aEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;

View File

@ -327,7 +327,7 @@ nsHTMLButtonElement::HandleDOMEvent(nsIPresContext& aPresContext,
if (target.Length() == 0) {
GetAttribute(nsString(NS_HTML_BASE_TARGET), target);
}
mInner.TriggerLink(aPresContext, base, href, target, PR_TRUE);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, base, href, target, PR_TRUE);
aEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
@ -348,7 +348,7 @@ nsHTMLButtonElement::HandleDOMEvent(nsIPresContext& aPresContext,
if (target.Length() == 0) {
GetAttribute(nsString(NS_HTML_BASE_TARGET), target);
}
mInner.TriggerLink(aPresContext, base, href, target, PR_FALSE);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, base, href, target, PR_FALSE);
aEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;
@ -357,7 +357,7 @@ nsHTMLButtonElement::HandleDOMEvent(nsIPresContext& aPresContext,
case NS_MOUSE_EXIT:
{
nsAutoString empty;
mInner.TriggerLink(aPresContext, empty, empty, empty, PR_FALSE);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, empty, empty, empty, PR_FALSE);
aEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;

View File

@ -24,6 +24,9 @@
#include "nsIHTMLAttributes.h"
#include "nsIDOMScriptObjectFactory.h"
#include "nsIEventStateManager.h"
#include "nsDOMEvent.h"
//static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID);
static NS_DEFINE_IID(kIXMLContentIID, NS_IXMLCONTENT_IID);
@ -48,6 +51,7 @@ nsXMLElement::nsXMLElement(nsIAtom *aTag)
mNameSpace = nsnull;
mNameSpaceId = gNameSpaceId_Unknown;
mScriptObject = nsnull;
mIsLink = PR_FALSE;
}
nsXMLElement::~nsXMLElement()
@ -160,6 +164,21 @@ nsXMLElement::GetNameSpaceIdentifier(PRInt32& aNameSpaceId)
return NS_OK;
}
NS_IMETHODIMP
nsXMLElement::SetAttribute(const nsString& aName,
const nsString& aValue,
PRBool aNotify)
{
// XXX It sucks that we have to do a couple of strcmps for
// every attribute set. It might be a bit more expensive
// to create an atom.
if (aName.Equals("xml:link") && (aValue.Equals("simple"))) {
mIsLink = PR_TRUE;
}
return mInner.SetAttribute(aName, aValue, aNotify);
}
NS_IMETHODIMP
nsXMLElement::HandleDOMEvent(nsIPresContext& aPresContext,
nsEvent* aEvent,
@ -167,8 +186,90 @@ nsXMLElement::HandleDOMEvent(nsIPresContext& aPresContext,
PRUint32 aFlags,
nsEventStatus& aEventStatus)
{
return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags, aEventStatus);
// Try script event handlers first
nsresult ret = mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags, aEventStatus);
if (mIsLink && (NS_OK == ret) && (nsEventStatus_eIgnore == aEventStatus)) {
switch (aEvent->message) {
case NS_MOUSE_LEFT_BUTTON_DOWN:
{
nsIEventStateManager *stateManager;
if (NS_OK == aPresContext.GetEventStateManager(&stateManager)) {
stateManager->SetActiveLink(this);
NS_RELEASE(stateManager);
}
aEventStatus = nsEventStatus_eConsumeNoDefault;
}
break;
case NS_MOUSE_LEFT_BUTTON_UP:
{
nsIEventStateManager *stateManager;
nsIContent *activeLink;
if (NS_OK == aPresContext.GetEventStateManager(&stateManager)) {
stateManager->GetActiveLink(&activeLink);
NS_RELEASE(stateManager);
}
if (activeLink == this) {
nsEventStatus status;
nsMouseEvent event;
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_MOUSE_LEFT_CLICK;
HandleDOMEvent(aPresContext, &event, nsnull, DOM_EVENT_INIT, status);
if (nsEventStatus_eConsumeNoDefault != status) {
nsAutoString show, href, base, target;
nsLinkVerb verb = eLinkVerb_Replace;
base.Truncate();
target.Truncate();
GetAttribute(nsString("href"), href);
GetAttribute(nsString("show"), show);
// XXX Should probably do this using atoms
if (show.Equals("new")) {
verb = eLinkVerb_New;
}
else if (show.Equals("embed")) {
verb = eLinkVerb_Embed;
}
mInner.TriggerLink(aPresContext, verb, base, href, target, PR_TRUE);
aEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
}
break;
case NS_MOUSE_RIGHT_BUTTON_DOWN:
// XXX Bring up a contextual menu provided by the application
break;
case NS_MOUSE_ENTER:
//mouse enter doesn't work yet. Use move until then.
{
nsAutoString base, href, target;
base.Truncate();
target.Truncate();
GetAttribute(nsString("href"), href);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, base, href, target, PR_FALSE);
aEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;
// XXX this doesn't seem to do anything yet
case NS_MOUSE_EXIT:
{
nsAutoString empty;
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, empty, empty, empty, PR_FALSE);
aEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;
default:
break;
}
}
return ret;
}
NS_IMETHODIMP

View File

@ -56,7 +56,86 @@ public:
NS_IMETHOD SetScriptObject(void *aScriptObject);
// nsIContent
NS_IMPL_ICONTENT_USING_GENERIC(mInner)
NS_IMETHOD GetDocument(nsIDocument*& aResult) const {
return mInner.GetDocument(aResult);
}
NS_IMETHOD SetDocument(nsIDocument* aDocument, PRBool aDeep) {
return mInner.SetDocument(aDocument, aDeep);
}
NS_IMETHOD GetParent(nsIContent*& aResult) const {
return mInner.GetParent(aResult);
}
NS_IMETHOD SetParent(nsIContent* aParent) {
return mInner.SetParent(aParent);
}
NS_IMETHOD CanContainChildren(PRBool& aResult) const {
return mInner.CanContainChildren(aResult);
}
NS_IMETHOD ChildCount(PRInt32& aResult) const {
return mInner.ChildCount(aResult);
}
NS_IMETHOD ChildAt(PRInt32 aIndex, nsIContent*& aResult) const {
return mInner.ChildAt(aIndex, aResult);
}
NS_IMETHOD IndexOf(nsIContent* aPossibleChild, PRInt32& aResult) const {
return mInner.IndexOf(aPossibleChild, aResult);
}
NS_IMETHOD InsertChildAt(nsIContent* aKid, PRInt32 aIndex,
PRBool aNotify) {
return mInner.InsertChildAt(aKid, aIndex, aNotify);
}
NS_IMETHOD ReplaceChildAt(nsIContent* aKid, PRInt32 aIndex,
PRBool aNotify) {
return mInner.ReplaceChildAt(aKid, aIndex, aNotify);
}
NS_IMETHOD AppendChildTo(nsIContent* aKid, PRBool aNotify) {
return mInner.AppendChildTo(aKid, aNotify);
}
NS_IMETHOD RemoveChildAt(PRInt32 aIndex, PRBool aNotify) {
return mInner.RemoveChildAt(aIndex, aNotify);
}
NS_IMETHOD IsSynthetic(PRBool& aResult) {
return mInner.IsSynthetic(aResult);
}
NS_IMETHOD GetTag(nsIAtom*& aResult) const {
return mInner.GetTag(aResult);
}
NS_IMETHOD SetAttribute(const nsString& aName, const nsString& aValue,
PRBool aNotify);
NS_IMETHOD GetAttribute(const nsString& aName,
nsString& aResult) const {
return mInner.GetAttribute(aName, aResult);
}
NS_IMETHOD UnsetAttribute(nsIAtom* aAttribute, PRBool aNotify) {
return mInner.UnsetAttribute(aAttribute, aNotify);
}
NS_IMETHOD GetAllAttributeNames(nsISupportsArray* aArray,
PRInt32& aResult) const {
return mInner.GetAllAttributeNames(aArray, aResult);
}
NS_IMETHOD GetAttributeCount(PRInt32& aResult) const {
return mInner.GetAttributeCount(aResult);
}
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const {
return mInner.List(out, aIndent);
}
NS_IMETHOD BeginConvertToXIF(nsXIFConverter& aConverter) const {
return mInner.BeginConvertToXIF(aConverter);
}
NS_IMETHOD ConvertContentToXIF(nsXIFConverter& aConverter) const {
return mInner.ConvertContentToXIF(aConverter);
}
NS_IMETHOD FinishConvertToXIF(nsXIFConverter& aConverter) const {
return mInner.FinishConvertToXIF(aConverter);
}
NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler) const {
return mInner.SizeOf(aHandler);
}
NS_IMETHOD HandleDOMEvent(nsIPresContext& aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus& aEventStatus);
// nsIXMLContent
NS_IMETHOD SetNameSpace(nsIAtom* aNameSpace);
@ -99,6 +178,7 @@ protected:
nsIAtom* mNameSpace;
PRInt32 mNameSpaceId;
void *mScriptObject;
PRBool mIsLink;
};
#endif // nsXMLElement_h___

View File

@ -60,6 +60,20 @@ static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID);
#define XML_PSEUDO_ELEMENT 0
// XXX Open Issues:
// 1) html:style - Should we allow inline style? If so, the content
// sink needs to process the tag and invoke the CSS parser.
// 2) html:base - Should we allow a base tag? If so, the content
// sink needs to maintain the base when resolving URLs for
// loaded scripts and style sheets. Should it be allowed anywhere?
// 3) what's not allowed - We need to figure out which HTML tags
// (prefixed with a HTML namespace qualifier) are explicitly not
// allowed (if any).
// 4) factoring code with nsHTMLContentSink - There's some amount of
// common code between this and the HTML content sink. This will
// increase as we support more and more HTML elements. How can code
// from the code be factored?
nsresult
NS_NewXMLContentSink(nsIXMLContentSink** aResult,
nsIDocument* aDoc,

View File

@ -47,7 +47,7 @@
#include "nsITimerCallback.h"
#include "jsurl.h"
#include "nsIBrowserWindow.h"
#include "nsIContent.h"
#include "prlog.h"
@ -206,11 +206,12 @@ public:
NS_IMETHOD FocusAvailable(nsIWebShell* aFocusedWebShell);
// nsILinkHandler
NS_IMETHOD OnLinkClick(nsIFrame* aFrame,
NS_IMETHOD OnLinkClick(nsIContent* aContent,
nsLinkVerb aVerb,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec,
nsIPostData* aPostData = 0);
NS_IMETHOD OnOverLink(nsIFrame* aFrame,
NS_IMETHOD OnOverLink(nsIContent* aContent,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec);
NS_IMETHOD GetLinkState(const PRUnichar* aURLSpec, nsLinkState& aState);
@ -260,7 +261,9 @@ public:
NS_IMETHOD FindNext(const PRUnichar * aSearchStr, PRBool aMatchCase, PRBool aSearchDown, PRBool &aIsFound);
// nsWebShell
void HandleLinkClickEvent(const PRUnichar* aURLSpec,
void HandleLinkClickEvent(nsIContent *aContent,
nsLinkVerb aVerb,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec,
nsIPostData* aPostDat = 0);
@ -1459,18 +1462,22 @@ nsWebShell::FocusAvailable(nsIWebShell* aFocusedWebShell)
// WebShell link handling
struct OnLinkClickEvent : public PLEvent {
OnLinkClickEvent(nsWebShell* aHandler, const PRUnichar* aURLSpec,
OnLinkClickEvent(nsWebShell* aHandler, nsIContent* aContent,
nsLinkVerb aVerb, const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec, nsIPostData* aPostData = 0);
~OnLinkClickEvent();
void HandleEvent() {
mHandler->HandleLinkClickEvent(*mURLSpec, *mTargetSpec, mPostData);
mHandler->HandleLinkClickEvent(mContent, mVerb, *mURLSpec, *
mTargetSpec, mPostData);
}
nsWebShell* mHandler;
nsString* mURLSpec;
nsString* mTargetSpec;
nsIPostData* mPostData;
nsIContent* mContent;
nsLinkVerb mVerb;
};
static void PR_CALLBACK HandlePLEvent(OnLinkClickEvent* aEvent)
@ -1484,6 +1491,8 @@ static void PR_CALLBACK DestroyPLEvent(OnLinkClickEvent* aEvent)
}
OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler,
nsIContent *aContent,
nsLinkVerb aVerb,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec,
nsIPostData* aPostData)
@ -1494,7 +1503,10 @@ OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler,
mTargetSpec = new nsString(aTargetSpec);
mPostData = aPostData;
NS_IF_ADDREF(mPostData);
mContent = aContent;
NS_IF_ADDREF(mContent);
mVerb = aVerb;
#ifdef XP_PC
PL_InitEvent(this, nsnull,
(PLHandleEventProc) ::HandlePLEvent,
@ -1516,16 +1528,19 @@ OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler,
OnLinkClickEvent::~OnLinkClickEvent()
{
NS_IF_RELEASE(mContent);
NS_IF_RELEASE(mHandler);
NS_IF_RELEASE(mPostData);
if (nsnull != mURLSpec) delete mURLSpec;
if (nsnull != mTargetSpec) delete mTargetSpec;
}
//----------------------------------------
NS_IMETHODIMP
nsWebShell::OnLinkClick(nsIFrame* aFrame,
nsWebShell::OnLinkClick(nsIContent* aContent,
nsLinkVerb aVerb,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec,
nsIPostData* aPostData)
@ -1533,7 +1548,8 @@ nsWebShell::OnLinkClick(nsIFrame* aFrame,
OnLinkClickEvent* ev;
nsresult rv = NS_OK;
ev = new OnLinkClickEvent(this, aURLSpec, aTargetSpec, aPostData);
ev = new OnLinkClickEvent(this, aContent, aVerb, aURLSpec,
aTargetSpec, aPostData);
if (nsnull == ev) {
rv = NS_ERROR_OUT_OF_MEMORY;
}
@ -1603,19 +1619,36 @@ nsWebShell::GetTarget(const PRUnichar* aName)
}
void
nsWebShell::HandleLinkClickEvent(const PRUnichar* aURLSpec,
nsWebShell::HandleLinkClickEvent(nsIContent *aContent,
nsLinkVerb aVerb,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec,
nsIPostData* aPostData)
{
nsIWebShell* shell = GetTarget(aTargetSpec);
if (nsnull != shell) {
shell->LoadURL(aURLSpec, aPostData);
NS_RELEASE(shell);
nsAutoString target(aTargetSpec);
switch(aVerb) {
case eLinkVerb_New:
target.SetString("_blank");
// Fall into replace case
case eLinkVerb_Replace:
{
nsIWebShell* shell = GetTarget(target.GetUnicode());
if (nsnull != shell) {
shell->LoadURL(aURLSpec, aPostData);
NS_RELEASE(shell);
}
}
break;
case eLinkVerb_Embed:
default:
;
// XXX Need to do this
}
}
NS_IMETHODIMP
nsWebShell::OnOverLink(nsIFrame* aFrame,
nsWebShell::OnOverLink(nsIContent* aContent,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec)
{

View File

@ -719,10 +719,10 @@ ImageFrame::TriggerLink(nsIPresContext& aPresContext,
aPresContext.GetLinkHandler(&handler);
if (nsnull != handler) {
if (aClick) {
handler->OnLinkClick(this, aURLSpec, aTargetSpec);
handler->OnLinkClick(mContent, eLinkVerb_Replace, aURLSpec, aTargetSpec);
}
else {
handler->OnOverLink(this, aURLSpec, aTargetSpec);
handler->OnOverLink(mContent, aURLSpec, aTargetSpec);
}
}
}

View File

@ -983,9 +983,12 @@ NS_IMETHODIMP nsPluginInstanceOwner :: GetURL(const char *aURL, const char *aTar
NS_RELEASE(docURL);
NS_RELEASE(doc);
if (NS_OK == rv)
rv = lh->OnLinkClick(mOwner, fullurl.GetUnicode(), unitarget.GetUnicode(), nsnull);
if (NS_OK == rv) {
nsIContent* content = nsnull;
mOwner->GetContent(content);
rv = lh->OnLinkClick(content, eLinkVerb_Replace, fullurl.GetUnicode(), unitarget.GetUnicode(), nsnull);
NS_IF_RELEASE(content);
}
NS_RELEASE(lh);
}

View File

@ -719,10 +719,10 @@ ImageFrame::TriggerLink(nsIPresContext& aPresContext,
aPresContext.GetLinkHandler(&handler);
if (nsnull != handler) {
if (aClick) {
handler->OnLinkClick(this, aURLSpec, aTargetSpec);
handler->OnLinkClick(mContent, eLinkVerb_Replace, aURLSpec, aTargetSpec);
}
else {
handler->OnOverLink(this, aURLSpec, aTargetSpec);
handler->OnOverLink(mContent, aURLSpec, aTargetSpec);
}
}
}

View File

@ -983,9 +983,12 @@ NS_IMETHODIMP nsPluginInstanceOwner :: GetURL(const char *aURL, const char *aTar
NS_RELEASE(docURL);
NS_RELEASE(doc);
if (NS_OK == rv)
rv = lh->OnLinkClick(mOwner, fullurl.GetUnicode(), unitarget.GetUnicode(), nsnull);
if (NS_OK == rv) {
nsIContent* content = nsnull;
mOwner->GetContent(content);
rv = lh->OnLinkClick(content, eLinkVerb_Replace, fullurl.GetUnicode(), unitarget.GetUnicode(), nsnull);
NS_IF_RELEASE(content);
}
NS_RELEASE(lh);
}

View File

@ -1303,10 +1303,11 @@ nsGenericElement::Release()
void
nsGenericElement::TriggerLink(nsIPresContext& aPresContext,
const nsString& aBase,
const nsString& aURLSpec,
const nsString& aTargetSpec,
PRBool aClick)
nsLinkVerb aVerb,
const nsString& aBase,
const nsString& aURLSpec,
const nsString& aTargetSpec,
PRBool aClick)
{
nsILinkHandler* handler;
nsresult rv = aPresContext.GetLinkHandler(&handler);
@ -1332,10 +1333,10 @@ nsGenericElement::TriggerLink(nsIPresContext& aPresContext,
// Now pass on absolute url to the click handler
if (aClick) {
handler->OnLinkClick(nsnull, absURLSpec, aTargetSpec);
handler->OnLinkClick(mContent, aVerb, absURLSpec, aTargetSpec);
}
else {
handler->OnOverLink(nsnull, absURLSpec, aTargetSpec);
handler->OnOverLink(mContent, absURLSpec, aTargetSpec);
}
NS_RELEASE(handler);
}

View File

@ -27,6 +27,7 @@
#include "nsVoidArray.h"
#include "nsIScriptObjectOwner.h"
#include "nsIJSScriptObject.h"
#include "nsILinkHandler.h"
extern const nsIID kIDOMNodeIID;
extern const nsIID kIDOMElementIID;
@ -238,6 +239,7 @@ public:
REFNSIID aIID);
void TriggerLink(nsIPresContext& aPresContext,
nsLinkVerb aVerb,
const nsString& aBase,
const nsString& aURLSpec,
const nsString& aTargetSpec,

View File

@ -279,7 +279,7 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext& aPresContext,
if (target.Length() == 0) {
GetAttribute(nsString(NS_HTML_BASE_TARGET), target);
}
mInner.TriggerLink(aPresContext, base, href, target, PR_TRUE);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, base, href, target, PR_TRUE);
aEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
@ -300,7 +300,7 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext& aPresContext,
if (target.Length() == 0) {
GetAttribute(nsString(NS_HTML_BASE_TARGET), target);
}
mInner.TriggerLink(aPresContext, base, href, target, PR_FALSE);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, base, href, target, PR_FALSE);
aEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;
@ -309,7 +309,7 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext& aPresContext,
case NS_MOUSE_EXIT:
{
nsAutoString empty;
mInner.TriggerLink(aPresContext, empty, empty, empty, PR_FALSE);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, empty, empty, empty, PR_FALSE);
aEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;

View File

@ -327,7 +327,7 @@ nsHTMLButtonElement::HandleDOMEvent(nsIPresContext& aPresContext,
if (target.Length() == 0) {
GetAttribute(nsString(NS_HTML_BASE_TARGET), target);
}
mInner.TriggerLink(aPresContext, base, href, target, PR_TRUE);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, base, href, target, PR_TRUE);
aEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
@ -348,7 +348,7 @@ nsHTMLButtonElement::HandleDOMEvent(nsIPresContext& aPresContext,
if (target.Length() == 0) {
GetAttribute(nsString(NS_HTML_BASE_TARGET), target);
}
mInner.TriggerLink(aPresContext, base, href, target, PR_FALSE);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, base, href, target, PR_FALSE);
aEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;
@ -357,7 +357,7 @@ nsHTMLButtonElement::HandleDOMEvent(nsIPresContext& aPresContext,
case NS_MOUSE_EXIT:
{
nsAutoString empty;
mInner.TriggerLink(aPresContext, empty, empty, empty, PR_FALSE);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, empty, empty, empty, PR_FALSE);
aEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;

View File

@ -457,8 +457,8 @@ nsFormFrame::OnSubmit(nsIPresContext* aPresContext, nsIFrame* aFrame)
}
/* The postBuffer is now owned by the IPostData instance */
}
handler->OnLinkClick(aFrame, absURLSpec, target, postData);
}
handler->OnLinkClick(mContent, eLinkVerb_Replace, absURLSpec, target, postData);
NS_IF_RELEASE(postData);
NS_RELEASE(handler);

View File

@ -24,6 +24,9 @@
#include "nsIHTMLAttributes.h"
#include "nsIDOMScriptObjectFactory.h"
#include "nsIEventStateManager.h"
#include "nsDOMEvent.h"
//static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID);
static NS_DEFINE_IID(kIXMLContentIID, NS_IXMLCONTENT_IID);
@ -48,6 +51,7 @@ nsXMLElement::nsXMLElement(nsIAtom *aTag)
mNameSpace = nsnull;
mNameSpaceId = gNameSpaceId_Unknown;
mScriptObject = nsnull;
mIsLink = PR_FALSE;
}
nsXMLElement::~nsXMLElement()
@ -160,6 +164,21 @@ nsXMLElement::GetNameSpaceIdentifier(PRInt32& aNameSpaceId)
return NS_OK;
}
NS_IMETHODIMP
nsXMLElement::SetAttribute(const nsString& aName,
const nsString& aValue,
PRBool aNotify)
{
// XXX It sucks that we have to do a couple of strcmps for
// every attribute set. It might be a bit more expensive
// to create an atom.
if (aName.Equals("xml:link") && (aValue.Equals("simple"))) {
mIsLink = PR_TRUE;
}
return mInner.SetAttribute(aName, aValue, aNotify);
}
NS_IMETHODIMP
nsXMLElement::HandleDOMEvent(nsIPresContext& aPresContext,
nsEvent* aEvent,
@ -167,8 +186,90 @@ nsXMLElement::HandleDOMEvent(nsIPresContext& aPresContext,
PRUint32 aFlags,
nsEventStatus& aEventStatus)
{
return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags, aEventStatus);
// Try script event handlers first
nsresult ret = mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
aFlags, aEventStatus);
if (mIsLink && (NS_OK == ret) && (nsEventStatus_eIgnore == aEventStatus)) {
switch (aEvent->message) {
case NS_MOUSE_LEFT_BUTTON_DOWN:
{
nsIEventStateManager *stateManager;
if (NS_OK == aPresContext.GetEventStateManager(&stateManager)) {
stateManager->SetActiveLink(this);
NS_RELEASE(stateManager);
}
aEventStatus = nsEventStatus_eConsumeNoDefault;
}
break;
case NS_MOUSE_LEFT_BUTTON_UP:
{
nsIEventStateManager *stateManager;
nsIContent *activeLink;
if (NS_OK == aPresContext.GetEventStateManager(&stateManager)) {
stateManager->GetActiveLink(&activeLink);
NS_RELEASE(stateManager);
}
if (activeLink == this) {
nsEventStatus status;
nsMouseEvent event;
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_MOUSE_LEFT_CLICK;
HandleDOMEvent(aPresContext, &event, nsnull, DOM_EVENT_INIT, status);
if (nsEventStatus_eConsumeNoDefault != status) {
nsAutoString show, href, base, target;
nsLinkVerb verb = eLinkVerb_Replace;
base.Truncate();
target.Truncate();
GetAttribute(nsString("href"), href);
GetAttribute(nsString("show"), show);
// XXX Should probably do this using atoms
if (show.Equals("new")) {
verb = eLinkVerb_New;
}
else if (show.Equals("embed")) {
verb = eLinkVerb_Embed;
}
mInner.TriggerLink(aPresContext, verb, base, href, target, PR_TRUE);
aEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
}
break;
case NS_MOUSE_RIGHT_BUTTON_DOWN:
// XXX Bring up a contextual menu provided by the application
break;
case NS_MOUSE_ENTER:
//mouse enter doesn't work yet. Use move until then.
{
nsAutoString base, href, target;
base.Truncate();
target.Truncate();
GetAttribute(nsString("href"), href);
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, base, href, target, PR_FALSE);
aEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;
// XXX this doesn't seem to do anything yet
case NS_MOUSE_EXIT:
{
nsAutoString empty;
mInner.TriggerLink(aPresContext, eLinkVerb_Replace, empty, empty, empty, PR_FALSE);
aEventStatus = nsEventStatus_eConsumeDoDefault;
}
break;
default:
break;
}
}
return ret;
}
NS_IMETHODIMP

View File

@ -56,7 +56,86 @@ public:
NS_IMETHOD SetScriptObject(void *aScriptObject);
// nsIContent
NS_IMPL_ICONTENT_USING_GENERIC(mInner)
NS_IMETHOD GetDocument(nsIDocument*& aResult) const {
return mInner.GetDocument(aResult);
}
NS_IMETHOD SetDocument(nsIDocument* aDocument, PRBool aDeep) {
return mInner.SetDocument(aDocument, aDeep);
}
NS_IMETHOD GetParent(nsIContent*& aResult) const {
return mInner.GetParent(aResult);
}
NS_IMETHOD SetParent(nsIContent* aParent) {
return mInner.SetParent(aParent);
}
NS_IMETHOD CanContainChildren(PRBool& aResult) const {
return mInner.CanContainChildren(aResult);
}
NS_IMETHOD ChildCount(PRInt32& aResult) const {
return mInner.ChildCount(aResult);
}
NS_IMETHOD ChildAt(PRInt32 aIndex, nsIContent*& aResult) const {
return mInner.ChildAt(aIndex, aResult);
}
NS_IMETHOD IndexOf(nsIContent* aPossibleChild, PRInt32& aResult) const {
return mInner.IndexOf(aPossibleChild, aResult);
}
NS_IMETHOD InsertChildAt(nsIContent* aKid, PRInt32 aIndex,
PRBool aNotify) {
return mInner.InsertChildAt(aKid, aIndex, aNotify);
}
NS_IMETHOD ReplaceChildAt(nsIContent* aKid, PRInt32 aIndex,
PRBool aNotify) {
return mInner.ReplaceChildAt(aKid, aIndex, aNotify);
}
NS_IMETHOD AppendChildTo(nsIContent* aKid, PRBool aNotify) {
return mInner.AppendChildTo(aKid, aNotify);
}
NS_IMETHOD RemoveChildAt(PRInt32 aIndex, PRBool aNotify) {
return mInner.RemoveChildAt(aIndex, aNotify);
}
NS_IMETHOD IsSynthetic(PRBool& aResult) {
return mInner.IsSynthetic(aResult);
}
NS_IMETHOD GetTag(nsIAtom*& aResult) const {
return mInner.GetTag(aResult);
}
NS_IMETHOD SetAttribute(const nsString& aName, const nsString& aValue,
PRBool aNotify);
NS_IMETHOD GetAttribute(const nsString& aName,
nsString& aResult) const {
return mInner.GetAttribute(aName, aResult);
}
NS_IMETHOD UnsetAttribute(nsIAtom* aAttribute, PRBool aNotify) {
return mInner.UnsetAttribute(aAttribute, aNotify);
}
NS_IMETHOD GetAllAttributeNames(nsISupportsArray* aArray,
PRInt32& aResult) const {
return mInner.GetAllAttributeNames(aArray, aResult);
}
NS_IMETHOD GetAttributeCount(PRInt32& aResult) const {
return mInner.GetAttributeCount(aResult);
}
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const {
return mInner.List(out, aIndent);
}
NS_IMETHOD BeginConvertToXIF(nsXIFConverter& aConverter) const {
return mInner.BeginConvertToXIF(aConverter);
}
NS_IMETHOD ConvertContentToXIF(nsXIFConverter& aConverter) const {
return mInner.ConvertContentToXIF(aConverter);
}
NS_IMETHOD FinishConvertToXIF(nsXIFConverter& aConverter) const {
return mInner.FinishConvertToXIF(aConverter);
}
NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler) const {
return mInner.SizeOf(aHandler);
}
NS_IMETHOD HandleDOMEvent(nsIPresContext& aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus& aEventStatus);
// nsIXMLContent
NS_IMETHOD SetNameSpace(nsIAtom* aNameSpace);
@ -99,6 +178,7 @@ protected:
nsIAtom* mNameSpace;
PRInt32 mNameSpaceId;
void *mScriptObject;
PRBool mIsLink;
};
#endif // nsXMLElement_h___

View File

@ -60,6 +60,20 @@ static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID);
#define XML_PSEUDO_ELEMENT 0
// XXX Open Issues:
// 1) html:style - Should we allow inline style? If so, the content
// sink needs to process the tag and invoke the CSS parser.
// 2) html:base - Should we allow a base tag? If so, the content
// sink needs to maintain the base when resolving URLs for
// loaded scripts and style sheets. Should it be allowed anywhere?
// 3) what's not allowed - We need to figure out which HTML tags
// (prefixed with a HTML namespace qualifier) are explicitly not
// allowed (if any).
// 4) factoring code with nsHTMLContentSink - There's some amount of
// common code between this and the HTML content sink. This will
// increase as we support more and more HTML elements. How can code
// from the code be factored?
nsresult
NS_NewXMLContentSink(nsIXMLContentSink** aResult,
nsIDocument* aDoc,

View File

@ -22,8 +22,8 @@
#include "nsweb.h"
#include "nsISupports.h"
class nsIFrame;
class nsIPostData;
class nsIContent;
struct nsGUIEvent;
// Interface ID for nsILinkHandler
@ -38,29 +38,40 @@ enum nsLinkState {
eLinkState_Hover = 4 // mouse is hovering over link
};
// XXX Verb to use for link actuation. These are the verbs specified
// in the current XLink draft. We may actually want to support more
// (especially for extended links).
enum nsLinkVerb {
eLinkVerb_Replace = 0,
eLinkVerb_New = 1,
eLinkVerb_Embed = 2
};
/**
* Interface used for handling clicks on links
*/
class nsILinkHandler : public nsISupports {
public:
/**
* Process a click on a link. aFrame is the frame that contains the
* linked content. aURLSpec is an absolute url spec that defines the
* destination for the link. aTargetSpec indicates where the link is
* targeted (it may be an empty string).
* Process a click on a link. aContent is the content for the frame
* that generated the trigger. aURLSpec is an absolute url spec that
* defines the destination for the link. aTargetSpec indicates where
* the link is targeted (it may be an empty string). aVerb indicates
* the verb to use when the link is triggered.
*/
NS_IMETHOD OnLinkClick(nsIFrame* aFrame,
NS_IMETHOD OnLinkClick(nsIContent* aContent,
nsLinkVerb aVerb,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec,
nsIPostData* aPostData = 0) = 0;
/**
* Process a mouse-over a link. aFrame is the frame that contains the
* Process a mouse-over a link. aContent is the
* linked content. aURLSpec is an absolute url spec that defines the
* destination for the link. aTargetSpec indicates where the link is
* targeted (it may be an empty string).
*/
NS_IMETHOD OnOverLink(nsIFrame* aFrame,
NS_IMETHOD OnOverLink(nsIContent* aContent,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec) = 0;

View File

@ -29,6 +29,7 @@
#include "nsILinkHandler.h"
#include "nsIWebShell.h"
#include "nsIBrowserWindow.h"
#include "nsIContent.h"
// Class IDs
static NS_DEFINE_IID(kChildWindowCID, NS_CHILD_CID);
@ -631,7 +632,7 @@ NS_IMETHODIMP pluginInstanceOwner :: GetURL(const char *aURL, const char *aTarge
rv = NS_MakeAbsoluteURL(url, base, uniurl, fullurl);
if (NS_OK == rv)
rv = lh->OnLinkClick(nsnull, fullurl.GetUnicode(), unitarget.GetUnicode(), nsnull);
rv = lh->OnLinkClick(nsnull, eLinkVerb_Replace, fullurl.GetUnicode(), unitarget.GetUnicode(), nsnull);
NS_RELEASE(url);
}

View File

@ -47,7 +47,7 @@
#include "nsITimerCallback.h"
#include "jsurl.h"
#include "nsIBrowserWindow.h"
#include "nsIContent.h"
#include "prlog.h"
@ -206,11 +206,12 @@ public:
NS_IMETHOD FocusAvailable(nsIWebShell* aFocusedWebShell);
// nsILinkHandler
NS_IMETHOD OnLinkClick(nsIFrame* aFrame,
NS_IMETHOD OnLinkClick(nsIContent* aContent,
nsLinkVerb aVerb,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec,
nsIPostData* aPostData = 0);
NS_IMETHOD OnOverLink(nsIFrame* aFrame,
NS_IMETHOD OnOverLink(nsIContent* aContent,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec);
NS_IMETHOD GetLinkState(const PRUnichar* aURLSpec, nsLinkState& aState);
@ -260,7 +261,9 @@ public:
NS_IMETHOD FindNext(const PRUnichar * aSearchStr, PRBool aMatchCase, PRBool aSearchDown, PRBool &aIsFound);
// nsWebShell
void HandleLinkClickEvent(const PRUnichar* aURLSpec,
void HandleLinkClickEvent(nsIContent *aContent,
nsLinkVerb aVerb,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec,
nsIPostData* aPostDat = 0);
@ -1459,18 +1462,22 @@ nsWebShell::FocusAvailable(nsIWebShell* aFocusedWebShell)
// WebShell link handling
struct OnLinkClickEvent : public PLEvent {
OnLinkClickEvent(nsWebShell* aHandler, const PRUnichar* aURLSpec,
OnLinkClickEvent(nsWebShell* aHandler, nsIContent* aContent,
nsLinkVerb aVerb, const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec, nsIPostData* aPostData = 0);
~OnLinkClickEvent();
void HandleEvent() {
mHandler->HandleLinkClickEvent(*mURLSpec, *mTargetSpec, mPostData);
mHandler->HandleLinkClickEvent(mContent, mVerb, *mURLSpec, *
mTargetSpec, mPostData);
}
nsWebShell* mHandler;
nsString* mURLSpec;
nsString* mTargetSpec;
nsIPostData* mPostData;
nsIContent* mContent;
nsLinkVerb mVerb;
};
static void PR_CALLBACK HandlePLEvent(OnLinkClickEvent* aEvent)
@ -1484,6 +1491,8 @@ static void PR_CALLBACK DestroyPLEvent(OnLinkClickEvent* aEvent)
}
OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler,
nsIContent *aContent,
nsLinkVerb aVerb,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec,
nsIPostData* aPostData)
@ -1494,7 +1503,10 @@ OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler,
mTargetSpec = new nsString(aTargetSpec);
mPostData = aPostData;
NS_IF_ADDREF(mPostData);
mContent = aContent;
NS_IF_ADDREF(mContent);
mVerb = aVerb;
#ifdef XP_PC
PL_InitEvent(this, nsnull,
(PLHandleEventProc) ::HandlePLEvent,
@ -1516,16 +1528,19 @@ OnLinkClickEvent::OnLinkClickEvent(nsWebShell* aHandler,
OnLinkClickEvent::~OnLinkClickEvent()
{
NS_IF_RELEASE(mContent);
NS_IF_RELEASE(mHandler);
NS_IF_RELEASE(mPostData);
if (nsnull != mURLSpec) delete mURLSpec;
if (nsnull != mTargetSpec) delete mTargetSpec;
}
//----------------------------------------
NS_IMETHODIMP
nsWebShell::OnLinkClick(nsIFrame* aFrame,
nsWebShell::OnLinkClick(nsIContent* aContent,
nsLinkVerb aVerb,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec,
nsIPostData* aPostData)
@ -1533,7 +1548,8 @@ nsWebShell::OnLinkClick(nsIFrame* aFrame,
OnLinkClickEvent* ev;
nsresult rv = NS_OK;
ev = new OnLinkClickEvent(this, aURLSpec, aTargetSpec, aPostData);
ev = new OnLinkClickEvent(this, aContent, aVerb, aURLSpec,
aTargetSpec, aPostData);
if (nsnull == ev) {
rv = NS_ERROR_OUT_OF_MEMORY;
}
@ -1603,19 +1619,36 @@ nsWebShell::GetTarget(const PRUnichar* aName)
}
void
nsWebShell::HandleLinkClickEvent(const PRUnichar* aURLSpec,
nsWebShell::HandleLinkClickEvent(nsIContent *aContent,
nsLinkVerb aVerb,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec,
nsIPostData* aPostData)
{
nsIWebShell* shell = GetTarget(aTargetSpec);
if (nsnull != shell) {
shell->LoadURL(aURLSpec, aPostData);
NS_RELEASE(shell);
nsAutoString target(aTargetSpec);
switch(aVerb) {
case eLinkVerb_New:
target.SetString("_blank");
// Fall into replace case
case eLinkVerb_Replace:
{
nsIWebShell* shell = GetTarget(target.GetUnicode());
if (nsnull != shell) {
shell->LoadURL(aURLSpec, aPostData);
NS_RELEASE(shell);
}
}
break;
case eLinkVerb_Embed:
default:
;
// XXX Need to do this
}
}
NS_IMETHODIMP
nsWebShell::OnOverLink(nsIFrame* aFrame,
nsWebShell::OnOverLink(nsIContent* aContent,
const PRUnichar* aURLSpec,
const PRUnichar* aTargetSpec)
{