mozilla-a11y.patch
author Michael Gorse <mgorse@suse.com>
Tue, 29 Nov 2011 15:56:24 +0100
changeset 358 b28670af14d5
child 369 04fc00b85b21
permissions -rw-r--r--
Read a11y status from Gnome3

# HG changeset patch
# User Michael Gorse <mgorse@suse.com>
# Parent d02253d1e8217008dfa26e6e2a901b6a8b75e989
a11y only enabled from Gnome 2's GConf setting
https://bugzilla.novell.com/show_bug.cgi?id=732898
https://bugzilla.mozilla.org/show_bug.cgi?id=693343

diff --git a/accessible/src/atk/Makefile.in b/accessible/src/atk/Makefile.in
--- a/accessible/src/atk/Makefile.in
+++ b/accessible/src/atk/Makefile.in
@@ -87,15 +87,19 @@ EXPORTS = \
 # we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 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 \
   -I$(srcdir)/../html \
   -I$(srcdir)/../xul \
   -I$(topsrcdir)/other-licenses/atk-1.0 \
   $(NULL)
diff --git a/accessible/src/atk/nsApplicationAccessibleWrap.cpp b/accessible/src/atk/nsApplicationAccessibleWrap.cpp
--- a/accessible/src/atk/nsApplicationAccessibleWrap.cpp
+++ b/accessible/src/atk/nsApplicationAccessibleWrap.cpp
@@ -47,29 +47,27 @@
 #include "nsIPrefBranch.h"
 #include "nsIServiceManager.h"
 #include "nsAutoPtr.h"
 #include "nsAccessibilityService.h"
 #include "AtkSocketAccessible.h"
 
 #include <gtk/gtk.h>
 #include <atk/atk.h>
+#include <dbus/dbus.h>
+
+using namespace mozilla::a11y;
 
 typedef GType (* AtkGetTypeType) (void);
 GType g_atk_hyperlink_impl_type = G_TYPE_INVALID;
-static bool sATKChecked = false;
+static PRBool sATKChecked = PR_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 sSysPrefService [] =
-    "@mozilla.org/system-preference-service;1";
-static const char sAccessibilityKey [] =
-    "config.use_system_prefs.accessibility";
 
 /* gail function pointer */
 static guint (* gail_add_global_event_listener) (GSignalEmissionHook listener,
                                                  const gchar *event_type);
 static void (* gail_remove_global_event_listener) (guint remove_listener);
 static void (* gail_remove_key_event_listener) (guint remove_listener);
 static AtkObject * (*gail_get_root) (void);
 
@@ -609,36 +607,17 @@ toplevel_event_watcher(GSignalInvocation
   }
 
   return TRUE;
 }
 
 PRBool
 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
-    PRBool isGnomeATEnabled = PR_FALSE;
-    const char *envValue = PR_GetEnv(sAccEnv);
-    if (envValue) {
-        isGnomeATEnabled = !!atoi(envValue);
-    } else {
-        //check gconf-2 setting
-        nsresult rv;
-        nsCOMPtr<nsIPrefBranch> sysPrefService =
-            do_GetService(sSysPrefService, &rv);
-        if (NS_SUCCEEDED(rv) && sysPrefService) {
-            sysPrefService->GetBoolPref(sAccessibilityKey, &isGnomeATEnabled);
-        }
-    }
-
-    if (isGnomeATEnabled) {
+    if (ShouldA11yBeEnabled()) {
         // load and initialize gail library
         nsresult rv = LoadGtkModule(sGail);
         if (NS_SUCCEEDED(rv)) {
             (*sGail.init)();
         }
         else {
             MAI_LOG_DEBUG(("Fail to load lib: %s\n", sGail.libName));
         }
@@ -877,8 +856,129 @@ LoadGtkModule(GnomeAccessibilityModule& 
                        aModule.init ? aModule.shutdownName : aModule.initName,
                        aModule.libName));
         PR_UnloadLibrary(aModule.lib);
         aModule.lib = NULL;
         return NS_ERROR_FAILURE;
     }
     return NS_OK;
 }
+
+namespace mozilla {
+namespace a11y {
+
+#ifdef MOZ_ENABLE_DBUS
+static DBusPendingCall *a11yPendingCall = NULL;
+#endif
+
+void
+PreInit()
+{
+  static PRBool sChecked = FALSE;
+  if (sChecked)
+    return;
+  sChecked = TRUE;
+  DBusError error;
+  dbus_error_init(&error);
+  DBusConnection* bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
+  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, &a11yPendingCall, 1000);
+
+dbus_done:
+  if (message)
+    dbus_message_unref(message);
+  if (bus)
+    dbus_connection_unref(bus);
+  dbus_error_free(&error);
+}
+
+PRBool
+ShouldA11yBeEnabled()
+{
+  static PRBool sChecked = PR_FALSE, sShouldEnable = PR_FALSE;
+  if (sChecked)
+    return sShouldEnable;
+
+  sChecked = PR_TRUE;
+
+  // check if accessibility enabled/disabled by environment variable
+  static const char sAccEnv [] = "GNOME_ACCESSIBILITY";
+  const char* envValue = PR_GetEnv(sAccEnv);
+  if (envValue)
+    return sShouldEnable = !!atoi(envValue);
+
+#ifdef MOZ_ENABLE_DBUS
+  PreInit();
+  PRBool dbusSuccess = PR_FALSE;
+  DBusMessage *reply = nsnull;
+  if (a11yPendingCall) {
+    dbus_pending_call_block(a11yPendingCall);
+    reply = dbus_pending_call_steal_reply(a11yPendingCall);
+    dbus_pending_call_unref(a11yPendingCall);
+    a11yPendingCall = nsnull;
+  }
+  if (!reply ||
+      dbus_message_get_type(reply) != DBUS_MESSAGE_TYPE_METHOD_RETURN ||
+      strcmp(dbus_message_get_signature (reply), "v"))
+    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
+  nsresult rv = NS_OK;
+  static const char sSysPrefService [] =
+    "@mozilla.org/system-preference-service;1";
+  static const char sAccessibilityKey [] =
+    "config.use_system_prefs.accessibility";
+  nsCOMPtr<nsIPrefBranch> sysPrefService =
+    do_GetService(sSysPrefService, &rv);
+  if (NS_SUCCEEDED(rv) && sysPrefService)
+    sysPrefService->GetBoolPref(sAccessibilityKey, &sShouldEnable);
+
+  return sShouldEnable;
+}
+} // namespace a11y
+} // namespace mozilla
+
diff --git a/accessible/src/base/nsAccessibilityService.h b/accessible/src/base/nsAccessibilityService.h
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -41,16 +41,36 @@
 
 #include "nsIAccessibilityService.h"
 
 #include "a11yGeneric.h"
 #include "nsAccDocManager.h"
 
 #include "nsIObserver.h"
 
+namespace mozilla {
+namespace a11y {
+#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.
+ */
+PRBool ShouldA11yBeEnabled();
+#endif
+
+} // namespace a11y
+} // namespace mozilla
+
 class nsAccessibilityService : public nsAccDocManager,
                                public nsIAccessibilityService,
                                public nsIObserver
 {
 public:
   virtual ~nsAccessibilityService();
 
   NS_DECL_ISUPPORTS_INHERITED
diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp
--- a/widget/src/gtk2/nsWindow.cpp
+++ b/widget/src/gtk2/nsWindow.cpp
@@ -103,29 +103,20 @@
 #include "nsIStringBundle.h"
 #include "nsGfxCIID.h"
 #include "nsIObserverService.h"
 
 #include "nsIdleService.h"
 #include "nsIPropertyBag2.h"
 
 #ifdef ACCESSIBILITY
-#include "nsIAccessibilityService.h"
+#include "nsAccessibilityService.h"
 #include "nsIAccessibleDocument.h"
-#include "prenv.h"
-#include "stdlib.h"
 
 using namespace mozilla;
-
-static PRBool sAccessibilityChecked = PR_FALSE;
-/* static */
-PRBool nsWindow::sAccessibilityEnabled = PR_FALSE;
-static const char sSysPrefService [] = "@mozilla.org/system-preference-service;1";
-static const char sAccEnv [] = "GNOME_ACCESSIBILITY";
-static const char sAccessibilityKey [] = "config.use_system_prefs.accessibility";
 #endif
 
 /* For SetIcon */
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsXPIDLString.h"
 #include "nsIFile.h"
 #include "nsILocalFile.h"
 
@@ -1109,19 +1100,18 @@ nsWindow::Show(PRBool aState)
             NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
                          PR_FALSE);
         } else if (mNeedsResize) {
             NativeResize(mBounds.width, mBounds.height, PR_FALSE);
         }
     }
 
 #ifdef ACCESSIBILITY
-    if (aState && sAccessibilityEnabled) {
+    if (aState && a11y::ShouldA11yBeEnabled())
         CreateRootAccessible();
-    }
 #endif
 
     NativeShow(aState);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -3887,16 +3877,21 @@ nsWindow::Create(nsIWidget        *aPare
     nsIWidget *baseParent = aInitData &&
         (aInitData->mWindowType == eWindowType_dialog ||
          aInitData->mWindowType == eWindowType_toplevel ||
          aInitData->mWindowType == eWindowType_invisible) ?
         nsnull : 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
+
     // initialize all the common bits of this class
     BaseCreate(baseParent, aRect, aHandleEventFunction, aContext,
                aAppShell, aToolkit, aInitData);
 
     // Do we need to listen for resizes?
     PRBool listenForResizes = PR_FALSE;;
     if (aNativeParent || (aInitData && aInitData->mListenForResizes))
         listenForResizes = PR_TRUE;
@@ -4278,43 +4273,16 @@ nsWindow::Create(nsIWidget        *aPare
         LOG(("\tmGdkWindow %p %lx\n", (void *)mGdkWindow,
              gdk_x11_window_get_xid(mGdkWindow)));
     }
 
     // resize so that everything is set to the right dimensions
     if (!mIsTopLevel)
         Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, PR_FALSE);
 
-#ifdef ACCESSIBILITY
-    nsresult rv;
-    if (!sAccessibilityChecked) {
-        sAccessibilityChecked = PR_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));
-        }
-        //check gconf-2 setting
-        else {
-            nsCOMPtr<nsIPrefBranch> sysPrefService =
-                do_GetService(sSysPrefService, &rv);
-            if (NS_SUCCEEDED(rv) && sysPrefService) {
-
-                // do the work to get gconf setting.
-                // will be done soon later.
-                sysPrefService->GetBoolPref(sAccessibilityKey,
-                                            &sAccessibilityEnabled);
-            }
-
-        }
-    }
-#endif
-
 #ifdef MOZ_DFB
     if (!mDFB) {
          DirectFBCreate( &mDFB );
 
          D_ASSUME( mDFB != NULL );
 
          if (mDFB)
               mDFB->GetDisplayLayer( mDFB, DLID_PRIMARY, &mDFBLayer );
@@ -6504,19 +6472,18 @@ nsWindow::DispatchAccessibleEvent()
     DispatchEvent(&event, status);
 
     return event.mAccessible;
 }
 
 void
 nsWindow::DispatchEventToRootAccessible(PRUint32 aEventType)
 {
-    if (!sAccessibilityEnabled) {
+    if (!a11y::ShouldA11yBeEnabled())
         return;
-    }
 
     nsCOMPtr<nsIAccessibilityService> accService =
         do_GetService("@mozilla.org/accessibilityService;1");
     if (!accService) {
         return;
     }
 
     // Get the root document accessible and fire event to it.