1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* vim:expandtab:shiftwidth=4:tabstop=4:
4
/* ***** BEGIN LICENSE BLOCK *****
5
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
8
* The contents of this file are subject to the Mozilla Public
9
* License Version 1.1 (the "License"); you may not use this file
10
* except in compliance with the License. You may obtain a copy of
11
* the License at http://www.mozilla.org/MPL/
13
* Software distributed under the License is distributed on an "AS
14
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
15
* implied. See the License for the specific language governing
16
* rights and limitations under the License.
18
* The Original Code is mozilla.org code.
20
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
21
* Portions created by Sun Microsystems are Copyright (C) 2002 Sun
22
* Microsystems, Inc. All Rights Reserved.
24
* Original Author: Bolian Yin (bolian.yin@sun.com)
28
* Alternatively, the contents of this file may be used under the terms of
29
* either the GNU General Public License Version 2 or later (the "GPL"), or
30
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31
* in which case the provisions of the GPL or the LGPL are applicable instead
32
* of those above. If you wish to allow use of your version of this file only
33
* under the terms of either the GPL or the LGPL, and not to allow others to
34
* use your version of this file under the terms of the NPL, indicate your
35
* decision by deleting the provisions above and replace them with the notice
36
* and other provisions required by the GPL or the LGPL. If you do not delete
37
* the provisions above, a recipient may use your version of this file under
38
* the terms of any one of the NPL, the GPL or the LGPL.
40
* ***** END LICENSE BLOCK ***** */
42
#include "nsMaiInterfaceAction.h"
43
#include "nsAccessibleWrap.h"
48
static void interfaceInitCB(AtkActionIface *aIface);
49
/* action interface callbacks */
50
static gboolean doActionCB(AtkAction *aAction, gint aActionIndex);
51
static gint getActionCountCB(AtkAction *aAction);
52
static const gchar *getDescriptionCB(AtkAction *aAction, gint aActionIndex);
53
static const gchar *getNameCB(AtkAction *aAction, gint aActionIndex);
54
static const gchar *getKeyBindingCB(AtkAction *aAction, gint aActionIndex);
55
static gboolean setDescriptionCB(AtkAction *aAction, gint aActionIndex,
59
MaiInterfaceAction::MaiInterfaceAction(nsAccessibleWrap *aAccWrap):
60
MaiInterface(aAccWrap)
64
MaiInterfaceAction::~MaiInterfaceAction()
69
MaiInterfaceAction::GetType()
71
return MAI_INTERFACE_ACTION;
74
const GInterfaceInfo *
75
MaiInterfaceAction::GetInterfaceInfo()
77
static const GInterfaceInfo atk_if_action_info = {
78
(GInterfaceInitFunc)interfaceInitCB,
79
(GInterfaceFinalizeFunc) NULL,
82
return &atk_if_action_info;
85
/* static functions */
88
interfaceInitCB(AtkActionIface *aIface)
90
NS_ASSERTION(aIface, "Invalid aIface");
94
aIface->do_action = doActionCB;
95
aIface->get_n_actions = getActionCountCB;
96
aIface->get_description = getDescriptionCB;
97
aIface->get_keybinding = getKeyBindingCB;
98
aIface->get_name = getNameCB;
99
aIface->set_description = setDescriptionCB;
103
doActionCB(AtkAction *aAction, gint aActionIndex)
105
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
106
NS_ENSURE_TRUE(accWrap, FALSE);
108
nsresult rv = accWrap->DoAction(aActionIndex);
109
return (NS_FAILED(rv)) ? FALSE : TRUE;
113
getActionCountCB(AtkAction *aAction)
115
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
116
NS_ENSURE_TRUE(accWrap, 0);
119
nsresult rv = accWrap->GetNumActions(&num);
120
return (NS_FAILED(rv)) ? 0 : NS_STATIC_CAST(gint, num);
124
getDescriptionCB(AtkAction *aAction, gint aActionIndex)
126
// the interface in nsIAccessibleAction is empty
127
// use getName as default description
128
return getNameCB(aAction, aActionIndex);
132
getNameCB(AtkAction *aAction, gint aActionIndex)
134
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
135
NS_ENSURE_TRUE(accWrap, nsnull);
137
MaiInterfaceAction *action =
138
NS_STATIC_CAST(MaiInterfaceAction *,
139
accWrap->GetMaiInterface(MAI_INTERFACE_ACTION));
140
NS_ENSURE_TRUE(action, nsnull);
142
const char *name = action->GetName();
143
if (!name || !*name) {
144
nsAutoString autoStr;
145
nsresult rv = accWrap->GetActionName(aActionIndex, autoStr);
146
NS_ENSURE_SUCCESS(rv, nsnull);
148
action->SetName(autoStr);
149
name = action->GetName();
155
getKeyBindingCB(AtkAction *aAction, gint aActionIndex)
157
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
158
NS_ENSURE_TRUE(accWrap, nsnull);
160
MaiInterfaceAction *action =
161
NS_STATIC_CAST(MaiInterfaceAction *,
162
accWrap->GetMaiInterface(MAI_INTERFACE_ACTION));
163
NS_ENSURE_TRUE(action, nsnull);
165
if (action->GetKeyBinding())
166
return action->GetKeyBinding();
168
//return all KeyBindings including accesskey and shortcut
170
nsAutoString allKeyBinding;
173
nsAutoString accessKey;
174
nsresult rv = accWrap->GetKeyboardShortcut(accessKey);
176
if (NS_SUCCEEDED(rv) && !accessKey.IsEmpty()) {
177
nsCOMPtr<nsIAccessible> parentAccessible;
178
accWrap->GetParent(getter_AddRefs(parentAccessible));
179
if (parentAccessible) {
181
parentAccessible->GetRole(&role);
183
if (role == ATK_ROLE_MENU_BAR) {
184
//it is topmenu, change from "Alt+f" to "f;<Alt>f"
185
nsAutoString rightChar;
186
accessKey.Right(rightChar, 1);
187
allKeyBinding = rightChar + NS_LITERAL_STRING(";<Alt>") +
190
else if ((role == ATK_ROLE_MENU) || (role == ATK_ROLE_MENU_ITEM)) {
191
//it is submenu, change from "s" to "s;<Alt>fs"
192
nsAutoString allKey = accessKey;
193
nsCOMPtr<nsIAccessible> grandParentAcc = parentAccessible;
195
while ((grandParentAcc) && (role != ATK_ROLE_MENU_BAR)) {
196
nsAutoString grandParentKey;
197
grandParentAcc->GetKeyboardShortcut(grandParentKey);
199
if (!grandParentKey.IsEmpty()) {
200
nsAutoString rightChar;
201
grandParentKey.Right(rightChar, 1);
202
allKey = rightChar + allKey;
205
nsCOMPtr<nsIAccessible> tempAcc = grandParentAcc;
206
tempAcc->GetParent(getter_AddRefs(grandParentAcc));
208
grandParentAcc->GetRole(&role);
210
allKeyBinding = accessKey + NS_LITERAL_STRING(";<Alt>") +
215
//default process, rarely happens.
216
nsAutoString rightChar;
217
accessKey.Right(rightChar, 1);
218
allKeyBinding = rightChar + NS_LITERAL_STRING(";<Alt>") + rightChar;
221
else //don't have accesskey
222
allKeyBinding = NS_LITERAL_STRING(";");
225
nsAutoString keyBinding, subShortcut;
226
rv = accWrap->GetKeyBinding(keyBinding);
228
if (NS_SUCCEEDED(rv) && !keyBinding.IsEmpty()) {
229
//change the shortcut from "Ctrl+Shift+L" to "<Control><Shift>L"
230
PRInt32 oldPos, curPos=0;
231
while ((curPos != -1) && (curPos < (PRInt32)keyBinding.Length())) {
233
nsAutoString subString;
234
curPos = keyBinding.FindChar('+', oldPos);
236
keyBinding.Mid(subString, oldPos, keyBinding.Length() - oldPos);
237
subShortcut += subString;
240
keyBinding.Mid(subString, oldPos, curPos - oldPos);
242
//change "Ctrl" to "Control"
243
if (subString.EqualsIgnoreCase("ctrl"))
244
subString = NS_LITERAL_STRING("Control");
246
subShortcut += NS_LITERAL_STRING("<") + subString +
247
NS_LITERAL_STRING(">");
253
allKeyBinding += NS_LITERAL_STRING(";") + subShortcut;
254
action->SetKeyBinding(allKeyBinding);
255
return action->GetKeyBinding();
259
setDescriptionCB(AtkAction *aAction, gint aActionIndex,
262
nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
263
NS_ENSURE_TRUE(accWrap, nsnull);
265
/* this is not supported in nsIAccessible yet */