summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordeanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-11 10:09:05 +0000
committerdeanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-11 10:09:05 +0000
commitd992e7610c3f05f0042250b1180165075ebf2f44 (patch)
treeb72d88e83dad4e07a5e909aa3a70f35dd3d0f1a4
parent386c889899593445683c2013ba3894f310995a91 (diff)
downloadchromium_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.cc22
-rw-r--r--chrome/browser/gtk/bookmark_bubble_gtk.h23
-rw-r--r--chrome/browser/gtk/info_bubble_gtk.cc14
-rw-r--r--chrome/browser/gtk/info_bubble_gtk.h12
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_;