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

Unified 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: rebase to remove conflicts 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/ui/gtk/reload_button_gtk.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/gtk/reload_button_gtk.cc
diff --git a/chrome/browser/ui/gtk/reload_button_gtk.cc b/chrome/browser/ui/gtk/reload_button_gtk.cc
index 5a2a57bccb83816ea0a15a97228bbf77702eee69..94394cda1a11d91def09c44a4c0cad64b4541dd5 100644
--- a/chrome/browser/ui/gtk/reload_button_gtk.cc
+++ b/chrome/browser/ui/gtk/reload_button_gtk.cc
@@ -11,6 +11,7 @@
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/gtk/accelerators_gtk.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"
@@ -20,6 +21,7 @@
#include "content/public/browser/notification_source.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
+#include "ui/base/accelerators/accelerator_gtk.h"
#include "ui/base/l10n/l10n_util.h"
// The width of this button in GTK+ theme mode. The Stop and Refresh stock icons
@@ -27,6 +29,16 @@
// doesn't change sizes when switching between the two.
static int GtkButtonWidth = 0;
+// The time in milliseconds between when the user clicks and the menu appears.
+static const int kReloadMenuTimerDelay = 500;
+
+// Content of the Reload drop-down menu.
+static const int kReloadMenuItems[] = {
+ IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM,
+ IDS_RELOAD_MENU_HARD_RELOAD_ITEM,
+ IDS_RELOAD_MENU_EMPTY_AND_HARD_RELOAD_ITEM,
+};
+
////////////////////////////////////////////////////////////////////////////////
// ReloadButton, public:
@@ -42,8 +54,15 @@ ReloadButtonGtk::ReloadButtonGtk(LocationBarViewGtk* location_bar,
stop_(theme_service_, IDR_STOP, IDR_STOP_P, IDR_STOP_H, IDR_STOP_D),
widget_(gtk_chrome_button_new()),
stop_to_reload_timer_delay_(base::TimeDelta::FromMilliseconds(1350)),
+ weak_factory_(this),
+ menu_visible_(false),
testing_mouse_hovered_(false),
testing_reload_count_(0) {
+ menu_model_.reset(new ui::SimpleMenuModel(this));
+ for (size_t i = 0; i < arraysize(kReloadMenuItems); i++) {
+ menu_model_->AddItemWithStringId(kReloadMenuItems[i], kReloadMenuItems[i]);
+ }
+
gtk_widget_set_size_request(widget(), reload_.Width(), reload_.Height());
gtk_widget_set_app_paintable(widget(), TRUE);
@@ -58,6 +77,17 @@ ReloadButtonGtk::ReloadButtonGtk(LocationBarViewGtk* location_bar,
g_signal_connect(widget(), "query-tooltip", G_CALLBACK(OnQueryTooltipThunk),
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));
+
hover_controller_.Init(widget());
gtk_util::SetButtonTriggersNavigation(widget());
@@ -93,8 +123,11 @@ void ReloadButtonGtk::ChangeMode(Mode mode, bool force) {
stop_to_reload_timer_.Stop();
visible_mode_ = mode;
- stop_.set_paint_override(-1);
- gtk_chrome_button_unset_paint_state(GTK_CHROME_BUTTON(widget_.get()));
+ // Do not change the state of the button if menu is currently visible.
+ if (!menu_visible_) {
+ stop_.set_paint_override(-1);
+ gtk_chrome_button_unset_paint_state(GTK_CHROME_BUTTON(widget_.get()));
+ }
UpdateThemeButtons();
gtk_widget_queue_draw(widget());
@@ -143,9 +176,80 @@ void ReloadButtonGtk::Observe(int type,
}
////////////////////////////////////////////////////////////////////////////////
+// ReloadButtonGtk, MenuGtk::Delegate implementation:
+
+void ReloadButtonGtk::StoppedShowing() {
+ menu_visible_ = false;
+ ChangeMode(intended_mode_, true);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ReloadButtonGtk, SimpleMenuModel::Delegate implementation:
+
+bool ReloadButtonGtk::IsCommandIdChecked(int command_id) const {
+ return false;
+}
+
+bool ReloadButtonGtk::IsCommandIdEnabled(int command_id) const {
+ return true;
+}
+
+bool ReloadButtonGtk::IsCommandIdVisible(int command_id) const {
+ return true;
+}
+
+bool ReloadButtonGtk::GetAcceleratorForCommandId(int command_id,
+ ui::Accelerator* accelerator) {
+ int command = 0;
+ switch (command_id) {
+ case IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM:
+ command = IDC_RELOAD;
+ break;
+ case IDS_RELOAD_MENU_HARD_RELOAD_ITEM:
+ command = IDC_RELOAD_IGNORING_CACHE;
+ break;
+ case IDS_RELOAD_MENU_EMPTY_AND_HARD_RELOAD_ITEM:
+ // No accelerator.
+ break;
+ default:
+ LOG(ERROR) << "Unknown reload menu command";
+ }
+
+ bool accelerator_set = false;
+ if (command) {
+ const ui::AcceleratorGtk* accelerator_gtk =
+ AcceleratorsGtk::GetInstance()->
+ GetPrimaryAcceleratorForCommand(command);
+ if (accelerator_gtk) {
+ *accelerator = *accelerator_gtk;
+ accelerator_set = true;
+ }
+ }
+ return accelerator_set;
+}
+
+void ReloadButtonGtk::ExecuteCommand(int command_id) {
+ switch (command_id) {
+ case IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM:
+ DoReload(IDC_RELOAD);
+ break;
+ case IDS_RELOAD_MENU_HARD_RELOAD_ITEM:
+ DoReload(IDC_RELOAD_IGNORING_CACHE);
+ break;
+ case IDS_RELOAD_MENU_EMPTY_AND_HARD_RELOAD_ITEM:
+ ClearCache();
+ DoReload(IDC_RELOAD_IGNORING_CACHE);
+ break;
+ default:
+ LOG(ERROR) << "Unknown reload menu command";
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
// ReloadButtonGtk, private:
void ReloadButtonGtk::OnClicked(GtkWidget* /* sender */) {
+ weak_factory_.InvalidateWeakPtrs();
if (visible_mode_ == MODE_STOP) {
// Do nothing if Stop was disabled due to an attempt to change back to
// RELOAD mode while hovered.
@@ -159,40 +263,7 @@ void ReloadButtonGtk::OnClicked(GtkWidget* /* sender */) {
// even if the mouse is still hovering.
ChangeMode(MODE_RELOAD, true);
} else if (!double_click_timer_.IsRunning()) {
- // Shift-clicking or Ctrl-clicking the reload button means we should ignore
- // any cached content.
- int command;
- GdkModifierType modifier_state;
- gtk_get_current_event_state(&modifier_state);
- guint modifier_state_uint = modifier_state;
- if (modifier_state_uint & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) {
- command = IDC_RELOAD_IGNORING_CACHE;
- // Mask off Shift and Control so they don't affect the disposition below.
- modifier_state_uint &= ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK);
- } else {
- command = IDC_RELOAD;
- }
-
- WindowOpenDisposition disposition =
- event_utils::DispositionFromGdkState(modifier_state_uint);
- if ((disposition == CURRENT_TAB) && location_bar_) {
- // Forcibly reset the location bar, since otherwise it won't discard any
- // ongoing user edits, since it doesn't realize this is a user-initiated
- // action.
- location_bar_->Revert();
- }
-
- // Start a timer - while this timer is running, the reload button cannot be
- // changed to a stop button. We do not set |intended_mode_| to MODE_STOP
- // here as the browser will do that when it actually starts loading (which
- // may happen synchronously, thus the need to do this before telling the
- // browser to execute the reload command).
- double_click_timer_.Start(FROM_HERE, double_click_timer_delay_, this,
- &ReloadButtonGtk::OnDoubleClickTimer);
-
- if (browser_)
- chrome::ExecuteCommandWithDisposition(browser_, command, disposition);
- ++testing_reload_count_;
+ DoReload(0);
}
}
@@ -220,12 +291,55 @@ gboolean ReloadButtonGtk::OnQueryTooltip(GtkWidget* /* sender */,
if (!location_bar_)
return FALSE;
+ int reload_tooltip = ReloadMenuEnabled() ?
+ IDS_TOOLTIP_RELOAD_WITH_MENU : IDS_TOOLTIP_RELOAD;
gtk_tooltip_set_text(tooltip, l10n_util::GetStringUTF8(
(visible_mode_ == MODE_RELOAD) ?
- IDS_TOOLTIP_RELOAD : IDS_TOOLTIP_STOP).c_str());
+ reload_tooltip : IDS_TOOLTIP_STOP).c_str());
return TRUE;
}
+gboolean ReloadButtonGtk::OnButtonPress(GtkWidget* widget,
+ GdkEventButton* event) {
+ if (!ReloadMenuEnabled() || visible_mode_ == MODE_STOP)
+ return FALSE;
+
+ if (event->button == 3)
+ ShowReloadMenu(event->button, event->time);
+
+ if (event->button != 1)
+ return FALSE;
+
+ y_position_of_last_press_ = static_cast<int>(event->y);
+ MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&ReloadButtonGtk::ShowReloadMenu,
+ weak_factory_.GetWeakPtr(),
+ event->button,
+ event->time),
+ base::TimeDelta::FromMilliseconds(kReloadMenuTimerDelay));
+ return FALSE;
+}
+
+gboolean ReloadButtonGtk::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();
+ ShowReloadMenu(/* button */ 1, event->time);
+ return FALSE;
+}
+
void ReloadButtonGtk::UpdateThemeButtons() {
bool use_gtk = theme_service_ && theme_service_->UsingNativeTheme();
@@ -282,3 +396,68 @@ void ReloadButtonGtk::OnDoubleClickTimer() {
void ReloadButtonGtk::OnStopToReloadTimer() {
ChangeMode(intended_mode_, true);
}
+
+void ReloadButtonGtk::ShowReloadMenu(int button, guint32 event_time) {
+ if (!ReloadMenuEnabled() || visible_mode_ == MODE_STOP)
+ return;
+
+ menu_visible_ = true;
+ menu_.reset(new MenuGtk(this, menu_model_.get()));
+ reload_.set_paint_override(GTK_STATE_ACTIVE);
+ gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(widget_.get()),
+ GTK_STATE_ACTIVE);
+ gtk_widget_queue_draw(widget());
+ menu_->PopupForWidget(widget(), button, event_time);
+}
+
+void ReloadButtonGtk::DoReload(int command) {
+ // Shift-clicking or Ctrl-clicking the reload button means we should ignore
+ // any cached content.
+ GdkModifierType modifier_state;
+ gtk_get_current_event_state(&modifier_state);
+ guint modifier_state_uint = modifier_state;
+
+ // Default reload behaviour.
+ if (command == 0) {
+ if (modifier_state_uint & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) {
+ command = IDC_RELOAD_IGNORING_CACHE;
+ // Mask off Shift and Control so they don't affect the disposition below.
+ modifier_state_uint &= ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK);
+ } else {
+ command = IDC_RELOAD;
+ }
+ }
+
+ WindowOpenDisposition disposition =
+ event_utils::DispositionFromGdkState(modifier_state_uint);
+ if ((disposition == CURRENT_TAB) && location_bar_) {
+ // Forcibly reset the location bar, since otherwise it won't discard any
+ // ongoing user edits, since it doesn't realize this is a user-initiated
+ // action.
+ location_bar_->Revert();
+ }
+
+ // Start a timer - while this timer is running, the reload button cannot be
+ // changed to a stop button. We do not set |intended_mode_| to MODE_STOP
+ // here as the browser will do that when it actually starts loading (which
+ // may happen synchronously, thus the need to do this before telling the
+ // browser to execute the reload command).
+ double_click_timer_.Start(FROM_HERE, double_click_timer_delay_, this,
+ &ReloadButtonGtk::OnDoubleClickTimer);
+
+ if (browser_)
+ chrome::ExecuteCommandWithDisposition(browser_, command, disposition);
+ ++testing_reload_count_;
+}
+
+bool ReloadButtonGtk::ReloadMenuEnabled() {
+ if (!browser_)
+ return false;
+ return chrome::IsDebuggerAttachedToCurrentTab(browser_);
+}
+
+void ReloadButtonGtk::ClearCache() {
+ if (browser_)
+ chrome::ClearCache(browser_);
+}
+
« 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