diff options
author | tc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-26 01:27:55 +0000 |
---|---|---|
committer | tc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-26 01:27:55 +0000 |
commit | 58377e2edb08dabeeba8a01bfb4484eb61527b4a (patch) | |
tree | 25fe434821c4537d799a316c91a995394ec00efb | |
parent | 24c289f856db14a85e5840ad0132512ef59c5c5f (diff) | |
download | chromium_src-58377e2edb08dabeeba8a01bfb4484eb61527b4a.zip chromium_src-58377e2edb08dabeeba8a01bfb4484eb61527b4a.tar.gz chromium_src-58377e2edb08dabeeba8a01bfb4484eb61527b4a.tar.bz2 |
Add an identity (id) to system drag & drop.
Used for gears file drag & drop in chrome, assign a drag id (identity) to
each drag and drop session.
Send the identity to the renderer WebViewImpl in drag enter notifications,
provide a getter method.
BUG=7995
Original patch by noel.gordon@gmail.com in:
http://codereview.chromium.org/28108/show
Review URL: http://codereview.chromium.org/28158
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10430 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/base_drop_target.cc | 6 | ||||
-rw-r--r-- | base/base_drop_target.h | 11 | ||||
-rw-r--r-- | chrome/browser/tab_contents/web_drop_target.cc | 8 | ||||
-rwxr-xr-x | chrome/common/render_messages.h | 2 | ||||
-rw-r--r-- | webkit/glue/webdropdata.h | 10 | ||||
-rw-r--r-- | webkit/glue/webview.h | 1 | ||||
-rw-r--r-- | webkit/glue/webview_impl.cc | 26 | ||||
-rw-r--r-- | webkit/glue/webview_impl.h | 9 |
8 files changed, 71 insertions, 2 deletions
diff --git a/base/base_drop_target.cc b/base/base_drop_target.cc index 9809255..1dda396 100644 --- a/base/base_drop_target.cc +++ b/base/base_drop_target.cc @@ -11,6 +11,7 @@ /////////////////////////////////////////////////////////////////////////////// IDropTargetHelper* BaseDropTarget::cached_drop_target_helper_ = NULL; +int32 BaseDropTarget::drag_identity_ = 0; BaseDropTarget::BaseDropTarget(HWND hwnd) : hwnd_(hwnd), @@ -53,6 +54,11 @@ HRESULT BaseDropTarget::DragEnter(IDataObject* data_object, *effect = DROPEFFECT_NONE; return S_OK; } + + // Update the drag identity, skipping 0. + if (++drag_identity_ == 0) + ++drag_identity_; + current_data_object_ = data_object; POINT screen_pt = { cursor_position.x, cursor_position.y }; *effect = OnDragEnter(current_data_object_, key_state, screen_pt, *effect); diff --git a/base/base_drop_target.h b/base/base_drop_target.h index 9f20752..cf63be28 100644 --- a/base/base_drop_target.h +++ b/base/base_drop_target.h @@ -85,6 +85,9 @@ class BaseDropTarget : public IDropTarget { POINT cursor_position, DWORD effect); + // Return the drag identity. + static int32 GetDragIdentity() { return drag_identity_; } + private: // Returns the cached drop helper, creating one if necessary. The returned // object is not addrefed. May return NULL if the object couldn't be created. @@ -103,6 +106,14 @@ class BaseDropTarget : public IDropTarget { // first time it is actually used. static IDropTargetHelper* cached_drop_target_helper_; + // The drag identity (id). An up-counter that increases when the cursor first + // moves over the HWND in a DnD session (OnDragEnter). 0 is reserved to mean + // the "no/unknown" identity, and is used for initialization. The identity is + // sent to the renderer in drag enter notifications. Note: the identity value + // is passed over the renderer NPAPI interface to gears, so use int32 instead + // of int here. + static int32 drag_identity_; + // The HWND of the source. This HWND is used to determine coordinates for // mouse events that are sent to the renderer notifying various drag states. HWND hwnd_; diff --git a/chrome/browser/tab_contents/web_drop_target.cc b/chrome/browser/tab_contents/web_drop_target.cc index 90ac002..eb740ee 100644 --- a/chrome/browser/tab_contents/web_drop_target.cc +++ b/chrome/browser/tab_contents/web_drop_target.cc @@ -100,7 +100,7 @@ DWORD WebDropTarget::OnDragEnter(IDataObject* data_object, // TODO(tc): PopulateWebDropData can be slow depending on what is in the // IDataObject. Maybe we can do this in a background thread. - WebDropData drop_data; + WebDropData drop_data(GetDragIdentity()); WebDropData::PopulateWebDropData(data_object, &drop_data); if (drop_data.url.is_empty()) @@ -136,6 +136,12 @@ DWORD WebDropTarget::OnDragOver(IDataObject* data_object, gfx::Point(client_pt.x, client_pt.y), gfx::Point(cursor_position.x, cursor_position.y)); + // Again we don't wait on the renderer to respond, but this can lead to + // a race condition. If the renderer does not want the drop data, then + // we won't know until the response from the renderer arrives. So if a + // drop happens before the response arrives, we drop on a renderer that + // doesn't want the data. TODO(noel): fix this. + if (!is_drop_target_) return DROPEFFECT_NONE; diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index e2a0aa0..7fa88de 100755 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -1539,6 +1539,7 @@ template <> struct ParamTraits<WebDropData> { typedef WebDropData param_type; static void Write(Message* m, const param_type& p) { + WriteParam(m, p.identity); WriteParam(m, p.url); WriteParam(m, p.url_title); WriteParam(m, p.file_extension); @@ -1551,6 +1552,7 @@ struct ParamTraits<WebDropData> { } static bool Read(const Message* m, void** iter, param_type* p) { return + ReadParam(m, iter, &p->identity) && ReadParam(m, iter, &p->url) && ReadParam(m, iter, &p->url_title) && ReadParam(m, iter, &p->file_extension) && diff --git a/webkit/glue/webdropdata.h b/webkit/glue/webdropdata.h index 9afcd04..7c9fe19 100644 --- a/webkit/glue/webdropdata.h +++ b/webkit/glue/webdropdata.h @@ -16,7 +16,15 @@ struct IDataObject; struct WebDropData { - // User is dropping a link on the webview. + // Construct with a given drag identity. Note: identity is an int32 because + // it is passed over the renderer NPAPI interface to gears. + explicit WebDropData(int32 drag_identity) : identity(drag_identity) {} + int32 identity; + + // For default constructions, use drag |identity| 0. + WebDropData() : identity(0) {} + + // User is dragging a link into the webview. GURL url; std::wstring url_title; // The title associated with |url|. diff --git a/webkit/glue/webview.h b/webkit/glue/webview.h index fbd4f33f..d8ef94d 100644 --- a/webkit/glue/webview.h +++ b/webkit/glue/webview.h @@ -185,6 +185,7 @@ class WebView : public WebWidget { virtual void DragTargetDragLeave() = 0; virtual void DragTargetDrop( int client_x, int client_y, int screen_x, int screen_y) = 0; + virtual int32 GetDragIdentity() = 0; // Notifies the webview that autofill suggestions are available for a node. virtual void AutofillSuggestionsForNode( diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc index 6b0444d..4db2ac0 100644 --- a/webkit/glue/webview_impl.cc +++ b/webkit/glue/webview_impl.cc @@ -334,6 +334,8 @@ WebViewImpl::WebViewImpl() suppress_next_keypress_event_(false), window_open_disposition_(IGNORE_ACTION), ime_accept_events_(true), + drag_target_dispatch_(false), + drag_identity_(0), autocomplete_popup_showing_(false) { // WebKit/win/WebView.cpp does the same thing, except they call the // KJS specific wrapper around this method. We need to have threading @@ -1472,37 +1474,61 @@ bool WebViewImpl::DragTargetDragEnter(const WebDropData& drop_data, DCHECK(!current_drop_data_.get()); current_drop_data_ = webkit_glue::WebDropDataToChromiumDataObject(drop_data); + drag_identity_ = drop_data.identity; DragData drag_data(current_drop_data_.get(), IntPoint(client_x, client_y), IntPoint(screen_x, screen_y), kDropTargetOperation); + drag_target_dispatch_ = true; DragOperation effect = page_->dragController()->dragEntered(&drag_data); + drag_target_dispatch_ = false; + return effect != DragOperationNone; } bool WebViewImpl::DragTargetDragOver( int client_x, int client_y, int screen_x, int screen_y) { DCHECK(current_drop_data_.get()); + DragData drag_data(current_drop_data_.get(), IntPoint(client_x, client_y), IntPoint(screen_x, screen_y), kDropTargetOperation); + drag_target_dispatch_ = true; DragOperation effect = page_->dragController()->dragUpdated(&drag_data); + drag_target_dispatch_ = false; + return effect != DragOperationNone; } void WebViewImpl::DragTargetDragLeave() { DCHECK(current_drop_data_.get()); + DragData drag_data(current_drop_data_.get(), IntPoint(), IntPoint(), DragOperationNone); + drag_target_dispatch_ = true; page_->dragController()->dragExited(&drag_data); + drag_target_dispatch_ = false; + current_drop_data_ = NULL; + drag_identity_ = 0; } void WebViewImpl::DragTargetDrop( int client_x, int client_y, int screen_x, int screen_y) { DCHECK(current_drop_data_.get()); + DragData drag_data(current_drop_data_.get(), IntPoint(client_x, client_y), IntPoint(screen_x, screen_y), kDropTargetOperation); + drag_target_dispatch_ = true; page_->dragController()->performDrag(&drag_data); + drag_target_dispatch_ = false; + current_drop_data_ = NULL; + drag_identity_ = 0; +} + +int32 WebViewImpl::GetDragIdentity() { + if (drag_target_dispatch_) + return drag_identity_; + return 0; } SearchableFormData* WebViewImpl::CreateSearchableFormDataForFocusedNode() { diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h index 9023d96..2c0a118 100644 --- a/webkit/glue/webview_impl.h +++ b/webkit/glue/webview_impl.h @@ -100,6 +100,7 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { virtual void DragTargetDragLeave(); virtual void DragTargetDrop( int client_x, int client_y, int screen_x, int screen_y); + virtual int32 GetDragIdentity(); virtual void AutofillSuggestionsForNode( int64 node_id, const std::vector<std::wstring>& suggestions, @@ -294,6 +295,14 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { // Represents whether or not this object should process incoming IME events. bool ime_accept_events_; + // True while dispatching system drag and drop events to drag/drop targets + // within this WebView. + bool drag_target_dispatch_; + + // Valid when drag_target_dispatch_ is true; the identity of the drag data + // copied from the WebDropData object sent from the browser process. + int32 drag_identity_; + // The autocomplete popup. Kept around and reused every-time new suggestions // should be shown. RefPtr<WebCore::PopupContainer> autocomplete_popup_; |