2011-04-27 17:42:27 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2011-05-28 02:37:24 +04:00
|
|
|
/* vim: set ts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2003-04-23 09:28:41 +04:00
|
|
|
|
2012-04-25 15:29:40 +04:00
|
|
|
#include "ApplicationAccessibleWrap.h"
|
2009-08-21 16:33:31 +04:00
|
|
|
|
2003-04-23 09:28:41 +04:00
|
|
|
#include "nsCOMPtr.h"
|
2003-05-06 06:23:50 +04:00
|
|
|
#include "nsMai.h"
|
2009-08-11 11:03:01 +04:00
|
|
|
#include "nsAccessibilityService.h"
|
2003-04-23 09:28:41 +04:00
|
|
|
|
2003-05-16 05:41:46 +04:00
|
|
|
#include <gtk/gtk.h>
|
2003-04-23 09:28:41 +04:00
|
|
|
#include <atk/atk.h>
|
|
|
|
|
2011-11-26 23:48:55 +04:00
|
|
|
using namespace mozilla;
|
2012-01-05 05:54:17 +04:00
|
|
|
using namespace mozilla::a11y;
|
2011-11-26 23:48:55 +04:00
|
|
|
|
2012-04-25 15:29:40 +04:00
|
|
|
// ApplicationAccessibleWrap
|
2007-06-02 07:01:38 +04:00
|
|
|
|
2012-04-25 15:29:40 +04:00
|
|
|
ApplicationAccessibleWrap::ApplicationAccessibleWrap()
|
|
|
|
: ApplicationAccessible() {}
|
2003-04-23 09:28:41 +04:00
|
|
|
|
2012-04-25 15:29:40 +04:00
|
|
|
ApplicationAccessibleWrap::~ApplicationAccessibleWrap() {
|
2012-05-29 05:18:45 +04:00
|
|
|
AccessibleWrap::ShutdownAtkObject();
|
2003-04-23 09:28:41 +04:00
|
|
|
}
|
|
|
|
|
2011-07-14 05:58:32 +04:00
|
|
|
gboolean toplevel_event_watcher(GSignalInvocationHint* ihint,
|
|
|
|
guint n_param_values,
|
|
|
|
const GValue* param_values, gpointer data) {
|
2011-07-22 01:31:36 +04:00
|
|
|
static GQuark sQuark_gecko_acc_obj = 0;
|
|
|
|
|
|
|
|
if (!sQuark_gecko_acc_obj)
|
|
|
|
sQuark_gecko_acc_obj = g_quark_from_static_string("GeckoAccObj");
|
|
|
|
|
2011-07-14 05:58:32 +04:00
|
|
|
if (nsAccessibilityService::IsShutdown()) return TRUE;
|
|
|
|
|
|
|
|
GObject* object =
|
|
|
|
reinterpret_cast<GObject*>(g_value_get_object(param_values));
|
|
|
|
if (!GTK_IS_WINDOW(object)) return TRUE;
|
|
|
|
|
|
|
|
AtkObject* child = gtk_widget_get_accessible(GTK_WIDGET(object));
|
2019-04-05 01:50:21 +03:00
|
|
|
AtkRole role = atk_object_get_role(child);
|
2011-07-14 05:58:32 +04:00
|
|
|
|
|
|
|
// GTK native dialog
|
|
|
|
if (!IS_MAI_OBJECT(child) &&
|
2019-04-05 01:50:21 +03:00
|
|
|
(role == ATK_ROLE_DIALOG || role == ATK_ROLE_FILE_CHOOSER ||
|
|
|
|
role == ATK_ROLE_COLOR_CHOOSER || role == ATK_ROLE_FONT_CHOOSER)) {
|
2011-07-14 05:58:32 +04:00
|
|
|
if (data == reinterpret_cast<gpointer>(nsIAccessibleEvent::EVENT_SHOW)) {
|
|
|
|
// Attach the dialog accessible to app accessible tree
|
2012-05-29 05:18:45 +04:00
|
|
|
Accessible* windowAcc = GetAccService()->AddNativeRootAccessible(child);
|
2011-07-14 05:58:32 +04:00
|
|
|
g_object_set_qdata(G_OBJECT(child), sQuark_gecko_acc_obj,
|
|
|
|
reinterpret_cast<gpointer>(windowAcc));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// Deattach the dialog accessible
|
2012-05-29 05:18:45 +04:00
|
|
|
Accessible* windowAcc = reinterpret_cast<Accessible*>(
|
2011-07-14 05:58:32 +04:00
|
|
|
g_object_get_qdata(G_OBJECT(child), sQuark_gecko_acc_obj));
|
|
|
|
if (windowAcc) {
|
|
|
|
GetAccService()->RemoveNativeRootAccessible(windowAcc);
|
2013-04-03 04:33:43 +04:00
|
|
|
g_object_set_qdata(G_OBJECT(child), sQuark_gecko_acc_obj, nullptr);
|
2011-07-14 05:58:32 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-05-15 19:13:02 +03:00
|
|
|
ENameValueFlag ApplicationAccessibleWrap::Name(nsString& aName) const {
|
2012-03-06 14:01:55 +04:00
|
|
|
// ATK doesn't provide a way to obtain an application name (for example,
|
|
|
|
// Firefox or Thunderbird) like IA2 does. Thus let's return an application
|
|
|
|
// name as accessible name that was used to get a branding name (for example,
|
|
|
|
// Minefield aka nightly Firefox or Daily aka nightly Thunderbird).
|
2014-09-23 16:23:02 +04:00
|
|
|
AppName(aName);
|
2012-05-01 07:08:31 +04:00
|
|
|
return eNameOK;
|
2012-03-06 14:01:55 +04:00
|
|
|
}
|
|
|
|
|
2012-04-25 15:29:40 +04:00
|
|
|
void ApplicationAccessibleWrap::GetNativeInterface(void** aOutAccessible) {
|
2014-10-22 04:49:28 +04:00
|
|
|
*aOutAccessible = nullptr;
|
2003-05-21 07:32:55 +04:00
|
|
|
|
2014-10-22 04:49:28 +04:00
|
|
|
if (!mAtkObject) {
|
|
|
|
mAtkObject = reinterpret_cast<AtkObject*>(
|
|
|
|
g_object_new(MAI_TYPE_ATK_OBJECT, nullptr));
|
|
|
|
if (!mAtkObject) return;
|
2003-05-06 06:23:50 +04:00
|
|
|
|
2014-10-22 04:49:28 +04:00
|
|
|
atk_object_initialize(mAtkObject, this);
|
|
|
|
mAtkObject->role = ATK_ROLE_INVALID;
|
|
|
|
mAtkObject->layer = ATK_LAYER_INVALID;
|
|
|
|
}
|
2003-05-06 06:23:50 +04:00
|
|
|
|
2014-10-22 04:49:28 +04:00
|
|
|
*aOutAccessible = mAtkObject;
|
2003-05-06 06:23:50 +04:00
|
|
|
}
|
|
|
|
|
2010-01-06 09:56:56 +03:00
|
|
|
struct AtkRootAccessibleAddedEvent {
|
|
|
|
AtkObject* app_accessible;
|
|
|
|
AtkObject* root_accessible;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t index;
|
2010-01-06 09:56:56 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
gboolean fireRootAccessibleAddedCB(gpointer data) {
|
|
|
|
AtkRootAccessibleAddedEvent* eventData = (AtkRootAccessibleAddedEvent*)data;
|
|
|
|
g_signal_emit_by_name(eventData->app_accessible, "children_changed::add",
|
2013-04-03 04:33:43 +04:00
|
|
|
eventData->index, eventData->root_accessible, nullptr);
|
2010-01-06 09:56:56 +03:00
|
|
|
g_object_unref(eventData->app_accessible);
|
|
|
|
g_object_unref(eventData->root_accessible);
|
|
|
|
free(data);
|
2011-07-14 05:58:32 +04:00
|
|
|
|
2010-01-06 09:56:56 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2013-03-14 08:53:28 +04:00
|
|
|
bool ApplicationAccessibleWrap::InsertChildAt(uint32_t aIdx,
|
|
|
|
Accessible* aChild) {
|
|
|
|
if (!ApplicationAccessible::InsertChildAt(aIdx, aChild)) return false;
|
2003-04-23 09:28:41 +04:00
|
|
|
|
2012-05-29 05:18:45 +04:00
|
|
|
AtkObject* atkAccessible = AccessibleWrap::GetAtkObject(aChild);
|
|
|
|
atk_object_set_parent(atkAccessible, mAtkObject);
|
2007-06-08 13:09:24 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mChildren.Length();
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2010-01-06 09:56:56 +03:00
|
|
|
// Emit children_changed::add in a timeout
|
|
|
|
// to make sure aRootAccWrap is fully initialized.
|
|
|
|
AtkRootAccessibleAddedEvent* eventData =
|
|
|
|
(AtkRootAccessibleAddedEvent*)malloc(sizeof(AtkRootAccessibleAddedEvent));
|
|
|
|
if (eventData) {
|
|
|
|
eventData->app_accessible = mAtkObject;
|
|
|
|
eventData->root_accessible = atkAccessible;
|
|
|
|
eventData->index = count - 1;
|
|
|
|
g_object_ref(mAtkObject);
|
|
|
|
g_object_ref(atkAccessible);
|
|
|
|
g_timeout_add(0, fireRootAccessibleAddedCB, eventData);
|
2003-04-23 09:28:41 +04:00
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2003-04-23 09:28:41 +04:00
|
|
|
}
|
|
|
|
|
2012-05-29 05:18:45 +04:00
|
|
|
bool ApplicationAccessibleWrap::RemoveChild(Accessible* aChild) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t index = aChild->IndexInParent();
|
2003-05-06 06:23:50 +04:00
|
|
|
|
2012-05-29 05:18:45 +04:00
|
|
|
AtkObject* atkAccessible = AccessibleWrap::GetAtkObject(aChild);
|
2013-04-03 04:33:43 +04:00
|
|
|
atk_object_set_parent(atkAccessible, nullptr);
|
2012-05-29 05:18:45 +04:00
|
|
|
g_signal_emit_by_name(mAtkObject, "children_changed::remove", index,
|
2013-04-03 04:33:43 +04:00
|
|
|
atkAccessible, nullptr);
|
2006-08-30 09:19:06 +04:00
|
|
|
|
2012-05-29 05:18:45 +04:00
|
|
|
return ApplicationAccessible::RemoveChild(aChild);
|
2003-04-23 09:28:41 +04:00
|
|
|
}
|