Commit 3ada8cbd authored by Tom Anderson's avatar Tom Anderson Committed by Commit Bot

Respect GTK settings when double-clicking or right-clicking the titlebar

BUG=789405
R=erg@chromium.org,sky@chromium.org

Change-Id: I9b313c1027cd5ac69ed1b3545f909b60a648b148
Reviewed-on: https://chromium-review.googlesource.com/803666
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Reviewed-by: default avatarElliot Glaysher <erg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#523354}
parent 696ce2f4
...@@ -47,7 +47,7 @@ template("libgtkui") { ...@@ -47,7 +47,7 @@ template("libgtkui") {
"libgtkui_export.h", "libgtkui_export.h",
"menu_util.cc", "menu_util.cc",
"menu_util.h", "menu_util.h",
"nav_button_layout_manager.h", "settings_provider.h",
"print_dialog_gtk.cc", "print_dialog_gtk.cc",
"print_dialog_gtk.h", "print_dialog_gtk.h",
"printing_gtk_util.cc", "printing_gtk_util.cc",
...@@ -72,8 +72,8 @@ template("libgtkui") { ...@@ -72,8 +72,8 @@ template("libgtkui") {
if (use_gio) { if (use_gio) {
sources += [ sources += [
"nav_button_layout_manager_gsettings.cc", "settings_provider_gsettings.cc",
"nav_button_layout_manager_gsettings.h", "settings_provider_gsettings.h",
] ]
configs += [ "//build/linux:gio_config" ] configs += [ "//build/linux:gio_config" ]
} }
...@@ -134,10 +134,10 @@ if (use_gtk3) { ...@@ -134,10 +134,10 @@ if (use_gtk3) {
"gtk3_background_painter.h", "gtk3_background_painter.h",
"native_theme_gtk3.cc", "native_theme_gtk3.cc",
"native_theme_gtk3.h", "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.cc",
"nav_button_provider_gtk3.h", "nav_button_provider_gtk3.h",
"settings_provider_gtk3.cc",
"settings_provider_gtk3.h",
] ]
deps = [ deps = [
"//build/config/linux/gtk3", "//build/config/linux/gtk3",
......
...@@ -68,13 +68,13 @@ ...@@ -68,13 +68,13 @@
#if GTK_MAJOR_VERSION == 2 #if GTK_MAJOR_VERSION == 2
#include "chrome/browser/ui/libgtkui/native_theme_gtk2.h" // nogncheck #include "chrome/browser/ui/libgtkui/native_theme_gtk2.h" // nogncheck
#elif GTK_MAJOR_VERSION == 3 #elif GTK_MAJOR_VERSION == 3
#include "chrome/browser/ui/libgtkui/native_theme_gtk3.h" // nogncheck #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 #include "chrome/browser/ui/libgtkui/nav_button_provider_gtk3.h" // nogncheck
#include "chrome/browser/ui/libgtkui/settings_provider_gtk3.h" // nogncheck
#endif #endif
#if defined(USE_GIO) #if defined(USE_GIO)
#include "chrome/browser/ui/libgtkui/nav_button_layout_manager_gsettings.h" #include "chrome/browser/ui/libgtkui/settings_provider_gsettings.h"
#endif #endif
#if BUILDFLAG(ENABLE_BASIC_PRINTING) #if BUILDFLAG(ENABLE_BASIC_PRINTING)
...@@ -275,14 +275,13 @@ int indicators_count; ...@@ -275,14 +275,13 @@ int indicators_count;
// The unknown content type. // The unknown content type.
const char* kUnknownContentType = "application/octet-stream"; const char* kUnknownContentType = "application/octet-stream";
std::unique_ptr<NavButtonLayoutManager> CreateNavButtonLayoutManager( std::unique_ptr<SettingsProvider> CreateSettingsProvider(GtkUi* gtk_ui) {
GtkUi* gtk_ui) {
#if GTK_MAJOR_VERSION == 3 #if GTK_MAJOR_VERSION == 3
if (GtkVersionCheck(3, 14)) if (GtkVersionCheck(3, 14))
return std::make_unique<NavButtonLayoutManagerGtk3>(gtk_ui); return std::make_unique<SettingsProviderGtk3>(gtk_ui);
#endif #endif
#if defined(USE_GIO) #if defined(USE_GIO)
return std::make_unique<NavButtonLayoutManagerGSettings>(gtk_ui); return std::make_unique<SettingsProviderGSettings>(gtk_ui);
#else #else
return nullptr; return nullptr;
#endif #endif
...@@ -337,7 +336,11 @@ gfx::FontRenderParams GetGtkFontRenderParams() { ...@@ -337,7 +336,11 @@ gfx::FontRenderParams GetGtkFontRenderParams() {
return params; return params;
} }
views::LinuxUI::NonClientMiddleClickAction GetDefaultMiddleClickAction() { views::LinuxUI::NonClientWindowFrameAction GetDefaultMiddleClickAction() {
#if GTK_MAJOR_VERSION == 3
if (GtkVersionCheck(3, 14))
return views::LinuxUI::WINDOW_FRAME_ACTION_NONE;
#endif
std::unique_ptr<base::Environment> env(base::Environment::Create()); std::unique_ptr<base::Environment> env(base::Environment::Create());
switch (base::nix::GetDesktopEnvironment(env.get())) { switch (base::nix::GetDesktopEnvironment(env.get())) {
case base::nix::DESKTOP_ENVIRONMENT_KDE4: case base::nix::DESKTOP_ENVIRONMENT_KDE4:
...@@ -346,9 +349,9 @@ views::LinuxUI::NonClientMiddleClickAction GetDefaultMiddleClickAction() { ...@@ -346,9 +349,9 @@ views::LinuxUI::NonClientMiddleClickAction GetDefaultMiddleClickAction() {
// middle mouse button to create tab groups. We don't support that in // middle mouse button to create tab groups. We don't support that in
// Chrome, but at least avoid lowering windows in response to middle // Chrome, but at least avoid lowering windows in response to middle
// clicks to avoid surprising users who expect the KDE behavior. // clicks to avoid surprising users who expect the KDE behavior.
return views::LinuxUI::MIDDLE_CLICK_ACTION_NONE; return views::LinuxUI::WINDOW_FRAME_ACTION_NONE;
default: default:
return views::LinuxUI::MIDDLE_CLICK_ACTION_LOWER; return views::LinuxUI::WINDOW_FRAME_ACTION_LOWER;
} }
} }
...@@ -413,7 +416,13 @@ PROTECTED_MEMORY_SECTION base::ProtectedMemory<GdkSetAllowedBackendsFn> ...@@ -413,7 +416,13 @@ PROTECTED_MEMORY_SECTION base::ProtectedMemory<GdkSetAllowedBackendsFn>
} // namespace } // namespace
GtkUi::GtkUi() : middle_click_action_(GetDefaultMiddleClickAction()) { GtkUi::GtkUi() {
window_frame_actions_[WINDOW_FRAME_ACTION_SOURCE_DOUBLE_CLICK] =
views::LinuxUI::WINDOW_FRAME_ACTION_TOGGLE_MAXIMIZE;
window_frame_actions_[WINDOW_FRAME_ACTION_SOURCE_MIDDLE_CLICK] =
GetDefaultMiddleClickAction();
window_frame_actions_[WINDOW_FRAME_ACTION_SOURCE_RIGHT_CLICK] =
views::LinuxUI::WINDOW_FRAME_ACTION_MENU;
#if GTK_MAJOR_VERSION > 2 #if GTK_MAJOR_VERSION > 2
// Force Gtk to use Xwayland if it would have used wayland. libgtkui assumes // Force Gtk to use Xwayland if it would have used wayland. libgtkui assumes
// the use of X11 (eg. X11InputMethodContextImplGtk) and will crash under // the use of X11 (eg. X11InputMethodContextImplGtk) and will crash under
...@@ -483,7 +492,7 @@ void GtkUi::Initialize() { ...@@ -483,7 +492,7 @@ void GtkUi::Initialize() {
#endif #endif
// We must build this after GTK gets initialized. // We must build this after GTK gets initialized.
nav_button_layout_manager_ = CreateNavButtonLayoutManager(this); settings_provider_ = CreateSettingsProvider(this);
indicators_count = 0; indicators_count = 0;
...@@ -755,8 +764,10 @@ void GtkUi::SetWindowButtonOrdering( ...@@ -755,8 +764,10 @@ void GtkUi::SetWindowButtonOrdering(
} }
} }
void GtkUi::SetNonClientMiddleClickAction(NonClientMiddleClickAction action) { void GtkUi::SetNonClientWindowFrameAction(
middle_click_action_ = action; NonClientWindowFrameActionSourceType source,
NonClientWindowFrameAction action) {
window_frame_actions_[source] = action;
} }
std::unique_ptr<ui::LinuxInputMethodContext> GtkUi::CreateInputMethodContext( std::unique_ptr<ui::LinuxInputMethodContext> GtkUi::CreateInputMethodContext(
...@@ -789,9 +800,9 @@ ui::SelectFileDialog* GtkUi::CreateSelectFileDialog( ...@@ -789,9 +800,9 @@ ui::SelectFileDialog* GtkUi::CreateSelectFileDialog(
return SelectFileDialogImpl::Create(listener, std::move(policy)); return SelectFileDialogImpl::Create(listener, std::move(policy));
} }
views::LinuxUI::NonClientMiddleClickAction views::LinuxUI::NonClientWindowFrameAction GtkUi::GetNonClientWindowFrameAction(
GtkUi::GetNonClientMiddleClickAction() { NonClientWindowFrameActionSourceType source) {
return middle_click_action_; return window_frame_actions_[source];
} }
void GtkUi::NotifyWindowManagerStartupComplete() { void GtkUi::NotifyWindowManagerStartupComplete() {
......
...@@ -26,7 +26,7 @@ typedef struct _GtkWidget GtkWidget; ...@@ -26,7 +26,7 @@ typedef struct _GtkWidget GtkWidget;
namespace libgtkui { namespace libgtkui {
class Gtk2KeyBindingsHandler; class Gtk2KeyBindingsHandler;
class DeviceScaleFactorObserver; class DeviceScaleFactorObserver;
class NavButtonLayoutManager; class SettingsProvider;
// Interface to GTK2 desktop features. // Interface to GTK2 desktop features.
// //
...@@ -38,11 +38,13 @@ class GtkUi : public views::LinuxUI { ...@@ -38,11 +38,13 @@ class GtkUi : public views::LinuxUI {
typedef base::Callback<ui::NativeTheme*(aura::Window* window)> typedef base::Callback<ui::NativeTheme*(aura::Window* window)>
NativeThemeGetter; NativeThemeGetter;
// Setters used by NavButtonLayoutManager: // Setters used by SettingsProvider:
void SetWindowButtonOrdering( void SetWindowButtonOrdering(
const std::vector<views::FrameButton>& leading_buttons, const std::vector<views::FrameButton>& leading_buttons,
const std::vector<views::FrameButton>& trailing_buttons); const std::vector<views::FrameButton>& trailing_buttons);
void SetNonClientMiddleClickAction(NonClientMiddleClickAction action); void SetNonClientWindowFrameAction(
NonClientWindowFrameActionSourceType source,
NonClientWindowFrameAction action);
// Called when gtk style changes // Called when gtk style changes
void ResetStyle(); void ResetStyle();
...@@ -97,7 +99,8 @@ class GtkUi : public views::LinuxUI { ...@@ -97,7 +99,8 @@ class GtkUi : public views::LinuxUI {
views::WindowButtonOrderObserver* observer) override; views::WindowButtonOrderObserver* observer) override;
void RemoveWindowButtonOrderObserver( void RemoveWindowButtonOrderObserver(
views::WindowButtonOrderObserver* observer) override; views::WindowButtonOrderObserver* observer) override;
NonClientMiddleClickAction GetNonClientMiddleClickAction() override; NonClientWindowFrameAction GetNonClientWindowFrameAction(
NonClientWindowFrameActionSourceType source) override;
void NotifyWindowManagerStartupComplete() override; void NotifyWindowManagerStartupComplete() override;
void UpdateDeviceScaleFactor() override; void UpdateDeviceScaleFactor() override;
float GetDeviceScaleFactor() const override; float GetDeviceScaleFactor() const override;
...@@ -174,7 +177,7 @@ class GtkUi : public views::LinuxUI { ...@@ -174,7 +177,7 @@ class GtkUi : public views::LinuxUI {
gfx::Font::Weight default_font_weight_ = gfx::Font::Weight::NORMAL; gfx::Font::Weight default_font_weight_ = gfx::Font::Weight::NORMAL;
gfx::FontRenderParams default_font_render_params_; gfx::FontRenderParams default_font_render_params_;
std::unique_ptr<NavButtonLayoutManager> nav_button_layout_manager_; std::unique_ptr<SettingsProvider> settings_provider_;
// Frame button layout state. If |nav_buttons_set_| is false, then // Frame button layout state. If |nav_buttons_set_| is false, then
// |leading_buttons_| and |trailing_buttons_| are meaningless. // |leading_buttons_| and |trailing_buttons_| are meaningless.
...@@ -192,9 +195,9 @@ class GtkUi : public views::LinuxUI { ...@@ -192,9 +195,9 @@ class GtkUi : public views::LinuxUI {
base::ObserverList<views::DeviceScaleFactorObserver> base::ObserverList<views::DeviceScaleFactorObserver>
device_scale_factor_observer_list_; device_scale_factor_observer_list_;
// Whether we should lower the window on a middle click to the non client // The action to take when middle, double, or right clicking the titlebar.
// area. NonClientWindowFrameAction
NonClientMiddleClickAction middle_click_action_; window_frame_actions_[WINDOW_FRAME_ACTION_SOURCE_LAST];
// Used to override the native theme for a window. If no override is provided // Used to override the native theme for a window. If no override is provided
// or the callback returns nullptr, GtkUi will default to a NativeThemeGtk2 // or the callback returns nullptr, GtkUi will default to a NativeThemeGtk2
......
...@@ -2,30 +2,28 @@ ...@@ -2,30 +2,28 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_H_ #ifndef CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_H_
#define CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_H_ #define CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_H_
#include <string> #include <string>
#include <vector> #include <vector>
namespace libgtkui { namespace libgtkui {
// This class is just a switch between NavButtonLayoutManagerGconf and // This class is just a switch between SettingsProviderGconf and
// NavButtonLayoutManagerGtk3. Currently, it is empty and it's only // SettingsProviderGtk3. Currently, it is empty and it's only purpose is so
// purpose is so that GtkUi can store just a // that GtkUi can store just a std::unique_ptr<SettingsProvider> and not have to
// std::unique_ptr<NavButtonLayoutManager> and not have to have the // have the two impls each guarded by their own macros.
// two impls each guarded by their own macros. class SettingsProvider {
class NavButtonLayoutManager {
public: public:
virtual ~NavButtonLayoutManager() {} virtual ~SettingsProvider() {}
protected: protected:
// Even though this class is not pure virtual, it should not be // Even though this class is not pure virtual, it should not be instantiated
// instantiated directly. Use NavButtonLayoutManagerGconf or // directly. Use SettingsProviderGconf or SettingsProviderGtk3 instead.
// NavButtonLayoutManagerGtk3 instead. SettingsProvider() {}
NavButtonLayoutManager() {}
}; };
} // namespace libgtkui } // namespace libgtkui
#endif // CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_H_ #endif // CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_H_
// Copyright 2014 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/settings_provider_gconf.h"
#include <gtk/gtk.h>
#include <memory>
#include "base/bind.h"
#include "base/callback.h"
#include "base/environment.h"
#include "base/nix/xdg_util.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"
namespace {
// The GConf key we read for the button placement string. Even through the key
// has "metacity" in it, it's shared between metacity and compiz.
const char kButtonLayoutKey[] = "/apps/metacity/general/button_layout";
// The GConf key we read for what to do in case of middle clicks on non client
// area. Even through the key has "metacity" in it, it's shared between
// metacity and compiz.
const char kMiddleClickActionKey[] =
"/apps/metacity/general/action_middle_click_titlebar";
// GConf requires us to subscribe to a parent directory before we can subscribe
// to changes in an individual key in that directory.
const char kMetacityGeneral[] = "/apps/metacity/general";
const char kDefaultButtonString[] = ":minimize,maximize,close";
} // namespace
namespace libgtkui {
// Public interface:
SettingsProviderGconf::SettingsProviderGconf(GtkUi* delegate)
: delegate_(delegate), client_(nullptr) {
std::unique_ptr<base::Environment> env(base::Environment::Create());
base::nix::DesktopEnvironment de =
base::nix::GetDesktopEnvironment(env.get());
if (de == base::nix::DESKTOP_ENVIRONMENT_GNOME ||
de == base::nix::DESKTOP_ENVIRONMENT_UNITY ||
ui::GuessWindowManager() == ui::WM_METACITY) {
client_ = gconf_client_get_default();
// If we fail to get a context, that's OK, since we'll just fallback on
// not receiving gconf keys.
if (client_) {
// Register that we're interested in the values of this directory.
GError* error = nullptr;
gconf_client_add_dir(client_, kMetacityGeneral,
GCONF_CLIENT_PRELOAD_ONELEVEL, &error);
if (HandleGError(error, kMetacityGeneral))
return;
// Get the initial value of the keys we're interested in.
GetAndRegister(
kButtonLayoutKey,
base::BindOnce(&SettingsProviderGconf::ParseAndStoreButtonValue,
base::Unretained(this)));
GetAndRegister(
kMiddleClickActionKey,
base::BindOnce(&SettingsProviderGconf::ParseAndStoreMiddleClickValue,
base::Unretained(this)));
}
}
}
SettingsProviderGconf::~SettingsProviderGconf() {}
// Private:
void SettingsProviderGconf::GetAndRegister(
const char* key_to_subscribe,
base::OnceCallback<void(GConfValue*)> initial_setter) {
GError* error = nullptr;
GConfValue* gconf_value = gconf_client_get(client_, key_to_subscribe, &error);
if (HandleGError(error, key_to_subscribe))
return;
std::move(initial_setter).Run(gconf_value);
if (gconf_value)
gconf_value_free(gconf_value);
// Register to get notifies about changes to this key.
gconf_client_notify_add(
client_, key_to_subscribe,
reinterpret_cast<void (*)(GConfClient*, guint, GConfEntry*, void*)>(
OnChangeNotificationThunk),
this, nullptr, &error);
if (HandleGError(error, key_to_subscribe))
return;
}
void SettingsProviderGconf::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);
} else if (strcmp(gconf_entry_get_key(entry), kMiddleClickActionKey) == 0) {
GConfValue* gconf_value = gconf_entry_get_value(entry);
ParseAndStoreMiddleClickValue(gconf_value);
}
}
bool SettingsProviderGconf::HandleGError(GError* error, const char* key) {
if (error != nullptr) {
LOG(ERROR) << "Error with gconf key '" << key << "': " << error->message;
g_error_free(error);
g_object_unref(client_);
client_ = nullptr;
return true;
}
return false;
}
void SettingsProviderGconf::ParseAndStoreButtonValue(GConfValue* gconf_value) {
std::string button_string;
if (gconf_value) {
const char* value = gconf_value_get_string(gconf_value);
button_string = value ? value : kDefaultButtonString;
} else {
button_string = kDefaultButtonString;
}
std::vector<views::FrameButton> leading_buttons;
std::vector<views::FrameButton> trailing_buttons;
ParseButtonLayout(button_string, &leading_buttons, &trailing_buttons);
delegate_->SetWindowButtonOrdering(leading_buttons, trailing_buttons);
}
void SettingsProviderGconf::ParseAndStoreMiddleClickValue(
GConfValue* gconf_value) {
GtkUi::NonClientWindowFrameAction action =
views::LinuxUI::WINDOW_FRAME_ACTION_LOWER;
if (gconf_value) {
const char* value = gconf_value_get_string(gconf_value);
if (strcmp(value, "none") == 0) {
action = views::LinuxUI::WINDOW_FRAME_ACTION_NONE;
} else if (strcmp(value, "lower") == 0) {
action = views::LinuxUI::WINDOW_FRAME_ACTION_LOWER;
} else if (strcmp(value, "minimize") == 0) {
action = views::LinuxUI::WINDOW_FRAME_ACTION_MINIMIZE;
} else if (strcmp(value, "toggle-maximize") == 0) {
action = views::LinuxUI::WINDOW_FRAME_ACTION_TOGGLE_MAXIMIZE;
} else if (strcmp(value, "menu") == 0) {
action = views::LinuxUI::WINDOW_FRAME_ACTION_MENU;
} else {
// While we want to have the default state be lower if there isn't a
// value, we want to default to no action if the user has explicitly
// chose an action that we don't implement.
action = views::LinuxUI::WINDOW_FRAME_ACTION_NONE;
}
}
delegate_->SetNonClientWindowFrameAction(
views::LinuxUI::WINDOW_FRAME_ACTION_SOURCE_MIDDLE_CLICK, action);
}
} // namespace libgtkui
// Copyright 2014 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_SETTINGS_PROVIDER_GCONF_H_
#define CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GCONF_H_
#include <gconf/gconf-client.h>
#include <gtk/gtk.h>
#include <set>
#include <string>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "chrome/browser/ui/libgtkui/gtk_signal.h"
#include "chrome/browser/ui/libgtkui/settings_provider.h"
namespace libgtkui {
class GtkUi;
// 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 SettingsProviderGconf : public SettingsProvider {
public:
// Sends data to the GtkUi when available.
explicit SettingsProviderGconf(GtkUi* delegate);
~SettingsProviderGconf() override;
private:
// Called whenever the metacity key changes.
CHROMEG_CALLBACK_2(SettingsProviderGconf,
void,
OnChangeNotification,
GConfClient*,
guint,
GConfEntry*);
void GetAndRegister(const char* key_to_subscribe,
base::OnceCallback<void(GConfValue*)> initial_setter);
// Checks |error|. On error, prints out a message and closes the connection
// to GConf and reverts to default mode.
bool HandleGError(GError* error, const char* key);
// Parses the return data structure from GConf, falling back to the default
// value on any error.
void ParseAndStoreButtonValue(GConfValue* gconf_value);
void ParseAndStoreMiddleClickValue(GConfValue* gconf_value);
GtkUi* delegate_;
// Pointer to our gconf context. nullptr if we aren't on a desktop that uses
// gconf.
GConfClient* client_;
DISALLOW_COPY_AND_ASSIGN(SettingsProviderGconf);
};
} // namespace libgtkui
#endif // CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GCONF_H_
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/ui/libgtkui/nav_button_layout_manager_gsettings.h" #include "chrome/browser/ui/libgtkui/settings_provider_gsettings.h"
#include <gio/gio.h> #include <gio/gio.h>
...@@ -28,8 +28,7 @@ namespace libgtkui { ...@@ -28,8 +28,7 @@ namespace libgtkui {
// Public interface: // Public interface:
NavButtonLayoutManagerGSettings::NavButtonLayoutManagerGSettings( SettingsProviderGSettings::SettingsProviderGSettings(GtkUi* delegate)
GtkUi* delegate)
: delegate_(delegate), settings_(nullptr) { : delegate_(delegate), settings_(nullptr) {
DCHECK(delegate_); DCHECK(delegate_);
...@@ -54,7 +53,7 @@ NavButtonLayoutManagerGSettings::NavButtonLayoutManagerGSettings( ...@@ -54,7 +53,7 @@ NavButtonLayoutManagerGSettings::NavButtonLayoutManagerGSettings(
G_CALLBACK(OnMiddleClickActionChangedThunk), this); G_CALLBACK(OnMiddleClickActionChangedThunk), this);
} }
NavButtonLayoutManagerGSettings::~NavButtonLayoutManagerGSettings() { SettingsProviderGSettings::~SettingsProviderGSettings() {
if (settings_) { if (settings_) {
if (signal_button_id_) if (signal_button_id_)
g_signal_handler_disconnect(settings_, signal_button_id_); g_signal_handler_disconnect(settings_, signal_button_id_);
...@@ -66,7 +65,7 @@ NavButtonLayoutManagerGSettings::~NavButtonLayoutManagerGSettings() { ...@@ -66,7 +65,7 @@ NavButtonLayoutManagerGSettings::~NavButtonLayoutManagerGSettings() {
// Private: // Private:
void NavButtonLayoutManagerGSettings::OnDecorationButtonLayoutChanged( void SettingsProviderGSettings::OnDecorationButtonLayoutChanged(
GSettings* settings, GSettings* settings,
const gchar* key) { const gchar* key) {
gchar* button_layout = g_settings_get_string(settings, kButtonLayoutKey); gchar* button_layout = g_settings_get_string(settings, kButtonLayoutKey);
...@@ -76,7 +75,7 @@ void NavButtonLayoutManagerGSettings::OnDecorationButtonLayoutChanged( ...@@ -76,7 +75,7 @@ void NavButtonLayoutManagerGSettings::OnDecorationButtonLayoutChanged(
g_free(button_layout); g_free(button_layout);
} }
void NavButtonLayoutManagerGSettings::ParseAndStoreButtonValue( void SettingsProviderGSettings::ParseAndStoreButtonValue(
const std::string& button_string) { const std::string& button_string) {
std::vector<views::FrameButton> leading_buttons; std::vector<views::FrameButton> leading_buttons;
std::vector<views::FrameButton> trailing_buttons; std::vector<views::FrameButton> trailing_buttons;
...@@ -84,9 +83,8 @@ void NavButtonLayoutManagerGSettings::ParseAndStoreButtonValue( ...@@ -84,9 +83,8 @@ void NavButtonLayoutManagerGSettings::ParseAndStoreButtonValue(
delegate_->SetWindowButtonOrdering(leading_buttons, trailing_buttons); delegate_->SetWindowButtonOrdering(leading_buttons, trailing_buttons);
} }
void NavButtonLayoutManagerGSettings::OnMiddleClickActionChanged( void SettingsProviderGSettings::OnMiddleClickActionChanged(GSettings* settings,
GSettings* settings, const gchar* key) {
const gchar* key) {
gchar* click_action = g_settings_get_string(settings, kMiddleClickActionKey); gchar* click_action = g_settings_get_string(settings, kMiddleClickActionKey);
if (!click_action) if (!click_action)
return; return;
...@@ -94,26 +92,27 @@ void NavButtonLayoutManagerGSettings::OnMiddleClickActionChanged( ...@@ -94,26 +92,27 @@ void NavButtonLayoutManagerGSettings::OnMiddleClickActionChanged(
g_free(click_action); g_free(click_action);
} }
void NavButtonLayoutManagerGSettings::ParseAndStoreMiddleClickValue( void SettingsProviderGSettings::ParseAndStoreMiddleClickValue(
const std::string& click_action) { const std::string& click_action) {
GtkUi::NonClientMiddleClickAction action; GtkUi::NonClientWindowFrameAction action;
if (click_action == "none") { if (click_action == "none") {
action = views::LinuxUI::MIDDLE_CLICK_ACTION_NONE; action = views::LinuxUI::WINDOW_FRAME_ACTION_NONE;
} else if (click_action == "lower") { } else if (click_action == "lower") {
action = views::LinuxUI::MIDDLE_CLICK_ACTION_LOWER; action = views::LinuxUI::WINDOW_FRAME_ACTION_LOWER;
} else if (click_action == "minimize") { } else if (click_action == "minimize") {
action = views::LinuxUI::MIDDLE_CLICK_ACTION_MINIMIZE; action = views::LinuxUI::WINDOW_FRAME_ACTION_MINIMIZE;
} else if (click_action == "toggle-maximize") { } else if (click_action == "toggle-maximize") {
action = views::LinuxUI::MIDDLE_CLICK_ACTION_TOGGLE_MAXIMIZE; action = views::LinuxUI::WINDOW_FRAME_ACTION_TOGGLE_MAXIMIZE;
} else { } else {
// While we want to have the default state be lower if there isn't a // While we want to have the default state be lower if there isn't a
// value, we want to default to no action if the user has explicitly // value, we want to default to no action if the user has explicitly
// chose an action that we don't implement. // chose an action that we don't implement.
action = views::LinuxUI::MIDDLE_CLICK_ACTION_NONE; action = views::LinuxUI::WINDOW_FRAME_ACTION_NONE;
} }
delegate_->SetNonClientMiddleClickAction(action); delegate_->SetNonClientWindowFrameAction(
views::LinuxUI::WINDOW_FRAME_ACTION_SOURCE_MIDDLE_CLICK, action);
} }
} // namespace libgtkui } // namespace libgtkui
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_GSETTINGS_H_ #ifndef CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GSETTINGS_H_
#define CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_GSETTINGS_H_ #define CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GSETTINGS_H_
#include <gio/gio.h> #include <gio/gio.h>
#include "base/macros.h" #include "base/macros.h"
#include "chrome/browser/ui/libgtkui/nav_button_layout_manager.h" #include "chrome/browser/ui/libgtkui/settings_provider.h"
#include "ui/base/glib/glib_signal.h" #include "ui/base/glib/glib_signal.h"
namespace libgtkui { namespace libgtkui {
...@@ -17,20 +17,20 @@ class GtkUi; ...@@ -17,20 +17,20 @@ class GtkUi;
// On GNOME desktops, subscribes to the gsettings key which controlls button // On GNOME desktops, subscribes to the gsettings key which controlls button
// order and the middle click action. Everywhere else, SetTiltebarButtons() // order and the middle click action. Everywhere else, SetTiltebarButtons()
// just calls back into BrowserTitlebar with the default ordering. // just calls back into BrowserTitlebar with the default ordering.
class NavButtonLayoutManagerGSettings : public NavButtonLayoutManager { class SettingsProviderGSettings : public SettingsProvider {
public: public:
// Sends data to the GtkUi when available. // Sends data to the GtkUi when available.
explicit NavButtonLayoutManagerGSettings(GtkUi* delegate); explicit SettingsProviderGSettings(GtkUi* delegate);
~NavButtonLayoutManagerGSettings() override; ~SettingsProviderGSettings() override;
private: private:
CHROMEG_CALLBACK_1(NavButtonLayoutManagerGSettings, CHROMEG_CALLBACK_1(SettingsProviderGSettings,
void, void,
OnDecorationButtonLayoutChanged, OnDecorationButtonLayoutChanged,
GSettings*, GSettings*,
const gchar*); const gchar*);
CHROMEG_CALLBACK_1(NavButtonLayoutManagerGSettings, CHROMEG_CALLBACK_1(SettingsProviderGSettings,
void, void,
OnMiddleClickActionChanged, OnMiddleClickActionChanged,
GSettings*, GSettings*,
...@@ -46,9 +46,9 @@ class NavButtonLayoutManagerGSettings : public NavButtonLayoutManager { ...@@ -46,9 +46,9 @@ class NavButtonLayoutManagerGSettings : public NavButtonLayoutManager {
gulong signal_button_id_; gulong signal_button_id_;
gulong signal_middle_click_id_; gulong signal_middle_click_id_;
DISALLOW_COPY_AND_ASSIGN(NavButtonLayoutManagerGSettings); DISALLOW_COPY_AND_ASSIGN(SettingsProviderGSettings);
}; };
} // namespace libgtkui } // namespace libgtkui
#endif // CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_GSETTINGS_H_ #endif // CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GSETTINGS_H_
...@@ -2,12 +2,14 @@ ...@@ -2,12 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/ui/libgtkui/nav_button_layout_manager_gtk3.h" #include "chrome/browser/ui/libgtkui/settings_provider_gtk3.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "chrome/browser/ui/libgtkui/gtk_ui.h" #include "chrome/browser/ui/libgtkui/gtk_ui.h"
#include "chrome/browser/ui/libgtkui/gtk_util.h" #include "chrome/browser/ui/libgtkui/gtk_util.h"
#include "base/debug/stack_trace.h"
namespace libgtkui { namespace libgtkui {
namespace { namespace {
...@@ -41,28 +43,87 @@ std::string GetDecorationLayoutFromGtkWindow() { ...@@ -41,28 +43,87 @@ std::string GetDecorationLayoutFromGtkWindow() {
return layout; return layout;
} }
void ParseActionString(const std::string& value,
GtkUi::NonClientWindowFrameAction* action) {
if (value == "none")
*action = views::LinuxUI::WINDOW_FRAME_ACTION_NONE;
else if (value == "lower")
*action = views::LinuxUI::WINDOW_FRAME_ACTION_LOWER;
else if (value == "minimize")
*action = views::LinuxUI::WINDOW_FRAME_ACTION_MINIMIZE;
else if (value == "toggle-maximize")
*action = views::LinuxUI::WINDOW_FRAME_ACTION_TOGGLE_MAXIMIZE;
else if (value == "menu")
*action = views::LinuxUI::WINDOW_FRAME_ACTION_MENU;
}
} // namespace } // namespace
NavButtonLayoutManagerGtk3::NavButtonLayoutManagerGtk3(GtkUi* delegate) SettingsProviderGtk3::FrameActionSettingWatcher::FrameActionSettingWatcher(
: delegate_(delegate), signal_id_(0), signal_id_middle_click_(0) { SettingsProviderGtk3* settings_provider,
const std::string& setting_name,
views::LinuxUI::NonClientWindowFrameActionSourceType action_type,
views::LinuxUI::NonClientWindowFrameAction default_action)
: settings_provider_(settings_provider),
setting_name_(setting_name),
action_type_(action_type),
default_action_(default_action) {
GtkSettings* settings = gtk_settings_get_default();
std::string notify_setting = "notify::" + setting_name;
signal_id_ = g_signal_connect(settings, notify_setting.c_str(),
G_CALLBACK(OnSettingChangedThunk), this);
DCHECK(signal_id_);
OnSettingChanged(settings, nullptr);
}
SettingsProviderGtk3::FrameActionSettingWatcher::~FrameActionSettingWatcher() {
base::debug::StackTrace().Print();
if (signal_id_)
g_signal_handler_disconnect(gtk_settings_get_default(), signal_id_);
}
void SettingsProviderGtk3::FrameActionSettingWatcher::OnSettingChanged(
GtkSettings* settings,
GParamSpec* param) {
std::string value =
GetGtkSettingsStringProperty(settings, setting_name_.c_str());
GtkUi::NonClientWindowFrameAction action = default_action_;
ParseActionString(value, &action);
settings_provider_->delegate_->SetNonClientWindowFrameAction(action_type_,
action);
}
SettingsProviderGtk3::SettingsProviderGtk3(GtkUi* delegate)
: delegate_(delegate), signal_id_decoration_layout_(0) {
DCHECK(delegate_); DCHECK(delegate_);
GtkSettings* settings = gtk_settings_get_default(); GtkSettings* settings = gtk_settings_get_default();
if (GtkVersionCheck(3, 14)) { if (GtkVersionCheck(3, 14)) {
signal_id_ = g_signal_connect( signal_id_decoration_layout_ = g_signal_connect(
settings, "notify::gtk-decoration-layout", settings, "notify::gtk-decoration-layout",
G_CALLBACK(OnDecorationButtonLayoutChangedThunk), this); G_CALLBACK(OnDecorationButtonLayoutChangedThunk), this);
DCHECK(signal_id_); DCHECK(signal_id_decoration_layout_);
OnDecorationButtonLayoutChanged(settings, nullptr); OnDecorationButtonLayoutChanged(settings, nullptr);
signal_id_middle_click_ = frame_action_setting_watchers_.push_back(
g_signal_connect(settings, "notify::gtk-titlebar-middle-click", std::make_unique<FrameActionSettingWatcher>(
G_CALLBACK(OnMiddleClickActionChangedThunk), this); this, "gtk-titlebar-middle-click",
DCHECK(signal_id_middle_click_); views::LinuxUI::WINDOW_FRAME_ACTION_SOURCE_MIDDLE_CLICK,
OnMiddleClickActionChanged(settings, nullptr); views::LinuxUI::WINDOW_FRAME_ACTION_NONE));
frame_action_setting_watchers_.push_back(
std::make_unique<FrameActionSettingWatcher>(
this, "gtk-titlebar-double-click",
views::LinuxUI::WINDOW_FRAME_ACTION_SOURCE_DOUBLE_CLICK,
views::LinuxUI::WINDOW_FRAME_ACTION_TOGGLE_MAXIMIZE));
frame_action_setting_watchers_.push_back(
std::make_unique<FrameActionSettingWatcher>(
this, "gtk-titlebar-right-click",
views::LinuxUI::WINDOW_FRAME_ACTION_SOURCE_RIGHT_CLICK,
views::LinuxUI::WINDOW_FRAME_ACTION_MENU));
} else if (GtkVersionCheck(3, 10, 3)) { } else if (GtkVersionCheck(3, 10, 3)) {
signal_id_ = g_signal_connect_after(settings, "notify::gtk-theme-name", signal_id_decoration_layout_ =
G_CALLBACK(OnThemeChangedThunk), this); g_signal_connect_after(settings, "notify::gtk-theme-name",
DCHECK(signal_id_); G_CALLBACK(OnThemeChangedThunk), this);
DCHECK(signal_id_decoration_layout_);
OnThemeChanged(settings, nullptr); OnThemeChanged(settings, nullptr);
} else { } else {
// On versions older than 3.10.3, the layout was hardcoded. // On versions older than 3.10.3, the layout was hardcoded.
...@@ -70,15 +131,14 @@ NavButtonLayoutManagerGtk3::NavButtonLayoutManagerGtk3(GtkUi* delegate) ...@@ -70,15 +131,14 @@ NavButtonLayoutManagerGtk3::NavButtonLayoutManagerGtk3(GtkUi* delegate)
} }
} }
NavButtonLayoutManagerGtk3::~NavButtonLayoutManagerGtk3() { SettingsProviderGtk3::~SettingsProviderGtk3() {
if (signal_id_) if (signal_id_decoration_layout_) {
g_signal_handler_disconnect(gtk_settings_get_default(), signal_id_);
if (signal_id_middle_click_)
g_signal_handler_disconnect(gtk_settings_get_default(), g_signal_handler_disconnect(gtk_settings_get_default(),
signal_id_middle_click_); signal_id_decoration_layout_);
}
} }
void NavButtonLayoutManagerGtk3::SetWindowButtonOrderingFromGtkLayout( void SettingsProviderGtk3::SetWindowButtonOrderingFromGtkLayout(
const std::string& gtk_layout) { const std::string& gtk_layout) {
std::vector<views::FrameButton> leading_buttons; std::vector<views::FrameButton> leading_buttons;
std::vector<views::FrameButton> trailing_buttons; std::vector<views::FrameButton> trailing_buttons;
...@@ -86,37 +146,15 @@ void NavButtonLayoutManagerGtk3::SetWindowButtonOrderingFromGtkLayout( ...@@ -86,37 +146,15 @@ void NavButtonLayoutManagerGtk3::SetWindowButtonOrderingFromGtkLayout(
delegate_->SetWindowButtonOrdering(leading_buttons, trailing_buttons); delegate_->SetWindowButtonOrdering(leading_buttons, trailing_buttons);
} }
void NavButtonLayoutManagerGtk3::OnDecorationButtonLayoutChanged( void SettingsProviderGtk3::OnDecorationButtonLayoutChanged(
GtkSettings* settings, GtkSettings* settings,
GParamSpec* param) { GParamSpec* param) {
SetWindowButtonOrderingFromGtkLayout( SetWindowButtonOrderingFromGtkLayout(
GetGtkSettingsStringProperty(settings, "gtk-decoration-layout")); GetGtkSettingsStringProperty(settings, "gtk-decoration-layout"));
} }
void NavButtonLayoutManagerGtk3::OnMiddleClickActionChanged( void SettingsProviderGtk3::OnThemeChanged(GtkSettings* settings,
GtkSettings* settings, GParamSpec* param) {
GParamSpec* param) {
std::string value =
GetGtkSettingsStringProperty(settings, "gtk-titlebar-middle-click");
GtkUi::NonClientMiddleClickAction action;
if (value == "none") {
action = views::LinuxUI::MIDDLE_CLICK_ACTION_NONE;
} else if (value == "lower") {
action = views::LinuxUI::MIDDLE_CLICK_ACTION_LOWER;
} else if (value == "minimize") {
action = views::LinuxUI::MIDDLE_CLICK_ACTION_MINIMIZE;
} else if (value == "toggle-maximize") {
action = views::LinuxUI::MIDDLE_CLICK_ACTION_TOGGLE_MAXIMIZE;
} else {
// Default to no action if the user has explicitly
// chosen an action that we don't implement.
action = views::LinuxUI::MIDDLE_CLICK_ACTION_NONE;
}
delegate_->SetNonClientMiddleClickAction(action);
}
void NavButtonLayoutManagerGtk3::OnThemeChanged(GtkSettings* settings,
GParamSpec* param) {
std::string layout = GetDecorationLayoutFromGtkWindow(); std::string layout = GetDecorationLayoutFromGtkWindow();
SetWindowButtonOrderingFromGtkLayout(layout); SetWindowButtonOrderingFromGtkLayout(layout);
} }
......
...@@ -2,14 +2,15 @@ ...@@ -2,14 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_GTK3_H_ #ifndef CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GTK3_H_
#define CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_GTK3_H_ #define CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GTK3_H_
#include <string> #include <string>
#include "base/macros.h" #include "base/macros.h"
#include "chrome/browser/ui/libgtkui/nav_button_layout_manager.h" #include "chrome/browser/ui/libgtkui/settings_provider.h"
#include "ui/base/glib/glib_signal.h" #include "ui/base/glib/glib_signal.h"
#include "ui/views/linux_ui/linux_ui.h"
typedef struct _GParamSpec GParamSpec; typedef struct _GParamSpec GParamSpec;
typedef struct _GtkSettings GtkSettings; typedef struct _GtkSettings GtkSettings;
...@@ -18,27 +19,46 @@ namespace libgtkui { ...@@ -18,27 +19,46 @@ namespace libgtkui {
class GtkUi; class GtkUi;
class NavButtonLayoutManagerGtk3 : public NavButtonLayoutManager { class SettingsProviderGtk3 : public SettingsProvider {
public: public:
explicit NavButtonLayoutManagerGtk3(GtkUi* delegate); explicit SettingsProviderGtk3(GtkUi* delegate);
~NavButtonLayoutManagerGtk3() override; ~SettingsProviderGtk3() override;
private: private:
class FrameActionSettingWatcher {
public:
FrameActionSettingWatcher(
SettingsProviderGtk3* settings_provider,
const std::string& setting_name,
views::LinuxUI::NonClientWindowFrameActionSourceType action_type,
views::LinuxUI::NonClientWindowFrameAction default_action);
~FrameActionSettingWatcher();
CHROMEG_CALLBACK_1(FrameActionSettingWatcher,
void,
OnSettingChanged,
GtkSettings*,
GParamSpec*);
private:
SettingsProviderGtk3* settings_provider_;
std::string setting_name_;
views::LinuxUI::NonClientWindowFrameActionSourceType action_type_;
views::LinuxUI::NonClientWindowFrameAction default_action_;
unsigned long signal_id_;
DISALLOW_COPY_AND_ASSIGN(FrameActionSettingWatcher);
};
void SetWindowButtonOrderingFromGtkLayout(const std::string& gtk_layout); void SetWindowButtonOrderingFromGtkLayout(const std::string& gtk_layout);
CHROMEG_CALLBACK_1(NavButtonLayoutManagerGtk3, CHROMEG_CALLBACK_1(SettingsProviderGtk3,
void, void,
OnDecorationButtonLayoutChanged, OnDecorationButtonLayoutChanged,
GtkSettings*, GtkSettings*,
GParamSpec*); GParamSpec*);
CHROMEG_CALLBACK_1(NavButtonLayoutManagerGtk3, CHROMEG_CALLBACK_1(SettingsProviderGtk3,
void,
OnMiddleClickActionChanged,
GtkSettings*,
GParamSpec*);
CHROMEG_CALLBACK_1(NavButtonLayoutManagerGtk3,
void, void,
OnThemeChanged, OnThemeChanged,
GtkSettings*, GtkSettings*,
...@@ -46,13 +66,14 @@ class NavButtonLayoutManagerGtk3 : public NavButtonLayoutManager { ...@@ -46,13 +66,14 @@ class NavButtonLayoutManagerGtk3 : public NavButtonLayoutManager {
GtkUi* delegate_; GtkUi* delegate_;
unsigned long signal_id_; unsigned long signal_id_decoration_layout_;
unsigned long signal_id_middle_click_; std::vector<std::unique_ptr<FrameActionSettingWatcher>>
frame_action_setting_watchers_;
DISALLOW_COPY_AND_ASSIGN(NavButtonLayoutManagerGtk3); DISALLOW_COPY_AND_ASSIGN(SettingsProviderGtk3);
}; };
} // namespace libgtkui } // namespace libgtkui
#endif // CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_LAYOUT_MANAGER_GTK3_H_ #endif // CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GTK3_H_
...@@ -67,11 +67,21 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory, ...@@ -67,11 +67,21 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory,
public: public:
// Describes the window management actions that could be taken in response to // Describes the window management actions that could be taken in response to
// a middle click in the non client area. // a middle click in the non client area.
enum NonClientMiddleClickAction { enum NonClientWindowFrameAction {
MIDDLE_CLICK_ACTION_NONE, WINDOW_FRAME_ACTION_NONE,
MIDDLE_CLICK_ACTION_LOWER, WINDOW_FRAME_ACTION_LOWER,
MIDDLE_CLICK_ACTION_MINIMIZE, WINDOW_FRAME_ACTION_MINIMIZE,
MIDDLE_CLICK_ACTION_TOGGLE_MAXIMIZE WINDOW_FRAME_ACTION_TOGGLE_MAXIMIZE,
WINDOW_FRAME_ACTION_MENU,
};
// The types of clicks that might invoke a NonClientWindowFrameAction.
enum NonClientWindowFrameActionSourceType {
WINDOW_FRAME_ACTION_SOURCE_DOUBLE_CLICK = 0,
WINDOW_FRAME_ACTION_SOURCE_MIDDLE_CLICK,
WINDOW_FRAME_ACTION_SOURCE_RIGHT_CLICK,
WINDOW_FRAME_ACTION_SOURCE_LAST
}; };
typedef base::Callback<ui::NativeTheme*(aura::Window* window)> typedef base::Callback<ui::NativeTheme*(aura::Window* window)>
...@@ -149,9 +159,10 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory, ...@@ -149,9 +159,10 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory,
virtual void RemoveWindowButtonOrderObserver( virtual void RemoveWindowButtonOrderObserver(
WindowButtonOrderObserver* observer) = 0; WindowButtonOrderObserver* observer) = 0;
// What action we should take when the user middle clicks on non-client // What action we should take when the user clicks on the non-client area.
// area. The default is lowering the window. // |source| describes the type of click.
virtual NonClientMiddleClickAction GetNonClientMiddleClickAction() = 0; virtual NonClientWindowFrameAction GetNonClientWindowFrameAction(
NonClientWindowFrameActionSourceType source) = 0;
// Notifies the window manager that start up has completed. // Notifies the window manager that start up has completed.
// Normally Chromium opens a new window on startup and GTK does this // Normally Chromium opens a new window on startup and GTK does this
......
...@@ -56,49 +56,61 @@ void WindowEventFilter::OnMouseEvent(ui::MouseEvent* event) { ...@@ -56,49 +56,61 @@ void WindowEventFilter::OnMouseEvent(ui::MouseEvent* event) {
void WindowEventFilter::OnClickedCaption(ui::MouseEvent* event, void WindowEventFilter::OnClickedCaption(ui::MouseEvent* event,
int previous_click_component) { int previous_click_component) {
aura::Window* target = static_cast<aura::Window*>(event->target()); aura::Window* target = static_cast<aura::Window*>(event->target());
LinuxUI* linux_ui = LinuxUI::instance();
if (event->IsMiddleMouseButton()) {
LinuxUI::NonClientMiddleClickAction action = views::LinuxUI::NonClientWindowFrameActionSourceType action_type;
LinuxUI::MIDDLE_CLICK_ACTION_LOWER; views::LinuxUI::NonClientWindowFrameAction default_action;
LinuxUI* linux_ui = LinuxUI::instance();
if (linux_ui) if (event->IsRightMouseButton()) {
action = linux_ui->GetNonClientMiddleClickAction(); action_type = LinuxUI::WINDOW_FRAME_ACTION_SOURCE_RIGHT_CLICK;
default_action = LinuxUI::WINDOW_FRAME_ACTION_MENU;
switch (action) { } else if (event->IsMiddleMouseButton()) {
case LinuxUI::MIDDLE_CLICK_ACTION_NONE: action_type = LinuxUI::WINDOW_FRAME_ACTION_SOURCE_MIDDLE_CLICK;
break; default_action = LinuxUI::WINDOW_FRAME_ACTION_NONE;
case LinuxUI::MIDDLE_CLICK_ACTION_LOWER: } else if (event->IsLeftMouseButton() &&
LowerWindow(); event->flags() & ui::EF_IS_DOUBLE_CLICK) {
break;
case LinuxUI::MIDDLE_CLICK_ACTION_MINIMIZE:
window_tree_host_->Minimize();
break;
case LinuxUI::MIDDLE_CLICK_ACTION_TOGGLE_MAXIMIZE:
if (target->GetProperty(aura::client::kResizeBehaviorKey) &
ui::mojom::kResizeBehaviorCanMaximize)
ToggleMaximizedState();
break;
}
event->SetHandled();
return;
}
if (event->IsLeftMouseButton() && event->flags() & ui::EF_IS_DOUBLE_CLICK) {
click_component_ = HTNOWHERE; click_component_ = HTNOWHERE;
if ((target->GetProperty(aura::client::kResizeBehaviorKey) & if (previous_click_component == HTCAPTION) {
ui::mojom::kResizeBehaviorCanMaximize) && action_type = LinuxUI::WINDOW_FRAME_ACTION_SOURCE_DOUBLE_CLICK;
previous_click_component == HTCAPTION) { default_action = LinuxUI::WINDOW_FRAME_ACTION_TOGGLE_MAXIMIZE;
// Our event is a double click in the caption area in a window that can be } else {
// maximized. We are responsible for dispatching this as a minimize/
// maximize on X11 (Windows converts this to min/max events for us).
ToggleMaximizedState();
event->SetHandled();
return; return;
} }
} else {
MaybeDispatchHostWindowDragMovement(HTCAPTION, event);
return;
} }
MaybeDispatchHostWindowDragMovement(HTCAPTION, event); LinuxUI::NonClientWindowFrameAction action =
linux_ui ? linux_ui->GetNonClientWindowFrameAction(action_type)
: default_action;
switch (action) {
case LinuxUI::WINDOW_FRAME_ACTION_NONE:
break;
case LinuxUI::WINDOW_FRAME_ACTION_LOWER:
LowerWindow();
break;
case LinuxUI::WINDOW_FRAME_ACTION_MINIMIZE:
window_tree_host_->Minimize();
break;
case LinuxUI::WINDOW_FRAME_ACTION_TOGGLE_MAXIMIZE:
if (target->GetProperty(aura::client::kResizeBehaviorKey) &
ui::mojom::kResizeBehaviorCanMaximize)
ToggleMaximizedState();
break;
case LinuxUI::WINDOW_FRAME_ACTION_MENU:
views::Widget* widget = views::Widget::GetWidgetForNativeView(target);
if (!widget)
break;
views::View* view = widget->GetContentsView();
if (!view)
break;
gfx::Point location(event->location());
views::View::ConvertPointToScreen(view, &location);
view->ShowContextMenu(location, ui::MENU_SOURCE_MOUSE);
break;
}
event->SetHandled();
} }
void WindowEventFilter::OnClickedMaximizeButton(ui::MouseEvent* event) { void WindowEventFilter::OnClickedMaximizeButton(ui::MouseEvent* event) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment