| Index: chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.cc
|
| diff --git a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.cc b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.cc
|
| deleted file mode 100644
|
| index 6612538bd108f2492a8eeb34883fd87602833e56..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.cc
|
| +++ /dev/null
|
| @@ -1,1517 +0,0 @@
|
| -// Copyright (c) 2012 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/gtk/bookmarks/bookmark_bar_gtk.h"
|
| -
|
| -#include <vector>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/debug/trace_event.h"
|
| -#include "base/metrics/histogram.h"
|
| -#include "base/pickle.h"
|
| -#include "base/prefs/pref_service.h"
|
| -#include "base/strings/utf_string_conversions.h"
|
| -#include "chrome/browser/bookmarks/bookmark_model.h"
|
| -#include "chrome/browser/bookmarks/bookmark_model_factory.h"
|
| -#include "chrome/browser/bookmarks/bookmark_node_data.h"
|
| -#include "chrome/browser/bookmarks/bookmark_stats.h"
|
| -#include "chrome/browser/chrome_notification_types.h"
|
| -#include "chrome/browser/extensions/extension_service.h"
|
| -#include "chrome/browser/profiles/profile.h"
|
| -#include "chrome/browser/themes/theme_properties.h"
|
| -#include "chrome/browser/ui/bookmarks/bookmark_bar_constants.h"
|
| -#include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
|
| -#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
|
| -#include "chrome/browser/ui/browser.h"
|
| -#include "chrome/browser/ui/chrome_pages.h"
|
| -#include "chrome/browser/ui/gtk/bookmarks/bookmark_bar_instructions_gtk.h"
|
| -#include "chrome/browser/ui/gtk/bookmarks/bookmark_menu_controller_gtk.h"
|
| -#include "chrome/browser/ui/gtk/bookmarks/bookmark_utils_gtk.h"
|
| -#include "chrome/browser/ui/gtk/browser_window_gtk.h"
|
| -#include "chrome/browser/ui/gtk/custom_button.h"
|
| -#include "chrome/browser/ui/gtk/event_utils.h"
|
| -#include "chrome/browser/ui/gtk/gtk_chrome_button.h"
|
| -#include "chrome/browser/ui/gtk/gtk_theme_service.h"
|
| -#include "chrome/browser/ui/gtk/gtk_util.h"
|
| -#include "chrome/browser/ui/gtk/hover_controller_gtk.h"
|
| -#include "chrome/browser/ui/gtk/menu_gtk.h"
|
| -#include "chrome/browser/ui/gtk/rounded_window.h"
|
| -#include "chrome/browser/ui/gtk/tabstrip_origin_provider.h"
|
| -#include "chrome/browser/ui/gtk/view_id_util.h"
|
| -#include "chrome/browser/ui/ntp_background_util.h"
|
| -#include "chrome/browser/ui/tabs/tab_strip_model.h"
|
| -#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
|
| -#include "chrome/common/extensions/extension_constants.h"
|
| -#include "chrome/common/pref_names.h"
|
| -#include "chrome/common/url_constants.h"
|
| -#include "content/public/browser/notification_details.h"
|
| -#include "content/public/browser/notification_source.h"
|
| -#include "content/public/browser/user_metrics.h"
|
| -#include "content/public/browser/web_contents.h"
|
| -#include "content/public/browser/web_contents_view.h"
|
| -#include "grit/generated_resources.h"
|
| -#include "grit/theme_resources.h"
|
| -#include "grit/ui_resources.h"
|
| -#include "ui/base/dragdrop/drag_drop_types.h"
|
| -#include "ui/base/dragdrop/gtk_dnd_util.h"
|
| -#include "ui/base/l10n/l10n_util.h"
|
| -#include "ui/base/resource/resource_bundle.h"
|
| -#include "ui/gfx/canvas_skia_paint.h"
|
| -#include "ui/gfx/gtk_compat.h"
|
| -#include "ui/gfx/gtk_util.h"
|
| -#include "ui/gfx/image/cairo_cached_surface.h"
|
| -#include "ui/gfx/image/image.h"
|
| -
|
| -using base::UserMetricsAction;
|
| -using content::PageNavigator;
|
| -using content::WebContents;
|
| -
|
| -namespace {
|
| -
|
| -// Padding for when the bookmark bar is detached.
|
| -const int kTopBottomNTPPadding = 12;
|
| -const int kLeftRightNTPPadding = 8;
|
| -
|
| -// Padding around the bar's content area when the bookmark bar is detached.
|
| -const int kNTPPadding = 2;
|
| -
|
| -// The number of pixels of rounding on the corners of the bookmark bar content
|
| -// area when in detached mode.
|
| -const int kNTPRoundedness = 3;
|
| -
|
| -// The height of the bar when it is "hidden". It is usually not completely
|
| -// hidden because even when it is closed it forms the bottom few pixels of
|
| -// the toolbar.
|
| -const int kBookmarkBarMinimumHeight = 3;
|
| -
|
| -// Left-padding for the instructional text.
|
| -const int kInstructionsPadding = 6;
|
| -
|
| -// Padding around the "Other Bookmarks" button.
|
| -const int kOtherBookmarksPaddingHorizontal = 2;
|
| -const int kOtherBookmarksPaddingVertical = 1;
|
| -
|
| -// The targets accepted by the toolbar and folder buttons for DnD.
|
| -const int kDestTargetList[] = { ui::CHROME_BOOKMARK_ITEM,
|
| - ui::CHROME_NAMED_URL,
|
| - ui::TEXT_URI_LIST,
|
| - ui::NETSCAPE_URL,
|
| - ui::TEXT_PLAIN, -1 };
|
| -
|
| -// Acceptable drag actions for the bookmark bar drag destinations.
|
| -const GdkDragAction kDragAction =
|
| - GdkDragAction(GDK_ACTION_MOVE | GDK_ACTION_COPY);
|
| -
|
| -void SetToolBarStyle() {
|
| - static bool style_was_set = false;
|
| -
|
| - if (style_was_set)
|
| - return;
|
| - style_was_set = true;
|
| -
|
| - gtk_rc_parse_string(
|
| - "style \"chrome-bookmark-toolbar\" {"
|
| - " xthickness = 0\n"
|
| - " ythickness = 0\n"
|
| - " GtkWidget::focus-padding = 0\n"
|
| - " GtkContainer::border-width = 0\n"
|
| - " GtkToolbar::internal-padding = 1\n"
|
| - " GtkToolbar::shadow-type = GTK_SHADOW_NONE\n"
|
| - "}\n"
|
| - "widget \"*chrome-bookmark-toolbar\" style \"chrome-bookmark-toolbar\"");
|
| -}
|
| -
|
| -void RecordAppLaunch(Profile* profile, const GURL& url) {
|
| - DCHECK(profile->GetExtensionService());
|
| - const extensions::Extension* extension =
|
| - profile->GetExtensionService()->GetInstalledApp(url);
|
| - if (!extension)
|
| - return;
|
| -
|
| - CoreAppLauncherHandler::RecordAppLaunchType(
|
| - extension_misc::APP_LAUNCH_BOOKMARK_BAR,
|
| - extension->GetType());
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -BookmarkBarGtk::BookmarkBarGtk(BrowserWindowGtk* window,
|
| - Browser* browser,
|
| - TabstripOriginProvider* tabstrip_origin_provider)
|
| - : page_navigator_(NULL),
|
| - browser_(browser),
|
| - window_(window),
|
| - tabstrip_origin_provider_(tabstrip_origin_provider),
|
| - model_(NULL),
|
| - instructions_(NULL),
|
| - dragged_node_(NULL),
|
| - drag_icon_(NULL),
|
| - toolbar_drop_item_(NULL),
|
| - theme_service_(GtkThemeService::GetFrom(browser->profile())),
|
| - show_instructions_(true),
|
| - menu_bar_helper_(this),
|
| - slide_animation_(this),
|
| - last_allocation_width_(-1),
|
| - throbbing_widget_(NULL),
|
| - bookmark_bar_state_(BookmarkBar::DETACHED),
|
| - max_height_(0),
|
| - weak_factory_(this) {
|
| - Init();
|
| - // Force an update by simulating being in the wrong state.
|
| - // BrowserWindowGtk sets our true state after we're created.
|
| - SetBookmarkBarState(BookmarkBar::SHOW,
|
| - BookmarkBar::DONT_ANIMATE_STATE_CHANGE);
|
| -
|
| - registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
|
| - content::Source<ThemeService>(theme_service_));
|
| -
|
| - apps_shortcut_visible_.Init(
|
| - prefs::kShowAppsShortcutInBookmarkBar,
|
| - browser_->profile()->GetPrefs(),
|
| - base::Bind(&BookmarkBarGtk::OnAppsPageShortcutVisibilityChanged,
|
| - base::Unretained(this)));
|
| -
|
| - OnAppsPageShortcutVisibilityChanged();
|
| -
|
| - edit_bookmarks_enabled_.Init(
|
| - prefs::kEditBookmarksEnabled,
|
| - browser_->profile()->GetPrefs(),
|
| - base::Bind(&BookmarkBarGtk::OnEditBookmarksEnabledChanged,
|
| - base::Unretained(this)));
|
| -
|
| - OnEditBookmarksEnabledChanged();
|
| -}
|
| -
|
| -BookmarkBarGtk::~BookmarkBarGtk() {
|
| - RemoveAllButtons();
|
| - bookmark_toolbar_.Destroy();
|
| - event_box_.Destroy();
|
| -}
|
| -
|
| -void BookmarkBarGtk::SetPageNavigator(PageNavigator* navigator) {
|
| - page_navigator_ = navigator;
|
| -}
|
| -
|
| -void BookmarkBarGtk::Init() {
|
| - event_box_.Own(gtk_event_box_new());
|
| - g_signal_connect(event_box_.get(), "destroy",
|
| - G_CALLBACK(&OnEventBoxDestroyThunk), this);
|
| - g_signal_connect(event_box_.get(), "button-press-event",
|
| - G_CALLBACK(&OnButtonPressedThunk), this);
|
| -
|
| - ntp_padding_box_ = gtk_alignment_new(0, 0, 1, 1);
|
| - gtk_container_add(GTK_CONTAINER(event_box_.get()), ntp_padding_box_);
|
| -
|
| - paint_box_ = gtk_event_box_new();
|
| - gtk_container_add(GTK_CONTAINER(ntp_padding_box_), paint_box_);
|
| - GdkColor paint_box_color =
|
| - theme_service_->GetGdkColor(ThemeProperties::COLOR_TOOLBAR);
|
| - gtk_widget_modify_bg(paint_box_, GTK_STATE_NORMAL, &paint_box_color);
|
| - gtk_widget_add_events(paint_box_, GDK_POINTER_MOTION_MASK |
|
| - GDK_BUTTON_PRESS_MASK);
|
| -
|
| - bookmark_hbox_ = gtk_hbox_new(FALSE, 0);
|
| - gtk_container_add(GTK_CONTAINER(paint_box_), bookmark_hbox_);
|
| -
|
| - apps_shortcut_button_ = theme_service_->BuildChromeButton();
|
| - ConfigureAppsShortcutButton(apps_shortcut_button_, theme_service_);
|
| - g_signal_connect(apps_shortcut_button_, "clicked",
|
| - G_CALLBACK(OnAppsButtonClickedThunk), this);
|
| - // Accept middle mouse clicking.
|
| - gtk_util::SetButtonClickableByMouseButtons(
|
| - apps_shortcut_button_, true, true, false);
|
| - gtk_box_pack_start(GTK_BOX(bookmark_hbox_), apps_shortcut_button_,
|
| - FALSE, FALSE, 0);
|
| -
|
| - instructions_ = gtk_alignment_new(0, 0, 1, 1);
|
| - gtk_alignment_set_padding(GTK_ALIGNMENT(instructions_), 0, 0,
|
| - kInstructionsPadding, 0);
|
| - Profile* profile = browser_->profile();
|
| - instructions_gtk_.reset(new BookmarkBarInstructionsGtk(this, profile));
|
| - gtk_container_add(GTK_CONTAINER(instructions_), instructions_gtk_->widget());
|
| - gtk_box_pack_start(GTK_BOX(bookmark_hbox_), instructions_,
|
| - TRUE, TRUE, 0);
|
| -
|
| - gtk_drag_dest_set(instructions_,
|
| - GtkDestDefaults(GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_MOTION),
|
| - NULL, 0, kDragAction);
|
| - ui::SetDestTargetList(instructions_, kDestTargetList);
|
| - g_signal_connect(instructions_, "drag-data-received",
|
| - G_CALLBACK(&OnDragReceivedThunk), this);
|
| -
|
| - g_signal_connect(event_box_.get(), "expose-event",
|
| - G_CALLBACK(&OnEventBoxExposeThunk), this);
|
| - UpdateEventBoxPaintability();
|
| -
|
| - bookmark_toolbar_.Own(gtk_toolbar_new());
|
| - SetToolBarStyle();
|
| - gtk_widget_set_name(bookmark_toolbar_.get(), "chrome-bookmark-toolbar");
|
| - gtk_util::SuppressDefaultPainting(bookmark_toolbar_.get());
|
| - g_signal_connect(bookmark_toolbar_.get(), "size-allocate",
|
| - G_CALLBACK(&OnToolbarSizeAllocateThunk), this);
|
| - gtk_box_pack_start(GTK_BOX(bookmark_hbox_), bookmark_toolbar_.get(),
|
| - TRUE, TRUE, 0);
|
| -
|
| - overflow_button_ = theme_service_->BuildChromeButton();
|
| - g_object_set_data(G_OBJECT(overflow_button_), "left-align-popup",
|
| - reinterpret_cast<void*>(true));
|
| - SetOverflowButtonAppearance();
|
| - ConnectFolderButtonEvents(overflow_button_, false);
|
| - gtk_box_pack_start(GTK_BOX(bookmark_hbox_), overflow_button_,
|
| - FALSE, FALSE, 0);
|
| -
|
| - gtk_drag_dest_set(bookmark_toolbar_.get(), GTK_DEST_DEFAULT_DROP,
|
| - NULL, 0, kDragAction);
|
| - ui::SetDestTargetList(bookmark_toolbar_.get(), kDestTargetList);
|
| - g_signal_connect(bookmark_toolbar_.get(), "drag-motion",
|
| - G_CALLBACK(&OnToolbarDragMotionThunk), this);
|
| - g_signal_connect(bookmark_toolbar_.get(), "drag-leave",
|
| - G_CALLBACK(&OnDragLeaveThunk), this);
|
| - g_signal_connect(bookmark_toolbar_.get(), "drag-data-received",
|
| - G_CALLBACK(&OnDragReceivedThunk), this);
|
| -
|
| - other_bookmarks_separator_ = theme_service_->CreateToolbarSeparator();
|
| - gtk_box_pack_start(GTK_BOX(bookmark_hbox_), other_bookmarks_separator_,
|
| - FALSE, FALSE, 0);
|
| -
|
| - // We pack the button manually (rather than using gtk_button_set_*) so that
|
| - // we can have finer control over its label.
|
| - other_bookmarks_button_ = theme_service_->BuildChromeButton();
|
| - gtk_widget_show_all(other_bookmarks_button_);
|
| - ConnectFolderButtonEvents(other_bookmarks_button_, false);
|
| - other_padding_ = gtk_alignment_new(0, 0, 1, 1);
|
| - gtk_alignment_set_padding(GTK_ALIGNMENT(other_padding_),
|
| - kOtherBookmarksPaddingVertical,
|
| - kOtherBookmarksPaddingVertical,
|
| - kOtherBookmarksPaddingHorizontal,
|
| - kOtherBookmarksPaddingHorizontal);
|
| - gtk_container_add(GTK_CONTAINER(other_padding_), other_bookmarks_button_);
|
| - gtk_box_pack_start(GTK_BOX(bookmark_hbox_), other_padding_,
|
| - FALSE, FALSE, 0);
|
| - gtk_widget_set_no_show_all(other_padding_, TRUE);
|
| -
|
| - gtk_widget_set_size_request(event_box_.get(), -1, kBookmarkBarMinimumHeight);
|
| -
|
| - ViewIDUtil::SetID(other_bookmarks_button_, VIEW_ID_OTHER_BOOKMARKS);
|
| - ViewIDUtil::SetID(widget(), VIEW_ID_BOOKMARK_BAR);
|
| -
|
| - gtk_widget_show_all(widget());
|
| - gtk_widget_hide(widget());
|
| -
|
| - AddCoreButtons();
|
| - // TODO(erg): Handle extensions
|
| - model_ = BookmarkModelFactory::GetForProfile(profile);
|
| - model_->AddObserver(this);
|
| - if (model_->loaded())
|
| - BookmarkModelLoaded(model_, false);
|
| - // else case: we'll receive notification back from the BookmarkModel when done
|
| - // loading, then we'll populate the bar.
|
| -}
|
| -
|
| -void BookmarkBarGtk::SetBookmarkBarState(
|
| - BookmarkBar::State state,
|
| - BookmarkBar::AnimateChangeType animate_type) {
|
| - TRACE_EVENT0("ui::gtk", "BookmarkBarGtk::SetBookmarkBarState");
|
| - if (animate_type == BookmarkBar::ANIMATE_STATE_CHANGE &&
|
| - (state == BookmarkBar::DETACHED ||
|
| - bookmark_bar_state_ == BookmarkBar::DETACHED)) {
|
| - // TODO(estade): animate the transition between detached and non or remove
|
| - // detached entirely.
|
| - animate_type = BookmarkBar::DONT_ANIMATE_STATE_CHANGE;
|
| - }
|
| - BookmarkBar::State old_state = bookmark_bar_state_;
|
| - bookmark_bar_state_ = state;
|
| - if (state == BookmarkBar::SHOW || state == BookmarkBar::DETACHED)
|
| - Show(old_state, animate_type);
|
| - else
|
| - Hide(old_state, animate_type);
|
| -}
|
| -
|
| -int BookmarkBarGtk::GetHeight() {
|
| - GtkAllocation allocation;
|
| - gtk_widget_get_allocation(event_box_.get(), &allocation);
|
| - return allocation.height - kBookmarkBarMinimumHeight;
|
| -}
|
| -
|
| -bool BookmarkBarGtk::IsAnimating() {
|
| - return slide_animation_.is_animating();
|
| -}
|
| -
|
| -void BookmarkBarGtk::CalculateMaxHeight() {
|
| - if (theme_service_->UsingNativeTheme()) {
|
| - // Get the requisition of our single child instead of the event box itself
|
| - // because the event box probably already has a size request.
|
| - GtkRequisition req;
|
| - gtk_widget_size_request(ntp_padding_box_, &req);
|
| - max_height_ = req.height;
|
| - } else {
|
| - max_height_ = (bookmark_bar_state_ == BookmarkBar::DETACHED) ?
|
| - chrome::kNTPBookmarkBarHeight : chrome::kBookmarkBarHeight;
|
| - }
|
| -}
|
| -
|
| -void BookmarkBarGtk::AnimationProgressed(const gfx::Animation* animation) {
|
| - DCHECK_EQ(animation, &slide_animation_);
|
| -
|
| - gint height =
|
| - static_cast<gint>(animation->GetCurrentValue() *
|
| - (max_height_ - kBookmarkBarMinimumHeight)) +
|
| - kBookmarkBarMinimumHeight;
|
| - gtk_widget_set_size_request(event_box_.get(), -1, height);
|
| -}
|
| -
|
| -void BookmarkBarGtk::AnimationEnded(const gfx::Animation* animation) {
|
| - DCHECK_EQ(animation, &slide_animation_);
|
| -
|
| - if (!slide_animation_.IsShowing()) {
|
| - gtk_widget_hide(bookmark_hbox_);
|
| -
|
| - // We can be windowless during unit tests.
|
| - if (window_) {
|
| - // Because of our constant resizing and our toolbar/bookmark bar overlap
|
| - // shenanigans, gtk+ gets confused, partially draws parts of the bookmark
|
| - // bar into the toolbar and than doesn't queue a redraw to fix it. So do
|
| - // it manually by telling the toolbar area to redraw itself.
|
| - window_->QueueToolbarRedraw();
|
| - }
|
| - }
|
| -}
|
| -
|
| -// MenuBarHelper::Delegate implementation --------------------------------------
|
| -void BookmarkBarGtk::PopupForButton(GtkWidget* button) {
|
| - const BookmarkNode* node = GetNodeForToolButton(button);
|
| - DCHECK(node);
|
| - DCHECK(page_navigator_);
|
| -
|
| - int first_hidden = GetFirstHiddenBookmark(0, NULL);
|
| - if (first_hidden == -1) {
|
| - // No overflow exists: don't show anything for the overflow button.
|
| - if (button == overflow_button_)
|
| - return;
|
| - } else {
|
| - // Overflow exists: don't show anything for an overflowed folder button.
|
| - if (button != overflow_button_ && button != other_bookmarks_button_ &&
|
| - node->parent()->GetIndexOf(node) >= first_hidden) {
|
| - return;
|
| - }
|
| - }
|
| -
|
| - current_menu_.reset(
|
| - new BookmarkMenuController(browser_, page_navigator_,
|
| - GTK_WINDOW(gtk_widget_get_toplevel(button)),
|
| - node,
|
| - button == overflow_button_ ? first_hidden : 0));
|
| - menu_bar_helper_.MenuStartedShowing(button, current_menu_->widget());
|
| - GdkEvent* event = gtk_get_current_event();
|
| - current_menu_->Popup(button, event->button.button, event->button.time);
|
| - gdk_event_free(event);
|
| -}
|
| -
|
| -void BookmarkBarGtk::PopupForButtonNextTo(GtkWidget* button,
|
| - GtkMenuDirectionType dir) {
|
| - const BookmarkNode* relative_node = GetNodeForToolButton(button);
|
| - DCHECK(relative_node);
|
| -
|
| - // Find out the order of the buttons.
|
| - std::vector<GtkWidget*> folder_list;
|
| - const int first_hidden = GetFirstHiddenBookmark(0, &folder_list);
|
| - if (first_hidden != -1)
|
| - folder_list.push_back(overflow_button_);
|
| -
|
| - if (!model_->other_node()->empty())
|
| - folder_list.push_back(other_bookmarks_button_);
|
| -
|
| - // Find the position of |button|.
|
| - int button_idx = -1;
|
| - for (size_t i = 0; i < folder_list.size(); ++i) {
|
| - if (folder_list[i] == button) {
|
| - button_idx = i;
|
| - break;
|
| - }
|
| - }
|
| - DCHECK_NE(button_idx, -1);
|
| -
|
| - // Find the GtkWidget* for the actual target button.
|
| - int shift = dir == GTK_MENU_DIR_PARENT ? -1 : 1;
|
| - button_idx = (button_idx + shift + folder_list.size()) % folder_list.size();
|
| - PopupForButton(folder_list[button_idx]);
|
| -}
|
| -
|
| -void BookmarkBarGtk::CloseMenu() {
|
| - current_context_menu_->Cancel();
|
| -}
|
| -
|
| -void BookmarkBarGtk::Show(BookmarkBar::State old_state,
|
| - BookmarkBar::AnimateChangeType animate_type) {
|
| - gtk_widget_show_all(widget());
|
| - UpdateDetachedState(old_state);
|
| - CalculateMaxHeight();
|
| - if (animate_type == BookmarkBar::ANIMATE_STATE_CHANGE) {
|
| - slide_animation_.Show();
|
| - } else {
|
| - slide_animation_.Reset(1);
|
| - AnimationProgressed(&slide_animation_);
|
| - }
|
| -
|
| - if (model_ && model_->loaded())
|
| - UpdateOtherBookmarksVisibility();
|
| -
|
| - // Hide out behind the findbar. This is rather fragile code, it could
|
| - // probably be improved.
|
| - if (bookmark_bar_state_ == BookmarkBar::DETACHED) {
|
| - if (theme_service_->UsingNativeTheme()) {
|
| - GtkWidget* parent = gtk_widget_get_parent(event_box_.get());
|
| - if (gtk_widget_get_realized(parent))
|
| - gdk_window_lower(gtk_widget_get_window(parent));
|
| - if (gtk_widget_get_realized(event_box_.get()))
|
| - gdk_window_lower(gtk_widget_get_window(event_box_.get()));
|
| - } else { // Chromium theme mode.
|
| - if (gtk_widget_get_realized(paint_box_)) {
|
| - gdk_window_lower(gtk_widget_get_window(paint_box_));
|
| - // The event box won't stay below its children's GdkWindows unless we
|
| - // toggle the above-child property here. If the event box doesn't stay
|
| - // below its children then events will be routed to it rather than the
|
| - // children.
|
| - gtk_event_box_set_above_child(GTK_EVENT_BOX(event_box_.get()), TRUE);
|
| - gtk_event_box_set_above_child(GTK_EVENT_BOX(event_box_.get()), FALSE);
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Maybe show the instructions
|
| - gtk_widget_set_visible(bookmark_toolbar_.get(), !show_instructions_);
|
| - gtk_widget_set_visible(instructions_, show_instructions_);
|
| -
|
| - SetChevronState();
|
| -}
|
| -
|
| -void BookmarkBarGtk::Hide(BookmarkBar::State old_state,
|
| - BookmarkBar::AnimateChangeType animate_type) {
|
| - UpdateDetachedState(old_state);
|
| -
|
| - // After coming out of fullscreen, the browser window sets the bookmark bar
|
| - // to the "hidden" state, which means we need to show our minimum height.
|
| - if (!window_->IsFullscreen())
|
| - gtk_widget_show(widget());
|
| - CalculateMaxHeight();
|
| - // Sometimes we get called without a matching call to open. If that happens
|
| - // then force hide.
|
| - if (slide_animation_.IsShowing() &&
|
| - animate_type == BookmarkBar::ANIMATE_STATE_CHANGE) {
|
| - slide_animation_.Hide();
|
| - } else {
|
| - gtk_widget_hide(bookmark_hbox_);
|
| - slide_animation_.Reset(0);
|
| - AnimationProgressed(&slide_animation_);
|
| - }
|
| -}
|
| -
|
| -void BookmarkBarGtk::SetInstructionState() {
|
| - if (model_)
|
| - show_instructions_ = model_->bookmark_bar_node()->empty();
|
| -
|
| - gtk_widget_set_visible(bookmark_toolbar_.get(), !show_instructions_);
|
| - gtk_widget_set_visible(instructions_, show_instructions_);
|
| -}
|
| -
|
| -void BookmarkBarGtk::SetChevronState() {
|
| - if (!gtk_widget_get_visible(bookmark_hbox_))
|
| - return;
|
| -
|
| - if (show_instructions_) {
|
| - gtk_widget_hide(overflow_button_);
|
| - return;
|
| - }
|
| -
|
| - int extra_space = 0;
|
| - if (gtk_widget_get_visible(overflow_button_)) {
|
| - GtkAllocation allocation;
|
| - gtk_widget_get_allocation(overflow_button_, &allocation);
|
| - extra_space = allocation.width;
|
| - }
|
| -
|
| - int overflow_idx = GetFirstHiddenBookmark(extra_space, NULL);
|
| - if (overflow_idx == -1)
|
| - gtk_widget_hide(overflow_button_);
|
| - else
|
| - gtk_widget_show_all(overflow_button_);
|
| -}
|
| -
|
| -void BookmarkBarGtk::UpdateOtherBookmarksVisibility() {
|
| - bool has_other_children = !model_->other_node()->empty();
|
| -
|
| - gtk_widget_set_visible(other_padding_, has_other_children);
|
| - gtk_widget_set_visible(other_bookmarks_separator_, has_other_children);
|
| -}
|
| -
|
| -void BookmarkBarGtk::RemoveAllButtons() {
|
| - gtk_util::RemoveAllChildren(bookmark_toolbar_.get());
|
| - menu_bar_helper_.Clear();
|
| -}
|
| -
|
| -void BookmarkBarGtk::AddCoreButtons() {
|
| - menu_bar_helper_.Add(other_bookmarks_button_);
|
| - menu_bar_helper_.Add(overflow_button_);
|
| -}
|
| -
|
| -void BookmarkBarGtk::ResetButtons() {
|
| - RemoveAllButtons();
|
| - AddCoreButtons();
|
| -
|
| - const BookmarkNode* bar = model_->bookmark_bar_node();
|
| - DCHECK(bar && model_->other_node());
|
| -
|
| - // Create a button for each of the children on the bookmark bar.
|
| - for (int i = 0; i < bar->child_count(); ++i) {
|
| - const BookmarkNode* node = bar->GetChild(i);
|
| - GtkToolItem* item = CreateBookmarkToolItem(node);
|
| - gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()), item, -1);
|
| - if (node->is_folder())
|
| - menu_bar_helper_.Add(gtk_bin_get_child(GTK_BIN(item)));
|
| - }
|
| -
|
| - ConfigureButtonForNode(
|
| - model_->other_node(), model_, other_bookmarks_button_, theme_service_);
|
| -
|
| - SetInstructionState();
|
| - SetChevronState();
|
| -}
|
| -
|
| -int BookmarkBarGtk::GetBookmarkButtonCount() {
|
| - GList* children = gtk_container_get_children(
|
| - GTK_CONTAINER(bookmark_toolbar_.get()));
|
| - int count = g_list_length(children);
|
| - g_list_free(children);
|
| - return count;
|
| -}
|
| -
|
| -BookmarkLaunchLocation BookmarkBarGtk::GetBookmarkLaunchLocation() const {
|
| - return bookmark_bar_state_ == BookmarkBar::DETACHED ?
|
| - BOOKMARK_LAUNCH_LOCATION_DETACHED_BAR :
|
| - BOOKMARK_LAUNCH_LOCATION_ATTACHED_BAR;
|
| -}
|
| -
|
| -void BookmarkBarGtk::SetOverflowButtonAppearance() {
|
| - GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(overflow_button_));
|
| - if (former_child)
|
| - gtk_widget_destroy(former_child);
|
| -
|
| - GtkWidget* new_child;
|
| - if (theme_service_->UsingNativeTheme()) {
|
| - new_child = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
|
| - } else {
|
| - const gfx::Image& image = ui::ResourceBundle::GetSharedInstance().
|
| - GetNativeImageNamed(IDR_BOOKMARK_BAR_CHEVRONS,
|
| - ui::ResourceBundle::RTL_ENABLED);
|
| - new_child = gtk_image_new_from_pixbuf(image.ToGdkPixbuf());
|
| - }
|
| -
|
| - gtk_container_add(GTK_CONTAINER(overflow_button_), new_child);
|
| - SetChevronState();
|
| -}
|
| -
|
| -int BookmarkBarGtk::GetFirstHiddenBookmark(int extra_space,
|
| - std::vector<GtkWidget*>* showing_folders) {
|
| - int rv = 0;
|
| - // We're going to keep track of how much width we've used as we move along
|
| - // the bookmark bar. If we ever surpass the width of the bookmark bar, we'll
|
| - // know that's the first hidden bookmark.
|
| - int width_used = 0;
|
| - // GTK appears to require one pixel of padding to the side of the first and
|
| - // last buttons on the bar.
|
| - // TODO(gideonwald): figure out the precise source of these extra two pixels
|
| - // and make this calculation more reliable.
|
| - GtkAllocation allocation;
|
| - gtk_widget_get_allocation(bookmark_toolbar_.get(), &allocation);
|
| - int total_width = allocation.width - 2;
|
| - bool overflow = false;
|
| - GtkRequisition requested_size_;
|
| - GList* toolbar_items =
|
| - gtk_container_get_children(GTK_CONTAINER(bookmark_toolbar_.get()));
|
| - for (GList* iter = toolbar_items; iter; iter = g_list_next(iter)) {
|
| - GtkWidget* tool_item = reinterpret_cast<GtkWidget*>(iter->data);
|
| - gtk_widget_size_request(tool_item, &requested_size_);
|
| - width_used += requested_size_.width;
|
| - // |extra_space| is available if we can remove the chevron, which happens
|
| - // only if there are no more potential overflow bookmarks after this one.
|
| - overflow = width_used > total_width + (g_list_next(iter) ? 0 : extra_space);
|
| - if (overflow)
|
| - break;
|
| -
|
| - if (showing_folders &&
|
| - model_->bookmark_bar_node()->GetChild(rv)->is_folder()) {
|
| - showing_folders->push_back(gtk_bin_get_child(GTK_BIN(tool_item)));
|
| - }
|
| - rv++;
|
| - }
|
| -
|
| - g_list_free(toolbar_items);
|
| -
|
| - if (!overflow)
|
| - return -1;
|
| -
|
| - return rv;
|
| -}
|
| -
|
| -void BookmarkBarGtk::UpdateDetachedState(BookmarkBar::State old_state) {
|
| - bool old_detached = old_state == BookmarkBar::DETACHED;
|
| - bool detached = bookmark_bar_state_ == BookmarkBar::DETACHED;
|
| - if (detached == old_detached)
|
| - return;
|
| -
|
| - if (detached) {
|
| - gtk_event_box_set_visible_window(GTK_EVENT_BOX(paint_box_), TRUE);
|
| - GdkColor stroke_color = theme_service_->UsingNativeTheme() ?
|
| - theme_service_->GetBorderColor() :
|
| - theme_service_->GetGdkColor(ThemeProperties::COLOR_NTP_HEADER);
|
| - gtk_util::ActAsRoundedWindow(paint_box_, stroke_color, kNTPRoundedness,
|
| - gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL);
|
| -
|
| - gtk_alignment_set_padding(GTK_ALIGNMENT(ntp_padding_box_),
|
| - kTopBottomNTPPadding, kTopBottomNTPPadding,
|
| - kLeftRightNTPPadding, kLeftRightNTPPadding);
|
| - gtk_container_set_border_width(GTK_CONTAINER(bookmark_hbox_), kNTPPadding);
|
| - } else {
|
| - gtk_util::StopActingAsRoundedWindow(paint_box_);
|
| - gtk_event_box_set_visible_window(GTK_EVENT_BOX(paint_box_), FALSE);
|
| - gtk_alignment_set_padding(GTK_ALIGNMENT(ntp_padding_box_), 0, 0, 0, 0);
|
| - gtk_container_set_border_width(GTK_CONTAINER(bookmark_hbox_), 0);
|
| - }
|
| -
|
| - UpdateEventBoxPaintability();
|
| - // |window_| can be NULL during testing.
|
| - // Listen for parent size allocations. Only connect once.
|
| - if (window_ && detached) {
|
| - GtkWidget* parent = gtk_widget_get_parent(widget());
|
| - if (parent &&
|
| - g_signal_handler_find(parent, G_SIGNAL_MATCH_FUNC,
|
| - 0, 0, NULL, reinterpret_cast<gpointer>(OnParentSizeAllocateThunk),
|
| - NULL) == 0) {
|
| - g_signal_connect(parent, "size-allocate",
|
| - G_CALLBACK(OnParentSizeAllocateThunk), this);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void BookmarkBarGtk::UpdateEventBoxPaintability() {
|
| - gtk_widget_set_app_paintable(
|
| - event_box_.get(),
|
| - (!theme_service_->UsingNativeTheme() ||
|
| - bookmark_bar_state_ == BookmarkBar::DETACHED));
|
| - // When using the GTK+ theme, we need to have the event box be visible so
|
| - // buttons don't get a halo color from the background. When using Chromium
|
| - // themes, we want to let the background show through the toolbar.
|
| -
|
| - gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()),
|
| - theme_service_->UsingNativeTheme());
|
| -}
|
| -
|
| -void BookmarkBarGtk::PaintEventBox() {
|
| - gfx::Size web_contents_size;
|
| - if (GetWebContentsSize(&web_contents_size) &&
|
| - web_contents_size != last_web_contents_size_) {
|
| - last_web_contents_size_ = web_contents_size;
|
| - gtk_widget_queue_draw(event_box_.get());
|
| - }
|
| -}
|
| -
|
| -bool BookmarkBarGtk::GetWebContentsSize(gfx::Size* size) {
|
| - Browser* browser = browser_;
|
| - if (!browser) {
|
| - NOTREACHED();
|
| - return false;
|
| - }
|
| - WebContents* web_contents =
|
| - browser->tab_strip_model()->GetActiveWebContents();
|
| - if (!web_contents) {
|
| - // It is possible to have a browser but no WebContents while under testing,
|
| - // so don't NOTREACHED() and error the program.
|
| - return false;
|
| - }
|
| - if (!web_contents->GetView()) {
|
| - NOTREACHED();
|
| - return false;
|
| - }
|
| - *size = web_contents->GetView()->GetContainerSize();
|
| - return true;
|
| -}
|
| -
|
| -void BookmarkBarGtk::StartThrobbingAfterAllocation(GtkWidget* item) {
|
| - g_signal_connect_after(
|
| - item, "size-allocate", G_CALLBACK(OnItemAllocateThunk), this);
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnItemAllocate(GtkWidget* item,
|
| - GtkAllocation* allocation) {
|
| - // We only want to fire on the item's first allocation.
|
| - g_signal_handlers_disconnect_by_func(
|
| - item, reinterpret_cast<gpointer>(&OnItemAllocateThunk), this);
|
| -
|
| - GtkWidget* button = gtk_bin_get_child(GTK_BIN(item));
|
| - const BookmarkNode* node = GetNodeForToolButton(button);
|
| - if (node)
|
| - StartThrobbing(node);
|
| -}
|
| -
|
| -void BookmarkBarGtk::StartThrobbing(const BookmarkNode* node) {
|
| - const BookmarkNode* parent_on_bb = NULL;
|
| - for (const BookmarkNode* parent = node; parent;
|
| - parent = parent->parent()) {
|
| - if (parent->parent() == model_->bookmark_bar_node()) {
|
| - parent_on_bb = parent;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - GtkWidget* widget_to_throb = NULL;
|
| -
|
| - if (!parent_on_bb) {
|
| - // Descendant of "Other Bookmarks".
|
| - widget_to_throb = other_bookmarks_button_;
|
| - } else {
|
| - int hidden = GetFirstHiddenBookmark(0, NULL);
|
| - int idx = model_->bookmark_bar_node()->GetIndexOf(parent_on_bb);
|
| -
|
| - if (hidden >= 0 && hidden <= idx) {
|
| - widget_to_throb = overflow_button_;
|
| - } else {
|
| - widget_to_throb = gtk_bin_get_child(GTK_BIN(gtk_toolbar_get_nth_item(
|
| - GTK_TOOLBAR(bookmark_toolbar_.get()), idx)));
|
| - }
|
| - }
|
| -
|
| - SetThrobbingWidget(widget_to_throb);
|
| -}
|
| -
|
| -void BookmarkBarGtk::SetThrobbingWidget(GtkWidget* widget) {
|
| - if (throbbing_widget_) {
|
| - HoverControllerGtk* hover_controller =
|
| - HoverControllerGtk::GetHoverControllerGtk(throbbing_widget_);
|
| - if (hover_controller)
|
| - hover_controller->StartThrobbing(0);
|
| -
|
| - g_signal_handlers_disconnect_by_func(
|
| - throbbing_widget_,
|
| - reinterpret_cast<gpointer>(OnThrobbingWidgetDestroyThunk),
|
| - this);
|
| - g_object_unref(throbbing_widget_);
|
| - throbbing_widget_ = NULL;
|
| - }
|
| -
|
| - if (widget) {
|
| - throbbing_widget_ = widget;
|
| - g_object_ref(throbbing_widget_);
|
| - g_signal_connect(throbbing_widget_, "destroy",
|
| - G_CALLBACK(OnThrobbingWidgetDestroyThunk), this);
|
| -
|
| - HoverControllerGtk* hover_controller =
|
| - HoverControllerGtk::GetHoverControllerGtk(throbbing_widget_);
|
| - if (hover_controller)
|
| - hover_controller->StartThrobbing(4);
|
| - }
|
| -}
|
| -
|
| -gboolean BookmarkBarGtk::ItemDraggedOverToolbar(GdkDragContext* context,
|
| - int index,
|
| - guint time) {
|
| - if (!edit_bookmarks_enabled_.GetValue())
|
| - return FALSE;
|
| - GdkAtom target_type =
|
| - gtk_drag_dest_find_target(bookmark_toolbar_.get(), context, NULL);
|
| - if (target_type == GDK_NONE) {
|
| - // We shouldn't act like a drop target when something that we can't deal
|
| - // with is dragged over the toolbar.
|
| - return FALSE;
|
| - }
|
| -
|
| - if (!toolbar_drop_item_) {
|
| - if (dragged_node_) {
|
| - toolbar_drop_item_ = CreateBookmarkToolItem(dragged_node_);
|
| - g_object_ref_sink(GTK_OBJECT(toolbar_drop_item_));
|
| - } else {
|
| - // Create a fake item the size of other_node().
|
| - //
|
| - // TODO(erg): Maybe somehow figure out the real size for the drop target?
|
| - toolbar_drop_item_ =
|
| - CreateBookmarkToolItem(model_->other_node());
|
| - g_object_ref_sink(GTK_OBJECT(toolbar_drop_item_));
|
| - }
|
| - }
|
| -
|
| - gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(bookmark_toolbar_.get()),
|
| - GTK_TOOL_ITEM(toolbar_drop_item_),
|
| - index);
|
| - if (target_type == ui::GetAtomForTarget(ui::CHROME_BOOKMARK_ITEM)) {
|
| - gdk_drag_status(context, GDK_ACTION_MOVE, time);
|
| - } else {
|
| - gdk_drag_status(context, GDK_ACTION_COPY, time);
|
| - }
|
| -
|
| - return TRUE;
|
| -}
|
| -
|
| -int BookmarkBarGtk::GetToolbarIndexForDragOverFolder(GtkWidget* button,
|
| - gint x) {
|
| - GtkAllocation allocation;
|
| - gtk_widget_get_allocation(button, &allocation);
|
| -
|
| - int margin = std::min(15, static_cast<int>(0.3 * allocation.width));
|
| - if (x > margin && x < (allocation.width - margin))
|
| - return -1;
|
| -
|
| - GtkWidget* parent = gtk_widget_get_parent(button);
|
| - gint index = gtk_toolbar_get_item_index(GTK_TOOLBAR(bookmark_toolbar_.get()),
|
| - GTK_TOOL_ITEM(parent));
|
| - if (x > margin)
|
| - index++;
|
| - return index;
|
| -}
|
| -
|
| -void BookmarkBarGtk::ClearToolbarDropHighlighting() {
|
| - if (toolbar_drop_item_) {
|
| - g_object_unref(toolbar_drop_item_);
|
| - toolbar_drop_item_ = NULL;
|
| - }
|
| -
|
| - gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(bookmark_toolbar_.get()),
|
| - NULL, 0);
|
| -}
|
| -
|
| -void BookmarkBarGtk::BookmarkModelLoaded(BookmarkModel* model,
|
| - bool ids_reassigned) {
|
| - // If |instructions_| has been nulled, we are in the middle of browser
|
| - // shutdown. Do nothing.
|
| - if (!instructions_)
|
| - return;
|
| -
|
| - UpdateOtherBookmarksVisibility();
|
| - ResetButtons();
|
| -}
|
| -
|
| -void BookmarkBarGtk::BookmarkModelBeingDeleted(BookmarkModel* model) {
|
| - // The bookmark model should never be deleted before us. This code exists
|
| - // to check for regressions in shutdown code and not crash.
|
| - NOTREACHED();
|
| -
|
| - // Do minimal cleanup, presumably we'll be deleted shortly.
|
| - model_->RemoveObserver(this);
|
| - model_ = NULL;
|
| -}
|
| -
|
| -void BookmarkBarGtk::BookmarkNodeMoved(BookmarkModel* model,
|
| - const BookmarkNode* old_parent,
|
| - int old_index,
|
| - const BookmarkNode* new_parent,
|
| - int new_index) {
|
| - const BookmarkNode* node = new_parent->GetChild(new_index);
|
| - BookmarkNodeRemoved(model, old_parent, old_index, node);
|
| - BookmarkNodeAdded(model, new_parent, new_index);
|
| -}
|
| -
|
| -void BookmarkBarGtk::BookmarkNodeAdded(BookmarkModel* model,
|
| - const BookmarkNode* parent,
|
| - int index) {
|
| - UpdateOtherBookmarksVisibility();
|
| -
|
| - const BookmarkNode* node = parent->GetChild(index);
|
| - if (parent != model_->bookmark_bar_node()) {
|
| - StartThrobbing(node);
|
| - return;
|
| - }
|
| - DCHECK(index >= 0 && index <= GetBookmarkButtonCount());
|
| -
|
| - GtkToolItem* item = CreateBookmarkToolItem(node);
|
| - gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()),
|
| - item, index);
|
| - if (node->is_folder())
|
| - menu_bar_helper_.Add(gtk_bin_get_child(GTK_BIN(item)));
|
| -
|
| - SetInstructionState();
|
| - SetChevronState();
|
| -
|
| - StartThrobbingAfterAllocation(GTK_WIDGET(item));
|
| -}
|
| -
|
| -void BookmarkBarGtk::BookmarkNodeRemoved(BookmarkModel* model,
|
| - const BookmarkNode* parent,
|
| - int old_index,
|
| - const BookmarkNode* node) {
|
| - UpdateOtherBookmarksVisibility();
|
| -
|
| - if (parent != model_->bookmark_bar_node()) {
|
| - // We only care about nodes on the bookmark bar.
|
| - return;
|
| - }
|
| - DCHECK(old_index >= 0 && old_index < GetBookmarkButtonCount());
|
| -
|
| - GtkWidget* to_remove = GTK_WIDGET(gtk_toolbar_get_nth_item(
|
| - GTK_TOOLBAR(bookmark_toolbar_.get()), old_index));
|
| - if (node->is_folder())
|
| - menu_bar_helper_.Remove(gtk_bin_get_child(GTK_BIN(to_remove)));
|
| - gtk_container_remove(GTK_CONTAINER(bookmark_toolbar_.get()),
|
| - to_remove);
|
| -
|
| - SetInstructionState();
|
| - SetChevronState();
|
| -}
|
| -
|
| -void BookmarkBarGtk::BookmarkAllNodesRemoved(BookmarkModel* model) {
|
| - UpdateOtherBookmarksVisibility();
|
| - ResetButtons();
|
| -}
|
| -
|
| -void BookmarkBarGtk::BookmarkNodeChanged(BookmarkModel* model,
|
| - const BookmarkNode* node) {
|
| - if (node->parent() != model_->bookmark_bar_node()) {
|
| - // We only care about nodes on the bookmark bar.
|
| - return;
|
| - }
|
| - int index = model_->bookmark_bar_node()->GetIndexOf(node);
|
| - DCHECK(index != -1);
|
| -
|
| - GtkToolItem* item = gtk_toolbar_get_nth_item(
|
| - GTK_TOOLBAR(bookmark_toolbar_.get()), index);
|
| - GtkWidget* button = gtk_bin_get_child(GTK_BIN(item));
|
| - ConfigureButtonForNode(node, model, button, theme_service_);
|
| - SetChevronState();
|
| -}
|
| -
|
| -void BookmarkBarGtk::BookmarkNodeFaviconChanged(BookmarkModel* model,
|
| - const BookmarkNode* node) {
|
| - BookmarkNodeChanged(model, node);
|
| -}
|
| -
|
| -void BookmarkBarGtk::BookmarkNodeChildrenReordered(BookmarkModel* model,
|
| - const BookmarkNode* node) {
|
| - if (node != model_->bookmark_bar_node())
|
| - return; // We only care about reordering of the bookmark bar node.
|
| -
|
| - ResetButtons();
|
| -}
|
| -
|
| -void BookmarkBarGtk::Observe(int type,
|
| - const content::NotificationSource& source,
|
| - const content::NotificationDetails& details) {
|
| - if (type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED) {
|
| - if (model_ && model_->loaded()) {
|
| - // Regenerate the bookmark bar with all new objects with their theme
|
| - // properties set correctly for the new theme.
|
| - ResetButtons();
|
| - }
|
| -
|
| - // Resize the bookmark bar since the target height may have changed.
|
| - CalculateMaxHeight();
|
| - AnimationProgressed(&slide_animation_);
|
| -
|
| - UpdateEventBoxPaintability();
|
| -
|
| - GdkColor paint_box_color =
|
| - theme_service_->GetGdkColor(ThemeProperties::COLOR_TOOLBAR);
|
| - gtk_widget_modify_bg(paint_box_, GTK_STATE_NORMAL, &paint_box_color);
|
| -
|
| - if (bookmark_bar_state_ == BookmarkBar::DETACHED) {
|
| - GdkColor stroke_color = theme_service_->UsingNativeTheme() ?
|
| - theme_service_->GetBorderColor() :
|
| - theme_service_->GetGdkColor(ThemeProperties::COLOR_NTP_HEADER);
|
| - gtk_util::SetRoundedWindowBorderColor(paint_box_, stroke_color);
|
| - }
|
| -
|
| - SetOverflowButtonAppearance();
|
| - }
|
| -}
|
| -
|
| -GtkWidget* BookmarkBarGtk::CreateBookmarkButton(const BookmarkNode* node) {
|
| - GtkWidget* button = theme_service_->BuildChromeButton();
|
| - ConfigureButtonForNode(node, model_, button, theme_service_);
|
| -
|
| - // The tool item is also a source for dragging
|
| - gtk_drag_source_set(button, GDK_BUTTON1_MASK, NULL, 0,
|
| - static_cast<GdkDragAction>(GDK_ACTION_MOVE | GDK_ACTION_COPY));
|
| - int target_mask = GetCodeMask(node->is_folder());
|
| - ui::SetSourceTargetListFromCodeMask(button, target_mask);
|
| - g_signal_connect(button, "drag-begin",
|
| - G_CALLBACK(&OnButtonDragBeginThunk), this);
|
| - g_signal_connect(button, "drag-end",
|
| - G_CALLBACK(&OnButtonDragEndThunk), this);
|
| - g_signal_connect(button, "drag-data-get",
|
| - G_CALLBACK(&OnButtonDragGetThunk), this);
|
| - // We deliberately don't connect to "drag-data-delete" because the action of
|
| - // moving a button will regenerate all the contents of the bookmarks bar
|
| - // anyway.
|
| -
|
| - if (node->is_url()) {
|
| - // Connect to 'button-release-event' instead of 'clicked' because we need
|
| - // access to the modifier keys and we do different things on each
|
| - // button.
|
| - g_signal_connect(button, "button-press-event",
|
| - G_CALLBACK(OnButtonPressedThunk), this);
|
| - g_signal_connect(button, "clicked",
|
| - G_CALLBACK(OnClickedThunk), this);
|
| - gtk_util::SetButtonTriggersNavigation(button);
|
| - } else {
|
| - ConnectFolderButtonEvents(button, true);
|
| - }
|
| -
|
| - return button;
|
| -}
|
| -
|
| -GtkToolItem* BookmarkBarGtk::CreateBookmarkToolItem(const BookmarkNode* node) {
|
| - GtkWidget* button = CreateBookmarkButton(node);
|
| - g_object_set_data(G_OBJECT(button), "left-align-popup",
|
| - reinterpret_cast<void*>(true));
|
| -
|
| - GtkToolItem* item = gtk_tool_item_new();
|
| - gtk_container_add(GTK_CONTAINER(item), button);
|
| - gtk_widget_show_all(GTK_WIDGET(item));
|
| -
|
| - return item;
|
| -}
|
| -
|
| -void BookmarkBarGtk::ConnectFolderButtonEvents(GtkWidget* widget,
|
| - bool is_tool_item) {
|
| - // For toolbar items (i.e. not the overflow button or other bookmarks
|
| - // button), we handle motion and highlighting manually.
|
| - gtk_drag_dest_set(widget,
|
| - is_tool_item ? GTK_DEST_DEFAULT_DROP :
|
| - GTK_DEST_DEFAULT_ALL,
|
| - NULL,
|
| - 0,
|
| - kDragAction);
|
| - ui::SetDestTargetList(widget, kDestTargetList);
|
| - g_signal_connect(widget, "drag-data-received",
|
| - G_CALLBACK(&OnDragReceivedThunk), this);
|
| - if (is_tool_item) {
|
| - g_signal_connect(widget, "drag-motion",
|
| - G_CALLBACK(&OnFolderDragMotionThunk), this);
|
| - g_signal_connect(widget, "drag-leave",
|
| - G_CALLBACK(&OnDragLeaveThunk), this);
|
| - }
|
| -
|
| - g_signal_connect(widget, "button-press-event",
|
| - G_CALLBACK(OnButtonPressedThunk), this);
|
| - g_signal_connect(widget, "clicked",
|
| - G_CALLBACK(OnFolderClickedThunk), this);
|
| -
|
| - // Accept middle mouse clicking (which opens all). This must be called after
|
| - // connecting to "button-press-event" because the handler it attaches stops
|
| - // the propagation of that signal.
|
| - gtk_util::SetButtonClickableByMouseButtons(widget, true, true, false);
|
| -}
|
| -
|
| -const BookmarkNode* BookmarkBarGtk::GetNodeForToolButton(GtkWidget* widget) {
|
| - // First check to see if |button| is special cased.
|
| - if (widget == other_bookmarks_button_)
|
| - return model_->other_node();
|
| - else if (widget == event_box_.get() || widget == overflow_button_)
|
| - return model_->bookmark_bar_node();
|
| -
|
| - // Search the contents of |bookmark_toolbar_| for the corresponding widget
|
| - // and find its index.
|
| - GtkWidget* item_to_find = gtk_widget_get_parent(widget);
|
| - int index_to_use = -1;
|
| - int index = 0;
|
| - GList* children = gtk_container_get_children(
|
| - GTK_CONTAINER(bookmark_toolbar_.get()));
|
| - for (GList* item = children; item; item = item->next, index++) {
|
| - if (item->data == item_to_find) {
|
| - index_to_use = index;
|
| - break;
|
| - }
|
| - }
|
| - g_list_free(children);
|
| -
|
| - if (index_to_use != -1)
|
| - return model_->bookmark_bar_node()->GetChild(index_to_use);
|
| -
|
| - return NULL;
|
| -}
|
| -
|
| -void BookmarkBarGtk::PopupMenuForNode(GtkWidget* sender,
|
| - const BookmarkNode* node,
|
| - GdkEventButton* event) {
|
| - if (!model_->loaded()) {
|
| - // Don't do anything if the model isn't loaded.
|
| - return;
|
| - }
|
| -
|
| - const BookmarkNode* parent = NULL;
|
| - std::vector<const BookmarkNode*> nodes;
|
| - if (sender == other_bookmarks_button_) {
|
| - nodes.push_back(node);
|
| - parent = model_->bookmark_bar_node();
|
| - } else if (sender != bookmark_toolbar_.get()) {
|
| - nodes.push_back(node);
|
| - parent = node->parent();
|
| - } else {
|
| - parent = model_->bookmark_bar_node();
|
| - nodes.push_back(parent);
|
| - }
|
| -
|
| - GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(sender));
|
| - current_context_menu_controller_.reset(
|
| - new BookmarkContextMenuController(
|
| - window, this, browser_, browser_->profile(), page_navigator_, parent,
|
| - nodes));
|
| - current_context_menu_.reset(
|
| - new MenuGtk(NULL, current_context_menu_controller_->menu_model()));
|
| - current_context_menu_->PopupAsContext(
|
| - gfx::Point(event->x_root, event->y_root),
|
| - event->time);
|
| -}
|
| -
|
| -gboolean BookmarkBarGtk::OnButtonPressed(GtkWidget* sender,
|
| - GdkEventButton* event) {
|
| - last_pressed_coordinates_ = gfx::Point(event->x, event->y);
|
| -
|
| - if (event->button == 3 && gtk_widget_get_visible(bookmark_hbox_)) {
|
| - const BookmarkNode* node = GetNodeForToolButton(sender);
|
| - DCHECK(node);
|
| - DCHECK(page_navigator_);
|
| - PopupMenuForNode(sender, node, event);
|
| - }
|
| -
|
| - return FALSE;
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnClicked(GtkWidget* sender) {
|
| - const BookmarkNode* node = GetNodeForToolButton(sender);
|
| - DCHECK(node);
|
| - DCHECK(node->is_url());
|
| - DCHECK(page_navigator_);
|
| -
|
| - RecordAppLaunch(browser_->profile(), node->url());
|
| - chrome::OpenAll(window_->GetNativeWindow(), page_navigator_, node,
|
| - event_utils::DispositionForCurrentButtonPressEvent(),
|
| - browser_->profile());
|
| -
|
| - RecordBookmarkLaunch(node, GetBookmarkLaunchLocation());
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnButtonDragBegin(GtkWidget* button,
|
| - GdkDragContext* drag_context) {
|
| - GtkWidget* button_parent = gtk_widget_get_parent(button);
|
| -
|
| - // The parent tool item might be removed during the drag. Ref it so |button|
|
| - // won't get destroyed.
|
| - g_object_ref(button_parent);
|
| -
|
| - const BookmarkNode* node = GetNodeForToolButton(button);
|
| - DCHECK(!dragged_node_);
|
| - dragged_node_ = node;
|
| - DCHECK(dragged_node_);
|
| -
|
| - drag_icon_ = GetDragRepresentationForNode(node, model_, theme_service_);
|
| -
|
| - // We have to jump through some hoops to get the drag icon to line up because
|
| - // it is a different size than the button.
|
| - GtkRequisition req;
|
| - gtk_widget_size_request(drag_icon_, &req);
|
| - gfx::Rect button_rect = gtk_util::WidgetBounds(button);
|
| - gfx::Point drag_icon_relative =
|
| - gfx::Rect(req.width, req.height).CenterPoint() +
|
| - (last_pressed_coordinates_ - button_rect.CenterPoint());
|
| - gtk_drag_set_icon_widget(drag_context, drag_icon_,
|
| - drag_icon_relative.x(),
|
| - drag_icon_relative.y());
|
| -
|
| - // Hide our node, but reserve space for it on the toolbar.
|
| - int index = gtk_toolbar_get_item_index(GTK_TOOLBAR(bookmark_toolbar_.get()),
|
| - GTK_TOOL_ITEM(button_parent));
|
| - gtk_widget_hide(button);
|
| - toolbar_drop_item_ = CreateBookmarkToolItem(dragged_node_);
|
| - g_object_ref_sink(GTK_OBJECT(toolbar_drop_item_));
|
| - gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(bookmark_toolbar_.get()),
|
| - GTK_TOOL_ITEM(toolbar_drop_item_), index);
|
| - // Make sure it stays hidden for the duration of the drag.
|
| - gtk_widget_set_no_show_all(button, TRUE);
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnButtonDragEnd(GtkWidget* button,
|
| - GdkDragContext* drag_context) {
|
| - gtk_widget_show(button);
|
| - gtk_widget_set_no_show_all(button, FALSE);
|
| -
|
| - ClearToolbarDropHighlighting();
|
| -
|
| - DCHECK(dragged_node_);
|
| - dragged_node_ = NULL;
|
| -
|
| - DCHECK(drag_icon_);
|
| - gtk_widget_destroy(drag_icon_);
|
| - drag_icon_ = NULL;
|
| -
|
| - g_object_unref(gtk_widget_get_parent(button));
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnButtonDragGet(GtkWidget* widget,
|
| - GdkDragContext* context,
|
| - GtkSelectionData* selection_data,
|
| - guint target_type,
|
| - guint time) {
|
| - const BookmarkNode* node = BookmarkNodeForWidget(widget);
|
| - WriteBookmarkToSelection(
|
| - node, selection_data, target_type, browser_->profile());
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnAppsButtonClicked(GtkWidget* sender) {
|
| - content::OpenURLParams params(
|
| - GURL(chrome::kChromeUIAppsURL),
|
| - content::Referrer(),
|
| - event_utils::DispositionForCurrentButtonPressEvent(),
|
| - content::PAGE_TRANSITION_AUTO_BOOKMARK,
|
| - false);
|
| - browser_->OpenURL(params);
|
| - RecordBookmarkAppsPageOpen(GetBookmarkLaunchLocation());
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnFolderClicked(GtkWidget* sender) {
|
| - // Stop its throbbing, if any.
|
| - HoverControllerGtk* hover_controller =
|
| - HoverControllerGtk::GetHoverControllerGtk(sender);
|
| - if (hover_controller)
|
| - hover_controller->StartThrobbing(0);
|
| -
|
| - GdkEvent* event = gtk_get_current_event();
|
| - if (event->button.button == 1 ||
|
| - (event->button.button == 2 && sender == overflow_button_)) {
|
| - RecordBookmarkFolderOpen(GetBookmarkLaunchLocation());
|
| - PopupForButton(sender);
|
| - } else if (event->button.button == 2) {
|
| - const BookmarkNode* node = GetNodeForToolButton(sender);
|
| - chrome::OpenAll(window_->GetNativeWindow(), page_navigator_, node,
|
| - NEW_BACKGROUND_TAB, browser_->profile());
|
| - }
|
| - gdk_event_free(event);
|
| -}
|
| -
|
| -gboolean BookmarkBarGtk::OnToolbarDragMotion(GtkWidget* toolbar,
|
| - GdkDragContext* context,
|
| - gint x,
|
| - gint y,
|
| - guint time) {
|
| - gint index = gtk_toolbar_get_drop_index(GTK_TOOLBAR(toolbar), x, y);
|
| - return ItemDraggedOverToolbar(context, index, time);
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnToolbarSizeAllocate(GtkWidget* widget,
|
| - GtkAllocation* allocation) {
|
| - if (allocation->width == last_allocation_width_) {
|
| - // If the width hasn't changed, then the visibility of the chevron
|
| - // doesn't need to change. This check prevents us from getting stuck in a
|
| - // loop where allocates are queued indefinitely while the visibility of
|
| - // overflow chevron toggles without actual resizes of the toolbar.
|
| - return;
|
| - }
|
| - last_allocation_width_ = allocation->width;
|
| -
|
| - SetChevronState();
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnDragReceived(GtkWidget* widget,
|
| - GdkDragContext* context,
|
| - gint x, gint y,
|
| - GtkSelectionData* selection_data,
|
| - guint target_type, guint time) {
|
| - if (!edit_bookmarks_enabled_.GetValue()) {
|
| - gtk_drag_finish(context, FALSE, FALSE, time);
|
| - return;
|
| - }
|
| -
|
| - gboolean dnd_success = FALSE;
|
| - gboolean delete_selection_data = FALSE;
|
| -
|
| - const BookmarkNode* dest_node = model_->bookmark_bar_node();
|
| - gint index;
|
| - if (widget == bookmark_toolbar_.get()) {
|
| - index = gtk_toolbar_get_drop_index(
|
| - GTK_TOOLBAR(bookmark_toolbar_.get()), x, y);
|
| - } else if (widget == instructions_) {
|
| - dest_node = model_->bookmark_bar_node();
|
| - index = 0;
|
| - } else {
|
| - index = GetToolbarIndexForDragOverFolder(widget, x);
|
| - if (index < 0) {
|
| - dest_node = GetNodeForToolButton(widget);
|
| - index = dest_node->child_count();
|
| - }
|
| - }
|
| -
|
| - switch (target_type) {
|
| - case ui::CHROME_BOOKMARK_ITEM: {
|
| - gint length = gtk_selection_data_get_length(selection_data);
|
| - Pickle pickle(reinterpret_cast<const char*>(
|
| - gtk_selection_data_get_data(selection_data)), length);
|
| - BookmarkNodeData drag_data;
|
| - if (drag_data.ReadFromPickle(&pickle)) {
|
| - dnd_success = chrome::DropBookmarks(browser_->profile(),
|
| - drag_data, dest_node, index) != ui::DragDropTypes::DRAG_NONE;
|
| - }
|
| - break;
|
| - }
|
| -
|
| - case ui::CHROME_NAMED_URL: {
|
| - dnd_success = CreateNewBookmarkFromNamedUrl(
|
| - selection_data, model_, dest_node, index);
|
| - break;
|
| - }
|
| -
|
| - case ui::TEXT_URI_LIST: {
|
| - dnd_success = CreateNewBookmarksFromURIList(
|
| - selection_data, model_, dest_node, index);
|
| - break;
|
| - }
|
| -
|
| - case ui::NETSCAPE_URL: {
|
| - dnd_success = CreateNewBookmarkFromNetscapeURL(
|
| - selection_data, model_, dest_node, index);
|
| - break;
|
| - }
|
| -
|
| - case ui::TEXT_PLAIN: {
|
| - guchar* text = gtk_selection_data_get_text(selection_data);
|
| - if (!text)
|
| - break;
|
| - GURL url(reinterpret_cast<char*>(text));
|
| - g_free(text);
|
| - // TODO(estade): It would be nice to head this case off at drag motion,
|
| - // so that it doesn't look like we can drag onto the bookmark bar.
|
| - if (!url.is_valid())
|
| - break;
|
| - base::string16 title = GetNameForURL(url);
|
| - model_->AddURL(dest_node, index, title, url);
|
| - dnd_success = TRUE;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - gtk_drag_finish(context, dnd_success, delete_selection_data, time);
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnDragLeave(GtkWidget* sender,
|
| - GdkDragContext* context,
|
| - guint time) {
|
| - if (GTK_IS_BUTTON(sender))
|
| - gtk_drag_unhighlight(sender);
|
| -
|
| - ClearToolbarDropHighlighting();
|
| -}
|
| -
|
| -gboolean BookmarkBarGtk::OnFolderDragMotion(GtkWidget* button,
|
| - GdkDragContext* context,
|
| - gint x,
|
| - gint y,
|
| - guint time) {
|
| - if (!edit_bookmarks_enabled_.GetValue())
|
| - return FALSE;
|
| - GdkAtom target_type = gtk_drag_dest_find_target(button, context, NULL);
|
| - if (target_type == GDK_NONE)
|
| - return FALSE;
|
| -
|
| - int index = GetToolbarIndexForDragOverFolder(button, x);
|
| - if (index < 0) {
|
| - ClearToolbarDropHighlighting();
|
| -
|
| - // Drag is over middle of folder.
|
| - gtk_drag_highlight(button);
|
| - if (target_type == ui::GetAtomForTarget(ui::CHROME_BOOKMARK_ITEM)) {
|
| - gdk_drag_status(context, GDK_ACTION_MOVE, time);
|
| - } else {
|
| - gdk_drag_status(context, GDK_ACTION_COPY, time);
|
| - }
|
| -
|
| - return TRUE;
|
| - }
|
| -
|
| - // Remove previous highlighting.
|
| - gtk_drag_unhighlight(button);
|
| - return ItemDraggedOverToolbar(context, index, time);
|
| -}
|
| -
|
| -gboolean BookmarkBarGtk::OnEventBoxExpose(GtkWidget* widget,
|
| - GdkEventExpose* event) {
|
| - TRACE_EVENT0("ui::gtk", "BookmarkBarGtk::OnEventBoxExpose");
|
| - GtkThemeService* theme_provider = theme_service_;
|
| -
|
| - // We don't need to render the toolbar image in GTK mode, except when
|
| - // detached.
|
| - if (theme_provider->UsingNativeTheme() &&
|
| - bookmark_bar_state_ != BookmarkBar::DETACHED)
|
| - return FALSE;
|
| -
|
| - if (bookmark_bar_state_ != BookmarkBar::DETACHED) {
|
| - cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(widget));
|
| - gdk_cairo_rectangle(cr, &event->area);
|
| - cairo_clip(cr);
|
| -
|
| - // Paint the background theme image.
|
| - gfx::Point tabstrip_origin =
|
| - tabstrip_origin_provider_->GetTabStripOriginForWidget(widget);
|
| - gtk_util::DrawThemedToolbarBackground(widget, cr, event, tabstrip_origin,
|
| - theme_provider);
|
| -
|
| - cairo_destroy(cr);
|
| - } else {
|
| - gfx::Size web_contents_size;
|
| - if (!GetWebContentsSize(&web_contents_size))
|
| - return FALSE;
|
| - gfx::CanvasSkiaPaint canvas(event, true);
|
| -
|
| - GtkAllocation allocation;
|
| - gtk_widget_get_allocation(widget, &allocation);
|
| -
|
| - gfx::Rect area = gtk_widget_get_has_window(widget) ?
|
| - gfx::Rect(0, 0, allocation.width, allocation.height) :
|
| - gfx::Rect(allocation);
|
| - NtpBackgroundUtil::PaintBackgroundDetachedMode(theme_provider, &canvas,
|
| - area, web_contents_size.height());
|
| - }
|
| -
|
| - return FALSE; // Propagate expose to children.
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnEventBoxDestroy(GtkWidget* widget) {
|
| - if (model_)
|
| - model_->RemoveObserver(this);
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnParentSizeAllocate(GtkWidget* widget,
|
| - GtkAllocation* allocation) {
|
| - // In detached mode, our layout depends on the size of the tab contents.
|
| - // We get the size-allocate signal before the tab contents does, hence we
|
| - // need to post a delayed task so we will paint correctly. Note that
|
| - // gtk_widget_queue_draw by itself does not work, despite that it claims to
|
| - // be asynchronous.
|
| - if (bookmark_bar_state_ == BookmarkBar::DETACHED) {
|
| - base::MessageLoop::current()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&BookmarkBarGtk::PaintEventBox, weak_factory_.GetWeakPtr()));
|
| - }
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnThrobbingWidgetDestroy(GtkWidget* widget) {
|
| - SetThrobbingWidget(NULL);
|
| -}
|
| -
|
| -void BookmarkBarGtk::ShowImportDialog() {
|
| - chrome::ShowImportDialog(browser_);
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnAppsPageShortcutVisibilityChanged() {
|
| - const bool visible =
|
| - chrome::ShouldShowAppsShortcutInBookmarkBar(
|
| - browser_->profile(), browser_->host_desktop_type());
|
| - gtk_widget_set_visible(apps_shortcut_button_, visible);
|
| - gtk_widget_set_no_show_all(apps_shortcut_button_, !visible);
|
| -}
|
| -
|
| -void BookmarkBarGtk::OnEditBookmarksEnabledChanged() {
|
| - GtkDestDefaults dest_defaults =
|
| - *edit_bookmarks_enabled_ ? GTK_DEST_DEFAULT_ALL :
|
| - GTK_DEST_DEFAULT_DROP;
|
| - gtk_drag_dest_set(overflow_button_, dest_defaults, NULL, 0, kDragAction);
|
| - gtk_drag_dest_set(other_bookmarks_button_, dest_defaults,
|
| - NULL, 0, kDragAction);
|
| - ui::SetDestTargetList(overflow_button_, kDestTargetList);
|
| - ui::SetDestTargetList(other_bookmarks_button_, kDestTargetList);
|
| -}
|
|
|