root/chrome/browser/ui/gtk/back_forward_button_gtk.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. weak_factory_
  2. StoppedShowing
  3. AlwaysShowIconForCmd
  4. ShowBackForwardMenu
  5. OnClick
  6. OnButtonPress
  7. OnMouseMove

// 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/back_forward_button_gtk.h"

#include <gtk/gtk.h>

#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/gtk/event_utils.h"
#include "chrome/browser/ui/gtk/gtk_theme_service.h"
#include "chrome/browser/ui/gtk/gtk_util.h"
#include "chrome/browser/ui/gtk/menu_gtk.h"
#include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"

// The time in milliseconds between when the user clicks and the menu appears.
static const int kMenuTimerDelay = 500;

BackForwardButtonGtk::BackForwardButtonGtk(Browser* browser, bool is_forward)
    : browser_(browser),
      is_forward_(is_forward),
      weak_factory_(this) {
  int normal, pushed, hover, disabled, tooltip;
  const char* stock;
  if (is_forward) {
    normal = IDR_FORWARD;
    pushed = IDR_FORWARD_P;
    hover = IDR_FORWARD_H;
    disabled = IDR_FORWARD_D;
    tooltip = IDS_TOOLTIP_FORWARD;
    stock = GTK_STOCK_GO_FORWARD;
  } else {
    normal = IDR_BACK;
    pushed = IDR_BACK_P;
    hover = IDR_BACK_H;
    disabled = IDR_BACK_D;
    tooltip = IDS_TOOLTIP_BACK;
    stock = GTK_STOCK_GO_BACK;
  }
  button_.reset(new CustomDrawButton(
      GtkThemeService::GetFrom(browser_->profile()),
      normal, pushed, hover, disabled, stock, GTK_ICON_SIZE_SMALL_TOOLBAR));
  gtk_widget_set_tooltip_text(widget(),
                              l10n_util::GetStringUTF8(tooltip).c_str());
  menu_model_.reset(new BackForwardMenuModel(browser, is_forward ?
      BackForwardMenuModel::FORWARD_MENU :
      BackForwardMenuModel::BACKWARD_MENU));

  g_signal_connect(widget(), "clicked",
                   G_CALLBACK(OnClickThunk), this);
  g_signal_connect(widget(), "button-press-event",
                   G_CALLBACK(OnButtonPressThunk), this);
  gtk_widget_add_events(widget(), GDK_POINTER_MOTION_MASK);
  g_signal_connect(widget(), "motion-notify-event",
                   G_CALLBACK(OnMouseMoveThunk), this);

  // Popup the menu as left-aligned relative to this widget rather than the
  // default of right aligned.
  g_object_set_data(G_OBJECT(widget()), "left-align-popup",
                    reinterpret_cast<void*>(true));

  gtk_util::SetButtonTriggersNavigation(widget());
}

BackForwardButtonGtk::~BackForwardButtonGtk() {
}

void BackForwardButtonGtk::StoppedShowing() {
  button_->UnsetPaintOverride();
}

bool BackForwardButtonGtk::AlwaysShowIconForCmd(int command_id) const {
  return true;
}

void BackForwardButtonGtk::ShowBackForwardMenu(int button, guint32 event_time) {
  menu_.reset(new MenuGtk(this, menu_model_.get()));
  button_->SetPaintOverride(GTK_STATE_ACTIVE);
  menu_->PopupForWidget(widget(), button, event_time);
}

void BackForwardButtonGtk::OnClick(GtkWidget* widget) {
  weak_factory_.InvalidateWeakPtrs();

  chrome::ExecuteCommandWithDisposition(
      browser_,
      is_forward_ ? IDC_FORWARD : IDC_BACK,
      event_utils::DispositionForCurrentButtonPressEvent());
}

gboolean BackForwardButtonGtk::OnButtonPress(GtkWidget* widget,
                                             GdkEventButton* event) {
  if (event->button == 3)
    ShowBackForwardMenu(event->button, event->time);

  if (event->button != 1)
    return FALSE;

  y_position_of_last_press_ = static_cast<int>(event->y);
  base::MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&BackForwardButtonGtk::ShowBackForwardMenu,
                 weak_factory_.GetWeakPtr(),
                 event->button,
                 event->time),
      base::TimeDelta::FromMilliseconds(kMenuTimerDelay));
  return FALSE;
}

gboolean BackForwardButtonGtk::OnMouseMove(GtkWidget* widget,
                                           GdkEventMotion* event) {
  // If we aren't waiting to show the back forward menu, do nothing.
  if (!weak_factory_.HasWeakPtrs())
    return FALSE;

  // We only count moves about a certain threshold.
  GtkSettings* settings = gtk_widget_get_settings(widget);
  int drag_min_distance;
  g_object_get(settings, "gtk-dnd-drag-threshold", &drag_min_distance, NULL);
  if (event->y - y_position_of_last_press_ < drag_min_distance)
    return FALSE;

  // We will show the menu now. Cancel the delayed event.
  weak_factory_.InvalidateWeakPtrs();
  ShowBackForwardMenu(/* button */ 1, event->time);
  return FALSE;
}

/* [<][>][^][v][top][bottom][index][help] */