diff options
author | stuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-29 20:49:41 +0000 |
---|---|---|
committer | stuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-29 20:49:41 +0000 |
commit | 7c64a2f4b4aa2b755a67b6625d3a508039e2fad4 (patch) | |
tree | 9619a45a2736ca7bce7a27d2e3ce3daea91cd43f | |
parent | bb20bfdc0036e870e87fd9067f1f7f310d7de3c6 (diff) | |
download | chromium_src-7c64a2f4b4aa2b755a67b6625d3a508039e2fad4.zip chromium_src-7c64a2f4b4aa2b755a67b6625d3a508039e2fad4.tar.gz chromium_src-7c64a2f4b4aa2b755a67b6625d3a508039e2fad4.tar.bz2 |
Move Mac plugin event conversion into helper classes
Creates new helper classes for Carbon and Cocoa plugin event conversion, and abstracts away the difference via a common interface and a model-driven factory.
The guts of the converters is just the old static methods, moved into the classes with a couple of minor changes:
- Switched to using WebInputEvent::isMouseEventType/isKeyboardEventType, since our methods were essentially duplicates.
- The newer key types, RawKeyDown and Char, are now explicitly unhandled, rather than logging warnings.
BUG=none
TEST=Plugin events (mouse, keyboard, scroll wheel) on the Mac should continue to work as before.
Review URL: http://codereview.chromium.org/1566002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42993 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | webkit/glue/plugins/plugin_host.cc | 6 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_instance.h | 12 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_web_event_converter_mac.h | 60 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_web_event_converter_mac.mm | 368 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_mac.mm | 375 | ||||
-rw-r--r-- | webkit/glue/webkit_glue.gypi | 2 |
6 files changed, 478 insertions, 345 deletions
diff --git a/webkit/glue/plugins/plugin_host.cc b/webkit/glue/plugins/plugin_host.cc index 6341bc0..5ceea68 100644 --- a/webkit/glue/plugins/plugin_host.cc +++ b/webkit/glue/plugins/plugin_host.cc @@ -872,11 +872,11 @@ NPError NPN_SetValue(NPP id, NPPVariable variable, void* value) { case NPPVpluginDrawingModel: { int model = reinterpret_cast<int>(value); if (model == NPDrawingModelCoreGraphics) { - plugin->set_drawing_model(model); + plugin->set_drawing_model(static_cast<NPDrawingModel>(model)); return NPERR_NO_ERROR; } else if (model == NPDrawingModelCoreAnimation && SupportsSharingAcceleratedSurfaces()) { - plugin->set_drawing_model(model); + plugin->set_drawing_model(static_cast<NPDrawingModel>(model)); return NPERR_NO_ERROR; } return NPERR_GENERIC_ERROR; @@ -889,7 +889,7 @@ NPError NPN_SetValue(NPP id, NPPVariable variable, void* value) { case NPEventModelCarbon: #endif case NPEventModelCocoa: - plugin->set_event_model(model); + plugin->set_event_model(static_cast<NPEventModel>(model)); return NPERR_NO_ERROR; break; } diff --git a/webkit/glue/plugins/plugin_instance.h b/webkit/glue/plugins/plugin_instance.h index bd3a0d7..afb4b58 100644 --- a/webkit/glue/plugins/plugin_instance.h +++ b/webkit/glue/plugins/plugin_instance.h @@ -109,10 +109,10 @@ class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> { #if defined(OS_MACOSX) // Get/Set the Mac NPAPI drawing and event models - int drawing_model() { return drawing_model_; } - void set_drawing_model(int value) { drawing_model_ = value; } - int event_model() { return event_model_; } - void set_event_model(int value) { event_model_ = value; } + NPDrawingModel drawing_model() { return drawing_model_; } + void set_drawing_model(NPDrawingModel value) { drawing_model_ = value; } + NPEventModel event_model() { return event_model_; } + void set_event_model(NPEventModel value) { event_model_ = value; } // Updates the instance's tracking of the location of the plugin location // relative to the upper left of the screen. void set_plugin_origin(const gfx::Point& origin) { plugin_origin_ = origin; } @@ -286,8 +286,8 @@ class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> { intptr_t get_notify_data_; bool use_mozilla_user_agent_; #if defined(OS_MACOSX) - int drawing_model_; - int event_model_; + NPDrawingModel drawing_model_; + NPEventModel event_model_; gfx::Point plugin_origin_; gfx::Rect containing_window_frame_; NPCocoaEvent* currently_handled_event_; // weak diff --git a/webkit/glue/plugins/plugin_web_event_converter_mac.h b/webkit/glue/plugins/plugin_web_event_converter_mac.h new file mode 100644 index 0000000..ec5b86f --- /dev/null +++ b/webkit/glue/plugins/plugin_web_event_converter_mac.h @@ -0,0 +1,60 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBKIT_GLUE_PLUGIN_PLUGIN_WEB_EVENT_CONVERTER_MAC_H_ +#define WEBKIT_GLUE_PLUGIN_PLUGIN_WEB_EVENT_CONVERTER_MAC_H_ + +#include "third_party/npapi/bindings/npapi.h" + +namespace WebKit { +class WebInputEvent; +class WebKeyboardEvent; +class WebMouseEvent; +class WebMouseWheelEvent; +} + +// Utility class to translating WebInputEvent structs to equivalent structures +// suitable for sending to Mac plugins (via NPP_HandleEvent). +class PluginWebEventConverter { + public: + PluginWebEventConverter() {} + virtual ~PluginWebEventConverter() {} + + // Initializes a converter for the given web event. Returns false if the event + // could not be converted. + virtual bool InitWithEvent(const WebKit::WebInputEvent& web_event); + + // Returns a pointer to a plugin event--suitable for passing to + // NPP_HandleEvent--corresponding to the the web event this converter was + // created with. The pointer is valid only as long as this object is. + // Returns NULL iff InitWithEvent returned false. + virtual void* plugin_event() = 0; + +protected: + // To be overridden by subclasses to store a converted plugin representation + // of the given web event, suitable for returning from plugin_event. + // Returns true if the event was successfully converted. + virtual bool ConvertKeyboardEvent( + const WebKit::WebKeyboardEvent& web_event) = 0; + virtual bool ConvertMouseEvent(const WebKit::WebMouseEvent& web_event) = 0; + virtual bool ConvertMouseWheelEvent( + const WebKit::WebMouseWheelEvent& web_event) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(PluginWebEventConverter); +}; + +// Factory for generating PluginWebEventConverter objects by event model. +class PluginWebEventConverterFactory { + public: + // Returns a new PluginWebEventConverter corresponding to the given plugin + // event model. + static PluginWebEventConverter* + CreateConverterForModel(NPEventModel event_model); + + private: + DISALLOW_COPY_AND_ASSIGN(PluginWebEventConverterFactory); +}; + +#endif // WEBKIT_GLUE_PLUGIN_PLUGIN_WEB_EVENT_CONVERTER_MAC_H_ diff --git a/webkit/glue/plugins/plugin_web_event_converter_mac.mm b/webkit/glue/plugins/plugin_web_event_converter_mac.mm new file mode 100644 index 0000000..030ed06 --- /dev/null +++ b/webkit/glue/plugins/plugin_web_event_converter_mac.mm @@ -0,0 +1,368 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <Cocoa/Cocoa.h> + +#include "base/logging.h" +#include "webkit/glue/plugins/plugin_web_event_converter_mac.h" +#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" + +using WebKit::WebInputEvent; +using WebKit::WebKeyboardEvent; +using WebKit::WebMouseEvent; +using WebKit::WebMouseWheelEvent; + +namespace { + +// Returns true if the caps lock flag should be set for the given event. +// TODO: Ideally the event itself would know about the caps lock key; see +// <http://crbug.com/38226>. This function is only a temporary workaround that +// guesses based on live state. +bool CapsLockIsActive(const WebInputEvent& event) { + NSUInteger current_flags = [[NSApp currentEvent] modifierFlags]; + bool caps_lock_on = (current_flags & NSAlphaShiftKeyMask) ? true : false; + // If this a caps lock keypress, then the event stream state can be wrong. + // Luckily, the weird event stream for caps lock makes it easy to tell whether + // caps lock is being turned on or off. + if (event.type == WebInputEvent::KeyDown || + event.type == WebInputEvent::KeyUp) { + const WebKeyboardEvent* key_event = + static_cast<const WebKeyboardEvent*>(&event); + if (key_event->nativeKeyCode == 57) + caps_lock_on = (event.type == WebInputEvent::KeyDown); + } + return caps_lock_on; +} + +} // namespace + +#pragma mark - + +#ifndef NP_NO_CARBON + +// Converter implementation for the Carbon event model. +class CarbonPluginWebEventConverter : public PluginWebEventConverter { + public: + CarbonPluginWebEventConverter() {} + virtual ~CarbonPluginWebEventConverter() {} + + virtual bool InitWithEvent(const WebInputEvent& web_event); + + virtual void* plugin_event() { return &carbon_event_; } + + protected: + virtual bool ConvertKeyboardEvent(const WebKeyboardEvent& key_event); + virtual bool ConvertMouseEvent(const WebMouseEvent& mouse_event); + virtual bool ConvertMouseWheelEvent(const WebMouseWheelEvent& wheel_event); + + private: + // Returns the Carbon translation of web_event's modifiers. + static EventModifiers CarbonModifiers(const WebInputEvent& web_event); + + NPEvent carbon_event_; + + DISALLOW_COPY_AND_ASSIGN(CarbonPluginWebEventConverter); +}; + +bool CarbonPluginWebEventConverter::InitWithEvent( + const WebInputEvent& web_event) { + memset(&carbon_event_, 0, sizeof(carbon_event_)); + // Set the fields common to all event types. + carbon_event_.when = TickCount(); + carbon_event_.modifiers |= CarbonModifiers(web_event); + + return PluginWebEventConverter::InitWithEvent(web_event); +} + +bool CarbonPluginWebEventConverter::ConvertKeyboardEvent( + const WebKeyboardEvent& key_event) { + // TODO: Figure out how to handle Unicode input to plugins, if that's + // even possible in the NPAPI Carbon event model. + carbon_event_.message = (key_event.nativeKeyCode << 8) & keyCodeMask; + carbon_event_.message |= key_event.text[0] & charCodeMask; + carbon_event_.modifiers |= btnState; + + switch (key_event.type) { + case WebInputEvent::KeyDown: + if (key_event.modifiers & WebInputEvent::IsAutoRepeat) + carbon_event_.what = autoKey; + else + carbon_event_.what = keyDown; + return true; + case WebInputEvent::KeyUp: + carbon_event_.what = keyUp; + return true; + case WebInputEvent::RawKeyDown: + case WebInputEvent::Char: + // May be used eventually for IME, but currently not needed. + return false; + default: + NOTREACHED(); + return false; + } +} + +bool CarbonPluginWebEventConverter::ConvertMouseEvent( + const WebMouseEvent& mouse_event) { + carbon_event_.where.h = mouse_event.globalX; + carbon_event_.where.v = mouse_event.globalY; + + // Default to "button up"; override this for mouse down events below. + carbon_event_.modifiers |= btnState; + + switch (mouse_event.button) { + case WebMouseEvent::ButtonLeft: + break; + case WebMouseEvent::ButtonMiddle: + carbon_event_.modifiers |= cmdKey; + break; + case WebMouseEvent::ButtonRight: + carbon_event_.modifiers |= controlKey; + break; + default: + NOTIMPLEMENTED(); + } + switch (mouse_event.type) { + case WebInputEvent::MouseMove: + carbon_event_.what = nullEvent; + return true; + case WebInputEvent::MouseLeave: + case WebInputEvent::MouseEnter: + carbon_event_.what = NPEventType_AdjustCursorEvent; + return true; + case WebInputEvent::MouseDown: + carbon_event_.modifiers &= ~btnState; + carbon_event_.what = mouseDown; + return true; + case WebInputEvent::MouseUp: + carbon_event_.what = mouseUp; + return true; + default: + NOTREACHED(); + return false; + } +} + +bool CarbonPluginWebEventConverter::ConvertMouseWheelEvent( + const WebMouseWheelEvent& wheel_event) { + return false; // The Carbon NPAPI event model has no "mouse wheel" concept. +} + +EventModifiers CarbonPluginWebEventConverter::CarbonModifiers( + const WebInputEvent& web_event) { + NSInteger modifiers = 0; + if (web_event.modifiers & WebInputEvent::ControlKey) + modifiers |= controlKey; + if (web_event.modifiers & WebInputEvent::ShiftKey) + modifiers |= shiftKey; + if (web_event.modifiers & WebInputEvent::AltKey) + modifiers |= optionKey; + if (web_event.modifiers & WebInputEvent::MetaKey) + modifiers |= cmdKey; + if (CapsLockIsActive(web_event)) + modifiers |= alphaLock; + return modifiers; +} + +#endif // !NP_NO_CARBON + +#pragma mark - + +// Converter implementation for the Cocoa event model. +class CocoaPluginWebEventConverter : public PluginWebEventConverter { +public: + CocoaPluginWebEventConverter() {} + virtual ~CocoaPluginWebEventConverter() {} + + virtual bool InitWithEvent(const WebInputEvent& web_event); + + virtual void* plugin_event() { return &cocoa_event_; } + +protected: + virtual bool ConvertKeyboardEvent(const WebKeyboardEvent& key_event); + virtual bool ConvertMouseEvent(const WebMouseEvent& mouse_event); + virtual bool ConvertMouseWheelEvent(const WebMouseWheelEvent& wheel_event); + +private: + // Returns the Cocoa translation of web_event's modifiers. + static NSUInteger CocoaModifiers(const WebInputEvent& web_event); + + // Returns true if the given key is a modifier key. + static bool KeyIsModifier(int native_key_code); + + NPCocoaEvent cocoa_event_; + + DISALLOW_COPY_AND_ASSIGN(CocoaPluginWebEventConverter); +}; + +bool CocoaPluginWebEventConverter::InitWithEvent( + const WebInputEvent& web_event) { + memset(&cocoa_event_, 0, sizeof(cocoa_event_)); + return PluginWebEventConverter::InitWithEvent(web_event); +} + +bool CocoaPluginWebEventConverter::ConvertKeyboardEvent( + const WebKeyboardEvent& key_event) { + cocoa_event_.data.key.keyCode = key_event.nativeKeyCode; + + cocoa_event_.data.key.modifierFlags |= CocoaModifiers(key_event); + + // Modifier keys have their own event type, and don't get character or + // repeat data. + if (KeyIsModifier(key_event.nativeKeyCode)) { + cocoa_event_.type = NPCocoaEventFlagsChanged; + return true; + } + + cocoa_event_.data.key.characters = reinterpret_cast<NPNSString*>( + [NSString stringWithFormat:@"%S", key_event.text]); + cocoa_event_.data.key.charactersIgnoringModifiers = + reinterpret_cast<NPNSString*>( + [NSString stringWithFormat:@"%S", key_event.unmodifiedText]); + + if (key_event.modifiers & WebInputEvent::IsAutoRepeat) + cocoa_event_.data.key.isARepeat = true; + + switch (key_event.type) { + case WebInputEvent::KeyDown: + cocoa_event_.type = NPCocoaEventKeyDown; + return true; + case WebInputEvent::KeyUp: + cocoa_event_.type = NPCocoaEventKeyUp; + return true; + case WebInputEvent::RawKeyDown: + case WebInputEvent::Char: + // May be used eventually for IME, but currently not needed. + return false; + default: + NOTREACHED(); + return false; + } +} + +bool CocoaPluginWebEventConverter::ConvertMouseEvent( + const WebMouseEvent& mouse_event) { + cocoa_event_.data.mouse.pluginX = mouse_event.x; + cocoa_event_.data.mouse.pluginY = mouse_event.y; + cocoa_event_.data.mouse.modifierFlags |= CocoaModifiers(mouse_event); + cocoa_event_.data.mouse.clickCount = mouse_event.clickCount; + switch (mouse_event.button) { + case WebMouseEvent::ButtonLeft: + cocoa_event_.data.mouse.buttonNumber = 0; + break; + case WebMouseEvent::ButtonMiddle: + cocoa_event_.data.mouse.buttonNumber = 2; + break; + case WebMouseEvent::ButtonRight: + cocoa_event_.data.mouse.buttonNumber = 1; + break; + default: + cocoa_event_.data.mouse.buttonNumber = mouse_event.button; + break; + } + switch (mouse_event.type) { + case WebInputEvent::MouseDown: + cocoa_event_.type = NPCocoaEventMouseDown; + return true; + case WebInputEvent::MouseUp: + cocoa_event_.type = NPCocoaEventMouseUp; + return true; + case WebInputEvent::MouseMove: { + bool mouse_is_down = + (mouse_event.modifiers & WebInputEvent::LeftButtonDown) || + (mouse_event.modifiers & WebInputEvent::RightButtonDown) || + (mouse_event.modifiers & WebInputEvent::MiddleButtonDown); + cocoa_event_.type = mouse_is_down ? NPCocoaEventMouseDragged + : NPCocoaEventMouseMoved; + return true; + } + case WebInputEvent::MouseEnter: + cocoa_event_.type = NPCocoaEventMouseEntered; + return true; + case WebInputEvent::MouseLeave: + cocoa_event_.type = NPCocoaEventMouseExited; + return true; + default: + NOTREACHED(); + return false; + } +} + +bool CocoaPluginWebEventConverter::ConvertMouseWheelEvent( + const WebMouseWheelEvent& wheel_event) { + cocoa_event_.type = NPCocoaEventScrollWheel; + cocoa_event_.data.mouse.pluginX = wheel_event.x; + cocoa_event_.data.mouse.pluginY = wheel_event.y; + cocoa_event_.data.mouse.modifierFlags |= CocoaModifiers(wheel_event); + cocoa_event_.data.mouse.deltaX = wheel_event.deltaX; + cocoa_event_.data.mouse.deltaY = wheel_event.deltaY; + return true; +} + +NSUInteger CocoaPluginWebEventConverter::CocoaModifiers( + const WebInputEvent& web_event) { + NSInteger modifiers = 0; + if (web_event.modifiers & WebInputEvent::ControlKey) + modifiers |= NSControlKeyMask; + if (web_event.modifiers & WebInputEvent::ShiftKey) + modifiers |= NSShiftKeyMask; + if (web_event.modifiers & WebInputEvent::AltKey) + modifiers |= NSAlternateKeyMask; + if (web_event.modifiers & WebInputEvent::MetaKey) + modifiers |= NSCommandKeyMask; + if (CapsLockIsActive(web_event)) + modifiers |= NSAlphaShiftKeyMask; + return modifiers; +} + +bool CocoaPluginWebEventConverter::KeyIsModifier(int native_key_code) { + switch (native_key_code) { + case 55: // Left command + case 54: // Right command + case 58: // Left option + case 61: // Right option + case 59: // Left control + case 62: // Right control + case 56: // Left shift + case 60: // Right shift + case 57: // Caps lock + return true; + default: + return false; + } +} + +#pragma mark - + +bool PluginWebEventConverter::InitWithEvent(const WebInputEvent& web_event) { + if (web_event.type == WebInputEvent::MouseWheel) { + return ConvertMouseWheelEvent( + *static_cast<const WebMouseWheelEvent*>(&web_event)); + } else if (WebInputEvent::isMouseEventType(web_event.type)) { + return ConvertMouseEvent(*static_cast<const WebMouseEvent*>(&web_event)); + } else if (WebInputEvent::isKeyboardEventType(web_event.type)) { + return ConvertKeyboardEvent( + *static_cast<const WebKeyboardEvent*>(&web_event)); + } + DLOG(WARNING) << "Unknown event type " << web_event.type; + return false; +} + +#pragma mark - + +PluginWebEventConverter* + PluginWebEventConverterFactory::CreateConverterForModel( + NPEventModel event_model) { + switch (event_model) { + case NPEventModelCocoa: + return new CocoaPluginWebEventConverter(); +#ifndef NP_NO_CARBON + case NPEventModelCarbon: + return new CarbonPluginWebEventConverter(); +#endif + default: + NOTIMPLEMENTED(); + return NULL; + } +} diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm index f1f7cbd..d2445ed 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm +++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm @@ -21,11 +21,11 @@ #include "webkit/default_plugin/plugin_impl.h" #include "webkit/glue/webplugin.h" #include "webkit/glue/plugins/coregraphics_private_symbols_mac.h" -#include "webkit/glue/plugins/plugin_constants_win.h" #include "webkit/glue/plugins/plugin_instance.h" #include "webkit/glue/plugins/plugin_lib.h" #include "webkit/glue/plugins/plugin_list.h" #include "webkit/glue/plugins/plugin_stream_url.h" +#include "webkit/glue/plugins/plugin_web_event_converter_mac.h" #include "webkit/glue/webkit_glue.h" #ifndef NP_NO_CARBON @@ -935,300 +935,6 @@ void WebPluginDelegateImpl::UpdateIdleEventRate() { } #endif // !NP_NO_CARBON -static bool WebInputEventIsWebMouseEvent(const WebInputEvent& event) { - switch (event.type) { - case WebInputEvent::MouseMove: - case WebInputEvent::MouseLeave: - case WebInputEvent::MouseEnter: - case WebInputEvent::MouseDown: - case WebInputEvent::MouseUp: - if (event.size < sizeof(WebMouseEvent)) { - NOTREACHED(); - return false; - } - return true; - default: - return false; - } -} - -static bool WebInputEventIsWebKeyboardEvent(const WebInputEvent& event) { - switch (event.type) { - case WebInputEvent::KeyDown: - case WebInputEvent::KeyUp: - if (event.size < sizeof(WebKeyboardEvent)) { - NOTREACHED(); - return false; - } - return true; - default: - return false; - } -} - -// Returns true if the caps lock flag should be set for the given event. -// TODO: Ideally the event itself would know about the caps lock key; see -// <http://crbug.com/38226>. This function is only a temporary workaround that -// guesses based on live state. -static bool CapsLockIsActive(const WebInputEvent& event) { - NSUInteger current_flags = [[NSApp currentEvent] modifierFlags]; - bool caps_lock_on = (current_flags & NSAlphaShiftKeyMask) ? true : false; - // If this a caps lock keypress, then the event stream state can be wrong. - // Luckily, the weird event stream for caps lock makes it easy to tell whether - // caps lock is being turned on or off. - if (event.type == WebInputEvent::KeyDown || - event.type == WebInputEvent::KeyUp) { - const WebKeyboardEvent* key_event = - static_cast<const WebKeyboardEvent*>(&event); - if (key_event->nativeKeyCode == 57) - caps_lock_on = (event.type == WebInputEvent::KeyDown); - } - return caps_lock_on; -} - -#ifndef NP_NO_CARBON -static NSInteger CarbonModifiersFromWebEvent(const WebInputEvent& event) { - NSInteger modifiers = 0; - if (event.modifiers & WebInputEvent::ControlKey) - modifiers |= controlKey; - if (event.modifiers & WebInputEvent::ShiftKey) - modifiers |= shiftKey; - if (event.modifiers & WebInputEvent::AltKey) - modifiers |= optionKey; - if (event.modifiers & WebInputEvent::MetaKey) - modifiers |= cmdKey; - if (CapsLockIsActive(event)) - modifiers |= alphaLock; - return modifiers; -} - -static bool NPEventFromWebMouseEvent(const WebMouseEvent& event, - NPEvent *np_event) { - np_event->where.h = event.globalX; - np_event->where.v = event.globalY; - - np_event->modifiers |= CarbonModifiersFromWebEvent(event); - - // default to "button up"; override this for mouse down events below. - np_event->modifiers |= btnState; - - switch (event.button) { - case WebMouseEvent::ButtonLeft: - break; - case WebMouseEvent::ButtonMiddle: - np_event->modifiers |= cmdKey; - break; - case WebMouseEvent::ButtonRight: - np_event->modifiers |= controlKey; - break; - default: - NOTIMPLEMENTED(); - } - switch (event.type) { - case WebInputEvent::MouseMove: - np_event->what = nullEvent; - return true; - case WebInputEvent::MouseLeave: - case WebInputEvent::MouseEnter: - np_event->what = NPEventType_AdjustCursorEvent; - return true; - case WebInputEvent::MouseDown: - np_event->modifiers &= ~btnState; - np_event->what = mouseDown; - return true; - case WebInputEvent::MouseUp: - np_event->what = mouseUp; - return true; - default: - NOTREACHED(); - return false; - } -} - -static bool NPEventFromWebKeyboardEvent(const WebKeyboardEvent& event, - NPEvent *np_event) { - // TODO: figure out how to handle Unicode input to plugins, if that's - // even possible in the NPAPI Carbon event model. - np_event->message = (event.nativeKeyCode << 8) & keyCodeMask; - np_event->message |= event.text[0] & charCodeMask; - np_event->modifiers |= btnState; - np_event->modifiers |= CarbonModifiersFromWebEvent(event); - - switch (event.type) { - case WebInputEvent::KeyDown: - if (event.modifiers & WebInputEvent::IsAutoRepeat) - np_event->what = autoKey; - else - np_event->what = keyDown; - return true; - case WebInputEvent::KeyUp: - np_event->what = keyUp; - return true; - default: - NOTREACHED(); - return false; - } -} - -static bool NPEventFromWebInputEvent(const WebInputEvent& event, - NPEvent* np_event) { - np_event->when = TickCount(); - if (event.type == WebInputEvent::MouseWheel) { - return false; // Carbon NPAPI event model has no "mouse wheel" concept. - } else if (WebInputEventIsWebMouseEvent(event)) { - return NPEventFromWebMouseEvent(*static_cast<const WebMouseEvent*>(&event), - np_event); - } else if (WebInputEventIsWebKeyboardEvent(event)) { - return NPEventFromWebKeyboardEvent( - *static_cast<const WebKeyboardEvent*>(&event), np_event); - } - DLOG(WARNING) << "unknown event type " << event.type; - return false; -} -#endif // !NP_NO_CARBON - -static NSInteger CocoaModifiersFromWebEvent(const WebInputEvent& event) { - NSInteger modifiers = 0; - if (event.modifiers & WebInputEvent::ControlKey) - modifiers |= NSControlKeyMask; - if (event.modifiers & WebInputEvent::ShiftKey) - modifiers |= NSShiftKeyMask; - if (event.modifiers & WebInputEvent::AltKey) - modifiers |= NSAlternateKeyMask; - if (event.modifiers & WebInputEvent::MetaKey) - modifiers |= NSCommandKeyMask; - if (CapsLockIsActive(event)) - modifiers |= NSAlphaShiftKeyMask; - return modifiers; -} - -static bool KeyIsModifier(int native_key_code) { - switch (native_key_code) { - case 55: // Left command - case 54: // Right command - case 58: // Left option - case 61: // Right option - case 59: // Left control - case 62: // Right control - case 56: // Left shift - case 60: // Right shift - case 57: // Caps lock - return true; - default: - return false; - } -} - -static bool NPCocoaEventFromWebMouseEvent(const WebMouseEvent& event, - NPCocoaEvent *np_cocoa_event) { - np_cocoa_event->data.mouse.pluginX = event.x; - np_cocoa_event->data.mouse.pluginY = event.y; - np_cocoa_event->data.mouse.modifierFlags |= CocoaModifiersFromWebEvent(event); - np_cocoa_event->data.mouse.clickCount = event.clickCount; - switch (event.button) { - case WebMouseEvent::ButtonLeft: - np_cocoa_event->data.mouse.buttonNumber = 0; - break; - case WebMouseEvent::ButtonMiddle: - np_cocoa_event->data.mouse.buttonNumber = 2; - break; - case WebMouseEvent::ButtonRight: - np_cocoa_event->data.mouse.buttonNumber = 1; - break; - default: - np_cocoa_event->data.mouse.buttonNumber = event.button; - break; - } - switch (event.type) { - case WebInputEvent::MouseDown: - np_cocoa_event->type = NPCocoaEventMouseDown; - return true; - case WebInputEvent::MouseUp: - np_cocoa_event->type = NPCocoaEventMouseUp; - return true; - case WebInputEvent::MouseMove: { - bool mouse_is_down = (event.modifiers & WebInputEvent::LeftButtonDown) || - (event.modifiers & WebInputEvent::RightButtonDown) || - (event.modifiers & WebInputEvent::MiddleButtonDown); - np_cocoa_event->type = mouse_is_down ? NPCocoaEventMouseDragged - : NPCocoaEventMouseMoved; - return true; - } - case WebInputEvent::MouseEnter: - np_cocoa_event->type = NPCocoaEventMouseEntered; - return true; - case WebInputEvent::MouseLeave: - np_cocoa_event->type = NPCocoaEventMouseExited; - return true; - default: - NOTREACHED(); - return false; - } -} - -static bool NPCocoaEventFromWebMouseWheelEvent(const WebMouseWheelEvent& event, - NPCocoaEvent *np_cocoa_event) { - np_cocoa_event->type = NPCocoaEventScrollWheel; - np_cocoa_event->data.mouse.pluginX = event.x; - np_cocoa_event->data.mouse.pluginY = event.y; - np_cocoa_event->data.mouse.modifierFlags |= CocoaModifiersFromWebEvent(event); - np_cocoa_event->data.mouse.deltaX = event.deltaX; - np_cocoa_event->data.mouse.deltaY = event.deltaY; - return true; -} - -static bool NPCocoaEventFromWebKeyboardEvent(const WebKeyboardEvent& event, - NPCocoaEvent *np_cocoa_event) { - np_cocoa_event->data.key.keyCode = event.nativeKeyCode; - - np_cocoa_event->data.key.modifierFlags |= CocoaModifiersFromWebEvent(event); - - // Modifier keys have their own event type, and don't get character or - // repeat data. - if (KeyIsModifier(event.nativeKeyCode)) { - np_cocoa_event->type = NPCocoaEventFlagsChanged; - return true; - } - - np_cocoa_event->data.key.characters = reinterpret_cast<NPNSString*>( - [NSString stringWithFormat:@"%S", event.text]); - np_cocoa_event->data.key.charactersIgnoringModifiers = - reinterpret_cast<NPNSString*>( - [NSString stringWithFormat:@"%S", event.unmodifiedText]); - - if (event.modifiers & WebInputEvent::IsAutoRepeat) - np_cocoa_event->data.key.isARepeat = true; - - switch (event.type) { - case WebInputEvent::KeyDown: - np_cocoa_event->type = NPCocoaEventKeyDown; - return true; - case WebInputEvent::KeyUp: - np_cocoa_event->type = NPCocoaEventKeyUp; - return true; - default: - NOTREACHED(); - return false; - } -} - -static bool NPCocoaEventFromWebInputEvent(const WebInputEvent& event, - NPCocoaEvent *np_cocoa_event) { - memset(np_cocoa_event, 0, sizeof(NPCocoaEvent)); - if (event.type == WebInputEvent::MouseWheel) { - return NPCocoaEventFromWebMouseWheelEvent( - *static_cast<const WebMouseWheelEvent*>(&event), np_cocoa_event); - } else if (WebInputEventIsWebMouseEvent(event)) { - return NPCocoaEventFromWebMouseEvent( - *static_cast<const WebMouseEvent*>(&event), np_cocoa_event); - } else if (WebInputEventIsWebKeyboardEvent(event)) { - return NPCocoaEventFromWebKeyboardEvent( - *static_cast<const WebKeyboardEvent*>(&event), np_cocoa_event); - } - DLOG(WARNING) << "unknown event type " << event.type; - return false; -} - // Returns the mask for just the button state in a WebInputEvent's modifiers. static int WebEventButtonModifierMask() { return WebInputEvent::LeftButtonDown | @@ -1298,7 +1004,7 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent( } #endif - if (WebInputEventIsWebMouseEvent(event)) { + if (WebInputEvent::isMouseEventType(event.type)) { // Check our plugin location before we send the event to the plugin, just // in case we somehow missed a plugin frame change. const WebMouseEvent* mouse_event = @@ -1329,7 +1035,7 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent( // This isn't perfect (specifically, click-and-hold doesn't seem to work // if the fast path is on), but the slight regression is worthwhile // for the improved framerates. - if (WebInputEventIsWebMouseEvent(event)) { + if (WebInputEvent::isMouseEventType(event.type)) { if (event.type == WebInputEvent::MouseLeave) { SetQuickDrawFastPathEnabled(true); } else { @@ -1367,55 +1073,52 @@ bool WebPluginDelegateImpl::PlatformHandleInputEvent( ScopedActiveDelegate active_delegate(this); - // Create the plugin event structure, and send it to the plugin. - bool ret = false; - switch (instance()->event_model()) { -#ifndef NP_NO_CARBON - case NPEventModelCarbon: { - NPEvent np_event = {0}; - if (!NPEventFromWebInputEvent(event, &np_event)) - return false; - ret = instance()->NPP_HandleEvent(&np_event) != 0; - break; - } -#endif - case NPEventModelCocoa: { - NPCocoaEvent np_cocoa_event; - if (!NPCocoaEventFromWebInputEvent(event, &np_cocoa_event)) - 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; + // Create the plugin event structure. + NPEventModel event_model = instance()->event_model(); + scoped_ptr<PluginWebEventConverter> event_converter( + PluginWebEventConverterFactory::CreateConverterForModel(event_model)); + if (!(event_converter.get() && event_converter->InitWithEvent(event))) + return false; + void* plugin_event = event_converter->plugin_event(); + + if (instance()->event_model() == NPEventModelCocoa) { + // We recieve events related to drags starting outside the plugin, but the + // NPAPI Cocoa event model spec says plugins shouldn't receive them, so + // filter them out. + // If we add a page capture mode at the WebKit layer (like the plugin + // capture mode that handles drags starting inside) this can 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_) { + // When an external drag ends, we need to synthesize a MouseEntered. + NPCocoaEvent enter_event = *(static_cast<NPCocoaEvent*>(plugin_event)); + enter_event.type = NPCocoaEventMouseEntered; + NPAPI::ScopedCurrentPluginEvent event_scope(instance(), &enter_event); + instance()->NPP_HandleEvent(&enter_event); } - - NPAPI::ScopedCurrentPluginEvent event_scope(instance(), &np_cocoa_event); - ret = instance()->NPP_HandleEvent(&np_cocoa_event) != 0; - break; + return false; } } - if (WebInputEventIsWebMouseEvent(event)) { + // Send the plugin the event. + scoped_ptr<NPAPI::ScopedCurrentPluginEvent> event_scope(NULL); + if (instance()->event_model() == NPEventModelCocoa) { + event_scope.reset(new NPAPI::ScopedCurrentPluginEvent( + instance(), static_cast<NPCocoaEvent*>(plugin_event))); + } + bool handled = instance()->NPP_HandleEvent(plugin_event) != 0; + + if (WebInputEvent::isMouseEventType(event.type)) { // Plugins are not good about giving accurate information about whether or // not they handled events, and other browsers on the Mac generally ignore // the return value. We may need to expand this to other input types, but // we'll need to be careful about things like Command-keys. - ret = true; + handled = true; } - return ret; + return handled; } #ifndef NP_NO_CARBON diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi index c8f3725..ff96daa 100644 --- a/webkit/glue/webkit_glue.gypi +++ b/webkit/glue/webkit_glue.gypi @@ -182,6 +182,8 @@ 'plugins/plugin_string_stream.cc', 'plugins/plugin_string_stream.h', 'plugins/plugin_stubs.cc', + 'plugins/plugin_web_event_converter_mac.h', + 'plugins/plugin_web_event_converter_mac.mm', 'plugins/webplugin_2d_device_delegate.h', 'plugins/webplugin_3d_device_delegate.h', 'plugins/webplugin_delegate_impl.cc', |