Use GTK frame button layout when available
BUG=21438
R=erg@chromium.org
Change-Id: I9c596a297a48ab7b4405fbe13b99ddede99c5d54
Reviewed-on: https://chromium-review.googlesource.com/629317
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Reviewed-by: Elliot Glaysher <erg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#497169}
diff --git a/chrome/browser/ui/libgtkui/BUILD.gn b/chrome/browser/ui/libgtkui/BUILD.gn
index d53109c..33b4f820 100644
--- a/chrome/browser/ui/libgtkui/BUILD.gn
+++ b/chrome/browser/ui/libgtkui/BUILD.gn
@@ -47,6 +47,7 @@
"libgtkui_export.h",
"menu_util.cc",
"menu_util.h",
+ "nav_button_layout_manager.h",
"print_dialog_gtk.cc",
"print_dialog_gtk.h",
"printing_gtk_util.cc",
@@ -68,8 +69,8 @@
if (use_gconf) {
sources += [
- "gconf_listener.cc",
- "gconf_listener.h",
+ "nav_button_layout_manager_gconf.cc",
+ "nav_button_layout_manager_gconf.h",
]
configs += [ "//build/config/linux/gconf" ]
}
@@ -127,6 +128,8 @@
sources = [
"native_theme_gtk3.cc",
"native_theme_gtk3.h",
+ "nav_button_layout_manager_gtk3.cc",
+ "nav_button_layout_manager_gtk3.h",
"nav_button_provider_gtk3.cc",
"nav_button_provider_gtk3.h",
]
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.cc b/chrome/browser/ui/libgtkui/gtk_ui.cc
index 668d049..f1c3a3d 100644
--- a/chrome/browser/ui/libgtkui/gtk_ui.cc
+++ b/chrome/browser/ui/libgtkui/gtk_ui.cc
@@ -68,14 +68,16 @@
#include "chrome/browser/ui/libgtkui/native_theme_gtk2.h" // nogncheck
#elif GTK_MAJOR_VERSION == 3
#include "chrome/browser/ui/libgtkui/native_theme_gtk3.h" // nogncheck
+#include "chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.h" // nogncheck
#include "chrome/browser/ui/libgtkui/nav_button_provider_gtk3.h" // nogncheck
#endif
#if BUILDFLAG(ENABLE_BASIC_PRINTING)
#include "printing/printing_context_linux.h"
#endif
+
#if defined(USE_GCONF)
-#include "chrome/browser/ui/libgtkui/gconf_listener.h"
+#include "chrome/browser/ui/libgtkui/nav_button_layout_manager_gconf.h"
#endif
// A minimized port of GtkThemeService into something that can provide colors
@@ -90,6 +92,15 @@
namespace {
+// We would like this to be a feature flag, but GtkUi gets initialized
+// earlier than the feature flag registry, so just use a simple bool.
+// The reason for wanting a flag is so that we can release the GTK3
+// nav button layout manager and the GTK3 nav button provider at the
+// same time (so users don't have to deal with things changing twice).
+// Since this was never really intended to be toggled by users, this
+// is fine for now.
+const bool kUseGtkNavButtonLayoutManager = false;
+
const double kDefaultDPI = 96;
class GtkButtonImageSource : public gfx::ImageSkiaSource {
@@ -268,6 +279,18 @@
// The unknown content type.
const char* kUnknownContentType = "application/octet-stream";
+std::unique_ptr<NavButtonLayoutManager> CreateNavButtonLayoutManager(
+ GtkUi* gtk_ui) {
+#if GTK_MAJOR_VERSION == 3
+ if (GtkVersionCheck(3, 10) && kUseGtkNavButtonLayoutManager)
+ return std::make_unique<NavButtonLayoutManagerGtk3>(gtk_ui);
+#endif
+#if defined(USE_GCONF)
+ return std::make_unique<NavButtonLayoutManagerGconf>(gtk_ui);
+#endif
+ return nullptr;
+}
+
// Returns a gfx::FontRenderParams corresponding to GTK's configuration.
gfx::FontRenderParams GetGtkFontRenderParams() {
GtkSettings* gtk_settings = gtk_settings_get_default();
@@ -449,10 +472,8 @@
&GetPdfPaperSizeDeviceUnitsGtk);
#endif
-#if defined(USE_GCONF)
// We must build this after GTK gets initialized.
- gconf_listener_.reset(new GConfListener(this));
-#endif // defined(USE_GCONF)
+ nav_button_layout_manager_ = CreateNavButtonLayoutManager(this);
indicators_count = 0;
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.h b/chrome/browser/ui/libgtkui/gtk_ui.h
index 201414c..c3e7721 100644
--- a/chrome/browser/ui/libgtkui/gtk_ui.h
+++ b/chrome/browser/ui/libgtkui/gtk_ui.h
@@ -24,8 +24,8 @@
namespace libgtkui {
class Gtk2KeyBindingsHandler;
-class GConfListener;
class DeviceScaleFactorObserver;
+class NavButtonLayoutManager;
// Interface to GTK2 desktop features.
//
@@ -37,7 +37,7 @@
typedef base::Callback<ui::NativeTheme*(aura::Window* window)>
NativeThemeGetter;
- // Setters used by GConfListener:
+ // Setters used by NavButtonLayoutManager:
void SetWindowButtonOrdering(
const std::vector<views::FrameButton>& leading_buttons,
const std::vector<views::FrameButton>& trailing_buttons);
@@ -171,11 +171,7 @@
gfx::Font::Weight default_font_weight_ = gfx::Font::Weight::NORMAL;
gfx::FontRenderParams default_font_render_params_;
-#if defined(USE_GCONF)
- // Currently, the only source of window button configuration. This will
- // change if we ever have to support XFCE's configuration system or KDE's.
- std::unique_ptr<GConfListener> gconf_listener_;
-#endif // defined(USE_GCONF)
+ std::unique_ptr<NavButtonLayoutManager> nav_button_layout_manager_;
// If either of these vectors are non-empty, they represent the current
// window button configuration.
diff --git a/chrome/browser/ui/libgtkui/gtk_util.cc b/chrome/browser/ui/libgtkui/gtk_util.cc
index a5224ea..09191e00 100644
--- a/chrome/browser/ui/libgtkui/gtk_util.cc
+++ b/chrome/browser/ui/libgtkui/gtk_util.cc
@@ -198,6 +198,34 @@
g_object_set_data(G_OBJECT(dialog), kAuraTransientParent, nullptr);
}
+void ParseButtonLayout(const std::string& button_string,
+ std::vector<views::FrameButton>* leading_buttons,
+ std::vector<views::FrameButton>* trailing_buttons) {
+ leading_buttons->clear();
+ trailing_buttons->clear();
+ bool left_side = true;
+ base::StringTokenizer tokenizer(button_string, ":,");
+ tokenizer.set_options(base::StringTokenizer::RETURN_DELIMS);
+ while (tokenizer.GetNext()) {
+ if (tokenizer.token_is_delim()) {
+ if (*tokenizer.token_begin() == ':')
+ left_side = false;
+ } else {
+ base::StringPiece token = tokenizer.token_piece();
+ if (token == "minimize") {
+ (left_side ? leading_buttons : trailing_buttons)
+ ->push_back(views::FRAME_BUTTON_MINIMIZE);
+ } else if (token == "maximize") {
+ (left_side ? leading_buttons : trailing_buttons)
+ ->push_back(views::FRAME_BUTTON_MAXIMIZE);
+ } else if (token == "close") {
+ (left_side ? leading_buttons : trailing_buttons)
+ ->push_back(views::FRAME_BUTTON_CLOSE);
+ }
+ }
+ }
+}
+
#if GTK_MAJOR_VERSION > 2
void* GetGdkSharedLibrary() {
std::string lib_name =
diff --git a/chrome/browser/ui/libgtkui/gtk_util.h b/chrome/browser/ui/libgtkui/gtk_util.h
index cc6725b..1b0bf63 100644
--- a/chrome/browser/ui/libgtkui/gtk_util.h
+++ b/chrome/browser/ui/libgtkui/gtk_util.h
@@ -10,6 +10,7 @@
#include "ui/base/glib/scoped_gobject.h"
#include "ui/native_theme/native_theme.h"
+#include "ui/views/window/frame_buttons.h"
namespace aura {
class Window;
@@ -76,6 +77,14 @@
// Clears the transient parent for |dialog|.
void ClearAuraTransientParent(GtkWidget* dialog);
+// Parses |button_string| into |leading_buttons| and
+// |trailing_buttons|. The string is of the format
+// "<button>*:<button*>", for example, "close:minimize:maximize".
+// This format is used by GTK3 settings and several gconf settings.
+void ParseButtonLayout(const std::string& button_string,
+ std::vector<views::FrameButton>* leading_buttons,
+ std::vector<views::FrameButton>* trailing_buttons);
+
#if GTK_MAJOR_VERSION > 2
// These constants are defined in gtk/gtkenums.h in Gtk3.12 or later.
// They are added here as a convenience to avoid version checks, and
diff --git a/chrome/browser/ui/libgtkui/nav_button_layout_manager.h b/chrome/browser/ui/libgtkui/nav_button_layout_manager.h
new file mode 100644
index 0000000..018bba78
--- /dev/null
+++ b/chrome/browser/ui/libgtkui/nav_button_layout_manager.h
@@ -0,0 +1,31 @@
+// Copyright 2017 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 CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_H_
+#define CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_H_
+
+#include <string>
+#include <vector>
+
+namespace libgtkui {
+
+// This class is just a switch between NavButtonLayoutManagerGconf and
+// NavButtonLayoutManagerGtk3. Currently, it is empty and it's only
+// purpose is so that GtkUi can store just a
+// std::unique_ptr<NavButtonLayoutManager> and not have to have the
+// two impls each guarded by their own macros.
+class NavButtonLayoutManager {
+ public:
+ virtual ~NavButtonLayoutManager() {}
+
+ protected:
+ // Even though this class is not pure virtual, it should not be
+ // instantiated directly. Use NavButtonLayoutManagerGconf or
+ // NavButtonLayoutManagerGtk3 instead.
+ NavButtonLayoutManager() {}
+};
+
+} // namespace libgtkui
+
+#endif // CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_H_
diff --git a/chrome/browser/ui/libgtkui/gconf_listener.cc b/chrome/browser/ui/libgtkui/nav_button_layout_manager_gconf.cc
similarity index 71%
rename from chrome/browser/ui/libgtkui/gconf_listener.cc
rename to chrome/browser/ui/libgtkui/nav_button_layout_manager_gconf.cc
index 9beea250..946ff163 100644
--- a/chrome/browser/ui/libgtkui/gconf_listener.cc
+++ b/chrome/browser/ui/libgtkui/nav_button_layout_manager_gconf.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/ui/libgtkui/gconf_listener.h"
+#include "chrome/browser/ui/libgtkui/nav_button_layout_manager_gconf.h"
#include <gtk/gtk.h>
@@ -12,9 +12,8 @@
#include "base/callback.h"
#include "base/environment.h"
#include "base/nix/xdg_util.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_tokenizer.h"
#include "chrome/browser/ui/libgtkui/gtk_ui.h"
+#include "chrome/browser/ui/libgtkui/gtk_util.h"
#include "ui/base/x/x11_util.h"
#include "ui/views/window/frame_buttons.h"
@@ -42,7 +41,7 @@
// Public interface:
-GConfListener::GConfListener(GtkUi* delegate)
+NavButtonLayoutManagerGconf::NavButtonLayoutManagerGconf(GtkUi* delegate)
: delegate_(delegate), client_(nullptr) {
std::unique_ptr<base::Environment> env(base::Environment::Create());
base::nix::DesktopEnvironment de =
@@ -62,27 +61,28 @@
return;
// Get the initial value of the keys we're interested in.
- GetAndRegister(kButtonLayoutKey,
- base::Bind(&GConfListener::ParseAndStoreButtonValue,
- base::Unretained(this)));
- GetAndRegister(kMiddleClickActionKey,
- base::Bind(&GConfListener::ParseAndStoreMiddleClickValue,
- base::Unretained(this)));
+ GetAndRegister(
+ kButtonLayoutKey,
+ base::Bind(&NavButtonLayoutManagerGconf::ParseAndStoreButtonValue,
+ base::Unretained(this)));
+ GetAndRegister(
+ kMiddleClickActionKey,
+ base::Bind(
+ &NavButtonLayoutManagerGconf::ParseAndStoreMiddleClickValue,
+ base::Unretained(this)));
}
}
}
-GConfListener::~GConfListener() {
-}
+NavButtonLayoutManagerGconf::~NavButtonLayoutManagerGconf() {}
// Private:
-void GConfListener::GetAndRegister(
+void NavButtonLayoutManagerGconf::GetAndRegister(
const char* key_to_subscribe,
const base::Callback<void(GConfValue*)>& initial_setter) {
GError* error = nullptr;
- GConfValue* gconf_value = gconf_client_get(client_, key_to_subscribe,
- &error);
+ GConfValue* gconf_value = gconf_client_get(client_, key_to_subscribe, &error);
if (HandleGError(error, key_to_subscribe))
return;
initial_setter.Run(gconf_value);
@@ -99,9 +99,9 @@
return;
}
-void GConfListener::OnChangeNotification(GConfClient* client,
- guint cnxn_id,
- GConfEntry* entry) {
+void NavButtonLayoutManagerGconf::OnChangeNotification(GConfClient* client,
+ guint cnxn_id,
+ GConfEntry* entry) {
if (strcmp(gconf_entry_get_key(entry), kButtonLayoutKey) == 0) {
GConfValue* gconf_value = gconf_entry_get_value(entry);
ParseAndStoreButtonValue(gconf_value);
@@ -111,7 +111,7 @@
}
}
-bool GConfListener::HandleGError(GError* error, const char* key) {
+bool NavButtonLayoutManagerGconf::HandleGError(GError* error, const char* key) {
if (error != nullptr) {
LOG(ERROR) << "Error with gconf key '" << key << "': " << error->message;
g_error_free(error);
@@ -122,7 +122,8 @@
return false;
}
-void GConfListener::ParseAndStoreButtonValue(GConfValue* gconf_value) {
+void NavButtonLayoutManagerGconf::ParseAndStoreButtonValue(
+ GConfValue* gconf_value) {
std::string button_string;
if (gconf_value) {
const char* value = gconf_value_get_string(gconf_value);
@@ -131,35 +132,14 @@
button_string = kDefaultButtonString;
}
- // Parse the button_layout string.
std::vector<views::FrameButton> leading_buttons;
std::vector<views::FrameButton> trailing_buttons;
- bool left_side = true;
- base::StringTokenizer tokenizer(button_string, ":,");
- tokenizer.set_options(base::StringTokenizer::RETURN_DELIMS);
- while (tokenizer.GetNext()) {
- if (tokenizer.token_is_delim()) {
- if (*tokenizer.token_begin() == ':')
- left_side = false;
- } else {
- base::StringPiece token = tokenizer.token_piece();
- if (token == "minimize") {
- (left_side ? leading_buttons : trailing_buttons).push_back(
- views::FRAME_BUTTON_MINIMIZE);
- } else if (token == "maximize") {
- (left_side ? leading_buttons : trailing_buttons).push_back(
- views::FRAME_BUTTON_MAXIMIZE);
- } else if (token == "close") {
- (left_side ? leading_buttons : trailing_buttons).push_back(
- views::FRAME_BUTTON_CLOSE);
- }
- }
- }
-
+ ParseButtonLayout(button_string, &leading_buttons, &trailing_buttons);
delegate_->SetWindowButtonOrdering(leading_buttons, trailing_buttons);
}
-void GConfListener::ParseAndStoreMiddleClickValue(GConfValue* gconf_value) {
+void NavButtonLayoutManagerGconf::ParseAndStoreMiddleClickValue(
+ GConfValue* gconf_value) {
GtkUi::NonClientMiddleClickAction action =
views::LinuxUI::MIDDLE_CLICK_ACTION_LOWER;
if (gconf_value) {
diff --git a/chrome/browser/ui/libgtkui/gconf_listener.h b/chrome/browser/ui/libgtkui/nav_button_layout_manager_gconf.h
similarity index 65%
rename from chrome/browser/ui/libgtkui/gconf_listener.h
rename to chrome/browser/ui/libgtkui/nav_button_layout_manager_gconf.h
index 75d33696..4d3b80b5 100644
--- a/chrome/browser/ui/libgtkui/gconf_listener.h
+++ b/chrome/browser/ui/libgtkui/nav_button_layout_manager_gconf.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_UI_LIBGTKUI_GCONF_LISTENER_H_
-#define CHROME_BROWSER_UI_LIBGTKUI_GCONF_LISTENER_H_
+#ifndef CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_GCONF_H_
+#define CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_GCONF_H_
#include <gconf/gconf-client.h>
#include <gtk/gtk.h>
@@ -14,6 +14,7 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "chrome/browser/ui/libgtkui/gtk_signal.h"
+#include "chrome/browser/ui/libgtkui/nav_button_layout_manager.h"
namespace libgtkui {
class GtkUi;
@@ -21,16 +22,20 @@
// On GNOME desktops, subscribes to the gconf key which controlls button order.
// Everywhere else, SetTiltebarButtons() just calls back into BrowserTitlebar
// with the default ordering.
-class GConfListener {
+class NavButtonLayoutManagerGconf : public NavButtonLayoutManager {
public:
// Sends data to the GtkUi when available.
- explicit GConfListener(GtkUi* delegate);
- ~GConfListener();
+ explicit NavButtonLayoutManagerGconf(GtkUi* delegate);
+ ~NavButtonLayoutManagerGconf() override;
private:
// Called whenever the metacity key changes.
- CHROMEG_CALLBACK_2(GConfListener, void, OnChangeNotification,
- GConfClient*, guint, GConfEntry*);
+ CHROMEG_CALLBACK_2(NavButtonLayoutManagerGconf,
+ void,
+ OnChangeNotification,
+ GConfClient*,
+ guint,
+ GConfEntry*);
void GetAndRegister(const char* key_to_subscribe,
const base::Callback<void(GConfValue*)>& initial_setter);
@@ -50,9 +55,9 @@
// gconf.
GConfClient* client_;
- DISALLOW_COPY_AND_ASSIGN(GConfListener);
+ DISALLOW_COPY_AND_ASSIGN(NavButtonLayoutManagerGconf);
};
} // namespace libgtkui
-#endif // CHROME_BROWSER_UI_LIBGTKUI_GCONF_LISTENER_H_
+#endif // CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_GCONF_H_
diff --git a/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.cc b/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.cc
new file mode 100644
index 0000000..5fdc45d3
--- /dev/null
+++ b/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.cc
@@ -0,0 +1,93 @@
+// Copyright 2017 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 "chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.h"
+
+#include "base/strings/string_split.h"
+#include "chrome/browser/ui/libgtkui/gtk_ui.h"
+#include "chrome/browser/ui/libgtkui/gtk_util.h"
+
+namespace libgtkui {
+
+namespace {
+
+const char kDefaultGtkLayout[] = "menu:minimize,maximize,close";
+
+std::string GetGtkSettingsStringProperty(GtkSettings* settings,
+ const gchar* prop_name) {
+ GValue layout = G_VALUE_INIT;
+ g_value_init(&layout, G_TYPE_STRING);
+ g_object_get_property(G_OBJECT(settings), prop_name, &layout);
+ DCHECK(G_VALUE_HOLDS_STRING(&layout));
+ std::string prop_value(g_value_get_string(&layout));
+ g_value_unset(&layout);
+ return prop_value;
+}
+
+std::string GetDecorationLayoutFromGtkWindow() {
+ static ScopedStyleContext context;
+ if (!context) {
+ context = GetStyleContextFromCss("");
+ gtk_style_context_add_class(context, "csd");
+ }
+
+ gchar* layout_c = nullptr;
+ gtk_style_context_get_style(context, "decoration-button-layout", &layout_c,
+ nullptr);
+ DCHECK(layout_c);
+ std::string layout(layout_c);
+ g_free(layout_c);
+ return layout;
+}
+
+} // namespace
+
+NavButtonLayoutManagerGtk3::NavButtonLayoutManagerGtk3(GtkUi* delegate)
+ : delegate_(delegate), signal_id_(0) {
+ DCHECK(delegate_);
+ GtkSettings* settings = gtk_settings_get_default();
+ if (GtkVersionCheck(3, 14)) {
+ signal_id_ = g_signal_connect(
+ settings, "notify::gtk-decoration-layout",
+ G_CALLBACK(OnDecorationButtonLayoutChangedThunk), this);
+ DCHECK(signal_id_);
+ OnDecorationButtonLayoutChanged(settings, nullptr);
+ } else if (GtkVersionCheck(3, 10, 3)) {
+ signal_id_ = g_signal_connect_after(settings, "notify::gtk-theme-name",
+ G_CALLBACK(OnThemeChangedThunk), this);
+ DCHECK(signal_id_);
+ OnThemeChanged(settings, nullptr);
+ } else {
+ // On versions older than 3.10.3, the layout was hardcoded.
+ SetWindowButtonOrderingFromGtkLayout(kDefaultGtkLayout);
+ }
+}
+
+NavButtonLayoutManagerGtk3::~NavButtonLayoutManagerGtk3() {
+ if (signal_id_)
+ g_signal_handler_disconnect(gtk_settings_get_default(), signal_id_);
+}
+
+void NavButtonLayoutManagerGtk3::SetWindowButtonOrderingFromGtkLayout(
+ const std::string& gtk_layout) {
+ std::vector<views::FrameButton> leading_buttons;
+ std::vector<views::FrameButton> trailing_buttons;
+ ParseButtonLayout(gtk_layout, &leading_buttons, &trailing_buttons);
+ delegate_->SetWindowButtonOrdering(leading_buttons, trailing_buttons);
+}
+
+void NavButtonLayoutManagerGtk3::OnDecorationButtonLayoutChanged(
+ GtkSettings* settings,
+ GParamSpec* param) {
+ SetWindowButtonOrderingFromGtkLayout(
+ GetGtkSettingsStringProperty(settings, "gtk-decoration-layout"));
+}
+
+void NavButtonLayoutManagerGtk3::OnThemeChanged(GtkSettings* settings,
+ GParamSpec* param) {
+ std::string layout = GetDecorationLayoutFromGtkWindow();
+ SetWindowButtonOrderingFromGtkLayout(layout);
+}
+
+} // namespace libgtkui
diff --git a/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.h b/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.h
new file mode 100644
index 0000000..938a084
--- /dev/null
+++ b/chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.h
@@ -0,0 +1,50 @@
+// Copyright 2017 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 CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_GTK3_H_
+#define CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_GTK3_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/ui/libgtkui/nav_button_layout_manager.h"
+#include "ui/base/glib/glib_signal.h"
+
+typedef struct _GParamSpec GParamSpec;
+typedef struct _GtkSettings GtkSettings;
+
+namespace libgtkui {
+
+class GtkUi;
+
+class NavButtonLayoutManagerGtk3 : public NavButtonLayoutManager {
+ public:
+ explicit NavButtonLayoutManagerGtk3(GtkUi* delegate);
+ ~NavButtonLayoutManagerGtk3() override;
+
+ private:
+ void SetWindowButtonOrderingFromGtkLayout(const std::string& gtk_layout);
+
+ CHROMEG_CALLBACK_1(NavButtonLayoutManagerGtk3,
+ void,
+ OnDecorationButtonLayoutChanged,
+ GtkSettings*,
+ GParamSpec*);
+
+ CHROMEG_CALLBACK_1(NavButtonLayoutManagerGtk3,
+ void,
+ OnThemeChanged,
+ GtkSettings*,
+ GParamSpec*);
+
+ GtkUi* delegate_;
+
+ unsigned long signal_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(NavButtonLayoutManagerGtk3);
+};
+
+} // namespace libgtkui
+
+#endif // CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_GTK3_H_