diff options
author | tc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-22 00:12:15 +0000 |
---|---|---|
committer | tc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-22 00:12:15 +0000 |
commit | 124825ede0f1ff53db9ca2255142c4fcec1ad5ca (patch) | |
tree | a6182880b9caba34bf738bee043c109ba16838a7 | |
parent | 478ff2ed6a244658c0a30d6cbfff1a9046b9ba9d (diff) | |
download | chromium_src-124825ede0f1ff53db9ca2255142c4fcec1ad5ca.zip chromium_src-124825ede0f1ff53db9ca2255142c4fcec1ad5ca.tar.gz chromium_src-124825ede0f1ff53db9ca2255142c4fcec1ad5ca.tar.bz2 |
Provide an override for Webview drop effect.
Used for gears file drag & drop in chrome, provide a setter api to override
the default webview drop effect. If gears overrides the drop_effect, then
either a "copy" or "none" cursor is shown to the user. Otherwise, the drop
effect shown is the default for the webview (controlled by WebKit).
Also remove a TODO: during drag and drop, remember the drop accept state of
the webview (in drag enter, drag over). Use that to prevent drops on webviews
that can't accept the drop data.
BUG=7995
Original patch from Noel Gordon via
http://codereview.chromium.org/67297
Review URL: http://codereview.chromium.org/88073
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14162 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/tab_contents/web_drop_target.cc | 6 | ||||
-rw-r--r-- | webkit/glue/webview.h | 12 | ||||
-rw-r--r-- | webkit/glue/webview_impl.cc | 41 | ||||
-rw-r--r-- | webkit/glue/webview_impl.h | 13 |
4 files changed, 62 insertions, 10 deletions
diff --git a/chrome/browser/tab_contents/web_drop_target.cc b/chrome/browser/tab_contents/web_drop_target.cc index eb740ee..f934f62 100644 --- a/chrome/browser/tab_contents/web_drop_target.cc +++ b/chrome/browser/tab_contents/web_drop_target.cc @@ -136,12 +136,6 @@ 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/webkit/glue/webview.h b/webkit/glue/webview.h index 8f39bd31..600338f 100644 --- a/webkit/glue/webview.h +++ b/webkit/glue/webview.h @@ -191,8 +191,8 @@ class WebView : public WebWidget { // Notfies the webview that the system drag and drop operation has ended. virtual void DragSourceSystemDragEnded() = 0; - // Callback methods when a drag and drop operation is trying to drop - // something on the renderer. + // Callback methods when a drag and drop operation is trying to drop data + // on this webview. virtual bool DragTargetDragEnter( const WebKit::WebDragData& drag_data, int identity, const WebKit::WebPoint& client_point, @@ -204,8 +204,16 @@ class WebView : public WebWidget { virtual void DragTargetDrop( const WebKit::WebPoint& client_point, const WebKit::WebPoint& screen_point) = 0; + + // Helper method for drag and drop target operations: return the drag data + // identity. virtual int32 GetDragIdentity() = 0; + // Helper method for drag and drop target operations: override the default + // drop effect with either a "copy" (accept true) or "none" (accept false) + // effect. Return true on success. + virtual bool SetDropEffect(bool accept) = 0; + // Notifies the webview that autofill suggestions are available for a node. virtual void AutofillSuggestionsForNode( int64 node_id, diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc index 03db938..e974d44 100644 --- a/webkit/glue/webview_impl.cc +++ b/webkit/glue/webview_impl.cc @@ -363,6 +363,8 @@ WebViewImpl::WebViewImpl() ime_accept_events_(true), drag_target_dispatch_(false), drag_identity_(0), + drop_effect_(DROP_EFFECT_DEFAULT), + drop_accept_(false), 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 @@ -1632,11 +1634,15 @@ bool WebViewImpl::DragTargetDragEnter( webkit_glue::WebPointToIntPoint(client_point), webkit_glue::WebPointToIntPoint(screen_point), kDropTargetOperation); + + drop_effect_ = DROP_EFFECT_DEFAULT; drag_target_dispatch_ = true; DragOperation effect = page_->dragController()->dragEntered(&drag_data); drag_target_dispatch_ = false; - return effect != DragOperationNone; + if (drop_effect_ != DROP_EFFECT_DEFAULT) + return drop_accept_ = (drop_effect_ != DROP_EFFECT_NONE); + return drop_accept_ = (effect != DragOperationNone); } bool WebViewImpl::DragTargetDragOver( @@ -1649,11 +1655,15 @@ bool WebViewImpl::DragTargetDragOver( webkit_glue::WebPointToIntPoint(client_point), webkit_glue::WebPointToIntPoint(screen_point), kDropTargetOperation); + + drop_effect_ = DROP_EFFECT_DEFAULT; drag_target_dispatch_ = true; DragOperation effect = page_->dragController()->dragUpdated(&drag_data); drag_target_dispatch_ = false; - return effect != DragOperationNone; + if (drop_effect_ != DROP_EFFECT_DEFAULT) + return drop_accept_ = (drop_effect_ != DROP_EFFECT_NONE); + return drop_accept_ = (effect != DragOperationNone); } void WebViewImpl::DragTargetDragLeave() { @@ -1664,11 +1674,14 @@ void WebViewImpl::DragTargetDragLeave() { IntPoint(), IntPoint(), kDropTargetOperation); + drag_target_dispatch_ = true; page_->dragController()->dragExited(&drag_data); drag_target_dispatch_ = false; current_drag_data_ = NULL; + drop_effect_ = DROP_EFFECT_DEFAULT; + drop_accept_ = false; drag_identity_ = 0; } @@ -1677,16 +1690,31 @@ void WebViewImpl::DragTargetDrop( const WebPoint& screen_point) { DCHECK(current_drag_data_.get()); + // If this webview transitions from the "drop accepting" state to the "not + // accepting" state, then our IPC message reply indicating that may be in- + // flight, or else delayed by javascript processing in this webview. If a + // drop happens before our IPC reply has reached the browser process, then + // the browser forwards the drop to this webview. So only allow a drop to + // proceed if our webview drop_accept_ state is true. + + if (!drop_accept_) { // IPC RACE CONDITION: do not allow this drop. + DragTargetDragLeave(); + return; + } + DragData drag_data( current_drag_data_.get(), webkit_glue::WebPointToIntPoint(client_point), webkit_glue::WebPointToIntPoint(screen_point), kDropTargetOperation); + drag_target_dispatch_ = true; page_->dragController()->performDrag(&drag_data); drag_target_dispatch_ = false; current_drag_data_ = NULL; + drop_effect_ = DROP_EFFECT_DEFAULT; + drop_accept_ = false; drag_identity_ = 0; } @@ -1696,6 +1724,15 @@ int32 WebViewImpl::GetDragIdentity() { return 0; } +bool WebViewImpl::SetDropEffect(bool accept) { + if (drag_target_dispatch_) { + drop_effect_ = accept ? DROP_EFFECT_COPY : DROP_EFFECT_NONE; + return true; + } else { + return false; + } +} + SearchableFormData* WebViewImpl::CreateSearchableFormDataForFocusedNode() { if (!page_.get()) return NULL; diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h index 5b3565b..9080bf4 100644 --- a/webkit/glue/webview_impl.h +++ b/webkit/glue/webview_impl.h @@ -114,6 +114,7 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { const WebKit::WebPoint& client_point, const WebKit::WebPoint& screen_point); virtual int32 GetDragIdentity(); + virtual bool SetDropEffect(bool accept); virtual void AutofillSuggestionsForNode( int64 node_id, const std::vector<std::wstring>& suggestions, @@ -323,6 +324,18 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { // copied from the WebDropData object sent from the browser process. int32 drag_identity_; + // Valid when drag_target_dispatch_ is true. Used to override the default + // browser drop effect with the effects "copy" or "none". + enum DragTargetDropEffect { + DROP_EFFECT_DEFAULT = 0, + DROP_EFFECT_COPY, + DROP_EFFECT_NONE + } drop_effect_; + + // When true, the drag data can be dropped onto the current drop target in + // this WebView (the drop target can accept the drop). + bool drop_accept_; + // The autocomplete popup. Kept around and reused every-time new suggestions // should be shown. RefPtr<WebCore::PopupContainer> autocomplete_popup_; |