diff options
author | stuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-15 22:18:09 +0000 |
---|---|---|
committer | stuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-15 22:18:09 +0000 |
commit | 3be438a82625d80192d3ecd49c3b6cfe16f58f1b (patch) | |
tree | b5c217dcaaf5488da7958182bc59202b7389785a /webkit/glue/plugins | |
parent | 80044e61a25285e4ec1ff087c51eddccae09e06c (diff) | |
download | chromium_src-3be438a82625d80192d3ecd49c3b6cfe16f58f1b.zip chromium_src-3be438a82625d80192d3ecd49c3b6cfe16f58f1b.tar.gz chromium_src-3be438a82625d80192d3ecd49c3b6cfe16f58f1b.tar.bz2 |
Filter certain drag events for Cocoa plugins to comply with the event spec
BUG=32743
TEST=Mouse drags starting outside a Cocoa plugin should not send events to the plugin (see bug for details).
Review URL: http://codereview.chromium.org/862003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41647 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue/plugins')
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.h | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_mac.mm | 72 |
2 files changed, 76 insertions, 0 deletions
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h index e4913f0..ac0168b 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.h +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -400,6 +400,10 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { // True if the plugin thinks it has keyboard focus bool have_focus_; + // If non-zero, we are in the middle of a drag that started outside the + // plugin, and this corresponds to the WebInputEvent modifier flags for any + // buttons that were down when the mouse entered and are still down now. + int external_drag_buttons_; // A function to call when we want to accept keyboard focus void (*focus_notifier_)(WebPluginDelegateImpl* notifier); diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm index 7ff1182..8b484b6 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm +++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm @@ -189,6 +189,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( renderer_(nil), quirks_(0), have_focus_(false), + external_drag_buttons_(0), focus_notifier_(NULL), containing_window_has_focus_(false), initial_window_focus_(false), @@ -1035,6 +1036,59 @@ static bool NPCocoaEventFromWebInputEvent(const WebInputEvent& event, return false; } +// Returns the mask for just the button state in a WebInputEvent's modifiers. +static int WebEventButtonModifierMask() { + return WebInputEvent::LeftButtonDown | + WebInputEvent::RightButtonDown | + WebInputEvent::MiddleButtonDown; +} + +// Returns a new drag button state from applying |event| to the previous state. +static int UpdatedDragStateFromEvent(int drag_buttons, + const WebInputEvent& event) { + switch (event.type) { + case WebInputEvent::MouseEnter: + return event.modifiers & WebEventButtonModifierMask(); + case WebInputEvent::MouseUp: { + const WebMouseEvent* mouse_event = + static_cast<const WebMouseEvent*>(&event); + int new_buttons = drag_buttons; + if (mouse_event->button == WebMouseEvent::ButtonLeft) + new_buttons &= ~WebInputEvent::LeftButtonDown; + if (mouse_event->button == WebMouseEvent::ButtonMiddle) + new_buttons &= ~WebInputEvent::MiddleButtonDown; + if (mouse_event->button == WebMouseEvent::ButtonRight) + new_buttons &= ~WebInputEvent::RightButtonDown; + return new_buttons; + } + default: + return drag_buttons; + } +} + +// Returns true if this is an event that looks like part of a drag with the +// given button state. +static bool EventIsRelatedToDrag(const WebInputEvent& event, int drag_buttons) { + const WebMouseEvent* mouse_event = static_cast<const WebMouseEvent*>(&event); + switch (event.type) { + case WebInputEvent::MouseUp: + // We only care about release of buttons that were part of the drag. + return ((mouse_event->button == WebMouseEvent::ButtonLeft && + (drag_buttons & WebInputEvent::LeftButtonDown)) || + (mouse_event->button == WebMouseEvent::ButtonMiddle && + (drag_buttons & WebInputEvent::MiddleButtonDown)) || + (mouse_event->button == WebMouseEvent::ButtonRight && + (drag_buttons & WebInputEvent::RightButtonDown))); + case WebInputEvent::MouseMove: + case WebInputEvent::MouseEnter: + case WebInputEvent::MouseLeave: + return (event.modifiers & WebEventButtonModifierMask()) != 0; + default: + return false; + } + return false; +} + bool WebPluginDelegateImpl::PlatformHandleInputEvent( const WebInputEvent& event, WebCursorInfo* cursor_info) { DCHECK(cursor_info != NULL); @@ -1114,6 +1168,24 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent( LOG(WARNING) << "NPCocoaEventFromWebInputEvent failed"; return false; } + + // Keep track of whether or not we are in a drag that started outside the + // plugin; if we are, filter out drag-related events (and convert the end + // of the external drag into an enter event) per the NPAPI Cocoa event + // model spec. + // If we eventually add a page-capture mode at the WebKit layer, mirroring + // the plugin-capture mode that handles drags starting inside the plugin + // and going outside, this can all be removed. + bool drag_related = EventIsRelatedToDrag(event, external_drag_buttons_); + external_drag_buttons_ = UpdatedDragStateFromEvent(external_drag_buttons_, + event); + if (drag_related) { + if (event.type == WebInputEvent::MouseUp && !external_drag_buttons_) + np_cocoa_event.type = NPCocoaEventMouseEntered; + else + return false; + } + NPAPI::ScopedCurrentPluginEvent event_scope(instance(), &np_cocoa_event); ret = instance()->NPP_HandleEvent(&np_cocoa_event) != 0; break; |