michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "InterfaceInitFuncs.h" michael@0: michael@0: #include "Accessible-inl.h" michael@0: #include "nsMai.h" michael@0: #include "Role.h" michael@0: #include "mozilla/Likely.h" michael@0: michael@0: #include "nsString.h" michael@0: michael@0: using namespace mozilla::a11y; michael@0: michael@0: extern "C" { michael@0: michael@0: static gboolean michael@0: doActionCB(AtkAction *aAction, gint aActionIndex) michael@0: { michael@0: AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aAction)); michael@0: if (!accWrap) michael@0: return FALSE; michael@0: michael@0: nsresult rv = accWrap->DoAction(aActionIndex); michael@0: return (NS_FAILED(rv)) ? FALSE : TRUE; michael@0: } michael@0: michael@0: static gint michael@0: getActionCountCB(AtkAction *aAction) michael@0: { michael@0: AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aAction)); michael@0: return accWrap ? accWrap->ActionCount() : 0; michael@0: } michael@0: michael@0: static const gchar* michael@0: getActionDescriptionCB(AtkAction *aAction, gint aActionIndex) michael@0: { michael@0: AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aAction)); michael@0: if (!accWrap) michael@0: return nullptr; michael@0: michael@0: nsAutoString description; michael@0: nsresult rv = accWrap->GetActionDescription(aActionIndex, description); michael@0: NS_ENSURE_SUCCESS(rv, nullptr); michael@0: return AccessibleWrap::ReturnString(description); michael@0: } michael@0: michael@0: static const gchar* michael@0: getActionNameCB(AtkAction *aAction, gint aActionIndex) michael@0: { michael@0: AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aAction)); michael@0: if (!accWrap) michael@0: return nullptr; michael@0: michael@0: nsAutoString autoStr; michael@0: nsresult rv = accWrap->GetActionName(aActionIndex, autoStr); michael@0: NS_ENSURE_SUCCESS(rv, nullptr); michael@0: return AccessibleWrap::ReturnString(autoStr); michael@0: } michael@0: michael@0: static const gchar* michael@0: getKeyBindingCB(AtkAction *aAction, gint aActionIndex) michael@0: { michael@0: AccessibleWrap* acc = GetAccessibleWrap(ATK_OBJECT(aAction)); michael@0: if (!acc) michael@0: return nullptr; michael@0: michael@0: // Return all key bindings including access key and keyboard shortcut. michael@0: nsAutoString keyBindingsStr; michael@0: michael@0: // Get access key. michael@0: KeyBinding keyBinding = acc->AccessKey(); michael@0: if (!keyBinding.IsEmpty()) { michael@0: keyBinding.AppendToString(keyBindingsStr, KeyBinding::eAtkFormat); michael@0: michael@0: Accessible* parent = acc->Parent(); michael@0: roles::Role role = parent ? parent->Role() : roles::NOTHING; michael@0: if (role == roles::PARENT_MENUITEM || role == roles::MENUITEM || michael@0: role == roles::RADIO_MENU_ITEM || role == roles::CHECK_MENU_ITEM) { michael@0: // It is submenu, expose keyboard shortcuts from menu hierarchy like michael@0: // "s;f:s" michael@0: nsAutoString keysInHierarchyStr = keyBindingsStr; michael@0: do { michael@0: KeyBinding parentKeyBinding = parent->AccessKey(); michael@0: if (!parentKeyBinding.IsEmpty()) { michael@0: nsAutoString str; michael@0: parentKeyBinding.ToString(str, KeyBinding::eAtkFormat); michael@0: str.Append(':'); michael@0: michael@0: keysInHierarchyStr.Insert(str, 0); michael@0: } michael@0: } while ((parent = parent->Parent()) && parent->Role() != roles::MENUBAR); michael@0: michael@0: keyBindingsStr.Append(';'); michael@0: keyBindingsStr.Append(keysInHierarchyStr); michael@0: } michael@0: } else { michael@0: // No access key, add ';' to point this. michael@0: keyBindingsStr.Append(';'); michael@0: } michael@0: michael@0: // Get keyboard shortcut. michael@0: keyBindingsStr.Append(';'); michael@0: keyBinding = acc->KeyboardShortcut(); michael@0: if (!keyBinding.IsEmpty()) { michael@0: keyBinding.AppendToString(keyBindingsStr, KeyBinding::eAtkFormat); michael@0: } michael@0: michael@0: return AccessibleWrap::ReturnString(keyBindingsStr); michael@0: } michael@0: } michael@0: michael@0: void michael@0: actionInterfaceInitCB(AtkActionIface* aIface) michael@0: { michael@0: NS_ASSERTION(aIface, "Invalid aIface"); michael@0: if (MOZ_UNLIKELY(!aIface)) michael@0: return; michael@0: michael@0: aIface->do_action = doActionCB; michael@0: aIface->get_n_actions = getActionCountCB; michael@0: aIface->get_description = getActionDescriptionCB; michael@0: aIface->get_keybinding = getKeyBindingCB; michael@0: aIface->get_name = getActionNameCB; michael@0: }