diff options
Diffstat (limited to 'embed/mozilla/EventContext.cpp')
-rw-r--r-- | embed/mozilla/EventContext.cpp | 669 |
1 files changed, 669 insertions, 0 deletions
diff --git a/embed/mozilla/EventContext.cpp b/embed/mozilla/EventContext.cpp new file mode 100644 index 000000000..9d4e312b6 --- /dev/null +++ b/embed/mozilla/EventContext.cpp @@ -0,0 +1,669 @@ +/* + * Copyright (C) 2000 Marco Pesenti Gritti + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "EventContext.h" +#include "nsIDOMEventTarget.h" +#include "nsIDocument.h" +#include "nsIDOMHTMLInputElement.h" +#include "nsIDOMHTMLObjectElement.h" +#include "nsIInterfaceRequestor.h" +#include "nsIDOMHTMLImageElement.h" +#include "nsIDOMElement.h" +#include "nsIDOMXULDocument.h" +#include "nsIURI.h" +#include "nsIDOMNSDocument.h" +#include "nsReadableUtils.h" +#include "nsUnicharUtils.h" +#include "nsGUIEvent.h" +#include "nsIDOMNSEvent.h" +#include "nsIDOMCharacterData.h" +#include "nsIDOMHTMLButtonElement.h" +#include "nsIDOMHTMLLabelElement.h" +#include "nsIDOMHTMLLegendElement.h" +#include "nsIDOMHTMLTextAreaElement.h" +#include <gdk/gdkkeysyms.h> +#include "nsIPrivateDOMEvent.h" +#include "nsIDOMNSUIEvent.h" + +#define KEY_CODE 256 + +EventContext::EventContext () +{ +} + +EventContext::~EventContext () +{ +} + +nsresult EventContext::Init (nsIDOMEvent *event, EphyWrapper *wrapper) +{ + mEvent = event; + mWrapper = wrapper; + mDOMDocument = nsnull; + + return NS_OK; +} + +nsresult EventContext::GetEventContext (nsIDOMEventTarget *EventTarget, + EphyEmbedEvent *info) +{ + nsresult rv; + + mEmbedEvent = info; + + info->context = EMBED_CONTEXT_DOCUMENT; + + nsCOMPtr<nsIDOMNode> node = do_QueryInterface(EventTarget, &rv); + if (NS_FAILED(rv) || !node) return NS_ERROR_FAILURE; + + /* Is page xul ? then do not display context menus + * FIXME I guess there is an easier way ... */ + /* From philipl: This test needs to be here otherwise we + * arrogantly assume we can QI to a HTMLElement, which is + * not true for xul content. */ + + nsCOMPtr<nsIDOMDocument> domDoc; + rv = node->GetOwnerDocument(getter_AddRefs(domDoc)); + if (NS_FAILED(rv) || !domDoc) return NS_ERROR_FAILURE; + + mDOMDocument = domDoc; + + nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc, &rv); + if (NS_FAILED(rv) || !doc) return NS_ERROR_FAILURE; + + nsCOMPtr<nsIDOMXULDocument> xul_document = do_QueryInterface(domDoc); + if (xul_document) + { + info->context = EMBED_CONTEXT_NONE; + return NS_ERROR_FAILURE; + } + + // Now we know that the page isn't a xul window, we can try and + // do something useful with it. + + PRUint16 type; + rv = node->GetNodeType(&type); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(node); + if ((nsIDOMNode::ELEMENT_NODE == type) && element) + { + nsAutoString tag; + rv = element->GetTagName(tag); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + if (tag.Equals(NS_LITERAL_STRING("img"), + nsCaseInsensitiveStringComparator())) + { + info->context |= EMBED_CONTEXT_IMAGE; + + nsAutoString img; + nsCOMPtr <nsIDOMHTMLImageElement> image = + do_QueryInterface(node, &rv); + if (NS_FAILED(rv) || !image) return NS_ERROR_FAILURE; + + rv = image->GetSrc (img); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + SetStringProperty ("image", img); + + rv = image->GetAlt (img); + if (NS_SUCCEEDED(rv)) + { + SetStringProperty ("image_alt", img); + } + + rv = image->GetLongDesc (img); + if (NS_SUCCEEDED(rv) && !img.IsEmpty()) + { + nsCAutoString imglongdesc; + const nsACString &src = NS_ConvertUCS2toUTF8(img); + + nsCOMPtr<nsIURI> uri; + doc->GetDocumentURL(getter_AddRefs(uri)); + + rv = uri->Resolve (src, imglongdesc); + + SetStringProperty ("image_long_desc", + NS_ConvertUTF8toUCS2(imglongdesc)); + } + + int imgwidth, imgheight; + rv = image->GetWidth (&imgwidth); + rv = image->GetHeight (&imgheight); + SetIntProperty ("image_width", imgwidth); + SetIntProperty ("image_height", imgheight); + + rv = element->GetTitle (img); + if (NS_SUCCEEDED(rv)) + { + SetStringProperty ("image_title", + img); + } + } + else if (tag.Equals(NS_LITERAL_STRING("input"), + nsCaseInsensitiveStringComparator())) + { + nsCOMPtr<nsIDOMElement> element; + element = do_QueryInterface (node); + if (!element) return NS_ERROR_FAILURE; + + NS_NAMED_LITERAL_STRING(attr, "type"); + nsAutoString value; + element->GetAttribute (attr, value); + + if (value.Equals(NS_LITERAL_STRING("image"), + nsCaseInsensitiveStringComparator())) + { + info->context |= EMBED_CONTEXT_IMAGE; + nsCOMPtr<nsIDOMHTMLInputElement> input; + input = do_QueryInterface (node); + if (!input) return NS_ERROR_FAILURE; + + nsAutoString img; + rv = input->GetSrc (img); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + nsCAutoString cImg; + const nsACString &src = NS_ConvertUCS2toUTF8(img); + + nsCOMPtr<nsIURI> uri; + doc->GetDocumentURL(getter_AddRefs(uri)); + rv = uri->Resolve (src, cImg); + SetStringProperty ("image", + NS_ConvertUTF8toUCS2(cImg)); + + if (NS_FAILED (rv)) return NS_ERROR_FAILURE; + } + else if (!value.Equals(NS_LITERAL_STRING("radio"), + nsCaseInsensitiveStringComparator()) && + !value.Equals(NS_LITERAL_STRING("submit"), + nsCaseInsensitiveStringComparator()) && + !value.Equals(NS_LITERAL_STRING("reset"), + nsCaseInsensitiveStringComparator()) && + !value.Equals(NS_LITERAL_STRING("hidden"), + nsCaseInsensitiveStringComparator()) && + !value.Equals(NS_LITERAL_STRING("button"), + nsCaseInsensitiveStringComparator()) && + !value.Equals(NS_LITERAL_STRING("checkbox"), + nsCaseInsensitiveStringComparator())) + { + info->context |= EMBED_CONTEXT_INPUT; + } + } + else if (tag.Equals(NS_LITERAL_STRING("textarea"), + nsCaseInsensitiveStringComparator())) + { + info->context |= EMBED_CONTEXT_INPUT; + } + else if (tag.Equals(NS_LITERAL_STRING("object"), + nsCaseInsensitiveStringComparator())) + { + nsCOMPtr<nsIDOMHTMLObjectElement> object; + object = do_QueryInterface (node); + if (!element) return NS_ERROR_FAILURE; + + nsAutoString value; + object->GetType(value); + + //Forming a substring and confirming it's contents + //is quicker than doing a Find on the full string + //and then checking that "image/" is at the beginning + if (Substring(value, 0, 6).Equals(NS_LITERAL_STRING("image/"), + nsCaseInsensitiveStringComparator())) + { + info->context |= EMBED_CONTEXT_IMAGE; + + nsAutoString img; + + rv = object->GetData (img); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + nsCAutoString cImg; + const nsACString &src = NS_ConvertUCS2toUTF8(img); + + nsCOMPtr<nsIURI> uri; + doc->GetDocumentURL(getter_AddRefs(uri)); + rv = uri->Resolve (src, cImg); + SetStringProperty ("image", + NS_ConvertUTF8toUCS2(cImg)); + + if (NS_FAILED (rv)) return NS_ERROR_FAILURE; + } + else + { + info->context = EMBED_CONTEXT_NONE; + return NS_OK; + } + } + } + + /* Is page framed ? */ + PRBool framed; + IsPageFramed (node, &framed); + SetIntProperty ("framed_page", framed); + + /* Bubble out, looking for items of interest */ + while (node) + { + nsCOMPtr <nsIDOMElement> dom_elem = do_QueryInterface(node); + if (dom_elem) + { + NS_NAMED_LITERAL_STRING(nspace, "http://www.w3.org/1999/xlink"); + NS_NAMED_LITERAL_STRING(localname_type, "type"); + + nsAutoString value; + dom_elem->GetAttributeNS (nspace, localname_type, value); + + if (value.Equals(NS_LITERAL_STRING("simple"), + nsCaseInsensitiveStringComparator())) + { + info->context |= EMBED_CONTEXT_LINK; + NS_NAMED_LITERAL_STRING (localname_href, "href"); + dom_elem->GetAttributeNS (nspace, localname_href, value); + + SetStringProperty ("link", value); + } + } + + PRUint16 type; + rv = node->GetNodeType(&type); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + element = do_QueryInterface(node); + if ((nsIDOMNode::ELEMENT_NODE == type) && element) + { + nsAutoString tag; + rv = element->GetTagName(tag); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + /* Link */ + if (tag.Equals(NS_LITERAL_STRING("a"), + nsCaseInsensitiveStringComparator())) + { + nsCOMPtr <nsIDOMHTMLAnchorElement> anchor = + do_QueryInterface(node); + nsAutoString tmp; + rv = anchor->GetHref (tmp); + if (NS_FAILED(rv)) + return NS_ERROR_FAILURE; + + if (Substring(tmp, 0, 7).Equals(NS_LITERAL_STRING("mailto:"), + nsCaseInsensitiveStringComparator())) + { + info->context |= EMBED_CONTEXT_EMAIL_LINK; + const nsAString &address = Substring(tmp, 7, tmp.Length()-7); + SetStringProperty ("email", address); + } + + if (anchor && !tmp.IsEmpty()) + { + info->context |= EMBED_CONTEXT_LINK; + + SetStringProperty ("link", tmp); + rv = anchor->GetHreflang (tmp); + if (NS_SUCCEEDED(rv)) + SetStringProperty ("link_lang", tmp); + rv = anchor->GetTarget (tmp); + if (NS_SUCCEEDED(rv)) + SetStringProperty ("link_target", tmp); + rv = anchor->GetRel (tmp); + if (NS_SUCCEEDED(rv)) + SetStringProperty ("link_rel", tmp); + rv = anchor->GetRev (tmp); + if (NS_SUCCEEDED(rv)) + SetStringProperty ("link_rev", tmp); + rv = element->GetTitle (tmp); + if (NS_SUCCEEDED(rv)) + SetStringProperty ("link_title", tmp); + rv = anchor->GetType (tmp); + if (NS_SUCCEEDED(rv)) + SetStringProperty ("link_type", tmp); + + if (tmp.Equals(NS_LITERAL_STRING("text/smartbookmark"), + nsCaseInsensitiveStringComparator())) + { + SetIntProperty ("link_is_smart", TRUE); + + nsCOMPtr<nsIDOMNode> childNode; + node->GetFirstChild (getter_AddRefs(childNode)); + if (childNode) + { + nsCOMPtr <nsIDOMHTMLImageElement> image = + do_QueryInterface(childNode, &rv); + + if (image) + { + nsAutoString img; + rv = image->GetSrc (img); + if (!NS_FAILED(rv)) + { + SetStringProperty ("image", img); + } + } + } + } +#ifdef NOT_PORTED + /* Get the text of the link */ + info->linktext = mozilla_get_link_text (node); +#endif + } + + } + else if (tag.Equals(NS_LITERAL_STRING("option"), + nsCaseInsensitiveStringComparator())) + { + info->context = EMBED_CONTEXT_NONE; + return NS_OK; + } + if (tag.Equals(NS_LITERAL_STRING("area"), + nsCaseInsensitiveStringComparator())) + { + info->context |= EMBED_CONTEXT_LINK; + nsCOMPtr <nsIDOMHTMLAreaElement> area = + do_QueryInterface(node, &rv); + if (NS_SUCCEEDED(rv) && area) + { + nsAutoString href; + rv = area->GetHref (href); + if (NS_FAILED(rv)) + return NS_ERROR_FAILURE; + + SetStringProperty ("link", href); + } + } + else if (tag.Equals(NS_LITERAL_STRING("textarea"), + nsCaseInsensitiveStringComparator()) || + tag.Equals(NS_LITERAL_STRING("input"), + nsCaseInsensitiveStringComparator())) + { + info->context |= EMBED_CONTEXT_INPUT; + } + + nsCOMPtr<nsIDOMElement> domelement; + domelement = do_QueryInterface (node); + if (!domelement) return NS_ERROR_FAILURE; + + PRBool has_background = PR_FALSE; + + NS_NAMED_LITERAL_STRING(attr, "background"); + nsAutoString value; + domelement->GetAttribute (attr, value); + + if (!value.IsEmpty()) + { + nsCAutoString bgimg; + const nsACString &tmp = + NS_ConvertUCS2toUTF8(value); + + nsCOMPtr<nsIURI> uri; + doc->GetDocumentURL(getter_AddRefs(uri)); + rv = uri->Resolve (tmp, bgimg); + if (NS_FAILED (rv)) + return NS_ERROR_FAILURE; + SetStringProperty ("background_image", + NS_ConvertUTF8toUCS2(bgimg)); + } + else + { + nsCOMPtr<nsIDOMHTMLBodyElement> bgelement; + bgelement = do_QueryInterface (node); + if (bgelement) + { + nsAutoString value; + bgelement->GetBackground (value); + + if (!value.IsEmpty()) + { + nsCAutoString bgimg; + const nsACString &tmp = + NS_ConvertUCS2toUTF8(value); + + nsIURI *uri; + doc->GetBaseURL(uri); + rv = uri->Resolve + (tmp, bgimg); + SetStringProperty ("background_image", + NS_ConvertUTF8toUCS2(bgimg)); + if (NS_FAILED (rv)) + return NS_ERROR_FAILURE; + has_background = PR_TRUE; + } + } + } + + if (!has_background) + { + nsAutoString cssurl; + rv = GetCSSBackground (node, cssurl); + if (NS_SUCCEEDED (rv)) + { + nsCAutoString bgimg; + const nsACString &tmp = + NS_ConvertUCS2toUTF8(cssurl); + + nsIURI *uri; + doc->GetBaseURL(uri); + rv = uri->Resolve + (tmp, bgimg); + SetStringProperty ("background_image", + NS_ConvertUTF8toUCS2(bgimg)); + if (NS_FAILED (rv)) + return NS_ERROR_FAILURE; + } + } + } + + nsCOMPtr<nsIDOMNode> parentNode; + node->GetParentNode (getter_AddRefs(parentNode)); + node = parentNode; + } + + return NS_OK; +} + +nsresult EventContext::GetCSSBackground (nsIDOMNode *node, nsAutoString& url) +{ + nsresult result; + + nsCOMPtr<nsIDOMElementCSSInlineStyle> style; + style = do_QueryInterface (node); + if (!style) return NS_ERROR_FAILURE; + + nsCOMPtr<nsIDOMCSSStyleDeclaration> decl; + result = style->GetStyle (getter_AddRefs(decl)); + if (NS_FAILED(result)) return NS_ERROR_FAILURE; + + nsAutoString value; + NS_NAMED_LITERAL_STRING(prop_bgi, "background-image"); + decl->GetPropertyValue (prop_bgi, value); + + if (value.IsEmpty()) + { + NS_NAMED_LITERAL_STRING(prop_bg, "background"); + decl->GetPropertyValue (prop_bg, value); + if (value.IsEmpty()) + { + NS_NAMED_LITERAL_STRING(prop_bgr, "background-repeat"); + decl->GetPropertyValue (prop_bgr, value); + if (value.IsEmpty()) + return NS_ERROR_FAILURE; + } + } + + PRInt32 start, end; + nsAutoString cssurl; + + NS_NAMED_LITERAL_STRING(startsub, "url("); + NS_NAMED_LITERAL_STRING(endsub, ")"); + + start = value.Find (startsub) + 4; + end = value.Find (endsub); + + if (start == -1 || end == -1) + return NS_ERROR_FAILURE; + + url.Assign(Substring (value, start, end - start)); + + return NS_OK; +} + +nsresult EventContext::GetMouseEventInfo (EphyEmbedEvent *info) +{ + nsresult result; + DOMTimeStamp ts; + nsIDOMMouseEvent *aMouseEvent = (nsIDOMMouseEvent*)mEvent; + + aMouseEvent->GetButton ((PRUint16*)&info->mouse_button); + aMouseEvent->GetScreenX ((PRInt32*)&info->mouse_x); + aMouseEvent->GetScreenY ((PRInt32*)&info->mouse_y); + + aMouseEvent->GetTimeStamp(&ts); + info->timestamp = ts; + + /* be sure we are not clicking on the scroolbars */ + + nsCOMPtr<nsIDOMNSEvent> nsEvent = do_QueryInterface(aMouseEvent, &result); + if (NS_FAILED(result) || !nsEvent) return NS_ERROR_FAILURE; + + nsCOMPtr<nsIDOMEventTarget> OriginalTarget; + result = nsEvent->GetOriginalTarget(getter_AddRefs(OriginalTarget)); + if (NS_FAILED(result) || !OriginalTarget) return NS_ERROR_FAILURE; + + nsCOMPtr<nsIDOMNode> OriginalNode = do_QueryInterface(OriginalTarget); + if (!OriginalNode) return NS_ERROR_FAILURE; + + nsAutoString nodename; + OriginalNode->GetNodeName(nodename); + + if (nodename.Equals(NS_LITERAL_STRING("xul:scrollbarbutton"), + nsCaseInsensitiveStringComparator()) || + nodename.Equals(NS_LITERAL_STRING("xul:thumb"), + nsCaseInsensitiveStringComparator()) || + nodename.Equals(NS_LITERAL_STRING("xul:vbox"), + nsCaseInsensitiveStringComparator()) || + nodename.Equals(NS_LITERAL_STRING("xul:spacer"), + nsCaseInsensitiveStringComparator()) || + nodename.Equals(NS_LITERAL_STRING("xul:slider"), + nsCaseInsensitiveStringComparator())) + return NS_ERROR_FAILURE; + + nsCOMPtr<nsIDOMEventTarget> EventTarget; + result = aMouseEvent->GetTarget(getter_AddRefs(EventTarget)); + if (NS_FAILED(result) || !EventTarget) return NS_ERROR_FAILURE; + + result = GetEventContext (EventTarget, info); + if (NS_FAILED(result)) return result; + + /* Get the modifier */ + + PRBool mod_key; + + info->modifier = 0; + + aMouseEvent->GetAltKey(&mod_key); + if (mod_key) info->modifier |= GDK_MOD1_MASK; + + aMouseEvent->GetShiftKey(&mod_key); + if (mod_key) info->modifier |= GDK_SHIFT_MASK; + + aMouseEvent->GetMetaKey(&mod_key); + if (mod_key) info->modifier |= GDK_Meta_L; + + aMouseEvent->GetCtrlKey(&mod_key); + if (mod_key) info->modifier |= GDK_CONTROL_MASK; + + return NS_OK; +} + +nsresult EventContext::IsPageFramed (nsIDOMNode *node, PRBool *Framed) +{ + nsresult result; + + nsCOMPtr<nsIDOMDocument> mainDocument; + result = mWrapper->GetMainDOMDocument (getter_AddRefs(mainDocument)); + if (NS_FAILED(result) || !mainDocument) return NS_ERROR_FAILURE; + + nsCOMPtr<nsIDOMDocument> nodeDocument; + result = node->GetOwnerDocument (getter_AddRefs(nodeDocument)); + if (NS_FAILED(result) || !nodeDocument) return NS_ERROR_FAILURE; + + *Framed = (mainDocument != nodeDocument); + + return NS_OK; +} + +nsresult EventContext::GetTargetDocument (nsIDOMDocument **domDoc) +{ + if (!mDOMDocument) return NS_ERROR_FAILURE; + + *domDoc = mDOMDocument.get(); + + NS_IF_ADDREF(*domDoc); + + return NS_OK; +} + +nsresult EventContext::SetIntProperty (const char *name, int value) +{ + + GValue *val = g_new0 (GValue, 1); + + g_value_init (val, G_TYPE_INT); + + g_value_set_int (val, value); + + ephy_embed_event_set_property (mEmbedEvent, + g_strdup (name), + val); + + return NS_OK; +} + +nsresult EventContext::SetStringProperty (const char *name, const char *value) +{ + GValue *val = g_new0 (GValue, 1); + + g_value_init (val, G_TYPE_STRING); + + g_value_set_string (val, value); + + ephy_embed_event_set_property (mEmbedEvent, + g_strdup (name), + val); + + return NS_OK; +} + +nsresult EventContext::SetStringProperty (const char *name, const nsAString &value) +{ + GValue *val = g_new0 (GValue, 1);; + char *tmp; + + tmp = ToNewCString (NS_ConvertUCS2toUTF8(value)); + + g_value_init (val, G_TYPE_STRING); + + g_value_set_string (val, tmp); + + ephy_embed_event_set_property (mEmbedEvent, + g_strdup (name), + val); + nsMemory::Free (tmp); + + return NS_OK; +} |