diff options
author | deanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-11 10:09:05 +0000 |
---|---|---|
committer | deanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-11 10:09:05 +0000 |
commit | d992e7610c3f05f0042250b1180165075ebf2f44 (patch) | |
tree | b72d88e83dad4e07a5e909aa3a70f35dd3d0f1a4 | |
parent | 386c889899593445683c2013ba3894f310995a91 (diff) | |
download | chromium_src-d992e7610c3f05f0042250b1180165075ebf2f44.zip chromium_src-d992e7610c3f05f0042250b1180165075ebf2f44.tar.gz chromium_src-d992e7610c3f05f0042250b1180165075ebf2f44.tar.bz2 |
Final touches on the Linux BookmarkBubble.
- Implement "close on escape" with a top level accelerator.
- Fix an invalid read when opening the editor from the folder combo.
- Clean up some signal handlers (returning bool from a void function, etc).
BUG=11738
Review URL: http://codereview.chromium.org/118493
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18154 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/gtk/bookmark_bubble_gtk.cc | 22 | ||||
-rw-r--r-- | chrome/browser/gtk/bookmark_bubble_gtk.h | 23 | ||||
-rw-r--r-- | chrome/browser/gtk/info_bubble_gtk.cc | 14 | ||||
-rw-r--r-- | chrome/browser/gtk/info_bubble_gtk.h | 12 |
4 files changed, 59 insertions, 12 deletions
diff --git a/chrome/browser/gtk/bookmark_bubble_gtk.cc b/chrome/browser/gtk/bookmark_bubble_gtk.cc index b875f4f..ae07e3d 100644 --- a/chrome/browser/gtk/bookmark_bubble_gtk.cc +++ b/chrome/browser/gtk/bookmark_bubble_gtk.cc @@ -10,6 +10,7 @@ #include "app/resource_bundle.h" #include "base/basictypes.h" #include "base/logging.h" +#include "base/message_loop.h" #include "chrome/browser/bookmarks/bookmark_editor.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/bookmarks/bookmark_utils.h" @@ -18,6 +19,7 @@ #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/profile.h" #include "chrome/common/gtk_util.h" +#include "chrome/common/notification_service.h" #include "grit/generated_resources.h" namespace { @@ -98,6 +100,15 @@ void BookmarkBubbleGtk::Show(GtkWindow* transient_toplevel, void BookmarkBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble, bool closed_by_escape) { + if (closed_by_escape) { + remove_bookmark_ = newly_bookmarked_; + apply_edits_ = false; + } + + NotificationService::current()->Notify( + NotificationType::BOOKMARK_BUBBLE_HIDDEN, + Source<Profile>(profile_->GetOriginalProfile()), + NotificationService::NoDetails()); } BookmarkBubbleGtk::BookmarkBubbleGtk(GtkWindow* transient_toplevel, @@ -112,6 +123,7 @@ BookmarkBubbleGtk::BookmarkBubbleGtk(GtkWindow* transient_toplevel, name_entry_(NULL), folder_combo_(NULL), bubble_(NULL), + factory_(this), newly_bookmarked_(newly_bookmarked), apply_edits_(true), remove_bookmark_(false) { @@ -211,12 +223,11 @@ BookmarkBubbleGtk::~BookmarkBubbleGtk() { } } -gboolean BookmarkBubbleGtk::HandleDestroy() { +void BookmarkBubbleGtk::HandleDestroy() { // We are self deleting, we have a destroy signal setup to catch when we // destroyed (via the InfoBubble being destroyed), and delete ourself. content_ = NULL; // We are being destroyed. delete this; - return FALSE; // Propagate. } void BookmarkBubbleGtk::HandleNameActivate() { @@ -227,7 +238,12 @@ void BookmarkBubbleGtk::HandleFolderChanged() { size_t cur_folder = gtk_combo_box_get_active(GTK_COMBO_BOX(folder_combo_)); if (cur_folder == folder_nodes_.size()) { UserMetrics::RecordAction(L"BookmarkBubble_EditFromCombobox", profile_); - ShowEditor(); + // GTK doesn't handle having the combo box destroyed from the changed + // signal. Since showing the editor also closes the bubble, delay this + // so that GTK can unwind. Specifically gtk_menu_shell_button_release + // will run, and we need to keep the combo box alive until then. + MessageLoop::current()->PostTask(FROM_HERE, + factory_.NewRunnableMethod(&BookmarkBubbleGtk::ShowEditor)); } } diff --git a/chrome/browser/gtk/bookmark_bubble_gtk.h b/chrome/browser/gtk/bookmark_bubble_gtk.h index dcce212..8e67f6c 100644 --- a/chrome/browser/gtk/bookmark_bubble_gtk.h +++ b/chrome/browser/gtk/bookmark_bubble_gtk.h @@ -17,6 +17,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/task.h" #include "chrome/browser/gtk/info_bubble_gtk.h" #include "googleurl/src/gurl.h" @@ -49,45 +50,45 @@ class BookmarkBubbleGtk : public InfoBubbleGtkDelegate { bool newly_bookmarked); ~BookmarkBubbleGtk(); - static gboolean HandleDestroyThunk(GtkWidget* widget, - gpointer userdata) { - return reinterpret_cast<BookmarkBubbleGtk*>(userdata)-> + static void HandleDestroyThunk(GtkWidget* widget, + gpointer userdata) { + reinterpret_cast<BookmarkBubbleGtk*>(userdata)-> HandleDestroy(); } // Notified when |content_| is destroyed so we can delete our instance. - gboolean HandleDestroy(); + void HandleDestroy(); static void HandleNameActivateThunk(GtkWidget* widget, gpointer user_data) { - return reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> + reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> HandleNameActivate(); } void HandleNameActivate(); static void HandleFolderChangedThunk(GtkWidget* widget, gpointer user_data) { - return reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> + reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> HandleFolderChanged(); } void HandleFolderChanged(); static void HandleEditButtonThunk(GtkWidget* widget, gpointer user_data) { - return reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> + reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> HandleEditButton(); } void HandleEditButton(); static void HandleCloseButtonThunk(GtkWidget* widget, gpointer user_data) { - return reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> + reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> HandleCloseButton(); } void HandleCloseButton(); static void HandleRemoveButtonThunk(GtkWidget* widget, gpointer user_data) { - return reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> + reinterpret_cast<BookmarkBubbleGtk*>(user_data)-> HandleRemoveButton(); } void HandleRemoveButton(); @@ -124,6 +125,10 @@ class BookmarkBubbleGtk : public InfoBubbleGtkDelegate { InfoBubbleGtk* bubble_; + // We need to push some things on the back of the message loop, so we have + // a factory attached to our instance to manage task lifetimes. + ScopedRunnableMethodFactory<BookmarkBubbleGtk> factory_; + // Whether the bubble is creating or editing an existing bookmark. bool newly_bookmarked_; // When closing the window, whether we should update or remove the bookmark. diff --git a/chrome/browser/gtk/info_bubble_gtk.cc b/chrome/browser/gtk/info_bubble_gtk.cc index e171e3b..5708818 100644 --- a/chrome/browser/gtk/info_bubble_gtk.cc +++ b/chrome/browser/gtk/info_bubble_gtk.cc @@ -4,6 +4,7 @@ #include "chrome/browser/gtk/info_bubble_gtk.h" +#include <gdk/gdkkeysyms.h> #include <gtk/gtk.h> #include "app/gfx/path.h" @@ -129,12 +130,14 @@ InfoBubbleGtk* InfoBubbleGtk::Show(GtkWindow* transient_toplevel, InfoBubbleGtk::InfoBubbleGtk() : delegate_(NULL), window_(NULL), + accel_group_(gtk_accel_group_new()), screen_x_(0), screen_y_(0) { } InfoBubbleGtk::~InfoBubbleGtk() { + g_object_unref(accel_group_); } void InfoBubbleGtk::Init(GtkWindow* transient_toplevel, @@ -156,6 +159,12 @@ void InfoBubbleGtk::Init(GtkWindow* transient_toplevel, // Make sure that our window can be focused. GTK_WIDGET_SET_FLAGS(window_, GTK_CAN_FOCUS); + // Attach our accelerator group to the window with an escape accelerator. + gtk_accel_group_connect(accel_group_, GDK_Escape, + static_cast<GdkModifierType>(0), static_cast<GtkAccelFlags>(0), + g_cclosure_new(G_CALLBACK(&HandleEscapeThunk), this, NULL)); + gtk_window_add_accel_group(GTK_WINDOW(window_), accel_group_); + GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), kTopMargin, kBottomMargin, @@ -207,6 +216,11 @@ void InfoBubbleGtk::Close(bool closed_by_escape) { // |this| has been deleted, see HandleDestroy. } +gboolean InfoBubbleGtk::HandleEscape() { + Close(true); // Close by escape. + return TRUE; +} + gboolean InfoBubbleGtk::HandleConfigure(GdkEventConfigure* event) { // If the window is moved someplace besides where we want it, move it back. // TODO(deanm): In the end, I will probably remove this code and just let diff --git a/chrome/browser/gtk/info_bubble_gtk.h b/chrome/browser/gtk/info_bubble_gtk.h index 0ea6c05..695537a 100644 --- a/chrome/browser/gtk/info_bubble_gtk.h +++ b/chrome/browser/gtk/info_bubble_gtk.h @@ -64,6 +64,15 @@ class InfoBubbleGtk { // the close is the result of pressing escape. void Close(bool closed_by_escape); + static gboolean HandleEscapeThunk(GtkAccelGroup* group, + GObject* acceleratable, + guint keyval, + GdkModifierType modifier, + gpointer user_data) { + return reinterpret_cast<InfoBubbleGtk*>(user_data)->HandleEscape(); + } + gboolean HandleEscape(); + static gboolean HandleConfigureThunk(GtkWidget* widget, GdkEventConfigure* event, gpointer user_data) { @@ -101,6 +110,9 @@ class InfoBubbleGtk { // it deletes us when it is destroyed. GtkWidget* window_; + // The accel group attached to |window_|, to handle closing with escape. + GtkAccelGroup* accel_group_; + // Where we want our window to be positioned on the screen. int screen_x_; int screen_y_; |