From c46d85528a2077a523580c5a5d6291ddfa1e595c Mon Sep 17 00:00:00 2001 From: "surkov.alexander%gmail.com" Date: Wed, 16 May 2007 06:04:21 +0000 Subject: [PATCH] Bug 380524 - implement IAccessibleComponent, r=aaronlev, sr=neil --- accessible/public/nsIAccessNode.idl | 13 +- accessible/public/nsIAccessible.idl | 9 +- accessible/src/base/nsAccessNode.cpp | 26 +++ accessible/src/msaa/CAccessibleComponent.cpp | 225 +++++++++++++++++++ accessible/src/msaa/CAccessibleComponent.h | 77 +++++++ accessible/src/msaa/Makefile.in | 2 + accessible/src/msaa/nsAccessibleWrap.cpp | 6 + accessible/src/msaa/nsAccessibleWrap.h | 2 + 8 files changed, 354 insertions(+), 6 deletions(-) create mode 100755 accessible/src/msaa/CAccessibleComponent.cpp create mode 100755 accessible/src/msaa/CAccessibleComponent.h diff --git a/accessible/public/nsIAccessNode.idl b/accessible/public/nsIAccessNode.idl index 2e0d9be620a..913a7d8951c 100644 --- a/accessible/public/nsIAccessNode.idl +++ b/accessible/public/nsIAccessNode.idl @@ -37,9 +37,10 @@ * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" - + interface nsIDOMNode; interface nsIAccessibleDocument; +interface nsIDOMCSSPrimitiveValue; /** * An interface used by in-process accessibility clients @@ -55,7 +56,7 @@ interface nsIAccessibleDocument; * * @status UNDER_REVIEW */ -[scriptable, uuid(11c0007f-531c-43b7-be63-a3060a13d8d2)] +[scriptable, uuid(0120eb06-3df3-49bf-95b1-2e2593a59265)] interface nsIAccessNode : nsISupports { /** @@ -158,4 +159,12 @@ interface nsIAccessNode : nsISupports * for example "border-bottom". */ DOMString getComputedStyleValue(in DOMString pseudoElt, in DOMString propertyName); + + /** + * The method is similar to getComputedStyleValue() excepting that this one + * returns nsIDOMCSSPrimitiveValue. + */ + nsIDOMCSSPrimitiveValue getComputedStyleCSSValue(in DOMString pseudoElt, + in DOMString propertyName); }; + diff --git a/accessible/public/nsIAccessible.idl b/accessible/public/nsIAccessible.idl index 3c0d904442f..7e40db3993f 100644 --- a/accessible/public/nsIAccessible.idl +++ b/accessible/public/nsIAccessible.idl @@ -226,10 +226,11 @@ interface nsIAccessible : nsISupports */ nsIAccessible getAccessibleRelated(in unsigned long aRelationType); - void getBounds(out long x, - out long y, - out long width, - out long height); + /** + * Return accessible's x and y coordinates relative to the screen and + * accessible's width and height. + */ + void getBounds(out long x, out long y, out long width, out long height); /** * Add or remove this accessible to the current selection diff --git a/accessible/src/base/nsAccessNode.cpp b/accessible/src/base/nsAccessNode.cpp index fb37d6a499b..709a84fd151 100755 --- a/accessible/src/base/nsAccessNode.cpp +++ b/accessible/src/base/nsAccessNode.cpp @@ -48,6 +48,7 @@ #include "nsIDocument.h" #include "nsIDocumentViewer.h" #include "nsIDOMCSSStyleDeclaration.h" +#include "nsIDOMCSSPrimitiveValue.h" #include "nsIDOMDocument.h" #include "nsIDOMElement.h" #include "nsIDOMNSHTMLElement.h" @@ -561,6 +562,31 @@ nsAccessNode::GetComputedStyleValue(const nsAString& aPseudoElt, const nsAString return styleDecl->GetPropertyValue(aPropertyName, aValue); } +NS_IMETHODIMP +nsAccessNode::GetComputedStyleCSSValue(const nsAString& aPseudoElt, + const nsAString& aPropertyName, + nsIDOMCSSPrimitiveValue **aCSSValue) +{ + NS_ENSURE_ARG_POINTER(aCSSValue); + + *aCSSValue = nsnull; + + nsCOMPtr domElement(do_QueryInterface(mDOMNode)); + if (!domElement) + return NS_ERROR_FAILURE; + + nsCOMPtr styleDecl; + GetComputedStyleDeclaration(aPseudoElt, domElement, + getter_AddRefs(styleDecl)); + NS_ENSURE_STATE(styleDecl); + + nsCOMPtr cssValue; + styleDecl->GetPropertyCSSValue(aPropertyName, getter_AddRefs(cssValue)); + NS_ENSURE_TRUE(cssValue, NS_ERROR_FAILURE); + + return CallQueryInterface(cssValue, aCSSValue); +} + void nsAccessNode::GetComputedStyleDeclaration(const nsAString& aPseudoElt, nsIDOMElement *aElement, nsIDOMCSSStyleDeclaration **aCssDecl) diff --git a/accessible/src/msaa/CAccessibleComponent.cpp b/accessible/src/msaa/CAccessibleComponent.cpp new file mode 100755 index 00000000000..0c47bc900b8 --- /dev/null +++ b/accessible/src/msaa/CAccessibleComponent.cpp @@ -0,0 +1,225 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:expandtab:shiftwidth=2:tabstop=2: + */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alexander Surkov (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "CAccessibleComponent.h" + +#include "AccessibleComponent_i.c" + +#include "nsIAccessNode.h" +#include "nsIAccessible.h" +#include "nsIAccessibleStates.h" + +#include "nsCOMPtr.h" +#include "nsString.h" + +#include "nsIDOMCSSPrimitiveValue.h" +#include "nsIDOMNSRGBAColor.h" + +enum { + IA2AlphaShift = 24, + IA2RedShift = 16, + IA2GreenShift = 8, + IA2BlueShift = 0 +}; + +// IUnknown + +STDMETHODIMP +CAccessibleComponent::QueryInterface(REFIID iid, void** ppv) +{ + *ppv = NULL; + + if (IID_IAccessibleComponent == iid) { + nsCOMPtr acc(do_QueryInterface(this)); + if (!acc) + return E_FAIL; + + *ppv = NS_STATIC_CAST(IAccessibleComponent*, this); + (NS_REINTERPRET_CAST(IUnknown*, *ppv))->AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +// IAccessibleComponent + +STDMETHODIMP +CAccessibleComponent::get_locationInParent(long *aX, long *aY) +{ + *aX = 0; + *aY = 0; + + nsCOMPtr acc(do_QueryInterface(this)); + if (!acc) + return E_FAIL; + + // If the object is not on any screen the returned position is (0,0). + PRUint32 states = 0, extraStates = 0; + nsresult rv = acc->GetFinalState(&states, &extraStates); + if (NS_FAILED(rv)) + return E_FAIL; + + if (states & nsIAccessibleStates::STATE_INVISIBLE) + return S_OK; + + PRInt32 x = 0, y = 0, width = 0, height = 0; + rv = acc->GetBounds(&x, &y, &width, &height); + if (NS_FAILED(rv)) + return E_FAIL; + + nsCOMPtr parentAcc; + rv = acc->GetParent(getter_AddRefs(parentAcc)); + if (NS_FAILED(rv)) + return E_FAIL; + + // The coordinates of the returned position are relative to this object's + // parent or relative to the screen on which this object is rendered if it + // has no parent. + if (!parentAcc) { + *aX = x; + *aY = y; + return NS_OK; + } + + // The coordinates of the bounding box are given relative to the parent's + // coordinate system. + PRInt32 parentx = 0, parenty = 0; + rv = acc->GetBounds(&parentx, &parenty, &width, &height); + if (NS_FAILED(rv)) + return E_FAIL; + + *aX = x - parentx; + *aY = y - parenty; + + return S_OK; +} + +STDMETHODIMP +CAccessibleComponent::get_foreground(IA2Color *aForeground) +{ + return GetARGBValueFromCSSProperty(NS_LITERAL_STRING("color"), aForeground); +} + +STDMETHODIMP +CAccessibleComponent::get_background(IA2Color *aBackground) +{ + return GetARGBValueFromCSSProperty(NS_LITERAL_STRING("background-color"), + aBackground); +} + +HRESULT +CAccessibleComponent::GetARGBValueFromCSSProperty(const nsAString& aPropName, + IA2Color *aColorValue) +{ + *aColorValue = 0; + + nsCOMPtr acc(do_QueryInterface(this)); + if (!acc) + return E_FAIL; + + nsCOMPtr cssValue; + nsresult rv = acc->GetComputedStyleCSSValue(EmptyString(), aPropName, + getter_AddRefs(cssValue)); + if (NS_FAILED(rv) || !cssValue) + return E_FAIL; + + nsCOMPtr rgbColor; + rv = cssValue->GetRGBColorValue(getter_AddRefs(rgbColor)); + if (NS_FAILED(rv) || !rgbColor) + return E_FAIL; + + nsCOMPtr rgbaColor(do_QueryInterface(rgbColor)); + if (!rgbaColor) + return E_FAIL; + + // get alpha + nsCOMPtr alphaValue; + rv = rgbaColor->GetAlpha(getter_AddRefs(alphaValue)); + if (NS_FAILED(rv) || !alphaValue) + return E_FAIL; + + float alpha = 0.0; + rv = alphaValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &alpha); + if (NS_FAILED(rv)) + return E_FAIL; + + // get red + nsCOMPtr redValue; + rv = rgbaColor->GetRed(getter_AddRefs(redValue)); + if (NS_FAILED(rv) || !redValue) + return E_FAIL; + + float red = 0.0; + rv = redValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &red); + if (NS_FAILED(rv)) + return E_FAIL; + + // get green + nsCOMPtr greenValue; + rv = rgbaColor->GetGreen(getter_AddRefs(greenValue)); + if (NS_FAILED(rv) || !greenValue) + return E_FAIL; + + float green = 0.0; + rv = greenValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &green); + if (NS_FAILED(rv)) + return E_FAIL; + + // get blue + nsCOMPtr blueValue; + rv = rgbaColor->GetBlue(getter_AddRefs(blueValue)); + if (NS_FAILED(rv) || !blueValue) + return E_FAIL; + + float blue = 0.0; + rv = blueValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &blue); + if (NS_FAILED(rv)) + return E_FAIL; + + // compose ARGB value + *aColorValue = (((IA2Color) blue) << IA2BlueShift) | + (((IA2Color) green) << IA2GreenShift) | + (((IA2Color) red) << IA2RedShift) | + (((IA2Color) (alpha * 0xff)) << IA2AlphaShift); + + return S_OK; +} + diff --git a/accessible/src/msaa/CAccessibleComponent.h b/accessible/src/msaa/CAccessibleComponent.h new file mode 100755 index 00000000000..592c81f6061 --- /dev/null +++ b/accessible/src/msaa/CAccessibleComponent.h @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:expandtab:shiftwidth=2:tabstop=2: + */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alexander Surkov (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _ACCESSIBLE_COMPONENt_H +#define _ACCESSIBLE_COMPONENT_H + +#include "nsISupports.h" + +#include "AccessibleComponent.h" + +class CAccessibleComponent: public nsISupports, + public IAccessibleComponent +{ +public: + + // IUnknown + STDMETHODIMP QueryInterface(REFIID, void**); + + // IAccessibleComponent + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_locationInParent( + /* [out] */ long *x, + /* [retval][out] */ long *y); + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_foreground( + /* [retval][out] */ IA2Color *foreground); + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_background( + /* [retval][out] */ IA2Color *background); + +protected: + + /** + * Return ARGB value for CSS property like 'color' or 'background-color'. + */ + HRESULT GetARGBValueFromCSSProperty(const nsAString& aPropName, + IA2Color *aColorValue); +}; + +#endif + diff --git a/accessible/src/msaa/Makefile.in b/accessible/src/msaa/Makefile.in index bfb00672c38..ff2af8ea7c8 100644 --- a/accessible/src/msaa/Makefile.in +++ b/accessible/src/msaa/Makefile.in @@ -80,6 +80,7 @@ CPPSRCS = \ nsHTMLTableAccessibleWrap.cpp \ CAccessibleAction.cpp \ CAccessibleImage.cpp \ + CAccessibleComponent.cpp \ CAccessibleText.cpp \ CAccessibleEditableText.cpp \ CAccessibleHyperlink.cpp \ @@ -102,6 +103,7 @@ EXPORTS = \ nsHTMLTableAccessibleWrap.h \ CAccessibleAction.h \ CAccessibleImage.h \ + CAccessibleComponent.h \ CAccessibleText.h \ CAccessibleEditableText.h \ CAccessibleHyperlink.h \ diff --git a/accessible/src/msaa/nsAccessibleWrap.cpp b/accessible/src/msaa/nsAccessibleWrap.cpp index f563fa25b0f..36743b0eda2 100644 --- a/accessible/src/msaa/nsAccessibleWrap.cpp +++ b/accessible/src/msaa/nsAccessibleWrap.cpp @@ -117,6 +117,12 @@ STDMETHODIMP nsAccessibleWrap::QueryInterface(REFIID iid, void** ppv) else if (IID_IAccessible2 == iid) *ppv = NS_STATIC_CAST(IAccessible2*, this); + if (NULL == *ppv) { + HRESULT hr = CAccessibleComponent::QueryInterface(iid, ppv); + if (SUCCEEDED(hr)) + return hr; + } + if (NULL == *ppv) { HRESULT hr = CAccessibleHyperlink::QueryInterface(iid, ppv); if (SUCCEEDED(hr)) diff --git a/accessible/src/msaa/nsAccessibleWrap.h b/accessible/src/msaa/nsAccessibleWrap.h index 852af16deb7..a1de43a44bd 100644 --- a/accessible/src/msaa/nsAccessibleWrap.h +++ b/accessible/src/msaa/nsAccessibleWrap.h @@ -46,6 +46,7 @@ #include "nsCOMPtr.h" #include "nsAccessible.h" #include "Accessible2.h" +#include "CAccessibleComponent.h" #include "CAccessibleHyperlink.h" #include "CAccessibleValue.h" @@ -89,6 +90,7 @@ Class::QueryInterface(REFIID iid, void** ppv) \ class nsAccessibleWrap : public nsAccessible, + public CAccessibleComponent, public CAccessibleHyperlink, public CAccessibleValue, public IAccessible2,