diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-28 21:42:59 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-28 21:42:59 +0000 |
commit | 4768c65bc656d4352632a6fc718c8eb6d5046c84 (patch) | |
tree | c75cffe227847e1e1ab0952d337c3c853692924e /views/widget | |
parent | 6638b8716b5630233efa54f8e8ea4b4758f01ca4 (diff) | |
download | chromium_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.h | 17 | ||||
-rw-r--r-- | views/widget/root_view_gtk.cc | 16 | ||||
-rw-r--r-- | views/widget/root_view_win.cc | 9 | ||||
-rw-r--r-- | views/widget/widget_gtk.cc | 90 | ||||
-rw-r--r-- | views/widget/widget_gtk.h | 30 |
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); }; |