diff options
author | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-22 01:29:05 +0000 |
---|---|---|
committer | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-22 01:29:05 +0000 |
commit | 41fbf097c8e01c4971de118eb8fb791b9abaa6eb (patch) | |
tree | 8216ee10224ebb84ace23ef8d227e8ec07666bac /webkit/glue/plugins | |
parent | d77232f96be7900e1e7230d145c06bb9e5ed7e44 (diff) | |
download | chromium_src-41fbf097c8e01c4971de118eb8fb791b9abaa6eb.zip chromium_src-41fbf097c8e01c4971de118eb8fb791b9abaa6eb.tar.gz chromium_src-41fbf097c8e01c4971de118eb8fb791b9abaa6eb.tar.bz2 |
Add events to windowless plugins on linux. This CL also refactors the event
communication between WebPlugin and WebPluginDelegate, to use a cross-platform
message based on WebInputEvent.
BUG=8202
TEST=A lot of manual testing on Linux and Windows, with Flash plugins and a
custom plugin that dumps events on Linux.
Review URL: http://codereview.chromium.org/115330
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16692 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue/plugins')
-rw-r--r-- | webkit/glue/plugins/plugin_host.cc | 15 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_instance.cc | 7 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_instance.h | 13 | ||||
-rw-r--r-- | webkit/glue/plugins/test/plugin_javascript_open_popup.cc | 15 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.cc | 131 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.h | 9 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_gtk.cc | 235 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_mac.mm | 10 |
8 files changed, 353 insertions, 82 deletions
diff --git a/webkit/glue/plugins/plugin_host.cc b/webkit/glue/plugins/plugin_host.cc index a349e43..815b415 100644 --- a/webkit/glue/plugins/plugin_host.cc +++ b/webkit/glue/plugins/plugin_host.cc @@ -2,17 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// HACK: we need this #define in place before npapi.h is included for -// plugins to work. However, all sorts of headers include npapi.h, so -// the only way to be certain the define is in place is to put it -// here. You might ask, "Why not set it in npapi.h directly, or in -// this directory's SConscript, then?" but it turns out this define -// makes npapi.h include Xlib.h, which in turn defines a ton of symbols -// like None and Status, causing conflicts with the aforementioned -// many headers that include npapi.h. Ugh. -// See also webplugin_delegate_impl.cc. -#define MOZ_X11 1 - #include "config.h" #include "webkit/glue/plugins/plugin_host.h" @@ -720,9 +709,9 @@ NPError NPN_GetValue(NPP id, NPNVariable variable, void *value) { } case NPNVnetscapeWindow: { -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_LINUX) scoped_refptr<NPAPI::PluginInstance> plugin = FindInstance(id); - HWND handle = plugin->window_handle(); + gfx::NativeView handle = plugin->window_handle(); *((void**)value) = (void*)handle; rv = NPERR_NO_ERROR; #else diff --git a/webkit/glue/plugins/plugin_instance.cc b/webkit/glue/plugins/plugin_instance.cc index f8c1814..23df8c0 100644 --- a/webkit/glue/plugins/plugin_instance.cc +++ b/webkit/glue/plugins/plugin_instance.cc @@ -5,9 +5,6 @@ #include "config.h" #include "build/build_config.h" -#if defined(OS_LINUX) -#define MOZ_X11 1 -#endif #include "webkit/glue/plugins/plugin_instance.h" @@ -41,9 +38,7 @@ PluginInstance::PluginInstance(PluginLib *plugin, const std::string &mime_type) npp_(0), host_(PluginHost::Singleton()), npp_functions_(plugin->functions()), -#if defined(OS_WIN) - hwnd_(0), -#endif + window_handle_(0), windowless_(false), transparent_(true), webplugin_(0), diff --git a/webkit/glue/plugins/plugin_instance.h b/webkit/glue/plugins/plugin_instance.h index 2c3bb49..e73d49f 100644 --- a/webkit/glue/plugins/plugin_instance.h +++ b/webkit/glue/plugins/plugin_instance.h @@ -14,6 +14,7 @@ #include "base/basictypes.h" #include "base/file_path.h" +#include "base/gfx/native_widget_types.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "webkit/glue/plugins/nphostapi.h" @@ -68,11 +69,9 @@ class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> { // NPAPI's instance identifier for this instance NPP npp() { return npp_; } -#if defined(OS_WIN) - // Get/Set for the instance's HWND. - HWND window_handle() { return hwnd_; } - void set_window_handle(HWND value) { hwnd_ = value; } -#endif + // Get/Set for the instance's window handle. + gfx::NativeView window_handle() { return window_handle_; } + void set_window_handle(gfx::NativeView value) { window_handle_ = value; } // Get/Set whether this instance is in Windowless mode. // Default is false. @@ -224,9 +223,7 @@ class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> { scoped_refptr<PluginHost> host_; NPPluginFuncs* npp_functions_; std::vector<scoped_refptr<PluginStream> > open_streams_; -#if defined(OS_WIN) - HWND hwnd_; -#endif + gfx::NativeView window_handle_; bool windowless_; bool transparent_; WebPlugin* webplugin_; diff --git a/webkit/glue/plugins/test/plugin_javascript_open_popup.cc b/webkit/glue/plugins/test/plugin_javascript_open_popup.cc index 9af6656..558aa71 100644 --- a/webkit/glue/plugins/test/plugin_javascript_open_popup.cc +++ b/webkit/glue/plugins/test/plugin_javascript_open_popup.cc @@ -3,20 +3,11 @@ // found in the LICENSE file. #include "build/build_config.h" -#if defined(OS_LINUX) -// HACK: we need this #define in place before npapi.h is included for -// plugins to work. However, all sorts of headers include npapi.h, so -// the only way to be certain the define is in place is to put it -// here. You might ask, "Why not set it in npapi.h directly, or in -// this directory's SConscript, then?" but it turns out this define -// makes npapi.h include Xlib.h, which in turn defines a ton of symbols -// like None and Status, causing conflicts with the aforementioned -// many headers that include npapi.h. Ugh. -#define MOZ_X11 1 -#endif - #include "webkit/glue/plugins/test/plugin_javascript_open_popup.h" +#if defined(OS_LINUX) +#include "third_party/npapi/bindings/npapi_x11.h" +#endif #include "webkit/glue/plugins/test/plugin_client.h" namespace NPAPIClient { diff --git a/webkit/glue/plugins/webplugin_delegate_impl.cc b/webkit/glue/plugins/webplugin_delegate_impl.cc index 2c41851..23c11aa 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl.cc @@ -13,6 +13,7 @@ #include "base/message_loop.h" #include "base/stats_counters.h" #include "base/string_util.h" +#include "webkit/api/public/WebInputEvent.h" #include "webkit/default_plugin/plugin_impl.h" #include "webkit/glue/glue_util.h" #include "webkit/glue/webplugin.h" @@ -23,6 +24,10 @@ #include "webkit/glue/plugins/plugin_stream_url.h" #include "webkit/glue/webkit_glue.h" +using WebKit::WebKeyboardEvent; +using WebKit::WebInputEvent; +using WebKit::WebMouseEvent; + namespace { const wchar_t kWebPluginDelegateProperty[] = L"WebPluginDelegateProperty"; @@ -260,7 +265,6 @@ bool WebPluginDelegateImpl::Initialize(const GURL& url, } plugin->SetWindow(windowed_handle_); -#if defined(OS_WIN) if (windowless_) { // For windowless plugins we should set the containing window handle // as the instance window handle. This is what Safari does. Not having @@ -268,11 +272,12 @@ bool WebPluginDelegateImpl::Initialize(const GURL& url, // the window handle and validate the same. The window handle can be // retreived via NPN_GetValue of NPNVnetscapeWindow. instance_->set_window_handle(parent_); +#if defined(OS_WIN) CreateDummyWindowForActivation(); handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); plugin->SetWindowlessPumpEvent(handle_event_pump_messages_event_); - } #endif + } plugin_url_ = url.spec(); // The windowless version of the Silverlight plugin calls the @@ -999,11 +1004,117 @@ void WebPluginDelegateImpl::SetFocus() { instance()->NPP_HandleEvent(&focus_event); } -bool WebPluginDelegateImpl::HandleEvent(NPEvent* event, - WebCursor* cursor) { +static bool NPEventFromWebMouseEvent(const WebMouseEvent& event, + NPEvent *np_event) { + np_event->lParam = static_cast<uint32>(MAKELPARAM(event.windowX, + event.windowY)); + np_event->wParam = 0; + + if (event.modifiers & WebInputEvent::ControlKey) + np_event->wParam |= MK_CONTROL; + if (event.modifiers & WebInputEvent::ShiftKey) + np_event->wParam |= MK_SHIFT; + if (event.modifiers & WebInputEvent::LeftButtonDown) + np_event->wParam |= MK_LBUTTON; + if (event.modifiers & WebInputEvent::MiddleButtonDown) + np_event->wParam |= MK_MBUTTON; + if (event.modifiers & WebInputEvent::RightButtonDown) + np_event->wParam |= MK_RBUTTON; + + switch (event.type) { + case WebInputEvent::MouseMove: + case WebInputEvent::MouseLeave: + case WebInputEvent::MouseEnter: + np_event->event = WM_MOUSEMOVE; + return true; + case WebInputEvent::MouseDown: + switch (event.button) { + case WebMouseEvent::ButtonLeft: + np_event->event = WM_LBUTTONDOWN; + break; + case WebMouseEvent::ButtonMiddle: + np_event->event = WM_MBUTTONDOWN; + break; + case WebMouseEvent::ButtonRight: + np_event->event = WM_RBUTTONDOWN; + break; + } + return true; + case WebInputEvent::MouseUp: + switch (event.button) { + case WebMouseEvent::ButtonLeft: + np_event->event = WM_LBUTTONUP; + break; + case WebMouseEvent::ButtonMiddle: + np_event->event = WM_MBUTTONUP; + break; + case WebMouseEvent::ButtonRight: + np_event->event = WM_RBUTTONUP; + break; + } + return true; + default: + NOTREACHED(); + return false; + } +} + +static bool NPEventFromWebKeyboardEvent(const WebKeyboardEvent& event, + NPEvent *np_event) { + np_event->wParam = event.windowsKeyCode; + + switch (event.type) { + case WebInputEvent::KeyDown: + np_event->event = WM_KEYDOWN; + np_event->lParam = 0; + return true; + case WebInputEvent::KeyUp: + np_event->event = WM_KEYUP; + np_event->lParam = 0x8000; + return true; + default: + NOTREACHED(); + return false; + } +} + +static bool NPEventFromWebInputEvent(const WebInputEvent& event, + NPEvent* np_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 NPEventFromWebMouseEvent( + *static_cast<const WebMouseEvent*>(&event), np_event); + case WebInputEvent::KeyDown: + case WebInputEvent::KeyUp: + if (event.size < sizeof(WebKeyboardEvent)) { + NOTREACHED(); + return false; + } + return NPEventFromWebKeyboardEvent( + *static_cast<const WebKeyboardEvent*>(&event), np_event); + default: + return false; + } +} + +bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event, + WebCursor* cursor) { DCHECK(windowless_) << "events should only be received in windowless mode"; DCHECK(cursor != NULL); + NPEvent np_event; + if (!NPEventFromWebInputEvent(event, &np_event)) { + return false; + } + // To ensure that the plugin receives keyboard events we set focus to the // dummy window. // TODO(iyengar) We need a framework in the renderer to identify which @@ -1011,11 +1122,11 @@ bool WebPluginDelegateImpl::HandleEvent(NPEvent* event, // also require some changes in RenderWidgetHost to detect this in the // WM_MOUSEACTIVATE handler and inform the renderer accordingly. HWND prev_focus_window = NULL; - if (event->event == WM_RBUTTONDOWN) { + if (np_event.event == WM_RBUTTONDOWN) { prev_focus_window = ::SetFocus(dummy_window_for_activation_); } - if (ShouldTrackEventForModalLoops(event)) { + if (ShouldTrackEventForModalLoops(&np_event)) { // A windowless plugin can enter a modal loop in a NPP_HandleEvent call. // For e.g. Flash puts up a context menu when we right click on the // windowless plugin area. We detect this by setting up a message filter @@ -1042,14 +1153,14 @@ bool WebPluginDelegateImpl::HandleEvent(NPEvent* event, bool pop_user_gesture = false; - if (IsUserGestureMessage(event->event)) { + if (IsUserGestureMessage(np_event.event)) { pop_user_gesture = true; instance()->PushPopupsEnabledState(true); } - bool ret = instance()->NPP_HandleEvent(event) != 0; + bool ret = instance()->NPP_HandleEvent(&np_event) != 0; - if (event->event == WM_MOUSEMOVE) { + if (np_event.event == WM_MOUSEMOVE) { // Snag a reference to the current cursor ASAP in case the plugin modified // it. There is a nasty race condition here with the multiprocess browser // as someone might be setting the cursor in the main process as well. @@ -1078,7 +1189,7 @@ bool WebPluginDelegateImpl::HandleEvent(NPEvent* event, ResetEvent(handle_event_pump_messages_event_); } - if (event->event == WM_RBUTTONUP && ::IsWindow(prev_focus_window)) { + if (np_event.event == WM_RBUTTONUP && ::IsWindow(prev_focus_window)) { ::SetFocus(prev_focus_window); } diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h index 80c478b..aa856b4 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.h +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -53,9 +53,10 @@ class WebPluginDelegateImpl : public WebPluginDelegate { virtual void Print(gfx::NativeDrawingContext context); virtual void SetFocus(); // only called when windowless -// only called when windowless - virtual bool HandleEvent(NPEvent* event, - WebCursor* cursor); + // only called when windowless + // See NPAPI NPP_HandleEvent for more information. + virtual bool HandleInputEvent(const WebKit::WebInputEvent& event, + WebCursor* cursor); virtual NPObject* GetPluginScriptableObject(); virtual void DidFinishLoadWithReason(NPReason reason); virtual int GetProcessId(); @@ -146,7 +147,6 @@ class WebPluginDelegateImpl : public WebPluginDelegate { // See NPAPI NPP_SetWindow for more information. void WindowlessSetWindow(bool force_set_window); - //----------------------------------------- // used for windowed and windowless plugins @@ -186,6 +186,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate { #if defined(OS_LINUX) // The pixmap we're drawing into, for a windowless plugin. GdkPixmap* pixmap_; + double first_event_time_; // Ensure pixmap_ exists and is at least width by height pixels. void EnsurePixmapAtLeastSize(int width, int height); diff --git a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc index 4922bf4..45fe78c 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc @@ -2,17 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// HACK: we need this #define in place before npapi.h is included for -// plugins to work. However, all sorts of headers include npapi.h, so -// the only way to be certain the define is in place is to put it -// here. You might ask, "Why not set it in npapi.h directly, or in -// this directory's SConscript, then?" but it turns out this define -// makes npapi.h include Xlib.h, which in turn defines a ton of symbols -// like None and Status, causing conflicts with the aforementioned -// many headers that include npapi.h. Ugh. -// See also plugin_host.cc. -#define MOZ_X11 1 - #include "webkit/glue/plugins/webplugin_delegate_impl.h" #include <string> @@ -27,6 +16,7 @@ #include "base/process_util.h" #include "base/stats_counters.h" #include "base/string_util.h" +#include "webkit/api/public/WebInputEvent.h" // #include "webkit/default_plugin/plugin_impl.h" #include "webkit/glue/glue_util.h" #include "webkit/glue/webplugin.h" @@ -36,6 +26,13 @@ #include "webkit/glue/plugins/plugin_list.h" #include "webkit/glue/plugins/plugin_stream_url.h" #include "webkit/glue/webkit_glue.h" +#if defined(OS_LINUX) +#include "third_party/npapi/bindings/npapi_x11.h" +#endif + +using WebKit::WebKeyboardEvent; +using WebKit::WebInputEvent; +using WebKit::WebMouseEvent; WebPluginDelegate* WebPluginDelegate::Create( const FilePath& filename, @@ -63,13 +60,13 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( windowed_did_set_window_(false), windowless_(false), plugin_(NULL), + windowless_needs_set_window_(true), instance_(instance), pixmap_(NULL), + first_event_time_(-1.0), parent_(containing_view), - quirks_(0) - { + quirks_(0) { memset(&window_, 0, sizeof(window_)); - } WebPluginDelegateImpl::~WebPluginDelegateImpl() { @@ -120,7 +117,7 @@ bool WebPluginDelegateImpl::Initialize(const GURL& url, // a valid window handle causes subtle bugs with plugins which retreive // the window handle and validate the same. The window handle can be // retreived via NPN_GetValue of NPNVnetscapeWindow. - // instance_->set_window_handle(parent_); + instance_->set_window_handle(parent_); // CreateDummyWindowForActivation(); // handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); } else { @@ -393,7 +390,7 @@ void WebPluginDelegateImpl::WindowedSetWindow() { return; } - // XXX instance()->set_window_handle(windowed_handle_); + instance()->set_window_handle(windowed_handle_); DCHECK(!instance()->windowless()); @@ -545,7 +542,8 @@ void WebPluginDelegateImpl::WindowlessPaint(cairo_surface_t* context, cairo_destroy(cairo); // Construct the paint message, targeting the pixmap. - XGraphicsExposeEvent event = {0}; + NPEvent np_event = {0}; + XGraphicsExposeEvent &event = np_event.xgraphicsexpose; event.type = GraphicsExpose; event.display = GDK_DISPLAY(); event.drawable = GDK_PIXMAP_XID(pixmap_); @@ -557,7 +555,7 @@ void WebPluginDelegateImpl::WindowlessPaint(cairo_surface_t* context, // Tell the plugin to paint into the pixmap. static StatsRate plugin_paint("Plugin.Paint"); StatsScope<StatsRate> scope(plugin_paint); - NPError err = instance()->NPP_HandleEvent(reinterpret_cast<XEvent*>(&event)); + NPError err = instance()->NPP_HandleEvent(&np_event); DCHECK_EQ(err, NPERR_NO_ERROR); // Now copy the rendered image pixmap back into the drawing buffer. @@ -621,18 +619,201 @@ void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { void WebPluginDelegateImpl::SetFocus() { DCHECK(instance()->windowless()); - NOTIMPLEMENTED(); - /* NPEvent focus_event; - focus_event.event = WM_SETFOCUS; - focus_event.wParam = 0; - focus_event.lParam = 0; + NPEvent np_event = {0}; + XFocusChangeEvent &event = np_event.xfocus; + event.type = FocusIn; + event.display = GDK_DISPLAY(); + // Same values as Firefox. .serial and .window stay 0. + event.mode = -1; + event.detail = NotifyDetailNone; + instance()->NPP_HandleEvent(&np_event); +} + +// Converts a WebInputEvent::Modifiers bitfield into a +// corresponding X modifier state. +static int GetXModifierState(int modifiers) { + int x_state = 0; + if (modifiers & WebInputEvent::ControlKey) + x_state |= ControlMask; + if (modifiers & WebInputEvent::ShiftKey) + x_state |= ShiftMask; + if (modifiers & WebInputEvent::AltKey) + x_state |= Mod1Mask; + if (modifiers & WebInputEvent::MetaKey) + x_state |= Mod2Mask; + if (modifiers & WebInputEvent::LeftButtonDown) + x_state |= Button1Mask; + if (modifiers & WebInputEvent::MiddleButtonDown) + x_state |= Button2Mask; + if (modifiers & WebInputEvent::RightButtonDown) + x_state |= Button3Mask; + // TODO(piman@google.com): There are other modifiers, e.g. Num Lock, that + // should be set (and Firefox does), but we didn't keep the information in + // the WebKit event. + return x_state; +} + +static bool NPEventFromWebMouseEvent(const WebMouseEvent& event, + Time timestamp, + NPEvent *np_event) { + np_event->xany.display = GDK_DISPLAY(); + // NOTE: Firefox keeps xany.serial and xany.window as 0. + + int modifier_state = GetXModifierState(event.modifiers); + + Window root = GDK_ROOT_WINDOW(); + switch (event.type) { + case WebInputEvent::MouseMove: { + np_event->type = MotionNotify; + XMotionEvent &motion_event = np_event->xmotion; + motion_event.root = root; + motion_event.time = timestamp; + motion_event.x = event.x; + motion_event.y = event.y; + motion_event.x_root = event.globalX; + motion_event.y_root = event.globalY; + motion_event.state = modifier_state; + motion_event.is_hint = NotifyNormal; + motion_event.same_screen = True; + break; + } + case WebInputEvent::MouseLeave: + case WebInputEvent::MouseEnter: { + if (event.type == WebInputEvent::MouseEnter) { + np_event->type = EnterNotify; + } else { + np_event->type = LeaveNotify; + } + XCrossingEvent &crossing_event = np_event->xcrossing; + crossing_event.root = root; + crossing_event.time = timestamp; + crossing_event.x = event.x; + crossing_event.y = event.y; + crossing_event.x_root = event.globalX; + crossing_event.y_root = event.globalY; + crossing_event.mode = -1; // This is what Firefox sets it to. + crossing_event.detail = NotifyDetailNone; + crossing_event.same_screen = True; + // TODO(piman@google.com): set this to the correct value. Firefox does. I + // don't know where to get the information though, we get focus + // notifications, but no unfocus. + crossing_event.focus = 0; + crossing_event.state = modifier_state; + break; + } + case WebInputEvent::MouseUp: + case WebInputEvent::MouseDown: { + if (event.type == WebInputEvent::MouseDown) { + np_event->type = ButtonPress; + } else { + np_event->type = ButtonRelease; + } + XButtonEvent &button_event = np_event->xbutton; + button_event.root = root; + button_event.time = timestamp; + button_event.x = event.x; + button_event.y = event.y; + button_event.x_root = event.globalX; + button_event.y_root = event.globalY; + button_event.state = modifier_state; + switch (event.button) { + case WebMouseEvent::ButtonLeft: + button_event.button = Button1; + break; + case WebMouseEvent::ButtonMiddle: + button_event.button = Button2; + break; + case WebMouseEvent::ButtonRight: + button_event.button = Button3; + break; + } + button_event.same_screen = True; + break; + } + default: + NOTREACHED(); + return false; + } + return true; +} - instance()->NPP_HandleEvent(&focus_event);*/ +static bool NPEventFromWebKeyboardEvent(const WebKeyboardEvent& event, + Time timestamp, + NPEvent *np_event) { + np_event->xany.display = GDK_DISPLAY(); + // NOTE: Firefox keeps xany.serial and xany.window as 0. + + switch (event.type) { + case WebKeyboardEvent::KeyDown: + np_event->type = KeyPress; + break; + case WebKeyboardEvent::KeyUp: + np_event->type = KeyRelease; + break; + default: + NOTREACHED(); + return false; + } + XKeyEvent &key_event = np_event->xkey; + key_event.send_event = False; + key_event.display = GDK_DISPLAY(); + // NOTE: Firefox keeps xany.serial and xany.window as 0. + // TODO(piman@google.com): is this right for multiple screens ? + key_event.root = DefaultRootWindow(key_event.display); + key_event.time = timestamp; + // NOTE: We don't have the correct information for x/y/x_root/y_root. Firefox + // doesn't have it either, so we pass the same values. + key_event.x = 0; + key_event.y = 0; + key_event.x_root = -1; + key_event.y_root = -1; + key_event.state = GetXModifierState(event.modifiers); + key_event.keycode = event.nativeKeyCode; + key_event.same_screen = True; + return true; } -bool WebPluginDelegateImpl::HandleEvent(NPEvent* event, - WebCursor* cursor) { - bool ret = instance()->NPP_HandleEvent(event) != 0; +static bool NPEventFromWebInputEvent(const WebInputEvent& event, + Time timestamp, + NPEvent* np_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 NPEventFromWebMouseEvent( + *static_cast<const WebMouseEvent*>(&event), timestamp, np_event); + case WebInputEvent::KeyDown: + case WebInputEvent::KeyUp: + if (event.size < sizeof(WebKeyboardEvent)) { + NOTREACHED(); + return false; + } + return NPEventFromWebKeyboardEvent( + *static_cast<const WebKeyboardEvent*>(&event), timestamp, np_event); + default: + return false; + } +} + +bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event, + WebCursor* cursor) { + DCHECK(windowless_) << "events should only be received in windowless mode"; + + if (first_event_time_ < 0.0) + first_event_time_ = event.timeStampSeconds; + Time timestamp = static_cast<Time>( + (event.timeStampSeconds - first_event_time_) * 1.0e3); + NPEvent np_event = {0}; + if (!NPEventFromWebInputEvent(event, timestamp, &np_event)) { + return false; + } + bool ret = instance()->NPP_HandleEvent(&np_event) != 0; #if 0 if (event->event == WM_MOUSEMOVE) { diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm index f758ce0..54bf43b 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm +++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm @@ -13,6 +13,7 @@ #include "base/message_loop.h" #include "base/stats_counters.h" #include "base/string_util.h" +#include "webkit/api/public/WebInputEvent.h" #include "webkit/default_plugin/plugin_impl.h" #include "webkit/glue/glue_util.h" #include "webkit/glue/webplugin.h" @@ -23,6 +24,10 @@ #include "webkit/glue/plugins/plugin_stream_url.h" #include "webkit/glue/webkit_glue.h" +using WebKit::WebKeyboardEvent; +using WebKit::WebInputEvent; +using WebKit::WebMouseEvent; + namespace { const wchar_t kWebPluginDelegateProperty[] = L"WebPluginDelegateProperty"; @@ -413,10 +418,11 @@ void WebPluginDelegateImpl::SetFocus() { instance()->NPP_HandleEvent(&focus_event); } -bool WebPluginDelegateImpl::HandleEvent(NPEvent* event, - WebCursor* cursor) { +bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event, + WebCursor* cursor) { DCHECK(windowless_) << "events should only be received in windowless mode"; DCHECK(cursor != NULL); + // TODO: convert event into a NPEvent, and call NPP_HandleEvent(np_event). return true; } |