Bug 1735097 - Geolocation: use EpochTimeStamp instead of DOMTimeStamp r=saschanaz...
[gecko.git] / accessible / atk / ApplicationAccessibleWrap.cpp
blob219e41c296b5e41c27ba079c7dc8cd5657425d5b
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"
9 #include "nsCOMPtr.h"
10 #include "nsMai.h"
11 #include "nsAccessibilityService.h"
13 #include <gtk/gtk.h>
14 #include <atk/atk.h>
16 using namespace mozilla;
17 using namespace mozilla::a11y;
19 // ApplicationAccessibleWrap
21 ApplicationAccessibleWrap::ApplicationAccessibleWrap()
22 : ApplicationAccessible() {}
24 ApplicationAccessibleWrap::~ApplicationAccessibleWrap() {
25 AccessibleWrap::ShutdownAtkObject();
28 gboolean toplevel_event_watcher(GSignalInvocationHint* ihint,
29 guint n_param_values,
30 const GValue* param_values, gpointer data) {
31 static GQuark sQuark_gecko_acc_obj = 0;
33 if (!sQuark_gecko_acc_obj) {
34 sQuark_gecko_acc_obj = g_quark_from_static_string("GeckoAccObj");
37 if (nsAccessibilityService::IsShutdown()) return TRUE;
39 GObject* object =
40 reinterpret_cast<GObject*>(g_value_get_object(param_values));
41 if (!GTK_IS_WINDOW(object)) return TRUE;
43 AtkObject* child = gtk_widget_get_accessible(GTK_WIDGET(object));
44 AtkRole role = atk_object_get_role(child);
46 // GTK native dialog
47 if (!IS_MAI_OBJECT(child) &&
48 (role == ATK_ROLE_DIALOG || role == ATK_ROLE_FILE_CHOOSER ||
49 role == ATK_ROLE_COLOR_CHOOSER || role == ATK_ROLE_FONT_CHOOSER)) {
50 if (data == reinterpret_cast<gpointer>(nsIAccessibleEvent::EVENT_SHOW)) {
51 // Attach the dialog accessible to app accessible tree
52 LocalAccessible* windowAcc =
53 GetAccService()->AddNativeRootAccessible(child);
54 g_object_set_qdata(G_OBJECT(child), sQuark_gecko_acc_obj,
55 reinterpret_cast<gpointer>(windowAcc));
57 } else {
58 // Deattach the dialog accessible
59 LocalAccessible* windowAcc = reinterpret_cast<LocalAccessible*>(
60 g_object_get_qdata(G_OBJECT(child), sQuark_gecko_acc_obj));
61 if (windowAcc) {
62 GetAccService()->RemoveNativeRootAccessible(windowAcc);
63 g_object_set_qdata(G_OBJECT(child), sQuark_gecko_acc_obj, nullptr);
68 return TRUE;
71 ENameValueFlag ApplicationAccessibleWrap::Name(nsString& aName) const {
72 // ATK doesn't provide a way to obtain an application name (for example,
73 // Firefox or Thunderbird) like IA2 does. Thus let's return an application
74 // name as accessible name that was used to get a branding name (for example,
75 // Minefield aka nightly Firefox or Daily aka nightly Thunderbird).
76 AppName(aName);
77 return eNameOK;
80 void ApplicationAccessibleWrap::GetNativeInterface(void** aOutAccessible) {
81 *aOutAccessible = nullptr;
83 if (!mAtkObject) {
84 mAtkObject = reinterpret_cast<AtkObject*>(
85 g_object_new(MAI_TYPE_ATK_OBJECT, nullptr));
86 if (!mAtkObject) return;
88 atk_object_initialize(mAtkObject, static_cast<Accessible*>(this));
89 mAtkObject->role = ATK_ROLE_INVALID;
90 mAtkObject->layer = ATK_LAYER_INVALID;
93 *aOutAccessible = mAtkObject;
96 struct AtkRootAccessibleAddedEvent {
97 AtkObject* app_accessible;
98 AtkObject* root_accessible;
99 uint32_t index;
102 gboolean fireRootAccessibleAddedCB(gpointer data) {
103 AtkRootAccessibleAddedEvent* eventData = (AtkRootAccessibleAddedEvent*)data;
104 g_signal_emit_by_name(eventData->app_accessible, "children_changed::add",
105 eventData->index, eventData->root_accessible, nullptr);
106 g_object_unref(eventData->app_accessible);
107 g_object_unref(eventData->root_accessible);
108 free(data);
110 return FALSE;
113 bool ApplicationAccessibleWrap::InsertChildAt(uint32_t aIdx,
114 LocalAccessible* aChild) {
115 if (!ApplicationAccessible::InsertChildAt(aIdx, aChild)) return false;
117 AtkObject* atkAccessible = AccessibleWrap::GetAtkObject(aChild);
118 atk_object_set_parent(atkAccessible, mAtkObject);
120 uint32_t count = mChildren.Length();
122 // Emit children_changed::add in a timeout
123 // to make sure aRootAccWrap is fully initialized.
124 AtkRootAccessibleAddedEvent* eventData =
125 (AtkRootAccessibleAddedEvent*)malloc(sizeof(AtkRootAccessibleAddedEvent));
126 if (eventData) {
127 eventData->app_accessible = mAtkObject;
128 eventData->root_accessible = atkAccessible;
129 eventData->index = count - 1;
130 g_object_ref(mAtkObject);
131 g_object_ref(atkAccessible);
132 g_timeout_add(0, fireRootAccessibleAddedCB, eventData);
135 return true;
138 bool ApplicationAccessibleWrap::RemoveChild(LocalAccessible* aChild) {
139 int32_t index = aChild->IndexInParent();
141 AtkObject* atkAccessible = AccessibleWrap::GetAtkObject(aChild);
142 atk_object_set_parent(atkAccessible, nullptr);
143 g_signal_emit_by_name(mAtkObject, "children_changed::remove", index,
144 atkAccessible, nullptr);
146 return ApplicationAccessible::RemoveChild(aChild);