From 43431153a6dea7e614e8d984bb3c1e3cd4d3f644 Mon Sep 17 00:00:00 2001 From: Mike Gorse Date: Tue, 20 Dec 2011 09:25:13 -0500 Subject: [PATCH] bug 693343 - a11y disabled on gnome 3 when GNOME_ACCESSIBILITY is unset r=tbsaunde, karlt --- accessible/src/atk/Makefile.in | 4 + .../src/atk/nsApplicationAccessibleWrap.cpp | 155 +++++++++++++++--- accessible/src/base/nsAccessibilityService.h | 15 ++ widget/src/gtk2/nsWindow.cpp | 46 +----- widget/src/gtk2/nsWindow.h | 3 - 5 files changed, 157 insertions(+), 66 deletions(-) diff --git a/accessible/src/atk/Makefile.in b/accessible/src/atk/Makefile.in index 4934fd1e74c..9fe1f48b857 100644 --- a/accessible/src/atk/Makefile.in +++ b/accessible/src/atk/Makefile.in @@ -92,6 +92,10 @@ include $(topsrcdir)/config/rules.mk CFLAGS += $(MOZ_GTK2_CFLAGS) CXXFLAGS += $(MOZ_GTK2_CFLAGS) +ifdef MOZ_ENABLE_DBUS +CXXFLAGS += $(MOZ_DBUS_CFLAGS) +endif + LOCAL_INCLUDES += \ -I$(srcdir) \ -I$(srcdir)/../base \ diff --git a/accessible/src/atk/nsApplicationAccessibleWrap.cpp b/accessible/src/atk/nsApplicationAccessibleWrap.cpp index d415751d07b..2c5520f4493 100644 --- a/accessible/src/atk/nsApplicationAccessibleWrap.cpp +++ b/accessible/src/atk/nsApplicationAccessibleWrap.cpp @@ -52,8 +52,12 @@ #include #include +#ifdef MOZ_ENABLE_DBUS +#include +#endif using namespace mozilla; +using namespace mozilla::a11y; typedef GType (* AtkGetTypeType) (void); GType g_atk_hyperlink_impl_type = G_TYPE_INVALID; @@ -61,10 +65,7 @@ static bool sATKChecked = false; static PRLibrary *sATKLib = nsnull; static const char sATKLibName[] = "libatk-1.0.so.0"; static const char sATKHyperlinkImplGetTypeSymbol[] = - "atk_hyperlink_impl_get_type"; -static const char sAccEnv [] = "GNOME_ACCESSIBILITY"; -static const char sGconfAccessibilityKey[] = - "/desktop/gnome/interface/accessibility"; + "atk_hyperlink_impl_get_type"; /* gail function pointer */ static guint (* gail_add_global_event_listener) (GSignalEmissionHook listener, @@ -614,27 +615,7 @@ toplevel_event_watcher(GSignalInvocationHint* ihint, bool nsApplicationAccessibleWrap::Init() { - // XXX following code is copied from widget/src/gtk2/nsWindow.cpp - // we should put it to somewhere that can be used from both modules - // see bug 390761 - - // check if accessibility enabled/disabled by environment variable - bool isGnomeATEnabled = false; - const char *envValue = PR_GetEnv(sAccEnv); - if (envValue) { - isGnomeATEnabled = !!atoi(envValue); - } else { - //check gconf-2 setting - nsresult rv; - nsCOMPtr gconf = - do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv); - if (NS_SUCCEEDED(rv) && gconf) { - gconf->GetBool(NS_LITERAL_CSTRING(sGconfAccessibilityKey), - &isGnomeATEnabled); - } - } - - if (isGnomeATEnabled) { + if (ShouldA11yBeEnabled()) { // load and initialize gail library nsresult rv = LoadGtkModule(sGail); if (NS_SUCCEEDED(rv)) { @@ -883,3 +864,127 @@ LoadGtkModule(GnomeAccessibilityModule& aModule) } return NS_OK; } + +namespace mozilla { +namespace a11y { + + static const char sAccEnv [] = "GNOME_ACCESSIBILITY"; +#ifdef MOZ_ENABLE_DBUS +static DBusPendingCall *sPendingCall = nsnull; +#endif + +void +PreInit() +{ +#ifdef MOZ_ENABLE_DBUS + static bool sChecked = FALSE; + if (sChecked) + return; + + sChecked = TRUE; + + // dbus is only checked if GNOME_ACCESSIBILITY is unset + if (PR_GetEnv(sAccEnv)) + return; + + DBusConnection* bus = dbus_bus_get(DBUS_BUS_SESSION, nsnull); + if (!bus) + return; + + dbus_connection_set_exit_on_disconnect(bus, FALSE); + + DBusMessage *message; + message = dbus_message_new_method_call("org.a11y.Bus", "/org/a11y/bus", + "org.freedesktop.DBus.Properties", + "Get"); + if (!message) + goto dbus_done; + + static const char* iface = "org.a11y.Status"; + static const char* member = "IsEnabled"; + dbus_message_append_args(message, DBUS_TYPE_STRING, &iface, + DBUS_TYPE_STRING, &member, DBUS_TYPE_INVALID); + dbus_connection_send_with_reply(bus, message, &sPendingCall, 1000); + dbus_message_unref(message); + +dbus_done: + dbus_connection_unref(bus); +#endif +} + +bool +ShouldA11yBeEnabled() +{ + static bool sChecked = false, sShouldEnable = false; + if (sChecked) + return sShouldEnable; + + sChecked = true; + + // check if accessibility enabled/disabled by environment variable + const char* envValue = PR_GetEnv(sAccEnv); + if (envValue) + return sShouldEnable = !!atoi(envValue); + +#ifdef MOZ_ENABLE_DBUS + PreInit(); + bool dbusSuccess = false; + DBusMessage *reply = nsnull; + if (!sPendingCall) + goto dbus_done; + + dbus_pending_call_block(sPendingCall); + reply = dbus_pending_call_steal_reply(sPendingCall); + dbus_pending_call_unref(sPendingCall); + sPendingCall = nsnull; + if (!reply || + dbus_message_get_type(reply) != DBUS_MESSAGE_TYPE_METHOD_RETURN || + strcmp(dbus_message_get_signature (reply), DBUS_TYPE_VARIANT_AS_STRING)) + goto dbus_done; + + DBusMessageIter iter, iter_variant, iter_struct; + dbus_bool_t dResult; + dbus_message_iter_init(reply, &iter); + dbus_message_iter_recurse (&iter, &iter_variant); + switch (dbus_message_iter_get_arg_type(&iter_variant)) { + case DBUS_TYPE_STRUCT: + // at-spi2-core 2.2.0-2.2.1 had a bug where it returned a struct + dbus_message_iter_recurse(&iter_variant, &iter_struct); + if (dbus_message_iter_get_arg_type(&iter_struct) == DBUS_TYPE_BOOLEAN) { + dbus_message_iter_get_basic(&iter_struct, &dResult); + sShouldEnable = dResult; + dbusSuccess = true; + } + + break; + case DBUS_TYPE_BOOLEAN: + dbus_message_iter_get_basic(&iter_variant, &dResult); + sShouldEnable = dResult; + dbusSuccess = true; + break; + default: + break; + } + +dbus_done: + if (reply) + dbus_message_unref(reply); + + if (dbusSuccess) + return sShouldEnable; +#endif + + //check gconf-2 setting +static const char sGconfAccessibilityKey[] = + "/desktop/gnome/interface/accessibility"; + nsresult rv = NS_OK; + nsCOMPtr gconf = + do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv) && gconf) + gconf->GetBool(NS_LITERAL_CSTRING(sGconfAccessibilityKey), &sShouldEnable); + + return sShouldEnable; +} +} // namespace a11y +} // namespace mozilla + diff --git a/accessible/src/base/nsAccessibilityService.h b/accessible/src/base/nsAccessibilityService.h index dd7bcda50de..6370e74d6fa 100644 --- a/accessible/src/base/nsAccessibilityService.h +++ b/accessible/src/base/nsAccessibilityService.h @@ -56,6 +56,21 @@ namespace a11y { */ FocusManager* FocusMgr(); +#ifdef MOZ_ACCESSIBILITY_ATK +/** + * Perform initialization that should be done as soon as possible, in order + * to minimize startup time. + * XXX: this function and the next defined in nsApplicationAccessibleWrap.cpp + */ +void PreInit(); + +/** + * Is platform accessibility enabled. + * Only used on linux with atk for now. + */ +bool ShouldA11yBeEnabled(); +#endif + } // namespace a11y } // namespace mozilla diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp index 5ff608d4f26..3f3edd7260c 100644 --- a/widget/src/gtk2/nsWindow.cpp +++ b/widget/src/gtk2/nsWindow.cpp @@ -109,19 +109,11 @@ #include "nsIPropertyBag2.h" #ifdef ACCESSIBILITY -#include "nsIAccessibilityService.h" +#include "nsAccessibilityService.h" #include "nsIAccessibleDocument.h" -#include "prenv.h" -#include "stdlib.h" using namespace mozilla; using namespace mozilla::widget; - -static bool sAccessibilityChecked = false; -/* static */ -bool nsWindow::sAccessibilityEnabled = false; -static const char sAccEnv [] = "GNOME_ACCESSIBILITY"; -static const char sGconfAccessibilityKey[] = "/desktop/gnome/interface/accessibility"; #endif /* For SetIcon */ @@ -1123,9 +1115,8 @@ nsWindow::Show(bool aState) } #ifdef ACCESSIBILITY - if (aState && sAccessibilityEnabled) { + if (aState && a11y::ShouldA11yBeEnabled()) CreateRootAccessible(); - } #endif NativeShow(aState); @@ -3962,6 +3953,11 @@ nsWindow::Create(nsIWidget *aParent, NS_ASSERTION(!mWindowGroup, "already have window group (leaking it)"); +#ifdef ACCESSIBILITY + // Send a DBus message to check whether a11y is enabled + a11y::PreInit(); +#endif + // Ensure that the toolkit is created. nsGTKToolkit::GetToolkit(); @@ -4355,31 +4351,6 @@ nsWindow::Create(nsIWidget *aParent, if (!mIsTopLevel) Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, false); -#ifdef ACCESSIBILITY - nsresult rv; - if (!sAccessibilityChecked) { - sAccessibilityChecked = true; - - //check if accessibility enabled/disabled by environment variable - const char *envValue = PR_GetEnv(sAccEnv); - if (envValue) { - sAccessibilityEnabled = atoi(envValue) != 0; - LOG(("Accessibility Env %s=%s\n", sAccEnv, envValue)); - } else { - //check gconf-2 setting - nsCOMPtr gconf = - do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv); - if (NS_SUCCEEDED(rv) && gconf) { - - // do the work to get gconf setting. - // will be done soon later. - gconf->GetBool(NS_LITERAL_CSTRING(sGconfAccessibilityKey), - &sAccessibilityEnabled); - } - } - } -#endif - #ifdef MOZ_DFB if (!mDFB) { DirectFBCreate( &mDFB ); @@ -6559,9 +6530,8 @@ nsWindow::DispatchAccessibleEvent() void nsWindow::DispatchEventToRootAccessible(PRUint32 aEventType) { - if (!sAccessibilityEnabled) { + if (!a11y::ShouldA11yBeEnabled()) return; - } nsCOMPtr accService = do_GetService("@mozilla.org/accessibilityService;1"); diff --git a/widget/src/gtk2/nsWindow.h b/widget/src/gtk2/nsWindow.h index fad9159657a..0da158c2763 100644 --- a/widget/src/gtk2/nsWindow.h +++ b/widget/src/gtk2/nsWindow.h @@ -347,9 +347,6 @@ public: #endif NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent); -#ifdef ACCESSIBILITY - static bool sAccessibilityEnabled; -#endif protected: // Helper for SetParent and ReparentNativeWidget. void ReparentNativeWidgetInternal(nsIWidget* aNewParent,