summaryrefslogtreecommitdiffstats
path: root/chrome/browser/gtk/tabs/tab_gtk.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/gtk/tabs/tab_gtk.cc')
-rw-r--r--chrome/browser/gtk/tabs/tab_gtk.cc25
1 files changed, 23 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.