Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / back_forward_button_gtk.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/gtk/back_forward_button_gtk.h"
6
7 #include <gtk/gtk.h>
8
9 #include "base/bind.h"
10 #include "base/message_loop/message_loop.h"
11 #include "chrome/app/chrome_command_ids.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/browser_commands.h"
15 #include "chrome/browser/ui/gtk/event_utils.h"
16 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
17 #include "chrome/browser/ui/gtk/gtk_util.h"
18 #include "chrome/browser/ui/gtk/menu_gtk.h"
19 #include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
20 #include "grit/generated_resources.h"
21 #include "grit/theme_resources.h"
22 #include "ui/base/l10n/l10n_util.h"
23
24 // The time in milliseconds between when the user clicks and the menu appears.
25 static const int kMenuTimerDelay = 500;
26
27 BackForwardButtonGtk::BackForwardButtonGtk(Browser* browser, bool is_forward)
28     : browser_(browser),
29       is_forward_(is_forward),
30       weak_factory_(this) {
31   int normal, pushed, hover, disabled, tooltip;
32   const char* stock;
33   if (is_forward) {
34     normal = IDR_FORWARD;
35     pushed = IDR_FORWARD_P;
36     hover = IDR_FORWARD_H;
37     disabled = IDR_FORWARD_D;
38     tooltip = IDS_TOOLTIP_FORWARD;
39     stock = GTK_STOCK_GO_FORWARD;
40   } else {
41     normal = IDR_BACK;
42     pushed = IDR_BACK_P;
43     hover = IDR_BACK_H;
44     disabled = IDR_BACK_D;
45     tooltip = IDS_TOOLTIP_BACK;
46     stock = GTK_STOCK_GO_BACK;
47   }
48   button_.reset(new CustomDrawButton(
49       GtkThemeService::GetFrom(browser_->profile()),
50       normal, pushed, hover, disabled, stock, GTK_ICON_SIZE_SMALL_TOOLBAR));
51   gtk_widget_set_tooltip_text(widget(),
52                               l10n_util::GetStringUTF8(tooltip).c_str());
53   menu_model_.reset(new BackForwardMenuModel(browser, is_forward ?
54       BackForwardMenuModel::FORWARD_MENU :
55       BackForwardMenuModel::BACKWARD_MENU));
56
57   g_signal_connect(widget(), "clicked",
58                    G_CALLBACK(OnClickThunk), this);
59   g_signal_connect(widget(), "button-press-event",
60                    G_CALLBACK(OnButtonPressThunk), this);
61   gtk_widget_add_events(widget(), GDK_POINTER_MOTION_MASK);
62   g_signal_connect(widget(), "motion-notify-event",
63                    G_CALLBACK(OnMouseMoveThunk), this);
64
65   // Popup the menu as left-aligned relative to this widget rather than the
66   // default of right aligned.
67   g_object_set_data(G_OBJECT(widget()), "left-align-popup",
68                     reinterpret_cast<void*>(true));
69
70   gtk_util::SetButtonTriggersNavigation(widget());
71 }
72
73 BackForwardButtonGtk::~BackForwardButtonGtk() {
74 }
75
76 void BackForwardButtonGtk::StoppedShowing() {
77   button_->UnsetPaintOverride();
78 }
79
80 bool BackForwardButtonGtk::AlwaysShowIconForCmd(int command_id) const {
81   return true;
82 }
83
84 void BackForwardButtonGtk::ShowBackForwardMenu(int button, guint32 event_time) {
85   menu_.reset(new MenuGtk(this, menu_model_.get()));
86   button_->SetPaintOverride(GTK_STATE_ACTIVE);
87   menu_->PopupForWidget(widget(), button, event_time);
88 }
89
90 void BackForwardButtonGtk::OnClick(GtkWidget* widget) {
91   weak_factory_.InvalidateWeakPtrs();
92
93   chrome::ExecuteCommandWithDisposition(
94       browser_,
95       is_forward_ ? IDC_FORWARD : IDC_BACK,
96       event_utils::DispositionForCurrentButtonPressEvent());
97 }
98
99 gboolean BackForwardButtonGtk::OnButtonPress(GtkWidget* widget,
100                                              GdkEventButton* event) {
101   if (event->button == 3)
102     ShowBackForwardMenu(event->button, event->time);
103
104   if (event->button != 1)
105     return FALSE;
106
107   y_position_of_last_press_ = static_cast<int>(event->y);
108   base::MessageLoop::current()->PostDelayedTask(
109       FROM_HERE,
110       base::Bind(&BackForwardButtonGtk::ShowBackForwardMenu,
111                  weak_factory_.GetWeakPtr(),
112                  event->button,
113                  event->time),
114       base::TimeDelta::FromMilliseconds(kMenuTimerDelay));
115   return FALSE;
116 }
117
118 gboolean BackForwardButtonGtk::OnMouseMove(GtkWidget* widget,
119                                            GdkEventMotion* event) {
120   // If we aren't waiting to show the back forward menu, do nothing.
121   if (!weak_factory_.HasWeakPtrs())
122     return FALSE;
123
124   // We only count moves about a certain threshold.
125   GtkSettings* settings = gtk_widget_get_settings(widget);
126   int drag_min_distance;
127   g_object_get(settings, "gtk-dnd-drag-threshold", &drag_min_distance, NULL);
128   if (event->y - y_position_of_last_press_ < drag_min_distance)
129     return FALSE;
130
131   // We will show the menu now. Cancel the delayed event.
132   weak_factory_.InvalidateWeakPtrs();
133   ShowBackForwardMenu(/* button */ 1, event->time);
134   return FALSE;
135 }