Bug 686433 - move out nsXULSelectableAccessible class from nsXULMenuAccessible.h file. r=tbsaunde
authorJignesh Kakadiya <jigneshhk1992@gmail.com>
Sun, 31 Dec 2000 19:12:15 -0500
changeset 84629 252d3d08fbc411732d1fd57a2eae514e92247237
parent 84628 e40e72d6264ddf069d78a4c99a9544e6d396092c
child 84630 f0cf32f96fa8cf15e0817d3ead738fad803fe4e4
push id21868
push usermak77@bonardo.net
push dateTue, 17 Jan 2012 15:23:07 +0000
treeherdermozilla-central@ff1bedd7d463 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstbsaunde
bugs686433
milestone12.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 686433 - move out nsXULSelectableAccessible class from nsXULMenuAccessible.h file. r=tbsaunde
accessible/src/xul/Makefile.in
accessible/src/xul/XULSelectControlAccessible.cpp
accessible/src/xul/XULSelectControlAccessible.h
accessible/src/xul/nsXULFormControlAccessible.cpp
accessible/src/xul/nsXULFormControlAccessible.h
accessible/src/xul/nsXULListboxAccessible.cpp
accessible/src/xul/nsXULListboxAccessible.h
accessible/src/xul/nsXULMenuAccessible.cpp
accessible/src/xul/nsXULMenuAccessible.h
accessible/src/xul/nsXULTabAccessible.cpp
accessible/src/xul/nsXULTabAccessible.h
--- a/accessible/src/xul/Makefile.in
+++ b/accessible/src/xul/Makefile.in
@@ -45,16 +45,17 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_xul_s
 LIBXUL_LIBRARY = 1
 
 
 
 CPPSRCS = \
+  XULSelectControlAccessible.cpp \
   nsXULAlertAccessible.cpp \
   nsXULColorPickerAccessible.cpp \
   nsXULComboboxAccessible.cpp \
   nsXULFormControlAccessible.cpp \
   nsXULListboxAccessible.cpp \
   nsXULMenuAccessible.cpp \
   nsXULSliderAccessible.cpp \
   nsXULTabAccessible.cpp \
new file mode 100644
--- /dev/null
+++ b/accessible/src/xul/XULSelectControlAccessible.cpp
@@ -0,0 +1,309 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* ***** 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) 2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jignesh Kakadiya (jigneshhk1992@gmail.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 "XULSelectControlAccessible.h"
+
+#include "nsAccessibilityService.h"
+#include "nsDocAccessible.h"
+
+#include "nsIDOMXULContainerElement.h"
+#include "nsIDOMXULSelectCntrlItemEl.h"
+#include "nsIDOMXULMultSelectCntrlEl.h"
+#include "nsIDOMKeyEvent.h"
+#include "nsIDOMElement.h"
+#include "nsIDOMXULElement.h"
+#include "nsIMutableArray.h"
+#include "nsIServiceManager.h"
+
+#include "mozilla/dom/Element.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+////////////////////////////////////////////////////////////////////////////////
+// XULSelectControlAccessible
+////////////////////////////////////////////////////////////////////////////////
+
+XULSelectControlAccessible::
+  XULSelectControlAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
+  nsAccessibleWrap(aContent, aShell)
+{
+  mSelectControl = do_QueryInterface(aContent);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// XULSelectControlAccessible: nsAccessNode
+
+void
+XULSelectControlAccessible::Shutdown()
+{
+  mSelectControl = nsnull;
+  nsAccessibleWrap::Shutdown();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// XULSelectControlAccessible: SelectAccessible
+
+bool
+XULSelectControlAccessible::IsSelect()
+{
+  return !!mSelectControl;
+}
+
+// Interface methods
+already_AddRefed<nsIArray>
+XULSelectControlAccessible::SelectedItems()
+{
+  nsCOMPtr<nsIMutableArray> selectedItems =
+    do_CreateInstance(NS_ARRAY_CONTRACTID);
+  if (!selectedItems)
+    return nsnull;
+
+  // For XUL multi-select control
+  nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect =
+    do_QueryInterface(mSelectControl);
+  if (xulMultiSelect) {
+    PRInt32 length = 0;
+    xulMultiSelect->GetSelectedCount(&length);
+    for (PRInt32 index = 0; index < length; index++) {
+      nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm;
+      xulMultiSelect->GetSelectedItem(index, getter_AddRefs(itemElm));
+      nsCOMPtr<nsINode> itemNode(do_QueryInterface(itemElm));
+      nsAccessible* item =
+        GetAccService()->GetAccessibleInWeakShell(itemNode, mWeakShell);
+      if (item)
+        selectedItems->AppendElement(static_cast<nsIAccessible*>(item),
+                                     false);
+    }
+  } else {  // Single select?
+      nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm;
+      mSelectControl->GetSelectedItem(getter_AddRefs(itemElm));
+      nsCOMPtr<nsINode> itemNode(do_QueryInterface(itemElm));
+      if(itemNode) {
+        nsAccessible* item =
+          GetAccService()->GetAccessibleInWeakShell(itemNode, mWeakShell);
+        if (item)
+          selectedItems->AppendElement(static_cast<nsIAccessible*>(item),
+                                     false);
+      }
+    }
+
+  nsIMutableArray* items = nsnull;
+  selectedItems.forget(&items);
+  return items;
+}
+
+nsAccessible*
+XULSelectControlAccessible::GetSelectedItem(PRUint32 aIndex)
+{
+  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+    do_QueryInterface(mSelectControl);
+
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm;
+  if (multiSelectControl)
+    multiSelectControl->GetSelectedItem(aIndex, getter_AddRefs(itemElm));
+  else if (aIndex == 0)
+    mSelectControl->GetSelectedItem(getter_AddRefs(itemElm));
+
+  nsCOMPtr<nsINode> itemNode(do_QueryInterface(itemElm));
+  return itemNode ?
+    GetAccService()->GetAccessibleInWeakShell(itemNode, mWeakShell) : nsnull;
+}
+
+PRUint32
+XULSelectControlAccessible::SelectedItemCount()
+{
+  // For XUL multi-select control
+  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+    do_QueryInterface(mSelectControl);
+  if (multiSelectControl) {
+    PRInt32 count = 0;
+    multiSelectControl->GetSelectedCount(&count);
+    return count;
+  }
+
+  // For XUL single-select control/menulist
+  PRInt32 index;
+  mSelectControl->GetSelectedIndex(&index);
+  return (index >= 0) ? 1 : 0;
+}
+
+bool
+XULSelectControlAccessible::AddItemToSelection(PRUint32 aIndex)
+{
+  nsAccessible* item = GetChildAt(aIndex);
+  if (!item)
+    return false;
+
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
+    do_QueryInterface(item->GetContent());
+  if (!itemElm)
+    return false;
+
+  bool isItemSelected = false;
+  itemElm->GetSelected(&isItemSelected);
+  if (isItemSelected)
+    return true;
+
+  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+    do_QueryInterface(mSelectControl);
+
+  if (multiSelectControl)
+    multiSelectControl->AddItemToSelection(itemElm);
+  else
+    mSelectControl->SetSelectedItem(itemElm);
+
+  return true;
+}
+
+bool
+XULSelectControlAccessible::RemoveItemFromSelection(PRUint32 aIndex)
+{
+  nsAccessible* item = GetChildAt(aIndex);
+  if (!item)
+    return false;
+
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
+      do_QueryInterface(item->GetContent());
+  if (!itemElm)
+    return false;
+
+  bool isItemSelected = false;
+  itemElm->GetSelected(&isItemSelected);
+  if (!isItemSelected)
+    return true;
+
+  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+    do_QueryInterface(mSelectControl);
+
+  if (multiSelectControl)
+    multiSelectControl->RemoveItemFromSelection(itemElm);
+  else
+    mSelectControl->SetSelectedItem(nsnull);
+
+  return true;
+}
+
+bool
+XULSelectControlAccessible::IsItemSelected(PRUint32 aIndex)
+{
+  nsAccessible* item = GetChildAt(aIndex);
+  if (!item)
+    return false;
+
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
+    do_QueryInterface(item->GetContent());
+  if (!itemElm)
+    return false;
+
+  bool isItemSelected = false;
+  itemElm->GetSelected(&isItemSelected);
+  return isItemSelected;
+}
+
+bool
+XULSelectControlAccessible::UnselectAll()
+{
+  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+    do_QueryInterface(mSelectControl);
+  multiSelectControl ?
+    multiSelectControl->ClearSelection() : mSelectControl->SetSelectedIndex(-1);
+
+  return true;
+}
+
+bool
+XULSelectControlAccessible::SelectAll()
+{
+  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+    do_QueryInterface(mSelectControl);
+  if (multiSelectControl) {
+    multiSelectControl->SelectAll();
+    return true;
+  }
+
+  // otherwise, don't support this method
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// XULSelectControlAccessible: Widgets
+
+nsAccessible*
+XULSelectControlAccessible::CurrentItem()
+{
+  if (!mSelectControl)
+    return nsnull;
+
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> currentItemElm;
+  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+    do_QueryInterface(mSelectControl);
+  if (multiSelectControl)
+    multiSelectControl->GetCurrentItem(getter_AddRefs(currentItemElm));
+  else
+    mSelectControl->GetSelectedItem(getter_AddRefs(currentItemElm));
+
+  nsCOMPtr<nsINode> DOMNode;
+  if (currentItemElm)
+    DOMNode = do_QueryInterface(currentItemElm);
+
+  if (DOMNode) {
+    nsDocAccessible* document = GetDocAccessible();
+    if (document)
+      return document->GetAccessible(DOMNode);
+  }
+
+  return nsnull;
+}
+
+void
+XULSelectControlAccessible::SetCurrentItem(nsAccessible* aItem)
+{
+  if (!mSelectControl)
+    return;
+
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
+    do_QueryInterface(aItem->GetContent());
+  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
+    do_QueryInterface(mSelectControl);
+  if (multiSelectControl)
+    multiSelectControl->SetCurrentItem(itemElm);
+  else
+    mSelectControl->SetSelectedItem(itemElm);
+}
new file mode 100644
--- /dev/null
+++ b/accessible/src/xul/XULSelectControlAccessible.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* ***** 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) 2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jignesh Kakadiya (jigneshhk1992@gmail.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 _XULSelectControlAccessible_H_
+#define _XULSelectControlAccessible_H_
+
+#include "nsAccessibleWrap.h"
+#include "nsIDOMXULSelectCntrlEl.h"
+
+/**
+ * The basic implementation of accessible selection for XUL select controls.
+ */
+class XULSelectControlAccessible : public nsAccessibleWrap
+{
+public:
+  XULSelectControlAccessible(nsIContent *aContent, nsIWeakReference *aShell);
+  virtual ~XULSelectControlAccessible() {}
+
+  // nsAccessNode
+  virtual void Shutdown();
+
+  // SelectAccessible
+  virtual bool IsSelect();
+  virtual already_AddRefed<nsIArray> SelectedItems();
+  virtual PRUint32 SelectedItemCount();
+  virtual nsAccessible* GetSelectedItem(PRUint32 aIndex);
+  virtual bool IsItemSelected(PRUint32 aIndex);
+  virtual bool AddItemToSelection(PRUint32 aIndex);
+  virtual bool RemoveItemFromSelection(PRUint32 aIndex);
+  virtual bool SelectAll();
+  virtual bool UnselectAll();
+
+  // Widgets
+  virtual nsAccessible* CurrentItem();
+  virtual void SetCurrentItem(nsAccessible* aItem);
+
+protected:
+  // nsIDOMXULMultiSelectControlElement inherits from this, so we'll always have
+  // one of these if the widget is valid and not defunct
+  nsCOMPtr<nsIDOMXULSelectControlElement> mSelectControl;
+};
+
+#endif
+
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp
+++ b/accessible/src/xul/nsXULFormControlAccessible.cpp
@@ -554,17 +554,17 @@ nsXULRadioButtonAccessible::ContainerWid
   *   focus whereas the Buttons do not. So we only have an accessible object for
   *   this for the purpose of getting the proper RadioButton. Need this here to 
   *   avoid circular reference problems when navigating the accessible tree and
   *   for getting to the radiobuttons.
   */
 
 nsXULRadioGroupAccessible::
   nsXULRadioGroupAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
-  nsXULSelectableAccessible(aContent, aShell)
+  XULSelectControlAccessible(aContent, aShell)
 { 
 }
 
 role
 nsXULRadioGroupAccessible::NativeRole()
 {
   return roles::GROUPING;
 }
--- a/accessible/src/xul/nsXULFormControlAccessible.h
+++ b/accessible/src/xul/nsXULFormControlAccessible.h
@@ -38,18 +38,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsXULFormControlAccessible_H_
 #define _nsXULFormControlAccessible_H_
 
 // NOTE: alphabetically ordered
 #include "nsAccessibleWrap.h"
 #include "nsFormControlAccessible.h"
-#include "nsXULMenuAccessible.h"
 #include "nsHyperTextAccessibleWrap.h"
+#include "XULSelectControlAccessible.h"
 
 /**
  * Used for XUL progressmeter element.
  */
 typedef ProgressMeterAccessible<100> XULProgressMeterAccessible;
 
 /**
  * Used for XUL button.
@@ -168,17 +168,17 @@ public:
 
   // Widgets
   virtual nsAccessible* ContainerWidget() const;
 };
 
 /**
  * Used for XUL radiogroup element.
  */
-class nsXULRadioGroupAccessible : public nsXULSelectableAccessible
+class nsXULRadioGroupAccessible : public XULSelectControlAccessible
 {
 public:
   nsXULRadioGroupAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
   // nsAccessible
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
 
@@ -279,10 +279,10 @@ protected:
   // nsHyperTextAccessible
   virtual already_AddRefed<nsFrameSelection> FrameSelection();
 
   // nsXULTextFieldAccessible
   already_AddRefed<nsIContent> GetInputField() const;
 };
 
 
-#endif  
+#endif
 
--- a/accessible/src/xul/nsXULListboxAccessible.cpp
+++ b/accessible/src/xul/nsXULListboxAccessible.cpp
@@ -128,34 +128,34 @@ nsXULColumnItemAccessible::DoAction(PRUi
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULListboxAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULListboxAccessible::
   nsXULListboxAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
-  nsXULSelectableAccessible(aContent, aShell)
+  XULSelectControlAccessible(aContent, aShell)
 {
   nsIContent* parentContent = mContent->GetParent();
   if (parentContent) {
     nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
       do_QueryInterface(parentContent);
     if (autoCompletePopupElm)
       mFlags |= eAutoCompletePopupAccessible;
   }
 }
 
-NS_IMPL_ADDREF_INHERITED(nsXULListboxAccessible, nsXULSelectableAccessible)
-NS_IMPL_RELEASE_INHERITED(nsXULListboxAccessible, nsXULSelectableAccessible)
+NS_IMPL_ADDREF_INHERITED(nsXULListboxAccessible, XULSelectControlAccessible)
+NS_IMPL_RELEASE_INHERITED(nsXULListboxAccessible, XULSelectControlAccessible)
 
 nsresult
 nsXULListboxAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
 {
-  nsresult rv = nsXULSelectableAccessible::QueryInterface(aIID, aInstancePtr);
+  nsresult rv = XULSelectControlAccessible::QueryInterface(aIID, aInstancePtr);
   if (*aInstancePtr)
     return rv;
 
   if (aIID.Equals(NS_GET_IID(nsIAccessibleTable)) && IsMulticolumn()) {
     *aInstancePtr = static_cast<nsIAccessibleTable*>(this);
     NS_ADDREF_THIS();
     return NS_OK;
   }
--- a/accessible/src/xul/nsXULListboxAccessible.h
+++ b/accessible/src/xul/nsXULListboxAccessible.h
@@ -40,16 +40,17 @@
 #ifndef __nsXULListboxAccessible_h__
 #define __nsXULListboxAccessible_h__
 
 #include "nsIAccessibleTable.h"
 
 #include "nsCOMPtr.h"
 #include "nsXULMenuAccessible.h"
 #include "nsBaseWidgetAccessible.h"
+#include "XULSelectControlAccessible.h"
 
 class nsIWeakReference;
 
 /**
  * nsXULColumnsAccessible are accessible for list and tree columns elements
  * (xul:treecols and xul:listcols).
  */
 class nsXULColumnsAccessible : public nsAccessibleWrap
@@ -83,17 +84,17 @@ public:
   virtual PRUint8 ActionCount();
 
   enum { eAction_Click = 0 };
 };
 
 /*
  * A class the represents the XUL Listbox widget.
  */
-class nsXULListboxAccessible : public nsXULSelectableAccessible,
+class nsXULListboxAccessible : public XULSelectControlAccessible,
                                public nsIAccessibleTable
 {
 public:
   nsXULListboxAccessible(nsIContent *aContent, nsIWeakReference *aShell);
   virtual ~nsXULListboxAccessible() {}
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLETABLE
--- a/accessible/src/xul/nsXULMenuAccessible.cpp
+++ b/accessible/src/xul/nsXULMenuAccessible.cpp
@@ -62,269 +62,16 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULSelectableAccessible
-////////////////////////////////////////////////////////////////////////////////
-
-nsXULSelectableAccessible::
-  nsXULSelectableAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
-  nsAccessibleWrap(aContent, aShell)
-{
-  mSelectControl = do_QueryInterface(aContent);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// nsXULSelectableAccessible: nsAccessNode
-
-void
-nsXULSelectableAccessible::Shutdown()
-{
-  mSelectControl = nsnull;
-  nsAccessibleWrap::Shutdown();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// nsXULSelectableAccessible: SelectAccessible
-
-bool
-nsXULSelectableAccessible::IsSelect()
-{
-  return !!mSelectControl;
-}
-
-// Interface methods
-already_AddRefed<nsIArray>
-nsXULSelectableAccessible::SelectedItems()
-{
-  nsCOMPtr<nsIMutableArray> selectedItems =
-    do_CreateInstance(NS_ARRAY_CONTRACTID);
-  if (!selectedItems)
-    return nsnull;
-
-  // For XUL multi-select control
-  nsCOMPtr<nsIDOMXULMultiSelectControlElement> xulMultiSelect =
-    do_QueryInterface(mSelectControl);
-  if (xulMultiSelect) {
-    PRInt32 length = 0;
-    xulMultiSelect->GetSelectedCount(&length);
-    for (PRInt32 index = 0; index < length; index++) {
-      nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm;
-      xulMultiSelect->GetSelectedItem(index, getter_AddRefs(itemElm));
-      nsCOMPtr<nsINode> itemNode(do_QueryInterface(itemElm));
-      nsAccessible* item =
-        GetAccService()->GetAccessibleInWeakShell(itemNode, mWeakShell);
-      if (item)
-        selectedItems->AppendElement(static_cast<nsIAccessible*>(item),
-                                     false);
-    }
-  }
-  else {  // Single select?
-    nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm;
-    mSelectControl->GetSelectedItem(getter_AddRefs(itemElm));
-    nsCOMPtr<nsINode> itemNode(do_QueryInterface(itemElm));
-    if(itemNode) {
-      nsAccessible* item =
-        GetAccService()->GetAccessibleInWeakShell(itemNode, mWeakShell);
-      if (item)
-        selectedItems->AppendElement(static_cast<nsIAccessible*>(item),
-                                     false);
-    }
-  }
-
-  nsIMutableArray* items = nsnull;
-  selectedItems.forget(&items);
-  return items;
-}
-
-nsAccessible*
-nsXULSelectableAccessible::GetSelectedItem(PRUint32 aIndex)
-{
-  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-    do_QueryInterface(mSelectControl);
-
-  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm;
-  if (multiSelectControl)
-    multiSelectControl->GetSelectedItem(aIndex, getter_AddRefs(itemElm));
-  else if (aIndex == 0)
-    mSelectControl->GetSelectedItem(getter_AddRefs(itemElm));
-
-  nsCOMPtr<nsINode> itemNode(do_QueryInterface(itemElm));
-  return itemNode ?
-    GetAccService()->GetAccessibleInWeakShell(itemNode, mWeakShell) : nsnull;
-}
-
-PRUint32
-nsXULSelectableAccessible::SelectedItemCount()
-{
-  // For XUL multi-select control
-  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-    do_QueryInterface(mSelectControl);
-  if (multiSelectControl) {
-    PRInt32 count = 0;
-    multiSelectControl->GetSelectedCount(&count);
-    return count;
-  }
-
-  // For XUL single-select control/menulist
-  PRInt32 index;
-  mSelectControl->GetSelectedIndex(&index);
-  return (index >= 0) ? 1 : 0;
-}
-
-bool
-nsXULSelectableAccessible::AddItemToSelection(PRUint32 aIndex)
-{
-  nsAccessible* item = GetChildAt(aIndex);
-  if (!item)
-    return false;
-
-  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
-    do_QueryInterface(item->GetContent());
-  if (!itemElm)
-    return false;
-
-  bool isItemSelected = false;
-  itemElm->GetSelected(&isItemSelected);
-  if (isItemSelected)
-    return true;
-
-  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-    do_QueryInterface(mSelectControl);
-
-  if (multiSelectControl)
-    multiSelectControl->AddItemToSelection(itemElm);
-  else
-    mSelectControl->SetSelectedItem(itemElm);
-
-  return true;
-}
-
-bool
-nsXULSelectableAccessible::RemoveItemFromSelection(PRUint32 aIndex)
-{
-  nsAccessible* item = GetChildAt(aIndex);
-  if (!item)
-    return false;
-
-  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
-      do_QueryInterface(item->GetContent());
-  if (!itemElm)
-    return false;
-
-  bool isItemSelected = false;
-  itemElm->GetSelected(&isItemSelected);
-  if (!isItemSelected)
-    return true;
-
-  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-    do_QueryInterface(mSelectControl);
-
-  if (multiSelectControl)
-    multiSelectControl->RemoveItemFromSelection(itemElm);
-  else
-    mSelectControl->SetSelectedItem(nsnull);
-
-  return true;
-}
-
-bool
-nsXULSelectableAccessible::IsItemSelected(PRUint32 aIndex)
-{
-  nsAccessible* item = GetChildAt(aIndex);
-  if (!item)
-    return false;
-
-  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
-    do_QueryInterface(item->GetContent());
-  if (!itemElm)
-    return false;
-
-  bool isItemSelected = false;
-  itemElm->GetSelected(&isItemSelected);
-  return isItemSelected;
-}
-
-bool
-nsXULSelectableAccessible::UnselectAll()
-{
-  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-    do_QueryInterface(mSelectControl);
-  multiSelectControl ?
-    multiSelectControl->ClearSelection() : mSelectControl->SetSelectedIndex(-1);
-
-  return true;
-}
-
-bool
-nsXULSelectableAccessible::SelectAll()
-{
-  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-    do_QueryInterface(mSelectControl);
-  if (multiSelectControl) {
-    multiSelectControl->SelectAll();
-    return true;
-  }
-
-  // otherwise, don't support this method
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// nsXULSelectableAccessible: Widgets
-
-nsAccessible*
-nsXULSelectableAccessible::CurrentItem()
-{
-  if (!mSelectControl)
-    return nsnull;
-
-  nsCOMPtr<nsIDOMXULSelectControlItemElement> currentItemElm;
-  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-    do_QueryInterface(mSelectControl);
-  if (multiSelectControl)
-    multiSelectControl->GetCurrentItem(getter_AddRefs(currentItemElm));
-  else
-    mSelectControl->GetSelectedItem(getter_AddRefs(currentItemElm));
-
-  nsCOMPtr<nsINode> DOMNode;
-  if (currentItemElm)
-    DOMNode = do_QueryInterface(currentItemElm);
-
-  if (DOMNode) {
-    nsDocAccessible* document = GetDocAccessible();
-    if (document)
-      return document->GetAccessible(DOMNode);
-  }
-
-  return nsnull;
-}
-
-void
-nsXULSelectableAccessible::SetCurrentItem(nsAccessible* aItem)
-{
-  if (!mSelectControl)
-    return;
-
-  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
-    do_QueryInterface(aItem->GetContent());
-  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
-    do_QueryInterface(mSelectControl);
-  if (multiSelectControl)
-    multiSelectControl->SetCurrentItem(itemElm);
-  else
-    mSelectControl->SetSelectedItem(itemElm);
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // nsXULMenuitemAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULMenuitemAccessible::
   nsXULMenuitemAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsAccessibleWrap(aContent, aShell)
 {
 }
@@ -703,17 +450,17 @@ nsXULMenuSeparatorAccessible::ActionCoun
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULMenupopupAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULMenupopupAccessible::
   nsXULMenupopupAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
-  nsXULSelectableAccessible(aContent, aShell)
+  XULSelectControlAccessible(aContent, aShell)
 {
   nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(GetFrame());
   if (menuPopupFrame && menuPopupFrame->IsMenu())
     mFlags |= eMenuPopupAccessible;
 
   // May be the anonymous <menupopup> inside <menulist> (a combobox)
   mSelectControl = do_QueryInterface(mContent->GetParent());
 }
--- a/accessible/src/xul/nsXULMenuAccessible.h
+++ b/accessible/src/xul/nsXULMenuAccessible.h
@@ -36,49 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsXULMenuAccessible_H_
 #define _nsXULMenuAccessible_H_
 
 #include "nsAccessibleWrap.h"
 #include "nsIDOMXULSelectCntrlEl.h"
-
-/**
- * The basic implementation of SelectAccessible for XUL select controls.
- */
-class nsXULSelectableAccessible : public nsAccessibleWrap
-{
-public:
-  nsXULSelectableAccessible(nsIContent *aContent, nsIWeakReference *aShell);
-  virtual ~nsXULSelectableAccessible() {}
-
-  // nsAccessNode
-  virtual void Shutdown();
-
-  // SelectAccessible
-  virtual bool IsSelect();
-  virtual already_AddRefed<nsIArray> SelectedItems();
-  virtual PRUint32 SelectedItemCount();
-  virtual nsAccessible* GetSelectedItem(PRUint32 aIndex);
-  virtual bool IsItemSelected(PRUint32 aIndex);
-  virtual bool AddItemToSelection(PRUint32 aIndex);
-  virtual bool RemoveItemFromSelection(PRUint32 aIndex);
-  virtual bool SelectAll();
-  virtual bool UnselectAll();
-
-  // Widgets
-  virtual nsAccessible* CurrentItem();
-  virtual void SetCurrentItem(nsAccessible* aItem);
-
-protected:
-  // nsIDOMXULMultiSelectControlElement inherits from this, so we'll always have
-  // one of these if the widget is valid and not defunct
-  nsCOMPtr<nsIDOMXULSelectControlElement> mSelectControl;
-};
+#include "XULSelectControlAccessible.h"
 
 /**
  * Used for XUL menu, menuitem elements.
  */
 class nsXULMenuitemAccessible : public nsAccessibleWrap
 {
 public:
   enum { eAction_Click = 0 };
@@ -131,17 +99,17 @@ public:
   // ActionAccessible
   virtual PRUint8 ActionCount();
 };
 
 
 /**
  * Used for XUL menupopup and panel.
  */
-class nsXULMenupopupAccessible : public nsXULSelectableAccessible
+class nsXULMenupopupAccessible : public XULSelectControlAccessible
 {
 public:
   nsXULMenupopupAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
   // nsAccessible
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
@@ -169,9 +137,9 @@ public:
 
   // Widget
   virtual bool IsActiveWidget() const;
   virtual bool AreItemsOperable() const;
   virtual nsAccessible* CurrentItem();
   virtual void SetCurrentItem(nsAccessible* aItem);
 };
 
-#endif  
+#endif
--- a/accessible/src/xul/nsXULTabAccessible.cpp
+++ b/accessible/src/xul/nsXULTabAccessible.cpp
@@ -174,17 +174,17 @@ nsXULTabAccessible::GetPositionAndSizeIn
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTabsAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULTabsAccessible::
   nsXULTabsAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
-  nsXULSelectableAccessible(aContent, aShell)
+  XULSelectControlAccessible(aContent, aShell)
 {
 }
 
 role
 nsXULTabsAccessible::NativeRole()
 {
   return roles::PAGETABLIST;
 }
--- a/accessible/src/xul/nsXULTabAccessible.h
+++ b/accessible/src/xul/nsXULTabAccessible.h
@@ -37,16 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsXULTabAccessible_H_
 #define _nsXULTabAccessible_H_
 
 // NOTE: alphabetically ordered
 #include "nsBaseWidgetAccessible.h"
 #include "nsXULMenuAccessible.h"
+#include "XULSelectControlAccessible.h"
 
 /**
  * An individual tab, xul:tab element.
  */
 class nsXULTabAccessible : public nsAccessibleWrap
 {
 public:
   enum { eAction_Switch = 0 };
@@ -67,17 +68,17 @@ public:
   // ActionAccessible
   virtual PRUint8 ActionCount();
 };
 
 
 /**
  * A container of tab objects, xul:tabs element.
  */
-class nsXULTabsAccessible : public nsXULSelectableAccessible
+class nsXULTabsAccessible : public XULSelectControlAccessible
 {
 public:
   nsXULTabsAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
   // nsIAccessible
   NS_IMETHOD GetValue(nsAString& _retval);
 
   // nsAccessible