diff options
author | tony@chromium.org <tony@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-21 20:19:12 +0000 |
---|---|---|
committer | tony@chromium.org <tony@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-21 20:19:12 +0000 |
commit | 840da55a87590507054a43cc550718022eef86b8 (patch) | |
tree | d94856626dd2d5f51bb61afaec47ac09b3959530 | |
parent | cdd9fea014653052e1e2fc2a354b8526235bc65f (diff) | |
download | chromium_src-840da55a87590507054a43cc550718022eef86b8.zip chromium_src-840da55a87590507054a43cc550718022eef86b8.tar.gz chromium_src-840da55a87590507054a43cc550718022eef86b8.tar.bz2 |
Hack around the floating tab when using space/enter to end a drag.
We don't get a drag-end or a drag-failed event if the user presses
space/enter, so we hack around this with a timer. I filed a bug with
GTK+ upstream about not getting the event:
https://bugzilla.gnome.org/show_bug.cgi?id=599130
BUG=21627
Review URL: http://codereview.chromium.org/300028
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29697 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/gtk/tabs/tab_gtk.cc | 25 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/tab_gtk.h | 15 |
2 files changed, 38 insertions, 2 deletions
diff --git a/chrome/browser/gtk/tabs/tab_gtk.cc b/chrome/browser/gtk/tabs/tab_gtk.cc index 251f04f..4713063 100644 --- a/chrome/browser/gtk/tabs/tab_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_gtk.cc @@ -118,7 +118,8 @@ TabGtk::TabGtk(TabDelegate* delegate) last_mouse_down_(NULL), drag_widget_(NULL), title_width_(0), - ALLOW_THIS_IN_INITIALIZER_LIST(destroy_factory_(this)) { + ALLOW_THIS_IN_INITIALIZER_LIST(destroy_factory_(this)), + ALLOW_THIS_IN_INITIALIZER_LIST(drag_end_factory_(this)) { event_box_ = gtk_event_box_new(); gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), FALSE); g_signal_connect(G_OBJECT(event_box_), "button-press-event", @@ -219,6 +220,19 @@ gboolean TabGtk::OnDragFailed(GtkWidget* widget, GdkDragContext* context, } // static +gboolean TabGtk::OnDragButtonReleased(GtkWidget* widget, GdkEventButton* button, + TabGtk* tab) { + // We always get this event when gtk is releasing the grab and ending the + // drag. However, if the user ended the drag with space or enter, we don't + // get a follow up event to tell us the drag has finished (either a + // drag-failed or a drag-end). So we post a task to manually end the drag. + // If GTK+ does send the drag-failed or drag-end event, we cancel the task. + MessageLoop::current()->PostTask(FROM_HERE, + tab->drag_end_factory_.NewRunnableMethod(&TabGtk::EndDrag, false)); + return TRUE; +} + +// static void TabGtk::OnDragBegin(GtkWidget* widget, GdkDragContext* context, TabGtk* tab) { GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 1, 1); @@ -319,9 +333,12 @@ void TabGtk::UpdateTooltipState() { } void TabGtk::CreateDragWidget() { + DCHECK(!drag_widget_); drag_widget_ = gtk_invisible_new(); g_signal_connect(drag_widget_, "drag-failed", G_CALLBACK(OnDragFailed), this); + g_signal_connect(drag_widget_, "button-release-event", + G_CALLBACK(OnDragButtonReleased), this); g_signal_connect_after(drag_widget_, "drag-begin", G_CALLBACK(OnDragBegin), this); } @@ -338,7 +355,7 @@ void TabGtk::StartDragging(gfx::Point drag_offset) { GtkTargetList* list = GtkDndUtil::GetTargetListFromCodeMask( GtkDndUtil::CHROME_TAB); - gtk_drag_begin(drag_widget_, list, GDK_ACTION_COPY, + gtk_drag_begin(drag_widget_, list, GDK_ACTION_MOVE, 1, // Drags are always initiated by the left button. last_mouse_down_); @@ -346,6 +363,10 @@ void TabGtk::StartDragging(gfx::Point drag_offset) { } void TabGtk::EndDrag(bool canceled) { + // Make sure we only run EndDrag once by canceling any tasks that want + // to call EndDrag. + drag_end_factory_.RevokeAll(); + // We must let gtk clean up after we handle the drag operation, otherwise // there will be outstanding references to the drag widget when we try to // destroy it. diff --git a/chrome/browser/gtk/tabs/tab_gtk.h b/chrome/browser/gtk/tabs/tab_gtk.h index 5c3c662..c5a91d2 100644 --- a/chrome/browser/gtk/tabs/tab_gtk.h +++ b/chrome/browser/gtk/tabs/tab_gtk.h @@ -122,6 +122,14 @@ class TabGtk : public TabRendererGtk, static gboolean OnDragFailed(GtkWidget* widget, GdkDragContext* context, GtkDragResult result, TabGtk* tab); + // When a drag is ending, a fake button release event is passed to the drag + // widget to fake letting go of the mouse button. We need a callback for + // this event because it is the only way to catch drag end events when the + // user presses space or return. + static gboolean OnDragButtonReleased(GtkWidget* widget, + GdkEventButton* event, + TabGtk* tab); + // Shows the context menu. void ShowContextMenu(); @@ -179,6 +187,13 @@ class TabGtk : public TabRendererGtk, // Used to destroy the drag widget after a return to the message loop. ScopedRunnableMethodFactory<TabGtk> destroy_factory_; + // Due to a bug in GTK+, we need to force the end of a drag when we get a + // mouse release event on the the dragged widget, otherwise, we don't know + // when the drag has ended when the user presses space or enter. We queue + // a task to end the drag and only run it if GTK+ didn't send us the + // drag-failed event. + ScopedRunnableMethodFactory<TabGtk> drag_end_factory_; + DISALLOW_COPY_AND_ASSIGN(TabGtk); }; |