summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominic Mazzoni <dmazzoni@chromium.org>2015-03-16 13:51:09 -0700
committerDominic Mazzoni <dmazzoni@chromium.org>2015-03-16 20:54:11 +0000
commit0e9bcce45c12479259c705a07a6b4b1e73b84bf2 (patch)
treebaf231cb4ce2f6dadc976db8cce21d564071e82c
parent772e590605971ee9c165e4ffdfec844edaf017f8 (diff)
downloadchromium_src-0e9bcce45c12479259c705a07a6b4b1e73b84bf2.zip
chromium_src-0e9bcce45c12479259c705a07a6b4b1e73b84bf2.tar.gz
chromium_src-0e9bcce45c12479259c705a07a6b4b1e73b84bf2.tar.bz2
Re-land: Resurrect Aura Linux accessibility.
1. Avoids overloading in a C linkage block (mostynb) 2. Only compiles ATK support if use_x11 is true to avoid ChromeCast issue (gunsch) 3. Updates chrome/installer/linux expectations Original changelist: https://codereview.chromium.org/975113002/ BUG=463671 R=thestig@chromium.org TBR=dpranke, plundblad, sky Review URL: https://codereview.chromium.org/1005293002 Cr-Commit-Position: refs/heads/master@{#320790}
-rw-r--r--build/config/linux/BUILD.gn19
-rw-r--r--build/config/linux/pkg-config.py13
-rw-r--r--build/linux/system.gyp24
-rw-r--r--chrome/browser/ui/views/chrome_views_delegate.cc5
-rw-r--r--chrome/browser/ui/views/chrome_views_delegate.h1
-rw-r--r--chrome/installer/linux/debian/expected_deps_ia321
-rw-r--r--chrome/installer/linux/debian/expected_deps_x641
-rw-r--r--chrome/installer/linux/rpm/expected_deps_i3862
-rw-r--r--chrome/installer/linux/rpm/expected_deps_x86_642
-rwxr-xr-xtools/accessibility/dump_accessibility_tree_auralinux.py32
-rw-r--r--ui/accessibility/BUILD.gn17
-rw-r--r--ui/accessibility/accessibility.gyp25
-rw-r--r--ui/accessibility/platform/atk_util_auralinux.cc161
-rw-r--r--ui/accessibility/platform/atk_util_auralinux.h30
-rw-r--r--ui/accessibility/platform/ax_platform_node.cc2
-rw-r--r--ui/accessibility/platform/ax_platform_node_auralinux.cc283
-rw-r--r--ui/accessibility/platform/ax_platform_node_auralinux.h51
-rw-r--r--ui/accessibility/platform/ax_platform_node_base.h4
-rw-r--r--ui/gfx/native_widget_types.h11
-rw-r--r--ui/views/BUILD.gn1
-rw-r--r--ui/views/accessibility/native_view_accessibility.cc5
-rw-r--r--ui/views/accessibility/native_view_accessibility_auralinux.cc164
-rw-r--r--ui/views/accessibility/native_view_accessibility_auralinux.h27
-rw-r--r--ui/views/views.gyp3
-rw-r--r--ui/views/views_delegate.cc6
-rw-r--r--ui/views/views_delegate.h3
26 files changed, 889 insertions, 4 deletions
diff --git a/build/config/linux/BUILD.gn b/build/config/linux/BUILD.gn
index 202fd73..3d65937 100644
--- a/build/config/linux/BUILD.gn
+++ b/build/config/linux/BUILD.gn
@@ -35,6 +35,25 @@ config("sdk") {
}
}
+pkg_config("atk") {
+ packages = [ "atk" ]
+ atk_lib_dir = exec_script(pkg_config_script,
+ [
+ "--libdir",
+ "atk",
+ ],
+ "string")
+ defines = [ "ATK_LIB_DIR=\"$atk_lib_dir\"" ]
+}
+
+# gn orders flags on a target before flags from configs. The default config
+# adds -Wall, and these flags have to be after -Wall -- so they need to come
+# from a config and can't be on the target directly.
+config("atk_warnings") {
+ # glib uses the pre-c++11 typedef-as-static_assert hack.
+ cflags = [ "-Wno-unused-local-typedef" ]
+}
+
config("fontconfig") {
libs = [ "fontconfig" ]
}
diff --git a/build/config/linux/pkg-config.py b/build/config/linux/pkg-config.py
index a4f4703..fadcc0b 100644
--- a/build/config/linux/pkg-config.py
+++ b/build/config/linux/pkg-config.py
@@ -112,6 +112,7 @@ parser.add_option('-s', action='store', dest='sysroot', type='string')
parser.add_option('-a', action='store', dest='arch', type='string')
parser.add_option('--atleast-version', action='store',
dest='atleast_version', type='string')
+parser.add_option('--libdir', action='store_true', dest='libdir')
(options, args) = parser.parse_args()
# Make a list of regular expressions to strip out.
@@ -138,6 +139,18 @@ if options.atleast_version:
print "false"
sys.exit(0)
+if options.libdir:
+ try:
+ libdir = subprocess.check_output([options.pkg_config,
+ "--variable=libdir"] +
+ args,
+ env=os.environ)
+ except:
+ print "Error from pkg-config."
+ sys.exit(1)
+ sys.stdout.write(libdir.strip())
+ sys.exit(0)
+
try:
flag_string = subprocess.check_output(
[ options.pkg_config, "--cflags", "--libs-only-l", "--libs-only-L" ] +
diff --git a/build/linux/system.gyp b/build/linux/system.gyp
index 59fc13a..5333798 100644
--- a/build/linux/system.gyp
+++ b/build/linux/system.gyp
@@ -91,6 +91,30 @@
# added back to Chrome OS and Ozone. Don't try to use GTK on Chrome OS and Ozone.
'targets': [
{
+ 'target_name': 'atk',
+ 'type': 'none',
+ 'conditions': [
+ ['_toolset=="target"', {
+ 'direct_dependent_settings': {
+ 'cflags': [
+ '<!@(<(pkg-config) --cflags atk)',
+ ],
+ 'defines': [
+ 'ATK_LIB_DIR="<!@(<(pkg-config) --variable=libdir atk)"',
+ ],
+ },
+ 'link_settings': {
+ 'ldflags': [
+ '<!@(<(pkg-config) --libs-only-L --libs-only-other atk)',
+ ],
+ 'libraries': [
+ '<!@(<(pkg-config) --libs-only-l atk)',
+ ],
+ },
+ }],
+ ],
+ },
+ {
'target_name': 'gdk',
'type': 'none',
'conditions': [
diff --git a/chrome/browser/ui/views/chrome_views_delegate.cc b/chrome/browser/ui/views/chrome_views_delegate.cc
index 82c9190a..daba64b 100644
--- a/chrome/browser/ui/views/chrome_views_delegate.cc
+++ b/chrome/browser/ui/views/chrome_views_delegate.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser_window_state.h"
+#include "chrome/common/chrome_version_info.h"
#include "content/public/browser/context_factory.h"
#include "grit/chrome_unscaled_resources.h"
#include "ui/base/resource/resource_bundle.h"
@@ -383,6 +384,10 @@ ui::ContextFactory* ChromeViewsDelegate::GetContextFactory() {
return content::GetContextFactory();
}
+std::string ChromeViewsDelegate::GetApplicationName() {
+ return chrome::VersionInfo().Name();
+}
+
#if defined(OS_WIN)
int ChromeViewsDelegate::GetAppbarAutohideEdges(HMONITOR monitor,
const base::Closure& callback) {
diff --git a/chrome/browser/ui/views/chrome_views_delegate.h b/chrome/browser/ui/views/chrome_views_delegate.h
index 3846d9e..d4d197f 100644
--- a/chrome/browser/ui/views/chrome_views_delegate.h
+++ b/chrome/browser/ui/views/chrome_views_delegate.h
@@ -48,6 +48,7 @@ class ChromeViewsDelegate : public views::ViewsDelegate {
bool WindowManagerProvidesTitleBar(bool maximized) override;
#endif
ui::ContextFactory* GetContextFactory() override;
+ std::string GetApplicationName() override;
#if defined(OS_WIN)
virtual int GetAppbarAutohideEdges(HMONITOR monitor,
const base::Closure& callback) override;
diff --git a/chrome/installer/linux/debian/expected_deps_ia32 b/chrome/installer/linux/debian/expected_deps_ia32
index 62dfcce..b0a61a9 100644
--- a/chrome/installer/linux/debian/expected_deps_ia32
+++ b/chrome/installer/linux/debian/expected_deps_ia32
@@ -1,5 +1,6 @@
gconf-service
libasound2 (>= 1.0.23)
+libatk1.0-0 (>= 1.12.4)
libc6 (>= 2.11)
libcairo2 (>= 1.6.0)
libcap2 (>= 2.10)
diff --git a/chrome/installer/linux/debian/expected_deps_x64 b/chrome/installer/linux/debian/expected_deps_x64
index 62dfcce..b0a61a9 100644
--- a/chrome/installer/linux/debian/expected_deps_x64
+++ b/chrome/installer/linux/debian/expected_deps_x64
@@ -1,5 +1,6 @@
gconf-service
libasound2 (>= 1.0.23)
+libatk1.0-0 (>= 1.12.4)
libc6 (>= 2.11)
libcairo2 (>= 1.6.0)
libcap2 (>= 2.10)
diff --git a/chrome/installer/linux/rpm/expected_deps_i386 b/chrome/installer/linux/rpm/expected_deps_i386
index 215d0f7..7931d51 100644
--- a/chrome/installer/linux/rpm/expected_deps_i386
+++ b/chrome/installer/linux/rpm/expected_deps_i386
@@ -2,6 +2,7 @@ ld-linux.so.2
ld-linux.so.2(GLIBC_2.1)
ld-linux.so.2(GLIBC_2.3)
libasound.so.2
+libatk-1.0.so.0
libcairo.so.2
libcap.so.2
libc.so.6
@@ -33,6 +34,7 @@ libgdk_pixbuf-2.0.so.0
libgdk-x11-2.0.so.0
libgio-2.0.so.0
libglib-2.0.so.0
+libgmodule-2.0.so.0
libgobject-2.0.so.0
libgtk-x11-2.0.so.0
libm.so.6
diff --git a/chrome/installer/linux/rpm/expected_deps_x86_64 b/chrome/installer/linux/rpm/expected_deps_x86_64
index 5cbde42..92c02ff 100644
--- a/chrome/installer/linux/rpm/expected_deps_x86_64
+++ b/chrome/installer/linux/rpm/expected_deps_x86_64
@@ -2,6 +2,7 @@ ld-linux-x86-64.so.2()(64bit)
ld-linux-x86-64.so.2(GLIBC_2.2.5)(64bit)
ld-linux-x86-64.so.2(GLIBC_2.3)(64bit)
libasound.so.2()(64bit)
+libatk-1.0.so.0()(64bit)
libcairo.so.2()(64bit)
libcap.so.2()(64bit)
libc.so.6()(64bit)
@@ -26,6 +27,7 @@ libgdk_pixbuf-2.0.so.0()(64bit)
libgdk-x11-2.0.so.0()(64bit)
libgio-2.0.so.0()(64bit)
libglib-2.0.so.0()(64bit)
+libgmodule-2.0.so.0()(64bit)
libgobject-2.0.so.0()(64bit)
libgtk-x11-2.0.so.0()(64bit)
libm.so.6()(64bit)
diff --git a/tools/accessibility/dump_accessibility_tree_auralinux.py b/tools/accessibility/dump_accessibility_tree_auralinux.py
new file mode 100755
index 0000000..4c352d1
--- /dev/null
+++ b/tools/accessibility/dump_accessibility_tree_auralinux.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Dump Chrome's ATK accessibility tree to the command line.
+
+Accerciser is slow and buggy. This is a quick way to check that Chrome is
+exposing its interface to ATK from the command line.
+"""
+
+import pyatspi
+
+def Dump(obj, indent):
+ if not obj:
+ return
+ indent_str = ' ' * indent
+ role = obj.get_role_name()
+ name = obj.get_name()
+ print '%s%s name="%s"' % (indent_str, role, name)
+
+ # Don't recurse into applications other than Chrome
+ if role == 'application':
+ if (name.lower().find('chrom') != 0 and
+ name.lower().find('google chrome') != 0):
+ return
+
+ for i in range(obj.get_child_count()):
+ Dump(obj.get_child_at_index(i), indent + 1)
+
+desktop = pyatspi.Registry.getDesktop(0)
+Dump(desktop, 0)
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index d168b5e..a5c67ba 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/ui.gni")
import("//build/json_schema_api.gni")
import("//testing/test.gni")
@@ -47,6 +48,22 @@ component("accessibility") {
if (is_win) {
public_deps += [ "//third_party/iaccessible2" ]
}
+
+ if (use_aura && !is_chromeos && is_linux && use_x11) {
+ sources += [
+ "platform/atk_util_auralinux.cc",
+ "platform/atk_util_auralinux.h",
+ "platform/ax_platform_node_auralinux.cc",
+ "platform/ax_platform_node_auralinux.h",
+ ]
+
+ configs += [
+ "//build/config/linux:atk",
+ "//build/config/linux:atk_warnings",
+ "//build/config/linux:gconf",
+ "//build/config/linux:glib",
+ ]
+ }
}
source_set("test_support") {
diff --git a/ui/accessibility/accessibility.gyp b/ui/accessibility/accessibility.gyp
index 88613e6..e417f10 100644
--- a/ui/accessibility/accessibility.gyp
+++ b/ui/accessibility/accessibility.gyp
@@ -43,8 +43,12 @@
'ax_tree_update.h',
'ax_view_state.cc',
'ax_view_state.h',
+ 'platform/atk_util_auralinux.cc',
+ 'platform/atk_util_auralinux.h',
'platform/ax_platform_node.cc',
'platform/ax_platform_node.h',
+ 'platform/ax_platform_node_auralinux.cc',
+ 'platform/ax_platform_node_auralinux.h',
'platform/ax_platform_node_base.cc',
'platform/ax_platform_node_base.h',
'platform/ax_platform_node_delegate.h',
@@ -59,6 +63,27 @@
'../../third_party/iaccessible2/iaccessible2.gyp:iaccessible2'
],
}],
+ ['OS=="linux" and chromeos==0 and use_x11==1', {
+ 'dependencies': [
+ '../../build/linux/system.gyp:atk',
+ '../../build/linux/system.gyp:gconf',
+ '../../build/linux/system.gyp:glib',
+ ],
+ 'variables': {
+ 'clang_warning_flags': [
+ # glib uses the pre-c++11 typedef-as-static_assert hack.
+ '-Wno-unused-local-typedefs',
+ ],
+ },
+ }],
+ ['OS!="linux" or chromeos==1 or use_x11==0', {
+ 'sources!': [
+ 'platform/ax_platform_node_auralinux.cc',
+ 'platform/ax_platform_node_auralinux.h',
+ 'platform/atk_util_auralinux.cc',
+ 'platform/atk_util_auralinux.h',
+ ],
+ }],
],
},
{
diff --git a/ui/accessibility/platform/atk_util_auralinux.cc b/ui/accessibility/platform/atk_util_auralinux.cc
new file mode 100644
index 0000000..a15df08
--- /dev/null
+++ b/ui/accessibility/platform/atk_util_auralinux.cc
@@ -0,0 +1,161 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <atk/atk.h>
+#include <gconf/gconf-client.h>
+#include <glib-2.0/gmodule.h>
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "ui/accessibility/platform/atk_util_auralinux.h"
+#include "ui/accessibility/platform/ax_platform_node_auralinux.h"
+
+namespace {
+
+const char kGnomeAccessibilityEnabledKey[] =
+ "/desktop/gnome/interface/accessibility";
+
+bool ShouldEnableAccessibility() {
+ GConfClient* client = gconf_client_get_default();
+ if (!client) {
+ LOG(ERROR) << "gconf_client_get_default failed";
+ return false;
+ }
+
+ GError* error = nullptr;
+ gboolean value = gconf_client_get_bool(client,
+ kGnomeAccessibilityEnabledKey,
+ &error);
+ if (error) {
+ VLOG(1) << "gconf_client_get_bool failed";
+ g_error_free(error);
+ g_object_unref(client);
+ return false;
+ }
+
+ g_object_unref(client);
+ return value;
+}
+
+} // namespace
+
+G_BEGIN_DECLS
+
+//
+// atk_util_auralinux AtkObject definition and implementation.
+//
+
+#define ATK_UTIL_AURALINUX_TYPE (atk_util_auralinux_get_type())
+#define ATK_UTIL_AURALINUX(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+ ATK_UTIL_AURALINUX_TYPE, \
+ AtkUtilAuraLinux))
+#define ATK_UTIL_AURALINUX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), \
+ ATK_UTIL_AURALINUX_TYPE, \
+ AtkUtilAuraLinuxClass))
+#define IS_ATK_UTIL_AURALINUX(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), ATK_UTIL_AURALINUX_TYPE))
+#define IS_ATK_UTIL_AURALINUX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), ATK_UTIL_AURALINUX_TYPE))
+#define ATK_UTIL_AURALINUX_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), \
+ ATK_UTIL_AURALINUX_TYPE, \
+ AtkUtilAuraLinuxClass))
+
+typedef struct _AtkUtilAuraLinux AtkUtilAuraLinux;
+typedef struct _AtkUtilAuraLinuxClass AtkUtilAuraLinuxClass;
+
+struct _AtkUtilAuraLinux
+{
+ AtkUtil parent;
+};
+
+struct _AtkUtilAuraLinuxClass
+{
+ AtkUtilClass parent_class;
+};
+
+GType atk_util_auralinux_get_type();
+
+G_DEFINE_TYPE(AtkUtilAuraLinux, atk_util_auralinux, ATK_TYPE_UTIL);
+
+static void atk_util_auralinux_init(AtkUtilAuraLinux *ax_util) {
+}
+
+static AtkObject* atk_util_auralinux_get_root() {
+ ui::AXPlatformNode* application = ui::AXPlatformNodeAuraLinux::application();
+ if (application) {
+ return application->GetNativeViewAccessible();
+ }
+ return nullptr;
+}
+
+static G_CONST_RETURN gchar* atk_util_auralinux_get_toolkit_name(void) {
+ return "Chromium";
+}
+
+static G_CONST_RETURN gchar* atk_util_auralinux_get_toolkit_version(void) {
+ return "1.0";
+}
+
+static void atk_util_auralinux_class_init(AtkUtilAuraLinuxClass *klass) {
+ AtkUtilClass *atk_class;
+ gpointer data;
+
+ data = g_type_class_peek(ATK_TYPE_UTIL);
+ atk_class = ATK_UTIL_CLASS(data);
+
+ atk_class->get_root = atk_util_auralinux_get_root;
+ atk_class->get_toolkit_name = atk_util_auralinux_get_toolkit_name;
+ atk_class->get_toolkit_version = atk_util_auralinux_get_toolkit_version;
+}
+
+G_END_DECLS
+
+//
+// AtkUtilAuraLinuxClass implementation.
+//
+
+namespace ui {
+
+// static
+AtkUtilAuraLinux* AtkUtilAuraLinux::GetInstance() {
+ return Singleton<AtkUtilAuraLinux>::get();
+}
+
+AtkUtilAuraLinux::AtkUtilAuraLinux() {
+ // Register our util class.
+ g_type_class_unref(g_type_class_ref(ATK_UTIL_AURALINUX_TYPE));
+
+ if (!ShouldEnableAccessibility()) {
+ VLOG(1) << "Will not enable ATK accessibility support.";
+ return;
+ }
+
+ VLOG(1) << "Enabling ATK accessibility support.";
+
+ // Try to load libatk-bridge.so.
+ base::FilePath atk_bridge_path(ATK_LIB_DIR);
+ atk_bridge_path = atk_bridge_path.Append("gtk-2.0/modules/libatk-bridge.so");
+ GModule* bridge = g_module_open(atk_bridge_path.value().c_str(),
+ static_cast<GModuleFlags>(0));
+ if (!bridge) {
+ VLOG(1) << "Unable to open module " << atk_bridge_path.value();
+ return;
+ }
+
+ // Try to call gnome_accessibility_module_init from libatk-bridge.so.
+ void (*gnome_accessibility_module_init)();
+ if (g_module_symbol(bridge, "gnome_accessibility_module_init",
+ (gpointer *)&gnome_accessibility_module_init)) {
+ (*gnome_accessibility_module_init)();
+ }
+}
+
+AtkUtilAuraLinux::~AtkUtilAuraLinux() {
+}
+
+} // namespace ui
diff --git a/ui/accessibility/platform/atk_util_auralinux.h b/ui/accessibility/platform/atk_util_auralinux.h
new file mode 100644
index 0000000..349c41a
--- /dev/null
+++ b/ui/accessibility/platform/atk_util_auralinux.h
@@ -0,0 +1,30 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_AX_UTIL_AURALINUX_H_
+#define UI_ACCESSIBILITY_AX_UTIL_AURALINUX_H_
+
+#include "base/memory/singleton.h"
+#include "ui/accessibility/ax_export.h"
+
+namespace ui {
+
+// This singleton class initializes ATK (accessibility toolkit) and
+// registers an implementation of the AtkUtil class, a global class that
+// every accessible application needs to register once.
+class AtkUtilAuraLinux {
+ public:
+ // Get the single instance of this class.
+ static AtkUtilAuraLinux* GetInstance();
+
+ AtkUtilAuraLinux();
+ virtual ~AtkUtilAuraLinux();
+
+ private:
+ friend struct DefaultSingletonTraits<AtkUtilAuraLinux>;
+};
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_AX_UTIL_AURALINUX_H_
diff --git a/ui/accessibility/platform/ax_platform_node.cc b/ui/accessibility/platform/ax_platform_node.cc
index 363b3ee..ec268a0 100644
--- a/ui/accessibility/platform/ax_platform_node.cc
+++ b/ui/accessibility/platform/ax_platform_node.cc
@@ -9,7 +9,7 @@
namespace ui {
-#if !defined(OS_MACOSX) && !defined(OS_WIN)
+#if !defined(OS_MACOSX) && !defined(OS_WIN) && !(defined(OS_LINUX) && !defined(OS_CHROMEOS))
// static
AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
return nullptr;
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc
new file mode 100644
index 0000000..b675dc4
--- /dev/null
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -0,0 +1,283 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/platform/ax_platform_node_auralinux.h"
+
+#include "base/command_line.h"
+#include "base/strings/sys_string_conversions.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/accessibility/platform/atk_util_auralinux.h"
+#include "ui/accessibility/platform/ax_platform_node_delegate.h"
+
+//
+// ax_platform_node_auralinux AtkObject definition and implementation.
+//
+
+G_BEGIN_DECLS
+
+#define AX_PLATFORM_NODE_AURALINUX_TYPE (ax_platform_node_auralinux_get_type())
+#define AX_PLATFORM_NODE_AURALINUX(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST( \
+ (obj), AX_PLATFORM_NODE_AURALINUX_TYPE, AXPlatformNodeAuraLinuxObject))
+#define AX_PLATFORM_NODE_AURALINUX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST( \
+ (klass), AX_PLATFORM_NODE_AURALINUX_TYPE, AXPlatformNodeAuraLinuxClass))
+#define IS_AX_PLATFORM_NODE_AURALINUX(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), AX_PLATFORM_NODE_AURALINUX_TYPE))
+#define IS_AX_PLATFORM_NODE_AURALINUX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), AX_PLATFORM_NODE_AURALINUX_TYPE))
+#define AX_PLATFORM_NODE_AURALINUX_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS( \
+ (obj), AX_PLATFORM_NODE_AURALINUX_TYPE, AXPlatformNodeAuraLinuxClass))
+
+typedef struct _AXPlatformNodeAuraLinuxObject AXPlatformNodeAuraLinuxObject;
+typedef struct _AXPlatformNodeAuraLinuxClass AXPlatformNodeAuraLinuxClass;
+
+struct _AXPlatformNodeAuraLinuxObject {
+ AtkObject parent;
+ ui::AXPlatformNodeAuraLinux* m_object;
+};
+
+struct _AXPlatformNodeAuraLinuxClass {
+ AtkObjectClass parent_class;
+};
+
+GType ax_platform_node_auralinux_get_type();
+
+static ui::AXPlatformNodeAuraLinux* ToAXPlatformNodeAuraLinux(
+ AXPlatformNodeAuraLinuxObject* atk_object) {
+ if (!atk_object)
+ return nullptr;
+
+ return atk_object->m_object;
+}
+
+static ui::AXPlatformNodeAuraLinux* AtkObjectToAXPlatformNodeAuraLinux(
+ AtkObject* atk_object) {
+ if (!atk_object)
+ return nullptr;
+
+ if (IS_AX_PLATFORM_NODE_AURALINUX(atk_object))
+ return ToAXPlatformNodeAuraLinux(AX_PLATFORM_NODE_AURALINUX(atk_object));
+
+ return nullptr;
+}
+
+static const gchar* ax_platform_node_auralinux_get_name(AtkObject* atk_object) {
+ ui::AXPlatformNodeAuraLinux* obj =
+ AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ if (!obj)
+ return nullptr;
+
+ return obj->GetStringAttribute(ui::AX_ATTR_NAME).c_str();
+}
+
+static const gchar* ax_platform_node_auralinux_get_description(
+ AtkObject* atk_object) {
+ ui::AXPlatformNodeAuraLinux* obj =
+ AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ if (!obj)
+ return nullptr;
+
+ return obj->GetStringAttribute(
+ ui::AX_ATTR_DESCRIPTION).c_str();
+}
+
+static AtkObject* ax_platform_node_auralinux_get_parent(AtkObject* atk_object) {
+ ui::AXPlatformNodeAuraLinux* obj =
+ AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ if (!obj)
+ return nullptr;
+
+ return obj->GetParent();
+}
+
+static gint ax_platform_node_auralinux_get_n_children(AtkObject* atk_object) {
+ ui::AXPlatformNodeAuraLinux* obj =
+ AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ if (!obj)
+ return 0;
+
+ return obj->GetChildCount();
+}
+
+static AtkObject* ax_platform_node_auralinux_ref_child(
+ AtkObject* atk_object, gint index) {
+ ui::AXPlatformNodeAuraLinux* obj =
+ AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ if (!obj)
+ return nullptr;
+
+ AtkObject* result = obj->ChildAtIndex(index);
+ if (result)
+ g_object_ref(result);
+ return result;
+}
+
+static AtkRole ax_platform_node_auralinux_get_role(AtkObject* atk_object) {
+ ui::AXPlatformNodeAuraLinux* obj =
+ AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ if (!obj)
+ return ATK_ROLE_INVALID;
+ return obj->GetAtkRole();
+}
+
+//
+// The rest of the AXPlatformNodeAuraLinux code, not specific to one
+// of the Atk* interfaces.
+//
+
+static gpointer ax_platform_node_auralinux_parent_class = nullptr;
+
+static void ax_platform_node_auralinux_init(AtkObject* atk_object,
+ gpointer data) {
+ if (ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class)->initialize) {
+ ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class)->initialize(
+ atk_object, data);
+ }
+
+ AX_PLATFORM_NODE_AURALINUX(atk_object)->m_object =
+ reinterpret_cast<ui::AXPlatformNodeAuraLinux*>(data);
+}
+
+static void ax_platform_node_auralinux_finalize(GObject* atk_object) {
+ G_OBJECT_CLASS(ax_platform_node_auralinux_parent_class)->finalize(atk_object);
+}
+
+static void ax_platform_node_auralinux_class_init(AtkObjectClass* klass) {
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ ax_platform_node_auralinux_parent_class = g_type_class_peek_parent(klass);
+
+ gobject_class->finalize = ax_platform_node_auralinux_finalize;
+ klass->initialize = ax_platform_node_auralinux_init;
+ klass->get_name = ax_platform_node_auralinux_get_name;
+ klass->get_description = ax_platform_node_auralinux_get_description;
+ klass->get_parent = ax_platform_node_auralinux_get_parent;
+ klass->get_n_children = ax_platform_node_auralinux_get_n_children;
+ klass->ref_child = ax_platform_node_auralinux_ref_child;
+ klass->get_role = ax_platform_node_auralinux_get_role;
+}
+
+GType ax_platform_node_auralinux_get_type() {
+ static volatile gsize type_volatile = 0;
+
+ if (g_once_init_enter(&type_volatile)) {
+ static const GTypeInfo tinfo = {
+ sizeof(AXPlatformNodeAuraLinuxClass),
+ (GBaseInitFunc) 0,
+ (GBaseFinalizeFunc) 0,
+ (GClassInitFunc) ax_platform_node_auralinux_class_init,
+ (GClassFinalizeFunc) 0,
+ 0, /* class data */
+ sizeof(AXPlatformNodeAuraLinuxObject), /* instance size */
+ 0, /* nb preallocs */
+ (GInstanceInitFunc) 0,
+ 0 /* value table */
+ };
+
+ GType type = g_type_register_static(
+ ATK_TYPE_OBJECT, "AXPlatformNodeAuraLinux", &tinfo, GTypeFlags(0));
+ g_once_init_leave(&type_volatile, type);
+ }
+
+ return type_volatile;
+}
+
+AXPlatformNodeAuraLinuxObject* ax_platform_node_auralinux_new(
+ ui::AXPlatformNodeAuraLinux* obj) {
+ #if !GLIB_CHECK_VERSION(2, 36, 0)
+ static bool first_time = true;
+ if (first_time) {
+ g_type_init();
+ first_time = false;
+ }
+ #endif
+
+ GType type = AX_PLATFORM_NODE_AURALINUX_TYPE;
+ AtkObject* atk_object = static_cast<AtkObject*>(g_object_new(type, 0));
+ atk_object_initialize(atk_object, obj);
+ return AX_PLATFORM_NODE_AURALINUX(atk_object);
+}
+
+void ax_platform_node_auralinux_detach(
+ AXPlatformNodeAuraLinuxObject* atk_object) {
+ atk_object->m_object = nullptr;
+}
+
+G_END_DECLS
+
+//
+// AXPlatformNodeAuraLinux implementation.
+//
+
+namespace ui {
+
+// static
+AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
+ AXPlatformNodeAuraLinux* node = new AXPlatformNodeAuraLinux();
+ node->Init(delegate);
+ return node;
+}
+
+// static
+AXPlatformNode* AXPlatformNodeAuraLinux::application_ = nullptr;
+
+// static
+void AXPlatformNodeAuraLinux::SetApplication(AXPlatformNode* application) {
+ application_ = application;
+ AtkUtilAuraLinux::GetInstance();
+}
+
+AtkRole AXPlatformNodeAuraLinux::GetAtkRole() {
+ switch (GetData().role) {
+ case ui::AX_ROLE_APPLICATION:
+ return ATK_ROLE_APPLICATION;
+ case ui::AX_ROLE_BUTTON:
+ return ATK_ROLE_PUSH_BUTTON;
+ case ui::AX_ROLE_CHECK_BOX:
+ return ATK_ROLE_CHECK_BOX;
+ case ui::AX_ROLE_COMBO_BOX:
+ return ATK_ROLE_COMBO_BOX;
+ case ui::AX_ROLE_STATIC_TEXT:
+ return ATK_ROLE_TEXT;
+ case ui::AX_ROLE_TEXT_FIELD:
+ return ATK_ROLE_ENTRY;
+ case ui::AX_ROLE_WINDOW:
+ return ATK_ROLE_WINDOW;
+ default:
+ return ATK_ROLE_UNKNOWN;
+ }
+}
+
+AXPlatformNodeAuraLinux::AXPlatformNodeAuraLinux()
+ : atk_object_(nullptr) {
+}
+
+AXPlatformNodeAuraLinux::~AXPlatformNodeAuraLinux() {
+ g_object_unref(atk_object_);
+}
+
+void AXPlatformNodeAuraLinux::Init(AXPlatformNodeDelegate* delegate) {
+ // Initialize ATK.
+ AXPlatformNodeBase::Init(delegate);
+ atk_object_ = ATK_OBJECT(ax_platform_node_auralinux_new(this));
+}
+
+void AXPlatformNodeAuraLinux::Destroy() {
+ delegate_ = nullptr;
+ delete this;
+}
+
+gfx::NativeViewAccessible AXPlatformNodeAuraLinux::GetNativeViewAccessible() {
+ return atk_object_;
+}
+
+void AXPlatformNodeAuraLinux::NotifyAccessibilityEvent(ui::AXEvent event_type) {
+}
+
+int AXPlatformNodeAuraLinux::GetIndexInParent() {
+ return 0;
+}
+
+} // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.h b/ui/accessibility/platform/ax_platform_node_auralinux.h
new file mode 100644
index 0000000..eea1427
--- /dev/null
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -0,0 +1,51 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_AX_PLATFORM_NODE_AURALINUX_H_
+#define UI_ACCESSIBILITY_AX_PLATFORM_NODE_AURALINUX_H_
+
+#include <atk/atk.h>
+
+#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/platform/ax_platform_node_base.h"
+
+namespace ui {
+
+// Implements accessibility on Aura Linux using ATK.
+class AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
+ public:
+ AXPlatformNodeAuraLinux();
+
+ // Set or get the root-level Application object that's the parent of all
+ // top-level windows.
+ AX_EXPORT static void SetApplication(AXPlatformNode* application);
+ static AXPlatformNode* application() { return application_; }
+
+ AtkRole GetAtkRole();
+
+ // AXPlatformNode overrides.
+ void Destroy() override;
+ gfx::NativeViewAccessible GetNativeViewAccessible() override;
+ void NotifyAccessibilityEvent(ui::AXEvent event_type) override;
+
+ // AXPlatformNodeBase overrides.
+ void Init(AXPlatformNodeDelegate* delegate) override;
+ int GetIndexInParent() override;
+
+ private:
+ ~AXPlatformNodeAuraLinux() override;
+
+ // We own a reference to this ref-counted object.
+ AtkObject* atk_object_;
+
+ // The root-level Application object that's the parent of all
+ // top-level windows.
+ static AXPlatformNode* application_;
+
+ DISALLOW_COPY_AND_ASSIGN(AXPlatformNodeAuraLinux);
+};
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_AX_PLATFORM_NODE_AURALINUX_H_
diff --git a/ui/accessibility/platform/ax_platform_node_base.h b/ui/accessibility/platform/ax_platform_node_base.h
index 7555ec0..324b239 100644
--- a/ui/accessibility/platform/ax_platform_node_base.h
+++ b/ui/accessibility/platform/ax_platform_node_base.h
@@ -61,6 +61,8 @@ class AXPlatformNodeBase : public AXPlatformNode {
base::string16 GetString16Attribute(
ui::AXStringAttribute attribute) const;
+ AXPlatformNodeDelegate* delegate_; // Weak. Owns this.
+
protected:
AXPlatformNodeBase();
~AXPlatformNodeBase() override;
@@ -70,7 +72,7 @@ class AXPlatformNodeBase : public AXPlatformNode {
static AXPlatformNodeBase* FromNativeViewAccessible(
gfx::NativeViewAccessible accessible);
- AXPlatformNodeDelegate* delegate_; // Weak. Owns this.
+
private:
DISALLOW_COPY_AND_ASSIGN(AXPlatformNodeBase);
diff --git a/ui/gfx/native_widget_types.h b/ui/gfx/native_widget_types.h
index 8cf8a5f..1a8256b 100644
--- a/ui/gfx/native_widget_types.h
+++ b/ui/gfx/native_widget_types.h
@@ -106,6 +106,13 @@ class ViewAndroid;
#endif
class SkBitmap;
+#if defined(USE_X11) && !defined(OS_CHROMEOS)
+extern "C" {
+struct _AtkObject;
+typedef struct _AtkObject AtkObject;
+}
+#endif
+
namespace gfx {
#if defined(USE_AURA)
@@ -164,8 +171,12 @@ typedef cairo_t* NativeDrawingContext;
#else
typedef void* NativeDrawingContext;
#endif // defined(USE_CAIRO)
+#if defined(USE_X11) && !defined(OS_CHROMEOS)
+typedef AtkObject* NativeViewAccessible;
+#else
typedef void* NativeViewAccessible;
#endif
+#endif
// A constant value to indicate that gfx::NativeCursor refers to no cursor.
#if defined(USE_AURA)
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 922ce0c..0ed3920 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -102,6 +102,7 @@ component("views") {
sources += gypi_values.views_desktop_aura_sources
if (use_x11) {
sources += gypi_values.views_desktop_aura_x11_sources
+ configs += [ "//build/config/linux:atk" ]
} else if (is_win) {
sources += gypi_values.views_desktop_aura_win_sources
} else if (use_ozone) {
diff --git a/ui/views/accessibility/native_view_accessibility.cc b/ui/views/accessibility/native_view_accessibility.cc
index aeb2c70..a11f773 100644
--- a/ui/views/accessibility/native_view_accessibility.cc
+++ b/ui/views/accessibility/native_view_accessibility.cc
@@ -13,7 +13,7 @@
namespace views {
-#if !defined(OS_WIN)
+#if !defined(OS_WIN) && !(defined(OS_LINUX) && !defined(OS_CHROMEOS))
// static
NativeViewAccessibility* NativeViewAccessibility::Create(View* view) {
return new NativeViewAccessibility(view);
@@ -23,7 +23,8 @@ NativeViewAccessibility* NativeViewAccessibility::Create(View* view) {
NativeViewAccessibility::NativeViewAccessibility(View* view)
: view_(view),
parent_widget_(nullptr),
- ax_node_(ui::AXPlatformNode::Create(this)) {
+ ax_node_(nullptr) {
+ ax_node_ = ui::AXPlatformNode::Create(this);
}
NativeViewAccessibility::~NativeViewAccessibility() {
diff --git a/ui/views/accessibility/native_view_accessibility_auralinux.cc b/ui/views/accessibility/native_view_accessibility_auralinux.cc
new file mode 100644
index 0000000..afee535
--- /dev/null
+++ b/ui/views/accessibility/native_view_accessibility_auralinux.cc
@@ -0,0 +1,164 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/accessibility/native_view_accessibility_auralinux.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "base/memory/singleton.h"
+#include "ui/accessibility/ax_enums.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/accessibility/platform/ax_platform_node_auralinux.h"
+#include "ui/accessibility/platform/ax_platform_node_delegate.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/views/views_delegate.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_observer.h"
+
+namespace views {
+
+namespace {
+
+// ATK requires that we have a single root "application" object that's the
+// owner of all other windows. This is a simple class that implements the
+// AXPlatformNodeDelegate interface so we can create such an application
+// object. Every time we create an accessibility object for a View, we add its
+// top-level widget to a vector so we can return the list of all top-level
+// windows as children of this application object.
+class AuraLinuxApplication
+ : public ui::AXPlatformNodeDelegate,
+ public WidgetObserver {
+ public:
+ // Get the single instance of this class.
+ static AuraLinuxApplication* GetInstance() {
+ return Singleton<AuraLinuxApplication>::get();
+ }
+
+ // Called every time we create a new accessibility on a View.
+ // Add the top-level widget to our registry so that we can enumerate all
+ // top-level widgets.
+ void RegisterWidget(Widget* widget) {
+ if (!widget)
+ return;
+
+ widget = widget->GetTopLevelWidget();
+ if (std::find(widgets_.begin(), widgets_.end(), widget) != widgets_.end())
+ return;
+
+ widgets_.push_back(widget);
+ widget->AddObserver(this);
+ }
+
+ gfx::NativeViewAccessible GetNativeViewAccessible() {
+ return platform_node_->GetNativeViewAccessible();
+ }
+
+ //
+ // WidgetObserver overrides.
+ //
+
+ void OnWidgetDestroying(Widget* widget) override {
+ auto iter = std::find(widgets_.begin(), widgets_.end(), widget);
+ if (iter != widgets_.end())
+ widgets_.erase(iter);
+ }
+
+ //
+ // ui::AXPlatformNodeDelegate overrides.
+ //
+
+ const ui::AXNodeData& GetData() override {
+ return data_;
+ }
+
+ gfx::NativeViewAccessible GetParent() override {
+ return nullptr;
+ }
+
+ int GetChildCount() override {
+ return static_cast<int>(widgets_.size());
+ }
+
+ gfx::NativeViewAccessible ChildAtIndex(int index) override {
+ if (index < 0 || index >= GetChildCount())
+ return nullptr;
+
+ Widget* widget = widgets_[index];
+ CHECK(widget);
+ return widget->GetRootView()->GetNativeViewAccessible();
+ }
+
+ gfx::Vector2d GetGlobalCoordinateOffset() override {
+ return gfx::Vector2d();
+ }
+
+ gfx::NativeViewAccessible HitTestSync(int x, int y) override {
+ return nullptr;
+ }
+
+ gfx::NativeViewAccessible GetFocus() override {
+ return nullptr;
+ }
+
+ gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override {
+ return gfx::kNullAcceleratedWidget;
+ }
+
+ void DoDefaultAction() override {
+ }
+
+ bool SetStringValue(const base::string16& new_value) override {
+ return false;
+ }
+
+ private:
+ friend struct DefaultSingletonTraits<AuraLinuxApplication>;
+
+ AuraLinuxApplication()
+ : platform_node_(ui::AXPlatformNode::Create(this)) {
+ data_.role = ui::AX_ROLE_APPLICATION;
+ if (ViewsDelegate::views_delegate) {
+ data_.AddStringAttribute(
+ ui::AX_ATTR_NAME,
+ ViewsDelegate::views_delegate->GetApplicationName());
+ }
+ ui::AXPlatformNodeAuraLinux::SetApplication(platform_node_);
+ }
+
+ ~AuraLinuxApplication() override {
+ platform_node_->Destroy();
+ platform_node_ = nullptr;
+ }
+
+ ui::AXPlatformNode* platform_node_;
+ ui::AXNodeData data_;
+ std::vector<Widget*> widgets_;
+
+ DISALLOW_COPY_AND_ASSIGN(AuraLinuxApplication);
+};
+
+} // namespace
+
+// static
+NativeViewAccessibility* NativeViewAccessibility::Create(View* view) {
+ AuraLinuxApplication::GetInstance()->RegisterWidget(view->GetWidget());
+ return new NativeViewAccessibilityAuraLinux(view);
+}
+
+NativeViewAccessibilityAuraLinux::NativeViewAccessibilityAuraLinux(View* view)
+ : NativeViewAccessibility(view) {
+}
+
+NativeViewAccessibilityAuraLinux::~NativeViewAccessibilityAuraLinux() {
+}
+
+gfx::NativeViewAccessible NativeViewAccessibilityAuraLinux::GetParent() {
+ gfx::NativeViewAccessible parent = NativeViewAccessibility::GetParent();
+ if (!parent)
+ parent = AuraLinuxApplication::GetInstance()->GetNativeViewAccessible();
+ return parent;
+}
+
+} // namespace views
diff --git a/ui/views/accessibility/native_view_accessibility_auralinux.h b/ui/views/accessibility/native_view_accessibility_auralinux.h
new file mode 100644
index 0000000..f817dc7
--- /dev/null
+++ b/ui/views/accessibility/native_view_accessibility_auralinux.h
@@ -0,0 +1,27 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ACCESSIBILITY_NATIVE_VIEW_ACCESSIBILITY_AURALINUX_H_
+#define UI_VIEWS_ACCESSIBILITY_NATIVE_VIEW_ACCESSIBILITY_AURALINUX_H_
+
+#include "ui/views/accessibility/native_view_accessibility.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+class NativeViewAccessibilityAuraLinux : public NativeViewAccessibility {
+ public:
+ NativeViewAccessibilityAuraLinux(View* view);
+ ~NativeViewAccessibilityAuraLinux() override;
+
+ // NativeViewAccessibility.
+ gfx::NativeViewAccessible GetParent() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NativeViewAccessibilityAuraLinux);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ACCESSIBILITY_NATIVE_VIEW_ACCESSIBILITY_AURALINUX_H_
diff --git a/ui/views/views.gyp b/ui/views/views.gyp
index 0b92a2c..e73f361 100644
--- a/ui/views/views.gyp
+++ b/ui/views/views.gyp
@@ -423,6 +423,8 @@
'widget/desktop_aura/desktop_cursor_loader_updater_auralinux.h',
],
'views_desktop_aura_x11_sources': [
+ 'accessibility/native_view_accessibility_auralinux.cc',
+ 'accessibility/native_view_accessibility_auralinux.h',
'widget/desktop_aura/desktop_drag_drop_client_aurax11.cc',
'widget/desktop_aura/desktop_drag_drop_client_aurax11.h',
'widget/desktop_aura/desktop_screen_x11.cc',
@@ -635,6 +637,7 @@
}],
['OS=="linux" and chromeos==0', {
'dependencies': [
+ '../../build/linux/system.gyp:atk',
'../shell_dialogs/shell_dialogs.gyp:shell_dialogs',
],
'sources!': [
diff --git a/ui/views/views_delegate.cc b/ui/views/views_delegate.cc
index de9ccbb..4c1ae4f 100644
--- a/ui/views/views_delegate.cc
+++ b/ui/views/views_delegate.cc
@@ -4,6 +4,7 @@
#include "ui/views/views_delegate.h"
+#include "base/command_line.h"
#include "ui/views/views_touch_selection_controller_factory.h"
namespace views {
@@ -85,6 +86,11 @@ ui::ContextFactory* ViewsDelegate::GetContextFactory() {
return NULL;
}
+std::string ViewsDelegate::GetApplicationName() {
+ base::FilePath program = base::CommandLine::ForCurrentProcess()->GetProgram();
+ return program.BaseName().AsUTF8Unsafe();
+}
+
#if defined(OS_WIN)
int ViewsDelegate::GetAppbarAutohideEdges(HMONITOR monitor,
const base::Closure& callback) {
diff --git a/ui/views/views_delegate.h b/ui/views/views_delegate.h
index 6cc5a6b..ea14e78 100644
--- a/ui/views/views_delegate.h
+++ b/ui/views/views_delegate.h
@@ -135,6 +135,9 @@ class VIEWS_EXPORT ViewsDelegate {
// Returns the context factory for new windows.
virtual ui::ContextFactory* GetContextFactory();
+ // Returns the user-visible name of the application.
+ virtual std::string GetApplicationName();
+
#if defined(OS_WIN)
// Starts a query for the appbar autohide edges of the specified monitor and
// returns the current value. If the query finds the edges have changed from