OLD | NEW |
| (Empty) |
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 } | |
OLD | NEW |