summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-26 01:27:55 +0000
committertc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-26 01:27:55 +0000
commit58377e2edb08dabeeba8a01bfb4484eb61527b4a (patch)
tree25fe434821c4537d799a316c91a995394ec00efb
parent24c289f856db14a85e5840ad0132512ef59c5c5f (diff)
downloadchromium_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.cc6
-rw-r--r--base/base_drop_target.h11
-rw-r--r--chrome/browser/tab_contents/web_drop_target.cc8
-rwxr-xr-xchrome/common/render_messages.h2
-rw-r--r--webkit/glue/webdropdata.h10
-rw-r--r--webkit/glue/webview.h1
-rw-r--r--webkit/glue/webview_impl.cc26
-rw-r--r--webkit/glue/webview_impl.h9
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_;