summaryrefslogtreecommitdiffstats
path: root/views/widget
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-28 21:42:59 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-28 21:42:59 +0000
commit4768c65bc656d4352632a6fc718c8eb6d5046c84 (patch)
treec75cffe227847e1e1ab0952d337c3c853692924e /views/widget
parent6638b8716b5630233efa54f8e8ea4b4758f01ca4 (diff)
downloadchromium_src-4768c65bc656d4352632a6fc718c8eb6d5046c84.zip
chromium_src-4768c65bc656d4352632a6fc718c8eb6d5046c84.tar.gz
chromium_src-4768c65bc656d4352632a6fc718c8eb6d5046c84.tar.bz2
Adds support for initiating drags from bookmark menus.
BUG=none TEST=make sure bookmark menus work on Windows. Review URL: http://codereview.chromium.org/176006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24801 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/widget')
-rw-r--r--views/widget/root_view.h17
-rw-r--r--views/widget/root_view_gtk.cc16
-rw-r--r--views/widget/root_view_win.cc9
-rw-r--r--views/widget/widget_gtk.cc90
-rw-r--r--views/widget/widget_gtk.h30
5 files changed, 148 insertions, 14 deletions
diff --git a/views/widget/root_view.h b/views/widget/root_view.h
index b3c43d8..25ca7a2 100644
--- a/views/widget/root_view.h
+++ b/views/widget/root_view.h
@@ -166,6 +166,14 @@ class RootView : public View,
void OnPaint(GdkEventExpose* event);
#endif
+ // Starts a drag operation for the specified view. This blocks until done.
+ // If the view has not been deleted during the drag, OnDragDone is invoked
+ // on the view.
+ // NOTE: |view| may be null.
+ void StartDragForViewFromMouseEvent(View* view,
+ const OSExchangeData& data,
+ int operation);
+
// Accessibility accessors/mutators, overridden from View.
virtual bool GetAccessibleRole(AccessibilityTypes::Role* role);
virtual bool GetAccessibleName(std::wstring* name);
@@ -242,15 +250,6 @@ class RootView : public View,
// Updates the last_mouse_* fields from e.
void SetMouseLocationAndFlags(const MouseEvent& e);
-#if defined(OS_WIN)
- // Starts a drag operation for the specified view. This blocks until done.
- // If the view has not been deleted during the drag, OnDragDone is invoked
- // on the view.
- void StartDragForViewFromMouseEvent(View* view,
- IDataObject* data,
- int operation);
-#endif
-
// If a view is dragging, this returns it. Otherwise returns NULL.
View* GetDragView();
diff --git a/views/widget/root_view_gtk.cc b/views/widget/root_view_gtk.cc
index 6984429..290203f 100644
--- a/views/widget/root_view_gtk.cc
+++ b/views/widget/root_view_gtk.cc
@@ -36,4 +36,20 @@ void RootView::OnPaint(GdkEventExpose* event) {
}
}
+void RootView::StartDragForViewFromMouseEvent(
+ View* view,
+ const OSExchangeData& data,
+ int operation) {
+ // NOTE: view may be null.
+ drag_view_ = view;
+ static_cast<WidgetGtk*>(GetWidget())->DoDrag(data, operation);
+ // If the view is removed during the drag operation, drag_view_ is set to
+ // NULL.
+ if (view && drag_view_ == view) {
+ View* drag_view = drag_view_;
+ drag_view_ = NULL;
+ drag_view->OnDragDone();
+ }
+}
+
}
diff --git a/views/widget/root_view_win.cc b/views/widget/root_view_win.cc
index fedb40d..65aa1b7 100644
--- a/views/widget/root_view_win.cc
+++ b/views/widget/root_view_win.cc
@@ -6,6 +6,8 @@
#include "app/drag_drop_types.h"
#include "app/gfx/canvas_paint.h"
+#include "app/os_exchange_data.h"
+#include "app/os_exchange_data_provider_win.h"
#include "base/base_drag_source.h"
#include "base/logging.h"
@@ -33,16 +35,17 @@ void RootView::OnPaint(HWND hwnd) {
void RootView::StartDragForViewFromMouseEvent(
View* view,
- IDataObject* data,
+ const OSExchangeData& data,
int operation) {
+ // NOTE: view may be null.
drag_view_ = view;
scoped_refptr<BaseDragSource> drag_source(new BaseDragSource);
DWORD effects;
- DoDragDrop(data, drag_source,
+ DoDragDrop(OSExchangeDataProviderWin::GetIDataObject(data), drag_source,
DragDropTypes::DragOperationToDropEffect(operation), &effects);
// If the view is removed during the drag operation, drag_view_ is set to
// NULL.
- if (drag_view_ == view) {
+ if (view && drag_view_ == view) {
View* drag_view = drag_view_;
drag_view_ = NULL;
drag_view->OnDragDone();
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc
index a2044221..91b7e5c 100644
--- a/views/widget/widget_gtk.cc
+++ b/views/widget/widget_gtk.cc
@@ -4,8 +4,12 @@
#include "views/widget/widget_gtk.h"
+#include "app/drag_drop_types.h"
#include "app/gfx/path.h"
+#include "app/os_exchange_data.h"
+#include "app/os_exchange_data_provider_gtk.h"
#include "base/compiler_specific.h"
+#include "base/message_loop.h"
#include "views/widget/default_theme_provider.h"
#include "views/widget/drop_target_gtk.h"
#include "views/widget/root_view.h"
@@ -102,7 +106,8 @@ WidgetGtk::WidgetGtk(Type type)
delete_on_destroy_(true),
transparent_(false),
ignore_drag_leave_(false),
- opacity_(255) {
+ opacity_(255),
+ drag_data_(NULL) {
static bool installed_message_loop_observer = false;
if (!installed_message_loop_observer) {
installed_message_loop_observer = true;
@@ -163,6 +168,27 @@ void WidgetGtk::PositionChild(GtkWidget* child, int x, int y, int w, int h) {
gtk_fixed_move(GTK_FIXED(window_contents_), child, x, y);
}
+void WidgetGtk::DoDrag(const OSExchangeData& data, int operation) {
+ const OSExchangeDataProviderGtk& data_provider =
+ static_cast<const OSExchangeDataProviderGtk&>(data.provider());
+ GtkTargetList* targets = data_provider.GetTargetList();
+ GdkEvent* current_event = gtk_get_current_event();
+ DCHECK(current_event);
+ gtk_drag_begin(window_contents_, targets,
+ static_cast<GdkDragAction>(
+ DragDropTypes::DragOperationToGdkDragAction(operation)),
+ 1, current_event);
+ gdk_event_free(current_event);
+ gtk_target_list_unref(targets);
+
+ drag_data_ = &data_provider;
+
+ // Block the caller until drag is done by running a nested message loop.
+ MessageLoopForUI::current()->Run(NULL);
+
+ drag_data_ = NULL;
+}
+
////////////////////////////////////////////////////////////////////////////////
// WidgetGtk, Widget implementation:
@@ -256,6 +282,12 @@ void WidgetGtk::Init(GtkWidget* parent,
G_CALLBACK(CallDragDrop), this);
g_signal_connect(G_OBJECT(window_contents_), "drag_leave",
G_CALLBACK(CallDragLeave), this);
+ g_signal_connect(G_OBJECT(window_contents_), "drag_data_get",
+ G_CALLBACK(CallDragDataGet), this);
+ g_signal_connect(G_OBJECT(window_contents_), "drag_end",
+ G_CALLBACK(CallDragEnd), this);
+ g_signal_connect(G_OBJECT(window_contents_), "drag_failed",
+ G_CALLBACK(CallDragFailed), this);
tooltip_manager_.reset(new TooltipManagerGtk(this));
@@ -546,6 +578,17 @@ void WidgetGtk::OnPaint(GtkWidget* widget, GdkEventExpose* event) {
root_view_->OnPaint(event);
}
+void WidgetGtk::OnDragDataGet(GdkDragContext* context,
+ GtkSelectionData* data,
+ guint info,
+ guint time) {
+ if (!drag_data_) {
+ NOTREACHED();
+ return;
+ }
+ drag_data_->WriteFormatToSelection(info, data);
+}
+
void WidgetGtk::OnDragDataReceived(GdkDragContext* context,
gint x,
gint y,
@@ -566,6 +609,22 @@ gboolean WidgetGtk::OnDragDrop(GdkDragContext* context,
return FALSE;
}
+void WidgetGtk::OnDragEnd(GdkDragContext* context) {
+ if (!drag_data_) {
+ // This indicates we didn't start a drag operation, and should never
+ // happen.
+ NOTREACHED();
+ return;
+ }
+ // Quit the nested message loop we spawned in DoDrag.
+ MessageLoop::current()->Quit();
+}
+
+gboolean WidgetGtk::OnDragFailed(GdkDragContext* context,
+ GtkDragResult result) {
+ return FALSE;
+}
+
void WidgetGtk::OnDragLeave(GdkDragContext* context,
guint time) {
if (ignore_drag_leave_) {
@@ -705,7 +764,9 @@ void WidgetGtk::ProcessMouseReleased(GdkEventButton* event) {
if (has_capture_ && ReleaseCaptureOnMouseReleased())
ReleaseGrab();
is_mouse_down_ = false;
- root_view_->OnMouseReleased(mouse_up, false);
+ // GTK generates a mouse release at the end of dnd. We need to ignore it.
+ if (!drag_data_)
+ root_view_->OnMouseReleased(mouse_up, false);
}
// static
@@ -761,6 +822,16 @@ gboolean WidgetGtk::CallWindowPaint(GtkWidget* widget,
}
// static
+void WidgetGtk::CallDragDataGet(GtkWidget* widget,
+ GdkDragContext* context,
+ GtkSelectionData* data,
+ guint info,
+ guint time,
+ WidgetGtk* host) {
+ host->OnDragDataGet(context, data, info, time);
+}
+
+// static
void WidgetGtk::CallDragDataReceived(GtkWidget* widget,
GdkDragContext* context,
gint x,
@@ -783,6 +854,21 @@ gboolean WidgetGtk::CallDragDrop(GtkWidget* widget,
}
// static
+void WidgetGtk::CallDragEnd(GtkWidget* widget,
+ GdkDragContext* context,
+ WidgetGtk* host) {
+ host->OnDragEnd(context);
+}
+
+// static
+gboolean WidgetGtk::CallDragFailed(GtkWidget* widget,
+ GdkDragContext* context,
+ GtkDragResult result,
+ WidgetGtk* host) {
+ return host->OnDragFailed(context, result);
+}
+
+// static
void WidgetGtk::CallDragLeave(GtkWidget* widget,
GdkDragContext* context,
guint time,
diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h
index 7de1492..a7e905e 100644
--- a/views/widget/widget_gtk.h
+++ b/views/widget/widget_gtk.h
@@ -10,6 +10,9 @@
#include "base/message_loop.h"
#include "views/widget/widget.h"
+class OSExchangeData;
+class OSExchangeDataProviderGtk;
+
namespace gfx {
class Rect;
}
@@ -72,6 +75,9 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
// |widget_|.
GtkWidget* window_contents() const { return window_contents_; }
+ // Starts a drag on this widget. This blocks until the drag is done.
+ void DoDrag(const OSExchangeData& data, int operation);
+
// Overridden from Widget:
virtual void Init(gfx::NativeView parent, const gfx::Rect& bounds);
virtual void SetContentsView(View* view);
@@ -114,6 +120,10 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
protected:
virtual void OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation);
virtual void OnPaint(GtkWidget* widget, GdkEventExpose* event);
+ virtual void OnDragDataGet(GdkDragContext* context,
+ GtkSelectionData* data,
+ guint info,
+ guint time);
virtual void OnDragDataReceived(GdkDragContext* context,
gint x,
gint y,
@@ -124,6 +134,9 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
gint x,
gint y,
guint time);
+ virtual void OnDragEnd(GdkDragContext* context);
+ virtual gboolean OnDragFailed(GdkDragContext* context,
+ GtkDragResult result);
virtual void OnDragLeave(GdkDragContext* context,
guint time);
virtual gboolean OnDragMotion(GdkDragContext* context,
@@ -201,6 +214,12 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
static gboolean CallWindowPaint(GtkWidget* widget,
GdkEventExpose* event,
WidgetGtk* widget_gtk);
+ static void CallDragDataGet(GtkWidget* widget,
+ GdkDragContext* context,
+ GtkSelectionData* data,
+ guint info,
+ guint time,
+ WidgetGtk* host);
static void CallDragDataReceived(GtkWidget* widget,
GdkDragContext* context,
gint x,
@@ -215,6 +234,13 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
gint y,
guint time,
WidgetGtk* host);
+ static void CallDragEnd(GtkWidget* widget,
+ GdkDragContext* context,
+ WidgetGtk* host);
+ static gboolean CallDragFailed(GtkWidget* widget,
+ GdkDragContext* context,
+ GtkDragResult result,
+ WidgetGtk* host);
static void CallDragLeave(GtkWidget* widget,
GdkDragContext* context,
guint time,
@@ -319,6 +345,10 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
unsigned char opacity_;
+ // This is non-null during the life of DoDrag and contains the actual data
+ // for the drag.
+ const OSExchangeDataProviderGtk* drag_data_;
+
DISALLOW_COPY_AND_ASSIGN(WidgetGtk);
};