Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(853)

Side by Side Diff: chrome/browser/ui/gtk/reload_button_gtk.cc

Issue 10736008: Added reload drop-down menu for the Reload button on Linux when in the DevTools mode. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comment about browser interface. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/gtk/reload_button_gtk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/gtk/reload_button_gtk.h" 5 #include "chrome/browser/ui/gtk/reload_button_gtk.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 10 matching lines...) Expand all
21 #include "grit/generated_resources.h" 21 #include "grit/generated_resources.h"
22 #include "grit/theme_resources.h" 22 #include "grit/theme_resources.h"
23 #include "grit/theme_resources_standard.h" 23 #include "grit/theme_resources_standard.h"
24 #include "ui/base/l10n/l10n_util.h" 24 #include "ui/base/l10n/l10n_util.h"
25 25
26 // The width of this button in GTK+ theme mode. The Stop and Refresh stock icons 26 // The width of this button in GTK+ theme mode. The Stop and Refresh stock icons
27 // can be different sizes; this variable is used to make sure that the button 27 // can be different sizes; this variable is used to make sure that the button
28 // doesn't change sizes when switching between the two. 28 // doesn't change sizes when switching between the two.
29 static int GtkButtonWidth = 0; 29 static int GtkButtonWidth = 0;
30 30
31 // The time in milliseconds between when the user clicks and the menu appears.
32 static const int kReloadMenuTimerDelay = 500;
33
34 // Content of the Reload drop-down menu.
35 static const int kReloadMenuItems[] = {
36 IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM,
37 IDS_RELOAD_MENU_HARD_RELOAD_ITEM,
38 IDS_RELOAD_MENU_CLEAR_AND_HARD_RELOAD_ITEM,
39 };
40
31 //////////////////////////////////////////////////////////////////////////////// 41 ////////////////////////////////////////////////////////////////////////////////
32 // ReloadButton, public: 42 // ReloadButton, public:
33 43
34 ReloadButtonGtk::ReloadButtonGtk(LocationBarViewGtk* location_bar, 44 ReloadButtonGtk::ReloadButtonGtk(LocationBarViewGtk* location_bar,
35 Browser* browser) 45 Browser* browser)
36 : location_bar_(location_bar), 46 : location_bar_(location_bar),
37 browser_(browser), 47 browser_(browser),
38 intended_mode_(MODE_RELOAD), 48 intended_mode_(MODE_RELOAD),
39 visible_mode_(MODE_RELOAD), 49 visible_mode_(MODE_RELOAD),
40 theme_service_(browser ? 50 theme_service_(browser ?
41 GtkThemeService::GetFrom(browser->profile()) : NULL), 51 GtkThemeService::GetFrom(browser->profile()) : NULL),
42 reload_(theme_service_, IDR_RELOAD, IDR_RELOAD_P, IDR_RELOAD_H, 0), 52 reload_(theme_service_, IDR_RELOAD, IDR_RELOAD_P, IDR_RELOAD_H, 0),
43 stop_(theme_service_, IDR_STOP, IDR_STOP_P, IDR_STOP_H, IDR_STOP_D), 53 stop_(theme_service_, IDR_STOP, IDR_STOP_P, IDR_STOP_H, IDR_STOP_D),
44 widget_(gtk_chrome_button_new()), 54 widget_(gtk_chrome_button_new()),
45 stop_to_reload_timer_delay_(base::TimeDelta::FromMilliseconds(1350)), 55 stop_to_reload_timer_delay_(base::TimeDelta::FromMilliseconds(1350)),
56 weak_factory_(this),
46 testing_mouse_hovered_(false), 57 testing_mouse_hovered_(false),
47 testing_reload_count_(0) { 58 testing_reload_count_(0) {
59 menu_model_.reset(new ui::SimpleMenuModel(this));
60 for (size_t i = 0; i < arraysize(kReloadMenuItems); i++) {
61 menu_model_->AddItemWithStringId(kReloadMenuItems[i], kReloadMenuItems[i]);
62 }
63
48 gtk_widget_set_size_request(widget(), reload_.Width(), reload_.Height()); 64 gtk_widget_set_size_request(widget(), reload_.Width(), reload_.Height());
49 65
50 gtk_widget_set_app_paintable(widget(), TRUE); 66 gtk_widget_set_app_paintable(widget(), TRUE);
51 67
52 g_signal_connect(widget(), "clicked", G_CALLBACK(OnClickedThunk), this); 68 g_signal_connect(widget(), "clicked", G_CALLBACK(OnClickedThunk), this);
53 g_signal_connect(widget(), "expose-event", G_CALLBACK(OnExposeThunk), this); 69 g_signal_connect(widget(), "expose-event", G_CALLBACK(OnExposeThunk), this);
54 g_signal_connect(widget(), "leave-notify-event", 70 g_signal_connect(widget(), "leave-notify-event",
55 G_CALLBACK(OnLeaveNotifyThunk), this); 71 G_CALLBACK(OnLeaveNotifyThunk), this);
56 gtk_widget_set_can_focus(widget(), FALSE); 72 gtk_widget_set_can_focus(widget(), FALSE);
57 73
58 gtk_widget_set_has_tooltip(widget(), TRUE); 74 gtk_widget_set_has_tooltip(widget(), TRUE);
59 g_signal_connect(widget(), "query-tooltip", G_CALLBACK(OnQueryTooltipThunk), 75 g_signal_connect(widget(), "query-tooltip", G_CALLBACK(OnQueryTooltipThunk),
60 this); 76 this);
61 77
78 g_signal_connect(widget(), "button-press-event",
79 G_CALLBACK(OnButtonPressThunk), this);
80 gtk_widget_add_events(widget(), GDK_POINTER_MOTION_MASK);
81 g_signal_connect(widget(), "motion-notify-event",
82 G_CALLBACK(OnMouseMoveThunk), this);
83
84 // Popup the menu as left-aligned relative to this widget rather than the
85 // default of right aligned.
86 g_object_set_data(G_OBJECT(widget()), "left-align-popup",
87 reinterpret_cast<void*>(true));
88
62 hover_controller_.Init(widget()); 89 hover_controller_.Init(widget());
63 gtk_util::SetButtonTriggersNavigation(widget()); 90 gtk_util::SetButtonTriggersNavigation(widget());
64 91
65 if (theme_service_) { 92 if (theme_service_) {
66 theme_service_->InitThemesFor(this); 93 theme_service_->InitThemesFor(this);
67 registrar_.Add(this, 94 registrar_.Add(this,
68 chrome::NOTIFICATION_BROWSER_THEME_CHANGED, 95 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
69 content::Source<ThemeService>(theme_service_)); 96 content::Source<ThemeService>(theme_service_));
70 } 97 }
71 98
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 DCHECK(chrome::NOTIFICATION_BROWSER_THEME_CHANGED == type); 164 DCHECK(chrome::NOTIFICATION_BROWSER_THEME_CHANGED == type);
138 165
139 GtkThemeService* provider = static_cast<GtkThemeService*>( 166 GtkThemeService* provider = static_cast<GtkThemeService*>(
140 content::Source<ThemeService>(source).ptr()); 167 content::Source<ThemeService>(source).ptr());
141 DCHECK_EQ(provider, theme_service_); 168 DCHECK_EQ(provider, theme_service_);
142 GtkButtonWidth = 0; 169 GtkButtonWidth = 0;
143 UpdateThemeButtons(); 170 UpdateThemeButtons();
144 } 171 }
145 172
146 //////////////////////////////////////////////////////////////////////////////// 173 ////////////////////////////////////////////////////////////////////////////////
174 // ReloadButtonGtk, MenuGtk::Delegate implementation:
175
176 void ReloadButtonGtk::StoppedShowing() {
177 reload_.set_paint_override(-1);
178 }
179
180 ////////////////////////////////////////////////////////////////////////////////
181 // ReloadButtonGtk, SimpleMenuModel::Delegate implementation:
182
183 bool ReloadButtonGtk::IsCommandIdChecked(int command_id) const {
184 return false;
185 }
186
187 bool ReloadButtonGtk::IsCommandIdEnabled(int command_id) const {
188 return true;
189 }
190
191 bool ReloadButtonGtk::IsCommandIdVisible(int command_id) const {
192 return true;
193 }
194
195 bool ReloadButtonGtk::GetAcceleratorForCommandId(int command_id,
196 ui::Accelerator* accelerator) {
197 return false;
198 }
199
200 void ReloadButtonGtk::ExecuteCommand(int command_id) {
201 switch (command_id) {
202 case IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM:
203 DoReload(IDC_RELOAD);
204 break;
205 case IDS_RELOAD_MENU_HARD_RELOAD_ITEM:
206 DoReload(IDC_RELOAD_IGNORING_CACHE);
207 break;
208 case IDS_RELOAD_MENU_CLEAR_AND_HARD_RELOAD_ITEM:
209 ClearCache();
210 DoReload(IDC_RELOAD_IGNORING_CACHE);
211 break;
212 default:
213 LOG(ERROR) << "Unknown reload menu command";
214 }
215 }
216
217 ////////////////////////////////////////////////////////////////////////////////
147 // ReloadButtonGtk, private: 218 // ReloadButtonGtk, private:
148 219
149 void ReloadButtonGtk::OnClicked(GtkWidget* /* sender */) { 220 void ReloadButtonGtk::OnClicked(GtkWidget* /* sender */) {
221 weak_factory_.InvalidateWeakPtrs();
150 if (visible_mode_ == MODE_STOP) { 222 if (visible_mode_ == MODE_STOP) {
151 // Do nothing if Stop was disabled due to an attempt to change back to 223 // Do nothing if Stop was disabled due to an attempt to change back to
152 // RELOAD mode while hovered. 224 // RELOAD mode while hovered.
153 if (stop_.paint_override() == GTK_STATE_INSENSITIVE) 225 if (stop_.paint_override() == GTK_STATE_INSENSITIVE)
154 return; 226 return;
155 227
156 if (browser_) 228 if (browser_)
157 chrome::Stop(browser_); 229 chrome::Stop(browser_);
158 230
159 // The user has clicked, so we can feel free to update the button, 231 // The user has clicked, so we can feel free to update the button,
160 // even if the mouse is still hovering. 232 // even if the mouse is still hovering.
161 ChangeMode(MODE_RELOAD, true); 233 ChangeMode(MODE_RELOAD, true);
162 } else if (!double_click_timer_.IsRunning()) { 234 } else if (!double_click_timer_.IsRunning()) {
163 // Shift-clicking or Ctrl-clicking the reload button means we should ignore 235 DoReload(0);
164 // any cached content.
165 int command;
166 GdkModifierType modifier_state;
167 gtk_get_current_event_state(&modifier_state);
168 guint modifier_state_uint = modifier_state;
169 if (modifier_state_uint & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) {
170 command = IDC_RELOAD_IGNORING_CACHE;
171 // Mask off Shift and Control so they don't affect the disposition below.
172 modifier_state_uint &= ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK);
173 } else {
174 command = IDC_RELOAD;
175 }
176
177 WindowOpenDisposition disposition =
178 event_utils::DispositionFromGdkState(modifier_state_uint);
179 if ((disposition == CURRENT_TAB) && location_bar_) {
180 // Forcibly reset the location bar, since otherwise it won't discard any
181 // ongoing user edits, since it doesn't realize this is a user-initiated
182 // action.
183 location_bar_->Revert();
184 }
185
186 // Start a timer - while this timer is running, the reload button cannot be
187 // changed to a stop button. We do not set |intended_mode_| to MODE_STOP
188 // here as the browser will do that when it actually starts loading (which
189 // may happen synchronously, thus the need to do this before telling the
190 // browser to execute the reload command).
191 double_click_timer_.Start(FROM_HERE, double_click_timer_delay_, this,
192 &ReloadButtonGtk::OnDoubleClickTimer);
193
194 if (browser_)
195 chrome::ExecuteCommandWithDisposition(browser_, command, disposition);
196 ++testing_reload_count_;
197 } 236 }
198 } 237 }
199 238
200 gboolean ReloadButtonGtk::OnExpose(GtkWidget* widget, 239 gboolean ReloadButtonGtk::OnExpose(GtkWidget* widget,
201 GdkEventExpose* e) { 240 GdkEventExpose* e) {
202 TRACE_EVENT0("ui::gtk", "ReloadButtonGtk::OnExpose"); 241 TRACE_EVENT0("ui::gtk", "ReloadButtonGtk::OnExpose");
203 if (theme_service_ && theme_service_->UsingNativeTheme()) 242 if (theme_service_ && theme_service_->UsingNativeTheme())
204 return FALSE; 243 return FALSE;
205 return ((visible_mode_ == MODE_RELOAD) ? reload_ : stop_).OnExpose( 244 return ((visible_mode_ == MODE_RELOAD) ? reload_ : stop_).OnExpose(
206 widget, e, hover_controller_.GetCurrentValue()); 245 widget, e, hover_controller_.GetCurrentValue());
207 } 246 }
208 247
209 gboolean ReloadButtonGtk::OnLeaveNotify(GtkWidget* /* widget */, 248 gboolean ReloadButtonGtk::OnLeaveNotify(GtkWidget* /* widget */,
210 GdkEventCrossing* /* event */) { 249 GdkEventCrossing* /* event */) {
211 ChangeMode(intended_mode_, true); 250 ChangeMode(intended_mode_, true);
212 return FALSE; 251 return FALSE;
213 } 252 }
214 253
215 gboolean ReloadButtonGtk::OnQueryTooltip(GtkWidget* /* sender */, 254 gboolean ReloadButtonGtk::OnQueryTooltip(GtkWidget* /* sender */,
216 gint /* x */, 255 gint /* x */,
217 gint /* y */, 256 gint /* y */,
218 gboolean /* keyboard_mode */, 257 gboolean /* keyboard_mode */,
219 GtkTooltip* tooltip) { 258 GtkTooltip* tooltip) {
220 // |location_bar_| can be NULL in tests. 259 // |location_bar_| can be NULL in tests.
221 if (!location_bar_) 260 if (!location_bar_)
222 return FALSE; 261 return FALSE;
223 262
263 int reload_tooltip = ReloadMenuEnabled() ?
264 IDS_TOOLTIP_RELOAD_WITH_MENU : IDS_TOOLTIP_RELOAD;
224 gtk_tooltip_set_text(tooltip, l10n_util::GetStringUTF8( 265 gtk_tooltip_set_text(tooltip, l10n_util::GetStringUTF8(
225 (visible_mode_ == MODE_RELOAD) ? 266 (visible_mode_ == MODE_RELOAD) ?
226 IDS_TOOLTIP_RELOAD : IDS_TOOLTIP_STOP).c_str()); 267 reload_tooltip : IDS_TOOLTIP_STOP).c_str());
227 return TRUE; 268 return TRUE;
228 } 269 }
229 270
271 gboolean ReloadButtonGtk::OnButtonPress(GtkWidget* widget,
272 GdkEventButton* event) {
273 if (!ReloadMenuEnabled() || visible_mode_ == MODE_STOP)
274 return FALSE;
275
276 if (event->button == 3)
277 ShowReloadMenu(event->button, event->time);
278
279 if (event->button != 1)
280 return FALSE;
281
282 y_position_of_last_press_ = static_cast<int>(event->y);
283 MessageLoop::current()->PostDelayedTask(
284 FROM_HERE,
285 base::Bind(&ReloadButtonGtk::ShowReloadMenu,
286 weak_factory_.GetWeakPtr(),
287 event->button,
288 event->time),
289 base::TimeDelta::FromMilliseconds(kReloadMenuTimerDelay));
290 return FALSE;
291 }
292
293 gboolean ReloadButtonGtk::OnMouseMove(GtkWidget* widget,
294 GdkEventMotion* event) {
295 // If we aren't waiting to show the back forward menu, do nothing.
296 if (!weak_factory_.HasWeakPtrs())
297 return FALSE;
298
299 // We only count moves about a certain threshold.
300 GtkSettings* settings = gtk_widget_get_settings(widget);
301 int drag_min_distance;
302 g_object_get(settings, "gtk-dnd-drag-threshold", &drag_min_distance, NULL);
303 if (event->y - y_position_of_last_press_ < drag_min_distance)
304 return FALSE;
305
306 // We will show the menu now. Cancel the delayed event.
307 weak_factory_.InvalidateWeakPtrs();
308 ShowReloadMenu(/* button */ 1, event->time);
309 return FALSE;
310 }
311
230 void ReloadButtonGtk::UpdateThemeButtons() { 312 void ReloadButtonGtk::UpdateThemeButtons() {
231 bool use_gtk = theme_service_ && theme_service_->UsingNativeTheme(); 313 bool use_gtk = theme_service_ && theme_service_->UsingNativeTheme();
232 314
233 if (use_gtk) { 315 if (use_gtk) {
234 gtk_widget_ensure_style(widget()); 316 gtk_widget_ensure_style(widget());
235 GtkStyle* style = gtk_widget_get_style(widget()); 317 GtkStyle* style = gtk_widget_get_style(widget());
236 GtkIconSet* icon_set = gtk_style_lookup_icon_set( 318 GtkIconSet* icon_set = gtk_style_lookup_icon_set(
237 style, 319 style,
238 (visible_mode_ == MODE_RELOAD) ? GTK_STOCK_REFRESH : GTK_STOCK_STOP); 320 (visible_mode_ == MODE_RELOAD) ? GTK_STOCK_REFRESH : GTK_STOCK_STOP);
239 if (icon_set) { 321 if (icon_set) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 gtk_chrome_button_set_use_gtk_rendering(GTK_CHROME_BUTTON(widget()), use_gtk); 358 gtk_chrome_button_set_use_gtk_rendering(GTK_CHROME_BUTTON(widget()), use_gtk);
277 } 359 }
278 360
279 void ReloadButtonGtk::OnDoubleClickTimer() { 361 void ReloadButtonGtk::OnDoubleClickTimer() {
280 ChangeMode(intended_mode_, false); 362 ChangeMode(intended_mode_, false);
281 } 363 }
282 364
283 void ReloadButtonGtk::OnStopToReloadTimer() { 365 void ReloadButtonGtk::OnStopToReloadTimer() {
284 ChangeMode(intended_mode_, true); 366 ChangeMode(intended_mode_, true);
285 } 367 }
368
369 void ReloadButtonGtk::ShowReloadMenu(int button, guint32 event_time) {
370 if (!ReloadMenuEnabled() || visible_mode_ == MODE_STOP)
371 return;
372
373 menu_.reset(new MenuGtk(this, menu_model_.get()));
374 reload_.set_paint_override(GTK_STATE_ACTIVE);
375 menu_->PopupForWidget(widget(), button, event_time);
376 }
377
378 void ReloadButtonGtk::DoReload(int command) {
379 // Shift-clicking or Ctrl-clicking the reload button means we should ignore
380 // any cached content.
381 GdkModifierType modifier_state;
382 gtk_get_current_event_state(&modifier_state);
383 guint modifier_state_uint = modifier_state;
384
385 // Default reload behaviour.
386 if (command == 0) {
387 if (modifier_state_uint & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) {
388 command = IDC_RELOAD_IGNORING_CACHE;
389 // Mask off Shift and Control so they don't affect the disposition below.
390 modifier_state_uint &= ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK);
391 } else {
392 command = IDC_RELOAD;
393 }
394 }
395
396 WindowOpenDisposition disposition =
397 event_utils::DispositionFromGdkState(modifier_state_uint);
398 if ((disposition == CURRENT_TAB) && location_bar_) {
399 // Forcibly reset the location bar, since otherwise it won't discard any
400 // ongoing user edits, since it doesn't realize this is a user-initiated
401 // action.
402 location_bar_->Revert();
403 }
404
405 // Start a timer - while this timer is running, the reload button cannot be
406 // changed to a stop button. We do not set |intended_mode_| to MODE_STOP
407 // here as the browser will do that when it actually starts loading (which
408 // may happen synchronously, thus the need to do this before telling the
409 // browser to execute the reload command).
410 double_click_timer_.Start(FROM_HERE, double_click_timer_delay_, this,
411 &ReloadButtonGtk::OnDoubleClickTimer);
412
413 if (browser_)
414 chrome::ExecuteCommandWithDisposition(browser_, command, disposition);
415 ++testing_reload_count_;
416 }
417
418 bool ReloadButtonGtk::ReloadMenuEnabled() {
419 if (!browser_)
420 return false;
421 return chrome::IsDebuggerAttachedToCurrentTab(browser_);
422 }
423
424 void ReloadButtonGtk::ClearCache() {
425 if (browser_) {
Evan Stade 2012/07/11 02:13:30 no curlies
426 chrome::ClearCache(browser_);
427 }
428 }
429
OLDNEW
« no previous file with comments | « chrome/browser/ui/gtk/reload_button_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698