1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ApplicationAccessibleWrap.h"
10 #include "nsAccessibilityService.h"
13 #include "atk/atkobject.h"
15 using namespace mozilla
;
16 using namespace mozilla::a11y
;
18 // ApplicationAccessibleWrap
20 ApplicationAccessibleWrap::ApplicationAccessibleWrap() = default;
22 ApplicationAccessibleWrap::~ApplicationAccessibleWrap() {
23 AccessibleWrap::ShutdownAtkObject();
26 gboolean
toplevel_event_watcher(GSignalInvocationHint
* ihint
,
28 const GValue
* param_values
, gpointer data
) {
29 static GQuark sQuark_gecko_acc_obj
= 0;
31 if (!sQuark_gecko_acc_obj
) {
32 sQuark_gecko_acc_obj
= g_quark_from_static_string("GeckoAccObj");
35 if (nsAccessibilityService::IsShutdown()) return TRUE
;
38 reinterpret_cast<GObject
*>(g_value_get_object(param_values
));
39 if (!GTK_IS_WINDOW(object
)) return TRUE
;
41 AtkObject
* child
= gtk_widget_get_accessible(GTK_WIDGET(object
));
42 AtkRole role
= atk_object_get_role(child
);
45 if (!IS_MAI_OBJECT(child
) &&
46 (role
== ATK_ROLE_DIALOG
|| role
== ATK_ROLE_FILE_CHOOSER
||
47 role
== ATK_ROLE_COLOR_CHOOSER
|| role
== ATK_ROLE_FONT_CHOOSER
)) {
48 if (data
== reinterpret_cast<gpointer
>(nsIAccessibleEvent::EVENT_SHOW
)) {
49 // Attach the dialog accessible to app accessible tree
50 LocalAccessible
* windowAcc
=
51 GetAccService()->AddNativeRootAccessible(child
);
52 g_object_set_qdata(G_OBJECT(child
), sQuark_gecko_acc_obj
,
53 reinterpret_cast<gpointer
>(windowAcc
));
56 // Deattach the dialog accessible
57 LocalAccessible
* windowAcc
= reinterpret_cast<LocalAccessible
*>(
58 g_object_get_qdata(G_OBJECT(child
), sQuark_gecko_acc_obj
));
60 GetAccService()->RemoveNativeRootAccessible(windowAcc
);
61 g_object_set_qdata(G_OBJECT(child
), sQuark_gecko_acc_obj
, nullptr);
69 ENameValueFlag
ApplicationAccessibleWrap::Name(nsString
& aName
) const {
70 // ATK doesn't provide a way to obtain an application name (for example,
71 // Firefox or Thunderbird) like IA2 does. Thus let's return an application
72 // name as accessible name that was used to get a branding name (for example,
73 // Minefield aka nightly Firefox or Daily aka nightly Thunderbird).
78 void ApplicationAccessibleWrap::GetNativeInterface(void** aOutAccessible
) {
79 *aOutAccessible
= nullptr;
82 mAtkObject
= reinterpret_cast<AtkObject
*>(
83 g_object_new(MAI_TYPE_ATK_OBJECT
, nullptr));
84 if (!mAtkObject
) return;
86 atk_object_initialize(mAtkObject
, static_cast<Accessible
*>(this));
87 mAtkObject
->role
= ATK_ROLE_INVALID
;
88 mAtkObject
->layer
= ATK_LAYER_INVALID
;
91 *aOutAccessible
= mAtkObject
;
94 struct AtkRootAccessibleAddedEvent
{
95 AtkObject
* app_accessible
;
96 AtkObject
* root_accessible
;
100 gboolean
fireRootAccessibleAddedCB(gpointer data
) {
101 AtkRootAccessibleAddedEvent
* eventData
= (AtkRootAccessibleAddedEvent
*)data
;
102 g_signal_emit_by_name(eventData
->app_accessible
, "children_changed::add",
103 eventData
->index
, eventData
->root_accessible
, nullptr);
104 g_object_unref(eventData
->app_accessible
);
105 g_object_unref(eventData
->root_accessible
);
111 bool ApplicationAccessibleWrap::InsertChildAt(uint32_t aIdx
,
112 LocalAccessible
* aChild
) {
113 if (!ApplicationAccessible::InsertChildAt(aIdx
, aChild
)) return false;
115 AtkObject
* atkAccessible
= AccessibleWrap::GetAtkObject(aChild
);
116 atk_object_set_parent(atkAccessible
, mAtkObject
);
118 uint32_t count
= mChildren
.Length();
120 // Emit children_changed::add in a timeout
121 // to make sure aRootAccWrap is fully initialized.
122 AtkRootAccessibleAddedEvent
* eventData
=
123 (AtkRootAccessibleAddedEvent
*)malloc(sizeof(AtkRootAccessibleAddedEvent
));
125 eventData
->app_accessible
= mAtkObject
;
126 eventData
->root_accessible
= atkAccessible
;
127 eventData
->index
= count
- 1;
128 g_object_ref(mAtkObject
);
129 g_object_ref(atkAccessible
);
130 g_timeout_add(0, fireRootAccessibleAddedCB
, eventData
);
136 bool ApplicationAccessibleWrap::RemoveChild(LocalAccessible
* aChild
) {
137 int32_t index
= aChild
->IndexInParent();
139 AtkObject
* atkAccessible
= AccessibleWrap::GetAtkObject(aChild
);
140 atk_object_set_parent(atkAccessible
, nullptr);
141 g_signal_emit_by_name(mAtkObject
, "children_changed::remove", index
,
142 atkAccessible
, nullptr);
144 return ApplicationAccessible::RemoveChild(aChild
);